diff options
author | Naresh Gottumukkala <bgottumukkala@emulex.com> | 2013-08-26 05:57:48 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2013-09-03 00:18:44 -0400 |
commit | 117e6dd1c5c96ef1edd6e5def4dd9937d98cae94 (patch) | |
tree | 26c73a5fecf0701e6e468fd28f45b7581c100fce /drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | |
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/hw/ocrdma/ocrdma_verbs.c')
-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, | |||
1820 | memset(sge, 0, sizeof(*sge)); | 1820 | memset(sge, 0, sizeof(*sge)); |
1821 | } | 1821 | } |
1822 | 1822 | ||
1823 | static inline uint32_t ocrdma_sglist_len(struct ib_sge *sg_list, int num_sge) | ||
1824 | { | ||
1825 | uint32_t total_len = 0, i; | ||
1826 | |||
1827 | for (i = 0; i < num_sge; i++) | ||
1828 | total_len += sg_list[i].length; | ||
1829 | return total_len; | ||
1830 | } | ||
1831 | |||
1832 | |||
1823 | static int ocrdma_build_inline_sges(struct ocrdma_qp *qp, | 1833 | static int ocrdma_build_inline_sges(struct ocrdma_qp *qp, |
1824 | struct ocrdma_hdr_wqe *hdr, | 1834 | struct ocrdma_hdr_wqe *hdr, |
1825 | struct ocrdma_sge *sge, | 1835 | struct ocrdma_sge *sge, |
1826 | struct ib_send_wr *wr, u32 wqe_size) | 1836 | struct ib_send_wr *wr, u32 wqe_size) |
1827 | { | 1837 | { |
1838 | int i; | ||
1839 | char *dpp_addr; | ||
1840 | |||
1828 | if (wr->send_flags & IB_SEND_INLINE && qp->qp_type != IB_QPT_UD) { | 1841 | if (wr->send_flags & IB_SEND_INLINE && qp->qp_type != IB_QPT_UD) { |
1829 | if (wr->sg_list[0].length > qp->max_inline_data) { | 1842 | hdr->total_len = ocrdma_sglist_len(wr->sg_list, wr->num_sge); |
1843 | if (unlikely(hdr->total_len > qp->max_inline_data)) { | ||
1830 | pr_err("%s() supported_len=0x%x,\n" | 1844 | pr_err("%s() supported_len=0x%x,\n" |
1831 | " unspported len req=0x%x\n", __func__, | 1845 | " unspported len req=0x%x\n", __func__, |
1832 | qp->max_inline_data, wr->sg_list[0].length); | 1846 | qp->max_inline_data, hdr->total_len); |
1833 | return -EINVAL; | 1847 | return -EINVAL; |
1834 | } | 1848 | } |
1835 | memcpy(sge, | 1849 | dpp_addr = (char *)sge; |
1836 | (void *)(unsigned long)wr->sg_list[0].addr, | 1850 | for (i = 0; i < wr->num_sge; i++) { |
1837 | wr->sg_list[0].length); | 1851 | memcpy(dpp_addr, |
1838 | hdr->total_len = wr->sg_list[0].length; | 1852 | (void *)(unsigned long)wr->sg_list[i].addr, |
1853 | wr->sg_list[i].length); | ||
1854 | dpp_addr += wr->sg_list[i].length; | ||
1855 | } | ||
1856 | |||
1839 | wqe_size += roundup(hdr->total_len, OCRDMA_WQE_ALIGN_BYTES); | 1857 | wqe_size += roundup(hdr->total_len, OCRDMA_WQE_ALIGN_BYTES); |
1840 | if (0 == wr->sg_list[0].length) | 1858 | if (0 == hdr->total_len) |
1841 | wqe_size += sizeof(struct ocrdma_sge); | 1859 | wqe_size += sizeof(struct ocrdma_sge); |
1842 | hdr->cw |= (OCRDMA_TYPE_INLINE << OCRDMA_WQE_TYPE_SHIFT); | 1860 | hdr->cw |= (OCRDMA_TYPE_INLINE << OCRDMA_WQE_TYPE_SHIFT); |
1843 | } else { | 1861 | } else { |