Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions drivers/infiniband/core/uverbs_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,14 @@ static int uverbs_process_attr(struct bundle_priv *pbundle,

break;

case UVERBS_ATTR_TYPE_RAW_FD:
if (uattr->attr_data.reserved || uattr->len != 0 ||
uattr->data_s64 < INT_MIN || uattr->data_s64 > INT_MAX)
return -EINVAL;
/* _uverbs_get_const_signed() is the accessor */
e->ptr_attr.data = uattr->data_s64;
break;

case UVERBS_ATTR_TYPE_IDRS_ARRAY:
return uverbs_process_idrs_array(pbundle, attr_uapi,
&e->objs_arr_attr, uattr,
Expand Down
55 changes: 39 additions & 16 deletions drivers/infiniband/hw/mlx5/devx.c
Original file line number Diff line number Diff line change
Expand Up @@ -2175,32 +2175,39 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT)(

static int devx_umem_get(struct mlx5_ib_dev *dev, struct ib_ucontext *ucontext,
struct uverbs_attr_bundle *attrs,
struct devx_umem *obj)
struct devx_umem *obj, u32 access_flags)
{
u64 addr;
size_t size;
u32 access;
int err;

if (uverbs_copy_from(&addr, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR) ||
uverbs_copy_from(&size, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_LEN))
return -EFAULT;

err = uverbs_get_flags32(&access, attrs,
MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
IB_ACCESS_LOCAL_WRITE |
IB_ACCESS_REMOTE_WRITE |
IB_ACCESS_REMOTE_READ);
err = ib_check_mr_access(&dev->ib_dev, access_flags);
if (err)
return err;

err = ib_check_mr_access(&dev->ib_dev, access);
if (err)
return err;
if (uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_DMABUF_FD)) {
struct ib_umem_dmabuf *umem_dmabuf;
int dmabuf_fd;

err = uverbs_get_raw_fd(&dmabuf_fd, attrs,
MLX5_IB_ATTR_DEVX_UMEM_REG_DMABUF_FD);
if (err)
return -EFAULT;

obj->umem = ib_umem_get_peer(&dev->ib_dev, addr, size, access, 0);
if (IS_ERR(obj->umem))
return PTR_ERR(obj->umem);
umem_dmabuf = ib_umem_dmabuf_get_pinned(
&dev->ib_dev, addr, size, dmabuf_fd, access_flags);
if (IS_ERR(umem_dmabuf))
return PTR_ERR(umem_dmabuf);
obj->umem = &umem_dmabuf->umem;
} else {
obj->umem = ib_umem_get(&dev->ib_dev, addr, size, access_flags);
if (IS_ERR(obj->umem))
return PTR_ERR(obj->umem);
}
return 0;
}

Expand Down Expand Up @@ -2239,7 +2246,8 @@ static unsigned int devx_umem_find_best_pgsize(struct ib_umem *umem,
static int devx_umem_reg_cmd_alloc(struct mlx5_ib_dev *dev,
struct uverbs_attr_bundle *attrs,
struct devx_umem *obj,
struct devx_umem_reg_cmd *cmd)
struct devx_umem_reg_cmd *cmd,
int access)
{
unsigned long pgsz_bitmap;
unsigned int page_size;
Expand Down Expand Up @@ -2290,6 +2298,9 @@ static int devx_umem_reg_cmd_alloc(struct mlx5_ib_dev *dev,
if (obj->umem->is_peer)
MLX5_SET(umem, umem, ats, MLX5_CAP_GEN(dev->mdev, ats));

if (mlx5_umem_needs_ats(dev, obj->umem, access))
MLX5_SET(umem, umem, ats, 1);

mlx5_ib_populate_pas(obj->umem, page_size, mtt,
(obj->umem->writable ? MLX5_IB_MTT_WRITE : 0) |
MLX5_IB_MTT_READ);
Expand All @@ -2307,20 +2318,30 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_UMEM_REG)(
struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
int access_flags;
int err;

if (!c->devx_uid)
return -EINVAL;

err = uverbs_get_flags32(&access_flags, attrs,
MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
IB_ACCESS_LOCAL_WRITE |
IB_ACCESS_REMOTE_WRITE |
IB_ACCESS_REMOTE_READ |
IB_ACCESS_RELAXED_ORDERING);
if (err)
return err;

obj = kzalloc(sizeof(struct devx_umem), GFP_KERNEL);
if (!obj)
return -ENOMEM;

err = devx_umem_get(dev, &c->ibucontext, attrs, obj);
err = devx_umem_get(dev, &c->ibucontext, attrs, obj, access_flags);
if (err)
goto err_obj_free;

err = devx_umem_reg_cmd_alloc(dev, attrs, obj, &cmd);
err = devx_umem_reg_cmd_alloc(dev, attrs, obj, &cmd, access_flags);
if (err)
goto err_umem_release;

Expand Down Expand Up @@ -2852,6 +2873,8 @@ DECLARE_UVERBS_NAMED_METHOD(
UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_LEN,
UVERBS_ATTR_TYPE(u64),
UA_MANDATORY),
UVERBS_ATTR_RAW_FD(MLX5_IB_ATTR_DEVX_UMEM_REG_DMABUF_FD,
UA_OPTIONAL),
UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
enum ib_access_flags),
UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_PGSZ_BITMAP,
Expand Down
36 changes: 36 additions & 0 deletions drivers/infiniband/hw/mlx5/mlx5_ib.h
Original file line number Diff line number Diff line change
Expand Up @@ -1615,4 +1615,40 @@ static inline bool rt_supported(int ts_cap)
return ts_cap == MLX5_TIMESTAMP_FORMAT_CAP_REAL_TIME ||
ts_cap == MLX5_TIMESTAMP_FORMAT_CAP_FREE_RUNNING_AND_REAL_TIME;
}

/*
* PCI Peer to Peer is a trainwreck. If no switch is present then things
* sometimes work, depending on the pci_distance_p2p logic for excluding broken
* root complexes. However if a switch is present in the path, then things get
* really ugly depending on how the switch is setup. This table assumes that the
* root complex is strict and is validating that all req/reps are matches
* perfectly - so any scenario where it sees only half the transaction is a
* failure.
*
* CR/RR/DT ATS RO P2P
* 00X X X OK
* 010 X X fails (request is routed to root but root never sees comp)
* 011 0 X fails (request is routed to root but root never sees comp)
* 011 1 X OK
* 10X X 1 OK
* 101 X 0 fails (completion is routed to root but root didn't see req)
* 110 X 0 SLOW
* 111 0 0 SLOW
* 111 1 0 fails (completion is routed to root but root didn't see req)
* 111 1 1 OK
*
* Unfortunately we cannot reliably know if a switch is present or what the
* CR/RR/DT ACS settings are, as in a VM that is all hidden. Assume that
* CR/RR/DT is 111 if the ATS cap is enabled and follow the last three rows.
*
* For now assume if the umem is a dma_buf then it is P2P.
*/
static inline bool mlx5_umem_needs_ats(struct mlx5_ib_dev *dev,
struct ib_umem *umem, int access_flags)
{
if (!MLX5_CAP_GEN(dev->mdev, ats) || !umem->is_dmabuf)
return false;
return access_flags & IB_ACCESS_RELAXED_ORDERING;
}

#endif /* MLX5_IB_H */
6 changes: 5 additions & 1 deletion drivers/infiniband/hw/mlx5/mr.c
Original file line number Diff line number Diff line change
Expand Up @@ -960,7 +960,8 @@ static struct mlx5_ib_mr *alloc_cacheable_mr(struct ib_pd *pd,
* cache then synchronously create an uncached one.
*/
if (!ent || ent->limit == 0 ||
!mlx5_ib_can_reconfig_with_umr(dev, 0, access_flags)) {
!mlx5_ib_can_reconfig_with_umr(dev, 0, access_flags) ||
mlx5_umem_needs_ats(dev, umem, access_flags)) {
mutex_lock(&dev->slow_path_mutex);
mr = reg_create(pd, umem, iova, access_flags, page_size, false);
mutex_unlock(&dev->slow_path_mutex);
Expand Down Expand Up @@ -1334,6 +1335,9 @@ static struct mlx5_ib_mr *reg_create(struct ib_pd *pd, struct ib_umem *umem,
MLX5_SET(mkc, mkc, translations_octword_size,
get_octo_len(iova, umem->length, mr->page_shift));
MLX5_SET(mkc, mkc, log_page_size, mr->page_shift);
if (mlx5_umem_needs_ats(dev, umem, access_flags))
MLX5_SET(mkc, mkc, ma_translation_mode, 1);

if (umem->is_peer)
MLX5_SET(mkc, mkc, ma_translation_mode,
MLX5_CAP_GEN(dev->mdev, ats));
Expand Down
13 changes: 13 additions & 0 deletions include/rdma/uverbs_ioctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ enum uverbs_attr_type {
UVERBS_ATTR_TYPE_PTR_OUT,
UVERBS_ATTR_TYPE_IDR,
UVERBS_ATTR_TYPE_FD,
UVERBS_ATTR_TYPE_RAW_FD,
UVERBS_ATTR_TYPE_ENUM_IN,
UVERBS_ATTR_TYPE_IDRS_ARRAY,
};
Expand Down Expand Up @@ -521,6 +522,11 @@ struct uapi_definition {
.u.obj.access = _access, \
__VA_ARGS__ } })

#define UVERBS_ATTR_RAW_FD(_attr_id, ...) \
(&(const struct uverbs_attr_def){ \
.id = (_attr_id), \
.attr = { .type = UVERBS_ATTR_TYPE_RAW_FD, __VA_ARGS__ } })

#define UVERBS_ATTR_PTR_IN(_attr_id, _type, ...) \
(&(const struct uverbs_attr_def){ \
.id = _attr_id, \
Expand Down Expand Up @@ -999,4 +1005,11 @@ _uverbs_get_const_unsigned(u64 *to,
uverbs_get_const_default_unsigned(_to, _attrs_bundle, _idx, \
_default))

static inline int
uverbs_get_raw_fd(int *to, const struct uverbs_attr_bundle *attrs_bundle,
size_t idx)
{
return uverbs_get_const_signed(to, attrs_bundle, idx);
}

#endif
1 change: 1 addition & 0 deletions include/uapi/rdma/mlx5_user_ioctl_cmds.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ enum mlx5_ib_devx_umem_reg_attrs {
MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID,
MLX5_IB_ATTR_DEVX_UMEM_REG_PGSZ_BITMAP,
MLX5_IB_ATTR_DEVX_UMEM_REG_DMABUF_FD,
};

enum mlx5_ib_devx_umem_dereg_attrs {
Expand Down