iw_cxgb_mem.c revision 178786
1/**************************************************************************
2
3Copyright (c) 2007, Chelsio Inc.
4All rights reserved.
5
6Redistribution and use in source and binary forms, with or without
7modification, 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
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26POSSIBILITY OF SUCH DAMAGE.
27
28***************************************************************************/
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: head/sys/dev/cxgb/ulp/iw_cxgb/iw_cxgb_mem.c 178786 2008-05-05 18:46:18Z kmacy $");
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
67#ifdef CONFIG_DEFINED
68#include <cxgb_include.h>
69#include <ulp/iw_cxgb/iw_cxgb_wr.h>
70#include <ulp/iw_cxgb/iw_cxgb_hal.h>
71#include <ulp/iw_cxgb/iw_cxgb_provider.h>
72#include <ulp/iw_cxgb/iw_cxgb_cm.h>
73#include <ulp/iw_cxgb/iw_cxgb.h>
74#include <ulp/iw_cxgb/iw_cxgb_resource.h>
75#include <ulp/iw_cxgb/iw_cxgb_user.h>
76#else
77#include <dev/cxgb/cxgb_include.h>
78#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_wr.h>
79#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_hal.h>
80#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_provider.h>
81#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_cm.h>
82#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb.h>
83#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_resource.h>
84#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_user.h>
85#endif
86
87
88int iwch_register_mem(struct iwch_dev *rhp, struct iwch_pd *php,
89					struct iwch_mr *mhp,
90					int shift,
91					__be64 *page_list)
92{
93	u32 stag;
94	u32 mmid;
95
96
97	if (cxio_register_phys_mem(&rhp->rdev,
98				   &stag, mhp->attr.pdid,
99				   mhp->attr.perms,
100				   mhp->attr.zbva,
101				   mhp->attr.va_fbo,
102				   mhp->attr.len,
103				   shift-12,
104				   page_list,
105				   &mhp->attr.pbl_size, &mhp->attr.pbl_addr))
106		return (-ENOMEM);
107	mhp->attr.state = 1;
108	mhp->attr.stag = stag;
109	mmid = stag >> 8;
110	mhp->ibmr.rkey = mhp->ibmr.lkey = stag;
111	insert_handle(rhp, &rhp->mmidr, mhp, mmid);
112	CTR3(KTR_IW_CXGB, "%s mmid 0x%x mhp %p", __FUNCTION__, mmid, mhp);
113	return 0;
114}
115
116int iwch_reregister_mem(struct iwch_dev *rhp, struct iwch_pd *php,
117					struct iwch_mr *mhp,
118					int shift,
119					__be64 *page_list,
120					int npages)
121{
122	u32 stag;
123	u32 mmid;
124
125
126	/* We could support this... */
127	if (npages > mhp->attr.pbl_size)
128		return (-ENOMEM);
129
130	stag = mhp->attr.stag;
131	if (cxio_reregister_phys_mem(&rhp->rdev,
132				   &stag, mhp->attr.pdid,
133				   mhp->attr.perms,
134				   mhp->attr.zbva,
135				   mhp->attr.va_fbo,
136				   mhp->attr.len,
137				   shift-12,
138				   page_list,
139				   &mhp->attr.pbl_size, &mhp->attr.pbl_addr))
140		return (-ENOMEM);
141	mhp->attr.state = 1;
142	mhp->attr.stag = stag;
143	mmid = stag >> 8;
144	mhp->ibmr.rkey = mhp->ibmr.lkey = stag;
145	insert_handle(rhp, &rhp->mmidr, mhp, mmid);
146	CTR3(KTR_IW_CXGB, "%s mmid 0x%x mhp %p", __FUNCTION__, mmid, mhp);
147	return 0;
148}
149
150int build_phys_page_list(struct ib_phys_buf *buffer_list,
151					int num_phys_buf,
152					u64 *iova_start,
153					u64 *total_size,
154					int *npages,
155					int *shift,
156					__be64 **page_list)
157{
158	u64 mask;
159	int i, j, n;
160
161	mask = 0;
162	*total_size = 0;
163	for (i = 0; i < num_phys_buf; ++i) {
164		if (i != 0 && buffer_list[i].addr & ~PAGE_MASK)
165			return (-EINVAL);
166		if (i != 0 && i != num_phys_buf - 1 &&
167		    (buffer_list[i].size & ~PAGE_MASK))
168			return (-EINVAL);
169		*total_size += buffer_list[i].size;
170		if (i > 0)
171			mask |= buffer_list[i].addr;
172		else
173			mask |= buffer_list[i].addr & PAGE_MASK;
174		if (i != num_phys_buf - 1)
175			mask |= buffer_list[i].addr + buffer_list[i].size;
176		else
177			mask |= (buffer_list[i].addr + buffer_list[i].size +
178				PAGE_SIZE - 1) & PAGE_MASK;
179	}
180
181	if (*total_size > 0xFFFFFFFFULL)
182		return (-ENOMEM);
183
184	/* Find largest page shift we can use to cover buffers */
185	for (*shift = PAGE_SHIFT; *shift < 27; ++(*shift))
186		if ((1ULL << *shift) & mask)
187			break;
188
189	buffer_list[0].size += buffer_list[0].addr & ((1ULL << *shift) - 1);
190	buffer_list[0].addr &= ~0ull << *shift;
191
192	*npages = 0;
193	for (i = 0; i < num_phys_buf; ++i)
194		*npages += (buffer_list[i].size +
195			(1ULL << *shift) - 1) >> *shift;
196
197	if (!*npages)
198		return (-EINVAL);
199
200	*page_list = kmalloc(sizeof(u64) * *npages, M_NOWAIT);
201	if (!*page_list)
202		return (-ENOMEM);
203
204	n = 0;
205	for (i = 0; i < num_phys_buf; ++i)
206		for (j = 0;
207		     j < (buffer_list[i].size + (1ULL << *shift) - 1) >> *shift;
208		     ++j)
209			(*page_list)[n++] = htobe64(buffer_list[i].addr +
210			    ((u64) j << *shift));
211
212	CTR6(KTR_IW_CXGB, "%s va 0x%llx mask 0x%llx shift %d len %lld pbl_size %d",
213	     __FUNCTION__, (unsigned long long) *iova_start,
214	     (unsigned long long) mask, *shift, (unsigned long long) *total_size,
215	     *npages);
216
217	return 0;
218
219}
220