aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNaresh Gottumukkala <bgottumukkala@emulex.com>2013-08-26 05:57:39 -0400
committerRoland Dreier <roland@purestorage.com>2013-09-03 00:17:48 -0400
commit7c33880c3cb2cda816d4d64852c6a81018b9bc1f (patch)
tree517ab6a470642f8c07f59a7eb734c58cecf80c10
parent43a6b4025c79ded5b44e58ba0db97c29dd38d718 (diff)
RDMA/ocrdma: Add support for fast register work requests (FRWR)
Also get the max_srq value from query_config mailbox response. Signed-off-by: Naresh Gottumukkala <bgottumukkala@emulex.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma.h2
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_hw.c3
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_main.c4
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_sli.h19
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_verbs.c162
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_verbs.h5
6 files changed, 192 insertions, 3 deletions
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma.h b/drivers/infiniband/hw/ocrdma/ocrdma.h
index b4511668514d..634c2e18521b 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma.h
+++ b/drivers/infiniband/hw/ocrdma/ocrdma.h
@@ -56,6 +56,7 @@ struct ocrdma_dev_attr {
56 u16 max_qp; 56 u16 max_qp;
57 u16 max_wqe; 57 u16 max_wqe;
58 u16 max_rqe; 58 u16 max_rqe;
59 u16 max_srq;
59 u32 max_inline_data; 60 u32 max_inline_data;
60 int max_send_sge; 61 int max_send_sge;
61 int max_recv_sge; 62 int max_recv_sge;
@@ -169,6 +170,7 @@ struct ocrdma_dev {
169 struct list_head entry; 170 struct list_head entry;
170 struct rcu_head rcu; 171 struct rcu_head rcu;
171 int id; 172 int id;
173 u64 stag_arr[OCRDMA_MAX_STAG];
172}; 174};
173 175
174struct ocrdma_cq { 176struct ocrdma_cq {
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
index 31fd3ff1d1d0..af3c5f564d60 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
@@ -999,6 +999,9 @@ static void ocrdma_get_attr(struct ocrdma_dev *dev,
999 attr->max_ord_per_qp = (rsp->max_ird_ord_per_qp & 999 attr->max_ord_per_qp = (rsp->max_ird_ord_per_qp &
1000 OCRDMA_MBX_QUERY_CFG_MAX_ORD_PER_QP_MASK) >> 1000 OCRDMA_MBX_QUERY_CFG_MAX_ORD_PER_QP_MASK) >>
1001 OCRDMA_MBX_QUERY_CFG_MAX_ORD_PER_QP_SHIFT; 1001 OCRDMA_MBX_QUERY_CFG_MAX_ORD_PER_QP_SHIFT;
1002 attr->max_srq =
1003 (rsp->max_srq_rpir_qps & OCRDMA_MBX_QUERY_CFG_MAX_SRQ_MASK) >>
1004 OCRDMA_MBX_QUERY_CFG_MAX_SRQ_OFFSET;
1002 attr->max_ird_per_qp = (rsp->max_ird_ord_per_qp & 1005 attr->max_ird_per_qp = (rsp->max_ird_ord_per_qp &
1003 OCRDMA_MBX_QUERY_CFG_MAX_IRD_PER_QP_MASK) >> 1006 OCRDMA_MBX_QUERY_CFG_MAX_IRD_PER_QP_MASK) >>
1004 OCRDMA_MBX_QUERY_CFG_MAX_IRD_PER_QP_SHIFT; 1007 OCRDMA_MBX_QUERY_CFG_MAX_IRD_PER_QP_SHIFT;
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
index ded416f1adea..4eeea56f7b31 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
@@ -329,6 +329,10 @@ static int ocrdma_register_device(struct ocrdma_dev *dev)
329 dev->ibdev.dereg_mr = ocrdma_dereg_mr; 329 dev->ibdev.dereg_mr = ocrdma_dereg_mr;
330 dev->ibdev.reg_user_mr = ocrdma_reg_user_mr; 330 dev->ibdev.reg_user_mr = ocrdma_reg_user_mr;
331 331
332 dev->ibdev.alloc_fast_reg_mr = ocrdma_alloc_frmr;
333 dev->ibdev.alloc_fast_reg_page_list = ocrdma_alloc_frmr_page_list;
334 dev->ibdev.free_fast_reg_page_list = ocrdma_free_frmr_page_list;
335
332 /* mandatory to support user space verbs consumer. */ 336 /* mandatory to support user space verbs consumer. */
333 dev->ibdev.alloc_ucontext = ocrdma_alloc_ucontext; 337 dev->ibdev.alloc_ucontext = ocrdma_alloc_ucontext;
334 dev->ibdev.dealloc_ucontext = ocrdma_dealloc_ucontext; 338 dev->ibdev.dealloc_ucontext = ocrdma_dealloc_ucontext;
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_sli.h b/drivers/infiniband/hw/ocrdma/ocrdma_sli.h
index 0184009060db..6cf5a96f38c6 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_sli.h
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_sli.h
@@ -91,6 +91,7 @@ enum {
91 91
92#define OCRDMA_MAX_QP 2048 92#define OCRDMA_MAX_QP 2048
93#define OCRDMA_MAX_CQ 2048 93#define OCRDMA_MAX_CQ 2048
94#define OCRDMA_MAX_STAG 2048
94 95
95enum { 96enum {
96 OCRDMA_DB_RQ_OFFSET = 0xE0, 97 OCRDMA_DB_RQ_OFFSET = 0xE0,
@@ -1564,6 +1565,7 @@ enum OCRDMA_WQE_OPCODE {
1564 OCRDMA_SEND = 0x00, 1565 OCRDMA_SEND = 0x00,
1565 OCRDMA_CMP_SWP = 0x14, 1566 OCRDMA_CMP_SWP = 0x14,
1566 OCRDMA_BIND_MW = 0x10, 1567 OCRDMA_BIND_MW = 0x10,
1568 OCRDMA_FR_MR = 0x11,
1567 OCRDMA_RESV1 = 0x0A, 1569 OCRDMA_RESV1 = 0x0A,
1568 OCRDMA_LKEY_INV = 0x15, 1570 OCRDMA_LKEY_INV = 0x15,
1569 OCRDMA_FETCH_ADD = 0x13, 1571 OCRDMA_FETCH_ADD = 0x13,
@@ -1610,6 +1612,23 @@ struct ocrdma_ewqe_ud_hdr {
1610 u32 rsvd; 1612 u32 rsvd;
1611}; 1613};
1612 1614
1615#define OCRDMA_MAX_FR_PBES 11
1616struct ocrdma_fr_pbe {
1617 u32 pa_hi;
1618 u32 pa_lo;
1619};
1620
1621/* extended wqe followed by hdr_wqe for Fast Memory register */
1622struct ocrdma_ewqe_fr {
1623 u32 va_hi;
1624 u32 va_lo;
1625 u32 fbo_hi;
1626 u32 fbo_lo;
1627 u32 size_sge;
1628 u32 num_sges;
1629 struct ocrdma_fr_pbe pbe[0];
1630};
1631
1613struct ocrdma_eth_basic { 1632struct ocrdma_eth_basic {
1614 u8 dmac[6]; 1633 u8 dmac[6];
1615 u8 smac[6]; 1634 u8 smac[6];
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
index 278b33b628e1..ffa5511baf3c 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
@@ -96,7 +96,7 @@ int ocrdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr)
96 attr->max_qp_rd_atom = 96 attr->max_qp_rd_atom =
97 min(dev->attr.max_ord_per_qp, dev->attr.max_ird_per_qp); 97 min(dev->attr.max_ord_per_qp, dev->attr.max_ird_per_qp);
98 attr->max_qp_init_rd_atom = dev->attr.max_ord_per_qp; 98 attr->max_qp_init_rd_atom = dev->attr.max_ord_per_qp;
99 attr->max_srq = (dev->attr.max_qp - 1); 99 attr->max_srq = dev->attr.max_srq;
100 attr->max_srq_sge = dev->attr.max_srq_sge; 100 attr->max_srq_sge = dev->attr.max_srq_sge;
101 attr->max_srq_wr = dev->attr.max_rqe; 101 attr->max_srq_wr = dev->attr.max_rqe;
102 attr->local_ca_ack_delay = dev->attr.local_ca_ack_delay; 102 attr->local_ca_ack_delay = dev->attr.local_ca_ack_delay;
@@ -1304,7 +1304,6 @@ static void ocrdma_srq_toggle_bit(struct ocrdma_srq *srq, int idx)
1304 1304
1305static int ocrdma_hwq_free_cnt(struct ocrdma_qp_hwq_info *q) 1305static int ocrdma_hwq_free_cnt(struct ocrdma_qp_hwq_info *q)
1306{ 1306{
1307 int free_cnt;
1308 return ((q->max_wqe_idx - q->head) + q->tail) % q->max_cnt; 1307 return ((q->max_wqe_idx - q->head) + q->tail) % q->max_cnt;
1309} 1308}
1310 1309
@@ -1746,6 +1745,96 @@ static void ocrdma_build_read(struct ocrdma_qp *qp, struct ocrdma_hdr_wqe *hdr,
1746 ext_rw->len = hdr->total_len; 1745 ext_rw->len = hdr->total_len;
1747} 1746}
1748 1747
1748static void build_frmr_pbes(struct ib_send_wr *wr, struct ocrdma_pbl *pbl_tbl,
1749 struct ocrdma_hw_mr *hwmr)
1750{
1751 int i;
1752 u64 buf_addr = 0;
1753 int num_pbes;
1754 struct ocrdma_pbe *pbe;
1755
1756 pbe = (struct ocrdma_pbe *)pbl_tbl->va;
1757 num_pbes = 0;
1758
1759 /* go through the OS phy regions & fill hw pbe entries into pbls. */
1760 for (i = 0; i < wr->wr.fast_reg.page_list_len; i++) {
1761 /* number of pbes can be more for one OS buf, when
1762 * buffers are of different sizes.
1763 * split the ib_buf to one or more pbes.
1764 */
1765 buf_addr = wr->wr.fast_reg.page_list->page_list[i];
1766 pbe->pa_lo = cpu_to_le32((u32) (buf_addr & PAGE_MASK));
1767 pbe->pa_hi = cpu_to_le32((u32) upper_32_bits(buf_addr));
1768 num_pbes += 1;
1769 pbe++;
1770
1771 /* if the pbl is full storing the pbes,
1772 * move to next pbl.
1773 */
1774 if (num_pbes == (hwmr->pbl_size/sizeof(u64))) {
1775 pbl_tbl++;
1776 pbe = (struct ocrdma_pbe *)pbl_tbl->va;
1777 }
1778 }
1779 return;
1780}
1781
1782static int get_encoded_page_size(int pg_sz)
1783{
1784 /* Max size is 256M 4096 << 16 */
1785 int i = 0;
1786 for (; i < 17; i++)
1787 if (pg_sz == (4096 << i))
1788 break;
1789 return i;
1790}
1791
1792
1793static int ocrdma_build_fr(struct ocrdma_qp *qp, struct ocrdma_hdr_wqe *hdr,
1794 struct ib_send_wr *wr)
1795{
1796 u64 fbo;
1797 struct ocrdma_ewqe_fr *fast_reg = (struct ocrdma_ewqe_fr *)(hdr + 1);
1798 struct ocrdma_mr *mr;
1799 u32 wqe_size = sizeof(*fast_reg) + sizeof(*hdr);
1800
1801 wqe_size = roundup(wqe_size, OCRDMA_WQE_ALIGN_BYTES);
1802
1803 if ((wr->wr.fast_reg.page_list_len >
1804 qp->dev->attr.max_pages_per_frmr) ||
1805 (wr->wr.fast_reg.length > 0xffffffffULL))
1806 return -EINVAL;
1807
1808 hdr->cw |= (OCRDMA_FR_MR << OCRDMA_WQE_OPCODE_SHIFT);
1809 hdr->cw |= ((wqe_size / OCRDMA_WQE_STRIDE) << OCRDMA_WQE_SIZE_SHIFT);
1810
1811 if (wr->wr.fast_reg.page_list_len == 0)
1812 BUG();
1813 if (wr->wr.fast_reg.access_flags & IB_ACCESS_LOCAL_WRITE)
1814 hdr->rsvd_lkey_flags |= OCRDMA_LKEY_FLAG_LOCAL_WR;
1815 if (wr->wr.fast_reg.access_flags & IB_ACCESS_REMOTE_WRITE)
1816 hdr->rsvd_lkey_flags |= OCRDMA_LKEY_FLAG_REMOTE_WR;
1817 if (wr->wr.fast_reg.access_flags & IB_ACCESS_REMOTE_READ)
1818 hdr->rsvd_lkey_flags |= OCRDMA_LKEY_FLAG_REMOTE_RD;
1819 hdr->lkey = wr->wr.fast_reg.rkey;
1820 hdr->total_len = wr->wr.fast_reg.length;
1821
1822 fbo = wr->wr.fast_reg.iova_start -
1823 (wr->wr.fast_reg.page_list->page_list[0] & PAGE_MASK);
1824
1825 fast_reg->va_hi = upper_32_bits(wr->wr.fast_reg.iova_start);
1826 fast_reg->va_lo = (u32) (wr->wr.fast_reg.iova_start & 0xffffffff);
1827 fast_reg->fbo_hi = upper_32_bits(fbo);
1828 fast_reg->fbo_lo = (u32) fbo & 0xffffffff;
1829 fast_reg->num_sges = wr->wr.fast_reg.page_list_len;
1830 fast_reg->size_sge =
1831 get_encoded_page_size(1 << wr->wr.fast_reg.page_shift);
1832 mr = (struct ocrdma_mr *)qp->dev->stag_arr[(hdr->lkey >> 8) &
1833 (OCRDMA_MAX_STAG - 1)];
1834 build_frmr_pbes(wr, mr->hwmr.pbl_table, &mr->hwmr);
1835 return 0;
1836}
1837
1749static void ocrdma_ring_sq_db(struct ocrdma_qp *qp) 1838static void ocrdma_ring_sq_db(struct ocrdma_qp *qp)
1750{ 1839{
1751 u32 val = qp->sq.dbid | (1 << 16); 1840 u32 val = qp->sq.dbid | (1 << 16);
@@ -1815,10 +1904,14 @@ int ocrdma_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
1815 case IB_WR_LOCAL_INV: 1904 case IB_WR_LOCAL_INV:
1816 hdr->cw |= 1905 hdr->cw |=
1817 (OCRDMA_LKEY_INV << OCRDMA_WQE_OPCODE_SHIFT); 1906 (OCRDMA_LKEY_INV << OCRDMA_WQE_OPCODE_SHIFT);
1818 hdr->cw |= (sizeof(struct ocrdma_hdr_wqe) / 1907 hdr->cw |= ((sizeof(struct ocrdma_hdr_wqe) +
1908 sizeof(struct ocrdma_sge)) /
1819 OCRDMA_WQE_STRIDE) << OCRDMA_WQE_SIZE_SHIFT; 1909 OCRDMA_WQE_STRIDE) << OCRDMA_WQE_SIZE_SHIFT;
1820 hdr->lkey = wr->ex.invalidate_rkey; 1910 hdr->lkey = wr->ex.invalidate_rkey;
1821 break; 1911 break;
1912 case IB_WR_FAST_REG_MR:
1913 status = ocrdma_build_fr(qp, hdr, wr);
1914 break;
1822 default: 1915 default:
1823 status = -EINVAL; 1916 status = -EINVAL;
1824 break; 1917 break;
@@ -2085,6 +2178,9 @@ static void ocrdma_update_wc(struct ocrdma_qp *qp, struct ib_wc *ibwc,
2085 case OCRDMA_SEND: 2178 case OCRDMA_SEND:
2086 ibwc->opcode = IB_WC_SEND; 2179 ibwc->opcode = IB_WC_SEND;
2087 break; 2180 break;
2181 case OCRDMA_FR_MR:
2182 ibwc->opcode = IB_WC_FAST_REG_MR;
2183 break;
2088 case OCRDMA_LKEY_INV: 2184 case OCRDMA_LKEY_INV:
2089 ibwc->opcode = IB_WC_LOCAL_INV; 2185 ibwc->opcode = IB_WC_LOCAL_INV;
2090 break; 2186 break;
@@ -2530,3 +2626,63 @@ int ocrdma_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags cq_flags)
2530 spin_unlock_irqrestore(&cq->cq_lock, flags); 2626 spin_unlock_irqrestore(&cq->cq_lock, flags);
2531 return 0; 2627 return 0;
2532} 2628}
2629
2630struct ib_mr *ocrdma_alloc_frmr(struct ib_pd *ibpd, int max_page_list_len)
2631{
2632 int status;
2633 struct ocrdma_mr *mr;
2634 struct ocrdma_pd *pd = get_ocrdma_pd(ibpd);
2635 struct ocrdma_dev *dev = get_ocrdma_dev(ibpd->device);
2636
2637 if (max_page_list_len > dev->attr.max_pages_per_frmr)
2638 return ERR_PTR(-EINVAL);
2639
2640 mr = kzalloc(sizeof(*mr), GFP_KERNEL);
2641 if (!mr)
2642 return ERR_PTR(-ENOMEM);
2643
2644 status = ocrdma_get_pbl_info(dev, mr, max_page_list_len);
2645 if (status)
2646 goto pbl_err;
2647 mr->hwmr.fr_mr = 1;
2648 mr->hwmr.remote_rd = 0;
2649 mr->hwmr.remote_wr = 0;
2650 mr->hwmr.local_rd = 0;
2651 mr->hwmr.local_wr = 0;
2652 mr->hwmr.mw_bind = 0;
2653 status = ocrdma_build_pbl_tbl(dev, &mr->hwmr);
2654 if (status)
2655 goto pbl_err;
2656 status = ocrdma_reg_mr(dev, &mr->hwmr, pd->id, 0);
2657 if (status)
2658 goto mbx_err;
2659 mr->ibmr.rkey = mr->hwmr.lkey;
2660 mr->ibmr.lkey = mr->hwmr.lkey;
2661 dev->stag_arr[(mr->hwmr.lkey >> 8) & (OCRDMA_MAX_STAG - 1)] = (u64) mr;
2662 return &mr->ibmr;
2663mbx_err:
2664 ocrdma_free_mr_pbl_tbl(dev, &mr->hwmr);
2665pbl_err:
2666 kfree(mr);
2667 return ERR_PTR(-ENOMEM);
2668}
2669
2670struct ib_fast_reg_page_list *ocrdma_alloc_frmr_page_list(struct ib_device
2671 *ibdev,
2672 int page_list_len)
2673{
2674 struct ib_fast_reg_page_list *frmr_list;
2675 int size;
2676
2677 size = sizeof(*frmr_list) + (page_list_len * sizeof(u64));
2678 frmr_list = kzalloc(size, GFP_KERNEL);
2679 if (!frmr_list)
2680 return ERR_PTR(-ENOMEM);
2681 frmr_list->page_list = (u64 *)(frmr_list + 1);
2682 return frmr_list;
2683}
2684
2685void ocrdma_free_frmr_page_list(struct ib_fast_reg_page_list *page_list)
2686{
2687 kfree(page_list);
2688}
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
index 633f03d80274..7f3056731af1 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
@@ -89,5 +89,10 @@ struct ib_mr *ocrdma_reg_kernel_mr(struct ib_pd *,
89 int num_phys_buf, int acc, u64 *iova_start); 89 int num_phys_buf, int acc, u64 *iova_start);
90struct ib_mr *ocrdma_reg_user_mr(struct ib_pd *, u64 start, u64 length, 90struct ib_mr *ocrdma_reg_user_mr(struct ib_pd *, u64 start, u64 length,
91 u64 virt, int acc, struct ib_udata *); 91 u64 virt, int acc, struct ib_udata *);
92struct ib_mr *ocrdma_alloc_frmr(struct ib_pd *pd, int max_page_list_len);
93struct ib_fast_reg_page_list *ocrdma_alloc_frmr_page_list(struct ib_device
94 *ibdev,
95 int page_list_len);
96void ocrdma_free_frmr_page_list(struct ib_fast_reg_page_list *page_list);
92 97
93#endif /* __OCRDMA_VERBS_H__ */ 98#endif /* __OCRDMA_VERBS_H__ */