1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 /* 3 * Copyright (c) 2018, Mellanox Technologies inc. All rights reserved. 4 */ 5 6 #include <rdma/ib_user_verbs.h> 7 #include <rdma/ib_verbs.h> 8 #include <rdma/uverbs_types.h> 9 #include <rdma/uverbs_ioctl.h> 10 #include <rdma/mlx5_user_ioctl_cmds.h> 11 #include <rdma/ib_umem.h> 12 #include <rdma/uverbs_std_types.h> 13 #include <linux/mlx5/driver.h> 14 #include <linux/mlx5/fs.h> 15 #include "mlx5_ib.h" 16 17 #define UVERBS_MODULE_NAME mlx5_ib 18 #include <rdma/uverbs_named_ioctl.h> 19 20 #define MLX5_MAX_DESTROY_INBOX_SIZE_DW MLX5_ST_SZ_DW(delete_fte_in) 21 struct devx_obj { 22 struct mlx5_core_dev *mdev; 23 u64 obj_id; 24 u32 dinlen; /* destroy inbox length */ 25 u32 dinbox[MLX5_MAX_DESTROY_INBOX_SIZE_DW]; 26 }; 27 28 struct devx_umem { 29 struct mlx5_core_dev *mdev; 30 struct ib_umem *umem; 31 u32 page_offset; 32 int page_shift; 33 int ncont; 34 u32 dinlen; 35 u32 dinbox[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)]; 36 }; 37 38 struct devx_umem_reg_cmd { 39 void *in; 40 u32 inlen; 41 u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)]; 42 }; 43 44 static struct mlx5_ib_ucontext * 45 devx_ufile2uctx(const struct uverbs_attr_bundle *attrs) 46 { 47 return to_mucontext(ib_uverbs_get_ucontext(attrs)); 48 } 49 50 int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, bool is_user) 51 { 52 u32 in[MLX5_ST_SZ_DW(create_uctx_in)] = {0}; 53 u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0}; 54 void *uctx; 55 int err; 56 u16 uid; 57 u32 cap = 0; 58 59 /* 0 means not supported */ 60 if (!MLX5_CAP_GEN(dev->mdev, log_max_uctx)) 61 return -EINVAL; 62 63 uctx = MLX5_ADDR_OF(create_uctx_in, in, uctx); 64 if (is_user && capable(CAP_NET_RAW) && 65 (MLX5_CAP_GEN(dev->mdev, uctx_cap) & MLX5_UCTX_CAP_RAW_TX)) 66 cap |= MLX5_UCTX_CAP_RAW_TX; 67 68 MLX5_SET(create_uctx_in, in, opcode, MLX5_CMD_OP_CREATE_UCTX); 69 MLX5_SET(uctx, uctx, cap, cap); 70 71 err = mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out)); 72 if (err) 73 return err; 74 75 uid = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 76 return uid; 77 } 78 79 void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev, u16 uid) 80 { 81 u32 in[MLX5_ST_SZ_DW(destroy_uctx_in)] = {0}; 82 u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0}; 83 84 MLX5_SET(destroy_uctx_in, in, opcode, MLX5_CMD_OP_DESTROY_UCTX); 85 MLX5_SET(destroy_uctx_in, in, uid, uid); 86 87 mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out)); 88 } 89 90 bool mlx5_ib_devx_is_flow_dest(void *obj, int *dest_id, int *dest_type) 91 { 92 struct devx_obj *devx_obj = obj; 93 u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, opcode); 94 95 switch (opcode) { 96 case MLX5_CMD_OP_DESTROY_TIR: 97 *dest_type = MLX5_FLOW_DESTINATION_TYPE_TIR; 98 *dest_id = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, 99 obj_id); 100 return true; 101 102 case MLX5_CMD_OP_DESTROY_FLOW_TABLE: 103 *dest_type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 104 *dest_id = MLX5_GET(destroy_flow_table_in, devx_obj->dinbox, 105 table_id); 106 return true; 107 default: 108 return false; 109 } 110 } 111 112 bool mlx5_ib_devx_is_flow_counter(void *obj, u32 *counter_id) 113 { 114 struct devx_obj *devx_obj = obj; 115 u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, opcode); 116 117 if (opcode == MLX5_CMD_OP_DEALLOC_FLOW_COUNTER) { 118 *counter_id = MLX5_GET(dealloc_flow_counter_in, 119 devx_obj->dinbox, 120 flow_counter_id); 121 return true; 122 } 123 124 return false; 125 } 126 127 /* 128 * As the obj_id in the firmware is not globally unique the object type 129 * must be considered upon checking for a valid object id. 130 * For that the opcode of the creator command is encoded as part of the obj_id. 131 */ 132 static u64 get_enc_obj_id(u16 opcode, u32 obj_id) 133 { 134 return ((u64)opcode << 32) | obj_id; 135 } 136 137 static u64 devx_get_obj_id(const void *in) 138 { 139 u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 140 u64 obj_id; 141 142 switch (opcode) { 143 case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT: 144 case MLX5_CMD_OP_QUERY_GENERAL_OBJECT: 145 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_GENERAL_OBJECT, 146 MLX5_GET(general_obj_in_cmd_hdr, in, 147 obj_id)); 148 break; 149 case MLX5_CMD_OP_QUERY_MKEY: 150 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_MKEY, 151 MLX5_GET(query_mkey_in, in, 152 mkey_index)); 153 break; 154 case MLX5_CMD_OP_QUERY_CQ: 155 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_CQ, 156 MLX5_GET(query_cq_in, in, cqn)); 157 break; 158 case MLX5_CMD_OP_MODIFY_CQ: 159 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_CQ, 160 MLX5_GET(modify_cq_in, in, cqn)); 161 break; 162 case MLX5_CMD_OP_QUERY_SQ: 163 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ, 164 MLX5_GET(query_sq_in, in, sqn)); 165 break; 166 case MLX5_CMD_OP_MODIFY_SQ: 167 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ, 168 MLX5_GET(modify_sq_in, in, sqn)); 169 break; 170 case MLX5_CMD_OP_QUERY_RQ: 171 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ, 172 MLX5_GET(query_rq_in, in, rqn)); 173 break; 174 case MLX5_CMD_OP_MODIFY_RQ: 175 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ, 176 MLX5_GET(modify_rq_in, in, rqn)); 177 break; 178 case MLX5_CMD_OP_QUERY_RMP: 179 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RMP, 180 MLX5_GET(query_rmp_in, in, rmpn)); 181 break; 182 case MLX5_CMD_OP_MODIFY_RMP: 183 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RMP, 184 MLX5_GET(modify_rmp_in, in, rmpn)); 185 break; 186 case MLX5_CMD_OP_QUERY_RQT: 187 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT, 188 MLX5_GET(query_rqt_in, in, rqtn)); 189 break; 190 case MLX5_CMD_OP_MODIFY_RQT: 191 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT, 192 MLX5_GET(modify_rqt_in, in, rqtn)); 193 break; 194 case MLX5_CMD_OP_QUERY_TIR: 195 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR, 196 MLX5_GET(query_tir_in, in, tirn)); 197 break; 198 case MLX5_CMD_OP_MODIFY_TIR: 199 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR, 200 MLX5_GET(modify_tir_in, in, tirn)); 201 break; 202 case MLX5_CMD_OP_QUERY_TIS: 203 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS, 204 MLX5_GET(query_tis_in, in, tisn)); 205 break; 206 case MLX5_CMD_OP_MODIFY_TIS: 207 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS, 208 MLX5_GET(modify_tis_in, in, tisn)); 209 break; 210 case MLX5_CMD_OP_QUERY_FLOW_TABLE: 211 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_FLOW_TABLE, 212 MLX5_GET(query_flow_table_in, in, 213 table_id)); 214 break; 215 case MLX5_CMD_OP_MODIFY_FLOW_TABLE: 216 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_FLOW_TABLE, 217 MLX5_GET(modify_flow_table_in, in, 218 table_id)); 219 break; 220 case MLX5_CMD_OP_QUERY_FLOW_GROUP: 221 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_FLOW_GROUP, 222 MLX5_GET(query_flow_group_in, in, 223 group_id)); 224 break; 225 case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY: 226 obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY, 227 MLX5_GET(query_fte_in, in, 228 flow_index)); 229 break; 230 case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY: 231 obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY, 232 MLX5_GET(set_fte_in, in, flow_index)); 233 break; 234 case MLX5_CMD_OP_QUERY_Q_COUNTER: 235 obj_id = get_enc_obj_id(MLX5_CMD_OP_ALLOC_Q_COUNTER, 236 MLX5_GET(query_q_counter_in, in, 237 counter_set_id)); 238 break; 239 case MLX5_CMD_OP_QUERY_FLOW_COUNTER: 240 obj_id = get_enc_obj_id(MLX5_CMD_OP_ALLOC_FLOW_COUNTER, 241 MLX5_GET(query_flow_counter_in, in, 242 flow_counter_id)); 243 break; 244 case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT: 245 obj_id = get_enc_obj_id(MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT, 246 MLX5_GET(general_obj_in_cmd_hdr, in, 247 obj_id)); 248 break; 249 case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT: 250 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT, 251 MLX5_GET(query_scheduling_element_in, 252 in, scheduling_element_id)); 253 break; 254 case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT: 255 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT, 256 MLX5_GET(modify_scheduling_element_in, 257 in, scheduling_element_id)); 258 break; 259 case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT: 260 obj_id = get_enc_obj_id(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT, 261 MLX5_GET(add_vxlan_udp_dport_in, in, 262 vxlan_udp_port)); 263 break; 264 case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY: 265 obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_L2_TABLE_ENTRY, 266 MLX5_GET(query_l2_table_entry_in, in, 267 table_index)); 268 break; 269 case MLX5_CMD_OP_SET_L2_TABLE_ENTRY: 270 obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_L2_TABLE_ENTRY, 271 MLX5_GET(set_l2_table_entry_in, in, 272 table_index)); 273 break; 274 case MLX5_CMD_OP_QUERY_QP: 275 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 276 MLX5_GET(query_qp_in, in, qpn)); 277 break; 278 case MLX5_CMD_OP_RST2INIT_QP: 279 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 280 MLX5_GET(rst2init_qp_in, in, qpn)); 281 break; 282 case MLX5_CMD_OP_INIT2RTR_QP: 283 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 284 MLX5_GET(init2rtr_qp_in, in, qpn)); 285 break; 286 case MLX5_CMD_OP_RTR2RTS_QP: 287 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 288 MLX5_GET(rtr2rts_qp_in, in, qpn)); 289 break; 290 case MLX5_CMD_OP_RTS2RTS_QP: 291 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 292 MLX5_GET(rts2rts_qp_in, in, qpn)); 293 break; 294 case MLX5_CMD_OP_SQERR2RTS_QP: 295 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 296 MLX5_GET(sqerr2rts_qp_in, in, qpn)); 297 break; 298 case MLX5_CMD_OP_2ERR_QP: 299 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 300 MLX5_GET(qp_2err_in, in, qpn)); 301 break; 302 case MLX5_CMD_OP_2RST_QP: 303 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 304 MLX5_GET(qp_2rst_in, in, qpn)); 305 break; 306 case MLX5_CMD_OP_QUERY_DCT: 307 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT, 308 MLX5_GET(query_dct_in, in, dctn)); 309 break; 310 case MLX5_CMD_OP_QUERY_XRQ: 311 case MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY: 312 case MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS: 313 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRQ, 314 MLX5_GET(query_xrq_in, in, xrqn)); 315 break; 316 case MLX5_CMD_OP_QUERY_XRC_SRQ: 317 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRC_SRQ, 318 MLX5_GET(query_xrc_srq_in, in, 319 xrc_srqn)); 320 break; 321 case MLX5_CMD_OP_ARM_XRC_SRQ: 322 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRC_SRQ, 323 MLX5_GET(arm_xrc_srq_in, in, xrc_srqn)); 324 break; 325 case MLX5_CMD_OP_QUERY_SRQ: 326 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SRQ, 327 MLX5_GET(query_srq_in, in, srqn)); 328 break; 329 case MLX5_CMD_OP_ARM_RQ: 330 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ, 331 MLX5_GET(arm_rq_in, in, srq_number)); 332 break; 333 case MLX5_CMD_OP_DRAIN_DCT: 334 case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION: 335 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT, 336 MLX5_GET(drain_dct_in, in, dctn)); 337 break; 338 case MLX5_CMD_OP_ARM_XRQ: 339 case MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY: 340 obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRQ, 341 MLX5_GET(arm_xrq_in, in, xrqn)); 342 break; 343 case MLX5_CMD_OP_QUERY_PACKET_REFORMAT_CONTEXT: 344 obj_id = get_enc_obj_id 345 (MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT, 346 MLX5_GET(query_packet_reformat_context_in, 347 in, packet_reformat_id)); 348 break; 349 default: 350 obj_id = 0; 351 } 352 353 return obj_id; 354 } 355 356 static bool devx_is_valid_obj_id(struct ib_uobject *uobj, const void *in) 357 { 358 u64 obj_id = devx_get_obj_id(in); 359 360 if (!obj_id) 361 return false; 362 363 switch (uobj_get_object_id(uobj)) { 364 case UVERBS_OBJECT_CQ: 365 return get_enc_obj_id(MLX5_CMD_OP_CREATE_CQ, 366 to_mcq(uobj->object)->mcq.cqn) == 367 obj_id; 368 369 case UVERBS_OBJECT_SRQ: 370 { 371 struct mlx5_core_srq *srq = &(to_msrq(uobj->object)->msrq); 372 struct mlx5_ib_dev *dev = to_mdev(uobj->context->device); 373 u16 opcode; 374 375 switch (srq->common.res) { 376 case MLX5_RES_XSRQ: 377 opcode = MLX5_CMD_OP_CREATE_XRC_SRQ; 378 break; 379 case MLX5_RES_XRQ: 380 opcode = MLX5_CMD_OP_CREATE_XRQ; 381 break; 382 default: 383 if (!dev->mdev->issi) 384 opcode = MLX5_CMD_OP_CREATE_SRQ; 385 else 386 opcode = MLX5_CMD_OP_CREATE_RMP; 387 } 388 389 return get_enc_obj_id(opcode, 390 to_msrq(uobj->object)->msrq.srqn) == 391 obj_id; 392 } 393 394 case UVERBS_OBJECT_QP: 395 { 396 struct mlx5_ib_qp *qp = to_mqp(uobj->object); 397 enum ib_qp_type qp_type = qp->ibqp.qp_type; 398 399 if (qp_type == IB_QPT_RAW_PACKET || 400 (qp->flags & MLX5_IB_QP_UNDERLAY)) { 401 struct mlx5_ib_raw_packet_qp *raw_packet_qp = 402 &qp->raw_packet_qp; 403 struct mlx5_ib_rq *rq = &raw_packet_qp->rq; 404 struct mlx5_ib_sq *sq = &raw_packet_qp->sq; 405 406 return (get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ, 407 rq->base.mqp.qpn) == obj_id || 408 get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ, 409 sq->base.mqp.qpn) == obj_id || 410 get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR, 411 rq->tirn) == obj_id || 412 get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS, 413 sq->tisn) == obj_id); 414 } 415 416 if (qp_type == MLX5_IB_QPT_DCT) 417 return get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT, 418 qp->dct.mdct.mqp.qpn) == obj_id; 419 420 return get_enc_obj_id(MLX5_CMD_OP_CREATE_QP, 421 qp->ibqp.qp_num) == obj_id; 422 } 423 424 case UVERBS_OBJECT_WQ: 425 return get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ, 426 to_mrwq(uobj->object)->core_qp.qpn) == 427 obj_id; 428 429 case UVERBS_OBJECT_RWQ_IND_TBL: 430 return get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT, 431 to_mrwq_ind_table(uobj->object)->rqtn) == 432 obj_id; 433 434 case MLX5_IB_OBJECT_DEVX_OBJ: 435 return ((struct devx_obj *)uobj->object)->obj_id == obj_id; 436 437 default: 438 return false; 439 } 440 } 441 442 static void devx_set_umem_valid(const void *in) 443 { 444 u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 445 446 switch (opcode) { 447 case MLX5_CMD_OP_CREATE_MKEY: 448 MLX5_SET(create_mkey_in, in, mkey_umem_valid, 1); 449 break; 450 case MLX5_CMD_OP_CREATE_CQ: 451 { 452 void *cqc; 453 454 MLX5_SET(create_cq_in, in, cq_umem_valid, 1); 455 cqc = MLX5_ADDR_OF(create_cq_in, in, cq_context); 456 MLX5_SET(cqc, cqc, dbr_umem_valid, 1); 457 break; 458 } 459 case MLX5_CMD_OP_CREATE_QP: 460 { 461 void *qpc; 462 463 qpc = MLX5_ADDR_OF(create_qp_in, in, qpc); 464 MLX5_SET(qpc, qpc, dbr_umem_valid, 1); 465 MLX5_SET(create_qp_in, in, wq_umem_valid, 1); 466 break; 467 } 468 469 case MLX5_CMD_OP_CREATE_RQ: 470 { 471 void *rqc, *wq; 472 473 rqc = MLX5_ADDR_OF(create_rq_in, in, ctx); 474 wq = MLX5_ADDR_OF(rqc, rqc, wq); 475 MLX5_SET(wq, wq, dbr_umem_valid, 1); 476 MLX5_SET(wq, wq, wq_umem_valid, 1); 477 break; 478 } 479 480 case MLX5_CMD_OP_CREATE_SQ: 481 { 482 void *sqc, *wq; 483 484 sqc = MLX5_ADDR_OF(create_sq_in, in, ctx); 485 wq = MLX5_ADDR_OF(sqc, sqc, wq); 486 MLX5_SET(wq, wq, dbr_umem_valid, 1); 487 MLX5_SET(wq, wq, wq_umem_valid, 1); 488 break; 489 } 490 491 case MLX5_CMD_OP_MODIFY_CQ: 492 MLX5_SET(modify_cq_in, in, cq_umem_valid, 1); 493 break; 494 495 case MLX5_CMD_OP_CREATE_RMP: 496 { 497 void *rmpc, *wq; 498 499 rmpc = MLX5_ADDR_OF(create_rmp_in, in, ctx); 500 wq = MLX5_ADDR_OF(rmpc, rmpc, wq); 501 MLX5_SET(wq, wq, dbr_umem_valid, 1); 502 MLX5_SET(wq, wq, wq_umem_valid, 1); 503 break; 504 } 505 506 case MLX5_CMD_OP_CREATE_XRQ: 507 { 508 void *xrqc, *wq; 509 510 xrqc = MLX5_ADDR_OF(create_xrq_in, in, xrq_context); 511 wq = MLX5_ADDR_OF(xrqc, xrqc, wq); 512 MLX5_SET(wq, wq, dbr_umem_valid, 1); 513 MLX5_SET(wq, wq, wq_umem_valid, 1); 514 break; 515 } 516 517 case MLX5_CMD_OP_CREATE_XRC_SRQ: 518 { 519 void *xrc_srqc; 520 521 MLX5_SET(create_xrc_srq_in, in, xrc_srq_umem_valid, 1); 522 xrc_srqc = MLX5_ADDR_OF(create_xrc_srq_in, in, 523 xrc_srq_context_entry); 524 MLX5_SET(xrc_srqc, xrc_srqc, dbr_umem_valid, 1); 525 break; 526 } 527 528 default: 529 return; 530 } 531 } 532 533 static bool devx_is_obj_create_cmd(const void *in, u16 *opcode) 534 { 535 *opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 536 537 switch (*opcode) { 538 case MLX5_CMD_OP_CREATE_GENERAL_OBJECT: 539 case MLX5_CMD_OP_CREATE_MKEY: 540 case MLX5_CMD_OP_CREATE_CQ: 541 case MLX5_CMD_OP_ALLOC_PD: 542 case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN: 543 case MLX5_CMD_OP_CREATE_RMP: 544 case MLX5_CMD_OP_CREATE_SQ: 545 case MLX5_CMD_OP_CREATE_RQ: 546 case MLX5_CMD_OP_CREATE_RQT: 547 case MLX5_CMD_OP_CREATE_TIR: 548 case MLX5_CMD_OP_CREATE_TIS: 549 case MLX5_CMD_OP_ALLOC_Q_COUNTER: 550 case MLX5_CMD_OP_CREATE_FLOW_TABLE: 551 case MLX5_CMD_OP_CREATE_FLOW_GROUP: 552 case MLX5_CMD_OP_ALLOC_FLOW_COUNTER: 553 case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT: 554 case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT: 555 case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT: 556 case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT: 557 case MLX5_CMD_OP_SET_L2_TABLE_ENTRY: 558 case MLX5_CMD_OP_CREATE_QP: 559 case MLX5_CMD_OP_CREATE_SRQ: 560 case MLX5_CMD_OP_CREATE_XRC_SRQ: 561 case MLX5_CMD_OP_CREATE_DCT: 562 case MLX5_CMD_OP_CREATE_XRQ: 563 case MLX5_CMD_OP_ATTACH_TO_MCG: 564 case MLX5_CMD_OP_ALLOC_XRCD: 565 return true; 566 case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY: 567 { 568 u16 op_mod = MLX5_GET(set_fte_in, in, op_mod); 569 if (op_mod == 0) 570 return true; 571 return false; 572 } 573 default: 574 return false; 575 } 576 } 577 578 static bool devx_is_obj_modify_cmd(const void *in) 579 { 580 u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 581 582 switch (opcode) { 583 case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT: 584 case MLX5_CMD_OP_MODIFY_CQ: 585 case MLX5_CMD_OP_MODIFY_RMP: 586 case MLX5_CMD_OP_MODIFY_SQ: 587 case MLX5_CMD_OP_MODIFY_RQ: 588 case MLX5_CMD_OP_MODIFY_RQT: 589 case MLX5_CMD_OP_MODIFY_TIR: 590 case MLX5_CMD_OP_MODIFY_TIS: 591 case MLX5_CMD_OP_MODIFY_FLOW_TABLE: 592 case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT: 593 case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT: 594 case MLX5_CMD_OP_SET_L2_TABLE_ENTRY: 595 case MLX5_CMD_OP_RST2INIT_QP: 596 case MLX5_CMD_OP_INIT2RTR_QP: 597 case MLX5_CMD_OP_RTR2RTS_QP: 598 case MLX5_CMD_OP_RTS2RTS_QP: 599 case MLX5_CMD_OP_SQERR2RTS_QP: 600 case MLX5_CMD_OP_2ERR_QP: 601 case MLX5_CMD_OP_2RST_QP: 602 case MLX5_CMD_OP_ARM_XRC_SRQ: 603 case MLX5_CMD_OP_ARM_RQ: 604 case MLX5_CMD_OP_DRAIN_DCT: 605 case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION: 606 case MLX5_CMD_OP_ARM_XRQ: 607 case MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY: 608 return true; 609 case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY: 610 { 611 u16 op_mod = MLX5_GET(set_fte_in, in, op_mod); 612 613 if (op_mod == 1) 614 return true; 615 return false; 616 } 617 default: 618 return false; 619 } 620 } 621 622 static bool devx_is_obj_query_cmd(const void *in) 623 { 624 u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 625 626 switch (opcode) { 627 case MLX5_CMD_OP_QUERY_GENERAL_OBJECT: 628 case MLX5_CMD_OP_QUERY_MKEY: 629 case MLX5_CMD_OP_QUERY_CQ: 630 case MLX5_CMD_OP_QUERY_RMP: 631 case MLX5_CMD_OP_QUERY_SQ: 632 case MLX5_CMD_OP_QUERY_RQ: 633 case MLX5_CMD_OP_QUERY_RQT: 634 case MLX5_CMD_OP_QUERY_TIR: 635 case MLX5_CMD_OP_QUERY_TIS: 636 case MLX5_CMD_OP_QUERY_Q_COUNTER: 637 case MLX5_CMD_OP_QUERY_FLOW_TABLE: 638 case MLX5_CMD_OP_QUERY_FLOW_GROUP: 639 case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY: 640 case MLX5_CMD_OP_QUERY_FLOW_COUNTER: 641 case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT: 642 case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT: 643 case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY: 644 case MLX5_CMD_OP_QUERY_QP: 645 case MLX5_CMD_OP_QUERY_SRQ: 646 case MLX5_CMD_OP_QUERY_XRC_SRQ: 647 case MLX5_CMD_OP_QUERY_DCT: 648 case MLX5_CMD_OP_QUERY_XRQ: 649 case MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY: 650 case MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS: 651 case MLX5_CMD_OP_QUERY_PACKET_REFORMAT_CONTEXT: 652 return true; 653 default: 654 return false; 655 } 656 } 657 658 static bool devx_is_whitelist_cmd(void *in) 659 { 660 u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 661 662 switch (opcode) { 663 case MLX5_CMD_OP_QUERY_HCA_CAP: 664 case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT: 665 return true; 666 default: 667 return false; 668 } 669 } 670 671 static int devx_get_uid(struct mlx5_ib_ucontext *c, void *cmd_in) 672 { 673 if (devx_is_whitelist_cmd(cmd_in)) { 674 struct mlx5_ib_dev *dev; 675 676 if (c->devx_uid) 677 return c->devx_uid; 678 679 dev = to_mdev(c->ibucontext.device); 680 if (dev->devx_whitelist_uid) 681 return dev->devx_whitelist_uid; 682 683 return -EOPNOTSUPP; 684 } 685 686 if (!c->devx_uid) 687 return -EINVAL; 688 689 return c->devx_uid; 690 } 691 static bool devx_is_general_cmd(void *in) 692 { 693 u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); 694 695 if (opcode >= MLX5_CMD_OP_GENERAL_START && 696 opcode < MLX5_CMD_OP_GENERAL_END) 697 return true; 698 699 switch (opcode) { 700 case MLX5_CMD_OP_QUERY_HCA_CAP: 701 case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT: 702 case MLX5_CMD_OP_QUERY_VPORT_STATE: 703 case MLX5_CMD_OP_QUERY_ADAPTER: 704 case MLX5_CMD_OP_QUERY_ISSI: 705 case MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT: 706 case MLX5_CMD_OP_QUERY_ROCE_ADDRESS: 707 case MLX5_CMD_OP_QUERY_VNIC_ENV: 708 case MLX5_CMD_OP_QUERY_VPORT_COUNTER: 709 case MLX5_CMD_OP_GET_DROPPED_PACKET_LOG: 710 case MLX5_CMD_OP_NOP: 711 case MLX5_CMD_OP_QUERY_CONG_STATUS: 712 case MLX5_CMD_OP_QUERY_CONG_PARAMS: 713 case MLX5_CMD_OP_QUERY_CONG_STATISTICS: 714 return true; 715 default: 716 return false; 717 } 718 } 719 720 static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_EQN)( 721 struct uverbs_attr_bundle *attrs) 722 { 723 struct mlx5_ib_ucontext *c; 724 struct mlx5_ib_dev *dev; 725 int user_vector; 726 int dev_eqn; 727 unsigned int irqn; 728 int err; 729 730 if (uverbs_copy_from(&user_vector, attrs, 731 MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC)) 732 return -EFAULT; 733 734 c = devx_ufile2uctx(attrs); 735 if (IS_ERR(c)) 736 return PTR_ERR(c); 737 dev = to_mdev(c->ibucontext.device); 738 739 err = mlx5_vector2eqn(dev->mdev, user_vector, &dev_eqn, &irqn); 740 if (err < 0) 741 return err; 742 743 if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN, 744 &dev_eqn, sizeof(dev_eqn))) 745 return -EFAULT; 746 747 return 0; 748 } 749 750 /* 751 *Security note: 752 * The hardware protection mechanism works like this: Each device object that 753 * is subject to UAR doorbells (QP/SQ/CQ) gets a UAR ID (called uar_page in 754 * the device specification manual) upon its creation. Then upon doorbell, 755 * hardware fetches the object context for which the doorbell was rang, and 756 * validates that the UAR through which the DB was rang matches the UAR ID 757 * of the object. 758 * If no match the doorbell is silently ignored by the hardware. Of course, 759 * the user cannot ring a doorbell on a UAR that was not mapped to it. 760 * Now in devx, as the devx kernel does not manipulate the QP/SQ/CQ command 761 * mailboxes (except tagging them with UID), we expose to the user its UAR 762 * ID, so it can embed it in these objects in the expected specification 763 * format. So the only thing the user can do is hurt itself by creating a 764 * QP/SQ/CQ with a UAR ID other than his, and then in this case other users 765 * may ring a doorbell on its objects. 766 * The consequence of that will be that another user can schedule a QP/SQ 767 * of the buggy user for execution (just insert it to the hardware schedule 768 * queue or arm its CQ for event generation), no further harm is expected. 769 */ 770 static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_UAR)( 771 struct uverbs_attr_bundle *attrs) 772 { 773 struct mlx5_ib_ucontext *c; 774 struct mlx5_ib_dev *dev; 775 u32 user_idx; 776 s32 dev_idx; 777 778 c = devx_ufile2uctx(attrs); 779 if (IS_ERR(c)) 780 return PTR_ERR(c); 781 dev = to_mdev(c->ibucontext.device); 782 783 if (uverbs_copy_from(&user_idx, attrs, 784 MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX)) 785 return -EFAULT; 786 787 dev_idx = bfregn_to_uar_index(dev, &c->bfregi, user_idx, true); 788 if (dev_idx < 0) 789 return dev_idx; 790 791 if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX, 792 &dev_idx, sizeof(dev_idx))) 793 return -EFAULT; 794 795 return 0; 796 } 797 798 static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)( 799 struct uverbs_attr_bundle *attrs) 800 { 801 struct mlx5_ib_ucontext *c; 802 struct mlx5_ib_dev *dev; 803 void *cmd_in = uverbs_attr_get_alloced_ptr( 804 attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN); 805 int cmd_out_len = uverbs_attr_get_len(attrs, 806 MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT); 807 void *cmd_out; 808 int err; 809 int uid; 810 811 c = devx_ufile2uctx(attrs); 812 if (IS_ERR(c)) 813 return PTR_ERR(c); 814 dev = to_mdev(c->ibucontext.device); 815 816 uid = devx_get_uid(c, cmd_in); 817 if (uid < 0) 818 return uid; 819 820 /* Only white list of some general HCA commands are allowed for this method. */ 821 if (!devx_is_general_cmd(cmd_in)) 822 return -EINVAL; 823 824 cmd_out = uverbs_zalloc(attrs, cmd_out_len); 825 if (IS_ERR(cmd_out)) 826 return PTR_ERR(cmd_out); 827 828 MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); 829 err = mlx5_cmd_exec(dev->mdev, cmd_in, 830 uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN), 831 cmd_out, cmd_out_len); 832 if (err) 833 return err; 834 835 return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT, cmd_out, 836 cmd_out_len); 837 } 838 839 static void devx_obj_build_destroy_cmd(void *in, void *out, void *din, 840 u32 *dinlen, 841 u32 *obj_id) 842 { 843 u16 obj_type = MLX5_GET(general_obj_in_cmd_hdr, in, obj_type); 844 u16 uid = MLX5_GET(general_obj_in_cmd_hdr, in, uid); 845 846 *obj_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 847 *dinlen = MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr); 848 849 MLX5_SET(general_obj_in_cmd_hdr, din, obj_id, *obj_id); 850 MLX5_SET(general_obj_in_cmd_hdr, din, uid, uid); 851 852 switch (MLX5_GET(general_obj_in_cmd_hdr, in, opcode)) { 853 case MLX5_CMD_OP_CREATE_GENERAL_OBJECT: 854 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT); 855 MLX5_SET(general_obj_in_cmd_hdr, din, obj_type, obj_type); 856 break; 857 858 case MLX5_CMD_OP_CREATE_UMEM: 859 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 860 MLX5_CMD_OP_DESTROY_UMEM); 861 break; 862 case MLX5_CMD_OP_CREATE_MKEY: 863 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_MKEY); 864 break; 865 case MLX5_CMD_OP_CREATE_CQ: 866 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_CQ); 867 break; 868 case MLX5_CMD_OP_ALLOC_PD: 869 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DEALLOC_PD); 870 break; 871 case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN: 872 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 873 MLX5_CMD_OP_DEALLOC_TRANSPORT_DOMAIN); 874 break; 875 case MLX5_CMD_OP_CREATE_RMP: 876 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RMP); 877 break; 878 case MLX5_CMD_OP_CREATE_SQ: 879 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_SQ); 880 break; 881 case MLX5_CMD_OP_CREATE_RQ: 882 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RQ); 883 break; 884 case MLX5_CMD_OP_CREATE_RQT: 885 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RQT); 886 break; 887 case MLX5_CMD_OP_CREATE_TIR: 888 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIR); 889 break; 890 case MLX5_CMD_OP_CREATE_TIS: 891 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIS); 892 break; 893 case MLX5_CMD_OP_ALLOC_Q_COUNTER: 894 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 895 MLX5_CMD_OP_DEALLOC_Q_COUNTER); 896 break; 897 case MLX5_CMD_OP_CREATE_FLOW_TABLE: 898 *dinlen = MLX5_ST_SZ_BYTES(destroy_flow_table_in); 899 *obj_id = MLX5_GET(create_flow_table_out, out, table_id); 900 MLX5_SET(destroy_flow_table_in, din, other_vport, 901 MLX5_GET(create_flow_table_in, in, other_vport)); 902 MLX5_SET(destroy_flow_table_in, din, vport_number, 903 MLX5_GET(create_flow_table_in, in, vport_number)); 904 MLX5_SET(destroy_flow_table_in, din, table_type, 905 MLX5_GET(create_flow_table_in, in, table_type)); 906 MLX5_SET(destroy_flow_table_in, din, table_id, *obj_id); 907 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 908 MLX5_CMD_OP_DESTROY_FLOW_TABLE); 909 break; 910 case MLX5_CMD_OP_CREATE_FLOW_GROUP: 911 *dinlen = MLX5_ST_SZ_BYTES(destroy_flow_group_in); 912 *obj_id = MLX5_GET(create_flow_group_out, out, group_id); 913 MLX5_SET(destroy_flow_group_in, din, other_vport, 914 MLX5_GET(create_flow_group_in, in, other_vport)); 915 MLX5_SET(destroy_flow_group_in, din, vport_number, 916 MLX5_GET(create_flow_group_in, in, vport_number)); 917 MLX5_SET(destroy_flow_group_in, din, table_type, 918 MLX5_GET(create_flow_group_in, in, table_type)); 919 MLX5_SET(destroy_flow_group_in, din, table_id, 920 MLX5_GET(create_flow_group_in, in, table_id)); 921 MLX5_SET(destroy_flow_group_in, din, group_id, *obj_id); 922 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 923 MLX5_CMD_OP_DESTROY_FLOW_GROUP); 924 break; 925 case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY: 926 *dinlen = MLX5_ST_SZ_BYTES(delete_fte_in); 927 *obj_id = MLX5_GET(set_fte_in, in, flow_index); 928 MLX5_SET(delete_fte_in, din, other_vport, 929 MLX5_GET(set_fte_in, in, other_vport)); 930 MLX5_SET(delete_fte_in, din, vport_number, 931 MLX5_GET(set_fte_in, in, vport_number)); 932 MLX5_SET(delete_fte_in, din, table_type, 933 MLX5_GET(set_fte_in, in, table_type)); 934 MLX5_SET(delete_fte_in, din, table_id, 935 MLX5_GET(set_fte_in, in, table_id)); 936 MLX5_SET(delete_fte_in, din, flow_index, *obj_id); 937 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 938 MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY); 939 break; 940 case MLX5_CMD_OP_ALLOC_FLOW_COUNTER: 941 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 942 MLX5_CMD_OP_DEALLOC_FLOW_COUNTER); 943 break; 944 case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT: 945 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 946 MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT); 947 break; 948 case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT: 949 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 950 MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT); 951 break; 952 case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT: 953 *dinlen = MLX5_ST_SZ_BYTES(destroy_scheduling_element_in); 954 *obj_id = MLX5_GET(create_scheduling_element_out, out, 955 scheduling_element_id); 956 MLX5_SET(destroy_scheduling_element_in, din, 957 scheduling_hierarchy, 958 MLX5_GET(create_scheduling_element_in, in, 959 scheduling_hierarchy)); 960 MLX5_SET(destroy_scheduling_element_in, din, 961 scheduling_element_id, *obj_id); 962 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 963 MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT); 964 break; 965 case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT: 966 *dinlen = MLX5_ST_SZ_BYTES(delete_vxlan_udp_dport_in); 967 *obj_id = MLX5_GET(add_vxlan_udp_dport_in, in, vxlan_udp_port); 968 MLX5_SET(delete_vxlan_udp_dport_in, din, vxlan_udp_port, *obj_id); 969 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 970 MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT); 971 break; 972 case MLX5_CMD_OP_SET_L2_TABLE_ENTRY: 973 *dinlen = MLX5_ST_SZ_BYTES(delete_l2_table_entry_in); 974 *obj_id = MLX5_GET(set_l2_table_entry_in, in, table_index); 975 MLX5_SET(delete_l2_table_entry_in, din, table_index, *obj_id); 976 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 977 MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY); 978 break; 979 case MLX5_CMD_OP_CREATE_QP: 980 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_QP); 981 break; 982 case MLX5_CMD_OP_CREATE_SRQ: 983 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_SRQ); 984 break; 985 case MLX5_CMD_OP_CREATE_XRC_SRQ: 986 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, 987 MLX5_CMD_OP_DESTROY_XRC_SRQ); 988 break; 989 case MLX5_CMD_OP_CREATE_DCT: 990 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_DCT); 991 break; 992 case MLX5_CMD_OP_CREATE_XRQ: 993 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_XRQ); 994 break; 995 case MLX5_CMD_OP_ATTACH_TO_MCG: 996 *dinlen = MLX5_ST_SZ_BYTES(detach_from_mcg_in); 997 MLX5_SET(detach_from_mcg_in, din, qpn, 998 MLX5_GET(attach_to_mcg_in, in, qpn)); 999 memcpy(MLX5_ADDR_OF(detach_from_mcg_in, din, multicast_gid), 1000 MLX5_ADDR_OF(attach_to_mcg_in, in, multicast_gid), 1001 MLX5_FLD_SZ_BYTES(attach_to_mcg_in, multicast_gid)); 1002 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DETACH_FROM_MCG); 1003 break; 1004 case MLX5_CMD_OP_ALLOC_XRCD: 1005 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DEALLOC_XRCD); 1006 break; 1007 default: 1008 /* The entry must match to one of the devx_is_obj_create_cmd */ 1009 WARN_ON(true); 1010 break; 1011 } 1012 } 1013 1014 static int devx_obj_cleanup(struct ib_uobject *uobject, 1015 enum rdma_remove_reason why) 1016 { 1017 u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)]; 1018 struct devx_obj *obj = uobject->object; 1019 int ret; 1020 1021 ret = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out)); 1022 if (ib_is_destroy_retryable(ret, why, uobject)) 1023 return ret; 1024 1025 kfree(obj); 1026 return ret; 1027 } 1028 1029 static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)( 1030 struct uverbs_attr_bundle *attrs) 1031 { 1032 void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN); 1033 int cmd_out_len = uverbs_attr_get_len(attrs, 1034 MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT); 1035 void *cmd_out; 1036 struct ib_uobject *uobj = uverbs_attr_get_uobject( 1037 attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE); 1038 struct mlx5_ib_ucontext *c = to_mucontext(uobj->context); 1039 struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device); 1040 u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)]; 1041 struct devx_obj *obj; 1042 int err; 1043 int uid; 1044 u32 obj_id; 1045 u16 opcode; 1046 1047 uid = devx_get_uid(c, cmd_in); 1048 if (uid < 0) 1049 return uid; 1050 1051 if (!devx_is_obj_create_cmd(cmd_in, &opcode)) 1052 return -EINVAL; 1053 1054 cmd_out = uverbs_zalloc(attrs, cmd_out_len); 1055 if (IS_ERR(cmd_out)) 1056 return PTR_ERR(cmd_out); 1057 1058 obj = kzalloc(sizeof(struct devx_obj), GFP_KERNEL); 1059 if (!obj) 1060 return -ENOMEM; 1061 1062 MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); 1063 devx_set_umem_valid(cmd_in); 1064 1065 err = mlx5_cmd_exec(dev->mdev, cmd_in, 1066 uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN), 1067 cmd_out, cmd_out_len); 1068 if (err) 1069 goto obj_free; 1070 1071 uobj->object = obj; 1072 obj->mdev = dev->mdev; 1073 devx_obj_build_destroy_cmd(cmd_in, cmd_out, obj->dinbox, &obj->dinlen, 1074 &obj_id); 1075 WARN_ON(obj->dinlen > MLX5_MAX_DESTROY_INBOX_SIZE_DW * sizeof(u32)); 1076 1077 err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT, cmd_out, cmd_out_len); 1078 if (err) 1079 goto obj_destroy; 1080 1081 obj->obj_id = get_enc_obj_id(opcode, obj_id); 1082 return 0; 1083 1084 obj_destroy: 1085 mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out)); 1086 obj_free: 1087 kfree(obj); 1088 return err; 1089 } 1090 1091 static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_MODIFY)( 1092 struct uverbs_attr_bundle *attrs) 1093 { 1094 void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN); 1095 int cmd_out_len = uverbs_attr_get_len(attrs, 1096 MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT); 1097 struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs, 1098 MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE); 1099 struct mlx5_ib_ucontext *c = to_mucontext(uobj->context); 1100 struct mlx5_ib_dev *mdev = to_mdev(uobj->context->device); 1101 void *cmd_out; 1102 int err; 1103 int uid; 1104 1105 uid = devx_get_uid(c, cmd_in); 1106 if (uid < 0) 1107 return uid; 1108 1109 if (!devx_is_obj_modify_cmd(cmd_in)) 1110 return -EINVAL; 1111 1112 if (!devx_is_valid_obj_id(uobj, cmd_in)) 1113 return -EINVAL; 1114 1115 cmd_out = uverbs_zalloc(attrs, cmd_out_len); 1116 if (IS_ERR(cmd_out)) 1117 return PTR_ERR(cmd_out); 1118 1119 MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); 1120 devx_set_umem_valid(cmd_in); 1121 1122 err = mlx5_cmd_exec(mdev->mdev, cmd_in, 1123 uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN), 1124 cmd_out, cmd_out_len); 1125 if (err) 1126 return err; 1127 1128 return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT, 1129 cmd_out, cmd_out_len); 1130 } 1131 1132 static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)( 1133 struct uverbs_attr_bundle *attrs) 1134 { 1135 void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN); 1136 int cmd_out_len = uverbs_attr_get_len(attrs, 1137 MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT); 1138 struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs, 1139 MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE); 1140 struct mlx5_ib_ucontext *c = to_mucontext(uobj->context); 1141 void *cmd_out; 1142 int err; 1143 int uid; 1144 struct mlx5_ib_dev *mdev = to_mdev(uobj->context->device); 1145 1146 uid = devx_get_uid(c, cmd_in); 1147 if (uid < 0) 1148 return uid; 1149 1150 if (!devx_is_obj_query_cmd(cmd_in)) 1151 return -EINVAL; 1152 1153 if (!devx_is_valid_obj_id(uobj, cmd_in)) 1154 return -EINVAL; 1155 1156 cmd_out = uverbs_zalloc(attrs, cmd_out_len); 1157 if (IS_ERR(cmd_out)) 1158 return PTR_ERR(cmd_out); 1159 1160 MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); 1161 err = mlx5_cmd_exec(mdev->mdev, cmd_in, 1162 uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN), 1163 cmd_out, cmd_out_len); 1164 if (err) 1165 return err; 1166 1167 return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT, 1168 cmd_out, cmd_out_len); 1169 } 1170 1171 static int devx_umem_get(struct mlx5_ib_dev *dev, struct ib_ucontext *ucontext, 1172 struct uverbs_attr_bundle *attrs, 1173 struct devx_umem *obj) 1174 { 1175 u64 addr; 1176 size_t size; 1177 u32 access; 1178 int npages; 1179 int err; 1180 u32 page_mask; 1181 1182 if (uverbs_copy_from(&addr, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR) || 1183 uverbs_copy_from(&size, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_LEN)) 1184 return -EFAULT; 1185 1186 err = uverbs_get_flags32(&access, attrs, 1187 MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS, 1188 IB_ACCESS_LOCAL_WRITE | 1189 IB_ACCESS_REMOTE_WRITE | 1190 IB_ACCESS_REMOTE_READ); 1191 if (err) 1192 return err; 1193 1194 err = ib_check_mr_access(access); 1195 if (err) 1196 return err; 1197 1198 obj->umem = ib_umem_get(ucontext, addr, size, access, 0); 1199 if (IS_ERR(obj->umem)) 1200 return PTR_ERR(obj->umem); 1201 1202 mlx5_ib_cont_pages(obj->umem, obj->umem->address, 1203 MLX5_MKEY_PAGE_SHIFT_MASK, &npages, 1204 &obj->page_shift, &obj->ncont, NULL); 1205 1206 if (!npages) { 1207 ib_umem_release(obj->umem); 1208 return -EINVAL; 1209 } 1210 1211 page_mask = (1 << obj->page_shift) - 1; 1212 obj->page_offset = obj->umem->address & page_mask; 1213 1214 return 0; 1215 } 1216 1217 static int devx_umem_reg_cmd_alloc(struct uverbs_attr_bundle *attrs, 1218 struct devx_umem *obj, 1219 struct devx_umem_reg_cmd *cmd) 1220 { 1221 cmd->inlen = MLX5_ST_SZ_BYTES(create_umem_in) + 1222 (MLX5_ST_SZ_BYTES(mtt) * obj->ncont); 1223 cmd->in = uverbs_zalloc(attrs, cmd->inlen); 1224 return PTR_ERR_OR_ZERO(cmd->in); 1225 } 1226 1227 static void devx_umem_reg_cmd_build(struct mlx5_ib_dev *dev, 1228 struct devx_umem *obj, 1229 struct devx_umem_reg_cmd *cmd) 1230 { 1231 void *umem; 1232 __be64 *mtt; 1233 1234 umem = MLX5_ADDR_OF(create_umem_in, cmd->in, umem); 1235 mtt = (__be64 *)MLX5_ADDR_OF(umem, umem, mtt); 1236 1237 MLX5_SET(create_umem_in, cmd->in, opcode, MLX5_CMD_OP_CREATE_UMEM); 1238 MLX5_SET64(umem, umem, num_of_mtt, obj->ncont); 1239 MLX5_SET(umem, umem, log_page_size, obj->page_shift - 1240 MLX5_ADAPTER_PAGE_SHIFT); 1241 MLX5_SET(umem, umem, page_offset, obj->page_offset); 1242 mlx5_ib_populate_pas(dev, obj->umem, obj->page_shift, mtt, 1243 (obj->umem->writable ? MLX5_IB_MTT_WRITE : 0) | 1244 MLX5_IB_MTT_READ); 1245 } 1246 1247 static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_UMEM_REG)( 1248 struct uverbs_attr_bundle *attrs) 1249 { 1250 struct devx_umem_reg_cmd cmd; 1251 struct devx_umem *obj; 1252 struct ib_uobject *uobj = uverbs_attr_get_uobject( 1253 attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE); 1254 u32 obj_id; 1255 struct mlx5_ib_ucontext *c = to_mucontext(uobj->context); 1256 struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device); 1257 int err; 1258 1259 if (!c->devx_uid) 1260 return -EINVAL; 1261 1262 obj = kzalloc(sizeof(struct devx_umem), GFP_KERNEL); 1263 if (!obj) 1264 return -ENOMEM; 1265 1266 err = devx_umem_get(dev, &c->ibucontext, attrs, obj); 1267 if (err) 1268 goto err_obj_free; 1269 1270 err = devx_umem_reg_cmd_alloc(attrs, obj, &cmd); 1271 if (err) 1272 goto err_umem_release; 1273 1274 devx_umem_reg_cmd_build(dev, obj, &cmd); 1275 1276 MLX5_SET(create_umem_in, cmd.in, uid, c->devx_uid); 1277 err = mlx5_cmd_exec(dev->mdev, cmd.in, cmd.inlen, cmd.out, 1278 sizeof(cmd.out)); 1279 if (err) 1280 goto err_umem_release; 1281 1282 obj->mdev = dev->mdev; 1283 uobj->object = obj; 1284 devx_obj_build_destroy_cmd(cmd.in, cmd.out, obj->dinbox, &obj->dinlen, &obj_id); 1285 err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID, &obj_id, sizeof(obj_id)); 1286 if (err) 1287 goto err_umem_destroy; 1288 1289 return 0; 1290 1291 err_umem_destroy: 1292 mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, cmd.out, sizeof(cmd.out)); 1293 err_umem_release: 1294 ib_umem_release(obj->umem); 1295 err_obj_free: 1296 kfree(obj); 1297 return err; 1298 } 1299 1300 static int devx_umem_cleanup(struct ib_uobject *uobject, 1301 enum rdma_remove_reason why) 1302 { 1303 struct devx_umem *obj = uobject->object; 1304 u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)]; 1305 int err; 1306 1307 err = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out)); 1308 if (ib_is_destroy_retryable(err, why, uobject)) 1309 return err; 1310 1311 ib_umem_release(obj->umem); 1312 kfree(obj); 1313 return 0; 1314 } 1315 1316 DECLARE_UVERBS_NAMED_METHOD( 1317 MLX5_IB_METHOD_DEVX_UMEM_REG, 1318 UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE, 1319 MLX5_IB_OBJECT_DEVX_UMEM, 1320 UVERBS_ACCESS_NEW, 1321 UA_MANDATORY), 1322 UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR, 1323 UVERBS_ATTR_TYPE(u64), 1324 UA_MANDATORY), 1325 UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_LEN, 1326 UVERBS_ATTR_TYPE(u64), 1327 UA_MANDATORY), 1328 UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS, 1329 enum ib_access_flags), 1330 UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID, 1331 UVERBS_ATTR_TYPE(u32), 1332 UA_MANDATORY)); 1333 1334 DECLARE_UVERBS_NAMED_METHOD_DESTROY( 1335 MLX5_IB_METHOD_DEVX_UMEM_DEREG, 1336 UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_DEREG_HANDLE, 1337 MLX5_IB_OBJECT_DEVX_UMEM, 1338 UVERBS_ACCESS_DESTROY, 1339 UA_MANDATORY)); 1340 1341 DECLARE_UVERBS_NAMED_METHOD( 1342 MLX5_IB_METHOD_DEVX_QUERY_EQN, 1343 UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC, 1344 UVERBS_ATTR_TYPE(u32), 1345 UA_MANDATORY), 1346 UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN, 1347 UVERBS_ATTR_TYPE(u32), 1348 UA_MANDATORY)); 1349 1350 DECLARE_UVERBS_NAMED_METHOD( 1351 MLX5_IB_METHOD_DEVX_QUERY_UAR, 1352 UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX, 1353 UVERBS_ATTR_TYPE(u32), 1354 UA_MANDATORY), 1355 UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX, 1356 UVERBS_ATTR_TYPE(u32), 1357 UA_MANDATORY)); 1358 1359 DECLARE_UVERBS_NAMED_METHOD( 1360 MLX5_IB_METHOD_DEVX_OTHER, 1361 UVERBS_ATTR_PTR_IN( 1362 MLX5_IB_ATTR_DEVX_OTHER_CMD_IN, 1363 UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)), 1364 UA_MANDATORY, 1365 UA_ALLOC_AND_COPY), 1366 UVERBS_ATTR_PTR_OUT( 1367 MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT, 1368 UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)), 1369 UA_MANDATORY)); 1370 1371 DECLARE_UVERBS_NAMED_METHOD( 1372 MLX5_IB_METHOD_DEVX_OBJ_CREATE, 1373 UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE, 1374 MLX5_IB_OBJECT_DEVX_OBJ, 1375 UVERBS_ACCESS_NEW, 1376 UA_MANDATORY), 1377 UVERBS_ATTR_PTR_IN( 1378 MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN, 1379 UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)), 1380 UA_MANDATORY, 1381 UA_ALLOC_AND_COPY), 1382 UVERBS_ATTR_PTR_OUT( 1383 MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT, 1384 UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)), 1385 UA_MANDATORY)); 1386 1387 DECLARE_UVERBS_NAMED_METHOD_DESTROY( 1388 MLX5_IB_METHOD_DEVX_OBJ_DESTROY, 1389 UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_DESTROY_HANDLE, 1390 MLX5_IB_OBJECT_DEVX_OBJ, 1391 UVERBS_ACCESS_DESTROY, 1392 UA_MANDATORY)); 1393 1394 DECLARE_UVERBS_NAMED_METHOD( 1395 MLX5_IB_METHOD_DEVX_OBJ_MODIFY, 1396 UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE, 1397 UVERBS_IDR_ANY_OBJECT, 1398 UVERBS_ACCESS_WRITE, 1399 UA_MANDATORY), 1400 UVERBS_ATTR_PTR_IN( 1401 MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN, 1402 UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)), 1403 UA_MANDATORY, 1404 UA_ALLOC_AND_COPY), 1405 UVERBS_ATTR_PTR_OUT( 1406 MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT, 1407 UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)), 1408 UA_MANDATORY)); 1409 1410 DECLARE_UVERBS_NAMED_METHOD( 1411 MLX5_IB_METHOD_DEVX_OBJ_QUERY, 1412 UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE, 1413 UVERBS_IDR_ANY_OBJECT, 1414 UVERBS_ACCESS_READ, 1415 UA_MANDATORY), 1416 UVERBS_ATTR_PTR_IN( 1417 MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN, 1418 UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)), 1419 UA_MANDATORY, 1420 UA_ALLOC_AND_COPY), 1421 UVERBS_ATTR_PTR_OUT( 1422 MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT, 1423 UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)), 1424 UA_MANDATORY)); 1425 1426 DECLARE_UVERBS_GLOBAL_METHODS(MLX5_IB_OBJECT_DEVX, 1427 &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OTHER), 1428 &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_UAR), 1429 &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_EQN)); 1430 1431 DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ, 1432 UVERBS_TYPE_ALLOC_IDR(devx_obj_cleanup), 1433 &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_CREATE), 1434 &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_DESTROY), 1435 &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_MODIFY), 1436 &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_QUERY)); 1437 1438 DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM, 1439 UVERBS_TYPE_ALLOC_IDR(devx_umem_cleanup), 1440 &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_REG), 1441 &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_DEREG)); 1442 1443 static bool devx_is_supported(struct ib_device *device) 1444 { 1445 struct mlx5_ib_dev *dev = to_mdev(device); 1446 1447 return !dev->rep && MLX5_CAP_GEN(dev->mdev, log_max_uctx); 1448 } 1449 1450 const struct uapi_definition mlx5_ib_devx_defs[] = { 1451 UAPI_DEF_CHAIN_OBJ_TREE_NAMED( 1452 MLX5_IB_OBJECT_DEVX, 1453 UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)), 1454 UAPI_DEF_CHAIN_OBJ_TREE_NAMED( 1455 MLX5_IB_OBJECT_DEVX_OBJ, 1456 UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)), 1457 UAPI_DEF_CHAIN_OBJ_TREE_NAMED( 1458 MLX5_IB_OBJECT_DEVX_UMEM, 1459 UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)), 1460 {}, 1461 }; 1462