diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2008-07-14 03:58:45 -0400 |
---|---|---|
committer | Heiko Carstens <heiko.carstens@de.ibm.com> | 2008-07-14 04:02:05 -0400 |
commit | c820de39bd083222f5be2563181c87493e436f7c (patch) | |
tree | 4861db1aeca00d55d76b5844ad209d81a2795105 /drivers/s390/cio/device_fsm.c | |
parent | 7e9db9eaefdb8798730790214ff1b7746006ec98 (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.c | 106 |
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 | ||
28 | static int timeout_log_enabled; | 27 | static int timeout_log_enabled; |
29 | 28 | ||
30 | int | ||
31 | device_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 | |||
41 | int | ||
42 | device_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 | |||
53 | void | ||
54 | device_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 | |||
68 | void 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 | |||
78 | int 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 | |||
89 | static int __init ccw_timeout_log_setup(char *unused) | 29 | static 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. */ | ||
175 | void | ||
176 | device_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 | ||
319 | int 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 | |||
391 | static void | 328 | static void |
392 | ccw_device_oper_notify(struct work_struct *work) | 329 | ccw_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 | ||
989 | void device_kill_io(struct subchannel *sch) | 919 | void 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 | ||
1058 | void | 986 | void ccw_device_trigger_reprobe(struct ccw_device *cdev) |
1059 | device_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) { |