aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSagi Grimberg <sagig@mellanox.com>2016-02-29 12:07:33 -0500
committerDoug Ledford <dledford@redhat.com>2016-03-04 11:59:35 -0500
commitb005d316471374b1ff26df8c8460cc1ea9186647 (patch)
treeeee7d5f6dd1f268252019d9ef8572ba72d16cf48
parentf5aa9159a418726d74b67c8815ffd2739afb4c7a (diff)
mlx5: Add arbitrary sg list support
Allocate proper context for arbitrary scatterlist registration If ib_alloc_mr is called with IB_MR_MAP_ARB_SG, the driver allocate a private klm list instead of a private page list. Set the UMR wqe correctly when posting the fast registration. Also, expose device cap IB_DEVICE_MAP_ARB_SG according to the device id (until we have a FW bit that correctly exposes it). Signed-off-by: Sagi Grimberg <sagig@mellanox.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/hw/mlx5/main.c2
-rw-r--r--drivers/infiniband/hw/mlx5/mlx5_ib.h1
-rw-r--r--drivers/infiniband/hw/mlx5/mr.c50
-rw-r--r--drivers/infiniband/hw/mlx5/qp.c15
4 files changed, 60 insertions, 8 deletions
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 55fa5889d3b2..7e89a547bf34 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -491,6 +491,8 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
491 props->device_cap_flags |= IB_DEVICE_MEM_WINDOW | 491 props->device_cap_flags |= IB_DEVICE_MEM_WINDOW |
492 IB_DEVICE_MEM_WINDOW_TYPE_2B; 492 IB_DEVICE_MEM_WINDOW_TYPE_2B;
493 props->max_mw = 1 << MLX5_CAP_GEN(mdev, log_max_mkey); 493 props->max_mw = 1 << MLX5_CAP_GEN(mdev, log_max_mkey);
494 /* We support 'Gappy' memory registration too */
495 props->device_cap_flags |= IB_DEVICE_SG_GAPS_REG;
494 } 496 }
495 props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS; 497 props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS;
496 if (MLX5_CAP_GEN(mdev, sho)) { 498 if (MLX5_CAP_GEN(mdev, sho)) {
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index 3c02b3ce76ae..60b89629f091 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -447,6 +447,7 @@ struct mlx5_ib_mr {
447 int ndescs; 447 int ndescs;
448 int max_descs; 448 int max_descs;
449 int desc_size; 449 int desc_size;
450 int access_mode;
450 struct mlx5_core_mkey mmkey; 451 struct mlx5_core_mkey mmkey;
451 struct ib_umem *umem; 452 struct ib_umem *umem;
452 struct mlx5_shared_mr_info *smr_info; 453 struct mlx5_shared_mr_info *smr_info;
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c
index 628f43506d91..4d5bff151cdf 100644
--- a/drivers/infiniband/hw/mlx5/mr.c
+++ b/drivers/infiniband/hw/mlx5/mr.c
@@ -1521,8 +1521,8 @@ struct ib_mr *mlx5_ib_alloc_mr(struct ib_pd *pd,
1521 struct mlx5_ib_dev *dev = to_mdev(pd->device); 1521 struct mlx5_ib_dev *dev = to_mdev(pd->device);
1522 struct mlx5_create_mkey_mbox_in *in; 1522 struct mlx5_create_mkey_mbox_in *in;
1523 struct mlx5_ib_mr *mr; 1523 struct mlx5_ib_mr *mr;
1524 int access_mode, err; 1524 int ndescs = ALIGN(max_num_sg, 4);
1525 int ndescs = roundup(max_num_sg, 4); 1525 int err;
1526 1526
1527 mr = kzalloc(sizeof(*mr), GFP_KERNEL); 1527 mr = kzalloc(sizeof(*mr), GFP_KERNEL);
1528 if (!mr) 1528 if (!mr)
@@ -1540,7 +1540,7 @@ struct ib_mr *mlx5_ib_alloc_mr(struct ib_pd *pd,
1540 in->seg.flags_pd = cpu_to_be32(to_mpd(pd)->pdn); 1540 in->seg.flags_pd = cpu_to_be32(to_mpd(pd)->pdn);
1541 1541
1542 if (mr_type == IB_MR_TYPE_MEM_REG) { 1542 if (mr_type == IB_MR_TYPE_MEM_REG) {
1543 access_mode = MLX5_ACCESS_MODE_MTT; 1543 mr->access_mode = MLX5_ACCESS_MODE_MTT;
1544 in->seg.log2_page_size = PAGE_SHIFT; 1544 in->seg.log2_page_size = PAGE_SHIFT;
1545 1545
1546 err = mlx5_alloc_priv_descs(pd->device, mr, 1546 err = mlx5_alloc_priv_descs(pd->device, mr,
@@ -1550,6 +1550,15 @@ struct ib_mr *mlx5_ib_alloc_mr(struct ib_pd *pd,
1550 1550
1551 mr->desc_size = sizeof(u64); 1551 mr->desc_size = sizeof(u64);
1552 mr->max_descs = ndescs; 1552 mr->max_descs = ndescs;
1553 } else if (mr_type == IB_MR_TYPE_SG_GAPS) {
1554 mr->access_mode = MLX5_ACCESS_MODE_KLM;
1555
1556 err = mlx5_alloc_priv_descs(pd->device, mr,
1557 ndescs, sizeof(struct mlx5_klm));
1558 if (err)
1559 goto err_free_in;
1560 mr->desc_size = sizeof(struct mlx5_klm);
1561 mr->max_descs = ndescs;
1553 } else if (mr_type == IB_MR_TYPE_SIGNATURE) { 1562 } else if (mr_type == IB_MR_TYPE_SIGNATURE) {
1554 u32 psv_index[2]; 1563 u32 psv_index[2];
1555 1564
@@ -1568,7 +1577,7 @@ struct ib_mr *mlx5_ib_alloc_mr(struct ib_pd *pd,
1568 if (err) 1577 if (err)
1569 goto err_free_sig; 1578 goto err_free_sig;
1570 1579
1571 access_mode = MLX5_ACCESS_MODE_KLM; 1580 mr->access_mode = MLX5_ACCESS_MODE_KLM;
1572 mr->sig->psv_memory.psv_idx = psv_index[0]; 1581 mr->sig->psv_memory.psv_idx = psv_index[0];
1573 mr->sig->psv_wire.psv_idx = psv_index[1]; 1582 mr->sig->psv_wire.psv_idx = psv_index[1];
1574 1583
@@ -1582,7 +1591,7 @@ struct ib_mr *mlx5_ib_alloc_mr(struct ib_pd *pd,
1582 goto err_free_in; 1591 goto err_free_in;
1583 } 1592 }
1584 1593
1585 in->seg.flags = MLX5_PERM_UMR_EN | access_mode; 1594 in->seg.flags = MLX5_PERM_UMR_EN | mr->access_mode;
1586 err = mlx5_core_create_mkey(dev->mdev, &mr->mmkey, in, sizeof(*in), 1595 err = mlx5_core_create_mkey(dev->mdev, &mr->mmkey, in, sizeof(*in),
1587 NULL, NULL, NULL); 1596 NULL, NULL, NULL);
1588 if (err) 1597 if (err)
@@ -1739,6 +1748,32 @@ done:
1739 return ret; 1748 return ret;
1740} 1749}
1741 1750
1751static int
1752mlx5_ib_sg_to_klms(struct mlx5_ib_mr *mr,
1753 struct scatterlist *sgl,
1754 unsigned short sg_nents)
1755{
1756 struct scatterlist *sg = sgl;
1757 struct mlx5_klm *klms = mr->descs;
1758 u32 lkey = mr->ibmr.pd->local_dma_lkey;
1759 int i;
1760
1761 mr->ibmr.iova = sg_dma_address(sg);
1762 mr->ibmr.length = 0;
1763 mr->ndescs = sg_nents;
1764
1765 for_each_sg(sgl, sg, sg_nents, i) {
1766 if (unlikely(i > mr->max_descs))
1767 break;
1768 klms[i].va = cpu_to_be64(sg_dma_address(sg));
1769 klms[i].bcount = cpu_to_be32(sg_dma_len(sg));
1770 klms[i].key = cpu_to_be32(lkey);
1771 mr->ibmr.length += sg_dma_len(sg);
1772 }
1773
1774 return i;
1775}
1776
1742static int mlx5_set_page(struct ib_mr *ibmr, u64 addr) 1777static int mlx5_set_page(struct ib_mr *ibmr, u64 addr)
1743{ 1778{
1744 struct mlx5_ib_mr *mr = to_mmr(ibmr); 1779 struct mlx5_ib_mr *mr = to_mmr(ibmr);
@@ -1766,7 +1801,10 @@ int mlx5_ib_map_mr_sg(struct ib_mr *ibmr,
1766 mr->desc_size * mr->max_descs, 1801 mr->desc_size * mr->max_descs,
1767 DMA_TO_DEVICE); 1802 DMA_TO_DEVICE);
1768 1803
1769 n = ib_sg_to_pages(ibmr, sg, sg_nents, mlx5_set_page); 1804 if (mr->access_mode == MLX5_ACCESS_MODE_KLM)
1805 n = mlx5_ib_sg_to_klms(mr, sg, sg_nents);
1806 else
1807 n = ib_sg_to_pages(ibmr, sg, sg_nents, mlx5_set_page);
1770 1808
1771 ib_dma_sync_single_for_device(ibmr->device, mr->desc_map, 1809 ib_dma_sync_single_for_device(ibmr->device, mr->desc_map,
1772 mr->desc_size * mr->max_descs, 1810 mr->desc_size * mr->max_descs,
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index 295eb2a54851..8dee8bc1e0fe 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -2629,6 +2629,11 @@ static void set_reg_umr_seg(struct mlx5_wqe_umr_ctrl_seg *umr,
2629 int ndescs = mr->ndescs; 2629 int ndescs = mr->ndescs;
2630 2630
2631 memset(umr, 0, sizeof(*umr)); 2631 memset(umr, 0, sizeof(*umr));
2632
2633 if (mr->access_mode == MLX5_ACCESS_MODE_KLM)
2634 /* KLMs take twice the size of MTTs */
2635 ndescs *= 2;
2636
2632 umr->flags = MLX5_UMR_CHECK_NOT_FREE; 2637 umr->flags = MLX5_UMR_CHECK_NOT_FREE;
2633 umr->klm_octowords = get_klm_octo(ndescs); 2638 umr->klm_octowords = get_klm_octo(ndescs);
2634 umr->mkey_mask = frwr_mkey_mask(); 2639 umr->mkey_mask = frwr_mkey_mask();
@@ -2767,13 +2772,19 @@ static void set_reg_mkey_seg(struct mlx5_mkey_seg *seg,
2767 int ndescs = ALIGN(mr->ndescs, 8) >> 1; 2772 int ndescs = ALIGN(mr->ndescs, 8) >> 1;
2768 2773
2769 memset(seg, 0, sizeof(*seg)); 2774 memset(seg, 0, sizeof(*seg));
2770 seg->flags = get_umr_flags(access) | MLX5_ACCESS_MODE_MTT; 2775
2776 if (mr->access_mode == MLX5_ACCESS_MODE_MTT)
2777 seg->log2_page_size = ilog2(mr->ibmr.page_size);
2778 else if (mr->access_mode == MLX5_ACCESS_MODE_KLM)
2779 /* KLMs take twice the size of MTTs */
2780 ndescs *= 2;
2781
2782 seg->flags = get_umr_flags(access) | mr->access_mode;
2771 seg->qpn_mkey7_0 = cpu_to_be32((key & 0xff) | 0xffffff00); 2783 seg->qpn_mkey7_0 = cpu_to_be32((key & 0xff) | 0xffffff00);
2772 seg->flags_pd = cpu_to_be32(MLX5_MKEY_REMOTE_INVAL); 2784 seg->flags_pd = cpu_to_be32(MLX5_MKEY_REMOTE_INVAL);
2773 seg->start_addr = cpu_to_be64(mr->ibmr.iova); 2785 seg->start_addr = cpu_to_be64(mr->ibmr.iova);
2774 seg->len = cpu_to_be64(mr->ibmr.length); 2786 seg->len = cpu_to_be64(mr->ibmr.length);
2775 seg->xlt_oct_size = cpu_to_be32(ndescs); 2787 seg->xlt_oct_size = cpu_to_be32(ndescs);
2776 seg->log2_page_size = ilog2(mr->ibmr.page_size);
2777} 2788}
2778 2789
2779static void set_linv_mkey_seg(struct mlx5_mkey_seg *seg) 2790static void set_linv_mkey_seg(struct mlx5_mkey_seg *seg)