devx.c 39 KB

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