module_param(streams, bool, 0644);
 MODULE_PARM_DESC(streams, "turn on support for Streams write directives");
 
+/*
+ * nvme_wq - hosts nvme related works that are not reset or delete
+ * nvme_reset_wq - hosts nvme reset works
+ * nvme_delete_wq - hosts nvme delete works
+ *
+ * nvme_wq will host works such are scan, aen handling, fw activation,
+ * keep-alive error recovery, periodic reconnects etc. nvme_reset_wq
+ * runs reset works which also flush works hosted on nvme_wq for
+ * serialization purposes. nvme_delete_wq host controller deletion
+ * works which flush reset works for serialization.
+ */
 struct workqueue_struct *nvme_wq;
 EXPORT_SYMBOL_GPL(nvme_wq);
 
+struct workqueue_struct *nvme_reset_wq;
+EXPORT_SYMBOL_GPL(nvme_reset_wq);
+
+struct workqueue_struct *nvme_delete_wq;
+EXPORT_SYMBOL_GPL(nvme_delete_wq);
+
 static DEFINE_IDA(nvme_subsystems_ida);
 static LIST_HEAD(nvme_subsystems);
 static DEFINE_MUTEX(nvme_subsystems_lock);
 {
        if (!nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING))
                return -EBUSY;
-       if (!queue_work(nvme_wq, &ctrl->reset_work))
+       if (!queue_work(nvme_reset_wq, &ctrl->reset_work))
                return -EBUSY;
        return 0;
 }
 {
        if (!nvme_change_ctrl_state(ctrl, NVME_CTRL_DELETING))
                return -EBUSY;
-       if (!queue_work(nvme_wq, &ctrl->delete_work))
+       if (!queue_work(nvme_delete_wq, &ctrl->delete_work))
                return -EBUSY;
        return 0;
 }
 
 int __init nvme_core_init(void)
 {
-       int result;
+       int result = -ENOMEM;
 
        nvme_wq = alloc_workqueue("nvme-wq",
                        WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, 0);
        if (!nvme_wq)
-               return -ENOMEM;
+               goto out;
+
+       nvme_reset_wq = alloc_workqueue("nvme-reset-wq",
+                       WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, 0);
+       if (!nvme_reset_wq)
+               goto destroy_wq;
+
+       nvme_delete_wq = alloc_workqueue("nvme-delete-wq",
+                       WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, 0);
+       if (!nvme_delete_wq)
+               goto destroy_reset_wq;
 
        result = alloc_chrdev_region(&nvme_chr_devt, 0, NVME_MINORS, "nvme");
        if (result < 0)
-               goto destroy_wq;
+               goto destroy_delete_wq;
 
        nvme_class = class_create(THIS_MODULE, "nvme");
        if (IS_ERR(nvme_class)) {
        class_destroy(nvme_class);
 unregister_chrdev:
        unregister_chrdev_region(nvme_chr_devt, NVME_MINORS);
+destroy_delete_wq:
+       destroy_workqueue(nvme_delete_wq);
+destroy_reset_wq:
+       destroy_workqueue(nvme_reset_wq);
 destroy_wq:
        destroy_workqueue(nvme_wq);
+out:
        return result;
 }
 
        class_destroy(nvme_subsys_class);
        class_destroy(nvme_class);
        unregister_chrdev_region(nvme_chr_devt, NVME_MINORS);
+       destroy_workqueue(nvme_delete_wq);
+       destroy_workqueue(nvme_reset_wq);
        destroy_workqueue(nvme_wq);
 }