devx.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107
  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. u32 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, struct mlx5_ib_ucontext *context)
  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 *uctx;
  47. void *hdr;
  48. int err;
  49. uctx = MLX5_ADDR_OF(create_uctx_in, in, uctx);
  50. hdr = MLX5_ADDR_OF(create_uctx_in, in, hdr);
  51. general_obj_types = MLX5_CAP_GEN_64(dev->mdev, general_obj_types);
  52. if (!(general_obj_types & MLX5_GENERAL_OBJ_TYPES_CAP_UCTX) ||
  53. !(general_obj_types & MLX5_GENERAL_OBJ_TYPES_CAP_UMEM))
  54. return -EINVAL;
  55. if (!capable(CAP_NET_RAW))
  56. return -EPERM;
  57. MLX5_SET(general_obj_in_cmd_hdr, hdr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
  58. MLX5_SET(general_obj_in_cmd_hdr, hdr, obj_type, MLX5_OBJ_TYPE_UCTX);
  59. err = mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out));
  60. if (err)
  61. return err;
  62. context->devx_uid = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
  63. return 0;
  64. }
  65. void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev,
  66. struct mlx5_ib_ucontext *context)
  67. {
  68. u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {0};
  69. u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
  70. MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
  71. MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, MLX5_OBJ_TYPE_UCTX);
  72. MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, context->devx_uid);
  73. mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out));
  74. }
  75. static int devx_is_valid_obj_id(struct devx_obj *obj, const void *in)
  76. {
  77. u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
  78. u32 obj_id;
  79. switch (opcode) {
  80. case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
  81. case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
  82. obj_id = MLX5_GET(general_obj_in_cmd_hdr, in, obj_id);
  83. break;
  84. case MLX5_CMD_OP_QUERY_MKEY:
  85. obj_id = MLX5_GET(query_mkey_in, in, mkey_index);
  86. break;
  87. case MLX5_CMD_OP_QUERY_CQ:
  88. obj_id = MLX5_GET(query_cq_in, in, cqn);
  89. break;
  90. case MLX5_CMD_OP_MODIFY_CQ:
  91. obj_id = MLX5_GET(modify_cq_in, in, cqn);
  92. break;
  93. case MLX5_CMD_OP_QUERY_SQ:
  94. obj_id = MLX5_GET(query_sq_in, in, sqn);
  95. break;
  96. case MLX5_CMD_OP_MODIFY_SQ:
  97. obj_id = MLX5_GET(modify_sq_in, in, sqn);
  98. break;
  99. case MLX5_CMD_OP_QUERY_RQ:
  100. obj_id = MLX5_GET(query_rq_in, in, rqn);
  101. break;
  102. case MLX5_CMD_OP_MODIFY_RQ:
  103. obj_id = MLX5_GET(modify_rq_in, in, rqn);
  104. break;
  105. case MLX5_CMD_OP_QUERY_RMP:
  106. obj_id = MLX5_GET(query_rmp_in, in, rmpn);
  107. break;
  108. case MLX5_CMD_OP_MODIFY_RMP:
  109. obj_id = MLX5_GET(modify_rmp_in, in, rmpn);
  110. break;
  111. case MLX5_CMD_OP_QUERY_RQT:
  112. obj_id = MLX5_GET(query_rqt_in, in, rqtn);
  113. break;
  114. case MLX5_CMD_OP_MODIFY_RQT:
  115. obj_id = MLX5_GET(modify_rqt_in, in, rqtn);
  116. break;
  117. case MLX5_CMD_OP_QUERY_TIR:
  118. obj_id = MLX5_GET(query_tir_in, in, tirn);
  119. break;
  120. case MLX5_CMD_OP_MODIFY_TIR:
  121. obj_id = MLX5_GET(modify_tir_in, in, tirn);
  122. break;
  123. case MLX5_CMD_OP_QUERY_TIS:
  124. obj_id = MLX5_GET(query_tis_in, in, tisn);
  125. break;
  126. case MLX5_CMD_OP_MODIFY_TIS:
  127. obj_id = MLX5_GET(modify_tis_in, in, tisn);
  128. break;
  129. case MLX5_CMD_OP_QUERY_FLOW_TABLE:
  130. obj_id = MLX5_GET(query_flow_table_in, in, table_id);
  131. break;
  132. case MLX5_CMD_OP_MODIFY_FLOW_TABLE:
  133. obj_id = MLX5_GET(modify_flow_table_in, in, table_id);
  134. break;
  135. case MLX5_CMD_OP_QUERY_FLOW_GROUP:
  136. obj_id = MLX5_GET(query_flow_group_in, in, group_id);
  137. break;
  138. case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY:
  139. obj_id = MLX5_GET(query_fte_in, in, flow_index);
  140. break;
  141. case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
  142. obj_id = MLX5_GET(set_fte_in, in, flow_index);
  143. break;
  144. case MLX5_CMD_OP_QUERY_Q_COUNTER:
  145. obj_id = MLX5_GET(query_q_counter_in, in, counter_set_id);
  146. break;
  147. case MLX5_CMD_OP_QUERY_FLOW_COUNTER:
  148. obj_id = MLX5_GET(query_flow_counter_in, in, flow_counter_id);
  149. break;
  150. case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT:
  151. obj_id = MLX5_GET(general_obj_in_cmd_hdr, in, obj_id);
  152. break;
  153. case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT:
  154. obj_id = MLX5_GET(query_scheduling_element_in, in,
  155. scheduling_element_id);
  156. break;
  157. case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT:
  158. obj_id = MLX5_GET(modify_scheduling_element_in, in,
  159. scheduling_element_id);
  160. break;
  161. case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
  162. obj_id = MLX5_GET(add_vxlan_udp_dport_in, in, vxlan_udp_port);
  163. break;
  164. case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY:
  165. obj_id = MLX5_GET(query_l2_table_entry_in, in, table_index);
  166. break;
  167. case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
  168. obj_id = MLX5_GET(set_l2_table_entry_in, in, table_index);
  169. break;
  170. case MLX5_CMD_OP_QUERY_QP:
  171. obj_id = MLX5_GET(query_qp_in, in, qpn);
  172. break;
  173. case MLX5_CMD_OP_RST2INIT_QP:
  174. obj_id = MLX5_GET(rst2init_qp_in, in, qpn);
  175. break;
  176. case MLX5_CMD_OP_INIT2RTR_QP:
  177. obj_id = MLX5_GET(init2rtr_qp_in, in, qpn);
  178. break;
  179. case MLX5_CMD_OP_RTR2RTS_QP:
  180. obj_id = MLX5_GET(rtr2rts_qp_in, in, qpn);
  181. break;
  182. case MLX5_CMD_OP_RTS2RTS_QP:
  183. obj_id = MLX5_GET(rts2rts_qp_in, in, qpn);
  184. break;
  185. case MLX5_CMD_OP_SQERR2RTS_QP:
  186. obj_id = MLX5_GET(sqerr2rts_qp_in, in, qpn);
  187. break;
  188. case MLX5_CMD_OP_2ERR_QP:
  189. obj_id = MLX5_GET(qp_2err_in, in, qpn);
  190. break;
  191. case MLX5_CMD_OP_2RST_QP:
  192. obj_id = MLX5_GET(qp_2rst_in, in, qpn);
  193. break;
  194. case MLX5_CMD_OP_QUERY_DCT:
  195. obj_id = MLX5_GET(query_dct_in, in, dctn);
  196. break;
  197. case MLX5_CMD_OP_QUERY_XRQ:
  198. obj_id = MLX5_GET(query_xrq_in, in, xrqn);
  199. break;
  200. case MLX5_CMD_OP_QUERY_XRC_SRQ:
  201. obj_id = MLX5_GET(query_xrc_srq_in, in, xrc_srqn);
  202. break;
  203. case MLX5_CMD_OP_ARM_XRC_SRQ:
  204. obj_id = MLX5_GET(arm_xrc_srq_in, in, xrc_srqn);
  205. break;
  206. case MLX5_CMD_OP_QUERY_SRQ:
  207. obj_id = MLX5_GET(query_srq_in, in, srqn);
  208. break;
  209. case MLX5_CMD_OP_ARM_RQ:
  210. obj_id = MLX5_GET(arm_rq_in, in, srq_number);
  211. break;
  212. case MLX5_CMD_OP_DRAIN_DCT:
  213. case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION:
  214. obj_id = MLX5_GET(drain_dct_in, in, dctn);
  215. break;
  216. case MLX5_CMD_OP_ARM_XRQ:
  217. obj_id = MLX5_GET(arm_xrq_in, in, xrqn);
  218. break;
  219. default:
  220. return false;
  221. }
  222. if (obj_id == obj->obj_id)
  223. return true;
  224. return false;
  225. }
  226. static bool devx_is_obj_create_cmd(const void *in)
  227. {
  228. u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
  229. switch (opcode) {
  230. case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
  231. case MLX5_CMD_OP_CREATE_MKEY:
  232. case MLX5_CMD_OP_CREATE_CQ:
  233. case MLX5_CMD_OP_ALLOC_PD:
  234. case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN:
  235. case MLX5_CMD_OP_CREATE_RMP:
  236. case MLX5_CMD_OP_CREATE_SQ:
  237. case MLX5_CMD_OP_CREATE_RQ:
  238. case MLX5_CMD_OP_CREATE_RQT:
  239. case MLX5_CMD_OP_CREATE_TIR:
  240. case MLX5_CMD_OP_CREATE_TIS:
  241. case MLX5_CMD_OP_ALLOC_Q_COUNTER:
  242. case MLX5_CMD_OP_CREATE_FLOW_TABLE:
  243. case MLX5_CMD_OP_CREATE_FLOW_GROUP:
  244. case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
  245. case MLX5_CMD_OP_ALLOC_ENCAP_HEADER:
  246. case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
  247. case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
  248. case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
  249. case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
  250. case MLX5_CMD_OP_CREATE_QP:
  251. case MLX5_CMD_OP_CREATE_SRQ:
  252. case MLX5_CMD_OP_CREATE_XRC_SRQ:
  253. case MLX5_CMD_OP_CREATE_DCT:
  254. case MLX5_CMD_OP_CREATE_XRQ:
  255. case MLX5_CMD_OP_ATTACH_TO_MCG:
  256. case MLX5_CMD_OP_ALLOC_XRCD:
  257. return true;
  258. case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
  259. {
  260. u16 op_mod = MLX5_GET(set_fte_in, in, op_mod);
  261. if (op_mod == 0)
  262. return true;
  263. return false;
  264. }
  265. default:
  266. return false;
  267. }
  268. }
  269. static bool devx_is_obj_modify_cmd(const void *in)
  270. {
  271. u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
  272. switch (opcode) {
  273. case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
  274. case MLX5_CMD_OP_MODIFY_CQ:
  275. case MLX5_CMD_OP_MODIFY_RMP:
  276. case MLX5_CMD_OP_MODIFY_SQ:
  277. case MLX5_CMD_OP_MODIFY_RQ:
  278. case MLX5_CMD_OP_MODIFY_RQT:
  279. case MLX5_CMD_OP_MODIFY_TIR:
  280. case MLX5_CMD_OP_MODIFY_TIS:
  281. case MLX5_CMD_OP_MODIFY_FLOW_TABLE:
  282. case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT:
  283. case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
  284. case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
  285. case MLX5_CMD_OP_RST2INIT_QP:
  286. case MLX5_CMD_OP_INIT2RTR_QP:
  287. case MLX5_CMD_OP_RTR2RTS_QP:
  288. case MLX5_CMD_OP_RTS2RTS_QP:
  289. case MLX5_CMD_OP_SQERR2RTS_QP:
  290. case MLX5_CMD_OP_2ERR_QP:
  291. case MLX5_CMD_OP_2RST_QP:
  292. case MLX5_CMD_OP_ARM_XRC_SRQ:
  293. case MLX5_CMD_OP_ARM_RQ:
  294. case MLX5_CMD_OP_DRAIN_DCT:
  295. case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION:
  296. case MLX5_CMD_OP_ARM_XRQ:
  297. return true;
  298. case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
  299. {
  300. u16 op_mod = MLX5_GET(set_fte_in, in, op_mod);
  301. if (op_mod == 1)
  302. return true;
  303. return false;
  304. }
  305. default:
  306. return false;
  307. }
  308. }
  309. static bool devx_is_obj_query_cmd(const void *in)
  310. {
  311. u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
  312. switch (opcode) {
  313. case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
  314. case MLX5_CMD_OP_QUERY_MKEY:
  315. case MLX5_CMD_OP_QUERY_CQ:
  316. case MLX5_CMD_OP_QUERY_RMP:
  317. case MLX5_CMD_OP_QUERY_SQ:
  318. case MLX5_CMD_OP_QUERY_RQ:
  319. case MLX5_CMD_OP_QUERY_RQT:
  320. case MLX5_CMD_OP_QUERY_TIR:
  321. case MLX5_CMD_OP_QUERY_TIS:
  322. case MLX5_CMD_OP_QUERY_Q_COUNTER:
  323. case MLX5_CMD_OP_QUERY_FLOW_TABLE:
  324. case MLX5_CMD_OP_QUERY_FLOW_GROUP:
  325. case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY:
  326. case MLX5_CMD_OP_QUERY_FLOW_COUNTER:
  327. case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT:
  328. case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT:
  329. case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY:
  330. case MLX5_CMD_OP_QUERY_QP:
  331. case MLX5_CMD_OP_QUERY_SRQ:
  332. case MLX5_CMD_OP_QUERY_XRC_SRQ:
  333. case MLX5_CMD_OP_QUERY_DCT:
  334. case MLX5_CMD_OP_QUERY_XRQ:
  335. return true;
  336. default:
  337. return false;
  338. }
  339. }
  340. static bool devx_is_general_cmd(void *in)
  341. {
  342. u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
  343. switch (opcode) {
  344. case MLX5_CMD_OP_QUERY_HCA_CAP:
  345. case MLX5_CMD_OP_QUERY_VPORT_STATE:
  346. case MLX5_CMD_OP_QUERY_ADAPTER:
  347. case MLX5_CMD_OP_QUERY_ISSI:
  348. case MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT:
  349. case MLX5_CMD_OP_QUERY_ROCE_ADDRESS:
  350. case MLX5_CMD_OP_QUERY_VNIC_ENV:
  351. case MLX5_CMD_OP_QUERY_VPORT_COUNTER:
  352. case MLX5_CMD_OP_GET_DROPPED_PACKET_LOG:
  353. case MLX5_CMD_OP_NOP:
  354. case MLX5_CMD_OP_QUERY_CONG_STATUS:
  355. case MLX5_CMD_OP_QUERY_CONG_PARAMS:
  356. case MLX5_CMD_OP_QUERY_CONG_STATISTICS:
  357. return true;
  358. default:
  359. return false;
  360. }
  361. }
  362. static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_EQN)(struct ib_device *ib_dev,
  363. struct ib_uverbs_file *file,
  364. struct uverbs_attr_bundle *attrs)
  365. {
  366. struct mlx5_ib_dev *dev = to_mdev(ib_dev);
  367. int user_vector;
  368. int dev_eqn;
  369. unsigned int irqn;
  370. int err;
  371. if (uverbs_copy_from(&user_vector, attrs,
  372. MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC))
  373. return -EFAULT;
  374. err = mlx5_vector2eqn(dev->mdev, user_vector, &dev_eqn, &irqn);
  375. if (err < 0)
  376. return err;
  377. if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN,
  378. &dev_eqn, sizeof(dev_eqn)))
  379. return -EFAULT;
  380. return 0;
  381. }
  382. /*
  383. *Security note:
  384. * The hardware protection mechanism works like this: Each device object that
  385. * is subject to UAR doorbells (QP/SQ/CQ) gets a UAR ID (called uar_page in
  386. * the device specification manual) upon its creation. Then upon doorbell,
  387. * hardware fetches the object context for which the doorbell was rang, and
  388. * validates that the UAR through which the DB was rang matches the UAR ID
  389. * of the object.
  390. * If no match the doorbell is silently ignored by the hardware. Of course,
  391. * the user cannot ring a doorbell on a UAR that was not mapped to it.
  392. * Now in devx, as the devx kernel does not manipulate the QP/SQ/CQ command
  393. * mailboxes (except tagging them with UID), we expose to the user its UAR
  394. * ID, so it can embed it in these objects in the expected specification
  395. * format. So the only thing the user can do is hurt itself by creating a
  396. * QP/SQ/CQ with a UAR ID other than his, and then in this case other users
  397. * may ring a doorbell on its objects.
  398. * The consequence of that will be that another user can schedule a QP/SQ
  399. * of the buggy user for execution (just insert it to the hardware schedule
  400. * queue or arm its CQ for event generation), no further harm is expected.
  401. */
  402. static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_UAR)(struct ib_device *ib_dev,
  403. struct ib_uverbs_file *file,
  404. struct uverbs_attr_bundle *attrs)
  405. {
  406. struct mlx5_ib_ucontext *c = devx_ufile2uctx(file);
  407. u32 user_idx;
  408. s32 dev_idx;
  409. if (uverbs_copy_from(&user_idx, attrs,
  410. MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX))
  411. return -EFAULT;
  412. dev_idx = bfregn_to_uar_index(to_mdev(ib_dev),
  413. &c->bfregi, user_idx, true);
  414. if (dev_idx < 0)
  415. return dev_idx;
  416. if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX,
  417. &dev_idx, sizeof(dev_idx)))
  418. return -EFAULT;
  419. return 0;
  420. }
  421. static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)(struct ib_device *ib_dev,
  422. struct ib_uverbs_file *file,
  423. struct uverbs_attr_bundle *attrs)
  424. {
  425. struct mlx5_ib_ucontext *c = devx_ufile2uctx(file);
  426. struct mlx5_ib_dev *dev = to_mdev(ib_dev);
  427. void *cmd_in = uverbs_attr_get_alloced_ptr(
  428. attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN);
  429. int cmd_out_len = uverbs_attr_get_len(attrs,
  430. MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT);
  431. void *cmd_out;
  432. int err;
  433. if (!c->devx_uid)
  434. return -EPERM;
  435. /* Only white list of some general HCA commands are allowed for this method. */
  436. if (!devx_is_general_cmd(cmd_in))
  437. return -EINVAL;
  438. cmd_out = kvzalloc(cmd_out_len, GFP_KERNEL);
  439. if (!cmd_out)
  440. return -ENOMEM;
  441. MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, c->devx_uid);
  442. err = mlx5_cmd_exec(dev->mdev, cmd_in,
  443. uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN),
  444. cmd_out, cmd_out_len);
  445. if (err)
  446. goto other_cmd_free;
  447. err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT, cmd_out, cmd_out_len);
  448. other_cmd_free:
  449. kvfree(cmd_out);
  450. return err;
  451. }
  452. static void devx_obj_build_destroy_cmd(void *in, void *out, void *din,
  453. u32 *dinlen,
  454. u32 *obj_id)
  455. {
  456. u16 obj_type = MLX5_GET(general_obj_in_cmd_hdr, in, obj_type);
  457. u16 uid = MLX5_GET(general_obj_in_cmd_hdr, in, uid);
  458. *obj_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
  459. *dinlen = MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr);
  460. MLX5_SET(general_obj_in_cmd_hdr, din, obj_id, *obj_id);
  461. MLX5_SET(general_obj_in_cmd_hdr, din, uid, uid);
  462. switch (MLX5_GET(general_obj_in_cmd_hdr, in, opcode)) {
  463. case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
  464. MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
  465. MLX5_SET(general_obj_in_cmd_hdr, din, obj_type, obj_type);
  466. break;
  467. case MLX5_CMD_OP_CREATE_MKEY:
  468. MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_MKEY);
  469. break;
  470. case MLX5_CMD_OP_CREATE_CQ:
  471. MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_CQ);
  472. break;
  473. case MLX5_CMD_OP_ALLOC_PD:
  474. MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DEALLOC_PD);
  475. break;
  476. case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN:
  477. MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
  478. MLX5_CMD_OP_DEALLOC_TRANSPORT_DOMAIN);
  479. break;
  480. case MLX5_CMD_OP_CREATE_RMP:
  481. MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RMP);
  482. break;
  483. case MLX5_CMD_OP_CREATE_SQ:
  484. MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_SQ);
  485. break;
  486. case MLX5_CMD_OP_CREATE_RQ:
  487. MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RQ);
  488. break;
  489. case MLX5_CMD_OP_CREATE_RQT:
  490. MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RQT);
  491. break;
  492. case MLX5_CMD_OP_CREATE_TIR:
  493. MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIR);
  494. break;
  495. case MLX5_CMD_OP_CREATE_TIS:
  496. MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIS);
  497. break;
  498. case MLX5_CMD_OP_ALLOC_Q_COUNTER:
  499. MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
  500. MLX5_CMD_OP_DEALLOC_Q_COUNTER);
  501. break;
  502. case MLX5_CMD_OP_CREATE_FLOW_TABLE:
  503. *dinlen = MLX5_ST_SZ_BYTES(destroy_flow_table_in);
  504. *obj_id = MLX5_GET(create_flow_table_out, out, table_id);
  505. MLX5_SET(destroy_flow_table_in, din, other_vport,
  506. MLX5_GET(create_flow_table_in, in, other_vport));
  507. MLX5_SET(destroy_flow_table_in, din, vport_number,
  508. MLX5_GET(create_flow_table_in, in, vport_number));
  509. MLX5_SET(destroy_flow_table_in, din, table_type,
  510. MLX5_GET(create_flow_table_in, in, table_type));
  511. MLX5_SET(destroy_flow_table_in, din, table_id, *obj_id);
  512. MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
  513. MLX5_CMD_OP_DESTROY_FLOW_TABLE);
  514. break;
  515. case MLX5_CMD_OP_CREATE_FLOW_GROUP:
  516. *dinlen = MLX5_ST_SZ_BYTES(destroy_flow_group_in);
  517. *obj_id = MLX5_GET(create_flow_group_out, out, group_id);
  518. MLX5_SET(destroy_flow_group_in, din, other_vport,
  519. MLX5_GET(create_flow_group_in, in, other_vport));
  520. MLX5_SET(destroy_flow_group_in, din, vport_number,
  521. MLX5_GET(create_flow_group_in, in, vport_number));
  522. MLX5_SET(destroy_flow_group_in, din, table_type,
  523. MLX5_GET(create_flow_group_in, in, table_type));
  524. MLX5_SET(destroy_flow_group_in, din, table_id,
  525. MLX5_GET(create_flow_group_in, in, table_id));
  526. MLX5_SET(destroy_flow_group_in, din, group_id, *obj_id);
  527. MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
  528. MLX5_CMD_OP_DESTROY_FLOW_GROUP);
  529. break;
  530. case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
  531. *dinlen = MLX5_ST_SZ_BYTES(delete_fte_in);
  532. *obj_id = MLX5_GET(set_fte_in, in, flow_index);
  533. MLX5_SET(delete_fte_in, din, other_vport,
  534. MLX5_GET(set_fte_in, in, other_vport));
  535. MLX5_SET(delete_fte_in, din, vport_number,
  536. MLX5_GET(set_fte_in, in, vport_number));
  537. MLX5_SET(delete_fte_in, din, table_type,
  538. MLX5_GET(set_fte_in, in, table_type));
  539. MLX5_SET(delete_fte_in, din, table_id,
  540. MLX5_GET(set_fte_in, in, table_id));
  541. MLX5_SET(delete_fte_in, din, flow_index, *obj_id);
  542. MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
  543. MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY);
  544. break;
  545. case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
  546. MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
  547. MLX5_CMD_OP_DEALLOC_FLOW_COUNTER);
  548. break;
  549. case MLX5_CMD_OP_ALLOC_ENCAP_HEADER:
  550. MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
  551. MLX5_CMD_OP_DEALLOC_ENCAP_HEADER);
  552. break;
  553. case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
  554. MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
  555. MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT);
  556. break;
  557. case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
  558. *dinlen = MLX5_ST_SZ_BYTES(destroy_scheduling_element_in);
  559. *obj_id = MLX5_GET(create_scheduling_element_out, out,
  560. scheduling_element_id);
  561. MLX5_SET(destroy_scheduling_element_in, din,
  562. scheduling_hierarchy,
  563. MLX5_GET(create_scheduling_element_in, in,
  564. scheduling_hierarchy));
  565. MLX5_SET(destroy_scheduling_element_in, din,
  566. scheduling_element_id, *obj_id);
  567. MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
  568. MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT);
  569. break;
  570. case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
  571. *dinlen = MLX5_ST_SZ_BYTES(delete_vxlan_udp_dport_in);
  572. *obj_id = MLX5_GET(add_vxlan_udp_dport_in, in, vxlan_udp_port);
  573. MLX5_SET(delete_vxlan_udp_dport_in, din, vxlan_udp_port, *obj_id);
  574. MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
  575. MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT);
  576. break;
  577. case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
  578. *dinlen = MLX5_ST_SZ_BYTES(delete_l2_table_entry_in);
  579. *obj_id = MLX5_GET(set_l2_table_entry_in, in, table_index);
  580. MLX5_SET(delete_l2_table_entry_in, din, table_index, *obj_id);
  581. MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
  582. MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY);
  583. break;
  584. case MLX5_CMD_OP_CREATE_QP:
  585. MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_QP);
  586. break;
  587. case MLX5_CMD_OP_CREATE_SRQ:
  588. MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_SRQ);
  589. break;
  590. case MLX5_CMD_OP_CREATE_XRC_SRQ:
  591. MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
  592. MLX5_CMD_OP_DESTROY_XRC_SRQ);
  593. break;
  594. case MLX5_CMD_OP_CREATE_DCT:
  595. MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_DCT);
  596. break;
  597. case MLX5_CMD_OP_CREATE_XRQ:
  598. MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_XRQ);
  599. break;
  600. case MLX5_CMD_OP_ATTACH_TO_MCG:
  601. *dinlen = MLX5_ST_SZ_BYTES(detach_from_mcg_in);
  602. MLX5_SET(detach_from_mcg_in, din, qpn,
  603. MLX5_GET(attach_to_mcg_in, in, qpn));
  604. memcpy(MLX5_ADDR_OF(detach_from_mcg_in, din, multicast_gid),
  605. MLX5_ADDR_OF(attach_to_mcg_in, in, multicast_gid),
  606. MLX5_FLD_SZ_BYTES(attach_to_mcg_in, multicast_gid));
  607. MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DETACH_FROM_MCG);
  608. break;
  609. case MLX5_CMD_OP_ALLOC_XRCD:
  610. MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DEALLOC_XRCD);
  611. break;
  612. default:
  613. /* The entry must match to one of the devx_is_obj_create_cmd */
  614. WARN_ON(true);
  615. break;
  616. }
  617. }
  618. static int devx_obj_cleanup(struct ib_uobject *uobject,
  619. enum rdma_remove_reason why)
  620. {
  621. u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
  622. struct devx_obj *obj = uobject->object;
  623. int ret;
  624. ret = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out));
  625. if (ret && why == RDMA_REMOVE_DESTROY)
  626. return ret;
  627. kfree(obj);
  628. return ret;
  629. }
  630. static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_DESTROY)(struct ib_device *ib_dev,
  631. struct ib_uverbs_file *file,
  632. struct uverbs_attr_bundle *attrs)
  633. {
  634. return 0;
  635. }
  636. static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(struct ib_device *ib_dev,
  637. struct ib_uverbs_file *file,
  638. struct uverbs_attr_bundle *attrs)
  639. {
  640. struct mlx5_ib_ucontext *c = devx_ufile2uctx(file);
  641. struct mlx5_ib_dev *dev = to_mdev(ib_dev);
  642. void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN);
  643. int cmd_out_len = uverbs_attr_get_len(attrs,
  644. MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT);
  645. void *cmd_out;
  646. struct ib_uobject *uobj;
  647. struct devx_obj *obj;
  648. int err;
  649. if (!c->devx_uid)
  650. return -EPERM;
  651. if (!devx_is_obj_create_cmd(cmd_in))
  652. return -EINVAL;
  653. obj = kzalloc(sizeof(struct devx_obj), GFP_KERNEL);
  654. if (!obj)
  655. return -ENOMEM;
  656. cmd_out = kvzalloc(cmd_out_len, GFP_KERNEL);
  657. if (!cmd_out) {
  658. err = -ENOMEM;
  659. goto obj_free;
  660. }
  661. MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, c->devx_uid);
  662. err = mlx5_cmd_exec(dev->mdev, cmd_in,
  663. uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN),
  664. cmd_out, cmd_out_len);
  665. if (err)
  666. goto cmd_free;
  667. uobj = uverbs_attr_get_uobject(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE);
  668. uobj->object = obj;
  669. obj->mdev = dev->mdev;
  670. devx_obj_build_destroy_cmd(cmd_in, cmd_out, obj->dinbox, &obj->dinlen, &obj->obj_id);
  671. WARN_ON(obj->dinlen > MLX5_MAX_DESTROY_INBOX_SIZE_DW * sizeof(u32));
  672. err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT, cmd_out, cmd_out_len);
  673. if (err)
  674. goto cmd_free;
  675. kvfree(cmd_out);
  676. return 0;
  677. cmd_free:
  678. kvfree(cmd_out);
  679. obj_free:
  680. kfree(obj);
  681. return err;
  682. }
  683. static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_MODIFY)(struct ib_device *ib_dev,
  684. struct ib_uverbs_file *file,
  685. struct uverbs_attr_bundle *attrs)
  686. {
  687. struct mlx5_ib_ucontext *c = devx_ufile2uctx(file);
  688. struct mlx5_ib_dev *dev = to_mdev(ib_dev);
  689. void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN);
  690. int cmd_out_len = uverbs_attr_get_len(attrs,
  691. MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT);
  692. struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
  693. MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE);
  694. void *cmd_out;
  695. int err;
  696. if (!c->devx_uid)
  697. return -EPERM;
  698. if (!devx_is_obj_modify_cmd(cmd_in))
  699. return -EINVAL;
  700. if (!devx_is_valid_obj_id(uobj->object, cmd_in))
  701. return -EINVAL;
  702. cmd_out = kvzalloc(cmd_out_len, GFP_KERNEL);
  703. if (!cmd_out)
  704. return -ENOMEM;
  705. MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, c->devx_uid);
  706. err = mlx5_cmd_exec(dev->mdev, cmd_in,
  707. uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN),
  708. cmd_out, cmd_out_len);
  709. if (err)
  710. goto other_cmd_free;
  711. err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT,
  712. cmd_out, cmd_out_len);
  713. other_cmd_free:
  714. kvfree(cmd_out);
  715. return err;
  716. }
  717. static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)(struct ib_device *ib_dev,
  718. struct ib_uverbs_file *file,
  719. struct uverbs_attr_bundle *attrs)
  720. {
  721. struct mlx5_ib_ucontext *c = devx_ufile2uctx(file);
  722. struct mlx5_ib_dev *dev = to_mdev(ib_dev);
  723. void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN);
  724. int cmd_out_len = uverbs_attr_get_len(attrs,
  725. MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT);
  726. struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
  727. MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE);
  728. void *cmd_out;
  729. int err;
  730. if (!c->devx_uid)
  731. return -EPERM;
  732. if (!devx_is_obj_query_cmd(cmd_in))
  733. return -EINVAL;
  734. if (!devx_is_valid_obj_id(uobj->object, cmd_in))
  735. return -EINVAL;
  736. cmd_out = kvzalloc(cmd_out_len, GFP_KERNEL);
  737. if (!cmd_out)
  738. return -ENOMEM;
  739. MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, c->devx_uid);
  740. err = mlx5_cmd_exec(dev->mdev, cmd_in,
  741. uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN),
  742. cmd_out, cmd_out_len);
  743. if (err)
  744. goto other_cmd_free;
  745. err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT, cmd_out, cmd_out_len);
  746. other_cmd_free:
  747. kvfree(cmd_out);
  748. return err;
  749. }
  750. static int devx_umem_get(struct mlx5_ib_dev *dev, struct ib_ucontext *ucontext,
  751. struct uverbs_attr_bundle *attrs,
  752. struct devx_umem *obj)
  753. {
  754. u64 addr;
  755. size_t size;
  756. int access;
  757. int npages;
  758. int err;
  759. u32 page_mask;
  760. if (uverbs_copy_from(&addr, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR) ||
  761. uverbs_copy_from(&size, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_LEN) ||
  762. uverbs_copy_from(&access, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS))
  763. return -EFAULT;
  764. err = ib_check_mr_access(access);
  765. if (err)
  766. return err;
  767. obj->umem = ib_umem_get(ucontext, addr, size, access, 0);
  768. if (IS_ERR(obj->umem))
  769. return PTR_ERR(obj->umem);
  770. mlx5_ib_cont_pages(obj->umem, obj->umem->address,
  771. MLX5_MKEY_PAGE_SHIFT_MASK, &npages,
  772. &obj->page_shift, &obj->ncont, NULL);
  773. if (!npages) {
  774. ib_umem_release(obj->umem);
  775. return -EINVAL;
  776. }
  777. page_mask = (1 << obj->page_shift) - 1;
  778. obj->page_offset = obj->umem->address & page_mask;
  779. return 0;
  780. }
  781. static int devx_umem_reg_cmd_alloc(struct devx_umem *obj,
  782. struct devx_umem_reg_cmd *cmd)
  783. {
  784. cmd->inlen = MLX5_ST_SZ_BYTES(create_umem_in) +
  785. (MLX5_ST_SZ_BYTES(mtt) * obj->ncont);
  786. cmd->in = kvzalloc(cmd->inlen, GFP_KERNEL);
  787. return cmd->in ? 0 : -ENOMEM;
  788. }
  789. static void devx_umem_reg_cmd_free(struct devx_umem_reg_cmd *cmd)
  790. {
  791. kvfree(cmd->in);
  792. }
  793. static void devx_umem_reg_cmd_build(struct mlx5_ib_dev *dev,
  794. struct devx_umem *obj,
  795. struct devx_umem_reg_cmd *cmd)
  796. {
  797. void *umem;
  798. __be64 *mtt;
  799. umem = MLX5_ADDR_OF(create_umem_in, cmd->in, umem);
  800. mtt = (__be64 *)MLX5_ADDR_OF(umem, umem, mtt);
  801. MLX5_SET(general_obj_in_cmd_hdr, cmd->in, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
  802. MLX5_SET(general_obj_in_cmd_hdr, cmd->in, obj_type, MLX5_OBJ_TYPE_UMEM);
  803. MLX5_SET64(umem, umem, num_of_mtt, obj->ncont);
  804. MLX5_SET(umem, umem, log_page_size, obj->page_shift -
  805. MLX5_ADAPTER_PAGE_SHIFT);
  806. MLX5_SET(umem, umem, page_offset, obj->page_offset);
  807. mlx5_ib_populate_pas(dev, obj->umem, obj->page_shift, mtt,
  808. (obj->umem->writable ? MLX5_IB_MTT_WRITE : 0) |
  809. MLX5_IB_MTT_READ);
  810. }
  811. static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_UMEM_REG)(struct ib_device *ib_dev,
  812. struct ib_uverbs_file *file,
  813. struct uverbs_attr_bundle *attrs)
  814. {
  815. struct mlx5_ib_ucontext *c = devx_ufile2uctx(file);
  816. struct mlx5_ib_dev *dev = to_mdev(ib_dev);
  817. struct devx_umem_reg_cmd cmd;
  818. struct devx_umem *obj;
  819. struct ib_uobject *uobj;
  820. u32 obj_id;
  821. int err;
  822. if (!c->devx_uid)
  823. return -EPERM;
  824. uobj = uverbs_attr_get_uobject(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE);
  825. obj = kzalloc(sizeof(struct devx_umem), GFP_KERNEL);
  826. if (!obj)
  827. return -ENOMEM;
  828. err = devx_umem_get(dev, &c->ibucontext, attrs, obj);
  829. if (err)
  830. goto err_obj_free;
  831. err = devx_umem_reg_cmd_alloc(obj, &cmd);
  832. if (err)
  833. goto err_umem_release;
  834. devx_umem_reg_cmd_build(dev, obj, &cmd);
  835. MLX5_SET(general_obj_in_cmd_hdr, cmd.in, uid, c->devx_uid);
  836. err = mlx5_cmd_exec(dev->mdev, cmd.in, cmd.inlen, cmd.out,
  837. sizeof(cmd.out));
  838. if (err)
  839. goto err_umem_reg_cmd_free;
  840. obj->mdev = dev->mdev;
  841. uobj->object = obj;
  842. devx_obj_build_destroy_cmd(cmd.in, cmd.out, obj->dinbox, &obj->dinlen, &obj_id);
  843. err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID, &obj_id, sizeof(obj_id));
  844. if (err)
  845. goto err_umem_destroy;
  846. devx_umem_reg_cmd_free(&cmd);
  847. return 0;
  848. err_umem_destroy:
  849. mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, cmd.out, sizeof(cmd.out));
  850. err_umem_reg_cmd_free:
  851. devx_umem_reg_cmd_free(&cmd);
  852. err_umem_release:
  853. ib_umem_release(obj->umem);
  854. err_obj_free:
  855. kfree(obj);
  856. return err;
  857. }
  858. static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_UMEM_DEREG)(struct ib_device *ib_dev,
  859. struct ib_uverbs_file *file,
  860. struct uverbs_attr_bundle *attrs)
  861. {
  862. return 0;
  863. }
  864. static int devx_umem_cleanup(struct ib_uobject *uobject,
  865. enum rdma_remove_reason why)
  866. {
  867. struct devx_umem *obj = uobject->object;
  868. u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
  869. int err;
  870. err = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out));
  871. if (err && why == RDMA_REMOVE_DESTROY)
  872. return err;
  873. ib_umem_release(obj->umem);
  874. kfree(obj);
  875. return 0;
  876. }
  877. static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_UMEM_REG,
  878. &UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE,
  879. MLX5_IB_OBJECT_DEVX_UMEM,
  880. UVERBS_ACCESS_NEW,
  881. UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
  882. &UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR, UVERBS_ATTR_TYPE(u64),
  883. UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
  884. &UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_LEN, UVERBS_ATTR_TYPE(u64),
  885. UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
  886. &UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS, UVERBS_ATTR_TYPE(u32),
  887. UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
  888. &UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID, UVERBS_ATTR_TYPE(u32),
  889. UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
  890. static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_UMEM_DEREG,
  891. &UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_DEREG_HANDLE,
  892. MLX5_IB_OBJECT_DEVX_UMEM,
  893. UVERBS_ACCESS_DESTROY,
  894. UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
  895. static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_QUERY_EQN,
  896. &UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC, UVERBS_ATTR_TYPE(u32),
  897. UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
  898. &UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN, UVERBS_ATTR_TYPE(u32),
  899. UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
  900. static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_QUERY_UAR,
  901. &UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX, UVERBS_ATTR_TYPE(u32),
  902. UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
  903. &UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX, UVERBS_ATTR_TYPE(u32),
  904. UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
  905. static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_OTHER,
  906. &UVERBS_ATTR_PTR_IN_SZ(MLX5_IB_ATTR_DEVX_OTHER_CMD_IN,
  907. UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
  908. UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
  909. UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO |
  910. UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY)),
  911. &UVERBS_ATTR_PTR_OUT_SZ(MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT,
  912. UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
  913. UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
  914. UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO))
  915. );
  916. static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_OBJ_CREATE,
  917. &UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE,
  918. MLX5_IB_OBJECT_DEVX_OBJ,
  919. UVERBS_ACCESS_NEW,
  920. UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
  921. &UVERBS_ATTR_PTR_IN_SZ(MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN,
  922. UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
  923. UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
  924. UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO |
  925. UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY)),
  926. &UVERBS_ATTR_PTR_OUT_SZ(MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT,
  927. UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
  928. UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
  929. UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO)));
  930. static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_OBJ_DESTROY,
  931. &UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_DESTROY_HANDLE,
  932. MLX5_IB_OBJECT_DEVX_OBJ,
  933. UVERBS_ACCESS_DESTROY,
  934. UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
  935. static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_OBJ_MODIFY,
  936. &UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE,
  937. MLX5_IB_OBJECT_DEVX_OBJ,
  938. UVERBS_ACCESS_WRITE,
  939. UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
  940. &UVERBS_ATTR_PTR_IN_SZ(MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN,
  941. UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
  942. UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
  943. UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO |
  944. UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY)),
  945. &UVERBS_ATTR_PTR_OUT_SZ(MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT,
  946. UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
  947. UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
  948. UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO)));
  949. static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_OBJ_QUERY,
  950. &UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE,
  951. MLX5_IB_OBJECT_DEVX_OBJ,
  952. UVERBS_ACCESS_READ,
  953. UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
  954. &UVERBS_ATTR_PTR_IN_SZ(MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN,
  955. UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
  956. UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
  957. UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO |
  958. UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY)),
  959. &UVERBS_ATTR_PTR_OUT_SZ(MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT,
  960. UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
  961. UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
  962. UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO)));
  963. static DECLARE_UVERBS_GLOBAL_METHODS(MLX5_IB_OBJECT_DEVX,
  964. &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OTHER),
  965. &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_UAR),
  966. &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_EQN));
  967. static DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ,
  968. &UVERBS_TYPE_ALLOC_IDR(0, devx_obj_cleanup),
  969. &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_CREATE),
  970. &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_DESTROY),
  971. &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_MODIFY),
  972. &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_QUERY));
  973. static DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM,
  974. &UVERBS_TYPE_ALLOC_IDR(0, devx_umem_cleanup),
  975. &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_REG),
  976. &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_DEREG));
  977. static DECLARE_UVERBS_OBJECT_TREE(devx_objects,
  978. &UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX),
  979. &UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ),
  980. &UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM));
  981. const struct uverbs_object_tree_def *mlx5_ib_get_devx_tree(void)
  982. {
  983. return &devx_objects;
  984. }