iw_cxgb_mem.c revision 183292
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 183292 2008-09-23 03:16:54Z 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#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
75int 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
103int 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
137int 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}
207