diff options
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 4 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 6 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 62 |
3 files changed, 27 insertions, 45 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index ed9a8a1517c6..e8f39f02bc3b 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -529,7 +529,7 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
529 | goto generic_services_failed; | 529 | goto generic_services_failed; |
530 | 530 | ||
531 | init_waitqueue_head(&adapter->remove_wq); | 531 | init_waitqueue_head(&adapter->remove_wq); |
532 | init_waitqueue_head(&adapter->erp_thread_wqh); | 532 | init_waitqueue_head(&adapter->erp_ready_wq); |
533 | init_waitqueue_head(&adapter->erp_done_wqh); | 533 | init_waitqueue_head(&adapter->erp_done_wqh); |
534 | 534 | ||
535 | INIT_LIST_HEAD(&adapter->port_list_head); | 535 | INIT_LIST_HEAD(&adapter->port_list_head); |
@@ -541,8 +541,6 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
541 | rwlock_init(&adapter->erp_lock); | 541 | rwlock_init(&adapter->erp_lock); |
542 | rwlock_init(&adapter->abort_lock); | 542 | rwlock_init(&adapter->abort_lock); |
543 | 543 | ||
544 | sema_init(&adapter->erp_ready_sem, 0); | ||
545 | |||
546 | INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler); | 544 | INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler); |
547 | INIT_WORK(&adapter->scan_work, _zfcp_fc_scan_ports_later); | 545 | INIT_WORK(&adapter->scan_work, _zfcp_fc_scan_ports_later); |
548 | 546 | ||
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 9a8ff0553421..ce65d88e280c 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
@@ -222,8 +222,6 @@ struct zfcp_ls_adisc { | |||
222 | #define ZFCP_STATUS_ADAPTER_QDIOUP 0x00000002 | 222 | #define ZFCP_STATUS_ADAPTER_QDIOUP 0x00000002 |
223 | #define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008 | 223 | #define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008 |
224 | #define ZFCP_STATUS_ADAPTER_HOST_CON_INIT 0x00000010 | 224 | #define ZFCP_STATUS_ADAPTER_HOST_CON_INIT 0x00000010 |
225 | #define ZFCP_STATUS_ADAPTER_ERP_THREAD_UP 0x00000020 | ||
226 | #define ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL 0x00000080 | ||
227 | #define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100 | 225 | #define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100 |
228 | #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200 | 226 | #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200 |
229 | 227 | ||
@@ -481,10 +479,9 @@ struct zfcp_adapter { | |||
481 | atomic_t status; /* status of this adapter */ | 479 | atomic_t status; /* status of this adapter */ |
482 | struct list_head erp_ready_head; /* error recovery for this | 480 | struct list_head erp_ready_head; /* error recovery for this |
483 | adapter/devices */ | 481 | adapter/devices */ |
482 | wait_queue_head_t erp_ready_wq; | ||
484 | struct list_head erp_running_head; | 483 | struct list_head erp_running_head; |
485 | rwlock_t erp_lock; | 484 | rwlock_t erp_lock; |
486 | struct semaphore erp_ready_sem; | ||
487 | wait_queue_head_t erp_thread_wqh; | ||
488 | wait_queue_head_t erp_done_wqh; | 485 | wait_queue_head_t erp_done_wqh; |
489 | struct zfcp_erp_action erp_action; /* pending error recovery */ | 486 | struct zfcp_erp_action erp_action; /* pending error recovery */ |
490 | atomic_t erp_counter; | 487 | atomic_t erp_counter; |
@@ -492,6 +489,7 @@ struct zfcp_adapter { | |||
492 | actions */ | 489 | actions */ |
493 | u32 erp_low_mem_count; /* nr of erp actions waiting | 490 | u32 erp_low_mem_count; /* nr of erp actions waiting |
494 | for memory */ | 491 | for memory */ |
492 | struct task_struct *erp_thread; | ||
495 | struct zfcp_wka_ports *gs; /* generic services */ | 493 | struct zfcp_wka_ports *gs; /* generic services */ |
496 | struct zfcp_dbf *dbf; /* debug traces */ | 494 | struct zfcp_dbf *dbf; /* debug traces */ |
497 | struct zfcp_adapter_mempool pool; /* Adapter memory pools */ | 495 | struct zfcp_adapter_mempool pool; /* Adapter memory pools */ |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 373567eda8f6..577e15708598 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #define KMSG_COMPONENT "zfcp" | 9 | #define KMSG_COMPONENT "zfcp" |
10 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 10 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
11 | 11 | ||
12 | #include <linux/kthread.h> | ||
12 | #include "zfcp_ext.h" | 13 | #include "zfcp_ext.h" |
13 | 14 | ||
14 | #define ZFCP_MAX_ERPS 3 | 15 | #define ZFCP_MAX_ERPS 3 |
@@ -75,7 +76,7 @@ static void zfcp_erp_action_ready(struct zfcp_erp_action *act) | |||
75 | 76 | ||
76 | list_move(&act->list, &act->adapter->erp_ready_head); | 77 | list_move(&act->list, &act->adapter->erp_ready_head); |
77 | zfcp_dbf_rec_action("erardy1", act); | 78 | zfcp_dbf_rec_action("erardy1", act); |
78 | up(&adapter->erp_ready_sem); | 79 | wake_up(&adapter->erp_ready_wq); |
79 | zfcp_dbf_rec_thread("erardy2", adapter->dbf); | 80 | zfcp_dbf_rec_thread("erardy2", adapter->dbf); |
80 | } | 81 | } |
81 | 82 | ||
@@ -212,8 +213,7 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, | |||
212 | int retval = 1, need; | 213 | int retval = 1, need; |
213 | struct zfcp_erp_action *act = NULL; | 214 | struct zfcp_erp_action *act = NULL; |
214 | 215 | ||
215 | if (!(atomic_read(&adapter->status) & | 216 | if (!adapter->erp_thread) |
216 | ZFCP_STATUS_ADAPTER_ERP_THREAD_UP)) | ||
217 | return -EIO; | 217 | return -EIO; |
218 | 218 | ||
219 | need = zfcp_erp_required_act(want, adapter, port, unit); | 219 | need = zfcp_erp_required_act(want, adapter, port, unit); |
@@ -226,7 +226,7 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, | |||
226 | goto out; | 226 | goto out; |
227 | ++adapter->erp_total_count; | 227 | ++adapter->erp_total_count; |
228 | list_add_tail(&act->list, &adapter->erp_ready_head); | 228 | list_add_tail(&act->list, &adapter->erp_ready_head); |
229 | up(&adapter->erp_ready_sem); | 229 | wake_up(&adapter->erp_ready_wq); |
230 | zfcp_dbf_rec_thread("eracte1", adapter->dbf); | 230 | zfcp_dbf_rec_thread("eracte1", adapter->dbf); |
231 | retval = 0; | 231 | retval = 0; |
232 | out: | 232 | out: |
@@ -641,7 +641,8 @@ static int zfcp_erp_adapter_strat_fsf_xconf(struct zfcp_erp_action *erp_action) | |||
641 | } | 641 | } |
642 | 642 | ||
643 | zfcp_dbf_rec_thread_lock("erasfx1", adapter->dbf); | 643 | zfcp_dbf_rec_thread_lock("erasfx1", adapter->dbf); |
644 | down(&adapter->erp_ready_sem); | 644 | wait_event(adapter->erp_ready_wq, |
645 | !list_empty(&adapter->erp_ready_head)); | ||
645 | zfcp_dbf_rec_thread_lock("erasfx2", adapter->dbf); | 646 | zfcp_dbf_rec_thread_lock("erasfx2", adapter->dbf); |
646 | if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) | 647 | if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) |
647 | break; | 648 | break; |
@@ -682,7 +683,8 @@ static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *act) | |||
682 | return ZFCP_ERP_FAILED; | 683 | return ZFCP_ERP_FAILED; |
683 | 684 | ||
684 | zfcp_dbf_rec_thread_lock("erasox1", adapter->dbf); | 685 | zfcp_dbf_rec_thread_lock("erasox1", adapter->dbf); |
685 | down(&adapter->erp_ready_sem); | 686 | wait_event(adapter->erp_ready_wq, |
687 | !list_empty(&adapter->erp_ready_head)); | ||
686 | zfcp_dbf_rec_thread_lock("erasox2", adapter->dbf); | 688 | zfcp_dbf_rec_thread_lock("erasox2", adapter->dbf); |
687 | if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) | 689 | if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) |
688 | return ZFCP_ERP_FAILED; | 690 | return ZFCP_ERP_FAILED; |
@@ -1285,21 +1287,17 @@ static int zfcp_erp_thread(void *data) | |||
1285 | struct list_head *next; | 1287 | struct list_head *next; |
1286 | struct zfcp_erp_action *act; | 1288 | struct zfcp_erp_action *act; |
1287 | unsigned long flags; | 1289 | unsigned long flags; |
1288 | int ignore; | ||
1289 | |||
1290 | daemonize("zfcperp%s", dev_name(&adapter->ccw_device->dev)); | ||
1291 | /* Block all signals */ | ||
1292 | siginitsetinv(¤t->blocked, 0); | ||
1293 | atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); | ||
1294 | wake_up(&adapter->erp_thread_wqh); | ||
1295 | |||
1296 | while (!(atomic_read(&adapter->status) & | ||
1297 | ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL)) { | ||
1298 | 1290 | ||
1291 | for (;;) { | ||
1299 | zfcp_dbf_rec_thread_lock("erthrd1", adapter->dbf); | 1292 | zfcp_dbf_rec_thread_lock("erthrd1", adapter->dbf); |
1300 | ignore = down_interruptible(&adapter->erp_ready_sem); | 1293 | wait_event_interruptible(adapter->erp_ready_wq, |
1294 | !list_empty(&adapter->erp_ready_head) || | ||
1295 | kthread_should_stop()); | ||
1301 | zfcp_dbf_rec_thread_lock("erthrd2", adapter->dbf); | 1296 | zfcp_dbf_rec_thread_lock("erthrd2", adapter->dbf); |
1302 | 1297 | ||
1298 | if (kthread_should_stop()) | ||
1299 | break; | ||
1300 | |||
1303 | write_lock_irqsave(&adapter->erp_lock, flags); | 1301 | write_lock_irqsave(&adapter->erp_lock, flags); |
1304 | next = adapter->erp_ready_head.next; | 1302 | next = adapter->erp_ready_head.next; |
1305 | write_unlock_irqrestore(&adapter->erp_lock, flags); | 1303 | write_unlock_irqrestore(&adapter->erp_lock, flags); |
@@ -1313,9 +1311,6 @@ static int zfcp_erp_thread(void *data) | |||
1313 | } | 1311 | } |
1314 | } | 1312 | } |
1315 | 1313 | ||
1316 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); | ||
1317 | wake_up(&adapter->erp_thread_wqh); | ||
1318 | |||
1319 | return 0; | 1314 | return 0; |
1320 | } | 1315 | } |
1321 | 1316 | ||
@@ -1327,18 +1322,17 @@ static int zfcp_erp_thread(void *data) | |||
1327 | */ | 1322 | */ |
1328 | int zfcp_erp_thread_setup(struct zfcp_adapter *adapter) | 1323 | int zfcp_erp_thread_setup(struct zfcp_adapter *adapter) |
1329 | { | 1324 | { |
1330 | int retval; | 1325 | struct task_struct *thread; |
1331 | 1326 | ||
1332 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); | 1327 | thread = kthread_run(zfcp_erp_thread, adapter, "zfcperp%s", |
1333 | retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD); | 1328 | dev_name(&adapter->ccw_device->dev)); |
1334 | if (retval < 0) { | 1329 | if (IS_ERR(thread)) { |
1335 | dev_err(&adapter->ccw_device->dev, | 1330 | dev_err(&adapter->ccw_device->dev, |
1336 | "Creating an ERP thread for the FCP device failed.\n"); | 1331 | "Creating an ERP thread for the FCP device failed.\n"); |
1337 | return retval; | 1332 | return PTR_ERR(thread); |
1338 | } | 1333 | } |
1339 | wait_event(adapter->erp_thread_wqh, | 1334 | |
1340 | atomic_read(&adapter->status) & | 1335 | adapter->erp_thread = thread; |
1341 | ZFCP_STATUS_ADAPTER_ERP_THREAD_UP); | ||
1342 | return 0; | 1336 | return 0; |
1343 | } | 1337 | } |
1344 | 1338 | ||
@@ -1353,16 +1347,8 @@ int zfcp_erp_thread_setup(struct zfcp_adapter *adapter) | |||
1353 | */ | 1347 | */ |
1354 | void zfcp_erp_thread_kill(struct zfcp_adapter *adapter) | 1348 | void zfcp_erp_thread_kill(struct zfcp_adapter *adapter) |
1355 | { | 1349 | { |
1356 | atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, &adapter->status); | 1350 | kthread_stop(adapter->erp_thread); |
1357 | up(&adapter->erp_ready_sem); | 1351 | adapter->erp_thread = NULL; |
1358 | zfcp_dbf_rec_thread_lock("erthrk1", adapter->dbf); | ||
1359 | |||
1360 | wait_event(adapter->erp_thread_wqh, | ||
1361 | !(atomic_read(&adapter->status) & | ||
1362 | ZFCP_STATUS_ADAPTER_ERP_THREAD_UP)); | ||
1363 | |||
1364 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, | ||
1365 | &adapter->status); | ||
1366 | } | 1352 | } |
1367 | 1353 | ||
1368 | /** | 1354 | /** |