RDMA/ocrdma: Consider multiple SGES in case of DPP
authorNaresh Gottumukkala <bgottumukkala@emulex.com>
Mon, 26 Aug 2013 09:57:48 +0000 (15:27 +0530)
committerRoland Dreier <roland@purestorage.com>
Tue, 3 Sep 2013 04:18:44 +0000 (21:18 -0700)
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>
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c

index f09a9403b6002d4dd69f54b62383f1db61833c51..0504e7376f1ec293d41751b135bf40ef7e0522b1 100644 (file)
@@ -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 {
This page took 0.026205 seconds and 5 git commands to generate.