mem.c 20 KB

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