]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/dev/cxgb/ulp/iw_cxgb/iw_cxgb_mem.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / dev / cxgb / ulp / iw_cxgb / iw_cxgb_mem.c
1 /**************************************************************************
2
3 Copyright (c) 2007, Chelsio Inc.
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8
9  1. Redistributions of source code must retain the above copyright notice,
10     this list of conditions and the following disclaimer.
11
12  2. Neither the name of the Chelsio Corporation nor the names of its
13     contributors may be used to endorse or promote products derived from
14     this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 POSSIBILITY OF SUCH DAMAGE.
27
28 ***************************************************************************/
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/bus.h>
36 #include <sys/module.h>
37 #include <sys/pciio.h>
38 #include <sys/conf.h>
39 #include <machine/bus.h>
40 #include <machine/resource.h>
41 #include <sys/bus_dma.h>
42 #include <sys/rman.h>
43 #include <sys/ioccom.h>
44 #include <sys/mbuf.h>
45 #include <sys/mutex.h>
46 #include <sys/rwlock.h>
47 #include <sys/linker.h>
48 #include <sys/firmware.h>
49 #include <sys/socket.h>
50 #include <sys/sockio.h>
51 #include <sys/smp.h>
52 #include <sys/sysctl.h>
53 #include <sys/syslog.h>
54 #include <sys/queue.h>
55 #include <sys/taskqueue.h>
56 #include <sys/proc.h>
57 #include <sys/queue.h>
58 #include <sys/libkern.h>
59
60 #include <netinet/in.h>
61
62 #include <contrib/rdma/ib_verbs.h>
63 #include <contrib/rdma/ib_umem.h>
64 #include <contrib/rdma/ib_user_verbs.h>
65
66 #include <cxgb_include.h>
67 #include <ulp/iw_cxgb/iw_cxgb_wr.h>
68 #include <ulp/iw_cxgb/iw_cxgb_hal.h>
69 #include <ulp/iw_cxgb/iw_cxgb_provider.h>
70 #include <ulp/iw_cxgb/iw_cxgb_cm.h>
71 #include <ulp/iw_cxgb/iw_cxgb.h>
72 #include <ulp/iw_cxgb/iw_cxgb_resource.h>
73 #include <ulp/iw_cxgb/iw_cxgb_user.h>
74
75 int iwch_register_mem(struct iwch_dev *rhp, struct iwch_pd *php,
76                                         struct iwch_mr *mhp,
77                                         int shift,
78                                         __be64 *page_list)
79 {
80         u32 stag;
81         u32 mmid;
82
83
84         if (cxio_register_phys_mem(&rhp->rdev,
85                                    &stag, mhp->attr.pdid,
86                                    mhp->attr.perms,
87                                    mhp->attr.zbva,
88                                    mhp->attr.va_fbo,
89                                    mhp->attr.len,
90                                    shift-12,
91                                    page_list,
92                                    &mhp->attr.pbl_size, &mhp->attr.pbl_addr))
93                 return (-ENOMEM);
94         mhp->attr.state = 1;
95         mhp->attr.stag = stag;
96         mmid = stag >> 8;
97         mhp->ibmr.rkey = mhp->ibmr.lkey = stag;
98         insert_handle(rhp, &rhp->mmidr, mhp, mmid);
99         CTR3(KTR_IW_CXGB, "%s mmid 0x%x mhp %p", __FUNCTION__, mmid, mhp);
100         return 0;
101 }
102
103 int iwch_reregister_mem(struct iwch_dev *rhp, struct iwch_pd *php,
104                                         struct iwch_mr *mhp,
105                                         int shift,
106                                         __be64 *page_list,
107                                         int npages)
108 {
109         u32 stag;
110         u32 mmid;
111
112
113         /* We could support this... */
114         if (npages > mhp->attr.pbl_size)
115                 return (-ENOMEM);
116
117         stag = mhp->attr.stag;
118         if (cxio_reregister_phys_mem(&rhp->rdev,
119                                    &stag, mhp->attr.pdid,
120                                    mhp->attr.perms,
121                                    mhp->attr.zbva,
122                                    mhp->attr.va_fbo,
123                                    mhp->attr.len,
124                                    shift-12,
125                                    page_list,
126                                    &mhp->attr.pbl_size, &mhp->attr.pbl_addr))
127                 return (-ENOMEM);
128         mhp->attr.state = 1;
129         mhp->attr.stag = stag;
130         mmid = stag >> 8;
131         mhp->ibmr.rkey = mhp->ibmr.lkey = stag;
132         insert_handle(rhp, &rhp->mmidr, mhp, mmid);
133         CTR3(KTR_IW_CXGB, "%s mmid 0x%x mhp %p", __FUNCTION__, mmid, mhp);
134         return 0;
135 }
136
137 int build_phys_page_list(struct ib_phys_buf *buffer_list,
138                                         int num_phys_buf,
139                                         u64 *iova_start,
140                                         u64 *total_size,
141                                         int *npages,
142                                         int *shift,
143                                         __be64 **page_list)
144 {
145         u64 mask;
146         int i, j, n;
147
148         mask = 0;
149         *total_size = 0;
150         for (i = 0; i < num_phys_buf; ++i) {
151                 if (i != 0 && buffer_list[i].addr & ~PAGE_MASK)
152                         return (-EINVAL);
153                 if (i != 0 && i != num_phys_buf - 1 &&
154                     (buffer_list[i].size & ~PAGE_MASK))
155                         return (-EINVAL);
156                 *total_size += buffer_list[i].size;
157                 if (i > 0)
158                         mask |= buffer_list[i].addr;
159                 else
160                         mask |= buffer_list[i].addr & PAGE_MASK;
161                 if (i != num_phys_buf - 1)
162                         mask |= buffer_list[i].addr + buffer_list[i].size;
163                 else
164                         mask |= (buffer_list[i].addr + buffer_list[i].size +
165                                 PAGE_SIZE - 1) & PAGE_MASK;
166         }
167
168         if (*total_size > 0xFFFFFFFFULL)
169                 return (-ENOMEM);
170
171         /* Find largest page shift we can use to cover buffers */
172         for (*shift = PAGE_SHIFT; *shift < 27; ++(*shift))
173                 if ((1ULL << *shift) & mask)
174                         break;
175
176         buffer_list[0].size += buffer_list[0].addr & ((1ULL << *shift) - 1);
177         buffer_list[0].addr &= ~0ull << *shift;
178
179         *npages = 0;
180         for (i = 0; i < num_phys_buf; ++i)
181                 *npages += (buffer_list[i].size +
182                         (1ULL << *shift) - 1) >> *shift;
183
184         if (!*npages)
185                 return (-EINVAL);
186
187         *page_list = kmalloc(sizeof(u64) * *npages, M_NOWAIT);
188         if (!*page_list)
189                 return (-ENOMEM);
190
191         n = 0;
192         for (i = 0; i < num_phys_buf; ++i)
193                 for (j = 0;
194                      j < (buffer_list[i].size + (1ULL << *shift) - 1) >> *shift;
195                      ++j)
196                         (*page_list)[n++] = htobe64(buffer_list[i].addr +
197                             ((u64) j << *shift));
198
199         CTR6(KTR_IW_CXGB, "%s va 0x%llx mask 0x%llx shift %d len %lld pbl_size %d",
200              __FUNCTION__, (unsigned long long) *iova_start,
201              (unsigned long long) mask, *shift, (unsigned long long) *total_size,
202              *npages);
203
204         return 0;
205
206 }