1a8b92ca1SYishai Hadas // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2a8b92ca1SYishai Hadas /* 3a8b92ca1SYishai Hadas * Copyright (c) 2018, Mellanox Technologies inc. All rights reserved. 4a8b92ca1SYishai Hadas */ 5a8b92ca1SYishai Hadas 6a8b92ca1SYishai Hadas #include <rdma/ib_user_verbs.h> 7a8b92ca1SYishai Hadas #include <rdma/ib_verbs.h> 8a8b92ca1SYishai Hadas #include <rdma/uverbs_types.h> 9a8b92ca1SYishai Hadas #include <rdma/uverbs_ioctl.h> 10a8b92ca1SYishai Hadas #include <rdma/mlx5_user_ioctl_cmds.h> 11a124edbaSYishai Hadas #include <rdma/mlx5_user_ioctl_verbs.h> 12a8b92ca1SYishai Hadas #include <rdma/ib_umem.h> 1334613eb1SYishai Hadas #include <rdma/uverbs_std_types.h> 14a8b92ca1SYishai Hadas #include <linux/mlx5/driver.h> 15a8b92ca1SYishai Hadas #include <linux/mlx5/fs.h> 16a8b92ca1SYishai Hadas #include "mlx5_ib.h" 17*75973853SYishai Hadas #include <linux/xarray.h> 18a8b92ca1SYishai Hadas 198aa8c95cSYishai Hadas #define UVERBS_MODULE_NAME mlx5_ib 208aa8c95cSYishai Hadas #include <rdma/uverbs_named_ioctl.h> 218aa8c95cSYishai Hadas 22534fd7aaSYishai Hadas enum devx_obj_flags { 23534fd7aaSYishai Hadas DEVX_OBJ_FLAGS_INDIRECT_MKEY = 1 << 0, 24c5ae1954SYishai Hadas DEVX_OBJ_FLAGS_DCT = 1 << 1, 25534fd7aaSYishai Hadas }; 26534fd7aaSYishai Hadas 27a124edbaSYishai Hadas struct devx_async_data { 28a124edbaSYishai Hadas struct mlx5_ib_dev *mdev; 29a124edbaSYishai Hadas struct list_head list; 30a124edbaSYishai Hadas struct ib_uobject *fd_uobj; 31a124edbaSYishai Hadas struct mlx5_async_work cb_work; 32a124edbaSYishai Hadas u16 cmd_out_len; 33a124edbaSYishai Hadas /* must be last field in this structure */ 34a124edbaSYishai Hadas struct mlx5_ib_uapi_devx_async_cmd_hdr hdr; 35a124edbaSYishai Hadas }; 36a124edbaSYishai Hadas 37*75973853SYishai Hadas /* first level XA value data structure */ 38*75973853SYishai Hadas struct devx_event { 39*75973853SYishai Hadas struct xarray object_ids; /* second XA level, Key = object id */ 40*75973853SYishai Hadas struct list_head unaffiliated_list; 41*75973853SYishai Hadas }; 42*75973853SYishai Hadas 43*75973853SYishai Hadas /* second level XA value data structure */ 44*75973853SYishai Hadas struct devx_obj_event { 45*75973853SYishai Hadas struct rcu_head rcu; 46*75973853SYishai Hadas struct list_head obj_sub_list; 47*75973853SYishai Hadas }; 48*75973853SYishai Hadas 49*75973853SYishai Hadas struct devx_event_subscription { 50*75973853SYishai Hadas struct list_head file_list; /* headed in ev_file-> 51*75973853SYishai Hadas * subscribed_events_list 52*75973853SYishai Hadas */ 53*75973853SYishai Hadas struct list_head xa_list; /* headed in devx_event->unaffiliated_list or 54*75973853SYishai Hadas * devx_obj_event->obj_sub_list 55*75973853SYishai Hadas */ 56*75973853SYishai Hadas struct list_head obj_list; /* headed in devx_object */ 57*75973853SYishai Hadas struct list_head event_list; /* headed in ev_file->event_list or in 58*75973853SYishai Hadas * temp list via subscription 59*75973853SYishai Hadas */ 60*75973853SYishai Hadas 61*75973853SYishai Hadas u8 is_cleaned:1; 62*75973853SYishai Hadas u32 xa_key_level1; 63*75973853SYishai Hadas u32 xa_key_level2; 64*75973853SYishai Hadas struct rcu_head rcu; 65*75973853SYishai Hadas u64 cookie; 66*75973853SYishai Hadas struct devx_async_event_file *ev_file; 67*75973853SYishai Hadas struct file *filp; /* Upon hot unplug we need a direct access to */ 68*75973853SYishai Hadas struct eventfd_ctx *eventfd; 69*75973853SYishai Hadas }; 70*75973853SYishai Hadas 712afc5e1bSYishai Hadas struct devx_async_event_file { 722afc5e1bSYishai Hadas struct ib_uobject uobj; 732afc5e1bSYishai Hadas /* Head of events that are subscribed to this FD */ 742afc5e1bSYishai Hadas struct list_head subscribed_events_list; 752afc5e1bSYishai Hadas spinlock_t lock; 762afc5e1bSYishai Hadas wait_queue_head_t poll_wait; 772afc5e1bSYishai Hadas struct list_head event_list; 782afc5e1bSYishai Hadas struct mlx5_ib_dev *dev; 792afc5e1bSYishai Hadas u8 omit_data:1; 802afc5e1bSYishai Hadas }; 812afc5e1bSYishai Hadas 827efce369SYishai Hadas #define MLX5_MAX_DESTROY_INBOX_SIZE_DW MLX5_ST_SZ_DW(delete_fte_in) 837efce369SYishai Hadas struct devx_obj { 847efce369SYishai Hadas struct mlx5_core_dev *mdev; 852351776eSYishai Hadas u64 obj_id; 867efce369SYishai Hadas u32 dinlen; /* destroy inbox length */ 877efce369SYishai Hadas u32 dinbox[MLX5_MAX_DESTROY_INBOX_SIZE_DW]; 88534fd7aaSYishai Hadas u32 flags; 89c5ae1954SYishai Hadas union { 90534fd7aaSYishai Hadas struct mlx5_ib_devx_mr devx_mr; 91c5ae1954SYishai Hadas struct mlx5_core_dct core_dct; 92c5ae1954SYishai Hadas }; 93*75973853SYishai Hadas struct list_head event_sub; /* holds devx_event_subscription entries */ 947efce369SYishai Hadas }; 957efce369SYishai Hadas 96aeae9457SYishai Hadas struct devx_umem { 97aeae9457SYishai Hadas struct mlx5_core_dev *mdev; 98aeae9457SYishai Hadas struct ib_umem *umem; 99aeae9457SYishai Hadas u32 page_offset; 100aeae9457SYishai Hadas int page_shift; 101aeae9457SYishai Hadas int ncont; 102aeae9457SYishai Hadas u32 dinlen; 103aeae9457SYishai Hadas u32 dinbox[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)]; 104aeae9457SYishai Hadas }; 105aeae9457SYishai Hadas 106aeae9457SYishai Hadas struct devx_umem_reg_cmd { 107aeae9457SYishai Hadas void *in; 108aeae9457SYishai Hadas u32 inlen; 109aeae9457SYishai Hadas u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)]; 110aeae9457SYishai Hadas }; 111aeae9457SYishai Hadas 11215a1b4beSJason Gunthorpe static struct mlx5_ib_ucontext * 11315a1b4beSJason Gunthorpe devx_ufile2uctx(const struct uverbs_attr_bundle *attrs) 1148aa8c95cSYishai Hadas { 11515a1b4beSJason Gunthorpe return to_mucontext(ib_uverbs_get_ucontext(attrs)); 1168aa8c95cSYishai Hadas } 1178aa8c95cSYishai Hadas 118fb98153bSYishai Hadas int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, bool is_user) 119a8b92ca1SYishai Hadas { 120a8b92ca1SYishai Hadas u32 in[MLX5_ST_SZ_DW(create_uctx_in)] = {0}; 121a8b92ca1SYishai Hadas u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0}; 1226e3722baSYishai Hadas void *uctx; 123a8b92ca1SYishai Hadas int err; 12476dc5a84SYishai Hadas u16 uid; 125fb98153bSYishai Hadas u32 cap = 0; 126a8b92ca1SYishai Hadas 1276e3722baSYishai Hadas /* 0 means not supported */ 1286e3722baSYishai Hadas if (!MLX5_CAP_GEN(dev->mdev, log_max_uctx)) 129a8b92ca1SYishai Hadas return -EINVAL; 130a8b92ca1SYishai Hadas 1316e3722baSYishai Hadas uctx = MLX5_ADDR_OF(create_uctx_in, in, uctx); 132fb98153bSYishai Hadas if (is_user && capable(CAP_NET_RAW) && 133fb98153bSYishai Hadas (MLX5_CAP_GEN(dev->mdev, uctx_cap) & MLX5_UCTX_CAP_RAW_TX)) 134fb98153bSYishai Hadas cap |= MLX5_UCTX_CAP_RAW_TX; 13533cde96fSAriel Levkovich if (is_user && capable(CAP_SYS_RAWIO) && 13633cde96fSAriel Levkovich (MLX5_CAP_GEN(dev->mdev, uctx_cap) & 13733cde96fSAriel Levkovich MLX5_UCTX_CAP_INTERNAL_DEV_RES)) 13833cde96fSAriel Levkovich cap |= MLX5_UCTX_CAP_INTERNAL_DEV_RES; 139fb98153bSYishai Hadas 1406e3722baSYishai Hadas MLX5_SET(create_uctx_in, in, opcode, MLX5_CMD_OP_CREATE_UCTX); 141fb98153bSYishai Hadas MLX5_SET(uctx, uctx, cap, cap); 142a8b92ca1SYishai Hadas 143a8b92ca1SYishai Hadas err = mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out)); 144a8b92ca1SYishai Hadas if (err) 145a8b92ca1SYishai Hadas return err; 146a8b92ca1SYishai Hadas 14776dc5a84SYishai Hadas uid = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 14876dc5a84SYishai Hadas return uid; 149a8b92ca1SYishai Hadas } 150a8b92ca1SYishai Hadas 15176dc5a84SYishai Hadas void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev, u16 uid) 152a8b92ca1SYishai Hadas { 1536e3722baSYishai Hadas u32 in[MLX5_ST_SZ_DW(destroy_uctx_in)] = {0}; 154a8b92ca1SYishai Hadas u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0}; 155a8b92ca1SYishai Hadas 1566e3722baSYishai Hadas MLX5_SET(destroy_uctx_in, in, opcode, MLX5_CMD_OP_DESTROY_UCTX); 1576e3722baSYishai Hadas MLX5_SET(destroy_uctx_in, in, uid, uid); 158a8b92ca1SYishai Hadas 159a8b92ca1SYishai Hadas mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out)); 160a8b92ca1SYishai Hadas } 1618aa8c95cSYishai Hadas 16232269441SYishai Hadas bool mlx5_ib_devx_is_flow_dest(void *obj, int *dest_id, int *dest_type) 16332269441SYishai Hadas { 16432269441SYishai Hadas struct devx_obj *devx_obj = obj; 16532269441SYishai Hadas u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, opcode); 16632269441SYishai Hadas 16732269441SYishai Hadas switch (opcode) { 16832269441SYishai Hadas case MLX5_CMD_OP_DESTROY_TIR: 16932269441SYishai Hadas *dest_type = MLX5_FLOW_DESTINATION_TYPE_TIR; 17032269441SYishai Hadas *dest_id = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, 17132269441SYishai Hadas obj_id); 17232269441SYishai Hadas return true; 17332269441SYishai Hadas 17432269441SYishai Hadas case MLX5_CMD_OP_DESTROY_FLOW_TABLE: 17532269441SYishai Hadas *dest_type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 17632269441SYishai Hadas *dest_id = MLX5_GET(destroy_flow_table_in, devx_obj->dinbox, 17732269441SYishai Hadas table_id); 17832269441SYishai Hadas return true; 17932269441SYishai Hadas default: 18032269441SYishai Hadas return false; 18132269441SYishai Hadas } 18232269441SYishai Hadas } 18332269441SYishai Hadas 184bfc5d839SMark Bloch bool mlx5_ib_devx_is_flow_counter(void *obj, u32 *counter_id) 185bfc5d839SMark Bloch { 186bfc5d839SMark Bloch struct devx_obj *devx_obj = obj; 187bfc5d839SMark Bloch u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, opcode); 188bfc5d839SMark Bloch 189bfc5d839SMark Bloch if (opcode == MLX5_CMD_OP_DEALLOC_FLOW_COUNTER) { 190bfc5d839SMark Bloch *counter_id = MLX5_GET(dealloc_flow_counter_in, 191bfc5d839SMark Bloch devx_obj->dinbox, 192bfc5d839SMark Bloch flow_counter_id); 193bfc5d839SMark Bloch return true; 194bfc5d839SMark Bloch } 195bfc5d839SMark Bloch 196bfc5d839SMark Bloch return false; 197bfc5d839SMark Bloch } 198bfc5d839SMark Bloch 199*75973853SYishai Hadas static bool is_legacy_unaffiliated_event_num(u16 event_num) 200*75973853SYishai Hadas { 201*75973853SYishai Hadas switch (event_num) { 202*75973853SYishai Hadas case MLX5_EVENT_TYPE_PORT_CHANGE: 203*75973853SYishai Hadas return true; 204*75973853SYishai Hadas default: 205*75973853SYishai Hadas return false; 206*75973853SYishai Hadas } 207*75973853SYishai Hadas } 208*75973853SYishai Hadas 209*75973853SYishai Hadas static bool is_legacy_obj_event_num(u16 event_num) 210*75973853SYishai Hadas { 211*75973853SYishai Hadas switch (event_num) { 212*75973853SYishai Hadas case MLX5_EVENT_TYPE_PATH_MIG: 213*75973853SYishai Hadas case MLX5_EVENT_TYPE_COMM_EST: 214*75973853SYishai Hadas case MLX5_EVENT_TYPE_SQ_DRAINED: 215*75973853SYishai Hadas case MLX5_EVENT_TYPE_SRQ_LAST_WQE: 216*75973853SYishai Hadas case MLX5_EVENT_TYPE_SRQ_RQ_LIMIT: 217*75973853SYishai Hadas case MLX5_EVENT_TYPE_CQ_ERROR: 218*75973853SYishai Hadas case MLX5_EVENT_TYPE_WQ_CATAS_ERROR: 219*75973853SYishai Hadas case MLX5_EVENT_TYPE_PATH_MIG_FAILED: 220*75973853SYishai Hadas case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR: 221*75973853SYishai Hadas case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR: 222*75973853SYishai Hadas case MLX5_EVENT_TYPE_SRQ_CATAS_ERROR: 223*75973853SYishai Hadas case MLX5_EVENT_TYPE_DCT_DRAINED: 224*75973853SYishai Hadas case MLX5_EVENT_TYPE_COMP: 225*75973853SYishai Hadas return true; 226*75973853SYishai Hadas default: 227*75973853SYishai Hadas return false; 228*75973853SYishai Hadas } 229*75973853SYishai Hadas } 230*75973853SYishai Hadas 231*75973853SYishai Hadas static u16 get_legacy_obj_type(u16 opcode) 232*75973853SYishai Hadas { 233*75973853SYishai Hadas switch (opcode) { 234*75973853SYishai Hadas case MLX5_CMD_OP_CREATE_RQ: 235*75973853SYishai Hadas return MLX5_EVENT_QUEUE_TYPE_RQ; 236*75973853SYishai Hadas case MLX5_CMD_OP_CREATE_QP: 237*75973853SYishai Hadas return MLX5_EVENT_QUEUE_TYPE_QP; 238*75973853SYishai Hadas case MLX5_CMD_OP_CREATE_SQ: 239*75973853SYishai Hadas return MLX5_EVENT_QUEUE_TYPE_SQ; 240*75973853SYishai Hadas case MLX5_CMD_OP_CREATE_DCT: 241*75973853SYishai Hadas return MLX5_EVENT_QUEUE_TYPE_DCT; 242*75973853SYishai Hadas default: 243*75973853SYishai Hadas return 0; 244*75973853SYishai Hadas } 245*75973853SYishai Hadas } 246*75973853SYishai Hadas 247*75973853SYishai Hadas static u16 get_dec_obj_type(struct devx_obj *obj, u16 event_num) 248*75973853SYishai Hadas { 249*75973853SYishai Hadas u16 opcode; 250*75973853SYishai Hadas 251*75973853SYishai Hadas opcode = (obj->obj_id >> 32) & 0xffff; 252*75973853SYishai Hadas 253*75973853SYishai Hadas if (is_legacy_obj_event_num(event_num)) 254*75973853SYishai Hadas return get_legacy_obj_type(opcode); 255*75973853SYishai Hadas 256*75973853SYishai Hadas switch (opcode) { 257*75973853SYishai Hadas case MLX5_CMD_OP_CREATE_GENERAL_OBJECT: 258*75973853SYishai Hadas return (obj->obj_id >> 48); 259*75973853SYishai Hadas case MLX5_CMD_OP_CREATE_RQ: 260*75973853SYishai Hadas return MLX5_OBJ_TYPE_RQ; 261*75973853SYishai Hadas case MLX5_CMD_OP_CREATE_QP: 262*75973853SYishai Hadas return MLX5_OBJ_TYPE_QP; 263*75973853SYishai Hadas case MLX5_CMD_OP_CREATE_SQ: 264*75973853SYishai Hadas return MLX5_OBJ_TYPE_SQ; 265*75973853SYishai Hadas case MLX5_CMD_OP_CREATE_DCT: 266*75973853SYishai Hadas return MLX5_OBJ_TYPE_DCT; 267*75973853SYishai Hadas case MLX5_CMD_OP_CREATE_TIR: 268*75973853SYishai Hadas return MLX5_OBJ_TYPE_TIR; 269*75973853SYishai Hadas case MLX5_CMD_OP_CREATE_TIS: 270*75973853SYishai Hadas return MLX5_OBJ_TYPE_TIS; 271*75973853SYishai Hadas case MLX5_CMD_OP_CREATE_PSV: 272*75973853SYishai Hadas return MLX5_OBJ_TYPE_PSV; 273*75973853SYishai Hadas case MLX5_OBJ_TYPE_MKEY: 274*75973853SYishai Hadas return MLX5_OBJ_TYPE_MKEY; 275*75973853SYishai Hadas case MLX5_CMD_OP_CREATE_RMP: 276*75973853SYishai Hadas return MLX5_OBJ_TYPE_RMP; 277*75973853SYishai Hadas case MLX5_CMD_OP_CREATE_XRC_SRQ: 278*75973853SYishai Hadas return MLX5_OBJ_TYPE_XRC_SRQ; 279*75973853SYishai Hadas case MLX5_CMD_OP_CREATE_XRQ: 280*75973853SYishai Hadas return MLX5_OBJ_TYPE_XRQ; 281*75973853SYishai Hadas case MLX5_CMD_OP_CREATE_RQT: 282*75973853SYishai Hadas return MLX5_OBJ_TYPE_RQT; 283*75973853SYishai Hadas case MLX5_CMD_OP_ALLOC_FLOW_COUNTER: 284*75973853SYishai Hadas return MLX5_OBJ_TYPE_FLOW_COUNTER; 285*75973853SYishai Hadas case MLX5_CMD_OP_CREATE_CQ: 286*75973853SYishai Hadas return MLX5_OBJ_TYPE_CQ; 287*75973853SYishai Hadas default: 288*75973853SYishai Hadas return 0; 289*75973853SYishai Hadas } 290*75973853SYishai Hadas } 291*75973853SYishai Hadas 292*75973853SYishai Hadas static u32 get_dec_obj_id(u64 obj_id) 293*75973853SYishai Hadas { 294*75973853SYishai Hadas return (obj_id & 0xffffffff); 295*75973853SYishai Hadas } 296*75973853SYishai Hadas 2972351776eSYishai Hadas /* 2982351776eSYishai Hadas * As the obj_id in the firmware is not globally unique the object type 2992351776eSYishai Hadas * must be considered upon checking for a valid object id. 3002351776eSYishai Hadas * For that the opcode of the creator command is encoded as part of the obj_id. 3012351776eSYishai Hadas */ 302cd5d20f1SYishai Hadas static u64 get_enc_obj_id(u32 opcode, u32 obj_id) 3032351776eSYishai Hadas { 3042351776eSYishai Hadas return ((u64)opcode << 32) | obj_id; 3052351776eSYishai Hadas } 3062351776eSYishai Hadas 30734613eb1SYishai Hadas static u64 devx_get_obj_id(const void *in) 308e662e14dSYishai Hadas { 309e662e14dSYishai Hadas u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 3102351776eSYishai Hadas u64 obj_id; 311e662e14dSYishai Hadas 312e662e14dSYishai Hadas switch (opcode) { 313e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT: 314e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_GENERAL_OBJECT: 315cd5d20f1SYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_GENERAL_OBJECT | 316cd5d20f1SYishai Hadas MLX5_GET(general_obj_in_cmd_hdr, in, 317cd5d20f1SYishai Hadas obj_type) << 16, 3182351776eSYishai Hadas MLX5_GET(general_obj_in_cmd_hdr, in, 3192351776eSYishai Hadas obj_id)); 320e662e14dSYishai Hadas break; 321e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_MKEY: 3222351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_MKEY, 3232351776eSYishai Hadas MLX5_GET(query_mkey_in, in, 3242351776eSYishai Hadas mkey_index)); 325e662e14dSYishai Hadas break; 326e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_CQ: 3272351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_CQ, 3282351776eSYishai Hadas MLX5_GET(query_cq_in, in, cqn)); 329e662e14dSYishai Hadas break; 330e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_CQ: 3312351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_CQ, 3322351776eSYishai Hadas MLX5_GET(modify_cq_in, in, cqn)); 333e662e14dSYishai Hadas break; 334e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_SQ: 3352351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ, 3362351776eSYishai Hadas MLX5_GET(query_sq_in, in, sqn)); 337e662e14dSYishai Hadas break; 338e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_SQ: 3392351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ, 3402351776eSYishai Hadas MLX5_GET(modify_sq_in, in, sqn)); 341e662e14dSYishai Hadas break; 342e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_RQ: 3432351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ, 3442351776eSYishai Hadas MLX5_GET(query_rq_in, in, rqn)); 345e662e14dSYishai Hadas break; 346e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_RQ: 3472351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ, 3482351776eSYishai Hadas MLX5_GET(modify_rq_in, in, rqn)); 349e662e14dSYishai Hadas break; 350e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_RMP: 3512351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RMP, 3522351776eSYishai Hadas MLX5_GET(query_rmp_in, in, rmpn)); 353e662e14dSYishai Hadas break; 354e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_RMP: 3552351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RMP, 3562351776eSYishai Hadas MLX5_GET(modify_rmp_in, in, rmpn)); 357e662e14dSYishai Hadas break; 358e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_RQT: 3592351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT, 3602351776eSYishai Hadas MLX5_GET(query_rqt_in, in, rqtn)); 361e662e14dSYishai Hadas break; 362e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_RQT: 3632351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT, 3642351776eSYishai Hadas MLX5_GET(modify_rqt_in, in, rqtn)); 365e662e14dSYishai Hadas break; 366e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_TIR: 3672351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR, 3682351776eSYishai Hadas MLX5_GET(query_tir_in, in, tirn)); 369e662e14dSYishai Hadas break; 370e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_TIR: 3712351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR, 3722351776eSYishai Hadas MLX5_GET(modify_tir_in, in, tirn)); 373e662e14dSYishai Hadas break; 374e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_TIS: 3752351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS, 3762351776eSYishai Hadas MLX5_GET(query_tis_in, in, tisn)); 377e662e14dSYishai Hadas break; 378e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_TIS: 3792351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS, 3802351776eSYishai Hadas MLX5_GET(modify_tis_in, in, tisn)); 381e662e14dSYishai Hadas break; 382e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_FLOW_TABLE: 3832351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_FLOW_TABLE, 3842351776eSYishai Hadas MLX5_GET(query_flow_table_in, in, 3852351776eSYishai Hadas table_id)); 386e662e14dSYishai Hadas break; 387e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_FLOW_TABLE: 3882351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_FLOW_TABLE, 3892351776eSYishai Hadas MLX5_GET(modify_flow_table_in, in, 3902351776eSYishai Hadas table_id)); 391e662e14dSYishai Hadas break; 392e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_FLOW_GROUP: 3932351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_FLOW_GROUP, 3942351776eSYishai Hadas MLX5_GET(query_flow_group_in, in, 3952351776eSYishai Hadas group_id)); 396e662e14dSYishai Hadas break; 397e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY: 3982351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY, 3992351776eSYishai Hadas MLX5_GET(query_fte_in, in, 4002351776eSYishai Hadas flow_index)); 401e662e14dSYishai Hadas break; 402e662e14dSYishai Hadas case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY: 4032351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY, 4042351776eSYishai Hadas MLX5_GET(set_fte_in, in, flow_index)); 405e662e14dSYishai Hadas break; 406e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_Q_COUNTER: 4072351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_ALLOC_Q_COUNTER, 4082351776eSYishai Hadas MLX5_GET(query_q_counter_in, in, 4092351776eSYishai Hadas counter_set_id)); 410e662e14dSYishai Hadas break; 411e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_FLOW_COUNTER: 4122351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_ALLOC_FLOW_COUNTER, 4132351776eSYishai Hadas MLX5_GET(query_flow_counter_in, in, 4142351776eSYishai Hadas flow_counter_id)); 415e662e14dSYishai Hadas break; 416e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT: 4172351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT, 4182351776eSYishai Hadas MLX5_GET(general_obj_in_cmd_hdr, in, 4192351776eSYishai Hadas obj_id)); 420e662e14dSYishai Hadas break; 421e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT: 4222351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT, 4232351776eSYishai Hadas MLX5_GET(query_scheduling_element_in, 4242351776eSYishai Hadas in, scheduling_element_id)); 425e662e14dSYishai Hadas break; 426e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT: 4272351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT, 4282351776eSYishai Hadas MLX5_GET(modify_scheduling_element_in, 4292351776eSYishai Hadas in, scheduling_element_id)); 430e662e14dSYishai Hadas break; 431e662e14dSYishai Hadas case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT: 4322351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT, 4332351776eSYishai Hadas MLX5_GET(add_vxlan_udp_dport_in, in, 4342351776eSYishai Hadas vxlan_udp_port)); 435e662e14dSYishai Hadas break; 436e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY: 4372351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_L2_TABLE_ENTRY, 4382351776eSYishai Hadas MLX5_GET(query_l2_table_entry_in, in, 4392351776eSYishai Hadas table_index)); 440e662e14dSYishai Hadas break; 441e662e14dSYishai Hadas case MLX5_CMD_OP_SET_L2_TABLE_ENTRY: 4422351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_L2_TABLE_ENTRY, 4432351776eSYishai Hadas MLX5_GET(set_l2_table_entry_in, in, 4442351776eSYishai Hadas table_index)); 445e662e14dSYishai Hadas break; 446e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_QP: 4472351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 4482351776eSYishai Hadas MLX5_GET(query_qp_in, in, qpn)); 449e662e14dSYishai Hadas break; 450e662e14dSYishai Hadas case MLX5_CMD_OP_RST2INIT_QP: 4512351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 4522351776eSYishai Hadas MLX5_GET(rst2init_qp_in, in, qpn)); 453e662e14dSYishai Hadas break; 454e662e14dSYishai Hadas case MLX5_CMD_OP_INIT2RTR_QP: 4552351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 4562351776eSYishai Hadas MLX5_GET(init2rtr_qp_in, in, qpn)); 457e662e14dSYishai Hadas break; 458e662e14dSYishai Hadas case MLX5_CMD_OP_RTR2RTS_QP: 4592351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 4602351776eSYishai Hadas MLX5_GET(rtr2rts_qp_in, in, qpn)); 461e662e14dSYishai Hadas break; 462e662e14dSYishai Hadas case MLX5_CMD_OP_RTS2RTS_QP: 4632351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 4642351776eSYishai Hadas MLX5_GET(rts2rts_qp_in, in, qpn)); 465e662e14dSYishai Hadas break; 466e662e14dSYishai Hadas case MLX5_CMD_OP_SQERR2RTS_QP: 4672351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 4682351776eSYishai Hadas MLX5_GET(sqerr2rts_qp_in, in, qpn)); 469e662e14dSYishai Hadas break; 470e662e14dSYishai Hadas case MLX5_CMD_OP_2ERR_QP: 4712351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 4722351776eSYishai Hadas MLX5_GET(qp_2err_in, in, qpn)); 473e662e14dSYishai Hadas break; 474e662e14dSYishai Hadas case MLX5_CMD_OP_2RST_QP: 4752351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 4762351776eSYishai Hadas MLX5_GET(qp_2rst_in, in, qpn)); 477e662e14dSYishai Hadas break; 478e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_DCT: 4792351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT, 4802351776eSYishai Hadas MLX5_GET(query_dct_in, in, dctn)); 481e662e14dSYishai Hadas break; 482e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_XRQ: 483719598c9SYishai Hadas case MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY: 484719598c9SYishai Hadas case MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS: 4852351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRQ, 4862351776eSYishai Hadas MLX5_GET(query_xrq_in, in, xrqn)); 487e662e14dSYishai Hadas break; 488e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_XRC_SRQ: 4892351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRC_SRQ, 4902351776eSYishai Hadas MLX5_GET(query_xrc_srq_in, in, 4912351776eSYishai Hadas xrc_srqn)); 492e662e14dSYishai Hadas break; 493e662e14dSYishai Hadas case MLX5_CMD_OP_ARM_XRC_SRQ: 4942351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRC_SRQ, 4952351776eSYishai Hadas MLX5_GET(arm_xrc_srq_in, in, xrc_srqn)); 496e662e14dSYishai Hadas break; 497e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_SRQ: 4982351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SRQ, 4992351776eSYishai Hadas MLX5_GET(query_srq_in, in, srqn)); 500e662e14dSYishai Hadas break; 501e662e14dSYishai Hadas case MLX5_CMD_OP_ARM_RQ: 5022351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ, 5032351776eSYishai Hadas MLX5_GET(arm_rq_in, in, srq_number)); 504e662e14dSYishai Hadas break; 505e662e14dSYishai Hadas case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION: 5062351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT, 5072351776eSYishai Hadas MLX5_GET(drain_dct_in, in, dctn)); 508e662e14dSYishai Hadas break; 509e662e14dSYishai Hadas case MLX5_CMD_OP_ARM_XRQ: 510719598c9SYishai Hadas case MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY: 5112351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRQ, 5122351776eSYishai Hadas MLX5_GET(arm_xrq_in, in, xrqn)); 513e662e14dSYishai Hadas break; 514719598c9SYishai Hadas case MLX5_CMD_OP_QUERY_PACKET_REFORMAT_CONTEXT: 515719598c9SYishai Hadas obj_id = get_enc_obj_id 516719598c9SYishai Hadas (MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT, 517719598c9SYishai Hadas MLX5_GET(query_packet_reformat_context_in, 518719598c9SYishai Hadas in, packet_reformat_id)); 519719598c9SYishai Hadas break; 520e662e14dSYishai Hadas default: 52134613eb1SYishai Hadas obj_id = 0; 522e662e14dSYishai Hadas } 523e662e14dSYishai Hadas 52434613eb1SYishai Hadas return obj_id; 52534613eb1SYishai Hadas } 526e662e14dSYishai Hadas 527e79c9c60SJason Gunthorpe static bool devx_is_valid_obj_id(struct uverbs_attr_bundle *attrs, 528e79c9c60SJason Gunthorpe struct ib_uobject *uobj, const void *in) 52934613eb1SYishai Hadas { 530e79c9c60SJason Gunthorpe struct mlx5_ib_dev *dev = mlx5_udata_to_mdev(&attrs->driver_udata); 53134613eb1SYishai Hadas u64 obj_id = devx_get_obj_id(in); 53234613eb1SYishai Hadas 53334613eb1SYishai Hadas if (!obj_id) 534e662e14dSYishai Hadas return false; 53534613eb1SYishai Hadas 53634613eb1SYishai Hadas switch (uobj_get_object_id(uobj)) { 53734613eb1SYishai Hadas case UVERBS_OBJECT_CQ: 53834613eb1SYishai Hadas return get_enc_obj_id(MLX5_CMD_OP_CREATE_CQ, 53934613eb1SYishai Hadas to_mcq(uobj->object)->mcq.cqn) == 54034613eb1SYishai Hadas obj_id; 54134613eb1SYishai Hadas 54234613eb1SYishai Hadas case UVERBS_OBJECT_SRQ: 54334613eb1SYishai Hadas { 54434613eb1SYishai Hadas struct mlx5_core_srq *srq = &(to_msrq(uobj->object)->msrq); 54534613eb1SYishai Hadas u16 opcode; 54634613eb1SYishai Hadas 54734613eb1SYishai Hadas switch (srq->common.res) { 54834613eb1SYishai Hadas case MLX5_RES_XSRQ: 54934613eb1SYishai Hadas opcode = MLX5_CMD_OP_CREATE_XRC_SRQ; 55034613eb1SYishai Hadas break; 55134613eb1SYishai Hadas case MLX5_RES_XRQ: 55234613eb1SYishai Hadas opcode = MLX5_CMD_OP_CREATE_XRQ; 55334613eb1SYishai Hadas break; 55434613eb1SYishai Hadas default: 55534613eb1SYishai Hadas if (!dev->mdev->issi) 55634613eb1SYishai Hadas opcode = MLX5_CMD_OP_CREATE_SRQ; 55734613eb1SYishai Hadas else 55834613eb1SYishai Hadas opcode = MLX5_CMD_OP_CREATE_RMP; 55934613eb1SYishai Hadas } 56034613eb1SYishai Hadas 56134613eb1SYishai Hadas return get_enc_obj_id(opcode, 56234613eb1SYishai Hadas to_msrq(uobj->object)->msrq.srqn) == 56334613eb1SYishai Hadas obj_id; 56434613eb1SYishai Hadas } 56534613eb1SYishai Hadas 56634613eb1SYishai Hadas case UVERBS_OBJECT_QP: 56734613eb1SYishai Hadas { 56834613eb1SYishai Hadas struct mlx5_ib_qp *qp = to_mqp(uobj->object); 56934613eb1SYishai Hadas enum ib_qp_type qp_type = qp->ibqp.qp_type; 57034613eb1SYishai Hadas 57134613eb1SYishai Hadas if (qp_type == IB_QPT_RAW_PACKET || 57234613eb1SYishai Hadas (qp->flags & MLX5_IB_QP_UNDERLAY)) { 57334613eb1SYishai Hadas struct mlx5_ib_raw_packet_qp *raw_packet_qp = 57434613eb1SYishai Hadas &qp->raw_packet_qp; 57534613eb1SYishai Hadas struct mlx5_ib_rq *rq = &raw_packet_qp->rq; 57634613eb1SYishai Hadas struct mlx5_ib_sq *sq = &raw_packet_qp->sq; 57734613eb1SYishai Hadas 57834613eb1SYishai Hadas return (get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ, 57934613eb1SYishai Hadas rq->base.mqp.qpn) == obj_id || 58034613eb1SYishai Hadas get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ, 58134613eb1SYishai Hadas sq->base.mqp.qpn) == obj_id || 58234613eb1SYishai Hadas get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR, 58334613eb1SYishai Hadas rq->tirn) == obj_id || 58434613eb1SYishai Hadas get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS, 58534613eb1SYishai Hadas sq->tisn) == obj_id); 58634613eb1SYishai Hadas } 58734613eb1SYishai Hadas 58834613eb1SYishai Hadas if (qp_type == MLX5_IB_QPT_DCT) 58934613eb1SYishai Hadas return get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT, 59034613eb1SYishai Hadas qp->dct.mdct.mqp.qpn) == obj_id; 59134613eb1SYishai Hadas 59234613eb1SYishai Hadas return get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 59334613eb1SYishai Hadas qp->ibqp.qp_num) == obj_id; 59434613eb1SYishai Hadas } 59534613eb1SYishai Hadas 59634613eb1SYishai Hadas case UVERBS_OBJECT_WQ: 59734613eb1SYishai Hadas return get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ, 59834613eb1SYishai Hadas to_mrwq(uobj->object)->core_qp.qpn) == 59934613eb1SYishai Hadas obj_id; 60034613eb1SYishai Hadas 60134613eb1SYishai Hadas case UVERBS_OBJECT_RWQ_IND_TBL: 60234613eb1SYishai Hadas return get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT, 60334613eb1SYishai Hadas to_mrwq_ind_table(uobj->object)->rqtn) == 60434613eb1SYishai Hadas obj_id; 60534613eb1SYishai Hadas 60634613eb1SYishai Hadas case MLX5_IB_OBJECT_DEVX_OBJ: 60734613eb1SYishai Hadas return ((struct devx_obj *)uobj->object)->obj_id == obj_id; 60834613eb1SYishai Hadas 609e662e14dSYishai Hadas default: 610e662e14dSYishai Hadas return false; 611e662e14dSYishai Hadas } 612e662e14dSYishai Hadas } 613e662e14dSYishai Hadas 614ba1a057dSYishai Hadas static void devx_set_umem_valid(const void *in) 615ba1a057dSYishai Hadas { 616ba1a057dSYishai Hadas u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 617ba1a057dSYishai Hadas 618ba1a057dSYishai Hadas switch (opcode) { 619ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_MKEY: 620ba1a057dSYishai Hadas MLX5_SET(create_mkey_in, in, mkey_umem_valid, 1); 621ba1a057dSYishai Hadas break; 622ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_CQ: 623ba1a057dSYishai Hadas { 624ba1a057dSYishai Hadas void *cqc; 625ba1a057dSYishai Hadas 626ba1a057dSYishai Hadas MLX5_SET(create_cq_in, in, cq_umem_valid, 1); 627ba1a057dSYishai Hadas cqc = MLX5_ADDR_OF(create_cq_in, in, cq_context); 628ba1a057dSYishai Hadas MLX5_SET(cqc, cqc, dbr_umem_valid, 1); 629ba1a057dSYishai Hadas break; 630ba1a057dSYishai Hadas } 631ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_QP: 632ba1a057dSYishai Hadas { 633ba1a057dSYishai Hadas void *qpc; 634ba1a057dSYishai Hadas 635ba1a057dSYishai Hadas qpc = MLX5_ADDR_OF(create_qp_in, in, qpc); 636ba1a057dSYishai Hadas MLX5_SET(qpc, qpc, dbr_umem_valid, 1); 637ba1a057dSYishai Hadas MLX5_SET(create_qp_in, in, wq_umem_valid, 1); 638ba1a057dSYishai Hadas break; 639ba1a057dSYishai Hadas } 640ba1a057dSYishai Hadas 641ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_RQ: 642ba1a057dSYishai Hadas { 643ba1a057dSYishai Hadas void *rqc, *wq; 644ba1a057dSYishai Hadas 645ba1a057dSYishai Hadas rqc = MLX5_ADDR_OF(create_rq_in, in, ctx); 646ba1a057dSYishai Hadas wq = MLX5_ADDR_OF(rqc, rqc, wq); 647ba1a057dSYishai Hadas MLX5_SET(wq, wq, dbr_umem_valid, 1); 648ba1a057dSYishai Hadas MLX5_SET(wq, wq, wq_umem_valid, 1); 649ba1a057dSYishai Hadas break; 650ba1a057dSYishai Hadas } 651ba1a057dSYishai Hadas 652ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_SQ: 653ba1a057dSYishai Hadas { 654ba1a057dSYishai Hadas void *sqc, *wq; 655ba1a057dSYishai Hadas 656ba1a057dSYishai Hadas sqc = MLX5_ADDR_OF(create_sq_in, in, ctx); 657ba1a057dSYishai Hadas wq = MLX5_ADDR_OF(sqc, sqc, wq); 658ba1a057dSYishai Hadas MLX5_SET(wq, wq, dbr_umem_valid, 1); 659ba1a057dSYishai Hadas MLX5_SET(wq, wq, wq_umem_valid, 1); 660ba1a057dSYishai Hadas break; 661ba1a057dSYishai Hadas } 662ba1a057dSYishai Hadas 663ba1a057dSYishai Hadas case MLX5_CMD_OP_MODIFY_CQ: 664ba1a057dSYishai Hadas MLX5_SET(modify_cq_in, in, cq_umem_valid, 1); 665ba1a057dSYishai Hadas break; 666ba1a057dSYishai Hadas 667ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_RMP: 668ba1a057dSYishai Hadas { 669ba1a057dSYishai Hadas void *rmpc, *wq; 670ba1a057dSYishai Hadas 671ba1a057dSYishai Hadas rmpc = MLX5_ADDR_OF(create_rmp_in, in, ctx); 672ba1a057dSYishai Hadas wq = MLX5_ADDR_OF(rmpc, rmpc, wq); 673ba1a057dSYishai Hadas MLX5_SET(wq, wq, dbr_umem_valid, 1); 674ba1a057dSYishai Hadas MLX5_SET(wq, wq, wq_umem_valid, 1); 675ba1a057dSYishai Hadas break; 676ba1a057dSYishai Hadas } 677ba1a057dSYishai Hadas 678ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_XRQ: 679ba1a057dSYishai Hadas { 680ba1a057dSYishai Hadas void *xrqc, *wq; 681ba1a057dSYishai Hadas 682ba1a057dSYishai Hadas xrqc = MLX5_ADDR_OF(create_xrq_in, in, xrq_context); 683ba1a057dSYishai Hadas wq = MLX5_ADDR_OF(xrqc, xrqc, wq); 684ba1a057dSYishai Hadas MLX5_SET(wq, wq, dbr_umem_valid, 1); 685ba1a057dSYishai Hadas MLX5_SET(wq, wq, wq_umem_valid, 1); 686ba1a057dSYishai Hadas break; 687ba1a057dSYishai Hadas } 688ba1a057dSYishai Hadas 689ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_XRC_SRQ: 690ba1a057dSYishai Hadas { 691ba1a057dSYishai Hadas void *xrc_srqc; 692ba1a057dSYishai Hadas 693ba1a057dSYishai Hadas MLX5_SET(create_xrc_srq_in, in, xrc_srq_umem_valid, 1); 694ba1a057dSYishai Hadas xrc_srqc = MLX5_ADDR_OF(create_xrc_srq_in, in, 695ba1a057dSYishai Hadas xrc_srq_context_entry); 696ba1a057dSYishai Hadas MLX5_SET(xrc_srqc, xrc_srqc, dbr_umem_valid, 1); 697ba1a057dSYishai Hadas break; 698ba1a057dSYishai Hadas } 699ba1a057dSYishai Hadas 700ba1a057dSYishai Hadas default: 701ba1a057dSYishai Hadas return; 702ba1a057dSYishai Hadas } 703ba1a057dSYishai Hadas } 704ba1a057dSYishai Hadas 7052351776eSYishai Hadas static bool devx_is_obj_create_cmd(const void *in, u16 *opcode) 7067efce369SYishai Hadas { 7072351776eSYishai Hadas *opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 7087efce369SYishai Hadas 7092351776eSYishai Hadas switch (*opcode) { 7107efce369SYishai Hadas case MLX5_CMD_OP_CREATE_GENERAL_OBJECT: 7117efce369SYishai Hadas case MLX5_CMD_OP_CREATE_MKEY: 7127efce369SYishai Hadas case MLX5_CMD_OP_CREATE_CQ: 7137efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_PD: 7147efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN: 7157efce369SYishai Hadas case MLX5_CMD_OP_CREATE_RMP: 7167efce369SYishai Hadas case MLX5_CMD_OP_CREATE_SQ: 7177efce369SYishai Hadas case MLX5_CMD_OP_CREATE_RQ: 7187efce369SYishai Hadas case MLX5_CMD_OP_CREATE_RQT: 7197efce369SYishai Hadas case MLX5_CMD_OP_CREATE_TIR: 7207efce369SYishai Hadas case MLX5_CMD_OP_CREATE_TIS: 7217efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_Q_COUNTER: 7227efce369SYishai Hadas case MLX5_CMD_OP_CREATE_FLOW_TABLE: 7237efce369SYishai Hadas case MLX5_CMD_OP_CREATE_FLOW_GROUP: 7247efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_FLOW_COUNTER: 72560786f09SMark Bloch case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT: 7267efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT: 7277efce369SYishai Hadas case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT: 7287efce369SYishai Hadas case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT: 7297efce369SYishai Hadas case MLX5_CMD_OP_SET_L2_TABLE_ENTRY: 7307efce369SYishai Hadas case MLX5_CMD_OP_CREATE_QP: 7317efce369SYishai Hadas case MLX5_CMD_OP_CREATE_SRQ: 7327efce369SYishai Hadas case MLX5_CMD_OP_CREATE_XRC_SRQ: 7337efce369SYishai Hadas case MLX5_CMD_OP_CREATE_DCT: 7347efce369SYishai Hadas case MLX5_CMD_OP_CREATE_XRQ: 7357efce369SYishai Hadas case MLX5_CMD_OP_ATTACH_TO_MCG: 7367efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_XRCD: 7377efce369SYishai Hadas return true; 7387efce369SYishai Hadas case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY: 7397efce369SYishai Hadas { 7407efce369SYishai Hadas u16 op_mod = MLX5_GET(set_fte_in, in, op_mod); 7417efce369SYishai Hadas if (op_mod == 0) 7427efce369SYishai Hadas return true; 7437efce369SYishai Hadas return false; 7447efce369SYishai Hadas } 7457efce369SYishai Hadas default: 7467efce369SYishai Hadas return false; 7477efce369SYishai Hadas } 7487efce369SYishai Hadas } 7497efce369SYishai Hadas 750e662e14dSYishai Hadas static bool devx_is_obj_modify_cmd(const void *in) 751e662e14dSYishai Hadas { 752e662e14dSYishai Hadas u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 753e662e14dSYishai Hadas 754e662e14dSYishai Hadas switch (opcode) { 755e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT: 756e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_CQ: 757e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_RMP: 758e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_SQ: 759e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_RQ: 760e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_RQT: 761e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_TIR: 762e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_TIS: 763e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_FLOW_TABLE: 764e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT: 765e662e14dSYishai Hadas case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT: 766e662e14dSYishai Hadas case MLX5_CMD_OP_SET_L2_TABLE_ENTRY: 767e662e14dSYishai Hadas case MLX5_CMD_OP_RST2INIT_QP: 768e662e14dSYishai Hadas case MLX5_CMD_OP_INIT2RTR_QP: 769e662e14dSYishai Hadas case MLX5_CMD_OP_RTR2RTS_QP: 770e662e14dSYishai Hadas case MLX5_CMD_OP_RTS2RTS_QP: 771e662e14dSYishai Hadas case MLX5_CMD_OP_SQERR2RTS_QP: 772e662e14dSYishai Hadas case MLX5_CMD_OP_2ERR_QP: 773e662e14dSYishai Hadas case MLX5_CMD_OP_2RST_QP: 774e662e14dSYishai Hadas case MLX5_CMD_OP_ARM_XRC_SRQ: 775e662e14dSYishai Hadas case MLX5_CMD_OP_ARM_RQ: 776e662e14dSYishai Hadas case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION: 777e662e14dSYishai Hadas case MLX5_CMD_OP_ARM_XRQ: 778719598c9SYishai Hadas case MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY: 779e662e14dSYishai Hadas return true; 780e662e14dSYishai Hadas case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY: 781e662e14dSYishai Hadas { 782e662e14dSYishai Hadas u16 op_mod = MLX5_GET(set_fte_in, in, op_mod); 783e662e14dSYishai Hadas 784e662e14dSYishai Hadas if (op_mod == 1) 785e662e14dSYishai Hadas return true; 786e662e14dSYishai Hadas return false; 787e662e14dSYishai Hadas } 788e662e14dSYishai Hadas default: 789e662e14dSYishai Hadas return false; 790e662e14dSYishai Hadas } 791e662e14dSYishai Hadas } 792e662e14dSYishai Hadas 793e662e14dSYishai Hadas static bool devx_is_obj_query_cmd(const void *in) 794e662e14dSYishai Hadas { 795e662e14dSYishai Hadas u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 796e662e14dSYishai Hadas 797e662e14dSYishai Hadas switch (opcode) { 798e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_GENERAL_OBJECT: 799e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_MKEY: 800e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_CQ: 801e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_RMP: 802e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_SQ: 803e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_RQ: 804e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_RQT: 805e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_TIR: 806e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_TIS: 807e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_Q_COUNTER: 808e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_FLOW_TABLE: 809e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_FLOW_GROUP: 810e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY: 811e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_FLOW_COUNTER: 812e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT: 813e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT: 814e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY: 815e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_QP: 816e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_SRQ: 817e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_XRC_SRQ: 818e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_DCT: 819e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_XRQ: 820719598c9SYishai Hadas case MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY: 821719598c9SYishai Hadas case MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS: 822719598c9SYishai Hadas case MLX5_CMD_OP_QUERY_PACKET_REFORMAT_CONTEXT: 823e662e14dSYishai Hadas return true; 824e662e14dSYishai Hadas default: 825e662e14dSYishai Hadas return false; 826e662e14dSYishai Hadas } 827e662e14dSYishai Hadas } 828e662e14dSYishai Hadas 8297e1335a7SYishai Hadas static bool devx_is_whitelist_cmd(void *in) 8307e1335a7SYishai Hadas { 8317e1335a7SYishai Hadas u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 8327e1335a7SYishai Hadas 8337e1335a7SYishai Hadas switch (opcode) { 8347e1335a7SYishai Hadas case MLX5_CMD_OP_QUERY_HCA_CAP: 8357e1335a7SYishai Hadas case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT: 83656e5acd4SMaor Gottlieb case MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT: 8377e1335a7SYishai Hadas return true; 8387e1335a7SYishai Hadas default: 8397e1335a7SYishai Hadas return false; 8407e1335a7SYishai Hadas } 8417e1335a7SYishai Hadas } 8427e1335a7SYishai Hadas 8437e1335a7SYishai Hadas static int devx_get_uid(struct mlx5_ib_ucontext *c, void *cmd_in) 8447e1335a7SYishai Hadas { 8457e1335a7SYishai Hadas if (devx_is_whitelist_cmd(cmd_in)) { 8467e1335a7SYishai Hadas struct mlx5_ib_dev *dev; 8477e1335a7SYishai Hadas 8487e1335a7SYishai Hadas if (c->devx_uid) 8497e1335a7SYishai Hadas return c->devx_uid; 8507e1335a7SYishai Hadas 8517e1335a7SYishai Hadas dev = to_mdev(c->ibucontext.device); 8527e1335a7SYishai Hadas if (dev->devx_whitelist_uid) 8537e1335a7SYishai Hadas return dev->devx_whitelist_uid; 8547e1335a7SYishai Hadas 8557e1335a7SYishai Hadas return -EOPNOTSUPP; 8567e1335a7SYishai Hadas } 8577e1335a7SYishai Hadas 8587e1335a7SYishai Hadas if (!c->devx_uid) 8597e1335a7SYishai Hadas return -EINVAL; 8607e1335a7SYishai Hadas 8617e1335a7SYishai Hadas return c->devx_uid; 8627e1335a7SYishai Hadas } 863e662e14dSYishai Hadas static bool devx_is_general_cmd(void *in) 8648aa8c95cSYishai Hadas { 8658aa8c95cSYishai Hadas u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 8668aa8c95cSYishai Hadas 867719598c9SYishai Hadas if (opcode >= MLX5_CMD_OP_GENERAL_START && 868719598c9SYishai Hadas opcode < MLX5_CMD_OP_GENERAL_END) 869719598c9SYishai Hadas return true; 870719598c9SYishai Hadas 8718aa8c95cSYishai Hadas switch (opcode) { 8728aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_HCA_CAP: 8737e1335a7SYishai Hadas case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT: 87456e5acd4SMaor Gottlieb case MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT: 8758aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_VPORT_STATE: 8768aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_ADAPTER: 8778aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_ISSI: 8788aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT: 8798aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_ROCE_ADDRESS: 8808aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_VNIC_ENV: 8818aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_VPORT_COUNTER: 8828aa8c95cSYishai Hadas case MLX5_CMD_OP_GET_DROPPED_PACKET_LOG: 8838aa8c95cSYishai Hadas case MLX5_CMD_OP_NOP: 8848aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_CONG_STATUS: 8858aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_CONG_PARAMS: 8868aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_CONG_STATISTICS: 8878aa8c95cSYishai Hadas return true; 8888aa8c95cSYishai Hadas default: 8898aa8c95cSYishai Hadas return false; 8908aa8c95cSYishai Hadas } 8918aa8c95cSYishai Hadas } 8928aa8c95cSYishai Hadas 893e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_EQN)( 89415a1b4beSJason Gunthorpe struct uverbs_attr_bundle *attrs) 895f6fe01b7SYishai Hadas { 896e83f0ecdSJason Gunthorpe struct mlx5_ib_ucontext *c; 897e83f0ecdSJason Gunthorpe struct mlx5_ib_dev *dev; 898f6fe01b7SYishai Hadas int user_vector; 899f6fe01b7SYishai Hadas int dev_eqn; 900f6fe01b7SYishai Hadas unsigned int irqn; 901f6fe01b7SYishai Hadas int err; 902f6fe01b7SYishai Hadas 903f6fe01b7SYishai Hadas if (uverbs_copy_from(&user_vector, attrs, 904f6fe01b7SYishai Hadas MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC)) 905f6fe01b7SYishai Hadas return -EFAULT; 906f6fe01b7SYishai Hadas 90715a1b4beSJason Gunthorpe c = devx_ufile2uctx(attrs); 908e83f0ecdSJason Gunthorpe if (IS_ERR(c)) 909e83f0ecdSJason Gunthorpe return PTR_ERR(c); 910e83f0ecdSJason Gunthorpe dev = to_mdev(c->ibucontext.device); 911e83f0ecdSJason Gunthorpe 912f6fe01b7SYishai Hadas err = mlx5_vector2eqn(dev->mdev, user_vector, &dev_eqn, &irqn); 913f6fe01b7SYishai Hadas if (err < 0) 914f6fe01b7SYishai Hadas return err; 915f6fe01b7SYishai Hadas 916f6fe01b7SYishai Hadas if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN, 917f6fe01b7SYishai Hadas &dev_eqn, sizeof(dev_eqn))) 918f6fe01b7SYishai Hadas return -EFAULT; 919f6fe01b7SYishai Hadas 920f6fe01b7SYishai Hadas return 0; 921f6fe01b7SYishai Hadas } 922f6fe01b7SYishai Hadas 9237c043e90SYishai Hadas /* 9247c043e90SYishai Hadas *Security note: 9257c043e90SYishai Hadas * The hardware protection mechanism works like this: Each device object that 9267c043e90SYishai Hadas * is subject to UAR doorbells (QP/SQ/CQ) gets a UAR ID (called uar_page in 9277c043e90SYishai Hadas * the device specification manual) upon its creation. Then upon doorbell, 9287c043e90SYishai Hadas * hardware fetches the object context for which the doorbell was rang, and 9297c043e90SYishai Hadas * validates that the UAR through which the DB was rang matches the UAR ID 9307c043e90SYishai Hadas * of the object. 9317c043e90SYishai Hadas * If no match the doorbell is silently ignored by the hardware. Of course, 9327c043e90SYishai Hadas * the user cannot ring a doorbell on a UAR that was not mapped to it. 9337c043e90SYishai Hadas * Now in devx, as the devx kernel does not manipulate the QP/SQ/CQ command 9347c043e90SYishai Hadas * mailboxes (except tagging them with UID), we expose to the user its UAR 9357c043e90SYishai Hadas * ID, so it can embed it in these objects in the expected specification 9367c043e90SYishai Hadas * format. So the only thing the user can do is hurt itself by creating a 9377c043e90SYishai Hadas * QP/SQ/CQ with a UAR ID other than his, and then in this case other users 9387c043e90SYishai Hadas * may ring a doorbell on its objects. 9397c043e90SYishai Hadas * The consequence of that will be that another user can schedule a QP/SQ 9407c043e90SYishai Hadas * of the buggy user for execution (just insert it to the hardware schedule 9417c043e90SYishai Hadas * queue or arm its CQ for event generation), no further harm is expected. 9427c043e90SYishai Hadas */ 943e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_UAR)( 94415a1b4beSJason Gunthorpe struct uverbs_attr_bundle *attrs) 9457c043e90SYishai Hadas { 94622fa27fbSJason Gunthorpe struct mlx5_ib_ucontext *c; 94722fa27fbSJason Gunthorpe struct mlx5_ib_dev *dev; 9487c043e90SYishai Hadas u32 user_idx; 9497c043e90SYishai Hadas s32 dev_idx; 9507c043e90SYishai Hadas 95115a1b4beSJason Gunthorpe c = devx_ufile2uctx(attrs); 95222fa27fbSJason Gunthorpe if (IS_ERR(c)) 95322fa27fbSJason Gunthorpe return PTR_ERR(c); 95422fa27fbSJason Gunthorpe dev = to_mdev(c->ibucontext.device); 95522fa27fbSJason Gunthorpe 9567c043e90SYishai Hadas if (uverbs_copy_from(&user_idx, attrs, 9577c043e90SYishai Hadas MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX)) 9587c043e90SYishai Hadas return -EFAULT; 9597c043e90SYishai Hadas 96022fa27fbSJason Gunthorpe dev_idx = bfregn_to_uar_index(dev, &c->bfregi, user_idx, true); 9617c043e90SYishai Hadas if (dev_idx < 0) 9627c043e90SYishai Hadas return dev_idx; 9637c043e90SYishai Hadas 9647c043e90SYishai Hadas if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX, 9657c043e90SYishai Hadas &dev_idx, sizeof(dev_idx))) 9667c043e90SYishai Hadas return -EFAULT; 9677c043e90SYishai Hadas 9687c043e90SYishai Hadas return 0; 9697c043e90SYishai Hadas } 9707c043e90SYishai Hadas 971e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)( 97215a1b4beSJason Gunthorpe struct uverbs_attr_bundle *attrs) 9738aa8c95cSYishai Hadas { 97422fa27fbSJason Gunthorpe struct mlx5_ib_ucontext *c; 97522fa27fbSJason Gunthorpe struct mlx5_ib_dev *dev; 9767efce369SYishai Hadas void *cmd_in = uverbs_attr_get_alloced_ptr( 9777efce369SYishai Hadas attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN); 9788aa8c95cSYishai Hadas int cmd_out_len = uverbs_attr_get_len(attrs, 9798aa8c95cSYishai Hadas MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT); 9808aa8c95cSYishai Hadas void *cmd_out; 9818aa8c95cSYishai Hadas int err; 9827e1335a7SYishai Hadas int uid; 9838aa8c95cSYishai Hadas 98415a1b4beSJason Gunthorpe c = devx_ufile2uctx(attrs); 98522fa27fbSJason Gunthorpe if (IS_ERR(c)) 98622fa27fbSJason Gunthorpe return PTR_ERR(c); 98722fa27fbSJason Gunthorpe dev = to_mdev(c->ibucontext.device); 98822fa27fbSJason Gunthorpe 9897e1335a7SYishai Hadas uid = devx_get_uid(c, cmd_in); 9907e1335a7SYishai Hadas if (uid < 0) 9917e1335a7SYishai Hadas return uid; 9928aa8c95cSYishai Hadas 9938aa8c95cSYishai Hadas /* Only white list of some general HCA commands are allowed for this method. */ 9948aa8c95cSYishai Hadas if (!devx_is_general_cmd(cmd_in)) 9958aa8c95cSYishai Hadas return -EINVAL; 9968aa8c95cSYishai Hadas 997b61815e2SJason Gunthorpe cmd_out = uverbs_zalloc(attrs, cmd_out_len); 998b61815e2SJason Gunthorpe if (IS_ERR(cmd_out)) 999b61815e2SJason Gunthorpe return PTR_ERR(cmd_out); 10008aa8c95cSYishai Hadas 10017e1335a7SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); 10028aa8c95cSYishai Hadas err = mlx5_cmd_exec(dev->mdev, cmd_in, 10038aa8c95cSYishai Hadas uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN), 10048aa8c95cSYishai Hadas cmd_out, cmd_out_len); 10058aa8c95cSYishai Hadas if (err) 10068aa8c95cSYishai Hadas return err; 1007b61815e2SJason Gunthorpe 1008b61815e2SJason Gunthorpe return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT, cmd_out, 1009b61815e2SJason Gunthorpe cmd_out_len); 10108aa8c95cSYishai Hadas } 10118aa8c95cSYishai Hadas 10127efce369SYishai Hadas static void devx_obj_build_destroy_cmd(void *in, void *out, void *din, 10137efce369SYishai Hadas u32 *dinlen, 10147efce369SYishai Hadas u32 *obj_id) 10157efce369SYishai Hadas { 10167efce369SYishai Hadas u16 obj_type = MLX5_GET(general_obj_in_cmd_hdr, in, obj_type); 10177efce369SYishai Hadas u16 uid = MLX5_GET(general_obj_in_cmd_hdr, in, uid); 10187efce369SYishai Hadas 10197efce369SYishai Hadas *obj_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 10207efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr); 10217efce369SYishai Hadas 10227efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, obj_id, *obj_id); 10237efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, uid, uid); 10247efce369SYishai Hadas 10257efce369SYishai Hadas switch (MLX5_GET(general_obj_in_cmd_hdr, in, opcode)) { 10267efce369SYishai Hadas case MLX5_CMD_OP_CREATE_GENERAL_OBJECT: 10277efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT); 10287efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, obj_type, obj_type); 10297efce369SYishai Hadas break; 10307efce369SYishai Hadas 10316e3722baSYishai Hadas case MLX5_CMD_OP_CREATE_UMEM: 10326e3722baSYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 10336e3722baSYishai Hadas MLX5_CMD_OP_DESTROY_UMEM); 10346e3722baSYishai Hadas break; 10357efce369SYishai Hadas case MLX5_CMD_OP_CREATE_MKEY: 10367efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_MKEY); 10377efce369SYishai Hadas break; 10387efce369SYishai Hadas case MLX5_CMD_OP_CREATE_CQ: 10397efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_CQ); 10407efce369SYishai Hadas break; 10417efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_PD: 10427efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DEALLOC_PD); 10437efce369SYishai Hadas break; 10447efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN: 10457efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 10467efce369SYishai Hadas MLX5_CMD_OP_DEALLOC_TRANSPORT_DOMAIN); 10477efce369SYishai Hadas break; 10487efce369SYishai Hadas case MLX5_CMD_OP_CREATE_RMP: 10497efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RMP); 10507efce369SYishai Hadas break; 10517efce369SYishai Hadas case MLX5_CMD_OP_CREATE_SQ: 10527efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_SQ); 10537efce369SYishai Hadas break; 10547efce369SYishai Hadas case MLX5_CMD_OP_CREATE_RQ: 10557efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RQ); 10567efce369SYishai Hadas break; 10577efce369SYishai Hadas case MLX5_CMD_OP_CREATE_RQT: 10587efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RQT); 10597efce369SYishai Hadas break; 10607efce369SYishai Hadas case MLX5_CMD_OP_CREATE_TIR: 10617efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIR); 10627efce369SYishai Hadas break; 10637efce369SYishai Hadas case MLX5_CMD_OP_CREATE_TIS: 10647efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIS); 10657efce369SYishai Hadas break; 10667efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_Q_COUNTER: 10677efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 10687efce369SYishai Hadas MLX5_CMD_OP_DEALLOC_Q_COUNTER); 10697efce369SYishai Hadas break; 10707efce369SYishai Hadas case MLX5_CMD_OP_CREATE_FLOW_TABLE: 10717efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(destroy_flow_table_in); 10727efce369SYishai Hadas *obj_id = MLX5_GET(create_flow_table_out, out, table_id); 10737efce369SYishai Hadas MLX5_SET(destroy_flow_table_in, din, other_vport, 10747efce369SYishai Hadas MLX5_GET(create_flow_table_in, in, other_vport)); 10757efce369SYishai Hadas MLX5_SET(destroy_flow_table_in, din, vport_number, 10767efce369SYishai Hadas MLX5_GET(create_flow_table_in, in, vport_number)); 10777efce369SYishai Hadas MLX5_SET(destroy_flow_table_in, din, table_type, 10787efce369SYishai Hadas MLX5_GET(create_flow_table_in, in, table_type)); 10797efce369SYishai Hadas MLX5_SET(destroy_flow_table_in, din, table_id, *obj_id); 10807efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 10817efce369SYishai Hadas MLX5_CMD_OP_DESTROY_FLOW_TABLE); 10827efce369SYishai Hadas break; 10837efce369SYishai Hadas case MLX5_CMD_OP_CREATE_FLOW_GROUP: 10847efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(destroy_flow_group_in); 10857efce369SYishai Hadas *obj_id = MLX5_GET(create_flow_group_out, out, group_id); 10867efce369SYishai Hadas MLX5_SET(destroy_flow_group_in, din, other_vport, 10877efce369SYishai Hadas MLX5_GET(create_flow_group_in, in, other_vport)); 10887efce369SYishai Hadas MLX5_SET(destroy_flow_group_in, din, vport_number, 10897efce369SYishai Hadas MLX5_GET(create_flow_group_in, in, vport_number)); 10907efce369SYishai Hadas MLX5_SET(destroy_flow_group_in, din, table_type, 10917efce369SYishai Hadas MLX5_GET(create_flow_group_in, in, table_type)); 10927efce369SYishai Hadas MLX5_SET(destroy_flow_group_in, din, table_id, 10937efce369SYishai Hadas MLX5_GET(create_flow_group_in, in, table_id)); 10947efce369SYishai Hadas MLX5_SET(destroy_flow_group_in, din, group_id, *obj_id); 10957efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 10967efce369SYishai Hadas MLX5_CMD_OP_DESTROY_FLOW_GROUP); 10977efce369SYishai Hadas break; 10987efce369SYishai Hadas case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY: 10997efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(delete_fte_in); 11007efce369SYishai Hadas *obj_id = MLX5_GET(set_fte_in, in, flow_index); 11017efce369SYishai Hadas MLX5_SET(delete_fte_in, din, other_vport, 11027efce369SYishai Hadas MLX5_GET(set_fte_in, in, other_vport)); 11037efce369SYishai Hadas MLX5_SET(delete_fte_in, din, vport_number, 11047efce369SYishai Hadas MLX5_GET(set_fte_in, in, vport_number)); 11057efce369SYishai Hadas MLX5_SET(delete_fte_in, din, table_type, 11067efce369SYishai Hadas MLX5_GET(set_fte_in, in, table_type)); 11077efce369SYishai Hadas MLX5_SET(delete_fte_in, din, table_id, 11087efce369SYishai Hadas MLX5_GET(set_fte_in, in, table_id)); 11097efce369SYishai Hadas MLX5_SET(delete_fte_in, din, flow_index, *obj_id); 11107efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 11117efce369SYishai Hadas MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY); 11127efce369SYishai Hadas break; 11137efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_FLOW_COUNTER: 11147efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 11157efce369SYishai Hadas MLX5_CMD_OP_DEALLOC_FLOW_COUNTER); 11167efce369SYishai Hadas break; 111760786f09SMark Bloch case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT: 11187efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 111960786f09SMark Bloch MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT); 11207efce369SYishai Hadas break; 11217efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT: 11227efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 11237efce369SYishai Hadas MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT); 11247efce369SYishai Hadas break; 11257efce369SYishai Hadas case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT: 11267efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(destroy_scheduling_element_in); 11277efce369SYishai Hadas *obj_id = MLX5_GET(create_scheduling_element_out, out, 11287efce369SYishai Hadas scheduling_element_id); 11297efce369SYishai Hadas MLX5_SET(destroy_scheduling_element_in, din, 11307efce369SYishai Hadas scheduling_hierarchy, 11317efce369SYishai Hadas MLX5_GET(create_scheduling_element_in, in, 11327efce369SYishai Hadas scheduling_hierarchy)); 11337efce369SYishai Hadas MLX5_SET(destroy_scheduling_element_in, din, 11347efce369SYishai Hadas scheduling_element_id, *obj_id); 11357efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 11367efce369SYishai Hadas MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT); 11377efce369SYishai Hadas break; 11387efce369SYishai Hadas case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT: 11397efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(delete_vxlan_udp_dport_in); 11407efce369SYishai Hadas *obj_id = MLX5_GET(add_vxlan_udp_dport_in, in, vxlan_udp_port); 11417efce369SYishai Hadas MLX5_SET(delete_vxlan_udp_dport_in, din, vxlan_udp_port, *obj_id); 11427efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 11437efce369SYishai Hadas MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT); 11447efce369SYishai Hadas break; 11457efce369SYishai Hadas case MLX5_CMD_OP_SET_L2_TABLE_ENTRY: 11467efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(delete_l2_table_entry_in); 11477efce369SYishai Hadas *obj_id = MLX5_GET(set_l2_table_entry_in, in, table_index); 11487efce369SYishai Hadas MLX5_SET(delete_l2_table_entry_in, din, table_index, *obj_id); 11497efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 11507efce369SYishai Hadas MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY); 11517efce369SYishai Hadas break; 11527efce369SYishai Hadas case MLX5_CMD_OP_CREATE_QP: 11537efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_QP); 11547efce369SYishai Hadas break; 11557efce369SYishai Hadas case MLX5_CMD_OP_CREATE_SRQ: 11567efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_SRQ); 11577efce369SYishai Hadas break; 11587efce369SYishai Hadas case MLX5_CMD_OP_CREATE_XRC_SRQ: 11597efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 11607efce369SYishai Hadas MLX5_CMD_OP_DESTROY_XRC_SRQ); 11617efce369SYishai Hadas break; 11627efce369SYishai Hadas case MLX5_CMD_OP_CREATE_DCT: 11637efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_DCT); 11647efce369SYishai Hadas break; 11657efce369SYishai Hadas case MLX5_CMD_OP_CREATE_XRQ: 11667efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_XRQ); 11677efce369SYishai Hadas break; 11687efce369SYishai Hadas case MLX5_CMD_OP_ATTACH_TO_MCG: 11697efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(detach_from_mcg_in); 11707efce369SYishai Hadas MLX5_SET(detach_from_mcg_in, din, qpn, 11717efce369SYishai Hadas MLX5_GET(attach_to_mcg_in, in, qpn)); 11727efce369SYishai Hadas memcpy(MLX5_ADDR_OF(detach_from_mcg_in, din, multicast_gid), 11737efce369SYishai Hadas MLX5_ADDR_OF(attach_to_mcg_in, in, multicast_gid), 11747efce369SYishai Hadas MLX5_FLD_SZ_BYTES(attach_to_mcg_in, multicast_gid)); 11757efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DETACH_FROM_MCG); 11767efce369SYishai Hadas break; 11777efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_XRCD: 11787efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DEALLOC_XRCD); 11797efce369SYishai Hadas break; 11807efce369SYishai Hadas default: 11817efce369SYishai Hadas /* The entry must match to one of the devx_is_obj_create_cmd */ 11827efce369SYishai Hadas WARN_ON(true); 11837efce369SYishai Hadas break; 11847efce369SYishai Hadas } 11857efce369SYishai Hadas } 11867efce369SYishai Hadas 1187534fd7aaSYishai Hadas static int devx_handle_mkey_indirect(struct devx_obj *obj, 1188534fd7aaSYishai Hadas struct mlx5_ib_dev *dev, 1189534fd7aaSYishai Hadas void *in, void *out) 1190534fd7aaSYishai Hadas { 1191534fd7aaSYishai Hadas struct mlx5_ib_devx_mr *devx_mr = &obj->devx_mr; 1192534fd7aaSYishai Hadas struct mlx5_core_mkey *mkey; 1193534fd7aaSYishai Hadas void *mkc; 1194534fd7aaSYishai Hadas u8 key; 1195534fd7aaSYishai Hadas 1196534fd7aaSYishai Hadas mkey = &devx_mr->mmkey; 1197534fd7aaSYishai Hadas mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry); 1198534fd7aaSYishai Hadas key = MLX5_GET(mkc, mkc, mkey_7_0); 1199534fd7aaSYishai Hadas mkey->key = mlx5_idx_to_mkey( 1200534fd7aaSYishai Hadas MLX5_GET(create_mkey_out, out, mkey_index)) | key; 1201534fd7aaSYishai Hadas mkey->type = MLX5_MKEY_INDIRECT_DEVX; 1202534fd7aaSYishai Hadas mkey->iova = MLX5_GET64(mkc, mkc, start_addr); 1203534fd7aaSYishai Hadas mkey->size = MLX5_GET64(mkc, mkc, len); 1204534fd7aaSYishai Hadas mkey->pd = MLX5_GET(mkc, mkc, pd); 1205534fd7aaSYishai Hadas devx_mr->ndescs = MLX5_GET(mkc, mkc, translations_octword_size); 1206534fd7aaSYishai Hadas 1207792c4e9dSMatthew Wilcox return xa_err(xa_store(&dev->mdev->priv.mkey_table, 1208792c4e9dSMatthew Wilcox mlx5_base_mkey(mkey->key), mkey, GFP_KERNEL)); 1209534fd7aaSYishai Hadas } 1210534fd7aaSYishai Hadas 1211fa31f143SYishai Hadas static int devx_handle_mkey_create(struct mlx5_ib_dev *dev, 1212fa31f143SYishai Hadas struct devx_obj *obj, 1213fa31f143SYishai Hadas void *in, int in_len) 1214fa31f143SYishai Hadas { 1215fa31f143SYishai Hadas int min_len = MLX5_BYTE_OFF(create_mkey_in, memory_key_mkey_entry) + 1216fa31f143SYishai Hadas MLX5_FLD_SZ_BYTES(create_mkey_in, 1217fa31f143SYishai Hadas memory_key_mkey_entry); 1218fa31f143SYishai Hadas void *mkc; 1219fa31f143SYishai Hadas u8 access_mode; 1220fa31f143SYishai Hadas 1221fa31f143SYishai Hadas if (in_len < min_len) 1222fa31f143SYishai Hadas return -EINVAL; 1223fa31f143SYishai Hadas 1224fa31f143SYishai Hadas mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry); 1225fa31f143SYishai Hadas 1226fa31f143SYishai Hadas access_mode = MLX5_GET(mkc, mkc, access_mode_1_0); 1227fa31f143SYishai Hadas access_mode |= MLX5_GET(mkc, mkc, access_mode_4_2) << 2; 1228fa31f143SYishai Hadas 1229fa31f143SYishai Hadas if (access_mode == MLX5_MKC_ACCESS_MODE_KLMS || 1230534fd7aaSYishai Hadas access_mode == MLX5_MKC_ACCESS_MODE_KSM) { 1231534fd7aaSYishai Hadas if (IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING)) 1232534fd7aaSYishai Hadas obj->flags |= DEVX_OBJ_FLAGS_INDIRECT_MKEY; 1233fa31f143SYishai Hadas return 0; 1234534fd7aaSYishai Hadas } 1235fa31f143SYishai Hadas 1236fa31f143SYishai Hadas MLX5_SET(create_mkey_in, in, mkey_umem_valid, 1); 1237fa31f143SYishai Hadas return 0; 1238fa31f143SYishai Hadas } 1239fa31f143SYishai Hadas 1240534fd7aaSYishai Hadas static void devx_free_indirect_mkey(struct rcu_head *rcu) 1241534fd7aaSYishai Hadas { 1242534fd7aaSYishai Hadas kfree(container_of(rcu, struct devx_obj, devx_mr.rcu)); 1243534fd7aaSYishai Hadas } 1244534fd7aaSYishai Hadas 1245534fd7aaSYishai Hadas /* This function to delete from the radix tree needs to be called before 1246534fd7aaSYishai Hadas * destroying the underlying mkey. Otherwise a race might occur in case that 1247534fd7aaSYishai Hadas * other thread will get the same mkey before this one will be deleted, 1248534fd7aaSYishai Hadas * in that case it will fail via inserting to the tree its own data. 1249534fd7aaSYishai Hadas * 1250534fd7aaSYishai Hadas * Note: 1251534fd7aaSYishai Hadas * An error in the destroy is not expected unless there is some other indirect 1252534fd7aaSYishai Hadas * mkey which points to this one. In a kernel cleanup flow it will be just 1253534fd7aaSYishai Hadas * destroyed in the iterative destruction call. In a user flow, in case 1254534fd7aaSYishai Hadas * the application didn't close in the expected order it's its own problem, 1255534fd7aaSYishai Hadas * the mkey won't be part of the tree, in both cases the kernel is safe. 1256534fd7aaSYishai Hadas */ 1257534fd7aaSYishai Hadas static void devx_cleanup_mkey(struct devx_obj *obj) 1258534fd7aaSYishai Hadas { 1259792c4e9dSMatthew Wilcox xa_erase(&obj->mdev->priv.mkey_table, 1260792c4e9dSMatthew Wilcox mlx5_base_mkey(obj->devx_mr.mmkey.key)); 1261534fd7aaSYishai Hadas } 1262534fd7aaSYishai Hadas 1263*75973853SYishai Hadas static void devx_cleanup_subscription(struct mlx5_ib_dev *dev, 1264*75973853SYishai Hadas struct devx_event_subscription *sub) 1265*75973853SYishai Hadas { 1266*75973853SYishai Hadas struct devx_event *event; 1267*75973853SYishai Hadas struct devx_obj_event *xa_val_level2; 1268*75973853SYishai Hadas 1269*75973853SYishai Hadas if (sub->is_cleaned) 1270*75973853SYishai Hadas return; 1271*75973853SYishai Hadas 1272*75973853SYishai Hadas sub->is_cleaned = 1; 1273*75973853SYishai Hadas list_del_rcu(&sub->xa_list); 1274*75973853SYishai Hadas 1275*75973853SYishai Hadas if (list_empty(&sub->obj_list)) 1276*75973853SYishai Hadas return; 1277*75973853SYishai Hadas 1278*75973853SYishai Hadas list_del_rcu(&sub->obj_list); 1279*75973853SYishai Hadas /* check whether key level 1 for this obj_sub_list is empty */ 1280*75973853SYishai Hadas event = xa_load(&dev->devx_event_table.event_xa, 1281*75973853SYishai Hadas sub->xa_key_level1); 1282*75973853SYishai Hadas WARN_ON(!event); 1283*75973853SYishai Hadas 1284*75973853SYishai Hadas xa_val_level2 = xa_load(&event->object_ids, sub->xa_key_level2); 1285*75973853SYishai Hadas if (list_empty(&xa_val_level2->obj_sub_list)) { 1286*75973853SYishai Hadas xa_erase(&event->object_ids, 1287*75973853SYishai Hadas sub->xa_key_level2); 1288*75973853SYishai Hadas kfree_rcu(xa_val_level2, rcu); 1289*75973853SYishai Hadas } 1290*75973853SYishai Hadas } 1291*75973853SYishai Hadas 12927efce369SYishai Hadas static int devx_obj_cleanup(struct ib_uobject *uobject, 1293a6a3797dSShamir Rabinovitch enum rdma_remove_reason why, 1294a6a3797dSShamir Rabinovitch struct uverbs_attr_bundle *attrs) 12957efce369SYishai Hadas { 12967efce369SYishai Hadas u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)]; 1297*75973853SYishai Hadas struct mlx5_devx_event_table *devx_event_table; 12987efce369SYishai Hadas struct devx_obj *obj = uobject->object; 1299*75973853SYishai Hadas struct devx_event_subscription *sub_entry, *tmp; 1300*75973853SYishai Hadas struct mlx5_ib_dev *dev; 13017efce369SYishai Hadas int ret; 13027efce369SYishai Hadas 1303*75973853SYishai Hadas dev = mlx5_udata_to_mdev(&attrs->driver_udata); 1304534fd7aaSYishai Hadas if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY) 1305534fd7aaSYishai Hadas devx_cleanup_mkey(obj); 1306534fd7aaSYishai Hadas 1307c5ae1954SYishai Hadas if (obj->flags & DEVX_OBJ_FLAGS_DCT) 1308c5ae1954SYishai Hadas ret = mlx5_core_destroy_dct(obj->mdev, &obj->core_dct); 1309c5ae1954SYishai Hadas else 1310c5ae1954SYishai Hadas ret = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, 1311c5ae1954SYishai Hadas sizeof(out)); 13121c77483eSYishai Hadas if (ib_is_destroy_retryable(ret, why, uobject)) 13137efce369SYishai Hadas return ret; 13147efce369SYishai Hadas 1315*75973853SYishai Hadas devx_event_table = &dev->devx_event_table; 1316534fd7aaSYishai Hadas 1317*75973853SYishai Hadas mutex_lock(&devx_event_table->event_xa_lock); 1318*75973853SYishai Hadas list_for_each_entry_safe(sub_entry, tmp, &obj->event_sub, obj_list) 1319*75973853SYishai Hadas devx_cleanup_subscription(dev, sub_entry); 1320*75973853SYishai Hadas mutex_unlock(&devx_event_table->event_xa_lock); 1321*75973853SYishai Hadas 1322*75973853SYishai Hadas if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY) { 1323534fd7aaSYishai Hadas call_srcu(&dev->mr_srcu, &obj->devx_mr.rcu, 1324534fd7aaSYishai Hadas devx_free_indirect_mkey); 1325534fd7aaSYishai Hadas return ret; 1326534fd7aaSYishai Hadas } 1327534fd7aaSYishai Hadas 13287efce369SYishai Hadas kfree(obj); 13297efce369SYishai Hadas return ret; 13307efce369SYishai Hadas } 13317efce369SYishai Hadas 1332e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)( 133315a1b4beSJason Gunthorpe struct uverbs_attr_bundle *attrs) 13347efce369SYishai Hadas { 13357efce369SYishai Hadas void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN); 13367efce369SYishai Hadas int cmd_out_len = uverbs_attr_get_len(attrs, 13377efce369SYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT); 1338fa31f143SYishai Hadas int cmd_in_len = uverbs_attr_get_len(attrs, 1339fa31f143SYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN); 13407efce369SYishai Hadas void *cmd_out; 1341c36ee46dSJason Gunthorpe struct ib_uobject *uobj = uverbs_attr_get_uobject( 1342c36ee46dSJason Gunthorpe attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE); 134389944450SShamir Rabinovitch struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context( 134489944450SShamir Rabinovitch &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext); 1345c36ee46dSJason Gunthorpe struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device); 1346e8ef090aSYishai Hadas u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)]; 13477efce369SYishai Hadas struct devx_obj *obj; 1348cd5d20f1SYishai Hadas u16 obj_type = 0; 13497efce369SYishai Hadas int err; 13507e1335a7SYishai Hadas int uid; 13512351776eSYishai Hadas u32 obj_id; 13522351776eSYishai Hadas u16 opcode; 13537efce369SYishai Hadas 13547e1335a7SYishai Hadas uid = devx_get_uid(c, cmd_in); 13557e1335a7SYishai Hadas if (uid < 0) 13567e1335a7SYishai Hadas return uid; 13577efce369SYishai Hadas 13582351776eSYishai Hadas if (!devx_is_obj_create_cmd(cmd_in, &opcode)) 13597efce369SYishai Hadas return -EINVAL; 13607efce369SYishai Hadas 1361b61815e2SJason Gunthorpe cmd_out = uverbs_zalloc(attrs, cmd_out_len); 1362b61815e2SJason Gunthorpe if (IS_ERR(cmd_out)) 1363b61815e2SJason Gunthorpe return PTR_ERR(cmd_out); 1364b61815e2SJason Gunthorpe 13657efce369SYishai Hadas obj = kzalloc(sizeof(struct devx_obj), GFP_KERNEL); 13667efce369SYishai Hadas if (!obj) 13677efce369SYishai Hadas return -ENOMEM; 13687efce369SYishai Hadas 13697e1335a7SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); 1370fa31f143SYishai Hadas if (opcode == MLX5_CMD_OP_CREATE_MKEY) { 1371fa31f143SYishai Hadas err = devx_handle_mkey_create(dev, obj, cmd_in, cmd_in_len); 1372fa31f143SYishai Hadas if (err) 1373fa31f143SYishai Hadas goto obj_free; 1374fa31f143SYishai Hadas } else { 1375ba1a057dSYishai Hadas devx_set_umem_valid(cmd_in); 1376fa31f143SYishai Hadas } 1377ba1a057dSYishai Hadas 1378c5ae1954SYishai Hadas if (opcode == MLX5_CMD_OP_CREATE_DCT) { 1379c5ae1954SYishai Hadas obj->flags |= DEVX_OBJ_FLAGS_DCT; 1380c5ae1954SYishai Hadas err = mlx5_core_create_dct(dev->mdev, &obj->core_dct, 1381c5ae1954SYishai Hadas cmd_in, cmd_in_len, 1382c5ae1954SYishai Hadas cmd_out, cmd_out_len); 1383c5ae1954SYishai Hadas } else { 13847efce369SYishai Hadas err = mlx5_cmd_exec(dev->mdev, cmd_in, 1385fa31f143SYishai Hadas cmd_in_len, 13867efce369SYishai Hadas cmd_out, cmd_out_len); 1387c5ae1954SYishai Hadas } 1388c5ae1954SYishai Hadas 13897efce369SYishai Hadas if (err) 1390b61815e2SJason Gunthorpe goto obj_free; 13917efce369SYishai Hadas 13927efce369SYishai Hadas uobj->object = obj; 13937efce369SYishai Hadas obj->mdev = dev->mdev; 1394*75973853SYishai Hadas INIT_LIST_HEAD(&obj->event_sub); 13952351776eSYishai Hadas devx_obj_build_destroy_cmd(cmd_in, cmd_out, obj->dinbox, &obj->dinlen, 13962351776eSYishai Hadas &obj_id); 13977efce369SYishai Hadas WARN_ON(obj->dinlen > MLX5_MAX_DESTROY_INBOX_SIZE_DW * sizeof(u32)); 13987efce369SYishai Hadas 1399534fd7aaSYishai Hadas if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY) { 1400534fd7aaSYishai Hadas err = devx_handle_mkey_indirect(obj, dev, cmd_in, cmd_out); 1401534fd7aaSYishai Hadas if (err) 1402534fd7aaSYishai Hadas goto obj_destroy; 1403534fd7aaSYishai Hadas } 1404534fd7aaSYishai Hadas 14057efce369SYishai Hadas err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT, cmd_out, cmd_out_len); 14067efce369SYishai Hadas if (err) 14070da4d48dSYishai Hadas goto err_copy; 14087efce369SYishai Hadas 1409cd5d20f1SYishai Hadas if (opcode == MLX5_CMD_OP_CREATE_GENERAL_OBJECT) 1410cd5d20f1SYishai Hadas obj_type = MLX5_GET(general_obj_in_cmd_hdr, cmd_in, obj_type); 1411cd5d20f1SYishai Hadas 1412cd5d20f1SYishai Hadas obj->obj_id = get_enc_obj_id(opcode | obj_type << 16, obj_id); 1413cd5d20f1SYishai Hadas 14147efce369SYishai Hadas return 0; 14157efce369SYishai Hadas 14160da4d48dSYishai Hadas err_copy: 1417534fd7aaSYishai Hadas if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY) 1418534fd7aaSYishai Hadas devx_cleanup_mkey(obj); 14190da4d48dSYishai Hadas obj_destroy: 1420c5ae1954SYishai Hadas if (obj->flags & DEVX_OBJ_FLAGS_DCT) 1421c5ae1954SYishai Hadas mlx5_core_destroy_dct(obj->mdev, &obj->core_dct); 1422c5ae1954SYishai Hadas else 1423c5ae1954SYishai Hadas mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, 1424c5ae1954SYishai Hadas sizeof(out)); 14257efce369SYishai Hadas obj_free: 14267efce369SYishai Hadas kfree(obj); 14277efce369SYishai Hadas return err; 14287efce369SYishai Hadas } 14297efce369SYishai Hadas 1430e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_MODIFY)( 143115a1b4beSJason Gunthorpe struct uverbs_attr_bundle *attrs) 1432e662e14dSYishai Hadas { 1433e662e14dSYishai Hadas void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN); 1434e662e14dSYishai Hadas int cmd_out_len = uverbs_attr_get_len(attrs, 1435e662e14dSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT); 1436e662e14dSYishai Hadas struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs, 1437e662e14dSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE); 143889944450SShamir Rabinovitch struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context( 143989944450SShamir Rabinovitch &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext); 144089944450SShamir Rabinovitch struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device); 1441e662e14dSYishai Hadas void *cmd_out; 1442e662e14dSYishai Hadas int err; 14437e1335a7SYishai Hadas int uid; 1444e662e14dSYishai Hadas 14457e1335a7SYishai Hadas uid = devx_get_uid(c, cmd_in); 14467e1335a7SYishai Hadas if (uid < 0) 14477e1335a7SYishai Hadas return uid; 1448e662e14dSYishai Hadas 1449e662e14dSYishai Hadas if (!devx_is_obj_modify_cmd(cmd_in)) 1450e662e14dSYishai Hadas return -EINVAL; 1451e662e14dSYishai Hadas 1452e79c9c60SJason Gunthorpe if (!devx_is_valid_obj_id(attrs, uobj, cmd_in)) 1453e662e14dSYishai Hadas return -EINVAL; 1454e662e14dSYishai Hadas 1455b61815e2SJason Gunthorpe cmd_out = uverbs_zalloc(attrs, cmd_out_len); 1456b61815e2SJason Gunthorpe if (IS_ERR(cmd_out)) 1457b61815e2SJason Gunthorpe return PTR_ERR(cmd_out); 1458e662e14dSYishai Hadas 14597e1335a7SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); 1460ba1a057dSYishai Hadas devx_set_umem_valid(cmd_in); 1461ba1a057dSYishai Hadas 146234613eb1SYishai Hadas err = mlx5_cmd_exec(mdev->mdev, cmd_in, 1463e662e14dSYishai Hadas uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN), 1464e662e14dSYishai Hadas cmd_out, cmd_out_len); 1465e662e14dSYishai Hadas if (err) 1466e662e14dSYishai Hadas return err; 1467b61815e2SJason Gunthorpe 1468b61815e2SJason Gunthorpe return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT, 1469b61815e2SJason Gunthorpe cmd_out, cmd_out_len); 1470e662e14dSYishai Hadas } 1471e662e14dSYishai Hadas 1472e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)( 147315a1b4beSJason Gunthorpe struct uverbs_attr_bundle *attrs) 1474e662e14dSYishai Hadas { 1475e662e14dSYishai Hadas void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN); 1476e662e14dSYishai Hadas int cmd_out_len = uverbs_attr_get_len(attrs, 1477e662e14dSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT); 1478e662e14dSYishai Hadas struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs, 1479e662e14dSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE); 148089944450SShamir Rabinovitch struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context( 148189944450SShamir Rabinovitch &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext); 1482e662e14dSYishai Hadas void *cmd_out; 1483e662e14dSYishai Hadas int err; 14847e1335a7SYishai Hadas int uid; 148589944450SShamir Rabinovitch struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device); 1486e662e14dSYishai Hadas 14877e1335a7SYishai Hadas uid = devx_get_uid(c, cmd_in); 14887e1335a7SYishai Hadas if (uid < 0) 14897e1335a7SYishai Hadas return uid; 1490e662e14dSYishai Hadas 1491e662e14dSYishai Hadas if (!devx_is_obj_query_cmd(cmd_in)) 1492e662e14dSYishai Hadas return -EINVAL; 1493e662e14dSYishai Hadas 1494e79c9c60SJason Gunthorpe if (!devx_is_valid_obj_id(attrs, uobj, cmd_in)) 1495e662e14dSYishai Hadas return -EINVAL; 1496e662e14dSYishai Hadas 1497b61815e2SJason Gunthorpe cmd_out = uverbs_zalloc(attrs, cmd_out_len); 1498b61815e2SJason Gunthorpe if (IS_ERR(cmd_out)) 1499b61815e2SJason Gunthorpe return PTR_ERR(cmd_out); 1500e662e14dSYishai Hadas 15017e1335a7SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); 150234613eb1SYishai Hadas err = mlx5_cmd_exec(mdev->mdev, cmd_in, 1503e662e14dSYishai Hadas uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN), 1504e662e14dSYishai Hadas cmd_out, cmd_out_len); 1505e662e14dSYishai Hadas if (err) 1506e662e14dSYishai Hadas return err; 1507b61815e2SJason Gunthorpe 1508b61815e2SJason Gunthorpe return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT, 1509b61815e2SJason Gunthorpe cmd_out, cmd_out_len); 1510e662e14dSYishai Hadas } 1511e662e14dSYishai Hadas 15126bf8f22aSYishai Hadas struct devx_async_event_queue { 15136bf8f22aSYishai Hadas spinlock_t lock; 15146bf8f22aSYishai Hadas wait_queue_head_t poll_wait; 15156bf8f22aSYishai Hadas struct list_head event_list; 1516a124edbaSYishai Hadas atomic_t bytes_in_use; 1517eaebaf77SYishai Hadas u8 is_destroyed:1; 15186bf8f22aSYishai Hadas }; 15196bf8f22aSYishai Hadas 15206bf8f22aSYishai Hadas struct devx_async_cmd_event_file { 15216bf8f22aSYishai Hadas struct ib_uobject uobj; 15226bf8f22aSYishai Hadas struct devx_async_event_queue ev_queue; 1523a124edbaSYishai Hadas struct mlx5_async_ctx async_ctx; 15246bf8f22aSYishai Hadas }; 15256bf8f22aSYishai Hadas 15266bf8f22aSYishai Hadas static void devx_init_event_queue(struct devx_async_event_queue *ev_queue) 15276bf8f22aSYishai Hadas { 15286bf8f22aSYishai Hadas spin_lock_init(&ev_queue->lock); 15296bf8f22aSYishai Hadas INIT_LIST_HEAD(&ev_queue->event_list); 15306bf8f22aSYishai Hadas init_waitqueue_head(&ev_queue->poll_wait); 1531a124edbaSYishai Hadas atomic_set(&ev_queue->bytes_in_use, 0); 1532eaebaf77SYishai Hadas ev_queue->is_destroyed = 0; 15336bf8f22aSYishai Hadas } 15346bf8f22aSYishai Hadas 15356bf8f22aSYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC)( 15366bf8f22aSYishai Hadas struct uverbs_attr_bundle *attrs) 15376bf8f22aSYishai Hadas { 15386bf8f22aSYishai Hadas struct devx_async_cmd_event_file *ev_file; 15396bf8f22aSYishai Hadas 15406bf8f22aSYishai Hadas struct ib_uobject *uobj = uverbs_attr_get_uobject( 15416bf8f22aSYishai Hadas attrs, MLX5_IB_ATTR_DEVX_ASYNC_CMD_FD_ALLOC_HANDLE); 1542e79c9c60SJason Gunthorpe struct mlx5_ib_dev *mdev = mlx5_udata_to_mdev(&attrs->driver_udata); 15436bf8f22aSYishai Hadas 15446bf8f22aSYishai Hadas ev_file = container_of(uobj, struct devx_async_cmd_event_file, 15456bf8f22aSYishai Hadas uobj); 15466bf8f22aSYishai Hadas devx_init_event_queue(&ev_file->ev_queue); 1547a124edbaSYishai Hadas mlx5_cmd_init_async_ctx(mdev->mdev, &ev_file->async_ctx); 15486bf8f22aSYishai Hadas return 0; 15496bf8f22aSYishai Hadas } 15506bf8f22aSYishai Hadas 15512afc5e1bSYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_ASYNC_EVENT_FD_ALLOC)( 15522afc5e1bSYishai Hadas struct uverbs_attr_bundle *attrs) 15532afc5e1bSYishai Hadas { 15542afc5e1bSYishai Hadas struct ib_uobject *uobj = uverbs_attr_get_uobject( 15552afc5e1bSYishai Hadas attrs, MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_HANDLE); 15562afc5e1bSYishai Hadas struct devx_async_event_file *ev_file; 15572afc5e1bSYishai Hadas struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context( 15582afc5e1bSYishai Hadas &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext); 15592afc5e1bSYishai Hadas struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device); 15602afc5e1bSYishai Hadas u32 flags; 15612afc5e1bSYishai Hadas int err; 15622afc5e1bSYishai Hadas 15632afc5e1bSYishai Hadas err = uverbs_get_flags32(&flags, attrs, 15642afc5e1bSYishai Hadas MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_FLAGS, 15652afc5e1bSYishai Hadas MLX5_IB_UAPI_DEVX_CR_EV_CH_FLAGS_OMIT_DATA); 15662afc5e1bSYishai Hadas 15672afc5e1bSYishai Hadas if (err) 15682afc5e1bSYishai Hadas return err; 15692afc5e1bSYishai Hadas 15702afc5e1bSYishai Hadas ev_file = container_of(uobj, struct devx_async_event_file, 15712afc5e1bSYishai Hadas uobj); 15722afc5e1bSYishai Hadas spin_lock_init(&ev_file->lock); 15732afc5e1bSYishai Hadas INIT_LIST_HEAD(&ev_file->event_list); 15742afc5e1bSYishai Hadas init_waitqueue_head(&ev_file->poll_wait); 15752afc5e1bSYishai Hadas if (flags & MLX5_IB_UAPI_DEVX_CR_EV_CH_FLAGS_OMIT_DATA) 15762afc5e1bSYishai Hadas ev_file->omit_data = 1; 15772afc5e1bSYishai Hadas INIT_LIST_HEAD(&ev_file->subscribed_events_list); 15782afc5e1bSYishai Hadas ev_file->dev = dev; 1579*75973853SYishai Hadas get_device(&dev->ib_dev.dev); 15802afc5e1bSYishai Hadas return 0; 15812afc5e1bSYishai Hadas } 15822afc5e1bSYishai Hadas 1583a124edbaSYishai Hadas static void devx_query_callback(int status, struct mlx5_async_work *context) 1584a124edbaSYishai Hadas { 1585a124edbaSYishai Hadas struct devx_async_data *async_data = 1586a124edbaSYishai Hadas container_of(context, struct devx_async_data, cb_work); 1587a124edbaSYishai Hadas struct ib_uobject *fd_uobj = async_data->fd_uobj; 1588a124edbaSYishai Hadas struct devx_async_cmd_event_file *ev_file; 1589a124edbaSYishai Hadas struct devx_async_event_queue *ev_queue; 1590a124edbaSYishai Hadas unsigned long flags; 1591a124edbaSYishai Hadas 1592a124edbaSYishai Hadas ev_file = container_of(fd_uobj, struct devx_async_cmd_event_file, 1593a124edbaSYishai Hadas uobj); 1594a124edbaSYishai Hadas ev_queue = &ev_file->ev_queue; 1595a124edbaSYishai Hadas 1596a124edbaSYishai Hadas spin_lock_irqsave(&ev_queue->lock, flags); 1597a124edbaSYishai Hadas list_add_tail(&async_data->list, &ev_queue->event_list); 1598a124edbaSYishai Hadas spin_unlock_irqrestore(&ev_queue->lock, flags); 1599a124edbaSYishai Hadas 1600a124edbaSYishai Hadas wake_up_interruptible(&ev_queue->poll_wait); 1601a124edbaSYishai Hadas fput(fd_uobj->object); 1602a124edbaSYishai Hadas } 1603a124edbaSYishai Hadas 1604a124edbaSYishai Hadas #define MAX_ASYNC_BYTES_IN_USE (1024 * 1024) /* 1MB */ 1605a124edbaSYishai Hadas 1606a124edbaSYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY)( 1607a124edbaSYishai Hadas struct uverbs_attr_bundle *attrs) 1608a124edbaSYishai Hadas { 1609a124edbaSYishai Hadas void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, 1610a124edbaSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_CMD_IN); 1611a124edbaSYishai Hadas struct ib_uobject *uobj = uverbs_attr_get_uobject( 1612a124edbaSYishai Hadas attrs, 1613a124edbaSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_HANDLE); 1614a124edbaSYishai Hadas u16 cmd_out_len; 161589944450SShamir Rabinovitch struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context( 161689944450SShamir Rabinovitch &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext); 1617a124edbaSYishai Hadas struct ib_uobject *fd_uobj; 1618a124edbaSYishai Hadas int err; 1619a124edbaSYishai Hadas int uid; 162089944450SShamir Rabinovitch struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device); 1621a124edbaSYishai Hadas struct devx_async_cmd_event_file *ev_file; 1622a124edbaSYishai Hadas struct devx_async_data *async_data; 1623a124edbaSYishai Hadas 1624a124edbaSYishai Hadas uid = devx_get_uid(c, cmd_in); 1625a124edbaSYishai Hadas if (uid < 0) 1626a124edbaSYishai Hadas return uid; 1627a124edbaSYishai Hadas 1628a124edbaSYishai Hadas if (!devx_is_obj_query_cmd(cmd_in)) 1629a124edbaSYishai Hadas return -EINVAL; 1630a124edbaSYishai Hadas 1631a124edbaSYishai Hadas err = uverbs_get_const(&cmd_out_len, attrs, 1632a124edbaSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_OUT_LEN); 1633a124edbaSYishai Hadas if (err) 1634a124edbaSYishai Hadas return err; 1635a124edbaSYishai Hadas 1636e79c9c60SJason Gunthorpe if (!devx_is_valid_obj_id(attrs, uobj, cmd_in)) 1637a124edbaSYishai Hadas return -EINVAL; 1638a124edbaSYishai Hadas 1639a124edbaSYishai Hadas fd_uobj = uverbs_attr_get_uobject(attrs, 1640a124edbaSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_FD); 1641a124edbaSYishai Hadas if (IS_ERR(fd_uobj)) 1642a124edbaSYishai Hadas return PTR_ERR(fd_uobj); 1643a124edbaSYishai Hadas 1644a124edbaSYishai Hadas ev_file = container_of(fd_uobj, struct devx_async_cmd_event_file, 1645a124edbaSYishai Hadas uobj); 1646a124edbaSYishai Hadas 1647a124edbaSYishai Hadas if (atomic_add_return(cmd_out_len, &ev_file->ev_queue.bytes_in_use) > 1648a124edbaSYishai Hadas MAX_ASYNC_BYTES_IN_USE) { 1649a124edbaSYishai Hadas atomic_sub(cmd_out_len, &ev_file->ev_queue.bytes_in_use); 1650a124edbaSYishai Hadas return -EAGAIN; 1651a124edbaSYishai Hadas } 1652a124edbaSYishai Hadas 1653a124edbaSYishai Hadas async_data = kvzalloc(struct_size(async_data, hdr.out_data, 1654a124edbaSYishai Hadas cmd_out_len), GFP_KERNEL); 1655a124edbaSYishai Hadas if (!async_data) { 1656a124edbaSYishai Hadas err = -ENOMEM; 1657a124edbaSYishai Hadas goto sub_bytes; 1658a124edbaSYishai Hadas } 1659a124edbaSYishai Hadas 1660a124edbaSYishai Hadas err = uverbs_copy_from(&async_data->hdr.wr_id, attrs, 1661a124edbaSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_WR_ID); 1662a124edbaSYishai Hadas if (err) 1663a124edbaSYishai Hadas goto free_async; 1664a124edbaSYishai Hadas 1665a124edbaSYishai Hadas async_data->cmd_out_len = cmd_out_len; 1666a124edbaSYishai Hadas async_data->mdev = mdev; 1667a124edbaSYishai Hadas async_data->fd_uobj = fd_uobj; 1668a124edbaSYishai Hadas 1669a124edbaSYishai Hadas get_file(fd_uobj->object); 1670a124edbaSYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); 1671a124edbaSYishai Hadas err = mlx5_cmd_exec_cb(&ev_file->async_ctx, cmd_in, 1672a124edbaSYishai Hadas uverbs_attr_get_len(attrs, 1673a124edbaSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_CMD_IN), 1674a124edbaSYishai Hadas async_data->hdr.out_data, 1675a124edbaSYishai Hadas async_data->cmd_out_len, 1676a124edbaSYishai Hadas devx_query_callback, &async_data->cb_work); 1677a124edbaSYishai Hadas 1678a124edbaSYishai Hadas if (err) 1679a124edbaSYishai Hadas goto cb_err; 1680a124edbaSYishai Hadas 1681a124edbaSYishai Hadas return 0; 1682a124edbaSYishai Hadas 1683a124edbaSYishai Hadas cb_err: 1684a124edbaSYishai Hadas fput(fd_uobj->object); 1685a124edbaSYishai Hadas free_async: 1686a124edbaSYishai Hadas kvfree(async_data); 1687a124edbaSYishai Hadas sub_bytes: 1688a124edbaSYishai Hadas atomic_sub(cmd_out_len, &ev_file->ev_queue.bytes_in_use); 1689a124edbaSYishai Hadas return err; 1690a124edbaSYishai Hadas } 1691a124edbaSYishai Hadas 1692*75973853SYishai Hadas static void 1693*75973853SYishai Hadas subscribe_event_xa_dealloc(struct mlx5_devx_event_table *devx_event_table, 1694*75973853SYishai Hadas u32 key_level1, 1695*75973853SYishai Hadas bool is_level2, 1696*75973853SYishai Hadas u32 key_level2) 1697*75973853SYishai Hadas { 1698*75973853SYishai Hadas struct devx_event *event; 1699*75973853SYishai Hadas struct devx_obj_event *xa_val_level2; 1700*75973853SYishai Hadas 1701*75973853SYishai Hadas /* Level 1 is valid for future use, no need to free */ 1702*75973853SYishai Hadas if (!is_level2) 1703*75973853SYishai Hadas return; 1704*75973853SYishai Hadas 1705*75973853SYishai Hadas event = xa_load(&devx_event_table->event_xa, key_level1); 1706*75973853SYishai Hadas WARN_ON(!event); 1707*75973853SYishai Hadas 1708*75973853SYishai Hadas xa_val_level2 = xa_load(&event->object_ids, 1709*75973853SYishai Hadas key_level2); 1710*75973853SYishai Hadas if (list_empty(&xa_val_level2->obj_sub_list)) { 1711*75973853SYishai Hadas xa_erase(&event->object_ids, 1712*75973853SYishai Hadas key_level2); 1713*75973853SYishai Hadas kfree_rcu(xa_val_level2, rcu); 1714*75973853SYishai Hadas } 1715*75973853SYishai Hadas } 1716*75973853SYishai Hadas 1717*75973853SYishai Hadas static int 1718*75973853SYishai Hadas subscribe_event_xa_alloc(struct mlx5_devx_event_table *devx_event_table, 1719*75973853SYishai Hadas u32 key_level1, 1720*75973853SYishai Hadas bool is_level2, 1721*75973853SYishai Hadas u32 key_level2) 1722*75973853SYishai Hadas { 1723*75973853SYishai Hadas struct devx_obj_event *obj_event; 1724*75973853SYishai Hadas struct devx_event *event; 1725*75973853SYishai Hadas int err; 1726*75973853SYishai Hadas 1727*75973853SYishai Hadas event = xa_load(&devx_event_table->event_xa, key_level1); 1728*75973853SYishai Hadas if (!event) { 1729*75973853SYishai Hadas event = kzalloc(sizeof(*event), GFP_KERNEL); 1730*75973853SYishai Hadas if (!event) 1731*75973853SYishai Hadas return -ENOMEM; 1732*75973853SYishai Hadas 1733*75973853SYishai Hadas INIT_LIST_HEAD(&event->unaffiliated_list); 1734*75973853SYishai Hadas xa_init(&event->object_ids); 1735*75973853SYishai Hadas 1736*75973853SYishai Hadas err = xa_insert(&devx_event_table->event_xa, 1737*75973853SYishai Hadas key_level1, 1738*75973853SYishai Hadas event, 1739*75973853SYishai Hadas GFP_KERNEL); 1740*75973853SYishai Hadas if (err) { 1741*75973853SYishai Hadas kfree(event); 1742*75973853SYishai Hadas return err; 1743*75973853SYishai Hadas } 1744*75973853SYishai Hadas } 1745*75973853SYishai Hadas 1746*75973853SYishai Hadas if (!is_level2) 1747*75973853SYishai Hadas return 0; 1748*75973853SYishai Hadas 1749*75973853SYishai Hadas obj_event = xa_load(&event->object_ids, key_level2); 1750*75973853SYishai Hadas if (!obj_event) { 1751*75973853SYishai Hadas obj_event = kzalloc(sizeof(*obj_event), GFP_KERNEL); 1752*75973853SYishai Hadas if (!obj_event) 1753*75973853SYishai Hadas /* Level1 is valid for future use, no need to free */ 1754*75973853SYishai Hadas return -ENOMEM; 1755*75973853SYishai Hadas 1756*75973853SYishai Hadas err = xa_insert(&event->object_ids, 1757*75973853SYishai Hadas key_level2, 1758*75973853SYishai Hadas obj_event, 1759*75973853SYishai Hadas GFP_KERNEL); 1760*75973853SYishai Hadas if (err) 1761*75973853SYishai Hadas return err; 1762*75973853SYishai Hadas INIT_LIST_HEAD(&obj_event->obj_sub_list); 1763*75973853SYishai Hadas } 1764*75973853SYishai Hadas 1765*75973853SYishai Hadas return 0; 1766*75973853SYishai Hadas } 1767*75973853SYishai Hadas 1768*75973853SYishai Hadas static bool is_valid_events_legacy(int num_events, u16 *event_type_num_list, 1769*75973853SYishai Hadas struct devx_obj *obj) 1770*75973853SYishai Hadas { 1771*75973853SYishai Hadas int i; 1772*75973853SYishai Hadas 1773*75973853SYishai Hadas for (i = 0; i < num_events; i++) { 1774*75973853SYishai Hadas if (obj) { 1775*75973853SYishai Hadas if (!is_legacy_obj_event_num(event_type_num_list[i])) 1776*75973853SYishai Hadas return false; 1777*75973853SYishai Hadas } else if (!is_legacy_unaffiliated_event_num( 1778*75973853SYishai Hadas event_type_num_list[i])) { 1779*75973853SYishai Hadas return false; 1780*75973853SYishai Hadas } 1781*75973853SYishai Hadas } 1782*75973853SYishai Hadas 1783*75973853SYishai Hadas return true; 1784*75973853SYishai Hadas } 1785*75973853SYishai Hadas 1786*75973853SYishai Hadas #define MAX_SUPP_EVENT_NUM 255 1787*75973853SYishai Hadas static bool is_valid_events(struct mlx5_core_dev *dev, 1788*75973853SYishai Hadas int num_events, u16 *event_type_num_list, 1789*75973853SYishai Hadas struct devx_obj *obj) 1790*75973853SYishai Hadas { 1791*75973853SYishai Hadas __be64 *aff_events; 1792*75973853SYishai Hadas __be64 *unaff_events; 1793*75973853SYishai Hadas int mask_entry; 1794*75973853SYishai Hadas int mask_bit; 1795*75973853SYishai Hadas int i; 1796*75973853SYishai Hadas 1797*75973853SYishai Hadas if (MLX5_CAP_GEN(dev, event_cap)) { 1798*75973853SYishai Hadas aff_events = MLX5_CAP_DEV_EVENT(dev, 1799*75973853SYishai Hadas user_affiliated_events); 1800*75973853SYishai Hadas unaff_events = MLX5_CAP_DEV_EVENT(dev, 1801*75973853SYishai Hadas user_unaffiliated_events); 1802*75973853SYishai Hadas } else { 1803*75973853SYishai Hadas return is_valid_events_legacy(num_events, event_type_num_list, 1804*75973853SYishai Hadas obj); 1805*75973853SYishai Hadas } 1806*75973853SYishai Hadas 1807*75973853SYishai Hadas for (i = 0; i < num_events; i++) { 1808*75973853SYishai Hadas if (event_type_num_list[i] > MAX_SUPP_EVENT_NUM) 1809*75973853SYishai Hadas return false; 1810*75973853SYishai Hadas 1811*75973853SYishai Hadas mask_entry = event_type_num_list[i] / 64; 1812*75973853SYishai Hadas mask_bit = event_type_num_list[i] % 64; 1813*75973853SYishai Hadas 1814*75973853SYishai Hadas if (obj) { 1815*75973853SYishai Hadas /* CQ completion */ 1816*75973853SYishai Hadas if (event_type_num_list[i] == 0) 1817*75973853SYishai Hadas continue; 1818*75973853SYishai Hadas 1819*75973853SYishai Hadas if (!(be64_to_cpu(aff_events[mask_entry]) & 1820*75973853SYishai Hadas (1ull << mask_bit))) 1821*75973853SYishai Hadas return false; 1822*75973853SYishai Hadas 1823*75973853SYishai Hadas continue; 1824*75973853SYishai Hadas } 1825*75973853SYishai Hadas 1826*75973853SYishai Hadas if (!(be64_to_cpu(unaff_events[mask_entry]) & 1827*75973853SYishai Hadas (1ull << mask_bit))) 1828*75973853SYishai Hadas return false; 1829*75973853SYishai Hadas } 1830*75973853SYishai Hadas 1831*75973853SYishai Hadas return true; 1832*75973853SYishai Hadas } 1833*75973853SYishai Hadas 1834*75973853SYishai Hadas #define MAX_NUM_EVENTS 16 1835*75973853SYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT)( 1836*75973853SYishai Hadas struct uverbs_attr_bundle *attrs) 1837*75973853SYishai Hadas { 1838*75973853SYishai Hadas struct ib_uobject *devx_uobj = uverbs_attr_get_uobject( 1839*75973853SYishai Hadas attrs, 1840*75973853SYishai Hadas MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_OBJ_HANDLE); 1841*75973853SYishai Hadas struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context( 1842*75973853SYishai Hadas &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext); 1843*75973853SYishai Hadas struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device); 1844*75973853SYishai Hadas struct ib_uobject *fd_uobj; 1845*75973853SYishai Hadas struct devx_obj *obj = NULL; 1846*75973853SYishai Hadas struct devx_async_event_file *ev_file; 1847*75973853SYishai Hadas struct mlx5_devx_event_table *devx_event_table = &dev->devx_event_table; 1848*75973853SYishai Hadas u16 *event_type_num_list; 1849*75973853SYishai Hadas struct devx_event_subscription *event_sub, *tmp_sub; 1850*75973853SYishai Hadas struct list_head sub_list; 1851*75973853SYishai Hadas int redirect_fd; 1852*75973853SYishai Hadas bool use_eventfd = false; 1853*75973853SYishai Hadas int num_events; 1854*75973853SYishai Hadas int num_alloc_xa_entries = 0; 1855*75973853SYishai Hadas u16 obj_type = 0; 1856*75973853SYishai Hadas u64 cookie = 0; 1857*75973853SYishai Hadas u32 obj_id = 0; 1858*75973853SYishai Hadas int err; 1859*75973853SYishai Hadas int i; 1860*75973853SYishai Hadas 1861*75973853SYishai Hadas if (!c->devx_uid) 1862*75973853SYishai Hadas return -EINVAL; 1863*75973853SYishai Hadas 1864*75973853SYishai Hadas if (!IS_ERR(devx_uobj)) { 1865*75973853SYishai Hadas obj = (struct devx_obj *)devx_uobj->object; 1866*75973853SYishai Hadas if (obj) 1867*75973853SYishai Hadas obj_id = get_dec_obj_id(obj->obj_id); 1868*75973853SYishai Hadas } 1869*75973853SYishai Hadas 1870*75973853SYishai Hadas fd_uobj = uverbs_attr_get_uobject(attrs, 1871*75973853SYishai Hadas MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_HANDLE); 1872*75973853SYishai Hadas if (IS_ERR(fd_uobj)) 1873*75973853SYishai Hadas return PTR_ERR(fd_uobj); 1874*75973853SYishai Hadas 1875*75973853SYishai Hadas ev_file = container_of(fd_uobj, struct devx_async_event_file, 1876*75973853SYishai Hadas uobj); 1877*75973853SYishai Hadas 1878*75973853SYishai Hadas if (uverbs_attr_is_valid(attrs, 1879*75973853SYishai Hadas MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_NUM)) { 1880*75973853SYishai Hadas err = uverbs_copy_from(&redirect_fd, attrs, 1881*75973853SYishai Hadas MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_NUM); 1882*75973853SYishai Hadas if (err) 1883*75973853SYishai Hadas return err; 1884*75973853SYishai Hadas 1885*75973853SYishai Hadas use_eventfd = true; 1886*75973853SYishai Hadas } 1887*75973853SYishai Hadas 1888*75973853SYishai Hadas if (uverbs_attr_is_valid(attrs, 1889*75973853SYishai Hadas MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_COOKIE)) { 1890*75973853SYishai Hadas if (use_eventfd) 1891*75973853SYishai Hadas return -EINVAL; 1892*75973853SYishai Hadas 1893*75973853SYishai Hadas err = uverbs_copy_from(&cookie, attrs, 1894*75973853SYishai Hadas MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_COOKIE); 1895*75973853SYishai Hadas if (err) 1896*75973853SYishai Hadas return err; 1897*75973853SYishai Hadas } 1898*75973853SYishai Hadas 1899*75973853SYishai Hadas num_events = uverbs_attr_ptr_get_array_size( 1900*75973853SYishai Hadas attrs, MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_TYPE_NUM_LIST, 1901*75973853SYishai Hadas sizeof(u16)); 1902*75973853SYishai Hadas 1903*75973853SYishai Hadas if (num_events < 0) 1904*75973853SYishai Hadas return num_events; 1905*75973853SYishai Hadas 1906*75973853SYishai Hadas if (num_events > MAX_NUM_EVENTS) 1907*75973853SYishai Hadas return -EINVAL; 1908*75973853SYishai Hadas 1909*75973853SYishai Hadas event_type_num_list = uverbs_attr_get_alloced_ptr(attrs, 1910*75973853SYishai Hadas MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_TYPE_NUM_LIST); 1911*75973853SYishai Hadas 1912*75973853SYishai Hadas if (!is_valid_events(dev->mdev, num_events, event_type_num_list, obj)) 1913*75973853SYishai Hadas return -EINVAL; 1914*75973853SYishai Hadas 1915*75973853SYishai Hadas INIT_LIST_HEAD(&sub_list); 1916*75973853SYishai Hadas 1917*75973853SYishai Hadas /* Protect from concurrent subscriptions to same XA entries to allow 1918*75973853SYishai Hadas * both to succeed 1919*75973853SYishai Hadas */ 1920*75973853SYishai Hadas mutex_lock(&devx_event_table->event_xa_lock); 1921*75973853SYishai Hadas for (i = 0; i < num_events; i++) { 1922*75973853SYishai Hadas u32 key_level1; 1923*75973853SYishai Hadas 1924*75973853SYishai Hadas if (obj) 1925*75973853SYishai Hadas obj_type = get_dec_obj_type(obj, 1926*75973853SYishai Hadas event_type_num_list[i]); 1927*75973853SYishai Hadas key_level1 = event_type_num_list[i] | obj_type << 16; 1928*75973853SYishai Hadas 1929*75973853SYishai Hadas err = subscribe_event_xa_alloc(devx_event_table, 1930*75973853SYishai Hadas key_level1, 1931*75973853SYishai Hadas obj, 1932*75973853SYishai Hadas obj_id); 1933*75973853SYishai Hadas if (err) 1934*75973853SYishai Hadas goto err; 1935*75973853SYishai Hadas 1936*75973853SYishai Hadas num_alloc_xa_entries++; 1937*75973853SYishai Hadas event_sub = kzalloc(sizeof(*event_sub), GFP_KERNEL); 1938*75973853SYishai Hadas if (!event_sub) 1939*75973853SYishai Hadas goto err; 1940*75973853SYishai Hadas 1941*75973853SYishai Hadas list_add_tail(&event_sub->event_list, &sub_list); 1942*75973853SYishai Hadas if (use_eventfd) { 1943*75973853SYishai Hadas event_sub->eventfd = 1944*75973853SYishai Hadas eventfd_ctx_fdget(redirect_fd); 1945*75973853SYishai Hadas 1946*75973853SYishai Hadas if (IS_ERR(event_sub)) { 1947*75973853SYishai Hadas err = PTR_ERR(event_sub->eventfd); 1948*75973853SYishai Hadas event_sub->eventfd = NULL; 1949*75973853SYishai Hadas goto err; 1950*75973853SYishai Hadas } 1951*75973853SYishai Hadas } 1952*75973853SYishai Hadas 1953*75973853SYishai Hadas event_sub->cookie = cookie; 1954*75973853SYishai Hadas event_sub->ev_file = ev_file; 1955*75973853SYishai Hadas event_sub->filp = fd_uobj->object; 1956*75973853SYishai Hadas /* May be needed upon cleanup the devx object/subscription */ 1957*75973853SYishai Hadas event_sub->xa_key_level1 = key_level1; 1958*75973853SYishai Hadas event_sub->xa_key_level2 = obj_id; 1959*75973853SYishai Hadas INIT_LIST_HEAD(&event_sub->obj_list); 1960*75973853SYishai Hadas } 1961*75973853SYishai Hadas 1962*75973853SYishai Hadas /* Once all the allocations and the XA data insertions were done we 1963*75973853SYishai Hadas * can go ahead and add all the subscriptions to the relevant lists 1964*75973853SYishai Hadas * without concern of a failure. 1965*75973853SYishai Hadas */ 1966*75973853SYishai Hadas list_for_each_entry_safe(event_sub, tmp_sub, &sub_list, event_list) { 1967*75973853SYishai Hadas struct devx_event *event; 1968*75973853SYishai Hadas struct devx_obj_event *obj_event; 1969*75973853SYishai Hadas 1970*75973853SYishai Hadas list_del_init(&event_sub->event_list); 1971*75973853SYishai Hadas 1972*75973853SYishai Hadas spin_lock_irq(&ev_file->lock); 1973*75973853SYishai Hadas list_add_tail_rcu(&event_sub->file_list, 1974*75973853SYishai Hadas &ev_file->subscribed_events_list); 1975*75973853SYishai Hadas spin_unlock_irq(&ev_file->lock); 1976*75973853SYishai Hadas 1977*75973853SYishai Hadas event = xa_load(&devx_event_table->event_xa, 1978*75973853SYishai Hadas event_sub->xa_key_level1); 1979*75973853SYishai Hadas WARN_ON(!event); 1980*75973853SYishai Hadas 1981*75973853SYishai Hadas if (!obj) { 1982*75973853SYishai Hadas list_add_tail_rcu(&event_sub->xa_list, 1983*75973853SYishai Hadas &event->unaffiliated_list); 1984*75973853SYishai Hadas continue; 1985*75973853SYishai Hadas } 1986*75973853SYishai Hadas 1987*75973853SYishai Hadas obj_event = xa_load(&event->object_ids, obj_id); 1988*75973853SYishai Hadas WARN_ON(!obj_event); 1989*75973853SYishai Hadas list_add_tail_rcu(&event_sub->xa_list, 1990*75973853SYishai Hadas &obj_event->obj_sub_list); 1991*75973853SYishai Hadas list_add_tail_rcu(&event_sub->obj_list, 1992*75973853SYishai Hadas &obj->event_sub); 1993*75973853SYishai Hadas } 1994*75973853SYishai Hadas 1995*75973853SYishai Hadas mutex_unlock(&devx_event_table->event_xa_lock); 1996*75973853SYishai Hadas return 0; 1997*75973853SYishai Hadas 1998*75973853SYishai Hadas err: 1999*75973853SYishai Hadas list_for_each_entry_safe(event_sub, tmp_sub, &sub_list, event_list) { 2000*75973853SYishai Hadas list_del(&event_sub->event_list); 2001*75973853SYishai Hadas 2002*75973853SYishai Hadas subscribe_event_xa_dealloc(devx_event_table, 2003*75973853SYishai Hadas event_sub->xa_key_level1, 2004*75973853SYishai Hadas obj, 2005*75973853SYishai Hadas obj_id); 2006*75973853SYishai Hadas 2007*75973853SYishai Hadas if (event_sub->eventfd) 2008*75973853SYishai Hadas eventfd_ctx_put(event_sub->eventfd); 2009*75973853SYishai Hadas 2010*75973853SYishai Hadas kfree(event_sub); 2011*75973853SYishai Hadas } 2012*75973853SYishai Hadas 2013*75973853SYishai Hadas mutex_unlock(&devx_event_table->event_xa_lock); 2014*75973853SYishai Hadas return err; 2015*75973853SYishai Hadas } 2016*75973853SYishai Hadas 2017aeae9457SYishai Hadas static int devx_umem_get(struct mlx5_ib_dev *dev, struct ib_ucontext *ucontext, 2018aeae9457SYishai Hadas struct uverbs_attr_bundle *attrs, 2019aeae9457SYishai Hadas struct devx_umem *obj) 2020aeae9457SYishai Hadas { 2021aeae9457SYishai Hadas u64 addr; 2022aeae9457SYishai Hadas size_t size; 2023bccd0622SJason Gunthorpe u32 access; 2024aeae9457SYishai Hadas int npages; 2025aeae9457SYishai Hadas int err; 2026aeae9457SYishai Hadas u32 page_mask; 2027aeae9457SYishai Hadas 2028aeae9457SYishai Hadas if (uverbs_copy_from(&addr, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR) || 2029bccd0622SJason Gunthorpe uverbs_copy_from(&size, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_LEN)) 2030aeae9457SYishai Hadas return -EFAULT; 2031aeae9457SYishai Hadas 2032bccd0622SJason Gunthorpe err = uverbs_get_flags32(&access, attrs, 2033bccd0622SJason Gunthorpe MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS, 203447f07f03SYishai Hadas IB_ACCESS_LOCAL_WRITE | 203547f07f03SYishai Hadas IB_ACCESS_REMOTE_WRITE | 203647f07f03SYishai Hadas IB_ACCESS_REMOTE_READ); 2037bccd0622SJason Gunthorpe if (err) 2038bccd0622SJason Gunthorpe return err; 2039bccd0622SJason Gunthorpe 2040aeae9457SYishai Hadas err = ib_check_mr_access(access); 2041aeae9457SYishai Hadas if (err) 2042aeae9457SYishai Hadas return err; 2043aeae9457SYishai Hadas 2044b0ea0fa5SJason Gunthorpe obj->umem = ib_umem_get(&attrs->driver_udata, addr, size, access, 0); 2045aeae9457SYishai Hadas if (IS_ERR(obj->umem)) 2046aeae9457SYishai Hadas return PTR_ERR(obj->umem); 2047aeae9457SYishai Hadas 2048aeae9457SYishai Hadas mlx5_ib_cont_pages(obj->umem, obj->umem->address, 2049aeae9457SYishai Hadas MLX5_MKEY_PAGE_SHIFT_MASK, &npages, 2050aeae9457SYishai Hadas &obj->page_shift, &obj->ncont, NULL); 2051aeae9457SYishai Hadas 2052aeae9457SYishai Hadas if (!npages) { 2053aeae9457SYishai Hadas ib_umem_release(obj->umem); 2054aeae9457SYishai Hadas return -EINVAL; 2055aeae9457SYishai Hadas } 2056aeae9457SYishai Hadas 2057aeae9457SYishai Hadas page_mask = (1 << obj->page_shift) - 1; 2058aeae9457SYishai Hadas obj->page_offset = obj->umem->address & page_mask; 2059aeae9457SYishai Hadas 2060aeae9457SYishai Hadas return 0; 2061aeae9457SYishai Hadas } 2062aeae9457SYishai Hadas 2063b61815e2SJason Gunthorpe static int devx_umem_reg_cmd_alloc(struct uverbs_attr_bundle *attrs, 2064b61815e2SJason Gunthorpe struct devx_umem *obj, 2065aeae9457SYishai Hadas struct devx_umem_reg_cmd *cmd) 2066aeae9457SYishai Hadas { 2067aeae9457SYishai Hadas cmd->inlen = MLX5_ST_SZ_BYTES(create_umem_in) + 2068aeae9457SYishai Hadas (MLX5_ST_SZ_BYTES(mtt) * obj->ncont); 2069b61815e2SJason Gunthorpe cmd->in = uverbs_zalloc(attrs, cmd->inlen); 2070b61815e2SJason Gunthorpe return PTR_ERR_OR_ZERO(cmd->in); 2071aeae9457SYishai Hadas } 2072aeae9457SYishai Hadas 2073aeae9457SYishai Hadas static void devx_umem_reg_cmd_build(struct mlx5_ib_dev *dev, 2074aeae9457SYishai Hadas struct devx_umem *obj, 2075aeae9457SYishai Hadas struct devx_umem_reg_cmd *cmd) 2076aeae9457SYishai Hadas { 2077aeae9457SYishai Hadas void *umem; 2078aeae9457SYishai Hadas __be64 *mtt; 2079aeae9457SYishai Hadas 2080aeae9457SYishai Hadas umem = MLX5_ADDR_OF(create_umem_in, cmd->in, umem); 2081aeae9457SYishai Hadas mtt = (__be64 *)MLX5_ADDR_OF(umem, umem, mtt); 2082aeae9457SYishai Hadas 20836e3722baSYishai Hadas MLX5_SET(create_umem_in, cmd->in, opcode, MLX5_CMD_OP_CREATE_UMEM); 2084aeae9457SYishai Hadas MLX5_SET64(umem, umem, num_of_mtt, obj->ncont); 2085aeae9457SYishai Hadas MLX5_SET(umem, umem, log_page_size, obj->page_shift - 2086aeae9457SYishai Hadas MLX5_ADAPTER_PAGE_SHIFT); 2087aeae9457SYishai Hadas MLX5_SET(umem, umem, page_offset, obj->page_offset); 2088aeae9457SYishai Hadas mlx5_ib_populate_pas(dev, obj->umem, obj->page_shift, mtt, 2089aeae9457SYishai Hadas (obj->umem->writable ? MLX5_IB_MTT_WRITE : 0) | 2090aeae9457SYishai Hadas MLX5_IB_MTT_READ); 2091aeae9457SYishai Hadas } 2092aeae9457SYishai Hadas 2093e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_UMEM_REG)( 209415a1b4beSJason Gunthorpe struct uverbs_attr_bundle *attrs) 2095aeae9457SYishai Hadas { 2096aeae9457SYishai Hadas struct devx_umem_reg_cmd cmd; 2097aeae9457SYishai Hadas struct devx_umem *obj; 2098c36ee46dSJason Gunthorpe struct ib_uobject *uobj = uverbs_attr_get_uobject( 2099c36ee46dSJason Gunthorpe attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE); 2100aeae9457SYishai Hadas u32 obj_id; 210189944450SShamir Rabinovitch struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context( 210289944450SShamir Rabinovitch &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext); 2103c36ee46dSJason Gunthorpe struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device); 2104aeae9457SYishai Hadas int err; 2105aeae9457SYishai Hadas 2106aeae9457SYishai Hadas if (!c->devx_uid) 21077e1335a7SYishai Hadas return -EINVAL; 21087e1335a7SYishai Hadas 2109aeae9457SYishai Hadas obj = kzalloc(sizeof(struct devx_umem), GFP_KERNEL); 2110aeae9457SYishai Hadas if (!obj) 2111aeae9457SYishai Hadas return -ENOMEM; 2112aeae9457SYishai Hadas 2113aeae9457SYishai Hadas err = devx_umem_get(dev, &c->ibucontext, attrs, obj); 2114aeae9457SYishai Hadas if (err) 2115aeae9457SYishai Hadas goto err_obj_free; 2116aeae9457SYishai Hadas 2117b61815e2SJason Gunthorpe err = devx_umem_reg_cmd_alloc(attrs, obj, &cmd); 2118aeae9457SYishai Hadas if (err) 2119aeae9457SYishai Hadas goto err_umem_release; 2120aeae9457SYishai Hadas 2121aeae9457SYishai Hadas devx_umem_reg_cmd_build(dev, obj, &cmd); 2122aeae9457SYishai Hadas 21236e3722baSYishai Hadas MLX5_SET(create_umem_in, cmd.in, uid, c->devx_uid); 2124aeae9457SYishai Hadas err = mlx5_cmd_exec(dev->mdev, cmd.in, cmd.inlen, cmd.out, 2125aeae9457SYishai Hadas sizeof(cmd.out)); 2126aeae9457SYishai Hadas if (err) 2127b61815e2SJason Gunthorpe goto err_umem_release; 2128aeae9457SYishai Hadas 2129aeae9457SYishai Hadas obj->mdev = dev->mdev; 2130aeae9457SYishai Hadas uobj->object = obj; 2131aeae9457SYishai Hadas devx_obj_build_destroy_cmd(cmd.in, cmd.out, obj->dinbox, &obj->dinlen, &obj_id); 2132aeae9457SYishai Hadas err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID, &obj_id, sizeof(obj_id)); 2133aeae9457SYishai Hadas if (err) 2134aeae9457SYishai Hadas goto err_umem_destroy; 2135aeae9457SYishai Hadas 2136aeae9457SYishai Hadas return 0; 2137aeae9457SYishai Hadas 2138aeae9457SYishai Hadas err_umem_destroy: 2139aeae9457SYishai Hadas mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, cmd.out, sizeof(cmd.out)); 2140aeae9457SYishai Hadas err_umem_release: 2141aeae9457SYishai Hadas ib_umem_release(obj->umem); 2142aeae9457SYishai Hadas err_obj_free: 2143aeae9457SYishai Hadas kfree(obj); 2144aeae9457SYishai Hadas return err; 2145aeae9457SYishai Hadas } 2146aeae9457SYishai Hadas 2147aeae9457SYishai Hadas static int devx_umem_cleanup(struct ib_uobject *uobject, 2148a6a3797dSShamir Rabinovitch enum rdma_remove_reason why, 2149a6a3797dSShamir Rabinovitch struct uverbs_attr_bundle *attrs) 2150aeae9457SYishai Hadas { 2151aeae9457SYishai Hadas struct devx_umem *obj = uobject->object; 2152aeae9457SYishai Hadas u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)]; 2153aeae9457SYishai Hadas int err; 2154aeae9457SYishai Hadas 2155aeae9457SYishai Hadas err = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out)); 21561c77483eSYishai Hadas if (ib_is_destroy_retryable(err, why, uobject)) 2157aeae9457SYishai Hadas return err; 2158aeae9457SYishai Hadas 2159aeae9457SYishai Hadas ib_umem_release(obj->umem); 2160aeae9457SYishai Hadas kfree(obj); 2161aeae9457SYishai Hadas return 0; 2162aeae9457SYishai Hadas } 2163aeae9457SYishai Hadas 2164e337dd53SYishai Hadas static int devx_event_notifier(struct notifier_block *nb, 2165e337dd53SYishai Hadas unsigned long event_type, void *data) 2166e337dd53SYishai Hadas { 2167e337dd53SYishai Hadas return NOTIFY_DONE; 2168e337dd53SYishai Hadas } 2169e337dd53SYishai Hadas 2170e337dd53SYishai Hadas void mlx5_ib_devx_init_event_table(struct mlx5_ib_dev *dev) 2171e337dd53SYishai Hadas { 2172e337dd53SYishai Hadas struct mlx5_devx_event_table *table = &dev->devx_event_table; 2173e337dd53SYishai Hadas 2174e337dd53SYishai Hadas xa_init(&table->event_xa); 2175e337dd53SYishai Hadas mutex_init(&table->event_xa_lock); 2176e337dd53SYishai Hadas MLX5_NB_INIT(&table->devx_nb, devx_event_notifier, NOTIFY_ANY); 2177e337dd53SYishai Hadas mlx5_eq_notifier_register(dev->mdev, &table->devx_nb); 2178e337dd53SYishai Hadas } 2179e337dd53SYishai Hadas 2180e337dd53SYishai Hadas void mlx5_ib_devx_cleanup_event_table(struct mlx5_ib_dev *dev) 2181e337dd53SYishai Hadas { 2182e337dd53SYishai Hadas struct mlx5_devx_event_table *table = &dev->devx_event_table; 2183*75973853SYishai Hadas struct devx_event_subscription *sub, *tmp; 2184*75973853SYishai Hadas struct devx_event *event; 2185e337dd53SYishai Hadas void *entry; 2186e337dd53SYishai Hadas unsigned long id; 2187e337dd53SYishai Hadas 2188e337dd53SYishai Hadas mlx5_eq_notifier_unregister(dev->mdev, &table->devx_nb); 2189*75973853SYishai Hadas mutex_lock(&dev->devx_event_table.event_xa_lock); 2190*75973853SYishai Hadas xa_for_each(&table->event_xa, id, entry) { 2191*75973853SYishai Hadas event = entry; 2192*75973853SYishai Hadas list_for_each_entry_safe(sub, tmp, &event->unaffiliated_list, 2193*75973853SYishai Hadas xa_list) 2194*75973853SYishai Hadas devx_cleanup_subscription(dev, sub); 2195e337dd53SYishai Hadas kfree(entry); 2196*75973853SYishai Hadas } 2197*75973853SYishai Hadas mutex_unlock(&dev->devx_event_table.event_xa_lock); 2198e337dd53SYishai Hadas xa_destroy(&table->event_xa); 2199e337dd53SYishai Hadas } 2200e337dd53SYishai Hadas 22016bf8f22aSYishai Hadas static ssize_t devx_async_cmd_event_read(struct file *filp, char __user *buf, 22026bf8f22aSYishai Hadas size_t count, loff_t *pos) 22036bf8f22aSYishai Hadas { 22044accbb3fSYishai Hadas struct devx_async_cmd_event_file *comp_ev_file = filp->private_data; 22054accbb3fSYishai Hadas struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue; 22064accbb3fSYishai Hadas struct devx_async_data *event; 22074accbb3fSYishai Hadas int ret = 0; 22084accbb3fSYishai Hadas size_t eventsz; 22094accbb3fSYishai Hadas 22104accbb3fSYishai Hadas spin_lock_irq(&ev_queue->lock); 22114accbb3fSYishai Hadas 22124accbb3fSYishai Hadas while (list_empty(&ev_queue->event_list)) { 22134accbb3fSYishai Hadas spin_unlock_irq(&ev_queue->lock); 22144accbb3fSYishai Hadas 22154accbb3fSYishai Hadas if (filp->f_flags & O_NONBLOCK) 22164accbb3fSYishai Hadas return -EAGAIN; 22174accbb3fSYishai Hadas 22184accbb3fSYishai Hadas if (wait_event_interruptible( 22194accbb3fSYishai Hadas ev_queue->poll_wait, 2220eaebaf77SYishai Hadas (!list_empty(&ev_queue->event_list) || 2221eaebaf77SYishai Hadas ev_queue->is_destroyed))) { 22224accbb3fSYishai Hadas return -ERESTARTSYS; 22234accbb3fSYishai Hadas } 2224eaebaf77SYishai Hadas 2225eaebaf77SYishai Hadas if (list_empty(&ev_queue->event_list) && 2226eaebaf77SYishai Hadas ev_queue->is_destroyed) 2227eaebaf77SYishai Hadas return -EIO; 2228eaebaf77SYishai Hadas 22294accbb3fSYishai Hadas spin_lock_irq(&ev_queue->lock); 22304accbb3fSYishai Hadas } 22314accbb3fSYishai Hadas 22324accbb3fSYishai Hadas event = list_entry(ev_queue->event_list.next, 22334accbb3fSYishai Hadas struct devx_async_data, list); 22344accbb3fSYishai Hadas eventsz = event->cmd_out_len + 22354accbb3fSYishai Hadas sizeof(struct mlx5_ib_uapi_devx_async_cmd_hdr); 22364accbb3fSYishai Hadas 22374accbb3fSYishai Hadas if (eventsz > count) { 22384accbb3fSYishai Hadas spin_unlock_irq(&ev_queue->lock); 22394accbb3fSYishai Hadas return -ENOSPC; 22404accbb3fSYishai Hadas } 22414accbb3fSYishai Hadas 22424accbb3fSYishai Hadas list_del(ev_queue->event_list.next); 22434accbb3fSYishai Hadas spin_unlock_irq(&ev_queue->lock); 22444accbb3fSYishai Hadas 22454accbb3fSYishai Hadas if (copy_to_user(buf, &event->hdr, eventsz)) 22464accbb3fSYishai Hadas ret = -EFAULT; 22474accbb3fSYishai Hadas else 22484accbb3fSYishai Hadas ret = eventsz; 22494accbb3fSYishai Hadas 22504accbb3fSYishai Hadas atomic_sub(event->cmd_out_len, &ev_queue->bytes_in_use); 22514accbb3fSYishai Hadas kvfree(event); 22524accbb3fSYishai Hadas return ret; 22536bf8f22aSYishai Hadas } 22546bf8f22aSYishai Hadas 22556bf8f22aSYishai Hadas static int devx_async_cmd_event_close(struct inode *inode, struct file *filp) 22566bf8f22aSYishai Hadas { 2257a124edbaSYishai Hadas struct ib_uobject *uobj = filp->private_data; 2258a124edbaSYishai Hadas struct devx_async_cmd_event_file *comp_ev_file = container_of( 2259a124edbaSYishai Hadas uobj, struct devx_async_cmd_event_file, uobj); 2260a124edbaSYishai Hadas struct devx_async_data *entry, *tmp; 2261a124edbaSYishai Hadas 2262a124edbaSYishai Hadas spin_lock_irq(&comp_ev_file->ev_queue.lock); 2263a124edbaSYishai Hadas list_for_each_entry_safe(entry, tmp, 2264a124edbaSYishai Hadas &comp_ev_file->ev_queue.event_list, list) 2265a124edbaSYishai Hadas kvfree(entry); 2266a124edbaSYishai Hadas spin_unlock_irq(&comp_ev_file->ev_queue.lock); 2267a124edbaSYishai Hadas 22686bf8f22aSYishai Hadas uverbs_close_fd(filp); 22696bf8f22aSYishai Hadas return 0; 22706bf8f22aSYishai Hadas } 22716bf8f22aSYishai Hadas 22726bf8f22aSYishai Hadas static __poll_t devx_async_cmd_event_poll(struct file *filp, 22736bf8f22aSYishai Hadas struct poll_table_struct *wait) 22746bf8f22aSYishai Hadas { 22754accbb3fSYishai Hadas struct devx_async_cmd_event_file *comp_ev_file = filp->private_data; 22764accbb3fSYishai Hadas struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue; 22774accbb3fSYishai Hadas __poll_t pollflags = 0; 22784accbb3fSYishai Hadas 22794accbb3fSYishai Hadas poll_wait(filp, &ev_queue->poll_wait, wait); 22804accbb3fSYishai Hadas 22814accbb3fSYishai Hadas spin_lock_irq(&ev_queue->lock); 2282eaebaf77SYishai Hadas if (ev_queue->is_destroyed) 2283eaebaf77SYishai Hadas pollflags = EPOLLIN | EPOLLRDNORM | EPOLLRDHUP; 2284eaebaf77SYishai Hadas else if (!list_empty(&ev_queue->event_list)) 22854accbb3fSYishai Hadas pollflags = EPOLLIN | EPOLLRDNORM; 22864accbb3fSYishai Hadas spin_unlock_irq(&ev_queue->lock); 22874accbb3fSYishai Hadas 22884accbb3fSYishai Hadas return pollflags; 22896bf8f22aSYishai Hadas } 22906bf8f22aSYishai Hadas 22911f687edeSBart Van Assche static const struct file_operations devx_async_cmd_event_fops = { 22926bf8f22aSYishai Hadas .owner = THIS_MODULE, 22936bf8f22aSYishai Hadas .read = devx_async_cmd_event_read, 22946bf8f22aSYishai Hadas .poll = devx_async_cmd_event_poll, 22956bf8f22aSYishai Hadas .release = devx_async_cmd_event_close, 22966bf8f22aSYishai Hadas .llseek = no_llseek, 22976bf8f22aSYishai Hadas }; 22986bf8f22aSYishai Hadas 22992afc5e1bSYishai Hadas static ssize_t devx_async_event_read(struct file *filp, char __user *buf, 23002afc5e1bSYishai Hadas size_t count, loff_t *pos) 23012afc5e1bSYishai Hadas { 23022afc5e1bSYishai Hadas return -EINVAL; 23032afc5e1bSYishai Hadas } 23042afc5e1bSYishai Hadas 23052afc5e1bSYishai Hadas static __poll_t devx_async_event_poll(struct file *filp, 23062afc5e1bSYishai Hadas struct poll_table_struct *wait) 23072afc5e1bSYishai Hadas { 23082afc5e1bSYishai Hadas return 0; 23092afc5e1bSYishai Hadas } 23102afc5e1bSYishai Hadas 23112afc5e1bSYishai Hadas static int devx_async_event_close(struct inode *inode, struct file *filp) 23122afc5e1bSYishai Hadas { 2313*75973853SYishai Hadas struct devx_async_event_file *ev_file = filp->private_data; 2314*75973853SYishai Hadas struct devx_event_subscription *event_sub, *event_sub_tmp; 2315*75973853SYishai Hadas 2316*75973853SYishai Hadas mutex_lock(&ev_file->dev->devx_event_table.event_xa_lock); 2317*75973853SYishai Hadas /* delete the subscriptions which are related to this FD */ 2318*75973853SYishai Hadas list_for_each_entry_safe(event_sub, event_sub_tmp, 2319*75973853SYishai Hadas &ev_file->subscribed_events_list, file_list) { 2320*75973853SYishai Hadas devx_cleanup_subscription(ev_file->dev, event_sub); 2321*75973853SYishai Hadas if (event_sub->eventfd) 2322*75973853SYishai Hadas eventfd_ctx_put(event_sub->eventfd); 2323*75973853SYishai Hadas 2324*75973853SYishai Hadas list_del_rcu(&event_sub->file_list); 2325*75973853SYishai Hadas /* subscription may not be used by the read API any more */ 2326*75973853SYishai Hadas kfree_rcu(event_sub, rcu); 2327*75973853SYishai Hadas } 2328*75973853SYishai Hadas 2329*75973853SYishai Hadas mutex_unlock(&ev_file->dev->devx_event_table.event_xa_lock); 2330*75973853SYishai Hadas 23312afc5e1bSYishai Hadas uverbs_close_fd(filp); 2332*75973853SYishai Hadas put_device(&ev_file->dev->ib_dev.dev); 23332afc5e1bSYishai Hadas return 0; 23342afc5e1bSYishai Hadas } 23352afc5e1bSYishai Hadas 23362afc5e1bSYishai Hadas static const struct file_operations devx_async_event_fops = { 23372afc5e1bSYishai Hadas .owner = THIS_MODULE, 23382afc5e1bSYishai Hadas .read = devx_async_event_read, 23392afc5e1bSYishai Hadas .poll = devx_async_event_poll, 23402afc5e1bSYishai Hadas .release = devx_async_event_close, 23412afc5e1bSYishai Hadas .llseek = no_llseek, 23422afc5e1bSYishai Hadas }; 23432afc5e1bSYishai Hadas 23446bf8f22aSYishai Hadas static int devx_hot_unplug_async_cmd_event_file(struct ib_uobject *uobj, 23456bf8f22aSYishai Hadas enum rdma_remove_reason why) 23466bf8f22aSYishai Hadas { 2347a124edbaSYishai Hadas struct devx_async_cmd_event_file *comp_ev_file = 2348a124edbaSYishai Hadas container_of(uobj, struct devx_async_cmd_event_file, 2349a124edbaSYishai Hadas uobj); 2350eaebaf77SYishai Hadas struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue; 2351eaebaf77SYishai Hadas 2352eaebaf77SYishai Hadas spin_lock_irq(&ev_queue->lock); 2353eaebaf77SYishai Hadas ev_queue->is_destroyed = 1; 2354eaebaf77SYishai Hadas spin_unlock_irq(&ev_queue->lock); 2355eaebaf77SYishai Hadas 2356eaebaf77SYishai Hadas if (why == RDMA_REMOVE_DRIVER_REMOVE) 2357eaebaf77SYishai Hadas wake_up_interruptible(&ev_queue->poll_wait); 2358a124edbaSYishai Hadas 2359a124edbaSYishai Hadas mlx5_cmd_cleanup_async_ctx(&comp_ev_file->async_ctx); 23606bf8f22aSYishai Hadas return 0; 23616bf8f22aSYishai Hadas }; 23626bf8f22aSYishai Hadas 23632afc5e1bSYishai Hadas static int devx_hot_unplug_async_event_file(struct ib_uobject *uobj, 23642afc5e1bSYishai Hadas enum rdma_remove_reason why) 23652afc5e1bSYishai Hadas { 23662afc5e1bSYishai Hadas return 0; 23672afc5e1bSYishai Hadas }; 23682afc5e1bSYishai Hadas 23699a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD( 23709a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_UMEM_REG, 23719a119cd5SJason Gunthorpe UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE, 2372aeae9457SYishai Hadas MLX5_IB_OBJECT_DEVX_UMEM, 2373aeae9457SYishai Hadas UVERBS_ACCESS_NEW, 237483bb4442SJason Gunthorpe UA_MANDATORY), 23759a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR, 23769a119cd5SJason Gunthorpe UVERBS_ATTR_TYPE(u64), 237783bb4442SJason Gunthorpe UA_MANDATORY), 23789a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_LEN, 23799a119cd5SJason Gunthorpe UVERBS_ATTR_TYPE(u64), 238083bb4442SJason Gunthorpe UA_MANDATORY), 2381bccd0622SJason Gunthorpe UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS, 2382bccd0622SJason Gunthorpe enum ib_access_flags), 23839a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID, 23849a119cd5SJason Gunthorpe UVERBS_ATTR_TYPE(u32), 238583bb4442SJason Gunthorpe UA_MANDATORY)); 2386aeae9457SYishai Hadas 2387528922afSYishai Hadas DECLARE_UVERBS_NAMED_METHOD_DESTROY( 23889a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_UMEM_DEREG, 23899a119cd5SJason Gunthorpe UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_DEREG_HANDLE, 2390aeae9457SYishai Hadas MLX5_IB_OBJECT_DEVX_UMEM, 2391aeae9457SYishai Hadas UVERBS_ACCESS_DESTROY, 239283bb4442SJason Gunthorpe UA_MANDATORY)); 2393aeae9457SYishai Hadas 23949a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD( 23959a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_QUERY_EQN, 23969a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC, 23979a119cd5SJason Gunthorpe UVERBS_ATTR_TYPE(u32), 239883bb4442SJason Gunthorpe UA_MANDATORY), 23999a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN, 24009a119cd5SJason Gunthorpe UVERBS_ATTR_TYPE(u32), 240183bb4442SJason Gunthorpe UA_MANDATORY)); 2402f6fe01b7SYishai Hadas 24039a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD( 24049a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_QUERY_UAR, 24059a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX, 24069a119cd5SJason Gunthorpe UVERBS_ATTR_TYPE(u32), 240783bb4442SJason Gunthorpe UA_MANDATORY), 24089a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX, 24099a119cd5SJason Gunthorpe UVERBS_ATTR_TYPE(u32), 241083bb4442SJason Gunthorpe UA_MANDATORY)); 24117c043e90SYishai Hadas 24129a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD( 24139a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_OTHER, 24149a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN( 24159a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OTHER_CMD_IN, 24168aa8c95cSYishai Hadas UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)), 241783bb4442SJason Gunthorpe UA_MANDATORY, 241883bb4442SJason Gunthorpe UA_ALLOC_AND_COPY), 24199a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_OUT( 24209a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT, 24217efce369SYishai Hadas UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)), 2422540cd692SJason Gunthorpe UA_MANDATORY)); 24237efce369SYishai Hadas 24249a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD( 24259a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_OBJ_CREATE, 24269a119cd5SJason Gunthorpe UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE, 24279a119cd5SJason Gunthorpe MLX5_IB_OBJECT_DEVX_OBJ, 24289a119cd5SJason Gunthorpe UVERBS_ACCESS_NEW, 242983bb4442SJason Gunthorpe UA_MANDATORY), 24309a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN( 24319a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN, 24329a119cd5SJason Gunthorpe UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)), 243383bb4442SJason Gunthorpe UA_MANDATORY, 243483bb4442SJason Gunthorpe UA_ALLOC_AND_COPY), 24359a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_OUT( 24369a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT, 24379a119cd5SJason Gunthorpe UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)), 2438540cd692SJason Gunthorpe UA_MANDATORY)); 24399a119cd5SJason Gunthorpe 2440528922afSYishai Hadas DECLARE_UVERBS_NAMED_METHOD_DESTROY( 24419a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_OBJ_DESTROY, 24429a119cd5SJason Gunthorpe UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_DESTROY_HANDLE, 24437efce369SYishai Hadas MLX5_IB_OBJECT_DEVX_OBJ, 24447efce369SYishai Hadas UVERBS_ACCESS_DESTROY, 244583bb4442SJason Gunthorpe UA_MANDATORY)); 24467efce369SYishai Hadas 24479a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD( 24489a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_OBJ_MODIFY, 24499a119cd5SJason Gunthorpe UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE, 245034613eb1SYishai Hadas UVERBS_IDR_ANY_OBJECT, 2451e662e14dSYishai Hadas UVERBS_ACCESS_WRITE, 245283bb4442SJason Gunthorpe UA_MANDATORY), 24539a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN( 24549a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN, 2455e662e14dSYishai Hadas UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)), 245683bb4442SJason Gunthorpe UA_MANDATORY, 245783bb4442SJason Gunthorpe UA_ALLOC_AND_COPY), 24589a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_OUT( 24599a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT, 2460e662e14dSYishai Hadas UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)), 2461540cd692SJason Gunthorpe UA_MANDATORY)); 2462e662e14dSYishai Hadas 24639a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD( 24649a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_OBJ_QUERY, 24659a119cd5SJason Gunthorpe UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE, 246634613eb1SYishai Hadas UVERBS_IDR_ANY_OBJECT, 2467e662e14dSYishai Hadas UVERBS_ACCESS_READ, 246883bb4442SJason Gunthorpe UA_MANDATORY), 24699a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN( 24709a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN, 2471e662e14dSYishai Hadas UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)), 247283bb4442SJason Gunthorpe UA_MANDATORY, 247383bb4442SJason Gunthorpe UA_ALLOC_AND_COPY), 24749a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_OUT( 24759a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT, 2476e662e14dSYishai Hadas UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)), 2477540cd692SJason Gunthorpe UA_MANDATORY)); 2478e662e14dSYishai Hadas 2479a124edbaSYishai Hadas DECLARE_UVERBS_NAMED_METHOD( 2480a124edbaSYishai Hadas MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY, 2481a124edbaSYishai Hadas UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE, 2482a124edbaSYishai Hadas UVERBS_IDR_ANY_OBJECT, 2483a124edbaSYishai Hadas UVERBS_ACCESS_READ, 2484a124edbaSYishai Hadas UA_MANDATORY), 2485a124edbaSYishai Hadas UVERBS_ATTR_PTR_IN( 2486a124edbaSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN, 2487a124edbaSYishai Hadas UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)), 2488a124edbaSYishai Hadas UA_MANDATORY, 2489a124edbaSYishai Hadas UA_ALLOC_AND_COPY), 2490a124edbaSYishai Hadas UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_OUT_LEN, 2491a124edbaSYishai Hadas u16, UA_MANDATORY), 2492a124edbaSYishai Hadas UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_FD, 2493a124edbaSYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD, 2494a124edbaSYishai Hadas UVERBS_ACCESS_READ, 2495a124edbaSYishai Hadas UA_MANDATORY), 2496a124edbaSYishai Hadas UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_WR_ID, 2497a124edbaSYishai Hadas UVERBS_ATTR_TYPE(u64), 2498a124edbaSYishai Hadas UA_MANDATORY)); 2499a124edbaSYishai Hadas 2500*75973853SYishai Hadas DECLARE_UVERBS_NAMED_METHOD( 2501*75973853SYishai Hadas MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT, 2502*75973853SYishai Hadas UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_HANDLE, 2503*75973853SYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD, 2504*75973853SYishai Hadas UVERBS_ACCESS_READ, 2505*75973853SYishai Hadas UA_MANDATORY), 2506*75973853SYishai Hadas UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_OBJ_HANDLE, 2507*75973853SYishai Hadas MLX5_IB_OBJECT_DEVX_OBJ, 2508*75973853SYishai Hadas UVERBS_ACCESS_READ, 2509*75973853SYishai Hadas UA_OPTIONAL), 2510*75973853SYishai Hadas UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_TYPE_NUM_LIST, 2511*75973853SYishai Hadas UVERBS_ATTR_MIN_SIZE(sizeof(u16)), 2512*75973853SYishai Hadas UA_MANDATORY, 2513*75973853SYishai Hadas UA_ALLOC_AND_COPY), 2514*75973853SYishai Hadas UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_COOKIE, 2515*75973853SYishai Hadas UVERBS_ATTR_TYPE(u64), 2516*75973853SYishai Hadas UA_OPTIONAL), 2517*75973853SYishai Hadas UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_NUM, 2518*75973853SYishai Hadas UVERBS_ATTR_TYPE(u32), 2519*75973853SYishai Hadas UA_OPTIONAL)); 2520*75973853SYishai Hadas 25216c61d2a5SJason Gunthorpe DECLARE_UVERBS_GLOBAL_METHODS(MLX5_IB_OBJECT_DEVX, 25227c043e90SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OTHER), 2523f6fe01b7SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_UAR), 2524*75973853SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_EQN), 2525*75973853SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT)); 25268aa8c95cSYishai Hadas 25276c61d2a5SJason Gunthorpe DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ, 25289a119cd5SJason Gunthorpe UVERBS_TYPE_ALLOC_IDR(devx_obj_cleanup), 25297efce369SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_CREATE), 2530e662e14dSYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_DESTROY), 2531e662e14dSYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_MODIFY), 2532a124edbaSYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_QUERY), 2533a124edbaSYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY)); 25347efce369SYishai Hadas 25356c61d2a5SJason Gunthorpe DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM, 25369a119cd5SJason Gunthorpe UVERBS_TYPE_ALLOC_IDR(devx_umem_cleanup), 2537aeae9457SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_REG), 2538aeae9457SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_DEREG)); 2539aeae9457SYishai Hadas 25406bf8f22aSYishai Hadas 25416bf8f22aSYishai Hadas DECLARE_UVERBS_NAMED_METHOD( 25426bf8f22aSYishai Hadas MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC, 25436bf8f22aSYishai Hadas UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_ASYNC_CMD_FD_ALLOC_HANDLE, 25446bf8f22aSYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD, 25456bf8f22aSYishai Hadas UVERBS_ACCESS_NEW, 25466bf8f22aSYishai Hadas UA_MANDATORY)); 25476bf8f22aSYishai Hadas 25486bf8f22aSYishai Hadas DECLARE_UVERBS_NAMED_OBJECT( 25496bf8f22aSYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD, 25506bf8f22aSYishai Hadas UVERBS_TYPE_ALLOC_FD(sizeof(struct devx_async_cmd_event_file), 25516bf8f22aSYishai Hadas devx_hot_unplug_async_cmd_event_file, 25526bf8f22aSYishai Hadas &devx_async_cmd_event_fops, "[devx_async_cmd]", 25536bf8f22aSYishai Hadas O_RDONLY), 25546bf8f22aSYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC)); 25556bf8f22aSYishai Hadas 25562afc5e1bSYishai Hadas DECLARE_UVERBS_NAMED_METHOD( 25572afc5e1bSYishai Hadas MLX5_IB_METHOD_DEVX_ASYNC_EVENT_FD_ALLOC, 25582afc5e1bSYishai Hadas UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_HANDLE, 25592afc5e1bSYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD, 25602afc5e1bSYishai Hadas UVERBS_ACCESS_NEW, 25612afc5e1bSYishai Hadas UA_MANDATORY), 25622afc5e1bSYishai Hadas UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_FLAGS, 25632afc5e1bSYishai Hadas enum mlx5_ib_uapi_devx_create_event_channel_flags, 25642afc5e1bSYishai Hadas UA_MANDATORY)); 25652afc5e1bSYishai Hadas 25662afc5e1bSYishai Hadas DECLARE_UVERBS_NAMED_OBJECT( 25672afc5e1bSYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD, 25682afc5e1bSYishai Hadas UVERBS_TYPE_ALLOC_FD(sizeof(struct devx_async_event_file), 25692afc5e1bSYishai Hadas devx_hot_unplug_async_event_file, 25702afc5e1bSYishai Hadas &devx_async_event_fops, "[devx_async_event]", 25712afc5e1bSYishai Hadas O_RDONLY), 25722afc5e1bSYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_ASYNC_EVENT_FD_ALLOC)); 25732afc5e1bSYishai Hadas 257436e235c8SJason Gunthorpe static bool devx_is_supported(struct ib_device *device) 2575c59450c4SYishai Hadas { 257636e235c8SJason Gunthorpe struct mlx5_ib_dev *dev = to_mdev(device); 257736e235c8SJason Gunthorpe 25787f575103SMark Bloch return MLX5_CAP_GEN(dev->mdev, log_max_uctx); 2579c59450c4SYishai Hadas } 258036e235c8SJason Gunthorpe 25810cbf432dSJason Gunthorpe const struct uapi_definition mlx5_ib_devx_defs[] = { 258236e235c8SJason Gunthorpe UAPI_DEF_CHAIN_OBJ_TREE_NAMED( 258336e235c8SJason Gunthorpe MLX5_IB_OBJECT_DEVX, 258436e235c8SJason Gunthorpe UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)), 258536e235c8SJason Gunthorpe UAPI_DEF_CHAIN_OBJ_TREE_NAMED( 258636e235c8SJason Gunthorpe MLX5_IB_OBJECT_DEVX_OBJ, 258736e235c8SJason Gunthorpe UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)), 258836e235c8SJason Gunthorpe UAPI_DEF_CHAIN_OBJ_TREE_NAMED( 258936e235c8SJason Gunthorpe MLX5_IB_OBJECT_DEVX_UMEM, 259036e235c8SJason Gunthorpe UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)), 25916bf8f22aSYishai Hadas UAPI_DEF_CHAIN_OBJ_TREE_NAMED( 25926bf8f22aSYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD, 25936bf8f22aSYishai Hadas UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)), 25942afc5e1bSYishai Hadas UAPI_DEF_CHAIN_OBJ_TREE_NAMED( 25952afc5e1bSYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD, 25962afc5e1bSYishai Hadas UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)), 25970cbf432dSJason Gunthorpe {}, 25980cbf432dSJason Gunthorpe }; 2599