Skip to content

Commit

Permalink
[S390] cio: Remove grace period for vary off chpid.
Browse files Browse the repository at this point in the history
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: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Cornelia Huck authored and Martin Schwidefsky committed Oct 11, 2006
1 parent 7896426 commit e7769b4
Show file tree
Hide file tree
Showing 5 changed files with 14 additions and 76 deletions.
17 changes: 6 additions & 11 deletions drivers/s390/cio/chsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -707,8 +707,7 @@ chp_process_crw(int chpid, int on)
return chp_add(chpid);
}

static inline int
__check_for_io_and_kill(struct subchannel *sch, int index)
static inline int check_for_io_on_path(struct subchannel *sch, int index)
{
int cc;

Expand All @@ -718,10 +717,8 @@ __check_for_io_and_kill(struct subchannel *sch, int index)
cc = stsch(sch->schid, &sch->schib);
if (cc)
return 0;
if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == (0x80 >> index)) {
device_set_waiting(sch);
if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == (0x80 >> index))
return 1;
}
return 0;
}

Expand Down Expand Up @@ -750,12 +747,10 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
} else {
sch->opm &= ~(0x80 >> chp);
sch->lpm &= ~(0x80 >> chp);
/*
* Give running I/O a grace period in which it
* can successfully terminate, even using the
* just varied off path. Then kill it.
*/
if (!__check_for_io_and_kill(sch, chp) && !sch->lpm) {
if (check_for_io_on_path(sch, chp))
/* Path verification is done after killing. */
device_kill_io(sch);
else if (!sch->lpm) {
if (css_enqueue_subchannel_slow(sch->schid)) {
css_clear_subchannel_slow_list();
need_rescan = 1;
Expand Down
2 changes: 1 addition & 1 deletion drivers/s390/cio/css.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ void device_trigger_reprobe(struct subchannel *);

/* Helper functions for vary on/off. */
int device_is_online(struct subchannel *);
void device_set_waiting(struct subchannel *);
void device_kill_io(struct subchannel *);

/* Machine check helper function. */
void device_kill_pending_timer(struct subchannel *);
Expand Down
1 change: 0 additions & 1 deletion drivers/s390/cio/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ enum dev_state {
/* states to wait for i/o completion before doing something */
DEV_STATE_CLEAR_VERIFY,
DEV_STATE_TIMEOUT_KILL,
DEV_STATE_WAIT4IO,
DEV_STATE_QUIESCE,
/* special states for devices gone not operational */
DEV_STATE_DISCONNECTED,
Expand Down
68 changes: 7 additions & 61 deletions drivers/s390/cio/device_fsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -947,7 +935,7 @@ 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);
Expand Down Expand Up @@ -984,51 +972,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));
ERR_PTR(-EIO));
}

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);
}

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);
Expand All @@ -1047,12 +999,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);
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);
}
Expand Down Expand Up @@ -1289,12 +1241,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,
Expand Down
2 changes: 0 additions & 2 deletions drivers/s390/cio/device_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
if (cdev->private->state == DEV_STATE_NOT_OPER)
return -ENODEV;
if (cdev->private->state != DEV_STATE_ONLINE &&
cdev->private->state != DEV_STATE_WAIT4IO &&
cdev->private->state != DEV_STATE_W4SENSE)
return -EINVAL;
sch = to_subchannel(cdev->dev.parent);
Expand Down Expand Up @@ -155,7 +154,6 @@ ccw_device_halt(struct ccw_device *cdev, unsigned long intparm)
if (cdev->private->state == DEV_STATE_NOT_OPER)
return -ENODEV;
if (cdev->private->state != DEV_STATE_ONLINE &&
cdev->private->state != DEV_STATE_WAIT4IO &&
cdev->private->state != DEV_STATE_W4SENSE)
return -EINVAL;
sch = to_subchannel(cdev->dev.parent);
Expand Down

0 comments on commit e7769b4

Please sign in to comment.