diff options
| author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2006-10-11 09:31:41 -0400 |
|---|---|---|
| committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2006-10-11 09:31:41 -0400 |
| commit | e7769b48a0216d7262fe2ba59b1b3697be462cbb (patch) | |
| tree | a46d8a60d428c24183309ec5de08676ffc504191 /drivers | |
| parent | 789642680518b28e7dc13f96061460a8238ec622 (diff) | |
[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: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/s390/cio/chsc.c | 17 | ||||
| -rw-r--r-- | drivers/s390/cio/css.h | 2 | ||||
| -rw-r--r-- | drivers/s390/cio/device.h | 1 | ||||
| -rw-r--r-- | drivers/s390/cio/device_fsm.c | 68 | ||||
| -rw-r--r-- | drivers/s390/cio/device_ops.c | 2 |
5 files changed, 14 insertions, 76 deletions
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 07c7f19339d2..eabe018d348f 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
| @@ -707,8 +707,7 @@ chp_process_crw(int chpid, int on) | |||
| 707 | return chp_add(chpid); | 707 | return chp_add(chpid); |
| 708 | } | 708 | } |
| 709 | 709 | ||
| 710 | static inline int | 710 | static inline int check_for_io_on_path(struct subchannel *sch, int index) |
| 711 | __check_for_io_and_kill(struct subchannel *sch, int index) | ||
| 712 | { | 711 | { |
| 713 | int cc; | 712 | int cc; |
| 714 | 713 | ||
| @@ -718,10 +717,8 @@ __check_for_io_and_kill(struct subchannel *sch, int index) | |||
| 718 | cc = stsch(sch->schid, &sch->schib); | 717 | cc = stsch(sch->schid, &sch->schib); |
| 719 | if (cc) | 718 | if (cc) |
| 720 | return 0; | 719 | return 0; |
| 721 | if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == (0x80 >> index)) { | 720 | if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == (0x80 >> index)) |
| 722 | device_set_waiting(sch); | ||
| 723 | return 1; | 721 | return 1; |
| 724 | } | ||
| 725 | return 0; | 722 | return 0; |
| 726 | } | 723 | } |
| 727 | 724 | ||
| @@ -750,12 +747,10 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on) | |||
| 750 | } else { | 747 | } else { |
| 751 | sch->opm &= ~(0x80 >> chp); | 748 | sch->opm &= ~(0x80 >> chp); |
| 752 | sch->lpm &= ~(0x80 >> chp); | 749 | sch->lpm &= ~(0x80 >> chp); |
| 753 | /* | 750 | if (check_for_io_on_path(sch, chp)) |
| 754 | * Give running I/O a grace period in which it | 751 | /* Path verification is done after killing. */ |
| 755 | * can successfully terminate, even using the | 752 | device_kill_io(sch); |
| 756 | * just varied off path. Then kill it. | 753 | else if (!sch->lpm) { |
| 757 | */ | ||
| 758 | if (!__check_for_io_and_kill(sch, chp) && !sch->lpm) { | ||
| 759 | if (css_enqueue_subchannel_slow(sch->schid)) { | 754 | if (css_enqueue_subchannel_slow(sch->schid)) { |
| 760 | css_clear_subchannel_slow_list(); | 755 | css_clear_subchannel_slow_list(); |
| 761 | need_rescan = 1; | 756 | need_rescan = 1; |
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index 15bd1e28ed70..4c2ff8336288 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h | |||
| @@ -170,7 +170,7 @@ void device_trigger_reprobe(struct subchannel *); | |||
| 170 | 170 | ||
| 171 | /* Helper functions for vary on/off. */ | 171 | /* Helper functions for vary on/off. */ |
| 172 | int device_is_online(struct subchannel *); | 172 | int device_is_online(struct subchannel *); |
| 173 | void device_set_waiting(struct subchannel *); | 173 | void device_kill_io(struct subchannel *); |
| 174 | 174 | ||
| 175 | /* Machine check helper function. */ | 175 | /* Machine check helper function. */ |
| 176 | void device_kill_pending_timer(struct subchannel *); | 176 | void device_kill_pending_timer(struct subchannel *); |
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index 00be9a5b4acd..c6140cc97a80 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h | |||
| @@ -21,7 +21,6 @@ enum dev_state { | |||
| 21 | /* states to wait for i/o completion before doing something */ | 21 | /* states to wait for i/o completion before doing something */ |
| 22 | DEV_STATE_CLEAR_VERIFY, | 22 | DEV_STATE_CLEAR_VERIFY, |
| 23 | DEV_STATE_TIMEOUT_KILL, | 23 | DEV_STATE_TIMEOUT_KILL, |
| 24 | DEV_STATE_WAIT4IO, | ||
| 25 | DEV_STATE_QUIESCE, | 24 | DEV_STATE_QUIESCE, |
| 26 | /* special states for devices gone not operational */ | 25 | /* special states for devices gone not operational */ |
| 27 | DEV_STATE_DISCONNECTED, | 26 | DEV_STATE_DISCONNECTED, |
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 392eb33f3a9c..44e4a53c5981 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c | |||
| @@ -59,18 +59,6 @@ device_set_disconnected(struct subchannel *sch) | |||
| 59 | cdev->private->state = DEV_STATE_DISCONNECTED; | 59 | cdev->private->state = DEV_STATE_DISCONNECTED; |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | void | ||
| 63 | device_set_waiting(struct subchannel *sch) | ||
| 64 | { | ||
| 65 | struct ccw_device *cdev; | ||
| 66 | |||
| 67 | if (!sch->dev.driver_data) | ||
| 68 | return; | ||
| 69 | cdev = sch->dev.driver_data; | ||
| 70 | ccw_device_set_timeout(cdev, 10*HZ); | ||
| 71 | cdev->private->state = DEV_STATE_WAIT4IO; | ||
| 72 | } | ||
| 73 | |||
| 74 | /* | 62 | /* |
| 75 | * Timeout function. It just triggers a DEV_EVENT_TIMEOUT. | 63 | * Timeout function. It just triggers a DEV_EVENT_TIMEOUT. |
| 76 | */ | 64 | */ |
| @@ -947,7 +935,7 @@ ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event) | |||
| 947 | cdev->private->state = DEV_STATE_ONLINE; | 935 | cdev->private->state = DEV_STATE_ONLINE; |
| 948 | if (cdev->handler) | 936 | if (cdev->handler) |
| 949 | cdev->handler(cdev, cdev->private->intparm, | 937 | cdev->handler(cdev, cdev->private->intparm, |
| 950 | ERR_PTR(-ETIMEDOUT)); | 938 | ERR_PTR(-EIO)); |
| 951 | if (!sch->lpm) { | 939 | if (!sch->lpm) { |
| 952 | PREPARE_WORK(&cdev->private->kick_work, | 940 | PREPARE_WORK(&cdev->private->kick_work, |
| 953 | ccw_device_nopath_notify, (void *)cdev); | 941 | ccw_device_nopath_notify, (void *)cdev); |
| @@ -984,51 +972,15 @@ ccw_device_killing_timeout(struct ccw_device *cdev, enum dev_event dev_event) | |||
| 984 | cdev->private->state = DEV_STATE_ONLINE; | 972 | cdev->private->state = DEV_STATE_ONLINE; |
| 985 | if (cdev->handler) | 973 | if (cdev->handler) |
| 986 | cdev->handler(cdev, cdev->private->intparm, | 974 | cdev->handler(cdev, cdev->private->intparm, |
| 987 | ERR_PTR(-ETIMEDOUT)); | 975 | ERR_PTR(-EIO)); |
| 988 | } | 976 | } |
| 989 | 977 | ||
| 990 | static void | 978 | void device_kill_io(struct subchannel *sch) |
| 991 | ccw_device_wait4io_irq(struct ccw_device *cdev, enum dev_event dev_event) | ||
| 992 | { | ||
| 993 | struct irb *irb; | ||
| 994 | struct subchannel *sch; | ||
| 995 | |||
| 996 | irb = (struct irb *) __LC_IRB; | ||
| 997 | /* | ||
| 998 | * Accumulate status and find out if a basic sense is needed. | ||
| 999 | * This is fine since we have already adapted the lpm. | ||
| 1000 | */ | ||
| 1001 | ccw_device_accumulate_irb(cdev, irb); | ||
| 1002 | if (cdev->private->flags.dosense) { | ||
| 1003 | if (ccw_device_do_sense(cdev, irb) == 0) { | ||
| 1004 | cdev->private->state = DEV_STATE_W4SENSE; | ||
| 1005 | } | ||
| 1006 | return; | ||
| 1007 | } | ||
| 1008 | |||
| 1009 | /* Iff device is idle, reset timeout. */ | ||
| 1010 | sch = to_subchannel(cdev->dev.parent); | ||
| 1011 | if (!stsch(sch->schid, &sch->schib)) | ||
| 1012 | if (sch->schib.scsw.actl == 0) | ||
| 1013 | ccw_device_set_timeout(cdev, 0); | ||
| 1014 | /* Call the handler. */ | ||
| 1015 | ccw_device_call_handler(cdev); | ||
| 1016 | if (!sch->lpm) { | ||
| 1017 | PREPARE_WORK(&cdev->private->kick_work, | ||
| 1018 | ccw_device_nopath_notify, (void *)cdev); | ||
| 1019 | queue_work(ccw_device_notify_work, &cdev->private->kick_work); | ||
| 1020 | } else if (cdev->private->flags.doverify) | ||
| 1021 | ccw_device_online_verify(cdev, 0); | ||
| 1022 | } | ||
| 1023 | |||
| 1024 | static void | ||
| 1025 | ccw_device_wait4io_timeout(struct ccw_device *cdev, enum dev_event dev_event) | ||
| 1026 | { | 979 | { |
| 1027 | int ret; | 980 | int ret; |
| 1028 | struct subchannel *sch; | 981 | struct ccw_device *cdev; |
| 1029 | 982 | ||
| 1030 | sch = to_subchannel(cdev->dev.parent); | 983 | cdev = sch->dev.driver_data; |
| 1031 | ccw_device_set_timeout(cdev, 0); | ||
| 1032 | ret = ccw_device_cancel_halt_clear(cdev); | 984 | ret = ccw_device_cancel_halt_clear(cdev); |
| 1033 | if (ret == -EBUSY) { | 985 | if (ret == -EBUSY) { |
| 1034 | ccw_device_set_timeout(cdev, 3*HZ); | 986 | 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 | } | 999 | } |
| 1048 | if (cdev->handler) | 1000 | if (cdev->handler) |
| 1049 | cdev->handler(cdev, cdev->private->intparm, | 1001 | cdev->handler(cdev, cdev->private->intparm, |
| 1050 | ERR_PTR(-ETIMEDOUT)); | 1002 | ERR_PTR(-EIO)); |
| 1051 | if (!sch->lpm) { | 1003 | if (!sch->lpm) { |
| 1052 | PREPARE_WORK(&cdev->private->kick_work, | 1004 | PREPARE_WORK(&cdev->private->kick_work, |
| 1053 | ccw_device_nopath_notify, (void *)cdev); | 1005 | ccw_device_nopath_notify, (void *)cdev); |
| 1054 | queue_work(ccw_device_notify_work, &cdev->private->kick_work); | 1006 | queue_work(ccw_device_notify_work, &cdev->private->kick_work); |
| 1055 | } else if (cdev->private->flags.doverify) | 1007 | } else |
| 1056 | /* Start delayed path verification. */ | 1008 | /* Start delayed path verification. */ |
| 1057 | ccw_device_online_verify(cdev, 0); | 1009 | ccw_device_online_verify(cdev, 0); |
| 1058 | } | 1010 | } |
| @@ -1289,12 +1241,6 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = { | |||
| 1289 | [DEV_EVENT_TIMEOUT] = ccw_device_killing_timeout, | 1241 | [DEV_EVENT_TIMEOUT] = ccw_device_killing_timeout, |
| 1290 | [DEV_EVENT_VERIFY] = ccw_device_nop, //FIXME | 1242 | [DEV_EVENT_VERIFY] = ccw_device_nop, //FIXME |
| 1291 | }, | 1243 | }, |
| 1292 | [DEV_STATE_WAIT4IO] = { | ||
| 1293 | [DEV_EVENT_NOTOPER] = ccw_device_online_notoper, | ||
| 1294 | [DEV_EVENT_INTERRUPT] = ccw_device_wait4io_irq, | ||
| 1295 | [DEV_EVENT_TIMEOUT] = ccw_device_wait4io_timeout, | ||
| 1296 | [DEV_EVENT_VERIFY] = ccw_device_delay_verify, | ||
| 1297 | }, | ||
| 1298 | [DEV_STATE_QUIESCE] = { | 1244 | [DEV_STATE_QUIESCE] = { |
| 1299 | [DEV_EVENT_NOTOPER] = ccw_device_quiesce_done, | 1245 | [DEV_EVENT_NOTOPER] = ccw_device_quiesce_done, |
| 1300 | [DEV_EVENT_INTERRUPT] = ccw_device_quiesce_done, | 1246 | [DEV_EVENT_INTERRUPT] = ccw_device_quiesce_done, |
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 96219935a06a..b39c1fa48acd 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c | |||
| @@ -50,7 +50,6 @@ ccw_device_clear(struct ccw_device *cdev, unsigned long intparm) | |||
| 50 | if (cdev->private->state == DEV_STATE_NOT_OPER) | 50 | if (cdev->private->state == DEV_STATE_NOT_OPER) |
| 51 | return -ENODEV; | 51 | return -ENODEV; |
| 52 | if (cdev->private->state != DEV_STATE_ONLINE && | 52 | if (cdev->private->state != DEV_STATE_ONLINE && |
| 53 | cdev->private->state != DEV_STATE_WAIT4IO && | ||
| 54 | cdev->private->state != DEV_STATE_W4SENSE) | 53 | cdev->private->state != DEV_STATE_W4SENSE) |
| 55 | return -EINVAL; | 54 | return -EINVAL; |
| 56 | sch = to_subchannel(cdev->dev.parent); | 55 | sch = to_subchannel(cdev->dev.parent); |
| @@ -155,7 +154,6 @@ ccw_device_halt(struct ccw_device *cdev, unsigned long intparm) | |||
| 155 | if (cdev->private->state == DEV_STATE_NOT_OPER) | 154 | if (cdev->private->state == DEV_STATE_NOT_OPER) |
| 156 | return -ENODEV; | 155 | return -ENODEV; |
| 157 | if (cdev->private->state != DEV_STATE_ONLINE && | 156 | if (cdev->private->state != DEV_STATE_ONLINE && |
| 158 | cdev->private->state != DEV_STATE_WAIT4IO && | ||
| 159 | cdev->private->state != DEV_STATE_W4SENSE) | 157 | cdev->private->state != DEV_STATE_W4SENSE) |
| 160 | return -EINVAL; | 158 | return -EINVAL; |
| 161 | sch = to_subchannel(cdev->dev.parent); | 159 | sch = to_subchannel(cdev->dev.parent); |
