|
@@ -24,158 +24,6 @@ struct DCTL_data {
|
|
unsigned short res; /* reserved */
|
|
unsigned short res; /* reserved */
|
|
} __attribute__ ((packed));
|
|
} __attribute__ ((packed));
|
|
|
|
|
|
-/*
|
|
|
|
- *****************************************************************************
|
|
|
|
- * SECTION ERP EXAMINATION
|
|
|
|
- *****************************************************************************
|
|
|
|
- */
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
- * DASD_3990_ERP_EXAMINE_24
|
|
|
|
- *
|
|
|
|
- * DESCRIPTION
|
|
|
|
- * Checks only for fatal (unrecoverable) error.
|
|
|
|
- * A detailed examination of the sense data is done later outside
|
|
|
|
- * the interrupt handler.
|
|
|
|
- *
|
|
|
|
- * Each bit configuration leading to an action code 2 (Exit with
|
|
|
|
- * programming error or unusual condition indication)
|
|
|
|
- * are handled as fatal errors.
|
|
|
|
- *
|
|
|
|
- * All other configurations are handled as recoverable errors.
|
|
|
|
- *
|
|
|
|
- * RETURN VALUES
|
|
|
|
- * dasd_era_fatal for all fatal (unrecoverable errors)
|
|
|
|
- * dasd_era_recover for all others.
|
|
|
|
- */
|
|
|
|
-static dasd_era_t
|
|
|
|
-dasd_3990_erp_examine_24(struct dasd_ccw_req * cqr, char *sense)
|
|
|
|
-{
|
|
|
|
-
|
|
|
|
- struct dasd_device *device = cqr->device;
|
|
|
|
-
|
|
|
|
- /* check for 'Command Reject' */
|
|
|
|
- if ((sense[0] & SNS0_CMD_REJECT) &&
|
|
|
|
- (!(sense[2] & SNS2_ENV_DATA_PRESENT))) {
|
|
|
|
-
|
|
|
|
- DEV_MESSAGE(KERN_ERR, device, "%s",
|
|
|
|
- "EXAMINE 24: Command Reject detected - "
|
|
|
|
- "fatal error");
|
|
|
|
-
|
|
|
|
- return dasd_era_fatal;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* check for 'Invalid Track Format' */
|
|
|
|
- if ((sense[1] & SNS1_INV_TRACK_FORMAT) &&
|
|
|
|
- (!(sense[2] & SNS2_ENV_DATA_PRESENT))) {
|
|
|
|
-
|
|
|
|
- DEV_MESSAGE(KERN_ERR, device, "%s",
|
|
|
|
- "EXAMINE 24: Invalid Track Format detected "
|
|
|
|
- "- fatal error");
|
|
|
|
-
|
|
|
|
- return dasd_era_fatal;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* check for 'No Record Found' */
|
|
|
|
- if (sense[1] & SNS1_NO_REC_FOUND) {
|
|
|
|
-
|
|
|
|
- /* FIXME: fatal error ?!? */
|
|
|
|
- DEV_MESSAGE(KERN_ERR, device,
|
|
|
|
- "EXAMINE 24: No Record Found detected %s",
|
|
|
|
- device->state <= DASD_STATE_BASIC ?
|
|
|
|
- " " : "- fatal error");
|
|
|
|
-
|
|
|
|
- return dasd_era_fatal;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* return recoverable for all others */
|
|
|
|
- return dasd_era_recover;
|
|
|
|
-} /* END dasd_3990_erp_examine_24 */
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
- * DASD_3990_ERP_EXAMINE_32
|
|
|
|
- *
|
|
|
|
- * DESCRIPTION
|
|
|
|
- * Checks only for fatal/no/recoverable error.
|
|
|
|
- * A detailed examination of the sense data is done later outside
|
|
|
|
- * the interrupt handler.
|
|
|
|
- *
|
|
|
|
- * RETURN VALUES
|
|
|
|
- * dasd_era_none no error
|
|
|
|
- * dasd_era_fatal for all fatal (unrecoverable errors)
|
|
|
|
- * dasd_era_recover for recoverable others.
|
|
|
|
- */
|
|
|
|
-static dasd_era_t
|
|
|
|
-dasd_3990_erp_examine_32(struct dasd_ccw_req * cqr, char *sense)
|
|
|
|
-{
|
|
|
|
-
|
|
|
|
- struct dasd_device *device = cqr->device;
|
|
|
|
-
|
|
|
|
- switch (sense[25]) {
|
|
|
|
- case 0x00:
|
|
|
|
- return dasd_era_none;
|
|
|
|
-
|
|
|
|
- case 0x01:
|
|
|
|
- DEV_MESSAGE(KERN_ERR, device, "%s", "EXAMINE 32: fatal error");
|
|
|
|
-
|
|
|
|
- return dasd_era_fatal;
|
|
|
|
-
|
|
|
|
- default:
|
|
|
|
-
|
|
|
|
- return dasd_era_recover;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-} /* end dasd_3990_erp_examine_32 */
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
- * DASD_3990_ERP_EXAMINE
|
|
|
|
- *
|
|
|
|
- * DESCRIPTION
|
|
|
|
- * Checks only for fatal/no/recover error.
|
|
|
|
- * A detailed examination of the sense data is done later outside
|
|
|
|
- * the interrupt handler.
|
|
|
|
- *
|
|
|
|
- * The logic is based on the 'IBM 3990 Storage Control Reference' manual
|
|
|
|
- * 'Chapter 7. Error Recovery Procedures'.
|
|
|
|
- *
|
|
|
|
- * RETURN VALUES
|
|
|
|
- * dasd_era_none no error
|
|
|
|
- * dasd_era_fatal for all fatal (unrecoverable errors)
|
|
|
|
- * dasd_era_recover for all others.
|
|
|
|
- */
|
|
|
|
-dasd_era_t
|
|
|
|
-dasd_3990_erp_examine(struct dasd_ccw_req * cqr, struct irb * irb)
|
|
|
|
-{
|
|
|
|
-
|
|
|
|
- char *sense = irb->ecw;
|
|
|
|
- dasd_era_t era = dasd_era_recover;
|
|
|
|
- struct dasd_device *device = cqr->device;
|
|
|
|
-
|
|
|
|
- /* check for successful execution first */
|
|
|
|
- if (irb->scsw.cstat == 0x00 &&
|
|
|
|
- irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
|
|
|
|
- return dasd_era_none;
|
|
|
|
-
|
|
|
|
- /* distinguish between 24 and 32 byte sense data */
|
|
|
|
- if (sense[27] & DASD_SENSE_BIT_0) {
|
|
|
|
-
|
|
|
|
- era = dasd_3990_erp_examine_24(cqr, sense);
|
|
|
|
-
|
|
|
|
- } else {
|
|
|
|
-
|
|
|
|
- era = dasd_3990_erp_examine_32(cqr, sense);
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* log the erp chain if fatal error occurred */
|
|
|
|
- if ((era == dasd_era_fatal) && (device->state >= DASD_STATE_READY)) {
|
|
|
|
- dasd_log_sense(cqr, irb);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return era;
|
|
|
|
-
|
|
|
|
-} /* END dasd_3990_erp_examine */
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
*****************************************************************************
|
|
*****************************************************************************
|
|
* SECTION ERP HANDLING
|
|
* SECTION ERP HANDLING
|
|
@@ -206,7 +54,7 @@ dasd_3990_erp_cleanup(struct dasd_ccw_req * erp, char final_status)
|
|
{
|
|
{
|
|
struct dasd_ccw_req *cqr = erp->refers;
|
|
struct dasd_ccw_req *cqr = erp->refers;
|
|
|
|
|
|
- dasd_free_erp_request(erp, erp->device);
|
|
|
|
|
|
+ dasd_free_erp_request(erp, erp->memdev);
|
|
cqr->status = final_status;
|
|
cqr->status = final_status;
|
|
return cqr;
|
|
return cqr;
|
|
|
|
|
|
@@ -224,15 +72,17 @@ static void
|
|
dasd_3990_erp_block_queue(struct dasd_ccw_req * erp, int expires)
|
|
dasd_3990_erp_block_queue(struct dasd_ccw_req * erp, int expires)
|
|
{
|
|
{
|
|
|
|
|
|
- struct dasd_device *device = erp->device;
|
|
|
|
|
|
+ struct dasd_device *device = erp->startdev;
|
|
|
|
+ unsigned long flags;
|
|
|
|
|
|
DEV_MESSAGE(KERN_INFO, device,
|
|
DEV_MESSAGE(KERN_INFO, device,
|
|
"blocking request queue for %is", expires/HZ);
|
|
"blocking request queue for %is", expires/HZ);
|
|
|
|
|
|
|
|
+ spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
|
|
device->stopped |= DASD_STOPPED_PENDING;
|
|
device->stopped |= DASD_STOPPED_PENDING;
|
|
- erp->status = DASD_CQR_QUEUED;
|
|
|
|
-
|
|
|
|
- dasd_set_timer(device, expires);
|
|
|
|
|
|
+ spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
|
|
|
|
+ erp->status = DASD_CQR_FILLED;
|
|
|
|
+ dasd_block_set_timer(device->block, expires);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -251,7 +101,7 @@ static struct dasd_ccw_req *
|
|
dasd_3990_erp_int_req(struct dasd_ccw_req * erp)
|
|
dasd_3990_erp_int_req(struct dasd_ccw_req * erp)
|
|
{
|
|
{
|
|
|
|
|
|
- struct dasd_device *device = erp->device;
|
|
|
|
|
|
+ struct dasd_device *device = erp->startdev;
|
|
|
|
|
|
/* first time set initial retry counter and erp_function */
|
|
/* first time set initial retry counter and erp_function */
|
|
/* and retry once without blocking queue */
|
|
/* and retry once without blocking queue */
|
|
@@ -292,11 +142,14 @@ dasd_3990_erp_int_req(struct dasd_ccw_req * erp)
|
|
static void
|
|
static void
|
|
dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp)
|
|
dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp)
|
|
{
|
|
{
|
|
- struct dasd_device *device = erp->device;
|
|
|
|
|
|
+ struct dasd_device *device = erp->startdev;
|
|
__u8 opm;
|
|
__u8 opm;
|
|
|
|
+ unsigned long flags;
|
|
|
|
|
|
/* try alternate valid path */
|
|
/* try alternate valid path */
|
|
|
|
+ spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
|
|
opm = ccw_device_get_path_mask(device->cdev);
|
|
opm = ccw_device_get_path_mask(device->cdev);
|
|
|
|
+ spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
|
|
//FIXME: start with get_opm ?
|
|
//FIXME: start with get_opm ?
|
|
if (erp->lpm == 0)
|
|
if (erp->lpm == 0)
|
|
erp->lpm = LPM_ANYPATH & ~(erp->irb.esw.esw0.sublog.lpum);
|
|
erp->lpm = LPM_ANYPATH & ~(erp->irb.esw.esw0.sublog.lpum);
|
|
@@ -309,9 +162,8 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp)
|
|
"try alternate lpm=%x (lpum=%x / opm=%x)",
|
|
"try alternate lpm=%x (lpum=%x / opm=%x)",
|
|
erp->lpm, erp->irb.esw.esw0.sublog.lpum, opm);
|
|
erp->lpm, erp->irb.esw.esw0.sublog.lpum, opm);
|
|
|
|
|
|
- /* reset status to queued to handle the request again... */
|
|
|
|
- if (erp->status > DASD_CQR_QUEUED)
|
|
|
|
- erp->status = DASD_CQR_QUEUED;
|
|
|
|
|
|
+ /* reset status to submit the request again... */
|
|
|
|
+ erp->status = DASD_CQR_FILLED;
|
|
erp->retries = 1;
|
|
erp->retries = 1;
|
|
} else {
|
|
} else {
|
|
DEV_MESSAGE(KERN_ERR, device,
|
|
DEV_MESSAGE(KERN_ERR, device,
|
|
@@ -320,8 +172,7 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp)
|
|
erp->irb.esw.esw0.sublog.lpum, opm);
|
|
erp->irb.esw.esw0.sublog.lpum, opm);
|
|
|
|
|
|
/* post request with permanent error */
|
|
/* post request with permanent error */
|
|
- if (erp->status > DASD_CQR_QUEUED)
|
|
|
|
- erp->status = DASD_CQR_FAILED;
|
|
|
|
|
|
+ erp->status = DASD_CQR_FAILED;
|
|
}
|
|
}
|
|
} /* end dasd_3990_erp_alternate_path */
|
|
} /* end dasd_3990_erp_alternate_path */
|
|
|
|
|
|
@@ -344,14 +195,14 @@ static struct dasd_ccw_req *
|
|
dasd_3990_erp_DCTL(struct dasd_ccw_req * erp, char modifier)
|
|
dasd_3990_erp_DCTL(struct dasd_ccw_req * erp, char modifier)
|
|
{
|
|
{
|
|
|
|
|
|
- struct dasd_device *device = erp->device;
|
|
|
|
|
|
+ struct dasd_device *device = erp->startdev;
|
|
struct DCTL_data *DCTL_data;
|
|
struct DCTL_data *DCTL_data;
|
|
struct ccw1 *ccw;
|
|
struct ccw1 *ccw;
|
|
struct dasd_ccw_req *dctl_cqr;
|
|
struct dasd_ccw_req *dctl_cqr;
|
|
|
|
|
|
dctl_cqr = dasd_alloc_erp_request((char *) &erp->magic, 1,
|
|
dctl_cqr = dasd_alloc_erp_request((char *) &erp->magic, 1,
|
|
- sizeof (struct DCTL_data),
|
|
|
|
- erp->device);
|
|
|
|
|
|
+ sizeof(struct DCTL_data),
|
|
|
|
+ device);
|
|
if (IS_ERR(dctl_cqr)) {
|
|
if (IS_ERR(dctl_cqr)) {
|
|
DEV_MESSAGE(KERN_ERR, device, "%s",
|
|
DEV_MESSAGE(KERN_ERR, device, "%s",
|
|
"Unable to allocate DCTL-CQR");
|
|
"Unable to allocate DCTL-CQR");
|
|
@@ -365,13 +216,14 @@ dasd_3990_erp_DCTL(struct dasd_ccw_req * erp, char modifier)
|
|
DCTL_data->modifier = modifier;
|
|
DCTL_data->modifier = modifier;
|
|
|
|
|
|
ccw = dctl_cqr->cpaddr;
|
|
ccw = dctl_cqr->cpaddr;
|
|
- memset(ccw, 0, sizeof (struct ccw1));
|
|
|
|
|
|
+ memset(ccw, 0, sizeof(struct ccw1));
|
|
ccw->cmd_code = CCW_CMD_DCTL;
|
|
ccw->cmd_code = CCW_CMD_DCTL;
|
|
ccw->count = 4;
|
|
ccw->count = 4;
|
|
ccw->cda = (__u32)(addr_t) DCTL_data;
|
|
ccw->cda = (__u32)(addr_t) DCTL_data;
|
|
dctl_cqr->function = dasd_3990_erp_DCTL;
|
|
dctl_cqr->function = dasd_3990_erp_DCTL;
|
|
dctl_cqr->refers = erp;
|
|
dctl_cqr->refers = erp;
|
|
- dctl_cqr->device = erp->device;
|
|
|
|
|
|
+ dctl_cqr->startdev = device;
|
|
|
|
+ dctl_cqr->memdev = device;
|
|
dctl_cqr->magic = erp->magic;
|
|
dctl_cqr->magic = erp->magic;
|
|
dctl_cqr->expires = 5 * 60 * HZ;
|
|
dctl_cqr->expires = 5 * 60 * HZ;
|
|
dctl_cqr->retries = 2;
|
|
dctl_cqr->retries = 2;
|
|
@@ -435,7 +287,7 @@ static struct dasd_ccw_req *
|
|
dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense)
|
|
dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense)
|
|
{
|
|
{
|
|
|
|
|
|
- struct dasd_device *device = erp->device;
|
|
|
|
|
|
+ struct dasd_device *device = erp->startdev;
|
|
|
|
|
|
/* first time set initial retry counter and erp_function */
|
|
/* first time set initial retry counter and erp_function */
|
|
/* and retry once without waiting for state change pending */
|
|
/* and retry once without waiting for state change pending */
|
|
@@ -472,7 +324,7 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense)
|
|
"redriving request immediately, "
|
|
"redriving request immediately, "
|
|
"%d retries left",
|
|
"%d retries left",
|
|
erp->retries);
|
|
erp->retries);
|
|
- erp->status = DASD_CQR_QUEUED;
|
|
|
|
|
|
+ erp->status = DASD_CQR_FILLED;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -530,7 +382,7 @@ static void
|
|
dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense)
|
|
dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense)
|
|
{
|
|
{
|
|
|
|
|
|
- struct dasd_device *device = erp->device;
|
|
|
|
|
|
+ struct dasd_device *device = erp->startdev;
|
|
char msg_format = (sense[7] & 0xF0);
|
|
char msg_format = (sense[7] & 0xF0);
|
|
char msg_no = (sense[7] & 0x0F);
|
|
char msg_no = (sense[7] & 0x0F);
|
|
|
|
|
|
@@ -1157,7 +1009,7 @@ static struct dasd_ccw_req *
|
|
dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense)
|
|
dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense)
|
|
{
|
|
{
|
|
|
|
|
|
- struct dasd_device *device = erp->device;
|
|
|
|
|
|
+ struct dasd_device *device = erp->startdev;
|
|
|
|
|
|
erp->function = dasd_3990_erp_com_rej;
|
|
erp->function = dasd_3990_erp_com_rej;
|
|
|
|
|
|
@@ -1198,7 +1050,7 @@ static struct dasd_ccw_req *
|
|
dasd_3990_erp_bus_out(struct dasd_ccw_req * erp)
|
|
dasd_3990_erp_bus_out(struct dasd_ccw_req * erp)
|
|
{
|
|
{
|
|
|
|
|
|
- struct dasd_device *device = erp->device;
|
|
|
|
|
|
+ struct dasd_device *device = erp->startdev;
|
|
|
|
|
|
/* first time set initial retry counter and erp_function */
|
|
/* first time set initial retry counter and erp_function */
|
|
/* and retry once without blocking queue */
|
|
/* and retry once without blocking queue */
|
|
@@ -1237,7 +1089,7 @@ static struct dasd_ccw_req *
|
|
dasd_3990_erp_equip_check(struct dasd_ccw_req * erp, char *sense)
|
|
dasd_3990_erp_equip_check(struct dasd_ccw_req * erp, char *sense)
|
|
{
|
|
{
|
|
|
|
|
|
- struct dasd_device *device = erp->device;
|
|
|
|
|
|
+ struct dasd_device *device = erp->startdev;
|
|
|
|
|
|
erp->function = dasd_3990_erp_equip_check;
|
|
erp->function = dasd_3990_erp_equip_check;
|
|
|
|
|
|
@@ -1279,7 +1131,6 @@ dasd_3990_erp_equip_check(struct dasd_ccw_req * erp, char *sense)
|
|
|
|
|
|
erp = dasd_3990_erp_action_5(erp);
|
|
erp = dasd_3990_erp_action_5(erp);
|
|
}
|
|
}
|
|
-
|
|
|
|
return erp;
|
|
return erp;
|
|
|
|
|
|
} /* end dasd_3990_erp_equip_check */
|
|
} /* end dasd_3990_erp_equip_check */
|
|
@@ -1299,7 +1150,7 @@ static struct dasd_ccw_req *
|
|
dasd_3990_erp_data_check(struct dasd_ccw_req * erp, char *sense)
|
|
dasd_3990_erp_data_check(struct dasd_ccw_req * erp, char *sense)
|
|
{
|
|
{
|
|
|
|
|
|
- struct dasd_device *device = erp->device;
|
|
|
|
|
|
+ struct dasd_device *device = erp->startdev;
|
|
|
|
|
|
erp->function = dasd_3990_erp_data_check;
|
|
erp->function = dasd_3990_erp_data_check;
|
|
|
|
|
|
@@ -1358,7 +1209,7 @@ static struct dasd_ccw_req *
|
|
dasd_3990_erp_overrun(struct dasd_ccw_req * erp, char *sense)
|
|
dasd_3990_erp_overrun(struct dasd_ccw_req * erp, char *sense)
|
|
{
|
|
{
|
|
|
|
|
|
- struct dasd_device *device = erp->device;
|
|
|
|
|
|
+ struct dasd_device *device = erp->startdev;
|
|
|
|
|
|
erp->function = dasd_3990_erp_overrun;
|
|
erp->function = dasd_3990_erp_overrun;
|
|
|
|
|
|
@@ -1387,7 +1238,7 @@ static struct dasd_ccw_req *
|
|
dasd_3990_erp_inv_format(struct dasd_ccw_req * erp, char *sense)
|
|
dasd_3990_erp_inv_format(struct dasd_ccw_req * erp, char *sense)
|
|
{
|
|
{
|
|
|
|
|
|
- struct dasd_device *device = erp->device;
|
|
|
|
|
|
+ struct dasd_device *device = erp->startdev;
|
|
|
|
|
|
erp->function = dasd_3990_erp_inv_format;
|
|
erp->function = dasd_3990_erp_inv_format;
|
|
|
|
|
|
@@ -1403,8 +1254,7 @@ dasd_3990_erp_inv_format(struct dasd_ccw_req * erp, char *sense)
|
|
|
|
|
|
} else {
|
|
} else {
|
|
DEV_MESSAGE(KERN_ERR, device, "%s",
|
|
DEV_MESSAGE(KERN_ERR, device, "%s",
|
|
- "Invalid Track Format - Fatal error should have "
|
|
|
|
- "been handled within the interrupt handler");
|
|
|
|
|
|
+ "Invalid Track Format - Fatal error");
|
|
|
|
|
|
erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
|
|
erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
|
|
}
|
|
}
|
|
@@ -1428,7 +1278,7 @@ static struct dasd_ccw_req *
|
|
dasd_3990_erp_EOC(struct dasd_ccw_req * default_erp, char *sense)
|
|
dasd_3990_erp_EOC(struct dasd_ccw_req * default_erp, char *sense)
|
|
{
|
|
{
|
|
|
|
|
|
- struct dasd_device *device = default_erp->device;
|
|
|
|
|
|
+ struct dasd_device *device = default_erp->startdev;
|
|
|
|
|
|
DEV_MESSAGE(KERN_ERR, device, "%s",
|
|
DEV_MESSAGE(KERN_ERR, device, "%s",
|
|
"End-of-Cylinder - must never happen");
|
|
"End-of-Cylinder - must never happen");
|
|
@@ -1453,7 +1303,7 @@ static struct dasd_ccw_req *
|
|
dasd_3990_erp_env_data(struct dasd_ccw_req * erp, char *sense)
|
|
dasd_3990_erp_env_data(struct dasd_ccw_req * erp, char *sense)
|
|
{
|
|
{
|
|
|
|
|
|
- struct dasd_device *device = erp->device;
|
|
|
|
|
|
+ struct dasd_device *device = erp->startdev;
|
|
|
|
|
|
erp->function = dasd_3990_erp_env_data;
|
|
erp->function = dasd_3990_erp_env_data;
|
|
|
|
|
|
@@ -1463,11 +1313,9 @@ dasd_3990_erp_env_data(struct dasd_ccw_req * erp, char *sense)
|
|
|
|
|
|
/* don't retry on disabled interface */
|
|
/* don't retry on disabled interface */
|
|
if (sense[7] != 0x0F) {
|
|
if (sense[7] != 0x0F) {
|
|
-
|
|
|
|
erp = dasd_3990_erp_action_4(erp, sense);
|
|
erp = dasd_3990_erp_action_4(erp, sense);
|
|
} else {
|
|
} else {
|
|
-
|
|
|
|
- erp = dasd_3990_erp_cleanup(erp, DASD_CQR_IN_IO);
|
|
|
|
|
|
+ erp->status = DASD_CQR_FILLED;
|
|
}
|
|
}
|
|
|
|
|
|
return erp;
|
|
return erp;
|
|
@@ -1490,11 +1338,10 @@ static struct dasd_ccw_req *
|
|
dasd_3990_erp_no_rec(struct dasd_ccw_req * default_erp, char *sense)
|
|
dasd_3990_erp_no_rec(struct dasd_ccw_req * default_erp, char *sense)
|
|
{
|
|
{
|
|
|
|
|
|
- struct dasd_device *device = default_erp->device;
|
|
|
|
|
|
+ struct dasd_device *device = default_erp->startdev;
|
|
|
|
|
|
DEV_MESSAGE(KERN_ERR, device, "%s",
|
|
DEV_MESSAGE(KERN_ERR, device, "%s",
|
|
- "No Record Found - Fatal error should "
|
|
|
|
- "have been handled within the interrupt handler");
|
|
|
|
|
|
+ "No Record Found - Fatal error ");
|
|
|
|
|
|
return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED);
|
|
return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED);
|
|
|
|
|
|
@@ -1517,7 +1364,7 @@ static struct dasd_ccw_req *
|
|
dasd_3990_erp_file_prot(struct dasd_ccw_req * erp)
|
|
dasd_3990_erp_file_prot(struct dasd_ccw_req * erp)
|
|
{
|
|
{
|
|
|
|
|
|
- struct dasd_device *device = erp->device;
|
|
|
|
|
|
+ struct dasd_device *device = erp->startdev;
|
|
|
|
|
|
DEV_MESSAGE(KERN_ERR, device, "%s", "File Protected");
|
|
DEV_MESSAGE(KERN_ERR, device, "%s", "File Protected");
|
|
|
|
|
|
@@ -1525,6 +1372,43 @@ dasd_3990_erp_file_prot(struct dasd_ccw_req * erp)
|
|
|
|
|
|
} /* end dasd_3990_erp_file_prot */
|
|
} /* end dasd_3990_erp_file_prot */
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * DASD_3990_ERP_INSPECT_ALIAS
|
|
|
|
+ *
|
|
|
|
+ * DESCRIPTION
|
|
|
|
+ * Checks if the original request was started on an alias device.
|
|
|
|
+ * If yes, it modifies the original and the erp request so that
|
|
|
|
+ * the erp request can be started on a base device.
|
|
|
|
+ *
|
|
|
|
+ * PARAMETER
|
|
|
|
+ * erp pointer to the currently created default ERP
|
|
|
|
+ *
|
|
|
|
+ * RETURN VALUES
|
|
|
|
+ * erp pointer to the modified ERP, or NULL
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+static struct dasd_ccw_req *dasd_3990_erp_inspect_alias(
|
|
|
|
+ struct dasd_ccw_req *erp)
|
|
|
|
+{
|
|
|
|
+ struct dasd_ccw_req *cqr = erp->refers;
|
|
|
|
+
|
|
|
|
+ if (cqr->block &&
|
|
|
|
+ (cqr->block->base != cqr->startdev)) {
|
|
|
|
+ if (cqr->startdev->features & DASD_FEATURE_ERPLOG) {
|
|
|
|
+ DEV_MESSAGE(KERN_ERR, cqr->startdev,
|
|
|
|
+ "ERP on alias device for request %p,"
|
|
|
|
+ " recover on base device %s", cqr,
|
|
|
|
+ cqr->block->base->cdev->dev.bus_id);
|
|
|
|
+ }
|
|
|
|
+ dasd_eckd_reset_ccw_to_base_io(cqr);
|
|
|
|
+ erp->startdev = cqr->block->base;
|
|
|
|
+ erp->function = dasd_3990_erp_inspect_alias;
|
|
|
|
+ return erp;
|
|
|
|
+ } else
|
|
|
|
+ return NULL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* DASD_3990_ERP_INSPECT_24
|
|
* DASD_3990_ERP_INSPECT_24
|
|
*
|
|
*
|
|
@@ -1623,7 +1507,7 @@ static struct dasd_ccw_req *
|
|
dasd_3990_erp_action_10_32(struct dasd_ccw_req * erp, char *sense)
|
|
dasd_3990_erp_action_10_32(struct dasd_ccw_req * erp, char *sense)
|
|
{
|
|
{
|
|
|
|
|
|
- struct dasd_device *device = erp->device;
|
|
|
|
|
|
+ struct dasd_device *device = erp->startdev;
|
|
|
|
|
|
erp->retries = 256;
|
|
erp->retries = 256;
|
|
erp->function = dasd_3990_erp_action_10_32;
|
|
erp->function = dasd_3990_erp_action_10_32;
|
|
@@ -1657,13 +1541,14 @@ static struct dasd_ccw_req *
|
|
dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
|
|
dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
|
|
{
|
|
{
|
|
|
|
|
|
- struct dasd_device *device = default_erp->device;
|
|
|
|
|
|
+ struct dasd_device *device = default_erp->startdev;
|
|
__u32 cpa = 0;
|
|
__u32 cpa = 0;
|
|
struct dasd_ccw_req *cqr;
|
|
struct dasd_ccw_req *cqr;
|
|
struct dasd_ccw_req *erp;
|
|
struct dasd_ccw_req *erp;
|
|
struct DE_eckd_data *DE_data;
|
|
struct DE_eckd_data *DE_data;
|
|
|
|
+ struct PFX_eckd_data *PFX_data;
|
|
char *LO_data; /* LO_eckd_data_t */
|
|
char *LO_data; /* LO_eckd_data_t */
|
|
- struct ccw1 *ccw;
|
|
|
|
|
|
+ struct ccw1 *ccw, *oldccw;
|
|
|
|
|
|
DEV_MESSAGE(KERN_DEBUG, device, "%s",
|
|
DEV_MESSAGE(KERN_DEBUG, device, "%s",
|
|
"Write not finished because of unexpected condition");
|
|
"Write not finished because of unexpected condition");
|
|
@@ -1702,8 +1587,8 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
|
|
/* Build new ERP request including DE/LO */
|
|
/* Build new ERP request including DE/LO */
|
|
erp = dasd_alloc_erp_request((char *) &cqr->magic,
|
|
erp = dasd_alloc_erp_request((char *) &cqr->magic,
|
|
2 + 1,/* DE/LO + TIC */
|
|
2 + 1,/* DE/LO + TIC */
|
|
- sizeof (struct DE_eckd_data) +
|
|
|
|
- sizeof (struct LO_eckd_data), device);
|
|
|
|
|
|
+ sizeof(struct DE_eckd_data) +
|
|
|
|
+ sizeof(struct LO_eckd_data), device);
|
|
|
|
|
|
if (IS_ERR(erp)) {
|
|
if (IS_ERR(erp)) {
|
|
DEV_MESSAGE(KERN_ERR, device, "%s", "Unable to allocate ERP");
|
|
DEV_MESSAGE(KERN_ERR, device, "%s", "Unable to allocate ERP");
|
|
@@ -1712,10 +1597,16 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
|
|
|
|
|
|
/* use original DE */
|
|
/* use original DE */
|
|
DE_data = erp->data;
|
|
DE_data = erp->data;
|
|
- memcpy(DE_data, cqr->data, sizeof (struct DE_eckd_data));
|
|
|
|
|
|
+ oldccw = cqr->cpaddr;
|
|
|
|
+ if (oldccw->cmd_code == DASD_ECKD_CCW_PFX) {
|
|
|
|
+ PFX_data = cqr->data;
|
|
|
|
+ memcpy(DE_data, &PFX_data->define_extend,
|
|
|
|
+ sizeof(struct DE_eckd_data));
|
|
|
|
+ } else
|
|
|
|
+ memcpy(DE_data, cqr->data, sizeof(struct DE_eckd_data));
|
|
|
|
|
|
/* create LO */
|
|
/* create LO */
|
|
- LO_data = erp->data + sizeof (struct DE_eckd_data);
|
|
|
|
|
|
+ LO_data = erp->data + sizeof(struct DE_eckd_data);
|
|
|
|
|
|
if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) {
|
|
if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) {
|
|
|
|
|
|
@@ -1748,7 +1639,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
|
|
|
|
|
|
/* create DE ccw */
|
|
/* create DE ccw */
|
|
ccw = erp->cpaddr;
|
|
ccw = erp->cpaddr;
|
|
- memset(ccw, 0, sizeof (struct ccw1));
|
|
|
|
|
|
+ memset(ccw, 0, sizeof(struct ccw1));
|
|
ccw->cmd_code = DASD_ECKD_CCW_DEFINE_EXTENT;
|
|
ccw->cmd_code = DASD_ECKD_CCW_DEFINE_EXTENT;
|
|
ccw->flags = CCW_FLAG_CC;
|
|
ccw->flags = CCW_FLAG_CC;
|
|
ccw->count = 16;
|
|
ccw->count = 16;
|
|
@@ -1756,7 +1647,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
|
|
|
|
|
|
/* create LO ccw */
|
|
/* create LO ccw */
|
|
ccw++;
|
|
ccw++;
|
|
- memset(ccw, 0, sizeof (struct ccw1));
|
|
|
|
|
|
+ memset(ccw, 0, sizeof(struct ccw1));
|
|
ccw->cmd_code = DASD_ECKD_CCW_LOCATE_RECORD;
|
|
ccw->cmd_code = DASD_ECKD_CCW_LOCATE_RECORD;
|
|
ccw->flags = CCW_FLAG_CC;
|
|
ccw->flags = CCW_FLAG_CC;
|
|
ccw->count = 16;
|
|
ccw->count = 16;
|
|
@@ -1770,7 +1661,8 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
|
|
/* fill erp related fields */
|
|
/* fill erp related fields */
|
|
erp->function = dasd_3990_erp_action_1B_32;
|
|
erp->function = dasd_3990_erp_action_1B_32;
|
|
erp->refers = default_erp->refers;
|
|
erp->refers = default_erp->refers;
|
|
- erp->device = device;
|
|
|
|
|
|
+ erp->startdev = device;
|
|
|
|
+ erp->memdev = device;
|
|
erp->magic = default_erp->magic;
|
|
erp->magic = default_erp->magic;
|
|
erp->expires = 0;
|
|
erp->expires = 0;
|
|
erp->retries = 256;
|
|
erp->retries = 256;
|
|
@@ -1803,7 +1695,7 @@ static struct dasd_ccw_req *
|
|
dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense)
|
|
dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense)
|
|
{
|
|
{
|
|
|
|
|
|
- struct dasd_device *device = previous_erp->device;
|
|
|
|
|
|
+ struct dasd_device *device = previous_erp->startdev;
|
|
__u32 cpa = 0;
|
|
__u32 cpa = 0;
|
|
struct dasd_ccw_req *cqr;
|
|
struct dasd_ccw_req *cqr;
|
|
struct dasd_ccw_req *erp;
|
|
struct dasd_ccw_req *erp;
|
|
@@ -1827,7 +1719,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense)
|
|
DEV_MESSAGE(KERN_DEBUG, device, "%s",
|
|
DEV_MESSAGE(KERN_DEBUG, device, "%s",
|
|
"Imprecise ending is set - just retry");
|
|
"Imprecise ending is set - just retry");
|
|
|
|
|
|
- previous_erp->status = DASD_CQR_QUEUED;
|
|
|
|
|
|
+ previous_erp->status = DASD_CQR_FILLED;
|
|
|
|
|
|
return previous_erp;
|
|
return previous_erp;
|
|
}
|
|
}
|
|
@@ -1850,7 +1742,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense)
|
|
erp = previous_erp;
|
|
erp = previous_erp;
|
|
|
|
|
|
/* update the LO with the new returned sense data */
|
|
/* update the LO with the new returned sense data */
|
|
- LO_data = erp->data + sizeof (struct DE_eckd_data);
|
|
|
|
|
|
+ LO_data = erp->data + sizeof(struct DE_eckd_data);
|
|
|
|
|
|
if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) {
|
|
if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) {
|
|
|
|
|
|
@@ -1889,7 +1781,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense)
|
|
ccw++; /* addr of TIC ccw */
|
|
ccw++; /* addr of TIC ccw */
|
|
ccw->cda = cpa;
|
|
ccw->cda = cpa;
|
|
|
|
|
|
- erp->status = DASD_CQR_QUEUED;
|
|
|
|
|
|
+ erp->status = DASD_CQR_FILLED;
|
|
|
|
|
|
return erp;
|
|
return erp;
|
|
|
|
|
|
@@ -1968,9 +1860,7 @@ dasd_3990_erp_compound_path(struct dasd_ccw_req * erp, char *sense)
|
|
* try further actions. */
|
|
* try further actions. */
|
|
|
|
|
|
erp->lpm = 0;
|
|
erp->lpm = 0;
|
|
-
|
|
|
|
- erp->status = DASD_CQR_ERROR;
|
|
|
|
-
|
|
|
|
|
|
+ erp->status = DASD_CQR_NEED_ERP;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2047,7 +1937,7 @@ dasd_3990_erp_compound_config(struct dasd_ccw_req * erp, char *sense)
|
|
if ((sense[25] & DASD_SENSE_BIT_1) && (sense[26] & DASD_SENSE_BIT_2)) {
|
|
if ((sense[25] & DASD_SENSE_BIT_1) && (sense[26] & DASD_SENSE_BIT_2)) {
|
|
|
|
|
|
/* set to suspended duplex state then restart */
|
|
/* set to suspended duplex state then restart */
|
|
- struct dasd_device *device = erp->device;
|
|
|
|
|
|
+ struct dasd_device *device = erp->startdev;
|
|
|
|
|
|
DEV_MESSAGE(KERN_ERR, device, "%s",
|
|
DEV_MESSAGE(KERN_ERR, device, "%s",
|
|
"Set device to suspended duplex state should be "
|
|
"Set device to suspended duplex state should be "
|
|
@@ -2081,28 +1971,26 @@ dasd_3990_erp_compound(struct dasd_ccw_req * erp, char *sense)
|
|
{
|
|
{
|
|
|
|
|
|
if ((erp->function == dasd_3990_erp_compound_retry) &&
|
|
if ((erp->function == dasd_3990_erp_compound_retry) &&
|
|
- (erp->status == DASD_CQR_ERROR)) {
|
|
|
|
|
|
+ (erp->status == DASD_CQR_NEED_ERP)) {
|
|
|
|
|
|
dasd_3990_erp_compound_path(erp, sense);
|
|
dasd_3990_erp_compound_path(erp, sense);
|
|
}
|
|
}
|
|
|
|
|
|
if ((erp->function == dasd_3990_erp_compound_path) &&
|
|
if ((erp->function == dasd_3990_erp_compound_path) &&
|
|
- (erp->status == DASD_CQR_ERROR)) {
|
|
|
|
|
|
+ (erp->status == DASD_CQR_NEED_ERP)) {
|
|
|
|
|
|
erp = dasd_3990_erp_compound_code(erp, sense);
|
|
erp = dasd_3990_erp_compound_code(erp, sense);
|
|
}
|
|
}
|
|
|
|
|
|
if ((erp->function == dasd_3990_erp_compound_code) &&
|
|
if ((erp->function == dasd_3990_erp_compound_code) &&
|
|
- (erp->status == DASD_CQR_ERROR)) {
|
|
|
|
|
|
+ (erp->status == DASD_CQR_NEED_ERP)) {
|
|
|
|
|
|
dasd_3990_erp_compound_config(erp, sense);
|
|
dasd_3990_erp_compound_config(erp, sense);
|
|
}
|
|
}
|
|
|
|
|
|
/* if no compound action ERP specified, the request failed */
|
|
/* if no compound action ERP specified, the request failed */
|
|
- if (erp->status == DASD_CQR_ERROR) {
|
|
|
|
-
|
|
|
|
|
|
+ if (erp->status == DASD_CQR_NEED_ERP)
|
|
erp->status = DASD_CQR_FAILED;
|
|
erp->status = DASD_CQR_FAILED;
|
|
- }
|
|
|
|
|
|
|
|
return erp;
|
|
return erp;
|
|
|
|
|
|
@@ -2127,7 +2015,7 @@ static struct dasd_ccw_req *
|
|
dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
|
|
dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
|
|
{
|
|
{
|
|
|
|
|
|
- struct dasd_device *device = erp->device;
|
|
|
|
|
|
+ struct dasd_device *device = erp->startdev;
|
|
|
|
|
|
erp->function = dasd_3990_erp_inspect_32;
|
|
erp->function = dasd_3990_erp_inspect_32;
|
|
|
|
|
|
@@ -2149,8 +2037,7 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
|
|
|
|
|
|
case 0x01: /* fatal error */
|
|
case 0x01: /* fatal error */
|
|
DEV_MESSAGE(KERN_ERR, device, "%s",
|
|
DEV_MESSAGE(KERN_ERR, device, "%s",
|
|
- "Fatal error should have been "
|
|
|
|
- "handled within the interrupt handler");
|
|
|
|
|
|
+ "Retry not recommended - Fatal error");
|
|
|
|
|
|
erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
|
|
erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
|
|
break;
|
|
break;
|
|
@@ -2253,6 +2140,11 @@ dasd_3990_erp_inspect(struct dasd_ccw_req * erp)
|
|
/* already set up new ERP ! */
|
|
/* already set up new ERP ! */
|
|
char *sense = erp->refers->irb.ecw;
|
|
char *sense = erp->refers->irb.ecw;
|
|
|
|
|
|
|
|
+ /* if this problem occured on an alias retry on base */
|
|
|
|
+ erp_new = dasd_3990_erp_inspect_alias(erp);
|
|
|
|
+ if (erp_new)
|
|
|
|
+ return erp_new;
|
|
|
|
+
|
|
/* distinguish between 24 and 32 byte sense data */
|
|
/* distinguish between 24 and 32 byte sense data */
|
|
if (sense[27] & DASD_SENSE_BIT_0) {
|
|
if (sense[27] & DASD_SENSE_BIT_0) {
|
|
|
|
|
|
@@ -2287,13 +2179,13 @@ static struct dasd_ccw_req *
|
|
dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr)
|
|
dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr)
|
|
{
|
|
{
|
|
|
|
|
|
- struct dasd_device *device = cqr->device;
|
|
|
|
|
|
+ struct dasd_device *device = cqr->startdev;
|
|
struct ccw1 *ccw;
|
|
struct ccw1 *ccw;
|
|
|
|
|
|
/* allocate additional request block */
|
|
/* allocate additional request block */
|
|
struct dasd_ccw_req *erp;
|
|
struct dasd_ccw_req *erp;
|
|
|
|
|
|
- erp = dasd_alloc_erp_request((char *) &cqr->magic, 2, 0, cqr->device);
|
|
|
|
|
|
+ erp = dasd_alloc_erp_request((char *) &cqr->magic, 2, 0, device);
|
|
if (IS_ERR(erp)) {
|
|
if (IS_ERR(erp)) {
|
|
if (cqr->retries <= 0) {
|
|
if (cqr->retries <= 0) {
|
|
DEV_MESSAGE(KERN_ERR, device, "%s",
|
|
DEV_MESSAGE(KERN_ERR, device, "%s",
|
|
@@ -2305,7 +2197,7 @@ dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr)
|
|
"Unable to allocate ERP request "
|
|
"Unable to allocate ERP request "
|
|
"(%i retries left)",
|
|
"(%i retries left)",
|
|
cqr->retries);
|
|
cqr->retries);
|
|
- dasd_set_timer(device, (HZ << 3));
|
|
|
|
|
|
+ dasd_block_set_timer(device->block, (HZ << 3));
|
|
}
|
|
}
|
|
return cqr;
|
|
return cqr;
|
|
}
|
|
}
|
|
@@ -2319,7 +2211,9 @@ dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr)
|
|
ccw->cda = (long)(cqr->cpaddr);
|
|
ccw->cda = (long)(cqr->cpaddr);
|
|
erp->function = dasd_3990_erp_add_erp;
|
|
erp->function = dasd_3990_erp_add_erp;
|
|
erp->refers = cqr;
|
|
erp->refers = cqr;
|
|
- erp->device = cqr->device;
|
|
|
|
|
|
+ erp->startdev = device;
|
|
|
|
+ erp->memdev = device;
|
|
|
|
+ erp->block = cqr->block;
|
|
erp->magic = cqr->magic;
|
|
erp->magic = cqr->magic;
|
|
erp->expires = 0;
|
|
erp->expires = 0;
|
|
erp->retries = 256;
|
|
erp->retries = 256;
|
|
@@ -2466,7 +2360,7 @@ static struct dasd_ccw_req *
|
|
dasd_3990_erp_further_erp(struct dasd_ccw_req *erp)
|
|
dasd_3990_erp_further_erp(struct dasd_ccw_req *erp)
|
|
{
|
|
{
|
|
|
|
|
|
- struct dasd_device *device = erp->device;
|
|
|
|
|
|
+ struct dasd_device *device = erp->startdev;
|
|
char *sense = erp->irb.ecw;
|
|
char *sense = erp->irb.ecw;
|
|
|
|
|
|
/* check for 24 byte sense ERP */
|
|
/* check for 24 byte sense ERP */
|
|
@@ -2557,7 +2451,7 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head,
|
|
struct dasd_ccw_req *erp)
|
|
struct dasd_ccw_req *erp)
|
|
{
|
|
{
|
|
|
|
|
|
- struct dasd_device *device = erp_head->device;
|
|
|
|
|
|
+ struct dasd_device *device = erp_head->startdev;
|
|
struct dasd_ccw_req *erp_done = erp_head; /* finished req */
|
|
struct dasd_ccw_req *erp_done = erp_head; /* finished req */
|
|
struct dasd_ccw_req *erp_free = NULL; /* req to be freed */
|
|
struct dasd_ccw_req *erp_free = NULL; /* req to be freed */
|
|
|
|
|
|
@@ -2569,13 +2463,13 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head,
|
|
"original request was lost\n");
|
|
"original request was lost\n");
|
|
|
|
|
|
/* remove the request from the device queue */
|
|
/* remove the request from the device queue */
|
|
- list_del(&erp_done->list);
|
|
|
|
|
|
+ list_del(&erp_done->blocklist);
|
|
|
|
|
|
erp_free = erp_done;
|
|
erp_free = erp_done;
|
|
erp_done = erp_done->refers;
|
|
erp_done = erp_done->refers;
|
|
|
|
|
|
/* free the finished erp request */
|
|
/* free the finished erp request */
|
|
- dasd_free_erp_request(erp_free, erp_free->device);
|
|
|
|
|
|
+ dasd_free_erp_request(erp_free, erp_free->memdev);
|
|
|
|
|
|
} /* end while */
|
|
} /* end while */
|
|
|
|
|
|
@@ -2603,7 +2497,7 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head,
|
|
erp->retries, erp);
|
|
erp->retries, erp);
|
|
|
|
|
|
/* handle the request again... */
|
|
/* handle the request again... */
|
|
- erp->status = DASD_CQR_QUEUED;
|
|
|
|
|
|
+ erp->status = DASD_CQR_FILLED;
|
|
}
|
|
}
|
|
|
|
|
|
} else {
|
|
} else {
|
|
@@ -2636,9 +2530,8 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head,
|
|
struct dasd_ccw_req *
|
|
struct dasd_ccw_req *
|
|
dasd_3990_erp_action(struct dasd_ccw_req * cqr)
|
|
dasd_3990_erp_action(struct dasd_ccw_req * cqr)
|
|
{
|
|
{
|
|
-
|
|
|
|
struct dasd_ccw_req *erp = NULL;
|
|
struct dasd_ccw_req *erp = NULL;
|
|
- struct dasd_device *device = cqr->device;
|
|
|
|
|
|
+ struct dasd_device *device = cqr->startdev;
|
|
struct dasd_ccw_req *temp_erp = NULL;
|
|
struct dasd_ccw_req *temp_erp = NULL;
|
|
|
|
|
|
if (device->features & DASD_FEATURE_ERPLOG) {
|
|
if (device->features & DASD_FEATURE_ERPLOG) {
|
|
@@ -2704,10 +2597,11 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- /* enqueue added ERP request */
|
|
|
|
- if (erp->status == DASD_CQR_FILLED) {
|
|
|
|
- erp->status = DASD_CQR_QUEUED;
|
|
|
|
- list_add(&erp->list, &device->ccw_queue);
|
|
|
|
|
|
+ /* enqueue ERP request if it's a new one */
|
|
|
|
+ if (list_empty(&erp->blocklist)) {
|
|
|
|
+ cqr->status = DASD_CQR_IN_ERP;
|
|
|
|
+ /* add erp request before the cqr */
|
|
|
|
+ list_add_tail(&erp->blocklist, &cqr->blocklist);
|
|
}
|
|
}
|
|
|
|
|
|
return erp;
|
|
return erp;
|