As a preparation for supporting multiple transmission QPs for each GSI QP, add a SRQ that will be used for all the receive buffers of these QPs.
Signed-off-by: Haggai Eran <hagg...@mellanox.com> --- drivers/infiniband/core/mad.c | 58 ++++++++++++++++++++++++++++++++++---- drivers/infiniband/core/mad_priv.h | 1 + 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 7a1186173179..2d4457239908 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -2921,7 +2921,12 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info, post = (++recv_queue->count < recv_queue->max_active); list_add_tail(&mad_priv->header.mad_list.list, &recv_queue->list); spin_unlock_irqrestore(&recv_queue->lock, flags); - ret = ib_post_recv(qp_info->qp, &recv_wr, &bad_recv_wr); + if (qp_info->srq) + ret = ib_post_srq_recv(qp_info->srq, &recv_wr, + &bad_recv_wr); + else + ret = ib_post_recv(qp_info->qp, &recv_wr, &bad_recv_wr); + if (ret) { spin_lock_irqsave(&recv_queue->lock, flags); list_del(&mad_priv->header.mad_list.list); @@ -3074,6 +3079,16 @@ static void qp_event_handler(struct ib_event *event, void *qp_context) event->event, qp_info->qp->qp_num); } +static void srq_event_handler(struct ib_event *event, void *srq_context) +{ + struct ib_mad_qp_info *qp_info = srq_context; + + /* We aren't expecting limit reached events, so this must be an error */ + dev_err(&qp_info->port_priv->device->dev, + "Fatal error (%d) on MAD SRQ (QP%d)\n", + event->event, qp_info->qp->qp_num); +} + static void init_mad_queue(struct ib_mad_qp_info *qp_info, struct ib_mad_queue *mad_queue) { @@ -3099,19 +3114,45 @@ static void init_mad_qp(struct ib_mad_port_private *port_priv, static int create_mad_qp(struct ib_mad_qp_info *qp_info, enum ib_qp_type qp_type) { + struct ib_device *device = qp_info->port_priv->device; + struct ib_srq_init_attr srq_init_attr; struct ib_qp_init_attr qp_init_attr; + struct ib_srq *srq = NULL; + const bool multiple_qps = qp_type == IB_QPT_GSI && + device->gsi_pkey_index_in_qp; + int ret; qp_info->qp_type = qp_type; + if (multiple_qps) { + memset(&srq_init_attr, 0, sizeof(srq_init_attr)); + srq_init_attr.event_handler = srq_event_handler; + srq_init_attr.srq_context = qp_info; + srq_init_attr.attr.max_wr = mad_recvq_size; + srq_init_attr.attr.max_sge = IB_MAD_RECV_REQ_MAX_SG; + srq = ib_create_srq(qp_info->port_priv->pd, &srq_init_attr); + if (IS_ERR(srq)) { + dev_err(&qp_info->port_priv->device->dev, + "Couldn't create ib_mad SRQ for QP%d\n", + get_spl_qp_index(qp_type)); + ret = PTR_ERR(srq); + goto error_srq; + } + } + qp_info->srq = srq; + memset(&qp_init_attr, 0, sizeof qp_init_attr); qp_init_attr.send_cq = qp_info->port_priv->cq; qp_init_attr.recv_cq = qp_info->port_priv->cq; + qp_init_attr.srq = srq; qp_init_attr.sq_sig_type = IB_SIGNAL_ALL_WR; qp_init_attr.cap.max_send_wr = mad_sendq_size; - qp_init_attr.cap.max_recv_wr = mad_recvq_size; qp_init_attr.cap.max_send_sge = IB_MAD_SEND_REQ_MAX_SG; - qp_init_attr.cap.max_recv_sge = IB_MAD_RECV_REQ_MAX_SG; + if (!srq) { + qp_init_attr.cap.max_recv_wr = mad_recvq_size; + qp_init_attr.cap.max_recv_sge = IB_MAD_RECV_REQ_MAX_SG; + } qp_init_attr.qp_type = qp_type; qp_init_attr.port_num = qp_info->port_priv->port_num; qp_init_attr.qp_context = qp_info; @@ -3122,7 +3163,7 @@ static int create_mad_qp(struct ib_mad_qp_info *qp_info, "Couldn't create ib_mad QP%d\n", get_spl_qp_index(qp_type)); ret = PTR_ERR(qp_info->qp); - goto error; + goto error_qp; } /* Use minimum queue sizes unless the CQ is resized */ qp_info->send_queue.max_active = mad_sendq_size; @@ -3130,7 +3171,12 @@ static int create_mad_qp(struct ib_mad_qp_info *qp_info, qp_info->qp_num = qp_info->qp->qp_num; return 0; -error: +error_qp: + if (srq) { + WARN_ON(ib_destroy_srq(srq)); + qp_info->srq = NULL; + } +error_srq: return ret; } @@ -3140,6 +3186,8 @@ static void destroy_mad_qp(struct ib_mad_qp_info *qp_info) return; ib_destroy_qp(qp_info->qp); + if (qp_info->srq) + WARN_ON(ib_destroy_srq(qp_info->srq)); kfree(qp_info->snoop_table); } diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h index ae099f0f9701..0c3b7c576f3a 100644 --- a/drivers/infiniband/core/mad_priv.h +++ b/drivers/infiniband/core/mad_priv.h @@ -184,6 +184,7 @@ struct ib_mad_queue { struct ib_mad_qp_info { struct ib_mad_port_private *port_priv; struct ib_qp *qp; + struct ib_srq *srq; struct ib_mad_queue send_queue; struct ib_mad_queue recv_queue; struct list_head overflow_list; -- 1.7.11.2 -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html