[S390] more workqueue fixes.
[powerpc.git] / drivers / s390 / cio / device_pgid.c
index 8ca2d07..cb1879a 100644 (file)
@@ -71,6 +71,8 @@ __ccw_device_sense_pgid_start(struct ccw_device *cdev)
                ccw->cda = (__u32) __pa (&cdev->private->pgid[i]);
                if (cdev->private->iretry > 0) {
                        cdev->private->iretry--;
+                       /* Reset internal retry indication. */
+                       cdev->private->flags.intretry = 0;
                        ret = cio_start (sch, cdev->private->iccws, 
                                         cdev->private->imask);
                        /* ret is 0, -EBUSY, -EACCES or -ENODEV */
@@ -79,7 +81,8 @@ __ccw_device_sense_pgid_start(struct ccw_device *cdev)
                        CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel "
                                      "0.%x.%04x, lpm %02X, became 'not "
                                      "operational'\n",
-                                     cdev->private->devno, sch->schid.ssid,
+                                     cdev->private->dev_id.devno,
+                                     sch->schid.ssid,
                                      sch->schid.sch_no, cdev->private->imask);
 
                }
@@ -96,6 +99,9 @@ ccw_device_sense_pgid_start(struct ccw_device *cdev)
 {
        int ret;
 
+       /* Set a timeout of 60s */
+       ccw_device_set_timeout(cdev, 60*HZ);
+
        cdev->private->state = DEV_STATE_SENSE_PGID;
        cdev->private->imask = 0x80;
        cdev->private->iretry = 5;
@@ -118,8 +124,14 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
 
        sch = to_subchannel(cdev->dev.parent);
        irb = &cdev->private->irb;
-       if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC))
+       if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) {
+               /* Retry Sense PGID if requested. */
+               if (cdev->private->flags.intretry) {
+                       cdev->private->flags.intretry = 0;
+                       return -EAGAIN;
+               }
                return -ETIME;
+       }
        if (irb->esw.esw0.erw.cons &&
            (irb->ecw[0]&(SNS0_CMD_REJECT|SNS0_INTERVENTION_REQ))) {
                /*
@@ -132,7 +144,8 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
                CIO_MSG_EVENT(2, "SNID - device 0.%x.%04x, unit check, "
                              "lpum %02X, cnt %02d, sns : "
                              "%02X%02X%02X%02X %02X%02X%02X%02X ...\n",
-                             cdev->private->ssid, cdev->private->devno,
+                             cdev->private->dev_id.ssid,
+                             cdev->private->dev_id.devno,
                              irb->esw.esw0.sublog.lpum,
                              irb->esw.esw0.erw.scnt,
                              irb->ecw[0], irb->ecw[1],
@@ -144,7 +157,7 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
        if (irb->scsw.cc == 3) {
                CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x,"
                              " lpm %02X, became 'not operational'\n",
-                             cdev->private->devno, sch->schid.ssid,
+                             cdev->private->dev_id.devno, sch->schid.ssid,
                              sch->schid.sch_no, sch->orb.lpm);
                return -EACCES;
        }
@@ -152,7 +165,7 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
        if (cdev->private->pgid[i].inf.ps.state2 == SNID_STATE2_RESVD_ELSE) {
                CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x "
                              "is reserved by someone else\n",
-                             cdev->private->devno, sch->schid.ssid,
+                             cdev->private->dev_id.devno, sch->schid.ssid,
                              sch->schid.sch_no);
                return -EUSERS;
        }
@@ -248,6 +261,8 @@ __ccw_device_do_pgid(struct ccw_device *cdev, __u8 func)
        ret = -EACCES;
        if (cdev->private->iretry > 0) {
                cdev->private->iretry--;
+               /* Reset internal retry indication. */
+               cdev->private->flags.intretry = 0;
                ret = cio_start (sch, cdev->private->iccws,
                                 cdev->private->imask);
                /* We expect an interrupt in case of success or busy
@@ -258,7 +273,7 @@ __ccw_device_do_pgid(struct ccw_device *cdev, __u8 func)
        /* PGID command failed on this path. */
        CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel "
                      "0.%x.%04x, lpm %02X, became 'not operational'\n",
-                     cdev->private->devno, sch->schid.ssid,
+                     cdev->private->dev_id.devno, sch->schid.ssid,
                      sch->schid.sch_no, cdev->private->imask);
        return ret;
 }
@@ -288,6 +303,8 @@ static int __ccw_device_do_nop(struct ccw_device *cdev)
        ret = -EACCES;
        if (cdev->private->iretry > 0) {
                cdev->private->iretry--;
+               /* Reset internal retry indication. */
+               cdev->private->flags.intretry = 0;
                ret = cio_start (sch, cdev->private->iccws,
                                 cdev->private->imask);
                /* We expect an interrupt in case of success or busy
@@ -298,7 +315,7 @@ static int __ccw_device_do_nop(struct ccw_device *cdev)
        /* nop command failed on this path. */
        CIO_MSG_EVENT(2, "NOP - Device %04x on Subchannel "
                      "0.%x.%04x, lpm %02X, became 'not operational'\n",
-                     cdev->private->devno, sch->schid.ssid,
+                     cdev->private->dev_id.devno, sch->schid.ssid,
                      sch->schid.sch_no, cdev->private->imask);
        return ret;
 }
@@ -316,8 +333,14 @@ __ccw_device_check_pgid(struct ccw_device *cdev)
 
        sch = to_subchannel(cdev->dev.parent);
        irb = &cdev->private->irb;
-       if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC))
+       if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) {
+               /* Retry Set PGID if requested. */
+               if (cdev->private->flags.intretry) {
+                       cdev->private->flags.intretry = 0;
+                       return -EAGAIN;
+               }
                return -ETIME;
+       }
        if (irb->esw.esw0.erw.cons) {
                if (irb->ecw[0] & SNS0_CMD_REJECT)
                        return -EOPNOTSUPP;
@@ -325,8 +348,9 @@ __ccw_device_check_pgid(struct ccw_device *cdev)
                CIO_MSG_EVENT(2, "SPID - device 0.%x.%04x, unit check, "
                              "cnt %02d, "
                              "sns : %02X%02X%02X%02X %02X%02X%02X%02X ...\n",
-                             cdev->private->ssid,
-                             cdev->private->devno, irb->esw.esw0.erw.scnt,
+                             cdev->private->dev_id.ssid,
+                             cdev->private->dev_id.devno,
+                             irb->esw.esw0.erw.scnt,
                              irb->ecw[0], irb->ecw[1],
                              irb->ecw[2], irb->ecw[3],
                              irb->ecw[4], irb->ecw[5],
@@ -336,7 +360,7 @@ __ccw_device_check_pgid(struct ccw_device *cdev)
        if (irb->scsw.cc == 3) {
                CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel 0.%x.%04x,"
                              " lpm %02X, became 'not operational'\n",
-                             cdev->private->devno, sch->schid.ssid,
+                             cdev->private->dev_id.devno, sch->schid.ssid,
                              sch->schid.sch_no, cdev->private->imask);
                return -EACCES;
        }
@@ -354,12 +378,18 @@ static int __ccw_device_check_nop(struct ccw_device *cdev)
 
        sch = to_subchannel(cdev->dev.parent);
        irb = &cdev->private->irb;
-       if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC))
+       if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) {
+               /* Retry NOP if requested. */
+               if (cdev->private->flags.intretry) {
+                       cdev->private->flags.intretry = 0;
+                       return -EAGAIN;
+               }
                return -ETIME;
+       }
        if (irb->scsw.cc == 3) {
                CIO_MSG_EVENT(2, "NOP - Device %04x on Subchannel 0.%x.%04x,"
                              " lpm %02X, became 'not operational'\n",
-                             cdev->private->devno, sch->schid.ssid,
+                             cdev->private->dev_id.devno, sch->schid.ssid,
                              sch->schid.sch_no, cdev->private->imask);
                return -EACCES;
        }
@@ -480,6 +510,8 @@ ccw_device_verify_start(struct ccw_device *cdev)
                ccw_device_verify_done(cdev, -ENODEV);
                return;
        }
+       /* After 60s path verification is considered to have failed. */
+       ccw_device_set_timeout(cdev, 60*HZ);
        __ccw_device_verify_start(cdev);
 }
 
@@ -554,6 +586,9 @@ ccw_device_disband_irq(struct ccw_device *cdev, enum dev_event dev_event)
 void
 ccw_device_disband_start(struct ccw_device *cdev)
 {
+       /* After 60s disbanding is considered to have failed. */
+       ccw_device_set_timeout(cdev, 60*HZ);
+
        cdev->private->flags.pgid_single = 0;
        cdev->private->iretry = 5;
        cdev->private->imask = 0x80;