|
@@ -560,12 +560,6 @@ static void nvme_rdma_free_queue(struct nvme_rdma_queue *queue)
|
|
|
if (!test_and_clear_bit(NVME_RDMA_Q_ALLOCATED, &queue->flags))
|
|
|
return;
|
|
|
|
|
|
- if (nvme_rdma_queue_idx(queue) == 0) {
|
|
|
- nvme_rdma_free_qe(queue->device->dev,
|
|
|
- &queue->ctrl->async_event_sqe,
|
|
|
- sizeof(struct nvme_command), DMA_TO_DEVICE);
|
|
|
- }
|
|
|
-
|
|
|
nvme_rdma_destroy_queue_ib(queue);
|
|
|
rdma_destroy_id(queue->cm_id);
|
|
|
}
|
|
@@ -698,7 +692,7 @@ static struct blk_mq_tag_set *nvme_rdma_alloc_tagset(struct nvme_ctrl *nctrl,
|
|
|
set = &ctrl->tag_set;
|
|
|
memset(set, 0, sizeof(*set));
|
|
|
set->ops = &nvme_rdma_mq_ops;
|
|
|
- set->queue_depth = nctrl->opts->queue_size;
|
|
|
+ set->queue_depth = nctrl->sqsize + 1;
|
|
|
set->reserved_tags = 1; /* fabric connect */
|
|
|
set->numa_node = NUMA_NO_NODE;
|
|
|
set->flags = BLK_MQ_F_SHOULD_MERGE;
|
|
@@ -734,11 +728,12 @@ out:
|
|
|
static void nvme_rdma_destroy_admin_queue(struct nvme_rdma_ctrl *ctrl,
|
|
|
bool remove)
|
|
|
{
|
|
|
- nvme_rdma_stop_queue(&ctrl->queues[0]);
|
|
|
if (remove) {
|
|
|
blk_cleanup_queue(ctrl->ctrl.admin_q);
|
|
|
nvme_rdma_free_tagset(&ctrl->ctrl, ctrl->ctrl.admin_tagset);
|
|
|
}
|
|
|
+ nvme_rdma_free_qe(ctrl->device->dev, &ctrl->async_event_sqe,
|
|
|
+ sizeof(struct nvme_command), DMA_TO_DEVICE);
|
|
|
nvme_rdma_free_queue(&ctrl->queues[0]);
|
|
|
}
|
|
|
|
|
@@ -755,11 +750,16 @@ static int nvme_rdma_configure_admin_queue(struct nvme_rdma_ctrl *ctrl,
|
|
|
|
|
|
ctrl->max_fr_pages = nvme_rdma_get_max_fr_pages(ctrl->device->dev);
|
|
|
|
|
|
+ error = nvme_rdma_alloc_qe(ctrl->device->dev, &ctrl->async_event_sqe,
|
|
|
+ sizeof(struct nvme_command), DMA_TO_DEVICE);
|
|
|
+ if (error)
|
|
|
+ goto out_free_queue;
|
|
|
+
|
|
|
if (new) {
|
|
|
ctrl->ctrl.admin_tagset = nvme_rdma_alloc_tagset(&ctrl->ctrl, true);
|
|
|
if (IS_ERR(ctrl->ctrl.admin_tagset)) {
|
|
|
error = PTR_ERR(ctrl->ctrl.admin_tagset);
|
|
|
- goto out_free_queue;
|
|
|
+ goto out_free_async_qe;
|
|
|
}
|
|
|
|
|
|
ctrl->ctrl.admin_q = blk_mq_init_queue(&ctrl->admin_tag_set);
|
|
@@ -795,12 +795,6 @@ static int nvme_rdma_configure_admin_queue(struct nvme_rdma_ctrl *ctrl,
|
|
|
if (error)
|
|
|
goto out_stop_queue;
|
|
|
|
|
|
- error = nvme_rdma_alloc_qe(ctrl->queues[0].device->dev,
|
|
|
- &ctrl->async_event_sqe, sizeof(struct nvme_command),
|
|
|
- DMA_TO_DEVICE);
|
|
|
- if (error)
|
|
|
- goto out_stop_queue;
|
|
|
-
|
|
|
return 0;
|
|
|
|
|
|
out_stop_queue:
|
|
@@ -811,6 +805,9 @@ out_cleanup_queue:
|
|
|
out_free_tagset:
|
|
|
if (new)
|
|
|
nvme_rdma_free_tagset(&ctrl->ctrl, ctrl->ctrl.admin_tagset);
|
|
|
+out_free_async_qe:
|
|
|
+ nvme_rdma_free_qe(ctrl->device->dev, &ctrl->async_event_sqe,
|
|
|
+ sizeof(struct nvme_command), DMA_TO_DEVICE);
|
|
|
out_free_queue:
|
|
|
nvme_rdma_free_queue(&ctrl->queues[0]);
|
|
|
return error;
|
|
@@ -819,7 +816,6 @@ out_free_queue:
|
|
|
static void nvme_rdma_destroy_io_queues(struct nvme_rdma_ctrl *ctrl,
|
|
|
bool remove)
|
|
|
{
|
|
|
- nvme_rdma_stop_io_queues(ctrl);
|
|
|
if (remove) {
|
|
|
blk_cleanup_queue(ctrl->ctrl.connect_q);
|
|
|
nvme_rdma_free_tagset(&ctrl->ctrl, ctrl->ctrl.tagset);
|
|
@@ -888,9 +884,9 @@ static void nvme_rdma_free_ctrl(struct nvme_ctrl *nctrl)
|
|
|
list_del(&ctrl->list);
|
|
|
mutex_unlock(&nvme_rdma_ctrl_mutex);
|
|
|
|
|
|
- kfree(ctrl->queues);
|
|
|
nvmf_free_options(nctrl->opts);
|
|
|
free_ctrl:
|
|
|
+ kfree(ctrl->queues);
|
|
|
kfree(ctrl);
|
|
|
}
|
|
|
|
|
@@ -949,6 +945,7 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work)
|
|
|
return;
|
|
|
|
|
|
destroy_admin:
|
|
|
+ nvme_rdma_stop_queue(&ctrl->queues[0]);
|
|
|
nvme_rdma_destroy_admin_queue(ctrl, false);
|
|
|
requeue:
|
|
|
dev_info(ctrl->ctrl.device, "Failed reconnect attempt %d\n",
|
|
@@ -965,12 +962,14 @@ static void nvme_rdma_error_recovery_work(struct work_struct *work)
|
|
|
|
|
|
if (ctrl->ctrl.queue_count > 1) {
|
|
|
nvme_stop_queues(&ctrl->ctrl);
|
|
|
+ nvme_rdma_stop_io_queues(ctrl);
|
|
|
blk_mq_tagset_busy_iter(&ctrl->tag_set,
|
|
|
nvme_cancel_request, &ctrl->ctrl);
|
|
|
nvme_rdma_destroy_io_queues(ctrl, false);
|
|
|
}
|
|
|
|
|
|
blk_mq_quiesce_queue(ctrl->ctrl.admin_q);
|
|
|
+ nvme_rdma_stop_queue(&ctrl->queues[0]);
|
|
|
blk_mq_tagset_busy_iter(&ctrl->admin_tag_set,
|
|
|
nvme_cancel_request, &ctrl->ctrl);
|
|
|
nvme_rdma_destroy_admin_queue(ctrl, false);
|
|
@@ -1736,6 +1735,7 @@ static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl, bool shutdown)
|
|
|
{
|
|
|
if (ctrl->ctrl.queue_count > 1) {
|
|
|
nvme_stop_queues(&ctrl->ctrl);
|
|
|
+ nvme_rdma_stop_io_queues(ctrl);
|
|
|
blk_mq_tagset_busy_iter(&ctrl->tag_set,
|
|
|
nvme_cancel_request, &ctrl->ctrl);
|
|
|
nvme_rdma_destroy_io_queues(ctrl, shutdown);
|
|
@@ -1747,6 +1747,7 @@ static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl, bool shutdown)
|
|
|
nvme_disable_ctrl(&ctrl->ctrl, ctrl->ctrl.cap);
|
|
|
|
|
|
blk_mq_quiesce_queue(ctrl->ctrl.admin_q);
|
|
|
+ nvme_rdma_stop_queue(&ctrl->queues[0]);
|
|
|
blk_mq_tagset_busy_iter(&ctrl->admin_tag_set,
|
|
|
nvme_cancel_request, &ctrl->ctrl);
|
|
|
blk_mq_unquiesce_queue(ctrl->ctrl.admin_q);
|
|
@@ -1932,11 +1933,6 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
|
|
|
goto out_free_ctrl;
|
|
|
}
|
|
|
|
|
|
- ret = nvme_init_ctrl(&ctrl->ctrl, dev, &nvme_rdma_ctrl_ops,
|
|
|
- 0 /* no quirks, we're perfect! */);
|
|
|
- if (ret)
|
|
|
- goto out_free_ctrl;
|
|
|
-
|
|
|
INIT_DELAYED_WORK(&ctrl->reconnect_work,
|
|
|
nvme_rdma_reconnect_ctrl_work);
|
|
|
INIT_WORK(&ctrl->err_work, nvme_rdma_error_recovery_work);
|
|
@@ -1950,14 +1946,19 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
|
|
|
ctrl->queues = kcalloc(ctrl->ctrl.queue_count, sizeof(*ctrl->queues),
|
|
|
GFP_KERNEL);
|
|
|
if (!ctrl->queues)
|
|
|
- goto out_uninit_ctrl;
|
|
|
+ goto out_free_ctrl;
|
|
|
+
|
|
|
+ ret = nvme_init_ctrl(&ctrl->ctrl, dev, &nvme_rdma_ctrl_ops,
|
|
|
+ 0 /* no quirks, we're perfect! */);
|
|
|
+ if (ret)
|
|
|
+ goto out_kfree_queues;
|
|
|
|
|
|
changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING);
|
|
|
WARN_ON_ONCE(!changed);
|
|
|
|
|
|
ret = nvme_rdma_configure_admin_queue(ctrl, true);
|
|
|
if (ret)
|
|
|
- goto out_kfree_queues;
|
|
|
+ goto out_uninit_ctrl;
|
|
|
|
|
|
/* sanity check icdoff */
|
|
|
if (ctrl->ctrl.icdoff) {
|
|
@@ -1974,20 +1975,19 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
|
|
|
goto out_remove_admin_queue;
|
|
|
}
|
|
|
|
|
|
- if (opts->queue_size > ctrl->ctrl.maxcmd) {
|
|
|
- /* warn if maxcmd is lower than queue_size */
|
|
|
- dev_warn(ctrl->ctrl.device,
|
|
|
- "queue_size %zu > ctrl maxcmd %u, clamping down\n",
|
|
|
- opts->queue_size, ctrl->ctrl.maxcmd);
|
|
|
- opts->queue_size = ctrl->ctrl.maxcmd;
|
|
|
- }
|
|
|
-
|
|
|
+ /* only warn if argument is too large here, will clamp later */
|
|
|
if (opts->queue_size > ctrl->ctrl.sqsize + 1) {
|
|
|
- /* warn if sqsize is lower than queue_size */
|
|
|
dev_warn(ctrl->ctrl.device,
|
|
|
"queue_size %zu > ctrl sqsize %u, clamping down\n",
|
|
|
opts->queue_size, ctrl->ctrl.sqsize + 1);
|
|
|
- opts->queue_size = ctrl->ctrl.sqsize + 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* warn if maxcmd is lower than sqsize+1 */
|
|
|
+ if (ctrl->ctrl.sqsize + 1 > ctrl->ctrl.maxcmd) {
|
|
|
+ dev_warn(ctrl->ctrl.device,
|
|
|
+ "sqsize %u > ctrl maxcmd %u, clamping down\n",
|
|
|
+ ctrl->ctrl.sqsize + 1, ctrl->ctrl.maxcmd);
|
|
|
+ ctrl->ctrl.sqsize = ctrl->ctrl.maxcmd - 1;
|
|
|
}
|
|
|
|
|
|
if (opts->nr_io_queues) {
|
|
@@ -2013,15 +2013,16 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
|
|
|
return &ctrl->ctrl;
|
|
|
|
|
|
out_remove_admin_queue:
|
|
|
+ nvme_rdma_stop_queue(&ctrl->queues[0]);
|
|
|
nvme_rdma_destroy_admin_queue(ctrl, true);
|
|
|
-out_kfree_queues:
|
|
|
- kfree(ctrl->queues);
|
|
|
out_uninit_ctrl:
|
|
|
nvme_uninit_ctrl(&ctrl->ctrl);
|
|
|
nvme_put_ctrl(&ctrl->ctrl);
|
|
|
if (ret > 0)
|
|
|
ret = -EIO;
|
|
|
return ERR_PTR(ret);
|
|
|
+out_kfree_queues:
|
|
|
+ kfree(ctrl->queues);
|
|
|
out_free_ctrl:
|
|
|
kfree(ctrl);
|
|
|
return ERR_PTR(ret);
|