]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/s390/cio/device_fsm.c
Merge branch 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6
[linux-2.6-omap-h63xx.git] / drivers / s390 / cio / device_fsm.c
index dace46fc32e8d74e0e12657f159295f02061663f..de3d0857db9fb83b3526a5d0557876d35dc2b154 100644 (file)
@@ -59,18 +59,6 @@ device_set_disconnected(struct subchannel *sch)
        cdev->private->state = DEV_STATE_DISCONNECTED;
 }
 
-void
-device_set_waiting(struct subchannel *sch)
-{
-       struct ccw_device *cdev;
-
-       if (!sch->dev.driver_data)
-               return;
-       cdev = sch->dev.driver_data;
-       ccw_device_set_timeout(cdev, 10*HZ);
-       cdev->private->state = DEV_STATE_WAIT4IO;
-}
-
 /*
  * Timeout function. It just triggers a DEV_EVENT_TIMEOUT.
  */
@@ -183,9 +171,9 @@ ccw_device_handle_oper(struct ccw_device *cdev)
            cdev->id.cu_model != cdev->private->senseid.cu_model ||
            cdev->id.dev_type != cdev->private->senseid.dev_type ||
            cdev->id.dev_model != cdev->private->senseid.dev_model ||
-           cdev->private->devno != sch->schib.pmcw.dev) {
+           cdev->private->dev_id.devno != sch->schib.pmcw.dev) {
                PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_do_unreg_rereg, (void *)cdev);
+                            ccw_device_do_unreg_rereg, cdev);
                queue_work(ccw_device_work, &cdev->private->kick_work);
                return 0;
        }
@@ -255,7 +243,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
        case DEV_STATE_NOT_OPER:
                CIO_DEBUG(KERN_WARNING, 2,
                          "SenseID : unknown device %04x on subchannel "
-                         "0.%x.%04x\n", cdev->private->devno,
+                         "0.%x.%04x\n", cdev->private->dev_id.devno,
                          sch->schid.ssid, sch->schid.sch_no);
                break;
        case DEV_STATE_OFFLINE:
@@ -282,14 +270,15 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
                CIO_DEBUG(KERN_INFO, 2, "SenseID : device 0.%x.%04x reports: "
                          "CU  Type/Mod = %04X/%02X, Dev Type/Mod = "
                          "%04X/%02X\n",
-                         cdev->private->ssid, cdev->private->devno,
+                         cdev->private->dev_id.ssid,
+                         cdev->private->dev_id.devno,
                          cdev->id.cu_type, cdev->id.cu_model,
                          cdev->id.dev_type, cdev->id.dev_model);
                break;
        case DEV_STATE_BOXED:
                CIO_DEBUG(KERN_WARNING, 2,
                          "SenseID : boxed device %04x on subchannel "
-                         "0.%x.%04x\n", cdev->private->devno,
+                         "0.%x.%04x\n", cdev->private->dev_id.devno,
                          sch->schid.ssid, sch->schid.sch_no);
                break;
        }
@@ -325,13 +314,13 @@ ccw_device_oper_notify(void *data)
        struct subchannel *sch;
        int ret;
 
-       cdev = (struct ccw_device *)data;
+       cdev = data;
        sch = to_subchannel(cdev->dev.parent);
        ret = (sch->driver && sch->driver->notify) ?
                sch->driver->notify(&sch->dev, CIO_OPER) : 0;
        if (!ret)
                /* Driver doesn't want device back. */
-               ccw_device_do_unreg_rereg((void *)cdev);
+               ccw_device_do_unreg_rereg(cdev);
        else {
                /* Reenable channel measurements, if needed. */
                cmf_reenable(cdev);
@@ -349,6 +338,8 @@ ccw_device_done(struct ccw_device *cdev, int state)
 
        sch = to_subchannel(cdev->dev.parent);
 
+       ccw_device_set_timeout(cdev, 0);
+
        if (state != DEV_STATE_ONLINE)
                cio_disable_subchannel(sch);
 
@@ -361,12 +352,12 @@ ccw_device_done(struct ccw_device *cdev, int state)
        if (state == DEV_STATE_BOXED)
                CIO_DEBUG(KERN_WARNING, 2,
                          "Boxed device %04x on subchannel %04x\n",
-                         cdev->private->devno, sch->schid.sch_no);
+                         cdev->private->dev_id.devno, sch->schid.sch_no);
 
        if (cdev->private->flags.donotify) {
                cdev->private->flags.donotify = 0;
                PREPARE_WORK(&cdev->private->kick_work, ccw_device_oper_notify,
-                            (void *)cdev);
+                            cdev);
                queue_work(ccw_device_notify_work, &cdev->private->kick_work);
        }
        wake_up(&cdev->private->wait_q);
@@ -410,7 +401,8 @@ static void __ccw_device_get_common_pgid(struct ccw_device *cdev)
                /* PGID mismatch, can't pathgroup. */
                CIO_MSG_EVENT(0, "SNID - pgid mismatch for device "
                              "0.%x.%04x, can't pathgroup\n",
-                             cdev->private->ssid, cdev->private->devno);
+                             cdev->private->dev_id.ssid,
+                             cdev->private->dev_id.devno);
                cdev->private->options.pgroup = 0;
                return;
        }
@@ -521,7 +513,7 @@ ccw_device_nopath_notify(void *data)
        struct subchannel *sch;
        int ret;
 
-       cdev = (struct ccw_device *)data;
+       cdev = data;
        sch = to_subchannel(cdev->dev.parent);
        /* Extra sanity. */
        if (sch->lpm)
@@ -535,7 +527,7 @@ ccw_device_nopath_notify(void *data)
                        if (get_device(&cdev->dev)) {
                                PREPARE_WORK(&cdev->private->kick_work,
                                             ccw_device_call_sch_unregister,
-                                            (void *)cdev);
+                                            cdev);
                                queue_work(ccw_device_work,
                                           &cdev->private->kick_work);
                        } else
@@ -586,11 +578,15 @@ ccw_device_verify_done(struct ccw_device *cdev, int err)
                }
                break;
        case -ETIME:
+               /* Reset oper notify indication after verify error. */
+               cdev->private->flags.donotify = 0;
                ccw_device_done(cdev, DEV_STATE_BOXED);
                break;
        default:
+               /* Reset oper notify indication after verify error. */
+               cdev->private->flags.donotify = 0;
                PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_nopath_notify, (void *)cdev);
+                            ccw_device_nopath_notify, cdev);
                queue_work(ccw_device_notify_work, &cdev->private->kick_work);
                ccw_device_done(cdev, DEV_STATE_NOT_OPER);
                break;
@@ -721,7 +717,7 @@ ccw_device_offline_notoper(struct ccw_device *cdev, enum dev_event dev_event)
        sch = to_subchannel(cdev->dev.parent);
        if (get_device(&cdev->dev)) {
                PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_call_sch_unregister, (void *)cdev);
+                            ccw_device_call_sch_unregister, cdev);
                queue_work(ccw_device_work, &cdev->private->kick_work);
        }
        wake_up(&cdev->private->wait_q);
@@ -752,7 +748,7 @@ ccw_device_online_notoper(struct ccw_device *cdev, enum dev_event dev_event)
        }
        if (get_device(&cdev->dev)) {
                PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_call_sch_unregister, (void *)cdev);
+                            ccw_device_call_sch_unregister, cdev);
                queue_work(ccw_device_work, &cdev->private->kick_work);
        }
        wake_up(&cdev->private->wait_q);
@@ -857,7 +853,7 @@ ccw_device_online_timeout(struct ccw_device *cdev, enum dev_event dev_event)
                sch = to_subchannel(cdev->dev.parent);
                if (!sch->lpm) {
                        PREPARE_WORK(&cdev->private->kick_work,
-                                    ccw_device_nopath_notify, (void *)cdev);
+                                    ccw_device_nopath_notify, cdev);
                        queue_work(ccw_device_notify_work,
                                   &cdev->private->kick_work);
                } else
@@ -883,7 +879,8 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event)
                        /* Basic sense hasn't started. Try again. */
                        ccw_device_do_sense(cdev, irb);
                else {
-                       printk("Huh? %s(%s): unsolicited interrupt...\n",
+                       printk(KERN_INFO "Huh? %s(%s): unsolicited "
+                              "interrupt...\n",
                               __FUNCTION__, cdev->dev.bus_id);
                        if (cdev->handler)
                                cdev->handler (cdev, 0, irb);
@@ -942,10 +939,10 @@ ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event)
        cdev->private->state = DEV_STATE_ONLINE;
        if (cdev->handler)
                cdev->handler(cdev, cdev->private->intparm,
-                             ERR_PTR(-ETIMEDOUT));
+                             ERR_PTR(-EIO));
        if (!sch->lpm) {
                PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_nopath_notify, (void *)cdev);
+                            ccw_device_nopath_notify, cdev);
                queue_work(ccw_device_notify_work, &cdev->private->kick_work);
        } else if (cdev->private->flags.doverify)
                /* Start delayed path verification. */
@@ -968,7 +965,7 @@ ccw_device_killing_timeout(struct ccw_device *cdev, enum dev_event dev_event)
                sch = to_subchannel(cdev->dev.parent);
                if (!sch->lpm) {
                        PREPARE_WORK(&cdev->private->kick_work,
-                                    ccw_device_nopath_notify, (void *)cdev);
+                                    ccw_device_nopath_notify, cdev);
                        queue_work(ccw_device_notify_work,
                                   &cdev->private->kick_work);
                } else
@@ -979,51 +976,15 @@ ccw_device_killing_timeout(struct ccw_device *cdev, enum dev_event dev_event)
        cdev->private->state = DEV_STATE_ONLINE;
        if (cdev->handler)
                cdev->handler(cdev, cdev->private->intparm,
-                             ERR_PTR(-ETIMEDOUT));
-}
-
-static void
-ccw_device_wait4io_irq(struct ccw_device *cdev, enum dev_event dev_event)
-{
-       struct irb *irb;
-       struct subchannel *sch;
-
-       irb = (struct irb *) __LC_IRB;
-       /*
-        * Accumulate status and find out if a basic sense is needed.
-        * This is fine since we have already adapted the lpm.
-        */
-       ccw_device_accumulate_irb(cdev, irb);
-       if (cdev->private->flags.dosense) {
-               if (ccw_device_do_sense(cdev, irb) == 0) {
-                       cdev->private->state = DEV_STATE_W4SENSE;
-               }
-               return;
-       }
-
-       /* Iff device is idle, reset timeout. */
-       sch = to_subchannel(cdev->dev.parent);
-       if (!stsch(sch->schid, &sch->schib))
-               if (sch->schib.scsw.actl == 0)
-                       ccw_device_set_timeout(cdev, 0);
-       /* Call the handler. */
-       ccw_device_call_handler(cdev);
-       if (!sch->lpm) {
-               PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_nopath_notify, (void *)cdev);
-               queue_work(ccw_device_notify_work, &cdev->private->kick_work);
-       } else if (cdev->private->flags.doverify)
-               ccw_device_online_verify(cdev, 0);
+                             ERR_PTR(-EIO));
 }
 
-static void
-ccw_device_wait4io_timeout(struct ccw_device *cdev, enum dev_event dev_event)
+void device_kill_io(struct subchannel *sch)
 {
        int ret;
-       struct subchannel *sch;
+       struct ccw_device *cdev;
 
-       sch = to_subchannel(cdev->dev.parent);
-       ccw_device_set_timeout(cdev, 0);
+       cdev = sch->dev.driver_data;
        ret = ccw_device_cancel_halt_clear(cdev);
        if (ret == -EBUSY) {
                ccw_device_set_timeout(cdev, 3*HZ);
@@ -1033,7 +994,7 @@ ccw_device_wait4io_timeout(struct ccw_device *cdev, enum dev_event dev_event)
        if (ret == -ENODEV) {
                if (!sch->lpm) {
                        PREPARE_WORK(&cdev->private->kick_work,
-                                    ccw_device_nopath_notify, (void *)cdev);
+                                    ccw_device_nopath_notify, cdev);
                        queue_work(ccw_device_notify_work,
                                   &cdev->private->kick_work);
                } else
@@ -1042,12 +1003,12 @@ ccw_device_wait4io_timeout(struct ccw_device *cdev, enum dev_event dev_event)
        }
        if (cdev->handler)
                cdev->handler(cdev, cdev->private->intparm,
-                             ERR_PTR(-ETIMEDOUT));
+                             ERR_PTR(-EIO));
        if (!sch->lpm) {
                PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_nopath_notify, (void *)cdev);
+                            ccw_device_nopath_notify, cdev);
                queue_work(ccw_device_notify_work, &cdev->private->kick_work);
-       } else if (cdev->private->flags.doverify)
+       } else
                /* Start delayed path verification. */
                ccw_device_online_verify(cdev, 0);
 }
@@ -1284,12 +1245,6 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = {
                [DEV_EVENT_TIMEOUT]     = ccw_device_killing_timeout,
                [DEV_EVENT_VERIFY]      = ccw_device_nop, //FIXME
        },
-       [DEV_STATE_WAIT4IO] = {
-               [DEV_EVENT_NOTOPER]     = ccw_device_online_notoper,
-               [DEV_EVENT_INTERRUPT]   = ccw_device_wait4io_irq,
-               [DEV_EVENT_TIMEOUT]     = ccw_device_wait4io_timeout,
-               [DEV_EVENT_VERIFY]      = ccw_device_delay_verify,
-       },
        [DEV_STATE_QUIESCE] = {
                [DEV_EVENT_NOTOPER]     = ccw_device_quiesce_done,
                [DEV_EVENT_INTERRUPT]   = ccw_device_quiesce_done,