]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/nvme/target/rdma.c
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma
[mirror_ubuntu-artful-kernel.git] / drivers / nvme / target / rdma.c
index 50f237a46ea17baba33569a7dbb030dc7d37ef3c..8c3760a78ac080af522afb5892d471063243bd7b 100644 (file)
@@ -951,6 +951,7 @@ err_destroy_cq:
 
 static void nvmet_rdma_destroy_queue_ib(struct nvmet_rdma_queue *queue)
 {
+       ib_drain_qp(queue->cm_id->qp);
        rdma_destroy_qp(queue->cm_id);
        ib_free_cq(queue->cq);
 }
@@ -1044,8 +1045,10 @@ nvmet_rdma_alloc_queue(struct nvmet_rdma_device *ndev,
        }
 
        ret = nvmet_sq_init(&queue->nvme_sq);
-       if (ret)
+       if (ret) {
+               ret = NVME_RDMA_CM_NO_RSC;
                goto out_free_queue;
+       }
 
        ret = nvmet_rdma_parse_cm_connect_req(&event->param.conn, queue);
        if (ret)
@@ -1066,6 +1069,7 @@ nvmet_rdma_alloc_queue(struct nvmet_rdma_device *ndev,
        spin_lock_init(&queue->rsp_wr_wait_lock);
        INIT_LIST_HEAD(&queue->free_rsps);
        spin_lock_init(&queue->rsps_lock);
+       INIT_LIST_HEAD(&queue->queue_list);
 
        queue->idx = ida_simple_get(&nvmet_rdma_queue_ida, 0, 0, GFP_KERNEL);
        if (queue->idx < 0) {
@@ -1114,6 +1118,7 @@ out_destroy_sq:
 out_free_queue:
        kfree(queue);
 out_reject:
+       pr_debug("rejecting connect request with status code %d\n", ret);
        nvmet_rdma_cm_reject(cm_id, ret);
        return NULL;
 }
@@ -1127,7 +1132,8 @@ static void nvmet_rdma_qp_event(struct ib_event *event, void *priv)
                rdma_notify(queue->cm_id, event->event);
                break;
        default:
-               pr_err("received unrecognized IB QP event %d\n", event->event);
+               pr_err("received IB QP event: %s (%d)\n",
+                      ib_event_msg(event->event), event->event);
                break;
        }
 }
@@ -1244,7 +1250,6 @@ static void __nvmet_rdma_queue_disconnect(struct nvmet_rdma_queue *queue)
 
        if (disconnect) {
                rdma_disconnect(queue->cm_id);
-               ib_drain_qp(queue->cm_id->qp);
                schedule_work(&queue->release_work);
        }
 }
@@ -1269,7 +1274,12 @@ static void nvmet_rdma_queue_connect_fail(struct rdma_cm_id *cm_id,
 {
        WARN_ON_ONCE(queue->state != NVMET_RDMA_Q_CONNECTING);
 
-       pr_err("failed to connect queue\n");
+       mutex_lock(&nvmet_rdma_queue_mutex);
+       if (!list_empty(&queue->queue_list))
+               list_del_init(&queue->queue_list);
+       mutex_unlock(&nvmet_rdma_queue_mutex);
+
+       pr_err("failed to connect queue %d\n", queue->idx);
        schedule_work(&queue->release_work);
 }
 
@@ -1352,7 +1362,13 @@ static int nvmet_rdma_cm_handler(struct rdma_cm_id *cm_id,
        case RDMA_CM_EVENT_ADDR_CHANGE:
        case RDMA_CM_EVENT_DISCONNECTED:
        case RDMA_CM_EVENT_TIMEWAIT_EXIT:
-               nvmet_rdma_queue_disconnect(queue);
+               /*
+                * We might end up here when we already freed the qp
+                * which means queue release sequence is in progress,
+                * so don't get in the way...
+                */
+               if (queue)
+                       nvmet_rdma_queue_disconnect(queue);
                break;
        case RDMA_CM_EVENT_DEVICE_REMOVAL:
                ret = nvmet_rdma_device_removal(cm_id, queue);