[patch 5/9] s390: irb faking.

From: Cornelia Huck <[EMAIL PROTECTED]>

Common i/o layer changes:
 - If a device driver tries to start I/O while the common I/O layer wants
   to start path verification, don't reject the I/O with -EBUSY (which
   might prompt the driver to retry the next tick) but seemingly accept
   the I/O and deliver a fake irb with deferred cc 1 after path
   verification has finished (prompting the driver to retry the I/O).
   This prevents the device driver from doing useless retries while cio
   is still busy with path verification.

Signed-off-by: Martin Schwidefsky <[EMAIL PROTECTED]>

diffstat:
 drivers/s390/cio/chsc.c       |    3 +++
 drivers/s390/cio/css.h        |    2 ++
 drivers/s390/cio/device_fsm.c |   29 +++++++++++++++++++++++++++++
 drivers/s390/cio/device_ops.c |   10 ++++++++++
 4 files changed, 44 insertions(+)

diff -urN linux-2.6/drivers/s390/cio/chsc.c 
linux-2.6-patched/drivers/s390/cio/chsc.c
--- linux-2.6/drivers/s390/cio/chsc.c   2005-03-02 17:00:12.000000000 +0100
+++ linux-2.6-patched/drivers/s390/cio/chsc.c   2005-03-02 17:00:12.000000000 
+0100
@@ -703,6 +703,9 @@
 {
        int cc;
 
+       if (!device_is_online(sch))
+               /* cio could be doing I/O. */
+               return 0;
        cc = stsch(sch->irq, &sch->schib);
        if (cc)
                return 0;
diff -urN linux-2.6/drivers/s390/cio/css.h 
linux-2.6-patched/drivers/s390/cio/css.h
--- linux-2.6/drivers/s390/cio/css.h    2005-03-02 08:38:34.000000000 +0100
+++ linux-2.6-patched/drivers/s390/cio/css.h    2005-03-02 17:00:12.000000000 
+0100
@@ -84,6 +84,7 @@
                unsigned int doverify:1;    /* delayed path verification */
                unsigned int donotify:1;    /* call notify function */
                unsigned int recog_done:1;  /* dev. recog. complete */
+               unsigned int fake_irb:1;    /* deliver faked irb */
        } __attribute__((packed)) flags;
        unsigned long intparm;  /* user interruption parameter */
        struct qdio_irq *qdio_data;
@@ -136,6 +137,7 @@
 void device_trigger_reprobe(struct subchannel *);
 
 /* Helper functions for vary on/off. */
+int device_is_online(struct subchannel *);
 void device_set_waiting(struct subchannel *);
 
 /* Machine check helper function. */
diff -urN linux-2.6/drivers/s390/cio/device_fsm.c 
linux-2.6-patched/drivers/s390/cio/device_fsm.c
--- linux-2.6/drivers/s390/cio/device_fsm.c     2005-03-02 17:00:12.000000000 
+0100
+++ linux-2.6-patched/drivers/s390/cio/device_fsm.c     2005-03-02 
17:00:12.000000000 +0100
@@ -24,6 +24,17 @@
 #include "qdio.h"
 
 int
+device_is_online(struct subchannel *sch)
+{
+       struct ccw_device *cdev;
+
+       if (!sch->dev.driver_data)
+               return 0;
+       cdev = sch->dev.driver_data;
+       return (cdev->private->state == DEV_STATE_ONLINE);
+}
+
+int
 device_is_disconnected(struct subchannel *sch)
 {
        struct ccw_device *cdev;
@@ -44,6 +55,7 @@
                return;
        cdev = sch->dev.driver_data;
        ccw_device_set_timeout(cdev, 0);
+       cdev->private->flags.fake_irb = 0;
        cdev->private->state = DEV_STATE_DISCONNECTED;
 }
 
@@ -474,6 +486,7 @@
        } else {
                cio_disable_subchannel(sch);
                ccw_device_set_timeout(cdev, 0);
+               cdev->private->flags.fake_irb = 0;
                cdev->private->state = DEV_STATE_DISCONNECTED;
                wake_up(&cdev->private->wait_q);
        }
@@ -488,6 +501,21 @@
                cdev->private->options.pgroup = 0;
        case 0:
                ccw_device_done(cdev, DEV_STATE_ONLINE);
+               /* Deliver fake irb to device driver, if needed. */
+               if (cdev->private->flags.fake_irb) {
+                       memset(&cdev->private->irb, 0, sizeof(struct irb));
+                       cdev->private->irb.scsw = (struct scsw) {
+                               .cc = 1,
+                               .fctl = SCSW_FCTL_START_FUNC,
+                               .actl = SCSW_ACTL_START_PEND,
+                               .stctl = SCSW_STCTL_STATUS_PEND,
+                       };
+                       cdev->private->flags.fake_irb = 0;
+                       if (cdev->handler)
+                               cdev->handler(cdev, cdev->private->intparm,
+                                             &cdev->private->irb);
+                       memset(&cdev->private->irb, 0, sizeof(struct irb));
+               }
                break;
        case -ETIME:
                ccw_device_done(cdev, DEV_STATE_BOXED);
@@ -639,6 +667,7 @@
        if (sch->driver->notify &&
            sch->driver->notify(&sch->dev, sch->lpm ? CIO_GONE : CIO_NO_PATH)) {
                        ccw_device_set_timeout(cdev, 0);
+                       cdev->private->flags.fake_irb = 0;
                        cdev->private->state = DEV_STATE_DISCONNECTED;
                        wake_up(&cdev->private->wait_q);
                        return;
diff -urN linux-2.6/drivers/s390/cio/device_ops.c 
linux-2.6-patched/drivers/s390/cio/device_ops.c
--- linux-2.6/drivers/s390/cio/device_ops.c     2005-03-02 17:00:12.000000000 
+0100
+++ linux-2.6-patched/drivers/s390/cio/device_ops.c     2005-03-02 
17:00:12.000000000 +0100
@@ -81,6 +81,16 @@
                return -ENODEV;
        if (cdev->private->state == DEV_STATE_NOT_OPER)
                return -ENODEV;
+       if (cdev->private->state == DEV_STATE_VERIFY) {
+               /* Remember to fake irb when finished. */
+               if (!cdev->private->flags.fake_irb) {
+                       cdev->private->flags.fake_irb = 1;
+                       cdev->private->intparm = intparm;
+                       return 0;
+               } else
+                       /* There's already a fake I/O around. */
+                       return -EBUSY;
+       }
        if (cdev->private->state != DEV_STATE_ONLINE ||
            ((sch->schib.scsw.stctl & SCSW_STCTL_PRIM_STATUS) &&
             !(sch->schib.scsw.stctl & SCSW_STCTL_SEC_STATUS)) ||
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to