aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatan Barak <matanb@mellanox.com>2016-02-29 11:05:30 -0500
committerDoug Ledford <dledford@redhat.com>2016-03-01 11:18:54 -0500
commitd2370e0a573e5c5ea9c96373558727abb3ea71f7 (patch)
tree11e770e07728416ed1a26eb102b2274243b2697a
parentb2a239df4e65fe35240ddf3e5f9f31335c90589b (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.c13
-rw-r--r--drivers/infiniband/hw/mlx5/mlx5_ib.h14
-rw-r--r--drivers/infiniband/hw/mlx5/mr.c83
-rw-r--r--drivers/infiniband/hw/mlx5/user.h7
-rw-r--r--include/linux/mlx5/mlx5_ifc.h4
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...) \
48pr_debug("%s:%s:%d:(pid %d): " format, (dev)->ib_dev.name, __func__, \ 49pr_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
465struct mlx5_ib_mw {
466 struct ib_mw ibmw;
467 struct mlx5_core_mkey mmkey;
468};
469
464struct mlx5_ib_umr_context { 470struct 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
642static inline struct mlx5_ib_mw *to_mmw(struct ib_mw *ibmw)
643{
644 return container_of(ibmw, struct mlx5_ib_mw, ibmw);
645}
646
636struct mlx5_ib_ah { 647struct 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);
693struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, 704struct 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);
707struct ib_mw *mlx5_ib_alloc_mw(struct ib_pd *pd, enum ib_mw_type type,
708 struct ib_udata *udata);
709int mlx5_ib_dealloc_mw(struct ib_mw *mw);
696int mlx5_ib_update_mtt(struct mlx5_ib_mr *mr, u64 start_page_index, 710int mlx5_ib_update_mtt(struct mlx5_ib_mr *mr, u64 start_page_index,
697 int npages, int zap); 711 int npages, int zap);
698int mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start, 712int 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
44enum { 45enum {
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
1624struct 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
1688free:
1689 kfree(mw);
1690 kfree(in);
1691 return ERR_PTR(err);
1692}
1693
1694int 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
1623int mlx5_ib_check_mr_status(struct ib_mr *ibmr, u32 check_mask, 1706int 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
155struct mlx5_ib_alloc_mw {
156 __u32 comp_mask;
157 __u8 num_klms;
158 __u8 reserved1;
159 __u16 reserved2;
160};
161
155static inline int get_qp_user_index(struct mlx5_ib_ucontext *ucontext, 162static 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];