Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[pandora-kernel.git] / drivers / s390 / cio / device_fsm.c
index 8b6be21..4b92c84 100644 (file)
@@ -32,9 +32,9 @@ device_is_online(struct subchannel *sch)
 {
        struct ccw_device *cdev;
 
-       if (!sch->dev.driver_data)
+       cdev = sch_get_cdev(sch);
+       if (!cdev)
                return 0;
-       cdev = sch->dev.driver_data;
        return (cdev->private->state == DEV_STATE_ONLINE);
 }
 
@@ -43,9 +43,9 @@ device_is_disconnected(struct subchannel *sch)
 {
        struct ccw_device *cdev;
 
-       if (!sch->dev.driver_data)
+       cdev = sch_get_cdev(sch);
+       if (!cdev)
                return 0;
-       cdev = sch->dev.driver_data;
        return (cdev->private->state == DEV_STATE_DISCONNECTED ||
                cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID);
 }
@@ -55,19 +55,21 @@ device_set_disconnected(struct subchannel *sch)
 {
        struct ccw_device *cdev;
 
-       if (!sch->dev.driver_data)
+       cdev = sch_get_cdev(sch);
+       if (!cdev)
                return;
-       cdev = sch->dev.driver_data;
        ccw_device_set_timeout(cdev, 0);
        cdev->private->flags.fake_irb = 0;
        cdev->private->state = DEV_STATE_DISCONNECTED;
+       if (cdev->online)
+               ccw_device_schedule_recovery();
 }
 
 void device_set_intretry(struct subchannel *sch)
 {
        struct ccw_device *cdev;
 
-       cdev = sch->dev.driver_data;
+       cdev = sch_get_cdev(sch);
        if (!cdev)
                return;
        cdev->private->flags.intretry = 1;
@@ -77,7 +79,7 @@ int device_trigger_verify(struct subchannel *sch)
 {
        struct ccw_device *cdev;
 
-       cdev = sch->dev.driver_data;
+       cdev = sch_get_cdev(sch);
        if (!cdev || !cdev->online)
                return -EINVAL;
        dev_fsm_event(cdev, DEV_EVENT_VERIFY);
@@ -96,29 +98,32 @@ static void ccw_timeout_log(struct ccw_device *cdev)
 {
        struct schib schib;
        struct subchannel *sch;
+       struct io_subchannel_private *private;
        int cc;
 
        sch = to_subchannel(cdev->dev.parent);
+       private = to_io_private(sch);
        cc = stsch(sch->schid, &schib);
 
        printk(KERN_WARNING "cio: ccw device timeout occurred at %llx, "
               "device information:\n", get_clock());
        printk(KERN_WARNING "cio: orb:\n");
        print_hex_dump(KERN_WARNING, "cio:  ", DUMP_PREFIX_NONE, 16, 1,
-                      &sch->orb, sizeof(sch->orb), 0);
+                      &private->orb, sizeof(private->orb), 0);
        printk(KERN_WARNING "cio: ccw device bus id: %s\n", cdev->dev.bus_id);
        printk(KERN_WARNING "cio: subchannel bus id: %s\n", sch->dev.bus_id);
        printk(KERN_WARNING "cio: subchannel lpm: %02x, opm: %02x, "
               "vpm: %02x\n", sch->lpm, sch->opm, sch->vpm);
 
-       if ((void *)(addr_t)sch->orb.cpa == &sch->sense_ccw ||
-           (void *)(addr_t)sch->orb.cpa == cdev->private->iccws)
+       if ((void *)(addr_t)private->orb.cpa == &private->sense_ccw ||
+           (void *)(addr_t)private->orb.cpa == cdev->private->iccws)
                printk(KERN_WARNING "cio: last channel program (intern):\n");
        else
                printk(KERN_WARNING "cio: last channel program:\n");
 
        print_hex_dump(KERN_WARNING, "cio:  ", DUMP_PREFIX_NONE, 16, 1,
-                      (void *)(addr_t)sch->orb.cpa, sizeof(struct ccw1), 0);
+                      (void *)(addr_t)private->orb.cpa,
+                      sizeof(struct ccw1), 0);
        printk(KERN_WARNING "cio: ccw device state: %d\n",
               cdev->private->state);
        printk(KERN_WARNING "cio: store subchannel returned: cc=%d\n", cc);
@@ -172,9 +177,9 @@ device_kill_pending_timer(struct subchannel *sch)
 {
        struct ccw_device *cdev;
 
-       if (!sch->dev.driver_data)
+       cdev = sch_get_cdev(sch);
+       if (!cdev)
                return;
-       cdev = sch->dev.driver_data;
        ccw_device_set_timeout(cdev, 0);
 }
 
@@ -550,7 +555,8 @@ 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);
+       ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc,
+                                   (u32)(addr_t)sch);
        if (ret != 0)
                /* Couldn't enable the subchannel for i/o. Sick device. */
                return ret;
@@ -637,9 +643,10 @@ ccw_device_verify_done(struct ccw_device *cdev, int err)
        default:
                /* Reset oper notify indication after verify error. */
                cdev->private->flags.donotify = 0;
-               if (cdev->online)
+               if (cdev->online) {
+                       ccw_device_set_timeout(cdev, 0);
                        dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
-               else
+               else
                        ccw_device_done(cdev, DEV_STATE_NOT_OPER);
                break;
        }
@@ -660,7 +667,8 @@ 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);
+       ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc,
+                                   (u32)(addr_t)sch);
        if (ret != 0) {
                /* Couldn't enable the subchannel for i/o. Sick device. */
                if (ret == -ENODEV)
@@ -987,7 +995,7 @@ void device_kill_io(struct subchannel *sch)
        int ret;
        struct ccw_device *cdev;
 
-       cdev = sch->dev.driver_data;
+       cdev = sch_get_cdev(sch);
        ret = ccw_device_cancel_halt_clear(cdev);
        if (ret == -EBUSY) {
                ccw_device_set_timeout(cdev, 3*HZ);
@@ -1040,7 +1048,8 @@ 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) != 0)
+       if (cio_enable_subchannel(sch, sch->schib.pmcw.isc,
+                                 (u32)(addr_t)sch) != 0)
                /* Couldn't enable the subchannel for i/o. Sick device. */
                return;
 
@@ -1056,9 +1065,9 @@ device_trigger_reprobe(struct subchannel *sch)
 {
        struct ccw_device *cdev;
 
-       if (!sch->dev.driver_data)
+       cdev = sch_get_cdev(sch);
+       if (!cdev)
                return;
-       cdev = sch->dev.driver_data;
        if (cdev->private->state != DEV_STATE_DISCONNECTED)
                return;
 
@@ -1078,7 +1087,7 @@ device_trigger_reprobe(struct subchannel *sch)
        sch->schib.pmcw.ena = 0;
        if ((sch->lpm & (sch->lpm - 1)) != 0)
                sch->schib.pmcw.mp = 1;
-       sch->schib.pmcw.intparm = (__u32)(unsigned long)sch;
+       sch->schib.pmcw.intparm = (u32)(addr_t)sch;
        /* We should also udate ssd info, but this has to wait. */
        /* Check if this is another device which appeared on the same sch. */
        if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) {