qp.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. /*
  2. * Copyright (c) 2013-2015, Mellanox Technologies. All rights reserved.
  3. *
  4. * This software is available to you under a choice of one of two
  5. * licenses. You may choose to be licensed under the terms of the GNU
  6. * General Public License (GPL) Version 2, available from the file
  7. * COPYING in the main directory of this source tree, or the
  8. * OpenIB.org BSD license below:
  9. *
  10. * Redistribution and use in source and binary forms, with or
  11. * without modification, are permitted provided that the following
  12. * conditions are met:
  13. *
  14. * - Redistributions of source code must retain the above
  15. * copyright notice, this list of conditions and the following
  16. * disclaimer.
  17. *
  18. * - Redistributions in binary form must reproduce the above
  19. * copyright notice, this list of conditions and the following
  20. * disclaimer in the documentation and/or other materials
  21. * provided with the distribution.
  22. *
  23. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  27. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  28. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  29. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  30. * SOFTWARE.
  31. */
  32. #include <linux/gfp.h>
  33. #include <linux/export.h>
  34. #include <linux/mlx5/cmd.h>
  35. #include <linux/mlx5/qp.h>
  36. #include <linux/mlx5/driver.h>
  37. #include "mlx5_core.h"
  38. static struct mlx5_core_rsc_common *mlx5_get_rsc(struct mlx5_core_dev *dev,
  39. u32 rsn)
  40. {
  41. struct mlx5_qp_table *table = &dev->priv.qp_table;
  42. struct mlx5_core_rsc_common *common;
  43. spin_lock(&table->lock);
  44. common = radix_tree_lookup(&table->tree, rsn);
  45. if (common)
  46. atomic_inc(&common->refcount);
  47. spin_unlock(&table->lock);
  48. if (!common) {
  49. mlx5_core_warn(dev, "Async event for bogus resource 0x%x\n",
  50. rsn);
  51. return NULL;
  52. }
  53. return common;
  54. }
  55. void mlx5_core_put_rsc(struct mlx5_core_rsc_common *common)
  56. {
  57. if (atomic_dec_and_test(&common->refcount))
  58. complete(&common->free);
  59. }
  60. void mlx5_rsc_event(struct mlx5_core_dev *dev, u32 rsn, int event_type)
  61. {
  62. struct mlx5_core_rsc_common *common = mlx5_get_rsc(dev, rsn);
  63. struct mlx5_core_qp *qp;
  64. if (!common)
  65. return;
  66. switch (common->res) {
  67. case MLX5_RES_QP:
  68. qp = (struct mlx5_core_qp *)common;
  69. qp->event(qp, event_type);
  70. break;
  71. default:
  72. mlx5_core_warn(dev, "invalid resource type for 0x%x\n", rsn);
  73. }
  74. mlx5_core_put_rsc(common);
  75. }
  76. #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
  77. void mlx5_eq_pagefault(struct mlx5_core_dev *dev, struct mlx5_eqe *eqe)
  78. {
  79. struct mlx5_eqe_page_fault *pf_eqe = &eqe->data.page_fault;
  80. int qpn = be32_to_cpu(pf_eqe->flags_qpn) & MLX5_QPN_MASK;
  81. struct mlx5_core_rsc_common *common = mlx5_get_rsc(dev, qpn);
  82. struct mlx5_core_qp *qp =
  83. container_of(common, struct mlx5_core_qp, common);
  84. struct mlx5_pagefault pfault;
  85. if (!qp) {
  86. mlx5_core_warn(dev, "ODP event for non-existent QP %06x\n",
  87. qpn);
  88. return;
  89. }
  90. pfault.event_subtype = eqe->sub_type;
  91. pfault.flags = (be32_to_cpu(pf_eqe->flags_qpn) >> MLX5_QPN_BITS) &
  92. (MLX5_PFAULT_REQUESTOR | MLX5_PFAULT_WRITE | MLX5_PFAULT_RDMA);
  93. pfault.bytes_committed = be32_to_cpu(
  94. pf_eqe->bytes_committed);
  95. mlx5_core_dbg(dev,
  96. "PAGE_FAULT: subtype: 0x%02x, flags: 0x%02x,\n",
  97. eqe->sub_type, pfault.flags);
  98. switch (eqe->sub_type) {
  99. case MLX5_PFAULT_SUBTYPE_RDMA:
  100. /* RDMA based event */
  101. pfault.rdma.r_key =
  102. be32_to_cpu(pf_eqe->rdma.r_key);
  103. pfault.rdma.packet_size =
  104. be16_to_cpu(pf_eqe->rdma.packet_length);
  105. pfault.rdma.rdma_op_len =
  106. be32_to_cpu(pf_eqe->rdma.rdma_op_len);
  107. pfault.rdma.rdma_va =
  108. be64_to_cpu(pf_eqe->rdma.rdma_va);
  109. mlx5_core_dbg(dev,
  110. "PAGE_FAULT: qpn: 0x%06x, r_key: 0x%08x,\n",
  111. qpn, pfault.rdma.r_key);
  112. mlx5_core_dbg(dev,
  113. "PAGE_FAULT: rdma_op_len: 0x%08x,\n",
  114. pfault.rdma.rdma_op_len);
  115. mlx5_core_dbg(dev,
  116. "PAGE_FAULT: rdma_va: 0x%016llx,\n",
  117. pfault.rdma.rdma_va);
  118. mlx5_core_dbg(dev,
  119. "PAGE_FAULT: bytes_committed: 0x%06x\n",
  120. pfault.bytes_committed);
  121. break;
  122. case MLX5_PFAULT_SUBTYPE_WQE:
  123. /* WQE based event */
  124. pfault.wqe.wqe_index =
  125. be16_to_cpu(pf_eqe->wqe.wqe_index);
  126. pfault.wqe.packet_size =
  127. be16_to_cpu(pf_eqe->wqe.packet_length);
  128. mlx5_core_dbg(dev,
  129. "PAGE_FAULT: qpn: 0x%06x, wqe_index: 0x%04x,\n",
  130. qpn, pfault.wqe.wqe_index);
  131. mlx5_core_dbg(dev,
  132. "PAGE_FAULT: bytes_committed: 0x%06x\n",
  133. pfault.bytes_committed);
  134. break;
  135. default:
  136. mlx5_core_warn(dev,
  137. "Unsupported page fault event sub-type: 0x%02hhx, QP %06x\n",
  138. eqe->sub_type, qpn);
  139. /* Unsupported page faults should still be resolved by the
  140. * page fault handler
  141. */
  142. }
  143. if (qp->pfault_handler) {
  144. qp->pfault_handler(qp, &pfault);
  145. } else {
  146. mlx5_core_err(dev,
  147. "ODP event for QP %08x, without a fault handler in QP\n",
  148. qpn);
  149. /* Page fault will remain unresolved. QP will hang until it is
  150. * destroyed
  151. */
  152. }
  153. mlx5_core_put_rsc(common);
  154. }
  155. #endif
  156. int mlx5_core_create_qp(struct mlx5_core_dev *dev,
  157. struct mlx5_core_qp *qp,
  158. struct mlx5_create_qp_mbox_in *in,
  159. int inlen)
  160. {
  161. struct mlx5_qp_table *table = &dev->priv.qp_table;
  162. struct mlx5_create_qp_mbox_out out;
  163. struct mlx5_destroy_qp_mbox_in din;
  164. struct mlx5_destroy_qp_mbox_out dout;
  165. int err;
  166. void *qpc;
  167. memset(&out, 0, sizeof(out));
  168. in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_CREATE_QP);
  169. if (dev->issi) {
  170. qpc = MLX5_ADDR_OF(create_qp_in, in, qpc);
  171. /* 0xffffff means we ask to work with cqe version 0 */
  172. MLX5_SET(qpc, qpc, user_index, 0xffffff);
  173. }
  174. err = mlx5_cmd_exec(dev, in, inlen, &out, sizeof(out));
  175. if (err) {
  176. mlx5_core_warn(dev, "ret %d\n", err);
  177. return err;
  178. }
  179. if (out.hdr.status) {
  180. mlx5_core_warn(dev, "current num of QPs 0x%x\n",
  181. atomic_read(&dev->num_qps));
  182. return mlx5_cmd_status_to_err(&out.hdr);
  183. }
  184. qp->qpn = be32_to_cpu(out.qpn) & 0xffffff;
  185. mlx5_core_dbg(dev, "qpn = 0x%x\n", qp->qpn);
  186. qp->common.res = MLX5_RES_QP;
  187. spin_lock_irq(&table->lock);
  188. err = radix_tree_insert(&table->tree, qp->qpn, qp);
  189. spin_unlock_irq(&table->lock);
  190. if (err) {
  191. mlx5_core_warn(dev, "err %d\n", err);
  192. goto err_cmd;
  193. }
  194. err = mlx5_debug_qp_add(dev, qp);
  195. if (err)
  196. mlx5_core_dbg(dev, "failed adding QP 0x%x to debug file system\n",
  197. qp->qpn);
  198. qp->pid = current->pid;
  199. atomic_set(&qp->common.refcount, 1);
  200. atomic_inc(&dev->num_qps);
  201. init_completion(&qp->common.free);
  202. return 0;
  203. err_cmd:
  204. memset(&din, 0, sizeof(din));
  205. memset(&dout, 0, sizeof(dout));
  206. din.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DESTROY_QP);
  207. din.qpn = cpu_to_be32(qp->qpn);
  208. mlx5_cmd_exec(dev, &din, sizeof(din), &out, sizeof(dout));
  209. return err;
  210. }
  211. EXPORT_SYMBOL_GPL(mlx5_core_create_qp);
  212. int mlx5_core_destroy_qp(struct mlx5_core_dev *dev,
  213. struct mlx5_core_qp *qp)
  214. {
  215. struct mlx5_destroy_qp_mbox_in in;
  216. struct mlx5_destroy_qp_mbox_out out;
  217. struct mlx5_qp_table *table = &dev->priv.qp_table;
  218. unsigned long flags;
  219. int err;
  220. mlx5_debug_qp_remove(dev, qp);
  221. spin_lock_irqsave(&table->lock, flags);
  222. radix_tree_delete(&table->tree, qp->qpn);
  223. spin_unlock_irqrestore(&table->lock, flags);
  224. mlx5_core_put_rsc((struct mlx5_core_rsc_common *)qp);
  225. wait_for_completion(&qp->common.free);
  226. memset(&in, 0, sizeof(in));
  227. memset(&out, 0, sizeof(out));
  228. in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DESTROY_QP);
  229. in.qpn = cpu_to_be32(qp->qpn);
  230. err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
  231. if (err)
  232. return err;
  233. if (out.hdr.status)
  234. return mlx5_cmd_status_to_err(&out.hdr);
  235. atomic_dec(&dev->num_qps);
  236. return 0;
  237. }
  238. EXPORT_SYMBOL_GPL(mlx5_core_destroy_qp);
  239. int mlx5_core_qp_modify(struct mlx5_core_dev *dev, enum mlx5_qp_state cur_state,
  240. enum mlx5_qp_state new_state,
  241. struct mlx5_modify_qp_mbox_in *in, int sqd_event,
  242. struct mlx5_core_qp *qp)
  243. {
  244. static const u16 optab[MLX5_QP_NUM_STATE][MLX5_QP_NUM_STATE] = {
  245. [MLX5_QP_STATE_RST] = {
  246. [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP,
  247. [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP,
  248. [MLX5_QP_STATE_INIT] = MLX5_CMD_OP_RST2INIT_QP,
  249. },
  250. [MLX5_QP_STATE_INIT] = {
  251. [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP,
  252. [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP,
  253. [MLX5_QP_STATE_INIT] = MLX5_CMD_OP_INIT2INIT_QP,
  254. [MLX5_QP_STATE_RTR] = MLX5_CMD_OP_INIT2RTR_QP,
  255. },
  256. [MLX5_QP_STATE_RTR] = {
  257. [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP,
  258. [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP,
  259. [MLX5_QP_STATE_RTS] = MLX5_CMD_OP_RTR2RTS_QP,
  260. },
  261. [MLX5_QP_STATE_RTS] = {
  262. [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP,
  263. [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP,
  264. [MLX5_QP_STATE_RTS] = MLX5_CMD_OP_RTS2RTS_QP,
  265. },
  266. [MLX5_QP_STATE_SQD] = {
  267. [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP,
  268. [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP,
  269. },
  270. [MLX5_QP_STATE_SQER] = {
  271. [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP,
  272. [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP,
  273. [MLX5_QP_STATE_RTS] = MLX5_CMD_OP_SQERR2RTS_QP,
  274. },
  275. [MLX5_QP_STATE_ERR] = {
  276. [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP,
  277. [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP,
  278. }
  279. };
  280. struct mlx5_modify_qp_mbox_out out;
  281. int err = 0;
  282. u16 op;
  283. if (cur_state >= MLX5_QP_NUM_STATE || new_state >= MLX5_QP_NUM_STATE ||
  284. !optab[cur_state][new_state])
  285. return -EINVAL;
  286. memset(&out, 0, sizeof(out));
  287. op = optab[cur_state][new_state];
  288. in->hdr.opcode = cpu_to_be16(op);
  289. in->qpn = cpu_to_be32(qp->qpn);
  290. err = mlx5_cmd_exec(dev, in, sizeof(*in), &out, sizeof(out));
  291. if (err)
  292. return err;
  293. return mlx5_cmd_status_to_err(&out.hdr);
  294. }
  295. EXPORT_SYMBOL_GPL(mlx5_core_qp_modify);
  296. void mlx5_init_qp_table(struct mlx5_core_dev *dev)
  297. {
  298. struct mlx5_qp_table *table = &dev->priv.qp_table;
  299. spin_lock_init(&table->lock);
  300. INIT_RADIX_TREE(&table->tree, GFP_ATOMIC);
  301. mlx5_qp_debugfs_init(dev);
  302. }
  303. void mlx5_cleanup_qp_table(struct mlx5_core_dev *dev)
  304. {
  305. mlx5_qp_debugfs_cleanup(dev);
  306. }
  307. int mlx5_core_qp_query(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp,
  308. struct mlx5_query_qp_mbox_out *out, int outlen)
  309. {
  310. struct mlx5_query_qp_mbox_in in;
  311. int err;
  312. memset(&in, 0, sizeof(in));
  313. memset(out, 0, outlen);
  314. in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_QP);
  315. in.qpn = cpu_to_be32(qp->qpn);
  316. err = mlx5_cmd_exec(dev, &in, sizeof(in), out, outlen);
  317. if (err)
  318. return err;
  319. if (out->hdr.status)
  320. return mlx5_cmd_status_to_err(&out->hdr);
  321. return err;
  322. }
  323. EXPORT_SYMBOL_GPL(mlx5_core_qp_query);
  324. int mlx5_core_xrcd_alloc(struct mlx5_core_dev *dev, u32 *xrcdn)
  325. {
  326. struct mlx5_alloc_xrcd_mbox_in in;
  327. struct mlx5_alloc_xrcd_mbox_out out;
  328. int err;
  329. memset(&in, 0, sizeof(in));
  330. memset(&out, 0, sizeof(out));
  331. in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_ALLOC_XRCD);
  332. err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
  333. if (err)
  334. return err;
  335. if (out.hdr.status)
  336. err = mlx5_cmd_status_to_err(&out.hdr);
  337. else
  338. *xrcdn = be32_to_cpu(out.xrcdn);
  339. return err;
  340. }
  341. EXPORT_SYMBOL_GPL(mlx5_core_xrcd_alloc);
  342. int mlx5_core_xrcd_dealloc(struct mlx5_core_dev *dev, u32 xrcdn)
  343. {
  344. struct mlx5_dealloc_xrcd_mbox_in in;
  345. struct mlx5_dealloc_xrcd_mbox_out out;
  346. int err;
  347. memset(&in, 0, sizeof(in));
  348. memset(&out, 0, sizeof(out));
  349. in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DEALLOC_XRCD);
  350. in.xrcdn = cpu_to_be32(xrcdn);
  351. err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
  352. if (err)
  353. return err;
  354. if (out.hdr.status)
  355. err = mlx5_cmd_status_to_err(&out.hdr);
  356. return err;
  357. }
  358. EXPORT_SYMBOL_GPL(mlx5_core_xrcd_dealloc);
  359. #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
  360. int mlx5_core_page_fault_resume(struct mlx5_core_dev *dev, u32 qpn,
  361. u8 flags, int error)
  362. {
  363. struct mlx5_page_fault_resume_mbox_in in;
  364. struct mlx5_page_fault_resume_mbox_out out;
  365. int err;
  366. memset(&in, 0, sizeof(in));
  367. memset(&out, 0, sizeof(out));
  368. in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_PAGE_FAULT_RESUME);
  369. in.hdr.opmod = 0;
  370. flags &= (MLX5_PAGE_FAULT_RESUME_REQUESTOR |
  371. MLX5_PAGE_FAULT_RESUME_WRITE |
  372. MLX5_PAGE_FAULT_RESUME_RDMA);
  373. flags |= (error ? MLX5_PAGE_FAULT_RESUME_ERROR : 0);
  374. in.flags_qpn = cpu_to_be32((qpn & MLX5_QPN_MASK) |
  375. (flags << MLX5_QPN_BITS));
  376. err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
  377. if (err)
  378. return err;
  379. if (out.hdr.status)
  380. err = mlx5_cmd_status_to_err(&out.hdr);
  381. return err;
  382. }
  383. EXPORT_SYMBOL_GPL(mlx5_core_page_fault_resume);
  384. #endif