From 4e645536a2d30efdcad1f699c498cd4e3dc23fee Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 24 Nov 2014 17:59:14 +0000 Subject: [PATCH] ib_srpt: Add support for HCA's that do not support SRQ Based on a patch provided by Parav Pandit git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@5881 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- srpt/src/ib_srpt.c | 156 +++++++++++++++++++++++++++++++++------------ srpt/src/ib_srpt.h | 3 + 2 files changed, 118 insertions(+), 41 deletions(-) diff --git a/srpt/src/ib_srpt.c b/srpt/src/ib_srpt.c index 437aa5e83..21a40788d 100644 --- a/srpt/src/ib_srpt.c +++ b/srpt/src/ib_srpt.c @@ -118,6 +118,16 @@ module_param(srp_max_rsp_size, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(srp_max_rsp_size, "Maximum size of SRP response messages in bytes."); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) \ + || defined(RHEL_MAJOR) && RHEL_MAJOR -0 <= 5 +static int use_srq = true; +#else +static bool use_srq = true; +#endif +module_param(use_srq, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(use_srq, + "Whether or not to use SRQ"); + static int srpt_srq_size = DEFAULT_SRPT_SRQ_SIZE; module_param(srpt_srq_size, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(srpt_srq_size, @@ -459,6 +469,7 @@ static void srpt_get_ioc(struct srpt_device *sdev, u32 slot, struct ib_dm_mad *mad) { struct ib_dm_ioc_profile *iocp; + int send_queue_depth; iocp = (struct ib_dm_ioc_profile *)mad->data; @@ -472,6 +483,11 @@ static void srpt_get_ioc(struct srpt_device *sdev, u32 slot, return; } + if (sdev->use_srq) + send_queue_depth = sdev->srq_size; + else + send_queue_depth = min(SRPT_RQ_SIZE, sdev->dev_attr.max_qp_wr); + memset(iocp, 0, sizeof(*iocp)); strcpy(iocp->id_string, SRPT_ID_STRING); iocp->guid = cpu_to_be64(srpt_service_guid); @@ -484,7 +500,8 @@ static void srpt_get_ioc(struct srpt_device *sdev, u32 slot, iocp->io_subclass = cpu_to_be16(SRP_IO_SUBCLASS); iocp->protocol = cpu_to_be16(SRP_PROTOCOL); iocp->protocol_version = cpu_to_be16(SRP_PROTOCOL_VERSION); - iocp->send_queue_depth = cpu_to_be16(sdev->srq_size); + iocp->send_queue_depth = cpu_to_be16(send_queue_depth); + iocp->rdma_read_depth = 4; iocp->send_size = cpu_to_be32(srp_max_req_size); iocp->rdma_size = cpu_to_be32(min(max(srp_max_rdma_size, 256U), @@ -862,6 +879,9 @@ static void srpt_free_ioctx_ring(struct srpt_ioctx **ioctx_ring, { int i; + if (!ioctx_ring) + return; + for (i = 0; i < ring_size; ++i) srpt_free_ioctx(sdev, ioctx_ring[i], dma_size, dir); kfree(ioctx_ring); @@ -913,11 +933,12 @@ static bool srpt_test_and_set_cmd_state(struct srpt_send_ioctx *ioctx, /** * srpt_post_recv() - Post an IB receive request. */ -static int srpt_post_recv(struct srpt_device *sdev, +static int srpt_post_recv(struct srpt_device *sdev, struct srpt_rdma_ch *ch, struct srpt_recv_ioctx *ioctx) { struct ib_sge list; struct ib_recv_wr wr, *bad_wr; + int status; BUG_ON(!sdev); wr.wr_id = encode_wr_id(SRPT_RECV, ioctx->ioctx.index); @@ -930,7 +951,11 @@ static int srpt_post_recv(struct srpt_device *sdev, wr.sg_list = &list; wr.num_sge = 1; - return ib_post_srq_recv(sdev->srq, &wr, &bad_wr); + if (sdev->use_srq) + status = ib_post_srq_recv(sdev->srq, &wr, &bad_wr); + else + status = ib_post_recv(ch->qp, &wr, &bad_wr); + return status; } static int srpt_adjust_srq_wr_avail(struct srpt_rdma_ch *ch, int delta) @@ -1867,7 +1892,7 @@ srpt_handle_new_iu(struct srpt_rdma_ch *ch, break; } - srpt_post_recv(ch->sport->sdev, recv_ioctx); + srpt_post_recv(ch->sport->sdev, ch, recv_ioctx); out: return send_ioctx; @@ -1883,7 +1908,6 @@ static void srpt_process_rcv_completion(struct ib_cq *cq, struct srpt_rdma_ch *ch, struct ib_wc *wc) { - struct srpt_device *sdev = ch->sport->sdev; struct srpt_recv_ioctx *ioctx; u32 index; @@ -1894,7 +1918,11 @@ static void srpt_process_rcv_completion(struct ib_cq *cq, req_lim = srpt_adjust_req_lim(ch, -1, 0); if (unlikely(req_lim < 0)) PRINT_ERROR("req_lim = %d < 0", req_lim); - ioctx = sdev->ioctx_ring[index]; + if (ch->sport->sdev->use_srq) + ioctx = ch->sport->sdev->ioctx_ring[index]; + else + ioctx = ch->ioctx_recv_ring[index]; + srpt_handle_new_iu(ch, ioctx, srpt_new_iu_context); } else { PRINT_INFO("receiving failed for idx %u with status %d", @@ -2057,6 +2085,10 @@ static void srpt_unreg_sess(struct scst_session *scst_sess) sdev, ch->rq_size, ch->max_rsp_size, DMA_TO_DEVICE); + srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_recv_ring, + sdev, ch->rq_size, + srp_max_req_size, DMA_FROM_DEVICE); + /* Wait until CM callbacks have finished and prevent new callbacks. */ if (ch->using_rdma_cm) rdma_destroy_id(ch->rdma_cm.cm_id); @@ -2122,7 +2154,7 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch) { struct ib_qp_init_attr *qp_init; struct srpt_device *sdev = ch->sport->sdev; - int ret; + int i, ret; EXTRACHECKS_WARN_ON(ch->rq_size < 1); @@ -2151,12 +2183,17 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch) = (void(*)(struct ib_event *, void*))srpt_qp_event; qp_init->send_cq = ch->cq; qp_init->recv_cq = ch->cq; - qp_init->srq = sdev->srq; qp_init->sq_sig_type = IB_SIGNAL_REQ_WR; qp_init->qp_type = IB_QPT_RC; qp_init->cap.max_send_wr = srpt_sq_size; ch->max_sge = max_t(int, 1, sdev->dev_attr.max_sge - max_sge_delta); qp_init->cap.max_send_sge = ch->max_sge; + if (sdev->use_srq) { + qp_init->srq = sdev->srq; + } else { + qp_init->cap.max_recv_wr = ch->rq_size; + qp_init->cap.max_recv_sge = ch->max_sge; + } if (ch->using_rdma_cm) { ret = rdma_create_qp(ch->rdma_cm.cm_id, sdev->pd, qp_init); @@ -2182,6 +2219,10 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch) TRACE_DBG("qp_num = %#x", ch->qp->qp_num); + if (!sdev->use_srq) + for (i = 0; i < ch->rq_size; i++) + srpt_post_recv(sdev, ch, ch->ioctx_recv_ring[i]); + atomic_set(&ch->sq_wr_avail, qp_init->cap.max_send_wr); TRACE_DBG("%s: max_cqe= %d max_sge= %d sq_size = %d ch= %p", __func__, @@ -2570,6 +2611,8 @@ static int srpt_cm_req_recv(struct srpt_device *const sdev, sizeof(*ch->ioctx_ring[0]), ch->max_rsp_size, DMA_TO_DEVICE); if (!ch->ioctx_ring) { + PRINT_ERROR("rejected SRP_LOGIN_REQ because creating" + " a new QP SQ ring failed."); rej->reason = cpu_to_be32(SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); goto free_ch; } @@ -2579,6 +2622,22 @@ static int srpt_cm_req_recv(struct srpt_device *const sdev, ch->ioctx_ring[i]->ch = ch; list_add_tail(&ch->ioctx_ring[i]->free_list, &ch->free_list); } + if (!sdev->use_srq) { + ch->ioctx_recv_ring = (struct srpt_recv_ioctx **) + srpt_alloc_ioctx_ring(ch->sport->sdev, ch->rq_size, + sizeof(*ch->ioctx_recv_ring[0]), + srp_max_req_size, + DMA_FROM_DEVICE); + if (!ch->ioctx_recv_ring) { + PRINT_ERROR("rejected SRP_LOGIN_REQ because creating" + " a new QP RQ ring failed."); + rej->reason = + cpu_to_be32(SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); + goto free_ring; + } + for (i = 0; i < ch->rq_size; i++) + INIT_LIST_HEAD(&ch->ioctx_recv_ring[i]->wait_list); + } ch->comp_vector = srpt_next_comp_vector(srpt_tgt); @@ -2587,7 +2646,7 @@ static int srpt_cm_req_recv(struct srpt_device *const sdev, rej->reason = cpu_to_be32(SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); PRINT_ERROR("rejected SRP_LOGIN_REQ because creating" " a new RDMA channel failed."); - goto free_ring; + goto free_recv_ring; } if (one_target_per_port) { @@ -2747,6 +2806,11 @@ unreg_ch: destroy_ib: srpt_destroy_ch_ib(ch); +free_recv_ring: + srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_recv_ring, + ch->sport->sdev, ch->rq_size, + srp_max_req_size, DMA_FROM_DEVICE); + free_ring: srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring, ch->sport->sdev, ch->rq_size, @@ -4173,14 +4237,36 @@ static void srpt_add_one(struct ib_device *device) srq_attr.srq_type = IB_SRQT_BASIC; #endif - sdev->srq = ib_create_srq(sdev->pd, &srq_attr); + sdev->srq = use_srq ? ib_create_srq(sdev->pd, &srq_attr) : + ERR_PTR(-ENOSYS); if (IS_ERR(sdev->srq)) { - PRINT_ERROR("ib_create_srq() failed: %ld", PTR_ERR(sdev->srq)); - goto err_mr; - } + TRACE_DBG("%s: ib_create_srq() failed: %ld", __func__, + PTR_ERR(sdev->srq)); - TRACE_DBG("%s: create SRQ #wr= %d max_allow=%d dev= %s", __func__, - sdev->srq_size, sdev->dev_attr.max_srq_wr, device->name); + /* SRQ not supported. */ + sdev->use_srq = false; + } else { + TRACE_DBG("%s: create SRQ #wr= %d max_allow=%d dev= %s", + __func__, sdev->srq_size, sdev->dev_attr.max_srq_wr, + device->name); + + sdev->use_srq = true; + + sdev->ioctx_ring = (struct srpt_recv_ioctx **) + srpt_alloc_ioctx_ring(sdev, sdev->srq_size, + sizeof(*sdev->ioctx_ring[0]), + srp_max_req_size, + DMA_FROM_DEVICE); + if (!sdev->ioctx_ring) { + PRINT_ERROR("srpt_alloc_ioctx_ring() failed"); + goto err_mr; + } + + for (i = 0; i < sdev->srq_size; ++i) { + INIT_LIST_HEAD(&sdev->ioctx_ring[i]->wait_list); + srpt_post_recv(sdev, NULL, sdev->ioctx_ring[i]); + } + } if (!srpt_service_guid) srpt_service_guid = be64_to_cpu(device->node_guid) & @@ -4189,7 +4275,7 @@ static void srpt_add_one(struct ib_device *device) cm_id = ib_create_cm_id(device, srpt_cm_handler, sdev); if (IS_ERR(cm_id)) { PRINT_ERROR("ib_create_cm_id() failed: %ld", PTR_ERR(cm_id)); - goto err_srq; + goto err_ring; } sdev->cm_id = cm_id; @@ -4220,20 +4306,6 @@ static void srpt_add_one(struct ib_device *device) goto err_cm; } - sdev->ioctx_ring = (struct srpt_recv_ioctx **) - srpt_alloc_ioctx_ring(sdev, sdev->srq_size, - sizeof(*sdev->ioctx_ring[0]), - srp_max_req_size, DMA_FROM_DEVICE); - if (!sdev->ioctx_ring) { - PRINT_ERROR("srpt_alloc_ioctx_ring() failed"); - goto err_event; - } - - for (i = 0; i < sdev->srq_size; ++i) { - INIT_LIST_HEAD(&sdev->ioctx_ring[i]->wait_list); - srpt_post_recv(sdev, sdev->ioctx_ring[i]); - } - WARN_ON(sdev->device->phys_port_cnt > ARRAY_SIZE(sdev->port)); for (i = 1; i <= sdev->device->phys_port_cnt; i++) { @@ -4254,7 +4326,7 @@ static void srpt_add_one(struct ib_device *device) if (srpt_refresh_port(sport)) { PRINT_ERROR("MAD registration failed for %s-%d.", sdev->device->name, i); - goto err_ring; + goto err_event; } } @@ -4265,16 +4337,16 @@ out: TRACE_EXIT(); return; -err_ring: - srpt_free_ioctx_ring((struct srpt_ioctx **)sdev->ioctx_ring, sdev, - sdev->srq_size, srp_max_req_size, - DMA_FROM_DEVICE); err_event: ib_unregister_event_handler(&sdev->event_handler); err_cm: ib_destroy_cm_id(sdev->cm_id); -err_srq: - ib_destroy_srq(sdev->srq); +err_ring: + srpt_free_ioctx_ring((struct srpt_ioctx **)sdev->ioctx_ring, sdev, + sdev->srq_size, srp_max_req_size, + DMA_FROM_DEVICE); + if (sdev->use_srq) + ib_destroy_srq(sdev->srq); err_mr: ib_dereg_mr(sdev->mr); err_pd: @@ -4347,13 +4419,15 @@ static void srpt_remove_one(struct ib_device *device) sdev->srpt_tgt.scst_tgt = NULL; } - ib_destroy_srq(sdev->srq); - ib_dereg_mr(sdev->mr); - ib_dealloc_pd(sdev->pd); - srpt_free_ioctx_ring((struct srpt_ioctx **)sdev->ioctx_ring, sdev, sdev->srq_size, srp_max_req_size, DMA_FROM_DEVICE); sdev->ioctx_ring = NULL; + + if (sdev->use_srq) + ib_destroy_srq(sdev->srq); + ib_dereg_mr(sdev->mr); + ib_dealloc_pd(sdev->pd); + kfree(sdev); TRACE_EXIT(); diff --git a/srpt/src/ib_srpt.h b/srpt/src/ib_srpt.h index 49d2a9b9f..f62aabaf4 100644 --- a/srpt/src/ib_srpt.h +++ b/srpt/src/ib_srpt.h @@ -366,6 +366,7 @@ struct srpt_rdma_ch { spinlock_t spinlock; struct list_head free_list; struct srpt_send_ioctx **ioctx_ring; + struct srpt_recv_ioctx **ioctx_recv_ring; struct ib_wc wc[16]; enum rdma_ch_state state; struct list_head list; @@ -448,6 +449,7 @@ struct srpt_port { * @dev_attr: Attributes of the InfiniBand device as obtained during the * ib_client.add() callback. * @srq_size: SRQ size. + * @use_srq: Whether or not to use SRQ. * @ioctx_ring: Per-HCA SRQ. * @port: Information about the ports owned by this HCA. * @event_handler: Per-HCA asynchronous IB event handler. @@ -462,6 +464,7 @@ struct srpt_device { struct ib_cm_id *cm_id; struct ib_device_attr dev_attr; int srq_size; + bool use_srq; struct srpt_recv_ioctx **ioctx_ring; struct srpt_port port[2]; struct ib_event_handler event_handler;