]> err.no Git - linux-2.6/commitdiff
[S390] cio: Make isc handling more robust.
authorCornelia Huck <cornelia.huck@de.ibm.com>
Wed, 30 Apr 2008 11:38:39 +0000 (13:38 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 30 Apr 2008 11:38:45 +0000 (13:38 +0200)
Introduce an ->isc field in the subchannel to store the desired
interruption subclass, since sch->schib.pmcw.isc may be overwritten
by the hardware on stsch() after machine checks.

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
drivers/s390/cio/cio.c
drivers/s390/cio/cio.h
drivers/s390/cio/device_fsm.c
drivers/s390/cio/device_ops.c

index 23ffcc4768a7dba3a30cf6935ef261bb97c00b2a..08a578161306e1088f4fe6786ea85b518cfd7a12 100644 (file)
@@ -407,8 +407,7 @@ cio_modify (struct subchannel *sch)
 /*
  * Enable subchannel.
  */
-int cio_enable_subchannel(struct subchannel *sch, unsigned int isc,
-                         u32 intparm)
+int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
 {
        char dbf_txt[15];
        int ccode;
@@ -426,7 +425,7 @@ int cio_enable_subchannel(struct subchannel *sch, unsigned int isc,
 
        for (retry = 5, ret = 0; retry > 0; retry--) {
                sch->schib.pmcw.ena = 1;
-               sch->schib.pmcw.isc = isc;
+               sch->schib.pmcw.isc = sch->isc;
                sch->schib.pmcw.intparm = intparm;
                ret = cio_modify(sch);
                if (ret == -ENODEV)
@@ -600,6 +599,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
        else
                sch->opm = chp_get_sch_opm(sch);
        sch->lpm = sch->schib.pmcw.pam & sch->opm;
+       sch->isc = 3;
 
        CIO_DEBUG(KERN_INFO, 0,
                  "Detected device %04x on subchannel 0.%x.%04X"
@@ -610,13 +610,11 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
 
        /*
         * We now have to initially ...
-        *  ... set "interruption subclass"
         *  ... enable "concurrent sense"
         *  ... enable "multipath mode" if more than one
         *        CHPID is available. This is done regardless
         *        whether multiple paths are available for us.
         */
-       sch->schib.pmcw.isc = 3;        /* could be smth. else */
        sch->schib.pmcw.csense = 1;     /* concurrent sense */
        sch->schib.pmcw.ena = 0;
        if ((sch->lpm & (sch->lpm - 1)) != 0)
@@ -812,6 +810,7 @@ cio_probe_console(void)
         * enable console I/O-interrupt subclass 7
         */
        ctl_set_bit(6, 24);
+       console_subchannel.isc = 7;
        console_subchannel.schib.pmcw.isc = 7;
        console_subchannel.schib.pmcw.intparm =
                (u32)(addr_t)&console_subchannel;
index 08f2235c5a6fa0f38dc05f36f8e19bafec75986f..3c75412904dc495eade9f6627b148adc730e6e82 100644 (file)
@@ -74,6 +74,7 @@ struct subchannel {
        __u8 lpm;               /* logical path mask */
        __u8 opm;               /* operational path mask */
        struct schib schib;     /* subchannel information block */
+       int isc; /* desired interruption subclass */
        struct chsc_ssd_info ssd_info;  /* subchannel description */
        struct device dev;      /* entry in device tree */
        struct css_driver *driver;
@@ -85,7 +86,7 @@ struct subchannel {
 #define to_subchannel(n) container_of(n, struct subchannel, dev)
 
 extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id);
-extern int cio_enable_subchannel(struct subchannel *, unsigned int, u32);
+extern int cio_enable_subchannel(struct subchannel *, u32);
 extern int cio_disable_subchannel (struct subchannel *);
 extern int cio_cancel (struct subchannel *);
 extern int cio_clear (struct subchannel *);
index 4b92c84fb438440874eeb9ea4cb42b5f72965739..99403b0a97a7737a4865f72d41453048d1fb2600 100644 (file)
@@ -555,8 +555,7 @@ ccw_device_recognition(struct ccw_device *cdev)
            (cdev->private->state != DEV_STATE_BOXED))
                return -EINVAL;
        sch = to_subchannel(cdev->dev.parent);
-       ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc,
-                                   (u32)(addr_t)sch);
+       ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
        if (ret != 0)
                /* Couldn't enable the subchannel for i/o. Sick device. */
                return ret;
@@ -667,8 +666,7 @@ ccw_device_online(struct ccw_device *cdev)
        sch = to_subchannel(cdev->dev.parent);
        if (css_init_done && !get_device(&cdev->dev))
                return -ENODEV;
-       ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc,
-                                   (u32)(addr_t)sch);
+       ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
        if (ret != 0) {
                /* Couldn't enable the subchannel for i/o. Sick device. */
                if (ret == -ENODEV)
@@ -1048,8 +1046,7 @@ ccw_device_start_id(struct ccw_device *cdev, enum dev_event dev_event)
        struct subchannel *sch;
 
        sch = to_subchannel(cdev->dev.parent);
-       if (cio_enable_subchannel(sch, sch->schib.pmcw.isc,
-                                 (u32)(addr_t)sch) != 0)
+       if (cio_enable_subchannel(sch, (u32)(addr_t)sch) != 0)
                /* Couldn't enable the subchannel for i/o. Sick device. */
                return;
 
@@ -1082,7 +1079,6 @@ device_trigger_reprobe(struct subchannel *sch)
         */
        sch->lpm = sch->schib.pmcw.pam & sch->opm;
        /* Re-set some bits in the pmcw that were lost. */
-       sch->schib.pmcw.isc = 3;
        sch->schib.pmcw.csense = 1;
        sch->schib.pmcw.ena = 0;
        if ((sch->lpm & (sch->lpm - 1)) != 0)
index a1718a0aa539d07bb5f9852597b25f18ae3b3c75..f308ad55a6d5bed173b2fc5ee71197069bd764cc 100644 (file)
@@ -508,7 +508,7 @@ ccw_device_stlck(struct ccw_device *cdev)
                return -ENOMEM;
        }
        spin_lock_irqsave(sch->lock, flags);
-       ret = cio_enable_subchannel(sch, 3, (u32)(addr_t)sch);
+       ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
        if (ret)
                goto out_unlock;
        /*