130f2fe40SYishai Hadas // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
230f2fe40SYishai Hadas /*
330f2fe40SYishai Hadas * Copyright (c) 2020, Mellanox Technologies inc. All rights reserved.
430f2fe40SYishai Hadas */
530f2fe40SYishai Hadas
630f2fe40SYishai Hadas #include <rdma/uverbs_ioctl.h>
730f2fe40SYishai Hadas #include <rdma/mlx5_user_ioctl_cmds.h>
830f2fe40SYishai Hadas #include <rdma/mlx5_user_ioctl_verbs.h>
930f2fe40SYishai Hadas #include <linux/mlx5/driver.h>
1030f2fe40SYishai Hadas #include "mlx5_ib.h"
1130f2fe40SYishai Hadas
1230f2fe40SYishai Hadas #define UVERBS_MODULE_NAME mlx5_ib
1330f2fe40SYishai Hadas #include <rdma/uverbs_named_ioctl.h>
1430f2fe40SYishai Hadas
pp_is_supported(struct ib_device * device)1530f2fe40SYishai Hadas static bool pp_is_supported(struct ib_device *device)
1630f2fe40SYishai Hadas {
1730f2fe40SYishai Hadas struct mlx5_ib_dev *dev = to_mdev(device);
1830f2fe40SYishai Hadas
1930f2fe40SYishai Hadas return (MLX5_CAP_GEN(dev->mdev, qos) &&
2030f2fe40SYishai Hadas MLX5_CAP_QOS(dev->mdev, packet_pacing) &&
2130f2fe40SYishai Hadas MLX5_CAP_QOS(dev->mdev, packet_pacing_uid));
2230f2fe40SYishai Hadas }
2330f2fe40SYishai Hadas
UVERBS_HANDLER(MLX5_IB_METHOD_PP_OBJ_ALLOC)2430f2fe40SYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_PP_OBJ_ALLOC)(
2530f2fe40SYishai Hadas struct uverbs_attr_bundle *attrs)
2630f2fe40SYishai Hadas {
2730f2fe40SYishai Hadas u8 rl_raw[MLX5_ST_SZ_BYTES(set_pp_rate_limit_context)] = {};
2830f2fe40SYishai Hadas struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
2930f2fe40SYishai Hadas MLX5_IB_ATTR_PP_OBJ_ALLOC_HANDLE);
3030f2fe40SYishai Hadas struct mlx5_ib_dev *dev;
3130f2fe40SYishai Hadas struct mlx5_ib_ucontext *c;
3230f2fe40SYishai Hadas struct mlx5_ib_pp *pp_entry;
3330f2fe40SYishai Hadas void *in_ctx;
3430f2fe40SYishai Hadas u16 uid;
3530f2fe40SYishai Hadas int inlen;
3630f2fe40SYishai Hadas u32 flags;
3730f2fe40SYishai Hadas int err;
3830f2fe40SYishai Hadas
3930f2fe40SYishai Hadas c = to_mucontext(ib_uverbs_get_ucontext(attrs));
4030f2fe40SYishai Hadas if (IS_ERR(c))
4130f2fe40SYishai Hadas return PTR_ERR(c);
4230f2fe40SYishai Hadas
4330f2fe40SYishai Hadas /* The allocated entry can be used only by a DEVX context */
4430f2fe40SYishai Hadas if (!c->devx_uid)
4530f2fe40SYishai Hadas return -EINVAL;
4630f2fe40SYishai Hadas
4730f2fe40SYishai Hadas dev = to_mdev(c->ibucontext.device);
4830f2fe40SYishai Hadas pp_entry = kzalloc(sizeof(*pp_entry), GFP_KERNEL);
49a766fa84SDan Carpenter if (!pp_entry)
50a766fa84SDan Carpenter return -ENOMEM;
5130f2fe40SYishai Hadas
5230f2fe40SYishai Hadas in_ctx = uverbs_attr_get_alloced_ptr(attrs,
5330f2fe40SYishai Hadas MLX5_IB_ATTR_PP_OBJ_ALLOC_CTX);
5430f2fe40SYishai Hadas inlen = uverbs_attr_get_len(attrs,
5530f2fe40SYishai Hadas MLX5_IB_ATTR_PP_OBJ_ALLOC_CTX);
5630f2fe40SYishai Hadas memcpy(rl_raw, in_ctx, inlen);
5730f2fe40SYishai Hadas err = uverbs_get_flags32(&flags, attrs,
5830f2fe40SYishai Hadas MLX5_IB_ATTR_PP_OBJ_ALLOC_FLAGS,
5930f2fe40SYishai Hadas MLX5_IB_UAPI_PP_ALLOC_FLAGS_DEDICATED_INDEX);
6030f2fe40SYishai Hadas if (err)
6130f2fe40SYishai Hadas goto err;
6230f2fe40SYishai Hadas
6330f2fe40SYishai Hadas uid = (flags & MLX5_IB_UAPI_PP_ALLOC_FLAGS_DEDICATED_INDEX) ?
6430f2fe40SYishai Hadas c->devx_uid : MLX5_SHARED_RESOURCE_UID;
6530f2fe40SYishai Hadas
6630f2fe40SYishai Hadas err = mlx5_rl_add_rate_raw(dev->mdev, rl_raw, uid,
6730f2fe40SYishai Hadas (flags & MLX5_IB_UAPI_PP_ALLOC_FLAGS_DEDICATED_INDEX),
6830f2fe40SYishai Hadas &pp_entry->index);
6930f2fe40SYishai Hadas if (err)
7030f2fe40SYishai Hadas goto err;
7130f2fe40SYishai Hadas
7230f2fe40SYishai Hadas pp_entry->mdev = dev->mdev;
7330f2fe40SYishai Hadas uobj->object = pp_entry;
74*0ac8903cSJason Gunthorpe uverbs_finalize_uobj_create(attrs, MLX5_IB_ATTR_PP_OBJ_ALLOC_HANDLE);
7530f2fe40SYishai Hadas
76*0ac8903cSJason Gunthorpe err = uverbs_copy_to(attrs, MLX5_IB_ATTR_PP_OBJ_ALLOC_INDEX,
77*0ac8903cSJason Gunthorpe &pp_entry->index, sizeof(pp_entry->index));
78*0ac8903cSJason Gunthorpe return err;
79*0ac8903cSJason Gunthorpe
8030f2fe40SYishai Hadas err:
8130f2fe40SYishai Hadas kfree(pp_entry);
8230f2fe40SYishai Hadas return err;
8330f2fe40SYishai Hadas }
8430f2fe40SYishai Hadas
pp_obj_cleanup(struct ib_uobject * uobject,enum rdma_remove_reason why,struct uverbs_attr_bundle * attrs)8530f2fe40SYishai Hadas static int pp_obj_cleanup(struct ib_uobject *uobject,
8630f2fe40SYishai Hadas enum rdma_remove_reason why,
8730f2fe40SYishai Hadas struct uverbs_attr_bundle *attrs)
8830f2fe40SYishai Hadas {
8930f2fe40SYishai Hadas struct mlx5_ib_pp *pp_entry = uobject->object;
9030f2fe40SYishai Hadas
9130f2fe40SYishai Hadas mlx5_rl_remove_rate_raw(pp_entry->mdev, pp_entry->index);
9230f2fe40SYishai Hadas kfree(pp_entry);
9330f2fe40SYishai Hadas return 0;
9430f2fe40SYishai Hadas }
9530f2fe40SYishai Hadas
9630f2fe40SYishai Hadas DECLARE_UVERBS_NAMED_METHOD(
9730f2fe40SYishai Hadas MLX5_IB_METHOD_PP_OBJ_ALLOC,
9830f2fe40SYishai Hadas UVERBS_ATTR_IDR(MLX5_IB_ATTR_PP_OBJ_ALLOC_HANDLE,
9930f2fe40SYishai Hadas MLX5_IB_OBJECT_PP,
10030f2fe40SYishai Hadas UVERBS_ACCESS_NEW,
10130f2fe40SYishai Hadas UA_MANDATORY),
10230f2fe40SYishai Hadas UVERBS_ATTR_PTR_IN(
10330f2fe40SYishai Hadas MLX5_IB_ATTR_PP_OBJ_ALLOC_CTX,
10430f2fe40SYishai Hadas UVERBS_ATTR_SIZE(1,
10530f2fe40SYishai Hadas MLX5_ST_SZ_BYTES(set_pp_rate_limit_context)),
10630f2fe40SYishai Hadas UA_MANDATORY,
10730f2fe40SYishai Hadas UA_ALLOC_AND_COPY),
10830f2fe40SYishai Hadas UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_PP_OBJ_ALLOC_FLAGS,
10930f2fe40SYishai Hadas enum mlx5_ib_uapi_pp_alloc_flags,
11030f2fe40SYishai Hadas UA_MANDATORY),
11130f2fe40SYishai Hadas UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_PP_OBJ_ALLOC_INDEX,
11230f2fe40SYishai Hadas UVERBS_ATTR_TYPE(u16),
11330f2fe40SYishai Hadas UA_MANDATORY));
11430f2fe40SYishai Hadas
11530f2fe40SYishai Hadas DECLARE_UVERBS_NAMED_METHOD_DESTROY(
11630f2fe40SYishai Hadas MLX5_IB_METHOD_PP_OBJ_DESTROY,
11730f2fe40SYishai Hadas UVERBS_ATTR_IDR(MLX5_IB_ATTR_PP_OBJ_DESTROY_HANDLE,
11830f2fe40SYishai Hadas MLX5_IB_OBJECT_PP,
11930f2fe40SYishai Hadas UVERBS_ACCESS_DESTROY,
12030f2fe40SYishai Hadas UA_MANDATORY));
12130f2fe40SYishai Hadas
12230f2fe40SYishai Hadas DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_PP,
12330f2fe40SYishai Hadas UVERBS_TYPE_ALLOC_IDR(pp_obj_cleanup),
12430f2fe40SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_PP_OBJ_ALLOC),
12530f2fe40SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_PP_OBJ_DESTROY));
12630f2fe40SYishai Hadas
12730f2fe40SYishai Hadas
12830f2fe40SYishai Hadas const struct uapi_definition mlx5_ib_qos_defs[] = {
12930f2fe40SYishai Hadas UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
13030f2fe40SYishai Hadas MLX5_IB_OBJECT_PP,
13130f2fe40SYishai Hadas UAPI_DEF_IS_OBJ_SUPPORTED(pp_is_supported)),
13230f2fe40SYishai Hadas {},
13330f2fe40SYishai Hadas };
134