qp.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /*
  2. * Copyright (c) 2013, Mellanox Technologies inc. 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. int mlx5_core_create_qp(struct mlx5_core_dev *dev,
  77. struct mlx5_core_qp *qp,
  78. struct mlx5_create_qp_mbox_in *in,
  79. int inlen)
  80. {
  81. struct mlx5_qp_table *table = &dev->priv.qp_table;
  82. struct mlx5_create_qp_mbox_out out;
  83. struct mlx5_destroy_qp_mbox_in din;
  84. struct mlx5_destroy_qp_mbox_out dout;
  85. int err;
  86. memset(&out, 0, sizeof(out));
  87. in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_CREATE_QP);
  88. err = mlx5_cmd_exec(dev, in, inlen, &out, sizeof(out));
  89. if (err) {
  90. mlx5_core_warn(dev, "ret %d\n", err);
  91. return err;
  92. }
  93. if (out.hdr.status) {
  94. mlx5_core_warn(dev, "current num of QPs 0x%x\n",
  95. atomic_read(&dev->num_qps));
  96. return mlx5_cmd_status_to_err(&out.hdr);
  97. }
  98. qp->qpn = be32_to_cpu(out.qpn) & 0xffffff;
  99. mlx5_core_dbg(dev, "qpn = 0x%x\n", qp->qpn);
  100. qp->common.res = MLX5_RES_QP;
  101. spin_lock_irq(&table->lock);
  102. err = radix_tree_insert(&table->tree, qp->qpn, qp);
  103. spin_unlock_irq(&table->lock);
  104. if (err) {
  105. mlx5_core_warn(dev, "err %d\n", err);
  106. goto err_cmd;
  107. }
  108. err = mlx5_debug_qp_add(dev, qp);
  109. if (err)
  110. mlx5_core_dbg(dev, "failed adding QP 0x%x to debug file system\n",
  111. qp->qpn);
  112. qp->pid = current->pid;
  113. atomic_set(&qp->common.refcount, 1);
  114. atomic_inc(&dev->num_qps);
  115. init_completion(&qp->common.free);
  116. return 0;
  117. err_cmd:
  118. memset(&din, 0, sizeof(din));
  119. memset(&dout, 0, sizeof(dout));
  120. din.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DESTROY_QP);
  121. din.qpn = cpu_to_be32(qp->qpn);
  122. mlx5_cmd_exec(dev, &din, sizeof(din), &out, sizeof(dout));
  123. return err;
  124. }
  125. EXPORT_SYMBOL_GPL(mlx5_core_create_qp);
  126. int mlx5_core_destroy_qp(struct mlx5_core_dev *dev,
  127. struct mlx5_core_qp *qp)
  128. {
  129. struct mlx5_destroy_qp_mbox_in in;
  130. struct mlx5_destroy_qp_mbox_out out;
  131. struct mlx5_qp_table *table = &dev->priv.qp_table;
  132. unsigned long flags;
  133. int err;
  134. mlx5_debug_qp_remove(dev, qp);
  135. spin_lock_irqsave(&table->lock, flags);
  136. radix_tree_delete(&table->tree, qp->qpn);
  137. spin_unlock_irqrestore(&table->lock, flags);
  138. mlx5_core_put_rsc((struct mlx5_core_rsc_common *)qp);
  139. wait_for_completion(&qp->common.free);
  140. memset(&in, 0, sizeof(in));
  141. memset(&out, 0, sizeof(out));
  142. in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DESTROY_QP);
  143. in.qpn = cpu_to_be32(qp->qpn);
  144. err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
  145. if (err)
  146. return err;
  147. if (out.hdr.status)
  148. return mlx5_cmd_status_to_err(&out.hdr);
  149. atomic_dec(&dev->num_qps);
  150. return 0;
  151. }
  152. EXPORT_SYMBOL_GPL(mlx5_core_destroy_qp);
  153. int mlx5_core_qp_modify(struct mlx5_core_dev *dev, enum mlx5_qp_state cur_state,
  154. enum mlx5_qp_state new_state,
  155. struct mlx5_modify_qp_mbox_in *in, int sqd_event,
  156. struct mlx5_core_qp *qp)
  157. {
  158. static const u16 optab[MLX5_QP_NUM_STATE][MLX5_QP_NUM_STATE] = {
  159. [MLX5_QP_STATE_RST] = {
  160. [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP,
  161. [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP,
  162. [MLX5_QP_STATE_INIT] = MLX5_CMD_OP_RST2INIT_QP,
  163. },
  164. [MLX5_QP_STATE_INIT] = {
  165. [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP,
  166. [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP,
  167. [MLX5_QP_STATE_INIT] = MLX5_CMD_OP_INIT2INIT_QP,
  168. [MLX5_QP_STATE_RTR] = MLX5_CMD_OP_INIT2RTR_QP,
  169. },
  170. [MLX5_QP_STATE_RTR] = {
  171. [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP,
  172. [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP,
  173. [MLX5_QP_STATE_RTS] = MLX5_CMD_OP_RTR2RTS_QP,
  174. },
  175. [MLX5_QP_STATE_RTS] = {
  176. [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP,
  177. [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP,
  178. [MLX5_QP_STATE_RTS] = MLX5_CMD_OP_RTS2RTS_QP,
  179. },
  180. [MLX5_QP_STATE_SQD] = {
  181. [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP,
  182. [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP,
  183. },
  184. [MLX5_QP_STATE_SQER] = {
  185. [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP,
  186. [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP,
  187. [MLX5_QP_STATE_RTS] = MLX5_CMD_OP_SQERR2RTS_QP,
  188. },
  189. [MLX5_QP_STATE_ERR] = {
  190. [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP,
  191. [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP,
  192. }
  193. };
  194. struct mlx5_modify_qp_mbox_out out;
  195. int err = 0;
  196. u16 op;
  197. if (cur_state >= MLX5_QP_NUM_STATE || new_state >= MLX5_QP_NUM_STATE ||
  198. !optab[cur_state][new_state])
  199. return -EINVAL;
  200. memset(&out, 0, sizeof(out));
  201. op = optab[cur_state][new_state];
  202. in->hdr.opcode = cpu_to_be16(op);
  203. in->qpn = cpu_to_be32(qp->qpn);
  204. err = mlx5_cmd_exec(dev, in, sizeof(*in), &out, sizeof(out));
  205. if (err)
  206. return err;
  207. return mlx5_cmd_status_to_err(&out.hdr);
  208. }
  209. EXPORT_SYMBOL_GPL(mlx5_core_qp_modify);
  210. void mlx5_init_qp_table(struct mlx5_core_dev *dev)
  211. {
  212. struct mlx5_qp_table *table = &dev->priv.qp_table;
  213. spin_lock_init(&table->lock);
  214. INIT_RADIX_TREE(&table->tree, GFP_ATOMIC);
  215. mlx5_qp_debugfs_init(dev);
  216. }
  217. void mlx5_cleanup_qp_table(struct mlx5_core_dev *dev)
  218. {
  219. mlx5_qp_debugfs_cleanup(dev);
  220. }
  221. int mlx5_core_qp_query(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp,
  222. struct mlx5_query_qp_mbox_out *out, int outlen)
  223. {
  224. struct mlx5_query_qp_mbox_in in;
  225. int err;
  226. memset(&in, 0, sizeof(in));
  227. memset(out, 0, outlen);
  228. in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_QP);
  229. in.qpn = cpu_to_be32(qp->qpn);
  230. err = mlx5_cmd_exec(dev, &in, sizeof(in), out, outlen);
  231. if (err)
  232. return err;
  233. if (out->hdr.status)
  234. return mlx5_cmd_status_to_err(&out->hdr);
  235. return err;
  236. }
  237. EXPORT_SYMBOL_GPL(mlx5_core_qp_query);
  238. int mlx5_core_xrcd_alloc(struct mlx5_core_dev *dev, u32 *xrcdn)
  239. {
  240. struct mlx5_alloc_xrcd_mbox_in in;
  241. struct mlx5_alloc_xrcd_mbox_out out;
  242. int err;
  243. memset(&in, 0, sizeof(in));
  244. memset(&out, 0, sizeof(out));
  245. in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_ALLOC_XRCD);
  246. err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
  247. if (err)
  248. return err;
  249. if (out.hdr.status)
  250. err = mlx5_cmd_status_to_err(&out.hdr);
  251. else
  252. *xrcdn = be32_to_cpu(out.xrcdn);
  253. return err;
  254. }
  255. EXPORT_SYMBOL_GPL(mlx5_core_xrcd_alloc);
  256. int mlx5_core_xrcd_dealloc(struct mlx5_core_dev *dev, u32 xrcdn)
  257. {
  258. struct mlx5_dealloc_xrcd_mbox_in in;
  259. struct mlx5_dealloc_xrcd_mbox_out out;
  260. int err;
  261. memset(&in, 0, sizeof(in));
  262. memset(&out, 0, sizeof(out));
  263. in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DEALLOC_XRCD);
  264. in.xrcdn = cpu_to_be32(xrcdn);
  265. err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
  266. if (err)
  267. return err;
  268. if (out.hdr.status)
  269. err = mlx5_cmd_status_to_err(&out.hdr);
  270. return err;
  271. }
  272. EXPORT_SYMBOL_GPL(mlx5_core_xrcd_dealloc);