linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / s390 / block / dasd_3990_erp.c
index e90c1c9..4ee0f93 100644 (file)
@@ -5,7 +5,6 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001
  *
- * $Revision: 1.30 $
  */
 
 #include <linux/timer.h>
@@ -20,9 +19,9 @@
 
 
 struct DCTL_data {
-       unsigned char subcommand;       /* e.g Inhibit Write, Enable Write,... */
-       unsigned char modifier; /* Subcommand modifier                 */
-       unsigned short res;     /* reserved */
+       unsigned char subcommand;  /* e.g Inhibit Write, Enable Write,... */
+       unsigned char modifier;    /* Subcommand modifier */
+       unsigned short res;        /* reserved */
 } __attribute__ ((packed));
 
 /*
@@ -301,15 +300,15 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp)
        opm = ccw_device_get_path_mask(device->cdev);
        //FIXME: start with get_opm ?
        if (erp->lpm == 0)
-               erp->lpm = LPM_ANYPATH & ~(erp->dstat->esw.esw0.sublog.lpum);
+               erp->lpm = LPM_ANYPATH & ~(erp->irb.esw.esw0.sublog.lpum);
        else
-               erp->lpm &= ~(erp->dstat->esw.esw0.sublog.lpum);
+               erp->lpm &= ~(erp->irb.esw.esw0.sublog.lpum);
 
        if ((erp->lpm & opm) != 0x00) {
 
                DEV_MESSAGE(KERN_DEBUG, device,
                            "try alternate lpm=%x (lpum=%x / opm=%x)",
-                           erp->lpm, erp->dstat->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)
@@ -319,7 +318,7 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp)
                DEV_MESSAGE(KERN_ERR, device,
                            "No alternate channel path left (lpum=%x / "
                            "opm=%x) -> permanent error",
-                           erp->dstat->esw.esw0.sublog.lpum, opm);
+                           erp->irb.esw.esw0.sublog.lpum, opm);
 
                /* post request with permanent error */
                if (erp->status > DASD_CQR_QUEUED)
@@ -422,7 +421,8 @@ dasd_3990_erp_action_1(struct dasd_ccw_req * erp)
  *   Setup ERP to do the ERP action 4 (see Reference manual).
  *   Set the current request to PENDING to block the CQR queue for that device
  *   until the state change interrupt appears.
- *   Use a timer (20 seconds) to retry the cqr if the interrupt is still missing.
+ *   Use a timer (20 seconds) to retry the cqr if the interrupt is still
+ *   missing.
  *
  *  PARAMETER
  *   sense             sense data of the actual error
@@ -443,6 +443,9 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense)
        /* interrupt (this enables easier enqueing of the cqr)      */
        if (erp->function != dasd_3990_erp_action_4) {
 
+               DEV_MESSAGE(KERN_INFO, device, "%s",
+                           "dasd_3990_erp_action_4: first time retry");
+
                erp->retries = 256;
                erp->function = dasd_3990_erp_action_4;
 
@@ -457,6 +460,12 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense)
                        
                        dasd_3990_erp_block_queue(erp, 30*HZ);
 
+                } else if (sense[25] == 0x1E) {        /* busy */
+                       DEV_MESSAGE(KERN_INFO, device,
+                                   "busy - redriving request later, "
+                                   "%d retries left",
+                                   erp->retries);
+                        dasd_3990_erp_block_queue(erp, HZ);
                } else {
 
                        /* no state change pending - retry */
@@ -816,7 +825,7 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense)
                }
                break;
 
-       case 0x50:              /* Format 5 - Data Check with displacement information */
+       case 0x50:  /* Format 5 - Data Check with displacement information */
                switch (msg_no) {
                case 0x00:
                        DEV_MESSAGE(KERN_WARNING, device, "%s",
@@ -861,7 +870,7 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense)
                }
                break;
 
-       case 0x60:              /* Format 6 - Usage Statistics/Overrun Errors */
+       case 0x60:  /* Format 6 - Usage Statistics/Overrun Errors */
                switch (msg_no) {
                case 0x00:
                        DEV_MESSAGE(KERN_WARNING, device, "%s",
@@ -901,7 +910,7 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense)
                }
                break;
 
-       case 0x70:              /* Format 7 - Device Connection Control Checks */
+       case 0x70:  /* Format 7 - Device Connection Control Checks */
                switch (msg_no) {
                case 0x00:
                        DEV_MESSAGE(KERN_WARNING, device, "%s",
@@ -978,7 +987,7 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense)
                }
                break;
 
-       case 0x80:              /* Format 8 - Additional Device Equipment Checks */
+       case 0x80:  /* Format 8 - Additional Device Equipment Checks */
                switch (msg_no) {
                case 0x00:      /* No Message */
                case 0x01:
@@ -1031,7 +1040,7 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense)
                }
                break;
 
-       case 0x90:              /* Format 9 - Device Read, Write, and Seek Checks */
+       case 0x90:  /* Format 9 - Device Read, Write, and Seek Checks */
                switch (msg_no) {
                case 0x00:
                        break;  /* No Message */
@@ -1300,8 +1309,8 @@ dasd_3990_erp_data_check(struct dasd_ccw_req * erp, char *sense)
                            "fetch mode active");
 
                /* not possible to handle this situation in Linux */
-               panic("No way to inform appliction about the possibly "
-                     "incorret data");
+               panic("No way to inform application about the possibly "
+                     "incorrect data");
 
        } else if (sense[2] & SNS2_ENV_DATA_PRESENT) {
 
@@ -1677,7 +1686,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
 
        /* determine the address of the CCW to be restarted */
        /* Imprecise ending is not set -> addr from IRB-SCSW */
-       cpa = default_erp->refers->dstat->scsw.cpa;
+       cpa = default_erp->refers->irb.scsw.cpa;
 
        if (cpa == 0) {
 
@@ -1763,7 +1772,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
        erp->magic = default_erp->magic;
        erp->expires = 0;
        erp->retries = 256;
-       cqr->buildclk = get_clock();
+       erp->buildclk = get_clock();
        erp->status = DASD_CQR_FILLED;
 
        /* remove the default erp */
@@ -1823,7 +1832,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense)
 
        /* determine the address of the CCW to be restarted */
        /* Imprecise ending is not set -> addr from IRB-SCSW */
-       cpa = previous_erp->dstat->scsw.cpa;
+       cpa = previous_erp->irb.scsw.cpa;
 
        if (cpa == 0) {
 
@@ -2149,7 +2158,7 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
                        erp = dasd_3990_erp_int_req(erp);
                        break;
 
-               case 0x0F:      /* length mismatch during update write command */
+               case 0x0F:  /* length mismatch during update write command */
                        DEV_MESSAGE(KERN_ERR, device, "%s",
                                    "update write command error - should not "
                                    "happen;\n"
@@ -2160,7 +2169,7 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
                        erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
                        break;
 
-               case 0x10:      /* logging required for other channel program */
+               case 0x10:  /* logging required for other channel program */
                        erp = dasd_3990_erp_action_10_32(erp, sense);
                        break;
 
@@ -2187,8 +2196,8 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
 
                        /* not possible to handle this situation in Linux */
                        panic
-                           ("Invalid data - No way to inform appliction about "
-                            "the possibly incorret data");
+                           ("Invalid data - No way to inform application "
+                            "about the possibly incorrect data");
                        break;
 
                case 0x1D:      /* state-change pending */
@@ -2199,6 +2208,13 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
                        erp = dasd_3990_erp_action_4(erp, sense);
                        break;
 
+               case 0x1E:      /* busy */
+                        DEV_MESSAGE(KERN_DEBUG, device, "%s",
+                                   "Busy condition exists "
+                                   "for the subsystem or device");
+                        erp = dasd_3990_erp_action_4(erp, sense);
+                       break;
+
                default:        /* all others errors - default erp  */
                        break;
                }
@@ -2233,7 +2249,7 @@ dasd_3990_erp_inspect(struct dasd_ccw_req * erp)
        struct dasd_ccw_req *erp_new = NULL;
        /* sense data are located in the refers record of the */
        /* already set up new ERP !                           */
-       char *sense = erp->refers->dstat->ecw;
+       char *sense = erp->refers->irb.ecw;
 
        /* distinguish between 24 and 32 byte sense data */
        if (sense[27] & DASD_SENSE_BIT_0) {
@@ -2246,11 +2262,10 @@ dasd_3990_erp_inspect(struct dasd_ccw_req * erp)
                /* inspect the 32 byte sense data */
                erp_new = dasd_3990_erp_inspect_32(erp, sense);
 
-       }                       /* end distinguish between 24 and 32 byte sense data */
+       }       /* end distinguish between 24 and 32 byte sense data */
 
        return erp_new;
-
-}                              /* END dasd_3990_erp_inspect */
+}
 
 /*
  * DASD_3990_ERP_ADD_ERP
@@ -2306,6 +2321,7 @@ dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr)
        erp->magic    = cqr->magic;
        erp->expires  = 0;
        erp->retries  = 256;
+       erp->buildclk = get_clock();
 
        erp->status = DASD_CQR_FILLED;
 
@@ -2369,14 +2385,14 @@ dasd_3990_erp_error_match(struct dasd_ccw_req *cqr1, struct dasd_ccw_req *cqr2)
 {
 
        /* check failed CCW */
-       if (cqr1->dstat->scsw.cpa != cqr2->dstat->scsw.cpa) {
+       if (cqr1->irb.scsw.cpa != cqr2->irb.scsw.cpa) {
                //      return 0;       /* CCW doesn't match */
        }
 
        /* check sense data; byte 0-2,25,27 */
-       if (!((memcmp (cqr1->dstat->ecw, cqr2->dstat->ecw, 3) == 0) &&
-             (cqr1->dstat->ecw[27] == cqr2->dstat->ecw[27]) &&
-             (cqr1->dstat->ecw[25] == cqr2->dstat->ecw[25]))) {
+       if (!((memcmp (cqr1->irb.ecw, cqr2->irb.ecw, 3) == 0) &&
+             (cqr1->irb.ecw[27] == cqr2->irb.ecw[27]) &&
+             (cqr1->irb.ecw[25] == cqr2->irb.ecw[25]))) {
 
                return 0;       /* sense doesn't match */
        }
@@ -2449,7 +2465,7 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp)
 {
 
        struct dasd_device *device = erp->device;
-       char *sense = erp->dstat->ecw;
+       char *sense = erp->irb.ecw;
 
        /* check for 24 byte sense ERP */
        if ((erp->function == dasd_3990_erp_bus_out) ||
@@ -2502,7 +2518,8 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp)
                erp = dasd_3990_erp_compound(erp, sense);
 
        } else {
-               /* no retry left and no additional special handling necessary */
+               /* No retry left and no additional special handling */
+               /*necessary */
                DEV_MESSAGE(KERN_ERR, device,
                            "no retries left for erp %p - "
                            "set status to FAILED", erp);
@@ -2562,7 +2579,7 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head,
 
        if (erp->retries > 0) {
 
-               char *sense = erp->refers->dstat->ecw;
+               char *sense = erp->refers->irb.ecw;
 
                /* check for special retries */
                if (erp->function == dasd_3990_erp_action_4) {
@@ -2620,7 +2637,7 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
 
        struct dasd_ccw_req *erp = NULL;
        struct dasd_device *device = cqr->device;
-       __u32 cpa = cqr->dstat->scsw.cpa;
+       __u32 cpa = cqr->irb.scsw.cpa;
 
 #ifdef ERP_DEBUG
        /* print current erp_chain */
@@ -2641,8 +2658,8 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
 #endif                         /* ERP_DEBUG */
 
        /* double-check if current erp/cqr was successfull */
-       if ((cqr->dstat->scsw.cstat == 0x00) &&
-           (cqr->dstat->scsw.dstat == (DEV_STAT_CHN_END|DEV_STAT_DEV_END))) {
+       if ((cqr->irb.scsw.cstat == 0x00) &&
+           (cqr->irb.scsw.dstat == (DEV_STAT_CHN_END|DEV_STAT_DEV_END))) {
 
                DEV_MESSAGE(KERN_DEBUG, device,
                            "ERP called for successful request %p"
@@ -2653,7 +2670,7 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
                return cqr;
        }
        /* check if sense data are available */
-       if (!cqr->dstat->ecw) {
+       if (!cqr->irb.ecw) {
                DEV_MESSAGE(KERN_DEBUG, device,
                            "ERP called witout sense data avail ..."
                            "request %p - NO ERP possible", cqr);