diff options
-rw-r--r-- | drivers/scsi/fcoe/fcoe.c | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 8a1005d117b7..46c57e5755ae 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/fs.h> | 31 | #include <linux/fs.h> |
32 | #include <linux/sysfs.h> | 32 | #include <linux/sysfs.h> |
33 | #include <linux/ctype.h> | 33 | #include <linux/ctype.h> |
34 | #include <linux/workqueue.h> | ||
34 | #include <scsi/scsi_tcq.h> | 35 | #include <scsi/scsi_tcq.h> |
35 | #include <scsi/scsicam.h> | 36 | #include <scsi/scsicam.h> |
36 | #include <scsi/scsi_transport.h> | 37 | #include <scsi/scsi_transport.h> |
@@ -58,6 +59,8 @@ MODULE_PARM_DESC(ddp_min, "Minimum I/O size in bytes for " \ | |||
58 | 59 | ||
59 | DEFINE_MUTEX(fcoe_config_mutex); | 60 | DEFINE_MUTEX(fcoe_config_mutex); |
60 | 61 | ||
62 | static struct workqueue_struct *fcoe_wq; | ||
63 | |||
61 | /* fcoe_percpu_clean completion. Waiter protected by fcoe_create_mutex */ | 64 | /* fcoe_percpu_clean completion. Waiter protected by fcoe_create_mutex */ |
62 | static DECLARE_COMPLETION(fcoe_flush_completion); | 65 | static DECLARE_COMPLETION(fcoe_flush_completion); |
63 | 66 | ||
@@ -1896,7 +1899,7 @@ static int fcoe_device_notification(struct notifier_block *notifier, | |||
1896 | list_del(&fcoe->list); | 1899 | list_del(&fcoe->list); |
1897 | port = lport_priv(fcoe->ctlr.lp); | 1900 | port = lport_priv(fcoe->ctlr.lp); |
1898 | fcoe_interface_cleanup(fcoe); | 1901 | fcoe_interface_cleanup(fcoe); |
1899 | schedule_work(&port->destroy_work); | 1902 | queue_work(fcoe_wq, &port->destroy_work); |
1900 | goto out; | 1903 | goto out; |
1901 | break; | 1904 | break; |
1902 | case NETDEV_FEAT_CHANGE: | 1905 | case NETDEV_FEAT_CHANGE: |
@@ -2387,6 +2390,10 @@ static int __init fcoe_init(void) | |||
2387 | unsigned int cpu; | 2390 | unsigned int cpu; |
2388 | int rc = 0; | 2391 | int rc = 0; |
2389 | 2392 | ||
2393 | fcoe_wq = alloc_workqueue("fcoe", 0, 0); | ||
2394 | if (!fcoe_wq) | ||
2395 | return -ENOMEM; | ||
2396 | |||
2390 | /* register as a fcoe transport */ | 2397 | /* register as a fcoe transport */ |
2391 | rc = fcoe_transport_attach(&fcoe_sw_transport); | 2398 | rc = fcoe_transport_attach(&fcoe_sw_transport); |
2392 | if (rc) { | 2399 | if (rc) { |
@@ -2425,6 +2432,7 @@ out_free: | |||
2425 | fcoe_percpu_thread_destroy(cpu); | 2432 | fcoe_percpu_thread_destroy(cpu); |
2426 | } | 2433 | } |
2427 | mutex_unlock(&fcoe_config_mutex); | 2434 | mutex_unlock(&fcoe_config_mutex); |
2435 | destroy_workqueue(fcoe_wq); | ||
2428 | return rc; | 2436 | return rc; |
2429 | } | 2437 | } |
2430 | module_init(fcoe_init); | 2438 | module_init(fcoe_init); |
@@ -2450,7 +2458,7 @@ static void __exit fcoe_exit(void) | |||
2450 | list_del(&fcoe->list); | 2458 | list_del(&fcoe->list); |
2451 | port = lport_priv(fcoe->ctlr.lp); | 2459 | port = lport_priv(fcoe->ctlr.lp); |
2452 | fcoe_interface_cleanup(fcoe); | 2460 | fcoe_interface_cleanup(fcoe); |
2453 | schedule_work(&port->destroy_work); | 2461 | queue_work(fcoe_wq, &port->destroy_work); |
2454 | } | 2462 | } |
2455 | rtnl_unlock(); | 2463 | rtnl_unlock(); |
2456 | 2464 | ||
@@ -2461,15 +2469,17 @@ static void __exit fcoe_exit(void) | |||
2461 | 2469 | ||
2462 | mutex_unlock(&fcoe_config_mutex); | 2470 | mutex_unlock(&fcoe_config_mutex); |
2463 | 2471 | ||
2464 | /* flush any asyncronous interface destroys, | 2472 | /* |
2465 | * this should happen after the netdev notifier is unregistered */ | 2473 | * destroy_work's may be chained but destroy_workqueue() |
2466 | flush_scheduled_work(); | 2474 | * can take care of them. Just kill the fcoe_wq. |
2467 | /* That will flush out all the N_Ports on the hostlist, but now we | 2475 | */ |
2468 | * may have NPIV VN_Ports scheduled for destruction */ | 2476 | destroy_workqueue(fcoe_wq); |
2469 | flush_scheduled_work(); | ||
2470 | 2477 | ||
2471 | /* detach from scsi transport | 2478 | /* |
2472 | * must happen after all destroys are done, therefor after the flush */ | 2479 | * Detaching from the scsi transport must happen after all |
2480 | * destroys are done on the fcoe_wq. destroy_workqueue will | ||
2481 | * enusre the fcoe_wq is flushed. | ||
2482 | */ | ||
2473 | fcoe_if_exit(); | 2483 | fcoe_if_exit(); |
2474 | 2484 | ||
2475 | /* detach from fcoe transport */ | 2485 | /* detach from fcoe transport */ |
@@ -2618,7 +2628,7 @@ static int fcoe_vport_destroy(struct fc_vport *vport) | |||
2618 | mutex_lock(&n_port->lp_mutex); | 2628 | mutex_lock(&n_port->lp_mutex); |
2619 | list_del(&vn_port->list); | 2629 | list_del(&vn_port->list); |
2620 | mutex_unlock(&n_port->lp_mutex); | 2630 | mutex_unlock(&n_port->lp_mutex); |
2621 | schedule_work(&port->destroy_work); | 2631 | queue_work(fcoe_wq, &port->destroy_work); |
2622 | return 0; | 2632 | return 0; |
2623 | } | 2633 | } |
2624 | 2634 | ||