|
@@ -65,9 +65,26 @@ static bool streams;
|
|
|
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);
|
|
@@ -89,7 +106,7 @@ int nvme_reset_ctrl(struct nvme_ctrl *ctrl)
|
|
|
{
|
|
|
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;
|
|
|
}
|
|
@@ -123,7 +140,7 @@ int nvme_delete_ctrl(struct nvme_ctrl *ctrl)
|
|
|
{
|
|
|
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;
|
|
|
}
|
|
@@ -3526,16 +3543,26 @@ EXPORT_SYMBOL_GPL(nvme_reinit_tagset);
|
|
|
|
|
|
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)) {
|
|
@@ -3554,8 +3581,13 @@ destroy_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;
|
|
|
}
|
|
|
|
|
@@ -3565,6 +3597,8 @@ void nvme_core_exit(void)
|
|
|
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);
|
|
|
}
|
|
|
|