rxe_mw.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
  2. /*
  3. * Copyright (c) 2020 Hewlett Packard Enterprise, Inc. All rights reserved.
  4. */
  5. /*
  6. * The rdma_rxe driver supports type 1 or type 2B memory windows.
  7. * Type 1 MWs are created by ibv_alloc_mw() verbs calls and bound by
  8. * ibv_bind_mw() calls. Type 2 MWs are also created by ibv_alloc_mw()
  9. * but bound by bind_mw work requests. The ibv_bind_mw() call is converted
  10. * by libibverbs to a bind_mw work request.
  11. */
  12. #include "rxe.h"
  13. int rxe_alloc_mw(struct ib_mw *ibmw, struct ib_udata *udata)
  14. {
  15. struct rxe_mw *mw = to_rmw(ibmw);
  16. struct rxe_pd *pd = to_rpd(ibmw->pd);
  17. struct rxe_dev *rxe = to_rdev(ibmw->device);
  18. int ret;
  19. rxe_get(pd);
  20. ret = rxe_add_to_pool(&rxe->mw_pool, mw);
  21. if (ret) {
  22. rxe_put(pd);
  23. return ret;
  24. }
  25. mw->rkey = ibmw->rkey = (mw->elem.index << 8) | rxe_get_next_key(-1);
  26. mw->state = (mw->ibmw.type == IB_MW_TYPE_2) ?
  27. RXE_MW_STATE_FREE : RXE_MW_STATE_VALID;
  28. spin_lock_init(&mw->lock);
  29. rxe_finalize(mw);
  30. return 0;
  31. }
  32. int rxe_dealloc_mw(struct ib_mw *ibmw)
  33. {
  34. struct rxe_mw *mw = to_rmw(ibmw);
  35. rxe_cleanup(mw);
  36. return 0;
  37. }
  38. static int rxe_check_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
  39. struct rxe_mw *mw, struct rxe_mr *mr, int access)
  40. {
  41. if (mw->ibmw.type == IB_MW_TYPE_1) {
  42. if (unlikely(mw->state != RXE_MW_STATE_VALID)) {
  43. rxe_dbg_mw(mw,
  44. "attempt to bind a type 1 MW not in the valid state\n");
  45. return -EINVAL;
  46. }
  47. /* o10-36.2.2 */
  48. if (unlikely((access & IB_ZERO_BASED))) {
  49. rxe_dbg_mw(mw, "attempt to bind a zero based type 1 MW\n");
  50. return -EINVAL;
  51. }
  52. }
  53. if (mw->ibmw.type == IB_MW_TYPE_2) {
  54. /* o10-37.2.30 */
  55. if (unlikely(mw->state != RXE_MW_STATE_FREE)) {
  56. rxe_dbg_mw(mw,
  57. "attempt to bind a type 2 MW not in the free state\n");
  58. return -EINVAL;
  59. }
  60. /* C10-72 */
  61. if (unlikely(qp->pd != to_rpd(mw->ibmw.pd))) {
  62. rxe_dbg_mw(mw,
  63. "attempt to bind type 2 MW with qp with different PD\n");
  64. return -EINVAL;
  65. }
  66. /* o10-37.2.40 */
  67. if (unlikely(!mr || wqe->wr.wr.mw.length == 0)) {
  68. rxe_dbg_mw(mw,
  69. "attempt to invalidate type 2 MW by binding with NULL or zero length MR\n");
  70. return -EINVAL;
  71. }
  72. }
  73. /* remaining checks only apply to a nonzero MR */
  74. if (!mr)
  75. return 0;
  76. if (unlikely(mr->access & IB_ZERO_BASED)) {
  77. rxe_dbg_mw(mw, "attempt to bind MW to zero based MR\n");
  78. return -EINVAL;
  79. }
  80. /* C10-73 */
  81. if (unlikely(!(mr->access & IB_ACCESS_MW_BIND))) {
  82. rxe_dbg_mw(mw,
  83. "attempt to bind an MW to an MR without bind access\n");
  84. return -EINVAL;
  85. }
  86. /* C10-74 */
  87. if (unlikely((access &
  88. (IB_ACCESS_REMOTE_WRITE | IB_ACCESS_REMOTE_ATOMIC)) &&
  89. !(mr->access & IB_ACCESS_LOCAL_WRITE))) {
  90. rxe_dbg_mw(mw,
  91. "attempt to bind an Writable MW to an MR without local write access\n");
  92. return -EINVAL;
  93. }
  94. /* C10-75 */
  95. if (access & IB_ZERO_BASED) {
  96. if (unlikely(wqe->wr.wr.mw.length > mr->ibmr.length)) {
  97. rxe_dbg_mw(mw,
  98. "attempt to bind a ZB MW outside of the MR\n");
  99. return -EINVAL;
  100. }
  101. } else {
  102. if (unlikely((wqe->wr.wr.mw.addr < mr->ibmr.iova) ||
  103. ((wqe->wr.wr.mw.addr + wqe->wr.wr.mw.length) >
  104. (mr->ibmr.iova + mr->ibmr.length)))) {
  105. rxe_dbg_mw(mw,
  106. "attempt to bind a VA MW outside of the MR\n");
  107. return -EINVAL;
  108. }
  109. }
  110. return 0;
  111. }
  112. static void rxe_do_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
  113. struct rxe_mw *mw, struct rxe_mr *mr, int access)
  114. {
  115. u32 key = wqe->wr.wr.mw.rkey & 0xff;
  116. mw->rkey = (mw->rkey & ~0xff) | key;
  117. mw->access = access;
  118. mw->state = RXE_MW_STATE_VALID;
  119. mw->addr = wqe->wr.wr.mw.addr;
  120. mw->length = wqe->wr.wr.mw.length;
  121. if (mw->mr) {
  122. rxe_put(mw->mr);
  123. atomic_dec(&mw->mr->num_mw);
  124. mw->mr = NULL;
  125. }
  126. if (mw->length) {
  127. mw->mr = mr;
  128. atomic_inc(&mr->num_mw);
  129. rxe_get(mr);
  130. }
  131. if (mw->ibmw.type == IB_MW_TYPE_2) {
  132. rxe_get(qp);
  133. mw->qp = qp;
  134. }
  135. }
  136. int rxe_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe)
  137. {
  138. int ret;
  139. struct rxe_mw *mw;
  140. struct rxe_mr *mr;
  141. struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
  142. u32 mw_rkey = wqe->wr.wr.mw.mw_rkey;
  143. u32 mr_lkey = wqe->wr.wr.mw.mr_lkey;
  144. int access = wqe->wr.wr.mw.access;
  145. mw = rxe_pool_get_index(&rxe->mw_pool, mw_rkey >> 8);
  146. if (unlikely(!mw)) {
  147. ret = -EINVAL;
  148. goto err;
  149. }
  150. if (unlikely(mw->rkey != mw_rkey)) {
  151. ret = -EINVAL;
  152. goto err_drop_mw;
  153. }
  154. if (likely(wqe->wr.wr.mw.length)) {
  155. mr = rxe_pool_get_index(&rxe->mr_pool, mr_lkey >> 8);
  156. if (unlikely(!mr)) {
  157. ret = -EINVAL;
  158. goto err_drop_mw;
  159. }
  160. if (unlikely(mr->lkey != mr_lkey)) {
  161. ret = -EINVAL;
  162. goto err_drop_mr;
  163. }
  164. } else {
  165. mr = NULL;
  166. }
  167. spin_lock_bh(&mw->lock);
  168. ret = rxe_check_bind_mw(qp, wqe, mw, mr, access);
  169. if (ret)
  170. goto err_unlock;
  171. rxe_do_bind_mw(qp, wqe, mw, mr, access);
  172. err_unlock:
  173. spin_unlock_bh(&mw->lock);
  174. err_drop_mr:
  175. if (mr)
  176. rxe_put(mr);
  177. err_drop_mw:
  178. rxe_put(mw);
  179. err:
  180. return ret;
  181. }
  182. static int rxe_check_invalidate_mw(struct rxe_qp *qp, struct rxe_mw *mw)
  183. {
  184. if (unlikely(mw->state == RXE_MW_STATE_INVALID))
  185. return -EINVAL;
  186. /* o10-37.2.26 */
  187. if (unlikely(mw->ibmw.type == IB_MW_TYPE_1))
  188. return -EINVAL;
  189. return 0;
  190. }
  191. static void rxe_do_invalidate_mw(struct rxe_mw *mw)
  192. {
  193. struct rxe_qp *qp;
  194. struct rxe_mr *mr;
  195. /* valid type 2 MW will always have a QP pointer */
  196. qp = mw->qp;
  197. mw->qp = NULL;
  198. rxe_put(qp);
  199. /* valid type 2 MW will always have an MR pointer */
  200. mr = mw->mr;
  201. mw->mr = NULL;
  202. atomic_dec(&mr->num_mw);
  203. rxe_put(mr);
  204. mw->access = 0;
  205. mw->addr = 0;
  206. mw->length = 0;
  207. mw->state = RXE_MW_STATE_FREE;
  208. }
  209. int rxe_invalidate_mw(struct rxe_qp *qp, u32 rkey)
  210. {
  211. struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
  212. struct rxe_mw *mw;
  213. int ret;
  214. mw = rxe_pool_get_index(&rxe->mw_pool, rkey >> 8);
  215. if (!mw) {
  216. ret = -EINVAL;
  217. goto err;
  218. }
  219. if (rkey != mw->rkey) {
  220. ret = -EINVAL;
  221. goto err_drop_ref;
  222. }
  223. spin_lock_bh(&mw->lock);
  224. ret = rxe_check_invalidate_mw(qp, mw);
  225. if (ret)
  226. goto err_unlock;
  227. rxe_do_invalidate_mw(mw);
  228. err_unlock:
  229. spin_unlock_bh(&mw->lock);
  230. err_drop_ref:
  231. rxe_put(mw);
  232. err:
  233. return ret;
  234. }
  235. struct rxe_mw *rxe_lookup_mw(struct rxe_qp *qp, int access, u32 rkey)
  236. {
  237. struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
  238. struct rxe_pd *pd = to_rpd(qp->ibqp.pd);
  239. struct rxe_mw *mw;
  240. int index = rkey >> 8;
  241. mw = rxe_pool_get_index(&rxe->mw_pool, index);
  242. if (!mw)
  243. return NULL;
  244. if (unlikely((mw->rkey != rkey) || rxe_mw_pd(mw) != pd ||
  245. (mw->ibmw.type == IB_MW_TYPE_2 && mw->qp != qp) ||
  246. (mw->length == 0) ||
  247. (access && !(access & mw->access)) ||
  248. mw->state != RXE_MW_STATE_VALID)) {
  249. rxe_put(mw);
  250. return NULL;
  251. }
  252. return mw;
  253. }
  254. void rxe_mw_cleanup(struct rxe_pool_elem *elem)
  255. {
  256. struct rxe_mw *mw = container_of(elem, typeof(*mw), elem);
  257. struct rxe_pd *pd = to_rpd(mw->ibmw.pd);
  258. rxe_put(pd);
  259. if (mw->mr) {
  260. struct rxe_mr *mr = mw->mr;
  261. mw->mr = NULL;
  262. atomic_dec(&mr->num_mw);
  263. rxe_put(mr);
  264. }
  265. if (mw->qp) {
  266. struct rxe_qp *qp = mw->qp;
  267. mw->qp = NULL;
  268. rxe_put(qp);
  269. }
  270. mw->access = 0;
  271. mw->addr = 0;
  272. mw->length = 0;
  273. mw->state = RXE_MW_STATE_INVALID;
  274. }