diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_erp.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 162 |
1 files changed, 87 insertions, 75 deletions
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index f73e2180f333..0be5e7ea2828 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Error Recovery Procedures (ERP). | 4 | * Error Recovery Procedures (ERP). |
5 | * | 5 | * |
6 | * Copyright IBM Corporation 2002, 2009 | 6 | * Copyright IBM Corporation 2002, 2010 |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #define KMSG_COMPONENT "zfcp" | 9 | #define KMSG_COMPONENT "zfcp" |
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | #include <linux/kthread.h> | 12 | #include <linux/kthread.h> |
13 | #include "zfcp_ext.h" | 13 | #include "zfcp_ext.h" |
14 | #include "zfcp_reqlist.h" | ||
14 | 15 | ||
15 | #define ZFCP_MAX_ERPS 3 | 16 | #define ZFCP_MAX_ERPS 3 |
16 | 17 | ||
@@ -99,9 +100,12 @@ static void zfcp_erp_action_dismiss_port(struct zfcp_port *port) | |||
99 | 100 | ||
100 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE) | 101 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE) |
101 | zfcp_erp_action_dismiss(&port->erp_action); | 102 | zfcp_erp_action_dismiss(&port->erp_action); |
102 | else | 103 | else { |
103 | list_for_each_entry(unit, &port->unit_list_head, list) | 104 | read_lock(&port->unit_list_lock); |
104 | zfcp_erp_action_dismiss_unit(unit); | 105 | list_for_each_entry(unit, &port->unit_list, list) |
106 | zfcp_erp_action_dismiss_unit(unit); | ||
107 | read_unlock(&port->unit_list_lock); | ||
108 | } | ||
105 | } | 109 | } |
106 | 110 | ||
107 | static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) | 111 | static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) |
@@ -110,9 +114,12 @@ static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) | |||
110 | 114 | ||
111 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_INUSE) | 115 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_INUSE) |
112 | zfcp_erp_action_dismiss(&adapter->erp_action); | 116 | zfcp_erp_action_dismiss(&adapter->erp_action); |
113 | else | 117 | else { |
114 | list_for_each_entry(port, &adapter->port_list_head, list) | 118 | read_lock(&adapter->port_list_lock); |
119 | list_for_each_entry(port, &adapter->port_list, list) | ||
115 | zfcp_erp_action_dismiss_port(port); | 120 | zfcp_erp_action_dismiss_port(port); |
121 | read_unlock(&adapter->port_list_lock); | ||
122 | } | ||
116 | } | 123 | } |
117 | 124 | ||
118 | 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, |
@@ -168,7 +175,8 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, | |||
168 | 175 | ||
169 | switch (need) { | 176 | switch (need) { |
170 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 177 | case ZFCP_ERP_ACTION_REOPEN_UNIT: |
171 | zfcp_unit_get(unit); | 178 | if (!get_device(&unit->dev)) |
179 | return NULL; | ||
172 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status); | 180 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status); |
173 | erp_action = &unit->erp_action; | 181 | erp_action = &unit->erp_action; |
174 | if (!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_RUNNING)) | 182 | if (!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_RUNNING)) |
@@ -177,7 +185,8 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, | |||
177 | 185 | ||
178 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 186 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
179 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 187 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
180 | zfcp_port_get(port); | 188 | if (!get_device(&port->dev)) |
189 | return NULL; | ||
181 | zfcp_erp_action_dismiss_port(port); | 190 | zfcp_erp_action_dismiss_port(port); |
182 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status); | 191 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status); |
183 | erp_action = &port->erp_action; | 192 | erp_action = &port->erp_action; |
@@ -186,7 +195,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, | |||
186 | break; | 195 | break; |
187 | 196 | ||
188 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | 197 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: |
189 | zfcp_adapter_get(adapter); | 198 | kref_get(&adapter->ref); |
190 | zfcp_erp_action_dismiss_adapter(adapter); | 199 | zfcp_erp_action_dismiss_adapter(adapter); |
191 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status); | 200 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status); |
192 | erp_action = &adapter->erp_action; | 201 | erp_action = &adapter->erp_action; |
@@ -264,11 +273,16 @@ void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, | |||
264 | { | 273 | { |
265 | unsigned long flags; | 274 | unsigned long flags; |
266 | 275 | ||
267 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 276 | zfcp_erp_adapter_block(adapter, clear); |
268 | write_lock(&adapter->erp_lock); | 277 | zfcp_scsi_schedule_rports_block(adapter); |
269 | _zfcp_erp_adapter_reopen(adapter, clear, id, ref); | 278 | |
270 | write_unlock(&adapter->erp_lock); | 279 | write_lock_irqsave(&adapter->erp_lock, flags); |
271 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | 280 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) |
281 | zfcp_erp_adapter_failed(adapter, "erareo1", NULL); | ||
282 | else | ||
283 | zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter, | ||
284 | NULL, NULL, id, ref); | ||
285 | write_unlock_irqrestore(&adapter->erp_lock, flags); | ||
272 | } | 286 | } |
273 | 287 | ||
274 | /** | 288 | /** |
@@ -345,11 +359,9 @@ void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, char *id, | |||
345 | unsigned long flags; | 359 | unsigned long flags; |
346 | struct zfcp_adapter *adapter = port->adapter; | 360 | struct zfcp_adapter *adapter = port->adapter; |
347 | 361 | ||
348 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 362 | write_lock_irqsave(&adapter->erp_lock, flags); |
349 | write_lock(&adapter->erp_lock); | ||
350 | _zfcp_erp_port_forced_reopen(port, clear, id, ref); | 363 | _zfcp_erp_port_forced_reopen(port, clear, id, ref); |
351 | write_unlock(&adapter->erp_lock); | 364 | write_unlock_irqrestore(&adapter->erp_lock, flags); |
352 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
353 | } | 365 | } |
354 | 366 | ||
355 | static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, | 367 | static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, |
@@ -377,15 +389,13 @@ static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, | |||
377 | */ | 389 | */ |
378 | int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, void *ref) | 390 | int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, void *ref) |
379 | { | 391 | { |
380 | unsigned long flags; | ||
381 | int retval; | 392 | int retval; |
393 | unsigned long flags; | ||
382 | struct zfcp_adapter *adapter = port->adapter; | 394 | struct zfcp_adapter *adapter = port->adapter; |
383 | 395 | ||
384 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 396 | write_lock_irqsave(&adapter->erp_lock, flags); |
385 | write_lock(&adapter->erp_lock); | ||
386 | retval = _zfcp_erp_port_reopen(port, clear, id, ref); | 397 | retval = _zfcp_erp_port_reopen(port, clear, id, ref); |
387 | write_unlock(&adapter->erp_lock); | 398 | write_unlock_irqrestore(&adapter->erp_lock, flags); |
388 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
389 | 399 | ||
390 | return retval; | 400 | return retval; |
391 | } | 401 | } |
@@ -424,11 +434,9 @@ void zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id, | |||
424 | struct zfcp_port *port = unit->port; | 434 | struct zfcp_port *port = unit->port; |
425 | struct zfcp_adapter *adapter = port->adapter; | 435 | struct zfcp_adapter *adapter = port->adapter; |
426 | 436 | ||
427 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 437 | write_lock_irqsave(&adapter->erp_lock, flags); |
428 | write_lock(&adapter->erp_lock); | ||
429 | _zfcp_erp_unit_reopen(unit, clear, id, ref); | 438 | _zfcp_erp_unit_reopen(unit, clear, id, ref); |
430 | write_unlock(&adapter->erp_lock); | 439 | write_unlock_irqrestore(&adapter->erp_lock, flags); |
431 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
432 | } | 440 | } |
433 | 441 | ||
434 | static int status_change_set(unsigned long mask, atomic_t *status) | 442 | static int status_change_set(unsigned long mask, atomic_t *status) |
@@ -471,26 +479,27 @@ static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) | |||
471 | static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act) | 479 | static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act) |
472 | { | 480 | { |
473 | struct zfcp_adapter *adapter = act->adapter; | 481 | struct zfcp_adapter *adapter = act->adapter; |
482 | struct zfcp_fsf_req *req; | ||
474 | 483 | ||
475 | if (!act->fsf_req) | 484 | if (!act->fsf_req_id) |
476 | return; | 485 | return; |
477 | 486 | ||
478 | spin_lock(&adapter->req_list_lock); | 487 | spin_lock(&adapter->req_list->lock); |
479 | if (zfcp_reqlist_find_safe(adapter, act->fsf_req) && | 488 | req = _zfcp_reqlist_find(adapter->req_list, act->fsf_req_id); |
480 | act->fsf_req->erp_action == act) { | 489 | if (req && req->erp_action == act) { |
481 | if (act->status & (ZFCP_STATUS_ERP_DISMISSED | | 490 | if (act->status & (ZFCP_STATUS_ERP_DISMISSED | |
482 | ZFCP_STATUS_ERP_TIMEDOUT)) { | 491 | ZFCP_STATUS_ERP_TIMEDOUT)) { |
483 | act->fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; | 492 | req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; |
484 | zfcp_dbf_rec_action("erscf_1", act); | 493 | zfcp_dbf_rec_action("erscf_1", act); |
485 | act->fsf_req->erp_action = NULL; | 494 | req->erp_action = NULL; |
486 | } | 495 | } |
487 | if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) | 496 | if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) |
488 | zfcp_dbf_rec_action("erscf_2", act); | 497 | zfcp_dbf_rec_action("erscf_2", act); |
489 | if (act->fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) | 498 | if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) |
490 | act->fsf_req = NULL; | 499 | act->fsf_req_id = 0; |
491 | } else | 500 | } else |
492 | act->fsf_req = NULL; | 501 | act->fsf_req_id = 0; |
493 | spin_unlock(&adapter->req_list_lock); | 502 | spin_unlock(&adapter->req_list->lock); |
494 | } | 503 | } |
495 | 504 | ||
496 | /** | 505 | /** |
@@ -540,8 +549,10 @@ static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, | |||
540 | { | 549 | { |
541 | struct zfcp_port *port; | 550 | struct zfcp_port *port; |
542 | 551 | ||
543 | list_for_each_entry(port, &adapter->port_list_head, list) | 552 | read_lock(&adapter->port_list_lock); |
553 | list_for_each_entry(port, &adapter->port_list, list) | ||
544 | _zfcp_erp_port_reopen(port, clear, id, ref); | 554 | _zfcp_erp_port_reopen(port, clear, id, ref); |
555 | read_unlock(&adapter->port_list_lock); | ||
545 | } | 556 | } |
546 | 557 | ||
547 | static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear, | 558 | static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear, |
@@ -549,8 +560,10 @@ static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear, | |||
549 | { | 560 | { |
550 | struct zfcp_unit *unit; | 561 | struct zfcp_unit *unit; |
551 | 562 | ||
552 | list_for_each_entry(unit, &port->unit_list_head, list) | 563 | read_lock(&port->unit_list_lock); |
564 | list_for_each_entry(unit, &port->unit_list, list) | ||
553 | _zfcp_erp_unit_reopen(unit, clear, id, ref); | 565 | _zfcp_erp_unit_reopen(unit, clear, id, ref); |
566 | read_unlock(&port->unit_list_lock); | ||
554 | } | 567 | } |
555 | 568 | ||
556 | static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act) | 569 | static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act) |
@@ -590,16 +603,14 @@ static void zfcp_erp_wakeup(struct zfcp_adapter *adapter) | |||
590 | { | 603 | { |
591 | unsigned long flags; | 604 | unsigned long flags; |
592 | 605 | ||
593 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 606 | read_lock_irqsave(&adapter->erp_lock, flags); |
594 | read_lock(&adapter->erp_lock); | ||
595 | if (list_empty(&adapter->erp_ready_head) && | 607 | if (list_empty(&adapter->erp_ready_head) && |
596 | list_empty(&adapter->erp_running_head)) { | 608 | list_empty(&adapter->erp_running_head)) { |
597 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, | 609 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, |
598 | &adapter->status); | 610 | &adapter->status); |
599 | wake_up(&adapter->erp_done_wqh); | 611 | wake_up(&adapter->erp_done_wqh); |
600 | } | 612 | } |
601 | read_unlock(&adapter->erp_lock); | 613 | read_unlock_irqrestore(&adapter->erp_lock, flags); |
602 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
603 | } | 614 | } |
604 | 615 | ||
605 | static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *act) | 616 | static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *act) |
@@ -1170,28 +1181,28 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) | |||
1170 | switch (act->action) { | 1181 | switch (act->action) { |
1171 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 1182 | case ZFCP_ERP_ACTION_REOPEN_UNIT: |
1172 | if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) { | 1183 | if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) { |
1173 | zfcp_unit_get(unit); | 1184 | get_device(&unit->dev); |
1174 | if (scsi_queue_work(unit->port->adapter->scsi_host, | 1185 | if (scsi_queue_work(unit->port->adapter->scsi_host, |
1175 | &unit->scsi_work) <= 0) | 1186 | &unit->scsi_work) <= 0) |
1176 | zfcp_unit_put(unit); | 1187 | put_device(&unit->dev); |
1177 | } | 1188 | } |
1178 | zfcp_unit_put(unit); | 1189 | put_device(&unit->dev); |
1179 | break; | 1190 | break; |
1180 | 1191 | ||
1181 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 1192 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
1182 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 1193 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
1183 | if (result == ZFCP_ERP_SUCCEEDED) | 1194 | if (result == ZFCP_ERP_SUCCEEDED) |
1184 | zfcp_scsi_schedule_rport_register(port); | 1195 | zfcp_scsi_schedule_rport_register(port); |
1185 | zfcp_port_put(port); | 1196 | put_device(&port->dev); |
1186 | break; | 1197 | break; |
1187 | 1198 | ||
1188 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | 1199 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: |
1189 | if (result == ZFCP_ERP_SUCCEEDED) { | 1200 | if (result == ZFCP_ERP_SUCCEEDED) { |
1190 | register_service_level(&adapter->service_level); | 1201 | register_service_level(&adapter->service_level); |
1191 | schedule_work(&adapter->scan_work); | 1202 | queue_work(adapter->work_queue, &adapter->scan_work); |
1192 | } else | 1203 | } else |
1193 | unregister_service_level(&adapter->service_level); | 1204 | unregister_service_level(&adapter->service_level); |
1194 | zfcp_adapter_put(adapter); | 1205 | kref_put(&adapter->ref, zfcp_adapter_release); |
1195 | break; | 1206 | break; |
1196 | } | 1207 | } |
1197 | } | 1208 | } |
@@ -1214,12 +1225,12 @@ static int zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action) | |||
1214 | static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action) | 1225 | static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action) |
1215 | { | 1226 | { |
1216 | int retval; | 1227 | int retval; |
1217 | struct zfcp_adapter *adapter = erp_action->adapter; | ||
1218 | unsigned long flags; | 1228 | unsigned long flags; |
1229 | struct zfcp_adapter *adapter = erp_action->adapter; | ||
1219 | 1230 | ||
1220 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 1231 | kref_get(&adapter->ref); |
1221 | write_lock(&adapter->erp_lock); | ||
1222 | 1232 | ||
1233 | write_lock_irqsave(&adapter->erp_lock, flags); | ||
1223 | zfcp_erp_strategy_check_fsfreq(erp_action); | 1234 | zfcp_erp_strategy_check_fsfreq(erp_action); |
1224 | 1235 | ||
1225 | if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) { | 1236 | if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) { |
@@ -1231,11 +1242,9 @@ static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action) | |||
1231 | zfcp_erp_action_to_running(erp_action); | 1242 | zfcp_erp_action_to_running(erp_action); |
1232 | 1243 | ||
1233 | /* no lock to allow for blocking operations */ | 1244 | /* no lock to allow for blocking operations */ |
1234 | write_unlock(&adapter->erp_lock); | 1245 | write_unlock_irqrestore(&adapter->erp_lock, flags); |
1235 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
1236 | retval = zfcp_erp_strategy_do_action(erp_action); | 1246 | retval = zfcp_erp_strategy_do_action(erp_action); |
1237 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 1247 | write_lock_irqsave(&adapter->erp_lock, flags); |
1238 | write_lock(&adapter->erp_lock); | ||
1239 | 1248 | ||
1240 | if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) | 1249 | if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) |
1241 | retval = ZFCP_ERP_CONTINUES; | 1250 | retval = ZFCP_ERP_CONTINUES; |
@@ -1273,12 +1282,12 @@ static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action) | |||
1273 | zfcp_erp_strategy_followup_failed(erp_action); | 1282 | zfcp_erp_strategy_followup_failed(erp_action); |
1274 | 1283 | ||
1275 | unlock: | 1284 | unlock: |
1276 | write_unlock(&adapter->erp_lock); | 1285 | write_unlock_irqrestore(&adapter->erp_lock, flags); |
1277 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
1278 | 1286 | ||
1279 | if (retval != ZFCP_ERP_CONTINUES) | 1287 | if (retval != ZFCP_ERP_CONTINUES) |
1280 | zfcp_erp_action_cleanup(erp_action, retval); | 1288 | zfcp_erp_action_cleanup(erp_action, retval); |
1281 | 1289 | ||
1290 | kref_put(&adapter->ref, zfcp_adapter_release); | ||
1282 | return retval; | 1291 | return retval; |
1283 | } | 1292 | } |
1284 | 1293 | ||
@@ -1415,6 +1424,7 @@ void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, char *id, | |||
1415 | void *ref, u32 mask, int set_or_clear) | 1424 | void *ref, u32 mask, int set_or_clear) |
1416 | { | 1425 | { |
1417 | struct zfcp_port *port; | 1426 | struct zfcp_port *port; |
1427 | unsigned long flags; | ||
1418 | u32 common_mask = mask & ZFCP_COMMON_FLAGS; | 1428 | u32 common_mask = mask & ZFCP_COMMON_FLAGS; |
1419 | 1429 | ||
1420 | if (set_or_clear == ZFCP_SET) { | 1430 | if (set_or_clear == ZFCP_SET) { |
@@ -1429,10 +1439,13 @@ void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, char *id, | |||
1429 | atomic_set(&adapter->erp_counter, 0); | 1439 | atomic_set(&adapter->erp_counter, 0); |
1430 | } | 1440 | } |
1431 | 1441 | ||
1432 | if (common_mask) | 1442 | if (common_mask) { |
1433 | list_for_each_entry(port, &adapter->port_list_head, list) | 1443 | read_lock_irqsave(&adapter->port_list_lock, flags); |
1444 | list_for_each_entry(port, &adapter->port_list, list) | ||
1434 | zfcp_erp_modify_port_status(port, id, ref, common_mask, | 1445 | zfcp_erp_modify_port_status(port, id, ref, common_mask, |
1435 | set_or_clear); | 1446 | set_or_clear); |
1447 | read_unlock_irqrestore(&adapter->port_list_lock, flags); | ||
1448 | } | ||
1436 | } | 1449 | } |
1437 | 1450 | ||
1438 | /** | 1451 | /** |
@@ -1449,6 +1462,7 @@ void zfcp_erp_modify_port_status(struct zfcp_port *port, char *id, void *ref, | |||
1449 | u32 mask, int set_or_clear) | 1462 | u32 mask, int set_or_clear) |
1450 | { | 1463 | { |
1451 | struct zfcp_unit *unit; | 1464 | struct zfcp_unit *unit; |
1465 | unsigned long flags; | ||
1452 | u32 common_mask = mask & ZFCP_COMMON_FLAGS; | 1466 | u32 common_mask = mask & ZFCP_COMMON_FLAGS; |
1453 | 1467 | ||
1454 | if (set_or_clear == ZFCP_SET) { | 1468 | if (set_or_clear == ZFCP_SET) { |
@@ -1463,10 +1477,13 @@ void zfcp_erp_modify_port_status(struct zfcp_port *port, char *id, void *ref, | |||
1463 | atomic_set(&port->erp_counter, 0); | 1477 | atomic_set(&port->erp_counter, 0); |
1464 | } | 1478 | } |
1465 | 1479 | ||
1466 | if (common_mask) | 1480 | if (common_mask) { |
1467 | list_for_each_entry(unit, &port->unit_list_head, list) | 1481 | read_lock_irqsave(&port->unit_list_lock, flags); |
1482 | list_for_each_entry(unit, &port->unit_list, list) | ||
1468 | zfcp_erp_modify_unit_status(unit, id, ref, common_mask, | 1483 | zfcp_erp_modify_unit_status(unit, id, ref, common_mask, |
1469 | set_or_clear); | 1484 | set_or_clear); |
1485 | read_unlock_irqrestore(&port->unit_list_lock, flags); | ||
1486 | } | ||
1470 | } | 1487 | } |
1471 | 1488 | ||
1472 | /** | 1489 | /** |
@@ -1502,12 +1519,8 @@ void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, char *id, void *ref, | |||
1502 | */ | 1519 | */ |
1503 | void zfcp_erp_port_boxed(struct zfcp_port *port, char *id, void *ref) | 1520 | void zfcp_erp_port_boxed(struct zfcp_port *port, char *id, void *ref) |
1504 | { | 1521 | { |
1505 | unsigned long flags; | ||
1506 | |||
1507 | read_lock_irqsave(&zfcp_data.config_lock, flags); | ||
1508 | zfcp_erp_modify_port_status(port, id, ref, | 1522 | zfcp_erp_modify_port_status(port, id, ref, |
1509 | ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET); | 1523 | ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET); |
1510 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
1511 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); | 1524 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); |
1512 | } | 1525 | } |
1513 | 1526 | ||
@@ -1535,13 +1548,9 @@ void zfcp_erp_unit_boxed(struct zfcp_unit *unit, char *id, void *ref) | |||
1535 | */ | 1548 | */ |
1536 | void zfcp_erp_port_access_denied(struct zfcp_port *port, char *id, void *ref) | 1549 | void zfcp_erp_port_access_denied(struct zfcp_port *port, char *id, void *ref) |
1537 | { | 1550 | { |
1538 | unsigned long flags; | ||
1539 | |||
1540 | read_lock_irqsave(&zfcp_data.config_lock, flags); | ||
1541 | zfcp_erp_modify_port_status(port, id, ref, | 1551 | zfcp_erp_modify_port_status(port, id, ref, |
1542 | ZFCP_STATUS_COMMON_ERP_FAILED | | 1552 | ZFCP_STATUS_COMMON_ERP_FAILED | |
1543 | ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET); | 1553 | ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET); |
1544 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
1545 | } | 1554 | } |
1546 | 1555 | ||
1547 | /** | 1556 | /** |
@@ -1574,12 +1583,15 @@ static void zfcp_erp_port_access_changed(struct zfcp_port *port, char *id, | |||
1574 | void *ref) | 1583 | void *ref) |
1575 | { | 1584 | { |
1576 | struct zfcp_unit *unit; | 1585 | struct zfcp_unit *unit; |
1586 | unsigned long flags; | ||
1577 | int status = atomic_read(&port->status); | 1587 | int status = atomic_read(&port->status); |
1578 | 1588 | ||
1579 | if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED | | 1589 | if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED | |
1580 | ZFCP_STATUS_COMMON_ACCESS_BOXED))) { | 1590 | ZFCP_STATUS_COMMON_ACCESS_BOXED))) { |
1581 | list_for_each_entry(unit, &port->unit_list_head, list) | 1591 | read_lock_irqsave(&port->unit_list_lock, flags); |
1592 | list_for_each_entry(unit, &port->unit_list, list) | ||
1582 | zfcp_erp_unit_access_changed(unit, id, ref); | 1593 | zfcp_erp_unit_access_changed(unit, id, ref); |
1594 | read_unlock_irqrestore(&port->unit_list_lock, flags); | ||
1583 | return; | 1595 | return; |
1584 | } | 1596 | } |
1585 | 1597 | ||
@@ -1595,14 +1607,14 @@ static void zfcp_erp_port_access_changed(struct zfcp_port *port, char *id, | |||
1595 | void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, char *id, | 1607 | void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, char *id, |
1596 | void *ref) | 1608 | void *ref) |
1597 | { | 1609 | { |
1598 | struct zfcp_port *port; | ||
1599 | unsigned long flags; | 1610 | unsigned long flags; |
1611 | struct zfcp_port *port; | ||
1600 | 1612 | ||
1601 | if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) | 1613 | if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) |
1602 | return; | 1614 | return; |
1603 | 1615 | ||
1604 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 1616 | read_lock_irqsave(&adapter->port_list_lock, flags); |
1605 | list_for_each_entry(port, &adapter->port_list_head, list) | 1617 | list_for_each_entry(port, &adapter->port_list, list) |
1606 | zfcp_erp_port_access_changed(port, id, ref); | 1618 | zfcp_erp_port_access_changed(port, id, ref); |
1607 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | 1619 | read_unlock_irqrestore(&adapter->port_list_lock, flags); |
1608 | } | 1620 | } |