Commit e7769b48 authored by Cornelia Huck's avatar Cornelia Huck Committed by Martin Schwidefsky

[S390] cio: Remove grace period for vary off chpid.

The grace period handling introduced needless complexity. It didn't
help the dasd driver (which can handle terminated I/O just well),
and it doesn't help for long running channel programs (which won't
complete during the grace period anyway). Terminating I/O using a
path that just disappeared immediately is much more consistent with
what the user expects.
Signed-off-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 78964268
...@@ -707,8 +707,7 @@ chp_process_crw(int chpid, int on) ...@@ -707,8 +707,7 @@ chp_process_crw(int chpid, int on)
return chp_add(chpid); return chp_add(chpid);
} }
static inline int static inline int check_for_io_on_path(struct subchannel *sch, int index)
__check_for_io_and_kill(struct subchannel *sch, int index)
{ {
int cc; int cc;
...@@ -718,10 +717,8 @@ __check_for_io_and_kill(struct subchannel *sch, int index) ...@@ -718,10 +717,8 @@ __check_for_io_and_kill(struct subchannel *sch, int index)
cc = stsch(sch->schid, &sch->schib); cc = stsch(sch->schid, &sch->schib);
if (cc) if (cc)
return 0; return 0;
if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == (0x80 >> index)) { if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == (0x80 >> index))
device_set_waiting(sch);
return 1; return 1;
}
return 0; return 0;
} }
...@@ -750,12 +747,10 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on) ...@@ -750,12 +747,10 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
} else { } else {
sch->opm &= ~(0x80 >> chp); sch->opm &= ~(0x80 >> chp);
sch->lpm &= ~(0x80 >> chp); sch->lpm &= ~(0x80 >> chp);
/* if (check_for_io_on_path(sch, chp))
* Give running I/O a grace period in which it /* Path verification is done after killing. */
* can successfully terminate, even using the device_kill_io(sch);
* just varied off path. Then kill it. else if (!sch->lpm) {
*/
if (!__check_for_io_and_kill(sch, chp) && !sch->lpm) {
if (css_enqueue_subchannel_slow(sch->schid)) { if (css_enqueue_subchannel_slow(sch->schid)) {
css_clear_subchannel_slow_list(); css_clear_subchannel_slow_list();
need_rescan = 1; need_rescan = 1;
......
...@@ -170,7 +170,7 @@ void device_trigger_reprobe(struct subchannel *); ...@@ -170,7 +170,7 @@ void device_trigger_reprobe(struct subchannel *);
/* Helper functions for vary on/off. */ /* Helper functions for vary on/off. */
int device_is_online(struct subchannel *); int device_is_online(struct subchannel *);
void device_set_waiting(struct subchannel *); void device_kill_io(struct subchannel *);
/* Machine check helper function. */ /* Machine check helper function. */
void device_kill_pending_timer(struct subchannel *); void device_kill_pending_timer(struct subchannel *);
......
...@@ -21,7 +21,6 @@ enum dev_state { ...@@ -21,7 +21,6 @@ enum dev_state {
/* states to wait for i/o completion before doing something */ /* states to wait for i/o completion before doing something */
DEV_STATE_CLEAR_VERIFY, DEV_STATE_CLEAR_VERIFY,
DEV_STATE_TIMEOUT_KILL, DEV_STATE_TIMEOUT_KILL,
DEV_STATE_WAIT4IO,
DEV_STATE_QUIESCE, DEV_STATE_QUIESCE,
/* special states for devices gone not operational */ /* special states for devices gone not operational */
DEV_STATE_DISCONNECTED, DEV_STATE_DISCONNECTED,
......
...@@ -59,18 +59,6 @@ device_set_disconnected(struct subchannel *sch) ...@@ -59,18 +59,6 @@ device_set_disconnected(struct subchannel *sch)
cdev->private->state = DEV_STATE_DISCONNECTED; 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. * Timeout function. It just triggers a DEV_EVENT_TIMEOUT.
*/ */
...@@ -947,7 +935,7 @@ ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event) ...@@ -947,7 +935,7 @@ ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event)
cdev->private->state = DEV_STATE_ONLINE; cdev->private->state = DEV_STATE_ONLINE;
if (cdev->handler) if (cdev->handler)
cdev->handler(cdev, cdev->private->intparm, cdev->handler(cdev, cdev->private->intparm,
ERR_PTR(-ETIMEDOUT)); ERR_PTR(-EIO));
if (!sch->lpm) { if (!sch->lpm) {
PREPARE_WORK(&cdev->private->kick_work, PREPARE_WORK(&cdev->private->kick_work,
ccw_device_nopath_notify, (void *)cdev); ccw_device_nopath_notify, (void *)cdev);
...@@ -984,51 +972,15 @@ ccw_device_killing_timeout(struct ccw_device *cdev, enum dev_event dev_event) ...@@ -984,51 +972,15 @@ ccw_device_killing_timeout(struct ccw_device *cdev, enum dev_event dev_event)
cdev->private->state = DEV_STATE_ONLINE; cdev->private->state = DEV_STATE_ONLINE;
if (cdev->handler) if (cdev->handler)
cdev->handler(cdev, cdev->private->intparm, cdev->handler(cdev, cdev->private->intparm,
ERR_PTR(-ETIMEDOUT)); ERR_PTR(-EIO));
} }
static void void device_kill_io(struct subchannel *sch)
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);
}
static void
ccw_device_wait4io_timeout(struct ccw_device *cdev, enum dev_event dev_event)
{ {
int ret; int ret;
struct subchannel *sch; struct ccw_device *cdev;
sch = to_subchannel(cdev->dev.parent); cdev = sch->dev.driver_data;
ccw_device_set_timeout(cdev, 0);
ret = ccw_device_cancel_halt_clear(cdev); ret = ccw_device_cancel_halt_clear(cdev);
if (ret == -EBUSY) { if (ret == -EBUSY) {
ccw_device_set_timeout(cdev, 3*HZ); ccw_device_set_timeout(cdev, 3*HZ);
...@@ -1047,12 +999,12 @@ ccw_device_wait4io_timeout(struct ccw_device *cdev, enum dev_event dev_event) ...@@ -1047,12 +999,12 @@ ccw_device_wait4io_timeout(struct ccw_device *cdev, enum dev_event dev_event)
} }
if (cdev->handler) if (cdev->handler)
cdev->handler(cdev, cdev->private->intparm, cdev->handler(cdev, cdev->private->intparm,
ERR_PTR(-ETIMEDOUT)); ERR_PTR(-EIO));
if (!sch->lpm) { if (!sch->lpm) {
PREPARE_WORK(&cdev->private->kick_work, PREPARE_WORK(&cdev->private->kick_work,
ccw_device_nopath_notify, (void *)cdev); ccw_device_nopath_notify, (void *)cdev);
queue_work(ccw_device_notify_work, &cdev->private->kick_work); queue_work(ccw_device_notify_work, &cdev->private->kick_work);
} else if (cdev->private->flags.doverify) } else
/* Start delayed path verification. */ /* Start delayed path verification. */
ccw_device_online_verify(cdev, 0); ccw_device_online_verify(cdev, 0);
} }
...@@ -1289,12 +1241,6 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = { ...@@ -1289,12 +1241,6 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = {
[DEV_EVENT_TIMEOUT] = ccw_device_killing_timeout, [DEV_EVENT_TIMEOUT] = ccw_device_killing_timeout,
[DEV_EVENT_VERIFY] = ccw_device_nop, //FIXME [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_STATE_QUIESCE] = {
[DEV_EVENT_NOTOPER] = ccw_device_quiesce_done, [DEV_EVENT_NOTOPER] = ccw_device_quiesce_done,
[DEV_EVENT_INTERRUPT] = ccw_device_quiesce_done, [DEV_EVENT_INTERRUPT] = ccw_device_quiesce_done,
......
...@@ -50,7 +50,6 @@ ccw_device_clear(struct ccw_device *cdev, unsigned long intparm) ...@@ -50,7 +50,6 @@ ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
if (cdev->private->state == DEV_STATE_NOT_OPER) if (cdev->private->state == DEV_STATE_NOT_OPER)
return -ENODEV; return -ENODEV;
if (cdev->private->state != DEV_STATE_ONLINE && if (cdev->private->state != DEV_STATE_ONLINE &&
cdev->private->state != DEV_STATE_WAIT4IO &&
cdev->private->state != DEV_STATE_W4SENSE) cdev->private->state != DEV_STATE_W4SENSE)
return -EINVAL; return -EINVAL;
sch = to_subchannel(cdev->dev.parent); sch = to_subchannel(cdev->dev.parent);
...@@ -155,7 +154,6 @@ ccw_device_halt(struct ccw_device *cdev, unsigned long intparm) ...@@ -155,7 +154,6 @@ ccw_device_halt(struct ccw_device *cdev, unsigned long intparm)
if (cdev->private->state == DEV_STATE_NOT_OPER) if (cdev->private->state == DEV_STATE_NOT_OPER)
return -ENODEV; return -ENODEV;
if (cdev->private->state != DEV_STATE_ONLINE && if (cdev->private->state != DEV_STATE_ONLINE &&
cdev->private->state != DEV_STATE_WAIT4IO &&
cdev->private->state != DEV_STATE_W4SENSE) cdev->private->state != DEV_STATE_W4SENSE)
return -EINVAL; return -EINVAL;
sch = to_subchannel(cdev->dev.parent); sch = to_subchannel(cdev->dev.parent);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment