mem.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806
  1. /*
  2. * Copyright (c) 2009-2010 Chelsio, 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 <rdma/ib_umem.h>
  33. #include <linux/atomic.h>
  34. #include "iw_cxgb4.h"
  35. #define T4_ULPTX_MIN_IO 32
  36. #define C4IW_MAX_INLINE_SIZE 96
  37. static int write_adapter_mem(struct c4iw_rdev *rdev, u32 addr, u32 len,
  38. void *data)
  39. {
  40. struct sk_buff *skb;
  41. struct ulp_mem_io *req;
  42. struct ulptx_idata *sc;
  43. u8 wr_len, *to_dp, *from_dp;
  44. int copy_len, num_wqe, i, ret = 0;
  45. struct c4iw_wr_wait wr_wait;
  46. addr &= 0x7FFFFFF;
  47. PDBG("%s addr 0x%x len %u\n", __func__, addr, len);
  48. num_wqe = DIV_ROUND_UP(len, C4IW_MAX_INLINE_SIZE);
  49. c4iw_init_wr_wait(&wr_wait);
  50. for (i = 0; i < num_wqe; i++) {
  51. copy_len = len > C4IW_MAX_INLINE_SIZE ? C4IW_MAX_INLINE_SIZE :
  52. len;
  53. wr_len = roundup(sizeof *req + sizeof *sc +
  54. roundup(copy_len, T4_ULPTX_MIN_IO), 16);
  55. skb = alloc_skb(wr_len, GFP_KERNEL);
  56. if (!skb)
  57. return -ENOMEM;
  58. set_wr_txq(skb, CPL_PRIORITY_CONTROL, 0);
  59. req = (struct ulp_mem_io *)__skb_put(skb, wr_len);
  60. memset(req, 0, wr_len);
  61. INIT_ULPTX_WR(req, wr_len, 0, 0);
  62. if (i == (num_wqe-1)) {
  63. req->wr.wr_hi = cpu_to_be32(FW_WR_OP(FW_ULPTX_WR) |
  64. FW_WR_COMPL(1));
  65. req->wr.wr_lo = (__force __be64)(unsigned long) &wr_wait;
  66. } else
  67. req->wr.wr_hi = cpu_to_be32(FW_WR_OP(FW_ULPTX_WR));
  68. req->wr.wr_mid = cpu_to_be32(
  69. FW_WR_LEN16(DIV_ROUND_UP(wr_len, 16)));
  70. req->cmd = cpu_to_be32(ULPTX_CMD(ULP_TX_MEM_WRITE) | (1<<23));
  71. req->dlen = cpu_to_be32(ULP_MEMIO_DATA_LEN(
  72. DIV_ROUND_UP(copy_len, T4_ULPTX_MIN_IO)));
  73. req->len16 = cpu_to_be32(DIV_ROUND_UP(wr_len-sizeof(req->wr),
  74. 16));
  75. req->lock_addr = cpu_to_be32(ULP_MEMIO_ADDR(addr + i * 3));
  76. sc = (struct ulptx_idata *)(req + 1);
  77. sc->cmd_more = cpu_to_be32(ULPTX_CMD(ULP_TX_SC_IMM));
  78. sc->len = cpu_to_be32(roundup(copy_len, T4_ULPTX_MIN_IO));
  79. to_dp = (u8 *)(sc + 1);
  80. from_dp = (u8 *)data + i * C4IW_MAX_INLINE_SIZE;
  81. if (data)
  82. memcpy(to_dp, from_dp, copy_len);
  83. else
  84. memset(to_dp, 0, copy_len);
  85. if (copy_len % T4_ULPTX_MIN_IO)
  86. memset(to_dp + copy_len, 0, T4_ULPTX_MIN_IO -
  87. (copy_len % T4_ULPTX_MIN_IO));
  88. ret = c4iw_ofld_send(rdev, skb);
  89. if (ret)
  90. return ret;
  91. len -= C4IW_MAX_INLINE_SIZE;
  92. }
  93. ret = c4iw_wait_for_reply(rdev, &wr_wait, 0, 0, __func__);
  94. return ret;
  95. }
  96. /*
  97. * Build and write a TPT entry.
  98. * IN: stag key, pdid, perm, bind_enabled, zbva, to, len, page_size,
  99. * pbl_size and pbl_addr
  100. * OUT: stag index
  101. */
  102. static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,
  103. u32 *stag, u8 stag_state, u32 pdid,
  104. enum fw_ri_stag_type type, enum fw_ri_mem_perms perm,
  105. int bind_enabled, u32 zbva, u64 to,
  106. u64 len, u8 page_size, u32 pbl_size, u32 pbl_addr)
  107. {
  108. int err;
  109. struct fw_ri_tpte tpt;
  110. u32 stag_idx;
  111. static atomic_t key;
  112. if (c4iw_fatal_error(rdev))
  113. return -EIO;
  114. stag_state = stag_state > 0;
  115. stag_idx = (*stag) >> 8;
  116. if ((!reset_tpt_entry) && (*stag == T4_STAG_UNSET)) {
  117. stag_idx = c4iw_get_resource(&rdev->resource.tpt_fifo,
  118. &rdev->resource.tpt_fifo_lock);
  119. if (!stag_idx)
  120. return -ENOMEM;
  121. *stag = (stag_idx << 8) | (atomic_inc_return(&key) & 0xff);
  122. }
  123. PDBG("%s stag_state 0x%0x type 0x%0x pdid 0x%0x, stag_idx 0x%x\n",
  124. __func__, stag_state, type, pdid, stag_idx);
  125. /* write TPT entry */
  126. if (reset_tpt_entry)
  127. memset(&tpt, 0, sizeof(tpt));
  128. else {
  129. tpt.valid_to_pdid = cpu_to_be32(F_FW_RI_TPTE_VALID |
  130. V_FW_RI_TPTE_STAGKEY((*stag & M_FW_RI_TPTE_STAGKEY)) |
  131. V_FW_RI_TPTE_STAGSTATE(stag_state) |
  132. V_FW_RI_TPTE_STAGTYPE(type) | V_FW_RI_TPTE_PDID(pdid));
  133. tpt.locread_to_qpid = cpu_to_be32(V_FW_RI_TPTE_PERM(perm) |
  134. (bind_enabled ? F_FW_RI_TPTE_MWBINDEN : 0) |
  135. V_FW_RI_TPTE_ADDRTYPE((zbva ? FW_RI_ZERO_BASED_TO :
  136. FW_RI_VA_BASED_TO))|
  137. V_FW_RI_TPTE_PS(page_size));
  138. tpt.nosnoop_pbladdr = !pbl_size ? 0 : cpu_to_be32(
  139. V_FW_RI_TPTE_PBLADDR(PBL_OFF(rdev, pbl_addr)>>3));
  140. tpt.len_lo = cpu_to_be32((u32)(len & 0xffffffffUL));
  141. tpt.va_hi = cpu_to_be32((u32)(to >> 32));
  142. tpt.va_lo_fbo = cpu_to_be32((u32)(to & 0xffffffffUL));
  143. tpt.dca_mwbcnt_pstag = cpu_to_be32(0);
  144. tpt.len_hi = cpu_to_be32((u32)(len >> 32));
  145. }
  146. err = write_adapter_mem(rdev, stag_idx +
  147. (rdev->lldi.vr->stag.start >> 5),
  148. sizeof(tpt), &tpt);
  149. if (reset_tpt_entry)
  150. c4iw_put_resource(&rdev->resource.tpt_fifo, stag_idx,
  151. &rdev->resource.tpt_fifo_lock);
  152. return err;
  153. }
  154. static int write_pbl(struct c4iw_rdev *rdev, __be64 *pbl,
  155. u32 pbl_addr, u32 pbl_size)
  156. {
  157. int err;
  158. PDBG("%s *pdb_addr 0x%x, pbl_base 0x%x, pbl_size %d\n",
  159. __func__, pbl_addr, rdev->lldi.vr->pbl.start,
  160. pbl_size);
  161. err = write_adapter_mem(rdev, pbl_addr >> 5, pbl_size << 3, pbl);
  162. return err;
  163. }
  164. static int dereg_mem(struct c4iw_rdev *rdev, u32 stag, u32 pbl_size,
  165. u32 pbl_addr)
  166. {
  167. return write_tpt_entry(rdev, 1, &stag, 0, 0, 0, 0, 0, 0, 0UL, 0, 0,
  168. pbl_size, pbl_addr);
  169. }
  170. static int allocate_window(struct c4iw_rdev *rdev, u32 * stag, u32 pdid)
  171. {
  172. *stag = T4_STAG_UNSET;
  173. return write_tpt_entry(rdev, 0, stag, 0, pdid, FW_RI_STAG_MW, 0, 0, 0,
  174. 0UL, 0, 0, 0, 0);
  175. }
  176. static int deallocate_window(struct c4iw_rdev *rdev, u32 stag)
  177. {
  178. return write_tpt_entry(rdev, 1, &stag, 0, 0, 0, 0, 0, 0, 0UL, 0, 0, 0,
  179. 0);
  180. }
  181. static int allocate_stag(struct c4iw_rdev *rdev, u32 *stag, u32 pdid,
  182. u32 pbl_size, u32 pbl_addr)
  183. {
  184. *stag = T4_STAG_UNSET;
  185. return write_tpt_entry(rdev, 0, stag, 0, pdid, FW_RI_STAG_NSMR, 0, 0, 0,
  186. 0UL, 0, 0, pbl_size, pbl_addr);
  187. }
  188. static int finish_mem_reg(struct c4iw_mr *mhp, u32 stag)
  189. {
  190. u32 mmid;
  191. mhp->attr.state = 1;
  192. mhp->attr.stag = stag;
  193. mmid = stag >> 8;
  194. mhp->ibmr.rkey = mhp->ibmr.lkey = stag;
  195. PDBG("%s mmid 0x%x mhp %p\n", __func__, mmid, mhp);
  196. return insert_handle(mhp->rhp, &mhp->rhp->mmidr, mhp, mmid);
  197. }
  198. static int register_mem(struct c4iw_dev *rhp, struct c4iw_pd *php,
  199. struct c4iw_mr *mhp, int shift)
  200. {
  201. u32 stag = T4_STAG_UNSET;
  202. int ret;
  203. ret = write_tpt_entry(&rhp->rdev, 0, &stag, 1, mhp->attr.pdid,
  204. FW_RI_STAG_NSMR, mhp->attr.perms,
  205. mhp->attr.mw_bind_enable, mhp->attr.zbva,
  206. mhp->attr.va_fbo, mhp->attr.len, shift - 12,
  207. mhp->attr.pbl_size, mhp->attr.pbl_addr);
  208. if (ret)
  209. return ret;
  210. ret = finish_mem_reg(mhp, stag);
  211. if (ret)
  212. dereg_mem(&rhp->rdev, mhp->attr.stag, mhp->attr.pbl_size,
  213. mhp->attr.pbl_addr);
  214. return ret;
  215. }
  216. static int reregister_mem(struct c4iw_dev *rhp, struct c4iw_pd *php,
  217. struct c4iw_mr *mhp, int shift, int npages)
  218. {
  219. u32 stag;
  220. int ret;
  221. if (npages > mhp->attr.pbl_size)
  222. return -ENOMEM;
  223. stag = mhp->attr.stag;
  224. ret = write_tpt_entry(&rhp->rdev, 0, &stag, 1, mhp->attr.pdid,
  225. FW_RI_STAG_NSMR, mhp->attr.perms,
  226. mhp->attr.mw_bind_enable, mhp->attr.zbva,
  227. mhp->attr.va_fbo, mhp->attr.len, shift - 12,
  228. mhp->attr.pbl_size, mhp->attr.pbl_addr);
  229. if (ret)
  230. return ret;
  231. ret = finish_mem_reg(mhp, stag);
  232. if (ret)
  233. dereg_mem(&rhp->rdev, mhp->attr.stag, mhp->attr.pbl_size,
  234. mhp->attr.pbl_addr);
  235. return ret;
  236. }
  237. static int alloc_pbl(struct c4iw_mr *mhp, int npages)
  238. {
  239. mhp->attr.pbl_addr = c4iw_pblpool_alloc(&mhp->rhp->rdev,
  240. npages << 3);
  241. if (!mhp->attr.pbl_addr)
  242. return -ENOMEM;
  243. mhp->attr.pbl_size = npages;
  244. return 0;
  245. }
  246. static int build_phys_page_list(struct ib_phys_buf *buffer_list,
  247. int num_phys_buf, u64 *iova_start,
  248. u64 *total_size, int *npages,
  249. int *shift, __be64 **page_list)
  250. {
  251. u64 mask;
  252. int i, j, n;
  253. mask = 0;
  254. *total_size = 0;
  255. for (i = 0; i < num_phys_buf; ++i) {
  256. if (i != 0 && buffer_list[i].addr & ~PAGE_MASK)
  257. return -EINVAL;
  258. if (i != 0 && i != num_phys_buf - 1 &&
  259. (buffer_list[i].size & ~PAGE_MASK))
  260. return -EINVAL;
  261. *total_size += buffer_list[i].size;
  262. if (i > 0)
  263. mask |= buffer_list[i].addr;
  264. else
  265. mask |= buffer_list[i].addr & PAGE_MASK;
  266. if (i != num_phys_buf - 1)
  267. mask |= buffer_list[i].addr + buffer_list[i].size;
  268. else
  269. mask |= (buffer_list[i].addr + buffer_list[i].size +
  270. PAGE_SIZE - 1) & PAGE_MASK;
  271. }
  272. if (*total_size > 0xFFFFFFFFULL)
  273. return -ENOMEM;
  274. /* Find largest page shift we can use to cover buffers */
  275. for (*shift = PAGE_SHIFT; *shift < 27; ++(*shift))
  276. if ((1ULL << *shift) & mask)
  277. break;
  278. buffer_list[0].size += buffer_list[0].addr & ((1ULL << *shift) - 1);
  279. buffer_list[0].addr &= ~0ull << *shift;
  280. *npages = 0;
  281. for (i = 0; i < num_phys_buf; ++i)
  282. *npages += (buffer_list[i].size +
  283. (1ULL << *shift) - 1) >> *shift;
  284. if (!*npages)
  285. return -EINVAL;
  286. *page_list = kmalloc(sizeof(u64) * *npages, GFP_KERNEL);
  287. if (!*page_list)
  288. return -ENOMEM;
  289. n = 0;
  290. for (i = 0; i < num_phys_buf; ++i)
  291. for (j = 0;
  292. j < (buffer_list[i].size + (1ULL << *shift) - 1) >> *shift;
  293. ++j)
  294. (*page_list)[n++] = cpu_to_be64(buffer_list[i].addr +
  295. ((u64) j << *shift));
  296. PDBG("%s va 0x%llx mask 0x%llx shift %d len %lld pbl_size %d\n",
  297. __func__, (unsigned long long)*iova_start,
  298. (unsigned long long)mask, *shift, (unsigned long long)*total_size,
  299. *npages);
  300. return 0;
  301. }
  302. int c4iw_reregister_phys_mem(struct ib_mr *mr, int mr_rereg_mask,
  303. struct ib_pd *pd, struct ib_phys_buf *buffer_list,
  304. int num_phys_buf, int acc, u64 *iova_start)
  305. {
  306. struct c4iw_mr mh, *mhp;
  307. struct c4iw_pd *php;
  308. struct c4iw_dev *rhp;
  309. __be64 *page_list = NULL;
  310. int shift = 0;
  311. u64 total_size;
  312. int npages;
  313. int ret;
  314. PDBG("%s ib_mr %p ib_pd %p\n", __func__, mr, pd);
  315. /* There can be no memory windows */
  316. if (atomic_read(&mr->usecnt))
  317. return -EINVAL;
  318. mhp = to_c4iw_mr(mr);
  319. rhp = mhp->rhp;
  320. php = to_c4iw_pd(mr->pd);
  321. /* make sure we are on the same adapter */
  322. if (rhp != php->rhp)
  323. return -EINVAL;
  324. memcpy(&mh, mhp, sizeof *mhp);
  325. if (mr_rereg_mask & IB_MR_REREG_PD)
  326. php = to_c4iw_pd(pd);
  327. if (mr_rereg_mask & IB_MR_REREG_ACCESS) {
  328. mh.attr.perms = c4iw_ib_to_tpt_access(acc);
  329. mh.attr.mw_bind_enable = (acc & IB_ACCESS_MW_BIND) ==
  330. IB_ACCESS_MW_BIND;
  331. }
  332. if (mr_rereg_mask & IB_MR_REREG_TRANS) {
  333. ret = build_phys_page_list(buffer_list, num_phys_buf,
  334. iova_start,
  335. &total_size, &npages,
  336. &shift, &page_list);
  337. if (ret)
  338. return ret;
  339. }
  340. ret = reregister_mem(rhp, php, &mh, shift, npages);
  341. kfree(page_list);
  342. if (ret)
  343. return ret;
  344. if (mr_rereg_mask & IB_MR_REREG_PD)
  345. mhp->attr.pdid = php->pdid;
  346. if (mr_rereg_mask & IB_MR_REREG_ACCESS)
  347. mhp->attr.perms = c4iw_ib_to_tpt_access(acc);
  348. if (mr_rereg_mask & IB_MR_REREG_TRANS) {
  349. mhp->attr.zbva = 0;
  350. mhp->attr.va_fbo = *iova_start;
  351. mhp->attr.page_size = shift - 12;
  352. mhp->attr.len = (u32) total_size;
  353. mhp->attr.pbl_size = npages;
  354. }
  355. return 0;
  356. }
  357. struct ib_mr *c4iw_register_phys_mem(struct ib_pd *pd,
  358. struct ib_phys_buf *buffer_list,
  359. int num_phys_buf, int acc, u64 *iova_start)
  360. {
  361. __be64 *page_list;
  362. int shift;
  363. u64 total_size;
  364. int npages;
  365. struct c4iw_dev *rhp;
  366. struct c4iw_pd *php;
  367. struct c4iw_mr *mhp;
  368. int ret;
  369. PDBG("%s ib_pd %p\n", __func__, pd);
  370. php = to_c4iw_pd(pd);
  371. rhp = php->rhp;
  372. mhp = kzalloc(sizeof(*mhp), GFP_KERNEL);
  373. if (!mhp)
  374. return ERR_PTR(-ENOMEM);
  375. mhp->rhp = rhp;
  376. /* First check that we have enough alignment */
  377. if ((*iova_start & ~PAGE_MASK) != (buffer_list[0].addr & ~PAGE_MASK)) {
  378. ret = -EINVAL;
  379. goto err;
  380. }
  381. if (num_phys_buf > 1 &&
  382. ((buffer_list[0].addr + buffer_list[0].size) & ~PAGE_MASK)) {
  383. ret = -EINVAL;
  384. goto err;
  385. }
  386. ret = build_phys_page_list(buffer_list, num_phys_buf, iova_start,
  387. &total_size, &npages, &shift,
  388. &page_list);
  389. if (ret)
  390. goto err;
  391. ret = alloc_pbl(mhp, npages);
  392. if (ret) {
  393. kfree(page_list);
  394. goto err_pbl;
  395. }
  396. ret = write_pbl(&mhp->rhp->rdev, page_list, mhp->attr.pbl_addr,
  397. npages);
  398. kfree(page_list);
  399. if (ret)
  400. goto err_pbl;
  401. mhp->attr.pdid = php->pdid;
  402. mhp->attr.zbva = 0;
  403. mhp->attr.perms = c4iw_ib_to_tpt_access(acc);
  404. mhp->attr.va_fbo = *iova_start;
  405. mhp->attr.page_size = shift - 12;
  406. mhp->attr.len = (u32) total_size;
  407. mhp->attr.pbl_size = npages;
  408. ret = register_mem(rhp, php, mhp, shift);
  409. if (ret)
  410. goto err_pbl;
  411. return &mhp->ibmr;
  412. err_pbl:
  413. c4iw_pblpool_free(&mhp->rhp->rdev, mhp->attr.pbl_addr,
  414. mhp->attr.pbl_size << 3);
  415. err:
  416. kfree(mhp);
  417. return ERR_PTR(ret);
  418. }
  419. struct ib_mr *c4iw_get_dma_mr(struct ib_pd *pd, int acc)
  420. {
  421. struct c4iw_dev *rhp;
  422. struct c4iw_pd *php;
  423. struct c4iw_mr *mhp;
  424. int ret;
  425. u32 stag = T4_STAG_UNSET;
  426. PDBG("%s ib_pd %p\n", __func__, pd);
  427. php = to_c4iw_pd(pd);
  428. rhp = php->rhp;
  429. mhp = kzalloc(sizeof(*mhp), GFP_KERNEL);
  430. if (!mhp)
  431. return ERR_PTR(-ENOMEM);
  432. mhp->rhp = rhp;
  433. mhp->attr.pdid = php->pdid;
  434. mhp->attr.perms = c4iw_ib_to_tpt_access(acc);
  435. mhp->attr.mw_bind_enable = (acc&IB_ACCESS_MW_BIND) == IB_ACCESS_MW_BIND;
  436. mhp->attr.zbva = 0;
  437. mhp->attr.va_fbo = 0;
  438. mhp->attr.page_size = 0;
  439. mhp->attr.len = ~0UL;
  440. mhp->attr.pbl_size = 0;
  441. ret = write_tpt_entry(&rhp->rdev, 0, &stag, 1, php->pdid,
  442. FW_RI_STAG_NSMR, mhp->attr.perms,
  443. mhp->attr.mw_bind_enable, 0, 0, ~0UL, 0, 0, 0);
  444. if (ret)
  445. goto err1;
  446. ret = finish_mem_reg(mhp, stag);
  447. if (ret)
  448. goto err2;
  449. return &mhp->ibmr;
  450. err2:
  451. dereg_mem(&rhp->rdev, mhp->attr.stag, mhp->attr.pbl_size,
  452. mhp->attr.pbl_addr);
  453. err1:
  454. kfree(mhp);
  455. return ERR_PTR(ret);
  456. }
  457. struct ib_mr *c4iw_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
  458. u64 virt, int acc, struct ib_udata *udata)
  459. {
  460. __be64 *pages;
  461. int shift, n, len;
  462. int i, j, k;
  463. int err = 0;
  464. struct ib_umem_chunk *chunk;
  465. struct c4iw_dev *rhp;
  466. struct c4iw_pd *php;
  467. struct c4iw_mr *mhp;
  468. PDBG("%s ib_pd %p\n", __func__, pd);
  469. if (length == ~0ULL)
  470. return ERR_PTR(-EINVAL);
  471. if ((length + start) < start)
  472. return ERR_PTR(-EINVAL);
  473. php = to_c4iw_pd(pd);
  474. rhp = php->rhp;
  475. mhp = kzalloc(sizeof(*mhp), GFP_KERNEL);
  476. if (!mhp)
  477. return ERR_PTR(-ENOMEM);
  478. mhp->rhp = rhp;
  479. mhp->umem = ib_umem_get(pd->uobject->context, start, length, acc, 0);
  480. if (IS_ERR(mhp->umem)) {
  481. err = PTR_ERR(mhp->umem);
  482. kfree(mhp);
  483. return ERR_PTR(err);
  484. }
  485. shift = ffs(mhp->umem->page_size) - 1;
  486. n = 0;
  487. list_for_each_entry(chunk, &mhp->umem->chunk_list, list)
  488. n += chunk->nents;
  489. err = alloc_pbl(mhp, n);
  490. if (err)
  491. goto err;
  492. pages = (__be64 *) __get_free_page(GFP_KERNEL);
  493. if (!pages) {
  494. err = -ENOMEM;
  495. goto err_pbl;
  496. }
  497. i = n = 0;
  498. list_for_each_entry(chunk, &mhp->umem->chunk_list, list)
  499. for (j = 0; j < chunk->nmap; ++j) {
  500. len = sg_dma_len(&chunk->page_list[j]) >> shift;
  501. for (k = 0; k < len; ++k) {
  502. pages[i++] = cpu_to_be64(sg_dma_address(
  503. &chunk->page_list[j]) +
  504. mhp->umem->page_size * k);
  505. if (i == PAGE_SIZE / sizeof *pages) {
  506. err = write_pbl(&mhp->rhp->rdev,
  507. pages,
  508. mhp->attr.pbl_addr + (n << 3), i);
  509. if (err)
  510. goto pbl_done;
  511. n += i;
  512. i = 0;
  513. }
  514. }
  515. }
  516. if (i)
  517. err = write_pbl(&mhp->rhp->rdev, pages,
  518. mhp->attr.pbl_addr + (n << 3), i);
  519. pbl_done:
  520. free_page((unsigned long) pages);
  521. if (err)
  522. goto err_pbl;
  523. mhp->attr.pdid = php->pdid;
  524. mhp->attr.zbva = 0;
  525. mhp->attr.perms = c4iw_ib_to_tpt_access(acc);
  526. mhp->attr.va_fbo = virt;
  527. mhp->attr.page_size = shift - 12;
  528. mhp->attr.len = length;
  529. err = register_mem(rhp, php, mhp, shift);
  530. if (err)
  531. goto err_pbl;
  532. return &mhp->ibmr;
  533. err_pbl:
  534. c4iw_pblpool_free(&mhp->rhp->rdev, mhp->attr.pbl_addr,
  535. mhp->attr.pbl_size << 3);
  536. err:
  537. ib_umem_release(mhp->umem);
  538. kfree(mhp);
  539. return ERR_PTR(err);
  540. }
  541. struct ib_mw *c4iw_alloc_mw(struct ib_pd *pd)
  542. {
  543. struct c4iw_dev *rhp;
  544. struct c4iw_pd *php;
  545. struct c4iw_mw *mhp;
  546. u32 mmid;
  547. u32 stag = 0;
  548. int ret;
  549. php = to_c4iw_pd(pd);
  550. rhp = php->rhp;
  551. mhp = kzalloc(sizeof(*mhp), GFP_KERNEL);
  552. if (!mhp)
  553. return ERR_PTR(-ENOMEM);
  554. ret = allocate_window(&rhp->rdev, &stag, php->pdid);
  555. if (ret) {
  556. kfree(mhp);
  557. return ERR_PTR(ret);
  558. }
  559. mhp->rhp = rhp;
  560. mhp->attr.pdid = php->pdid;
  561. mhp->attr.type = FW_RI_STAG_MW;
  562. mhp->attr.stag = stag;
  563. mmid = (stag) >> 8;
  564. mhp->ibmw.rkey = stag;
  565. if (insert_handle(rhp, &rhp->mmidr, mhp, mmid)) {
  566. deallocate_window(&rhp->rdev, mhp->attr.stag);
  567. kfree(mhp);
  568. return ERR_PTR(-ENOMEM);
  569. }
  570. PDBG("%s mmid 0x%x mhp %p stag 0x%x\n", __func__, mmid, mhp, stag);
  571. return &(mhp->ibmw);
  572. }
  573. int c4iw_dealloc_mw(struct ib_mw *mw)
  574. {
  575. struct c4iw_dev *rhp;
  576. struct c4iw_mw *mhp;
  577. u32 mmid;
  578. mhp = to_c4iw_mw(mw);
  579. rhp = mhp->rhp;
  580. mmid = (mw->rkey) >> 8;
  581. deallocate_window(&rhp->rdev, mhp->attr.stag);
  582. remove_handle(rhp, &rhp->mmidr, mmid);
  583. kfree(mhp);
  584. PDBG("%s ib_mw %p mmid 0x%x ptr %p\n", __func__, mw, mmid, mhp);
  585. return 0;
  586. }
  587. struct ib_mr *c4iw_alloc_fast_reg_mr(struct ib_pd *pd, int pbl_depth)
  588. {
  589. struct c4iw_dev *rhp;
  590. struct c4iw_pd *php;
  591. struct c4iw_mr *mhp;
  592. u32 mmid;
  593. u32 stag = 0;
  594. int ret = 0;
  595. php = to_c4iw_pd(pd);
  596. rhp = php->rhp;
  597. mhp = kzalloc(sizeof(*mhp), GFP_KERNEL);
  598. if (!mhp) {
  599. ret = -ENOMEM;
  600. goto err;
  601. }
  602. mhp->rhp = rhp;
  603. ret = alloc_pbl(mhp, pbl_depth);
  604. if (ret)
  605. goto err1;
  606. mhp->attr.pbl_size = pbl_depth;
  607. ret = allocate_stag(&rhp->rdev, &stag, php->pdid,
  608. mhp->attr.pbl_size, mhp->attr.pbl_addr);
  609. if (ret)
  610. goto err2;
  611. mhp->attr.pdid = php->pdid;
  612. mhp->attr.type = FW_RI_STAG_NSMR;
  613. mhp->attr.stag = stag;
  614. mhp->attr.state = 1;
  615. mmid = (stag) >> 8;
  616. mhp->ibmr.rkey = mhp->ibmr.lkey = stag;
  617. if (insert_handle(rhp, &rhp->mmidr, mhp, mmid)) {
  618. ret = -ENOMEM;
  619. goto err3;
  620. }
  621. PDBG("%s mmid 0x%x mhp %p stag 0x%x\n", __func__, mmid, mhp, stag);
  622. return &(mhp->ibmr);
  623. err3:
  624. dereg_mem(&rhp->rdev, stag, mhp->attr.pbl_size,
  625. mhp->attr.pbl_addr);
  626. err2:
  627. c4iw_pblpool_free(&mhp->rhp->rdev, mhp->attr.pbl_addr,
  628. mhp->attr.pbl_size << 3);
  629. err1:
  630. kfree(mhp);
  631. err:
  632. return ERR_PTR(ret);
  633. }
  634. struct ib_fast_reg_page_list *c4iw_alloc_fastreg_pbl(struct ib_device *device,
  635. int page_list_len)
  636. {
  637. struct c4iw_fr_page_list *c4pl;
  638. struct c4iw_dev *dev = to_c4iw_dev(device);
  639. dma_addr_t dma_addr;
  640. int size = sizeof *c4pl + page_list_len * sizeof(u64);
  641. c4pl = dma_alloc_coherent(&dev->rdev.lldi.pdev->dev, size,
  642. &dma_addr, GFP_KERNEL);
  643. if (!c4pl)
  644. return ERR_PTR(-ENOMEM);
  645. dma_unmap_addr_set(c4pl, mapping, dma_addr);
  646. c4pl->dma_addr = dma_addr;
  647. c4pl->dev = dev;
  648. c4pl->size = size;
  649. c4pl->ibpl.page_list = (u64 *)(c4pl + 1);
  650. c4pl->ibpl.max_page_list_len = page_list_len;
  651. return &c4pl->ibpl;
  652. }
  653. void c4iw_free_fastreg_pbl(struct ib_fast_reg_page_list *ibpl)
  654. {
  655. struct c4iw_fr_page_list *c4pl = to_c4iw_fr_page_list(ibpl);
  656. dma_free_coherent(&c4pl->dev->rdev.lldi.pdev->dev, c4pl->size,
  657. c4pl, dma_unmap_addr(c4pl, mapping));
  658. }
  659. int c4iw_dereg_mr(struct ib_mr *ib_mr)
  660. {
  661. struct c4iw_dev *rhp;
  662. struct c4iw_mr *mhp;
  663. u32 mmid;
  664. PDBG("%s ib_mr %p\n", __func__, ib_mr);
  665. /* There can be no memory windows */
  666. if (atomic_read(&ib_mr->usecnt))
  667. return -EINVAL;
  668. mhp = to_c4iw_mr(ib_mr);
  669. rhp = mhp->rhp;
  670. mmid = mhp->attr.stag >> 8;
  671. dereg_mem(&rhp->rdev, mhp->attr.stag, mhp->attr.pbl_size,
  672. mhp->attr.pbl_addr);
  673. if (mhp->attr.pbl_size)
  674. c4iw_pblpool_free(&mhp->rhp->rdev, mhp->attr.pbl_addr,
  675. mhp->attr.pbl_size << 3);
  676. remove_handle(rhp, &rhp->mmidr, mmid);
  677. if (mhp->kva)
  678. kfree((void *) (unsigned long) mhp->kva);
  679. if (mhp->umem)
  680. ib_umem_release(mhp->umem);
  681. PDBG("%s mmid 0x%x ptr %p\n", __func__, mmid, mhp);
  682. kfree(mhp);
  683. return 0;
  684. }