1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 /* 3 * Copyright (c) 2020, Mellanox Technologies inc. All rights reserved. 4 */ 5 6 #include <rdma/uverbs_ioctl.h> 7 #include <rdma/mlx5_user_ioctl_cmds.h> 8 #include <rdma/mlx5_user_ioctl_verbs.h> 9 #include <linux/mlx5/driver.h> 10 #include "mlx5_ib.h" 11 12 #define UVERBS_MODULE_NAME mlx5_ib 13 #include <rdma/uverbs_named_ioctl.h> 14 15 static bool pp_is_supported(struct ib_device *device) 16 { 17 struct mlx5_ib_dev *dev = to_mdev(device); 18 19 return (MLX5_CAP_GEN(dev->mdev, qos) && 20 MLX5_CAP_QOS(dev->mdev, packet_pacing) && 21 MLX5_CAP_QOS(dev->mdev, packet_pacing_uid)); 22 } 23 24 static int UVERBS_HANDLER(MLX5_IB_METHOD_PP_OBJ_ALLOC)( 25 struct uverbs_attr_bundle *attrs) 26 { 27 u8 rl_raw[MLX5_ST_SZ_BYTES(set_pp_rate_limit_context)] = {}; 28 struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs, 29 MLX5_IB_ATTR_PP_OBJ_ALLOC_HANDLE); 30 struct mlx5_ib_dev *dev; 31 struct mlx5_ib_ucontext *c; 32 struct mlx5_ib_pp *pp_entry; 33 void *in_ctx; 34 u16 uid; 35 int inlen; 36 u32 flags; 37 int err; 38 39 c = to_mucontext(ib_uverbs_get_ucontext(attrs)); 40 if (IS_ERR(c)) 41 return PTR_ERR(c); 42 43 /* The allocated entry can be used only by a DEVX context */ 44 if (!c->devx_uid) 45 return -EINVAL; 46 47 dev = to_mdev(c->ibucontext.device); 48 pp_entry = kzalloc(sizeof(*pp_entry), GFP_KERNEL); 49 if (!pp_entry) 50 return -ENOMEM; 51 52 in_ctx = uverbs_attr_get_alloced_ptr(attrs, 53 MLX5_IB_ATTR_PP_OBJ_ALLOC_CTX); 54 inlen = uverbs_attr_get_len(attrs, 55 MLX5_IB_ATTR_PP_OBJ_ALLOC_CTX); 56 memcpy(rl_raw, in_ctx, inlen); 57 err = uverbs_get_flags32(&flags, attrs, 58 MLX5_IB_ATTR_PP_OBJ_ALLOC_FLAGS, 59 MLX5_IB_UAPI_PP_ALLOC_FLAGS_DEDICATED_INDEX); 60 if (err) 61 goto err; 62 63 uid = (flags & MLX5_IB_UAPI_PP_ALLOC_FLAGS_DEDICATED_INDEX) ? 64 c->devx_uid : MLX5_SHARED_RESOURCE_UID; 65 66 err = mlx5_rl_add_rate_raw(dev->mdev, rl_raw, uid, 67 (flags & MLX5_IB_UAPI_PP_ALLOC_FLAGS_DEDICATED_INDEX), 68 &pp_entry->index); 69 if (err) 70 goto err; 71 72 err = uverbs_copy_to(attrs, MLX5_IB_ATTR_PP_OBJ_ALLOC_INDEX, 73 &pp_entry->index, sizeof(pp_entry->index)); 74 if (err) 75 goto clean; 76 77 pp_entry->mdev = dev->mdev; 78 uobj->object = pp_entry; 79 return 0; 80 81 clean: 82 mlx5_rl_remove_rate_raw(dev->mdev, pp_entry->index); 83 err: 84 kfree(pp_entry); 85 return err; 86 } 87 88 static int pp_obj_cleanup(struct ib_uobject *uobject, 89 enum rdma_remove_reason why, 90 struct uverbs_attr_bundle *attrs) 91 { 92 struct mlx5_ib_pp *pp_entry = uobject->object; 93 94 mlx5_rl_remove_rate_raw(pp_entry->mdev, pp_entry->index); 95 kfree(pp_entry); 96 return 0; 97 } 98 99 DECLARE_UVERBS_NAMED_METHOD( 100 MLX5_IB_METHOD_PP_OBJ_ALLOC, 101 UVERBS_ATTR_IDR(MLX5_IB_ATTR_PP_OBJ_ALLOC_HANDLE, 102 MLX5_IB_OBJECT_PP, 103 UVERBS_ACCESS_NEW, 104 UA_MANDATORY), 105 UVERBS_ATTR_PTR_IN( 106 MLX5_IB_ATTR_PP_OBJ_ALLOC_CTX, 107 UVERBS_ATTR_SIZE(1, 108 MLX5_ST_SZ_BYTES(set_pp_rate_limit_context)), 109 UA_MANDATORY, 110 UA_ALLOC_AND_COPY), 111 UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_PP_OBJ_ALLOC_FLAGS, 112 enum mlx5_ib_uapi_pp_alloc_flags, 113 UA_MANDATORY), 114 UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_PP_OBJ_ALLOC_INDEX, 115 UVERBS_ATTR_TYPE(u16), 116 UA_MANDATORY)); 117 118 DECLARE_UVERBS_NAMED_METHOD_DESTROY( 119 MLX5_IB_METHOD_PP_OBJ_DESTROY, 120 UVERBS_ATTR_IDR(MLX5_IB_ATTR_PP_OBJ_DESTROY_HANDLE, 121 MLX5_IB_OBJECT_PP, 122 UVERBS_ACCESS_DESTROY, 123 UA_MANDATORY)); 124 125 DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_PP, 126 UVERBS_TYPE_ALLOC_IDR(pp_obj_cleanup), 127 &UVERBS_METHOD(MLX5_IB_METHOD_PP_OBJ_ALLOC), 128 &UVERBS_METHOD(MLX5_IB_METHOD_PP_OBJ_DESTROY)); 129 130 131 const struct uapi_definition mlx5_ib_qos_defs[] = { 132 UAPI_DEF_CHAIN_OBJ_TREE_NAMED( 133 MLX5_IB_OBJECT_PP, 134 UAPI_DEF_IS_OBJ_SUPPORTED(pp_is_supported)), 135 {}, 136 }; 137