Hi Yuval, some very small things, psb. On 7/29/2018 3:16 AM, Yuval Bason wrote: > Implement the SRQ specific verbs and update the poll_cq verb to deal with > SRQ completions. > > Signed-off-by: Michal Kalderon <michal.kalderon@xxxxxxxxxx> > Signed-off-by: Yuval Bason <yuval.bason@xxxxxxxxxx> > --- > drivers/infiniband/hw/qedr/main.c | 5 + > drivers/infiniband/hw/qedr/qedr.h | 35 +++ > drivers/infiniband/hw/qedr/qedr_hsi_rdma.h | 11 + > drivers/infiniband/hw/qedr/verbs.c | 417 ++++++++++++++++++++++++++++- > drivers/infiniband/hw/qedr/verbs.h | 9 + > 5 files changed, 464 insertions(+), 13 deletions(-) > > diff --git a/drivers/infiniband/hw/qedr/main.c b/drivers/infiniband/hw/qedr/main.c > index 912a0ca..2642caf 100644 > --- a/drivers/infiniband/hw/qedr/main.c > +++ b/drivers/infiniband/hw/qedr/main.c > @@ -229,6 +229,11 @@ static int qedr_register_device(struct qedr_dev *dev) > dev->ibdev.query_qp = qedr_query_qp; > dev->ibdev.destroy_qp = qedr_destroy_qp; > > + dev->ibdev.create_srq = qedr_create_srq; > + dev->ibdev.destroy_srq = qedr_destroy_srq; > + dev->ibdev.modify_srq = qedr_modify_srq; > + dev->ibdev.query_srq = qedr_query_srq; > + dev->ibdev.post_srq_recv = qedr_post_srq_recv; > dev->ibdev.query_pkey = qedr_query_pkey; > > dev->ibdev.create_ah = qedr_create_ah; > diff --git a/drivers/infiniband/hw/qedr/qedr.h b/drivers/infiniband/hw/qedr/qedr.h > index 5d0b75e..a2d708d 100644 > --- a/drivers/infiniband/hw/qedr/qedr.h > +++ b/drivers/infiniband/hw/qedr/qedr.h > @@ -58,6 +58,7 @@ > #define QEDR_MSG_RQ " RQ" > #define QEDR_MSG_SQ " SQ" > #define QEDR_MSG_QP " QP" > +#define QEDR_MSG_SRQ " SRQ" > #define QEDR_MSG_GSI " GSI" > #define QEDR_MSG_IWARP " IW" > > @@ -171,6 +172,7 @@ struct qedr_dev { > struct qedr_qp *gsi_qp; > enum qed_rdma_type rdma_type; > struct qedr_idr qpidr; > + struct qedr_idr srqidr; > struct workqueue_struct *iwarp_wq; > u16 iwarp_max_mtu; > > @@ -341,6 +343,34 @@ struct qedr_qp_hwq_info { > qed_chain_get_capacity(p_info->pbl) \ > } while (0) > > +struct qedr_srq_hwq_info { > + u32 max_sges; > + u32 max_wr; > + struct qed_chain pbl; > + u64 p_phys_addr_tbl; > + u32 wqe_prod; > + u32 sge_prod; > + u32 wr_prod_cnt; > + u32 wr_cons_cnt; > + u32 num_elems; > + > + u32 *virt_prod_pair_addr; > + dma_addr_t phy_prod_pair_addr; > +}; > + > +struct qedr_srq { > + struct ib_srq ibsrq; > + struct qedr_dev *dev; > + > + struct qedr_userq usrq; > + struct qedr_srq_hwq_info hw_srq; > + struct ib_umem *prod_umem; > + u16 srq_id; > + u32 srq_limit; > + /* lock to protect srq recv post */ > + spinlock_t lock; > +}; > + > enum qedr_qp_err_bitmap { > QEDR_QP_ERR_SQ_FULL = 1, > QEDR_QP_ERR_RQ_FULL = 2, > @@ -542,4 +572,9 @@ static inline struct qedr_mr *get_qedr_mr(struct ib_mr *ibmr) > { > return container_of(ibmr, struct qedr_mr, ibmr); > } > + > +static inline struct qedr_srq *get_qedr_srq(struct ib_srq *ibsrq) > +{ > + return container_of(ibsrq, struct qedr_srq, ibsrq); > +} > #endif > diff --git a/drivers/infiniband/hw/qedr/qedr_hsi_rdma.h b/drivers/infiniband/hw/qedr/qedr_hsi_rdma.h > index 7e1f702..228dd7d 100644 > --- a/drivers/infiniband/hw/qedr/qedr_hsi_rdma.h > +++ b/drivers/infiniband/hw/qedr/qedr_hsi_rdma.h > @@ -161,12 +161,23 @@ struct rdma_rq_sge { > #define RDMA_RQ_SGE_L_KEY_HI_SHIFT 29 > }; > > +struct rdma_srq_wqe_header { > + struct regpair wr_id; > + u8 num_sges /* number of SGEs in WQE */; > + u8 reserved2[7]; > +}; > + > struct rdma_srq_sge { > struct regpair addr; > __le32 length; > __le32 l_key; > }; > > +union rdma_srq_elm { > + struct rdma_srq_wqe_header header; > + struct rdma_srq_sge sge; > +}; > + > /* Rdma doorbell data for flags update */ > struct rdma_pwm_flags_data { > __le16 icid; /* internal CID */ > diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c > index 2f8b2da..13130bb 100644 > --- a/drivers/infiniband/hw/qedr/verbs.c > +++ b/drivers/infiniband/hw/qedr/verbs.c > @@ -51,6 +51,10 @@ > #include <rdma/qedr-abi.h> > #include "qedr_roce_cm.h" > > +#define QEDR_SRQ_WQE_ELEM_SIZE sizeof(union rdma_srq_elm) > +#define RDMA_MAX_SGE_PER_SRQ (4) > +#define RDMA_MAX_SRQ_WQE_SIZE (RDMA_MAX_SGE_PER_SRQ + 1) > + > #define DB_ADDR_SHIFT(addr) ((addr) << DB_PWM_ADDR_OFFSET_SHIFT) > > static inline int qedr_ib_copy_to_udata(struct ib_udata *udata, void *src, > @@ -84,6 +88,19 @@ int qedr_iw_query_gid(struct ib_device *ibdev, u8 port, > return 0; > } > > +int qedr_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr) > +{ > + struct qedr_dev *dev = get_qedr_dev(ibsrq->device); > + struct qedr_device_attr *qattr = &dev->attr; > + struct qedr_srq *srq = get_qedr_srq(ibsrq); > + > + srq_attr->srq_limit = srq->srq_limit; > + srq_attr->max_wr = qattr->max_srq_wr; > + srq_attr->max_sge = qattr->max_sge; > + > + return 0; > +} > + > int qedr_query_device(struct ib_device *ibdev, > struct ib_device_attr *attr, struct ib_udata *udata) > { > @@ -1248,13 +1265,18 @@ static void qedr_set_common_qp_params(struct qedr_dev *dev, > qp->state = QED_ROCE_QP_STATE_RESET; > qp->signaled = (attrs->sq_sig_type == IB_SIGNAL_ALL_WR) ? true : false; > qp->sq_cq = get_qedr_cq(attrs->send_cq); > - qp->rq_cq = get_qedr_cq(attrs->recv_cq); > qp->dev = dev; > - qp->rq.max_sges = attrs->cap.max_recv_sge; > > - DP_DEBUG(dev, QEDR_MSG_QP, > - "RQ params:\trq_max_sges = %d, rq_cq_id = %d\n", > - qp->rq.max_sges, qp->rq_cq->icid); > + if (attrs->srq) { > + qp->srq = get_qedr_srq(attrs->srq); > + } else { > + qp->rq_cq = get_qedr_cq(attrs->recv_cq); > + qp->rq.max_sges = attrs->cap.max_recv_sge; > + DP_DEBUG(dev, QEDR_MSG_QP, > + "RQ params:\trq_max_sges = %d, rq_cq_id = %d\n", > + qp->rq.max_sges, qp->rq_cq->icid); > + } > + > DP_DEBUG(dev, QEDR_MSG_QP, > "QP params:\tpd = %d, qp_type = %d, max_inline_data = %d, state = %d, signaled = %d, use_srq=%d\n", > pd->pd_id, qp->qp_type, qp->max_inline_data, > @@ -1269,9 +1291,234 @@ static void qedr_set_roce_db_info(struct qedr_dev *dev, struct qedr_qp *qp) > qp->sq.db = dev->db_addr + > DB_ADDR_SHIFT(DQ_PWM_OFFSET_XCM_RDMA_SQ_PROD); > qp->sq.db_data.data.icid = qp->icid + 1; > - qp->rq.db = dev->db_addr + > - DB_ADDR_SHIFT(DQ_PWM_OFFSET_TCM_ROCE_RQ_PROD); > - qp->rq.db_data.data.icid = qp->icid; > + if (!qp->srq) { > + qp->rq.db = dev->db_addr + > + DB_ADDR_SHIFT(DQ_PWM_OFFSET_TCM_ROCE_RQ_PROD); > + qp->rq.db_data.data.icid = qp->icid; > + } > +} > + > +static int qedr_check_srq_params(struct ib_pd *ibpd, struct qedr_dev *dev, > + struct ib_srq_init_attr *attrs, > + struct ib_udata *udata) > +{ > + struct qedr_device_attr *qattr = &dev->attr; > + > + if (attrs->attr.max_wr > qattr->max_srq_wr) { > + DP_ERR(dev, > + "create srq: unsupported srq_wr=0x%x requested (max_srq_wr=0x%x)\n", > + attrs->attr.max_wr, qattr->max_srq_wr); > + return -EINVAL; > + } > + > + if (attrs->attr.max_sge > qattr->max_sge) { > + DP_ERR(dev, > + "create srq: unsupported sge=0x%x requested (max_srq_sge=0x%x)\n", > + attrs->attr.max_sge, qattr->max_sge); No error? > + } > + > + return 0; > +} > + > +static void qedr_free_srq_kernel_params(struct qedr_srq *srq) > +{ > + struct qedr_srq_hwq_info *hw_srq = &srq->hw_srq; > + struct qedr_dev *dev = srq->dev; > + > + dev->ops->common->chain_free(dev->cdev, &hw_srq->pbl); > + checkpatch > + dma_free_coherent(&dev->pdev->dev, sizeof(struct rdma_srq_producers), > + hw_srq->virt_prod_pair_addr, > + hw_srq->phy_prod_pair_addr); > +} > + > +static int qedr_alloc_srq_kernel_params(struct qedr_srq *srq, > + struct qedr_dev *dev, > + struct ib_srq_init_attr *init_attr) > +{ > + struct qedr_srq_hwq_info *hw_srq = &srq->hw_srq; > + dma_addr_t phy_prod_pair_addr; > + u32 num_elems, max_wr; > + void *va; > + int rc; > + > + va = dma_alloc_coherent(&dev->pdev->dev, > + sizeof(struct rdma_srq_producers), > + &phy_prod_pair_addr, GFP_KERNEL); > + if (!va) { > + DP_ERR(dev, > + "create srq: failed to allocate dma memory for producer\n"); > + return -ENOMEM; > + } > + > + hw_srq->phy_prod_pair_addr = phy_prod_pair_addr; > + hw_srq->virt_prod_pair_addr = va; > + > + max_wr = init_attr->attr.max_wr; > + > + num_elems = max_wr * RDMA_MAX_SRQ_WQE_SIZE; > + rc = dev->ops->common->chain_alloc(dev->cdev, > + QED_CHAIN_USE_TO_CONSUME_PRODUCE, > + QED_CHAIN_MODE_PBL, > + QED_CHAIN_CNT_TYPE_U32, > + num_elems, > + QEDR_SRQ_WQE_ELEM_SIZE, > + &hw_srq->pbl, NULL); > + if (rc) > + goto err0; > + > + hw_srq->max_wr = max_wr; > + hw_srq->num_elems = num_elems; > + hw_srq->max_sges = RDMA_MAX_SGE_PER_SRQ; Didn't you do that in qedr_create_srq()? > + > + return 0; > + > +err0: > + dma_free_coherent(&dev->pdev->dev, sizeof(struct rdma_srq_producers), > + va, phy_prod_pair_addr); > + return rc; > +} > + > +static int qedr_idr_add(struct qedr_dev *dev, struct qedr_idr *qidr, > + void *ptr, u32 id); > +static void qedr_idr_remove(struct qedr_dev *dev, > + struct qedr_idr *qidr, u32 id); > + > +struct ib_srq *qedr_create_srq(struct ib_pd *ibpd, > + struct ib_srq_init_attr *init_attr, > + struct ib_udata *udata) > +{ > + struct qed_rdma_destroy_srq_in_params destroy_in_params; > + struct qed_rdma_create_srq_in_params in_params = {}; > + struct qedr_dev *dev = get_qedr_dev(ibpd->device); > + struct qed_rdma_create_srq_out_params out_params; > + struct qedr_pd *pd = get_qedr_pd(ibpd); > + u64 pbl_base_addr, phy_prod_pair_addr; > + struct qedr_srq_hwq_info *hw_srq; > + u32 page_cnt, page_size; > + struct qed_chain *pbl; > + struct qedr_srq *srq; > + int rc = 0; > + > + DP_DEBUG(dev, QEDR_MSG_QP, > + "create SRQ called from %s (pd %p)\n", > + (udata) ? "User lib" : "kernel", pd); > + > + rc = qedr_check_srq_params(ibpd, dev, init_attr, udata); > + if (rc) > + return ERR_PTR(-EINVAL); > + > + srq = kzalloc(sizeof(*srq), GFP_KERNEL); > + if (!srq) > + return ERR_PTR(-ENOMEM); > + > + srq->dev = dev; > + hw_srq = &srq->hw_srq; > + spin_lock_init(&srq->lock); > + > + hw_srq->max_wr = init_attr->attr.max_wr; > + hw_srq->max_sges = RDMA_MAX_SGE_PER_SRQ; Why aren't you using the user supplied value? > + > + rc = qedr_alloc_srq_kernel_params(srq, dev, init_attr); > + if (rc) > + goto err0; > + > + pbl = &hw_srq->pbl; > + page_cnt = qed_chain_get_page_cnt(pbl); > + pbl_base_addr = qed_chain_get_pbl_phys(pbl); > + phy_prod_pair_addr = hw_srq->phy_prod_pair_addr; > + page_size = QED_CHAIN_PAGE_SIZE; > + in_params.pd_id = pd->pd_id; > + in_params.pbl_base_addr = pbl_base_addr; > + in_params.prod_pair_addr = phy_prod_pair_addr; > + in_params.num_pages = page_cnt; > + in_params.page_size = page_size; > + > + rc = dev->ops->rdma_create_srq(dev->rdma_ctx, &in_params, &out_params); > + if (rc) > + goto err1; > + > + srq->srq_id = out_params.srq_id; > + > + rc = qedr_idr_add(dev, &dev->srqidr, srq, srq->srq_id); > + if (rc) > + goto err2; > + > + DP_DEBUG(dev, QEDR_MSG_SRQ, > + "create srq: created srq with srq_id=0x%0x\n", srq->srq_id); > + return &srq->ibsrq; > + > +err2: > + memset(&in_params, 0, sizeof(in_params)); Why the memet? > + destroy_in_params.srq_id = srq->srq_id; > + > + /* Intentionally ignore return value, keep the original rc */ But you return ERR_PTR(-EFAULT), don't understand the comment. > + dev->ops->rdma_destroy_srq(dev->rdma_ctx, &destroy_in_params); > +err1: > + qedr_free_srq_kernel_params(srq); > +err0: > + kfree(srq); > + > + return ERR_PTR(-EFAULT); > +} > + > +int qedr_destroy_srq(struct ib_srq *ibsrq) > +{ > + struct qed_rdma_destroy_srq_in_params in_params = {}; > + struct qedr_dev *dev = get_qedr_dev(ibsrq->device); > + struct qedr_srq *srq = get_qedr_srq(ibsrq); > + > + in_params.srq_id = srq->srq_id; > + dev->ops->rdma_destroy_srq(dev->rdma_ctx, &in_params); > + > + qedr_free_srq_kernel_params(srq); > + > + qedr_idr_remove(dev, &dev->srqidr, srq->srq_id); Why first free/destroy and only then removing from the idr? > + > + DP_DEBUG(dev, QEDR_MSG_SRQ, > + "destroy srq: destroyed srq with srq_id=0x%0x\n", > + srq->srq_id); > + kfree(srq); > + > + return 0; > +} > + > +int qedr_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, > + enum ib_srq_attr_mask attr_mask, struct ib_udata *udata) > +{ > + struct qed_rdma_modify_srq_in_params in_params = {}; > + struct qedr_dev *dev = get_qedr_dev(ibsrq->device); > + struct qedr_srq *srq = get_qedr_srq(ibsrq); > + int rc; > + > + if (attr_mask & IB_SRQ_MAX_WR) { > + DP_ERR(dev, > + "modify srq: invalid attribute mask=0x%x specified for %p\n", > + attr_mask, srq); > + return -EINVAL; > + } > + > + if (attr_mask & IB_SRQ_LIMIT) { > + if (attr->srq_limit >= srq->hw_srq.max_wr) { > + DP_ERR(dev, > + "modify srq: invalid srq_limit=0x%x (max_srq_limit=0x%x)\n", > + attr->srq_limit, srq->hw_srq.max_wr); > + return -EINVAL; > + } > + > + in_params.srq_id = srq->srq_id; > + in_params.wqe_limit = attr->srq_limit; > + rc = dev->ops->rdma_modify_srq(dev->rdma_ctx, &in_params); > + if (rc) > + return rc; > + } > + > + srq->srq_limit = attr->srq_limit; > + > + DP_DEBUG(dev, QEDR_MSG_SRQ, > + "modify srq: modified srq with srq_id=0x%0x\n", srq->srq_id); > + > + return 0; > } > > static inline void > @@ -1292,9 +1539,17 @@ static void qedr_set_roce_db_info(struct qedr_dev *dev, struct qedr_qp *qp) > params->dpi = pd->uctx ? pd->uctx->dpi : dev->dpi; > params->sq_cq_id = get_qedr_cq(attrs->send_cq)->icid; > params->stats_queue = 0; > - params->rq_cq_id = get_qedr_cq(attrs->recv_cq)->icid; > params->srq_id = 0; > params->use_srq = false; > + > + if (!qp->srq) { > + params->rq_cq_id = get_qedr_cq(attrs->recv_cq)->icid; > + > + } else { > + params->rq_cq_id = get_qedr_cq(attrs->recv_cq)->icid; > + params->srq_id = qp->srq->srq_id; > + params->use_srq = true; > + } > } > > static inline void qedr_qp_user_print(struct qedr_dev *dev, struct qedr_qp *qp) > @@ -1667,16 +1922,13 @@ struct ib_qp *qedr_create_qp(struct ib_pd *ibpd, > if (rc) > return ERR_PTR(rc); > > - if (attrs->srq) > - return ERR_PTR(-EINVAL); > - > DP_DEBUG(dev, QEDR_MSG_QP, > "create qp: called from %s, event_handler=%p, eepd=%p sq_cq=%p, sq_icid=%d, rq_cq=%p, rq_icid=%d\n", > udata ? "user library" : "kernel", attrs->event_handler, pd, > get_qedr_cq(attrs->send_cq), > get_qedr_cq(attrs->send_cq)->icid, > get_qedr_cq(attrs->recv_cq), > - get_qedr_cq(attrs->recv_cq)->icid); > + attrs->recv_cq ? get_qedr_cq(attrs->recv_cq)->icid : 0); > > qp = kzalloc(sizeof(*qp), GFP_KERNEL); > if (!qp) { > @@ -3222,6 +3474,102 @@ int qedr_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, > return rc; > } > > +static u32 qedr_srq_elem_left(struct qedr_srq_hwq_info *hw_srq) > +{ > + u32 used; > + > + /* Calculate number of elements used based on producer > + * count and consumer count and subtract it from max > + * work request supported so that we get elements left. > + */ > + used = hw_srq->wr_prod_cnt - hw_srq->wr_cons_cnt; > + > + return hw_srq->max_wr - used; > +} > + > +int qedr_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, > + struct ib_recv_wr **bad_wr) > +{ > + struct qedr_srq *srq = get_qedr_srq(ibsrq); > + struct qedr_srq_hwq_info *hw_srq; > + struct qedr_dev *dev = srq->dev; > + struct qed_chain *pbl; > + unsigned long flags; > + int status = 0; > + u32 num_sge; > + u32 offset; > + > + spin_lock_irqsave(&srq->lock, flags); > + > + hw_srq = &srq->hw_srq; > + pbl = &srq->hw_srq.pbl; > + while (wr) { > + struct rdma_srq_wqe_header *hdr; > + int i; > + > + if (!qedr_srq_elem_left(hw_srq) || > + wr->num_sge > srq->hw_srq.max_sges) { > + DP_ERR(dev, "Can't post WR (%d,%d) || (%d > %d)\n", > + hw_srq->wr_prod_cnt, hw_srq->wr_cons_cnt, > + wr->num_sge, srq->hw_srq.max_sges); > + status = -ENOMEM; > + *bad_wr = wr; > + break; > + } > + > + hdr = qed_chain_produce(pbl); > + num_sge = wr->num_sge; > + /* Set number of sge and work request id in header */ > + SRQ_HDR_SET(hdr, wr->wr_id, num_sge); > + > + srq->hw_srq.wr_prod_cnt++; > + hw_srq->wqe_prod++; > + hw_srq->sge_prod++; > + > + DP_DEBUG(dev, QEDR_MSG_SRQ, > + "SRQ WR: SGEs: %d with wr_id[%d] = %llx\n", > + wr->num_sge, hw_srq->wqe_prod, wr->wr_id); > + > + for (i = 0; i < wr->num_sge; i++) { > + struct rdma_srq_sge *srq_sge = qed_chain_produce(pbl); > + > + /* Set SGE length, lkey and address */ > + SRQ_SGE_SET(srq_sge, wr->sg_list[i].addr, > + wr->sg_list[i].length, wr->sg_list[i].lkey); > + > + DP_DEBUG(dev, QEDR_MSG_SRQ, > + "[%d]: len %d key %x addr %x:%x\n", > + i, srq_sge->length, srq_sge->l_key, > + srq_sge->addr.hi, srq_sge->addr.lo); > + hw_srq->sge_prod++; > + } > + > + /* Flush WQE and SGE information before > + * updating producer. > + */ > + wmb(); > + > + /* SRQ producer is 8 bytes. Need to update SGE producer index > + * in first 4 bytes and need to update WQE producer in > + * next 4 bytes. > + */ > + *srq->hw_srq.virt_prod_pair_addr = hw_srq->sge_prod; > + offset = offsetof(struct rdma_srq_producers, wqe_prod); > + *((u8 *)srq->hw_srq.virt_prod_pair_addr + offset) = > + hw_srq->wqe_prod; > + > + /* Flush producer after updating it. */ > + wmb(); > + wr = wr->next; > + } > + > + DP_DEBUG(dev, QEDR_MSG_SRQ, "POST: Elements in S-RQ: %d\n", > + qed_chain_get_elem_left(pbl)); > + spin_unlock_irqrestore(&srq->lock, flags); > + > + return status; > +} > + > int qedr_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr, > struct ib_recv_wr **bad_wr) > { > @@ -3613,6 +3961,31 @@ static void __process_resp_one(struct qedr_dev *dev, struct qedr_qp *qp, > wc->wr_id = wr_id; > } > > +static int process_resp_one_srq(struct qedr_dev *dev, struct qedr_qp *qp, > + struct qedr_cq *cq, struct ib_wc *wc, > + struct rdma_cqe_responder *resp) > +{ > + struct qedr_srq *srq = qp->srq; > + u64 wr_id; > + > + wr_id = HILO_GEN(le32_to_cpu(resp->srq_wr_id.hi), > + le32_to_cpu(resp->srq_wr_id.lo), u64); > + > + if (resp->status == RDMA_CQE_RESP_STS_WORK_REQUEST_FLUSHED_ERR) { > + wc->status = IB_WC_WR_FLUSH_ERR; > + wc->vendor_err = 0; > + wc->wr_id = wr_id; > + wc->byte_len = 0; > + wc->src_qp = qp->id; > + wc->qp = &qp->ibqp; > + wc->wr_id = wr_id; > + } else { > + __process_resp_one(dev, qp, cq, wc, resp, wr_id); > + } > + srq->hw_srq.wr_cons_cnt++; > + > + return 1; > +} > static int process_resp_one(struct qedr_dev *dev, struct qedr_qp *qp, > struct qedr_cq *cq, struct ib_wc *wc, > struct rdma_cqe_responder *resp) > @@ -3662,6 +4035,20 @@ static void try_consume_resp_cqe(struct qedr_cq *cq, struct qedr_qp *qp, > } > } > > +static int qedr_poll_cq_resp_srq(struct qedr_dev *dev, struct qedr_qp *qp, > + struct qedr_cq *cq, int num_entries, > + struct ib_wc *wc, > + struct rdma_cqe_responder *resp, int *update) > +{ > + int cnt; > + > + cnt = process_resp_one_srq(dev, qp, cq, wc, resp); > + consume_cqe(cq); > + *update |= 1; This is just strange, just make it to bool and set to true. both try_consume_req_cqe() and qedr_poll_cq_resp() touch it only to do that same |= 1 thing. Mark > + > + return cnt; > +} > + > static int qedr_poll_cq_resp(struct qedr_dev *dev, struct qedr_qp *qp, > struct qedr_cq *cq, int num_entries, > struct ib_wc *wc, struct rdma_cqe_responder *resp, > @@ -3739,6 +4126,10 @@ int qedr_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc) > cnt = qedr_poll_cq_resp(dev, qp, cq, num_entries, wc, > &cqe->resp, &update); > break; > + case RDMA_CQE_TYPE_RESPONDER_SRQ: > + cnt = qedr_poll_cq_resp_srq(dev, qp, cq, num_entries, > + wc, &cqe->resp, &update); > + break; > case RDMA_CQE_TYPE_INVALID: > default: > DP_ERR(dev, "Error: invalid CQE type = %d\n", > diff --git a/drivers/infiniband/hw/qedr/verbs.h b/drivers/infiniband/hw/qedr/verbs.h > index 2c57e4c..7c7aabd 100644 > --- a/drivers/infiniband/hw/qedr/verbs.h > +++ b/drivers/infiniband/hw/qedr/verbs.h > @@ -66,6 +66,15 @@ int qedr_query_qp(struct ib_qp *, struct ib_qp_attr *qp_attr, > int qp_attr_mask, struct ib_qp_init_attr *); > int qedr_destroy_qp(struct ib_qp *ibqp); > > +struct ib_srq *qedr_create_srq(struct ib_pd *ibpd, > + struct ib_srq_init_attr *attr, > + struct ib_udata *udata); > +int qedr_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, > + enum ib_srq_attr_mask attr_mask, struct ib_udata *udata); > +int qedr_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr); > +int qedr_destroy_srq(struct ib_srq *ibsrq); > +int qedr_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, > + struct ib_recv_wr **bad_recv_wr); > struct ib_ah *qedr_create_ah(struct ib_pd *ibpd, struct rdma_ah_attr *attr, > struct ib_udata *udata); > int qedr_destroy_ah(struct ib_ah *ibah); > -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html