aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCornelia Huck <cornelia.huck@de.ibm.com>2006-10-11 09:31:41 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2006-10-11 09:31:41 -0400
commite7769b48a0216d7262fe2ba59b1b3697be462cbb (patch)
treea46d8a60d428c24183309ec5de08676ffc504191
parent789642680518b28e7dc13f96061460a8238ec622 (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>
-rw-r--r--drivers/s390/cio/chsc.c17
-rw-r--r--drivers/s390/cio/css.h2
-rw-r--r--drivers/s390/cio/device.h1
-rw-r--r--drivers/s390/cio/device_fsm.c68
-rw-r--r--drivers/s390/cio/device_ops.c2
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
710static inline int 710static 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. */
172int device_is_online(struct subchannel *); 172int device_is_online(struct subchannel *);
173void device_set_waiting(struct subchannel *); 173void device_kill_io(struct subchannel *);
174 174
175/* Machine check helper function. */ 175/* Machine check helper function. */
176void device_kill_pending_timer(struct subchannel *); 176void 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
62void
63device_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
990static void 978void device_kill_io(struct subchannel *sch)
991ccw_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
1024static void
1025ccw_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);