]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From: Gerald Schaefer <geraldsc@de.ibm.com> |
2 | Subject: cio: notify ccw driver for boxed devices | |
3 | References: bnc#487755,LTC#52560 | |
4 | ||
5 | Symptom: Dasd driver keeps trying to start io on not accessible device. | |
6 | Problem: Missing notification for ccw device drivers. | |
7 | Solution: Add proper notification if a device goes into boxed state. | |
8 | ||
9 | Acked-by: John Jolly <jjolly@suse.de> | |
10 | --- | |
11 | Documentation/kmsg/s390/zfcp | 15 +++++++++++++++ | |
12 | arch/s390/include/asm/cio.h | 2 ++ | |
13 | drivers/s390/block/dasd.c | 1 + | |
14 | drivers/s390/cio/device.c | 26 +++++++++++++++++--------- | |
15 | drivers/s390/cio/device.h | 1 + | |
16 | drivers/s390/cio/device_fsm.c | 29 ++++++++++++++++++----------- | |
17 | drivers/s390/scsi/zfcp_ccw.c | 5 +++++ | |
18 | 7 files changed, 59 insertions(+), 20 deletions(-) | |
19 | ||
20 | --- a/Documentation/kmsg/s390/zfcp | |
21 | +++ b/Documentation/kmsg/s390/zfcp | |
22 | @@ -100,6 +100,21 @@ | |
23 | */ | |
24 | ||
25 | /*? | |
26 | + * Text: "%s: The FCP device did not respond within the specified time\n" | |
27 | + * Severity: Warning | |
28 | + * Parameter: | |
29 | + * @1: bus ID of the zfcp device | |
30 | + * Description: | |
31 | + * The common I/O layer waited for a response from the FCP adapter but | |
32 | + * no response was received within the specified time limit. This might | |
33 | + * indicate a hardware problem. | |
34 | + * User action: | |
35 | + * Consult your hardware administrator. If this problem persists, | |
36 | + * gather Linux debug data, collect the FCP adapter hardware logs, and | |
37 | + * report the problem to your support organization. | |
38 | + */ | |
39 | + | |
40 | +/*? | |
41 | * Text: "%s: Registering the FCP device with the SCSI stack failed\n" | |
42 | * Severity: Error | |
43 | * Parameter: | |
44 | --- a/arch/s390/include/asm/cio.h | |
45 | +++ b/arch/s390/include/asm/cio.h | |
46 | @@ -456,6 +456,8 @@ struct ciw { | |
47 | #define CIO_OPER 0x0004 | |
48 | /* Sick revalidation of device. */ | |
49 | #define CIO_REVALIDATE 0x0008 | |
50 | +/* Device did not respond in time. */ | |
51 | +#define CIO_BOXED 0x0010 | |
52 | ||
53 | /** | |
54 | * struct ccw_dev_id - unique identifier for ccw devices | |
55 | --- a/drivers/s390/block/dasd.c | |
56 | +++ b/drivers/s390/block/dasd.c | |
57 | @@ -2359,6 +2359,7 @@ int dasd_generic_notify(struct ccw_devic | |
58 | ret = 0; | |
59 | switch (event) { | |
60 | case CIO_GONE: | |
61 | + case CIO_BOXED: | |
62 | case CIO_NO_PATH: | |
63 | /* First of all call extended error reporting. */ | |
64 | dasd_eer_write(device, NULL, DASD_EER_NOPATH); | |
65 | --- a/drivers/s390/cio/device.c | |
66 | +++ b/drivers/s390/cio/device.c | |
67 | @@ -479,11 +479,15 @@ static int online_store_recog_and_online | |
68 | } | |
69 | wait_event(cdev->private->wait_q, | |
70 | cdev->private->flags.recog_done); | |
71 | + if (cdev->private->state != DEV_STATE_OFFLINE) | |
72 | + /* recognition failed */ | |
73 | + return -EAGAIN; | |
74 | } | |
75 | if (cdev->drv && cdev->drv->set_online) | |
76 | ccw_device_set_online(cdev); | |
77 | return 0; | |
78 | } | |
79 | + | |
80 | static int online_store_handle_online(struct ccw_device *cdev, int force) | |
81 | { | |
82 | int ret; | |
83 | @@ -497,7 +501,9 @@ static int online_store_handle_online(st | |
84 | return ret; | |
85 | if (cdev->id.cu_type == 0) | |
86 | cdev->private->state = DEV_STATE_NOT_OPER; | |
87 | - online_store_recog_and_online(cdev); | |
88 | + ret = online_store_recog_and_online(cdev); | |
89 | + if (ret) | |
90 | + return ret; | |
91 | } | |
92 | return 0; | |
93 | } | |
94 | @@ -1017,33 +1023,35 @@ static void ccw_device_call_sch_unregist | |
95 | put_device(&sch->dev); | |
96 | } | |
97 | ||
98 | +void ccw_device_schedule_sch_unregister(struct ccw_device *cdev) | |
99 | +{ | |
100 | + PREPARE_WORK(&cdev->private->kick_work, | |
101 | + ccw_device_call_sch_unregister); | |
102 | + queue_work(slow_path_wq, &cdev->private->kick_work); | |
103 | +} | |
104 | + | |
105 | /* | |
106 | * subchannel recognition done. Called from the state machine. | |
107 | */ | |
108 | void | |
109 | io_subchannel_recog_done(struct ccw_device *cdev) | |
110 | { | |
111 | - struct subchannel *sch; | |
112 | - | |
113 | if (css_init_done == 0) { | |
114 | cdev->private->flags.recog_done = 1; | |
115 | return; | |
116 | } | |
117 | switch (cdev->private->state) { | |
118 | + case DEV_STATE_BOXED: | |
119 | + /* Device did not respond in time. */ | |
120 | case DEV_STATE_NOT_OPER: | |
121 | cdev->private->flags.recog_done = 1; | |
122 | /* Remove device found not operational. */ | |
123 | if (!get_device(&cdev->dev)) | |
124 | break; | |
125 | - sch = to_subchannel(cdev->dev.parent); | |
126 | - PREPARE_WORK(&cdev->private->kick_work, | |
127 | - ccw_device_call_sch_unregister); | |
128 | - queue_work(slow_path_wq, &cdev->private->kick_work); | |
129 | + ccw_device_schedule_sch_unregister(cdev); | |
130 | if (atomic_dec_and_test(&ccw_device_init_count)) | |
131 | wake_up(&ccw_device_init_wq); | |
132 | break; | |
133 | - case DEV_STATE_BOXED: | |
134 | - /* Device did not respond in time. */ | |
135 | case DEV_STATE_OFFLINE: | |
136 | /* | |
137 | * We can't register the device in interrupt context so | |
138 | --- a/drivers/s390/cio/device.h | |
139 | +++ b/drivers/s390/cio/device.h | |
140 | @@ -86,6 +86,7 @@ int ccw_device_is_orphan(struct ccw_devi | |
141 | int ccw_device_recognition(struct ccw_device *); | |
142 | int ccw_device_online(struct ccw_device *); | |
143 | int ccw_device_offline(struct ccw_device *); | |
144 | +void ccw_device_schedule_sch_unregister(struct ccw_device *); | |
145 | ||
146 | /* Function prototypes for device status and basic sense stuff. */ | |
147 | void ccw_device_accumulate_irb(struct ccw_device *, struct irb *); | |
148 | --- a/drivers/s390/cio/device_fsm.c | |
149 | +++ b/drivers/s390/cio/device_fsm.c | |
150 | @@ -253,13 +253,12 @@ ccw_device_recog_done(struct ccw_device | |
151 | old_lpm = 0; | |
152 | if (sch->lpm != old_lpm) | |
153 | __recover_lost_chpids(sch, old_lpm); | |
154 | - if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) { | |
155 | - if (state == DEV_STATE_NOT_OPER) { | |
156 | - cdev->private->flags.recog_done = 1; | |
157 | - cdev->private->state = DEV_STATE_DISCONNECTED; | |
158 | - return; | |
159 | - } | |
160 | - /* Boxed devices don't need extra treatment. */ | |
161 | + if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID && | |
162 | + (state == DEV_STATE_NOT_OPER || state == DEV_STATE_BOXED)) { | |
163 | + cdev->private->flags.recog_done = 1; | |
164 | + cdev->private->state = DEV_STATE_DISCONNECTED; | |
165 | + wake_up(&cdev->private->wait_q); | |
166 | + return; | |
167 | } | |
168 | notify = 0; | |
169 | same_dev = 0; /* Keep the compiler quiet... */ | |
170 | @@ -304,12 +303,17 @@ ccw_device_recog_done(struct ccw_device | |
171 | " subchannel 0.%x.%04x\n", | |
172 | cdev->private->dev_id.devno, | |
173 | sch->schid.ssid, sch->schid.sch_no); | |
174 | + if (cdev->id.cu_type != 0) { /* device was recognized before */ | |
175 | + cdev->private->flags.recog_done = 1; | |
176 | + cdev->private->state = DEV_STATE_BOXED; | |
177 | + wake_up(&cdev->private->wait_q); | |
178 | + return; | |
179 | + } | |
180 | break; | |
181 | } | |
182 | cdev->private->state = state; | |
183 | io_subchannel_recog_done(cdev); | |
184 | - if (state != DEV_STATE_NOT_OPER) | |
185 | - wake_up(&cdev->private->wait_q); | |
186 | + wake_up(&cdev->private->wait_q); | |
187 | } | |
188 | ||
189 | /* | |
190 | @@ -387,10 +391,13 @@ ccw_device_done(struct ccw_device *cdev, | |
191 | ||
192 | cdev->private->state = state; | |
193 | ||
194 | - | |
195 | - if (state == DEV_STATE_BOXED) | |
196 | + if (state == DEV_STATE_BOXED) { | |
197 | CIO_MSG_EVENT(0, "Boxed device %04x on subchannel %04x\n", | |
198 | cdev->private->dev_id.devno, sch->schid.sch_no); | |
199 | + if (cdev->online && !ccw_device_notify(cdev, CIO_BOXED)) | |
200 | + ccw_device_schedule_sch_unregister(cdev); | |
201 | + cdev->private->flags.donotify = 0; | |
202 | + } | |
203 | ||
204 | if (cdev->private->flags.donotify) { | |
205 | cdev->private->flags.donotify = 0; | |
206 | --- a/drivers/s390/scsi/zfcp_ccw.c | |
207 | +++ b/drivers/s390/scsi/zfcp_ccw.c | |
208 | @@ -181,6 +181,11 @@ static int zfcp_ccw_notify(struct ccw_de | |
209 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, | |
210 | 89, NULL); | |
211 | break; | |
212 | + case CIO_BOXED: | |
213 | + dev_warn(&adapter->ccw_device->dev, "The FCP device " | |
214 | + "did not respond within the specified time\n"); | |
215 | + zfcp_erp_adapter_shutdown(adapter, 0, 91, NULL); | |
216 | + break; | |
217 | } | |
218 | return 1; | |
219 | } |