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/s390 | |
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/s390')
-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); |