diff options
author | Matan Barak <matanb@mellanox.com> | 2016-02-29 11:05:30 -0500 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2016-03-01 11:18:54 -0500 |
commit | d2370e0a573e5c5ea9c96373558727abb3ea71f7 (patch) | |
tree | 11e770e07728416ed1a26eb102b2274243b2697a | |
parent | b2a239df4e65fe35240ddf3e5f9f31335c90589b (diff) |
IB/mlx5: Add memory windows allocation support
This patch adds user-space support for memory windows allocation and
deallocation. It also exposes the supported types via
query_device_caps verb.
Signed-off-by: Matan Barak <matanb@mellanox.com>
Reviewed-by: Yishai Hadas <yishaih@mellanox.com>
Tested-by: Max Gurtovoy <maxg@mellanox.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r-- | drivers/infiniband/hw/mlx5/main.c | 13 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx5/mlx5_ib.h | 14 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx5/mr.c | 83 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx5/user.h | 7 | ||||
-rw-r--r-- | include/linux/mlx5/mlx5_ifc.h | 4 |
5 files changed, 120 insertions, 1 deletions
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index 16f7d0b41c04..4d9b7cc4ca73 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c | |||
@@ -487,6 +487,11 @@ static int mlx5_ib_query_device(struct ib_device *ibdev, | |||
487 | props->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG; | 487 | props->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG; |
488 | if (MLX5_CAP_GEN(mdev, xrc)) | 488 | if (MLX5_CAP_GEN(mdev, xrc)) |
489 | props->device_cap_flags |= IB_DEVICE_XRC; | 489 | props->device_cap_flags |= IB_DEVICE_XRC; |
490 | if (MLX5_CAP_GEN(mdev, imaicl)) { | ||
491 | props->device_cap_flags |= IB_DEVICE_MEM_WINDOW | | ||
492 | IB_DEVICE_MEM_WINDOW_TYPE_2B; | ||
493 | props->max_mw = 1 << MLX5_CAP_GEN(mdev, log_max_mkey); | ||
494 | } | ||
490 | props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS; | 495 | props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS; |
491 | if (MLX5_CAP_GEN(mdev, sho)) { | 496 | if (MLX5_CAP_GEN(mdev, sho)) { |
492 | props->device_cap_flags |= IB_DEVICE_SIGNATURE_HANDOVER; | 497 | props->device_cap_flags |= IB_DEVICE_SIGNATURE_HANDOVER; |
@@ -2306,6 +2311,14 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev) | |||
2306 | 2311 | ||
2307 | mlx5_ib_internal_fill_odp_caps(dev); | 2312 | mlx5_ib_internal_fill_odp_caps(dev); |
2308 | 2313 | ||
2314 | if (MLX5_CAP_GEN(mdev, imaicl)) { | ||
2315 | dev->ib_dev.alloc_mw = mlx5_ib_alloc_mw; | ||
2316 | dev->ib_dev.dealloc_mw = mlx5_ib_dealloc_mw; | ||
2317 | dev->ib_dev.uverbs_cmd_mask |= | ||
2318 | (1ull << IB_USER_VERBS_CMD_ALLOC_MW) | | ||
2319 | (1ull << IB_USER_VERBS_CMD_DEALLOC_MW); | ||
2320 | } | ||
2321 | |||
2309 | if (MLX5_CAP_GEN(mdev, xrc)) { | 2322 | if (MLX5_CAP_GEN(mdev, xrc)) { |
2310 | dev->ib_dev.alloc_xrcd = mlx5_ib_alloc_xrcd; | 2323 | dev->ib_dev.alloc_xrcd = mlx5_ib_alloc_xrcd; |
2311 | dev->ib_dev.dealloc_xrcd = mlx5_ib_dealloc_xrcd; | 2324 | dev->ib_dev.dealloc_xrcd = mlx5_ib_dealloc_xrcd; |
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h index 4167d67179ff..648d2e2e445b 100644 --- a/drivers/infiniband/hw/mlx5/mlx5_ib.h +++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/mlx5/srq.h> | 43 | #include <linux/mlx5/srq.h> |
44 | #include <linux/types.h> | 44 | #include <linux/types.h> |
45 | #include <linux/mlx5/transobj.h> | 45 | #include <linux/mlx5/transobj.h> |
46 | #include <rdma/ib_user_verbs.h> | ||
46 | 47 | ||
47 | #define mlx5_ib_dbg(dev, format, arg...) \ | 48 | #define mlx5_ib_dbg(dev, format, arg...) \ |
48 | pr_debug("%s:%s:%d:(pid %d): " format, (dev)->ib_dev.name, __func__, \ | 49 | pr_debug("%s:%s:%d:(pid %d): " format, (dev)->ib_dev.name, __func__, \ |
@@ -461,6 +462,11 @@ struct mlx5_ib_mr { | |||
461 | int access_flags; /* Needed for rereg MR */ | 462 | int access_flags; /* Needed for rereg MR */ |
462 | }; | 463 | }; |
463 | 464 | ||
465 | struct mlx5_ib_mw { | ||
466 | struct ib_mw ibmw; | ||
467 | struct mlx5_core_mkey mmkey; | ||
468 | }; | ||
469 | |||
464 | struct mlx5_ib_umr_context { | 470 | struct mlx5_ib_umr_context { |
465 | enum ib_wc_status status; | 471 | enum ib_wc_status status; |
466 | struct completion done; | 472 | struct completion done; |
@@ -633,6 +639,11 @@ static inline struct mlx5_ib_mr *to_mmr(struct ib_mr *ibmr) | |||
633 | return container_of(ibmr, struct mlx5_ib_mr, ibmr); | 639 | return container_of(ibmr, struct mlx5_ib_mr, ibmr); |
634 | } | 640 | } |
635 | 641 | ||
642 | static inline struct mlx5_ib_mw *to_mmw(struct ib_mw *ibmw) | ||
643 | { | ||
644 | return container_of(ibmw, struct mlx5_ib_mw, ibmw); | ||
645 | } | ||
646 | |||
636 | struct mlx5_ib_ah { | 647 | struct mlx5_ib_ah { |
637 | struct ib_ah ibah; | 648 | struct ib_ah ibah; |
638 | struct mlx5_av av; | 649 | struct mlx5_av av; |
@@ -693,6 +704,9 @@ struct ib_mr *mlx5_ib_get_dma_mr(struct ib_pd *pd, int acc); | |||
693 | struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, | 704 | struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, |
694 | u64 virt_addr, int access_flags, | 705 | u64 virt_addr, int access_flags, |
695 | struct ib_udata *udata); | 706 | struct ib_udata *udata); |
707 | struct ib_mw *mlx5_ib_alloc_mw(struct ib_pd *pd, enum ib_mw_type type, | ||
708 | struct ib_udata *udata); | ||
709 | int mlx5_ib_dealloc_mw(struct ib_mw *mw); | ||
696 | int mlx5_ib_update_mtt(struct mlx5_ib_mr *mr, u64 start_page_index, | 710 | int mlx5_ib_update_mtt(struct mlx5_ib_mr *mr, u64 start_page_index, |
697 | int npages, int zap); | 711 | int npages, int zap); |
698 | int mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start, | 712 | int mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start, |
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c index 399e2b5fb573..70a047dde69e 100644 --- a/drivers/infiniband/hw/mlx5/mr.c +++ b/drivers/infiniband/hw/mlx5/mr.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <rdma/ib_umem_odp.h> | 40 | #include <rdma/ib_umem_odp.h> |
41 | #include <rdma/ib_verbs.h> | 41 | #include <rdma/ib_verbs.h> |
42 | #include "mlx5_ib.h" | 42 | #include "mlx5_ib.h" |
43 | #include "user.h" | ||
43 | 44 | ||
44 | enum { | 45 | enum { |
45 | MAX_PENDING_REG_MR = 8, | 46 | MAX_PENDING_REG_MR = 8, |
@@ -1620,6 +1621,88 @@ err_free: | |||
1620 | return ERR_PTR(err); | 1621 | return ERR_PTR(err); |
1621 | } | 1622 | } |
1622 | 1623 | ||
1624 | struct ib_mw *mlx5_ib_alloc_mw(struct ib_pd *pd, enum ib_mw_type type, | ||
1625 | struct ib_udata *udata) | ||
1626 | { | ||
1627 | struct mlx5_ib_dev *dev = to_mdev(pd->device); | ||
1628 | struct mlx5_create_mkey_mbox_in *in = NULL; | ||
1629 | struct mlx5_ib_mw *mw = NULL; | ||
1630 | int ndescs; | ||
1631 | int err; | ||
1632 | struct mlx5_ib_alloc_mw req = {}; | ||
1633 | struct { | ||
1634 | __u32 comp_mask; | ||
1635 | __u32 response_length; | ||
1636 | } resp = {}; | ||
1637 | |||
1638 | err = ib_copy_from_udata(&req, udata, min(udata->inlen, sizeof(req))); | ||
1639 | if (err) | ||
1640 | return ERR_PTR(err); | ||
1641 | |||
1642 | if (req.comp_mask || req.reserved1 || req.reserved2) | ||
1643 | return ERR_PTR(-EOPNOTSUPP); | ||
1644 | |||
1645 | if (udata->inlen > sizeof(req) && | ||
1646 | !ib_is_udata_cleared(udata, sizeof(req), | ||
1647 | udata->inlen - sizeof(req))) | ||
1648 | return ERR_PTR(-EOPNOTSUPP); | ||
1649 | |||
1650 | ndescs = req.num_klms ? roundup(req.num_klms, 4) : roundup(1, 4); | ||
1651 | |||
1652 | mw = kzalloc(sizeof(*mw), GFP_KERNEL); | ||
1653 | in = kzalloc(sizeof(*in), GFP_KERNEL); | ||
1654 | if (!mw || !in) { | ||
1655 | err = -ENOMEM; | ||
1656 | goto free; | ||
1657 | } | ||
1658 | |||
1659 | in->seg.status = MLX5_MKEY_STATUS_FREE; | ||
1660 | in->seg.xlt_oct_size = cpu_to_be32(ndescs); | ||
1661 | in->seg.flags_pd = cpu_to_be32(to_mpd(pd)->pdn); | ||
1662 | in->seg.flags = MLX5_PERM_UMR_EN | MLX5_ACCESS_MODE_KLM | | ||
1663 | MLX5_PERM_LOCAL_READ; | ||
1664 | if (type == IB_MW_TYPE_2) | ||
1665 | in->seg.flags_pd |= cpu_to_be32(MLX5_MKEY_REMOTE_INVAL); | ||
1666 | in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8); | ||
1667 | |||
1668 | err = mlx5_core_create_mkey(dev->mdev, &mw->mmkey, in, sizeof(*in), | ||
1669 | NULL, NULL, NULL); | ||
1670 | if (err) | ||
1671 | goto free; | ||
1672 | |||
1673 | mw->ibmw.rkey = mw->mmkey.key; | ||
1674 | |||
1675 | resp.response_length = min(offsetof(typeof(resp), response_length) + | ||
1676 | sizeof(resp.response_length), udata->outlen); | ||
1677 | if (resp.response_length) { | ||
1678 | err = ib_copy_to_udata(udata, &resp, resp.response_length); | ||
1679 | if (err) { | ||
1680 | mlx5_core_destroy_mkey(dev->mdev, &mw->mmkey); | ||
1681 | goto free; | ||
1682 | } | ||
1683 | } | ||
1684 | |||
1685 | kfree(in); | ||
1686 | return &mw->ibmw; | ||
1687 | |||
1688 | free: | ||
1689 | kfree(mw); | ||
1690 | kfree(in); | ||
1691 | return ERR_PTR(err); | ||
1692 | } | ||
1693 | |||
1694 | int mlx5_ib_dealloc_mw(struct ib_mw *mw) | ||
1695 | { | ||
1696 | struct mlx5_ib_mw *mmw = to_mmw(mw); | ||
1697 | int err; | ||
1698 | |||
1699 | err = mlx5_core_destroy_mkey((to_mdev(mw->device))->mdev, | ||
1700 | &mmw->mmkey); | ||
1701 | if (!err) | ||
1702 | kfree(mmw); | ||
1703 | return err; | ||
1704 | } | ||
1705 | |||
1623 | int mlx5_ib_check_mr_status(struct ib_mr *ibmr, u32 check_mask, | 1706 | int mlx5_ib_check_mr_status(struct ib_mr *ibmr, u32 check_mask, |
1624 | struct ib_mr_status *mr_status) | 1707 | struct ib_mr_status *mr_status) |
1625 | { | 1708 | { |
diff --git a/drivers/infiniband/hw/mlx5/user.h b/drivers/infiniband/hw/mlx5/user.h index b94a55404a59..61bc308bb802 100644 --- a/drivers/infiniband/hw/mlx5/user.h +++ b/drivers/infiniband/hw/mlx5/user.h | |||
@@ -152,6 +152,13 @@ struct mlx5_ib_create_qp_resp { | |||
152 | __u32 uuar_index; | 152 | __u32 uuar_index; |
153 | }; | 153 | }; |
154 | 154 | ||
155 | struct mlx5_ib_alloc_mw { | ||
156 | __u32 comp_mask; | ||
157 | __u8 num_klms; | ||
158 | __u8 reserved1; | ||
159 | __u16 reserved2; | ||
160 | }; | ||
161 | |||
155 | static inline int get_qp_user_index(struct mlx5_ib_ucontext *ucontext, | 162 | static inline int get_qp_user_index(struct mlx5_ib_ucontext *ucontext, |
156 | struct mlx5_ib_create_qp *ucmd, | 163 | struct mlx5_ib_create_qp *ucmd, |
157 | int inlen, | 164 | int inlen, |
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 72bba5261766..3044cfa683f1 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h | |||
@@ -769,7 +769,9 @@ struct mlx5_ifc_cmd_hca_cap_bits { | |||
769 | u8 cd[0x1]; | 769 | u8 cd[0x1]; |
770 | u8 reserved_at_22c[0x1]; | 770 | u8 reserved_at_22c[0x1]; |
771 | u8 apm[0x1]; | 771 | u8 apm[0x1]; |
772 | u8 reserved_at_22e[0x7]; | 772 | u8 reserved_at_22e[0x2]; |
773 | u8 imaicl[0x1]; | ||
774 | u8 reserved_at_231[0x4]; | ||
773 | u8 qkv[0x1]; | 775 | u8 qkv[0x1]; |
774 | u8 pkv[0x1]; | 776 | u8 pkv[0x1]; |
775 | u8 set_deth_sqpn[0x1]; | 777 | u8 set_deth_sqpn[0x1]; |