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; 971368ead0SYishai 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; 1031368ead0SYishai 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 { 1141368ead0SYishai Hadas u32 in[MLX5_ST_SZ_DW(create_uctx_in)] = {}; 1151368ead0SYishai 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 1411368ead0SYishai 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 { 1471368ead0SYishai Hadas u32 in[MLX5_ST_SZ_DW(destroy_uctx_in)] = {}; 1481368ead0SYishai 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 2911368ead0SYishai Hadas static u32 devx_get_created_obj_id(const void *in, const void *out, u16 opcode) 2921368ead0SYishai Hadas { 2931368ead0SYishai Hadas switch (opcode) { 2941368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_GENERAL_OBJECT: 2951368ead0SYishai Hadas return MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 2961368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_UMEM: 2971368ead0SYishai Hadas return MLX5_GET(create_umem_out, out, umem_id); 2981368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_MKEY: 2991368ead0SYishai Hadas return MLX5_GET(create_mkey_out, out, mkey_index); 3001368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_CQ: 3011368ead0SYishai Hadas return MLX5_GET(create_cq_out, out, cqn); 3021368ead0SYishai Hadas case MLX5_CMD_OP_ALLOC_PD: 3031368ead0SYishai Hadas return MLX5_GET(alloc_pd_out, out, pd); 3041368ead0SYishai Hadas case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN: 3051368ead0SYishai Hadas return MLX5_GET(alloc_transport_domain_out, out, 3061368ead0SYishai Hadas transport_domain); 3071368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_RMP: 3081368ead0SYishai Hadas return MLX5_GET(create_rmp_out, out, rmpn); 3091368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_SQ: 3101368ead0SYishai Hadas return MLX5_GET(create_sq_out, out, sqn); 3111368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_RQ: 3121368ead0SYishai Hadas return MLX5_GET(create_rq_out, out, rqn); 3131368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_RQT: 3141368ead0SYishai Hadas return MLX5_GET(create_rqt_out, out, rqtn); 3151368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_TIR: 3161368ead0SYishai Hadas return MLX5_GET(create_tir_out, out, tirn); 3171368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_TIS: 3181368ead0SYishai Hadas return MLX5_GET(create_tis_out, out, tisn); 3191368ead0SYishai Hadas case MLX5_CMD_OP_ALLOC_Q_COUNTER: 3201368ead0SYishai Hadas return MLX5_GET(alloc_q_counter_out, out, counter_set_id); 3211368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_FLOW_TABLE: 3221368ead0SYishai Hadas return MLX5_GET(create_flow_table_out, out, table_id); 3231368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_FLOW_GROUP: 3241368ead0SYishai Hadas return MLX5_GET(create_flow_group_out, out, group_id); 3251368ead0SYishai Hadas case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY: 3261368ead0SYishai Hadas return MLX5_GET(set_fte_in, in, flow_index); 3271368ead0SYishai Hadas case MLX5_CMD_OP_ALLOC_FLOW_COUNTER: 3281368ead0SYishai Hadas return MLX5_GET(alloc_flow_counter_out, out, flow_counter_id); 3291368ead0SYishai Hadas case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT: 3301368ead0SYishai Hadas return MLX5_GET(alloc_packet_reformat_context_out, out, 3311368ead0SYishai Hadas packet_reformat_id); 3321368ead0SYishai Hadas case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT: 3331368ead0SYishai Hadas return MLX5_GET(alloc_modify_header_context_out, out, 3341368ead0SYishai Hadas modify_header_id); 3351368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT: 3361368ead0SYishai Hadas return MLX5_GET(create_scheduling_element_out, out, 3371368ead0SYishai Hadas scheduling_element_id); 3381368ead0SYishai Hadas case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT: 3391368ead0SYishai Hadas return MLX5_GET(add_vxlan_udp_dport_in, in, vxlan_udp_port); 3401368ead0SYishai Hadas case MLX5_CMD_OP_SET_L2_TABLE_ENTRY: 3411368ead0SYishai Hadas return MLX5_GET(set_l2_table_entry_in, in, table_index); 3421368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_QP: 3431368ead0SYishai Hadas return MLX5_GET(create_qp_out, out, qpn); 3441368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_SRQ: 3451368ead0SYishai Hadas return MLX5_GET(create_srq_out, out, srqn); 3461368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_XRC_SRQ: 3471368ead0SYishai Hadas return MLX5_GET(create_xrc_srq_out, out, xrc_srqn); 3481368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_DCT: 3491368ead0SYishai Hadas return MLX5_GET(create_dct_out, out, dctn); 3501368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_XRQ: 3511368ead0SYishai Hadas return MLX5_GET(create_xrq_out, out, xrqn); 3521368ead0SYishai Hadas case MLX5_CMD_OP_ATTACH_TO_MCG: 3531368ead0SYishai Hadas return MLX5_GET(attach_to_mcg_in, in, qpn); 3541368ead0SYishai Hadas case MLX5_CMD_OP_ALLOC_XRCD: 3551368ead0SYishai Hadas return MLX5_GET(alloc_xrcd_out, out, xrcd); 3561368ead0SYishai Hadas case MLX5_CMD_OP_CREATE_PSV: 3571368ead0SYishai Hadas return MLX5_GET(create_psv_out, out, psv0_index); 3581368ead0SYishai Hadas default: 3591368ead0SYishai Hadas /* The entry must match to one of the devx_is_obj_create_cmd */ 3601368ead0SYishai Hadas WARN_ON(true); 3611368ead0SYishai Hadas return 0; 3621368ead0SYishai Hadas } 3631368ead0SYishai Hadas } 3641368ead0SYishai 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, 4761368ead0SYishai Hadas MLX5_GET(query_modify_header_context_in, 4771368ead0SYishai 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 634cfa3b797SMaor Gottlieb if (qp->type == IB_QPT_RAW_PACKET || 6352be08c30SLeon Romanovsky (qp->flags & IB_QP_CREATE_SOURCE_QPN)) { 63634613eb1SYishai Hadas struct mlx5_ib_raw_packet_qp *raw_packet_qp = 63734613eb1SYishai Hadas &qp->raw_packet_qp; 63834613eb1SYishai Hadas struct mlx5_ib_rq *rq = &raw_packet_qp->rq; 63934613eb1SYishai Hadas struct mlx5_ib_sq *sq = &raw_packet_qp->sq; 64034613eb1SYishai Hadas 64134613eb1SYishai Hadas return (get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ, 64234613eb1SYishai Hadas rq->base.mqp.qpn) == obj_id || 64334613eb1SYishai Hadas get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ, 64434613eb1SYishai Hadas sq->base.mqp.qpn) == obj_id || 64534613eb1SYishai Hadas get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR, 64634613eb1SYishai Hadas rq->tirn) == obj_id || 64734613eb1SYishai Hadas get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS, 64834613eb1SYishai Hadas sq->tisn) == obj_id); 64934613eb1SYishai Hadas } 65034613eb1SYishai Hadas 651cfa3b797SMaor Gottlieb if (qp->type == MLX5_IB_QPT_DCT) 65234613eb1SYishai Hadas return get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT, 65334613eb1SYishai Hadas qp->dct.mdct.mqp.qpn) == obj_id; 65434613eb1SYishai Hadas return get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 65534613eb1SYishai Hadas qp->ibqp.qp_num) == obj_id; 65634613eb1SYishai Hadas } 65734613eb1SYishai Hadas 65834613eb1SYishai Hadas case UVERBS_OBJECT_WQ: 65934613eb1SYishai Hadas return get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ, 66034613eb1SYishai Hadas to_mrwq(uobj->object)->core_qp.qpn) == 66134613eb1SYishai Hadas obj_id; 66234613eb1SYishai Hadas 66334613eb1SYishai Hadas case UVERBS_OBJECT_RWQ_IND_TBL: 66434613eb1SYishai Hadas return get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT, 66534613eb1SYishai Hadas to_mrwq_ind_table(uobj->object)->rqtn) == 66634613eb1SYishai Hadas obj_id; 66734613eb1SYishai Hadas 66834613eb1SYishai Hadas case MLX5_IB_OBJECT_DEVX_OBJ: 6693e358ea8SMark Bloch { 6703e358ea8SMark Bloch u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 6713e358ea8SMark Bloch struct devx_obj *devx_uobj = uobj->object; 6723e358ea8SMark Bloch 6733e358ea8SMark Bloch if (opcode == MLX5_CMD_OP_QUERY_FLOW_COUNTER && 6743e358ea8SMark Bloch devx_uobj->flow_counter_bulk_size) { 6753e358ea8SMark Bloch u64 end; 6763e358ea8SMark Bloch 6773e358ea8SMark Bloch end = devx_uobj->obj_id + 6783e358ea8SMark Bloch devx_uobj->flow_counter_bulk_size; 6793e358ea8SMark Bloch return devx_uobj->obj_id <= obj_id && end > obj_id; 6803e358ea8SMark Bloch } 6813e358ea8SMark Bloch 6823e358ea8SMark Bloch return devx_uobj->obj_id == obj_id; 6833e358ea8SMark Bloch } 68434613eb1SYishai Hadas 685e662e14dSYishai Hadas default: 686e662e14dSYishai Hadas return false; 687e662e14dSYishai Hadas } 688e662e14dSYishai Hadas } 689e662e14dSYishai Hadas 690ba1a057dSYishai Hadas static void devx_set_umem_valid(const void *in) 691ba1a057dSYishai Hadas { 692ba1a057dSYishai Hadas u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 693ba1a057dSYishai Hadas 694ba1a057dSYishai Hadas switch (opcode) { 695ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_MKEY: 696ba1a057dSYishai Hadas MLX5_SET(create_mkey_in, in, mkey_umem_valid, 1); 697ba1a057dSYishai Hadas break; 698ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_CQ: 699ba1a057dSYishai Hadas { 700ba1a057dSYishai Hadas void *cqc; 701ba1a057dSYishai Hadas 702ba1a057dSYishai Hadas MLX5_SET(create_cq_in, in, cq_umem_valid, 1); 703ba1a057dSYishai Hadas cqc = MLX5_ADDR_OF(create_cq_in, in, cq_context); 704ba1a057dSYishai Hadas MLX5_SET(cqc, cqc, dbr_umem_valid, 1); 705ba1a057dSYishai Hadas break; 706ba1a057dSYishai Hadas } 707ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_QP: 708ba1a057dSYishai Hadas { 709ba1a057dSYishai Hadas void *qpc; 710ba1a057dSYishai Hadas 711ba1a057dSYishai Hadas qpc = MLX5_ADDR_OF(create_qp_in, in, qpc); 712ba1a057dSYishai Hadas MLX5_SET(qpc, qpc, dbr_umem_valid, 1); 713ba1a057dSYishai Hadas MLX5_SET(create_qp_in, in, wq_umem_valid, 1); 714ba1a057dSYishai Hadas break; 715ba1a057dSYishai Hadas } 716ba1a057dSYishai Hadas 717ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_RQ: 718ba1a057dSYishai Hadas { 719ba1a057dSYishai Hadas void *rqc, *wq; 720ba1a057dSYishai Hadas 721ba1a057dSYishai Hadas rqc = MLX5_ADDR_OF(create_rq_in, in, ctx); 722ba1a057dSYishai Hadas wq = MLX5_ADDR_OF(rqc, rqc, wq); 723ba1a057dSYishai Hadas MLX5_SET(wq, wq, dbr_umem_valid, 1); 724ba1a057dSYishai Hadas MLX5_SET(wq, wq, wq_umem_valid, 1); 725ba1a057dSYishai Hadas break; 726ba1a057dSYishai Hadas } 727ba1a057dSYishai Hadas 728ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_SQ: 729ba1a057dSYishai Hadas { 730ba1a057dSYishai Hadas void *sqc, *wq; 731ba1a057dSYishai Hadas 732ba1a057dSYishai Hadas sqc = MLX5_ADDR_OF(create_sq_in, in, ctx); 733ba1a057dSYishai Hadas wq = MLX5_ADDR_OF(sqc, sqc, wq); 734ba1a057dSYishai Hadas MLX5_SET(wq, wq, dbr_umem_valid, 1); 735ba1a057dSYishai Hadas MLX5_SET(wq, wq, wq_umem_valid, 1); 736ba1a057dSYishai Hadas break; 737ba1a057dSYishai Hadas } 738ba1a057dSYishai Hadas 739ba1a057dSYishai Hadas case MLX5_CMD_OP_MODIFY_CQ: 740ba1a057dSYishai Hadas MLX5_SET(modify_cq_in, in, cq_umem_valid, 1); 741ba1a057dSYishai Hadas break; 742ba1a057dSYishai Hadas 743ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_RMP: 744ba1a057dSYishai Hadas { 745ba1a057dSYishai Hadas void *rmpc, *wq; 746ba1a057dSYishai Hadas 747ba1a057dSYishai Hadas rmpc = MLX5_ADDR_OF(create_rmp_in, in, ctx); 748ba1a057dSYishai Hadas wq = MLX5_ADDR_OF(rmpc, rmpc, wq); 749ba1a057dSYishai Hadas MLX5_SET(wq, wq, dbr_umem_valid, 1); 750ba1a057dSYishai Hadas MLX5_SET(wq, wq, wq_umem_valid, 1); 751ba1a057dSYishai Hadas break; 752ba1a057dSYishai Hadas } 753ba1a057dSYishai Hadas 754ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_XRQ: 755ba1a057dSYishai Hadas { 756ba1a057dSYishai Hadas void *xrqc, *wq; 757ba1a057dSYishai Hadas 758ba1a057dSYishai Hadas xrqc = MLX5_ADDR_OF(create_xrq_in, in, xrq_context); 759ba1a057dSYishai Hadas wq = MLX5_ADDR_OF(xrqc, xrqc, wq); 760ba1a057dSYishai Hadas MLX5_SET(wq, wq, dbr_umem_valid, 1); 761ba1a057dSYishai Hadas MLX5_SET(wq, wq, wq_umem_valid, 1); 762ba1a057dSYishai Hadas break; 763ba1a057dSYishai Hadas } 764ba1a057dSYishai Hadas 765ba1a057dSYishai Hadas case MLX5_CMD_OP_CREATE_XRC_SRQ: 766ba1a057dSYishai Hadas { 767ba1a057dSYishai Hadas void *xrc_srqc; 768ba1a057dSYishai Hadas 769ba1a057dSYishai Hadas MLX5_SET(create_xrc_srq_in, in, xrc_srq_umem_valid, 1); 770ba1a057dSYishai Hadas xrc_srqc = MLX5_ADDR_OF(create_xrc_srq_in, in, 771ba1a057dSYishai Hadas xrc_srq_context_entry); 772ba1a057dSYishai Hadas MLX5_SET(xrc_srqc, xrc_srqc, dbr_umem_valid, 1); 773ba1a057dSYishai Hadas break; 774ba1a057dSYishai Hadas } 775ba1a057dSYishai Hadas 776ba1a057dSYishai Hadas default: 777ba1a057dSYishai Hadas return; 778ba1a057dSYishai Hadas } 779ba1a057dSYishai Hadas } 780ba1a057dSYishai Hadas 7812351776eSYishai Hadas static bool devx_is_obj_create_cmd(const void *in, u16 *opcode) 7827efce369SYishai Hadas { 7832351776eSYishai Hadas *opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 7847efce369SYishai Hadas 7852351776eSYishai Hadas switch (*opcode) { 7867efce369SYishai Hadas case MLX5_CMD_OP_CREATE_GENERAL_OBJECT: 7877efce369SYishai Hadas case MLX5_CMD_OP_CREATE_MKEY: 7887efce369SYishai Hadas case MLX5_CMD_OP_CREATE_CQ: 7897efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_PD: 7907efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN: 7917efce369SYishai Hadas case MLX5_CMD_OP_CREATE_RMP: 7927efce369SYishai Hadas case MLX5_CMD_OP_CREATE_SQ: 7937efce369SYishai Hadas case MLX5_CMD_OP_CREATE_RQ: 7947efce369SYishai Hadas case MLX5_CMD_OP_CREATE_RQT: 7957efce369SYishai Hadas case MLX5_CMD_OP_CREATE_TIR: 7967efce369SYishai Hadas case MLX5_CMD_OP_CREATE_TIS: 7977efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_Q_COUNTER: 7987efce369SYishai Hadas case MLX5_CMD_OP_CREATE_FLOW_TABLE: 7997efce369SYishai Hadas case MLX5_CMD_OP_CREATE_FLOW_GROUP: 8007efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_FLOW_COUNTER: 80160786f09SMark Bloch case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT: 8027efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT: 8037efce369SYishai Hadas case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT: 8047efce369SYishai Hadas case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT: 8057efce369SYishai Hadas case MLX5_CMD_OP_SET_L2_TABLE_ENTRY: 8067efce369SYishai Hadas case MLX5_CMD_OP_CREATE_QP: 8077efce369SYishai Hadas case MLX5_CMD_OP_CREATE_SRQ: 8087efce369SYishai Hadas case MLX5_CMD_OP_CREATE_XRC_SRQ: 8097efce369SYishai Hadas case MLX5_CMD_OP_CREATE_DCT: 8107efce369SYishai Hadas case MLX5_CMD_OP_CREATE_XRQ: 8117efce369SYishai Hadas case MLX5_CMD_OP_ATTACH_TO_MCG: 8127efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_XRCD: 8137efce369SYishai Hadas return true; 8147efce369SYishai Hadas case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY: 8157efce369SYishai Hadas { 8167efce369SYishai Hadas u16 op_mod = MLX5_GET(set_fte_in, in, op_mod); 8177efce369SYishai Hadas if (op_mod == 0) 8187efce369SYishai Hadas return true; 8197efce369SYishai Hadas return false; 8207efce369SYishai Hadas } 8218b38c538SMax Gurtovoy case MLX5_CMD_OP_CREATE_PSV: 8228b38c538SMax Gurtovoy { 8238b38c538SMax Gurtovoy u8 num_psv = MLX5_GET(create_psv_in, in, num_psv); 8248b38c538SMax Gurtovoy 8258b38c538SMax Gurtovoy if (num_psv == 1) 8268b38c538SMax Gurtovoy return true; 8278b38c538SMax Gurtovoy return false; 8288b38c538SMax Gurtovoy } 8297efce369SYishai Hadas default: 8307efce369SYishai Hadas return false; 8317efce369SYishai Hadas } 8327efce369SYishai Hadas } 8337efce369SYishai Hadas 834e662e14dSYishai Hadas static bool devx_is_obj_modify_cmd(const void *in) 835e662e14dSYishai Hadas { 836e662e14dSYishai Hadas u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 837e662e14dSYishai Hadas 838e662e14dSYishai Hadas switch (opcode) { 839e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT: 840e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_CQ: 841e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_RMP: 842e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_SQ: 843e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_RQ: 844e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_RQT: 845e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_TIR: 846e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_TIS: 847e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_FLOW_TABLE: 848e662e14dSYishai Hadas case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT: 849e662e14dSYishai Hadas case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT: 850e662e14dSYishai Hadas case MLX5_CMD_OP_SET_L2_TABLE_ENTRY: 851e662e14dSYishai Hadas case MLX5_CMD_OP_RST2INIT_QP: 852e662e14dSYishai Hadas case MLX5_CMD_OP_INIT2RTR_QP: 853819f7427SAharon Landau case MLX5_CMD_OP_INIT2INIT_QP: 854e662e14dSYishai Hadas case MLX5_CMD_OP_RTR2RTS_QP: 855e662e14dSYishai Hadas case MLX5_CMD_OP_RTS2RTS_QP: 856e662e14dSYishai Hadas case MLX5_CMD_OP_SQERR2RTS_QP: 857e662e14dSYishai Hadas case MLX5_CMD_OP_2ERR_QP: 858e662e14dSYishai Hadas case MLX5_CMD_OP_2RST_QP: 859e662e14dSYishai Hadas case MLX5_CMD_OP_ARM_XRC_SRQ: 860e662e14dSYishai Hadas case MLX5_CMD_OP_ARM_RQ: 861e662e14dSYishai Hadas case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION: 862e662e14dSYishai Hadas case MLX5_CMD_OP_ARM_XRQ: 863719598c9SYishai Hadas case MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY: 8648293a598SYishai Hadas case MLX5_CMD_OP_RELEASE_XRQ_ERROR: 8658293a598SYishai Hadas case MLX5_CMD_OP_MODIFY_XRQ: 866e662e14dSYishai Hadas return true; 867e662e14dSYishai Hadas case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY: 868e662e14dSYishai Hadas { 869e662e14dSYishai Hadas u16 op_mod = MLX5_GET(set_fte_in, in, op_mod); 870e662e14dSYishai Hadas 871e662e14dSYishai Hadas if (op_mod == 1) 872e662e14dSYishai Hadas return true; 873e662e14dSYishai Hadas return false; 874e662e14dSYishai Hadas } 875e662e14dSYishai Hadas default: 876e662e14dSYishai Hadas return false; 877e662e14dSYishai Hadas } 878e662e14dSYishai Hadas } 879e662e14dSYishai Hadas 880e662e14dSYishai Hadas static bool devx_is_obj_query_cmd(const void *in) 881e662e14dSYishai Hadas { 882e662e14dSYishai Hadas u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 883e662e14dSYishai Hadas 884e662e14dSYishai Hadas switch (opcode) { 885e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_GENERAL_OBJECT: 886e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_MKEY: 887e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_CQ: 888e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_RMP: 889e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_SQ: 890e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_RQ: 891e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_RQT: 892e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_TIR: 893e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_TIS: 894e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_Q_COUNTER: 895e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_FLOW_TABLE: 896e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_FLOW_GROUP: 897e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY: 898e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_FLOW_COUNTER: 899e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT: 900e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT: 901e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY: 902e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_QP: 903e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_SRQ: 904e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_XRC_SRQ: 905e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_DCT: 906e662e14dSYishai Hadas case MLX5_CMD_OP_QUERY_XRQ: 907719598c9SYishai Hadas case MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY: 908719598c9SYishai Hadas case MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS: 909719598c9SYishai Hadas case MLX5_CMD_OP_QUERY_PACKET_REFORMAT_CONTEXT: 910e662e14dSYishai Hadas return true; 911e662e14dSYishai Hadas default: 912e662e14dSYishai Hadas return false; 913e662e14dSYishai Hadas } 914e662e14dSYishai Hadas } 915e662e14dSYishai Hadas 9167e1335a7SYishai Hadas static bool devx_is_whitelist_cmd(void *in) 9177e1335a7SYishai Hadas { 9187e1335a7SYishai Hadas u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 9197e1335a7SYishai Hadas 9207e1335a7SYishai Hadas switch (opcode) { 9217e1335a7SYishai Hadas case MLX5_CMD_OP_QUERY_HCA_CAP: 9227e1335a7SYishai Hadas case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT: 92356e5acd4SMaor Gottlieb case MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT: 924b021d82eSBodong Wang case MLX5_CMD_OP_QUERY_ESW_FUNCTIONS: 9257e1335a7SYishai Hadas return true; 9267e1335a7SYishai Hadas default: 9277e1335a7SYishai Hadas return false; 9287e1335a7SYishai Hadas } 9297e1335a7SYishai Hadas } 9307e1335a7SYishai Hadas 9317e1335a7SYishai Hadas static int devx_get_uid(struct mlx5_ib_ucontext *c, void *cmd_in) 9327e1335a7SYishai Hadas { 9337e1335a7SYishai Hadas if (devx_is_whitelist_cmd(cmd_in)) { 9347e1335a7SYishai Hadas struct mlx5_ib_dev *dev; 9357e1335a7SYishai Hadas 9367e1335a7SYishai Hadas if (c->devx_uid) 9377e1335a7SYishai Hadas return c->devx_uid; 9387e1335a7SYishai Hadas 9397e1335a7SYishai Hadas dev = to_mdev(c->ibucontext.device); 9407e1335a7SYishai Hadas if (dev->devx_whitelist_uid) 9417e1335a7SYishai Hadas return dev->devx_whitelist_uid; 9427e1335a7SYishai Hadas 9437e1335a7SYishai Hadas return -EOPNOTSUPP; 9447e1335a7SYishai Hadas } 9457e1335a7SYishai Hadas 9467e1335a7SYishai Hadas if (!c->devx_uid) 9477e1335a7SYishai Hadas return -EINVAL; 9487e1335a7SYishai Hadas 9497e1335a7SYishai Hadas return c->devx_uid; 9507e1335a7SYishai Hadas } 951b6142608SMax Gurtovoy 952b6142608SMax Gurtovoy static bool devx_is_general_cmd(void *in, struct mlx5_ib_dev *dev) 9538aa8c95cSYishai Hadas { 9548aa8c95cSYishai Hadas u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 9558aa8c95cSYishai Hadas 956b6142608SMax Gurtovoy /* Pass all cmds for vhca_tunnel as general, tracking is done in FW */ 957b6142608SMax Gurtovoy if ((MLX5_CAP_GEN_64(dev->mdev, vhca_tunnel_commands) && 958b6142608SMax Gurtovoy MLX5_GET(general_obj_in_cmd_hdr, in, vhca_tunnel_id)) || 959b6142608SMax Gurtovoy (opcode >= MLX5_CMD_OP_GENERAL_START && 960b6142608SMax Gurtovoy opcode < MLX5_CMD_OP_GENERAL_END)) 961719598c9SYishai Hadas return true; 962719598c9SYishai Hadas 9638aa8c95cSYishai Hadas switch (opcode) { 9648aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_HCA_CAP: 9657e1335a7SYishai Hadas case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT: 96656e5acd4SMaor Gottlieb case MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT: 9678aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_VPORT_STATE: 9688aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_ADAPTER: 9698aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_ISSI: 9708aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT: 9718aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_ROCE_ADDRESS: 9728aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_VNIC_ENV: 9738aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_VPORT_COUNTER: 9748aa8c95cSYishai Hadas case MLX5_CMD_OP_GET_DROPPED_PACKET_LOG: 9758aa8c95cSYishai Hadas case MLX5_CMD_OP_NOP: 9768aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_CONG_STATUS: 9778aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_CONG_PARAMS: 9788aa8c95cSYishai Hadas case MLX5_CMD_OP_QUERY_CONG_STATISTICS: 9797084ed30SMark Zhang case MLX5_CMD_OP_QUERY_LAG: 980b021d82eSBodong Wang case MLX5_CMD_OP_QUERY_ESW_FUNCTIONS: 9818aa8c95cSYishai Hadas return true; 9828aa8c95cSYishai Hadas default: 9838aa8c95cSYishai Hadas return false; 9848aa8c95cSYishai Hadas } 9858aa8c95cSYishai Hadas } 9868aa8c95cSYishai Hadas 987e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_EQN)( 98815a1b4beSJason Gunthorpe struct uverbs_attr_bundle *attrs) 989f6fe01b7SYishai Hadas { 990e83f0ecdSJason Gunthorpe struct mlx5_ib_ucontext *c; 991e83f0ecdSJason Gunthorpe struct mlx5_ib_dev *dev; 992f6fe01b7SYishai Hadas int user_vector; 993f6fe01b7SYishai Hadas int dev_eqn; 994f6fe01b7SYishai Hadas int err; 995f6fe01b7SYishai Hadas 996f6fe01b7SYishai Hadas if (uverbs_copy_from(&user_vector, attrs, 997f6fe01b7SYishai Hadas MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC)) 998f6fe01b7SYishai Hadas return -EFAULT; 999f6fe01b7SYishai Hadas 100015a1b4beSJason Gunthorpe c = devx_ufile2uctx(attrs); 1001e83f0ecdSJason Gunthorpe if (IS_ERR(c)) 1002e83f0ecdSJason Gunthorpe return PTR_ERR(c); 1003e83f0ecdSJason Gunthorpe dev = to_mdev(c->ibucontext.device); 1004e83f0ecdSJason Gunthorpe 1005f14c1a14SMaher Sanalla err = mlx5_comp_eqn_get(dev->mdev, user_vector, &dev_eqn); 1006f6fe01b7SYishai Hadas if (err < 0) 1007f6fe01b7SYishai Hadas return err; 1008f6fe01b7SYishai Hadas 1009f6fe01b7SYishai Hadas if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN, 1010f6fe01b7SYishai Hadas &dev_eqn, sizeof(dev_eqn))) 1011f6fe01b7SYishai Hadas return -EFAULT; 1012f6fe01b7SYishai Hadas 1013f6fe01b7SYishai Hadas return 0; 1014f6fe01b7SYishai Hadas } 1015f6fe01b7SYishai Hadas 10167c043e90SYishai Hadas /* 10177c043e90SYishai Hadas *Security note: 10187c043e90SYishai Hadas * The hardware protection mechanism works like this: Each device object that 10197c043e90SYishai Hadas * is subject to UAR doorbells (QP/SQ/CQ) gets a UAR ID (called uar_page in 10207c043e90SYishai Hadas * the device specification manual) upon its creation. Then upon doorbell, 10217c043e90SYishai Hadas * hardware fetches the object context for which the doorbell was rang, and 10227c043e90SYishai Hadas * validates that the UAR through which the DB was rang matches the UAR ID 10237c043e90SYishai Hadas * of the object. 10247c043e90SYishai Hadas * If no match the doorbell is silently ignored by the hardware. Of course, 10257c043e90SYishai Hadas * the user cannot ring a doorbell on a UAR that was not mapped to it. 10267c043e90SYishai Hadas * Now in devx, as the devx kernel does not manipulate the QP/SQ/CQ command 10277c043e90SYishai Hadas * mailboxes (except tagging them with UID), we expose to the user its UAR 10287c043e90SYishai Hadas * ID, so it can embed it in these objects in the expected specification 10297c043e90SYishai Hadas * format. So the only thing the user can do is hurt itself by creating a 10307c043e90SYishai Hadas * QP/SQ/CQ with a UAR ID other than his, and then in this case other users 10317c043e90SYishai Hadas * may ring a doorbell on its objects. 10327c043e90SYishai Hadas * The consequence of that will be that another user can schedule a QP/SQ 10337c043e90SYishai Hadas * of the buggy user for execution (just insert it to the hardware schedule 10347c043e90SYishai Hadas * queue or arm its CQ for event generation), no further harm is expected. 10357c043e90SYishai Hadas */ 1036e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_UAR)( 103715a1b4beSJason Gunthorpe struct uverbs_attr_bundle *attrs) 10387c043e90SYishai Hadas { 103922fa27fbSJason Gunthorpe struct mlx5_ib_ucontext *c; 104022fa27fbSJason Gunthorpe struct mlx5_ib_dev *dev; 10417c043e90SYishai Hadas u32 user_idx; 10427c043e90SYishai Hadas s32 dev_idx; 10437c043e90SYishai Hadas 104415a1b4beSJason Gunthorpe c = devx_ufile2uctx(attrs); 104522fa27fbSJason Gunthorpe if (IS_ERR(c)) 104622fa27fbSJason Gunthorpe return PTR_ERR(c); 104722fa27fbSJason Gunthorpe dev = to_mdev(c->ibucontext.device); 104822fa27fbSJason Gunthorpe 10497c043e90SYishai Hadas if (uverbs_copy_from(&user_idx, attrs, 10507c043e90SYishai Hadas MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX)) 10517c043e90SYishai Hadas return -EFAULT; 10527c043e90SYishai Hadas 105322fa27fbSJason Gunthorpe dev_idx = bfregn_to_uar_index(dev, &c->bfregi, user_idx, true); 10547c043e90SYishai Hadas if (dev_idx < 0) 10557c043e90SYishai Hadas return dev_idx; 10567c043e90SYishai Hadas 10577c043e90SYishai Hadas if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX, 10587c043e90SYishai Hadas &dev_idx, sizeof(dev_idx))) 10597c043e90SYishai Hadas return -EFAULT; 10607c043e90SYishai Hadas 10617c043e90SYishai Hadas return 0; 10627c043e90SYishai Hadas } 10637c043e90SYishai Hadas 1064e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)( 106515a1b4beSJason Gunthorpe struct uverbs_attr_bundle *attrs) 10668aa8c95cSYishai Hadas { 106722fa27fbSJason Gunthorpe struct mlx5_ib_ucontext *c; 106822fa27fbSJason Gunthorpe struct mlx5_ib_dev *dev; 10697efce369SYishai Hadas void *cmd_in = uverbs_attr_get_alloced_ptr( 10707efce369SYishai Hadas attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN); 10718aa8c95cSYishai Hadas int cmd_out_len = uverbs_attr_get_len(attrs, 10728aa8c95cSYishai Hadas MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT); 10738aa8c95cSYishai Hadas void *cmd_out; 1074c76a1e90SSaeed Mahameed int err, err2; 10757e1335a7SYishai Hadas int uid; 10768aa8c95cSYishai Hadas 107715a1b4beSJason Gunthorpe c = devx_ufile2uctx(attrs); 107822fa27fbSJason Gunthorpe if (IS_ERR(c)) 107922fa27fbSJason Gunthorpe return PTR_ERR(c); 108022fa27fbSJason Gunthorpe dev = to_mdev(c->ibucontext.device); 108122fa27fbSJason Gunthorpe 10827e1335a7SYishai Hadas uid = devx_get_uid(c, cmd_in); 10837e1335a7SYishai Hadas if (uid < 0) 10847e1335a7SYishai Hadas return uid; 10858aa8c95cSYishai Hadas 10868aa8c95cSYishai Hadas /* Only white list of some general HCA commands are allowed for this method. */ 1087b6142608SMax Gurtovoy if (!devx_is_general_cmd(cmd_in, dev)) 10888aa8c95cSYishai Hadas return -EINVAL; 10898aa8c95cSYishai Hadas 1090b61815e2SJason Gunthorpe cmd_out = uverbs_zalloc(attrs, cmd_out_len); 1091b61815e2SJason Gunthorpe if (IS_ERR(cmd_out)) 1092b61815e2SJason Gunthorpe return PTR_ERR(cmd_out); 10938aa8c95cSYishai Hadas 10947e1335a7SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); 1095c76a1e90SSaeed Mahameed err = mlx5_cmd_do(dev->mdev, cmd_in, 10968aa8c95cSYishai Hadas uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN), 10978aa8c95cSYishai Hadas cmd_out, cmd_out_len); 1098c76a1e90SSaeed Mahameed if (err && err != -EREMOTEIO) 10998aa8c95cSYishai Hadas return err; 1100b61815e2SJason Gunthorpe 1101c76a1e90SSaeed Mahameed err2 = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT, cmd_out, 1102b61815e2SJason Gunthorpe cmd_out_len); 1103c76a1e90SSaeed Mahameed 1104c76a1e90SSaeed Mahameed return err2 ?: err; 11058aa8c95cSYishai Hadas } 11068aa8c95cSYishai Hadas 11077efce369SYishai Hadas static void devx_obj_build_destroy_cmd(void *in, void *out, void *din, 11087efce369SYishai Hadas u32 *dinlen, 11097efce369SYishai Hadas u32 *obj_id) 11107efce369SYishai Hadas { 11111368ead0SYishai Hadas u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 11127efce369SYishai Hadas u16 uid = MLX5_GET(general_obj_in_cmd_hdr, in, uid); 11137efce369SYishai Hadas 11141368ead0SYishai Hadas *obj_id = devx_get_created_obj_id(in, out, opcode); 11157efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr); 11167efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, uid, uid); 11177efce369SYishai Hadas 11181368ead0SYishai Hadas switch (opcode) { 11197efce369SYishai Hadas case MLX5_CMD_OP_CREATE_GENERAL_OBJECT: 11207efce369SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT); 11211368ead0SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, obj_id, *obj_id); 11221368ead0SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, din, obj_type, 11231368ead0SYishai Hadas MLX5_GET(general_obj_in_cmd_hdr, in, obj_type)); 11247efce369SYishai Hadas break; 11257efce369SYishai Hadas 11266e3722baSYishai Hadas case MLX5_CMD_OP_CREATE_UMEM: 11271368ead0SYishai Hadas MLX5_SET(destroy_umem_in, din, opcode, 11286e3722baSYishai Hadas MLX5_CMD_OP_DESTROY_UMEM); 11291368ead0SYishai Hadas MLX5_SET(destroy_umem_in, din, umem_id, *obj_id); 11306e3722baSYishai Hadas break; 11317efce369SYishai Hadas case MLX5_CMD_OP_CREATE_MKEY: 11321368ead0SYishai Hadas MLX5_SET(destroy_mkey_in, din, opcode, 11331368ead0SYishai Hadas MLX5_CMD_OP_DESTROY_MKEY); 113422053df0SMark Zhang MLX5_SET(destroy_mkey_in, din, mkey_index, *obj_id); 11357efce369SYishai Hadas break; 11367efce369SYishai Hadas case MLX5_CMD_OP_CREATE_CQ: 11371368ead0SYishai Hadas MLX5_SET(destroy_cq_in, din, opcode, MLX5_CMD_OP_DESTROY_CQ); 11381368ead0SYishai Hadas MLX5_SET(destroy_cq_in, din, cqn, *obj_id); 11397efce369SYishai Hadas break; 11407efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_PD: 11411368ead0SYishai Hadas MLX5_SET(dealloc_pd_in, din, opcode, MLX5_CMD_OP_DEALLOC_PD); 11421368ead0SYishai Hadas MLX5_SET(dealloc_pd_in, din, pd, *obj_id); 11437efce369SYishai Hadas break; 11447efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN: 11451368ead0SYishai Hadas MLX5_SET(dealloc_transport_domain_in, din, opcode, 11467efce369SYishai Hadas MLX5_CMD_OP_DEALLOC_TRANSPORT_DOMAIN); 11471368ead0SYishai Hadas MLX5_SET(dealloc_transport_domain_in, din, transport_domain, 11481368ead0SYishai Hadas *obj_id); 11497efce369SYishai Hadas break; 11507efce369SYishai Hadas case MLX5_CMD_OP_CREATE_RMP: 11511368ead0SYishai Hadas MLX5_SET(destroy_rmp_in, din, opcode, MLX5_CMD_OP_DESTROY_RMP); 11521368ead0SYishai Hadas MLX5_SET(destroy_rmp_in, din, rmpn, *obj_id); 11537efce369SYishai Hadas break; 11547efce369SYishai Hadas case MLX5_CMD_OP_CREATE_SQ: 11551368ead0SYishai Hadas MLX5_SET(destroy_sq_in, din, opcode, MLX5_CMD_OP_DESTROY_SQ); 11561368ead0SYishai Hadas MLX5_SET(destroy_sq_in, din, sqn, *obj_id); 11577efce369SYishai Hadas break; 11587efce369SYishai Hadas case MLX5_CMD_OP_CREATE_RQ: 11591368ead0SYishai Hadas MLX5_SET(destroy_rq_in, din, opcode, MLX5_CMD_OP_DESTROY_RQ); 11601368ead0SYishai Hadas MLX5_SET(destroy_rq_in, din, rqn, *obj_id); 11617efce369SYishai Hadas break; 11627efce369SYishai Hadas case MLX5_CMD_OP_CREATE_RQT: 11631368ead0SYishai Hadas MLX5_SET(destroy_rqt_in, din, opcode, MLX5_CMD_OP_DESTROY_RQT); 11641368ead0SYishai Hadas MLX5_SET(destroy_rqt_in, din, rqtn, *obj_id); 11657efce369SYishai Hadas break; 11667efce369SYishai Hadas case MLX5_CMD_OP_CREATE_TIR: 11678798e4adSYishai Hadas MLX5_SET(destroy_tir_in, din, opcode, MLX5_CMD_OP_DESTROY_TIR); 11688798e4adSYishai Hadas MLX5_SET(destroy_tir_in, din, tirn, *obj_id); 11697efce369SYishai Hadas break; 11707efce369SYishai Hadas case MLX5_CMD_OP_CREATE_TIS: 11711368ead0SYishai Hadas MLX5_SET(destroy_tis_in, din, opcode, MLX5_CMD_OP_DESTROY_TIS); 11721368ead0SYishai Hadas MLX5_SET(destroy_tis_in, din, tisn, *obj_id); 11737efce369SYishai Hadas break; 11747efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_Q_COUNTER: 11751368ead0SYishai Hadas MLX5_SET(dealloc_q_counter_in, din, opcode, 11767efce369SYishai Hadas MLX5_CMD_OP_DEALLOC_Q_COUNTER); 11771368ead0SYishai Hadas MLX5_SET(dealloc_q_counter_in, din, counter_set_id, *obj_id); 11787efce369SYishai Hadas break; 11797efce369SYishai Hadas case MLX5_CMD_OP_CREATE_FLOW_TABLE: 11807efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(destroy_flow_table_in); 11817efce369SYishai Hadas MLX5_SET(destroy_flow_table_in, din, other_vport, 11827efce369SYishai Hadas MLX5_GET(create_flow_table_in, in, other_vport)); 11837efce369SYishai Hadas MLX5_SET(destroy_flow_table_in, din, vport_number, 11847efce369SYishai Hadas MLX5_GET(create_flow_table_in, in, vport_number)); 11857efce369SYishai Hadas MLX5_SET(destroy_flow_table_in, din, table_type, 11867efce369SYishai Hadas MLX5_GET(create_flow_table_in, in, table_type)); 11877efce369SYishai Hadas MLX5_SET(destroy_flow_table_in, din, table_id, *obj_id); 11881368ead0SYishai Hadas MLX5_SET(destroy_flow_table_in, din, opcode, 11897efce369SYishai Hadas MLX5_CMD_OP_DESTROY_FLOW_TABLE); 11907efce369SYishai Hadas break; 11917efce369SYishai Hadas case MLX5_CMD_OP_CREATE_FLOW_GROUP: 11927efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(destroy_flow_group_in); 11937efce369SYishai Hadas MLX5_SET(destroy_flow_group_in, din, other_vport, 11947efce369SYishai Hadas MLX5_GET(create_flow_group_in, in, other_vport)); 11957efce369SYishai Hadas MLX5_SET(destroy_flow_group_in, din, vport_number, 11967efce369SYishai Hadas MLX5_GET(create_flow_group_in, in, vport_number)); 11977efce369SYishai Hadas MLX5_SET(destroy_flow_group_in, din, table_type, 11987efce369SYishai Hadas MLX5_GET(create_flow_group_in, in, table_type)); 11997efce369SYishai Hadas MLX5_SET(destroy_flow_group_in, din, table_id, 12007efce369SYishai Hadas MLX5_GET(create_flow_group_in, in, table_id)); 12017efce369SYishai Hadas MLX5_SET(destroy_flow_group_in, din, group_id, *obj_id); 12021368ead0SYishai Hadas MLX5_SET(destroy_flow_group_in, din, opcode, 12037efce369SYishai Hadas MLX5_CMD_OP_DESTROY_FLOW_GROUP); 12047efce369SYishai Hadas break; 12057efce369SYishai Hadas case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY: 12067efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(delete_fte_in); 12077efce369SYishai Hadas MLX5_SET(delete_fte_in, din, other_vport, 12087efce369SYishai Hadas MLX5_GET(set_fte_in, in, other_vport)); 12097efce369SYishai Hadas MLX5_SET(delete_fte_in, din, vport_number, 12107efce369SYishai Hadas MLX5_GET(set_fte_in, in, vport_number)); 12117efce369SYishai Hadas MLX5_SET(delete_fte_in, din, table_type, 12127efce369SYishai Hadas MLX5_GET(set_fte_in, in, table_type)); 12137efce369SYishai Hadas MLX5_SET(delete_fte_in, din, table_id, 12147efce369SYishai Hadas MLX5_GET(set_fte_in, in, table_id)); 12157efce369SYishai Hadas MLX5_SET(delete_fte_in, din, flow_index, *obj_id); 12161368ead0SYishai Hadas MLX5_SET(delete_fte_in, din, opcode, 12177efce369SYishai Hadas MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY); 12187efce369SYishai Hadas break; 12197efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_FLOW_COUNTER: 12201368ead0SYishai Hadas MLX5_SET(dealloc_flow_counter_in, din, opcode, 12217efce369SYishai Hadas MLX5_CMD_OP_DEALLOC_FLOW_COUNTER); 12221368ead0SYishai Hadas MLX5_SET(dealloc_flow_counter_in, din, flow_counter_id, 12231368ead0SYishai Hadas *obj_id); 12247efce369SYishai Hadas break; 122560786f09SMark Bloch case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT: 12261368ead0SYishai Hadas MLX5_SET(dealloc_packet_reformat_context_in, din, opcode, 122760786f09SMark Bloch MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT); 12281368ead0SYishai Hadas MLX5_SET(dealloc_packet_reformat_context_in, din, 12291368ead0SYishai Hadas packet_reformat_id, *obj_id); 12307efce369SYishai Hadas break; 12317efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT: 12321368ead0SYishai Hadas MLX5_SET(dealloc_modify_header_context_in, din, opcode, 12337efce369SYishai Hadas MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT); 12341368ead0SYishai Hadas MLX5_SET(dealloc_modify_header_context_in, din, 12351368ead0SYishai Hadas modify_header_id, *obj_id); 12367efce369SYishai Hadas break; 12377efce369SYishai Hadas case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT: 12387efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(destroy_scheduling_element_in); 12397efce369SYishai Hadas MLX5_SET(destroy_scheduling_element_in, din, 12407efce369SYishai Hadas scheduling_hierarchy, 12417efce369SYishai Hadas MLX5_GET(create_scheduling_element_in, in, 12427efce369SYishai Hadas scheduling_hierarchy)); 12437efce369SYishai Hadas MLX5_SET(destroy_scheduling_element_in, din, 12447efce369SYishai Hadas scheduling_element_id, *obj_id); 12451368ead0SYishai Hadas MLX5_SET(destroy_scheduling_element_in, din, opcode, 12467efce369SYishai Hadas MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT); 12477efce369SYishai Hadas break; 12487efce369SYishai Hadas case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT: 12497efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(delete_vxlan_udp_dport_in); 12507efce369SYishai Hadas MLX5_SET(delete_vxlan_udp_dport_in, din, vxlan_udp_port, *obj_id); 12511368ead0SYishai Hadas MLX5_SET(delete_vxlan_udp_dport_in, din, opcode, 12527efce369SYishai Hadas MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT); 12537efce369SYishai Hadas break; 12547efce369SYishai Hadas case MLX5_CMD_OP_SET_L2_TABLE_ENTRY: 12557efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(delete_l2_table_entry_in); 12567efce369SYishai Hadas MLX5_SET(delete_l2_table_entry_in, din, table_index, *obj_id); 12571368ead0SYishai Hadas MLX5_SET(delete_l2_table_entry_in, din, opcode, 12587efce369SYishai Hadas MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY); 12597efce369SYishai Hadas break; 12607efce369SYishai Hadas case MLX5_CMD_OP_CREATE_QP: 12611368ead0SYishai Hadas MLX5_SET(destroy_qp_in, din, opcode, MLX5_CMD_OP_DESTROY_QP); 12621368ead0SYishai Hadas MLX5_SET(destroy_qp_in, din, qpn, *obj_id); 12637efce369SYishai Hadas break; 12647efce369SYishai Hadas case MLX5_CMD_OP_CREATE_SRQ: 12651368ead0SYishai Hadas MLX5_SET(destroy_srq_in, din, opcode, MLX5_CMD_OP_DESTROY_SRQ); 12661368ead0SYishai Hadas MLX5_SET(destroy_srq_in, din, srqn, *obj_id); 12677efce369SYishai Hadas break; 12687efce369SYishai Hadas case MLX5_CMD_OP_CREATE_XRC_SRQ: 12691368ead0SYishai Hadas MLX5_SET(destroy_xrc_srq_in, din, opcode, 12707efce369SYishai Hadas MLX5_CMD_OP_DESTROY_XRC_SRQ); 12711368ead0SYishai Hadas MLX5_SET(destroy_xrc_srq_in, din, xrc_srqn, *obj_id); 12727efce369SYishai Hadas break; 12737efce369SYishai Hadas case MLX5_CMD_OP_CREATE_DCT: 12741368ead0SYishai Hadas MLX5_SET(destroy_dct_in, din, opcode, MLX5_CMD_OP_DESTROY_DCT); 12751368ead0SYishai Hadas MLX5_SET(destroy_dct_in, din, dctn, *obj_id); 12767efce369SYishai Hadas break; 12777efce369SYishai Hadas case MLX5_CMD_OP_CREATE_XRQ: 12781368ead0SYishai Hadas MLX5_SET(destroy_xrq_in, din, opcode, MLX5_CMD_OP_DESTROY_XRQ); 12791368ead0SYishai Hadas MLX5_SET(destroy_xrq_in, din, xrqn, *obj_id); 12807efce369SYishai Hadas break; 12817efce369SYishai Hadas case MLX5_CMD_OP_ATTACH_TO_MCG: 12827efce369SYishai Hadas *dinlen = MLX5_ST_SZ_BYTES(detach_from_mcg_in); 12837efce369SYishai Hadas MLX5_SET(detach_from_mcg_in, din, qpn, 12847efce369SYishai Hadas MLX5_GET(attach_to_mcg_in, in, qpn)); 12857efce369SYishai Hadas memcpy(MLX5_ADDR_OF(detach_from_mcg_in, din, multicast_gid), 12867efce369SYishai Hadas MLX5_ADDR_OF(attach_to_mcg_in, in, multicast_gid), 12877efce369SYishai Hadas MLX5_FLD_SZ_BYTES(attach_to_mcg_in, multicast_gid)); 12881368ead0SYishai Hadas MLX5_SET(detach_from_mcg_in, din, opcode, 12891368ead0SYishai Hadas MLX5_CMD_OP_DETACH_FROM_MCG); 12901368ead0SYishai Hadas MLX5_SET(detach_from_mcg_in, din, qpn, *obj_id); 12917efce369SYishai Hadas break; 12927efce369SYishai Hadas case MLX5_CMD_OP_ALLOC_XRCD: 12931368ead0SYishai Hadas MLX5_SET(dealloc_xrcd_in, din, opcode, 12941368ead0SYishai Hadas MLX5_CMD_OP_DEALLOC_XRCD); 12951368ead0SYishai Hadas MLX5_SET(dealloc_xrcd_in, din, xrcd, *obj_id); 12967efce369SYishai Hadas break; 12978b38c538SMax Gurtovoy case MLX5_CMD_OP_CREATE_PSV: 12981368ead0SYishai Hadas MLX5_SET(destroy_psv_in, din, opcode, 12998b38c538SMax Gurtovoy MLX5_CMD_OP_DESTROY_PSV); 13001368ead0SYishai Hadas MLX5_SET(destroy_psv_in, din, psvn, *obj_id); 13018b38c538SMax Gurtovoy break; 13027efce369SYishai Hadas default: 13037efce369SYishai Hadas /* The entry must match to one of the devx_is_obj_create_cmd */ 13047efce369SYishai Hadas WARN_ON(true); 13057efce369SYishai Hadas break; 13067efce369SYishai Hadas } 13077efce369SYishai Hadas } 13087efce369SYishai Hadas 1309534fd7aaSYishai Hadas static int devx_handle_mkey_indirect(struct devx_obj *obj, 1310534fd7aaSYishai Hadas struct mlx5_ib_dev *dev, 1311534fd7aaSYishai Hadas void *in, void *out) 1312534fd7aaSYishai Hadas { 1313ae0579acSAharon Landau struct mlx5_ib_mkey *mkey = &obj->mkey; 1314534fd7aaSYishai Hadas void *mkc; 1315534fd7aaSYishai Hadas u8 key; 1316534fd7aaSYishai Hadas 1317534fd7aaSYishai Hadas mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry); 1318534fd7aaSYishai Hadas key = MLX5_GET(mkc, mkc, mkey_7_0); 1319534fd7aaSYishai Hadas mkey->key = mlx5_idx_to_mkey( 1320534fd7aaSYishai Hadas MLX5_GET(create_mkey_out, out, mkey_index)) | key; 1321534fd7aaSYishai Hadas mkey->type = MLX5_MKEY_INDIRECT_DEVX; 1322ae0579acSAharon Landau mkey->ndescs = MLX5_GET(mkc, mkc, translations_octword_size); 1323db72438cSYishai Hadas init_waitqueue_head(&mkey->wait); 1324534fd7aaSYishai Hadas 1325db72438cSYishai Hadas return mlx5r_store_odp_mkey(dev, mkey); 1326534fd7aaSYishai Hadas } 1327534fd7aaSYishai Hadas 1328fa31f143SYishai Hadas static int devx_handle_mkey_create(struct mlx5_ib_dev *dev, 1329fa31f143SYishai Hadas struct devx_obj *obj, 1330fa31f143SYishai Hadas void *in, int in_len) 1331fa31f143SYishai Hadas { 1332fa31f143SYishai Hadas int min_len = MLX5_BYTE_OFF(create_mkey_in, memory_key_mkey_entry) + 1333fa31f143SYishai Hadas MLX5_FLD_SZ_BYTES(create_mkey_in, 1334fa31f143SYishai Hadas memory_key_mkey_entry); 1335fa31f143SYishai Hadas void *mkc; 1336fa31f143SYishai Hadas u8 access_mode; 1337fa31f143SYishai Hadas 1338fa31f143SYishai Hadas if (in_len < min_len) 1339fa31f143SYishai Hadas return -EINVAL; 1340fa31f143SYishai Hadas 1341fa31f143SYishai Hadas mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry); 1342fa31f143SYishai Hadas 1343fa31f143SYishai Hadas access_mode = MLX5_GET(mkc, mkc, access_mode_1_0); 1344fa31f143SYishai Hadas access_mode |= MLX5_GET(mkc, mkc, access_mode_4_2) << 2; 1345fa31f143SYishai Hadas 1346fa31f143SYishai Hadas if (access_mode == MLX5_MKC_ACCESS_MODE_KLMS || 1347534fd7aaSYishai Hadas access_mode == MLX5_MKC_ACCESS_MODE_KSM) { 1348534fd7aaSYishai Hadas if (IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING)) 1349534fd7aaSYishai Hadas obj->flags |= DEVX_OBJ_FLAGS_INDIRECT_MKEY; 1350fa31f143SYishai Hadas return 0; 1351534fd7aaSYishai Hadas } 1352fa31f143SYishai Hadas 1353fa31f143SYishai Hadas MLX5_SET(create_mkey_in, in, mkey_umem_valid, 1); 1354fa31f143SYishai Hadas return 0; 1355fa31f143SYishai Hadas } 1356fa31f143SYishai Hadas 135775973853SYishai Hadas static void devx_cleanup_subscription(struct mlx5_ib_dev *dev, 135875973853SYishai Hadas struct devx_event_subscription *sub) 135975973853SYishai Hadas { 136075973853SYishai Hadas struct devx_event *event; 136175973853SYishai Hadas struct devx_obj_event *xa_val_level2; 136275973853SYishai Hadas 136375973853SYishai Hadas if (sub->is_cleaned) 136475973853SYishai Hadas return; 136575973853SYishai Hadas 136675973853SYishai Hadas sub->is_cleaned = 1; 136775973853SYishai Hadas list_del_rcu(&sub->xa_list); 136875973853SYishai Hadas 136975973853SYishai Hadas if (list_empty(&sub->obj_list)) 137075973853SYishai Hadas return; 137175973853SYishai Hadas 137275973853SYishai Hadas list_del_rcu(&sub->obj_list); 137375973853SYishai Hadas /* check whether key level 1 for this obj_sub_list is empty */ 137475973853SYishai Hadas event = xa_load(&dev->devx_event_table.event_xa, 137575973853SYishai Hadas sub->xa_key_level1); 137675973853SYishai Hadas WARN_ON(!event); 137775973853SYishai Hadas 137875973853SYishai Hadas xa_val_level2 = xa_load(&event->object_ids, sub->xa_key_level2); 137975973853SYishai Hadas if (list_empty(&xa_val_level2->obj_sub_list)) { 138075973853SYishai Hadas xa_erase(&event->object_ids, 138175973853SYishai Hadas sub->xa_key_level2); 138275973853SYishai Hadas kfree_rcu(xa_val_level2, rcu); 138375973853SYishai Hadas } 138475973853SYishai Hadas } 138575973853SYishai Hadas 13867efce369SYishai Hadas static int devx_obj_cleanup(struct ib_uobject *uobject, 1387a6a3797dSShamir Rabinovitch enum rdma_remove_reason why, 1388a6a3797dSShamir Rabinovitch struct uverbs_attr_bundle *attrs) 13897efce369SYishai Hadas { 13907efce369SYishai Hadas u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)]; 139175973853SYishai Hadas struct mlx5_devx_event_table *devx_event_table; 13927efce369SYishai Hadas struct devx_obj *obj = uobject->object; 139375973853SYishai Hadas struct devx_event_subscription *sub_entry, *tmp; 139475973853SYishai Hadas struct mlx5_ib_dev *dev; 13957efce369SYishai Hadas int ret; 13967efce369SYishai Hadas 139775973853SYishai Hadas dev = mlx5_udata_to_mdev(&attrs->driver_udata); 1398db72438cSYishai Hadas if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY && 1399db72438cSYishai Hadas xa_erase(&obj->ib_dev->odp_mkeys, 1400ae0579acSAharon Landau mlx5_base_mkey(obj->mkey.key))) 140104177915SJason Gunthorpe /* 140204177915SJason Gunthorpe * The pagefault_single_data_segment() does commands against 140304177915SJason Gunthorpe * the mmkey, we must wait for that to stop before freeing the 140404177915SJason Gunthorpe * mkey, as another allocation could get the same mkey #. 140504177915SJason Gunthorpe */ 1406ae0579acSAharon Landau mlx5r_deref_wait_odp_mkey(&obj->mkey); 1407534fd7aaSYishai Hadas 1408c5ae1954SYishai Hadas if (obj->flags & DEVX_OBJ_FLAGS_DCT) 1409333fbaa0SLeon Romanovsky ret = mlx5_core_destroy_dct(obj->ib_dev, &obj->core_dct); 1410ef1659adSYishai Hadas else if (obj->flags & DEVX_OBJ_FLAGS_CQ) 14115832fdd3SYishai Hadas ret = mlx5_core_destroy_cq(obj->ib_dev->mdev, &obj->core_cq); 1412c5ae1954SYishai Hadas else 14135832fdd3SYishai Hadas ret = mlx5_cmd_exec(obj->ib_dev->mdev, obj->dinbox, 14145832fdd3SYishai Hadas obj->dinlen, out, sizeof(out)); 1415efa968eeSLeon Romanovsky if (ret) 14167efce369SYishai Hadas return ret; 14177efce369SYishai Hadas 141875973853SYishai Hadas devx_event_table = &dev->devx_event_table; 1419534fd7aaSYishai Hadas 142075973853SYishai Hadas mutex_lock(&devx_event_table->event_xa_lock); 142175973853SYishai Hadas list_for_each_entry_safe(sub_entry, tmp, &obj->event_sub, obj_list) 142275973853SYishai Hadas devx_cleanup_subscription(dev, sub_entry); 142375973853SYishai Hadas mutex_unlock(&devx_event_table->event_xa_lock); 142475973853SYishai Hadas 14257efce369SYishai Hadas kfree(obj); 14267efce369SYishai Hadas return ret; 14277efce369SYishai Hadas } 14287efce369SYishai Hadas 1429ef1659adSYishai Hadas static void devx_cq_comp(struct mlx5_core_cq *mcq, struct mlx5_eqe *eqe) 1430ef1659adSYishai Hadas { 1431ef1659adSYishai Hadas struct devx_obj *obj = container_of(mcq, struct devx_obj, core_cq); 1432ef1659adSYishai Hadas struct mlx5_devx_event_table *table; 1433ef1659adSYishai Hadas struct devx_event *event; 1434ef1659adSYishai Hadas struct devx_obj_event *obj_event; 1435ef1659adSYishai Hadas u32 obj_id = mcq->cqn; 1436ef1659adSYishai Hadas 1437ef1659adSYishai Hadas table = &obj->ib_dev->devx_event_table; 1438ef1659adSYishai Hadas rcu_read_lock(); 1439ef1659adSYishai Hadas event = xa_load(&table->event_xa, MLX5_EVENT_TYPE_COMP); 1440ef1659adSYishai Hadas if (!event) 1441ef1659adSYishai Hadas goto out; 1442ef1659adSYishai Hadas 1443ef1659adSYishai Hadas obj_event = xa_load(&event->object_ids, obj_id); 1444ef1659adSYishai Hadas if (!obj_event) 1445ef1659adSYishai Hadas goto out; 1446ef1659adSYishai Hadas 1447ef1659adSYishai Hadas dispatch_event_fd(&obj_event->obj_sub_list, eqe); 1448ef1659adSYishai Hadas out: 1449ef1659adSYishai Hadas rcu_read_unlock(); 1450ef1659adSYishai Hadas } 1451ef1659adSYishai Hadas 1452616d5769STal Gilboa static bool is_apu_cq(struct mlx5_ib_dev *dev, const void *in) 14537232c132STal Gilboa { 14547232c132STal Gilboa if (!MLX5_CAP_GEN(dev->mdev, apu) || 1455616d5769STal Gilboa !MLX5_GET(cqc, MLX5_ADDR_OF(create_cq_in, in, cq_context), apu_cq)) 14567232c132STal Gilboa return false; 14577232c132STal Gilboa 14587232c132STal Gilboa return true; 14597232c132STal Gilboa } 14607232c132STal Gilboa 1461e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)( 146215a1b4beSJason Gunthorpe struct uverbs_attr_bundle *attrs) 14637efce369SYishai Hadas { 14647efce369SYishai Hadas void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN); 14657efce369SYishai Hadas int cmd_out_len = uverbs_attr_get_len(attrs, 14667efce369SYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT); 1467fa31f143SYishai Hadas int cmd_in_len = uverbs_attr_get_len(attrs, 1468fa31f143SYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN); 14697efce369SYishai Hadas void *cmd_out; 1470c36ee46dSJason Gunthorpe struct ib_uobject *uobj = uverbs_attr_get_uobject( 1471c36ee46dSJason Gunthorpe attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE); 147289944450SShamir Rabinovitch struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context( 147389944450SShamir Rabinovitch &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext); 1474c36ee46dSJason Gunthorpe struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device); 1475e8ef090aSYishai Hadas u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)]; 14767efce369SYishai Hadas struct devx_obj *obj; 1477cd5d20f1SYishai Hadas u16 obj_type = 0; 1478c76a1e90SSaeed Mahameed int err, err2 = 0; 14797e1335a7SYishai Hadas int uid; 14802351776eSYishai Hadas u32 obj_id; 14812351776eSYishai Hadas u16 opcode; 14827efce369SYishai Hadas 1483b6142608SMax Gurtovoy if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id)) 1484b6142608SMax Gurtovoy return -EINVAL; 1485b6142608SMax Gurtovoy 14867e1335a7SYishai Hadas uid = devx_get_uid(c, cmd_in); 14877e1335a7SYishai Hadas if (uid < 0) 14887e1335a7SYishai Hadas return uid; 14897efce369SYishai Hadas 14902351776eSYishai Hadas if (!devx_is_obj_create_cmd(cmd_in, &opcode)) 14917efce369SYishai Hadas return -EINVAL; 14927efce369SYishai Hadas 1493b61815e2SJason Gunthorpe cmd_out = uverbs_zalloc(attrs, cmd_out_len); 1494b61815e2SJason Gunthorpe if (IS_ERR(cmd_out)) 1495b61815e2SJason Gunthorpe return PTR_ERR(cmd_out); 1496b61815e2SJason Gunthorpe 14977efce369SYishai Hadas obj = kzalloc(sizeof(struct devx_obj), GFP_KERNEL); 14987efce369SYishai Hadas if (!obj) 14997efce369SYishai Hadas return -ENOMEM; 15007efce369SYishai Hadas 15017e1335a7SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); 1502fa31f143SYishai Hadas if (opcode == MLX5_CMD_OP_CREATE_MKEY) { 1503fa31f143SYishai Hadas err = devx_handle_mkey_create(dev, obj, cmd_in, cmd_in_len); 1504fa31f143SYishai Hadas if (err) 1505fa31f143SYishai Hadas goto obj_free; 1506fa31f143SYishai Hadas } else { 1507ba1a057dSYishai Hadas devx_set_umem_valid(cmd_in); 1508fa31f143SYishai Hadas } 1509ba1a057dSYishai Hadas 1510c5ae1954SYishai Hadas if (opcode == MLX5_CMD_OP_CREATE_DCT) { 1511c5ae1954SYishai Hadas obj->flags |= DEVX_OBJ_FLAGS_DCT; 1512333fbaa0SLeon Romanovsky err = mlx5_core_create_dct(dev, &obj->core_dct, cmd_in, 1513333fbaa0SLeon Romanovsky cmd_in_len, cmd_out, cmd_out_len); 15147232c132STal Gilboa } else if (opcode == MLX5_CMD_OP_CREATE_CQ && 1515616d5769STal Gilboa !is_apu_cq(dev, cmd_in)) { 1516ef1659adSYishai Hadas obj->flags |= DEVX_OBJ_FLAGS_CQ; 1517ef1659adSYishai Hadas obj->core_cq.comp = devx_cq_comp; 151831803e59SSaeed Mahameed err = mlx5_create_cq(dev->mdev, &obj->core_cq, 1519ef1659adSYishai Hadas cmd_in, cmd_in_len, cmd_out, 1520ef1659adSYishai Hadas cmd_out_len); 1521c5ae1954SYishai Hadas } else { 1522c76a1e90SSaeed Mahameed err = mlx5_cmd_do(dev->mdev, cmd_in, cmd_in_len, 15237efce369SYishai Hadas cmd_out, cmd_out_len); 1524c5ae1954SYishai Hadas } 1525c5ae1954SYishai Hadas 1526c76a1e90SSaeed Mahameed if (err == -EREMOTEIO) 1527c76a1e90SSaeed Mahameed err2 = uverbs_copy_to(attrs, 1528c76a1e90SSaeed Mahameed MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT, 1529c76a1e90SSaeed Mahameed cmd_out, cmd_out_len); 15307efce369SYishai Hadas if (err) 1531b61815e2SJason Gunthorpe goto obj_free; 15327efce369SYishai Hadas 1533208d70f5SYevgeny Kliteynik if (opcode == MLX5_CMD_OP_ALLOC_FLOW_COUNTER) { 15343e358ea8SMark Bloch u32 bulk = MLX5_GET(alloc_flow_counter_in, 15353e358ea8SMark Bloch cmd_in, 15363e358ea8SMark Bloch flow_counter_bulk_log_size); 15373e358ea8SMark Bloch 15383e358ea8SMark Bloch if (bulk) 15393e358ea8SMark Bloch bulk = 1 << bulk; 15403e358ea8SMark Bloch else 15413e358ea8SMark Bloch bulk = 128UL * MLX5_GET(alloc_flow_counter_in, 1542208d70f5SYevgeny Kliteynik cmd_in, 1543208d70f5SYevgeny Kliteynik flow_counter_bulk); 15443e358ea8SMark Bloch obj->flow_counter_bulk_size = bulk; 1545208d70f5SYevgeny Kliteynik } 1546208d70f5SYevgeny Kliteynik 15477efce369SYishai Hadas uobj->object = obj; 154875973853SYishai Hadas INIT_LIST_HEAD(&obj->event_sub); 1549ef1659adSYishai Hadas obj->ib_dev = dev; 15502351776eSYishai Hadas devx_obj_build_destroy_cmd(cmd_in, cmd_out, obj->dinbox, &obj->dinlen, 15512351776eSYishai Hadas &obj_id); 15527efce369SYishai Hadas WARN_ON(obj->dinlen > MLX5_MAX_DESTROY_INBOX_SIZE_DW * sizeof(u32)); 15537efce369SYishai Hadas 155404177915SJason Gunthorpe err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT, cmd_out, cmd_out_len); 155504177915SJason Gunthorpe if (err) 155604177915SJason Gunthorpe goto obj_destroy; 155704177915SJason Gunthorpe 155804177915SJason Gunthorpe if (opcode == MLX5_CMD_OP_CREATE_GENERAL_OBJECT) 155904177915SJason Gunthorpe obj_type = MLX5_GET(general_obj_in_cmd_hdr, cmd_in, obj_type); 156004177915SJason Gunthorpe obj->obj_id = get_enc_obj_id(opcode | obj_type << 16, obj_id); 156104177915SJason Gunthorpe 1562534fd7aaSYishai Hadas if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY) { 1563534fd7aaSYishai Hadas err = devx_handle_mkey_indirect(obj, dev, cmd_in, cmd_out); 1564534fd7aaSYishai Hadas if (err) 1565534fd7aaSYishai Hadas goto obj_destroy; 1566534fd7aaSYishai Hadas } 15677efce369SYishai Hadas return 0; 15687efce369SYishai Hadas 15690da4d48dSYishai Hadas obj_destroy: 1570c5ae1954SYishai Hadas if (obj->flags & DEVX_OBJ_FLAGS_DCT) 1571333fbaa0SLeon Romanovsky mlx5_core_destroy_dct(obj->ib_dev, &obj->core_dct); 1572ef1659adSYishai Hadas else if (obj->flags & DEVX_OBJ_FLAGS_CQ) 15735832fdd3SYishai Hadas mlx5_core_destroy_cq(obj->ib_dev->mdev, &obj->core_cq); 1574c5ae1954SYishai Hadas else 15755832fdd3SYishai Hadas mlx5_cmd_exec(obj->ib_dev->mdev, obj->dinbox, obj->dinlen, out, 1576c5ae1954SYishai Hadas sizeof(out)); 15777efce369SYishai Hadas obj_free: 15787efce369SYishai Hadas kfree(obj); 1579c76a1e90SSaeed Mahameed return err2 ?: err; 15807efce369SYishai Hadas } 15817efce369SYishai Hadas 1582e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_MODIFY)( 158315a1b4beSJason Gunthorpe struct uverbs_attr_bundle *attrs) 1584e662e14dSYishai Hadas { 1585e662e14dSYishai Hadas void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN); 1586e662e14dSYishai Hadas int cmd_out_len = uverbs_attr_get_len(attrs, 1587e662e14dSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT); 1588e662e14dSYishai Hadas struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs, 1589e662e14dSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE); 159089944450SShamir Rabinovitch struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context( 159189944450SShamir Rabinovitch &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext); 159289944450SShamir Rabinovitch struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device); 1593e662e14dSYishai Hadas void *cmd_out; 1594c76a1e90SSaeed Mahameed int err, err2; 15957e1335a7SYishai Hadas int uid; 1596e662e14dSYishai Hadas 1597b6142608SMax Gurtovoy if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id)) 1598b6142608SMax Gurtovoy return -EINVAL; 1599b6142608SMax Gurtovoy 16007e1335a7SYishai Hadas uid = devx_get_uid(c, cmd_in); 16017e1335a7SYishai Hadas if (uid < 0) 16027e1335a7SYishai Hadas return uid; 1603e662e14dSYishai Hadas 1604e662e14dSYishai Hadas if (!devx_is_obj_modify_cmd(cmd_in)) 1605e662e14dSYishai Hadas return -EINVAL; 1606e662e14dSYishai Hadas 1607e79c9c60SJason Gunthorpe if (!devx_is_valid_obj_id(attrs, uobj, cmd_in)) 1608e662e14dSYishai Hadas return -EINVAL; 1609e662e14dSYishai Hadas 1610b61815e2SJason Gunthorpe cmd_out = uverbs_zalloc(attrs, cmd_out_len); 1611b61815e2SJason Gunthorpe if (IS_ERR(cmd_out)) 1612b61815e2SJason Gunthorpe return PTR_ERR(cmd_out); 1613e662e14dSYishai Hadas 16147e1335a7SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); 1615ba1a057dSYishai Hadas devx_set_umem_valid(cmd_in); 1616ba1a057dSYishai Hadas 1617c76a1e90SSaeed Mahameed err = mlx5_cmd_do(mdev->mdev, cmd_in, 1618e662e14dSYishai Hadas uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN), 1619e662e14dSYishai Hadas cmd_out, cmd_out_len); 1620c76a1e90SSaeed Mahameed if (err && err != -EREMOTEIO) 1621e662e14dSYishai Hadas return err; 1622b61815e2SJason Gunthorpe 1623c76a1e90SSaeed Mahameed err2 = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT, 1624b61815e2SJason Gunthorpe cmd_out, cmd_out_len); 1625c76a1e90SSaeed Mahameed 1626c76a1e90SSaeed Mahameed return err2 ?: err; 1627e662e14dSYishai Hadas } 1628e662e14dSYishai Hadas 1629e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)( 163015a1b4beSJason Gunthorpe struct uverbs_attr_bundle *attrs) 1631e662e14dSYishai Hadas { 1632e662e14dSYishai Hadas void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN); 1633e662e14dSYishai Hadas int cmd_out_len = uverbs_attr_get_len(attrs, 1634e662e14dSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT); 1635e662e14dSYishai Hadas struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs, 1636e662e14dSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE); 163789944450SShamir Rabinovitch struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context( 163889944450SShamir Rabinovitch &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext); 1639e662e14dSYishai Hadas void *cmd_out; 1640c76a1e90SSaeed Mahameed int err, err2; 16417e1335a7SYishai Hadas int uid; 164289944450SShamir Rabinovitch struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device); 1643e662e14dSYishai Hadas 1644b6142608SMax Gurtovoy if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id)) 1645b6142608SMax Gurtovoy return -EINVAL; 1646b6142608SMax Gurtovoy 16477e1335a7SYishai Hadas uid = devx_get_uid(c, cmd_in); 16487e1335a7SYishai Hadas if (uid < 0) 16497e1335a7SYishai Hadas return uid; 1650e662e14dSYishai Hadas 1651e662e14dSYishai Hadas if (!devx_is_obj_query_cmd(cmd_in)) 1652e662e14dSYishai Hadas return -EINVAL; 1653e662e14dSYishai Hadas 1654e79c9c60SJason Gunthorpe if (!devx_is_valid_obj_id(attrs, uobj, cmd_in)) 1655e662e14dSYishai Hadas return -EINVAL; 1656e662e14dSYishai Hadas 1657b61815e2SJason Gunthorpe cmd_out = uverbs_zalloc(attrs, cmd_out_len); 1658b61815e2SJason Gunthorpe if (IS_ERR(cmd_out)) 1659b61815e2SJason Gunthorpe return PTR_ERR(cmd_out); 1660e662e14dSYishai Hadas 16617e1335a7SYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); 1662c76a1e90SSaeed Mahameed err = mlx5_cmd_do(mdev->mdev, cmd_in, 1663e662e14dSYishai Hadas uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN), 1664e662e14dSYishai Hadas cmd_out, cmd_out_len); 1665c76a1e90SSaeed Mahameed if (err && err != -EREMOTEIO) 1666e662e14dSYishai Hadas return err; 1667b61815e2SJason Gunthorpe 1668c76a1e90SSaeed Mahameed err2 = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT, 1669b61815e2SJason Gunthorpe cmd_out, cmd_out_len); 1670c76a1e90SSaeed Mahameed 1671c76a1e90SSaeed Mahameed return err2 ?: err; 1672e662e14dSYishai Hadas } 1673e662e14dSYishai Hadas 16746bf8f22aSYishai Hadas struct devx_async_event_queue { 16756bf8f22aSYishai Hadas spinlock_t lock; 16766bf8f22aSYishai Hadas wait_queue_head_t poll_wait; 16776bf8f22aSYishai Hadas struct list_head event_list; 1678a124edbaSYishai Hadas atomic_t bytes_in_use; 1679eaebaf77SYishai Hadas u8 is_destroyed:1; 16806bf8f22aSYishai Hadas }; 16816bf8f22aSYishai Hadas 16826bf8f22aSYishai Hadas struct devx_async_cmd_event_file { 16836bf8f22aSYishai Hadas struct ib_uobject uobj; 16846bf8f22aSYishai Hadas struct devx_async_event_queue ev_queue; 1685a124edbaSYishai Hadas struct mlx5_async_ctx async_ctx; 16866bf8f22aSYishai Hadas }; 16876bf8f22aSYishai Hadas 16886bf8f22aSYishai Hadas static void devx_init_event_queue(struct devx_async_event_queue *ev_queue) 16896bf8f22aSYishai Hadas { 16906bf8f22aSYishai Hadas spin_lock_init(&ev_queue->lock); 16916bf8f22aSYishai Hadas INIT_LIST_HEAD(&ev_queue->event_list); 16926bf8f22aSYishai Hadas init_waitqueue_head(&ev_queue->poll_wait); 1693a124edbaSYishai Hadas atomic_set(&ev_queue->bytes_in_use, 0); 1694eaebaf77SYishai Hadas ev_queue->is_destroyed = 0; 16956bf8f22aSYishai Hadas } 16966bf8f22aSYishai Hadas 16976bf8f22aSYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC)( 16986bf8f22aSYishai Hadas struct uverbs_attr_bundle *attrs) 16996bf8f22aSYishai Hadas { 17006bf8f22aSYishai Hadas struct devx_async_cmd_event_file *ev_file; 17016bf8f22aSYishai Hadas 17026bf8f22aSYishai Hadas struct ib_uobject *uobj = uverbs_attr_get_uobject( 17036bf8f22aSYishai Hadas attrs, MLX5_IB_ATTR_DEVX_ASYNC_CMD_FD_ALLOC_HANDLE); 1704e79c9c60SJason Gunthorpe struct mlx5_ib_dev *mdev = mlx5_udata_to_mdev(&attrs->driver_udata); 17056bf8f22aSYishai Hadas 17066bf8f22aSYishai Hadas ev_file = container_of(uobj, struct devx_async_cmd_event_file, 17076bf8f22aSYishai Hadas uobj); 17086bf8f22aSYishai Hadas devx_init_event_queue(&ev_file->ev_queue); 1709a124edbaSYishai Hadas mlx5_cmd_init_async_ctx(mdev->mdev, &ev_file->async_ctx); 17106bf8f22aSYishai Hadas return 0; 17116bf8f22aSYishai Hadas } 17126bf8f22aSYishai Hadas 17132afc5e1bSYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_ASYNC_EVENT_FD_ALLOC)( 17142afc5e1bSYishai Hadas struct uverbs_attr_bundle *attrs) 17152afc5e1bSYishai Hadas { 17162afc5e1bSYishai Hadas struct ib_uobject *uobj = uverbs_attr_get_uobject( 17172afc5e1bSYishai Hadas attrs, MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_HANDLE); 17182afc5e1bSYishai Hadas struct devx_async_event_file *ev_file; 17192afc5e1bSYishai Hadas struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context( 17202afc5e1bSYishai Hadas &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext); 17212afc5e1bSYishai Hadas struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device); 17222afc5e1bSYishai Hadas u32 flags; 17232afc5e1bSYishai Hadas int err; 17242afc5e1bSYishai Hadas 17252afc5e1bSYishai Hadas err = uverbs_get_flags32(&flags, attrs, 17262afc5e1bSYishai Hadas MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_FLAGS, 17272afc5e1bSYishai Hadas MLX5_IB_UAPI_DEVX_CR_EV_CH_FLAGS_OMIT_DATA); 17282afc5e1bSYishai Hadas 17292afc5e1bSYishai Hadas if (err) 17302afc5e1bSYishai Hadas return err; 17312afc5e1bSYishai Hadas 17322afc5e1bSYishai Hadas ev_file = container_of(uobj, struct devx_async_event_file, 17332afc5e1bSYishai Hadas uobj); 17342afc5e1bSYishai Hadas spin_lock_init(&ev_file->lock); 17352afc5e1bSYishai Hadas INIT_LIST_HEAD(&ev_file->event_list); 17362afc5e1bSYishai Hadas init_waitqueue_head(&ev_file->poll_wait); 17372afc5e1bSYishai Hadas if (flags & MLX5_IB_UAPI_DEVX_CR_EV_CH_FLAGS_OMIT_DATA) 17382afc5e1bSYishai Hadas ev_file->omit_data = 1; 17392afc5e1bSYishai Hadas INIT_LIST_HEAD(&ev_file->subscribed_events_list); 17402afc5e1bSYishai Hadas ev_file->dev = dev; 174175973853SYishai Hadas get_device(&dev->ib_dev.dev); 17422afc5e1bSYishai Hadas return 0; 17432afc5e1bSYishai Hadas } 17442afc5e1bSYishai Hadas 1745a124edbaSYishai Hadas static void devx_query_callback(int status, struct mlx5_async_work *context) 1746a124edbaSYishai Hadas { 1747a124edbaSYishai Hadas struct devx_async_data *async_data = 1748a124edbaSYishai Hadas container_of(context, struct devx_async_data, cb_work); 174993887e66SJason Gunthorpe struct devx_async_cmd_event_file *ev_file = async_data->ev_file; 175093887e66SJason Gunthorpe struct devx_async_event_queue *ev_queue = &ev_file->ev_queue; 1751a124edbaSYishai Hadas unsigned long flags; 1752a124edbaSYishai Hadas 175393887e66SJason Gunthorpe /* 175493887e66SJason Gunthorpe * Note that if the struct devx_async_cmd_event_file uobj begins to be 175593887e66SJason Gunthorpe * destroyed it will block at mlx5_cmd_cleanup_async_ctx() until this 175693887e66SJason Gunthorpe * routine returns, ensuring that it always remains valid here. 175793887e66SJason Gunthorpe */ 1758a124edbaSYishai Hadas spin_lock_irqsave(&ev_queue->lock, flags); 1759a124edbaSYishai Hadas list_add_tail(&async_data->list, &ev_queue->event_list); 1760a124edbaSYishai Hadas spin_unlock_irqrestore(&ev_queue->lock, flags); 1761a124edbaSYishai Hadas 1762a124edbaSYishai Hadas wake_up_interruptible(&ev_queue->poll_wait); 1763a124edbaSYishai Hadas } 1764a124edbaSYishai Hadas 1765a124edbaSYishai Hadas #define MAX_ASYNC_BYTES_IN_USE (1024 * 1024) /* 1MB */ 1766a124edbaSYishai Hadas 1767a124edbaSYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY)( 1768a124edbaSYishai Hadas struct uverbs_attr_bundle *attrs) 1769a124edbaSYishai Hadas { 1770a124edbaSYishai Hadas void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, 1771a124edbaSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_CMD_IN); 1772a124edbaSYishai Hadas struct ib_uobject *uobj = uverbs_attr_get_uobject( 1773a124edbaSYishai Hadas attrs, 1774a124edbaSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_HANDLE); 1775a124edbaSYishai Hadas u16 cmd_out_len; 177689944450SShamir Rabinovitch struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context( 177789944450SShamir Rabinovitch &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext); 1778a124edbaSYishai Hadas struct ib_uobject *fd_uobj; 1779a124edbaSYishai Hadas int err; 1780a124edbaSYishai Hadas int uid; 178189944450SShamir Rabinovitch struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device); 1782a124edbaSYishai Hadas struct devx_async_cmd_event_file *ev_file; 1783a124edbaSYishai Hadas struct devx_async_data *async_data; 1784a124edbaSYishai Hadas 1785b6142608SMax Gurtovoy if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id)) 1786b6142608SMax Gurtovoy return -EINVAL; 1787b6142608SMax Gurtovoy 1788a124edbaSYishai Hadas uid = devx_get_uid(c, cmd_in); 1789a124edbaSYishai Hadas if (uid < 0) 1790a124edbaSYishai Hadas return uid; 1791a124edbaSYishai Hadas 1792a124edbaSYishai Hadas if (!devx_is_obj_query_cmd(cmd_in)) 1793a124edbaSYishai Hadas return -EINVAL; 1794a124edbaSYishai Hadas 1795a124edbaSYishai Hadas err = uverbs_get_const(&cmd_out_len, attrs, 1796a124edbaSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_OUT_LEN); 1797a124edbaSYishai Hadas if (err) 1798a124edbaSYishai Hadas return err; 1799a124edbaSYishai Hadas 1800e79c9c60SJason Gunthorpe if (!devx_is_valid_obj_id(attrs, uobj, cmd_in)) 1801a124edbaSYishai Hadas return -EINVAL; 1802a124edbaSYishai Hadas 1803a124edbaSYishai Hadas fd_uobj = uverbs_attr_get_uobject(attrs, 1804a124edbaSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_FD); 1805a124edbaSYishai Hadas if (IS_ERR(fd_uobj)) 1806a124edbaSYishai Hadas return PTR_ERR(fd_uobj); 1807a124edbaSYishai Hadas 1808a124edbaSYishai Hadas ev_file = container_of(fd_uobj, struct devx_async_cmd_event_file, 1809a124edbaSYishai Hadas uobj); 1810a124edbaSYishai Hadas 1811a124edbaSYishai Hadas if (atomic_add_return(cmd_out_len, &ev_file->ev_queue.bytes_in_use) > 1812a124edbaSYishai Hadas MAX_ASYNC_BYTES_IN_USE) { 1813a124edbaSYishai Hadas atomic_sub(cmd_out_len, &ev_file->ev_queue.bytes_in_use); 1814a124edbaSYishai Hadas return -EAGAIN; 1815a124edbaSYishai Hadas } 1816a124edbaSYishai Hadas 1817a124edbaSYishai Hadas async_data = kvzalloc(struct_size(async_data, hdr.out_data, 1818a124edbaSYishai Hadas cmd_out_len), GFP_KERNEL); 1819a124edbaSYishai Hadas if (!async_data) { 1820a124edbaSYishai Hadas err = -ENOMEM; 1821a124edbaSYishai Hadas goto sub_bytes; 1822a124edbaSYishai Hadas } 1823a124edbaSYishai Hadas 1824a124edbaSYishai Hadas err = uverbs_copy_from(&async_data->hdr.wr_id, attrs, 1825a124edbaSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_WR_ID); 1826a124edbaSYishai Hadas if (err) 1827a124edbaSYishai Hadas goto free_async; 1828a124edbaSYishai Hadas 1829a124edbaSYishai Hadas async_data->cmd_out_len = cmd_out_len; 1830a124edbaSYishai Hadas async_data->mdev = mdev; 183193887e66SJason Gunthorpe async_data->ev_file = ev_file; 1832a124edbaSYishai Hadas 1833a124edbaSYishai Hadas MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); 1834a124edbaSYishai Hadas err = mlx5_cmd_exec_cb(&ev_file->async_ctx, cmd_in, 1835a124edbaSYishai Hadas uverbs_attr_get_len(attrs, 1836a124edbaSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_CMD_IN), 1837a124edbaSYishai Hadas async_data->hdr.out_data, 1838a124edbaSYishai Hadas async_data->cmd_out_len, 1839a124edbaSYishai Hadas devx_query_callback, &async_data->cb_work); 1840a124edbaSYishai Hadas 1841a124edbaSYishai Hadas if (err) 184293887e66SJason Gunthorpe goto free_async; 1843a124edbaSYishai Hadas 1844a124edbaSYishai Hadas return 0; 1845a124edbaSYishai Hadas 1846a124edbaSYishai Hadas free_async: 1847a124edbaSYishai Hadas kvfree(async_data); 1848a124edbaSYishai Hadas sub_bytes: 1849a124edbaSYishai Hadas atomic_sub(cmd_out_len, &ev_file->ev_queue.bytes_in_use); 1850a124edbaSYishai Hadas return err; 1851a124edbaSYishai Hadas } 1852a124edbaSYishai Hadas 185375973853SYishai Hadas static void 185475973853SYishai Hadas subscribe_event_xa_dealloc(struct mlx5_devx_event_table *devx_event_table, 185575973853SYishai Hadas u32 key_level1, 185675973853SYishai Hadas bool is_level2, 185775973853SYishai Hadas u32 key_level2) 185875973853SYishai Hadas { 185975973853SYishai Hadas struct devx_event *event; 186075973853SYishai Hadas struct devx_obj_event *xa_val_level2; 186175973853SYishai Hadas 186275973853SYishai Hadas /* Level 1 is valid for future use, no need to free */ 186375973853SYishai Hadas if (!is_level2) 186475973853SYishai Hadas return; 186575973853SYishai Hadas 186675973853SYishai Hadas event = xa_load(&devx_event_table->event_xa, key_level1); 186775973853SYishai Hadas WARN_ON(!event); 186875973853SYishai Hadas 186975973853SYishai Hadas xa_val_level2 = xa_load(&event->object_ids, 187075973853SYishai Hadas key_level2); 187175973853SYishai Hadas if (list_empty(&xa_val_level2->obj_sub_list)) { 187275973853SYishai Hadas xa_erase(&event->object_ids, 187375973853SYishai Hadas key_level2); 187475973853SYishai Hadas kfree_rcu(xa_val_level2, rcu); 187575973853SYishai Hadas } 187675973853SYishai Hadas } 187775973853SYishai Hadas 187875973853SYishai Hadas static int 187975973853SYishai Hadas subscribe_event_xa_alloc(struct mlx5_devx_event_table *devx_event_table, 188075973853SYishai Hadas u32 key_level1, 188175973853SYishai Hadas bool is_level2, 188275973853SYishai Hadas u32 key_level2) 188375973853SYishai Hadas { 188475973853SYishai Hadas struct devx_obj_event *obj_event; 188575973853SYishai Hadas struct devx_event *event; 188675973853SYishai Hadas int err; 188775973853SYishai Hadas 188875973853SYishai Hadas event = xa_load(&devx_event_table->event_xa, key_level1); 188975973853SYishai Hadas if (!event) { 189075973853SYishai Hadas event = kzalloc(sizeof(*event), GFP_KERNEL); 189175973853SYishai Hadas if (!event) 189275973853SYishai Hadas return -ENOMEM; 189375973853SYishai Hadas 189475973853SYishai Hadas INIT_LIST_HEAD(&event->unaffiliated_list); 189575973853SYishai Hadas xa_init(&event->object_ids); 189675973853SYishai Hadas 189775973853SYishai Hadas err = xa_insert(&devx_event_table->event_xa, 189875973853SYishai Hadas key_level1, 189975973853SYishai Hadas event, 190075973853SYishai Hadas GFP_KERNEL); 190175973853SYishai Hadas if (err) { 190275973853SYishai Hadas kfree(event); 190375973853SYishai Hadas return err; 190475973853SYishai Hadas } 190575973853SYishai Hadas } 190675973853SYishai Hadas 190775973853SYishai Hadas if (!is_level2) 190875973853SYishai Hadas return 0; 190975973853SYishai Hadas 191075973853SYishai Hadas obj_event = xa_load(&event->object_ids, key_level2); 191175973853SYishai Hadas if (!obj_event) { 191275973853SYishai Hadas obj_event = kzalloc(sizeof(*obj_event), GFP_KERNEL); 191375973853SYishai Hadas if (!obj_event) 191475973853SYishai Hadas /* Level1 is valid for future use, no need to free */ 191575973853SYishai Hadas return -ENOMEM; 191675973853SYishai Hadas 191775973853SYishai Hadas err = xa_insert(&event->object_ids, 191875973853SYishai Hadas key_level2, 191975973853SYishai Hadas obj_event, 192075973853SYishai Hadas GFP_KERNEL); 1921087f9c3fSYongzhi Liu if (err) { 1922087f9c3fSYongzhi Liu kfree(obj_event); 192375973853SYishai Hadas return err; 1924087f9c3fSYongzhi Liu } 192575973853SYishai Hadas INIT_LIST_HEAD(&obj_event->obj_sub_list); 192675973853SYishai Hadas } 192775973853SYishai Hadas 192875973853SYishai Hadas return 0; 192975973853SYishai Hadas } 193075973853SYishai Hadas 193175973853SYishai Hadas static bool is_valid_events_legacy(int num_events, u16 *event_type_num_list, 193275973853SYishai Hadas struct devx_obj *obj) 193375973853SYishai Hadas { 193475973853SYishai Hadas int i; 193575973853SYishai Hadas 193675973853SYishai Hadas for (i = 0; i < num_events; i++) { 193775973853SYishai Hadas if (obj) { 193875973853SYishai Hadas if (!is_legacy_obj_event_num(event_type_num_list[i])) 193975973853SYishai Hadas return false; 194075973853SYishai Hadas } else if (!is_legacy_unaffiliated_event_num( 194175973853SYishai Hadas event_type_num_list[i])) { 194275973853SYishai Hadas return false; 194375973853SYishai Hadas } 194475973853SYishai Hadas } 194575973853SYishai Hadas 194675973853SYishai Hadas return true; 194775973853SYishai Hadas } 194875973853SYishai Hadas 194975973853SYishai Hadas #define MAX_SUPP_EVENT_NUM 255 195075973853SYishai Hadas static bool is_valid_events(struct mlx5_core_dev *dev, 195175973853SYishai Hadas int num_events, u16 *event_type_num_list, 195275973853SYishai Hadas struct devx_obj *obj) 195375973853SYishai Hadas { 195475973853SYishai Hadas __be64 *aff_events; 195575973853SYishai Hadas __be64 *unaff_events; 195675973853SYishai Hadas int mask_entry; 195775973853SYishai Hadas int mask_bit; 195875973853SYishai Hadas int i; 195975973853SYishai Hadas 196075973853SYishai Hadas if (MLX5_CAP_GEN(dev, event_cap)) { 196175973853SYishai Hadas aff_events = MLX5_CAP_DEV_EVENT(dev, 196275973853SYishai Hadas user_affiliated_events); 196375973853SYishai Hadas unaff_events = MLX5_CAP_DEV_EVENT(dev, 196475973853SYishai Hadas user_unaffiliated_events); 196575973853SYishai Hadas } else { 196675973853SYishai Hadas return is_valid_events_legacy(num_events, event_type_num_list, 196775973853SYishai Hadas obj); 196875973853SYishai Hadas } 196975973853SYishai Hadas 197075973853SYishai Hadas for (i = 0; i < num_events; i++) { 197175973853SYishai Hadas if (event_type_num_list[i] > MAX_SUPP_EVENT_NUM) 197275973853SYishai Hadas return false; 197375973853SYishai Hadas 197475973853SYishai Hadas mask_entry = event_type_num_list[i] / 64; 197575973853SYishai Hadas mask_bit = event_type_num_list[i] % 64; 197675973853SYishai Hadas 197775973853SYishai Hadas if (obj) { 197875973853SYishai Hadas /* CQ completion */ 197975973853SYishai Hadas if (event_type_num_list[i] == 0) 198075973853SYishai Hadas continue; 198175973853SYishai Hadas 198275973853SYishai Hadas if (!(be64_to_cpu(aff_events[mask_entry]) & 198375973853SYishai Hadas (1ull << mask_bit))) 198475973853SYishai Hadas return false; 198575973853SYishai Hadas 198675973853SYishai Hadas continue; 198775973853SYishai Hadas } 198875973853SYishai Hadas 198975973853SYishai Hadas if (!(be64_to_cpu(unaff_events[mask_entry]) & 199075973853SYishai Hadas (1ull << mask_bit))) 199175973853SYishai Hadas return false; 199275973853SYishai Hadas } 199375973853SYishai Hadas 199475973853SYishai Hadas return true; 199575973853SYishai Hadas } 199675973853SYishai Hadas 199775973853SYishai Hadas #define MAX_NUM_EVENTS 16 199875973853SYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT)( 199975973853SYishai Hadas struct uverbs_attr_bundle *attrs) 200075973853SYishai Hadas { 200175973853SYishai Hadas struct ib_uobject *devx_uobj = uverbs_attr_get_uobject( 200275973853SYishai Hadas attrs, 200375973853SYishai Hadas MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_OBJ_HANDLE); 200475973853SYishai Hadas struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context( 200575973853SYishai Hadas &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext); 200675973853SYishai Hadas struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device); 200775973853SYishai Hadas struct ib_uobject *fd_uobj; 200875973853SYishai Hadas struct devx_obj *obj = NULL; 200975973853SYishai Hadas struct devx_async_event_file *ev_file; 201075973853SYishai Hadas struct mlx5_devx_event_table *devx_event_table = &dev->devx_event_table; 201175973853SYishai Hadas u16 *event_type_num_list; 201275973853SYishai Hadas struct devx_event_subscription *event_sub, *tmp_sub; 201375973853SYishai Hadas struct list_head sub_list; 201475973853SYishai Hadas int redirect_fd; 201575973853SYishai Hadas bool use_eventfd = false; 201675973853SYishai Hadas int num_events; 201775973853SYishai Hadas u16 obj_type = 0; 201875973853SYishai Hadas u64 cookie = 0; 201975973853SYishai Hadas u32 obj_id = 0; 202075973853SYishai Hadas int err; 202175973853SYishai Hadas int i; 202275973853SYishai Hadas 202375973853SYishai Hadas if (!c->devx_uid) 202475973853SYishai Hadas return -EINVAL; 202575973853SYishai Hadas 202675973853SYishai Hadas if (!IS_ERR(devx_uobj)) { 202775973853SYishai Hadas obj = (struct devx_obj *)devx_uobj->object; 202875973853SYishai Hadas if (obj) 202975973853SYishai Hadas obj_id = get_dec_obj_id(obj->obj_id); 203075973853SYishai Hadas } 203175973853SYishai Hadas 203275973853SYishai Hadas fd_uobj = uverbs_attr_get_uobject(attrs, 203375973853SYishai Hadas MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_HANDLE); 203475973853SYishai Hadas if (IS_ERR(fd_uobj)) 203575973853SYishai Hadas return PTR_ERR(fd_uobj); 203675973853SYishai Hadas 203775973853SYishai Hadas ev_file = container_of(fd_uobj, struct devx_async_event_file, 203875973853SYishai Hadas uobj); 203975973853SYishai Hadas 204075973853SYishai Hadas if (uverbs_attr_is_valid(attrs, 204175973853SYishai Hadas MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_NUM)) { 204275973853SYishai Hadas err = uverbs_copy_from(&redirect_fd, attrs, 204375973853SYishai Hadas MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_NUM); 204475973853SYishai Hadas if (err) 204575973853SYishai Hadas return err; 204675973853SYishai Hadas 204775973853SYishai Hadas use_eventfd = true; 204875973853SYishai Hadas } 204975973853SYishai Hadas 205075973853SYishai Hadas if (uverbs_attr_is_valid(attrs, 205175973853SYishai Hadas MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_COOKIE)) { 205275973853SYishai Hadas if (use_eventfd) 205375973853SYishai Hadas return -EINVAL; 205475973853SYishai Hadas 205575973853SYishai Hadas err = uverbs_copy_from(&cookie, attrs, 205675973853SYishai Hadas MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_COOKIE); 205775973853SYishai Hadas if (err) 205875973853SYishai Hadas return err; 205975973853SYishai Hadas } 206075973853SYishai Hadas 206175973853SYishai Hadas num_events = uverbs_attr_ptr_get_array_size( 206275973853SYishai Hadas attrs, MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_TYPE_NUM_LIST, 206375973853SYishai Hadas sizeof(u16)); 206475973853SYishai Hadas 206575973853SYishai Hadas if (num_events < 0) 206675973853SYishai Hadas return num_events; 206775973853SYishai Hadas 206875973853SYishai Hadas if (num_events > MAX_NUM_EVENTS) 206975973853SYishai Hadas return -EINVAL; 207075973853SYishai Hadas 207175973853SYishai Hadas event_type_num_list = uverbs_attr_get_alloced_ptr(attrs, 207275973853SYishai Hadas MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_TYPE_NUM_LIST); 207375973853SYishai Hadas 207475973853SYishai Hadas if (!is_valid_events(dev->mdev, num_events, event_type_num_list, obj)) 207575973853SYishai Hadas return -EINVAL; 207675973853SYishai Hadas 207775973853SYishai Hadas INIT_LIST_HEAD(&sub_list); 207875973853SYishai Hadas 207975973853SYishai Hadas /* Protect from concurrent subscriptions to same XA entries to allow 208075973853SYishai Hadas * both to succeed 208175973853SYishai Hadas */ 208275973853SYishai Hadas mutex_lock(&devx_event_table->event_xa_lock); 208375973853SYishai Hadas for (i = 0; i < num_events; i++) { 208475973853SYishai Hadas u32 key_level1; 208575973853SYishai Hadas 208675973853SYishai Hadas if (obj) 208775973853SYishai Hadas obj_type = get_dec_obj_type(obj, 208875973853SYishai Hadas event_type_num_list[i]); 208975973853SYishai Hadas key_level1 = event_type_num_list[i] | obj_type << 16; 209075973853SYishai Hadas 209175973853SYishai Hadas err = subscribe_event_xa_alloc(devx_event_table, 209275973853SYishai Hadas key_level1, 209375973853SYishai Hadas obj, 209475973853SYishai Hadas obj_id); 209575973853SYishai Hadas if (err) 209675973853SYishai Hadas goto err; 209775973853SYishai Hadas 209875973853SYishai Hadas event_sub = kzalloc(sizeof(*event_sub), GFP_KERNEL); 20993a9b3d45SYueHaibing if (!event_sub) { 21003a9b3d45SYueHaibing err = -ENOMEM; 210175973853SYishai Hadas goto err; 21023a9b3d45SYueHaibing } 210375973853SYishai Hadas 210475973853SYishai Hadas list_add_tail(&event_sub->event_list, &sub_list); 21056898d1c6SJason Gunthorpe uverbs_uobject_get(&ev_file->uobj); 210675973853SYishai Hadas if (use_eventfd) { 210775973853SYishai Hadas event_sub->eventfd = 210875973853SYishai Hadas eventfd_ctx_fdget(redirect_fd); 210975973853SYishai Hadas 2110e7e6c632SDan Carpenter if (IS_ERR(event_sub->eventfd)) { 211175973853SYishai Hadas err = PTR_ERR(event_sub->eventfd); 211275973853SYishai Hadas event_sub->eventfd = NULL; 211375973853SYishai Hadas goto err; 211475973853SYishai Hadas } 211575973853SYishai Hadas } 211675973853SYishai Hadas 211775973853SYishai Hadas event_sub->cookie = cookie; 211875973853SYishai Hadas event_sub->ev_file = ev_file; 211975973853SYishai Hadas /* May be needed upon cleanup the devx object/subscription */ 212075973853SYishai Hadas event_sub->xa_key_level1 = key_level1; 212175973853SYishai Hadas event_sub->xa_key_level2 = obj_id; 212275973853SYishai Hadas INIT_LIST_HEAD(&event_sub->obj_list); 212375973853SYishai Hadas } 212475973853SYishai Hadas 212575973853SYishai Hadas /* Once all the allocations and the XA data insertions were done we 212675973853SYishai Hadas * can go ahead and add all the subscriptions to the relevant lists 212775973853SYishai Hadas * without concern of a failure. 212875973853SYishai Hadas */ 212975973853SYishai Hadas list_for_each_entry_safe(event_sub, tmp_sub, &sub_list, event_list) { 213075973853SYishai Hadas struct devx_event *event; 213175973853SYishai Hadas struct devx_obj_event *obj_event; 213275973853SYishai Hadas 213375973853SYishai Hadas list_del_init(&event_sub->event_list); 213475973853SYishai Hadas 213575973853SYishai Hadas spin_lock_irq(&ev_file->lock); 213675973853SYishai Hadas list_add_tail_rcu(&event_sub->file_list, 213775973853SYishai Hadas &ev_file->subscribed_events_list); 213875973853SYishai Hadas spin_unlock_irq(&ev_file->lock); 213975973853SYishai Hadas 214075973853SYishai Hadas event = xa_load(&devx_event_table->event_xa, 214175973853SYishai Hadas event_sub->xa_key_level1); 214275973853SYishai Hadas WARN_ON(!event); 214375973853SYishai Hadas 214475973853SYishai Hadas if (!obj) { 214575973853SYishai Hadas list_add_tail_rcu(&event_sub->xa_list, 214675973853SYishai Hadas &event->unaffiliated_list); 214775973853SYishai Hadas continue; 214875973853SYishai Hadas } 214975973853SYishai Hadas 215075973853SYishai Hadas obj_event = xa_load(&event->object_ids, obj_id); 215175973853SYishai Hadas WARN_ON(!obj_event); 215275973853SYishai Hadas list_add_tail_rcu(&event_sub->xa_list, 215375973853SYishai Hadas &obj_event->obj_sub_list); 215475973853SYishai Hadas list_add_tail_rcu(&event_sub->obj_list, 215575973853SYishai Hadas &obj->event_sub); 215675973853SYishai Hadas } 215775973853SYishai Hadas 215875973853SYishai Hadas mutex_unlock(&devx_event_table->event_xa_lock); 215975973853SYishai Hadas return 0; 216075973853SYishai Hadas 216175973853SYishai Hadas err: 216275973853SYishai Hadas list_for_each_entry_safe(event_sub, tmp_sub, &sub_list, event_list) { 216375973853SYishai Hadas list_del(&event_sub->event_list); 216475973853SYishai Hadas 216575973853SYishai Hadas subscribe_event_xa_dealloc(devx_event_table, 216675973853SYishai Hadas event_sub->xa_key_level1, 216775973853SYishai Hadas obj, 216875973853SYishai Hadas obj_id); 216975973853SYishai Hadas 217075973853SYishai Hadas if (event_sub->eventfd) 217175973853SYishai Hadas eventfd_ctx_put(event_sub->eventfd); 21726898d1c6SJason Gunthorpe uverbs_uobject_put(&event_sub->ev_file->uobj); 217375973853SYishai Hadas kfree(event_sub); 217475973853SYishai Hadas } 217575973853SYishai Hadas 217675973853SYishai Hadas mutex_unlock(&devx_event_table->event_xa_lock); 217775973853SYishai Hadas return err; 217875973853SYishai Hadas } 217975973853SYishai Hadas 2180aeae9457SYishai Hadas static int devx_umem_get(struct mlx5_ib_dev *dev, struct ib_ucontext *ucontext, 2181aeae9457SYishai Hadas struct uverbs_attr_bundle *attrs, 218272b2f760SJason Gunthorpe struct devx_umem *obj, u32 access_flags) 2183aeae9457SYishai Hadas { 2184aeae9457SYishai Hadas u64 addr; 2185aeae9457SYishai Hadas size_t size; 2186aeae9457SYishai Hadas int err; 2187aeae9457SYishai Hadas 2188aeae9457SYishai Hadas if (uverbs_copy_from(&addr, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR) || 2189bccd0622SJason Gunthorpe uverbs_copy_from(&size, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_LEN)) 2190aeae9457SYishai Hadas return -EFAULT; 2191aeae9457SYishai Hadas 219272b2f760SJason Gunthorpe err = ib_check_mr_access(&dev->ib_dev, access_flags); 2193aeae9457SYishai Hadas if (err) 2194aeae9457SYishai Hadas return err; 2195aeae9457SYishai Hadas 21969af859c5SJason Gunthorpe if (uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_DMABUF_FD)) { 21979af859c5SJason Gunthorpe struct ib_umem_dmabuf *umem_dmabuf; 21989af859c5SJason Gunthorpe int dmabuf_fd; 21999af859c5SJason Gunthorpe 22009af859c5SJason Gunthorpe err = uverbs_get_raw_fd(&dmabuf_fd, attrs, 22019af859c5SJason Gunthorpe MLX5_IB_ATTR_DEVX_UMEM_REG_DMABUF_FD); 22029af859c5SJason Gunthorpe if (err) 22039af859c5SJason Gunthorpe return -EFAULT; 22049af859c5SJason Gunthorpe 22059af859c5SJason Gunthorpe umem_dmabuf = ib_umem_dmabuf_get_pinned( 220672b2f760SJason Gunthorpe &dev->ib_dev, addr, size, dmabuf_fd, access_flags); 22079af859c5SJason Gunthorpe if (IS_ERR(umem_dmabuf)) 22089af859c5SJason Gunthorpe return PTR_ERR(umem_dmabuf); 22099af859c5SJason Gunthorpe obj->umem = &umem_dmabuf->umem; 22109af859c5SJason Gunthorpe } else { 221172b2f760SJason Gunthorpe obj->umem = ib_umem_get(&dev->ib_dev, addr, size, access_flags); 2212aeae9457SYishai Hadas if (IS_ERR(obj->umem)) 2213aeae9457SYishai Hadas return PTR_ERR(obj->umem); 22149af859c5SJason Gunthorpe } 2215aeae9457SYishai Hadas return 0; 2216aeae9457SYishai Hadas } 2217aeae9457SYishai Hadas 22187610ab57SJason Gunthorpe static unsigned int devx_umem_find_best_pgsize(struct ib_umem *umem, 22197610ab57SJason Gunthorpe unsigned long pgsz_bitmap) 22207610ab57SJason Gunthorpe { 22217610ab57SJason Gunthorpe unsigned long page_size; 22227610ab57SJason Gunthorpe 22237610ab57SJason Gunthorpe /* Don't bother checking larger page sizes as offset must be zero and 22247610ab57SJason Gunthorpe * total DEVX umem length must be equal to total umem length. 22257610ab57SJason Gunthorpe */ 22267610ab57SJason Gunthorpe pgsz_bitmap &= GENMASK_ULL(max_t(u64, order_base_2(umem->length), 22277610ab57SJason Gunthorpe PAGE_SHIFT), 22287610ab57SJason Gunthorpe MLX5_ADAPTER_PAGE_SHIFT); 22297610ab57SJason Gunthorpe if (!pgsz_bitmap) 22307610ab57SJason Gunthorpe return 0; 22317610ab57SJason Gunthorpe 22327610ab57SJason Gunthorpe page_size = ib_umem_find_best_pgoff(umem, pgsz_bitmap, U64_MAX); 22337610ab57SJason Gunthorpe if (!page_size) 22347610ab57SJason Gunthorpe return 0; 22357610ab57SJason Gunthorpe 22367610ab57SJason Gunthorpe /* If the page_size is less than the CPU page size then we can use the 22377610ab57SJason Gunthorpe * offset and create a umem which is a subset of the page list. 22387610ab57SJason Gunthorpe * For larger page sizes we can't be sure the DMA list reflects the 22397610ab57SJason Gunthorpe * VA so we must ensure that the umem extent is exactly equal to the 22407610ab57SJason Gunthorpe * page list. Reduce the page size until one of these cases is true. 22417610ab57SJason Gunthorpe */ 22427610ab57SJason Gunthorpe while ((ib_umem_dma_offset(umem, page_size) != 0 || 22437610ab57SJason Gunthorpe (umem->length % page_size) != 0) && 22447610ab57SJason Gunthorpe page_size > PAGE_SIZE) 22457610ab57SJason Gunthorpe page_size /= 2; 22467610ab57SJason Gunthorpe 22477610ab57SJason Gunthorpe return page_size; 22487610ab57SJason Gunthorpe } 22497610ab57SJason Gunthorpe 2250878f7b31SJason Gunthorpe static int devx_umem_reg_cmd_alloc(struct mlx5_ib_dev *dev, 2251878f7b31SJason Gunthorpe struct uverbs_attr_bundle *attrs, 2252b61815e2SJason Gunthorpe struct devx_umem *obj, 225372b2f760SJason Gunthorpe struct devx_umem_reg_cmd *cmd, 225472b2f760SJason Gunthorpe int access) 2255aeae9457SYishai Hadas { 22567610ab57SJason Gunthorpe unsigned long pgsz_bitmap; 2257878f7b31SJason Gunthorpe unsigned int page_size; 2258aeae9457SYishai Hadas __be64 *mtt; 2259878f7b31SJason Gunthorpe void *umem; 22607610ab57SJason Gunthorpe int ret; 2261878f7b31SJason Gunthorpe 2262878f7b31SJason Gunthorpe /* 22637610ab57SJason Gunthorpe * If the user does not pass in pgsz_bitmap then the user promises not 22647610ab57SJason Gunthorpe * to use umem_offset!=0 in any commands that allocate on top of the 22657610ab57SJason Gunthorpe * umem. 22667610ab57SJason Gunthorpe * 22677610ab57SJason Gunthorpe * If the user wants to use a umem_offset then it must pass in 22687610ab57SJason Gunthorpe * pgsz_bitmap which guides the maximum page size and thus maximum 22697610ab57SJason Gunthorpe * object alignment inside the umem. See the PRM. 22707610ab57SJason Gunthorpe * 22717610ab57SJason Gunthorpe * Users are not allowed to use IOVA here, mkeys are not supported on 22727610ab57SJason Gunthorpe * umem. 2273878f7b31SJason Gunthorpe */ 22747610ab57SJason Gunthorpe ret = uverbs_get_const_default(&pgsz_bitmap, attrs, 22757610ab57SJason Gunthorpe MLX5_IB_ATTR_DEVX_UMEM_REG_PGSZ_BITMAP, 22767610ab57SJason Gunthorpe GENMASK_ULL(63, 22777610ab57SJason Gunthorpe min(PAGE_SHIFT, MLX5_ADAPTER_PAGE_SHIFT))); 22787610ab57SJason Gunthorpe if (ret) 22797610ab57SJason Gunthorpe return ret; 22807610ab57SJason Gunthorpe 22817610ab57SJason Gunthorpe page_size = devx_umem_find_best_pgsize(obj->umem, pgsz_bitmap); 2282878f7b31SJason Gunthorpe if (!page_size) 2283878f7b31SJason Gunthorpe return -EINVAL; 2284878f7b31SJason Gunthorpe 2285878f7b31SJason Gunthorpe cmd->inlen = MLX5_ST_SZ_BYTES(create_umem_in) + 2286878f7b31SJason Gunthorpe (MLX5_ST_SZ_BYTES(mtt) * 2287878f7b31SJason Gunthorpe ib_umem_num_dma_blocks(obj->umem, page_size)); 2288878f7b31SJason Gunthorpe cmd->in = uverbs_zalloc(attrs, cmd->inlen); 2289d0b7721cSJason Gunthorpe if (IS_ERR(cmd->in)) 2290878f7b31SJason Gunthorpe return PTR_ERR(cmd->in); 2291aeae9457SYishai Hadas 2292aeae9457SYishai Hadas umem = MLX5_ADDR_OF(create_umem_in, cmd->in, umem); 2293aeae9457SYishai Hadas mtt = (__be64 *)MLX5_ADDR_OF(umem, umem, mtt); 2294aeae9457SYishai Hadas 22956e3722baSYishai Hadas MLX5_SET(create_umem_in, cmd->in, opcode, MLX5_CMD_OP_CREATE_UMEM); 22967db0eea9SJason Gunthorpe MLX5_SET64(umem, umem, num_of_mtt, 2297878f7b31SJason Gunthorpe ib_umem_num_dma_blocks(obj->umem, page_size)); 2298878f7b31SJason Gunthorpe MLX5_SET(umem, umem, log_page_size, 2299878f7b31SJason Gunthorpe order_base_2(page_size) - MLX5_ADAPTER_PAGE_SHIFT); 2300878f7b31SJason Gunthorpe MLX5_SET(umem, umem, page_offset, 2301878f7b31SJason Gunthorpe ib_umem_dma_offset(obj->umem, page_size)); 2302878f7b31SJason Gunthorpe 230372b2f760SJason Gunthorpe if (mlx5_umem_needs_ats(dev, obj->umem, access)) 230472b2f760SJason Gunthorpe MLX5_SET(umem, umem, ats, 1); 230572b2f760SJason Gunthorpe 2306878f7b31SJason Gunthorpe mlx5_ib_populate_pas(obj->umem, page_size, mtt, 2307aeae9457SYishai Hadas (obj->umem->writable ? MLX5_IB_MTT_WRITE : 0) | 2308aeae9457SYishai Hadas MLX5_IB_MTT_READ); 2309878f7b31SJason Gunthorpe return 0; 2310aeae9457SYishai Hadas } 2311aeae9457SYishai Hadas 2312e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_UMEM_REG)( 231315a1b4beSJason Gunthorpe struct uverbs_attr_bundle *attrs) 2314aeae9457SYishai Hadas { 2315aeae9457SYishai Hadas struct devx_umem_reg_cmd cmd; 2316aeae9457SYishai Hadas struct devx_umem *obj; 2317c36ee46dSJason Gunthorpe struct ib_uobject *uobj = uverbs_attr_get_uobject( 2318c36ee46dSJason Gunthorpe attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE); 2319aeae9457SYishai Hadas u32 obj_id; 232089944450SShamir Rabinovitch struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context( 232189944450SShamir Rabinovitch &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext); 2322c36ee46dSJason Gunthorpe struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device); 232372b2f760SJason Gunthorpe int access_flags; 2324aeae9457SYishai Hadas int err; 2325aeae9457SYishai Hadas 2326aeae9457SYishai Hadas if (!c->devx_uid) 23277e1335a7SYishai Hadas return -EINVAL; 23287e1335a7SYishai Hadas 232972b2f760SJason Gunthorpe err = uverbs_get_flags32(&access_flags, attrs, 233072b2f760SJason Gunthorpe MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS, 233172b2f760SJason Gunthorpe IB_ACCESS_LOCAL_WRITE | 233272b2f760SJason Gunthorpe IB_ACCESS_REMOTE_WRITE | 233372b2f760SJason Gunthorpe IB_ACCESS_REMOTE_READ | 233472b2f760SJason Gunthorpe IB_ACCESS_RELAXED_ORDERING); 233572b2f760SJason Gunthorpe if (err) 233672b2f760SJason Gunthorpe return err; 233772b2f760SJason Gunthorpe 2338aeae9457SYishai Hadas obj = kzalloc(sizeof(struct devx_umem), GFP_KERNEL); 2339aeae9457SYishai Hadas if (!obj) 2340aeae9457SYishai Hadas return -ENOMEM; 2341aeae9457SYishai Hadas 234272b2f760SJason Gunthorpe err = devx_umem_get(dev, &c->ibucontext, attrs, obj, access_flags); 2343aeae9457SYishai Hadas if (err) 2344aeae9457SYishai Hadas goto err_obj_free; 2345aeae9457SYishai Hadas 234672b2f760SJason Gunthorpe err = devx_umem_reg_cmd_alloc(dev, attrs, obj, &cmd, access_flags); 2347aeae9457SYishai Hadas if (err) 2348aeae9457SYishai Hadas goto err_umem_release; 2349aeae9457SYishai Hadas 23506e3722baSYishai Hadas MLX5_SET(create_umem_in, cmd.in, uid, c->devx_uid); 2351aeae9457SYishai Hadas err = mlx5_cmd_exec(dev->mdev, cmd.in, cmd.inlen, cmd.out, 2352aeae9457SYishai Hadas sizeof(cmd.out)); 2353aeae9457SYishai Hadas if (err) 2354b61815e2SJason Gunthorpe goto err_umem_release; 2355aeae9457SYishai Hadas 2356aeae9457SYishai Hadas obj->mdev = dev->mdev; 2357aeae9457SYishai Hadas uobj->object = obj; 2358aeae9457SYishai Hadas devx_obj_build_destroy_cmd(cmd.in, cmd.out, obj->dinbox, &obj->dinlen, &obj_id); 23590ac8903cSJason Gunthorpe uverbs_finalize_uobj_create(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE); 2360aeae9457SYishai Hadas 23610ac8903cSJason Gunthorpe err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID, &obj_id, 23620ac8903cSJason Gunthorpe sizeof(obj_id)); 23630ac8903cSJason Gunthorpe return err; 2364aeae9457SYishai Hadas 2365aeae9457SYishai Hadas err_umem_release: 2366aeae9457SYishai Hadas ib_umem_release(obj->umem); 2367aeae9457SYishai Hadas err_obj_free: 2368aeae9457SYishai Hadas kfree(obj); 2369aeae9457SYishai Hadas return err; 2370aeae9457SYishai Hadas } 2371aeae9457SYishai Hadas 2372aeae9457SYishai Hadas static int devx_umem_cleanup(struct ib_uobject *uobject, 2373a6a3797dSShamir Rabinovitch enum rdma_remove_reason why, 2374a6a3797dSShamir Rabinovitch struct uverbs_attr_bundle *attrs) 2375aeae9457SYishai Hadas { 2376aeae9457SYishai Hadas struct devx_umem *obj = uobject->object; 2377aeae9457SYishai Hadas u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)]; 2378aeae9457SYishai Hadas int err; 2379aeae9457SYishai Hadas 2380aeae9457SYishai Hadas err = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out)); 2381efa968eeSLeon Romanovsky if (err) 2382aeae9457SYishai Hadas return err; 2383aeae9457SYishai Hadas 2384aeae9457SYishai Hadas ib_umem_release(obj->umem); 2385aeae9457SYishai Hadas kfree(obj); 2386aeae9457SYishai Hadas return 0; 2387aeae9457SYishai Hadas } 2388aeae9457SYishai Hadas 23895ec9d8eeSYishai Hadas static bool is_unaffiliated_event(struct mlx5_core_dev *dev, 23905ec9d8eeSYishai Hadas unsigned long event_type) 23915ec9d8eeSYishai Hadas { 23925ec9d8eeSYishai Hadas __be64 *unaff_events; 23935ec9d8eeSYishai Hadas int mask_entry; 23945ec9d8eeSYishai Hadas int mask_bit; 23955ec9d8eeSYishai Hadas 23965ec9d8eeSYishai Hadas if (!MLX5_CAP_GEN(dev, event_cap)) 23975ec9d8eeSYishai Hadas return is_legacy_unaffiliated_event_num(event_type); 23985ec9d8eeSYishai Hadas 23995ec9d8eeSYishai Hadas unaff_events = MLX5_CAP_DEV_EVENT(dev, 24005ec9d8eeSYishai Hadas user_unaffiliated_events); 24015ec9d8eeSYishai Hadas WARN_ON(event_type > MAX_SUPP_EVENT_NUM); 24025ec9d8eeSYishai Hadas 24035ec9d8eeSYishai Hadas mask_entry = event_type / 64; 24045ec9d8eeSYishai Hadas mask_bit = event_type % 64; 24055ec9d8eeSYishai Hadas 24065ec9d8eeSYishai Hadas if (!(be64_to_cpu(unaff_events[mask_entry]) & (1ull << mask_bit))) 24075ec9d8eeSYishai Hadas return false; 24085ec9d8eeSYishai Hadas 24095ec9d8eeSYishai Hadas return true; 24105ec9d8eeSYishai Hadas } 24115ec9d8eeSYishai Hadas 24125ec9d8eeSYishai Hadas static u32 devx_get_obj_id_from_event(unsigned long event_type, void *data) 24135ec9d8eeSYishai Hadas { 24145ec9d8eeSYishai Hadas struct mlx5_eqe *eqe = data; 24155ec9d8eeSYishai Hadas u32 obj_id = 0; 24165ec9d8eeSYishai Hadas 24175ec9d8eeSYishai Hadas switch (event_type) { 24185ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_SRQ_CATAS_ERROR: 24195ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_SRQ_RQ_LIMIT: 24205ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_PATH_MIG: 24215ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_COMM_EST: 24225ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_SQ_DRAINED: 24235ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_SRQ_LAST_WQE: 24245ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_WQ_CATAS_ERROR: 24255ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_PATH_MIG_FAILED: 24265ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR: 24275ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR: 24285ec9d8eeSYishai Hadas obj_id = be32_to_cpu(eqe->data.qp_srq.qp_srq_n) & 0xffffff; 24295ec9d8eeSYishai Hadas break; 2430972d7560SYishai Hadas case MLX5_EVENT_TYPE_XRQ_ERROR: 2431972d7560SYishai Hadas obj_id = be32_to_cpu(eqe->data.xrq_err.type_xrqn) & 0xffffff; 2432972d7560SYishai Hadas break; 24335ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_DCT_DRAINED: 2434972d7560SYishai Hadas case MLX5_EVENT_TYPE_DCT_KEY_VIOLATION: 24355ec9d8eeSYishai Hadas obj_id = be32_to_cpu(eqe->data.dct.dctn) & 0xffffff; 24365ec9d8eeSYishai Hadas break; 24375ec9d8eeSYishai Hadas case MLX5_EVENT_TYPE_CQ_ERROR: 24385ec9d8eeSYishai Hadas obj_id = be32_to_cpu(eqe->data.cq_err.cqn) & 0xffffff; 24395ec9d8eeSYishai Hadas break; 24405ec9d8eeSYishai Hadas default: 24415ec9d8eeSYishai Hadas obj_id = MLX5_GET(affiliated_event_header, &eqe->data, obj_id); 24425ec9d8eeSYishai Hadas break; 24435ec9d8eeSYishai Hadas } 24445ec9d8eeSYishai Hadas 24455ec9d8eeSYishai Hadas return obj_id; 24465ec9d8eeSYishai Hadas } 24475ec9d8eeSYishai Hadas 24485ec9d8eeSYishai Hadas static int deliver_event(struct devx_event_subscription *event_sub, 24495ec9d8eeSYishai Hadas const void *data) 24505ec9d8eeSYishai Hadas { 24515ec9d8eeSYishai Hadas struct devx_async_event_file *ev_file; 24525ec9d8eeSYishai Hadas struct devx_async_event_data *event_data; 24535ec9d8eeSYishai Hadas unsigned long flags; 24545ec9d8eeSYishai Hadas 24555ec9d8eeSYishai Hadas ev_file = event_sub->ev_file; 24565ec9d8eeSYishai Hadas 24575ec9d8eeSYishai Hadas if (ev_file->omit_data) { 24585ec9d8eeSYishai Hadas spin_lock_irqsave(&ev_file->lock, flags); 2459a8af8694SYishai Hadas if (!list_empty(&event_sub->event_list) || 2460a8af8694SYishai Hadas ev_file->is_destroyed) { 24615ec9d8eeSYishai Hadas spin_unlock_irqrestore(&ev_file->lock, flags); 24625ec9d8eeSYishai Hadas return 0; 24635ec9d8eeSYishai Hadas } 24645ec9d8eeSYishai Hadas 24655ec9d8eeSYishai Hadas list_add_tail(&event_sub->event_list, &ev_file->event_list); 24665ec9d8eeSYishai Hadas spin_unlock_irqrestore(&ev_file->lock, flags); 24675ec9d8eeSYishai Hadas wake_up_interruptible(&ev_file->poll_wait); 24685ec9d8eeSYishai Hadas return 0; 24695ec9d8eeSYishai Hadas } 24705ec9d8eeSYishai Hadas 24715ec9d8eeSYishai Hadas event_data = kzalloc(sizeof(*event_data) + sizeof(struct mlx5_eqe), 24725ec9d8eeSYishai Hadas GFP_ATOMIC); 24735ec9d8eeSYishai Hadas if (!event_data) { 24745ec9d8eeSYishai Hadas spin_lock_irqsave(&ev_file->lock, flags); 24755ec9d8eeSYishai Hadas ev_file->is_overflow_err = 1; 24765ec9d8eeSYishai Hadas spin_unlock_irqrestore(&ev_file->lock, flags); 24775ec9d8eeSYishai Hadas return -ENOMEM; 24785ec9d8eeSYishai Hadas } 24795ec9d8eeSYishai Hadas 24805ec9d8eeSYishai Hadas event_data->hdr.cookie = event_sub->cookie; 24815ec9d8eeSYishai Hadas memcpy(event_data->hdr.out_data, data, sizeof(struct mlx5_eqe)); 24825ec9d8eeSYishai Hadas 24835ec9d8eeSYishai Hadas spin_lock_irqsave(&ev_file->lock, flags); 2484f7c8416cSJason Gunthorpe if (!ev_file->is_destroyed) 24855ec9d8eeSYishai Hadas list_add_tail(&event_data->list, &ev_file->event_list); 2486f7c8416cSJason Gunthorpe else 2487f7c8416cSJason Gunthorpe kfree(event_data); 24885ec9d8eeSYishai Hadas spin_unlock_irqrestore(&ev_file->lock, flags); 24895ec9d8eeSYishai Hadas wake_up_interruptible(&ev_file->poll_wait); 24905ec9d8eeSYishai Hadas 24915ec9d8eeSYishai Hadas return 0; 24925ec9d8eeSYishai Hadas } 24935ec9d8eeSYishai Hadas 24945ec9d8eeSYishai Hadas static void dispatch_event_fd(struct list_head *fd_list, 24955ec9d8eeSYishai Hadas const void *data) 24965ec9d8eeSYishai Hadas { 24975ec9d8eeSYishai Hadas struct devx_event_subscription *item; 24985ec9d8eeSYishai Hadas 24995ec9d8eeSYishai Hadas list_for_each_entry_rcu(item, fd_list, xa_list) { 25006898d1c6SJason Gunthorpe if (item->eventfd) 25013652117fSChristian Brauner eventfd_signal(item->eventfd); 25026898d1c6SJason Gunthorpe else 25035ec9d8eeSYishai Hadas deliver_event(item, data); 25045ec9d8eeSYishai Hadas } 25055ec9d8eeSYishai Hadas } 25065ec9d8eeSYishai Hadas 2507e337dd53SYishai Hadas static int devx_event_notifier(struct notifier_block *nb, 2508e337dd53SYishai Hadas unsigned long event_type, void *data) 2509e337dd53SYishai Hadas { 25105ec9d8eeSYishai Hadas struct mlx5_devx_event_table *table; 25115ec9d8eeSYishai Hadas struct mlx5_ib_dev *dev; 25125ec9d8eeSYishai Hadas struct devx_event *event; 25135ec9d8eeSYishai Hadas struct devx_obj_event *obj_event; 25145ec9d8eeSYishai Hadas u16 obj_type = 0; 25155ec9d8eeSYishai Hadas bool is_unaffiliated; 25165ec9d8eeSYishai Hadas u32 obj_id; 25175ec9d8eeSYishai Hadas 25185ec9d8eeSYishai Hadas /* Explicit filtering to kernel events which may occur frequently */ 25195ec9d8eeSYishai Hadas if (event_type == MLX5_EVENT_TYPE_CMD || 25205ec9d8eeSYishai Hadas event_type == MLX5_EVENT_TYPE_PAGE_REQUEST) 25215ec9d8eeSYishai Hadas return NOTIFY_OK; 25225ec9d8eeSYishai Hadas 25235ec9d8eeSYishai Hadas table = container_of(nb, struct mlx5_devx_event_table, devx_nb.nb); 25245ec9d8eeSYishai Hadas dev = container_of(table, struct mlx5_ib_dev, devx_event_table); 25255ec9d8eeSYishai Hadas is_unaffiliated = is_unaffiliated_event(dev->mdev, event_type); 25265ec9d8eeSYishai Hadas 25275ec9d8eeSYishai Hadas if (!is_unaffiliated) 25285ec9d8eeSYishai Hadas obj_type = get_event_obj_type(event_type, data); 25295ec9d8eeSYishai Hadas 25305ec9d8eeSYishai Hadas rcu_read_lock(); 25315ec9d8eeSYishai Hadas event = xa_load(&table->event_xa, event_type | (obj_type << 16)); 25325ec9d8eeSYishai Hadas if (!event) { 25335ec9d8eeSYishai Hadas rcu_read_unlock(); 2534e337dd53SYishai Hadas return NOTIFY_DONE; 2535e337dd53SYishai Hadas } 2536e337dd53SYishai Hadas 25375ec9d8eeSYishai Hadas if (is_unaffiliated) { 25385ec9d8eeSYishai Hadas dispatch_event_fd(&event->unaffiliated_list, data); 25395ec9d8eeSYishai Hadas rcu_read_unlock(); 25405ec9d8eeSYishai Hadas return NOTIFY_OK; 25415ec9d8eeSYishai Hadas } 25425ec9d8eeSYishai Hadas 25435ec9d8eeSYishai Hadas obj_id = devx_get_obj_id_from_event(event_type, data); 25445ec9d8eeSYishai Hadas obj_event = xa_load(&event->object_ids, obj_id); 25455ec9d8eeSYishai Hadas if (!obj_event) { 25465ec9d8eeSYishai Hadas rcu_read_unlock(); 25475ec9d8eeSYishai Hadas return NOTIFY_DONE; 25485ec9d8eeSYishai Hadas } 25495ec9d8eeSYishai Hadas 25505ec9d8eeSYishai Hadas dispatch_event_fd(&obj_event->obj_sub_list, data); 25515ec9d8eeSYishai Hadas 25525ec9d8eeSYishai Hadas rcu_read_unlock(); 25535ec9d8eeSYishai Hadas return NOTIFY_OK; 25545ec9d8eeSYishai Hadas } 25555ec9d8eeSYishai Hadas 2556d8b7515eSLeon Romanovsky int mlx5_ib_devx_init(struct mlx5_ib_dev *dev) 2557e337dd53SYishai Hadas { 2558e337dd53SYishai Hadas struct mlx5_devx_event_table *table = &dev->devx_event_table; 2559d8b7515eSLeon Romanovsky int uid; 2560e337dd53SYishai Hadas 2561d8b7515eSLeon Romanovsky uid = mlx5_ib_devx_create(dev, false); 2562d8b7515eSLeon Romanovsky if (uid > 0) { 2563d8b7515eSLeon Romanovsky dev->devx_whitelist_uid = uid; 2564e337dd53SYishai Hadas xa_init(&table->event_xa); 2565e337dd53SYishai Hadas mutex_init(&table->event_xa_lock); 2566e337dd53SYishai Hadas MLX5_NB_INIT(&table->devx_nb, devx_event_notifier, NOTIFY_ANY); 2567e337dd53SYishai Hadas mlx5_eq_notifier_register(dev->mdev, &table->devx_nb); 2568e337dd53SYishai Hadas } 2569e337dd53SYishai Hadas 2570d8b7515eSLeon Romanovsky return 0; 2571d8b7515eSLeon Romanovsky } 2572d8b7515eSLeon Romanovsky 2573d8b7515eSLeon Romanovsky void mlx5_ib_devx_cleanup(struct mlx5_ib_dev *dev) 2574e337dd53SYishai Hadas { 2575e337dd53SYishai Hadas struct mlx5_devx_event_table *table = &dev->devx_event_table; 257675973853SYishai Hadas struct devx_event_subscription *sub, *tmp; 257775973853SYishai Hadas struct devx_event *event; 2578e337dd53SYishai Hadas void *entry; 2579e337dd53SYishai Hadas unsigned long id; 2580e337dd53SYishai Hadas 2581d8b7515eSLeon Romanovsky if (dev->devx_whitelist_uid) { 2582e337dd53SYishai Hadas mlx5_eq_notifier_unregister(dev->mdev, &table->devx_nb); 258375973853SYishai Hadas mutex_lock(&dev->devx_event_table.event_xa_lock); 258475973853SYishai Hadas xa_for_each(&table->event_xa, id, entry) { 258575973853SYishai Hadas event = entry; 2586d8b7515eSLeon Romanovsky list_for_each_entry_safe( 2587d8b7515eSLeon Romanovsky sub, tmp, &event->unaffiliated_list, xa_list) 258875973853SYishai Hadas devx_cleanup_subscription(dev, sub); 2589e337dd53SYishai Hadas kfree(entry); 259075973853SYishai Hadas } 259175973853SYishai Hadas mutex_unlock(&dev->devx_event_table.event_xa_lock); 2592e337dd53SYishai Hadas xa_destroy(&table->event_xa); 2593d8b7515eSLeon Romanovsky 2594d8b7515eSLeon Romanovsky mlx5_ib_devx_destroy(dev, dev->devx_whitelist_uid); 2595d8b7515eSLeon Romanovsky } 2596e337dd53SYishai Hadas } 2597e337dd53SYishai Hadas 25986bf8f22aSYishai Hadas static ssize_t devx_async_cmd_event_read(struct file *filp, char __user *buf, 25996bf8f22aSYishai Hadas size_t count, loff_t *pos) 26006bf8f22aSYishai Hadas { 26014accbb3fSYishai Hadas struct devx_async_cmd_event_file *comp_ev_file = filp->private_data; 26024accbb3fSYishai Hadas struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue; 26034accbb3fSYishai Hadas struct devx_async_data *event; 26044accbb3fSYishai Hadas int ret = 0; 26054accbb3fSYishai Hadas size_t eventsz; 26064accbb3fSYishai Hadas 26074accbb3fSYishai Hadas spin_lock_irq(&ev_queue->lock); 26084accbb3fSYishai Hadas 26094accbb3fSYishai Hadas while (list_empty(&ev_queue->event_list)) { 26104accbb3fSYishai Hadas spin_unlock_irq(&ev_queue->lock); 26114accbb3fSYishai Hadas 26124accbb3fSYishai Hadas if (filp->f_flags & O_NONBLOCK) 26134accbb3fSYishai Hadas return -EAGAIN; 26144accbb3fSYishai Hadas 26154accbb3fSYishai Hadas if (wait_event_interruptible( 26164accbb3fSYishai Hadas ev_queue->poll_wait, 2617eaebaf77SYishai Hadas (!list_empty(&ev_queue->event_list) || 2618eaebaf77SYishai Hadas ev_queue->is_destroyed))) { 26194accbb3fSYishai Hadas return -ERESTARTSYS; 26204accbb3fSYishai Hadas } 2621eaebaf77SYishai Hadas 26224accbb3fSYishai Hadas spin_lock_irq(&ev_queue->lock); 2623a8af8694SYishai Hadas if (ev_queue->is_destroyed) { 2624a8af8694SYishai Hadas spin_unlock_irq(&ev_queue->lock); 2625a8af8694SYishai Hadas return -EIO; 2626a8af8694SYishai Hadas } 26274accbb3fSYishai Hadas } 26284accbb3fSYishai Hadas 26294accbb3fSYishai Hadas event = list_entry(ev_queue->event_list.next, 26304accbb3fSYishai Hadas struct devx_async_data, list); 26314accbb3fSYishai Hadas eventsz = event->cmd_out_len + 26324accbb3fSYishai Hadas sizeof(struct mlx5_ib_uapi_devx_async_cmd_hdr); 26334accbb3fSYishai Hadas 26344accbb3fSYishai Hadas if (eventsz > count) { 26354accbb3fSYishai Hadas spin_unlock_irq(&ev_queue->lock); 26364accbb3fSYishai Hadas return -ENOSPC; 26374accbb3fSYishai Hadas } 26384accbb3fSYishai Hadas 26394accbb3fSYishai Hadas list_del(ev_queue->event_list.next); 26404accbb3fSYishai Hadas spin_unlock_irq(&ev_queue->lock); 26414accbb3fSYishai Hadas 26424accbb3fSYishai Hadas if (copy_to_user(buf, &event->hdr, eventsz)) 26434accbb3fSYishai Hadas ret = -EFAULT; 26444accbb3fSYishai Hadas else 26454accbb3fSYishai Hadas ret = eventsz; 26464accbb3fSYishai Hadas 26474accbb3fSYishai Hadas atomic_sub(event->cmd_out_len, &ev_queue->bytes_in_use); 26484accbb3fSYishai Hadas kvfree(event); 26494accbb3fSYishai Hadas return ret; 26506bf8f22aSYishai Hadas } 26516bf8f22aSYishai Hadas 26526bf8f22aSYishai Hadas static __poll_t devx_async_cmd_event_poll(struct file *filp, 26536bf8f22aSYishai Hadas struct poll_table_struct *wait) 26546bf8f22aSYishai Hadas { 26554accbb3fSYishai Hadas struct devx_async_cmd_event_file *comp_ev_file = filp->private_data; 26564accbb3fSYishai Hadas struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue; 26574accbb3fSYishai Hadas __poll_t pollflags = 0; 26584accbb3fSYishai Hadas 26594accbb3fSYishai Hadas poll_wait(filp, &ev_queue->poll_wait, wait); 26604accbb3fSYishai Hadas 26614accbb3fSYishai Hadas spin_lock_irq(&ev_queue->lock); 2662eaebaf77SYishai Hadas if (ev_queue->is_destroyed) 2663eaebaf77SYishai Hadas pollflags = EPOLLIN | EPOLLRDNORM | EPOLLRDHUP; 2664eaebaf77SYishai Hadas else if (!list_empty(&ev_queue->event_list)) 26654accbb3fSYishai Hadas pollflags = EPOLLIN | EPOLLRDNORM; 26664accbb3fSYishai Hadas spin_unlock_irq(&ev_queue->lock); 26674accbb3fSYishai Hadas 26684accbb3fSYishai Hadas return pollflags; 26696bf8f22aSYishai Hadas } 26706bf8f22aSYishai Hadas 26711f687edeSBart Van Assche static const struct file_operations devx_async_cmd_event_fops = { 26726bf8f22aSYishai Hadas .owner = THIS_MODULE, 26736bf8f22aSYishai Hadas .read = devx_async_cmd_event_read, 26746bf8f22aSYishai Hadas .poll = devx_async_cmd_event_poll, 2675f7c8416cSJason Gunthorpe .release = uverbs_uobject_fd_release, 26766bf8f22aSYishai Hadas }; 26776bf8f22aSYishai Hadas 26782afc5e1bSYishai Hadas static ssize_t devx_async_event_read(struct file *filp, char __user *buf, 26792afc5e1bSYishai Hadas size_t count, loff_t *pos) 26802afc5e1bSYishai Hadas { 26815ec9d8eeSYishai Hadas struct devx_async_event_file *ev_file = filp->private_data; 26825ec9d8eeSYishai Hadas struct devx_event_subscription *event_sub; 26833f649ab7SKees Cook struct devx_async_event_data *event; 26845ec9d8eeSYishai Hadas int ret = 0; 26855ec9d8eeSYishai Hadas size_t eventsz; 26865ec9d8eeSYishai Hadas bool omit_data; 26875ec9d8eeSYishai Hadas void *event_data; 26885ec9d8eeSYishai Hadas 26895ec9d8eeSYishai Hadas omit_data = ev_file->omit_data; 26905ec9d8eeSYishai Hadas 26915ec9d8eeSYishai Hadas spin_lock_irq(&ev_file->lock); 26925ec9d8eeSYishai Hadas 26935ec9d8eeSYishai Hadas if (ev_file->is_overflow_err) { 26945ec9d8eeSYishai Hadas ev_file->is_overflow_err = 0; 26955ec9d8eeSYishai Hadas spin_unlock_irq(&ev_file->lock); 26965ec9d8eeSYishai Hadas return -EOVERFLOW; 26975ec9d8eeSYishai Hadas } 26985ec9d8eeSYishai Hadas 26995ec9d8eeSYishai Hadas 27005ec9d8eeSYishai Hadas while (list_empty(&ev_file->event_list)) { 27015ec9d8eeSYishai Hadas spin_unlock_irq(&ev_file->lock); 27025ec9d8eeSYishai Hadas 27035ec9d8eeSYishai Hadas if (filp->f_flags & O_NONBLOCK) 27045ec9d8eeSYishai Hadas return -EAGAIN; 27055ec9d8eeSYishai Hadas 27065ec9d8eeSYishai Hadas if (wait_event_interruptible(ev_file->poll_wait, 27075ec9d8eeSYishai Hadas (!list_empty(&ev_file->event_list) || 27085ec9d8eeSYishai Hadas ev_file->is_destroyed))) { 27095ec9d8eeSYishai Hadas return -ERESTARTSYS; 27105ec9d8eeSYishai Hadas } 27115ec9d8eeSYishai Hadas 27125ec9d8eeSYishai Hadas spin_lock_irq(&ev_file->lock); 27135ec9d8eeSYishai Hadas if (ev_file->is_destroyed) { 27145ec9d8eeSYishai Hadas spin_unlock_irq(&ev_file->lock); 27155ec9d8eeSYishai Hadas return -EIO; 27165ec9d8eeSYishai Hadas } 27175ec9d8eeSYishai Hadas } 27185ec9d8eeSYishai Hadas 27195ec9d8eeSYishai Hadas if (omit_data) { 27205ec9d8eeSYishai Hadas event_sub = list_first_entry(&ev_file->event_list, 27215ec9d8eeSYishai Hadas struct devx_event_subscription, 27225ec9d8eeSYishai Hadas event_list); 27235ec9d8eeSYishai Hadas eventsz = sizeof(event_sub->cookie); 27245ec9d8eeSYishai Hadas event_data = &event_sub->cookie; 27255ec9d8eeSYishai Hadas } else { 27265ec9d8eeSYishai Hadas event = list_first_entry(&ev_file->event_list, 27275ec9d8eeSYishai Hadas struct devx_async_event_data, list); 27285ec9d8eeSYishai Hadas eventsz = sizeof(struct mlx5_eqe) + 27295ec9d8eeSYishai Hadas sizeof(struct mlx5_ib_uapi_devx_async_event_hdr); 27305ec9d8eeSYishai Hadas event_data = &event->hdr; 27315ec9d8eeSYishai Hadas } 27325ec9d8eeSYishai Hadas 27335ec9d8eeSYishai Hadas if (eventsz > count) { 27345ec9d8eeSYishai Hadas spin_unlock_irq(&ev_file->lock); 27352afc5e1bSYishai Hadas return -EINVAL; 27362afc5e1bSYishai Hadas } 27372afc5e1bSYishai Hadas 27385ec9d8eeSYishai Hadas if (omit_data) 27395ec9d8eeSYishai Hadas list_del_init(&event_sub->event_list); 27405ec9d8eeSYishai Hadas else 27415ec9d8eeSYishai Hadas list_del(&event->list); 27425ec9d8eeSYishai Hadas 27435ec9d8eeSYishai Hadas spin_unlock_irq(&ev_file->lock); 27445ec9d8eeSYishai Hadas 27455ec9d8eeSYishai Hadas if (copy_to_user(buf, event_data, eventsz)) 27465ec9d8eeSYishai Hadas /* This points to an application issue, not a kernel concern */ 27475ec9d8eeSYishai Hadas ret = -EFAULT; 27485ec9d8eeSYishai Hadas else 27495ec9d8eeSYishai Hadas ret = eventsz; 27505ec9d8eeSYishai Hadas 27515ec9d8eeSYishai Hadas if (!omit_data) 27525ec9d8eeSYishai Hadas kfree(event); 27535ec9d8eeSYishai Hadas return ret; 27545ec9d8eeSYishai Hadas } 27555ec9d8eeSYishai Hadas 27562afc5e1bSYishai Hadas static __poll_t devx_async_event_poll(struct file *filp, 27572afc5e1bSYishai Hadas struct poll_table_struct *wait) 27582afc5e1bSYishai Hadas { 27595ec9d8eeSYishai Hadas struct devx_async_event_file *ev_file = filp->private_data; 27605ec9d8eeSYishai Hadas __poll_t pollflags = 0; 27615ec9d8eeSYishai Hadas 27625ec9d8eeSYishai Hadas poll_wait(filp, &ev_file->poll_wait, wait); 27635ec9d8eeSYishai Hadas 27645ec9d8eeSYishai Hadas spin_lock_irq(&ev_file->lock); 27655ec9d8eeSYishai Hadas if (ev_file->is_destroyed) 27665ec9d8eeSYishai Hadas pollflags = EPOLLIN | EPOLLRDNORM | EPOLLRDHUP; 27675ec9d8eeSYishai Hadas else if (!list_empty(&ev_file->event_list)) 27685ec9d8eeSYishai Hadas pollflags = EPOLLIN | EPOLLRDNORM; 27695ec9d8eeSYishai Hadas spin_unlock_irq(&ev_file->lock); 27705ec9d8eeSYishai Hadas 27715ec9d8eeSYishai Hadas return pollflags; 27722afc5e1bSYishai Hadas } 27732afc5e1bSYishai Hadas 27746898d1c6SJason Gunthorpe static void devx_free_subscription(struct rcu_head *rcu) 27756898d1c6SJason Gunthorpe { 27766898d1c6SJason Gunthorpe struct devx_event_subscription *event_sub = 27776898d1c6SJason Gunthorpe container_of(rcu, struct devx_event_subscription, rcu); 27786898d1c6SJason Gunthorpe 27796898d1c6SJason Gunthorpe if (event_sub->eventfd) 27806898d1c6SJason Gunthorpe eventfd_ctx_put(event_sub->eventfd); 27816898d1c6SJason Gunthorpe uverbs_uobject_put(&event_sub->ev_file->uobj); 27826898d1c6SJason Gunthorpe kfree(event_sub); 27836898d1c6SJason Gunthorpe } 27846898d1c6SJason Gunthorpe 2785f7c8416cSJason Gunthorpe static const struct file_operations devx_async_event_fops = { 2786f7c8416cSJason Gunthorpe .owner = THIS_MODULE, 2787f7c8416cSJason Gunthorpe .read = devx_async_event_read, 2788f7c8416cSJason Gunthorpe .poll = devx_async_event_poll, 2789f7c8416cSJason Gunthorpe .release = uverbs_uobject_fd_release, 2790f7c8416cSJason Gunthorpe }; 2791f7c8416cSJason Gunthorpe 2792c5633a72SLeon Romanovsky static void devx_async_cmd_event_destroy_uobj(struct ib_uobject *uobj, 2793f7c8416cSJason Gunthorpe enum rdma_remove_reason why) 27942afc5e1bSYishai Hadas { 2795f7c8416cSJason Gunthorpe struct devx_async_cmd_event_file *comp_ev_file = 2796f7c8416cSJason Gunthorpe container_of(uobj, struct devx_async_cmd_event_file, 2797f7c8416cSJason Gunthorpe uobj); 2798f7c8416cSJason Gunthorpe struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue; 2799f7c8416cSJason Gunthorpe struct devx_async_data *entry, *tmp; 2800f7c8416cSJason Gunthorpe 2801f7c8416cSJason Gunthorpe spin_lock_irq(&ev_queue->lock); 2802f7c8416cSJason Gunthorpe ev_queue->is_destroyed = 1; 2803f7c8416cSJason Gunthorpe spin_unlock_irq(&ev_queue->lock); 2804f7c8416cSJason Gunthorpe wake_up_interruptible(&ev_queue->poll_wait); 2805f7c8416cSJason Gunthorpe 2806f7c8416cSJason Gunthorpe mlx5_cmd_cleanup_async_ctx(&comp_ev_file->async_ctx); 2807f7c8416cSJason Gunthorpe 2808f7c8416cSJason Gunthorpe spin_lock_irq(&comp_ev_file->ev_queue.lock); 2809f7c8416cSJason Gunthorpe list_for_each_entry_safe(entry, tmp, 2810a8af8694SYishai Hadas &comp_ev_file->ev_queue.event_list, list) { 2811a8af8694SYishai Hadas list_del(&entry->list); 2812f7c8416cSJason Gunthorpe kvfree(entry); 2813a8af8694SYishai Hadas } 2814f7c8416cSJason Gunthorpe spin_unlock_irq(&comp_ev_file->ev_queue.lock); 2815f7c8416cSJason Gunthorpe }; 2816f7c8416cSJason Gunthorpe 2817c5633a72SLeon Romanovsky static void devx_async_event_destroy_uobj(struct ib_uobject *uobj, 2818f7c8416cSJason Gunthorpe enum rdma_remove_reason why) 2819f7c8416cSJason Gunthorpe { 2820f7c8416cSJason Gunthorpe struct devx_async_event_file *ev_file = 2821f7c8416cSJason Gunthorpe container_of(uobj, struct devx_async_event_file, 2822f7c8416cSJason Gunthorpe uobj); 282375973853SYishai Hadas struct devx_event_subscription *event_sub, *event_sub_tmp; 2824e9eec6a5SYishai Hadas struct mlx5_ib_dev *dev = ev_file->dev; 282575973853SYishai Hadas 2826f7c8416cSJason Gunthorpe spin_lock_irq(&ev_file->lock); 2827f7c8416cSJason Gunthorpe ev_file->is_destroyed = 1; 2828a8af8694SYishai Hadas 2829a8af8694SYishai Hadas /* free the pending events allocation */ 2830a8af8694SYishai Hadas if (ev_file->omit_data) { 2831a8af8694SYishai Hadas struct devx_event_subscription *event_sub, *tmp; 2832a8af8694SYishai Hadas 2833a8af8694SYishai Hadas list_for_each_entry_safe(event_sub, tmp, &ev_file->event_list, 2834a8af8694SYishai Hadas event_list) 2835a8af8694SYishai Hadas list_del_init(&event_sub->event_list); 2836a8af8694SYishai Hadas 2837a8af8694SYishai Hadas } else { 2838a8af8694SYishai Hadas struct devx_async_event_data *entry, *tmp; 2839a8af8694SYishai Hadas 2840a8af8694SYishai Hadas list_for_each_entry_safe(entry, tmp, &ev_file->event_list, 2841a8af8694SYishai Hadas list) { 2842a8af8694SYishai Hadas list_del(&entry->list); 2843a8af8694SYishai Hadas kfree(entry); 2844a8af8694SYishai Hadas } 2845a8af8694SYishai Hadas } 2846a8af8694SYishai Hadas 2847f7c8416cSJason Gunthorpe spin_unlock_irq(&ev_file->lock); 2848f7c8416cSJason Gunthorpe wake_up_interruptible(&ev_file->poll_wait); 2849f7c8416cSJason Gunthorpe 2850e9eec6a5SYishai Hadas mutex_lock(&dev->devx_event_table.event_xa_lock); 285175973853SYishai Hadas /* delete the subscriptions which are related to this FD */ 285275973853SYishai Hadas list_for_each_entry_safe(event_sub, event_sub_tmp, 285375973853SYishai Hadas &ev_file->subscribed_events_list, file_list) { 2854e9eec6a5SYishai Hadas devx_cleanup_subscription(dev, event_sub); 285575973853SYishai Hadas list_del_rcu(&event_sub->file_list); 285675973853SYishai Hadas /* subscription may not be used by the read API any more */ 28576898d1c6SJason Gunthorpe call_rcu(&event_sub->rcu, devx_free_subscription); 285875973853SYishai Hadas } 2859e9eec6a5SYishai Hadas mutex_unlock(&dev->devx_event_table.event_xa_lock); 286075973853SYishai Hadas 2861e9eec6a5SYishai Hadas put_device(&dev->ib_dev.dev); 28622afc5e1bSYishai Hadas }; 28632afc5e1bSYishai Hadas 28649a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD( 28659a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_UMEM_REG, 28669a119cd5SJason Gunthorpe UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE, 2867aeae9457SYishai Hadas MLX5_IB_OBJECT_DEVX_UMEM, 2868aeae9457SYishai Hadas UVERBS_ACCESS_NEW, 286983bb4442SJason Gunthorpe UA_MANDATORY), 28709a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR, 28719a119cd5SJason Gunthorpe UVERBS_ATTR_TYPE(u64), 287283bb4442SJason Gunthorpe UA_MANDATORY), 28739a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_LEN, 28749a119cd5SJason Gunthorpe UVERBS_ATTR_TYPE(u64), 287583bb4442SJason Gunthorpe UA_MANDATORY), 28769af859c5SJason Gunthorpe UVERBS_ATTR_RAW_FD(MLX5_IB_ATTR_DEVX_UMEM_REG_DMABUF_FD, 28779af859c5SJason Gunthorpe UA_OPTIONAL), 2878bccd0622SJason Gunthorpe UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS, 2879bccd0622SJason Gunthorpe enum ib_access_flags), 28807610ab57SJason Gunthorpe UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_PGSZ_BITMAP, 28817610ab57SJason Gunthorpe u64), 28829a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID, 28839a119cd5SJason Gunthorpe UVERBS_ATTR_TYPE(u32), 288483bb4442SJason Gunthorpe UA_MANDATORY)); 2885aeae9457SYishai Hadas 2886528922afSYishai Hadas DECLARE_UVERBS_NAMED_METHOD_DESTROY( 28879a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_UMEM_DEREG, 28889a119cd5SJason Gunthorpe UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_DEREG_HANDLE, 2889aeae9457SYishai Hadas MLX5_IB_OBJECT_DEVX_UMEM, 2890aeae9457SYishai Hadas UVERBS_ACCESS_DESTROY, 289183bb4442SJason Gunthorpe UA_MANDATORY)); 2892aeae9457SYishai Hadas 28939a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD( 28949a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_QUERY_EQN, 28959a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC, 28969a119cd5SJason Gunthorpe UVERBS_ATTR_TYPE(u32), 289783bb4442SJason Gunthorpe UA_MANDATORY), 28989a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN, 28999a119cd5SJason Gunthorpe UVERBS_ATTR_TYPE(u32), 290083bb4442SJason Gunthorpe UA_MANDATORY)); 2901f6fe01b7SYishai Hadas 29029a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD( 29039a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_QUERY_UAR, 29049a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX, 29059a119cd5SJason Gunthorpe UVERBS_ATTR_TYPE(u32), 290683bb4442SJason Gunthorpe UA_MANDATORY), 29079a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX, 29089a119cd5SJason Gunthorpe UVERBS_ATTR_TYPE(u32), 290983bb4442SJason Gunthorpe UA_MANDATORY)); 29107c043e90SYishai Hadas 29119a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD( 29129a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_OTHER, 29139a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN( 29149a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OTHER_CMD_IN, 29158aa8c95cSYishai Hadas UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)), 291683bb4442SJason Gunthorpe UA_MANDATORY, 291783bb4442SJason Gunthorpe UA_ALLOC_AND_COPY), 29189a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_OUT( 29199a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT, 29207efce369SYishai Hadas UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)), 2921540cd692SJason Gunthorpe UA_MANDATORY)); 29227efce369SYishai Hadas 29239a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD( 29249a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_OBJ_CREATE, 29259a119cd5SJason Gunthorpe UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE, 29269a119cd5SJason Gunthorpe MLX5_IB_OBJECT_DEVX_OBJ, 29279a119cd5SJason Gunthorpe UVERBS_ACCESS_NEW, 292883bb4442SJason Gunthorpe UA_MANDATORY), 29299a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN( 29309a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN, 29319a119cd5SJason Gunthorpe UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)), 293283bb4442SJason Gunthorpe UA_MANDATORY, 293383bb4442SJason Gunthorpe UA_ALLOC_AND_COPY), 29349a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_OUT( 29359a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT, 29369a119cd5SJason Gunthorpe UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)), 2937540cd692SJason Gunthorpe UA_MANDATORY)); 29389a119cd5SJason Gunthorpe 2939528922afSYishai Hadas DECLARE_UVERBS_NAMED_METHOD_DESTROY( 29409a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_OBJ_DESTROY, 29419a119cd5SJason Gunthorpe UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_DESTROY_HANDLE, 29427efce369SYishai Hadas MLX5_IB_OBJECT_DEVX_OBJ, 29437efce369SYishai Hadas UVERBS_ACCESS_DESTROY, 294483bb4442SJason Gunthorpe UA_MANDATORY)); 29457efce369SYishai Hadas 29469a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD( 29479a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_OBJ_MODIFY, 29489a119cd5SJason Gunthorpe UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE, 294934613eb1SYishai Hadas UVERBS_IDR_ANY_OBJECT, 2950*be551ee1SYishai Hadas UVERBS_ACCESS_READ, 295183bb4442SJason Gunthorpe UA_MANDATORY), 29529a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN( 29539a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN, 2954e662e14dSYishai Hadas UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)), 295583bb4442SJason Gunthorpe UA_MANDATORY, 295683bb4442SJason Gunthorpe UA_ALLOC_AND_COPY), 29579a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_OUT( 29589a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT, 2959e662e14dSYishai Hadas UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)), 2960540cd692SJason Gunthorpe UA_MANDATORY)); 2961e662e14dSYishai Hadas 29629a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD( 29639a119cd5SJason Gunthorpe MLX5_IB_METHOD_DEVX_OBJ_QUERY, 29649a119cd5SJason Gunthorpe UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE, 296534613eb1SYishai Hadas UVERBS_IDR_ANY_OBJECT, 2966e662e14dSYishai Hadas UVERBS_ACCESS_READ, 296783bb4442SJason Gunthorpe UA_MANDATORY), 29689a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_IN( 29699a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN, 2970e662e14dSYishai Hadas UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)), 297183bb4442SJason Gunthorpe UA_MANDATORY, 297283bb4442SJason Gunthorpe UA_ALLOC_AND_COPY), 29739a119cd5SJason Gunthorpe UVERBS_ATTR_PTR_OUT( 29749a119cd5SJason Gunthorpe MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT, 2975e662e14dSYishai Hadas UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)), 2976540cd692SJason Gunthorpe UA_MANDATORY)); 2977e662e14dSYishai Hadas 2978a124edbaSYishai Hadas DECLARE_UVERBS_NAMED_METHOD( 2979a124edbaSYishai Hadas MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY, 2980a124edbaSYishai Hadas UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE, 2981a124edbaSYishai Hadas UVERBS_IDR_ANY_OBJECT, 2982a124edbaSYishai Hadas UVERBS_ACCESS_READ, 2983a124edbaSYishai Hadas UA_MANDATORY), 2984a124edbaSYishai Hadas UVERBS_ATTR_PTR_IN( 2985a124edbaSYishai Hadas MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN, 2986a124edbaSYishai Hadas UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)), 2987a124edbaSYishai Hadas UA_MANDATORY, 2988a124edbaSYishai Hadas UA_ALLOC_AND_COPY), 2989a124edbaSYishai Hadas UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_OUT_LEN, 2990a124edbaSYishai Hadas u16, UA_MANDATORY), 2991a124edbaSYishai Hadas UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_FD, 2992a124edbaSYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD, 2993a124edbaSYishai Hadas UVERBS_ACCESS_READ, 2994a124edbaSYishai Hadas UA_MANDATORY), 2995a124edbaSYishai Hadas UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_WR_ID, 2996a124edbaSYishai Hadas UVERBS_ATTR_TYPE(u64), 2997a124edbaSYishai Hadas UA_MANDATORY)); 2998a124edbaSYishai Hadas 299975973853SYishai Hadas DECLARE_UVERBS_NAMED_METHOD( 300075973853SYishai Hadas MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT, 300175973853SYishai Hadas UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_HANDLE, 300275973853SYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD, 300375973853SYishai Hadas UVERBS_ACCESS_READ, 300475973853SYishai Hadas UA_MANDATORY), 300575973853SYishai Hadas UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_OBJ_HANDLE, 300675973853SYishai Hadas MLX5_IB_OBJECT_DEVX_OBJ, 300775973853SYishai Hadas UVERBS_ACCESS_READ, 300875973853SYishai Hadas UA_OPTIONAL), 300975973853SYishai Hadas UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_TYPE_NUM_LIST, 301075973853SYishai Hadas UVERBS_ATTR_MIN_SIZE(sizeof(u16)), 301175973853SYishai Hadas UA_MANDATORY, 301275973853SYishai Hadas UA_ALLOC_AND_COPY), 301375973853SYishai Hadas UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_COOKIE, 301475973853SYishai Hadas UVERBS_ATTR_TYPE(u64), 301575973853SYishai Hadas UA_OPTIONAL), 301675973853SYishai Hadas UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_NUM, 301775973853SYishai Hadas UVERBS_ATTR_TYPE(u32), 301875973853SYishai Hadas UA_OPTIONAL)); 301975973853SYishai Hadas 30206c61d2a5SJason Gunthorpe DECLARE_UVERBS_GLOBAL_METHODS(MLX5_IB_OBJECT_DEVX, 30217c043e90SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OTHER), 3022f6fe01b7SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_UAR), 302375973853SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_EQN), 302475973853SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT)); 30258aa8c95cSYishai Hadas 30266c61d2a5SJason Gunthorpe DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ, 30279a119cd5SJason Gunthorpe UVERBS_TYPE_ALLOC_IDR(devx_obj_cleanup), 30287efce369SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_CREATE), 3029e662e14dSYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_DESTROY), 3030e662e14dSYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_MODIFY), 3031a124edbaSYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_QUERY), 3032a124edbaSYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY)); 30337efce369SYishai Hadas 30346c61d2a5SJason Gunthorpe DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM, 30359a119cd5SJason Gunthorpe UVERBS_TYPE_ALLOC_IDR(devx_umem_cleanup), 3036aeae9457SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_REG), 3037aeae9457SYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_DEREG)); 3038aeae9457SYishai Hadas 30396bf8f22aSYishai Hadas 30406bf8f22aSYishai Hadas DECLARE_UVERBS_NAMED_METHOD( 30416bf8f22aSYishai Hadas MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC, 30426bf8f22aSYishai Hadas UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_ASYNC_CMD_FD_ALLOC_HANDLE, 30436bf8f22aSYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD, 30446bf8f22aSYishai Hadas UVERBS_ACCESS_NEW, 30456bf8f22aSYishai Hadas UA_MANDATORY)); 30466bf8f22aSYishai Hadas 30476bf8f22aSYishai Hadas DECLARE_UVERBS_NAMED_OBJECT( 30486bf8f22aSYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD, 30496bf8f22aSYishai Hadas UVERBS_TYPE_ALLOC_FD(sizeof(struct devx_async_cmd_event_file), 3050f7c8416cSJason Gunthorpe devx_async_cmd_event_destroy_uobj, 30516bf8f22aSYishai Hadas &devx_async_cmd_event_fops, "[devx_async_cmd]", 30526bf8f22aSYishai Hadas O_RDONLY), 30536bf8f22aSYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC)); 30546bf8f22aSYishai Hadas 30552afc5e1bSYishai Hadas DECLARE_UVERBS_NAMED_METHOD( 30562afc5e1bSYishai Hadas MLX5_IB_METHOD_DEVX_ASYNC_EVENT_FD_ALLOC, 30572afc5e1bSYishai Hadas UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_HANDLE, 30582afc5e1bSYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD, 30592afc5e1bSYishai Hadas UVERBS_ACCESS_NEW, 30602afc5e1bSYishai Hadas UA_MANDATORY), 30612afc5e1bSYishai Hadas UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_FLAGS, 30622afc5e1bSYishai Hadas enum mlx5_ib_uapi_devx_create_event_channel_flags, 30632afc5e1bSYishai Hadas UA_MANDATORY)); 30642afc5e1bSYishai Hadas 30652afc5e1bSYishai Hadas DECLARE_UVERBS_NAMED_OBJECT( 30662afc5e1bSYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD, 30672afc5e1bSYishai Hadas UVERBS_TYPE_ALLOC_FD(sizeof(struct devx_async_event_file), 3068f7c8416cSJason Gunthorpe devx_async_event_destroy_uobj, 30692afc5e1bSYishai Hadas &devx_async_event_fops, "[devx_async_event]", 30702afc5e1bSYishai Hadas O_RDONLY), 30712afc5e1bSYishai Hadas &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_ASYNC_EVENT_FD_ALLOC)); 30722afc5e1bSYishai Hadas 307336e235c8SJason Gunthorpe static bool devx_is_supported(struct ib_device *device) 3074c59450c4SYishai Hadas { 307536e235c8SJason Gunthorpe struct mlx5_ib_dev *dev = to_mdev(device); 307636e235c8SJason Gunthorpe 30777f575103SMark Bloch return MLX5_CAP_GEN(dev->mdev, log_max_uctx); 3078c59450c4SYishai Hadas } 307936e235c8SJason Gunthorpe 30800cbf432dSJason Gunthorpe const struct uapi_definition mlx5_ib_devx_defs[] = { 308136e235c8SJason Gunthorpe UAPI_DEF_CHAIN_OBJ_TREE_NAMED( 308236e235c8SJason Gunthorpe MLX5_IB_OBJECT_DEVX, 308336e235c8SJason Gunthorpe UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)), 308436e235c8SJason Gunthorpe UAPI_DEF_CHAIN_OBJ_TREE_NAMED( 308536e235c8SJason Gunthorpe MLX5_IB_OBJECT_DEVX_OBJ, 308636e235c8SJason Gunthorpe UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)), 308736e235c8SJason Gunthorpe UAPI_DEF_CHAIN_OBJ_TREE_NAMED( 308836e235c8SJason Gunthorpe MLX5_IB_OBJECT_DEVX_UMEM, 308936e235c8SJason Gunthorpe UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)), 30906bf8f22aSYishai Hadas UAPI_DEF_CHAIN_OBJ_TREE_NAMED( 30916bf8f22aSYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD, 30926bf8f22aSYishai Hadas UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)), 30932afc5e1bSYishai Hadas UAPI_DEF_CHAIN_OBJ_TREE_NAMED( 30942afc5e1bSYishai Hadas MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD, 30952afc5e1bSYishai Hadas UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)), 30960cbf432dSJason Gunthorpe {}, 30970cbf432dSJason Gunthorpe }; 3098