]> err.no Git - linux-2.6/blobdiff - drivers/s390/cio/device_fsm.c
Merge master.kernel.org:/home/rmk/linux-2.6-arm
[linux-2.6] / drivers / s390 / cio / device_fsm.c
index 8baa9cd3794cdc14a47d1e6f625c1fbd8fe8164c..8633dc537695db3a99a03d35e462133fca0fa829 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <asm/ccwdev.h>
 #include <asm/cio.h>
+#include <asm/chpid.h>
 
 #include "cio.h"
 #include "cio_debug.h"
@@ -22,6 +23,7 @@
 #include "device.h"
 #include "chsc.h"
 #include "ioasm.h"
+#include "chp.h"
 
 int
 device_is_online(struct subchannel *sch)
@@ -144,8 +146,8 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev)
        ret = stsch(sch->schid, &sch->schib);
        if (ret || !sch->schib.pmcw.dnv)
                return -ENODEV; 
-       if (!sch->schib.pmcw.ena || sch->schib.scsw.actl == 0)
-               /* Not operational or no activity -> done. */
+       if (!sch->schib.pmcw.ena)
+               /* Not operational -> done. */
                return 0;
        /* Stage 1: cancel io. */
        if (!(sch->schib.scsw.actl & SCSW_ACTL_HALT_PEND) &&
@@ -210,14 +212,18 @@ static void
 __recover_lost_chpids(struct subchannel *sch, int old_lpm)
 {
        int mask, i;
+       struct chp_id chpid;
 
+       chp_id_init(&chpid);
        for (i = 0; i<8; i++) {
                mask = 0x80 >> i;
                if (!(sch->lpm & mask))
                        continue;
                if (old_lpm & mask)
                        continue;
-               chpid_is_actually_online(sch->schib.pmcw.chpid[i]);
+               chpid.id = sch->schib.pmcw.chpid[i];
+               if (!chp_is_registered(chpid))
+                       css_schedule_eval_all();
        }
 }
 
@@ -262,7 +268,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
        switch (state) {
        case DEV_STATE_NOT_OPER:
                CIO_DEBUG(KERN_WARNING, 2,
-                         "SenseID : unknown device %04x on subchannel "
+                         "cio: SenseID : unknown device %04x on subchannel "
                          "0.%x.%04x\n", cdev->private->dev_id.devno,
                          sch->schid.ssid, sch->schid.sch_no);
                break;
@@ -287,7 +293,8 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
                        return;
                }
                /* Issue device info message. */
-               CIO_DEBUG(KERN_INFO, 2, "SenseID : device 0.%x.%04x reports: "
+               CIO_DEBUG(KERN_INFO, 2,
+                         "cio: SenseID : device 0.%x.%04x reports: "
                          "CU  Type/Mod = %04X/%02X, Dev Type/Mod = "
                          "%04X/%02X\n",
                          cdev->private->dev_id.ssid,
@@ -297,7 +304,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
                break;
        case DEV_STATE_BOXED:
                CIO_DEBUG(KERN_WARNING, 2,
-                         "SenseID : boxed device %04x on subchannel "
+                         "cio: SenseID : boxed device %04x on subchannel "
                          "0.%x.%04x\n", cdev->private->dev_id.devno,
                          sch->schid.ssid, sch->schid.sch_no);
                break;
@@ -382,7 +389,7 @@ 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",
+                         "cio: Boxed device %04x on subchannel %04x\n",
                          cdev->private->dev_id.devno, sch->schid.sch_no);
 
        if (cdev->private->flags.donotify) {
@@ -682,6 +689,12 @@ ccw_device_disband_done(struct ccw_device *cdev, int err)
                ccw_device_done(cdev, DEV_STATE_BOXED);
                break;
        default:
+               cdev->private->flags.donotify = 0;
+               if (get_device(&cdev->dev)) {
+                       PREPARE_WORK(&cdev->private->kick_work,
+                                    ccw_device_call_sch_unregister);
+                       queue_work(ccw_device_work, &cdev->private->kick_work);
+               }
                ccw_device_done(cdev, DEV_STATE_NOT_OPER);
                break;
        }
@@ -934,9 +947,10 @@ 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(KERN_INFO "Huh? %s(%s): unsolicited "
-                              "interrupt...\n",
-                              __FUNCTION__, cdev->dev.bus_id);
+                       CIO_MSG_EVENT(2, "Huh? 0.%x.%04x: unsolicited "
+                                     "interrupt during w4sense...\n",
+                                     cdev->private->dev_id.ssid,
+                                     cdev->private->dev_id.devno);
                        if (cdev->handler)
                                cdev->handler (cdev, 0, irb);
                }
@@ -996,18 +1010,12 @@ ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event)
 
        sch = to_subchannel(cdev->dev.parent);
        ccw_device_set_timeout(cdev, 0);
+       /* Start delayed path verification. */
+       ccw_device_online_verify(cdev, 0);
        /* OK, i/o is dead now. Call interrupt handler. */
-       cdev->private->state = DEV_STATE_ONLINE;
        if (cdev->handler)
                cdev->handler(cdev, cdev->private->intparm,
                              ERR_PTR(-EIO));
-       if (!sch->lpm) {
-               PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_nopath_notify);
-               queue_work(ccw_device_notify_work, &cdev->private->kick_work);
-       } else if (cdev->private->flags.doverify)
-               /* Start delayed path verification. */
-               ccw_device_online_verify(cdev, 0);
 }
 
 static void
@@ -1020,21 +1028,8 @@ ccw_device_killing_timeout(struct ccw_device *cdev, enum dev_event dev_event)
                ccw_device_set_timeout(cdev, 3*HZ);
                return;
        }
-       if (ret == -ENODEV) {
-               struct subchannel *sch;
-
-               sch = to_subchannel(cdev->dev.parent);
-               if (!sch->lpm) {
-                       PREPARE_WORK(&cdev->private->kick_work,
-                                    ccw_device_nopath_notify);
-                       queue_work(ccw_device_notify_work,
-                                  &cdev->private->kick_work);
-               } else
-                       dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
-               return;
-       }
-       //FIXME: Can we get here?
-       cdev->private->state = DEV_STATE_ONLINE;
+       /* Start delayed path verification. */
+       ccw_device_online_verify(cdev, 0);
        if (cdev->handler)
                cdev->handler(cdev, cdev->private->intparm,
                              ERR_PTR(-EIO));
@@ -1052,26 +1047,11 @@ void device_kill_io(struct subchannel *sch)
                cdev->private->state = DEV_STATE_TIMEOUT_KILL;
                return;
        }
-       if (ret == -ENODEV) {
-               if (!sch->lpm) {
-                       PREPARE_WORK(&cdev->private->kick_work,
-                                    ccw_device_nopath_notify);
-                       queue_work(ccw_device_notify_work,
-                                  &cdev->private->kick_work);
-               } else
-                       dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
-               return;
-       }
+       /* Start delayed path verification. */
+       ccw_device_online_verify(cdev, 0);
        if (cdev->handler)
                cdev->handler(cdev, cdev->private->intparm,
                              ERR_PTR(-EIO));
-       if (!sch->lpm) {
-               PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_nopath_notify);
-               queue_work(ccw_device_notify_work, &cdev->private->kick_work);
-       } else
-               /* Start delayed path verification. */
-               ccw_device_online_verify(cdev, 0);
 }
 
 static void
@@ -1237,8 +1217,8 @@ ccw_device_nop(struct ccw_device *cdev, enum dev_event dev_event)
 static void
 ccw_device_bug(struct ccw_device *cdev, enum dev_event dev_event)
 {
-       printk(KERN_EMERG "dev_jumptable[%i][%i] == NULL\n",
-              cdev->private->state, dev_event);
+       CIO_MSG_EVENT(0, "dev_jumptable[%i][%i] == NULL\n",
+                     cdev->private->state, dev_event);
        BUG();
 }