#include <linux/fs.h>
 #include <linux/sysfs.h>
 #include <linux/ctype.h>
+#include <linux/workqueue.h>
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsicam.h>
 #include <scsi/scsi_transport.h>
 
 DEFINE_MUTEX(fcoe_config_mutex);
 
+static struct workqueue_struct *fcoe_wq;
+
 /* fcoe_percpu_clean completion.  Waiter protected by fcoe_create_mutex */
 static DECLARE_COMPLETION(fcoe_flush_completion);
 
                list_del(&fcoe->list);
                port = lport_priv(fcoe->ctlr.lp);
                fcoe_interface_cleanup(fcoe);
-               schedule_work(&port->destroy_work);
+               queue_work(fcoe_wq, &port->destroy_work);
                goto out;
                break;
        case NETDEV_FEAT_CHANGE:
        unsigned int cpu;
        int rc = 0;
 
+       fcoe_wq = alloc_workqueue("fcoe", 0, 0);
+       if (!fcoe_wq)
+               return -ENOMEM;
+
        /* register as a fcoe transport */
        rc = fcoe_transport_attach(&fcoe_sw_transport);
        if (rc) {
                fcoe_percpu_thread_destroy(cpu);
        }
        mutex_unlock(&fcoe_config_mutex);
+       destroy_workqueue(fcoe_wq);
        return rc;
 }
 module_init(fcoe_init);
                list_del(&fcoe->list);
                port = lport_priv(fcoe->ctlr.lp);
                fcoe_interface_cleanup(fcoe);
-               schedule_work(&port->destroy_work);
+               queue_work(fcoe_wq, &port->destroy_work);
        }
        rtnl_unlock();
 
 
        mutex_unlock(&fcoe_config_mutex);
 
-       /* flush any asyncronous interface destroys,
-        * this should happen after the netdev notifier is unregistered */
-       flush_scheduled_work();
-       /* That will flush out all the N_Ports on the hostlist, but now we
-        * may have NPIV VN_Ports scheduled for destruction */
-       flush_scheduled_work();
+       /*
+        * destroy_work's may be chained but destroy_workqueue()
+        * can take care of them. Just kill the fcoe_wq.
+        */
+       destroy_workqueue(fcoe_wq);
 
-       /* detach from scsi transport
-        * must happen after all destroys are done, therefor after the flush */
+       /*
+        * Detaching from the scsi transport must happen after all
+        * destroys are done on the fcoe_wq. destroy_workqueue will
+        * enusre the fcoe_wq is flushed.
+        */
        fcoe_if_exit();
 
        /* detach from fcoe transport */
        mutex_lock(&n_port->lp_mutex);
        list_del(&vn_port->list);
        mutex_unlock(&n_port->lp_mutex);
-       schedule_work(&port->destroy_work);
+       queue_work(fcoe_wq, &port->destroy_work);
        return 0;
 }