diff options
author | Sagi Grimberg <sagig@mellanox.com> | 2016-02-29 12:07:33 -0500 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2016-03-04 11:59:35 -0500 |
commit | b005d316471374b1ff26df8c8460cc1ea9186647 (patch) | |
tree | eee7d5f6dd1f268252019d9ef8572ba72d16cf48 | |
parent | f5aa9159a418726d74b67c8815ffd2739afb4c7a (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.c | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx5/mlx5_ib.h | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx5/mr.c | 50 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx5/qp.c | 15 |
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 | ||
1751 | static int | ||
1752 | mlx5_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 | |||
1742 | static int mlx5_set_page(struct ib_mr *ibmr, u64 addr) | 1777 | static 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 | ||
2779 | static void set_linv_mkey_seg(struct mlx5_mkey_seg *seg) | 2790 | static void set_linv_mkey_seg(struct mlx5_mkey_seg *seg) |