aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/device_fsm.c
diff options
context:
space:
mode:
authorCornelia Huck <cornelia.huck@de.ibm.com>2008-07-14 03:58:45 -0400
committerHeiko Carstens <heiko.carstens@de.ibm.com>2008-07-14 04:02:05 -0400
commitc820de39bd083222f5be2563181c87493e436f7c (patch)
tree4861db1aeca00d55d76b5844ad209d81a2795105 /drivers/s390/cio/device_fsm.c
parent7e9db9eaefdb8798730790214ff1b7746006ec98 (diff)
[S390] cio: Rework css driver.
Rework the css driver methods to provide sane callbacks for subchannels of all types. As a bonus, this cleans up and simplyfies the machine check handling for I/O subchannels a lot. Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio/device_fsm.c')
-rw-r--r--drivers/s390/cio/device_fsm.c106
1 files changed, 15 insertions, 91 deletions
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index e268d5a77c12..c9b97cbc2203 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -2,8 +2,7 @@
2 * drivers/s390/cio/device_fsm.c 2 * drivers/s390/cio/device_fsm.c
3 * finite state machine for device handling 3 * finite state machine for device handling
4 * 4 *
5 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, 5 * Copyright IBM Corp. 2002,2008
6 * IBM Corporation
7 * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com) 6 * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
8 * Martin Schwidefsky (schwidefsky@de.ibm.com) 7 * Martin Schwidefsky (schwidefsky@de.ibm.com)
9 */ 8 */
@@ -27,65 +26,6 @@
27 26
28static int timeout_log_enabled; 27static int timeout_log_enabled;
29 28
30int
31device_is_online(struct subchannel *sch)
32{
33 struct ccw_device *cdev;
34
35 cdev = sch_get_cdev(sch);
36 if (!cdev)
37 return 0;
38 return (cdev->private->state == DEV_STATE_ONLINE);
39}
40
41int
42device_is_disconnected(struct subchannel *sch)
43{
44 struct ccw_device *cdev;
45
46 cdev = sch_get_cdev(sch);
47 if (!cdev)
48 return 0;
49 return (cdev->private->state == DEV_STATE_DISCONNECTED ||
50 cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID);
51}
52
53void
54device_set_disconnected(struct subchannel *sch)
55{
56 struct ccw_device *cdev;
57
58 cdev = sch_get_cdev(sch);
59 if (!cdev)
60 return;
61 ccw_device_set_timeout(cdev, 0);
62 cdev->private->flags.fake_irb = 0;
63 cdev->private->state = DEV_STATE_DISCONNECTED;
64 if (cdev->online)
65 ccw_device_schedule_recovery();
66}
67
68void device_set_intretry(struct subchannel *sch)
69{
70 struct ccw_device *cdev;
71
72 cdev = sch_get_cdev(sch);
73 if (!cdev)
74 return;
75 cdev->private->flags.intretry = 1;
76}
77
78int device_trigger_verify(struct subchannel *sch)
79{
80 struct ccw_device *cdev;
81
82 cdev = sch_get_cdev(sch);
83 if (!cdev || !cdev->online)
84 return -EINVAL;
85 dev_fsm_event(cdev, DEV_EVENT_VERIFY);
86 return 0;
87}
88
89static int __init ccw_timeout_log_setup(char *unused) 29static int __init ccw_timeout_log_setup(char *unused)
90{ 30{
91 timeout_log_enabled = 1; 31 timeout_log_enabled = 1;
@@ -171,18 +111,6 @@ ccw_device_set_timeout(struct ccw_device *cdev, int expires)
171 add_timer(&cdev->private->timer); 111 add_timer(&cdev->private->timer);
172} 112}
173 113
174/* Kill any pending timers after machine check. */
175void
176device_kill_pending_timer(struct subchannel *sch)
177{
178 struct ccw_device *cdev;
179
180 cdev = sch_get_cdev(sch);
181 if (!cdev)
182 return;
183 ccw_device_set_timeout(cdev, 0);
184}
185
186/* 114/*
187 * Cancel running i/o. This is called repeatedly since halt/clear are 115 * Cancel running i/o. This is called repeatedly since halt/clear are
188 * asynchronous operations. We do one try with cio_cancel, two tries 116 * asynchronous operations. We do one try with cio_cancel, two tries
@@ -388,25 +316,27 @@ ccw_device_sense_id_done(struct ccw_device *cdev, int err)
388 } 316 }
389} 317}
390 318
319int ccw_device_notify(struct ccw_device *cdev, int event)
320{
321 if (!cdev->drv)
322 return 0;
323 if (!cdev->online)
324 return 0;
325 return cdev->drv->notify ? cdev->drv->notify(cdev, event) : 0;
326}
327
391static void 328static void
392ccw_device_oper_notify(struct work_struct *work) 329ccw_device_oper_notify(struct work_struct *work)
393{ 330{
394 struct ccw_device_private *priv; 331 struct ccw_device_private *priv;
395 struct ccw_device *cdev; 332 struct ccw_device *cdev;
396 struct subchannel *sch;
397 int ret; 333 int ret;
398 unsigned long flags; 334 unsigned long flags;
399 335
400 priv = container_of(work, struct ccw_device_private, kick_work); 336 priv = container_of(work, struct ccw_device_private, kick_work);
401 cdev = priv->cdev; 337 cdev = priv->cdev;
338 ret = ccw_device_notify(cdev, CIO_OPER);
402 spin_lock_irqsave(cdev->ccwlock, flags); 339 spin_lock_irqsave(cdev->ccwlock, flags);
403 sch = to_subchannel(cdev->dev.parent);
404 if (sch->driver && sch->driver->notify) {
405 spin_unlock_irqrestore(cdev->ccwlock, flags);
406 ret = sch->driver->notify(sch, CIO_OPER);
407 spin_lock_irqsave(cdev->ccwlock, flags);
408 } else
409 ret = 0;
410 if (ret) { 340 if (ret) {
411 /* Reenable channel measurements, if needed. */ 341 /* Reenable channel measurements, if needed. */
412 spin_unlock_irqrestore(cdev->ccwlock, flags); 342 spin_unlock_irqrestore(cdev->ccwlock, flags);
@@ -986,12 +916,10 @@ ccw_device_killing_timeout(struct ccw_device *cdev, enum dev_event dev_event)
986 ERR_PTR(-EIO)); 916 ERR_PTR(-EIO));
987} 917}
988 918
989void device_kill_io(struct subchannel *sch) 919void ccw_device_kill_io(struct ccw_device *cdev)
990{ 920{
991 int ret; 921 int ret;
992 struct ccw_device *cdev;
993 922
994 cdev = sch_get_cdev(sch);
995 ret = ccw_device_cancel_halt_clear(cdev); 923 ret = ccw_device_cancel_halt_clear(cdev);
996 if (ret == -EBUSY) { 924 if (ret == -EBUSY) {
997 ccw_device_set_timeout(cdev, 3*HZ); 925 ccw_device_set_timeout(cdev, 3*HZ);
@@ -1055,17 +983,14 @@ ccw_device_start_id(struct ccw_device *cdev, enum dev_event dev_event)
1055 ccw_device_sense_id_start(cdev); 983 ccw_device_sense_id_start(cdev);
1056} 984}
1057 985
1058void 986void ccw_device_trigger_reprobe(struct ccw_device *cdev)
1059device_trigger_reprobe(struct subchannel *sch)
1060{ 987{
1061 struct ccw_device *cdev; 988 struct subchannel *sch;
1062 989
1063 cdev = sch_get_cdev(sch);
1064 if (!cdev)
1065 return;
1066 if (cdev->private->state != DEV_STATE_DISCONNECTED) 990 if (cdev->private->state != DEV_STATE_DISCONNECTED)
1067 return; 991 return;
1068 992
993 sch = to_subchannel(cdev->dev.parent);
1069 /* Update some values. */ 994 /* Update some values. */
1070 if (stsch(sch->schid, &sch->schib)) 995 if (stsch(sch->schid, &sch->schib))
1071 return; 996 return;
@@ -1081,7 +1006,6 @@ device_trigger_reprobe(struct subchannel *sch)
1081 sch->schib.pmcw.ena = 0; 1006 sch->schib.pmcw.ena = 0;
1082 if ((sch->lpm & (sch->lpm - 1)) != 0) 1007 if ((sch->lpm & (sch->lpm - 1)) != 0)
1083 sch->schib.pmcw.mp = 1; 1008 sch->schib.pmcw.mp = 1;
1084 sch->schib.pmcw.intparm = (u32)(addr_t)sch;
1085 /* We should also udate ssd info, but this has to wait. */ 1009 /* We should also udate ssd info, but this has to wait. */
1086 /* Check if this is another device which appeared on the same sch. */ 1010 /* Check if this is another device which appeared on the same sch. */
1087 if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) { 1011 if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) {