uverbs_std_types_device.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
  2. /*
  3. * Copyright (c) 2018, Mellanox Technologies inc. All rights reserved.
  4. */
  5. #include <linux/overflow.h>
  6. #include <rdma/uverbs_std_types.h>
  7. #include "rdma_core.h"
  8. #include "uverbs.h"
  9. #include <rdma/uverbs_ioctl.h>
  10. #include <rdma/opa_addr.h>
  11. #include <rdma/ib_cache.h>
  12. /*
  13. * This ioctl method allows calling any defined write or write_ex
  14. * handler. This essentially replaces the hdr/ex_hdr system with the ioctl
  15. * marshalling, and brings the non-ex path into the same marshalling as the ex
  16. * path.
  17. */
  18. static int UVERBS_HANDLER(UVERBS_METHOD_INVOKE_WRITE)(
  19. struct uverbs_attr_bundle *attrs)
  20. {
  21. struct uverbs_api *uapi = attrs->ufile->device->uapi;
  22. const struct uverbs_api_write_method *method_elm;
  23. u32 cmd;
  24. int rc;
  25. rc = uverbs_get_const(&cmd, attrs, UVERBS_ATTR_WRITE_CMD);
  26. if (rc)
  27. return rc;
  28. method_elm = uapi_get_method(uapi, cmd);
  29. if (IS_ERR(method_elm))
  30. return PTR_ERR(method_elm);
  31. uverbs_fill_udata(attrs, &attrs->ucore, UVERBS_ATTR_CORE_IN,
  32. UVERBS_ATTR_CORE_OUT);
  33. if (attrs->ucore.inlen < method_elm->req_size ||
  34. attrs->ucore.outlen < method_elm->resp_size)
  35. return -ENOSPC;
  36. attrs->uobject = NULL;
  37. rc = method_elm->handler(attrs);
  38. if (attrs->uobject)
  39. uverbs_finalize_object(attrs->uobject, UVERBS_ACCESS_NEW, true,
  40. !rc, attrs);
  41. return rc;
  42. }
  43. DECLARE_UVERBS_NAMED_METHOD(UVERBS_METHOD_INVOKE_WRITE,
  44. UVERBS_ATTR_CONST_IN(UVERBS_ATTR_WRITE_CMD,
  45. enum ib_uverbs_write_cmds,
  46. UA_MANDATORY),
  47. UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CORE_IN,
  48. UVERBS_ATTR_MIN_SIZE(sizeof(u32)),
  49. UA_OPTIONAL),
  50. UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CORE_OUT,
  51. UVERBS_ATTR_MIN_SIZE(0),
  52. UA_OPTIONAL),
  53. UVERBS_ATTR_UHW());
  54. static uint32_t *
  55. gather_objects_handle(struct ib_uverbs_file *ufile,
  56. const struct uverbs_api_object *uapi_object,
  57. struct uverbs_attr_bundle *attrs,
  58. ssize_t out_len,
  59. u64 *total)
  60. {
  61. u64 max_count = out_len / sizeof(u32);
  62. struct ib_uobject *obj;
  63. u64 count = 0;
  64. u32 *handles;
  65. /* Allocated memory that cannot page out where we gather
  66. * all object ids under a spin_lock.
  67. */
  68. handles = uverbs_zalloc(attrs, out_len);
  69. if (IS_ERR(handles))
  70. return handles;
  71. spin_lock_irq(&ufile->uobjects_lock);
  72. list_for_each_entry(obj, &ufile->uobjects, list) {
  73. u32 obj_id = obj->id;
  74. if (obj->uapi_object != uapi_object)
  75. continue;
  76. if (count >= max_count)
  77. break;
  78. handles[count] = obj_id;
  79. count++;
  80. }
  81. spin_unlock_irq(&ufile->uobjects_lock);
  82. *total = count;
  83. return handles;
  84. }
  85. static int UVERBS_HANDLER(UVERBS_METHOD_INFO_HANDLES)(
  86. struct uverbs_attr_bundle *attrs)
  87. {
  88. const struct uverbs_api_object *uapi_object;
  89. ssize_t out_len;
  90. u64 total = 0;
  91. u16 object_id;
  92. u32 *handles;
  93. int ret;
  94. out_len = uverbs_attr_get_len(attrs, UVERBS_ATTR_INFO_HANDLES_LIST);
  95. if (out_len <= 0 || (out_len % sizeof(u32) != 0))
  96. return -EINVAL;
  97. ret = uverbs_get_const(&object_id, attrs, UVERBS_ATTR_INFO_OBJECT_ID);
  98. if (ret)
  99. return ret;
  100. uapi_object = uapi_get_object(attrs->ufile->device->uapi, object_id);
  101. if (IS_ERR(uapi_object))
  102. return PTR_ERR(uapi_object);
  103. handles = gather_objects_handle(attrs->ufile, uapi_object, attrs,
  104. out_len, &total);
  105. if (IS_ERR(handles))
  106. return PTR_ERR(handles);
  107. ret = uverbs_copy_to(attrs, UVERBS_ATTR_INFO_HANDLES_LIST, handles,
  108. sizeof(u32) * total);
  109. if (ret)
  110. goto err;
  111. ret = uverbs_copy_to(attrs, UVERBS_ATTR_INFO_TOTAL_HANDLES, &total,
  112. sizeof(total));
  113. err:
  114. return ret;
  115. }
  116. void copy_port_attr_to_resp(struct ib_port_attr *attr,
  117. struct ib_uverbs_query_port_resp *resp,
  118. struct ib_device *ib_dev, u8 port_num)
  119. {
  120. resp->state = attr->state;
  121. resp->max_mtu = attr->max_mtu;
  122. resp->active_mtu = attr->active_mtu;
  123. resp->gid_tbl_len = attr->gid_tbl_len;
  124. resp->port_cap_flags = make_port_cap_flags(attr);
  125. resp->max_msg_sz = attr->max_msg_sz;
  126. resp->bad_pkey_cntr = attr->bad_pkey_cntr;
  127. resp->qkey_viol_cntr = attr->qkey_viol_cntr;
  128. resp->pkey_tbl_len = attr->pkey_tbl_len;
  129. if (rdma_is_grh_required(ib_dev, port_num))
  130. resp->flags |= IB_UVERBS_QPF_GRH_REQUIRED;
  131. if (rdma_cap_opa_ah(ib_dev, port_num)) {
  132. resp->lid = OPA_TO_IB_UCAST_LID(attr->lid);
  133. resp->sm_lid = OPA_TO_IB_UCAST_LID(attr->sm_lid);
  134. } else {
  135. resp->lid = ib_lid_cpu16(attr->lid);
  136. resp->sm_lid = ib_lid_cpu16(attr->sm_lid);
  137. }
  138. resp->lmc = attr->lmc;
  139. resp->max_vl_num = attr->max_vl_num;
  140. resp->sm_sl = attr->sm_sl;
  141. resp->subnet_timeout = attr->subnet_timeout;
  142. resp->init_type_reply = attr->init_type_reply;
  143. resp->active_width = attr->active_width;
  144. /* This ABI needs to be extended to provide any speed more than IB_SPEED_NDR */
  145. resp->active_speed = min_t(u16, attr->active_speed, IB_SPEED_NDR);
  146. resp->phys_state = attr->phys_state;
  147. resp->link_layer = rdma_port_get_link_layer(ib_dev, port_num);
  148. }
  149. static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_PORT)(
  150. struct uverbs_attr_bundle *attrs)
  151. {
  152. struct ib_device *ib_dev;
  153. struct ib_port_attr attr = {};
  154. struct ib_uverbs_query_port_resp_ex resp = {};
  155. struct ib_ucontext *ucontext;
  156. int ret;
  157. u8 port_num;
  158. ucontext = ib_uverbs_get_ucontext(attrs);
  159. if (IS_ERR(ucontext))
  160. return PTR_ERR(ucontext);
  161. ib_dev = ucontext->device;
  162. /* FIXME: Extend the UAPI_DEF_OBJ_NEEDS_FN stuff.. */
  163. if (!ib_dev->ops.query_port)
  164. return -EOPNOTSUPP;
  165. ret = uverbs_get_const(&port_num, attrs,
  166. UVERBS_ATTR_QUERY_PORT_PORT_NUM);
  167. if (ret)
  168. return ret;
  169. ret = ib_query_port(ib_dev, port_num, &attr);
  170. if (ret)
  171. return ret;
  172. copy_port_attr_to_resp(&attr, &resp.legacy_resp, ib_dev, port_num);
  173. resp.port_cap_flags2 = attr.port_cap_flags2;
  174. return uverbs_copy_to_struct_or_zero(attrs, UVERBS_ATTR_QUERY_PORT_RESP,
  175. &resp, sizeof(resp));
  176. }
  177. static int UVERBS_HANDLER(UVERBS_METHOD_GET_CONTEXT)(
  178. struct uverbs_attr_bundle *attrs)
  179. {
  180. u32 num_comp = attrs->ufile->device->num_comp_vectors;
  181. u64 core_support = IB_UVERBS_CORE_SUPPORT_OPTIONAL_MR_ACCESS;
  182. int ret;
  183. ret = uverbs_copy_to(attrs, UVERBS_ATTR_GET_CONTEXT_NUM_COMP_VECTORS,
  184. &num_comp, sizeof(num_comp));
  185. if (IS_UVERBS_COPY_ERR(ret))
  186. return ret;
  187. ret = uverbs_copy_to(attrs, UVERBS_ATTR_GET_CONTEXT_CORE_SUPPORT,
  188. &core_support, sizeof(core_support));
  189. if (IS_UVERBS_COPY_ERR(ret))
  190. return ret;
  191. ret = ib_alloc_ucontext(attrs);
  192. if (ret)
  193. return ret;
  194. ret = ib_init_ucontext(attrs);
  195. if (ret) {
  196. kfree(attrs->context);
  197. attrs->context = NULL;
  198. return ret;
  199. }
  200. return 0;
  201. }
  202. static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_CONTEXT)(
  203. struct uverbs_attr_bundle *attrs)
  204. {
  205. u64 core_support = IB_UVERBS_CORE_SUPPORT_OPTIONAL_MR_ACCESS;
  206. struct ib_ucontext *ucontext;
  207. struct ib_device *ib_dev;
  208. u32 num_comp;
  209. int ret;
  210. ucontext = ib_uverbs_get_ucontext(attrs);
  211. if (IS_ERR(ucontext))
  212. return PTR_ERR(ucontext);
  213. ib_dev = ucontext->device;
  214. if (!ib_dev->ops.query_ucontext)
  215. return -EOPNOTSUPP;
  216. num_comp = attrs->ufile->device->num_comp_vectors;
  217. ret = uverbs_copy_to(attrs, UVERBS_ATTR_QUERY_CONTEXT_NUM_COMP_VECTORS,
  218. &num_comp, sizeof(num_comp));
  219. if (IS_UVERBS_COPY_ERR(ret))
  220. return ret;
  221. ret = uverbs_copy_to(attrs, UVERBS_ATTR_QUERY_CONTEXT_CORE_SUPPORT,
  222. &core_support, sizeof(core_support));
  223. if (IS_UVERBS_COPY_ERR(ret))
  224. return ret;
  225. return ucontext->device->ops.query_ucontext(ucontext, attrs);
  226. }
  227. static int copy_gid_entries_to_user(struct uverbs_attr_bundle *attrs,
  228. struct ib_uverbs_gid_entry *entries,
  229. size_t num_entries, size_t user_entry_size)
  230. {
  231. const struct uverbs_attr *attr;
  232. void __user *user_entries;
  233. size_t copy_len;
  234. int ret;
  235. int i;
  236. if (user_entry_size == sizeof(*entries)) {
  237. ret = uverbs_copy_to(attrs,
  238. UVERBS_ATTR_QUERY_GID_TABLE_RESP_ENTRIES,
  239. entries, sizeof(*entries) * num_entries);
  240. return ret;
  241. }
  242. copy_len = min_t(size_t, user_entry_size, sizeof(*entries));
  243. attr = uverbs_attr_get(attrs, UVERBS_ATTR_QUERY_GID_TABLE_RESP_ENTRIES);
  244. if (IS_ERR(attr))
  245. return PTR_ERR(attr);
  246. user_entries = u64_to_user_ptr(attr->ptr_attr.data);
  247. for (i = 0; i < num_entries; i++) {
  248. if (copy_to_user(user_entries, entries, copy_len))
  249. return -EFAULT;
  250. if (user_entry_size > sizeof(*entries)) {
  251. if (clear_user(user_entries + sizeof(*entries),
  252. user_entry_size - sizeof(*entries)))
  253. return -EFAULT;
  254. }
  255. entries++;
  256. user_entries += user_entry_size;
  257. }
  258. return uverbs_output_written(attrs,
  259. UVERBS_ATTR_QUERY_GID_TABLE_RESP_ENTRIES);
  260. }
  261. static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_GID_TABLE)(
  262. struct uverbs_attr_bundle *attrs)
  263. {
  264. struct ib_uverbs_gid_entry *entries;
  265. struct ib_ucontext *ucontext;
  266. struct ib_device *ib_dev;
  267. size_t user_entry_size;
  268. ssize_t num_entries;
  269. int max_entries;
  270. u32 flags;
  271. int ret;
  272. ret = uverbs_get_flags32(&flags, attrs,
  273. UVERBS_ATTR_QUERY_GID_TABLE_FLAGS, 0);
  274. if (ret)
  275. return ret;
  276. ret = uverbs_get_const(&user_entry_size, attrs,
  277. UVERBS_ATTR_QUERY_GID_TABLE_ENTRY_SIZE);
  278. if (ret)
  279. return ret;
  280. if (!user_entry_size)
  281. return -EINVAL;
  282. max_entries = uverbs_attr_ptr_get_array_size(
  283. attrs, UVERBS_ATTR_QUERY_GID_TABLE_RESP_ENTRIES,
  284. user_entry_size);
  285. if (max_entries <= 0)
  286. return max_entries ?: -EINVAL;
  287. ucontext = ib_uverbs_get_ucontext(attrs);
  288. if (IS_ERR(ucontext))
  289. return PTR_ERR(ucontext);
  290. ib_dev = ucontext->device;
  291. entries = uverbs_kcalloc(attrs, max_entries, sizeof(*entries));
  292. if (IS_ERR(entries))
  293. return PTR_ERR(entries);
  294. num_entries = rdma_query_gid_table(ib_dev, entries, max_entries);
  295. if (num_entries < 0)
  296. return -EINVAL;
  297. ret = copy_gid_entries_to_user(attrs, entries, num_entries,
  298. user_entry_size);
  299. if (ret)
  300. return ret;
  301. ret = uverbs_copy_to(attrs,
  302. UVERBS_ATTR_QUERY_GID_TABLE_RESP_NUM_ENTRIES,
  303. &num_entries, sizeof(num_entries));
  304. return ret;
  305. }
  306. static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_GID_ENTRY)(
  307. struct uverbs_attr_bundle *attrs)
  308. {
  309. struct ib_uverbs_gid_entry entry = {};
  310. const struct ib_gid_attr *gid_attr;
  311. struct ib_ucontext *ucontext;
  312. struct ib_device *ib_dev;
  313. struct net_device *ndev;
  314. u32 gid_index;
  315. u32 port_num;
  316. u32 flags;
  317. int ret;
  318. ret = uverbs_get_flags32(&flags, attrs,
  319. UVERBS_ATTR_QUERY_GID_ENTRY_FLAGS, 0);
  320. if (ret)
  321. return ret;
  322. ret = uverbs_get_const(&port_num, attrs,
  323. UVERBS_ATTR_QUERY_GID_ENTRY_PORT);
  324. if (ret)
  325. return ret;
  326. ret = uverbs_get_const(&gid_index, attrs,
  327. UVERBS_ATTR_QUERY_GID_ENTRY_GID_INDEX);
  328. if (ret)
  329. return ret;
  330. ucontext = ib_uverbs_get_ucontext(attrs);
  331. if (IS_ERR(ucontext))
  332. return PTR_ERR(ucontext);
  333. ib_dev = ucontext->device;
  334. if (!rdma_is_port_valid(ib_dev, port_num))
  335. return -EINVAL;
  336. gid_attr = rdma_get_gid_attr(ib_dev, port_num, gid_index);
  337. if (IS_ERR(gid_attr))
  338. return PTR_ERR(gid_attr);
  339. memcpy(&entry.gid, &gid_attr->gid, sizeof(gid_attr->gid));
  340. entry.gid_index = gid_attr->index;
  341. entry.port_num = gid_attr->port_num;
  342. entry.gid_type = gid_attr->gid_type;
  343. rcu_read_lock();
  344. ndev = rdma_read_gid_attr_ndev_rcu(gid_attr);
  345. if (IS_ERR(ndev)) {
  346. if (PTR_ERR(ndev) != -ENODEV) {
  347. ret = PTR_ERR(ndev);
  348. rcu_read_unlock();
  349. goto out;
  350. }
  351. } else {
  352. entry.netdev_ifindex = ndev->ifindex;
  353. }
  354. rcu_read_unlock();
  355. ret = uverbs_copy_to_struct_or_zero(
  356. attrs, UVERBS_ATTR_QUERY_GID_ENTRY_RESP_ENTRY, &entry,
  357. sizeof(entry));
  358. out:
  359. rdma_put_gid_attr(gid_attr);
  360. return ret;
  361. }
  362. DECLARE_UVERBS_NAMED_METHOD(
  363. UVERBS_METHOD_GET_CONTEXT,
  364. UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_GET_CONTEXT_NUM_COMP_VECTORS,
  365. UVERBS_ATTR_TYPE(u32), UA_OPTIONAL),
  366. UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_GET_CONTEXT_CORE_SUPPORT,
  367. UVERBS_ATTR_TYPE(u64), UA_OPTIONAL),
  368. UVERBS_ATTR_UHW());
  369. DECLARE_UVERBS_NAMED_METHOD(
  370. UVERBS_METHOD_QUERY_CONTEXT,
  371. UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_QUERY_CONTEXT_NUM_COMP_VECTORS,
  372. UVERBS_ATTR_TYPE(u32), UA_OPTIONAL),
  373. UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_QUERY_CONTEXT_CORE_SUPPORT,
  374. UVERBS_ATTR_TYPE(u64), UA_OPTIONAL));
  375. DECLARE_UVERBS_NAMED_METHOD(
  376. UVERBS_METHOD_INFO_HANDLES,
  377. /* Also includes any device specific object ids */
  378. UVERBS_ATTR_CONST_IN(UVERBS_ATTR_INFO_OBJECT_ID,
  379. enum uverbs_default_objects, UA_MANDATORY),
  380. UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_INFO_TOTAL_HANDLES,
  381. UVERBS_ATTR_TYPE(u32), UA_OPTIONAL),
  382. UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_INFO_HANDLES_LIST,
  383. UVERBS_ATTR_MIN_SIZE(sizeof(u32)), UA_OPTIONAL));
  384. DECLARE_UVERBS_NAMED_METHOD(
  385. UVERBS_METHOD_QUERY_PORT,
  386. UVERBS_ATTR_CONST_IN(UVERBS_ATTR_QUERY_PORT_PORT_NUM, u8, UA_MANDATORY),
  387. UVERBS_ATTR_PTR_OUT(
  388. UVERBS_ATTR_QUERY_PORT_RESP,
  389. UVERBS_ATTR_STRUCT(struct ib_uverbs_query_port_resp_ex,
  390. reserved),
  391. UA_MANDATORY));
  392. DECLARE_UVERBS_NAMED_METHOD(
  393. UVERBS_METHOD_QUERY_GID_TABLE,
  394. UVERBS_ATTR_CONST_IN(UVERBS_ATTR_QUERY_GID_TABLE_ENTRY_SIZE, u64,
  395. UA_MANDATORY),
  396. UVERBS_ATTR_FLAGS_IN(UVERBS_ATTR_QUERY_GID_TABLE_FLAGS, u32,
  397. UA_OPTIONAL),
  398. UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_QUERY_GID_TABLE_RESP_ENTRIES,
  399. UVERBS_ATTR_MIN_SIZE(0), UA_MANDATORY),
  400. UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_QUERY_GID_TABLE_RESP_NUM_ENTRIES,
  401. UVERBS_ATTR_TYPE(u64), UA_MANDATORY));
  402. DECLARE_UVERBS_NAMED_METHOD(
  403. UVERBS_METHOD_QUERY_GID_ENTRY,
  404. UVERBS_ATTR_CONST_IN(UVERBS_ATTR_QUERY_GID_ENTRY_PORT, u32,
  405. UA_MANDATORY),
  406. UVERBS_ATTR_CONST_IN(UVERBS_ATTR_QUERY_GID_ENTRY_GID_INDEX, u32,
  407. UA_MANDATORY),
  408. UVERBS_ATTR_FLAGS_IN(UVERBS_ATTR_QUERY_GID_ENTRY_FLAGS, u32,
  409. UA_MANDATORY),
  410. UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_QUERY_GID_ENTRY_RESP_ENTRY,
  411. UVERBS_ATTR_STRUCT(struct ib_uverbs_gid_entry,
  412. netdev_ifindex),
  413. UA_MANDATORY));
  414. DECLARE_UVERBS_GLOBAL_METHODS(UVERBS_OBJECT_DEVICE,
  415. &UVERBS_METHOD(UVERBS_METHOD_GET_CONTEXT),
  416. &UVERBS_METHOD(UVERBS_METHOD_INVOKE_WRITE),
  417. &UVERBS_METHOD(UVERBS_METHOD_INFO_HANDLES),
  418. &UVERBS_METHOD(UVERBS_METHOD_QUERY_PORT),
  419. &UVERBS_METHOD(UVERBS_METHOD_QUERY_CONTEXT),
  420. &UVERBS_METHOD(UVERBS_METHOD_QUERY_GID_TABLE),
  421. &UVERBS_METHOD(UVERBS_METHOD_QUERY_GID_ENTRY));
  422. const struct uapi_definition uverbs_def_obj_device[] = {
  423. UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_DEVICE),
  424. {},
  425. };