diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_erp.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 631 |
1 files changed, 287 insertions, 344 deletions
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 160b432c907f..d37c7331f244 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -21,6 +21,7 @@ enum zfcp_erp_act_flags { | |||
21 | ZFCP_STATUS_ERP_DISMISSING = 0x00100000, | 21 | ZFCP_STATUS_ERP_DISMISSING = 0x00100000, |
22 | ZFCP_STATUS_ERP_DISMISSED = 0x00200000, | 22 | ZFCP_STATUS_ERP_DISMISSED = 0x00200000, |
23 | ZFCP_STATUS_ERP_LOWMEM = 0x00400000, | 23 | ZFCP_STATUS_ERP_LOWMEM = 0x00400000, |
24 | ZFCP_STATUS_ERP_NO_REF = 0x00800000, | ||
24 | }; | 25 | }; |
25 | 26 | ||
26 | enum zfcp_erp_steps { | 27 | enum zfcp_erp_steps { |
@@ -29,12 +30,12 @@ enum zfcp_erp_steps { | |||
29 | ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010, | 30 | ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010, |
30 | ZFCP_ERP_STEP_PORT_CLOSING = 0x0100, | 31 | ZFCP_ERP_STEP_PORT_CLOSING = 0x0100, |
31 | ZFCP_ERP_STEP_PORT_OPENING = 0x0800, | 32 | ZFCP_ERP_STEP_PORT_OPENING = 0x0800, |
32 | ZFCP_ERP_STEP_UNIT_CLOSING = 0x1000, | 33 | ZFCP_ERP_STEP_LUN_CLOSING = 0x1000, |
33 | ZFCP_ERP_STEP_UNIT_OPENING = 0x2000, | 34 | ZFCP_ERP_STEP_LUN_OPENING = 0x2000, |
34 | }; | 35 | }; |
35 | 36 | ||
36 | enum zfcp_erp_act_type { | 37 | enum zfcp_erp_act_type { |
37 | ZFCP_ERP_ACTION_REOPEN_UNIT = 1, | 38 | ZFCP_ERP_ACTION_REOPEN_LUN = 1, |
38 | ZFCP_ERP_ACTION_REOPEN_PORT = 2, | 39 | ZFCP_ERP_ACTION_REOPEN_PORT = 2, |
39 | ZFCP_ERP_ACTION_REOPEN_PORT_FORCED = 3, | 40 | ZFCP_ERP_ACTION_REOPEN_PORT_FORCED = 3, |
40 | ZFCP_ERP_ACTION_REOPEN_ADAPTER = 4, | 41 | ZFCP_ERP_ACTION_REOPEN_ADAPTER = 4, |
@@ -56,9 +57,8 @@ enum zfcp_erp_act_result { | |||
56 | 57 | ||
57 | static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int mask) | 58 | static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int mask) |
58 | { | 59 | { |
59 | zfcp_erp_modify_adapter_status(adapter, "erablk1", NULL, | 60 | zfcp_erp_clear_adapter_status(adapter, |
60 | ZFCP_STATUS_COMMON_UNBLOCKED | mask, | 61 | ZFCP_STATUS_COMMON_UNBLOCKED | mask); |
61 | ZFCP_CLEAR); | ||
62 | } | 62 | } |
63 | 63 | ||
64 | static int zfcp_erp_action_exists(struct zfcp_erp_action *act) | 64 | static int zfcp_erp_action_exists(struct zfcp_erp_action *act) |
@@ -88,24 +88,24 @@ static void zfcp_erp_action_dismiss(struct zfcp_erp_action *act) | |||
88 | zfcp_erp_action_ready(act); | 88 | zfcp_erp_action_ready(act); |
89 | } | 89 | } |
90 | 90 | ||
91 | static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit) | 91 | static void zfcp_erp_action_dismiss_lun(struct scsi_device *sdev) |
92 | { | 92 | { |
93 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_INUSE) | 93 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); |
94 | zfcp_erp_action_dismiss(&unit->erp_action); | 94 | |
95 | if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_INUSE) | ||
96 | zfcp_erp_action_dismiss(&zfcp_sdev->erp_action); | ||
95 | } | 97 | } |
96 | 98 | ||
97 | static void zfcp_erp_action_dismiss_port(struct zfcp_port *port) | 99 | static void zfcp_erp_action_dismiss_port(struct zfcp_port *port) |
98 | { | 100 | { |
99 | struct zfcp_unit *unit; | 101 | struct scsi_device *sdev; |
100 | 102 | ||
101 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE) | 103 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE) |
102 | zfcp_erp_action_dismiss(&port->erp_action); | 104 | zfcp_erp_action_dismiss(&port->erp_action); |
103 | else { | 105 | else |
104 | read_lock(&port->unit_list_lock); | 106 | shost_for_each_device(sdev, port->adapter->scsi_host) |
105 | list_for_each_entry(unit, &port->unit_list, list) | 107 | if (sdev_to_zfcp(sdev)->port == port) |
106 | zfcp_erp_action_dismiss_unit(unit); | 108 | zfcp_erp_action_dismiss_lun(sdev); |
107 | read_unlock(&port->unit_list_lock); | ||
108 | } | ||
109 | } | 109 | } |
110 | 110 | ||
111 | static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) | 111 | static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) |
@@ -124,15 +124,17 @@ static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) | |||
124 | 124 | ||
125 | static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter, | 125 | static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter, |
126 | struct zfcp_port *port, | 126 | struct zfcp_port *port, |
127 | struct zfcp_unit *unit) | 127 | struct scsi_device *sdev) |
128 | { | 128 | { |
129 | int need = want; | 129 | int need = want; |
130 | int u_status, p_status, a_status; | 130 | int l_status, p_status, a_status; |
131 | struct zfcp_scsi_dev *zfcp_sdev; | ||
131 | 132 | ||
132 | switch (want) { | 133 | switch (want) { |
133 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 134 | case ZFCP_ERP_ACTION_REOPEN_LUN: |
134 | u_status = atomic_read(&unit->status); | 135 | zfcp_sdev = sdev_to_zfcp(sdev); |
135 | if (u_status & ZFCP_STATUS_COMMON_ERP_INUSE) | 136 | l_status = atomic_read(&zfcp_sdev->status); |
137 | if (l_status & ZFCP_STATUS_COMMON_ERP_INUSE) | ||
136 | return 0; | 138 | return 0; |
137 | p_status = atomic_read(&port->status); | 139 | p_status = atomic_read(&port->status); |
138 | if (!(p_status & ZFCP_STATUS_COMMON_RUNNING) || | 140 | if (!(p_status & ZFCP_STATUS_COMMON_RUNNING) || |
@@ -169,22 +171,26 @@ static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter, | |||
169 | return need; | 171 | return need; |
170 | } | 172 | } |
171 | 173 | ||
172 | static struct zfcp_erp_action *zfcp_erp_setup_act(int need, | 174 | static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status, |
173 | struct zfcp_adapter *adapter, | 175 | struct zfcp_adapter *adapter, |
174 | struct zfcp_port *port, | 176 | struct zfcp_port *port, |
175 | struct zfcp_unit *unit) | 177 | struct scsi_device *sdev) |
176 | { | 178 | { |
177 | struct zfcp_erp_action *erp_action; | 179 | struct zfcp_erp_action *erp_action; |
178 | u32 status = 0; | 180 | struct zfcp_scsi_dev *zfcp_sdev; |
179 | 181 | ||
180 | switch (need) { | 182 | switch (need) { |
181 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 183 | case ZFCP_ERP_ACTION_REOPEN_LUN: |
182 | if (!get_device(&unit->dev)) | 184 | zfcp_sdev = sdev_to_zfcp(sdev); |
183 | return NULL; | 185 | if (!(act_status & ZFCP_STATUS_ERP_NO_REF)) |
184 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status); | 186 | if (scsi_device_get(sdev)) |
185 | erp_action = &unit->erp_action; | 187 | return NULL; |
186 | if (!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_RUNNING)) | 188 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, |
187 | status = ZFCP_STATUS_ERP_CLOSE_ONLY; | 189 | &zfcp_sdev->status); |
190 | erp_action = &zfcp_sdev->erp_action; | ||
191 | if (!(atomic_read(&zfcp_sdev->status) & | ||
192 | ZFCP_STATUS_COMMON_RUNNING)) | ||
193 | act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY; | ||
188 | break; | 194 | break; |
189 | 195 | ||
190 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 196 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
@@ -195,7 +201,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, | |||
195 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status); | 201 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status); |
196 | erp_action = &port->erp_action; | 202 | erp_action = &port->erp_action; |
197 | if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING)) | 203 | if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING)) |
198 | status = ZFCP_STATUS_ERP_CLOSE_ONLY; | 204 | act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY; |
199 | break; | 205 | break; |
200 | 206 | ||
201 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | 207 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: |
@@ -205,7 +211,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, | |||
205 | erp_action = &adapter->erp_action; | 211 | erp_action = &adapter->erp_action; |
206 | if (!(atomic_read(&adapter->status) & | 212 | if (!(atomic_read(&adapter->status) & |
207 | ZFCP_STATUS_COMMON_RUNNING)) | 213 | ZFCP_STATUS_COMMON_RUNNING)) |
208 | status = ZFCP_STATUS_ERP_CLOSE_ONLY; | 214 | act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY; |
209 | break; | 215 | break; |
210 | 216 | ||
211 | default: | 217 | default: |
@@ -215,16 +221,17 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, | |||
215 | memset(erp_action, 0, sizeof(struct zfcp_erp_action)); | 221 | memset(erp_action, 0, sizeof(struct zfcp_erp_action)); |
216 | erp_action->adapter = adapter; | 222 | erp_action->adapter = adapter; |
217 | erp_action->port = port; | 223 | erp_action->port = port; |
218 | erp_action->unit = unit; | 224 | erp_action->sdev = sdev; |
219 | erp_action->action = need; | 225 | erp_action->action = need; |
220 | erp_action->status = status; | 226 | erp_action->status = act_status; |
221 | 227 | ||
222 | return erp_action; | 228 | return erp_action; |
223 | } | 229 | } |
224 | 230 | ||
225 | static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, | 231 | static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, |
226 | struct zfcp_port *port, | 232 | struct zfcp_port *port, |
227 | struct zfcp_unit *unit, char *id, void *ref) | 233 | struct scsi_device *sdev, |
234 | char *id, void *ref, u32 act_status) | ||
228 | { | 235 | { |
229 | int retval = 1, need; | 236 | int retval = 1, need; |
230 | struct zfcp_erp_action *act = NULL; | 237 | struct zfcp_erp_action *act = NULL; |
@@ -232,21 +239,21 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, | |||
232 | if (!adapter->erp_thread) | 239 | if (!adapter->erp_thread) |
233 | return -EIO; | 240 | return -EIO; |
234 | 241 | ||
235 | need = zfcp_erp_required_act(want, adapter, port, unit); | 242 | need = zfcp_erp_required_act(want, adapter, port, sdev); |
236 | if (!need) | 243 | if (!need) |
237 | goto out; | 244 | goto out; |
238 | 245 | ||
239 | atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status); | 246 | act = zfcp_erp_setup_act(need, act_status, adapter, port, sdev); |
240 | act = zfcp_erp_setup_act(need, adapter, port, unit); | ||
241 | if (!act) | 247 | if (!act) |
242 | goto out; | 248 | goto out; |
249 | atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status); | ||
243 | ++adapter->erp_total_count; | 250 | ++adapter->erp_total_count; |
244 | list_add_tail(&act->list, &adapter->erp_ready_head); | 251 | list_add_tail(&act->list, &adapter->erp_ready_head); |
245 | wake_up(&adapter->erp_ready_wq); | 252 | wake_up(&adapter->erp_ready_wq); |
246 | zfcp_dbf_rec_thread("eracte1", adapter->dbf); | 253 | zfcp_dbf_rec_thread("eracte1", adapter->dbf); |
247 | retval = 0; | 254 | retval = 0; |
248 | out: | 255 | out: |
249 | zfcp_dbf_rec_trigger(id, ref, want, need, act, adapter, port, unit); | 256 | zfcp_dbf_rec_trigger(id, ref, want, need, act, adapter, port, sdev); |
250 | return retval; | 257 | return retval; |
251 | } | 258 | } |
252 | 259 | ||
@@ -258,11 +265,12 @@ static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, | |||
258 | 265 | ||
259 | /* ensure propagation of failed status to new devices */ | 266 | /* ensure propagation of failed status to new devices */ |
260 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { | 267 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { |
261 | zfcp_erp_adapter_failed(adapter, "erareo1", NULL); | 268 | zfcp_erp_set_adapter_status(adapter, |
269 | ZFCP_STATUS_COMMON_ERP_FAILED); | ||
262 | return -EIO; | 270 | return -EIO; |
263 | } | 271 | } |
264 | return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, | 272 | return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, |
265 | adapter, NULL, NULL, id, ref); | 273 | adapter, NULL, NULL, id, ref, 0); |
266 | } | 274 | } |
267 | 275 | ||
268 | /** | 276 | /** |
@@ -282,10 +290,11 @@ void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, | |||
282 | 290 | ||
283 | write_lock_irqsave(&adapter->erp_lock, flags); | 291 | write_lock_irqsave(&adapter->erp_lock, flags); |
284 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) | 292 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) |
285 | zfcp_erp_adapter_failed(adapter, "erareo1", NULL); | 293 | zfcp_erp_set_adapter_status(adapter, |
294 | ZFCP_STATUS_COMMON_ERP_FAILED); | ||
286 | else | 295 | else |
287 | zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter, | 296 | zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter, |
288 | NULL, NULL, id, ref); | 297 | NULL, NULL, id, ref, 0); |
289 | write_unlock_irqrestore(&adapter->erp_lock, flags); | 298 | write_unlock_irqrestore(&adapter->erp_lock, flags); |
290 | } | 299 | } |
291 | 300 | ||
@@ -317,25 +326,10 @@ void zfcp_erp_port_shutdown(struct zfcp_port *port, int clear, char *id, | |||
317 | zfcp_erp_port_reopen(port, clear | flags, id, ref); | 326 | zfcp_erp_port_reopen(port, clear | flags, id, ref); |
318 | } | 327 | } |
319 | 328 | ||
320 | /** | ||
321 | * zfcp_erp_unit_shutdown - Shutdown unit | ||
322 | * @unit: Unit to shut down. | ||
323 | * @clear: Status flags to clear. | ||
324 | * @id: Id for debug trace event. | ||
325 | * @ref: Reference for debug trace event. | ||
326 | */ | ||
327 | void zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear, char *id, | ||
328 | void *ref) | ||
329 | { | ||
330 | int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; | ||
331 | zfcp_erp_unit_reopen(unit, clear | flags, id, ref); | ||
332 | } | ||
333 | |||
334 | static void zfcp_erp_port_block(struct zfcp_port *port, int clear) | 329 | static void zfcp_erp_port_block(struct zfcp_port *port, int clear) |
335 | { | 330 | { |
336 | zfcp_erp_modify_port_status(port, "erpblk1", NULL, | 331 | zfcp_erp_clear_port_status(port, |
337 | ZFCP_STATUS_COMMON_UNBLOCKED | clear, | 332 | ZFCP_STATUS_COMMON_UNBLOCKED | clear); |
338 | ZFCP_CLEAR); | ||
339 | } | 333 | } |
340 | 334 | ||
341 | static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, | 335 | static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, |
@@ -348,7 +342,7 @@ static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, | |||
348 | return; | 342 | return; |
349 | 343 | ||
350 | zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, | 344 | zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, |
351 | port->adapter, port, NULL, id, ref); | 345 | port->adapter, port, NULL, id, ref, 0); |
352 | } | 346 | } |
353 | 347 | ||
354 | /** | 348 | /** |
@@ -376,12 +370,12 @@ static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, | |||
376 | 370 | ||
377 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { | 371 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { |
378 | /* ensure propagation of failed status to new devices */ | 372 | /* ensure propagation of failed status to new devices */ |
379 | zfcp_erp_port_failed(port, "erpreo1", NULL); | 373 | zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED); |
380 | return -EIO; | 374 | return -EIO; |
381 | } | 375 | } |
382 | 376 | ||
383 | return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT, | 377 | return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT, |
384 | port->adapter, port, NULL, id, ref); | 378 | port->adapter, port, NULL, id, ref, 0); |
385 | } | 379 | } |
386 | 380 | ||
387 | /** | 381 | /** |
@@ -404,53 +398,88 @@ int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, void *ref) | |||
404 | return retval; | 398 | return retval; |
405 | } | 399 | } |
406 | 400 | ||
407 | static void zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask) | 401 | static void zfcp_erp_lun_block(struct scsi_device *sdev, int clear_mask) |
408 | { | 402 | { |
409 | zfcp_erp_modify_unit_status(unit, "erublk1", NULL, | 403 | zfcp_erp_clear_lun_status(sdev, |
410 | ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask, | 404 | ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask); |
411 | ZFCP_CLEAR); | ||
412 | } | 405 | } |
413 | 406 | ||
414 | static void _zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id, | 407 | static void _zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id, |
415 | void *ref) | 408 | void *ref, u32 act_status) |
416 | { | 409 | { |
417 | struct zfcp_adapter *adapter = unit->port->adapter; | 410 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); |
411 | struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; | ||
418 | 412 | ||
419 | zfcp_erp_unit_block(unit, clear); | 413 | zfcp_erp_lun_block(sdev, clear); |
420 | 414 | ||
421 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_FAILED) | 415 | if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED) |
422 | return; | 416 | return; |
423 | 417 | ||
424 | zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_UNIT, | 418 | zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_LUN, adapter, |
425 | adapter, unit->port, unit, id, ref); | 419 | zfcp_sdev->port, sdev, id, ref, act_status); |
426 | } | 420 | } |
427 | 421 | ||
428 | /** | 422 | /** |
429 | * zfcp_erp_unit_reopen - initiate reopen of a unit | 423 | * zfcp_erp_lun_reopen - initiate reopen of a LUN |
430 | * @unit: unit to be reopened | 424 | * @sdev: SCSI device / LUN to be reopened |
431 | * @clear_mask: specifies flags in unit status to be cleared | 425 | * @clear_mask: specifies flags in LUN status to be cleared |
432 | * Return: 0 on success, < 0 on error | 426 | * Return: 0 on success, < 0 on error |
433 | */ | 427 | */ |
434 | void zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id, | 428 | void zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id, |
435 | void *ref) | 429 | void *ref) |
436 | { | 430 | { |
437 | unsigned long flags; | 431 | unsigned long flags; |
438 | struct zfcp_port *port = unit->port; | 432 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); |
433 | struct zfcp_port *port = zfcp_sdev->port; | ||
439 | struct zfcp_adapter *adapter = port->adapter; | 434 | struct zfcp_adapter *adapter = port->adapter; |
440 | 435 | ||
441 | write_lock_irqsave(&adapter->erp_lock, flags); | 436 | write_lock_irqsave(&adapter->erp_lock, flags); |
442 | _zfcp_erp_unit_reopen(unit, clear, id, ref); | 437 | _zfcp_erp_lun_reopen(sdev, clear, id, ref, 0); |
443 | write_unlock_irqrestore(&adapter->erp_lock, flags); | 438 | write_unlock_irqrestore(&adapter->erp_lock, flags); |
444 | } | 439 | } |
445 | 440 | ||
446 | static int status_change_set(unsigned long mask, atomic_t *status) | 441 | /** |
442 | * zfcp_erp_lun_shutdown - Shutdown LUN | ||
443 | * @sdev: SCSI device / LUN to shut down. | ||
444 | * @clear: Status flags to clear. | ||
445 | * @id: Id for debug trace event. | ||
446 | * @ref: Reference for debug trace event. | ||
447 | */ | ||
448 | void zfcp_erp_lun_shutdown(struct scsi_device *sdev, int clear, char *id, | ||
449 | void *ref) | ||
447 | { | 450 | { |
448 | return (atomic_read(status) ^ mask) & mask; | 451 | int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; |
452 | zfcp_erp_lun_reopen(sdev, clear | flags, id, ref); | ||
449 | } | 453 | } |
450 | 454 | ||
451 | static int status_change_clear(unsigned long mask, atomic_t *status) | 455 | /** |
456 | * zfcp_erp_lun_shutdown_wait - Shutdown LUN and wait for erp completion | ||
457 | * @sdev: SCSI device / LUN to shut down. | ||
458 | * @id: Id for debug trace event. | ||
459 | * | ||
460 | * Do not acquire a reference for the LUN when creating the ERP | ||
461 | * action. It is safe, because this function waits for the ERP to | ||
462 | * complete first. This allows to shutdown the LUN, even when the SCSI | ||
463 | * device is in the state SDEV_DEL when scsi_device_get will fail. | ||
464 | */ | ||
465 | void zfcp_erp_lun_shutdown_wait(struct scsi_device *sdev, char *id) | ||
452 | { | 466 | { |
453 | return atomic_read(status) & mask; | 467 | unsigned long flags; |
468 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); | ||
469 | struct zfcp_port *port = zfcp_sdev->port; | ||
470 | struct zfcp_adapter *adapter = port->adapter; | ||
471 | int clear = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; | ||
472 | |||
473 | write_lock_irqsave(&adapter->erp_lock, flags); | ||
474 | _zfcp_erp_lun_reopen(sdev, clear, id, NULL, ZFCP_STATUS_ERP_NO_REF); | ||
475 | write_unlock_irqrestore(&adapter->erp_lock, flags); | ||
476 | |||
477 | zfcp_erp_wait(adapter); | ||
478 | } | ||
479 | |||
480 | static int status_change_set(unsigned long mask, atomic_t *status) | ||
481 | { | ||
482 | return (atomic_read(status) ^ mask) & mask; | ||
454 | } | 483 | } |
455 | 484 | ||
456 | static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter) | 485 | static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter) |
@@ -467,11 +496,13 @@ static void zfcp_erp_port_unblock(struct zfcp_port *port) | |||
467 | atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status); | 496 | atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status); |
468 | } | 497 | } |
469 | 498 | ||
470 | static void zfcp_erp_unit_unblock(struct zfcp_unit *unit) | 499 | static void zfcp_erp_lun_unblock(struct scsi_device *sdev) |
471 | { | 500 | { |
472 | if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status)) | 501 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); |
473 | zfcp_dbf_rec_unit("eruubl1", NULL, unit); | 502 | |
474 | atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status); | 503 | if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status)) |
504 | zfcp_dbf_rec_lun("erlubl1", NULL, sdev); | ||
505 | atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status); | ||
475 | } | 506 | } |
476 | 507 | ||
477 | static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) | 508 | static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) |
@@ -559,15 +590,14 @@ static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, | |||
559 | read_unlock(&adapter->port_list_lock); | 590 | read_unlock(&adapter->port_list_lock); |
560 | } | 591 | } |
561 | 592 | ||
562 | static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear, | 593 | static void _zfcp_erp_lun_reopen_all(struct zfcp_port *port, int clear, |
563 | char *id, void *ref) | 594 | char *id, void *ref) |
564 | { | 595 | { |
565 | struct zfcp_unit *unit; | 596 | struct scsi_device *sdev; |
566 | 597 | ||
567 | read_lock(&port->unit_list_lock); | 598 | shost_for_each_device(sdev, port->adapter->scsi_host) |
568 | list_for_each_entry(unit, &port->unit_list, list) | 599 | if (sdev_to_zfcp(sdev)->port == port) |
569 | _zfcp_erp_unit_reopen(unit, clear, id, ref); | 600 | _zfcp_erp_lun_reopen(sdev, clear, id, ref, 0); |
570 | read_unlock(&port->unit_list_lock); | ||
571 | } | 601 | } |
572 | 602 | ||
573 | static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act) | 603 | static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act) |
@@ -582,8 +612,8 @@ static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act) | |||
582 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 612 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
583 | _zfcp_erp_port_reopen(act->port, 0, "ersff_3", NULL); | 613 | _zfcp_erp_port_reopen(act->port, 0, "ersff_3", NULL); |
584 | break; | 614 | break; |
585 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 615 | case ZFCP_ERP_ACTION_REOPEN_LUN: |
586 | _zfcp_erp_unit_reopen(act->unit, 0, "ersff_4", NULL); | 616 | _zfcp_erp_lun_reopen(act->sdev, 0, "ersff_4", NULL, 0); |
587 | break; | 617 | break; |
588 | } | 618 | } |
589 | } | 619 | } |
@@ -598,7 +628,7 @@ static void zfcp_erp_strategy_followup_success(struct zfcp_erp_action *act) | |||
598 | _zfcp_erp_port_reopen(act->port, 0, "ersfs_2", NULL); | 628 | _zfcp_erp_port_reopen(act->port, 0, "ersfs_2", NULL); |
599 | break; | 629 | break; |
600 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 630 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
601 | _zfcp_erp_unit_reopen_all(act->port, 0, "ersfs_3", NULL); | 631 | _zfcp_erp_lun_reopen_all(act->port, 0, "ersfs_3", NULL); |
602 | break; | 632 | break; |
603 | } | 633 | } |
604 | } | 634 | } |
@@ -742,9 +772,8 @@ static void zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *act) | |||
742 | zfcp_fsf_req_dismiss_all(adapter); | 772 | zfcp_fsf_req_dismiss_all(adapter); |
743 | adapter->fsf_req_seq_no = 0; | 773 | adapter->fsf_req_seq_no = 0; |
744 | zfcp_fc_wka_ports_force_offline(adapter->gs); | 774 | zfcp_fc_wka_ports_force_offline(adapter->gs); |
745 | /* all ports and units are closed */ | 775 | /* all ports and LUNs are closed */ |
746 | zfcp_erp_modify_adapter_status(adapter, "erascl1", NULL, | 776 | zfcp_erp_clear_adapter_status(adapter, ZFCP_STATUS_COMMON_OPEN); |
747 | ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); | ||
748 | 777 | ||
749 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | | 778 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | |
750 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); | 779 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); |
@@ -861,7 +890,7 @@ static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act) | |||
861 | struct zfcp_port *port = act->port; | 890 | struct zfcp_port *port = act->port; |
862 | 891 | ||
863 | if (port->wwpn != adapter->peer_wwpn) { | 892 | if (port->wwpn != adapter->peer_wwpn) { |
864 | zfcp_erp_port_failed(port, "eroptp1", NULL); | 893 | zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED); |
865 | return ZFCP_ERP_FAILED; | 894 | return ZFCP_ERP_FAILED; |
866 | } | 895 | } |
867 | port->d_id = adapter->peer_d_id; | 896 | port->d_id = adapter->peer_d_id; |
@@ -933,82 +962,87 @@ close_init_done: | |||
933 | return zfcp_erp_port_strategy_open_common(erp_action); | 962 | return zfcp_erp_port_strategy_open_common(erp_action); |
934 | } | 963 | } |
935 | 964 | ||
936 | static void zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit) | 965 | static void zfcp_erp_lun_strategy_clearstati(struct scsi_device *sdev) |
937 | { | 966 | { |
967 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); | ||
968 | |||
938 | atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | | 969 | atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | |
939 | ZFCP_STATUS_UNIT_SHARED | | 970 | ZFCP_STATUS_LUN_SHARED | ZFCP_STATUS_LUN_READONLY, |
940 | ZFCP_STATUS_UNIT_READONLY, | 971 | &zfcp_sdev->status); |
941 | &unit->status); | ||
942 | } | 972 | } |
943 | 973 | ||
944 | static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *erp_action) | 974 | static int zfcp_erp_lun_strategy_close(struct zfcp_erp_action *erp_action) |
945 | { | 975 | { |
946 | int retval = zfcp_fsf_close_unit(erp_action); | 976 | int retval = zfcp_fsf_close_lun(erp_action); |
947 | if (retval == -ENOMEM) | 977 | if (retval == -ENOMEM) |
948 | return ZFCP_ERP_NOMEM; | 978 | return ZFCP_ERP_NOMEM; |
949 | erp_action->step = ZFCP_ERP_STEP_UNIT_CLOSING; | 979 | erp_action->step = ZFCP_ERP_STEP_LUN_CLOSING; |
950 | if (retval) | 980 | if (retval) |
951 | return ZFCP_ERP_FAILED; | 981 | return ZFCP_ERP_FAILED; |
952 | return ZFCP_ERP_CONTINUES; | 982 | return ZFCP_ERP_CONTINUES; |
953 | } | 983 | } |
954 | 984 | ||
955 | static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action) | 985 | static int zfcp_erp_lun_strategy_open(struct zfcp_erp_action *erp_action) |
956 | { | 986 | { |
957 | int retval = zfcp_fsf_open_unit(erp_action); | 987 | int retval = zfcp_fsf_open_lun(erp_action); |
958 | if (retval == -ENOMEM) | 988 | if (retval == -ENOMEM) |
959 | return ZFCP_ERP_NOMEM; | 989 | return ZFCP_ERP_NOMEM; |
960 | erp_action->step = ZFCP_ERP_STEP_UNIT_OPENING; | 990 | erp_action->step = ZFCP_ERP_STEP_LUN_OPENING; |
961 | if (retval) | 991 | if (retval) |
962 | return ZFCP_ERP_FAILED; | 992 | return ZFCP_ERP_FAILED; |
963 | return ZFCP_ERP_CONTINUES; | 993 | return ZFCP_ERP_CONTINUES; |
964 | } | 994 | } |
965 | 995 | ||
966 | static int zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action) | 996 | static int zfcp_erp_lun_strategy(struct zfcp_erp_action *erp_action) |
967 | { | 997 | { |
968 | struct zfcp_unit *unit = erp_action->unit; | 998 | struct scsi_device *sdev = erp_action->sdev; |
999 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); | ||
969 | 1000 | ||
970 | switch (erp_action->step) { | 1001 | switch (erp_action->step) { |
971 | case ZFCP_ERP_STEP_UNINITIALIZED: | 1002 | case ZFCP_ERP_STEP_UNINITIALIZED: |
972 | zfcp_erp_unit_strategy_clearstati(unit); | 1003 | zfcp_erp_lun_strategy_clearstati(sdev); |
973 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN) | 1004 | if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN) |
974 | return zfcp_erp_unit_strategy_close(erp_action); | 1005 | return zfcp_erp_lun_strategy_close(erp_action); |
975 | /* already closed, fall through */ | 1006 | /* already closed, fall through */ |
976 | case ZFCP_ERP_STEP_UNIT_CLOSING: | 1007 | case ZFCP_ERP_STEP_LUN_CLOSING: |
977 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN) | 1008 | if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN) |
978 | return ZFCP_ERP_FAILED; | 1009 | return ZFCP_ERP_FAILED; |
979 | if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) | 1010 | if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) |
980 | return ZFCP_ERP_EXIT; | 1011 | return ZFCP_ERP_EXIT; |
981 | return zfcp_erp_unit_strategy_open(erp_action); | 1012 | return zfcp_erp_lun_strategy_open(erp_action); |
982 | 1013 | ||
983 | case ZFCP_ERP_STEP_UNIT_OPENING: | 1014 | case ZFCP_ERP_STEP_LUN_OPENING: |
984 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN) | 1015 | if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN) |
985 | return ZFCP_ERP_SUCCEEDED; | 1016 | return ZFCP_ERP_SUCCEEDED; |
986 | } | 1017 | } |
987 | return ZFCP_ERP_FAILED; | 1018 | return ZFCP_ERP_FAILED; |
988 | } | 1019 | } |
989 | 1020 | ||
990 | static int zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result) | 1021 | static int zfcp_erp_strategy_check_lun(struct scsi_device *sdev, int result) |
991 | { | 1022 | { |
1023 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); | ||
1024 | |||
992 | switch (result) { | 1025 | switch (result) { |
993 | case ZFCP_ERP_SUCCEEDED : | 1026 | case ZFCP_ERP_SUCCEEDED : |
994 | atomic_set(&unit->erp_counter, 0); | 1027 | atomic_set(&zfcp_sdev->erp_counter, 0); |
995 | zfcp_erp_unit_unblock(unit); | 1028 | zfcp_erp_lun_unblock(sdev); |
996 | break; | 1029 | break; |
997 | case ZFCP_ERP_FAILED : | 1030 | case ZFCP_ERP_FAILED : |
998 | atomic_inc(&unit->erp_counter); | 1031 | atomic_inc(&zfcp_sdev->erp_counter); |
999 | if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) { | 1032 | if (atomic_read(&zfcp_sdev->erp_counter) > ZFCP_MAX_ERPS) { |
1000 | dev_err(&unit->port->adapter->ccw_device->dev, | 1033 | dev_err(&zfcp_sdev->port->adapter->ccw_device->dev, |
1001 | "ERP failed for unit 0x%016Lx on " | 1034 | "ERP failed for LUN 0x%016Lx on " |
1002 | "port 0x%016Lx\n", | 1035 | "port 0x%016Lx\n", |
1003 | (unsigned long long)unit->fcp_lun, | 1036 | (unsigned long long)zfcp_scsi_dev_lun(sdev), |
1004 | (unsigned long long)unit->port->wwpn); | 1037 | (unsigned long long)zfcp_sdev->port->wwpn); |
1005 | zfcp_erp_unit_failed(unit, "erusck1", NULL); | 1038 | zfcp_erp_set_lun_status(sdev, |
1039 | ZFCP_STATUS_COMMON_ERP_FAILED); | ||
1006 | } | 1040 | } |
1007 | break; | 1041 | break; |
1008 | } | 1042 | } |
1009 | 1043 | ||
1010 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { | 1044 | if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { |
1011 | zfcp_erp_unit_block(unit, 0); | 1045 | zfcp_erp_lun_block(sdev, 0); |
1012 | result = ZFCP_ERP_EXIT; | 1046 | result = ZFCP_ERP_EXIT; |
1013 | } | 1047 | } |
1014 | return result; | 1048 | return result; |
@@ -1032,7 +1066,8 @@ static int zfcp_erp_strategy_check_port(struct zfcp_port *port, int result) | |||
1032 | dev_err(&port->adapter->ccw_device->dev, | 1066 | dev_err(&port->adapter->ccw_device->dev, |
1033 | "ERP failed for remote port 0x%016Lx\n", | 1067 | "ERP failed for remote port 0x%016Lx\n", |
1034 | (unsigned long long)port->wwpn); | 1068 | (unsigned long long)port->wwpn); |
1035 | zfcp_erp_port_failed(port, "erpsck1", NULL); | 1069 | zfcp_erp_set_port_status(port, |
1070 | ZFCP_STATUS_COMMON_ERP_FAILED); | ||
1036 | } | 1071 | } |
1037 | break; | 1072 | break; |
1038 | } | 1073 | } |
@@ -1059,7 +1094,8 @@ static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, | |||
1059 | dev_err(&adapter->ccw_device->dev, | 1094 | dev_err(&adapter->ccw_device->dev, |
1060 | "ERP cannot recover an error " | 1095 | "ERP cannot recover an error " |
1061 | "on the FCP device\n"); | 1096 | "on the FCP device\n"); |
1062 | zfcp_erp_adapter_failed(adapter, "erasck1", NULL); | 1097 | zfcp_erp_set_adapter_status(adapter, |
1098 | ZFCP_STATUS_COMMON_ERP_FAILED); | ||
1063 | } | 1099 | } |
1064 | break; | 1100 | break; |
1065 | } | 1101 | } |
@@ -1076,12 +1112,12 @@ static int zfcp_erp_strategy_check_target(struct zfcp_erp_action *erp_action, | |||
1076 | { | 1112 | { |
1077 | struct zfcp_adapter *adapter = erp_action->adapter; | 1113 | struct zfcp_adapter *adapter = erp_action->adapter; |
1078 | struct zfcp_port *port = erp_action->port; | 1114 | struct zfcp_port *port = erp_action->port; |
1079 | struct zfcp_unit *unit = erp_action->unit; | 1115 | struct scsi_device *sdev = erp_action->sdev; |
1080 | 1116 | ||
1081 | switch (erp_action->action) { | 1117 | switch (erp_action->action) { |
1082 | 1118 | ||
1083 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 1119 | case ZFCP_ERP_ACTION_REOPEN_LUN: |
1084 | result = zfcp_erp_strategy_check_unit(unit, result); | 1120 | result = zfcp_erp_strategy_check_lun(sdev, result); |
1085 | break; | 1121 | break; |
1086 | 1122 | ||
1087 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 1123 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
@@ -1116,7 +1152,8 @@ static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret) | |||
1116 | int action = act->action; | 1152 | int action = act->action; |
1117 | struct zfcp_adapter *adapter = act->adapter; | 1153 | struct zfcp_adapter *adapter = act->adapter; |
1118 | struct zfcp_port *port = act->port; | 1154 | struct zfcp_port *port = act->port; |
1119 | struct zfcp_unit *unit = act->unit; | 1155 | struct scsi_device *sdev = act->sdev; |
1156 | struct zfcp_scsi_dev *zfcp_sdev; | ||
1120 | u32 erp_status = act->status; | 1157 | u32 erp_status = act->status; |
1121 | 1158 | ||
1122 | switch (action) { | 1159 | switch (action) { |
@@ -1139,11 +1176,12 @@ static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret) | |||
1139 | } | 1176 | } |
1140 | break; | 1177 | break; |
1141 | 1178 | ||
1142 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 1179 | case ZFCP_ERP_ACTION_REOPEN_LUN: |
1143 | if (zfcp_erp_strat_change_det(&unit->status, erp_status)) { | 1180 | zfcp_sdev = sdev_to_zfcp(sdev); |
1144 | _zfcp_erp_unit_reopen(unit, | 1181 | if (zfcp_erp_strat_change_det(&zfcp_sdev->status, erp_status)) { |
1145 | ZFCP_STATUS_COMMON_ERP_FAILED, | 1182 | _zfcp_erp_lun_reopen(sdev, |
1146 | "ersscg3", NULL); | 1183 | ZFCP_STATUS_COMMON_ERP_FAILED, |
1184 | "ersscg3", NULL, 0); | ||
1147 | return ZFCP_ERP_EXIT; | 1185 | return ZFCP_ERP_EXIT; |
1148 | } | 1186 | } |
1149 | break; | 1187 | break; |
@@ -1154,6 +1192,7 @@ static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret) | |||
1154 | static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) | 1192 | static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) |
1155 | { | 1193 | { |
1156 | struct zfcp_adapter *adapter = erp_action->adapter; | 1194 | struct zfcp_adapter *adapter = erp_action->adapter; |
1195 | struct zfcp_scsi_dev *zfcp_sdev; | ||
1157 | 1196 | ||
1158 | adapter->erp_total_count--; | 1197 | adapter->erp_total_count--; |
1159 | if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) { | 1198 | if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) { |
@@ -1165,9 +1204,10 @@ static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) | |||
1165 | zfcp_dbf_rec_action("eractd1", erp_action); | 1204 | zfcp_dbf_rec_action("eractd1", erp_action); |
1166 | 1205 | ||
1167 | switch (erp_action->action) { | 1206 | switch (erp_action->action) { |
1168 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 1207 | case ZFCP_ERP_ACTION_REOPEN_LUN: |
1208 | zfcp_sdev = sdev_to_zfcp(erp_action->sdev); | ||
1169 | atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE, | 1209 | atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE, |
1170 | &erp_action->unit->status); | 1210 | &zfcp_sdev->status); |
1171 | break; | 1211 | break; |
1172 | 1212 | ||
1173 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 1213 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
@@ -1187,11 +1227,12 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) | |||
1187 | { | 1227 | { |
1188 | struct zfcp_adapter *adapter = act->adapter; | 1228 | struct zfcp_adapter *adapter = act->adapter; |
1189 | struct zfcp_port *port = act->port; | 1229 | struct zfcp_port *port = act->port; |
1190 | struct zfcp_unit *unit = act->unit; | 1230 | struct scsi_device *sdev = act->sdev; |
1191 | 1231 | ||
1192 | switch (act->action) { | 1232 | switch (act->action) { |
1193 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 1233 | case ZFCP_ERP_ACTION_REOPEN_LUN: |
1194 | put_device(&unit->dev); | 1234 | if (!(act->status & ZFCP_STATUS_ERP_NO_REF)) |
1235 | scsi_device_put(sdev); | ||
1195 | break; | 1236 | break; |
1196 | 1237 | ||
1197 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 1238 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
@@ -1222,8 +1263,8 @@ static int zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action) | |||
1222 | return zfcp_erp_port_forced_strategy(erp_action); | 1263 | return zfcp_erp_port_forced_strategy(erp_action); |
1223 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 1264 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
1224 | return zfcp_erp_port_strategy(erp_action); | 1265 | return zfcp_erp_port_strategy(erp_action); |
1225 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 1266 | case ZFCP_ERP_ACTION_REOPEN_LUN: |
1226 | return zfcp_erp_unit_strategy(erp_action); | 1267 | return zfcp_erp_lun_strategy(erp_action); |
1227 | } | 1268 | } |
1228 | return ZFCP_ERP_FAILED; | 1269 | return ZFCP_ERP_FAILED; |
1229 | } | 1270 | } |
@@ -1376,42 +1417,6 @@ void zfcp_erp_thread_kill(struct zfcp_adapter *adapter) | |||
1376 | } | 1417 | } |
1377 | 1418 | ||
1378 | /** | 1419 | /** |
1379 | * zfcp_erp_adapter_failed - Set adapter status to failed. | ||
1380 | * @adapter: Failed adapter. | ||
1381 | * @id: Event id for debug trace. | ||
1382 | * @ref: Reference for debug trace. | ||
1383 | */ | ||
1384 | void zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, char *id, void *ref) | ||
1385 | { | ||
1386 | zfcp_erp_modify_adapter_status(adapter, id, ref, | ||
1387 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); | ||
1388 | } | ||
1389 | |||
1390 | /** | ||
1391 | * zfcp_erp_port_failed - Set port status to failed. | ||
1392 | * @port: Failed port. | ||
1393 | * @id: Event id for debug trace. | ||
1394 | * @ref: Reference for debug trace. | ||
1395 | */ | ||
1396 | void zfcp_erp_port_failed(struct zfcp_port *port, char *id, void *ref) | ||
1397 | { | ||
1398 | zfcp_erp_modify_port_status(port, id, ref, | ||
1399 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); | ||
1400 | } | ||
1401 | |||
1402 | /** | ||
1403 | * zfcp_erp_unit_failed - Set unit status to failed. | ||
1404 | * @unit: Failed unit. | ||
1405 | * @id: Event id for debug trace. | ||
1406 | * @ref: Reference for debug trace. | ||
1407 | */ | ||
1408 | void zfcp_erp_unit_failed(struct zfcp_unit *unit, char *id, void *ref) | ||
1409 | { | ||
1410 | zfcp_erp_modify_unit_status(unit, id, ref, | ||
1411 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); | ||
1412 | } | ||
1413 | |||
1414 | /** | ||
1415 | * zfcp_erp_wait - wait for completion of error recovery on an adapter | 1420 | * zfcp_erp_wait - wait for completion of error recovery on an adapter |
1416 | * @adapter: adapter for which to wait for completion of its error recovery | 1421 | * @adapter: adapter for which to wait for completion of its error recovery |
1417 | */ | 1422 | */ |
@@ -1423,210 +1428,148 @@ void zfcp_erp_wait(struct zfcp_adapter *adapter) | |||
1423 | } | 1428 | } |
1424 | 1429 | ||
1425 | /** | 1430 | /** |
1426 | * zfcp_erp_modify_adapter_status - change adapter status bits | 1431 | * zfcp_erp_set_adapter_status - set adapter status bits |
1427 | * @adapter: adapter to change the status | 1432 | * @adapter: adapter to change the status |
1428 | * @id: id for the debug trace | ||
1429 | * @ref: reference for the debug trace | ||
1430 | * @mask: status bits to change | 1433 | * @mask: status bits to change |
1431 | * @set_or_clear: ZFCP_SET or ZFCP_CLEAR | ||
1432 | * | 1434 | * |
1433 | * Changes in common status bits are propagated to attached ports and units. | 1435 | * Changes in common status bits are propagated to attached ports and LUNs. |
1434 | */ | 1436 | */ |
1435 | void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, char *id, | 1437 | void zfcp_erp_set_adapter_status(struct zfcp_adapter *adapter, u32 mask) |
1436 | void *ref, u32 mask, int set_or_clear) | ||
1437 | { | 1438 | { |
1438 | struct zfcp_port *port; | 1439 | struct zfcp_port *port; |
1440 | struct scsi_device *sdev; | ||
1439 | unsigned long flags; | 1441 | unsigned long flags; |
1440 | u32 common_mask = mask & ZFCP_COMMON_FLAGS; | 1442 | u32 common_mask = mask & ZFCP_COMMON_FLAGS; |
1441 | 1443 | ||
1442 | if (set_or_clear == ZFCP_SET) { | 1444 | atomic_set_mask(mask, &adapter->status); |
1443 | if (status_change_set(mask, &adapter->status)) | ||
1444 | zfcp_dbf_rec_adapter(id, ref, adapter->dbf); | ||
1445 | atomic_set_mask(mask, &adapter->status); | ||
1446 | } else { | ||
1447 | if (status_change_clear(mask, &adapter->status)) | ||
1448 | zfcp_dbf_rec_adapter(id, ref, adapter->dbf); | ||
1449 | atomic_clear_mask(mask, &adapter->status); | ||
1450 | if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) | ||
1451 | atomic_set(&adapter->erp_counter, 0); | ||
1452 | } | ||
1453 | 1445 | ||
1454 | if (common_mask) { | 1446 | if (!common_mask) |
1455 | read_lock_irqsave(&adapter->port_list_lock, flags); | 1447 | return; |
1456 | list_for_each_entry(port, &adapter->port_list, list) | 1448 | |
1457 | zfcp_erp_modify_port_status(port, id, ref, common_mask, | 1449 | read_lock_irqsave(&adapter->port_list_lock, flags); |
1458 | set_or_clear); | 1450 | list_for_each_entry(port, &adapter->port_list, list) |
1459 | read_unlock_irqrestore(&adapter->port_list_lock, flags); | 1451 | atomic_set_mask(common_mask, &port->status); |
1460 | } | 1452 | read_unlock_irqrestore(&adapter->port_list_lock, flags); |
1453 | |||
1454 | shost_for_each_device(sdev, adapter->scsi_host) | ||
1455 | atomic_set_mask(common_mask, &sdev_to_zfcp(sdev)->status); | ||
1461 | } | 1456 | } |
1462 | 1457 | ||
1463 | /** | 1458 | /** |
1464 | * zfcp_erp_modify_port_status - change port status bits | 1459 | * zfcp_erp_clear_adapter_status - clear adapter status bits |
1465 | * @port: port to change the status bits | 1460 | * @adapter: adapter to change the status |
1466 | * @id: id for the debug trace | ||
1467 | * @ref: reference for the debug trace | ||
1468 | * @mask: status bits to change | 1461 | * @mask: status bits to change |
1469 | * @set_or_clear: ZFCP_SET or ZFCP_CLEAR | ||
1470 | * | 1462 | * |
1471 | * Changes in common status bits are propagated to attached units. | 1463 | * Changes in common status bits are propagated to attached ports and LUNs. |
1472 | */ | 1464 | */ |
1473 | void zfcp_erp_modify_port_status(struct zfcp_port *port, char *id, void *ref, | 1465 | void zfcp_erp_clear_adapter_status(struct zfcp_adapter *adapter, u32 mask) |
1474 | u32 mask, int set_or_clear) | ||
1475 | { | 1466 | { |
1476 | struct zfcp_unit *unit; | 1467 | struct zfcp_port *port; |
1468 | struct scsi_device *sdev; | ||
1477 | unsigned long flags; | 1469 | unsigned long flags; |
1478 | u32 common_mask = mask & ZFCP_COMMON_FLAGS; | 1470 | u32 common_mask = mask & ZFCP_COMMON_FLAGS; |
1471 | u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED; | ||
1472 | |||
1473 | atomic_clear_mask(mask, &adapter->status); | ||
1474 | |||
1475 | if (!common_mask) | ||
1476 | return; | ||
1477 | |||
1478 | if (clear_counter) | ||
1479 | atomic_set(&adapter->erp_counter, 0); | ||
1479 | 1480 | ||
1480 | if (set_or_clear == ZFCP_SET) { | 1481 | read_lock_irqsave(&adapter->port_list_lock, flags); |
1481 | if (status_change_set(mask, &port->status)) | 1482 | list_for_each_entry(port, &adapter->port_list, list) { |
1482 | zfcp_dbf_rec_port(id, ref, port); | 1483 | atomic_clear_mask(common_mask, &port->status); |
1483 | atomic_set_mask(mask, &port->status); | 1484 | if (clear_counter) |
1484 | } else { | ||
1485 | if (status_change_clear(mask, &port->status)) | ||
1486 | zfcp_dbf_rec_port(id, ref, port); | ||
1487 | atomic_clear_mask(mask, &port->status); | ||
1488 | if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) | ||
1489 | atomic_set(&port->erp_counter, 0); | 1485 | atomic_set(&port->erp_counter, 0); |
1490 | } | 1486 | } |
1487 | read_unlock_irqrestore(&adapter->port_list_lock, flags); | ||
1491 | 1488 | ||
1492 | if (common_mask) { | 1489 | shost_for_each_device(sdev, adapter->scsi_host) { |
1493 | read_lock_irqsave(&port->unit_list_lock, flags); | 1490 | atomic_clear_mask(common_mask, &sdev_to_zfcp(sdev)->status); |
1494 | list_for_each_entry(unit, &port->unit_list, list) | 1491 | if (clear_counter) |
1495 | zfcp_erp_modify_unit_status(unit, id, ref, common_mask, | 1492 | atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0); |
1496 | set_or_clear); | ||
1497 | read_unlock_irqrestore(&port->unit_list_lock, flags); | ||
1498 | } | 1493 | } |
1499 | } | 1494 | } |
1500 | 1495 | ||
1501 | /** | 1496 | /** |
1502 | * zfcp_erp_modify_unit_status - change unit status bits | 1497 | * zfcp_erp_set_port_status - set port status bits |
1503 | * @unit: unit to change the status bits | 1498 | * @port: port to change the status |
1504 | * @id: id for the debug trace | ||
1505 | * @ref: reference for the debug trace | ||
1506 | * @mask: status bits to change | 1499 | * @mask: status bits to change |
1507 | * @set_or_clear: ZFCP_SET or ZFCP_CLEAR | 1500 | * |
1508 | */ | 1501 | * Changes in common status bits are propagated to attached LUNs. |
1509 | void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, char *id, void *ref, | ||
1510 | u32 mask, int set_or_clear) | ||
1511 | { | ||
1512 | if (set_or_clear == ZFCP_SET) { | ||
1513 | if (status_change_set(mask, &unit->status)) | ||
1514 | zfcp_dbf_rec_unit(id, ref, unit); | ||
1515 | atomic_set_mask(mask, &unit->status); | ||
1516 | } else { | ||
1517 | if (status_change_clear(mask, &unit->status)) | ||
1518 | zfcp_dbf_rec_unit(id, ref, unit); | ||
1519 | atomic_clear_mask(mask, &unit->status); | ||
1520 | if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) { | ||
1521 | atomic_set(&unit->erp_counter, 0); | ||
1522 | } | ||
1523 | } | ||
1524 | } | ||
1525 | |||
1526 | /** | ||
1527 | * zfcp_erp_port_boxed - Mark port as "boxed" and start ERP | ||
1528 | * @port: The "boxed" port. | ||
1529 | * @id: The debug trace id. | ||
1530 | * @id: Reference for the debug trace. | ||
1531 | */ | 1502 | */ |
1532 | void zfcp_erp_port_boxed(struct zfcp_port *port, char *id, void *ref) | 1503 | void zfcp_erp_set_port_status(struct zfcp_port *port, u32 mask) |
1533 | { | 1504 | { |
1534 | zfcp_erp_modify_port_status(port, id, ref, | 1505 | struct scsi_device *sdev; |
1535 | ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET); | 1506 | u32 common_mask = mask & ZFCP_COMMON_FLAGS; |
1536 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); | ||
1537 | } | ||
1538 | 1507 | ||
1539 | /** | 1508 | atomic_set_mask(mask, &port->status); |
1540 | * zfcp_erp_unit_boxed - Mark unit as "boxed" and start ERP | ||
1541 | * @port: The "boxed" unit. | ||
1542 | * @id: The debug trace id. | ||
1543 | * @id: Reference for the debug trace. | ||
1544 | */ | ||
1545 | void zfcp_erp_unit_boxed(struct zfcp_unit *unit, char *id, void *ref) | ||
1546 | { | ||
1547 | zfcp_erp_modify_unit_status(unit, id, ref, | ||
1548 | ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET); | ||
1549 | zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); | ||
1550 | } | ||
1551 | 1509 | ||
1552 | /** | 1510 | if (!common_mask) |
1553 | * zfcp_erp_port_access_denied - Adapter denied access to port. | 1511 | return; |
1554 | * @port: port where access has been denied | 1512 | |
1555 | * @id: id for debug trace | 1513 | shost_for_each_device(sdev, port->adapter->scsi_host) |
1556 | * @ref: reference for debug trace | 1514 | if (sdev_to_zfcp(sdev)->port == port) |
1557 | * | 1515 | atomic_set_mask(common_mask, |
1558 | * Since the adapter has denied access, stop using the port and the | 1516 | &sdev_to_zfcp(sdev)->status); |
1559 | * attached units. | ||
1560 | */ | ||
1561 | void zfcp_erp_port_access_denied(struct zfcp_port *port, char *id, void *ref) | ||
1562 | { | ||
1563 | zfcp_erp_modify_port_status(port, id, ref, | ||
1564 | ZFCP_STATUS_COMMON_ERP_FAILED | | ||
1565 | ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET); | ||
1566 | } | 1517 | } |
1567 | 1518 | ||
1568 | /** | 1519 | /** |
1569 | * zfcp_erp_unit_access_denied - Adapter denied access to unit. | 1520 | * zfcp_erp_clear_port_status - clear port status bits |
1570 | * @unit: unit where access has been denied | 1521 | * @port: adapter to change the status |
1571 | * @id: id for debug trace | 1522 | * @mask: status bits to change |
1572 | * @ref: reference for debug trace | ||
1573 | * | 1523 | * |
1574 | * Since the adapter has denied access, stop using the unit. | 1524 | * Changes in common status bits are propagated to attached LUNs. |
1575 | */ | 1525 | */ |
1576 | void zfcp_erp_unit_access_denied(struct zfcp_unit *unit, char *id, void *ref) | 1526 | void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask) |
1577 | { | 1527 | { |
1578 | zfcp_erp_modify_unit_status(unit, id, ref, | 1528 | struct scsi_device *sdev; |
1579 | ZFCP_STATUS_COMMON_ERP_FAILED | | 1529 | u32 common_mask = mask & ZFCP_COMMON_FLAGS; |
1580 | ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET); | 1530 | u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED; |
1581 | } | ||
1582 | 1531 | ||
1583 | static void zfcp_erp_unit_access_changed(struct zfcp_unit *unit, char *id, | 1532 | atomic_clear_mask(mask, &port->status); |
1584 | void *ref) | 1533 | |
1585 | { | 1534 | if (!common_mask) |
1586 | int status = atomic_read(&unit->status); | ||
1587 | if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED | | ||
1588 | ZFCP_STATUS_COMMON_ACCESS_BOXED))) | ||
1589 | return; | 1535 | return; |
1590 | 1536 | ||
1591 | zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); | 1537 | if (clear_counter) |
1538 | atomic_set(&port->erp_counter, 0); | ||
1539 | |||
1540 | shost_for_each_device(sdev, port->adapter->scsi_host) | ||
1541 | if (sdev_to_zfcp(sdev)->port == port) { | ||
1542 | atomic_clear_mask(common_mask, | ||
1543 | &sdev_to_zfcp(sdev)->status); | ||
1544 | if (clear_counter) | ||
1545 | atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0); | ||
1546 | } | ||
1592 | } | 1547 | } |
1593 | 1548 | ||
1594 | static void zfcp_erp_port_access_changed(struct zfcp_port *port, char *id, | 1549 | /** |
1595 | void *ref) | 1550 | * zfcp_erp_set_lun_status - set lun status bits |
1551 | * @sdev: SCSI device / lun to set the status bits | ||
1552 | * @mask: status bits to change | ||
1553 | */ | ||
1554 | void zfcp_erp_set_lun_status(struct scsi_device *sdev, u32 mask) | ||
1596 | { | 1555 | { |
1597 | struct zfcp_unit *unit; | 1556 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); |
1598 | unsigned long flags; | ||
1599 | int status = atomic_read(&port->status); | ||
1600 | 1557 | ||
1601 | if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED | | 1558 | atomic_set_mask(mask, &zfcp_sdev->status); |
1602 | ZFCP_STATUS_COMMON_ACCESS_BOXED))) { | ||
1603 | read_lock_irqsave(&port->unit_list_lock, flags); | ||
1604 | list_for_each_entry(unit, &port->unit_list, list) | ||
1605 | zfcp_erp_unit_access_changed(unit, id, ref); | ||
1606 | read_unlock_irqrestore(&port->unit_list_lock, flags); | ||
1607 | return; | ||
1608 | } | ||
1609 | |||
1610 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); | ||
1611 | } | 1559 | } |
1612 | 1560 | ||
1613 | /** | 1561 | /** |
1614 | * zfcp_erp_adapter_access_changed - Process change in adapter ACT | 1562 | * zfcp_erp_clear_lun_status - clear lun status bits |
1615 | * @adapter: Adapter where the Access Control Table (ACT) changed | 1563 | * @sdev: SCSi device / lun to clear the status bits |
1616 | * @id: Id for debug trace | 1564 | * @mask: status bits to change |
1617 | * @ref: Reference for debug trace | ||
1618 | */ | 1565 | */ |
1619 | void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, char *id, | 1566 | void zfcp_erp_clear_lun_status(struct scsi_device *sdev, u32 mask) |
1620 | void *ref) | ||
1621 | { | 1567 | { |
1622 | unsigned long flags; | 1568 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); |
1623 | struct zfcp_port *port; | ||
1624 | 1569 | ||
1625 | if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) | 1570 | atomic_clear_mask(mask, &zfcp_sdev->status); |
1626 | return; | ||
1627 | 1571 | ||
1628 | read_lock_irqsave(&adapter->port_list_lock, flags); | 1572 | if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) |
1629 | list_for_each_entry(port, &adapter->port_list, list) | 1573 | atomic_set(&zfcp_sdev->erp_counter, 0); |
1630 | zfcp_erp_port_access_changed(port, id, ref); | ||
1631 | read_unlock_irqrestore(&adapter->port_list_lock, flags); | ||
1632 | } | 1574 | } |
1575 | |||