gsi.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. /*
  2. * Copyright (c) 2016, 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 "mlx5_ib.h"
  33. struct mlx5_ib_gsi_wr {
  34. struct ib_cqe cqe;
  35. struct ib_wc wc;
  36. int send_flags;
  37. bool completed:1;
  38. };
  39. struct mlx5_ib_gsi_qp {
  40. struct ib_qp ibqp;
  41. struct ib_qp *rx_qp;
  42. u8 port_num;
  43. struct ib_qp_cap cap;
  44. enum ib_sig_type sq_sig_type;
  45. /* Serialize qp state modifications */
  46. struct mutex mutex;
  47. struct ib_cq *cq;
  48. struct mlx5_ib_gsi_wr *outstanding_wrs;
  49. u32 outstanding_pi, outstanding_ci;
  50. int num_qps;
  51. /* Protects access to the tx_qps. Post send operations synchronize
  52. * with tx_qp creation in setup_qp(). Also protects the
  53. * outstanding_wrs array and indices.
  54. */
  55. spinlock_t lock;
  56. struct ib_qp **tx_qps;
  57. };
  58. static struct mlx5_ib_gsi_qp *gsi_qp(struct ib_qp *qp)
  59. {
  60. return container_of(qp, struct mlx5_ib_gsi_qp, ibqp);
  61. }
  62. static bool mlx5_ib_deth_sqpn_cap(struct mlx5_ib_dev *dev)
  63. {
  64. return MLX5_CAP_GEN(dev->mdev, set_deth_sqpn);
  65. }
  66. /* Call with gsi->lock locked */
  67. static void generate_completions(struct mlx5_ib_gsi_qp *gsi)
  68. {
  69. struct ib_cq *gsi_cq = gsi->ibqp.send_cq;
  70. struct mlx5_ib_gsi_wr *wr;
  71. u32 index;
  72. for (index = gsi->outstanding_ci; index != gsi->outstanding_pi;
  73. index++) {
  74. wr = &gsi->outstanding_wrs[index % gsi->cap.max_send_wr];
  75. if (!wr->completed)
  76. break;
  77. if (gsi->sq_sig_type == IB_SIGNAL_ALL_WR ||
  78. wr->send_flags & IB_SEND_SIGNALED)
  79. WARN_ON_ONCE(mlx5_ib_generate_wc(gsi_cq, &wr->wc));
  80. wr->completed = false;
  81. }
  82. gsi->outstanding_ci = index;
  83. }
  84. static void handle_single_completion(struct ib_cq *cq, struct ib_wc *wc)
  85. {
  86. struct mlx5_ib_gsi_qp *gsi = cq->cq_context;
  87. struct mlx5_ib_gsi_wr *wr =
  88. container_of(wc->wr_cqe, struct mlx5_ib_gsi_wr, cqe);
  89. u64 wr_id;
  90. unsigned long flags;
  91. spin_lock_irqsave(&gsi->lock, flags);
  92. wr->completed = true;
  93. wr_id = wr->wc.wr_id;
  94. wr->wc = *wc;
  95. wr->wc.wr_id = wr_id;
  96. wr->wc.qp = &gsi->ibqp;
  97. generate_completions(gsi);
  98. spin_unlock_irqrestore(&gsi->lock, flags);
  99. }
  100. struct ib_qp *mlx5_ib_gsi_create_qp(struct ib_pd *pd,
  101. struct ib_qp_init_attr *init_attr)
  102. {
  103. struct mlx5_ib_dev *dev = to_mdev(pd->device);
  104. struct mlx5_ib_gsi_qp *gsi;
  105. struct ib_qp_init_attr hw_init_attr = *init_attr;
  106. const u8 port_num = init_attr->port_num;
  107. const int num_pkeys = pd->device->attrs.max_pkeys;
  108. const int num_qps = mlx5_ib_deth_sqpn_cap(dev) ? num_pkeys : 0;
  109. int ret;
  110. mlx5_ib_dbg(dev, "creating GSI QP\n");
  111. if (port_num > ARRAY_SIZE(dev->devr.ports) || port_num < 1) {
  112. mlx5_ib_warn(dev,
  113. "invalid port number %d during GSI QP creation\n",
  114. port_num);
  115. return ERR_PTR(-EINVAL);
  116. }
  117. gsi = kzalloc(sizeof(*gsi), GFP_KERNEL);
  118. if (!gsi)
  119. return ERR_PTR(-ENOMEM);
  120. gsi->tx_qps = kcalloc(num_qps, sizeof(*gsi->tx_qps), GFP_KERNEL);
  121. if (!gsi->tx_qps) {
  122. ret = -ENOMEM;
  123. goto err_free;
  124. }
  125. gsi->outstanding_wrs = kcalloc(init_attr->cap.max_send_wr,
  126. sizeof(*gsi->outstanding_wrs),
  127. GFP_KERNEL);
  128. if (!gsi->outstanding_wrs) {
  129. ret = -ENOMEM;
  130. goto err_free_tx;
  131. }
  132. mutex_init(&gsi->mutex);
  133. mutex_lock(&dev->devr.mutex);
  134. if (dev->devr.ports[port_num - 1].gsi) {
  135. mlx5_ib_warn(dev, "GSI QP already exists on port %d\n",
  136. port_num);
  137. ret = -EBUSY;
  138. goto err_free_wrs;
  139. }
  140. gsi->num_qps = num_qps;
  141. spin_lock_init(&gsi->lock);
  142. gsi->cap = init_attr->cap;
  143. gsi->sq_sig_type = init_attr->sq_sig_type;
  144. gsi->ibqp.qp_num = 1;
  145. gsi->port_num = port_num;
  146. gsi->cq = ib_alloc_cq(pd->device, gsi, init_attr->cap.max_send_wr, 0,
  147. IB_POLL_SOFTIRQ);
  148. if (IS_ERR(gsi->cq)) {
  149. mlx5_ib_warn(dev, "unable to create send CQ for GSI QP. error %ld\n",
  150. PTR_ERR(gsi->cq));
  151. ret = PTR_ERR(gsi->cq);
  152. goto err_free_wrs;
  153. }
  154. hw_init_attr.qp_type = MLX5_IB_QPT_HW_GSI;
  155. hw_init_attr.send_cq = gsi->cq;
  156. if (num_qps) {
  157. hw_init_attr.cap.max_send_wr = 0;
  158. hw_init_attr.cap.max_send_sge = 0;
  159. hw_init_attr.cap.max_inline_data = 0;
  160. }
  161. gsi->rx_qp = ib_create_qp(pd, &hw_init_attr);
  162. if (IS_ERR(gsi->rx_qp)) {
  163. mlx5_ib_warn(dev, "unable to create hardware GSI QP. error %ld\n",
  164. PTR_ERR(gsi->rx_qp));
  165. ret = PTR_ERR(gsi->rx_qp);
  166. goto err_destroy_cq;
  167. }
  168. dev->devr.ports[init_attr->port_num - 1].gsi = gsi;
  169. mutex_unlock(&dev->devr.mutex);
  170. return &gsi->ibqp;
  171. err_destroy_cq:
  172. ib_free_cq(gsi->cq);
  173. err_free_wrs:
  174. mutex_unlock(&dev->devr.mutex);
  175. kfree(gsi->outstanding_wrs);
  176. err_free_tx:
  177. kfree(gsi->tx_qps);
  178. err_free:
  179. kfree(gsi);
  180. return ERR_PTR(ret);
  181. }
  182. int mlx5_ib_gsi_destroy_qp(struct ib_qp *qp)
  183. {
  184. struct mlx5_ib_dev *dev = to_mdev(qp->device);
  185. struct mlx5_ib_gsi_qp *gsi = gsi_qp(qp);
  186. const int port_num = gsi->port_num;
  187. int qp_index;
  188. int ret;
  189. mlx5_ib_dbg(dev, "destroying GSI QP\n");
  190. mutex_lock(&dev->devr.mutex);
  191. ret = ib_destroy_qp(gsi->rx_qp);
  192. if (ret) {
  193. mlx5_ib_warn(dev, "unable to destroy hardware GSI QP. error %d\n",
  194. ret);
  195. mutex_unlock(&dev->devr.mutex);
  196. return ret;
  197. }
  198. dev->devr.ports[port_num - 1].gsi = NULL;
  199. mutex_unlock(&dev->devr.mutex);
  200. gsi->rx_qp = NULL;
  201. for (qp_index = 0; qp_index < gsi->num_qps; ++qp_index) {
  202. if (!gsi->tx_qps[qp_index])
  203. continue;
  204. WARN_ON_ONCE(ib_destroy_qp(gsi->tx_qps[qp_index]));
  205. gsi->tx_qps[qp_index] = NULL;
  206. }
  207. ib_free_cq(gsi->cq);
  208. kfree(gsi->outstanding_wrs);
  209. kfree(gsi->tx_qps);
  210. kfree(gsi);
  211. return 0;
  212. }
  213. static struct ib_qp *create_gsi_ud_qp(struct mlx5_ib_gsi_qp *gsi)
  214. {
  215. struct ib_pd *pd = gsi->rx_qp->pd;
  216. struct ib_qp_init_attr init_attr = {
  217. .event_handler = gsi->rx_qp->event_handler,
  218. .qp_context = gsi->rx_qp->qp_context,
  219. .send_cq = gsi->cq,
  220. .recv_cq = gsi->rx_qp->recv_cq,
  221. .cap = {
  222. .max_send_wr = gsi->cap.max_send_wr,
  223. .max_send_sge = gsi->cap.max_send_sge,
  224. .max_inline_data = gsi->cap.max_inline_data,
  225. },
  226. .sq_sig_type = gsi->sq_sig_type,
  227. .qp_type = IB_QPT_UD,
  228. .create_flags = mlx5_ib_create_qp_sqpn_qp1(),
  229. };
  230. return ib_create_qp(pd, &init_attr);
  231. }
  232. static int modify_to_rts(struct mlx5_ib_gsi_qp *gsi, struct ib_qp *qp,
  233. u16 qp_index)
  234. {
  235. struct mlx5_ib_dev *dev = to_mdev(qp->device);
  236. struct ib_qp_attr attr;
  237. int mask;
  238. int ret;
  239. mask = IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_QKEY | IB_QP_PORT;
  240. attr.qp_state = IB_QPS_INIT;
  241. attr.pkey_index = qp_index;
  242. attr.qkey = IB_QP1_QKEY;
  243. attr.port_num = gsi->port_num;
  244. ret = ib_modify_qp(qp, &attr, mask);
  245. if (ret) {
  246. mlx5_ib_err(dev, "could not change QP%d state to INIT: %d\n",
  247. qp->qp_num, ret);
  248. return ret;
  249. }
  250. attr.qp_state = IB_QPS_RTR;
  251. ret = ib_modify_qp(qp, &attr, IB_QP_STATE);
  252. if (ret) {
  253. mlx5_ib_err(dev, "could not change QP%d state to RTR: %d\n",
  254. qp->qp_num, ret);
  255. return ret;
  256. }
  257. attr.qp_state = IB_QPS_RTS;
  258. attr.sq_psn = 0;
  259. ret = ib_modify_qp(qp, &attr, IB_QP_STATE | IB_QP_SQ_PSN);
  260. if (ret) {
  261. mlx5_ib_err(dev, "could not change QP%d state to RTS: %d\n",
  262. qp->qp_num, ret);
  263. return ret;
  264. }
  265. return 0;
  266. }
  267. static void setup_qp(struct mlx5_ib_gsi_qp *gsi, u16 qp_index)
  268. {
  269. struct ib_device *device = gsi->rx_qp->device;
  270. struct mlx5_ib_dev *dev = to_mdev(device);
  271. struct ib_qp *qp;
  272. unsigned long flags;
  273. u16 pkey;
  274. int ret;
  275. ret = ib_query_pkey(device, gsi->port_num, qp_index, &pkey);
  276. if (ret) {
  277. mlx5_ib_warn(dev, "unable to read P_Key at port %d, index %d\n",
  278. gsi->port_num, qp_index);
  279. return;
  280. }
  281. if (!pkey) {
  282. mlx5_ib_dbg(dev, "invalid P_Key at port %d, index %d. Skipping.\n",
  283. gsi->port_num, qp_index);
  284. return;
  285. }
  286. spin_lock_irqsave(&gsi->lock, flags);
  287. qp = gsi->tx_qps[qp_index];
  288. spin_unlock_irqrestore(&gsi->lock, flags);
  289. if (qp) {
  290. mlx5_ib_dbg(dev, "already existing GSI TX QP at port %d, index %d. Skipping\n",
  291. gsi->port_num, qp_index);
  292. return;
  293. }
  294. qp = create_gsi_ud_qp(gsi);
  295. if (IS_ERR(qp)) {
  296. mlx5_ib_warn(dev, "unable to create hardware UD QP for GSI: %ld\n",
  297. PTR_ERR(qp));
  298. return;
  299. }
  300. ret = modify_to_rts(gsi, qp, qp_index);
  301. if (ret)
  302. goto err_destroy_qp;
  303. spin_lock_irqsave(&gsi->lock, flags);
  304. WARN_ON_ONCE(gsi->tx_qps[qp_index]);
  305. gsi->tx_qps[qp_index] = qp;
  306. spin_unlock_irqrestore(&gsi->lock, flags);
  307. return;
  308. err_destroy_qp:
  309. WARN_ON_ONCE(qp);
  310. }
  311. static void setup_qps(struct mlx5_ib_gsi_qp *gsi)
  312. {
  313. u16 qp_index;
  314. for (qp_index = 0; qp_index < gsi->num_qps; ++qp_index)
  315. setup_qp(gsi, qp_index);
  316. }
  317. int mlx5_ib_gsi_modify_qp(struct ib_qp *qp, struct ib_qp_attr *attr,
  318. int attr_mask)
  319. {
  320. struct mlx5_ib_dev *dev = to_mdev(qp->device);
  321. struct mlx5_ib_gsi_qp *gsi = gsi_qp(qp);
  322. int ret;
  323. mlx5_ib_dbg(dev, "modifying GSI QP to state %d\n", attr->qp_state);
  324. mutex_lock(&gsi->mutex);
  325. ret = ib_modify_qp(gsi->rx_qp, attr, attr_mask);
  326. if (ret) {
  327. mlx5_ib_warn(dev, "unable to modify GSI rx QP: %d\n", ret);
  328. goto unlock;
  329. }
  330. if (to_mqp(gsi->rx_qp)->state == IB_QPS_RTS)
  331. setup_qps(gsi);
  332. unlock:
  333. mutex_unlock(&gsi->mutex);
  334. return ret;
  335. }
  336. int mlx5_ib_gsi_query_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
  337. int qp_attr_mask,
  338. struct ib_qp_init_attr *qp_init_attr)
  339. {
  340. struct mlx5_ib_gsi_qp *gsi = gsi_qp(qp);
  341. int ret;
  342. mutex_lock(&gsi->mutex);
  343. ret = ib_query_qp(gsi->rx_qp, qp_attr, qp_attr_mask, qp_init_attr);
  344. qp_init_attr->cap = gsi->cap;
  345. mutex_unlock(&gsi->mutex);
  346. return ret;
  347. }
  348. /* Call with gsi->lock locked */
  349. static int mlx5_ib_add_outstanding_wr(struct mlx5_ib_gsi_qp *gsi,
  350. struct ib_ud_wr *wr, struct ib_wc *wc)
  351. {
  352. struct mlx5_ib_dev *dev = to_mdev(gsi->rx_qp->device);
  353. struct mlx5_ib_gsi_wr *gsi_wr;
  354. if (gsi->outstanding_pi == gsi->outstanding_ci + gsi->cap.max_send_wr) {
  355. mlx5_ib_warn(dev, "no available GSI work request.\n");
  356. return -ENOMEM;
  357. }
  358. gsi_wr = &gsi->outstanding_wrs[gsi->outstanding_pi %
  359. gsi->cap.max_send_wr];
  360. gsi->outstanding_pi++;
  361. if (!wc) {
  362. memset(&gsi_wr->wc, 0, sizeof(gsi_wr->wc));
  363. gsi_wr->wc.pkey_index = wr->pkey_index;
  364. gsi_wr->wc.wr_id = wr->wr.wr_id;
  365. } else {
  366. gsi_wr->wc = *wc;
  367. gsi_wr->completed = true;
  368. }
  369. gsi_wr->cqe.done = &handle_single_completion;
  370. wr->wr.wr_cqe = &gsi_wr->cqe;
  371. return 0;
  372. }
  373. /* Call with gsi->lock locked */
  374. static int mlx5_ib_gsi_silent_drop(struct mlx5_ib_gsi_qp *gsi,
  375. struct ib_ud_wr *wr)
  376. {
  377. struct ib_wc wc = {
  378. { .wr_id = wr->wr.wr_id },
  379. .status = IB_WC_SUCCESS,
  380. .opcode = IB_WC_SEND,
  381. .qp = &gsi->ibqp,
  382. };
  383. int ret;
  384. ret = mlx5_ib_add_outstanding_wr(gsi, wr, &wc);
  385. if (ret)
  386. return ret;
  387. generate_completions(gsi);
  388. return 0;
  389. }
  390. /* Call with gsi->lock locked */
  391. static struct ib_qp *get_tx_qp(struct mlx5_ib_gsi_qp *gsi, struct ib_ud_wr *wr)
  392. {
  393. struct mlx5_ib_dev *dev = to_mdev(gsi->rx_qp->device);
  394. int qp_index = wr->pkey_index;
  395. if (!mlx5_ib_deth_sqpn_cap(dev))
  396. return gsi->rx_qp;
  397. if (qp_index >= gsi->num_qps)
  398. return NULL;
  399. return gsi->tx_qps[qp_index];
  400. }
  401. int mlx5_ib_gsi_post_send(struct ib_qp *qp, const struct ib_send_wr *wr,
  402. const struct ib_send_wr **bad_wr)
  403. {
  404. struct mlx5_ib_gsi_qp *gsi = gsi_qp(qp);
  405. struct ib_qp *tx_qp;
  406. unsigned long flags;
  407. int ret;
  408. for (; wr; wr = wr->next) {
  409. struct ib_ud_wr cur_wr = *ud_wr(wr);
  410. cur_wr.wr.next = NULL;
  411. spin_lock_irqsave(&gsi->lock, flags);
  412. tx_qp = get_tx_qp(gsi, &cur_wr);
  413. if (!tx_qp) {
  414. ret = mlx5_ib_gsi_silent_drop(gsi, &cur_wr);
  415. if (ret)
  416. goto err;
  417. spin_unlock_irqrestore(&gsi->lock, flags);
  418. continue;
  419. }
  420. ret = mlx5_ib_add_outstanding_wr(gsi, &cur_wr, NULL);
  421. if (ret)
  422. goto err;
  423. ret = ib_post_send(tx_qp, &cur_wr.wr, bad_wr);
  424. if (ret) {
  425. /* Undo the effect of adding the outstanding wr */
  426. gsi->outstanding_pi--;
  427. goto err;
  428. }
  429. spin_unlock_irqrestore(&gsi->lock, flags);
  430. }
  431. return 0;
  432. err:
  433. spin_unlock_irqrestore(&gsi->lock, flags);
  434. *bad_wr = wr;
  435. return ret;
  436. }
  437. int mlx5_ib_gsi_post_recv(struct ib_qp *qp, const struct ib_recv_wr *wr,
  438. const struct ib_recv_wr **bad_wr)
  439. {
  440. struct mlx5_ib_gsi_qp *gsi = gsi_qp(qp);
  441. return ib_post_recv(gsi->rx_qp, wr, bad_wr);
  442. }
  443. void mlx5_ib_gsi_pkey_change(struct mlx5_ib_gsi_qp *gsi)
  444. {
  445. if (!gsi)
  446. return;
  447. mutex_lock(&gsi->mutex);
  448. setup_qps(gsi);
  449. mutex_unlock(&gsi->mutex);
  450. }