diff options
author | Naresh Gottumukkala <bgottumukkala@emulex.com> | 2013-08-26 15:27:48 +0530 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2013-09-02 21:18:44 -0700 |
commit | 117e6dd1c5c96ef1edd6e5def4dd9937d98cae94 (patch) | |
tree | 26c73a5fecf0701e6e468fd28f45b7581c100fce /drivers/infiniband | |
parent | f24ceba6b6454f68f456981be2a337b6390d9aa0 (diff) |
RDMA/ocrdma: Consider multiple SGES in case of DPP
While posting inline DPP data, we are not considering multiple sges.
Fix this.
Signed-off-by: Naresh Gottumukkala <bgottumukkala@emulex.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 32 |
1 files changed, 25 insertions, 7 deletions
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index f09a9403b600..0504e7376f1e 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -1820,24 +1820,42 @@ static void ocrdma_build_sges(struct ocrdma_hdr_wqe *hdr, memset(sge, 0, sizeof(*sge)); } +static inline uint32_t ocrdma_sglist_len(struct ib_sge *sg_list, int num_sge) +{ + uint32_t total_len = 0, i; + + for (i = 0; i < num_sge; i++) + total_len += sg_list[i].length; + return total_len; +} + + static int ocrdma_build_inline_sges(struct ocrdma_qp *qp, struct ocrdma_hdr_wqe *hdr, struct ocrdma_sge *sge, struct ib_send_wr *wr, u32 wqe_size) { + int i; + char *dpp_addr; + if (wr->send_flags & IB_SEND_INLINE && qp->qp_type != IB_QPT_UD) { - if (wr->sg_list[0].length > qp->max_inline_data) { + hdr->total_len = ocrdma_sglist_len(wr->sg_list, wr->num_sge); + if (unlikely(hdr->total_len > qp->max_inline_data)) { pr_err("%s() supported_len=0x%x,\n" " unspported len req=0x%x\n", __func__, - qp->max_inline_data, wr->sg_list[0].length); + qp->max_inline_data, hdr->total_len); return -EINVAL; } - memcpy(sge, - (void *)(unsigned long)wr->sg_list[0].addr, - wr->sg_list[0].length); - hdr->total_len = wr->sg_list[0].length; + dpp_addr = (char *)sge; + for (i = 0; i < wr->num_sge; i++) { + memcpy(dpp_addr, + (void *)(unsigned long)wr->sg_list[i].addr, + wr->sg_list[i].length); + dpp_addr += wr->sg_list[i].length; + } + wqe_size += roundup(hdr->total_len, OCRDMA_WQE_ALIGN_BYTES); - if (0 == wr->sg_list[0].length) + if (0 == hdr->total_len) wqe_size += sizeof(struct ocrdma_sge); hdr->cw |= (OCRDMA_TYPE_INLINE << OCRDMA_WQE_TYPE_SHIFT); } else { |