]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/s390/cio/device_pgid.c
Merge git://git.infradead.org/battery-2.6
[linux-2.6-omap-h63xx.git] / drivers / s390 / cio / device_pgid.c
index 2975ce888c19ca3c2dc2b7fcf32ba79442323a46..c52449a1f9fce93f2af14456c88cb7dc7e390d96 100644 (file)
@@ -22,6 +22,7 @@
 #include "css.h"
 #include "device.h"
 #include "ioasm.h"
+#include "io_sch.h"
 
 /*
  * Helper function called from interrupt context to decide whether an
@@ -71,6 +72,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 */
@@ -122,8 +125,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))) {
                /*
@@ -147,10 +156,13 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
                return -EAGAIN;
        }
        if (irb->scsw.cc == 3) {
+               u8 lpm;
+
+               lpm = to_io_private(sch)->orb.lpm;
                CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x,"
                              " lpm %02X, became 'not operational'\n",
                              cdev->private->dev_id.devno, sch->schid.ssid,
-                             sch->schid.sch_no, sch->orb.lpm);
+                             sch->schid.sch_no, lpm);
                return -EACCES;
        }
        i = 8 - ffs(cdev->private->imask);
@@ -253,6 +265,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
@@ -293,6 +307,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
@@ -321,8 +337,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;
@@ -360,8 +382,14 @@ 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",