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" 17f7c4ffdaSLeon Romanovsky #include "devx.h" 18333fbaa0SLeon Romanovsky #include "qp.h" 1975973853SYishai Hadas #include <linux/xarray.h> 20a8b92ca1SYishai Hadas 218aa8c95cSYishai Hadas #define UVERBS_MODULE_NAME mlx5_ib 228aa8c95cSYishai Hadas #include <rdma/uverbs_named_ioctl.h> 238aa8c95cSYishai Hadas 24ef1659adSYishai Hadas static void dispatch_event_fd(struct list_head *fd_list, const void *data); 25ef1659adSYishai Hadas 26534fd7aaSYishai Hadas enum devx_obj_flags { 27534fd7aaSYishai Hadas DEVX_OBJ_FLAGS_INDIRECT_MKEY = 1 << 0, 28c5ae1954SYishai Hadas DEVX_OBJ_FLAGS_DCT = 1 << 1, 29ef1659adSYishai Hadas DEVX_OBJ_FLAGS_CQ = 1 << 2, 30534fd7aaSYishai Hadas }; 31534fd7aaSYishai Hadas 32a124edbaSYishai Hadas struct devx_async_data { 33a124edbaSYishai Hadas struct mlx5_ib_dev *mdev; 34a124edbaSYishai Hadas struct list_head list; 3593887e66SJason Gunthorpe struct devx_async_cmd_event_file *ev_file; 36a124edbaSYishai Hadas struct mlx5_async_work cb_work; 37a124edbaSYishai Hadas u16 cmd_out_len; 38a124edbaSYishai Hadas /* must be last field in this structure */ 39a124edbaSYishai Hadas struct mlx5_ib_uapi_devx_async_cmd_hdr hdr; 40a124edbaSYishai Hadas }; 41a124edbaSYishai Hadas 425ec9d8eeSYishai Hadas struct devx_async_event_data { 435ec9d8eeSYishai Hadas struct list_head list; /* headed in ev_file->event_list */ 445ec9d8eeSYishai Hadas struct mlx5_ib_uapi_devx_async_event_hdr hdr; 455ec9d8eeSYishai Hadas }; 465ec9d8eeSYishai Hadas 4775973853SYishai Hadas /* first level XA value data structure */ 4875973853SYishai Hadas struct devx_event { 4975973853SYishai Hadas struct xarray object_ids; /* second XA level, Key = object id */ 5075973853SYishai Hadas struct list_head unaffiliated_list; 5175973853SYishai Hadas }; 5275973853SYishai Hadas 5375973853SYishai Hadas /* second level XA value data structure */ 5475973853SYishai Hadas struct devx_obj_event { 5575973853SYishai Hadas struct rcu_head rcu; 5675973853SYishai Hadas struct list_head obj_sub_list; 5775973853SYishai Hadas }; 5875973853SYishai Hadas 5975973853SYishai Hadas struct devx_event_subscription { 6075973853SYishai Hadas struct list_head file_list; /* headed in ev_file-> 6175973853SYishai Hadas * subscribed_events_list 6275973853SYishai Hadas */ 6375973853SYishai Hadas struct list_head xa_list; /* headed in devx_event->unaffiliated_list or 6475973853SYishai Hadas * devx_obj_event->obj_sub_list 6575973853SYishai Hadas */ 6675973853SYishai Hadas struct list_head obj_list; /* headed in devx_object */ 6775973853SYishai Hadas struct list_head event_list; /* headed in ev_file->event_list or in 6875973853SYishai Hadas * temp list via subscription 6975973853SYishai Hadas */ 7075973853SYishai Hadas 7175973853SYishai Hadas u8 is_cleaned:1; 7275973853SYishai Hadas u32 xa_key_level1; 7375973853SYishai Hadas u32 xa_key_level2; 7475973853SYishai Hadas struct rcu_head rcu; 7575973853SYishai Hadas u64 cookie; 7675973853SYishai Hadas struct devx_async_event_file *ev_file; 7775973853SYishai Hadas struct eventfd_ctx *eventfd; 7875973853SYishai Hadas }; 7975973853SYishai Hadas 802afc5e1bSYishai Hadas struct devx_async_event_file { 812afc5e1bSYishai Hadas struct ib_uobject uobj; 822afc5e1bSYishai Hadas /* Head of events that are subscribed to this FD */ 832afc5e1bSYishai Hadas struct list_head subscribed_events_list; 842afc5e1bSYishai Hadas spinlock_t lock; 852afc5e1bSYishai Hadas wait_queue_head_t poll_wait; 862afc5e1bSYishai Hadas struct list_head event_list; 872afc5e1bSYishai Hadas struct mlx5_ib_dev *dev; 882afc5e1bSYishai Hadas u8 omit_data:1; 895ec9d8eeSYishai Hadas u8 is_overflow_err:1; 905ec9d8eeSYishai Hadas u8 is_destroyed:1; 912afc5e1bSYishai Hadas }; 922afc5e1bSYishai Hadas 93aeae9457SYishai Hadas struct devx_umem { 94aeae9457SYishai Hadas struct mlx5_core_dev *mdev; 95aeae9457SYishai Hadas struct ib_umem *umem; 96aeae9457SYishai Hadas u32 dinlen; 97*1368ead0SYishai Hadas u32 dinbox[MLX5_ST_SZ_DW(destroy_umem_in)]; 98aeae9457SYishai Hadas }; 99aeae9457SYishai Hadas 100aeae9457SYishai Hadas struct devx_umem_reg_cmd { 101aeae9457SYishai Hadas void *in; 102aeae9457SYishai Hadas u32 inlen; 103*1368ead0SYishai Hadas u32 out[MLX5_ST_SZ_DW(create_umem_out)]; 104aeae9457SYishai Hadas }; 105aeae9457SYishai Hadas 10615a1b4beSJason Gunthorpe static struct mlx5_ib_ucontext * 10715a1b4beSJason Gunthorpe devx_ufile2uctx(const struct uverbs_attr_bundle *attrs) 1088aa8c95cSYishai Hadas { 10915a1b4beSJason Gunthorpe return to_mucontext(ib_uverbs_get_ucontext(attrs)); 1108aa8c95cSYishai Hadas } 1118aa8c95cSYishai Hadas 112fb98153bSYishai Hadas int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, bool is_user) 113a8b92ca1SYishai Hadas { 114*1368ead0SYishai Hadas u32 in[MLX5_ST_SZ_DW(create_uctx_in)] = {}; 115*1368ead0SYishai Hadas u32 out[MLX5_ST_SZ_DW(create_uctx_out)] = {}; 1166e3722baSYishai Hadas void *uctx; 117a8b92ca1SYishai Hadas int err; 11876dc5a84SYishai Hadas u16 uid; 119fb98153bSYishai Hadas u32 cap = 0; 120a8b92ca1SYishai Hadas 1216e3722baSYishai Hadas /* 0 means not supported */ 1226e3722baSYishai Hadas if (!MLX5_CAP_GEN(dev->mdev, log_max_uctx)) 123a8b92ca1SYishai Hadas return -EINVAL; 124a8b92ca1SYishai Hadas 1256e3722baSYishai Hadas uctx = MLX5_ADDR_OF(create_uctx_in, in, uctx); 126fb98153bSYishai Hadas if (is_user && capable(CAP_NET_RAW) && 127fb98153bSYishai Hadas (MLX5_CAP_GEN(dev->mdev, uctx_cap) & MLX5_UCTX_CAP_RAW_TX)) 128fb98153bSYishai Hadas cap |= MLX5_UCTX_CAP_RAW_TX; 12933cde96fSAriel Levkovich if (is_user && capable(CAP_SYS_RAWIO) && 13033cde96fSAriel Levkovich (MLX5_CAP_GEN(dev->mdev, uctx_cap) & 13133cde96fSAriel Levkovich MLX5_UCTX_CAP_INTERNAL_DEV_RES)) 13233cde96fSAriel Levkovich cap |= MLX5_UCTX_CAP_INTERNAL_DEV_RES; 133fb98153bSYishai Hadas 1346e3722baSYishai Hadas MLX5_SET(create_uctx_in, in, opcode, MLX5_CMD_OP_CREATE_UCTX); 135fb98153bSYishai Hadas MLX5_SET(uctx, uctx, cap, cap); 136a8b92ca1SYishai Hadas 137a8b92ca1SYishai Hadas err = mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out)); 138a8b92ca1SYishai Hadas if (err) 139a8b92ca1SYishai Hadas return err; 140a8b92ca1SYishai Hadas 141*1368ead0SYishai Hadas uid = MLX5_GET(create_uctx_out, out, uid); 14276dc5a84SYishai Hadas return uid; 143a8b92ca1SYishai Hadas } 144a8b92ca1SYishai Hadas 14576dc5a84SYishai Hadas void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev, u16 uid) 146a8b92ca1SYishai Hadas { 147*1368ead0SYishai Hadas u32 in[MLX5_ST_SZ_DW(destroy_uctx_in)] = {}; 148*1368ead0SYishai Hadas u32 out[MLX5_ST_SZ_DW(destroy_uctx_out)] = {}; 149a8b92ca1SYishai Hadas 1506e3722baSYishai Hadas MLX5_SET(destroy_uctx_in, in, opcode, MLX5_CMD_OP_DESTROY_UCTX); 1516e3722baSYishai Hadas MLX5_SET(destroy_uctx_in, in, uid, uid); 152a8b92ca1SYishai Hadas 153a8b92ca1SYishai Hadas mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out)); 154a8b92ca1SYishai Hadas } 1558aa8c95cSYishai Hadas 15675973853SYishai Hadas static bool is_legacy_unaffiliated_event_num(u16 event_num) 15775973853SYishai Hadas { 15875973853SYishai Hadas switch (event_num) { 15975973853SYishai Hadas case MLX5_EVENT_TYPE_PORT_CHANGE: 16075973853SYishai Hadas return true; 16175973853SYishai Hadas default: 16275973853SYishai Hadas return false; 16375973853SYishai Hadas } 16475973853SYishai Hadas } 16575973853SYishai Hadas 16675973853SYishai Hadas static bool is_legacy_obj_event_num(u16 event_num) 16775973853SYishai Hadas { 16875973853SYishai Hadas switch (event_num) { 16975973853SYishai Hadas case MLX5_EVENT_TYPE_PATH_MIG: 17075973853SYishai Hadas case MLX5_EVENT_TYPE_COMM_EST: 17175973853SYishai Hadas case MLX5_EVENT_TYPE_SQ_DRAINED: 17275973853SYishai Hadas case MLX5_EVENT_TYPE_SRQ_LAST_WQE: 17375973853SYishai Hadas case MLX5_EVENT_TYPE_SRQ_RQ_LIMIT: 17475973853SYishai Hadas case MLX5_EVENT_TYPE_CQ_ERROR: 17575973853SYishai Hadas case MLX5_EVENT_TYPE_WQ_CATAS_ERROR: 17675973853SYishai Hadas case MLX5_EVENT_TYPE_PATH_MIG_FAILED: 17775973853SYishai Hadas case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR: 17875973853SYishai Hadas case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR: 17975973853SYishai Hadas case MLX5_EVENT_TYPE_SRQ_CATAS_ERROR: 18075973853SYishai Hadas case MLX5_EVENT_TYPE_DCT_DRAINED: 18175973853SYishai Hadas case MLX5_EVENT_TYPE_COMP: 182972d7560SYishai Hadas case MLX5_EVENT_TYPE_DCT_KEY_VIOLATION: 183972d7560SYishai Hadas case MLX5_EVENT_TYPE_XRQ_ERROR: 18475973853SYishai Hadas return true; 18575973853SYishai Hadas default: 18675973853SYishai Hadas return false; 18775973853SYishai Hadas } 18875973853SYishai Hadas } 18975973853SYishai Hadas 19075973853SYishai Hadas static u16 get_legacy_obj_type(u16 opcode) 19175973853SYishai Hadas { 19275973853SYishai Hadas switch (opcode) { 19375973853SYishai Hadas case MLX5_CMD_OP_CREATE_RQ: 19475973853SYishai Hadas return MLX5_EVENT_QUEUE_TYPE_RQ; 19575973853SYishai Hadas case MLX5_CMD_OP_CREATE_QP: 19675973853SYishai Hadas return MLX5_EVENT_QUEUE_TYPE_QP; 19775973853SYishai Hadas case MLX5_CMD_OP_CREATE_SQ: 19875973853SYishai Hadas return MLX5_EVENT_QUEUE_TYPE_SQ; 19975973853SYishai Hadas case MLX5_CMD_OP_CREATE_DCT: 20075973853SYishai Hadas return MLX5_EVENT_QUEUE_TYPE_DCT; 20175973853SYishai Hadas default: 20275973853SYishai Hadas return 0; 20375973853SYishai Hadas } 20475973853SYishai Hadas } 20575973853SYishai Hadas 20675973853SYishai Hadas static u16 get_dec_obj_type(struct devx_obj *obj, u16 event_num) 20775973853SYishai Hadas { 20875973853SYishai Hadas u16 opcode; 20975973853SYishai Hadas 21075973853SYishai Hadas opcode = (obj->obj_id >> 32) & 0xffff; 21175973853SYishai Hadas 21275973853SYishai Hadas if (is_legacy_obj_event_num(event_num)) 21375973853SYishai Hadas return get_legacy_obj_type(opcode); 21475973853SYishai Hadas 21575973853SYishai Hadas switch (opcode) { 21675973853SYishai Hadas case MLX5_CMD_OP_CREATE_GENERAL_OBJECT: 21775973853SYishai Hadas return (obj->obj_id >> 48); 21875973853SYishai Hadas case MLX5_CMD_OP_CREATE_RQ: 21975973853SYishai Hadas return MLX5_OBJ_TYPE_RQ; 22075973853SYishai Hadas case MLX5_CMD_OP_CREATE_QP: 22175973853SYishai Hadas return MLX5_OBJ_TYPE_QP; 22275973853SYishai Hadas case MLX5_CMD_OP_CREATE_SQ: 22375973853SYishai Hadas return MLX5_OBJ_TYPE_SQ; 22475973853SYishai Hadas case MLX5_CMD_OP_CREATE_DCT: 22575973853SYishai Hadas return MLX5_OBJ_TYPE_DCT; 22675973853SYishai Hadas case MLX5_CMD_OP_CREATE_TIR: 22775973853SYishai Hadas return MLX5_OBJ_TYPE_TIR; 22875973853SYishai Hadas case MLX5_CMD_OP_CREATE_TIS: 22975973853SYishai Hadas return MLX5_OBJ_TYPE_TIS; 23075973853SYishai Hadas case MLX5_CMD_OP_CREATE_PSV: 23175973853SYishai Hadas return MLX5_OBJ_TYPE_PSV; 23275973853SYishai Hadas case MLX5_OBJ_TYPE_MKEY: 23375973853SYishai Hadas return MLX5_OBJ_TYPE_MKEY; 23475973853SYishai Hadas case MLX5_CMD_OP_CREATE_RMP: 23575973853SYishai Hadas return MLX5_OBJ_TYPE_RMP; 23675973853SYishai Hadas case MLX5_CMD_OP_CREATE_XRC_SRQ: 23775973853SYishai Hadas return MLX5_OBJ_TYPE_XRC_SRQ; 23875973853SYishai Hadas case MLX5_CMD_OP_CREATE_XRQ: 23975973853SYishai Hadas return MLX5_OBJ_TYPE_XRQ; 24075973853SYishai Hadas case MLX5_CMD_OP_CREATE_RQT: 24175973853SYishai Hadas return MLX5_OBJ_TYPE_RQT; 24275973853SYishai Hadas case MLX5_CMD_OP_ALLOC_FLOW_COUNTER: 24375973853SYishai Hadas return MLX5_OBJ_TYPE_FLOW_COUNTER; 24475973853SYishai Hadas case MLX5_CMD_OP_CREATE_CQ: 24575973853SYishai Hadas return MLX5_OBJ_TYPE_CQ; 24675973853SYishai Hadas default: 24775973853SYishai Hadas return 0; 24875973853SYishai Hadas } 24975973853SYishai Hadas } 25075973853SYishai Hadas 2515ec9d8eeSYishai Hadas static u16 get_event_obj_type(unsigned long event_type, struct mlx5_eqe *eqe) 2525ec9d8eeSYishai Hadas { 2535ec9d8eeSYishai Hadas switch (event_type) { 2545ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_WQ_CATAS_ERROR: 2555ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR: 2565ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR: 2575ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_SRQ_LAST_WQE: 2585ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_PATH_MIG: 2595ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_PATH_MIG_FAILED: 2605ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_COMM_EST: 2615ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_SQ_DRAINED: 2625ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_SRQ_RQ_LIMIT: 2635ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_SRQ_CATAS_ERROR: 2645ec9d8eeSYishai Hadas return eqe->data.qp_srq.type; 2655ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_CQ_ERROR: 266972d7560SYishai Hadas case MLX5_EVENT_TYPE_XRQ_ERROR: 2675ec9d8eeSYishai Hadas return 0; 2685ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_DCT_DRAINED: 269972d7560SYishai Hadas case MLX5_EVENT_TYPE_DCT_KEY_VIOLATION: 2705ec9d8eeSYishai Hadas return MLX5_EVENT_QUEUE_TYPE_DCT; 2715ec9d8eeSYishai Hadas default: 2725ec9d8eeSYishai Hadas return MLX5_GET(affiliated_event_header, &eqe->data, obj_type); 2735ec9d8eeSYishai Hadas } 2745ec9d8eeSYishai Hadas } 2755ec9d8eeSYishai Hadas 27675973853SYishai Hadas static u32 get_dec_obj_id(u64 obj_id) 27775973853SYishai Hadas { 27875973853SYishai Hadas return (obj_id & 0xffffffff); 27975973853SYishai Hadas } 28075973853SYishai Hadas 2812351776eSYishai Hadas /* 2822351776eSYishai Hadas * As the obj_id in the firmware is not globally unique the object type 2832351776eSYishai Hadas * must be considered upon checking for a valid object id. 2842351776eSYishai Hadas * For that the opcode of the creator command is encoded as part of the obj_id. 2852351776eSYishai Hadas */ 286cd5d20f1SYishai Hadas static u64 get_enc_obj_id(u32 opcode, u32 obj_id) 2872351776eSYishai Hadas { 2882351776eSYishai Hadas return ((u64)opcode << 32) | obj_id; 2892351776eSYishai Hadas } 2902351776eSYishai Hadas 291*1368ead0SYishai Hadas static u32 devx_get_created_obj_id(const void *in, const void *out, u16 opcode) 292*1368ead0SYishai Hadas { 293*1368ead0SYishai Hadas switch (opcode) { 294*1368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_GENERAL_OBJECT: 295*1368ead0SYishai Hadas return MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 296*1368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_UMEM: 297*1368ead0SYishai Hadas return MLX5_GET(create_umem_out, out, umem_id); 298*1368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_MKEY: 299*1368ead0SYishai Hadas return MLX5_GET(create_mkey_out, out, mkey_index); 300*1368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_CQ: 301*1368ead0SYishai Hadas return MLX5_GET(create_cq_out, out, cqn); 302*1368ead0SYishai Hadas case MLX5_CMD_OP_ALLOC_PD: 303*1368ead0SYishai Hadas return MLX5_GET(alloc_pd_out, out, pd); 304*1368ead0SYishai Hadas case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN: 305*1368ead0SYishai Hadas return MLX5_GET(alloc_transport_domain_out, out, 306*1368ead0SYishai Hadas transport_domain); 307*1368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_RMP: 308*1368ead0SYishai Hadas return MLX5_GET(create_rmp_out, out, rmpn); 309*1368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_SQ: 310*1368ead0SYishai Hadas return MLX5_GET(create_sq_out, out, sqn); 311*1368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_RQ: 312*1368ead0SYishai Hadas return MLX5_GET(create_rq_out, out, rqn); 313*1368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_RQT: 314*1368ead0SYishai Hadas return MLX5_GET(create_rqt_out, out, rqtn); 315*1368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_TIR: 316*1368ead0SYishai Hadas return MLX5_GET(create_tir_out, out, tirn); 317*1368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_TIS: 318*1368ead0SYishai Hadas return MLX5_GET(create_tis_out, out, tisn); 319*1368ead0SYishai Hadas case MLX5_CMD_OP_ALLOC_Q_COUNTER: 320*1368ead0SYishai Hadas return MLX5_GET(alloc_q_counter_out, out, counter_set_id); 321*1368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_FLOW_TABLE: 322*1368ead0SYishai Hadas return MLX5_GET(create_flow_table_out, out, table_id); 323*1368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_FLOW_GROUP: 324*1368ead0SYishai Hadas return MLX5_GET(create_flow_group_out, out, group_id); 325*1368ead0SYishai Hadas case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY: 326*1368ead0SYishai Hadas return MLX5_GET(set_fte_in, in, flow_index); 327*1368ead0SYishai Hadas case MLX5_CMD_OP_ALLOC_FLOW_COUNTER: 328*1368ead0SYishai Hadas return MLX5_GET(alloc_flow_counter_out, out, flow_counter_id); 329*1368ead0SYishai Hadas case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT: 330*1368ead0SYishai Hadas return MLX5_GET(alloc_packet_reformat_context_out, out, 331*1368ead0SYishai Hadas packet_reformat_id); 332*1368ead0SYishai Hadas case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT: 333*1368ead0SYishai Hadas return MLX5_GET(alloc_modify_header_context_out, out, 334*1368ead0SYishai Hadas modify_header_id); 335*1368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT: 336*1368ead0SYishai Hadas return MLX5_GET(create_scheduling_element_out, out, 337*1368ead0SYishai Hadas scheduling_element_id); 338*1368ead0SYishai Hadas case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT: 339*1368ead0SYishai Hadas return MLX5_GET(add_vxlan_udp_dport_in, in, vxlan_udp_port); 340*1368ead0SYishai Hadas case MLX5_CMD_OP_SET_L2_TABLE_ENTRY: 341*1368ead0SYishai Hadas return MLX5_GET(set_l2_table_entry_in, in, table_index); 342*1368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_QP: 343*1368ead0SYishai Hadas return MLX5_GET(create_qp_out, out, qpn); 344*1368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_SRQ: 345*1368ead0SYishai Hadas return MLX5_GET(create_srq_out, out, srqn); 346*1368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_XRC_SRQ: 347*1368ead0SYishai Hadas return MLX5_GET(create_xrc_srq_out, out, xrc_srqn); 348*1368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_DCT: 349*1368ead0SYishai Hadas return MLX5_GET(create_dct_out, out, dctn); 350*1368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_XRQ: 351*1368ead0SYishai Hadas return MLX5_GET(create_xrq_out, out, xrqn); 352*1368ead0SYishai Hadas case MLX5_CMD_OP_ATTACH_TO_MCG: 353*1368ead0SYishai Hadas return MLX5_GET(attach_to_mcg_in, in, qpn); 354*1368ead0SYishai Hadas case MLX5_CMD_OP_ALLOC_XRCD: 355*1368ead0SYishai Hadas return MLX5_GET(alloc_xrcd_out, out, xrcd); 356*1368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_PSV: 357*1368ead0SYishai Hadas return MLX5_GET(create_psv_out, out, psv0_index); 358*1368ead0SYishai Hadas default: 359*1368ead0SYishai Hadas /* The entry must match to one of the devx_is_obj_create_cmd */ 360*1368ead0SYishai Hadas WARN_ON(true); 361*1368ead0SYishai Hadas return 0; 362*1368ead0SYishai Hadas } 363*1368ead0SYishai Hadas } 364*1368ead0SYishai Hadas 36534613eb1SYishai Hadas static u64 devx_get_obj_id(const void *in) 366e662e14dSYishai Hadas { 367e662e14dSYishai Hadas u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 3682351776eSYishai Hadas u64 obj_id; 369e662e14dSYishai Hadas 370e662e14dSYishai Hadas switch (opcode) { 371e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT: 372e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_GENERAL_OBJECT: 373cd5d20f1SYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_GENERAL_OBJECT | 374cd5d20f1SYishai Hadas MLX5_GET(general_obj_in_cmd_hdr, in, 375cd5d20f1SYishai Hadas obj_type) << 16, 3762351776eSYishai Hadas MLX5_GET(general_obj_in_cmd_hdr, in, 3772351776eSYishai Hadas obj_id)); 378e662e14dSYishai Hadas break; 379e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_MKEY: 3802351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_MKEY, 3812351776eSYishai Hadas MLX5_GET(query_mkey_in, in, 3822351776eSYishai Hadas mkey_index)); 383e662e14dSYishai Hadas break; 384e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_CQ: 3852351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_CQ, 3862351776eSYishai Hadas MLX5_GET(query_cq_in, in, cqn)); 387e662e14dSYishai Hadas break; 388e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_CQ: 3892351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_CQ, 3902351776eSYishai Hadas MLX5_GET(modify_cq_in, in, cqn)); 391e662e14dSYishai Hadas break; 392e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_SQ: 3932351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ, 3942351776eSYishai Hadas MLX5_GET(query_sq_in, in, sqn)); 395e662e14dSYishai Hadas break; 396e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_SQ: 3972351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ, 3982351776eSYishai Hadas MLX5_GET(modify_sq_in, in, sqn)); 399e662e14dSYishai Hadas break; 400e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_RQ: 4012351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ, 4022351776eSYishai Hadas MLX5_GET(query_rq_in, in, rqn)); 403e662e14dSYishai Hadas break; 404e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_RQ: 4052351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ, 4062351776eSYishai Hadas MLX5_GET(modify_rq_in, in, rqn)); 407e662e14dSYishai Hadas break; 408e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_RMP: 4092351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RMP, 4102351776eSYishai Hadas MLX5_GET(query_rmp_in, in, rmpn)); 411e662e14dSYishai Hadas break; 412e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_RMP: 4132351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RMP, 4142351776eSYishai Hadas MLX5_GET(modify_rmp_in, in, rmpn)); 415e662e14dSYishai Hadas break; 416e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_RQT: 4172351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT, 4182351776eSYishai Hadas MLX5_GET(query_rqt_in, in, rqtn)); 419e662e14dSYishai Hadas break; 420e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_RQT: 4212351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT, 4222351776eSYishai Hadas MLX5_GET(modify_rqt_in, in, rqtn)); 423e662e14dSYishai Hadas break; 424e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_TIR: 4252351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR, 4262351776eSYishai Hadas MLX5_GET(query_tir_in, in, tirn)); 427e662e14dSYishai Hadas break; 428e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_TIR: 4292351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR, 4302351776eSYishai Hadas MLX5_GET(modify_tir_in, in, tirn)); 431e662e14dSYishai Hadas break; 432e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_TIS: 4332351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS, 4342351776eSYishai Hadas MLX5_GET(query_tis_in, in, tisn)); 435e662e14dSYishai Hadas break; 436e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_TIS: 4372351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS, 4382351776eSYishai Hadas MLX5_GET(modify_tis_in, in, tisn)); 439e662e14dSYishai Hadas break; 440e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_FLOW_TABLE: 4412351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_FLOW_TABLE, 4422351776eSYishai Hadas MLX5_GET(query_flow_table_in, in, 4432351776eSYishai Hadas table_id)); 444e662e14dSYishai Hadas break; 445e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_FLOW_TABLE: 4462351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_FLOW_TABLE, 4472351776eSYishai Hadas MLX5_GET(modify_flow_table_in, in, 4482351776eSYishai Hadas table_id)); 449e662e14dSYishai Hadas break; 450e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_FLOW_GROUP: 4512351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_FLOW_GROUP, 4522351776eSYishai Hadas MLX5_GET(query_flow_group_in, in, 4532351776eSYishai Hadas group_id)); 454e662e14dSYishai Hadas break; 455e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY: 4562351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY, 4572351776eSYishai Hadas MLX5_GET(query_fte_in, in, 4582351776eSYishai Hadas flow_index)); 459e662e14dSYishai Hadas break; 460e662e14dSYishai Hadas case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY: 4612351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY, 4622351776eSYishai Hadas MLX5_GET(set_fte_in, in, flow_index)); 463e662e14dSYishai Hadas break; 464e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_Q_COUNTER: 4652351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_ALLOC_Q_COUNTER, 4662351776eSYishai Hadas MLX5_GET(query_q_counter_in, in, 4672351776eSYishai Hadas counter_set_id)); 468e662e14dSYishai Hadas break; 469e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_FLOW_COUNTER: 4702351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_ALLOC_FLOW_COUNTER, 4712351776eSYishai Hadas MLX5_GET(query_flow_counter_in, in, 4722351776eSYishai Hadas flow_counter_id)); 473e662e14dSYishai Hadas break; 474e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT: 4752351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT, 476*1368ead0SYishai Hadas MLX5_GET(query_modify_header_context_in, 477*1368ead0SYishai Hadas in, modify_header_id)); 478e662e14dSYishai Hadas break; 479e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT: 4802351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT, 4812351776eSYishai Hadas MLX5_GET(query_scheduling_element_in, 4822351776eSYishai Hadas in, scheduling_element_id)); 483e662e14dSYishai Hadas break; 484e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT: 4852351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT, 4862351776eSYishai Hadas MLX5_GET(modify_scheduling_element_in, 4872351776eSYishai Hadas in, scheduling_element_id)); 488e662e14dSYishai Hadas break; 489e662e14dSYishai Hadas case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT: 4902351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT, 4912351776eSYishai Hadas MLX5_GET(add_vxlan_udp_dport_in, in, 4922351776eSYishai Hadas vxlan_udp_port)); 493e662e14dSYishai Hadas break; 494e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY: 4952351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_L2_TABLE_ENTRY, 4962351776eSYishai Hadas MLX5_GET(query_l2_table_entry_in, in, 4972351776eSYishai Hadas table_index)); 498e662e14dSYishai Hadas break; 499e662e14dSYishai Hadas case MLX5_CMD_OP_SET_L2_TABLE_ENTRY: 5002351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_L2_TABLE_ENTRY, 5012351776eSYishai Hadas MLX5_GET(set_l2_table_entry_in, in, 5022351776eSYishai Hadas table_index)); 503e662e14dSYishai Hadas break; 504e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_QP: 5052351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 5062351776eSYishai Hadas MLX5_GET(query_qp_in, in, qpn)); 507e662e14dSYishai Hadas break; 508e662e14dSYishai Hadas case MLX5_CMD_OP_RST2INIT_QP: 5092351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 5102351776eSYishai Hadas MLX5_GET(rst2init_qp_in, in, qpn)); 511e662e14dSYishai Hadas break; 512d246a306SMark Zhang case MLX5_CMD_OP_INIT2INIT_QP: 513d246a306SMark Zhang obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 514d246a306SMark Zhang MLX5_GET(init2init_qp_in, in, qpn)); 515d246a306SMark Zhang break; 516e662e14dSYishai Hadas case MLX5_CMD_OP_INIT2RTR_QP: 5172351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 5182351776eSYishai Hadas MLX5_GET(init2rtr_qp_in, in, qpn)); 519e662e14dSYishai Hadas break; 520e662e14dSYishai Hadas case MLX5_CMD_OP_RTR2RTS_QP: 5212351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 5222351776eSYishai Hadas MLX5_GET(rtr2rts_qp_in, in, qpn)); 523e662e14dSYishai Hadas break; 524e662e14dSYishai Hadas case MLX5_CMD_OP_RTS2RTS_QP: 5252351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 5262351776eSYishai Hadas MLX5_GET(rts2rts_qp_in, in, qpn)); 527e662e14dSYishai Hadas break; 528e662e14dSYishai Hadas case MLX5_CMD_OP_SQERR2RTS_QP: 5292351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 5302351776eSYishai Hadas MLX5_GET(sqerr2rts_qp_in, in, qpn)); 531e662e14dSYishai Hadas break; 532e662e14dSYishai Hadas case MLX5_CMD_OP_2ERR_QP: 5332351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 5342351776eSYishai Hadas MLX5_GET(qp_2err_in, in, qpn)); 535e662e14dSYishai Hadas break; 536e662e14dSYishai Hadas case MLX5_CMD_OP_2RST_QP: 5372351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 5382351776eSYishai Hadas MLX5_GET(qp_2rst_in, in, qpn)); 539e662e14dSYishai Hadas break; 540e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_DCT: 5412351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT, 5422351776eSYishai Hadas MLX5_GET(query_dct_in, in, dctn)); 543e662e14dSYishai Hadas break; 544e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_XRQ: 545719598c9SYishai Hadas case MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY: 546719598c9SYishai Hadas case MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS: 5472351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRQ, 5482351776eSYishai Hadas MLX5_GET(query_xrq_in, in, xrqn)); 549e662e14dSYishai Hadas break; 550e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_XRC_SRQ: 5512351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRC_SRQ, 5522351776eSYishai Hadas MLX5_GET(query_xrc_srq_in, in, 5532351776eSYishai Hadas xrc_srqn)); 554e662e14dSYishai Hadas break; 555e662e14dSYishai Hadas case MLX5_CMD_OP_ARM_XRC_SRQ: 5562351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRC_SRQ, 5572351776eSYishai Hadas MLX5_GET(arm_xrc_srq_in, in, xrc_srqn)); 558e662e14dSYishai Hadas break; 559e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_SRQ: 5602351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SRQ, 5612351776eSYishai Hadas MLX5_GET(query_srq_in, in, srqn)); 562e662e14dSYishai Hadas break; 563e662e14dSYishai Hadas case MLX5_CMD_OP_ARM_RQ: 5642351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ, 5652351776eSYishai Hadas MLX5_GET(arm_rq_in, in, srq_number)); 566e662e14dSYishai Hadas break; 567e662e14dSYishai Hadas case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION: 5682351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT, 5692351776eSYishai Hadas MLX5_GET(drain_dct_in, in, dctn)); 570e662e14dSYishai Hadas break; 571e662e14dSYishai Hadas case MLX5_CMD_OP_ARM_XRQ: 572719598c9SYishai Hadas case MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY: 5738293a598SYishai Hadas case MLX5_CMD_OP_RELEASE_XRQ_ERROR: 5748293a598SYishai Hadas case MLX5_CMD_OP_MODIFY_XRQ: 5752351776eSYishai Hadas obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRQ, 5762351776eSYishai Hadas MLX5_GET(arm_xrq_in, in, xrqn)); 577e662e14dSYishai Hadas break; 578719598c9SYishai Hadas case MLX5_CMD_OP_QUERY_PACKET_REFORMAT_CONTEXT: 579719598c9SYishai Hadas obj_id = get_enc_obj_id 580719598c9SYishai Hadas (MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT, 581719598c9SYishai Hadas MLX5_GET(query_packet_reformat_context_in, 582719598c9SYishai Hadas in, packet_reformat_id)); 583719598c9SYishai Hadas break; 584e662e14dSYishai Hadas default: 58534613eb1SYishai Hadas obj_id = 0; 586e662e14dSYishai Hadas } 587e662e14dSYishai Hadas 58834613eb1SYishai Hadas return obj_id; 58934613eb1SYishai Hadas } 590e662e14dSYishai Hadas 591e79c9c60SJason Gunthorpe static bool devx_is_valid_obj_id(struct uverbs_attr_bundle *attrs, 592e79c9c60SJason Gunthorpe struct ib_uobject *uobj, const void *in) 59334613eb1SYishai Hadas { 594e79c9c60SJason Gunthorpe struct mlx5_ib_dev *dev = mlx5_udata_to_mdev(&attrs->driver_udata); 59534613eb1SYishai Hadas u64 obj_id = devx_get_obj_id(in); 59634613eb1SYishai Hadas 59734613eb1SYishai Hadas if (!obj_id) 598e662e14dSYishai Hadas return false; 59934613eb1SYishai Hadas 60034613eb1SYishai Hadas switch (uobj_get_object_id(uobj)) { 60134613eb1SYishai Hadas case UVERBS_OBJECT_CQ: 60234613eb1SYishai Hadas return get_enc_obj_id(MLX5_CMD_OP_CREATE_CQ, 60334613eb1SYishai Hadas to_mcq(uobj->object)->mcq.cqn) == 60434613eb1SYishai Hadas obj_id; 60534613eb1SYishai Hadas 60634613eb1SYishai Hadas case UVERBS_OBJECT_SRQ: 60734613eb1SYishai Hadas { 60834613eb1SYishai Hadas struct mlx5_core_srq *srq = &(to_msrq(uobj->object)->msrq); 60934613eb1SYishai Hadas u16 opcode; 61034613eb1SYishai Hadas 61134613eb1SYishai Hadas switch (srq->common.res) { 61234613eb1SYishai Hadas case MLX5_RES_XSRQ: 61334613eb1SYishai Hadas opcode = MLX5_CMD_OP_CREATE_XRC_SRQ; 61434613eb1SYishai Hadas break; 61534613eb1SYishai Hadas case MLX5_RES_XRQ: 61634613eb1SYishai Hadas opcode = MLX5_CMD_OP_CREATE_XRQ; 61734613eb1SYishai Hadas break; 61834613eb1SYishai Hadas default: 61934613eb1SYishai Hadas if (!dev->mdev->issi) 62034613eb1SYishai Hadas opcode = MLX5_CMD_OP_CREATE_SRQ; 62134613eb1SYishai Hadas else 62234613eb1SYishai Hadas opcode = MLX5_CMD_OP_CREATE_RMP; 62334613eb1SYishai Hadas } 62434613eb1SYishai Hadas 62534613eb1SYishai Hadas return get_enc_obj_id(opcode, 62634613eb1SYishai Hadas to_msrq(uobj->object)->msrq.srqn) == 62734613eb1SYishai Hadas obj_id; 62834613eb1SYishai Hadas } 62934613eb1SYishai Hadas 63034613eb1SYishai Hadas case UVERBS_OBJECT_QP: 63134613eb1SYishai Hadas { 63234613eb1SYishai Hadas struct mlx5_ib_qp *qp = to_mqp(uobj->object); 63334613eb1SYishai Hadas enum ib_qp_type qp_type = qp->ibqp.qp_type; 63434613eb1SYishai Hadas 63534613eb1SYishai Hadas if (qp_type == IB_QPT_RAW_PACKET || 6362be08c30SLeon Romanovsky (qp->flags & IB_QP_CREATE_SOURCE_QPN)) { 63734613eb1SYishai Hadas struct mlx5_ib_raw_packet_qp *raw_packet_qp = 63834613eb1SYishai Hadas &qp->raw_packet_qp; 63934613eb1SYishai Hadas struct mlx5_ib_rq *rq = &raw_packet_qp->rq; 64034613eb1SYishai Hadas struct mlx5_ib_sq *sq = &raw_packet_qp->sq; 64134613eb1SYishai Hadas 64234613eb1SYishai Hadas return (get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ, 64334613eb1SYishai Hadas rq->base.mqp.qpn) == obj_id || 64434613eb1SYishai Hadas get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ, 64534613eb1SYishai Hadas sq->base.mqp.qpn) == obj_id || 64634613eb1SYishai Hadas get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR, 64734613eb1SYishai Hadas rq->tirn) == obj_id || 64834613eb1SYishai Hadas get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS, 64934613eb1SYishai Hadas sq->tisn) == obj_id); 65034613eb1SYishai Hadas } 65134613eb1SYishai Hadas 65234613eb1SYishai Hadas if (qp_type == MLX5_IB_QPT_DCT) 65334613eb1SYishai Hadas return get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT, 65434613eb1SYishai Hadas qp->dct.mdct.mqp.qpn) == obj_id; 65534613eb1SYishai Hadas 65634613eb1SYishai Hadas return get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 65734613eb1SYishai Hadas qp->ibqp.qp_num) == obj_id; 65834613eb1SYishai Hadas } 65934613eb1SYishai Hadas 66034613eb1SYishai Hadas case UVERBS_OBJECT_WQ: 66134613eb1SYishai Hadas return get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ, 66234613eb1SYishai Hadas to_mrwq(uobj->object)->core_qp.qpn) == 66334613eb1SYishai Hadas obj_id; 66434613eb1SYishai Hadas 66534613eb1SYishai Hadas case UVERBS_OBJECT_RWQ_IND_TBL: 66634613eb1SYishai Hadas return get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT, 66734613eb1SYishai Hadas to_mrwq_ind_table(uobj->object)->rqtn) == 66834613eb1SYishai Hadas obj_id; 66934613eb1SYishai Hadas 67034613eb1SYishai Hadas case MLX5_IB_OBJECT_DEVX_OBJ: 67134613eb1SYishai Hadas return ((struct devx_obj *)uobj->object)->obj_id == obj_id; 67234613eb1SYishai Hadas 673e662e14dSYishai Hadas default: 674e662e14dSYishai Hadas return false; 675e662e14dSYishai Hadas } 676e662e14dSYishai Hadas } 677e662e14dSYishai Hadas 678ba1a057dSYishai Hadas static void devx_set_umem_valid(const void *in) 679ba1a057dSYishai Hadas { 680ba1a057dSYishai Hadas u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 681ba1a057dSYishai Hadas 682ba1a057dSYishai Hadas switch (opcode) { 683ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_MKEY: 684ba1a057dSYishai Hadas MLX5_SET(create_mkey_in, in, mkey_umem_valid, 1); 685ba1a057dSYishai Hadas break; 686ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_CQ: 687ba1a057dSYishai Hadas { 688ba1a057dSYishai Hadas void *cqc; 689ba1a057dSYishai Hadas 690ba1a057dSYishai Hadas MLX5_SET(create_cq_in, in, cq_umem_valid, 1); 691ba1a057dSYishai Hadas cqc = MLX5_ADDR_OF(create_cq_in, in, cq_context); 692ba1a057dSYishai Hadas MLX5_SET(cqc, cqc, dbr_umem_valid, 1); 693ba1a057dSYishai Hadas break; 694ba1a057dSYishai Hadas } 695ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_QP: 696ba1a057dSYishai Hadas { 697ba1a057dSYishai Hadas void *qpc; 698ba1a057dSYishai Hadas 699ba1a057dSYishai Hadas qpc = MLX5_ADDR_OF(create_qp_in, in, qpc); 700ba1a057dSYishai Hadas MLX5_SET(qpc, qpc, dbr_umem_valid, 1); 701ba1a057dSYishai Hadas MLX5_SET(create_qp_in, in, wq_umem_valid, 1); 702ba1a057dSYishai Hadas break; 703ba1a057dSYishai Hadas } 704ba1a057dSYishai Hadas 705ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_RQ: 706ba1a057dSYishai Hadas { 707ba1a057dSYishai Hadas void *rqc, *wq; 708ba1a057dSYishai Hadas 709ba1a057dSYishai Hadas rqc = MLX5_ADDR_OF(create_rq_in, in, ctx); 710ba1a057dSYishai Hadas wq = MLX5_ADDR_OF(rqc, rqc, wq); 711ba1a057dSYishai Hadas MLX5_SET(wq, wq, dbr_umem_valid, 1); 712ba1a057dSYishai Hadas MLX5_SET(wq, wq, wq_umem_valid, 1); 713ba1a057dSYishai Hadas break; 714ba1a057dSYishai Hadas } 715ba1a057dSYishai Hadas 716ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_SQ: 717ba1a057dSYishai Hadas { 718ba1a057dSYishai Hadas void *sqc, *wq; 719ba1a057dSYishai Hadas 720ba1a057dSYishai Hadas sqc = MLX5_ADDR_OF(create_sq_in, in, ctx); 721ba1a057dSYishai Hadas wq = MLX5_ADDR_OF(sqc, sqc, wq); 722ba1a057dSYishai Hadas MLX5_SET(wq, wq, dbr_umem_valid, 1); 723ba1a057dSYishai Hadas MLX5_SET(wq, wq, wq_umem_valid, 1); 724ba1a057dSYishai Hadas break; 725ba1a057dSYishai Hadas } 726ba1a057dSYishai Hadas 727ba1a057dSYishai Hadas case MLX5_CMD_OP_MODIFY_CQ: 728ba1a057dSYishai Hadas MLX5_SET(modify_cq_in, in, cq_umem_valid, 1); 729ba1a057dSYishai Hadas break; 730ba1a057dSYishai Hadas 731ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_RMP: 732ba1a057dSYishai Hadas { 733ba1a057dSYishai Hadas void *rmpc, *wq; 734ba1a057dSYishai Hadas 735ba1a057dSYishai Hadas rmpc = MLX5_ADDR_OF(create_rmp_in, in, ctx); 736ba1a057dSYishai Hadas wq = MLX5_ADDR_OF(rmpc, rmpc, wq); 737ba1a057dSYishai Hadas MLX5_SET(wq, wq, dbr_umem_valid, 1); 738ba1a057dSYishai Hadas MLX5_SET(wq, wq, wq_umem_valid, 1); 739ba1a057dSYishai Hadas break; 740ba1a057dSYishai Hadas } 741ba1a057dSYishai Hadas 742ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_XRQ: 743ba1a057dSYishai Hadas { 744ba1a057dSYishai Hadas void *xrqc, *wq; 745ba1a057dSYishai Hadas 746ba1a057dSYishai Hadas xrqc = MLX5_ADDR_OF(create_xrq_in, in, xrq_context); 747ba1a057dSYishai Hadas wq = MLX5_ADDR_OF(xrqc, xrqc, wq); 748ba1a057dSYishai Hadas MLX5_SET(wq, wq, dbr_umem_valid, 1); 749ba1a057dSYishai Hadas MLX5_SET(wq, wq, wq_umem_valid, 1); 750ba1a057dSYishai Hadas break; 751ba1a057dSYishai Hadas } 752ba1a057dSYishai Hadas 753ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_XRC_SRQ: 754ba1a057dSYishai Hadas { 755ba1a057dSYishai Hadas void *xrc_srqc; 756ba1a057dSYishai Hadas 757ba1a057dSYishai Hadas MLX5_SET(create_xrc_srq_in, in, xrc_srq_umem_valid, 1); 758ba1a057dSYishai Hadas xrc_srqc = MLX5_ADDR_OF(create_xrc_srq_in, in, 759ba1a057dSYishai Hadas xrc_srq_context_entry); 760ba1a057dSYishai Hadas MLX5_SET(xrc_srqc, xrc_srqc, dbr_umem_valid, 1); 761ba1a057dSYishai Hadas break; 762ba1a057dSYishai Hadas } 763ba1a057dSYishai Hadas 764ba1a057dSYishai Hadas default: 765ba1a057dSYishai Hadas return; 766ba1a057dSYishai Hadas } 767ba1a057dSYishai Hadas } 768ba1a057dSYishai Hadas 7692351776eSYishai Hadas static bool devx_is_obj_create_cmd(const void *in, u16 *opcode) 7707efce369SYishai Hadas { 7712351776eSYishai Hadas *opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 7727efce369SYishai Hadas 7732351776eSYishai Hadas switch (*opcode) { 7747efce369SYishai Hadas case MLX5_CMD_OP_CREATE_GENERAL_OBJECT: 7757efce369SYishai Hadas case MLX5_CMD_OP_CREATE_MKEY: 7767efce369SYishai Hadas case MLX5_CMD_OP_CREATE_CQ: 7777efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_PD: 7787efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN: 7797efce369SYishai Hadas case MLX5_CMD_OP_CREATE_RMP: 7807efce369SYishai Hadas case MLX5_CMD_OP_CREATE_SQ: 7817efce369SYishai Hadas case MLX5_CMD_OP_CREATE_RQ: 7827efce369SYishai Hadas case MLX5_CMD_OP_CREATE_RQT: 7837efce369SYishai Hadas case MLX5_CMD_OP_CREATE_TIR: 7847efce369SYishai Hadas case MLX5_CMD_OP_CREATE_TIS: 7857efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_Q_COUNTER: 7867efce369SYishai Hadas case MLX5_CMD_OP_CREATE_FLOW_TABLE: 7877efce369SYishai Hadas case MLX5_CMD_OP_CREATE_FLOW_GROUP: 7887efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_FLOW_COUNTER: 78960786f09SMark Bloch case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT: 7907efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT: 7917efce369SYishai Hadas case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT: 7927efce369SYishai Hadas case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT: 7937efce369SYishai Hadas case MLX5_CMD_OP_SET_L2_TABLE_ENTRY: 7947efce369SYishai Hadas case MLX5_CMD_OP_CREATE_QP: 7957efce369SYishai Hadas case MLX5_CMD_OP_CREATE_SRQ: 7967efce369SYishai Hadas case MLX5_CMD_OP_CREATE_XRC_SRQ: 7977efce369SYishai Hadas case MLX5_CMD_OP_CREATE_DCT: 7987efce369SYishai Hadas case MLX5_CMD_OP_CREATE_XRQ: 7997efce369SYishai Hadas case MLX5_CMD_OP_ATTACH_TO_MCG: 8007efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_XRCD: 8017efce369SYishai Hadas return true; 8027efce369SYishai Hadas case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY: 8037efce369SYishai Hadas { 8047efce369SYishai Hadas u16 op_mod = MLX5_GET(set_fte_in, in, op_mod); 8057efce369SYishai Hadas if (op_mod == 0) 8067efce369SYishai Hadas return true; 8077efce369SYishai Hadas return false; 8087efce369SYishai Hadas } 8098b38c538SMax Gurtovoy case MLX5_CMD_OP_CREATE_PSV: 8108b38c538SMax Gurtovoy { 8118b38c538SMax Gurtovoy u8 num_psv = MLX5_GET(create_psv_in, in, num_psv); 8128b38c538SMax Gurtovoy 8138b38c538SMax Gurtovoy if (num_psv == 1) 8148b38c538SMax Gurtovoy return true; 8158b38c538SMax Gurtovoy return false; 8168b38c538SMax Gurtovoy } 8177efce369SYishai Hadas default: 8187efce369SYishai Hadas return false; 8197efce369SYishai Hadas } 8207efce369SYishai Hadas } 8217efce369SYishai Hadas 822e662e14dSYishai Hadas static bool devx_is_obj_modify_cmd(const void *in) 823e662e14dSYishai Hadas { 824e662e14dSYishai Hadas u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 825e662e14dSYishai Hadas 826e662e14dSYishai Hadas switch (opcode) { 827e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT: 828e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_CQ: 829e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_RMP: 830e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_SQ: 831e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_RQ: 832e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_RQT: 833e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_TIR: 834e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_TIS: 835e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_FLOW_TABLE: 836e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT: 837e662e14dSYishai Hadas case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT: 838e662e14dSYishai Hadas case MLX5_CMD_OP_SET_L2_TABLE_ENTRY: 839e662e14dSYishai Hadas case MLX5_CMD_OP_RST2INIT_QP: 840e662e14dSYishai Hadas case MLX5_CMD_OP_INIT2RTR_QP: 841819f7427SAharon Landau case MLX5_CMD_OP_INIT2INIT_QP: 842e662e14dSYishai Hadas case MLX5_CMD_OP_RTR2RTS_QP: 843e662e14dSYishai Hadas case MLX5_CMD_OP_RTS2RTS_QP: 844e662e14dSYishai Hadas case MLX5_CMD_OP_SQERR2RTS_QP: 845e662e14dSYishai Hadas case MLX5_CMD_OP_2ERR_QP: 846e662e14dSYishai Hadas case MLX5_CMD_OP_2RST_QP: 847e662e14dSYishai Hadas case MLX5_CMD_OP_ARM_XRC_SRQ: 848e662e14dSYishai Hadas case MLX5_CMD_OP_ARM_RQ: 849e662e14dSYishai Hadas case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION: 850e662e14dSYishai Hadas case MLX5_CMD_OP_ARM_XRQ: 851719598c9SYishai Hadas case MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY: 8528293a598SYishai Hadas case MLX5_CMD_OP_RELEASE_XRQ_ERROR: 8538293a598SYishai Hadas case MLX5_CMD_OP_MODIFY_XRQ: 854e662e14dSYishai Hadas return true; 855e662e14dSYishai Hadas case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY: 856e662e14dSYishai Hadas { 857e662e14dSYishai Hadas u16 op_mod = MLX5_GET(set_fte_in, in, op_mod); 858e662e14dSYishai Hadas 859e662e14dSYishai Hadas if (op_mod == 1) 860e662e14dSYishai Hadas return true; 861e662e14dSYishai Hadas return false; 862e662e14dSYishai Hadas } 863e662e14dSYishai Hadas default: 864e662e14dSYishai Hadas return false; 865e662e14dSYishai Hadas } 866e662e14dSYishai Hadas } 867e662e14dSYishai Hadas 868e662e14dSYishai Hadas static bool devx_is_obj_query_cmd(const void *in) 869e662e14dSYishai Hadas { 870e662e14dSYishai Hadas u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 871e662e14dSYishai Hadas 872e662e14dSYishai Hadas switch (opcode) { 873e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_GENERAL_OBJECT: 874e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_MKEY: 875e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_CQ: 876e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_RMP: 877e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_SQ: 878e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_RQ: 879e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_RQT: 880e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_TIR: 881e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_TIS: 882e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_Q_COUNTER: 883e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_FLOW_TABLE: 884e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_FLOW_GROUP: 885e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY: 886e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_FLOW_COUNTER: 887e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT: 888e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT: 889e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY: 890e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_QP: 891e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_SRQ: 892e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_XRC_SRQ: 893e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_DCT: 894e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_XRQ: 895719598c9SYishai Hadas case MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY: 896719598c9SYishai Hadas case MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS: 897719598c9SYishai Hadas case MLX5_CMD_OP_QUERY_PACKET_REFORMAT_CONTEXT: 898e662e14dSYishai Hadas return true; 899e662e14dSYishai Hadas default: 900e662e14dSYishai Hadas return false; 901e662e14dSYishai Hadas } 902e662e14dSYishai Hadas } 903e662e14dSYishai Hadas 9047e1335a7SYishai Hadas static bool devx_is_whitelist_cmd(void *in) 9057e1335a7SYishai Hadas { 9067e1335a7SYishai Hadas u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 9077e1335a7SYishai Hadas 9087e1335a7SYishai Hadas switch (opcode) { 9097e1335a7SYishai Hadas case MLX5_CMD_OP_QUERY_HCA_CAP: 9107e1335a7SYishai Hadas case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT: 91156e5acd4SMaor Gottlieb case MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT: 9127e1335a7SYishai Hadas return true; 9137e1335a7SYishai Hadas default: 9147e1335a7SYishai Hadas return false; 9157e1335a7SYishai Hadas } 9167e1335a7SYishai Hadas } 9177e1335a7SYishai Hadas 9187e1335a7SYishai Hadas static int devx_get_uid(struct mlx5_ib_ucontext *c, void *cmd_in) 9197e1335a7SYishai Hadas { 9207e1335a7SYishai Hadas if (devx_is_whitelist_cmd(cmd_in)) { 9217e1335a7SYishai Hadas struct mlx5_ib_dev *dev; 9227e1335a7SYishai Hadas 9237e1335a7SYishai Hadas if (c->devx_uid) 9247e1335a7SYishai Hadas return c->devx_uid; 9257e1335a7SYishai Hadas 9267e1335a7SYishai Hadas dev = to_mdev(c->ibucontext.device); 9277e1335a7SYishai Hadas if (dev->devx_whitelist_uid) 9287e1335a7SYishai Hadas return dev->devx_whitelist_uid; 9297e1335a7SYishai Hadas 9307e1335a7SYishai Hadas return -EOPNOTSUPP; 9317e1335a7SYishai Hadas } 9327e1335a7SYishai Hadas 9337e1335a7SYishai Hadas if (!c->devx_uid) 9347e1335a7SYishai Hadas return -EINVAL; 9357e1335a7SYishai Hadas 9367e1335a7SYishai Hadas return c->devx_uid; 9377e1335a7SYishai Hadas } 938b6142608SMax Gurtovoy 939b6142608SMax Gurtovoy static bool devx_is_general_cmd(void *in, struct mlx5_ib_dev *dev) 9408aa8c95cSYishai Hadas { 9418aa8c95cSYishai Hadas u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 9428aa8c95cSYishai Hadas 943b6142608SMax Gurtovoy /* Pass all cmds for vhca_tunnel as general, tracking is done in FW */ 944b6142608SMax Gurtovoy if ((MLX5_CAP_GEN_64(dev->mdev, vhca_tunnel_commands) && 945b6142608SMax Gurtovoy MLX5_GET(general_obj_in_cmd_hdr, in, vhca_tunnel_id)) || 946b6142608SMax Gurtovoy (opcode >= MLX5_CMD_OP_GENERAL_START && 947b6142608SMax Gurtovoy opcode < MLX5_CMD_OP_GENERAL_END)) 948719598c9SYishai Hadas return true; 949719598c9SYishai Hadas 9508aa8c95cSYishai Hadas switch (opcode) { 9518aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_HCA_CAP: 9527e1335a7SYishai Hadas case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT: 95356e5acd4SMaor Gottlieb case MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT: 9548aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_VPORT_STATE: 9558aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_ADAPTER: 9568aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_ISSI: 9578aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT: 9588aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_ROCE_ADDRESS: 9598aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_VNIC_ENV: 9608aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_VPORT_COUNTER: 9618aa8c95cSYishai Hadas case MLX5_CMD_OP_GET_DROPPED_PACKET_LOG: 9628aa8c95cSYishai Hadas case MLX5_CMD_OP_NOP: 9638aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_CONG_STATUS: 9648aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_CONG_PARAMS: 9658aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_CONG_STATISTICS: 9667084ed30SMark Zhang case MLX5_CMD_OP_QUERY_LAG: 9678aa8c95cSYishai Hadas return true; 9688aa8c95cSYishai Hadas default: 9698aa8c95cSYishai Hadas return false; 9708aa8c95cSYishai Hadas } 9718aa8c95cSYishai Hadas } 9728aa8c95cSYishai Hadas 973e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_EQN)( 97415a1b4beSJason Gunthorpe struct uverbs_attr_bundle *attrs) 975f6fe01b7SYishai Hadas { 976e83f0ecdSJason Gunthorpe struct mlx5_ib_ucontext *c; 977e83f0ecdSJason Gunthorpe struct mlx5_ib_dev *dev; 978f6fe01b7SYishai Hadas int user_vector; 979f6fe01b7SYishai Hadas int dev_eqn; 980f6fe01b7SYishai Hadas unsigned int irqn; 981f6fe01b7SYishai Hadas int err; 982f6fe01b7SYishai Hadas 983f6fe01b7SYishai Hadas if (uverbs_copy_from(&user_vector, attrs, 984f6fe01b7SYishai Hadas MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC)) 985f6fe01b7SYishai Hadas return -EFAULT; 986f6fe01b7SYishai Hadas 98715a1b4beSJason Gunthorpe c = devx_ufile2uctx(attrs); 988e83f0ecdSJason Gunthorpe if (IS_ERR(c)) 989e83f0ecdSJason Gunthorpe return PTR_ERR(c); 990e83f0ecdSJason Gunthorpe dev = to_mdev(c->ibucontext.device); 991e83f0ecdSJason Gunthorpe 992f6fe01b7SYishai Hadas err = mlx5_vector2eqn(dev->mdev, user_vector, &dev_eqn, &irqn); 993f6fe01b7SYishai Hadas if (err < 0) 994f6fe01b7SYishai Hadas return err; 995f6fe01b7SYishai Hadas 996f6fe01b7SYishai Hadas if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN, 997f6fe01b7SYishai Hadas &dev_eqn, sizeof(dev_eqn))) 998f6fe01b7SYishai Hadas return -EFAULT; 999f6fe01b7SYishai Hadas 1000f6fe01b7SYishai Hadas return 0; 1001f6fe01b7SYishai Hadas } 1002f6fe01b7SYishai Hadas 10037c043e90SYishai Hadas /* 10047c043e90SYishai Hadas *Security note: 10057c043e90SYishai Hadas * The hardware protection mechanism works like this: Each device object that 10067c043e90SYishai Hadas * is subject to UAR doorbells (QP/SQ/CQ) gets a UAR ID (called uar_page in 10077c043e90SYishai Hadas * the device specification manual) upon its creation. Then upon doorbell, 10087c043e90SYishai Hadas * hardware fetches the object context for which the doorbell was rang, and 10097c043e90SYishai Hadas * validates that the UAR through which the DB was rang matches the UAR ID 10107c043e90SYishai Hadas * of the object. 10117c043e90SYishai Hadas * If no match the doorbell is silently ignored by the hardware. Of course, 10127c043e90SYishai Hadas * the user cannot ring a doorbell on a UAR that was not mapped to it. 10137c043e90SYishai Hadas * Now in devx, as the devx kernel does not manipulate the QP/SQ/CQ command 10147c043e90SYishai Hadas * mailboxes (except tagging them with UID), we expose to the user its UAR 10157c043e90SYishai Hadas * ID, so it can embed it in these objects in the expected specification 10167c043e90SYishai Hadas * format. So the only thing the user can do is hurt itself by creating a 10177c043e90SYishai Hadas * QP/SQ/CQ with a UAR ID other than his, and then in this case other users 10187c043e90SYishai Hadas * may ring a doorbell on its objects. 10197c043e90SYishai Hadas * The consequence of that will be that another user can schedule a QP/SQ 10207c043e90SYishai Hadas * of the buggy user for execution (just insert it to the hardware schedule 10217c043e90SYishai Hadas * queue or arm its CQ for event generation), no further harm is expected. 10227c043e90SYishai Hadas */ 1023e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_UAR)( 102415a1b4beSJason Gunthorpe struct uverbs_attr_bundle *attrs) 10257c043e90SYishai Hadas { 102622fa27fbSJason Gunthorpe struct mlx5_ib_ucontext *c; 102722fa27fbSJason Gunthorpe struct mlx5_ib_dev *dev; 10287c043e90SYishai Hadas u32 user_idx; 10297c043e90SYishai Hadas s32 dev_idx; 10307c043e90SYishai Hadas 103115a1b4beSJason Gunthorpe c = devx_ufile2uctx(attrs); 103222fa27fbSJason Gunthorpe if (IS_ERR(c)) 103322fa27fbSJason Gunthorpe return PTR_ERR(c); 103422fa27fbSJason Gunthorpe dev = to_mdev(c->ibucontext.device); 103522fa27fbSJason Gunthorpe 10367c043e90SYishai Hadas if (uverbs_copy_from(&user_idx, attrs, 10377c043e90SYishai Hadas MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX)) 10387c043e90SYishai Hadas return -EFAULT; 10397c043e90SYishai Hadas 104022fa27fbSJason Gunthorpe dev_idx = bfregn_to_uar_index(dev, &c->bfregi, user_idx, true); 10417c043e90SYishai Hadas if (dev_idx < 0) 10427c043e90SYishai Hadas return dev_idx; 10437c043e90SYishai Hadas 10447c043e90SYishai Hadas if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX, 10457c043e90SYishai Hadas &dev_idx, sizeof(dev_idx))) 10467c043e90SYishai Hadas return -EFAULT; 10477c043e90SYishai Hadas 10487c043e90SYishai Hadas return 0; 10497c043e90SYishai Hadas } 10507c043e90SYishai Hadas 1051e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)( 105215a1b4beSJason Gunthorpe struct uverbs_attr_bundle *attrs) 10538aa8c95cSYishai Hadas { 105422fa27fbSJason Gunthorpe struct mlx5_ib_ucontext *c; 105522fa27fbSJason Gunthorpe struct mlx5_ib_dev *dev; 10567efce369SYishai Hadas void *cmd_in = uverbs_attr_get_alloced_ptr( 10577efce369SYishai Hadas attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN); 10588aa8c95cSYishai Hadas int cmd_out_len = uverbs_attr_get_len(attrs, 10598aa8c95cSYishai Hadas MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT); 10608aa8c95cSYishai Hadas void *cmd_out; 10618aa8c95cSYishai Hadas int err; 10627e1335a7SYishai Hadas int uid; 10638aa8c95cSYishai Hadas 106415a1b4beSJason Gunthorpe c = devx_ufile2uctx(attrs); 106522fa27fbSJason Gunthorpe if (IS_ERR(c)) 106622fa27fbSJason Gunthorpe return PTR_ERR(c); 106722fa27fbSJason Gunthorpe dev = to_mdev(c->ibucontext.device); 106822fa27fbSJason Gunthorpe 10697e1335a7SYishai Hadas uid = devx_get_uid(c, cmd_in); 10707e1335a7SYishai Hadas if (uid < 0) 10717e1335a7SYishai Hadas return uid; 10728aa8c95cSYishai Hadas 10738aa8c95cSYishai Hadas /* Only white list of some general HCA commands are allowed for this method. */ 1074b6142608SMax Gurtovoy if (!devx_is_general_cmd(cmd_in, dev)) 10758aa8c95cSYishai Hadas return -EINVAL; 10768aa8c95cSYishai Hadas 1077b61815e2SJason Gunthorpe cmd_out = uverbs_zalloc(attrs, cmd_out_len); 1078b61815e2SJason Gunthorpe if (IS_ERR(cmd_out)) 1079b61815e2SJason Gunthorpe return PTR_ERR(cmd_out); 10808aa8c95cSYishai Hadas 10817e1335a7SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); 10828aa8c95cSYishai Hadas err = mlx5_cmd_exec(dev->mdev, cmd_in, 10838aa8c95cSYishai Hadas uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN), 10848aa8c95cSYishai Hadas cmd_out, cmd_out_len); 10858aa8c95cSYishai Hadas if (err) 10868aa8c95cSYishai Hadas return err; 1087b61815e2SJason Gunthorpe 1088b61815e2SJason Gunthorpe return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT, cmd_out, 1089b61815e2SJason Gunthorpe cmd_out_len); 10908aa8c95cSYishai Hadas } 10918aa8c95cSYishai Hadas 10927efce369SYishai Hadas static void devx_obj_build_destroy_cmd(void *in, void *out, void *din, 10937efce369SYishai Hadas u32 *dinlen, 10947efce369SYishai Hadas u32 *obj_id) 10957efce369SYishai Hadas { 1096*1368ead0SYishai Hadas u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 10977efce369SYishai Hadas u16 uid = MLX5_GET(general_obj_in_cmd_hdr, in, uid); 10987efce369SYishai Hadas 1099*1368ead0SYishai Hadas *obj_id = devx_get_created_obj_id(in, out, opcode); 11007efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr); 11017efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, uid, uid); 11027efce369SYishai Hadas 1103*1368ead0SYishai Hadas switch (opcode) { 11047efce369SYishai Hadas case MLX5_CMD_OP_CREATE_GENERAL_OBJECT: 11057efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT); 1106*1368ead0SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, obj_id, *obj_id); 1107*1368ead0SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, obj_type, 1108*1368ead0SYishai Hadas MLX5_GET(general_obj_in_cmd_hdr, in, obj_type)); 11097efce369SYishai Hadas break; 11107efce369SYishai Hadas 11116e3722baSYishai Hadas case MLX5_CMD_OP_CREATE_UMEM: 1112*1368ead0SYishai Hadas MLX5_SET(destroy_umem_in, din, opcode, 11136e3722baSYishai Hadas MLX5_CMD_OP_DESTROY_UMEM); 1114*1368ead0SYishai Hadas MLX5_SET(destroy_umem_in, din, umem_id, *obj_id); 11156e3722baSYishai Hadas break; 11167efce369SYishai Hadas case MLX5_CMD_OP_CREATE_MKEY: 1117*1368ead0SYishai Hadas MLX5_SET(destroy_mkey_in, din, opcode, 1118*1368ead0SYishai Hadas MLX5_CMD_OP_DESTROY_MKEY); 1119*1368ead0SYishai Hadas MLX5_SET(destroy_mkey_in, in, mkey_index, *obj_id); 11207efce369SYishai Hadas break; 11217efce369SYishai Hadas case MLX5_CMD_OP_CREATE_CQ: 1122*1368ead0SYishai Hadas MLX5_SET(destroy_cq_in, din, opcode, MLX5_CMD_OP_DESTROY_CQ); 1123*1368ead0SYishai Hadas MLX5_SET(destroy_cq_in, din, cqn, *obj_id); 11247efce369SYishai Hadas break; 11257efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_PD: 1126*1368ead0SYishai Hadas MLX5_SET(dealloc_pd_in, din, opcode, MLX5_CMD_OP_DEALLOC_PD); 1127*1368ead0SYishai Hadas MLX5_SET(dealloc_pd_in, din, pd, *obj_id); 11287efce369SYishai Hadas break; 11297efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN: 1130*1368ead0SYishai Hadas MLX5_SET(dealloc_transport_domain_in, din, opcode, 11317efce369SYishai Hadas MLX5_CMD_OP_DEALLOC_TRANSPORT_DOMAIN); 1132*1368ead0SYishai Hadas MLX5_SET(dealloc_transport_domain_in, din, transport_domain, 1133*1368ead0SYishai Hadas *obj_id); 11347efce369SYishai Hadas break; 11357efce369SYishai Hadas case MLX5_CMD_OP_CREATE_RMP: 1136*1368ead0SYishai Hadas MLX5_SET(destroy_rmp_in, din, opcode, MLX5_CMD_OP_DESTROY_RMP); 1137*1368ead0SYishai Hadas MLX5_SET(destroy_rmp_in, din, rmpn, *obj_id); 11387efce369SYishai Hadas break; 11397efce369SYishai Hadas case MLX5_CMD_OP_CREATE_SQ: 1140*1368ead0SYishai Hadas MLX5_SET(destroy_sq_in, din, opcode, MLX5_CMD_OP_DESTROY_SQ); 1141*1368ead0SYishai Hadas MLX5_SET(destroy_sq_in, din, sqn, *obj_id); 11427efce369SYishai Hadas break; 11437efce369SYishai Hadas case MLX5_CMD_OP_CREATE_RQ: 1144*1368ead0SYishai Hadas MLX5_SET(destroy_rq_in, din, opcode, MLX5_CMD_OP_DESTROY_RQ); 1145*1368ead0SYishai Hadas MLX5_SET(destroy_rq_in, din, rqn, *obj_id); 11467efce369SYishai Hadas break; 11477efce369SYishai Hadas case MLX5_CMD_OP_CREATE_RQT: 1148*1368ead0SYishai Hadas MLX5_SET(destroy_rqt_in, din, opcode, MLX5_CMD_OP_DESTROY_RQT); 1149*1368ead0SYishai Hadas MLX5_SET(destroy_rqt_in, din, rqtn, *obj_id); 11507efce369SYishai Hadas break; 11517efce369SYishai Hadas case MLX5_CMD_OP_CREATE_TIR: 11528798e4adSYishai Hadas MLX5_SET(destroy_tir_in, din, opcode, MLX5_CMD_OP_DESTROY_TIR); 11538798e4adSYishai Hadas MLX5_SET(destroy_tir_in, din, tirn, *obj_id); 11547efce369SYishai Hadas break; 11557efce369SYishai Hadas case MLX5_CMD_OP_CREATE_TIS: 1156*1368ead0SYishai Hadas MLX5_SET(destroy_tis_in, din, opcode, MLX5_CMD_OP_DESTROY_TIS); 1157*1368ead0SYishai Hadas MLX5_SET(destroy_tis_in, din, tisn, *obj_id); 11587efce369SYishai Hadas break; 11597efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_Q_COUNTER: 1160*1368ead0SYishai Hadas MLX5_SET(dealloc_q_counter_in, din, opcode, 11617efce369SYishai Hadas MLX5_CMD_OP_DEALLOC_Q_COUNTER); 1162*1368ead0SYishai Hadas MLX5_SET(dealloc_q_counter_in, din, counter_set_id, *obj_id); 11637efce369SYishai Hadas break; 11647efce369SYishai Hadas case MLX5_CMD_OP_CREATE_FLOW_TABLE: 11657efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(destroy_flow_table_in); 11667efce369SYishai Hadas MLX5_SET(destroy_flow_table_in, din, other_vport, 11677efce369SYishai Hadas MLX5_GET(create_flow_table_in, in, other_vport)); 11687efce369SYishai Hadas MLX5_SET(destroy_flow_table_in, din, vport_number, 11697efce369SYishai Hadas MLX5_GET(create_flow_table_in, in, vport_number)); 11707efce369SYishai Hadas MLX5_SET(destroy_flow_table_in, din, table_type, 11717efce369SYishai Hadas MLX5_GET(create_flow_table_in, in, table_type)); 11727efce369SYishai Hadas MLX5_SET(destroy_flow_table_in, din, table_id, *obj_id); 1173*1368ead0SYishai Hadas MLX5_SET(destroy_flow_table_in, din, opcode, 11747efce369SYishai Hadas MLX5_CMD_OP_DESTROY_FLOW_TABLE); 11757efce369SYishai Hadas break; 11767efce369SYishai Hadas case MLX5_CMD_OP_CREATE_FLOW_GROUP: 11777efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(destroy_flow_group_in); 11787efce369SYishai Hadas MLX5_SET(destroy_flow_group_in, din, other_vport, 11797efce369SYishai Hadas MLX5_GET(create_flow_group_in, in, other_vport)); 11807efce369SYishai Hadas MLX5_SET(destroy_flow_group_in, din, vport_number, 11817efce369SYishai Hadas MLX5_GET(create_flow_group_in, in, vport_number)); 11827efce369SYishai Hadas MLX5_SET(destroy_flow_group_in, din, table_type, 11837efce369SYishai Hadas MLX5_GET(create_flow_group_in, in, table_type)); 11847efce369SYishai Hadas MLX5_SET(destroy_flow_group_in, din, table_id, 11857efce369SYishai Hadas MLX5_GET(create_flow_group_in, in, table_id)); 11867efce369SYishai Hadas MLX5_SET(destroy_flow_group_in, din, group_id, *obj_id); 1187*1368ead0SYishai Hadas MLX5_SET(destroy_flow_group_in, din, opcode, 11887efce369SYishai Hadas MLX5_CMD_OP_DESTROY_FLOW_GROUP); 11897efce369SYishai Hadas break; 11907efce369SYishai Hadas case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY: 11917efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(delete_fte_in); 11927efce369SYishai Hadas MLX5_SET(delete_fte_in, din, other_vport, 11937efce369SYishai Hadas MLX5_GET(set_fte_in, in, other_vport)); 11947efce369SYishai Hadas MLX5_SET(delete_fte_in, din, vport_number, 11957efce369SYishai Hadas MLX5_GET(set_fte_in, in, vport_number)); 11967efce369SYishai Hadas MLX5_SET(delete_fte_in, din, table_type, 11977efce369SYishai Hadas MLX5_GET(set_fte_in, in, table_type)); 11987efce369SYishai Hadas MLX5_SET(delete_fte_in, din, table_id, 11997efce369SYishai Hadas MLX5_GET(set_fte_in, in, table_id)); 12007efce369SYishai Hadas MLX5_SET(delete_fte_in, din, flow_index, *obj_id); 1201*1368ead0SYishai Hadas MLX5_SET(delete_fte_in, din, opcode, 12027efce369SYishai Hadas MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY); 12037efce369SYishai Hadas break; 12047efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_FLOW_COUNTER: 1205*1368ead0SYishai Hadas MLX5_SET(dealloc_flow_counter_in, din, opcode, 12067efce369SYishai Hadas MLX5_CMD_OP_DEALLOC_FLOW_COUNTER); 1207*1368ead0SYishai Hadas MLX5_SET(dealloc_flow_counter_in, din, flow_counter_id, 1208*1368ead0SYishai Hadas *obj_id); 12097efce369SYishai Hadas break; 121060786f09SMark Bloch case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT: 1211*1368ead0SYishai Hadas MLX5_SET(dealloc_packet_reformat_context_in, din, opcode, 121260786f09SMark Bloch MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT); 1213*1368ead0SYishai Hadas MLX5_SET(dealloc_packet_reformat_context_in, din, 1214*1368ead0SYishai Hadas packet_reformat_id, *obj_id); 12157efce369SYishai Hadas break; 12167efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT: 1217*1368ead0SYishai Hadas MLX5_SET(dealloc_modify_header_context_in, din, opcode, 12187efce369SYishai Hadas MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT); 1219*1368ead0SYishai Hadas MLX5_SET(dealloc_modify_header_context_in, din, 1220*1368ead0SYishai Hadas modify_header_id, *obj_id); 12217efce369SYishai Hadas break; 12227efce369SYishai Hadas case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT: 12237efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(destroy_scheduling_element_in); 12247efce369SYishai Hadas MLX5_SET(destroy_scheduling_element_in, din, 12257efce369SYishai Hadas scheduling_hierarchy, 12267efce369SYishai Hadas MLX5_GET(create_scheduling_element_in, in, 12277efce369SYishai Hadas scheduling_hierarchy)); 12287efce369SYishai Hadas MLX5_SET(destroy_scheduling_element_in, din, 12297efce369SYishai Hadas scheduling_element_id, *obj_id); 1230*1368ead0SYishai Hadas MLX5_SET(destroy_scheduling_element_in, din, opcode, 12317efce369SYishai Hadas MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT); 12327efce369SYishai Hadas break; 12337efce369SYishai Hadas case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT: 12347efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(delete_vxlan_udp_dport_in); 12357efce369SYishai Hadas MLX5_SET(delete_vxlan_udp_dport_in, din, vxlan_udp_port, *obj_id); 1236*1368ead0SYishai Hadas MLX5_SET(delete_vxlan_udp_dport_in, din, opcode, 12377efce369SYishai Hadas MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT); 12387efce369SYishai Hadas break; 12397efce369SYishai Hadas case MLX5_CMD_OP_SET_L2_TABLE_ENTRY: 12407efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(delete_l2_table_entry_in); 12417efce369SYishai Hadas MLX5_SET(delete_l2_table_entry_in, din, table_index, *obj_id); 1242*1368ead0SYishai Hadas MLX5_SET(delete_l2_table_entry_in, din, opcode, 12437efce369SYishai Hadas MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY); 12447efce369SYishai Hadas break; 12457efce369SYishai Hadas case MLX5_CMD_OP_CREATE_QP: 1246*1368ead0SYishai Hadas MLX5_SET(destroy_qp_in, din, opcode, MLX5_CMD_OP_DESTROY_QP); 1247*1368ead0SYishai Hadas MLX5_SET(destroy_qp_in, din, qpn, *obj_id); 12487efce369SYishai Hadas break; 12497efce369SYishai Hadas case MLX5_CMD_OP_CREATE_SRQ: 1250*1368ead0SYishai Hadas MLX5_SET(destroy_srq_in, din, opcode, MLX5_CMD_OP_DESTROY_SRQ); 1251*1368ead0SYishai Hadas MLX5_SET(destroy_srq_in, din, srqn, *obj_id); 12527efce369SYishai Hadas break; 12537efce369SYishai Hadas case MLX5_CMD_OP_CREATE_XRC_SRQ: 1254*1368ead0SYishai Hadas MLX5_SET(destroy_xrc_srq_in, din, opcode, 12557efce369SYishai Hadas MLX5_CMD_OP_DESTROY_XRC_SRQ); 1256*1368ead0SYishai Hadas MLX5_SET(destroy_xrc_srq_in, din, xrc_srqn, *obj_id); 12577efce369SYishai Hadas break; 12587efce369SYishai Hadas case MLX5_CMD_OP_CREATE_DCT: 1259*1368ead0SYishai Hadas MLX5_SET(destroy_dct_in, din, opcode, MLX5_CMD_OP_DESTROY_DCT); 1260*1368ead0SYishai Hadas MLX5_SET(destroy_dct_in, din, dctn, *obj_id); 12617efce369SYishai Hadas break; 12627efce369SYishai Hadas case MLX5_CMD_OP_CREATE_XRQ: 1263*1368ead0SYishai Hadas MLX5_SET(destroy_xrq_in, din, opcode, MLX5_CMD_OP_DESTROY_XRQ); 1264*1368ead0SYishai Hadas MLX5_SET(destroy_xrq_in, din, xrqn, *obj_id); 12657efce369SYishai Hadas break; 12667efce369SYishai Hadas case MLX5_CMD_OP_ATTACH_TO_MCG: 12677efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(detach_from_mcg_in); 12687efce369SYishai Hadas MLX5_SET(detach_from_mcg_in, din, qpn, 12697efce369SYishai Hadas MLX5_GET(attach_to_mcg_in, in, qpn)); 12707efce369SYishai Hadas memcpy(MLX5_ADDR_OF(detach_from_mcg_in, din, multicast_gid), 12717efce369SYishai Hadas MLX5_ADDR_OF(attach_to_mcg_in, in, multicast_gid), 12727efce369SYishai Hadas MLX5_FLD_SZ_BYTES(attach_to_mcg_in, multicast_gid)); 1273*1368ead0SYishai Hadas MLX5_SET(detach_from_mcg_in, din, opcode, 1274*1368ead0SYishai Hadas MLX5_CMD_OP_DETACH_FROM_MCG); 1275*1368ead0SYishai Hadas MLX5_SET(detach_from_mcg_in, din, qpn, *obj_id); 12767efce369SYishai Hadas break; 12777efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_XRCD: 1278*1368ead0SYishai Hadas MLX5_SET(dealloc_xrcd_in, din, opcode, 1279*1368ead0SYishai Hadas MLX5_CMD_OP_DEALLOC_XRCD); 1280*1368ead0SYishai Hadas MLX5_SET(dealloc_xrcd_in, din, xrcd, *obj_id); 12817efce369SYishai Hadas break; 12828b38c538SMax Gurtovoy case MLX5_CMD_OP_CREATE_PSV: 1283*1368ead0SYishai Hadas MLX5_SET(destroy_psv_in, din, opcode, 12848b38c538SMax Gurtovoy MLX5_CMD_OP_DESTROY_PSV); 1285*1368ead0SYishai Hadas MLX5_SET(destroy_psv_in, din, psvn, *obj_id); 12868b38c538SMax Gurtovoy break; 12877efce369SYishai Hadas default: 12887efce369SYishai Hadas /* The entry must match to one of the devx_is_obj_create_cmd */ 12897efce369SYishai Hadas WARN_ON(true); 12907efce369SYishai Hadas break; 12917efce369SYishai Hadas } 12927efce369SYishai Hadas } 12937efce369SYishai Hadas 1294534fd7aaSYishai Hadas static int devx_handle_mkey_indirect(struct devx_obj *obj, 1295534fd7aaSYishai Hadas struct mlx5_ib_dev *dev, 1296534fd7aaSYishai Hadas void *in, void *out) 1297534fd7aaSYishai Hadas { 1298534fd7aaSYishai Hadas struct mlx5_ib_devx_mr *devx_mr = &obj->devx_mr; 1299534fd7aaSYishai Hadas struct mlx5_core_mkey *mkey; 1300534fd7aaSYishai Hadas void *mkc; 1301534fd7aaSYishai Hadas u8 key; 1302534fd7aaSYishai Hadas 1303534fd7aaSYishai Hadas mkey = &devx_mr->mmkey; 1304534fd7aaSYishai Hadas mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry); 1305534fd7aaSYishai Hadas key = MLX5_GET(mkc, mkc, mkey_7_0); 1306534fd7aaSYishai Hadas mkey->key = mlx5_idx_to_mkey( 1307534fd7aaSYishai Hadas MLX5_GET(create_mkey_out, out, mkey_index)) | key; 1308534fd7aaSYishai Hadas mkey->type = MLX5_MKEY_INDIRECT_DEVX; 1309534fd7aaSYishai Hadas mkey->iova = MLX5_GET64(mkc, mkc, start_addr); 1310534fd7aaSYishai Hadas mkey->size = MLX5_GET64(mkc, mkc, len); 1311534fd7aaSYishai Hadas mkey->pd = MLX5_GET(mkc, mkc, pd); 1312534fd7aaSYishai Hadas devx_mr->ndescs = MLX5_GET(mkc, mkc, translations_octword_size); 1313534fd7aaSYishai Hadas 1314806b101bSJason Gunthorpe return xa_err(xa_store(&dev->odp_mkeys, mlx5_base_mkey(mkey->key), mkey, 1315806b101bSJason Gunthorpe GFP_KERNEL)); 1316534fd7aaSYishai Hadas } 1317534fd7aaSYishai Hadas 1318fa31f143SYishai Hadas static int devx_handle_mkey_create(struct mlx5_ib_dev *dev, 1319fa31f143SYishai Hadas struct devx_obj *obj, 1320fa31f143SYishai Hadas void *in, int in_len) 1321fa31f143SYishai Hadas { 1322fa31f143SYishai Hadas int min_len = MLX5_BYTE_OFF(create_mkey_in, memory_key_mkey_entry) + 1323fa31f143SYishai Hadas MLX5_FLD_SZ_BYTES(create_mkey_in, 1324fa31f143SYishai Hadas memory_key_mkey_entry); 1325fa31f143SYishai Hadas void *mkc; 1326fa31f143SYishai Hadas u8 access_mode; 1327fa31f143SYishai Hadas 1328fa31f143SYishai Hadas if (in_len < min_len) 1329fa31f143SYishai Hadas return -EINVAL; 1330fa31f143SYishai Hadas 1331fa31f143SYishai Hadas mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry); 1332fa31f143SYishai Hadas 1333fa31f143SYishai Hadas access_mode = MLX5_GET(mkc, mkc, access_mode_1_0); 1334fa31f143SYishai Hadas access_mode |= MLX5_GET(mkc, mkc, access_mode_4_2) << 2; 1335fa31f143SYishai Hadas 1336fa31f143SYishai Hadas if (access_mode == MLX5_MKC_ACCESS_MODE_KLMS || 1337534fd7aaSYishai Hadas access_mode == MLX5_MKC_ACCESS_MODE_KSM) { 1338534fd7aaSYishai Hadas if (IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING)) 1339534fd7aaSYishai Hadas obj->flags |= DEVX_OBJ_FLAGS_INDIRECT_MKEY; 1340fa31f143SYishai Hadas return 0; 1341534fd7aaSYishai Hadas } 1342fa31f143SYishai Hadas 1343fa31f143SYishai Hadas MLX5_SET(create_mkey_in, in, mkey_umem_valid, 1); 1344fa31f143SYishai Hadas return 0; 1345fa31f143SYishai Hadas } 1346fa31f143SYishai Hadas 134775973853SYishai Hadas static void devx_cleanup_subscription(struct mlx5_ib_dev *dev, 134875973853SYishai Hadas struct devx_event_subscription *sub) 134975973853SYishai Hadas { 135075973853SYishai Hadas struct devx_event *event; 135175973853SYishai Hadas struct devx_obj_event *xa_val_level2; 135275973853SYishai Hadas 135375973853SYishai Hadas if (sub->is_cleaned) 135475973853SYishai Hadas return; 135575973853SYishai Hadas 135675973853SYishai Hadas sub->is_cleaned = 1; 135775973853SYishai Hadas list_del_rcu(&sub->xa_list); 135875973853SYishai Hadas 135975973853SYishai Hadas if (list_empty(&sub->obj_list)) 136075973853SYishai Hadas return; 136175973853SYishai Hadas 136275973853SYishai Hadas list_del_rcu(&sub->obj_list); 136375973853SYishai Hadas /* check whether key level 1 for this obj_sub_list is empty */ 136475973853SYishai Hadas event = xa_load(&dev->devx_event_table.event_xa, 136575973853SYishai Hadas sub->xa_key_level1); 136675973853SYishai Hadas WARN_ON(!event); 136775973853SYishai Hadas 136875973853SYishai Hadas xa_val_level2 = xa_load(&event->object_ids, sub->xa_key_level2); 136975973853SYishai Hadas if (list_empty(&xa_val_level2->obj_sub_list)) { 137075973853SYishai Hadas xa_erase(&event->object_ids, 137175973853SYishai Hadas sub->xa_key_level2); 137275973853SYishai Hadas kfree_rcu(xa_val_level2, rcu); 137375973853SYishai Hadas } 137475973853SYishai Hadas } 137575973853SYishai Hadas 13767efce369SYishai Hadas static int devx_obj_cleanup(struct ib_uobject *uobject, 1377a6a3797dSShamir Rabinovitch enum rdma_remove_reason why, 1378a6a3797dSShamir Rabinovitch struct uverbs_attr_bundle *attrs) 13797efce369SYishai Hadas { 13807efce369SYishai Hadas u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)]; 138175973853SYishai Hadas struct mlx5_devx_event_table *devx_event_table; 13827efce369SYishai Hadas struct devx_obj *obj = uobject->object; 138375973853SYishai Hadas struct devx_event_subscription *sub_entry, *tmp; 138475973853SYishai Hadas struct mlx5_ib_dev *dev; 13857efce369SYishai Hadas int ret; 13867efce369SYishai Hadas 138775973853SYishai Hadas dev = mlx5_udata_to_mdev(&attrs->driver_udata); 138804177915SJason Gunthorpe if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY) { 138904177915SJason Gunthorpe /* 139004177915SJason Gunthorpe * The pagefault_single_data_segment() does commands against 139104177915SJason Gunthorpe * the mmkey, we must wait for that to stop before freeing the 139204177915SJason Gunthorpe * mkey, as another allocation could get the same mkey #. 139304177915SJason Gunthorpe */ 1394806b101bSJason Gunthorpe xa_erase(&obj->ib_dev->odp_mkeys, 139504177915SJason Gunthorpe mlx5_base_mkey(obj->devx_mr.mmkey.key)); 1396806b101bSJason Gunthorpe synchronize_srcu(&dev->odp_srcu); 139704177915SJason Gunthorpe } 1398534fd7aaSYishai Hadas 1399c5ae1954SYishai Hadas if (obj->flags & DEVX_OBJ_FLAGS_DCT) 1400333fbaa0SLeon Romanovsky ret = mlx5_core_destroy_dct(obj->ib_dev, &obj->core_dct); 1401ef1659adSYishai Hadas else if (obj->flags & DEVX_OBJ_FLAGS_CQ) 14025832fdd3SYishai Hadas ret = mlx5_core_destroy_cq(obj->ib_dev->mdev, &obj->core_cq); 1403c5ae1954SYishai Hadas else 14045832fdd3SYishai Hadas ret = mlx5_cmd_exec(obj->ib_dev->mdev, obj->dinbox, 14055832fdd3SYishai Hadas obj->dinlen, out, sizeof(out)); 1406efa968eeSLeon Romanovsky if (ret) 14077efce369SYishai Hadas return ret; 14087efce369SYishai Hadas 140975973853SYishai Hadas devx_event_table = &dev->devx_event_table; 1410534fd7aaSYishai Hadas 141175973853SYishai Hadas mutex_lock(&devx_event_table->event_xa_lock); 141275973853SYishai Hadas list_for_each_entry_safe(sub_entry, tmp, &obj->event_sub, obj_list) 141375973853SYishai Hadas devx_cleanup_subscription(dev, sub_entry); 141475973853SYishai Hadas mutex_unlock(&devx_event_table->event_xa_lock); 141575973853SYishai Hadas 14167efce369SYishai Hadas kfree(obj); 14177efce369SYishai Hadas return ret; 14187efce369SYishai Hadas } 14197efce369SYishai Hadas 1420ef1659adSYishai Hadas static void devx_cq_comp(struct mlx5_core_cq *mcq, struct mlx5_eqe *eqe) 1421ef1659adSYishai Hadas { 1422ef1659adSYishai Hadas struct devx_obj *obj = container_of(mcq, struct devx_obj, core_cq); 1423ef1659adSYishai Hadas struct mlx5_devx_event_table *table; 1424ef1659adSYishai Hadas struct devx_event *event; 1425ef1659adSYishai Hadas struct devx_obj_event *obj_event; 1426ef1659adSYishai Hadas u32 obj_id = mcq->cqn; 1427ef1659adSYishai Hadas 1428ef1659adSYishai Hadas table = &obj->ib_dev->devx_event_table; 1429ef1659adSYishai Hadas rcu_read_lock(); 1430ef1659adSYishai Hadas event = xa_load(&table->event_xa, MLX5_EVENT_TYPE_COMP); 1431ef1659adSYishai Hadas if (!event) 1432ef1659adSYishai Hadas goto out; 1433ef1659adSYishai Hadas 1434ef1659adSYishai Hadas obj_event = xa_load(&event->object_ids, obj_id); 1435ef1659adSYishai Hadas if (!obj_event) 1436ef1659adSYishai Hadas goto out; 1437ef1659adSYishai Hadas 1438ef1659adSYishai Hadas dispatch_event_fd(&obj_event->obj_sub_list, eqe); 1439ef1659adSYishai Hadas out: 1440ef1659adSYishai Hadas rcu_read_unlock(); 1441ef1659adSYishai Hadas } 1442ef1659adSYishai Hadas 1443e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)( 144415a1b4beSJason Gunthorpe struct uverbs_attr_bundle *attrs) 14457efce369SYishai Hadas { 14467efce369SYishai Hadas void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN); 14477efce369SYishai Hadas int cmd_out_len = uverbs_attr_get_len(attrs, 14487efce369SYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT); 1449fa31f143SYishai Hadas int cmd_in_len = uverbs_attr_get_len(attrs, 1450fa31f143SYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN); 14517efce369SYishai Hadas void *cmd_out; 1452c36ee46dSJason Gunthorpe struct ib_uobject *uobj = uverbs_attr_get_uobject( 1453c36ee46dSJason Gunthorpe attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE); 145489944450SShamir Rabinovitch struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context( 145589944450SShamir Rabinovitch &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext); 1456c36ee46dSJason Gunthorpe struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device); 1457e8ef090aSYishai Hadas u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)]; 14587efce369SYishai Hadas struct devx_obj *obj; 1459cd5d20f1SYishai Hadas u16 obj_type = 0; 14607efce369SYishai Hadas int err; 14617e1335a7SYishai Hadas int uid; 14622351776eSYishai Hadas u32 obj_id; 14632351776eSYishai Hadas u16 opcode; 14647efce369SYishai Hadas 1465b6142608SMax Gurtovoy if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id)) 1466b6142608SMax Gurtovoy return -EINVAL; 1467b6142608SMax Gurtovoy 14687e1335a7SYishai Hadas uid = devx_get_uid(c, cmd_in); 14697e1335a7SYishai Hadas if (uid < 0) 14707e1335a7SYishai Hadas return uid; 14717efce369SYishai Hadas 14722351776eSYishai Hadas if (!devx_is_obj_create_cmd(cmd_in, &opcode)) 14737efce369SYishai Hadas return -EINVAL; 14747efce369SYishai Hadas 1475b61815e2SJason Gunthorpe cmd_out = uverbs_zalloc(attrs, cmd_out_len); 1476b61815e2SJason Gunthorpe if (IS_ERR(cmd_out)) 1477b61815e2SJason Gunthorpe return PTR_ERR(cmd_out); 1478b61815e2SJason Gunthorpe 14797efce369SYishai Hadas obj = kzalloc(sizeof(struct devx_obj), GFP_KERNEL); 14807efce369SYishai Hadas if (!obj) 14817efce369SYishai Hadas return -ENOMEM; 14827efce369SYishai Hadas 14837e1335a7SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); 1484fa31f143SYishai Hadas if (opcode == MLX5_CMD_OP_CREATE_MKEY) { 1485fa31f143SYishai Hadas err = devx_handle_mkey_create(dev, obj, cmd_in, cmd_in_len); 1486fa31f143SYishai Hadas if (err) 1487fa31f143SYishai Hadas goto obj_free; 1488fa31f143SYishai Hadas } else { 1489ba1a057dSYishai Hadas devx_set_umem_valid(cmd_in); 1490fa31f143SYishai Hadas } 1491ba1a057dSYishai Hadas 1492c5ae1954SYishai Hadas if (opcode == MLX5_CMD_OP_CREATE_DCT) { 1493c5ae1954SYishai Hadas obj->flags |= DEVX_OBJ_FLAGS_DCT; 1494333fbaa0SLeon Romanovsky err = mlx5_core_create_dct(dev, &obj->core_dct, cmd_in, 1495333fbaa0SLeon Romanovsky cmd_in_len, cmd_out, cmd_out_len); 1496ef1659adSYishai Hadas } else if (opcode == MLX5_CMD_OP_CREATE_CQ) { 1497ef1659adSYishai Hadas obj->flags |= DEVX_OBJ_FLAGS_CQ; 1498ef1659adSYishai Hadas obj->core_cq.comp = devx_cq_comp; 1499ef1659adSYishai Hadas err = mlx5_core_create_cq(dev->mdev, &obj->core_cq, 1500ef1659adSYishai Hadas cmd_in, cmd_in_len, cmd_out, 1501ef1659adSYishai Hadas cmd_out_len); 1502c5ae1954SYishai Hadas } else { 15037efce369SYishai Hadas err = mlx5_cmd_exec(dev->mdev, cmd_in, 1504fa31f143SYishai Hadas cmd_in_len, 15057efce369SYishai Hadas cmd_out, cmd_out_len); 1506c5ae1954SYishai Hadas } 1507c5ae1954SYishai Hadas 15087efce369SYishai Hadas if (err) 1509b61815e2SJason Gunthorpe goto obj_free; 15107efce369SYishai Hadas 1511208d70f5SYevgeny Kliteynik if (opcode == MLX5_CMD_OP_ALLOC_FLOW_COUNTER) { 1512208d70f5SYevgeny Kliteynik u8 bulk = MLX5_GET(alloc_flow_counter_in, 1513208d70f5SYevgeny Kliteynik cmd_in, 1514208d70f5SYevgeny Kliteynik flow_counter_bulk); 1515208d70f5SYevgeny Kliteynik obj->flow_counter_bulk_size = 128UL * bulk; 1516208d70f5SYevgeny Kliteynik } 1517208d70f5SYevgeny Kliteynik 15187efce369SYishai Hadas uobj->object = obj; 151975973853SYishai Hadas INIT_LIST_HEAD(&obj->event_sub); 1520ef1659adSYishai Hadas obj->ib_dev = dev; 15212351776eSYishai Hadas devx_obj_build_destroy_cmd(cmd_in, cmd_out, obj->dinbox, &obj->dinlen, 15222351776eSYishai Hadas &obj_id); 15237efce369SYishai Hadas WARN_ON(obj->dinlen > MLX5_MAX_DESTROY_INBOX_SIZE_DW * sizeof(u32)); 15247efce369SYishai Hadas 152504177915SJason Gunthorpe err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT, cmd_out, cmd_out_len); 152604177915SJason Gunthorpe if (err) 152704177915SJason Gunthorpe goto obj_destroy; 152804177915SJason Gunthorpe 152904177915SJason Gunthorpe if (opcode == MLX5_CMD_OP_CREATE_GENERAL_OBJECT) 153004177915SJason Gunthorpe obj_type = MLX5_GET(general_obj_in_cmd_hdr, cmd_in, obj_type); 153104177915SJason Gunthorpe obj->obj_id = get_enc_obj_id(opcode | obj_type << 16, obj_id); 153204177915SJason Gunthorpe 1533534fd7aaSYishai Hadas if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY) { 1534534fd7aaSYishai Hadas err = devx_handle_mkey_indirect(obj, dev, cmd_in, cmd_out); 1535534fd7aaSYishai Hadas if (err) 1536534fd7aaSYishai Hadas goto obj_destroy; 1537534fd7aaSYishai Hadas } 15387efce369SYishai Hadas return 0; 15397efce369SYishai Hadas 15400da4d48dSYishai Hadas obj_destroy: 1541c5ae1954SYishai Hadas if (obj->flags & DEVX_OBJ_FLAGS_DCT) 1542333fbaa0SLeon Romanovsky mlx5_core_destroy_dct(obj->ib_dev, &obj->core_dct); 1543ef1659adSYishai Hadas else if (obj->flags & DEVX_OBJ_FLAGS_CQ) 15445832fdd3SYishai Hadas mlx5_core_destroy_cq(obj->ib_dev->mdev, &obj->core_cq); 1545c5ae1954SYishai Hadas else 15465832fdd3SYishai Hadas mlx5_cmd_exec(obj->ib_dev->mdev, obj->dinbox, obj->dinlen, out, 1547c5ae1954SYishai Hadas sizeof(out)); 15487efce369SYishai Hadas obj_free: 15497efce369SYishai Hadas kfree(obj); 15507efce369SYishai Hadas return err; 15517efce369SYishai Hadas } 15527efce369SYishai Hadas 1553e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_MODIFY)( 155415a1b4beSJason Gunthorpe struct uverbs_attr_bundle *attrs) 1555e662e14dSYishai Hadas { 1556e662e14dSYishai Hadas void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN); 1557e662e14dSYishai Hadas int cmd_out_len = uverbs_attr_get_len(attrs, 1558e662e14dSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT); 1559e662e14dSYishai Hadas struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs, 1560e662e14dSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE); 156189944450SShamir Rabinovitch struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context( 156289944450SShamir Rabinovitch &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext); 156389944450SShamir Rabinovitch struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device); 1564e662e14dSYishai Hadas void *cmd_out; 1565e662e14dSYishai Hadas int err; 15667e1335a7SYishai Hadas int uid; 1567e662e14dSYishai Hadas 1568b6142608SMax Gurtovoy if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id)) 1569b6142608SMax Gurtovoy return -EINVAL; 1570b6142608SMax Gurtovoy 15717e1335a7SYishai Hadas uid = devx_get_uid(c, cmd_in); 15727e1335a7SYishai Hadas if (uid < 0) 15737e1335a7SYishai Hadas return uid; 1574e662e14dSYishai Hadas 1575e662e14dSYishai Hadas if (!devx_is_obj_modify_cmd(cmd_in)) 1576e662e14dSYishai Hadas return -EINVAL; 1577e662e14dSYishai Hadas 1578e79c9c60SJason Gunthorpe if (!devx_is_valid_obj_id(attrs, uobj, cmd_in)) 1579e662e14dSYishai Hadas return -EINVAL; 1580e662e14dSYishai Hadas 1581b61815e2SJason Gunthorpe cmd_out = uverbs_zalloc(attrs, cmd_out_len); 1582b61815e2SJason Gunthorpe if (IS_ERR(cmd_out)) 1583b61815e2SJason Gunthorpe return PTR_ERR(cmd_out); 1584e662e14dSYishai Hadas 15857e1335a7SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); 1586ba1a057dSYishai Hadas devx_set_umem_valid(cmd_in); 1587ba1a057dSYishai Hadas 158834613eb1SYishai Hadas err = mlx5_cmd_exec(mdev->mdev, cmd_in, 1589e662e14dSYishai Hadas uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN), 1590e662e14dSYishai Hadas cmd_out, cmd_out_len); 1591e662e14dSYishai Hadas if (err) 1592e662e14dSYishai Hadas return err; 1593b61815e2SJason Gunthorpe 1594b61815e2SJason Gunthorpe return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT, 1595b61815e2SJason Gunthorpe cmd_out, cmd_out_len); 1596e662e14dSYishai Hadas } 1597e662e14dSYishai Hadas 1598e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)( 159915a1b4beSJason Gunthorpe struct uverbs_attr_bundle *attrs) 1600e662e14dSYishai Hadas { 1601e662e14dSYishai Hadas void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN); 1602e662e14dSYishai Hadas int cmd_out_len = uverbs_attr_get_len(attrs, 1603e662e14dSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT); 1604e662e14dSYishai Hadas struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs, 1605e662e14dSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE); 160689944450SShamir Rabinovitch struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context( 160789944450SShamir Rabinovitch &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext); 1608e662e14dSYishai Hadas void *cmd_out; 1609e662e14dSYishai Hadas int err; 16107e1335a7SYishai Hadas int uid; 161189944450SShamir Rabinovitch struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device); 1612e662e14dSYishai Hadas 1613b6142608SMax Gurtovoy if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id)) 1614b6142608SMax Gurtovoy return -EINVAL; 1615b6142608SMax Gurtovoy 16167e1335a7SYishai Hadas uid = devx_get_uid(c, cmd_in); 16177e1335a7SYishai Hadas if (uid < 0) 16187e1335a7SYishai Hadas return uid; 1619e662e14dSYishai Hadas 1620e662e14dSYishai Hadas if (!devx_is_obj_query_cmd(cmd_in)) 1621e662e14dSYishai Hadas return -EINVAL; 1622e662e14dSYishai Hadas 1623e79c9c60SJason Gunthorpe if (!devx_is_valid_obj_id(attrs, uobj, cmd_in)) 1624e662e14dSYishai Hadas return -EINVAL; 1625e662e14dSYishai Hadas 1626b61815e2SJason Gunthorpe cmd_out = uverbs_zalloc(attrs, cmd_out_len); 1627b61815e2SJason Gunthorpe if (IS_ERR(cmd_out)) 1628b61815e2SJason Gunthorpe return PTR_ERR(cmd_out); 1629e662e14dSYishai Hadas 16307e1335a7SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); 163134613eb1SYishai Hadas err = mlx5_cmd_exec(mdev->mdev, cmd_in, 1632e662e14dSYishai Hadas uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN), 1633e662e14dSYishai Hadas cmd_out, cmd_out_len); 1634e662e14dSYishai Hadas if (err) 1635e662e14dSYishai Hadas return err; 1636b61815e2SJason Gunthorpe 1637b61815e2SJason Gunthorpe return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT, 1638b61815e2SJason Gunthorpe cmd_out, cmd_out_len); 1639e662e14dSYishai Hadas } 1640e662e14dSYishai Hadas 16416bf8f22aSYishai Hadas struct devx_async_event_queue { 16426bf8f22aSYishai Hadas spinlock_t lock; 16436bf8f22aSYishai Hadas wait_queue_head_t poll_wait; 16446bf8f22aSYishai Hadas struct list_head event_list; 1645a124edbaSYishai Hadas atomic_t bytes_in_use; 1646eaebaf77SYishai Hadas u8 is_destroyed:1; 16476bf8f22aSYishai Hadas }; 16486bf8f22aSYishai Hadas 16496bf8f22aSYishai Hadas struct devx_async_cmd_event_file { 16506bf8f22aSYishai Hadas struct ib_uobject uobj; 16516bf8f22aSYishai Hadas struct devx_async_event_queue ev_queue; 1652a124edbaSYishai Hadas struct mlx5_async_ctx async_ctx; 16536bf8f22aSYishai Hadas }; 16546bf8f22aSYishai Hadas 16556bf8f22aSYishai Hadas static void devx_init_event_queue(struct devx_async_event_queue *ev_queue) 16566bf8f22aSYishai Hadas { 16576bf8f22aSYishai Hadas spin_lock_init(&ev_queue->lock); 16586bf8f22aSYishai Hadas INIT_LIST_HEAD(&ev_queue->event_list); 16596bf8f22aSYishai Hadas init_waitqueue_head(&ev_queue->poll_wait); 1660a124edbaSYishai Hadas atomic_set(&ev_queue->bytes_in_use, 0); 1661eaebaf77SYishai Hadas ev_queue->is_destroyed = 0; 16626bf8f22aSYishai Hadas } 16636bf8f22aSYishai Hadas 16646bf8f22aSYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC)( 16656bf8f22aSYishai Hadas struct uverbs_attr_bundle *attrs) 16666bf8f22aSYishai Hadas { 16676bf8f22aSYishai Hadas struct devx_async_cmd_event_file *ev_file; 16686bf8f22aSYishai Hadas 16696bf8f22aSYishai Hadas struct ib_uobject *uobj = uverbs_attr_get_uobject( 16706bf8f22aSYishai Hadas attrs, MLX5_IB_ATTR_DEVX_ASYNC_CMD_FD_ALLOC_HANDLE); 1671e79c9c60SJason Gunthorpe struct mlx5_ib_dev *mdev = mlx5_udata_to_mdev(&attrs->driver_udata); 16726bf8f22aSYishai Hadas 16736bf8f22aSYishai Hadas ev_file = container_of(uobj, struct devx_async_cmd_event_file, 16746bf8f22aSYishai Hadas uobj); 16756bf8f22aSYishai Hadas devx_init_event_queue(&ev_file->ev_queue); 1676a124edbaSYishai Hadas mlx5_cmd_init_async_ctx(mdev->mdev, &ev_file->async_ctx); 16776bf8f22aSYishai Hadas return 0; 16786bf8f22aSYishai Hadas } 16796bf8f22aSYishai Hadas 16802afc5e1bSYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_ASYNC_EVENT_FD_ALLOC)( 16812afc5e1bSYishai Hadas struct uverbs_attr_bundle *attrs) 16822afc5e1bSYishai Hadas { 16832afc5e1bSYishai Hadas struct ib_uobject *uobj = uverbs_attr_get_uobject( 16842afc5e1bSYishai Hadas attrs, MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_HANDLE); 16852afc5e1bSYishai Hadas struct devx_async_event_file *ev_file; 16862afc5e1bSYishai Hadas struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context( 16872afc5e1bSYishai Hadas &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext); 16882afc5e1bSYishai Hadas struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device); 16892afc5e1bSYishai Hadas u32 flags; 16902afc5e1bSYishai Hadas int err; 16912afc5e1bSYishai Hadas 16922afc5e1bSYishai Hadas err = uverbs_get_flags32(&flags, attrs, 16932afc5e1bSYishai Hadas MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_FLAGS, 16942afc5e1bSYishai Hadas MLX5_IB_UAPI_DEVX_CR_EV_CH_FLAGS_OMIT_DATA); 16952afc5e1bSYishai Hadas 16962afc5e1bSYishai Hadas if (err) 16972afc5e1bSYishai Hadas return err; 16982afc5e1bSYishai Hadas 16992afc5e1bSYishai Hadas ev_file = container_of(uobj, struct devx_async_event_file, 17002afc5e1bSYishai Hadas uobj); 17012afc5e1bSYishai Hadas spin_lock_init(&ev_file->lock); 17022afc5e1bSYishai Hadas INIT_LIST_HEAD(&ev_file->event_list); 17032afc5e1bSYishai Hadas init_waitqueue_head(&ev_file->poll_wait); 17042afc5e1bSYishai Hadas if (flags & MLX5_IB_UAPI_DEVX_CR_EV_CH_FLAGS_OMIT_DATA) 17052afc5e1bSYishai Hadas ev_file->omit_data = 1; 17062afc5e1bSYishai Hadas INIT_LIST_HEAD(&ev_file->subscribed_events_list); 17072afc5e1bSYishai Hadas ev_file->dev = dev; 170875973853SYishai Hadas get_device(&dev->ib_dev.dev); 17092afc5e1bSYishai Hadas return 0; 17102afc5e1bSYishai Hadas } 17112afc5e1bSYishai Hadas 1712a124edbaSYishai Hadas static void devx_query_callback(int status, struct mlx5_async_work *context) 1713a124edbaSYishai Hadas { 1714a124edbaSYishai Hadas struct devx_async_data *async_data = 1715a124edbaSYishai Hadas container_of(context, struct devx_async_data, cb_work); 171693887e66SJason Gunthorpe struct devx_async_cmd_event_file *ev_file = async_data->ev_file; 171793887e66SJason Gunthorpe struct devx_async_event_queue *ev_queue = &ev_file->ev_queue; 1718a124edbaSYishai Hadas unsigned long flags; 1719a124edbaSYishai Hadas 172093887e66SJason Gunthorpe /* 172193887e66SJason Gunthorpe * Note that if the struct devx_async_cmd_event_file uobj begins to be 172293887e66SJason Gunthorpe * destroyed it will block at mlx5_cmd_cleanup_async_ctx() until this 172393887e66SJason Gunthorpe * routine returns, ensuring that it always remains valid here. 172493887e66SJason Gunthorpe */ 1725a124edbaSYishai Hadas spin_lock_irqsave(&ev_queue->lock, flags); 1726a124edbaSYishai Hadas list_add_tail(&async_data->list, &ev_queue->event_list); 1727a124edbaSYishai Hadas spin_unlock_irqrestore(&ev_queue->lock, flags); 1728a124edbaSYishai Hadas 1729a124edbaSYishai Hadas wake_up_interruptible(&ev_queue->poll_wait); 1730a124edbaSYishai Hadas } 1731a124edbaSYishai Hadas 1732a124edbaSYishai Hadas #define MAX_ASYNC_BYTES_IN_USE (1024 * 1024) /* 1MB */ 1733a124edbaSYishai Hadas 1734a124edbaSYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY)( 1735a124edbaSYishai Hadas struct uverbs_attr_bundle *attrs) 1736a124edbaSYishai Hadas { 1737a124edbaSYishai Hadas void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, 1738a124edbaSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_CMD_IN); 1739a124edbaSYishai Hadas struct ib_uobject *uobj = uverbs_attr_get_uobject( 1740a124edbaSYishai Hadas attrs, 1741a124edbaSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_HANDLE); 1742a124edbaSYishai Hadas u16 cmd_out_len; 174389944450SShamir Rabinovitch struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context( 174489944450SShamir Rabinovitch &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext); 1745a124edbaSYishai Hadas struct ib_uobject *fd_uobj; 1746a124edbaSYishai Hadas int err; 1747a124edbaSYishai Hadas int uid; 174889944450SShamir Rabinovitch struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device); 1749a124edbaSYishai Hadas struct devx_async_cmd_event_file *ev_file; 1750a124edbaSYishai Hadas struct devx_async_data *async_data; 1751a124edbaSYishai Hadas 1752b6142608SMax Gurtovoy if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id)) 1753b6142608SMax Gurtovoy return -EINVAL; 1754b6142608SMax Gurtovoy 1755a124edbaSYishai Hadas uid = devx_get_uid(c, cmd_in); 1756a124edbaSYishai Hadas if (uid < 0) 1757a124edbaSYishai Hadas return uid; 1758a124edbaSYishai Hadas 1759a124edbaSYishai Hadas if (!devx_is_obj_query_cmd(cmd_in)) 1760a124edbaSYishai Hadas return -EINVAL; 1761a124edbaSYishai Hadas 1762a124edbaSYishai Hadas err = uverbs_get_const(&cmd_out_len, attrs, 1763a124edbaSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_OUT_LEN); 1764a124edbaSYishai Hadas if (err) 1765a124edbaSYishai Hadas return err; 1766a124edbaSYishai Hadas 1767e79c9c60SJason Gunthorpe if (!devx_is_valid_obj_id(attrs, uobj, cmd_in)) 1768a124edbaSYishai Hadas return -EINVAL; 1769a124edbaSYishai Hadas 1770a124edbaSYishai Hadas fd_uobj = uverbs_attr_get_uobject(attrs, 1771a124edbaSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_FD); 1772a124edbaSYishai Hadas if (IS_ERR(fd_uobj)) 1773a124edbaSYishai Hadas return PTR_ERR(fd_uobj); 1774a124edbaSYishai Hadas 1775a124edbaSYishai Hadas ev_file = container_of(fd_uobj, struct devx_async_cmd_event_file, 1776a124edbaSYishai Hadas uobj); 1777a124edbaSYishai Hadas 1778a124edbaSYishai Hadas if (atomic_add_return(cmd_out_len, &ev_file->ev_queue.bytes_in_use) > 1779a124edbaSYishai Hadas MAX_ASYNC_BYTES_IN_USE) { 1780a124edbaSYishai Hadas atomic_sub(cmd_out_len, &ev_file->ev_queue.bytes_in_use); 1781a124edbaSYishai Hadas return -EAGAIN; 1782a124edbaSYishai Hadas } 1783a124edbaSYishai Hadas 1784a124edbaSYishai Hadas async_data = kvzalloc(struct_size(async_data, hdr.out_data, 1785a124edbaSYishai Hadas cmd_out_len), GFP_KERNEL); 1786a124edbaSYishai Hadas if (!async_data) { 1787a124edbaSYishai Hadas err = -ENOMEM; 1788a124edbaSYishai Hadas goto sub_bytes; 1789a124edbaSYishai Hadas } 1790a124edbaSYishai Hadas 1791a124edbaSYishai Hadas err = uverbs_copy_from(&async_data->hdr.wr_id, attrs, 1792a124edbaSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_WR_ID); 1793a124edbaSYishai Hadas if (err) 1794a124edbaSYishai Hadas goto free_async; 1795a124edbaSYishai Hadas 1796a124edbaSYishai Hadas async_data->cmd_out_len = cmd_out_len; 1797a124edbaSYishai Hadas async_data->mdev = mdev; 179893887e66SJason Gunthorpe async_data->ev_file = ev_file; 1799a124edbaSYishai Hadas 1800a124edbaSYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); 1801a124edbaSYishai Hadas err = mlx5_cmd_exec_cb(&ev_file->async_ctx, cmd_in, 1802a124edbaSYishai Hadas uverbs_attr_get_len(attrs, 1803a124edbaSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_CMD_IN), 1804a124edbaSYishai Hadas async_data->hdr.out_data, 1805a124edbaSYishai Hadas async_data->cmd_out_len, 1806a124edbaSYishai Hadas devx_query_callback, &async_data->cb_work); 1807a124edbaSYishai Hadas 1808a124edbaSYishai Hadas if (err) 180993887e66SJason Gunthorpe goto free_async; 1810a124edbaSYishai Hadas 1811a124edbaSYishai Hadas return 0; 1812a124edbaSYishai Hadas 1813a124edbaSYishai Hadas free_async: 1814a124edbaSYishai Hadas kvfree(async_data); 1815a124edbaSYishai Hadas sub_bytes: 1816a124edbaSYishai Hadas atomic_sub(cmd_out_len, &ev_file->ev_queue.bytes_in_use); 1817a124edbaSYishai Hadas return err; 1818a124edbaSYishai Hadas } 1819a124edbaSYishai Hadas 182075973853SYishai Hadas static void 182175973853SYishai Hadas subscribe_event_xa_dealloc(struct mlx5_devx_event_table *devx_event_table, 182275973853SYishai Hadas u32 key_level1, 182375973853SYishai Hadas bool is_level2, 182475973853SYishai Hadas u32 key_level2) 182575973853SYishai Hadas { 182675973853SYishai Hadas struct devx_event *event; 182775973853SYishai Hadas struct devx_obj_event *xa_val_level2; 182875973853SYishai Hadas 182975973853SYishai Hadas /* Level 1 is valid for future use, no need to free */ 183075973853SYishai Hadas if (!is_level2) 183175973853SYishai Hadas return; 183275973853SYishai Hadas 183375973853SYishai Hadas event = xa_load(&devx_event_table->event_xa, key_level1); 183475973853SYishai Hadas WARN_ON(!event); 183575973853SYishai Hadas 183675973853SYishai Hadas xa_val_level2 = xa_load(&event->object_ids, 183775973853SYishai Hadas key_level2); 183875973853SYishai Hadas if (list_empty(&xa_val_level2->obj_sub_list)) { 183975973853SYishai Hadas xa_erase(&event->object_ids, 184075973853SYishai Hadas key_level2); 184175973853SYishai Hadas kfree_rcu(xa_val_level2, rcu); 184275973853SYishai Hadas } 184375973853SYishai Hadas } 184475973853SYishai Hadas 184575973853SYishai Hadas static int 184675973853SYishai Hadas subscribe_event_xa_alloc(struct mlx5_devx_event_table *devx_event_table, 184775973853SYishai Hadas u32 key_level1, 184875973853SYishai Hadas bool is_level2, 184975973853SYishai Hadas u32 key_level2) 185075973853SYishai Hadas { 185175973853SYishai Hadas struct devx_obj_event *obj_event; 185275973853SYishai Hadas struct devx_event *event; 185375973853SYishai Hadas int err; 185475973853SYishai Hadas 185575973853SYishai Hadas event = xa_load(&devx_event_table->event_xa, key_level1); 185675973853SYishai Hadas if (!event) { 185775973853SYishai Hadas event = kzalloc(sizeof(*event), GFP_KERNEL); 185875973853SYishai Hadas if (!event) 185975973853SYishai Hadas return -ENOMEM; 186075973853SYishai Hadas 186175973853SYishai Hadas INIT_LIST_HEAD(&event->unaffiliated_list); 186275973853SYishai Hadas xa_init(&event->object_ids); 186375973853SYishai Hadas 186475973853SYishai Hadas err = xa_insert(&devx_event_table->event_xa, 186575973853SYishai Hadas key_level1, 186675973853SYishai Hadas event, 186775973853SYishai Hadas GFP_KERNEL); 186875973853SYishai Hadas if (err) { 186975973853SYishai Hadas kfree(event); 187075973853SYishai Hadas return err; 187175973853SYishai Hadas } 187275973853SYishai Hadas } 187375973853SYishai Hadas 187475973853SYishai Hadas if (!is_level2) 187575973853SYishai Hadas return 0; 187675973853SYishai Hadas 187775973853SYishai Hadas obj_event = xa_load(&event->object_ids, key_level2); 187875973853SYishai Hadas if (!obj_event) { 187975973853SYishai Hadas obj_event = kzalloc(sizeof(*obj_event), GFP_KERNEL); 188075973853SYishai Hadas if (!obj_event) 188175973853SYishai Hadas /* Level1 is valid for future use, no need to free */ 188275973853SYishai Hadas return -ENOMEM; 188375973853SYishai Hadas 188475973853SYishai Hadas err = xa_insert(&event->object_ids, 188575973853SYishai Hadas key_level2, 188675973853SYishai Hadas obj_event, 188775973853SYishai Hadas GFP_KERNEL); 188875973853SYishai Hadas if (err) 188975973853SYishai Hadas return err; 189075973853SYishai Hadas INIT_LIST_HEAD(&obj_event->obj_sub_list); 189175973853SYishai Hadas } 189275973853SYishai Hadas 189375973853SYishai Hadas return 0; 189475973853SYishai Hadas } 189575973853SYishai Hadas 189675973853SYishai Hadas static bool is_valid_events_legacy(int num_events, u16 *event_type_num_list, 189775973853SYishai Hadas struct devx_obj *obj) 189875973853SYishai Hadas { 189975973853SYishai Hadas int i; 190075973853SYishai Hadas 190175973853SYishai Hadas for (i = 0; i < num_events; i++) { 190275973853SYishai Hadas if (obj) { 190375973853SYishai Hadas if (!is_legacy_obj_event_num(event_type_num_list[i])) 190475973853SYishai Hadas return false; 190575973853SYishai Hadas } else if (!is_legacy_unaffiliated_event_num( 190675973853SYishai Hadas event_type_num_list[i])) { 190775973853SYishai Hadas return false; 190875973853SYishai Hadas } 190975973853SYishai Hadas } 191075973853SYishai Hadas 191175973853SYishai Hadas return true; 191275973853SYishai Hadas } 191375973853SYishai Hadas 191475973853SYishai Hadas #define MAX_SUPP_EVENT_NUM 255 191575973853SYishai Hadas static bool is_valid_events(struct mlx5_core_dev *dev, 191675973853SYishai Hadas int num_events, u16 *event_type_num_list, 191775973853SYishai Hadas struct devx_obj *obj) 191875973853SYishai Hadas { 191975973853SYishai Hadas __be64 *aff_events; 192075973853SYishai Hadas __be64 *unaff_events; 192175973853SYishai Hadas int mask_entry; 192275973853SYishai Hadas int mask_bit; 192375973853SYishai Hadas int i; 192475973853SYishai Hadas 192575973853SYishai Hadas if (MLX5_CAP_GEN(dev, event_cap)) { 192675973853SYishai Hadas aff_events = MLX5_CAP_DEV_EVENT(dev, 192775973853SYishai Hadas user_affiliated_events); 192875973853SYishai Hadas unaff_events = MLX5_CAP_DEV_EVENT(dev, 192975973853SYishai Hadas user_unaffiliated_events); 193075973853SYishai Hadas } else { 193175973853SYishai Hadas return is_valid_events_legacy(num_events, event_type_num_list, 193275973853SYishai Hadas obj); 193375973853SYishai Hadas } 193475973853SYishai Hadas 193575973853SYishai Hadas for (i = 0; i < num_events; i++) { 193675973853SYishai Hadas if (event_type_num_list[i] > MAX_SUPP_EVENT_NUM) 193775973853SYishai Hadas return false; 193875973853SYishai Hadas 193975973853SYishai Hadas mask_entry = event_type_num_list[i] / 64; 194075973853SYishai Hadas mask_bit = event_type_num_list[i] % 64; 194175973853SYishai Hadas 194275973853SYishai Hadas if (obj) { 194375973853SYishai Hadas /* CQ completion */ 194475973853SYishai Hadas if (event_type_num_list[i] == 0) 194575973853SYishai Hadas continue; 194675973853SYishai Hadas 194775973853SYishai Hadas if (!(be64_to_cpu(aff_events[mask_entry]) & 194875973853SYishai Hadas (1ull << mask_bit))) 194975973853SYishai Hadas return false; 195075973853SYishai Hadas 195175973853SYishai Hadas continue; 195275973853SYishai Hadas } 195375973853SYishai Hadas 195475973853SYishai Hadas if (!(be64_to_cpu(unaff_events[mask_entry]) & 195575973853SYishai Hadas (1ull << mask_bit))) 195675973853SYishai Hadas return false; 195775973853SYishai Hadas } 195875973853SYishai Hadas 195975973853SYishai Hadas return true; 196075973853SYishai Hadas } 196175973853SYishai Hadas 196275973853SYishai Hadas #define MAX_NUM_EVENTS 16 196375973853SYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT)( 196475973853SYishai Hadas struct uverbs_attr_bundle *attrs) 196575973853SYishai Hadas { 196675973853SYishai Hadas struct ib_uobject *devx_uobj = uverbs_attr_get_uobject( 196775973853SYishai Hadas attrs, 196875973853SYishai Hadas MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_OBJ_HANDLE); 196975973853SYishai Hadas struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context( 197075973853SYishai Hadas &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext); 197175973853SYishai Hadas struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device); 197275973853SYishai Hadas struct ib_uobject *fd_uobj; 197375973853SYishai Hadas struct devx_obj *obj = NULL; 197475973853SYishai Hadas struct devx_async_event_file *ev_file; 197575973853SYishai Hadas struct mlx5_devx_event_table *devx_event_table = &dev->devx_event_table; 197675973853SYishai Hadas u16 *event_type_num_list; 197775973853SYishai Hadas struct devx_event_subscription *event_sub, *tmp_sub; 197875973853SYishai Hadas struct list_head sub_list; 197975973853SYishai Hadas int redirect_fd; 198075973853SYishai Hadas bool use_eventfd = false; 198175973853SYishai Hadas int num_events; 198275973853SYishai Hadas int num_alloc_xa_entries = 0; 198375973853SYishai Hadas u16 obj_type = 0; 198475973853SYishai Hadas u64 cookie = 0; 198575973853SYishai Hadas u32 obj_id = 0; 198675973853SYishai Hadas int err; 198775973853SYishai Hadas int i; 198875973853SYishai Hadas 198975973853SYishai Hadas if (!c->devx_uid) 199075973853SYishai Hadas return -EINVAL; 199175973853SYishai Hadas 199275973853SYishai Hadas if (!IS_ERR(devx_uobj)) { 199375973853SYishai Hadas obj = (struct devx_obj *)devx_uobj->object; 199475973853SYishai Hadas if (obj) 199575973853SYishai Hadas obj_id = get_dec_obj_id(obj->obj_id); 199675973853SYishai Hadas } 199775973853SYishai Hadas 199875973853SYishai Hadas fd_uobj = uverbs_attr_get_uobject(attrs, 199975973853SYishai Hadas MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_HANDLE); 200075973853SYishai Hadas if (IS_ERR(fd_uobj)) 200175973853SYishai Hadas return PTR_ERR(fd_uobj); 200275973853SYishai Hadas 200375973853SYishai Hadas ev_file = container_of(fd_uobj, struct devx_async_event_file, 200475973853SYishai Hadas uobj); 200575973853SYishai Hadas 200675973853SYishai Hadas if (uverbs_attr_is_valid(attrs, 200775973853SYishai Hadas MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_NUM)) { 200875973853SYishai Hadas err = uverbs_copy_from(&redirect_fd, attrs, 200975973853SYishai Hadas MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_NUM); 201075973853SYishai Hadas if (err) 201175973853SYishai Hadas return err; 201275973853SYishai Hadas 201375973853SYishai Hadas use_eventfd = true; 201475973853SYishai Hadas } 201575973853SYishai Hadas 201675973853SYishai Hadas if (uverbs_attr_is_valid(attrs, 201775973853SYishai Hadas MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_COOKIE)) { 201875973853SYishai Hadas if (use_eventfd) 201975973853SYishai Hadas return -EINVAL; 202075973853SYishai Hadas 202175973853SYishai Hadas err = uverbs_copy_from(&cookie, attrs, 202275973853SYishai Hadas MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_COOKIE); 202375973853SYishai Hadas if (err) 202475973853SYishai Hadas return err; 202575973853SYishai Hadas } 202675973853SYishai Hadas 202775973853SYishai Hadas num_events = uverbs_attr_ptr_get_array_size( 202875973853SYishai Hadas attrs, MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_TYPE_NUM_LIST, 202975973853SYishai Hadas sizeof(u16)); 203075973853SYishai Hadas 203175973853SYishai Hadas if (num_events < 0) 203275973853SYishai Hadas return num_events; 203375973853SYishai Hadas 203475973853SYishai Hadas if (num_events > MAX_NUM_EVENTS) 203575973853SYishai Hadas return -EINVAL; 203675973853SYishai Hadas 203775973853SYishai Hadas event_type_num_list = uverbs_attr_get_alloced_ptr(attrs, 203875973853SYishai Hadas MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_TYPE_NUM_LIST); 203975973853SYishai Hadas 204075973853SYishai Hadas if (!is_valid_events(dev->mdev, num_events, event_type_num_list, obj)) 204175973853SYishai Hadas return -EINVAL; 204275973853SYishai Hadas 204375973853SYishai Hadas INIT_LIST_HEAD(&sub_list); 204475973853SYishai Hadas 204575973853SYishai Hadas /* Protect from concurrent subscriptions to same XA entries to allow 204675973853SYishai Hadas * both to succeed 204775973853SYishai Hadas */ 204875973853SYishai Hadas mutex_lock(&devx_event_table->event_xa_lock); 204975973853SYishai Hadas for (i = 0; i < num_events; i++) { 205075973853SYishai Hadas u32 key_level1; 205175973853SYishai Hadas 205275973853SYishai Hadas if (obj) 205375973853SYishai Hadas obj_type = get_dec_obj_type(obj, 205475973853SYishai Hadas event_type_num_list[i]); 205575973853SYishai Hadas key_level1 = event_type_num_list[i] | obj_type << 16; 205675973853SYishai Hadas 205775973853SYishai Hadas err = subscribe_event_xa_alloc(devx_event_table, 205875973853SYishai Hadas key_level1, 205975973853SYishai Hadas obj, 206075973853SYishai Hadas obj_id); 206175973853SYishai Hadas if (err) 206275973853SYishai Hadas goto err; 206375973853SYishai Hadas 206475973853SYishai Hadas num_alloc_xa_entries++; 206575973853SYishai Hadas event_sub = kzalloc(sizeof(*event_sub), GFP_KERNEL); 206675973853SYishai Hadas if (!event_sub) 206775973853SYishai Hadas goto err; 206875973853SYishai Hadas 206975973853SYishai Hadas list_add_tail(&event_sub->event_list, &sub_list); 20706898d1c6SJason Gunthorpe uverbs_uobject_get(&ev_file->uobj); 207175973853SYishai Hadas if (use_eventfd) { 207275973853SYishai Hadas event_sub->eventfd = 207375973853SYishai Hadas eventfd_ctx_fdget(redirect_fd); 207475973853SYishai Hadas 2075e7e6c632SDan Carpenter if (IS_ERR(event_sub->eventfd)) { 207675973853SYishai Hadas err = PTR_ERR(event_sub->eventfd); 207775973853SYishai Hadas event_sub->eventfd = NULL; 207875973853SYishai Hadas goto err; 207975973853SYishai Hadas } 208075973853SYishai Hadas } 208175973853SYishai Hadas 208275973853SYishai Hadas event_sub->cookie = cookie; 208375973853SYishai Hadas event_sub->ev_file = ev_file; 208475973853SYishai Hadas /* May be needed upon cleanup the devx object/subscription */ 208575973853SYishai Hadas event_sub->xa_key_level1 = key_level1; 208675973853SYishai Hadas event_sub->xa_key_level2 = obj_id; 208775973853SYishai Hadas INIT_LIST_HEAD(&event_sub->obj_list); 208875973853SYishai Hadas } 208975973853SYishai Hadas 209075973853SYishai Hadas /* Once all the allocations and the XA data insertions were done we 209175973853SYishai Hadas * can go ahead and add all the subscriptions to the relevant lists 209275973853SYishai Hadas * without concern of a failure. 209375973853SYishai Hadas */ 209475973853SYishai Hadas list_for_each_entry_safe(event_sub, tmp_sub, &sub_list, event_list) { 209575973853SYishai Hadas struct devx_event *event; 209675973853SYishai Hadas struct devx_obj_event *obj_event; 209775973853SYishai Hadas 209875973853SYishai Hadas list_del_init(&event_sub->event_list); 209975973853SYishai Hadas 210075973853SYishai Hadas spin_lock_irq(&ev_file->lock); 210175973853SYishai Hadas list_add_tail_rcu(&event_sub->file_list, 210275973853SYishai Hadas &ev_file->subscribed_events_list); 210375973853SYishai Hadas spin_unlock_irq(&ev_file->lock); 210475973853SYishai Hadas 210575973853SYishai Hadas event = xa_load(&devx_event_table->event_xa, 210675973853SYishai Hadas event_sub->xa_key_level1); 210775973853SYishai Hadas WARN_ON(!event); 210875973853SYishai Hadas 210975973853SYishai Hadas if (!obj) { 211075973853SYishai Hadas list_add_tail_rcu(&event_sub->xa_list, 211175973853SYishai Hadas &event->unaffiliated_list); 211275973853SYishai Hadas continue; 211375973853SYishai Hadas } 211475973853SYishai Hadas 211575973853SYishai Hadas obj_event = xa_load(&event->object_ids, obj_id); 211675973853SYishai Hadas WARN_ON(!obj_event); 211775973853SYishai Hadas list_add_tail_rcu(&event_sub->xa_list, 211875973853SYishai Hadas &obj_event->obj_sub_list); 211975973853SYishai Hadas list_add_tail_rcu(&event_sub->obj_list, 212075973853SYishai Hadas &obj->event_sub); 212175973853SYishai Hadas } 212275973853SYishai Hadas 212375973853SYishai Hadas mutex_unlock(&devx_event_table->event_xa_lock); 212475973853SYishai Hadas return 0; 212575973853SYishai Hadas 212675973853SYishai Hadas err: 212775973853SYishai Hadas list_for_each_entry_safe(event_sub, tmp_sub, &sub_list, event_list) { 212875973853SYishai Hadas list_del(&event_sub->event_list); 212975973853SYishai Hadas 213075973853SYishai Hadas subscribe_event_xa_dealloc(devx_event_table, 213175973853SYishai Hadas event_sub->xa_key_level1, 213275973853SYishai Hadas obj, 213375973853SYishai Hadas obj_id); 213475973853SYishai Hadas 213575973853SYishai Hadas if (event_sub->eventfd) 213675973853SYishai Hadas eventfd_ctx_put(event_sub->eventfd); 21376898d1c6SJason Gunthorpe uverbs_uobject_put(&event_sub->ev_file->uobj); 213875973853SYishai Hadas kfree(event_sub); 213975973853SYishai Hadas } 214075973853SYishai Hadas 214175973853SYishai Hadas mutex_unlock(&devx_event_table->event_xa_lock); 214275973853SYishai Hadas return err; 214375973853SYishai Hadas } 214475973853SYishai Hadas 2145aeae9457SYishai Hadas static int devx_umem_get(struct mlx5_ib_dev *dev, struct ib_ucontext *ucontext, 2146aeae9457SYishai Hadas struct uverbs_attr_bundle *attrs, 2147aeae9457SYishai Hadas struct devx_umem *obj) 2148aeae9457SYishai Hadas { 2149aeae9457SYishai Hadas u64 addr; 2150aeae9457SYishai Hadas size_t size; 2151bccd0622SJason Gunthorpe u32 access; 2152aeae9457SYishai Hadas int err; 2153aeae9457SYishai Hadas 2154aeae9457SYishai Hadas if (uverbs_copy_from(&addr, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR) || 2155bccd0622SJason Gunthorpe uverbs_copy_from(&size, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_LEN)) 2156aeae9457SYishai Hadas return -EFAULT; 2157aeae9457SYishai Hadas 2158bccd0622SJason Gunthorpe err = uverbs_get_flags32(&access, attrs, 2159bccd0622SJason Gunthorpe MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS, 216047f07f03SYishai Hadas IB_ACCESS_LOCAL_WRITE | 216147f07f03SYishai Hadas IB_ACCESS_REMOTE_WRITE | 216247f07f03SYishai Hadas IB_ACCESS_REMOTE_READ); 2163bccd0622SJason Gunthorpe if (err) 2164bccd0622SJason Gunthorpe return err; 2165bccd0622SJason Gunthorpe 2166adac4cb3SJason Gunthorpe err = ib_check_mr_access(&dev->ib_dev, access); 2167aeae9457SYishai Hadas if (err) 2168aeae9457SYishai Hadas return err; 2169aeae9457SYishai Hadas 2170c320e527SMoni Shoua obj->umem = ib_umem_get(&dev->ib_dev, addr, size, access); 2171aeae9457SYishai Hadas if (IS_ERR(obj->umem)) 2172aeae9457SYishai Hadas return PTR_ERR(obj->umem); 2173aeae9457SYishai Hadas return 0; 2174aeae9457SYishai Hadas } 2175aeae9457SYishai Hadas 2176878f7b31SJason Gunthorpe static int devx_umem_reg_cmd_alloc(struct mlx5_ib_dev *dev, 2177878f7b31SJason Gunthorpe struct uverbs_attr_bundle *attrs, 2178b61815e2SJason Gunthorpe struct devx_umem *obj, 2179aeae9457SYishai Hadas struct devx_umem_reg_cmd *cmd) 2180aeae9457SYishai Hadas { 2181878f7b31SJason Gunthorpe unsigned int page_size; 2182aeae9457SYishai Hadas __be64 *mtt; 2183878f7b31SJason Gunthorpe void *umem; 2184878f7b31SJason Gunthorpe 2185878f7b31SJason Gunthorpe /* 2186878f7b31SJason Gunthorpe * We don't know what the user intends to use this umem for, but the HW 2187878f7b31SJason Gunthorpe * restrictions must be met. MR, doorbell records, QP, WQ and CQ all 2188878f7b31SJason Gunthorpe * have different requirements. Since we have no idea how to sort this 2189878f7b31SJason Gunthorpe * out, only support PAGE_SIZE with the expectation that userspace will 2190878f7b31SJason Gunthorpe * provide the necessary alignments inside the known PAGE_SIZE and that 2191878f7b31SJason Gunthorpe * FW will check everything. 2192878f7b31SJason Gunthorpe */ 2193878f7b31SJason Gunthorpe page_size = ib_umem_find_best_pgoff( 2194878f7b31SJason Gunthorpe obj->umem, PAGE_SIZE, 2195878f7b31SJason Gunthorpe __mlx5_page_offset_to_bitmask(__mlx5_bit_sz(umem, page_offset), 2196878f7b31SJason Gunthorpe 0)); 2197878f7b31SJason Gunthorpe if (!page_size) 2198878f7b31SJason Gunthorpe return -EINVAL; 2199878f7b31SJason Gunthorpe 2200878f7b31SJason Gunthorpe cmd->inlen = MLX5_ST_SZ_BYTES(create_umem_in) + 2201878f7b31SJason Gunthorpe (MLX5_ST_SZ_BYTES(mtt) * 2202878f7b31SJason Gunthorpe ib_umem_num_dma_blocks(obj->umem, page_size)); 2203878f7b31SJason Gunthorpe cmd->in = uverbs_zalloc(attrs, cmd->inlen); 2204d0b7721cSJason Gunthorpe if (IS_ERR(cmd->in)) 2205878f7b31SJason Gunthorpe return PTR_ERR(cmd->in); 2206aeae9457SYishai Hadas 2207aeae9457SYishai Hadas umem = MLX5_ADDR_OF(create_umem_in, cmd->in, umem); 2208aeae9457SYishai Hadas mtt = (__be64 *)MLX5_ADDR_OF(umem, umem, mtt); 2209aeae9457SYishai Hadas 22106e3722baSYishai Hadas MLX5_SET(create_umem_in, cmd->in, opcode, MLX5_CMD_OP_CREATE_UMEM); 22117db0eea9SJason Gunthorpe MLX5_SET64(umem, umem, num_of_mtt, 2212878f7b31SJason Gunthorpe ib_umem_num_dma_blocks(obj->umem, page_size)); 2213878f7b31SJason Gunthorpe MLX5_SET(umem, umem, log_page_size, 2214878f7b31SJason Gunthorpe order_base_2(page_size) - MLX5_ADAPTER_PAGE_SHIFT); 2215878f7b31SJason Gunthorpe MLX5_SET(umem, umem, page_offset, 2216878f7b31SJason Gunthorpe ib_umem_dma_offset(obj->umem, page_size)); 2217878f7b31SJason Gunthorpe 2218878f7b31SJason Gunthorpe mlx5_ib_populate_pas(obj->umem, page_size, mtt, 2219aeae9457SYishai Hadas (obj->umem->writable ? MLX5_IB_MTT_WRITE : 0) | 2220aeae9457SYishai Hadas MLX5_IB_MTT_READ); 2221878f7b31SJason Gunthorpe return 0; 2222aeae9457SYishai Hadas } 2223aeae9457SYishai Hadas 2224e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_UMEM_REG)( 222515a1b4beSJason Gunthorpe struct uverbs_attr_bundle *attrs) 2226aeae9457SYishai Hadas { 2227aeae9457SYishai Hadas struct devx_umem_reg_cmd cmd; 2228aeae9457SYishai Hadas struct devx_umem *obj; 2229c36ee46dSJason Gunthorpe struct ib_uobject *uobj = uverbs_attr_get_uobject( 2230c36ee46dSJason Gunthorpe attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE); 2231aeae9457SYishai Hadas u32 obj_id; 223289944450SShamir Rabinovitch struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context( 223389944450SShamir Rabinovitch &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext); 2234c36ee46dSJason Gunthorpe struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device); 2235aeae9457SYishai Hadas int err; 2236aeae9457SYishai Hadas 2237aeae9457SYishai Hadas if (!c->devx_uid) 22387e1335a7SYishai Hadas return -EINVAL; 22397e1335a7SYishai Hadas 2240aeae9457SYishai Hadas obj = kzalloc(sizeof(struct devx_umem), GFP_KERNEL); 2241aeae9457SYishai Hadas if (!obj) 2242aeae9457SYishai Hadas return -ENOMEM; 2243aeae9457SYishai Hadas 2244aeae9457SYishai Hadas err = devx_umem_get(dev, &c->ibucontext, attrs, obj); 2245aeae9457SYishai Hadas if (err) 2246aeae9457SYishai Hadas goto err_obj_free; 2247aeae9457SYishai Hadas 2248878f7b31SJason Gunthorpe err = devx_umem_reg_cmd_alloc(dev, attrs, obj, &cmd); 2249aeae9457SYishai Hadas if (err) 2250aeae9457SYishai Hadas goto err_umem_release; 2251aeae9457SYishai Hadas 22526e3722baSYishai Hadas MLX5_SET(create_umem_in, cmd.in, uid, c->devx_uid); 2253aeae9457SYishai Hadas err = mlx5_cmd_exec(dev->mdev, cmd.in, cmd.inlen, cmd.out, 2254aeae9457SYishai Hadas sizeof(cmd.out)); 2255aeae9457SYishai Hadas if (err) 2256b61815e2SJason Gunthorpe goto err_umem_release; 2257aeae9457SYishai Hadas 2258aeae9457SYishai Hadas obj->mdev = dev->mdev; 2259aeae9457SYishai Hadas uobj->object = obj; 2260aeae9457SYishai Hadas devx_obj_build_destroy_cmd(cmd.in, cmd.out, obj->dinbox, &obj->dinlen, &obj_id); 22610ac8903cSJason Gunthorpe uverbs_finalize_uobj_create(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE); 2262aeae9457SYishai Hadas 22630ac8903cSJason Gunthorpe err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID, &obj_id, 22640ac8903cSJason Gunthorpe sizeof(obj_id)); 22650ac8903cSJason Gunthorpe return err; 2266aeae9457SYishai Hadas 2267aeae9457SYishai Hadas err_umem_release: 2268aeae9457SYishai Hadas ib_umem_release(obj->umem); 2269aeae9457SYishai Hadas err_obj_free: 2270aeae9457SYishai Hadas kfree(obj); 2271aeae9457SYishai Hadas return err; 2272aeae9457SYishai Hadas } 2273aeae9457SYishai Hadas 2274aeae9457SYishai Hadas static int devx_umem_cleanup(struct ib_uobject *uobject, 2275a6a3797dSShamir Rabinovitch enum rdma_remove_reason why, 2276a6a3797dSShamir Rabinovitch struct uverbs_attr_bundle *attrs) 2277aeae9457SYishai Hadas { 2278aeae9457SYishai Hadas struct devx_umem *obj = uobject->object; 2279aeae9457SYishai Hadas u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)]; 2280aeae9457SYishai Hadas int err; 2281aeae9457SYishai Hadas 2282aeae9457SYishai Hadas err = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out)); 2283efa968eeSLeon Romanovsky if (err) 2284aeae9457SYishai Hadas return err; 2285aeae9457SYishai Hadas 2286aeae9457SYishai Hadas ib_umem_release(obj->umem); 2287aeae9457SYishai Hadas kfree(obj); 2288aeae9457SYishai Hadas return 0; 2289aeae9457SYishai Hadas } 2290aeae9457SYishai Hadas 22915ec9d8eeSYishai Hadas static bool is_unaffiliated_event(struct mlx5_core_dev *dev, 22925ec9d8eeSYishai Hadas unsigned long event_type) 22935ec9d8eeSYishai Hadas { 22945ec9d8eeSYishai Hadas __be64 *unaff_events; 22955ec9d8eeSYishai Hadas int mask_entry; 22965ec9d8eeSYishai Hadas int mask_bit; 22975ec9d8eeSYishai Hadas 22985ec9d8eeSYishai Hadas if (!MLX5_CAP_GEN(dev, event_cap)) 22995ec9d8eeSYishai Hadas return is_legacy_unaffiliated_event_num(event_type); 23005ec9d8eeSYishai Hadas 23015ec9d8eeSYishai Hadas unaff_events = MLX5_CAP_DEV_EVENT(dev, 23025ec9d8eeSYishai Hadas user_unaffiliated_events); 23035ec9d8eeSYishai Hadas WARN_ON(event_type > MAX_SUPP_EVENT_NUM); 23045ec9d8eeSYishai Hadas 23055ec9d8eeSYishai Hadas mask_entry = event_type / 64; 23065ec9d8eeSYishai Hadas mask_bit = event_type % 64; 23075ec9d8eeSYishai Hadas 23085ec9d8eeSYishai Hadas if (!(be64_to_cpu(unaff_events[mask_entry]) & (1ull << mask_bit))) 23095ec9d8eeSYishai Hadas return false; 23105ec9d8eeSYishai Hadas 23115ec9d8eeSYishai Hadas return true; 23125ec9d8eeSYishai Hadas } 23135ec9d8eeSYishai Hadas 23145ec9d8eeSYishai Hadas static u32 devx_get_obj_id_from_event(unsigned long event_type, void *data) 23155ec9d8eeSYishai Hadas { 23165ec9d8eeSYishai Hadas struct mlx5_eqe *eqe = data; 23175ec9d8eeSYishai Hadas u32 obj_id = 0; 23185ec9d8eeSYishai Hadas 23195ec9d8eeSYishai Hadas switch (event_type) { 23205ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_SRQ_CATAS_ERROR: 23215ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_SRQ_RQ_LIMIT: 23225ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_PATH_MIG: 23235ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_COMM_EST: 23245ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_SQ_DRAINED: 23255ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_SRQ_LAST_WQE: 23265ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_WQ_CATAS_ERROR: 23275ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_PATH_MIG_FAILED: 23285ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR: 23295ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR: 23305ec9d8eeSYishai Hadas obj_id = be32_to_cpu(eqe->data.qp_srq.qp_srq_n) & 0xffffff; 23315ec9d8eeSYishai Hadas break; 2332972d7560SYishai Hadas case MLX5_EVENT_TYPE_XRQ_ERROR: 2333972d7560SYishai Hadas obj_id = be32_to_cpu(eqe->data.xrq_err.type_xrqn) & 0xffffff; 2334972d7560SYishai Hadas break; 23355ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_DCT_DRAINED: 2336972d7560SYishai Hadas case MLX5_EVENT_TYPE_DCT_KEY_VIOLATION: 23375ec9d8eeSYishai Hadas obj_id = be32_to_cpu(eqe->data.dct.dctn) & 0xffffff; 23385ec9d8eeSYishai Hadas break; 23395ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_CQ_ERROR: 23405ec9d8eeSYishai Hadas obj_id = be32_to_cpu(eqe->data.cq_err.cqn) & 0xffffff; 23415ec9d8eeSYishai Hadas break; 23425ec9d8eeSYishai Hadas default: 23435ec9d8eeSYishai Hadas obj_id = MLX5_GET(affiliated_event_header, &eqe->data, obj_id); 23445ec9d8eeSYishai Hadas break; 23455ec9d8eeSYishai Hadas } 23465ec9d8eeSYishai Hadas 23475ec9d8eeSYishai Hadas return obj_id; 23485ec9d8eeSYishai Hadas } 23495ec9d8eeSYishai Hadas 23505ec9d8eeSYishai Hadas static int deliver_event(struct devx_event_subscription *event_sub, 23515ec9d8eeSYishai Hadas const void *data) 23525ec9d8eeSYishai Hadas { 23535ec9d8eeSYishai Hadas struct devx_async_event_file *ev_file; 23545ec9d8eeSYishai Hadas struct devx_async_event_data *event_data; 23555ec9d8eeSYishai Hadas unsigned long flags; 23565ec9d8eeSYishai Hadas 23575ec9d8eeSYishai Hadas ev_file = event_sub->ev_file; 23585ec9d8eeSYishai Hadas 23595ec9d8eeSYishai Hadas if (ev_file->omit_data) { 23605ec9d8eeSYishai Hadas spin_lock_irqsave(&ev_file->lock, flags); 2361a8af8694SYishai Hadas if (!list_empty(&event_sub->event_list) || 2362a8af8694SYishai Hadas ev_file->is_destroyed) { 23635ec9d8eeSYishai Hadas spin_unlock_irqrestore(&ev_file->lock, flags); 23645ec9d8eeSYishai Hadas return 0; 23655ec9d8eeSYishai Hadas } 23665ec9d8eeSYishai Hadas 23675ec9d8eeSYishai Hadas list_add_tail(&event_sub->event_list, &ev_file->event_list); 23685ec9d8eeSYishai Hadas spin_unlock_irqrestore(&ev_file->lock, flags); 23695ec9d8eeSYishai Hadas wake_up_interruptible(&ev_file->poll_wait); 23705ec9d8eeSYishai Hadas return 0; 23715ec9d8eeSYishai Hadas } 23725ec9d8eeSYishai Hadas 23735ec9d8eeSYishai Hadas event_data = kzalloc(sizeof(*event_data) + sizeof(struct mlx5_eqe), 23745ec9d8eeSYishai Hadas GFP_ATOMIC); 23755ec9d8eeSYishai Hadas if (!event_data) { 23765ec9d8eeSYishai Hadas spin_lock_irqsave(&ev_file->lock, flags); 23775ec9d8eeSYishai Hadas ev_file->is_overflow_err = 1; 23785ec9d8eeSYishai Hadas spin_unlock_irqrestore(&ev_file->lock, flags); 23795ec9d8eeSYishai Hadas return -ENOMEM; 23805ec9d8eeSYishai Hadas } 23815ec9d8eeSYishai Hadas 23825ec9d8eeSYishai Hadas event_data->hdr.cookie = event_sub->cookie; 23835ec9d8eeSYishai Hadas memcpy(event_data->hdr.out_data, data, sizeof(struct mlx5_eqe)); 23845ec9d8eeSYishai Hadas 23855ec9d8eeSYishai Hadas spin_lock_irqsave(&ev_file->lock, flags); 2386f7c8416cSJason Gunthorpe if (!ev_file->is_destroyed) 23875ec9d8eeSYishai Hadas list_add_tail(&event_data->list, &ev_file->event_list); 2388f7c8416cSJason Gunthorpe else 2389f7c8416cSJason Gunthorpe kfree(event_data); 23905ec9d8eeSYishai Hadas spin_unlock_irqrestore(&ev_file->lock, flags); 23915ec9d8eeSYishai Hadas wake_up_interruptible(&ev_file->poll_wait); 23925ec9d8eeSYishai Hadas 23935ec9d8eeSYishai Hadas return 0; 23945ec9d8eeSYishai Hadas } 23955ec9d8eeSYishai Hadas 23965ec9d8eeSYishai Hadas static void dispatch_event_fd(struct list_head *fd_list, 23975ec9d8eeSYishai Hadas const void *data) 23985ec9d8eeSYishai Hadas { 23995ec9d8eeSYishai Hadas struct devx_event_subscription *item; 24005ec9d8eeSYishai Hadas 24015ec9d8eeSYishai Hadas list_for_each_entry_rcu(item, fd_list, xa_list) { 24026898d1c6SJason Gunthorpe if (item->eventfd) 24035ec9d8eeSYishai Hadas eventfd_signal(item->eventfd, 1); 24046898d1c6SJason Gunthorpe else 24055ec9d8eeSYishai Hadas deliver_event(item, data); 24065ec9d8eeSYishai Hadas } 24075ec9d8eeSYishai Hadas } 24085ec9d8eeSYishai Hadas 2409e337dd53SYishai Hadas static int devx_event_notifier(struct notifier_block *nb, 2410e337dd53SYishai Hadas unsigned long event_type, void *data) 2411e337dd53SYishai Hadas { 24125ec9d8eeSYishai Hadas struct mlx5_devx_event_table *table; 24135ec9d8eeSYishai Hadas struct mlx5_ib_dev *dev; 24145ec9d8eeSYishai Hadas struct devx_event *event; 24155ec9d8eeSYishai Hadas struct devx_obj_event *obj_event; 24165ec9d8eeSYishai Hadas u16 obj_type = 0; 24175ec9d8eeSYishai Hadas bool is_unaffiliated; 24185ec9d8eeSYishai Hadas u32 obj_id; 24195ec9d8eeSYishai Hadas 24205ec9d8eeSYishai Hadas /* Explicit filtering to kernel events which may occur frequently */ 24215ec9d8eeSYishai Hadas if (event_type == MLX5_EVENT_TYPE_CMD || 24225ec9d8eeSYishai Hadas event_type == MLX5_EVENT_TYPE_PAGE_REQUEST) 24235ec9d8eeSYishai Hadas return NOTIFY_OK; 24245ec9d8eeSYishai Hadas 24255ec9d8eeSYishai Hadas table = container_of(nb, struct mlx5_devx_event_table, devx_nb.nb); 24265ec9d8eeSYishai Hadas dev = container_of(table, struct mlx5_ib_dev, devx_event_table); 24275ec9d8eeSYishai Hadas is_unaffiliated = is_unaffiliated_event(dev->mdev, event_type); 24285ec9d8eeSYishai Hadas 24295ec9d8eeSYishai Hadas if (!is_unaffiliated) 24305ec9d8eeSYishai Hadas obj_type = get_event_obj_type(event_type, data); 24315ec9d8eeSYishai Hadas 24325ec9d8eeSYishai Hadas rcu_read_lock(); 24335ec9d8eeSYishai Hadas event = xa_load(&table->event_xa, event_type | (obj_type << 16)); 24345ec9d8eeSYishai Hadas if (!event) { 24355ec9d8eeSYishai Hadas rcu_read_unlock(); 2436e337dd53SYishai Hadas return NOTIFY_DONE; 2437e337dd53SYishai Hadas } 2438e337dd53SYishai Hadas 24395ec9d8eeSYishai Hadas if (is_unaffiliated) { 24405ec9d8eeSYishai Hadas dispatch_event_fd(&event->unaffiliated_list, data); 24415ec9d8eeSYishai Hadas rcu_read_unlock(); 24425ec9d8eeSYishai Hadas return NOTIFY_OK; 24435ec9d8eeSYishai Hadas } 24445ec9d8eeSYishai Hadas 24455ec9d8eeSYishai Hadas obj_id = devx_get_obj_id_from_event(event_type, data); 24465ec9d8eeSYishai Hadas obj_event = xa_load(&event->object_ids, obj_id); 24475ec9d8eeSYishai Hadas if (!obj_event) { 24485ec9d8eeSYishai Hadas rcu_read_unlock(); 24495ec9d8eeSYishai Hadas return NOTIFY_DONE; 24505ec9d8eeSYishai Hadas } 24515ec9d8eeSYishai Hadas 24525ec9d8eeSYishai Hadas dispatch_event_fd(&obj_event->obj_sub_list, data); 24535ec9d8eeSYishai Hadas 24545ec9d8eeSYishai Hadas rcu_read_unlock(); 24555ec9d8eeSYishai Hadas return NOTIFY_OK; 24565ec9d8eeSYishai Hadas } 24575ec9d8eeSYishai Hadas 2458d8b7515eSLeon Romanovsky int mlx5_ib_devx_init(struct mlx5_ib_dev *dev) 2459e337dd53SYishai Hadas { 2460e337dd53SYishai Hadas struct mlx5_devx_event_table *table = &dev->devx_event_table; 2461d8b7515eSLeon Romanovsky int uid; 2462e337dd53SYishai Hadas 2463d8b7515eSLeon Romanovsky uid = mlx5_ib_devx_create(dev, false); 2464d8b7515eSLeon Romanovsky if (uid > 0) { 2465d8b7515eSLeon Romanovsky dev->devx_whitelist_uid = uid; 2466e337dd53SYishai Hadas xa_init(&table->event_xa); 2467e337dd53SYishai Hadas mutex_init(&table->event_xa_lock); 2468e337dd53SYishai Hadas MLX5_NB_INIT(&table->devx_nb, devx_event_notifier, NOTIFY_ANY); 2469e337dd53SYishai Hadas mlx5_eq_notifier_register(dev->mdev, &table->devx_nb); 2470e337dd53SYishai Hadas } 2471e337dd53SYishai Hadas 2472d8b7515eSLeon Romanovsky return 0; 2473d8b7515eSLeon Romanovsky } 2474d8b7515eSLeon Romanovsky 2475d8b7515eSLeon Romanovsky void mlx5_ib_devx_cleanup(struct mlx5_ib_dev *dev) 2476e337dd53SYishai Hadas { 2477e337dd53SYishai Hadas struct mlx5_devx_event_table *table = &dev->devx_event_table; 247875973853SYishai Hadas struct devx_event_subscription *sub, *tmp; 247975973853SYishai Hadas struct devx_event *event; 2480e337dd53SYishai Hadas void *entry; 2481e337dd53SYishai Hadas unsigned long id; 2482e337dd53SYishai Hadas 2483d8b7515eSLeon Romanovsky if (dev->devx_whitelist_uid) { 2484e337dd53SYishai Hadas mlx5_eq_notifier_unregister(dev->mdev, &table->devx_nb); 248575973853SYishai Hadas mutex_lock(&dev->devx_event_table.event_xa_lock); 248675973853SYishai Hadas xa_for_each(&table->event_xa, id, entry) { 248775973853SYishai Hadas event = entry; 2488d8b7515eSLeon Romanovsky list_for_each_entry_safe( 2489d8b7515eSLeon Romanovsky sub, tmp, &event->unaffiliated_list, xa_list) 249075973853SYishai Hadas devx_cleanup_subscription(dev, sub); 2491e337dd53SYishai Hadas kfree(entry); 249275973853SYishai Hadas } 249375973853SYishai Hadas mutex_unlock(&dev->devx_event_table.event_xa_lock); 2494e337dd53SYishai Hadas xa_destroy(&table->event_xa); 2495d8b7515eSLeon Romanovsky 2496d8b7515eSLeon Romanovsky mlx5_ib_devx_destroy(dev, dev->devx_whitelist_uid); 2497d8b7515eSLeon Romanovsky } 2498e337dd53SYishai Hadas } 2499e337dd53SYishai Hadas 25006bf8f22aSYishai Hadas static ssize_t devx_async_cmd_event_read(struct file *filp, char __user *buf, 25016bf8f22aSYishai Hadas size_t count, loff_t *pos) 25026bf8f22aSYishai Hadas { 25034accbb3fSYishai Hadas struct devx_async_cmd_event_file *comp_ev_file = filp->private_data; 25044accbb3fSYishai Hadas struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue; 25054accbb3fSYishai Hadas struct devx_async_data *event; 25064accbb3fSYishai Hadas int ret = 0; 25074accbb3fSYishai Hadas size_t eventsz; 25084accbb3fSYishai Hadas 25094accbb3fSYishai Hadas spin_lock_irq(&ev_queue->lock); 25104accbb3fSYishai Hadas 25114accbb3fSYishai Hadas while (list_empty(&ev_queue->event_list)) { 25124accbb3fSYishai Hadas spin_unlock_irq(&ev_queue->lock); 25134accbb3fSYishai Hadas 25144accbb3fSYishai Hadas if (filp->f_flags & O_NONBLOCK) 25154accbb3fSYishai Hadas return -EAGAIN; 25164accbb3fSYishai Hadas 25174accbb3fSYishai Hadas if (wait_event_interruptible( 25184accbb3fSYishai Hadas ev_queue->poll_wait, 2519eaebaf77SYishai Hadas (!list_empty(&ev_queue->event_list) || 2520eaebaf77SYishai Hadas ev_queue->is_destroyed))) { 25214accbb3fSYishai Hadas return -ERESTARTSYS; 25224accbb3fSYishai Hadas } 2523eaebaf77SYishai Hadas 25244accbb3fSYishai Hadas spin_lock_irq(&ev_queue->lock); 2525a8af8694SYishai Hadas if (ev_queue->is_destroyed) { 2526a8af8694SYishai Hadas spin_unlock_irq(&ev_queue->lock); 2527a8af8694SYishai Hadas return -EIO; 2528a8af8694SYishai Hadas } 25294accbb3fSYishai Hadas } 25304accbb3fSYishai Hadas 25314accbb3fSYishai Hadas event = list_entry(ev_queue->event_list.next, 25324accbb3fSYishai Hadas struct devx_async_data, list); 25334accbb3fSYishai Hadas eventsz = event->cmd_out_len + 25344accbb3fSYishai Hadas sizeof(struct mlx5_ib_uapi_devx_async_cmd_hdr); 25354accbb3fSYishai Hadas 25364accbb3fSYishai Hadas if (eventsz > count) { 25374accbb3fSYishai Hadas spin_unlock_irq(&ev_queue->lock); 25384accbb3fSYishai Hadas return -ENOSPC; 25394accbb3fSYishai Hadas } 25404accbb3fSYishai Hadas 25414accbb3fSYishai Hadas list_del(ev_queue->event_list.next); 25424accbb3fSYishai Hadas spin_unlock_irq(&ev_queue->lock); 25434accbb3fSYishai Hadas 25444accbb3fSYishai Hadas if (copy_to_user(buf, &event->hdr, eventsz)) 25454accbb3fSYishai Hadas ret = -EFAULT; 25464accbb3fSYishai Hadas else 25474accbb3fSYishai Hadas ret = eventsz; 25484accbb3fSYishai Hadas 25494accbb3fSYishai Hadas atomic_sub(event->cmd_out_len, &ev_queue->bytes_in_use); 25504accbb3fSYishai Hadas kvfree(event); 25514accbb3fSYishai Hadas return ret; 25526bf8f22aSYishai Hadas } 25536bf8f22aSYishai Hadas 25546bf8f22aSYishai Hadas static __poll_t devx_async_cmd_event_poll(struct file *filp, 25556bf8f22aSYishai Hadas struct poll_table_struct *wait) 25566bf8f22aSYishai Hadas { 25574accbb3fSYishai Hadas struct devx_async_cmd_event_file *comp_ev_file = filp->private_data; 25584accbb3fSYishai Hadas struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue; 25594accbb3fSYishai Hadas __poll_t pollflags = 0; 25604accbb3fSYishai Hadas 25614accbb3fSYishai Hadas poll_wait(filp, &ev_queue->poll_wait, wait); 25624accbb3fSYishai Hadas 25634accbb3fSYishai Hadas spin_lock_irq(&ev_queue->lock); 2564eaebaf77SYishai Hadas if (ev_queue->is_destroyed) 2565eaebaf77SYishai Hadas pollflags = EPOLLIN | EPOLLRDNORM | EPOLLRDHUP; 2566eaebaf77SYishai Hadas else if (!list_empty(&ev_queue->event_list)) 25674accbb3fSYishai Hadas pollflags = EPOLLIN | EPOLLRDNORM; 25684accbb3fSYishai Hadas spin_unlock_irq(&ev_queue->lock); 25694accbb3fSYishai Hadas 25704accbb3fSYishai Hadas return pollflags; 25716bf8f22aSYishai Hadas } 25726bf8f22aSYishai Hadas 25731f687edeSBart Van Assche static const struct file_operations devx_async_cmd_event_fops = { 25746bf8f22aSYishai Hadas .owner = THIS_MODULE, 25756bf8f22aSYishai Hadas .read = devx_async_cmd_event_read, 25766bf8f22aSYishai Hadas .poll = devx_async_cmd_event_poll, 2577f7c8416cSJason Gunthorpe .release = uverbs_uobject_fd_release, 25786bf8f22aSYishai Hadas .llseek = no_llseek, 25796bf8f22aSYishai Hadas }; 25806bf8f22aSYishai Hadas 25812afc5e1bSYishai Hadas static ssize_t devx_async_event_read(struct file *filp, char __user *buf, 25822afc5e1bSYishai Hadas size_t count, loff_t *pos) 25832afc5e1bSYishai Hadas { 25845ec9d8eeSYishai Hadas struct devx_async_event_file *ev_file = filp->private_data; 25855ec9d8eeSYishai Hadas struct devx_event_subscription *event_sub; 25863f649ab7SKees Cook struct devx_async_event_data *event; 25875ec9d8eeSYishai Hadas int ret = 0; 25885ec9d8eeSYishai Hadas size_t eventsz; 25895ec9d8eeSYishai Hadas bool omit_data; 25905ec9d8eeSYishai Hadas void *event_data; 25915ec9d8eeSYishai Hadas 25925ec9d8eeSYishai Hadas omit_data = ev_file->omit_data; 25935ec9d8eeSYishai Hadas 25945ec9d8eeSYishai Hadas spin_lock_irq(&ev_file->lock); 25955ec9d8eeSYishai Hadas 25965ec9d8eeSYishai Hadas if (ev_file->is_overflow_err) { 25975ec9d8eeSYishai Hadas ev_file->is_overflow_err = 0; 25985ec9d8eeSYishai Hadas spin_unlock_irq(&ev_file->lock); 25995ec9d8eeSYishai Hadas return -EOVERFLOW; 26005ec9d8eeSYishai Hadas } 26015ec9d8eeSYishai Hadas 26025ec9d8eeSYishai Hadas 26035ec9d8eeSYishai Hadas while (list_empty(&ev_file->event_list)) { 26045ec9d8eeSYishai Hadas spin_unlock_irq(&ev_file->lock); 26055ec9d8eeSYishai Hadas 26065ec9d8eeSYishai Hadas if (filp->f_flags & O_NONBLOCK) 26075ec9d8eeSYishai Hadas return -EAGAIN; 26085ec9d8eeSYishai Hadas 26095ec9d8eeSYishai Hadas if (wait_event_interruptible(ev_file->poll_wait, 26105ec9d8eeSYishai Hadas (!list_empty(&ev_file->event_list) || 26115ec9d8eeSYishai Hadas ev_file->is_destroyed))) { 26125ec9d8eeSYishai Hadas return -ERESTARTSYS; 26135ec9d8eeSYishai Hadas } 26145ec9d8eeSYishai Hadas 26155ec9d8eeSYishai Hadas spin_lock_irq(&ev_file->lock); 26165ec9d8eeSYishai Hadas if (ev_file->is_destroyed) { 26175ec9d8eeSYishai Hadas spin_unlock_irq(&ev_file->lock); 26185ec9d8eeSYishai Hadas return -EIO; 26195ec9d8eeSYishai Hadas } 26205ec9d8eeSYishai Hadas } 26215ec9d8eeSYishai Hadas 26225ec9d8eeSYishai Hadas if (omit_data) { 26235ec9d8eeSYishai Hadas event_sub = list_first_entry(&ev_file->event_list, 26245ec9d8eeSYishai Hadas struct devx_event_subscription, 26255ec9d8eeSYishai Hadas event_list); 26265ec9d8eeSYishai Hadas eventsz = sizeof(event_sub->cookie); 26275ec9d8eeSYishai Hadas event_data = &event_sub->cookie; 26285ec9d8eeSYishai Hadas } else { 26295ec9d8eeSYishai Hadas event = list_first_entry(&ev_file->event_list, 26305ec9d8eeSYishai Hadas struct devx_async_event_data, list); 26315ec9d8eeSYishai Hadas eventsz = sizeof(struct mlx5_eqe) + 26325ec9d8eeSYishai Hadas sizeof(struct mlx5_ib_uapi_devx_async_event_hdr); 26335ec9d8eeSYishai Hadas event_data = &event->hdr; 26345ec9d8eeSYishai Hadas } 26355ec9d8eeSYishai Hadas 26365ec9d8eeSYishai Hadas if (eventsz > count) { 26375ec9d8eeSYishai Hadas spin_unlock_irq(&ev_file->lock); 26382afc5e1bSYishai Hadas return -EINVAL; 26392afc5e1bSYishai Hadas } 26402afc5e1bSYishai Hadas 26415ec9d8eeSYishai Hadas if (omit_data) 26425ec9d8eeSYishai Hadas list_del_init(&event_sub->event_list); 26435ec9d8eeSYishai Hadas else 26445ec9d8eeSYishai Hadas list_del(&event->list); 26455ec9d8eeSYishai Hadas 26465ec9d8eeSYishai Hadas spin_unlock_irq(&ev_file->lock); 26475ec9d8eeSYishai Hadas 26485ec9d8eeSYishai Hadas if (copy_to_user(buf, event_data, eventsz)) 26495ec9d8eeSYishai Hadas /* This points to an application issue, not a kernel concern */ 26505ec9d8eeSYishai Hadas ret = -EFAULT; 26515ec9d8eeSYishai Hadas else 26525ec9d8eeSYishai Hadas ret = eventsz; 26535ec9d8eeSYishai Hadas 26545ec9d8eeSYishai Hadas if (!omit_data) 26555ec9d8eeSYishai Hadas kfree(event); 26565ec9d8eeSYishai Hadas return ret; 26575ec9d8eeSYishai Hadas } 26585ec9d8eeSYishai Hadas 26592afc5e1bSYishai Hadas static __poll_t devx_async_event_poll(struct file *filp, 26602afc5e1bSYishai Hadas struct poll_table_struct *wait) 26612afc5e1bSYishai Hadas { 26625ec9d8eeSYishai Hadas struct devx_async_event_file *ev_file = filp->private_data; 26635ec9d8eeSYishai Hadas __poll_t pollflags = 0; 26645ec9d8eeSYishai Hadas 26655ec9d8eeSYishai Hadas poll_wait(filp, &ev_file->poll_wait, wait); 26665ec9d8eeSYishai Hadas 26675ec9d8eeSYishai Hadas spin_lock_irq(&ev_file->lock); 26685ec9d8eeSYishai Hadas if (ev_file->is_destroyed) 26695ec9d8eeSYishai Hadas pollflags = EPOLLIN | EPOLLRDNORM | EPOLLRDHUP; 26705ec9d8eeSYishai Hadas else if (!list_empty(&ev_file->event_list)) 26715ec9d8eeSYishai Hadas pollflags = EPOLLIN | EPOLLRDNORM; 26725ec9d8eeSYishai Hadas spin_unlock_irq(&ev_file->lock); 26735ec9d8eeSYishai Hadas 26745ec9d8eeSYishai Hadas return pollflags; 26752afc5e1bSYishai Hadas } 26762afc5e1bSYishai Hadas 26776898d1c6SJason Gunthorpe static void devx_free_subscription(struct rcu_head *rcu) 26786898d1c6SJason Gunthorpe { 26796898d1c6SJason Gunthorpe struct devx_event_subscription *event_sub = 26806898d1c6SJason Gunthorpe container_of(rcu, struct devx_event_subscription, rcu); 26816898d1c6SJason Gunthorpe 26826898d1c6SJason Gunthorpe if (event_sub->eventfd) 26836898d1c6SJason Gunthorpe eventfd_ctx_put(event_sub->eventfd); 26846898d1c6SJason Gunthorpe uverbs_uobject_put(&event_sub->ev_file->uobj); 26856898d1c6SJason Gunthorpe kfree(event_sub); 26866898d1c6SJason Gunthorpe } 26876898d1c6SJason Gunthorpe 2688f7c8416cSJason Gunthorpe static const struct file_operations devx_async_event_fops = { 2689f7c8416cSJason Gunthorpe .owner = THIS_MODULE, 2690f7c8416cSJason Gunthorpe .read = devx_async_event_read, 2691f7c8416cSJason Gunthorpe .poll = devx_async_event_poll, 2692f7c8416cSJason Gunthorpe .release = uverbs_uobject_fd_release, 2693f7c8416cSJason Gunthorpe .llseek = no_llseek, 2694f7c8416cSJason Gunthorpe }; 2695f7c8416cSJason Gunthorpe 2696c5633a72SLeon Romanovsky static void devx_async_cmd_event_destroy_uobj(struct ib_uobject *uobj, 2697f7c8416cSJason Gunthorpe enum rdma_remove_reason why) 26982afc5e1bSYishai Hadas { 2699f7c8416cSJason Gunthorpe struct devx_async_cmd_event_file *comp_ev_file = 2700f7c8416cSJason Gunthorpe container_of(uobj, struct devx_async_cmd_event_file, 2701f7c8416cSJason Gunthorpe uobj); 2702f7c8416cSJason Gunthorpe struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue; 2703f7c8416cSJason Gunthorpe struct devx_async_data *entry, *tmp; 2704f7c8416cSJason Gunthorpe 2705f7c8416cSJason Gunthorpe spin_lock_irq(&ev_queue->lock); 2706f7c8416cSJason Gunthorpe ev_queue->is_destroyed = 1; 2707f7c8416cSJason Gunthorpe spin_unlock_irq(&ev_queue->lock); 2708f7c8416cSJason Gunthorpe wake_up_interruptible(&ev_queue->poll_wait); 2709f7c8416cSJason Gunthorpe 2710f7c8416cSJason Gunthorpe mlx5_cmd_cleanup_async_ctx(&comp_ev_file->async_ctx); 2711f7c8416cSJason Gunthorpe 2712f7c8416cSJason Gunthorpe spin_lock_irq(&comp_ev_file->ev_queue.lock); 2713f7c8416cSJason Gunthorpe list_for_each_entry_safe(entry, tmp, 2714a8af8694SYishai Hadas &comp_ev_file->ev_queue.event_list, list) { 2715a8af8694SYishai Hadas list_del(&entry->list); 2716f7c8416cSJason Gunthorpe kvfree(entry); 2717a8af8694SYishai Hadas } 2718f7c8416cSJason Gunthorpe spin_unlock_irq(&comp_ev_file->ev_queue.lock); 2719f7c8416cSJason Gunthorpe }; 2720f7c8416cSJason Gunthorpe 2721c5633a72SLeon Romanovsky static void devx_async_event_destroy_uobj(struct ib_uobject *uobj, 2722f7c8416cSJason Gunthorpe enum rdma_remove_reason why) 2723f7c8416cSJason Gunthorpe { 2724f7c8416cSJason Gunthorpe struct devx_async_event_file *ev_file = 2725f7c8416cSJason Gunthorpe container_of(uobj, struct devx_async_event_file, 2726f7c8416cSJason Gunthorpe uobj); 272775973853SYishai Hadas struct devx_event_subscription *event_sub, *event_sub_tmp; 2728e9eec6a5SYishai Hadas struct mlx5_ib_dev *dev = ev_file->dev; 272975973853SYishai Hadas 2730f7c8416cSJason Gunthorpe spin_lock_irq(&ev_file->lock); 2731f7c8416cSJason Gunthorpe ev_file->is_destroyed = 1; 2732a8af8694SYishai Hadas 2733a8af8694SYishai Hadas /* free the pending events allocation */ 2734a8af8694SYishai Hadas if (ev_file->omit_data) { 2735a8af8694SYishai Hadas struct devx_event_subscription *event_sub, *tmp; 2736a8af8694SYishai Hadas 2737a8af8694SYishai Hadas list_for_each_entry_safe(event_sub, tmp, &ev_file->event_list, 2738a8af8694SYishai Hadas event_list) 2739a8af8694SYishai Hadas list_del_init(&event_sub->event_list); 2740a8af8694SYishai Hadas 2741a8af8694SYishai Hadas } else { 2742a8af8694SYishai Hadas struct devx_async_event_data *entry, *tmp; 2743a8af8694SYishai Hadas 2744a8af8694SYishai Hadas list_for_each_entry_safe(entry, tmp, &ev_file->event_list, 2745a8af8694SYishai Hadas list) { 2746a8af8694SYishai Hadas list_del(&entry->list); 2747a8af8694SYishai Hadas kfree(entry); 2748a8af8694SYishai Hadas } 2749a8af8694SYishai Hadas } 2750a8af8694SYishai Hadas 2751f7c8416cSJason Gunthorpe spin_unlock_irq(&ev_file->lock); 2752f7c8416cSJason Gunthorpe wake_up_interruptible(&ev_file->poll_wait); 2753f7c8416cSJason Gunthorpe 2754e9eec6a5SYishai Hadas mutex_lock(&dev->devx_event_table.event_xa_lock); 275575973853SYishai Hadas /* delete the subscriptions which are related to this FD */ 275675973853SYishai Hadas list_for_each_entry_safe(event_sub, event_sub_tmp, 275775973853SYishai Hadas &ev_file->subscribed_events_list, file_list) { 2758e9eec6a5SYishai Hadas devx_cleanup_subscription(dev, event_sub); 275975973853SYishai Hadas list_del_rcu(&event_sub->file_list); 276075973853SYishai Hadas /* subscription may not be used by the read API any more */ 27616898d1c6SJason Gunthorpe call_rcu(&event_sub->rcu, devx_free_subscription); 276275973853SYishai Hadas } 2763e9eec6a5SYishai Hadas mutex_unlock(&dev->devx_event_table.event_xa_lock); 276475973853SYishai Hadas 2765e9eec6a5SYishai Hadas put_device(&dev->ib_dev.dev); 27662afc5e1bSYishai Hadas }; 27672afc5e1bSYishai Hadas 27689a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD( 27699a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_UMEM_REG, 27709a119cd5SJason Gunthorpe UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE, 2771aeae9457SYishai Hadas MLX5_IB_OBJECT_DEVX_UMEM, 2772aeae9457SYishai Hadas UVERBS_ACCESS_NEW, 277383bb4442SJason Gunthorpe UA_MANDATORY), 27749a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR, 27759a119cd5SJason Gunthorpe UVERBS_ATTR_TYPE(u64), 277683bb4442SJason Gunthorpe UA_MANDATORY), 27779a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_LEN, 27789a119cd5SJason Gunthorpe UVERBS_ATTR_TYPE(u64), 277983bb4442SJason Gunthorpe UA_MANDATORY), 2780bccd0622SJason Gunthorpe UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS, 2781bccd0622SJason Gunthorpe enum ib_access_flags), 27829a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID, 27839a119cd5SJason Gunthorpe UVERBS_ATTR_TYPE(u32), 278483bb4442SJason Gunthorpe UA_MANDATORY)); 2785aeae9457SYishai Hadas 2786528922afSYishai Hadas DECLARE_UVERBS_NAMED_METHOD_DESTROY( 27879a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_UMEM_DEREG, 27889a119cd5SJason Gunthorpe UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_DEREG_HANDLE, 2789aeae9457SYishai Hadas MLX5_IB_OBJECT_DEVX_UMEM, 2790aeae9457SYishai Hadas UVERBS_ACCESS_DESTROY, 279183bb4442SJason Gunthorpe UA_MANDATORY)); 2792aeae9457SYishai Hadas 27939a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD( 27949a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_QUERY_EQN, 27959a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC, 27969a119cd5SJason Gunthorpe UVERBS_ATTR_TYPE(u32), 279783bb4442SJason Gunthorpe UA_MANDATORY), 27989a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN, 27999a119cd5SJason Gunthorpe UVERBS_ATTR_TYPE(u32), 280083bb4442SJason Gunthorpe UA_MANDATORY)); 2801f6fe01b7SYishai Hadas 28029a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD( 28039a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_QUERY_UAR, 28049a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX, 28059a119cd5SJason Gunthorpe UVERBS_ATTR_TYPE(u32), 280683bb4442SJason Gunthorpe UA_MANDATORY), 28079a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX, 28089a119cd5SJason Gunthorpe UVERBS_ATTR_TYPE(u32), 280983bb4442SJason Gunthorpe UA_MANDATORY)); 28107c043e90SYishai Hadas 28119a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD( 28129a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_OTHER, 28139a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN( 28149a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OTHER_CMD_IN, 28158aa8c95cSYishai Hadas UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)), 281683bb4442SJason Gunthorpe UA_MANDATORY, 281783bb4442SJason Gunthorpe UA_ALLOC_AND_COPY), 28189a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_OUT( 28199a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT, 28207efce369SYishai Hadas UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)), 2821540cd692SJason Gunthorpe UA_MANDATORY)); 28227efce369SYishai Hadas 28239a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD( 28249a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_OBJ_CREATE, 28259a119cd5SJason Gunthorpe UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE, 28269a119cd5SJason Gunthorpe MLX5_IB_OBJECT_DEVX_OBJ, 28279a119cd5SJason Gunthorpe UVERBS_ACCESS_NEW, 282883bb4442SJason Gunthorpe UA_MANDATORY), 28299a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN( 28309a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN, 28319a119cd5SJason Gunthorpe UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)), 283283bb4442SJason Gunthorpe UA_MANDATORY, 283383bb4442SJason Gunthorpe UA_ALLOC_AND_COPY), 28349a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_OUT( 28359a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT, 28369a119cd5SJason Gunthorpe UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)), 2837540cd692SJason Gunthorpe UA_MANDATORY)); 28389a119cd5SJason Gunthorpe 2839528922afSYishai Hadas DECLARE_UVERBS_NAMED_METHOD_DESTROY( 28409a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_OBJ_DESTROY, 28419a119cd5SJason Gunthorpe UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_DESTROY_HANDLE, 28427efce369SYishai Hadas MLX5_IB_OBJECT_DEVX_OBJ, 28437efce369SYishai Hadas UVERBS_ACCESS_DESTROY, 284483bb4442SJason Gunthorpe UA_MANDATORY)); 28457efce369SYishai Hadas 28469a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD( 28479a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_OBJ_MODIFY, 28489a119cd5SJason Gunthorpe UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE, 284934613eb1SYishai Hadas UVERBS_IDR_ANY_OBJECT, 2850e662e14dSYishai Hadas UVERBS_ACCESS_WRITE, 285183bb4442SJason Gunthorpe UA_MANDATORY), 28529a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN( 28539a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN, 2854e662e14dSYishai Hadas UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)), 285583bb4442SJason Gunthorpe UA_MANDATORY, 285683bb4442SJason Gunthorpe UA_ALLOC_AND_COPY), 28579a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_OUT( 28589a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT, 2859e662e14dSYishai Hadas UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)), 2860540cd692SJason Gunthorpe UA_MANDATORY)); 2861e662e14dSYishai Hadas 28629a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD( 28639a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_OBJ_QUERY, 28649a119cd5SJason Gunthorpe UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE, 286534613eb1SYishai Hadas UVERBS_IDR_ANY_OBJECT, 2866e662e14dSYishai Hadas UVERBS_ACCESS_READ, 286783bb4442SJason Gunthorpe UA_MANDATORY), 28689a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN( 28699a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN, 2870e662e14dSYishai Hadas UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)), 287183bb4442SJason Gunthorpe UA_MANDATORY, 287283bb4442SJason Gunthorpe UA_ALLOC_AND_COPY), 28739a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_OUT( 28749a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT, 2875e662e14dSYishai Hadas UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)), 2876540cd692SJason Gunthorpe UA_MANDATORY)); 2877e662e14dSYishai Hadas 2878a124edbaSYishai Hadas DECLARE_UVERBS_NAMED_METHOD( 2879a124edbaSYishai Hadas MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY, 2880a124edbaSYishai Hadas UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE, 2881a124edbaSYishai Hadas UVERBS_IDR_ANY_OBJECT, 2882a124edbaSYishai Hadas UVERBS_ACCESS_READ, 2883a124edbaSYishai Hadas UA_MANDATORY), 2884a124edbaSYishai Hadas UVERBS_ATTR_PTR_IN( 2885a124edbaSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN, 2886a124edbaSYishai Hadas UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)), 2887a124edbaSYishai Hadas UA_MANDATORY, 2888a124edbaSYishai Hadas UA_ALLOC_AND_COPY), 2889a124edbaSYishai Hadas UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_OUT_LEN, 2890a124edbaSYishai Hadas u16, UA_MANDATORY), 2891a124edbaSYishai Hadas UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_FD, 2892a124edbaSYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD, 2893a124edbaSYishai Hadas UVERBS_ACCESS_READ, 2894a124edbaSYishai Hadas UA_MANDATORY), 2895a124edbaSYishai Hadas UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_WR_ID, 2896a124edbaSYishai Hadas UVERBS_ATTR_TYPE(u64), 2897a124edbaSYishai Hadas UA_MANDATORY)); 2898a124edbaSYishai Hadas 289975973853SYishai Hadas DECLARE_UVERBS_NAMED_METHOD( 290075973853SYishai Hadas MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT, 290175973853SYishai Hadas UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_HANDLE, 290275973853SYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD, 290375973853SYishai Hadas UVERBS_ACCESS_READ, 290475973853SYishai Hadas UA_MANDATORY), 290575973853SYishai Hadas UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_OBJ_HANDLE, 290675973853SYishai Hadas MLX5_IB_OBJECT_DEVX_OBJ, 290775973853SYishai Hadas UVERBS_ACCESS_READ, 290875973853SYishai Hadas UA_OPTIONAL), 290975973853SYishai Hadas UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_TYPE_NUM_LIST, 291075973853SYishai Hadas UVERBS_ATTR_MIN_SIZE(sizeof(u16)), 291175973853SYishai Hadas UA_MANDATORY, 291275973853SYishai Hadas UA_ALLOC_AND_COPY), 291375973853SYishai Hadas UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_COOKIE, 291475973853SYishai Hadas UVERBS_ATTR_TYPE(u64), 291575973853SYishai Hadas UA_OPTIONAL), 291675973853SYishai Hadas UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_NUM, 291775973853SYishai Hadas UVERBS_ATTR_TYPE(u32), 291875973853SYishai Hadas UA_OPTIONAL)); 291975973853SYishai Hadas 29206c61d2a5SJason Gunthorpe DECLARE_UVERBS_GLOBAL_METHODS(MLX5_IB_OBJECT_DEVX, 29217c043e90SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OTHER), 2922f6fe01b7SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_UAR), 292375973853SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_EQN), 292475973853SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT)); 29258aa8c95cSYishai Hadas 29266c61d2a5SJason Gunthorpe DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ, 29279a119cd5SJason Gunthorpe UVERBS_TYPE_ALLOC_IDR(devx_obj_cleanup), 29287efce369SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_CREATE), 2929e662e14dSYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_DESTROY), 2930e662e14dSYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_MODIFY), 2931a124edbaSYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_QUERY), 2932a124edbaSYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY)); 29337efce369SYishai Hadas 29346c61d2a5SJason Gunthorpe DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM, 29359a119cd5SJason Gunthorpe UVERBS_TYPE_ALLOC_IDR(devx_umem_cleanup), 2936aeae9457SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_REG), 2937aeae9457SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_DEREG)); 2938aeae9457SYishai Hadas 29396bf8f22aSYishai Hadas 29406bf8f22aSYishai Hadas DECLARE_UVERBS_NAMED_METHOD( 29416bf8f22aSYishai Hadas MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC, 29426bf8f22aSYishai Hadas UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_ASYNC_CMD_FD_ALLOC_HANDLE, 29436bf8f22aSYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD, 29446bf8f22aSYishai Hadas UVERBS_ACCESS_NEW, 29456bf8f22aSYishai Hadas UA_MANDATORY)); 29466bf8f22aSYishai Hadas 29476bf8f22aSYishai Hadas DECLARE_UVERBS_NAMED_OBJECT( 29486bf8f22aSYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD, 29496bf8f22aSYishai Hadas UVERBS_TYPE_ALLOC_FD(sizeof(struct devx_async_cmd_event_file), 2950f7c8416cSJason Gunthorpe devx_async_cmd_event_destroy_uobj, 29516bf8f22aSYishai Hadas &devx_async_cmd_event_fops, "[devx_async_cmd]", 29526bf8f22aSYishai Hadas O_RDONLY), 29536bf8f22aSYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC)); 29546bf8f22aSYishai Hadas 29552afc5e1bSYishai Hadas DECLARE_UVERBS_NAMED_METHOD( 29562afc5e1bSYishai Hadas MLX5_IB_METHOD_DEVX_ASYNC_EVENT_FD_ALLOC, 29572afc5e1bSYishai Hadas UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_HANDLE, 29582afc5e1bSYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD, 29592afc5e1bSYishai Hadas UVERBS_ACCESS_NEW, 29602afc5e1bSYishai Hadas UA_MANDATORY), 29612afc5e1bSYishai Hadas UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_FLAGS, 29622afc5e1bSYishai Hadas enum mlx5_ib_uapi_devx_create_event_channel_flags, 29632afc5e1bSYishai Hadas UA_MANDATORY)); 29642afc5e1bSYishai Hadas 29652afc5e1bSYishai Hadas DECLARE_UVERBS_NAMED_OBJECT( 29662afc5e1bSYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD, 29672afc5e1bSYishai Hadas UVERBS_TYPE_ALLOC_FD(sizeof(struct devx_async_event_file), 2968f7c8416cSJason Gunthorpe devx_async_event_destroy_uobj, 29692afc5e1bSYishai Hadas &devx_async_event_fops, "[devx_async_event]", 29702afc5e1bSYishai Hadas O_RDONLY), 29712afc5e1bSYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_ASYNC_EVENT_FD_ALLOC)); 29722afc5e1bSYishai Hadas 297336e235c8SJason Gunthorpe static bool devx_is_supported(struct ib_device *device) 2974c59450c4SYishai Hadas { 297536e235c8SJason Gunthorpe struct mlx5_ib_dev *dev = to_mdev(device); 297636e235c8SJason Gunthorpe 29777f575103SMark Bloch return MLX5_CAP_GEN(dev->mdev, log_max_uctx); 2978c59450c4SYishai Hadas } 297936e235c8SJason Gunthorpe 29800cbf432dSJason Gunthorpe const struct uapi_definition mlx5_ib_devx_defs[] = { 298136e235c8SJason Gunthorpe UAPI_DEF_CHAIN_OBJ_TREE_NAMED( 298236e235c8SJason Gunthorpe MLX5_IB_OBJECT_DEVX, 298336e235c8SJason Gunthorpe UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)), 298436e235c8SJason Gunthorpe UAPI_DEF_CHAIN_OBJ_TREE_NAMED( 298536e235c8SJason Gunthorpe MLX5_IB_OBJECT_DEVX_OBJ, 298636e235c8SJason Gunthorpe UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)), 298736e235c8SJason Gunthorpe UAPI_DEF_CHAIN_OBJ_TREE_NAMED( 298836e235c8SJason Gunthorpe MLX5_IB_OBJECT_DEVX_UMEM, 298936e235c8SJason Gunthorpe UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)), 29906bf8f22aSYishai Hadas UAPI_DEF_CHAIN_OBJ_TREE_NAMED( 29916bf8f22aSYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD, 29926bf8f22aSYishai Hadas UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)), 29932afc5e1bSYishai Hadas UAPI_DEF_CHAIN_OBJ_TREE_NAMED( 29942afc5e1bSYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD, 29952afc5e1bSYishai Hadas UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)), 29960cbf432dSJason Gunthorpe {}, 29970cbf432dSJason Gunthorpe }; 2998