X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fs390%2Fcio%2Fdevice_fsm.c;h=cacebad072a8bbd849ce950eba6014af65355382;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=03b569b4b1a0533277e0da600a19568931775851;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 03b569b4b..cacebad07 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -93,6 +93,18 @@ ccw_device_set_timeout(struct ccw_device *cdev, int expires) add_timer(&cdev->private->timer); } +/* Kill any pending timers after machine check. */ +void +device_kill_pending_timer(struct subchannel *sch) +{ + struct ccw_device *cdev; + + if (!sch->dev.driver_data) + return; + cdev = sch->dev.driver_data; + ccw_device_set_timeout(cdev, 0); +} + /* * Cancel running i/o. This is called repeatedly since halt/clear are * asynchronous operations. We do one try with cio_cancel, two tries @@ -142,7 +154,7 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev) panic("Can't stop i/o on subchannel.\n"); } -static void +static int ccw_device_handle_oper(struct ccw_device *cdev) { struct subchannel *sch; @@ -162,9 +174,10 @@ ccw_device_handle_oper(struct ccw_device *cdev) PREPARE_WORK(&cdev->private->kick_work, ccw_device_do_unreg_rereg, (void *)cdev); queue_work(ccw_device_work, &cdev->private->kick_work); - return; + return 0; } cdev->private->flags.donotify = 1; + return 1; } /* @@ -194,7 +207,7 @@ static void ccw_device_recog_done(struct ccw_device *cdev, int state) { struct subchannel *sch; - int notify, old_lpm; + int notify, old_lpm, same_dev; sch = to_subchannel(cdev->dev.parent); @@ -224,6 +237,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) /* Boxed devices don't need extra treatment. */ } notify = 0; + same_dev = 0; /* Keep the compiler quiet... */ switch (state) { case DEV_STATE_NOT_OPER: CIO_DEBUG(KERN_WARNING, 2, @@ -232,7 +246,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) break; case DEV_STATE_OFFLINE: if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) { - ccw_device_handle_oper(cdev); + same_dev = ccw_device_handle_oper(cdev); notify = 1; } /* fill out sense information */ @@ -243,10 +257,12 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) .dev_model = cdev->private->senseid.dev_model, }; if (notify) { - /* Get device online again. */ cdev->private->state = DEV_STATE_OFFLINE; - ccw_device_online(cdev); - wake_up(&cdev->private->wait_q); + if (same_dev) { + /* Get device online again. */ + ccw_device_online(cdev); + wake_up(&cdev->private->wait_q); + } return; } /* Issue device info message. */ @@ -452,7 +468,8 @@ ccw_device_nopath_notify(void *data) (void *)cdev); queue_work(ccw_device_work, &cdev->private->kick_work); - } + } else + put_device(&sch->dev); } } else { cio_disable_subchannel(sch); @@ -1190,8 +1207,8 @@ io_subchannel_irq (struct device *pdev) CIO_TRACE_EVENT (3, "IRQ"); CIO_TRACE_EVENT (3, pdev->bus_id); - - dev_fsm_event(cdev, DEV_EVENT_INTERRUPT); + if (cdev) + dev_fsm_event(cdev, DEV_EVENT_INTERRUPT); } EXPORT_SYMBOL_GPL(ccw_device_set_timeout);