]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/cxgbe/iw_cxgbe/mem.c
cxgbe/iw_cxgbe: T6 has no limit on the amount of memory that can be
[FreeBSD/FreeBSD.git] / sys / dev / cxgbe / iw_cxgbe / mem.c
1 /*
2  * Copyright (c) 2009-2013 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 <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34
35 #include "opt_inet.h"
36
37 #ifdef TCP_OFFLOAD
38 #include <linux/types.h>
39 #include <linux/kref.h>
40 #include <rdma/ib_umem.h>
41 #include <asm/atomic.h>
42
43 #include <common/t4_msg.h>
44 #include "iw_cxgbe.h"
45
46 #define T4_ULPTX_MIN_IO 32
47 #define C4IW_MAX_INLINE_SIZE 96
48
49 static int
50 mr_exceeds_hw_limits(struct c4iw_dev *dev, u64 length)
51 {
52
53         return ((is_t4(dev->rdev.adap) ||
54                 is_t5(dev->rdev.adap)) &&
55                 length >= 8*1024*1024*1024ULL);
56 }
57
58 static int
59 write_adapter_mem(struct c4iw_rdev *rdev, u32 addr, u32 len, void *data)
60 {
61         struct adapter *sc = rdev->adap;
62         struct ulp_mem_io *ulpmc;
63         struct ulptx_idata *ulpsc;
64         u8 wr_len, *to_dp, *from_dp;
65         int copy_len, num_wqe, i, ret = 0;
66         struct c4iw_wr_wait wr_wait;
67         struct wrqe *wr;
68         u32 cmd;
69
70         cmd = cpu_to_be32(V_ULPTX_CMD(ULP_TX_MEM_WRITE));
71         if (is_t4(sc))
72                 cmd |= cpu_to_be32(F_ULP_MEMIO_ORDER);
73         else
74                 cmd |= cpu_to_be32(F_T5_ULP_MEMIO_IMM);
75
76         addr &= 0x7FFFFFF;
77         CTR3(KTR_IW_CXGBE, "%s addr 0x%x len %u", __func__, addr, len);
78         num_wqe = DIV_ROUND_UP(len, C4IW_MAX_INLINE_SIZE);
79         c4iw_init_wr_wait(&wr_wait);
80         for (i = 0; i < num_wqe; i++) {
81
82                 copy_len = min(len, C4IW_MAX_INLINE_SIZE);
83                 wr_len = roundup(sizeof *ulpmc + sizeof *ulpsc +
84                                  roundup(copy_len, T4_ULPTX_MIN_IO), 16);
85
86                 wr = alloc_wrqe(wr_len, &sc->sge.mgmtq);
87                 if (wr == NULL)
88                         return (0);
89                 ulpmc = wrtod(wr);
90
91                 memset(ulpmc, 0, wr_len);
92                 INIT_ULPTX_WR(ulpmc, wr_len, 0, 0);
93
94                 if (i == (num_wqe-1)) {
95                         ulpmc->wr.wr_hi = cpu_to_be32(V_FW_WR_OP(FW_ULPTX_WR) |
96                                                     F_FW_WR_COMPL);
97                         ulpmc->wr.wr_lo = (__force __be64)(unsigned long) &wr_wait;
98                 } else
99                         ulpmc->wr.wr_hi = cpu_to_be32(V_FW_WR_OP(FW_ULPTX_WR));
100                 ulpmc->wr.wr_mid = cpu_to_be32(
101                                        V_FW_WR_LEN16(DIV_ROUND_UP(wr_len, 16)));
102
103                 ulpmc->cmd = cmd;
104                 ulpmc->dlen = cpu_to_be32(V_ULP_MEMIO_DATA_LEN(
105                     DIV_ROUND_UP(copy_len, T4_ULPTX_MIN_IO)));
106                 ulpmc->len16 = cpu_to_be32(DIV_ROUND_UP(wr_len-sizeof(ulpmc->wr),
107                                                       16));
108                 ulpmc->lock_addr = cpu_to_be32(V_ULP_MEMIO_ADDR(addr + i * 3));
109
110                 ulpsc = (struct ulptx_idata *)(ulpmc + 1);
111                 ulpsc->cmd_more = cpu_to_be32(V_ULPTX_CMD(ULP_TX_SC_IMM));
112                 ulpsc->len = cpu_to_be32(roundup(copy_len, T4_ULPTX_MIN_IO));
113
114                 to_dp = (u8 *)(ulpsc + 1);
115                 from_dp = (u8 *)data + i * C4IW_MAX_INLINE_SIZE;
116                 if (data)
117                         memcpy(to_dp, from_dp, copy_len);
118                 else
119                         memset(to_dp, 0, copy_len);
120                 if (copy_len % T4_ULPTX_MIN_IO)
121                         memset(to_dp + copy_len, 0, T4_ULPTX_MIN_IO -
122                                (copy_len % T4_ULPTX_MIN_IO));
123                 t4_wrq_tx(sc, wr);
124                 len -= C4IW_MAX_INLINE_SIZE;
125         }
126
127         ret = c4iw_wait_for_reply(rdev, &wr_wait, 0, 0, __func__);
128         return ret;
129 }
130
131 /*
132  * Build and write a TPT entry.
133  * IN: stag key, pdid, perm, bind_enabled, zbva, to, len, page_size,
134  *     pbl_size and pbl_addr
135  * OUT: stag index
136  */
137 static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,
138                            u32 *stag, u8 stag_state, u32 pdid,
139                            enum fw_ri_stag_type type, enum fw_ri_mem_perms perm,
140                            int bind_enabled, u32 zbva, u64 to,
141                            u64 len, u8 page_size, u32 pbl_size, u32 pbl_addr)
142 {
143         int err;
144         struct fw_ri_tpte tpt;
145         u32 stag_idx;
146         static atomic_t key;
147
148         if (c4iw_fatal_error(rdev))
149                 return -EIO;
150
151         stag_state = stag_state > 0;
152         stag_idx = (*stag) >> 8;
153
154         if ((!reset_tpt_entry) && (*stag == T4_STAG_UNSET)) {
155                 stag_idx = c4iw_get_resource(&rdev->resource.tpt_table);
156                 if (!stag_idx) {
157                         mutex_lock(&rdev->stats.lock);
158                         rdev->stats.stag.fail++;
159                         mutex_unlock(&rdev->stats.lock);
160                         return -ENOMEM;
161                 }
162                 mutex_lock(&rdev->stats.lock);
163                 rdev->stats.stag.cur += 32;
164                 if (rdev->stats.stag.cur > rdev->stats.stag.max)
165                         rdev->stats.stag.max = rdev->stats.stag.cur;
166                 mutex_unlock(&rdev->stats.lock);
167                 *stag = (stag_idx << 8) | (atomic_inc_return(&key) & 0xff);
168         }
169         CTR5(KTR_IW_CXGBE,
170             "%s stag_state 0x%0x type 0x%0x pdid 0x%0x, stag_idx 0x%x",
171             __func__, stag_state, type, pdid, stag_idx);
172
173         /* write TPT entry */
174         if (reset_tpt_entry)
175                 memset(&tpt, 0, sizeof(tpt));
176         else {
177                 tpt.valid_to_pdid = cpu_to_be32(F_FW_RI_TPTE_VALID |
178                         V_FW_RI_TPTE_STAGKEY((*stag & M_FW_RI_TPTE_STAGKEY)) |
179                         V_FW_RI_TPTE_STAGSTATE(stag_state) |
180                         V_FW_RI_TPTE_STAGTYPE(type) | V_FW_RI_TPTE_PDID(pdid));
181                 tpt.locread_to_qpid = cpu_to_be32(V_FW_RI_TPTE_PERM(perm) |
182                         (bind_enabled ? F_FW_RI_TPTE_MWBINDEN : 0) |
183                         V_FW_RI_TPTE_ADDRTYPE((zbva ? FW_RI_ZERO_BASED_TO :
184                                                       FW_RI_VA_BASED_TO))|
185                         V_FW_RI_TPTE_PS(page_size));
186                 tpt.nosnoop_pbladdr = !pbl_size ? 0 : cpu_to_be32(
187                         V_FW_RI_TPTE_PBLADDR(PBL_OFF(rdev, pbl_addr)>>3));
188                 tpt.len_lo = cpu_to_be32((u32)(len & 0xffffffffUL));
189                 tpt.va_hi = cpu_to_be32((u32)(to >> 32));
190                 tpt.va_lo_fbo = cpu_to_be32((u32)(to & 0xffffffffUL));
191                 tpt.dca_mwbcnt_pstag = cpu_to_be32(0);
192                 tpt.len_hi = cpu_to_be32((u32)(len >> 32));
193         }
194         err = write_adapter_mem(rdev, stag_idx +
195                                 (rdev->adap->vres.stag.start >> 5),
196                                 sizeof(tpt), &tpt);
197
198         if (reset_tpt_entry) {
199                 c4iw_put_resource(&rdev->resource.tpt_table, stag_idx);
200                 mutex_lock(&rdev->stats.lock);
201                 rdev->stats.stag.cur -= 32;
202                 mutex_unlock(&rdev->stats.lock);
203         }
204         return err;
205 }
206
207 static int write_pbl(struct c4iw_rdev *rdev, __be64 *pbl,
208                      u32 pbl_addr, u32 pbl_size)
209 {
210         int err;
211
212         CTR4(KTR_IW_CXGBE, "%s *pdb_addr 0x%x, pbl_base 0x%x, pbl_size %d",
213              __func__, pbl_addr, rdev->adap->vres.pbl.start, pbl_size);
214
215         err = write_adapter_mem(rdev, pbl_addr >> 5, pbl_size << 3, pbl);
216         return err;
217 }
218
219 static int dereg_mem(struct c4iw_rdev *rdev, u32 stag, u32 pbl_size,
220                      u32 pbl_addr)
221 {
222         return write_tpt_entry(rdev, 1, &stag, 0, 0, 0, 0, 0, 0, 0UL, 0, 0,
223                                pbl_size, pbl_addr);
224 }
225
226 static int allocate_window(struct c4iw_rdev *rdev, u32 * stag, u32 pdid)
227 {
228         *stag = T4_STAG_UNSET;
229         return write_tpt_entry(rdev, 0, stag, 0, pdid, FW_RI_STAG_MW, 0, 0, 0,
230                                0UL, 0, 0, 0, 0);
231 }
232
233 static int deallocate_window(struct c4iw_rdev *rdev, u32 stag)
234 {
235         return write_tpt_entry(rdev, 1, &stag, 0, 0, 0, 0, 0, 0, 0UL, 0, 0, 0,
236                                0);
237 }
238
239 static int allocate_stag(struct c4iw_rdev *rdev, u32 *stag, u32 pdid,
240                          u32 pbl_size, u32 pbl_addr)
241 {
242         *stag = T4_STAG_UNSET;
243         return write_tpt_entry(rdev, 0, stag, 0, pdid, FW_RI_STAG_NSMR, 0, 0, 0,
244                                0UL, 0, 0, pbl_size, pbl_addr);
245 }
246
247 static int finish_mem_reg(struct c4iw_mr *mhp, u32 stag)
248 {
249         u32 mmid;
250
251         mhp->attr.state = 1;
252         mhp->attr.stag = stag;
253         mmid = stag >> 8;
254         mhp->ibmr.rkey = mhp->ibmr.lkey = stag;
255         CTR3(KTR_IW_CXGBE, "%s mmid 0x%x mhp %p", __func__, mmid, mhp);
256         return insert_handle(mhp->rhp, &mhp->rhp->mmidr, mhp, mmid);
257 }
258
259 static int register_mem(struct c4iw_dev *rhp, struct c4iw_pd *php,
260                       struct c4iw_mr *mhp, int shift)
261 {
262         u32 stag = T4_STAG_UNSET;
263         int ret;
264
265         ret = write_tpt_entry(&rhp->rdev, 0, &stag, 1, mhp->attr.pdid,
266                               FW_RI_STAG_NSMR, mhp->attr.len ? mhp->attr.perms : 0,
267                               mhp->attr.mw_bind_enable, mhp->attr.zbva,
268                               mhp->attr.va_fbo, mhp->attr.len ? mhp->attr.len : -1, shift - 12,
269                               mhp->attr.pbl_size, mhp->attr.pbl_addr);
270         if (ret)
271                 return ret;
272
273         ret = finish_mem_reg(mhp, stag);
274         if (ret)
275                 dereg_mem(&rhp->rdev, mhp->attr.stag, mhp->attr.pbl_size,
276                        mhp->attr.pbl_addr);
277         return ret;
278 }
279
280 static int reregister_mem(struct c4iw_dev *rhp, struct c4iw_pd *php,
281                           struct c4iw_mr *mhp, int shift, int npages)
282 {
283         u32 stag;
284         int ret;
285
286         if (npages > mhp->attr.pbl_size)
287                 return -ENOMEM;
288
289         stag = mhp->attr.stag;
290         ret = write_tpt_entry(&rhp->rdev, 0, &stag, 1, mhp->attr.pdid,
291                               FW_RI_STAG_NSMR, mhp->attr.perms,
292                               mhp->attr.mw_bind_enable, mhp->attr.zbva,
293                               mhp->attr.va_fbo, mhp->attr.len, shift - 12,
294                               mhp->attr.pbl_size, mhp->attr.pbl_addr);
295         if (ret)
296                 return ret;
297
298         ret = finish_mem_reg(mhp, stag);
299         if (ret)
300                 dereg_mem(&rhp->rdev, mhp->attr.stag, mhp->attr.pbl_size,
301                        mhp->attr.pbl_addr);
302
303         return ret;
304 }
305
306 static int alloc_pbl(struct c4iw_mr *mhp, int npages)
307 {
308         mhp->attr.pbl_addr = c4iw_pblpool_alloc(&mhp->rhp->rdev,
309                                                     npages << 3);
310
311         if (!mhp->attr.pbl_addr)
312                 return -ENOMEM;
313
314         mhp->attr.pbl_size = npages;
315
316         return 0;
317 }
318
319 static int build_phys_page_list(struct ib_phys_buf *buffer_list,
320                                 int num_phys_buf, u64 *iova_start,
321                                 u64 *total_size, int *npages,
322                                 int *shift, __be64 **page_list)
323 {
324         u64 mask;
325         int i, j, n;
326
327         mask = 0;
328         *total_size = 0;
329         for (i = 0; i < num_phys_buf; ++i) {
330                 if (i != 0 && buffer_list[i].addr & ~PAGE_MASK)
331                         return -EINVAL;
332                 if (i != 0 && i != num_phys_buf - 1 &&
333                     (buffer_list[i].size & ~PAGE_MASK))
334                         return -EINVAL;
335                 *total_size += buffer_list[i].size;
336                 if (i > 0)
337                         mask |= buffer_list[i].addr;
338                 else
339                         mask |= buffer_list[i].addr & PAGE_MASK;
340                 if (i != num_phys_buf - 1)
341                         mask |= buffer_list[i].addr + buffer_list[i].size;
342                 else
343                         mask |= (buffer_list[i].addr + buffer_list[i].size +
344                                 PAGE_SIZE - 1) & PAGE_MASK;
345         }
346
347         /* Find largest page shift we can use to cover buffers */
348         for (*shift = PAGE_SHIFT; *shift < 27; ++(*shift))
349                 if ((1ULL << *shift) & mask)
350                         break;
351
352         buffer_list[0].size += buffer_list[0].addr & ((1ULL << *shift) - 1);
353         buffer_list[0].addr &= ~0ull << *shift;
354
355         *npages = 0;
356         for (i = 0; i < num_phys_buf; ++i)
357                 *npages += (buffer_list[i].size +
358                         (1ULL << *shift) - 1) >> *shift;
359
360         if (!*npages)
361                 return -EINVAL;
362
363         *page_list = kmalloc(sizeof(u64) * *npages, GFP_KERNEL);
364         if (!*page_list)
365                 return -ENOMEM;
366
367         n = 0;
368         for (i = 0; i < num_phys_buf; ++i)
369                 for (j = 0;
370                      j < (buffer_list[i].size + (1ULL << *shift) - 1) >> *shift;
371                      ++j)
372                         (*page_list)[n++] = cpu_to_be64(buffer_list[i].addr +
373                             ((u64) j << *shift));
374
375         CTR6(KTR_IW_CXGBE,
376             "%s va 0x%llx mask 0x%llx shift %d len %lld pbl_size %d", __func__,
377             (unsigned long long)*iova_start, (unsigned long long)mask, *shift,
378             (unsigned long long)*total_size, *npages);
379
380         return 0;
381
382 }
383
384 int c4iw_reregister_phys_mem(struct ib_mr *mr, int mr_rereg_mask,
385                              struct ib_pd *pd, struct ib_phys_buf *buffer_list,
386                              int num_phys_buf, int acc, u64 *iova_start)
387 {
388
389         struct c4iw_mr mh, *mhp;
390         struct c4iw_pd *php;
391         struct c4iw_dev *rhp;
392         __be64 *page_list = NULL;
393         int shift = 0;
394         u64 total_size = 0;
395         int npages = 0;
396         int ret;
397
398         CTR3(KTR_IW_CXGBE, "%s ib_mr %p ib_pd %p", __func__, mr, pd);
399
400         /* There can be no memory windows */
401         if (atomic_read(&mr->usecnt))
402                 return -EINVAL;
403
404         mhp = to_c4iw_mr(mr);
405         rhp = mhp->rhp;
406         php = to_c4iw_pd(mr->pd);
407
408         /* make sure we are on the same adapter */
409         if (rhp != php->rhp)
410                 return -EINVAL;
411
412         memcpy(&mh, mhp, sizeof *mhp);
413
414         if (mr_rereg_mask & IB_MR_REREG_PD)
415                 php = to_c4iw_pd(pd);
416         if (mr_rereg_mask & IB_MR_REREG_ACCESS) {
417                 mh.attr.perms = c4iw_ib_to_tpt_access(acc);
418                 mh.attr.mw_bind_enable = (acc & IB_ACCESS_MW_BIND) ==
419                                          IB_ACCESS_MW_BIND;
420         }
421         if (mr_rereg_mask & IB_MR_REREG_TRANS) {
422                 ret = build_phys_page_list(buffer_list, num_phys_buf,
423                                                 iova_start,
424                                                 &total_size, &npages,
425                                                 &shift, &page_list);
426                 if (ret)
427                         return ret;
428         }
429         if (mr_exceeds_hw_limits(rhp, total_size)) {
430                 kfree(page_list);
431                 return -EINVAL;
432         }
433         ret = reregister_mem(rhp, php, &mh, shift, npages);
434         kfree(page_list);
435         if (ret)
436                 return ret;
437         if (mr_rereg_mask & IB_MR_REREG_PD)
438                 mhp->attr.pdid = php->pdid;
439         if (mr_rereg_mask & IB_MR_REREG_ACCESS)
440                 mhp->attr.perms = c4iw_ib_to_tpt_access(acc);
441         if (mr_rereg_mask & IB_MR_REREG_TRANS) {
442                 mhp->attr.zbva = 0;
443                 mhp->attr.va_fbo = *iova_start;
444                 mhp->attr.page_size = shift - 12;
445                 mhp->attr.len = (u32) total_size;
446                 mhp->attr.pbl_size = npages;
447         }
448
449         return 0;
450 }
451
452 struct ib_mr *c4iw_register_phys_mem(struct ib_pd *pd,
453                                      struct ib_phys_buf *buffer_list,
454                                      int num_phys_buf, int acc, u64 *iova_start)
455 {
456         __be64 *page_list;
457         int shift;
458         u64 total_size;
459         int npages;
460         struct c4iw_dev *rhp;
461         struct c4iw_pd *php;
462         struct c4iw_mr *mhp;
463         int ret;
464
465         CTR2(KTR_IW_CXGBE, "%s ib_pd %p", __func__, pd);
466         php = to_c4iw_pd(pd);
467         rhp = php->rhp;
468
469         mhp = kzalloc(sizeof(*mhp), GFP_KERNEL);
470         if (!mhp)
471                 return ERR_PTR(-ENOMEM);
472
473         mhp->rhp = rhp;
474
475         /* First check that we have enough alignment */
476         if ((*iova_start & ~PAGE_MASK) != (buffer_list[0].addr & ~PAGE_MASK)) {
477                 ret = -EINVAL;
478                 goto err;
479         }
480
481         if (num_phys_buf > 1 &&
482             ((buffer_list[0].addr + buffer_list[0].size) & ~PAGE_MASK)) {
483                 ret = -EINVAL;
484                 goto err;
485         }
486
487         ret = build_phys_page_list(buffer_list, num_phys_buf, iova_start,
488                                         &total_size, &npages, &shift,
489                                         &page_list);
490         if (ret)
491                 goto err;
492
493         if (mr_exceeds_hw_limits(rhp, total_size)) {
494                 kfree(page_list);
495                 ret = -EINVAL;
496                 goto err;
497         }
498         ret = alloc_pbl(mhp, npages);
499         if (ret) {
500                 kfree(page_list);
501                 goto err;
502         }
503
504         ret = write_pbl(&mhp->rhp->rdev, page_list, mhp->attr.pbl_addr,
505                              npages);
506         kfree(page_list);
507         if (ret)
508                 goto err_pbl;
509
510         mhp->attr.pdid = php->pdid;
511         mhp->attr.zbva = 0;
512
513         mhp->attr.perms = c4iw_ib_to_tpt_access(acc);
514         mhp->attr.va_fbo = *iova_start;
515         mhp->attr.page_size = shift - 12;
516
517         mhp->attr.len = (u32) total_size;
518         mhp->attr.pbl_size = npages;
519         ret = register_mem(rhp, php, mhp, shift);
520         if (ret)
521                 goto err_pbl;
522
523         return &mhp->ibmr;
524
525 err_pbl:
526         c4iw_pblpool_free(&mhp->rhp->rdev, mhp->attr.pbl_addr,
527                               mhp->attr.pbl_size << 3);
528
529 err:
530         kfree(mhp);
531         return ERR_PTR(ret);
532
533 }
534
535 struct ib_mr *c4iw_get_dma_mr(struct ib_pd *pd, int acc)
536 {
537         struct c4iw_dev *rhp;
538         struct c4iw_pd *php;
539         struct c4iw_mr *mhp;
540         int ret;
541         u32 stag = T4_STAG_UNSET;
542
543         CTR2(KTR_IW_CXGBE, "%s ib_pd %p", __func__, pd);
544         php = to_c4iw_pd(pd);
545         rhp = php->rhp;
546
547         mhp = kzalloc(sizeof(*mhp), GFP_KERNEL);
548         if (!mhp)
549                 return ERR_PTR(-ENOMEM);
550
551         mhp->rhp = rhp;
552         mhp->attr.pdid = php->pdid;
553         mhp->attr.perms = c4iw_ib_to_tpt_access(acc);
554         mhp->attr.mw_bind_enable = (acc&IB_ACCESS_MW_BIND) == IB_ACCESS_MW_BIND;
555         mhp->attr.zbva = 0;
556         mhp->attr.va_fbo = 0;
557         mhp->attr.page_size = 0;
558         mhp->attr.len = ~0UL;
559         mhp->attr.pbl_size = 0;
560
561         ret = write_tpt_entry(&rhp->rdev, 0, &stag, 1, php->pdid,
562                               FW_RI_STAG_NSMR, mhp->attr.perms,
563                               mhp->attr.mw_bind_enable, 0, 0, ~0UL, 0, 0, 0);
564         if (ret)
565                 goto err1;
566
567         ret = finish_mem_reg(mhp, stag);
568         if (ret)
569                 goto err2;
570         return &mhp->ibmr;
571 err2:
572         dereg_mem(&rhp->rdev, mhp->attr.stag, mhp->attr.pbl_size,
573                   mhp->attr.pbl_addr);
574 err1:
575         kfree(mhp);
576         return ERR_PTR(ret);
577 }
578
579 struct ib_mr *c4iw_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
580     u64 virt, int acc, struct ib_udata *udata, int mr_id)
581 {
582         __be64 *pages;
583         int shift, n, len;
584         int i, k, entry;
585         int err = 0;
586         struct scatterlist *sg;
587         struct c4iw_dev *rhp;
588         struct c4iw_pd *php;
589         struct c4iw_mr *mhp;
590
591         CTR2(KTR_IW_CXGBE, "%s ib_pd %p", __func__, pd);
592
593         if (length == ~0ULL)
594                 return ERR_PTR(-EINVAL);
595
596         if ((length + start) < start)
597                 return ERR_PTR(-EINVAL);
598
599         php = to_c4iw_pd(pd);
600         rhp = php->rhp;
601
602         if (mr_exceeds_hw_limits(rhp, length))
603                 return ERR_PTR(-EINVAL);
604
605         mhp = kzalloc(sizeof(*mhp), GFP_KERNEL);
606         if (!mhp)
607                 return ERR_PTR(-ENOMEM);
608
609         mhp->rhp = rhp;
610
611         mhp->umem = ib_umem_get(pd->uobject->context, start, length, acc, 0);
612         if (IS_ERR(mhp->umem)) {
613                 err = PTR_ERR(mhp->umem);
614                 kfree(mhp);
615                 return ERR_PTR(err);
616         }
617
618         shift = ffs(mhp->umem->page_size) - 1;
619         
620         n = mhp->umem->nmap;
621         err = alloc_pbl(mhp, n);
622         if (err)
623                 goto err;
624
625         pages = (__be64 *) __get_free_page(GFP_KERNEL);
626         if (!pages) {
627                 err = -ENOMEM;
628                 goto err_pbl;
629         }
630
631         i = n = 0;
632         for_each_sg(mhp->umem->sg_head.sgl, sg, mhp->umem->nmap, entry) {
633                 len = sg_dma_len(sg) >> shift;
634                 for (k = 0; k < len; ++k) {
635                         pages[i++] = cpu_to_be64(sg_dma_address(sg) +
636                                         mhp->umem->page_size * k);
637                         if (i == PAGE_SIZE / sizeof *pages) {
638                                 err = write_pbl(&mhp->rhp->rdev,
639                                                 pages,
640                                                 mhp->attr.pbl_addr + (n << 3), i);
641                                 if (err)
642                                         goto pbl_done;
643                                 n += i;
644                                 i = 0;
645
646                         }
647                 }
648         }
649
650         if (i)
651                 err = write_pbl(&mhp->rhp->rdev, pages,
652                                      mhp->attr.pbl_addr + (n << 3), i);
653
654 pbl_done:
655         free_page((unsigned long) pages);
656         if (err)
657                 goto err_pbl;
658
659         mhp->attr.pdid = php->pdid;
660         mhp->attr.zbva = 0;
661         mhp->attr.perms = c4iw_ib_to_tpt_access(acc);
662         mhp->attr.va_fbo = virt;
663         mhp->attr.page_size = shift - 12;
664         mhp->attr.len = length;
665
666         err = register_mem(rhp, php, mhp, shift);
667         if (err)
668                 goto err_pbl;
669
670         return &mhp->ibmr;
671
672 err_pbl:
673         c4iw_pblpool_free(&mhp->rhp->rdev, mhp->attr.pbl_addr,
674                               mhp->attr.pbl_size << 3);
675
676 err:
677         ib_umem_release(mhp->umem);
678         kfree(mhp);
679         return ERR_PTR(err);
680 }
681
682 struct ib_mw *c4iw_alloc_mw(struct ib_pd *pd, enum ib_mw_type type)
683 {
684         struct c4iw_dev *rhp;
685         struct c4iw_pd *php;
686         struct c4iw_mw *mhp;
687         u32 mmid;
688         u32 stag = 0;
689         int ret;
690
691         php = to_c4iw_pd(pd);
692         rhp = php->rhp;
693         mhp = kzalloc(sizeof(*mhp), GFP_KERNEL);
694         if (!mhp)
695                 return ERR_PTR(-ENOMEM);
696         ret = allocate_window(&rhp->rdev, &stag, php->pdid);
697         if (ret) {
698                 kfree(mhp);
699                 return ERR_PTR(ret);
700         }
701         mhp->rhp = rhp;
702         mhp->attr.pdid = php->pdid;
703         mhp->attr.type = FW_RI_STAG_MW;
704         mhp->attr.stag = stag;
705         mmid = (stag) >> 8;
706         mhp->ibmw.rkey = stag;
707         if (insert_handle(rhp, &rhp->mmidr, mhp, mmid)) {
708                 deallocate_window(&rhp->rdev, mhp->attr.stag);
709                 kfree(mhp);
710                 return ERR_PTR(-ENOMEM);
711         }
712         CTR4(KTR_IW_CXGBE, "%s mmid 0x%x mhp %p stag 0x%x", __func__, mmid, mhp,
713             stag);
714         return &(mhp->ibmw);
715 }
716
717 int c4iw_dealloc_mw(struct ib_mw *mw)
718 {
719         struct c4iw_dev *rhp;
720         struct c4iw_mw *mhp;
721         u32 mmid;
722
723         mhp = to_c4iw_mw(mw);
724         rhp = mhp->rhp;
725         mmid = (mw->rkey) >> 8;
726         remove_handle(rhp, &rhp->mmidr, mmid);
727         deallocate_window(&rhp->rdev, mhp->attr.stag);
728         kfree(mhp);
729         CTR4(KTR_IW_CXGBE, "%s ib_mw %p mmid 0x%x ptr %p", __func__, mw, mmid,
730             mhp);
731         return 0;
732 }
733
734 struct ib_mr *c4iw_alloc_fast_reg_mr(struct ib_pd *pd, int pbl_depth)
735 {
736         struct c4iw_dev *rhp;
737         struct c4iw_pd *php;
738         struct c4iw_mr *mhp;
739         u32 mmid;
740         u32 stag = 0;
741         int ret = 0;
742
743         php = to_c4iw_pd(pd);
744         rhp = php->rhp;
745         mhp = kzalloc(sizeof(*mhp), GFP_KERNEL);
746         if (!mhp) {
747                 ret = -ENOMEM;
748                 goto err;
749         }
750
751         mhp->rhp = rhp;
752         ret = alloc_pbl(mhp, pbl_depth);
753         if (ret)
754                 goto err1;
755         mhp->attr.pbl_size = pbl_depth;
756         ret = allocate_stag(&rhp->rdev, &stag, php->pdid,
757                                  mhp->attr.pbl_size, mhp->attr.pbl_addr);
758         if (ret)
759                 goto err2;
760         mhp->attr.pdid = php->pdid;
761         mhp->attr.type = FW_RI_STAG_NSMR;
762         mhp->attr.stag = stag;
763         mhp->attr.state = 1;
764         mmid = (stag) >> 8;
765         mhp->ibmr.rkey = mhp->ibmr.lkey = stag;
766         if (insert_handle(rhp, &rhp->mmidr, mhp, mmid)) {
767                 ret = -ENOMEM;
768                 goto err3;
769         }
770
771         CTR4(KTR_IW_CXGBE, "%s mmid 0x%x mhp %p stag 0x%x", __func__, mmid, mhp,
772             stag);
773         return &(mhp->ibmr);
774 err3:
775         dereg_mem(&rhp->rdev, stag, mhp->attr.pbl_size,
776                        mhp->attr.pbl_addr);
777 err2:
778         c4iw_pblpool_free(&mhp->rhp->rdev, mhp->attr.pbl_addr,
779                               mhp->attr.pbl_size << 3);
780 err1:
781         kfree(mhp);
782 err:
783         return ERR_PTR(ret);
784 }
785
786 struct ib_fast_reg_page_list *c4iw_alloc_fastreg_pbl(struct ib_device *device,
787                                                      int page_list_len)
788 {
789         struct c4iw_fr_page_list *c4pl;
790         struct c4iw_dev *dev = to_c4iw_dev(device);
791         bus_addr_t dma_addr;
792         int size = sizeof *c4pl + page_list_len * sizeof(u64);
793
794         c4pl = contigmalloc(size,
795             M_DEVBUF, M_NOWAIT, 0ul, ~0ul, 4096, 0);
796         if (c4pl)
797                 dma_addr = vtophys(c4pl);
798         else
799                 return ERR_PTR(-ENOMEM);
800
801         pci_unmap_addr_set(c4pl, mapping, dma_addr);
802         c4pl->dma_addr = dma_addr;
803         c4pl->dev = dev;
804         c4pl->size = size;
805         c4pl->ibpl.page_list = (u64 *)(c4pl + 1);
806         c4pl->ibpl.max_page_list_len = page_list_len;
807
808         return &c4pl->ibpl;
809 }
810
811 void c4iw_free_fastreg_pbl(struct ib_fast_reg_page_list *ibpl)
812 {
813         struct c4iw_fr_page_list *c4pl = to_c4iw_fr_page_list(ibpl);
814         contigfree(c4pl, c4pl->size, M_DEVBUF);
815 }
816
817 int c4iw_dereg_mr(struct ib_mr *ib_mr)
818 {
819         struct c4iw_dev *rhp;
820         struct c4iw_mr *mhp;
821         u32 mmid;
822
823         CTR2(KTR_IW_CXGBE, "%s ib_mr %p", __func__, ib_mr);
824         /* There can be no memory windows */
825         if (atomic_read(&ib_mr->usecnt))
826                 return -EINVAL;
827
828         mhp = to_c4iw_mr(ib_mr);
829         rhp = mhp->rhp;
830         mmid = mhp->attr.stag >> 8;
831         remove_handle(rhp, &rhp->mmidr, mmid);
832         dereg_mem(&rhp->rdev, mhp->attr.stag, mhp->attr.pbl_size,
833                        mhp->attr.pbl_addr);
834         if (mhp->attr.pbl_size)
835                 c4iw_pblpool_free(&mhp->rhp->rdev, mhp->attr.pbl_addr,
836                                   mhp->attr.pbl_size << 3);
837         if (mhp->kva)
838                 kfree((void *) (unsigned long) mhp->kva);
839         if (mhp->umem)
840                 ib_umem_release(mhp->umem);
841         CTR3(KTR_IW_CXGBE, "%s mmid 0x%x ptr %p", __func__, mmid, mhp);
842         kfree(mhp);
843         return 0;
844 }
845 #endif