1*9e39c5baSBill Taylor /*
2*9e39c5baSBill Taylor * CDDL HEADER START
3*9e39c5baSBill Taylor *
4*9e39c5baSBill Taylor * The contents of this file are subject to the terms of the
5*9e39c5baSBill Taylor * Common Development and Distribution License (the "License").
6*9e39c5baSBill Taylor * You may not use this file except in compliance with the License.
7*9e39c5baSBill Taylor *
8*9e39c5baSBill Taylor * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*9e39c5baSBill Taylor * or http://www.opensolaris.org/os/licensing.
10*9e39c5baSBill Taylor * See the License for the specific language governing permissions
11*9e39c5baSBill Taylor * and limitations under the License.
12*9e39c5baSBill Taylor *
13*9e39c5baSBill Taylor * When distributing Covered Code, include this CDDL HEADER in each
14*9e39c5baSBill Taylor * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*9e39c5baSBill Taylor * If applicable, add the following below this CDDL HEADER, with the
16*9e39c5baSBill Taylor * fields enclosed by brackets "[]" replaced with your own identifying
17*9e39c5baSBill Taylor * information: Portions Copyright [yyyy] [name of copyright owner]
18*9e39c5baSBill Taylor *
19*9e39c5baSBill Taylor * CDDL HEADER END
20*9e39c5baSBill Taylor */
21*9e39c5baSBill Taylor
22*9e39c5baSBill Taylor /*
23*9e39c5baSBill Taylor * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24*9e39c5baSBill Taylor * Use is subject to license terms.
25*9e39c5baSBill Taylor */
26*9e39c5baSBill Taylor
27*9e39c5baSBill Taylor /*
28*9e39c5baSBill Taylor * tavor_umap.c
29*9e39c5baSBill Taylor * Tavor Userland Mapping Routines
30*9e39c5baSBill Taylor *
31*9e39c5baSBill Taylor * Implements all the routines necessary for enabling direct userland
32*9e39c5baSBill Taylor * access to the Tavor hardware. This includes all routines necessary for
33*9e39c5baSBill Taylor * maintaining the "userland resources database" and all the support routines
34*9e39c5baSBill Taylor * for the devmap calls.
35*9e39c5baSBill Taylor */
36*9e39c5baSBill Taylor
37*9e39c5baSBill Taylor #include <sys/types.h>
38*9e39c5baSBill Taylor #include <sys/conf.h>
39*9e39c5baSBill Taylor #include <sys/ddi.h>
40*9e39c5baSBill Taylor #include <sys/sunddi.h>
41*9e39c5baSBill Taylor #include <sys/modctl.h>
42*9e39c5baSBill Taylor #include <sys/file.h>
43*9e39c5baSBill Taylor #include <sys/avl.h>
44*9e39c5baSBill Taylor #include <sys/sysmacros.h>
45*9e39c5baSBill Taylor
46*9e39c5baSBill Taylor #include <sys/ib/adapters/tavor/tavor.h>
47*9e39c5baSBill Taylor
48*9e39c5baSBill Taylor /* Tavor HCA state pointer (extern) */
49*9e39c5baSBill Taylor extern void *tavor_statep;
50*9e39c5baSBill Taylor
51*9e39c5baSBill Taylor /* Tavor HCA Userland Resource Database (extern) */
52*9e39c5baSBill Taylor extern tavor_umap_db_t tavor_userland_rsrc_db;
53*9e39c5baSBill Taylor
54*9e39c5baSBill Taylor static int tavor_umap_uarpg(tavor_state_t *state, devmap_cookie_t dhp,
55*9e39c5baSBill Taylor tavor_rsrc_t *rsrcp, size_t *maplen, int *err);
56*9e39c5baSBill Taylor static int tavor_umap_cqmem(tavor_state_t *state, devmap_cookie_t dhp,
57*9e39c5baSBill Taylor tavor_rsrc_t *rsrcp, offset_t off, size_t *maplen, int *err);
58*9e39c5baSBill Taylor static int tavor_umap_qpmem(tavor_state_t *state, devmap_cookie_t dhp,
59*9e39c5baSBill Taylor tavor_rsrc_t *rsrcp, offset_t off, size_t *maplen, int *err);
60*9e39c5baSBill Taylor static int tavor_umap_srqmem(tavor_state_t *state, devmap_cookie_t dhp,
61*9e39c5baSBill Taylor tavor_rsrc_t *rsrcp, offset_t off, size_t *maplen, int *err);
62*9e39c5baSBill Taylor static int tavor_devmap_umem_map(devmap_cookie_t dhp, dev_t dev, uint_t flags,
63*9e39c5baSBill Taylor offset_t off, size_t len, void **pvtp);
64*9e39c5baSBill Taylor static int tavor_devmap_umem_dup(devmap_cookie_t dhp, void *pvtp,
65*9e39c5baSBill Taylor devmap_cookie_t new_dhp, void **new_pvtp);
66*9e39c5baSBill Taylor static void tavor_devmap_umem_unmap(devmap_cookie_t dhp, void *pvtp,
67*9e39c5baSBill Taylor offset_t off, size_t len, devmap_cookie_t new_dhp1, void **pvtp1,
68*9e39c5baSBill Taylor devmap_cookie_t new_dhp2, void **pvtp2);
69*9e39c5baSBill Taylor static int tavor_devmap_devmem_map(devmap_cookie_t dhp, dev_t dev, uint_t flags,
70*9e39c5baSBill Taylor offset_t off, size_t len, void **pvtp);
71*9e39c5baSBill Taylor static int tavor_devmap_devmem_dup(devmap_cookie_t dhp, void *pvtp,
72*9e39c5baSBill Taylor devmap_cookie_t new_dhp, void **new_pvtp);
73*9e39c5baSBill Taylor static void tavor_devmap_devmem_unmap(devmap_cookie_t dhp, void *pvtp,
74*9e39c5baSBill Taylor offset_t off, size_t len, devmap_cookie_t new_dhp1, void **pvtp1,
75*9e39c5baSBill Taylor devmap_cookie_t new_dhp2, void **pvtp2);
76*9e39c5baSBill Taylor static ibt_status_t tavor_umap_mr_data_in(tavor_mrhdl_t mr,
77*9e39c5baSBill Taylor ibt_mr_data_in_t *data, size_t data_sz);
78*9e39c5baSBill Taylor static ibt_status_t tavor_umap_cq_data_out(tavor_cqhdl_t cq,
79*9e39c5baSBill Taylor mlnx_umap_cq_data_out_t *data, size_t data_sz);
80*9e39c5baSBill Taylor static ibt_status_t tavor_umap_qp_data_out(tavor_qphdl_t qp,
81*9e39c5baSBill Taylor mlnx_umap_qp_data_out_t *data, size_t data_sz);
82*9e39c5baSBill Taylor static ibt_status_t tavor_umap_srq_data_out(tavor_srqhdl_t srq,
83*9e39c5baSBill Taylor mlnx_umap_srq_data_out_t *data, size_t data_sz);
84*9e39c5baSBill Taylor static int tavor_umap_db_compare(const void *query, const void *entry);
85*9e39c5baSBill Taylor static ibt_status_t tavor_umap_pd_data_out(tavor_pdhdl_t pd,
86*9e39c5baSBill Taylor mlnx_umap_pd_data_out_t *data, size_t data_sz);
87*9e39c5baSBill Taylor
88*9e39c5baSBill Taylor
89*9e39c5baSBill Taylor /*
90*9e39c5baSBill Taylor * These callbacks are passed to devmap_umem_setup() and devmap_devmem_setup(),
91*9e39c5baSBill Taylor * respectively. They are used to handle (among other things) partial
92*9e39c5baSBill Taylor * unmappings and to provide a method for invalidating mappings inherited
93*9e39c5baSBill Taylor * as a result of a fork(2) system call.
94*9e39c5baSBill Taylor */
95*9e39c5baSBill Taylor static struct devmap_callback_ctl tavor_devmap_umem_cbops = {
96*9e39c5baSBill Taylor DEVMAP_OPS_REV,
97*9e39c5baSBill Taylor tavor_devmap_umem_map,
98*9e39c5baSBill Taylor NULL,
99*9e39c5baSBill Taylor tavor_devmap_umem_dup,
100*9e39c5baSBill Taylor tavor_devmap_umem_unmap
101*9e39c5baSBill Taylor };
102*9e39c5baSBill Taylor static struct devmap_callback_ctl tavor_devmap_devmem_cbops = {
103*9e39c5baSBill Taylor DEVMAP_OPS_REV,
104*9e39c5baSBill Taylor tavor_devmap_devmem_map,
105*9e39c5baSBill Taylor NULL,
106*9e39c5baSBill Taylor tavor_devmap_devmem_dup,
107*9e39c5baSBill Taylor tavor_devmap_devmem_unmap
108*9e39c5baSBill Taylor };
109*9e39c5baSBill Taylor
110*9e39c5baSBill Taylor /*
111*9e39c5baSBill Taylor * tavor_devmap()
112*9e39c5baSBill Taylor * Context: Can be called from user context.
113*9e39c5baSBill Taylor */
114*9e39c5baSBill Taylor /* ARGSUSED */
115*9e39c5baSBill Taylor int
tavor_devmap(dev_t dev,devmap_cookie_t dhp,offset_t off,size_t len,size_t * maplen,uint_t model)116*9e39c5baSBill Taylor tavor_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len,
117*9e39c5baSBill Taylor size_t *maplen, uint_t model)
118*9e39c5baSBill Taylor {
119*9e39c5baSBill Taylor tavor_state_t *state;
120*9e39c5baSBill Taylor tavor_rsrc_t *rsrcp;
121*9e39c5baSBill Taylor minor_t instance;
122*9e39c5baSBill Taylor uint64_t key, value;
123*9e39c5baSBill Taylor uint_t type;
124*9e39c5baSBill Taylor int err, status;
125*9e39c5baSBill Taylor
126*9e39c5baSBill Taylor /* Get Tavor softstate structure from instance */
127*9e39c5baSBill Taylor instance = TAVOR_DEV_INSTANCE(dev);
128*9e39c5baSBill Taylor state = ddi_get_soft_state(tavor_statep, instance);
129*9e39c5baSBill Taylor if (state == NULL) {
130*9e39c5baSBill Taylor return (ENXIO);
131*9e39c5baSBill Taylor }
132*9e39c5baSBill Taylor
133*9e39c5baSBill Taylor /*
134*9e39c5baSBill Taylor * Access to Tavor devmap interface is not allowed in
135*9e39c5baSBill Taylor * "maintenance mode".
136*9e39c5baSBill Taylor */
137*9e39c5baSBill Taylor if (state->ts_operational_mode == TAVOR_MAINTENANCE_MODE) {
138*9e39c5baSBill Taylor return (EFAULT);
139*9e39c5baSBill Taylor }
140*9e39c5baSBill Taylor
141*9e39c5baSBill Taylor /*
142*9e39c5baSBill Taylor * The bottom bits of "offset" are undefined (number depends on
143*9e39c5baSBill Taylor * system PAGESIZE). Shifting these off leaves us with a "key".
144*9e39c5baSBill Taylor * The "key" is actually a combination of both a real key value
145*9e39c5baSBill Taylor * (for the purpose of database lookup) and a "type" value. We
146*9e39c5baSBill Taylor * extract this information before doing the database lookup.
147*9e39c5baSBill Taylor */
148*9e39c5baSBill Taylor key = off >> PAGESHIFT;
149*9e39c5baSBill Taylor type = key & MLNX_UMAP_RSRC_TYPE_MASK;
150*9e39c5baSBill Taylor key = key >> MLNX_UMAP_RSRC_TYPE_SHIFT;
151*9e39c5baSBill Taylor status = tavor_umap_db_find(instance, key, type, &value, 0, NULL);
152*9e39c5baSBill Taylor if (status == DDI_SUCCESS) {
153*9e39c5baSBill Taylor rsrcp = (tavor_rsrc_t *)(uintptr_t)value;
154*9e39c5baSBill Taylor
155*9e39c5baSBill Taylor switch (type) {
156*9e39c5baSBill Taylor case MLNX_UMAP_UARPG_RSRC:
157*9e39c5baSBill Taylor /*
158*9e39c5baSBill Taylor * Double check that process who open()'d Tavor is
159*9e39c5baSBill Taylor * same process attempting to mmap() UAR page.
160*9e39c5baSBill Taylor */
161*9e39c5baSBill Taylor if (key != ddi_get_pid()) {
162*9e39c5baSBill Taylor return (EINVAL);
163*9e39c5baSBill Taylor }
164*9e39c5baSBill Taylor
165*9e39c5baSBill Taylor /* Map the UAR page out for userland access */
166*9e39c5baSBill Taylor status = tavor_umap_uarpg(state, dhp, rsrcp, maplen,
167*9e39c5baSBill Taylor &err);
168*9e39c5baSBill Taylor if (status != DDI_SUCCESS) {
169*9e39c5baSBill Taylor return (err);
170*9e39c5baSBill Taylor }
171*9e39c5baSBill Taylor break;
172*9e39c5baSBill Taylor
173*9e39c5baSBill Taylor case MLNX_UMAP_CQMEM_RSRC:
174*9e39c5baSBill Taylor /* Map the CQ memory out for userland access */
175*9e39c5baSBill Taylor status = tavor_umap_cqmem(state, dhp, rsrcp, off,
176*9e39c5baSBill Taylor maplen, &err);
177*9e39c5baSBill Taylor if (status != DDI_SUCCESS) {
178*9e39c5baSBill Taylor return (err);
179*9e39c5baSBill Taylor }
180*9e39c5baSBill Taylor break;
181*9e39c5baSBill Taylor
182*9e39c5baSBill Taylor case MLNX_UMAP_QPMEM_RSRC:
183*9e39c5baSBill Taylor /* Map the QP memory out for userland access */
184*9e39c5baSBill Taylor status = tavor_umap_qpmem(state, dhp, rsrcp, off,
185*9e39c5baSBill Taylor maplen, &err);
186*9e39c5baSBill Taylor if (status != DDI_SUCCESS) {
187*9e39c5baSBill Taylor return (err);
188*9e39c5baSBill Taylor }
189*9e39c5baSBill Taylor break;
190*9e39c5baSBill Taylor
191*9e39c5baSBill Taylor case MLNX_UMAP_SRQMEM_RSRC:
192*9e39c5baSBill Taylor /* Map the SRQ memory out for userland access */
193*9e39c5baSBill Taylor status = tavor_umap_srqmem(state, dhp, rsrcp, off,
194*9e39c5baSBill Taylor maplen, &err);
195*9e39c5baSBill Taylor if (status != DDI_SUCCESS) {
196*9e39c5baSBill Taylor return (err);
197*9e39c5baSBill Taylor }
198*9e39c5baSBill Taylor break;
199*9e39c5baSBill Taylor
200*9e39c5baSBill Taylor default:
201*9e39c5baSBill Taylor TAVOR_WARNING(state, "unexpected rsrc type in devmap");
202*9e39c5baSBill Taylor return (EINVAL);
203*9e39c5baSBill Taylor }
204*9e39c5baSBill Taylor } else {
205*9e39c5baSBill Taylor return (EINVAL);
206*9e39c5baSBill Taylor }
207*9e39c5baSBill Taylor
208*9e39c5baSBill Taylor return (0);
209*9e39c5baSBill Taylor }
210*9e39c5baSBill Taylor
211*9e39c5baSBill Taylor
212*9e39c5baSBill Taylor /*
213*9e39c5baSBill Taylor * tavor_umap_uarpg()
214*9e39c5baSBill Taylor * Context: Can be called from user context.
215*9e39c5baSBill Taylor */
216*9e39c5baSBill Taylor static int
tavor_umap_uarpg(tavor_state_t * state,devmap_cookie_t dhp,tavor_rsrc_t * rsrcp,size_t * maplen,int * err)217*9e39c5baSBill Taylor tavor_umap_uarpg(tavor_state_t *state, devmap_cookie_t dhp,
218*9e39c5baSBill Taylor tavor_rsrc_t *rsrcp, size_t *maplen, int *err)
219*9e39c5baSBill Taylor {
220*9e39c5baSBill Taylor int status;
221*9e39c5baSBill Taylor uint_t maxprot;
222*9e39c5baSBill Taylor
223*9e39c5baSBill Taylor /* Map out the UAR page (doorbell page) */
224*9e39c5baSBill Taylor maxprot = (PROT_READ | PROT_WRITE | PROT_USER);
225*9e39c5baSBill Taylor status = devmap_devmem_setup(dhp, state->ts_dip,
226*9e39c5baSBill Taylor &tavor_devmap_devmem_cbops, TAVOR_UAR_BAR, (rsrcp->tr_indx <<
227*9e39c5baSBill Taylor PAGESHIFT), PAGESIZE, maxprot, DEVMAP_ALLOW_REMAP,
228*9e39c5baSBill Taylor &state->ts_reg_accattr);
229*9e39c5baSBill Taylor if (status < 0) {
230*9e39c5baSBill Taylor *err = status;
231*9e39c5baSBill Taylor return (DDI_FAILURE);
232*9e39c5baSBill Taylor }
233*9e39c5baSBill Taylor
234*9e39c5baSBill Taylor *maplen = PAGESIZE;
235*9e39c5baSBill Taylor return (DDI_SUCCESS);
236*9e39c5baSBill Taylor }
237*9e39c5baSBill Taylor
238*9e39c5baSBill Taylor
239*9e39c5baSBill Taylor /*
240*9e39c5baSBill Taylor * tavor_umap_cqmem()
241*9e39c5baSBill Taylor * Context: Can be called from user context.
242*9e39c5baSBill Taylor */
243*9e39c5baSBill Taylor /* ARGSUSED */
244*9e39c5baSBill Taylor static int
tavor_umap_cqmem(tavor_state_t * state,devmap_cookie_t dhp,tavor_rsrc_t * rsrcp,offset_t off,size_t * maplen,int * err)245*9e39c5baSBill Taylor tavor_umap_cqmem(tavor_state_t *state, devmap_cookie_t dhp,
246*9e39c5baSBill Taylor tavor_rsrc_t *rsrcp, offset_t off, size_t *maplen, int *err)
247*9e39c5baSBill Taylor {
248*9e39c5baSBill Taylor tavor_cqhdl_t cq;
249*9e39c5baSBill Taylor size_t size;
250*9e39c5baSBill Taylor uint_t maxprot;
251*9e39c5baSBill Taylor int status;
252*9e39c5baSBill Taylor
253*9e39c5baSBill Taylor /* Extract the Tavor CQ handle pointer from the tavor_rsrc_t */
254*9e39c5baSBill Taylor cq = (tavor_cqhdl_t)rsrcp->tr_addr;
255*9e39c5baSBill Taylor
256*9e39c5baSBill Taylor /* Round-up the CQ size to system page size */
257*9e39c5baSBill Taylor size = ptob(btopr(cq->cq_cqinfo.qa_size));
258*9e39c5baSBill Taylor
259*9e39c5baSBill Taylor /* Map out the CQ memory */
260*9e39c5baSBill Taylor maxprot = (PROT_READ | PROT_WRITE | PROT_USER);
261*9e39c5baSBill Taylor status = devmap_umem_setup(dhp, state->ts_dip,
262*9e39c5baSBill Taylor &tavor_devmap_umem_cbops, cq->cq_cqinfo.qa_umemcookie, 0, size,
263*9e39c5baSBill Taylor maxprot, (DEVMAP_ALLOW_REMAP | DEVMAP_DEFAULTS), NULL);
264*9e39c5baSBill Taylor if (status < 0) {
265*9e39c5baSBill Taylor *err = status;
266*9e39c5baSBill Taylor return (DDI_FAILURE);
267*9e39c5baSBill Taylor }
268*9e39c5baSBill Taylor *maplen = size;
269*9e39c5baSBill Taylor
270*9e39c5baSBill Taylor return (DDI_SUCCESS);
271*9e39c5baSBill Taylor }
272*9e39c5baSBill Taylor
273*9e39c5baSBill Taylor
274*9e39c5baSBill Taylor /*
275*9e39c5baSBill Taylor * tavor_umap_qpmem()
276*9e39c5baSBill Taylor * Context: Can be called from user context.
277*9e39c5baSBill Taylor */
278*9e39c5baSBill Taylor /* ARGSUSED */
279*9e39c5baSBill Taylor static int
tavor_umap_qpmem(tavor_state_t * state,devmap_cookie_t dhp,tavor_rsrc_t * rsrcp,offset_t off,size_t * maplen,int * err)280*9e39c5baSBill Taylor tavor_umap_qpmem(tavor_state_t *state, devmap_cookie_t dhp,
281*9e39c5baSBill Taylor tavor_rsrc_t *rsrcp, offset_t off, size_t *maplen, int *err)
282*9e39c5baSBill Taylor {
283*9e39c5baSBill Taylor tavor_qphdl_t qp;
284*9e39c5baSBill Taylor offset_t offset;
285*9e39c5baSBill Taylor size_t size;
286*9e39c5baSBill Taylor uint_t maxprot;
287*9e39c5baSBill Taylor int status;
288*9e39c5baSBill Taylor
289*9e39c5baSBill Taylor /* Extract the Tavor QP handle pointer from the tavor_rsrc_t */
290*9e39c5baSBill Taylor qp = (tavor_qphdl_t)rsrcp->tr_addr;
291*9e39c5baSBill Taylor
292*9e39c5baSBill Taylor /*
293*9e39c5baSBill Taylor * Calculate the offset of the first work queue (send or recv) into
294*9e39c5baSBill Taylor * the memory (ddi_umem_alloc()) allocated previously for the QP.
295*9e39c5baSBill Taylor */
296*9e39c5baSBill Taylor offset = (offset_t)((uintptr_t)qp->qp_wqinfo.qa_buf_aligned -
297*9e39c5baSBill Taylor (uintptr_t)qp->qp_wqinfo.qa_buf_real);
298*9e39c5baSBill Taylor
299*9e39c5baSBill Taylor /* Round-up the QP work queue sizes to system page size */
300*9e39c5baSBill Taylor size = ptob(btopr(qp->qp_wqinfo.qa_size));
301*9e39c5baSBill Taylor
302*9e39c5baSBill Taylor /* Map out the QP memory */
303*9e39c5baSBill Taylor maxprot = (PROT_READ | PROT_WRITE | PROT_USER);
304*9e39c5baSBill Taylor status = devmap_umem_setup(dhp, state->ts_dip,
305*9e39c5baSBill Taylor &tavor_devmap_umem_cbops, qp->qp_wqinfo.qa_umemcookie, offset,
306*9e39c5baSBill Taylor size, maxprot, (DEVMAP_ALLOW_REMAP | DEVMAP_DEFAULTS), NULL);
307*9e39c5baSBill Taylor if (status < 0) {
308*9e39c5baSBill Taylor *err = status;
309*9e39c5baSBill Taylor return (DDI_FAILURE);
310*9e39c5baSBill Taylor }
311*9e39c5baSBill Taylor *maplen = size;
312*9e39c5baSBill Taylor
313*9e39c5baSBill Taylor return (DDI_SUCCESS);
314*9e39c5baSBill Taylor }
315*9e39c5baSBill Taylor
316*9e39c5baSBill Taylor
317*9e39c5baSBill Taylor /*
318*9e39c5baSBill Taylor * tavor_umap_srqmem()
319*9e39c5baSBill Taylor * Context: Can be called from user context.
320*9e39c5baSBill Taylor */
321*9e39c5baSBill Taylor /* ARGSUSED */
322*9e39c5baSBill Taylor static int
tavor_umap_srqmem(tavor_state_t * state,devmap_cookie_t dhp,tavor_rsrc_t * rsrcp,offset_t off,size_t * maplen,int * err)323*9e39c5baSBill Taylor tavor_umap_srqmem(tavor_state_t *state, devmap_cookie_t dhp,
324*9e39c5baSBill Taylor tavor_rsrc_t *rsrcp, offset_t off, size_t *maplen, int *err)
325*9e39c5baSBill Taylor {
326*9e39c5baSBill Taylor tavor_srqhdl_t srq;
327*9e39c5baSBill Taylor offset_t offset;
328*9e39c5baSBill Taylor size_t size;
329*9e39c5baSBill Taylor uint_t maxprot;
330*9e39c5baSBill Taylor int status;
331*9e39c5baSBill Taylor
332*9e39c5baSBill Taylor /* Extract the Tavor SRQ handle pointer from the tavor_rsrc_t */
333*9e39c5baSBill Taylor srq = (tavor_srqhdl_t)rsrcp->tr_addr;
334*9e39c5baSBill Taylor
335*9e39c5baSBill Taylor /*
336*9e39c5baSBill Taylor * Calculate the offset of the first shared recv queue into the memory
337*9e39c5baSBill Taylor * (ddi_umem_alloc()) allocated previously for the SRQ.
338*9e39c5baSBill Taylor */
339*9e39c5baSBill Taylor offset = (offset_t)((uintptr_t)srq->srq_wqinfo.qa_buf_aligned -
340*9e39c5baSBill Taylor (uintptr_t)srq->srq_wqinfo.qa_buf_real);
341*9e39c5baSBill Taylor
342*9e39c5baSBill Taylor /* Round-up the SRQ work queue sizes to system page size */
343*9e39c5baSBill Taylor size = ptob(btopr(srq->srq_wqinfo.qa_size));
344*9e39c5baSBill Taylor
345*9e39c5baSBill Taylor /* Map out the QP memory */
346*9e39c5baSBill Taylor maxprot = (PROT_READ | PROT_WRITE | PROT_USER);
347*9e39c5baSBill Taylor status = devmap_umem_setup(dhp, state->ts_dip,
348*9e39c5baSBill Taylor &tavor_devmap_umem_cbops, srq->srq_wqinfo.qa_umemcookie, offset,
349*9e39c5baSBill Taylor size, maxprot, (DEVMAP_ALLOW_REMAP | DEVMAP_DEFAULTS), NULL);
350*9e39c5baSBill Taylor if (status < 0) {
351*9e39c5baSBill Taylor *err = status;
352*9e39c5baSBill Taylor return (DDI_FAILURE);
353*9e39c5baSBill Taylor }
354*9e39c5baSBill Taylor *maplen = size;
355*9e39c5baSBill Taylor
356*9e39c5baSBill Taylor return (DDI_SUCCESS);
357*9e39c5baSBill Taylor }
358*9e39c5baSBill Taylor
359*9e39c5baSBill Taylor
360*9e39c5baSBill Taylor /*
361*9e39c5baSBill Taylor * tavor_devmap_umem_map()
362*9e39c5baSBill Taylor * Context: Can be called from kernel context.
363*9e39c5baSBill Taylor */
364*9e39c5baSBill Taylor /* ARGSUSED */
365*9e39c5baSBill Taylor static int
tavor_devmap_umem_map(devmap_cookie_t dhp,dev_t dev,uint_t flags,offset_t off,size_t len,void ** pvtp)366*9e39c5baSBill Taylor tavor_devmap_umem_map(devmap_cookie_t dhp, dev_t dev, uint_t flags,
367*9e39c5baSBill Taylor offset_t off, size_t len, void **pvtp)
368*9e39c5baSBill Taylor {
369*9e39c5baSBill Taylor tavor_state_t *state;
370*9e39c5baSBill Taylor tavor_devmap_track_t *dvm_track;
371*9e39c5baSBill Taylor tavor_cqhdl_t cq;
372*9e39c5baSBill Taylor tavor_qphdl_t qp;
373*9e39c5baSBill Taylor tavor_srqhdl_t srq;
374*9e39c5baSBill Taylor minor_t instance;
375*9e39c5baSBill Taylor uint64_t key;
376*9e39c5baSBill Taylor uint_t type;
377*9e39c5baSBill Taylor
378*9e39c5baSBill Taylor /* Get Tavor softstate structure from instance */
379*9e39c5baSBill Taylor instance = TAVOR_DEV_INSTANCE(dev);
380*9e39c5baSBill Taylor state = ddi_get_soft_state(tavor_statep, instance);
381*9e39c5baSBill Taylor if (state == NULL) {
382*9e39c5baSBill Taylor return (ENXIO);
383*9e39c5baSBill Taylor }
384*9e39c5baSBill Taylor
385*9e39c5baSBill Taylor /*
386*9e39c5baSBill Taylor * The bottom bits of "offset" are undefined (number depends on
387*9e39c5baSBill Taylor * system PAGESIZE). Shifting these off leaves us with a "key".
388*9e39c5baSBill Taylor * The "key" is actually a combination of both a real key value
389*9e39c5baSBill Taylor * (for the purpose of database lookup) and a "type" value. Although
390*9e39c5baSBill Taylor * we are not going to do any database lookup per se, we do want
391*9e39c5baSBill Taylor * to extract the "key" and the "type" (to enable faster lookup of
392*9e39c5baSBill Taylor * the appropriate CQ or QP handle).
393*9e39c5baSBill Taylor */
394*9e39c5baSBill Taylor key = off >> PAGESHIFT;
395*9e39c5baSBill Taylor type = key & MLNX_UMAP_RSRC_TYPE_MASK;
396*9e39c5baSBill Taylor key = key >> MLNX_UMAP_RSRC_TYPE_SHIFT;
397*9e39c5baSBill Taylor
398*9e39c5baSBill Taylor /*
399*9e39c5baSBill Taylor * Allocate an entry to track the mapping and unmapping (specifically,
400*9e39c5baSBill Taylor * partial unmapping) of this resource.
401*9e39c5baSBill Taylor */
402*9e39c5baSBill Taylor dvm_track = (tavor_devmap_track_t *)kmem_zalloc(
403*9e39c5baSBill Taylor sizeof (tavor_devmap_track_t), KM_SLEEP);
404*9e39c5baSBill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dvm_track))
405*9e39c5baSBill Taylor dvm_track->tdt_offset = off;
406*9e39c5baSBill Taylor dvm_track->tdt_state = state;
407*9e39c5baSBill Taylor dvm_track->tdt_refcnt = 1;
408*9e39c5baSBill Taylor mutex_init(&dvm_track->tdt_lock, NULL, MUTEX_DRIVER,
409*9e39c5baSBill Taylor DDI_INTR_PRI(state->ts_intrmsi_pri));
410*9e39c5baSBill Taylor
411*9e39c5baSBill Taylor /*
412*9e39c5baSBill Taylor * Depending of the type of resource that has been mapped out, we
413*9e39c5baSBill Taylor * need to update the QP or CQ handle to reflect that it has, in
414*9e39c5baSBill Taylor * fact, been mapped. This allows the driver code which frees a QP
415*9e39c5baSBill Taylor * or a CQ to know whether it is appropriate to do a
416*9e39c5baSBill Taylor * devmap_devmem_remap() to invalidate the userland mapping for the
417*9e39c5baSBill Taylor * corresponding queue's memory.
418*9e39c5baSBill Taylor */
419*9e39c5baSBill Taylor if (type == MLNX_UMAP_CQMEM_RSRC) {
420*9e39c5baSBill Taylor
421*9e39c5baSBill Taylor /* Use "key" (CQ number) to do fast lookup of CQ handle */
422*9e39c5baSBill Taylor cq = tavor_cqhdl_from_cqnum(state, key);
423*9e39c5baSBill Taylor
424*9e39c5baSBill Taylor /*
425*9e39c5baSBill Taylor * Update the handle to the userland mapping. Note: If
426*9e39c5baSBill Taylor * the CQ already has a valid userland mapping, then stop
427*9e39c5baSBill Taylor * and return failure.
428*9e39c5baSBill Taylor */
429*9e39c5baSBill Taylor mutex_enter(&cq->cq_lock);
430*9e39c5baSBill Taylor if (cq->cq_umap_dhp == NULL) {
431*9e39c5baSBill Taylor cq->cq_umap_dhp = dhp;
432*9e39c5baSBill Taylor dvm_track->tdt_size = cq->cq_cqinfo.qa_size;
433*9e39c5baSBill Taylor mutex_exit(&cq->cq_lock);
434*9e39c5baSBill Taylor } else {
435*9e39c5baSBill Taylor mutex_exit(&cq->cq_lock);
436*9e39c5baSBill Taylor goto umem_map_fail;
437*9e39c5baSBill Taylor }
438*9e39c5baSBill Taylor
439*9e39c5baSBill Taylor } else if (type == MLNX_UMAP_QPMEM_RSRC) {
440*9e39c5baSBill Taylor
441*9e39c5baSBill Taylor /* Use "key" (QP number) to do fast lookup of QP handle */
442*9e39c5baSBill Taylor qp = tavor_qphdl_from_qpnum(state, key);
443*9e39c5baSBill Taylor
444*9e39c5baSBill Taylor /*
445*9e39c5baSBill Taylor * Update the handle to the userland mapping. Note: If
446*9e39c5baSBill Taylor * the CQ already has a valid userland mapping, then stop
447*9e39c5baSBill Taylor * and return failure.
448*9e39c5baSBill Taylor */
449*9e39c5baSBill Taylor mutex_enter(&qp->qp_lock);
450*9e39c5baSBill Taylor if (qp->qp_umap_dhp == NULL) {
451*9e39c5baSBill Taylor qp->qp_umap_dhp = dhp;
452*9e39c5baSBill Taylor dvm_track->tdt_size = qp->qp_wqinfo.qa_size;
453*9e39c5baSBill Taylor mutex_exit(&qp->qp_lock);
454*9e39c5baSBill Taylor } else {
455*9e39c5baSBill Taylor mutex_exit(&qp->qp_lock);
456*9e39c5baSBill Taylor goto umem_map_fail;
457*9e39c5baSBill Taylor }
458*9e39c5baSBill Taylor
459*9e39c5baSBill Taylor } else if (type == MLNX_UMAP_SRQMEM_RSRC) {
460*9e39c5baSBill Taylor
461*9e39c5baSBill Taylor /* Use "key" (SRQ number) to do fast lookup on SRQ handle */
462*9e39c5baSBill Taylor srq = tavor_srqhdl_from_srqnum(state, key);
463*9e39c5baSBill Taylor
464*9e39c5baSBill Taylor /*
465*9e39c5baSBill Taylor * Update the handle to the userland mapping. Note: If the
466*9e39c5baSBill Taylor * SRQ already has a valid userland mapping, then stop and
467*9e39c5baSBill Taylor * return failure.
468*9e39c5baSBill Taylor */
469*9e39c5baSBill Taylor mutex_enter(&srq->srq_lock);
470*9e39c5baSBill Taylor if (srq->srq_umap_dhp == NULL) {
471*9e39c5baSBill Taylor srq->srq_umap_dhp = dhp;
472*9e39c5baSBill Taylor dvm_track->tdt_size = srq->srq_wqinfo.qa_size;
473*9e39c5baSBill Taylor mutex_exit(&srq->srq_lock);
474*9e39c5baSBill Taylor } else {
475*9e39c5baSBill Taylor mutex_exit(&srq->srq_lock);
476*9e39c5baSBill Taylor goto umem_map_fail;
477*9e39c5baSBill Taylor }
478*9e39c5baSBill Taylor }
479*9e39c5baSBill Taylor
480*9e39c5baSBill Taylor /*
481*9e39c5baSBill Taylor * Pass the private "Tavor devmap tracking structure" back. This
482*9e39c5baSBill Taylor * pointer will be returned in subsequent "unmap" callbacks.
483*9e39c5baSBill Taylor */
484*9e39c5baSBill Taylor *pvtp = dvm_track;
485*9e39c5baSBill Taylor
486*9e39c5baSBill Taylor return (DDI_SUCCESS);
487*9e39c5baSBill Taylor
488*9e39c5baSBill Taylor umem_map_fail:
489*9e39c5baSBill Taylor mutex_destroy(&dvm_track->tdt_lock);
490*9e39c5baSBill Taylor kmem_free(dvm_track, sizeof (tavor_devmap_track_t));
491*9e39c5baSBill Taylor return (DDI_FAILURE);
492*9e39c5baSBill Taylor }
493*9e39c5baSBill Taylor
494*9e39c5baSBill Taylor
495*9e39c5baSBill Taylor /*
496*9e39c5baSBill Taylor * tavor_devmap_umem_dup()
497*9e39c5baSBill Taylor * Context: Can be called from kernel context.
498*9e39c5baSBill Taylor */
499*9e39c5baSBill Taylor /* ARGSUSED */
500*9e39c5baSBill Taylor static int
tavor_devmap_umem_dup(devmap_cookie_t dhp,void * pvtp,devmap_cookie_t new_dhp,void ** new_pvtp)501*9e39c5baSBill Taylor tavor_devmap_umem_dup(devmap_cookie_t dhp, void *pvtp, devmap_cookie_t new_dhp,
502*9e39c5baSBill Taylor void **new_pvtp)
503*9e39c5baSBill Taylor {
504*9e39c5baSBill Taylor tavor_state_t *state;
505*9e39c5baSBill Taylor tavor_devmap_track_t *dvm_track, *new_dvm_track;
506*9e39c5baSBill Taylor uint_t maxprot;
507*9e39c5baSBill Taylor int status;
508*9e39c5baSBill Taylor
509*9e39c5baSBill Taylor /*
510*9e39c5baSBill Taylor * Extract the Tavor softstate pointer from "Tavor devmap tracking
511*9e39c5baSBill Taylor * structure" (in "pvtp").
512*9e39c5baSBill Taylor */
513*9e39c5baSBill Taylor dvm_track = (tavor_devmap_track_t *)pvtp;
514*9e39c5baSBill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dvm_track))
515*9e39c5baSBill Taylor state = dvm_track->tdt_state;
516*9e39c5baSBill Taylor
517*9e39c5baSBill Taylor /*
518*9e39c5baSBill Taylor * Since this devmap_dup() entry point is generally called
519*9e39c5baSBill Taylor * when a process does fork(2), it is incumbent upon the driver
520*9e39c5baSBill Taylor * to insure that the child does not inherit a valid copy of
521*9e39c5baSBill Taylor * the parent's QP or CQ resource. This is accomplished by using
522*9e39c5baSBill Taylor * devmap_devmem_remap() to invalidate the child's mapping to the
523*9e39c5baSBill Taylor * kernel memory.
524*9e39c5baSBill Taylor */
525*9e39c5baSBill Taylor maxprot = (PROT_READ | PROT_WRITE | PROT_USER);
526*9e39c5baSBill Taylor status = devmap_devmem_remap(new_dhp, state->ts_dip, 0, 0,
527*9e39c5baSBill Taylor dvm_track->tdt_size, maxprot, DEVMAP_MAPPING_INVALID, NULL);
528*9e39c5baSBill Taylor if (status != DDI_SUCCESS) {
529*9e39c5baSBill Taylor TAVOR_WARNING(state, "failed in tavor_devmap_umem_dup()");
530*9e39c5baSBill Taylor return (status);
531*9e39c5baSBill Taylor }
532*9e39c5baSBill Taylor
533*9e39c5baSBill Taylor /*
534*9e39c5baSBill Taylor * Allocate a new entry to track the subsequent unmapping
535*9e39c5baSBill Taylor * (specifically, all partial unmappings) of the child's newly
536*9e39c5baSBill Taylor * invalidated resource. Note: Setting the "tdt_size" field to
537*9e39c5baSBill Taylor * zero here is an indication to the devmap_unmap() entry point
538*9e39c5baSBill Taylor * that this mapping is invalid, and that its subsequent unmapping
539*9e39c5baSBill Taylor * should not affect any of the parent's CQ or QP resources.
540*9e39c5baSBill Taylor */
541*9e39c5baSBill Taylor new_dvm_track = (tavor_devmap_track_t *)kmem_zalloc(
542*9e39c5baSBill Taylor sizeof (tavor_devmap_track_t), KM_SLEEP);
543*9e39c5baSBill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*new_dvm_track))
544*9e39c5baSBill Taylor new_dvm_track->tdt_offset = 0;
545*9e39c5baSBill Taylor new_dvm_track->tdt_state = state;
546*9e39c5baSBill Taylor new_dvm_track->tdt_refcnt = 1;
547*9e39c5baSBill Taylor new_dvm_track->tdt_size = 0;
548*9e39c5baSBill Taylor mutex_init(&new_dvm_track->tdt_lock, NULL, MUTEX_DRIVER,
549*9e39c5baSBill Taylor DDI_INTR_PRI(state->ts_intrmsi_pri));
550*9e39c5baSBill Taylor *new_pvtp = new_dvm_track;
551*9e39c5baSBill Taylor
552*9e39c5baSBill Taylor return (DDI_SUCCESS);
553*9e39c5baSBill Taylor }
554*9e39c5baSBill Taylor
555*9e39c5baSBill Taylor
556*9e39c5baSBill Taylor /*
557*9e39c5baSBill Taylor * tavor_devmap_umem_unmap()
558*9e39c5baSBill Taylor * Context: Can be called from kernel context.
559*9e39c5baSBill Taylor */
560*9e39c5baSBill Taylor /* ARGSUSED */
561*9e39c5baSBill Taylor static void
tavor_devmap_umem_unmap(devmap_cookie_t dhp,void * pvtp,offset_t off,size_t len,devmap_cookie_t new_dhp1,void ** pvtp1,devmap_cookie_t new_dhp2,void ** pvtp2)562*9e39c5baSBill Taylor tavor_devmap_umem_unmap(devmap_cookie_t dhp, void *pvtp, offset_t off,
563*9e39c5baSBill Taylor size_t len, devmap_cookie_t new_dhp1, void **pvtp1,
564*9e39c5baSBill Taylor devmap_cookie_t new_dhp2, void **pvtp2)
565*9e39c5baSBill Taylor {
566*9e39c5baSBill Taylor tavor_state_t *state;
567*9e39c5baSBill Taylor tavor_rsrc_t *rsrcp;
568*9e39c5baSBill Taylor tavor_devmap_track_t *dvm_track;
569*9e39c5baSBill Taylor tavor_cqhdl_t cq;
570*9e39c5baSBill Taylor tavor_qphdl_t qp;
571*9e39c5baSBill Taylor tavor_srqhdl_t srq;
572*9e39c5baSBill Taylor uint64_t key, value;
573*9e39c5baSBill Taylor uint_t type;
574*9e39c5baSBill Taylor uint_t size;
575*9e39c5baSBill Taylor int status;
576*9e39c5baSBill Taylor
577*9e39c5baSBill Taylor /*
578*9e39c5baSBill Taylor * Extract the Tavor softstate pointer from "Tavor devmap tracking
579*9e39c5baSBill Taylor * structure" (in "pvtp").
580*9e39c5baSBill Taylor */
581*9e39c5baSBill Taylor dvm_track = (tavor_devmap_track_t *)pvtp;
582*9e39c5baSBill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dvm_track))
583*9e39c5baSBill Taylor state = dvm_track->tdt_state;
584*9e39c5baSBill Taylor
585*9e39c5baSBill Taylor /*
586*9e39c5baSBill Taylor * Extract the "offset" from the "Tavor devmap tracking structure".
587*9e39c5baSBill Taylor * Note: The input argument "off" is ignored here because the
588*9e39c5baSBill Taylor * Tavor mapping interfaces define a very specific meaning to
589*9e39c5baSBill Taylor * each "logical offset". Also extract the "key" and "type" encoded
590*9e39c5baSBill Taylor * in the logical offset.
591*9e39c5baSBill Taylor */
592*9e39c5baSBill Taylor key = dvm_track->tdt_offset >> PAGESHIFT;
593*9e39c5baSBill Taylor type = key & MLNX_UMAP_RSRC_TYPE_MASK;
594*9e39c5baSBill Taylor key = key >> MLNX_UMAP_RSRC_TYPE_SHIFT;
595*9e39c5baSBill Taylor
596*9e39c5baSBill Taylor /*
597*9e39c5baSBill Taylor * Extract the "size" of the mapping. If this size is determined
598*9e39c5baSBill Taylor * to be zero, then it is an indication of a previously invalidated
599*9e39c5baSBill Taylor * mapping, and no CQ or QP resources should be affected.
600*9e39c5baSBill Taylor */
601*9e39c5baSBill Taylor size = dvm_track->tdt_size;
602*9e39c5baSBill Taylor
603*9e39c5baSBill Taylor /*
604*9e39c5baSBill Taylor * If only the "middle portion of a given mapping is being unmapped,
605*9e39c5baSBill Taylor * then we are effectively creating one new piece of mapped memory.
606*9e39c5baSBill Taylor * (Original region is divided into three pieces of which the middle
607*9e39c5baSBill Taylor * piece is being removed. This leaves two pieces. Since we started
608*9e39c5baSBill Taylor * with one piece and now have two pieces, we need to increment the
609*9e39c5baSBill Taylor * counter in the "Tavor devmap tracking structure".
610*9e39c5baSBill Taylor *
611*9e39c5baSBill Taylor * If, however, the whole mapped region is being unmapped, then we
612*9e39c5baSBill Taylor * have started with one region which we are completely removing.
613*9e39c5baSBill Taylor * In this case, we need to decrement the counter in the "Tavor
614*9e39c5baSBill Taylor * devmap tracking structure".
615*9e39c5baSBill Taylor *
616*9e39c5baSBill Taylor * In each of the remaining cases, we will have started with one
617*9e39c5baSBill Taylor * mapped region and ended with one (different) region. So no counter
618*9e39c5baSBill Taylor * modification is necessary.
619*9e39c5baSBill Taylor */
620*9e39c5baSBill Taylor mutex_enter(&dvm_track->tdt_lock);
621*9e39c5baSBill Taylor if ((new_dhp1 == NULL) && (new_dhp2 == NULL)) {
622*9e39c5baSBill Taylor dvm_track->tdt_refcnt--;
623*9e39c5baSBill Taylor } else if ((new_dhp1 != NULL) && (new_dhp2 != NULL)) {
624*9e39c5baSBill Taylor dvm_track->tdt_refcnt++;
625*9e39c5baSBill Taylor }
626*9e39c5baSBill Taylor mutex_exit(&dvm_track->tdt_lock);
627*9e39c5baSBill Taylor
628*9e39c5baSBill Taylor /*
629*9e39c5baSBill Taylor * For each of the cases where the region is being divided, then we
630*9e39c5baSBill Taylor * need to pass back the "Tavor devmap tracking structure". This way
631*9e39c5baSBill Taylor * we get it back when each of the remaining pieces is subsequently
632*9e39c5baSBill Taylor * unmapped.
633*9e39c5baSBill Taylor */
634*9e39c5baSBill Taylor if (new_dhp1 != NULL) {
635*9e39c5baSBill Taylor *pvtp1 = pvtp;
636*9e39c5baSBill Taylor }
637*9e39c5baSBill Taylor if (new_dhp2 != NULL) {
638*9e39c5baSBill Taylor *pvtp2 = pvtp;
639*9e39c5baSBill Taylor }
640*9e39c5baSBill Taylor
641*9e39c5baSBill Taylor /*
642*9e39c5baSBill Taylor * If the "Tavor devmap tracking structure" is no longer being
643*9e39c5baSBill Taylor * referenced, then free it up. Otherwise, return.
644*9e39c5baSBill Taylor */
645*9e39c5baSBill Taylor if (dvm_track->tdt_refcnt == 0) {
646*9e39c5baSBill Taylor mutex_destroy(&dvm_track->tdt_lock);
647*9e39c5baSBill Taylor kmem_free(dvm_track, sizeof (tavor_devmap_track_t));
648*9e39c5baSBill Taylor
649*9e39c5baSBill Taylor /*
650*9e39c5baSBill Taylor * If the mapping was invalid (see explanation above), then
651*9e39c5baSBill Taylor * no further processing is necessary.
652*9e39c5baSBill Taylor */
653*9e39c5baSBill Taylor if (size == 0) {
654*9e39c5baSBill Taylor return;
655*9e39c5baSBill Taylor }
656*9e39c5baSBill Taylor } else {
657*9e39c5baSBill Taylor return;
658*9e39c5baSBill Taylor }
659*9e39c5baSBill Taylor
660*9e39c5baSBill Taylor /*
661*9e39c5baSBill Taylor * Now that we can guarantee that the user memory is fully unmapped,
662*9e39c5baSBill Taylor * we can use the "key" and "type" values to try to find the entry
663*9e39c5baSBill Taylor * in the "userland resources database". If it's found, then it
664*9e39c5baSBill Taylor * indicates that the queue memory (CQ or QP) has not yet been freed.
665*9e39c5baSBill Taylor * In this case, we update the corresponding CQ or QP handle to
666*9e39c5baSBill Taylor * indicate that the "devmap_devmem_remap()" call will be unnecessary.
667*9e39c5baSBill Taylor * If it's _not_ found, then it indicates that the CQ or QP memory
668*9e39c5baSBill Taylor * was, in fact, freed before it was unmapped (thus requiring a
669*9e39c5baSBill Taylor * previous invalidation by remapping - which will already have
670*9e39c5baSBill Taylor * been done in the free routine).
671*9e39c5baSBill Taylor */
672*9e39c5baSBill Taylor status = tavor_umap_db_find(state->ts_instance, key, type, &value,
673*9e39c5baSBill Taylor 0, NULL);
674*9e39c5baSBill Taylor if (status == DDI_SUCCESS) {
675*9e39c5baSBill Taylor /*
676*9e39c5baSBill Taylor * Depending on the type of the mapped resource (CQ or QP),
677*9e39c5baSBill Taylor * update handle to indicate that no invalidation remapping
678*9e39c5baSBill Taylor * will be necessary.
679*9e39c5baSBill Taylor */
680*9e39c5baSBill Taylor if (type == MLNX_UMAP_CQMEM_RSRC) {
681*9e39c5baSBill Taylor
682*9e39c5baSBill Taylor /* Use "value" to convert to CQ handle */
683*9e39c5baSBill Taylor rsrcp = (tavor_rsrc_t *)(uintptr_t)value;
684*9e39c5baSBill Taylor cq = (tavor_cqhdl_t)rsrcp->tr_addr;
685*9e39c5baSBill Taylor
686*9e39c5baSBill Taylor /*
687*9e39c5baSBill Taylor * Invalidate the handle to the userland mapping.
688*9e39c5baSBill Taylor * Note: We must ensure that the mapping being
689*9e39c5baSBill Taylor * unmapped here is the current one for the CQ. It
690*9e39c5baSBill Taylor * is possible that it might not be if this CQ has
691*9e39c5baSBill Taylor * been resized and the previous CQ memory has not
692*9e39c5baSBill Taylor * yet been unmapped. But in that case, because of
693*9e39c5baSBill Taylor * the devmap_devmem_remap(), there is no longer any
694*9e39c5baSBill Taylor * association between the mapping and the real CQ
695*9e39c5baSBill Taylor * kernel memory.
696*9e39c5baSBill Taylor */
697*9e39c5baSBill Taylor mutex_enter(&cq->cq_lock);
698*9e39c5baSBill Taylor if (cq->cq_umap_dhp == dhp) {
699*9e39c5baSBill Taylor cq->cq_umap_dhp = (devmap_cookie_t)NULL;
700*9e39c5baSBill Taylor }
701*9e39c5baSBill Taylor mutex_exit(&cq->cq_lock);
702*9e39c5baSBill Taylor
703*9e39c5baSBill Taylor } else if (type == MLNX_UMAP_QPMEM_RSRC) {
704*9e39c5baSBill Taylor
705*9e39c5baSBill Taylor /* Use "value" to convert to QP handle */
706*9e39c5baSBill Taylor rsrcp = (tavor_rsrc_t *)(uintptr_t)value;
707*9e39c5baSBill Taylor qp = (tavor_qphdl_t)rsrcp->tr_addr;
708*9e39c5baSBill Taylor
709*9e39c5baSBill Taylor /*
710*9e39c5baSBill Taylor * Invalidate the handle to the userland mapping.
711*9e39c5baSBill Taylor * Note: we ensure that the mapping being unmapped
712*9e39c5baSBill Taylor * here is the current one for the QP. This is
713*9e39c5baSBill Taylor * more of a sanity check here since, unlike CQs
714*9e39c5baSBill Taylor * (above) we do not support resize of QPs.
715*9e39c5baSBill Taylor */
716*9e39c5baSBill Taylor mutex_enter(&qp->qp_lock);
717*9e39c5baSBill Taylor if (qp->qp_umap_dhp == dhp) {
718*9e39c5baSBill Taylor qp->qp_umap_dhp = (devmap_cookie_t)NULL;
719*9e39c5baSBill Taylor }
720*9e39c5baSBill Taylor mutex_exit(&qp->qp_lock);
721*9e39c5baSBill Taylor
722*9e39c5baSBill Taylor } else if (type == MLNX_UMAP_SRQMEM_RSRC) {
723*9e39c5baSBill Taylor
724*9e39c5baSBill Taylor /* Use "value" to convert to SRQ handle */
725*9e39c5baSBill Taylor rsrcp = (tavor_rsrc_t *)(uintptr_t)value;
726*9e39c5baSBill Taylor srq = (tavor_srqhdl_t)rsrcp->tr_addr;
727*9e39c5baSBill Taylor
728*9e39c5baSBill Taylor /*
729*9e39c5baSBill Taylor * Invalidate the handle to the userland mapping.
730*9e39c5baSBill Taylor * Note: we ensure that the mapping being unmapped
731*9e39c5baSBill Taylor * here is the current one for the QP. This is
732*9e39c5baSBill Taylor * more of a sanity check here since, unlike CQs
733*9e39c5baSBill Taylor * (above) we do not support resize of QPs.
734*9e39c5baSBill Taylor */
735*9e39c5baSBill Taylor mutex_enter(&srq->srq_lock);
736*9e39c5baSBill Taylor if (srq->srq_umap_dhp == dhp) {
737*9e39c5baSBill Taylor srq->srq_umap_dhp = (devmap_cookie_t)NULL;
738*9e39c5baSBill Taylor }
739*9e39c5baSBill Taylor mutex_exit(&srq->srq_lock);
740*9e39c5baSBill Taylor }
741*9e39c5baSBill Taylor }
742*9e39c5baSBill Taylor }
743*9e39c5baSBill Taylor
744*9e39c5baSBill Taylor
745*9e39c5baSBill Taylor /*
746*9e39c5baSBill Taylor * tavor_devmap_devmem_map()
747*9e39c5baSBill Taylor * Context: Can be called from kernel context.
748*9e39c5baSBill Taylor */
749*9e39c5baSBill Taylor /* ARGSUSED */
750*9e39c5baSBill Taylor static int
tavor_devmap_devmem_map(devmap_cookie_t dhp,dev_t dev,uint_t flags,offset_t off,size_t len,void ** pvtp)751*9e39c5baSBill Taylor tavor_devmap_devmem_map(devmap_cookie_t dhp, dev_t dev, uint_t flags,
752*9e39c5baSBill Taylor offset_t off, size_t len, void **pvtp)
753*9e39c5baSBill Taylor {
754*9e39c5baSBill Taylor tavor_state_t *state;
755*9e39c5baSBill Taylor tavor_devmap_track_t *dvm_track;
756*9e39c5baSBill Taylor minor_t instance;
757*9e39c5baSBill Taylor
758*9e39c5baSBill Taylor /* Get Tavor softstate structure from instance */
759*9e39c5baSBill Taylor instance = TAVOR_DEV_INSTANCE(dev);
760*9e39c5baSBill Taylor state = ddi_get_soft_state(tavor_statep, instance);
761*9e39c5baSBill Taylor if (state == NULL) {
762*9e39c5baSBill Taylor return (ENXIO);
763*9e39c5baSBill Taylor }
764*9e39c5baSBill Taylor
765*9e39c5baSBill Taylor /*
766*9e39c5baSBill Taylor * Allocate an entry to track the mapping and unmapping of this
767*9e39c5baSBill Taylor * resource. Note: We don't need to initialize the "refcnt" or
768*9e39c5baSBill Taylor * "offset" fields here, nor do we need to initialize the mutex
769*9e39c5baSBill Taylor * used with the "refcnt". Since UAR pages are single pages, they
770*9e39c5baSBill Taylor * are not subject to "partial" unmappings. This makes these other
771*9e39c5baSBill Taylor * fields unnecessary.
772*9e39c5baSBill Taylor */
773*9e39c5baSBill Taylor dvm_track = (tavor_devmap_track_t *)kmem_zalloc(
774*9e39c5baSBill Taylor sizeof (tavor_devmap_track_t), KM_SLEEP);
775*9e39c5baSBill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dvm_track))
776*9e39c5baSBill Taylor dvm_track->tdt_state = state;
777*9e39c5baSBill Taylor dvm_track->tdt_size = PAGESIZE;
778*9e39c5baSBill Taylor
779*9e39c5baSBill Taylor /*
780*9e39c5baSBill Taylor * Pass the private "Tavor devmap tracking structure" back. This
781*9e39c5baSBill Taylor * pointer will be returned in a subsequent "unmap" callback.
782*9e39c5baSBill Taylor */
783*9e39c5baSBill Taylor *pvtp = dvm_track;
784*9e39c5baSBill Taylor
785*9e39c5baSBill Taylor return (DDI_SUCCESS);
786*9e39c5baSBill Taylor }
787*9e39c5baSBill Taylor
788*9e39c5baSBill Taylor
789*9e39c5baSBill Taylor /*
790*9e39c5baSBill Taylor * tavor_devmap_devmem_dup()
791*9e39c5baSBill Taylor * Context: Can be called from kernel context.
792*9e39c5baSBill Taylor */
793*9e39c5baSBill Taylor /* ARGSUSED */
794*9e39c5baSBill Taylor static int
tavor_devmap_devmem_dup(devmap_cookie_t dhp,void * pvtp,devmap_cookie_t new_dhp,void ** new_pvtp)795*9e39c5baSBill Taylor tavor_devmap_devmem_dup(devmap_cookie_t dhp, void *pvtp,
796*9e39c5baSBill Taylor devmap_cookie_t new_dhp, void **new_pvtp)
797*9e39c5baSBill Taylor {
798*9e39c5baSBill Taylor tavor_state_t *state;
799*9e39c5baSBill Taylor tavor_devmap_track_t *dvm_track;
800*9e39c5baSBill Taylor uint_t maxprot;
801*9e39c5baSBill Taylor int status;
802*9e39c5baSBill Taylor
803*9e39c5baSBill Taylor /*
804*9e39c5baSBill Taylor * Extract the Tavor softstate pointer from "Tavor devmap tracking
805*9e39c5baSBill Taylor * structure" (in "pvtp"). Note: If the tracking structure is NULL
806*9e39c5baSBill Taylor * here, it means that the mapping corresponds to an invalid mapping.
807*9e39c5baSBill Taylor * In this case, it can be safely ignored ("new_pvtp" set to NULL).
808*9e39c5baSBill Taylor */
809*9e39c5baSBill Taylor dvm_track = (tavor_devmap_track_t *)pvtp;
810*9e39c5baSBill Taylor if (dvm_track == NULL) {
811*9e39c5baSBill Taylor *new_pvtp = NULL;
812*9e39c5baSBill Taylor return (DDI_SUCCESS);
813*9e39c5baSBill Taylor }
814*9e39c5baSBill Taylor
815*9e39c5baSBill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dvm_track))
816*9e39c5baSBill Taylor state = dvm_track->tdt_state;
817*9e39c5baSBill Taylor
818*9e39c5baSBill Taylor /*
819*9e39c5baSBill Taylor * Since this devmap_dup() entry point is generally called
820*9e39c5baSBill Taylor * when a process does fork(2), it is incumbent upon the driver
821*9e39c5baSBill Taylor * to insure that the child does not inherit a valid copy of
822*9e39c5baSBill Taylor * the parent's resource. This is accomplished by using
823*9e39c5baSBill Taylor * devmap_devmem_remap() to invalidate the child's mapping to the
824*9e39c5baSBill Taylor * kernel memory.
825*9e39c5baSBill Taylor */
826*9e39c5baSBill Taylor maxprot = (PROT_READ | PROT_WRITE | PROT_USER);
827*9e39c5baSBill Taylor status = devmap_devmem_remap(new_dhp, state->ts_dip, 0, 0,
828*9e39c5baSBill Taylor dvm_track->tdt_size, maxprot, DEVMAP_MAPPING_INVALID, NULL);
829*9e39c5baSBill Taylor if (status != DDI_SUCCESS) {
830*9e39c5baSBill Taylor TAVOR_WARNING(state, "failed in tavor_devmap_devmem_dup()");
831*9e39c5baSBill Taylor return (status);
832*9e39c5baSBill Taylor }
833*9e39c5baSBill Taylor
834*9e39c5baSBill Taylor /*
835*9e39c5baSBill Taylor * Since the region is invalid, there is no need for us to
836*9e39c5baSBill Taylor * allocate and continue to track an additional "Tavor devmap
837*9e39c5baSBill Taylor * tracking structure". Instead we return NULL here, which is an
838*9e39c5baSBill Taylor * indication to the devmap_unmap() entry point that this entry
839*9e39c5baSBill Taylor * can be safely ignored.
840*9e39c5baSBill Taylor */
841*9e39c5baSBill Taylor *new_pvtp = NULL;
842*9e39c5baSBill Taylor
843*9e39c5baSBill Taylor return (DDI_SUCCESS);
844*9e39c5baSBill Taylor }
845*9e39c5baSBill Taylor
846*9e39c5baSBill Taylor
847*9e39c5baSBill Taylor /*
848*9e39c5baSBill Taylor * tavor_devmap_devmem_unmap()
849*9e39c5baSBill Taylor * Context: Can be called from kernel context.
850*9e39c5baSBill Taylor */
851*9e39c5baSBill Taylor /* ARGSUSED */
852*9e39c5baSBill Taylor static void
tavor_devmap_devmem_unmap(devmap_cookie_t dhp,void * pvtp,offset_t off,size_t len,devmap_cookie_t new_dhp1,void ** pvtp1,devmap_cookie_t new_dhp2,void ** pvtp2)853*9e39c5baSBill Taylor tavor_devmap_devmem_unmap(devmap_cookie_t dhp, void *pvtp, offset_t off,
854*9e39c5baSBill Taylor size_t len, devmap_cookie_t new_dhp1, void **pvtp1,
855*9e39c5baSBill Taylor devmap_cookie_t new_dhp2, void **pvtp2)
856*9e39c5baSBill Taylor {
857*9e39c5baSBill Taylor tavor_devmap_track_t *dvm_track;
858*9e39c5baSBill Taylor
859*9e39c5baSBill Taylor /*
860*9e39c5baSBill Taylor * Free up the "Tavor devmap tracking structure" (in "pvtp").
861*9e39c5baSBill Taylor * There cannot be "partial" unmappings here because all UAR pages
862*9e39c5baSBill Taylor * are single pages. Note: If the tracking structure is NULL here,
863*9e39c5baSBill Taylor * it means that the mapping corresponds to an invalid mapping. In
864*9e39c5baSBill Taylor * this case, it can be safely ignored.
865*9e39c5baSBill Taylor */
866*9e39c5baSBill Taylor dvm_track = (tavor_devmap_track_t *)pvtp;
867*9e39c5baSBill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dvm_track))
868*9e39c5baSBill Taylor if (dvm_track == NULL) {
869*9e39c5baSBill Taylor return;
870*9e39c5baSBill Taylor }
871*9e39c5baSBill Taylor
872*9e39c5baSBill Taylor kmem_free(dvm_track, sizeof (tavor_devmap_track_t));
873*9e39c5baSBill Taylor }
874*9e39c5baSBill Taylor
875*9e39c5baSBill Taylor
876*9e39c5baSBill Taylor /*
877*9e39c5baSBill Taylor * tavor_umap_ci_data_in()
878*9e39c5baSBill Taylor * Context: Can be called from user or kernel context.
879*9e39c5baSBill Taylor */
880*9e39c5baSBill Taylor /* ARGSUSED */
881*9e39c5baSBill Taylor ibt_status_t
tavor_umap_ci_data_in(tavor_state_t * state,ibt_ci_data_flags_t flags,ibt_object_type_t object,void * hdl,void * data_p,size_t data_sz)882*9e39c5baSBill Taylor tavor_umap_ci_data_in(tavor_state_t *state, ibt_ci_data_flags_t flags,
883*9e39c5baSBill Taylor ibt_object_type_t object, void *hdl, void *data_p, size_t data_sz)
884*9e39c5baSBill Taylor {
885*9e39c5baSBill Taylor int status;
886*9e39c5baSBill Taylor
887*9e39c5baSBill Taylor /*
888*9e39c5baSBill Taylor * Depending on the type of object about which additional information
889*9e39c5baSBill Taylor * is being provided (currently only MR is supported), we call the
890*9e39c5baSBill Taylor * appropriate resource-specific function.
891*9e39c5baSBill Taylor */
892*9e39c5baSBill Taylor switch (object) {
893*9e39c5baSBill Taylor case IBT_HDL_MR:
894*9e39c5baSBill Taylor status = tavor_umap_mr_data_in((tavor_mrhdl_t)hdl,
895*9e39c5baSBill Taylor (ibt_mr_data_in_t *)data_p, data_sz);
896*9e39c5baSBill Taylor if (status != DDI_SUCCESS) {
897*9e39c5baSBill Taylor return (status);
898*9e39c5baSBill Taylor }
899*9e39c5baSBill Taylor break;
900*9e39c5baSBill Taylor
901*9e39c5baSBill Taylor /*
902*9e39c5baSBill Taylor * For other possible valid IBT types, we return IBT_NOT_SUPPORTED,
903*9e39c5baSBill Taylor * since the Tavor driver does not support these.
904*9e39c5baSBill Taylor */
905*9e39c5baSBill Taylor case IBT_HDL_HCA:
906*9e39c5baSBill Taylor case IBT_HDL_QP:
907*9e39c5baSBill Taylor case IBT_HDL_CQ:
908*9e39c5baSBill Taylor case IBT_HDL_PD:
909*9e39c5baSBill Taylor case IBT_HDL_MW:
910*9e39c5baSBill Taylor case IBT_HDL_AH:
911*9e39c5baSBill Taylor case IBT_HDL_SCHED:
912*9e39c5baSBill Taylor case IBT_HDL_EEC:
913*9e39c5baSBill Taylor case IBT_HDL_RDD:
914*9e39c5baSBill Taylor case IBT_HDL_SRQ:
915*9e39c5baSBill Taylor return (IBT_NOT_SUPPORTED);
916*9e39c5baSBill Taylor
917*9e39c5baSBill Taylor /*
918*9e39c5baSBill Taylor * Any other types are invalid.
919*9e39c5baSBill Taylor */
920*9e39c5baSBill Taylor default:
921*9e39c5baSBill Taylor return (IBT_INVALID_PARAM);
922*9e39c5baSBill Taylor }
923*9e39c5baSBill Taylor
924*9e39c5baSBill Taylor return (DDI_SUCCESS);
925*9e39c5baSBill Taylor }
926*9e39c5baSBill Taylor
927*9e39c5baSBill Taylor
928*9e39c5baSBill Taylor /*
929*9e39c5baSBill Taylor * tavor_umap_mr_data_in()
930*9e39c5baSBill Taylor * Context: Can be called from user or kernel context.
931*9e39c5baSBill Taylor */
932*9e39c5baSBill Taylor static ibt_status_t
tavor_umap_mr_data_in(tavor_mrhdl_t mr,ibt_mr_data_in_t * data,size_t data_sz)933*9e39c5baSBill Taylor tavor_umap_mr_data_in(tavor_mrhdl_t mr, ibt_mr_data_in_t *data,
934*9e39c5baSBill Taylor size_t data_sz)
935*9e39c5baSBill Taylor {
936*9e39c5baSBill Taylor if (data->mr_rev != IBT_MR_DATA_IN_IF_VERSION) {
937*9e39c5baSBill Taylor return (IBT_NOT_SUPPORTED);
938*9e39c5baSBill Taylor }
939*9e39c5baSBill Taylor
940*9e39c5baSBill Taylor /* Check for valid MR handle pointer */
941*9e39c5baSBill Taylor if (mr == NULL) {
942*9e39c5baSBill Taylor return (IBT_MR_HDL_INVALID);
943*9e39c5baSBill Taylor }
944*9e39c5baSBill Taylor
945*9e39c5baSBill Taylor /* Check for valid MR input structure size */
946*9e39c5baSBill Taylor if (data_sz < sizeof (ibt_mr_data_in_t)) {
947*9e39c5baSBill Taylor return (IBT_INSUFF_RESOURCE);
948*9e39c5baSBill Taylor }
949*9e39c5baSBill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*data))
950*9e39c5baSBill Taylor
951*9e39c5baSBill Taylor /*
952*9e39c5baSBill Taylor * Ensure that the MR corresponds to userland memory and that it is
953*9e39c5baSBill Taylor * a currently valid memory region as well.
954*9e39c5baSBill Taylor */
955*9e39c5baSBill Taylor mutex_enter(&mr->mr_lock);
956*9e39c5baSBill Taylor if ((mr->mr_is_umem == 0) || (mr->mr_umemcookie == NULL)) {
957*9e39c5baSBill Taylor mutex_exit(&mr->mr_lock);
958*9e39c5baSBill Taylor return (IBT_MR_HDL_INVALID);
959*9e39c5baSBill Taylor }
960*9e39c5baSBill Taylor
961*9e39c5baSBill Taylor /*
962*9e39c5baSBill Taylor * If it has passed all the above checks, then extract the callback
963*9e39c5baSBill Taylor * function and argument from the input structure. Copy them into
964*9e39c5baSBill Taylor * the MR handle. This function will be called only if the memory
965*9e39c5baSBill Taylor * corresponding to the MR handle gets a umem_lockmemory() callback.
966*9e39c5baSBill Taylor */
967*9e39c5baSBill Taylor mr->mr_umem_cbfunc = data->mr_func;
968*9e39c5baSBill Taylor mr->mr_umem_cbarg1 = data->mr_arg1;
969*9e39c5baSBill Taylor mr->mr_umem_cbarg2 = data->mr_arg2;
970*9e39c5baSBill Taylor mutex_exit(&mr->mr_lock);
971*9e39c5baSBill Taylor
972*9e39c5baSBill Taylor return (DDI_SUCCESS);
973*9e39c5baSBill Taylor }
974*9e39c5baSBill Taylor
975*9e39c5baSBill Taylor
976*9e39c5baSBill Taylor /*
977*9e39c5baSBill Taylor * tavor_umap_ci_data_out()
978*9e39c5baSBill Taylor * Context: Can be called from user or kernel context.
979*9e39c5baSBill Taylor */
980*9e39c5baSBill Taylor /* ARGSUSED */
981*9e39c5baSBill Taylor ibt_status_t
tavor_umap_ci_data_out(tavor_state_t * state,ibt_ci_data_flags_t flags,ibt_object_type_t object,void * hdl,void * data_p,size_t data_sz)982*9e39c5baSBill Taylor tavor_umap_ci_data_out(tavor_state_t *state, ibt_ci_data_flags_t flags,
983*9e39c5baSBill Taylor ibt_object_type_t object, void *hdl, void *data_p, size_t data_sz)
984*9e39c5baSBill Taylor {
985*9e39c5baSBill Taylor int status;
986*9e39c5baSBill Taylor
987*9e39c5baSBill Taylor /*
988*9e39c5baSBill Taylor * Depending on the type of object about which additional information
989*9e39c5baSBill Taylor * is being requested (CQ or QP), we call the appropriate resource-
990*9e39c5baSBill Taylor * specific mapping function.
991*9e39c5baSBill Taylor */
992*9e39c5baSBill Taylor switch (object) {
993*9e39c5baSBill Taylor case IBT_HDL_CQ:
994*9e39c5baSBill Taylor status = tavor_umap_cq_data_out((tavor_cqhdl_t)hdl,
995*9e39c5baSBill Taylor (mlnx_umap_cq_data_out_t *)data_p, data_sz);
996*9e39c5baSBill Taylor if (status != DDI_SUCCESS) {
997*9e39c5baSBill Taylor return (status);
998*9e39c5baSBill Taylor }
999*9e39c5baSBill Taylor break;
1000*9e39c5baSBill Taylor
1001*9e39c5baSBill Taylor case IBT_HDL_QP:
1002*9e39c5baSBill Taylor status = tavor_umap_qp_data_out((tavor_qphdl_t)hdl,
1003*9e39c5baSBill Taylor (mlnx_umap_qp_data_out_t *)data_p, data_sz);
1004*9e39c5baSBill Taylor if (status != DDI_SUCCESS) {
1005*9e39c5baSBill Taylor return (status);
1006*9e39c5baSBill Taylor }
1007*9e39c5baSBill Taylor break;
1008*9e39c5baSBill Taylor
1009*9e39c5baSBill Taylor case IBT_HDL_SRQ:
1010*9e39c5baSBill Taylor status = tavor_umap_srq_data_out((tavor_srqhdl_t)hdl,
1011*9e39c5baSBill Taylor (mlnx_umap_srq_data_out_t *)data_p, data_sz);
1012*9e39c5baSBill Taylor if (status != DDI_SUCCESS) {
1013*9e39c5baSBill Taylor return (status);
1014*9e39c5baSBill Taylor }
1015*9e39c5baSBill Taylor break;
1016*9e39c5baSBill Taylor
1017*9e39c5baSBill Taylor /*
1018*9e39c5baSBill Taylor * For other possible valid IBT types, we return IBT_NOT_SUPPORTED,
1019*9e39c5baSBill Taylor * since the Tavor driver does not support these.
1020*9e39c5baSBill Taylor */
1021*9e39c5baSBill Taylor case IBT_HDL_PD:
1022*9e39c5baSBill Taylor status = tavor_umap_pd_data_out((tavor_pdhdl_t)hdl,
1023*9e39c5baSBill Taylor (mlnx_umap_pd_data_out_t *)data_p, data_sz);
1024*9e39c5baSBill Taylor if (status != DDI_SUCCESS) {
1025*9e39c5baSBill Taylor return (status);
1026*9e39c5baSBill Taylor }
1027*9e39c5baSBill Taylor break;
1028*9e39c5baSBill Taylor
1029*9e39c5baSBill Taylor case IBT_HDL_HCA:
1030*9e39c5baSBill Taylor case IBT_HDL_MR:
1031*9e39c5baSBill Taylor case IBT_HDL_MW:
1032*9e39c5baSBill Taylor case IBT_HDL_AH:
1033*9e39c5baSBill Taylor case IBT_HDL_SCHED:
1034*9e39c5baSBill Taylor case IBT_HDL_EEC:
1035*9e39c5baSBill Taylor case IBT_HDL_RDD:
1036*9e39c5baSBill Taylor return (IBT_NOT_SUPPORTED);
1037*9e39c5baSBill Taylor
1038*9e39c5baSBill Taylor /*
1039*9e39c5baSBill Taylor * Any other types are invalid.
1040*9e39c5baSBill Taylor */
1041*9e39c5baSBill Taylor default:
1042*9e39c5baSBill Taylor return (IBT_INVALID_PARAM);
1043*9e39c5baSBill Taylor }
1044*9e39c5baSBill Taylor
1045*9e39c5baSBill Taylor return (DDI_SUCCESS);
1046*9e39c5baSBill Taylor }
1047*9e39c5baSBill Taylor
1048*9e39c5baSBill Taylor
1049*9e39c5baSBill Taylor /*
1050*9e39c5baSBill Taylor * tavor_umap_cq_data_out()
1051*9e39c5baSBill Taylor * Context: Can be called from user or kernel context.
1052*9e39c5baSBill Taylor */
1053*9e39c5baSBill Taylor static ibt_status_t
tavor_umap_cq_data_out(tavor_cqhdl_t cq,mlnx_umap_cq_data_out_t * data,size_t data_sz)1054*9e39c5baSBill Taylor tavor_umap_cq_data_out(tavor_cqhdl_t cq, mlnx_umap_cq_data_out_t *data,
1055*9e39c5baSBill Taylor size_t data_sz)
1056*9e39c5baSBill Taylor {
1057*9e39c5baSBill Taylor /* Check for valid CQ handle pointer */
1058*9e39c5baSBill Taylor if (cq == NULL) {
1059*9e39c5baSBill Taylor return (IBT_CQ_HDL_INVALID);
1060*9e39c5baSBill Taylor }
1061*9e39c5baSBill Taylor
1062*9e39c5baSBill Taylor /* Check for valid CQ mapping structure size */
1063*9e39c5baSBill Taylor if (data_sz < sizeof (mlnx_umap_cq_data_out_t)) {
1064*9e39c5baSBill Taylor return (IBT_INSUFF_RESOURCE);
1065*9e39c5baSBill Taylor }
1066*9e39c5baSBill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*data))
1067*9e39c5baSBill Taylor
1068*9e39c5baSBill Taylor /*
1069*9e39c5baSBill Taylor * If it has passed all the above checks, then fill in all the useful
1070*9e39c5baSBill Taylor * mapping information (including the mapping offset that will be
1071*9e39c5baSBill Taylor * passed back to the devmap() interface during a subsequent mmap()
1072*9e39c5baSBill Taylor * call.
1073*9e39c5baSBill Taylor *
1074*9e39c5baSBill Taylor * The "offset" for CQ mmap()'s looks like this:
1075*9e39c5baSBill Taylor * +----------------------------------------+--------+--------------+
1076*9e39c5baSBill Taylor * | CQ Number | 0x33 | Reserved (0) |
1077*9e39c5baSBill Taylor * +----------------------------------------+--------+--------------+
1078*9e39c5baSBill Taylor * (64 - 8 - PAGESHIFT) bits 8 bits PAGESHIFT bits
1079*9e39c5baSBill Taylor *
1080*9e39c5baSBill Taylor * This returns information about the mapping offset, the length of
1081*9e39c5baSBill Taylor * the CQ memory, the CQ number (for use in later CQ doorbells), the
1082*9e39c5baSBill Taylor * number of CQEs the CQ memory can hold, and the size of each CQE.
1083*9e39c5baSBill Taylor */
1084*9e39c5baSBill Taylor data->mcq_rev = MLNX_UMAP_IF_VERSION;
1085*9e39c5baSBill Taylor data->mcq_mapoffset = ((((uint64_t)cq->cq_cqnum <<
1086*9e39c5baSBill Taylor MLNX_UMAP_RSRC_TYPE_SHIFT) | MLNX_UMAP_CQMEM_RSRC) << PAGESHIFT);
1087*9e39c5baSBill Taylor data->mcq_maplen = cq->cq_cqinfo.qa_size;
1088*9e39c5baSBill Taylor data->mcq_cqnum = cq->cq_cqnum;
1089*9e39c5baSBill Taylor data->mcq_numcqe = cq->cq_bufsz;
1090*9e39c5baSBill Taylor data->mcq_cqesz = sizeof (tavor_hw_cqe_t);
1091*9e39c5baSBill Taylor
1092*9e39c5baSBill Taylor return (DDI_SUCCESS);
1093*9e39c5baSBill Taylor }
1094*9e39c5baSBill Taylor
1095*9e39c5baSBill Taylor
1096*9e39c5baSBill Taylor /*
1097*9e39c5baSBill Taylor * tavor_umap_qp_data_out()
1098*9e39c5baSBill Taylor * Context: Can be called from user or kernel context.
1099*9e39c5baSBill Taylor */
1100*9e39c5baSBill Taylor static ibt_status_t
tavor_umap_qp_data_out(tavor_qphdl_t qp,mlnx_umap_qp_data_out_t * data,size_t data_sz)1101*9e39c5baSBill Taylor tavor_umap_qp_data_out(tavor_qphdl_t qp, mlnx_umap_qp_data_out_t *data,
1102*9e39c5baSBill Taylor size_t data_sz)
1103*9e39c5baSBill Taylor {
1104*9e39c5baSBill Taylor /* Check for valid QP handle pointer */
1105*9e39c5baSBill Taylor if (qp == NULL) {
1106*9e39c5baSBill Taylor return (IBT_QP_HDL_INVALID);
1107*9e39c5baSBill Taylor }
1108*9e39c5baSBill Taylor
1109*9e39c5baSBill Taylor /* Check for valid QP mapping structure size */
1110*9e39c5baSBill Taylor if (data_sz < sizeof (mlnx_umap_qp_data_out_t)) {
1111*9e39c5baSBill Taylor return (IBT_INSUFF_RESOURCE);
1112*9e39c5baSBill Taylor }
1113*9e39c5baSBill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*data))
1114*9e39c5baSBill Taylor
1115*9e39c5baSBill Taylor /*
1116*9e39c5baSBill Taylor * If it has passed all the checks, then fill in all the useful
1117*9e39c5baSBill Taylor * mapping information (including the mapping offset that will be
1118*9e39c5baSBill Taylor * passed back to the devmap() interface during a subsequent mmap()
1119*9e39c5baSBill Taylor * call.
1120*9e39c5baSBill Taylor *
1121*9e39c5baSBill Taylor * The "offset" for QP mmap()'s looks like this:
1122*9e39c5baSBill Taylor * +----------------------------------------+--------+--------------+
1123*9e39c5baSBill Taylor * | QP Number | 0x44 | Reserved (0) |
1124*9e39c5baSBill Taylor * +----------------------------------------+--------+--------------+
1125*9e39c5baSBill Taylor * (64 - 8 - PAGESHIFT) bits 8 bits PAGESHIFT bits
1126*9e39c5baSBill Taylor *
1127*9e39c5baSBill Taylor * This returns information about the mapping offset, the length of
1128*9e39c5baSBill Taylor * the QP memory, and the QP number (for use in later send and recv
1129*9e39c5baSBill Taylor * doorbells). It also returns the following information for both
1130*9e39c5baSBill Taylor * the receive work queue and the send work queue, respectively: the
1131*9e39c5baSBill Taylor * offset (from the base mapped address) of the start of the given
1132*9e39c5baSBill Taylor * work queue, the 64-bit IB virtual address that corresponds to
1133*9e39c5baSBill Taylor * the base mapped address (needed for posting WQEs though the
1134*9e39c5baSBill Taylor * QP doorbells), the number of WQEs the given work queue can hold,
1135*9e39c5baSBill Taylor * and the size of each WQE for the given work queue.
1136*9e39c5baSBill Taylor */
1137*9e39c5baSBill Taylor data->mqp_rev = MLNX_UMAP_IF_VERSION;
1138*9e39c5baSBill Taylor data->mqp_mapoffset = ((((uint64_t)qp->qp_qpnum <<
1139*9e39c5baSBill Taylor MLNX_UMAP_RSRC_TYPE_SHIFT) | MLNX_UMAP_QPMEM_RSRC) << PAGESHIFT);
1140*9e39c5baSBill Taylor data->mqp_maplen = qp->qp_wqinfo.qa_size;
1141*9e39c5baSBill Taylor data->mqp_qpnum = qp->qp_qpnum;
1142*9e39c5baSBill Taylor
1143*9e39c5baSBill Taylor /*
1144*9e39c5baSBill Taylor * If this QP is associated with a shared receive queue (SRQ),
1145*9e39c5baSBill Taylor * then return invalid RecvQ parameters. Otherwise, return
1146*9e39c5baSBill Taylor * the proper parameter values.
1147*9e39c5baSBill Taylor */
1148*9e39c5baSBill Taylor if (qp->qp_srq_en == TAVOR_QP_SRQ_ENABLED) {
1149*9e39c5baSBill Taylor data->mqp_rq_off = (uint32_t)qp->qp_wqinfo.qa_size;
1150*9e39c5baSBill Taylor data->mqp_rq_desc_addr = (uint32_t)qp->qp_wqinfo.qa_size;
1151*9e39c5baSBill Taylor data->mqp_rq_numwqe = 0;
1152*9e39c5baSBill Taylor data->mqp_rq_wqesz = 0;
1153*9e39c5baSBill Taylor } else {
1154*9e39c5baSBill Taylor data->mqp_rq_off = (uintptr_t)qp->qp_rq_buf -
1155*9e39c5baSBill Taylor (uintptr_t)qp->qp_wqinfo.qa_buf_aligned;
1156*9e39c5baSBill Taylor data->mqp_rq_desc_addr = (uint32_t)((uintptr_t)qp->qp_rq_buf -
1157*9e39c5baSBill Taylor qp->qp_desc_off);
1158*9e39c5baSBill Taylor data->mqp_rq_numwqe = qp->qp_rq_bufsz;
1159*9e39c5baSBill Taylor data->mqp_rq_wqesz = (1 << qp->qp_rq_log_wqesz);
1160*9e39c5baSBill Taylor }
1161*9e39c5baSBill Taylor data->mqp_sq_off = (uintptr_t)qp->qp_sq_buf -
1162*9e39c5baSBill Taylor (uintptr_t)qp->qp_wqinfo.qa_buf_aligned;
1163*9e39c5baSBill Taylor data->mqp_sq_desc_addr = (uint32_t)((uintptr_t)qp->qp_sq_buf -
1164*9e39c5baSBill Taylor qp->qp_desc_off);
1165*9e39c5baSBill Taylor data->mqp_sq_numwqe = qp->qp_sq_bufsz;
1166*9e39c5baSBill Taylor data->mqp_sq_wqesz = (1 << qp->qp_sq_log_wqesz);
1167*9e39c5baSBill Taylor
1168*9e39c5baSBill Taylor return (DDI_SUCCESS);
1169*9e39c5baSBill Taylor }
1170*9e39c5baSBill Taylor
1171*9e39c5baSBill Taylor
1172*9e39c5baSBill Taylor /*
1173*9e39c5baSBill Taylor * tavor_umap_srq_data_out()
1174*9e39c5baSBill Taylor * Context: Can be called from user or kernel context.
1175*9e39c5baSBill Taylor */
1176*9e39c5baSBill Taylor static ibt_status_t
tavor_umap_srq_data_out(tavor_srqhdl_t srq,mlnx_umap_srq_data_out_t * data,size_t data_sz)1177*9e39c5baSBill Taylor tavor_umap_srq_data_out(tavor_srqhdl_t srq, mlnx_umap_srq_data_out_t *data,
1178*9e39c5baSBill Taylor size_t data_sz)
1179*9e39c5baSBill Taylor {
1180*9e39c5baSBill Taylor /* Check for valid SRQ handle pointer */
1181*9e39c5baSBill Taylor if (srq == NULL) {
1182*9e39c5baSBill Taylor return (IBT_SRQ_HDL_INVALID);
1183*9e39c5baSBill Taylor }
1184*9e39c5baSBill Taylor
1185*9e39c5baSBill Taylor /* Check for valid SRQ mapping structure size */
1186*9e39c5baSBill Taylor if (data_sz < sizeof (mlnx_umap_srq_data_out_t)) {
1187*9e39c5baSBill Taylor return (IBT_INSUFF_RESOURCE);
1188*9e39c5baSBill Taylor }
1189*9e39c5baSBill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*data))
1190*9e39c5baSBill Taylor
1191*9e39c5baSBill Taylor /*
1192*9e39c5baSBill Taylor * If it has passed all the checks, then fill in all the useful
1193*9e39c5baSBill Taylor * mapping information (including the mapping offset that will be
1194*9e39c5baSBill Taylor * passed back to the devmap() interface during a subsequent mmap()
1195*9e39c5baSBill Taylor * call.
1196*9e39c5baSBill Taylor *
1197*9e39c5baSBill Taylor * The "offset" for SRQ mmap()'s looks like this:
1198*9e39c5baSBill Taylor * +----------------------------------------+--------+--------------+
1199*9e39c5baSBill Taylor * | SRQ Number | 0x66 | Reserved (0) |
1200*9e39c5baSBill Taylor * +----------------------------------------+--------+--------------+
1201*9e39c5baSBill Taylor * (64 - 8 - PAGESHIFT) bits 8 bits PAGESHIFT bits
1202*9e39c5baSBill Taylor *
1203*9e39c5baSBill Taylor * This returns information about the mapping offset, the length of the
1204*9e39c5baSBill Taylor * SRQ memory, and the SRQ number (for use in later send and recv
1205*9e39c5baSBill Taylor * doorbells). It also returns the following information for the
1206*9e39c5baSBill Taylor * shared receive queue: the offset (from the base mapped address) of
1207*9e39c5baSBill Taylor * the start of the given work queue, the 64-bit IB virtual address
1208*9e39c5baSBill Taylor * that corresponds to the base mapped address (needed for posting WQEs
1209*9e39c5baSBill Taylor * though the QP doorbells), the number of WQEs the given work queue
1210*9e39c5baSBill Taylor * can hold, and the size of each WQE for the given work queue.
1211*9e39c5baSBill Taylor */
1212*9e39c5baSBill Taylor data->msrq_rev = MLNX_UMAP_IF_VERSION;
1213*9e39c5baSBill Taylor data->msrq_mapoffset = ((((uint64_t)srq->srq_srqnum <<
1214*9e39c5baSBill Taylor MLNX_UMAP_RSRC_TYPE_SHIFT) | MLNX_UMAP_SRQMEM_RSRC) << PAGESHIFT);
1215*9e39c5baSBill Taylor data->msrq_maplen = srq->srq_wqinfo.qa_size;
1216*9e39c5baSBill Taylor data->msrq_srqnum = srq->srq_srqnum;
1217*9e39c5baSBill Taylor
1218*9e39c5baSBill Taylor data->msrq_desc_addr = (uint32_t)((uintptr_t)srq->srq_wq_buf -
1219*9e39c5baSBill Taylor srq->srq_desc_off);
1220*9e39c5baSBill Taylor data->msrq_numwqe = srq->srq_wq_bufsz;
1221*9e39c5baSBill Taylor data->msrq_wqesz = (1 << srq->srq_wq_log_wqesz);
1222*9e39c5baSBill Taylor
1223*9e39c5baSBill Taylor return (DDI_SUCCESS);
1224*9e39c5baSBill Taylor }
1225*9e39c5baSBill Taylor
1226*9e39c5baSBill Taylor /*
1227*9e39c5baSBill Taylor * tavor_umap_pd_data_out()
1228*9e39c5baSBill Taylor * Context: Can be called from user or kernel context.
1229*9e39c5baSBill Taylor */
1230*9e39c5baSBill Taylor static ibt_status_t
tavor_umap_pd_data_out(tavor_pdhdl_t pd,mlnx_umap_pd_data_out_t * data,size_t data_sz)1231*9e39c5baSBill Taylor tavor_umap_pd_data_out(tavor_pdhdl_t pd, mlnx_umap_pd_data_out_t *data,
1232*9e39c5baSBill Taylor size_t data_sz)
1233*9e39c5baSBill Taylor {
1234*9e39c5baSBill Taylor /* Check for valid PD handle pointer */
1235*9e39c5baSBill Taylor if (pd == NULL) {
1236*9e39c5baSBill Taylor return (IBT_PD_HDL_INVALID);
1237*9e39c5baSBill Taylor }
1238*9e39c5baSBill Taylor
1239*9e39c5baSBill Taylor /* Check for valid PD mapping structure size */
1240*9e39c5baSBill Taylor if (data_sz < sizeof (mlnx_umap_pd_data_out_t)) {
1241*9e39c5baSBill Taylor return (IBT_INSUFF_RESOURCE);
1242*9e39c5baSBill Taylor }
1243*9e39c5baSBill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*data))
1244*9e39c5baSBill Taylor
1245*9e39c5baSBill Taylor /*
1246*9e39c5baSBill Taylor * If it has passed all the checks, then fill the PD table index
1247*9e39c5baSBill Taylor * (the PD table allocated index for the PD pd_pdnum)
1248*9e39c5baSBill Taylor */
1249*9e39c5baSBill Taylor data->mpd_rev = MLNX_UMAP_IF_VERSION;
1250*9e39c5baSBill Taylor data->mpd_pdnum = pd->pd_pdnum;
1251*9e39c5baSBill Taylor
1252*9e39c5baSBill Taylor return (DDI_SUCCESS);
1253*9e39c5baSBill Taylor }
1254*9e39c5baSBill Taylor
1255*9e39c5baSBill Taylor /*
1256*9e39c5baSBill Taylor * tavor_umap_db_init()
1257*9e39c5baSBill Taylor * Context: Only called from attach() path context
1258*9e39c5baSBill Taylor */
1259*9e39c5baSBill Taylor void
tavor_umap_db_init(void)1260*9e39c5baSBill Taylor tavor_umap_db_init(void)
1261*9e39c5baSBill Taylor {
1262*9e39c5baSBill Taylor /*
1263*9e39c5baSBill Taylor * Initialize the lock used by the Tavor "userland resources database"
1264*9e39c5baSBill Taylor * This is used to ensure atomic access to add, remove, and find
1265*9e39c5baSBill Taylor * entries in the database.
1266*9e39c5baSBill Taylor */
1267*9e39c5baSBill Taylor mutex_init(&tavor_userland_rsrc_db.tdl_umapdb_lock, NULL,
1268*9e39c5baSBill Taylor MUTEX_DRIVER, NULL);
1269*9e39c5baSBill Taylor
1270*9e39c5baSBill Taylor /*
1271*9e39c5baSBill Taylor * Initialize the AVL tree used for the "userland resources
1272*9e39c5baSBill Taylor * database". Using an AVL tree here provides the ability to
1273*9e39c5baSBill Taylor * scale the database size to large numbers of resources. The
1274*9e39c5baSBill Taylor * entries in the tree are "tavor_umap_db_entry_t".
1275*9e39c5baSBill Taylor * The tree is searched with the help of the
1276*9e39c5baSBill Taylor * tavor_umap_db_compare() routine.
1277*9e39c5baSBill Taylor */
1278*9e39c5baSBill Taylor avl_create(&tavor_userland_rsrc_db.tdl_umapdb_avl,
1279*9e39c5baSBill Taylor tavor_umap_db_compare, sizeof (tavor_umap_db_entry_t),
1280*9e39c5baSBill Taylor offsetof(tavor_umap_db_entry_t, tdbe_avlnode));
1281*9e39c5baSBill Taylor }
1282*9e39c5baSBill Taylor
1283*9e39c5baSBill Taylor
1284*9e39c5baSBill Taylor /*
1285*9e39c5baSBill Taylor * tavor_umap_db_fini()
1286*9e39c5baSBill Taylor * Context: Only called from attach() and/or detach() path contexts
1287*9e39c5baSBill Taylor */
1288*9e39c5baSBill Taylor void
tavor_umap_db_fini(void)1289*9e39c5baSBill Taylor tavor_umap_db_fini(void)
1290*9e39c5baSBill Taylor {
1291*9e39c5baSBill Taylor /* Destroy the AVL tree for the "userland resources database" */
1292*9e39c5baSBill Taylor avl_destroy(&tavor_userland_rsrc_db.tdl_umapdb_avl);
1293*9e39c5baSBill Taylor
1294*9e39c5baSBill Taylor /* Destroy the lock for the "userland resources database" */
1295*9e39c5baSBill Taylor mutex_destroy(&tavor_userland_rsrc_db.tdl_umapdb_lock);
1296*9e39c5baSBill Taylor }
1297*9e39c5baSBill Taylor
1298*9e39c5baSBill Taylor
1299*9e39c5baSBill Taylor /*
1300*9e39c5baSBill Taylor * tavor_umap_db_alloc()
1301*9e39c5baSBill Taylor * Context: Can be called from user or kernel context.
1302*9e39c5baSBill Taylor */
1303*9e39c5baSBill Taylor tavor_umap_db_entry_t *
tavor_umap_db_alloc(uint_t instance,uint64_t key,uint_t type,uint64_t value)1304*9e39c5baSBill Taylor tavor_umap_db_alloc(uint_t instance, uint64_t key, uint_t type, uint64_t value)
1305*9e39c5baSBill Taylor {
1306*9e39c5baSBill Taylor tavor_umap_db_entry_t *umapdb;
1307*9e39c5baSBill Taylor
1308*9e39c5baSBill Taylor /* Allocate an entry to add to the "userland resources database" */
1309*9e39c5baSBill Taylor umapdb = kmem_zalloc(sizeof (tavor_umap_db_entry_t), KM_NOSLEEP);
1310*9e39c5baSBill Taylor if (umapdb == NULL) {
1311*9e39c5baSBill Taylor return (NULL);
1312*9e39c5baSBill Taylor }
1313*9e39c5baSBill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*umapdb))
1314*9e39c5baSBill Taylor
1315*9e39c5baSBill Taylor /* Fill in the fields in the database entry */
1316*9e39c5baSBill Taylor umapdb->tdbe_common.tdb_instance = instance;
1317*9e39c5baSBill Taylor umapdb->tdbe_common.tdb_type = type;
1318*9e39c5baSBill Taylor umapdb->tdbe_common.tdb_key = key;
1319*9e39c5baSBill Taylor umapdb->tdbe_common.tdb_value = value;
1320*9e39c5baSBill Taylor
1321*9e39c5baSBill Taylor return (umapdb);
1322*9e39c5baSBill Taylor }
1323*9e39c5baSBill Taylor
1324*9e39c5baSBill Taylor
1325*9e39c5baSBill Taylor /*
1326*9e39c5baSBill Taylor * tavor_umap_db_free()
1327*9e39c5baSBill Taylor * Context: Can be called from user or kernel context.
1328*9e39c5baSBill Taylor */
1329*9e39c5baSBill Taylor void
tavor_umap_db_free(tavor_umap_db_entry_t * umapdb)1330*9e39c5baSBill Taylor tavor_umap_db_free(tavor_umap_db_entry_t *umapdb)
1331*9e39c5baSBill Taylor {
1332*9e39c5baSBill Taylor /* Free the database entry */
1333*9e39c5baSBill Taylor kmem_free(umapdb, sizeof (tavor_umap_db_entry_t));
1334*9e39c5baSBill Taylor }
1335*9e39c5baSBill Taylor
1336*9e39c5baSBill Taylor
1337*9e39c5baSBill Taylor /*
1338*9e39c5baSBill Taylor * tavor_umap_db_add()
1339*9e39c5baSBill Taylor * Context: Can be called from user or kernel context.
1340*9e39c5baSBill Taylor */
1341*9e39c5baSBill Taylor void
tavor_umap_db_add(tavor_umap_db_entry_t * umapdb)1342*9e39c5baSBill Taylor tavor_umap_db_add(tavor_umap_db_entry_t *umapdb)
1343*9e39c5baSBill Taylor {
1344*9e39c5baSBill Taylor mutex_enter(&tavor_userland_rsrc_db.tdl_umapdb_lock);
1345*9e39c5baSBill Taylor tavor_umap_db_add_nolock(umapdb);
1346*9e39c5baSBill Taylor mutex_exit(&tavor_userland_rsrc_db.tdl_umapdb_lock);
1347*9e39c5baSBill Taylor }
1348*9e39c5baSBill Taylor
1349*9e39c5baSBill Taylor
1350*9e39c5baSBill Taylor /*
1351*9e39c5baSBill Taylor * tavor_umap_db_add_nolock()
1352*9e39c5baSBill Taylor * Context: Can be called from user or kernel context.
1353*9e39c5baSBill Taylor */
1354*9e39c5baSBill Taylor void
tavor_umap_db_add_nolock(tavor_umap_db_entry_t * umapdb)1355*9e39c5baSBill Taylor tavor_umap_db_add_nolock(tavor_umap_db_entry_t *umapdb)
1356*9e39c5baSBill Taylor {
1357*9e39c5baSBill Taylor tavor_umap_db_query_t query;
1358*9e39c5baSBill Taylor avl_index_t where;
1359*9e39c5baSBill Taylor
1360*9e39c5baSBill Taylor ASSERT(MUTEX_HELD(&tavor_userland_rsrc_db.tdl_umapdb_lock));
1361*9e39c5baSBill Taylor
1362*9e39c5baSBill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*umapdb))
1363*9e39c5baSBill Taylor
1364*9e39c5baSBill Taylor /*
1365*9e39c5baSBill Taylor * Copy the common portion of the "to-be-added" database entry
1366*9e39c5baSBill Taylor * into the "tavor_umap_db_query_t" structure. We use this structure
1367*9e39c5baSBill Taylor * (with no flags set) to find the appropriate location in the
1368*9e39c5baSBill Taylor * "userland resources database" for the new entry to be added.
1369*9e39c5baSBill Taylor *
1370*9e39c5baSBill Taylor * Note: we expect that this entry should not be found in the
1371*9e39c5baSBill Taylor * database (unless something bad has happened).
1372*9e39c5baSBill Taylor */
1373*9e39c5baSBill Taylor query.tqdb_common = umapdb->tdbe_common;
1374*9e39c5baSBill Taylor query.tqdb_flags = 0;
1375*9e39c5baSBill Taylor (void) avl_find(&tavor_userland_rsrc_db.tdl_umapdb_avl, &query,
1376*9e39c5baSBill Taylor &where);
1377*9e39c5baSBill Taylor
1378*9e39c5baSBill Taylor /*
1379*9e39c5baSBill Taylor * Now, using the "where" field from the avl_find() operation
1380*9e39c5baSBill Taylor * above, we will insert the new database entry ("umapdb").
1381*9e39c5baSBill Taylor */
1382*9e39c5baSBill Taylor avl_insert(&tavor_userland_rsrc_db.tdl_umapdb_avl, umapdb,
1383*9e39c5baSBill Taylor where);
1384*9e39c5baSBill Taylor }
1385*9e39c5baSBill Taylor
1386*9e39c5baSBill Taylor
1387*9e39c5baSBill Taylor /*
1388*9e39c5baSBill Taylor * tavor_umap_db_find()
1389*9e39c5baSBill Taylor * Context: Can be called from user or kernel context.
1390*9e39c5baSBill Taylor */
1391*9e39c5baSBill Taylor int
tavor_umap_db_find(uint_t instance,uint64_t key,uint_t type,uint64_t * value,uint_t flag,tavor_umap_db_entry_t ** umapdb)1392*9e39c5baSBill Taylor tavor_umap_db_find(uint_t instance, uint64_t key, uint_t type,
1393*9e39c5baSBill Taylor uint64_t *value, uint_t flag, tavor_umap_db_entry_t **umapdb)
1394*9e39c5baSBill Taylor {
1395*9e39c5baSBill Taylor int status;
1396*9e39c5baSBill Taylor
1397*9e39c5baSBill Taylor mutex_enter(&tavor_userland_rsrc_db.tdl_umapdb_lock);
1398*9e39c5baSBill Taylor status = tavor_umap_db_find_nolock(instance, key, type, value, flag,
1399*9e39c5baSBill Taylor umapdb);
1400*9e39c5baSBill Taylor mutex_exit(&tavor_userland_rsrc_db.tdl_umapdb_lock);
1401*9e39c5baSBill Taylor
1402*9e39c5baSBill Taylor return (status);
1403*9e39c5baSBill Taylor }
1404*9e39c5baSBill Taylor
1405*9e39c5baSBill Taylor
1406*9e39c5baSBill Taylor /*
1407*9e39c5baSBill Taylor * tavor_umap_db_find_nolock()
1408*9e39c5baSBill Taylor * Context: Can be called from user or kernel context.
1409*9e39c5baSBill Taylor */
1410*9e39c5baSBill Taylor int
tavor_umap_db_find_nolock(uint_t instance,uint64_t key,uint_t type,uint64_t * value,uint_t flags,tavor_umap_db_entry_t ** umapdb)1411*9e39c5baSBill Taylor tavor_umap_db_find_nolock(uint_t instance, uint64_t key, uint_t type,
1412*9e39c5baSBill Taylor uint64_t *value, uint_t flags, tavor_umap_db_entry_t **umapdb)
1413*9e39c5baSBill Taylor {
1414*9e39c5baSBill Taylor tavor_umap_db_query_t query;
1415*9e39c5baSBill Taylor tavor_umap_db_entry_t *entry;
1416*9e39c5baSBill Taylor avl_index_t where;
1417*9e39c5baSBill Taylor
1418*9e39c5baSBill Taylor ASSERT(MUTEX_HELD(&tavor_userland_rsrc_db.tdl_umapdb_lock));
1419*9e39c5baSBill Taylor
1420*9e39c5baSBill Taylor /*
1421*9e39c5baSBill Taylor * Fill in key, type, instance, and flags values of the
1422*9e39c5baSBill Taylor * tavor_umap_db_query_t in preparation for the database
1423*9e39c5baSBill Taylor * lookup.
1424*9e39c5baSBill Taylor */
1425*9e39c5baSBill Taylor query.tqdb_flags = flags;
1426*9e39c5baSBill Taylor query.tqdb_common.tdb_key = key;
1427*9e39c5baSBill Taylor query.tqdb_common.tdb_type = type;
1428*9e39c5baSBill Taylor query.tqdb_common.tdb_instance = instance;
1429*9e39c5baSBill Taylor
1430*9e39c5baSBill Taylor /*
1431*9e39c5baSBill Taylor * Perform the database query. If no entry is found, then
1432*9e39c5baSBill Taylor * return failure, else continue.
1433*9e39c5baSBill Taylor */
1434*9e39c5baSBill Taylor entry = (tavor_umap_db_entry_t *)avl_find(
1435*9e39c5baSBill Taylor &tavor_userland_rsrc_db.tdl_umapdb_avl, &query, &where);
1436*9e39c5baSBill Taylor if (entry == NULL) {
1437*9e39c5baSBill Taylor return (DDI_FAILURE);
1438*9e39c5baSBill Taylor }
1439*9e39c5baSBill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*entry))
1440*9e39c5baSBill Taylor
1441*9e39c5baSBill Taylor /*
1442*9e39c5baSBill Taylor * If the flags argument specifies that the entry should
1443*9e39c5baSBill Taylor * be removed if found, then call avl_remove() to remove
1444*9e39c5baSBill Taylor * the entry from the database.
1445*9e39c5baSBill Taylor */
1446*9e39c5baSBill Taylor if (flags & TAVOR_UMAP_DB_REMOVE) {
1447*9e39c5baSBill Taylor
1448*9e39c5baSBill Taylor avl_remove(&tavor_userland_rsrc_db.tdl_umapdb_avl, entry);
1449*9e39c5baSBill Taylor
1450*9e39c5baSBill Taylor /*
1451*9e39c5baSBill Taylor * The database entry is returned with the expectation
1452*9e39c5baSBill Taylor * that the caller will use tavor_umap_db_free() to
1453*9e39c5baSBill Taylor * free the entry's memory. ASSERT that this is non-NULL.
1454*9e39c5baSBill Taylor * NULL pointer should never be passed for the
1455*9e39c5baSBill Taylor * TAVOR_UMAP_DB_REMOVE case.
1456*9e39c5baSBill Taylor */
1457*9e39c5baSBill Taylor ASSERT(umapdb != NULL);
1458*9e39c5baSBill Taylor }
1459*9e39c5baSBill Taylor
1460*9e39c5baSBill Taylor /*
1461*9e39c5baSBill Taylor * If the caller would like visibility to the database entry
1462*9e39c5baSBill Taylor * (indicated through the use of a non-NULL "umapdb" argument),
1463*9e39c5baSBill Taylor * then fill it in.
1464*9e39c5baSBill Taylor */
1465*9e39c5baSBill Taylor if (umapdb != NULL) {
1466*9e39c5baSBill Taylor *umapdb = entry;
1467*9e39c5baSBill Taylor }
1468*9e39c5baSBill Taylor
1469*9e39c5baSBill Taylor /* Extract value field from database entry and return success */
1470*9e39c5baSBill Taylor *value = entry->tdbe_common.tdb_value;
1471*9e39c5baSBill Taylor
1472*9e39c5baSBill Taylor return (DDI_SUCCESS);
1473*9e39c5baSBill Taylor }
1474*9e39c5baSBill Taylor
1475*9e39c5baSBill Taylor
1476*9e39c5baSBill Taylor /*
1477*9e39c5baSBill Taylor * tavor_umap_umemlock_cb()
1478*9e39c5baSBill Taylor * Context: Can be called from callback context.
1479*9e39c5baSBill Taylor */
1480*9e39c5baSBill Taylor void
tavor_umap_umemlock_cb(ddi_umem_cookie_t * umem_cookie)1481*9e39c5baSBill Taylor tavor_umap_umemlock_cb(ddi_umem_cookie_t *umem_cookie)
1482*9e39c5baSBill Taylor {
1483*9e39c5baSBill Taylor tavor_umap_db_entry_t *umapdb;
1484*9e39c5baSBill Taylor tavor_state_t *state;
1485*9e39c5baSBill Taylor tavor_rsrc_t *rsrcp;
1486*9e39c5baSBill Taylor tavor_mrhdl_t mr;
1487*9e39c5baSBill Taylor uint64_t value;
1488*9e39c5baSBill Taylor uint_t instance;
1489*9e39c5baSBill Taylor int status;
1490*9e39c5baSBill Taylor void (*mr_callback)(void *, void *);
1491*9e39c5baSBill Taylor void *mr_cbarg1, *mr_cbarg2;
1492*9e39c5baSBill Taylor
1493*9e39c5baSBill Taylor /*
1494*9e39c5baSBill Taylor * If this was userland memory, then we need to remove its entry
1495*9e39c5baSBill Taylor * from the "userland resources database". Note: We use the
1496*9e39c5baSBill Taylor * TAVOR_UMAP_DB_IGNORE_INSTANCE flag here because we don't know
1497*9e39c5baSBill Taylor * which instance was used when the entry was added (but we want
1498*9e39c5baSBill Taylor * to know after the entry is found using the other search criteria).
1499*9e39c5baSBill Taylor */
1500*9e39c5baSBill Taylor status = tavor_umap_db_find(0, (uint64_t)(uintptr_t)umem_cookie,
1501*9e39c5baSBill Taylor MLNX_UMAP_MRMEM_RSRC, &value, (TAVOR_UMAP_DB_REMOVE |
1502*9e39c5baSBill Taylor TAVOR_UMAP_DB_IGNORE_INSTANCE), &umapdb);
1503*9e39c5baSBill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*umapdb))
1504*9e39c5baSBill Taylor if (status == DDI_SUCCESS) {
1505*9e39c5baSBill Taylor instance = umapdb->tdbe_common.tdb_instance;
1506*9e39c5baSBill Taylor state = ddi_get_soft_state(tavor_statep, instance);
1507*9e39c5baSBill Taylor if (state == NULL) {
1508*9e39c5baSBill Taylor cmn_err(CE_WARN, "Unable to match Tavor instance\n");
1509*9e39c5baSBill Taylor return;
1510*9e39c5baSBill Taylor }
1511*9e39c5baSBill Taylor
1512*9e39c5baSBill Taylor /* Free the database entry */
1513*9e39c5baSBill Taylor tavor_umap_db_free(umapdb);
1514*9e39c5baSBill Taylor
1515*9e39c5baSBill Taylor /* Use "value" to convert to an MR handle */
1516*9e39c5baSBill Taylor rsrcp = (tavor_rsrc_t *)(uintptr_t)value;
1517*9e39c5baSBill Taylor mr = (tavor_mrhdl_t)rsrcp->tr_addr;
1518*9e39c5baSBill Taylor
1519*9e39c5baSBill Taylor /*
1520*9e39c5baSBill Taylor * If a callback has been provided, call it first. This
1521*9e39c5baSBill Taylor * callback is expected to do any cleanup necessary to
1522*9e39c5baSBill Taylor * guarantee that the subsequent MR deregister (below)
1523*9e39c5baSBill Taylor * will succeed. Specifically, this means freeing up memory
1524*9e39c5baSBill Taylor * windows which might have been associated with the MR.
1525*9e39c5baSBill Taylor */
1526*9e39c5baSBill Taylor mutex_enter(&mr->mr_lock);
1527*9e39c5baSBill Taylor mr_callback = mr->mr_umem_cbfunc;
1528*9e39c5baSBill Taylor mr_cbarg1 = mr->mr_umem_cbarg1;
1529*9e39c5baSBill Taylor mr_cbarg2 = mr->mr_umem_cbarg2;
1530*9e39c5baSBill Taylor mutex_exit(&mr->mr_lock);
1531*9e39c5baSBill Taylor if (mr_callback != NULL) {
1532*9e39c5baSBill Taylor mr_callback(mr_cbarg1, mr_cbarg2);
1533*9e39c5baSBill Taylor }
1534*9e39c5baSBill Taylor
1535*9e39c5baSBill Taylor /*
1536*9e39c5baSBill Taylor * Then call tavor_mr_deregister() to release the resources
1537*9e39c5baSBill Taylor * associated with the MR handle. Note: Because this routine
1538*9e39c5baSBill Taylor * will also check for whether the ddi_umem_cookie_t is in the
1539*9e39c5baSBill Taylor * database, it will take responsibility for disabling the
1540*9e39c5baSBill Taylor * memory region and calling ddi_umem_unlock().
1541*9e39c5baSBill Taylor */
1542*9e39c5baSBill Taylor status = tavor_mr_deregister(state, &mr, TAVOR_MR_DEREG_ALL,
1543*9e39c5baSBill Taylor TAVOR_SLEEP);
1544*9e39c5baSBill Taylor if (status != DDI_SUCCESS) {
1545*9e39c5baSBill Taylor TAVOR_WARNING(state, "Unexpected failure in "
1546*9e39c5baSBill Taylor "deregister from callback\n");
1547*9e39c5baSBill Taylor }
1548*9e39c5baSBill Taylor }
1549*9e39c5baSBill Taylor }
1550*9e39c5baSBill Taylor
1551*9e39c5baSBill Taylor
1552*9e39c5baSBill Taylor /*
1553*9e39c5baSBill Taylor * tavor_umap_db_compare()
1554*9e39c5baSBill Taylor * Context: Can be called from user or kernel context.
1555*9e39c5baSBill Taylor */
1556*9e39c5baSBill Taylor static int
tavor_umap_db_compare(const void * q,const void * e)1557*9e39c5baSBill Taylor tavor_umap_db_compare(const void *q, const void *e)
1558*9e39c5baSBill Taylor {
1559*9e39c5baSBill Taylor tavor_umap_db_common_t *entry_common, *query_common;
1560*9e39c5baSBill Taylor uint_t query_flags;
1561*9e39c5baSBill Taylor
1562*9e39c5baSBill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*((tavor_umap_db_query_t *)q)))
1563*9e39c5baSBill Taylor
1564*9e39c5baSBill Taylor entry_common = &((tavor_umap_db_entry_t *)e)->tdbe_common;
1565*9e39c5baSBill Taylor query_common = &((tavor_umap_db_query_t *)q)->tqdb_common;
1566*9e39c5baSBill Taylor query_flags = ((tavor_umap_db_query_t *)q)->tqdb_flags;
1567*9e39c5baSBill Taylor
1568*9e39c5baSBill Taylor /*
1569*9e39c5baSBill Taylor * The first comparison is done on the "key" value in "query"
1570*9e39c5baSBill Taylor * and "entry". If they are not equal, then the appropriate
1571*9e39c5baSBill Taylor * search direction is returned. Else, we continue by
1572*9e39c5baSBill Taylor * comparing "type".
1573*9e39c5baSBill Taylor */
1574*9e39c5baSBill Taylor if (query_common->tdb_key < entry_common->tdb_key) {
1575*9e39c5baSBill Taylor return (-1);
1576*9e39c5baSBill Taylor } else if (query_common->tdb_key > entry_common->tdb_key) {
1577*9e39c5baSBill Taylor return (+1);
1578*9e39c5baSBill Taylor }
1579*9e39c5baSBill Taylor
1580*9e39c5baSBill Taylor /*
1581*9e39c5baSBill Taylor * If the search reaches this point, then "query" and "entry"
1582*9e39c5baSBill Taylor * have equal key values. So we continue be comparing their
1583*9e39c5baSBill Taylor * "type" values. Again, if they are not equal, then the
1584*9e39c5baSBill Taylor * appropriate search direction is returned. Else, we continue
1585*9e39c5baSBill Taylor * by comparing "instance".
1586*9e39c5baSBill Taylor */
1587*9e39c5baSBill Taylor if (query_common->tdb_type < entry_common->tdb_type) {
1588*9e39c5baSBill Taylor return (-1);
1589*9e39c5baSBill Taylor } else if (query_common->tdb_type > entry_common->tdb_type) {
1590*9e39c5baSBill Taylor return (+1);
1591*9e39c5baSBill Taylor }
1592*9e39c5baSBill Taylor
1593*9e39c5baSBill Taylor /*
1594*9e39c5baSBill Taylor * If the search reaches this point, then "query" and "entry"
1595*9e39c5baSBill Taylor * have exactly the same key and type values. Now we consult
1596*9e39c5baSBill Taylor * the "flags" field in the query to determine whether the
1597*9e39c5baSBill Taylor * "instance" is relevant to the search. If the
1598*9e39c5baSBill Taylor * TAVOR_UMAP_DB_IGNORE_INSTANCE flags is set, then return
1599*9e39c5baSBill Taylor * success (0) here. Otherwise, continue the search by comparing
1600*9e39c5baSBill Taylor * instance values and returning the appropriate search direction.
1601*9e39c5baSBill Taylor */
1602*9e39c5baSBill Taylor if (query_flags & TAVOR_UMAP_DB_IGNORE_INSTANCE) {
1603*9e39c5baSBill Taylor return (0);
1604*9e39c5baSBill Taylor }
1605*9e39c5baSBill Taylor
1606*9e39c5baSBill Taylor /*
1607*9e39c5baSBill Taylor * If the search has reached this point, then "query" and "entry"
1608*9e39c5baSBill Taylor * can only be differentiated by their instance values. If these
1609*9e39c5baSBill Taylor * are not equal, then return the appropriate search direction.
1610*9e39c5baSBill Taylor * Else, we return success (0).
1611*9e39c5baSBill Taylor */
1612*9e39c5baSBill Taylor if (query_common->tdb_instance < entry_common->tdb_instance) {
1613*9e39c5baSBill Taylor return (-1);
1614*9e39c5baSBill Taylor } else if (query_common->tdb_instance > entry_common->tdb_instance) {
1615*9e39c5baSBill Taylor return (+1);
1616*9e39c5baSBill Taylor }
1617*9e39c5baSBill Taylor
1618*9e39c5baSBill Taylor /* Everything matches... so return success */
1619*9e39c5baSBill Taylor return (0);
1620*9e39c5baSBill Taylor }
1621*9e39c5baSBill Taylor
1622*9e39c5baSBill Taylor
1623*9e39c5baSBill Taylor /*
1624*9e39c5baSBill Taylor * tavor_umap_db_set_onclose_cb()
1625*9e39c5baSBill Taylor * Context: Can be called from user or kernel context.
1626*9e39c5baSBill Taylor */
1627*9e39c5baSBill Taylor int
tavor_umap_db_set_onclose_cb(dev_t dev,uint64_t flag,void (* callback)(void *),void * arg)1628*9e39c5baSBill Taylor tavor_umap_db_set_onclose_cb(dev_t dev, uint64_t flag,
1629*9e39c5baSBill Taylor void (*callback)(void *), void *arg)
1630*9e39c5baSBill Taylor {
1631*9e39c5baSBill Taylor tavor_umap_db_priv_t *priv;
1632*9e39c5baSBill Taylor tavor_umap_db_entry_t *umapdb;
1633*9e39c5baSBill Taylor minor_t instance;
1634*9e39c5baSBill Taylor uint64_t value;
1635*9e39c5baSBill Taylor int status;
1636*9e39c5baSBill Taylor
1637*9e39c5baSBill Taylor instance = TAVOR_DEV_INSTANCE(dev);
1638*9e39c5baSBill Taylor if (instance == -1) {
1639*9e39c5baSBill Taylor return (DDI_FAILURE);
1640*9e39c5baSBill Taylor }
1641*9e39c5baSBill Taylor
1642*9e39c5baSBill Taylor if (flag != TAVOR_ONCLOSE_FLASH_INPROGRESS) {
1643*9e39c5baSBill Taylor return (DDI_FAILURE);
1644*9e39c5baSBill Taylor }
1645*9e39c5baSBill Taylor
1646*9e39c5baSBill Taylor /*
1647*9e39c5baSBill Taylor * Grab the lock for the "userland resources database" and find
1648*9e39c5baSBill Taylor * the entry corresponding to this minor number. Once it's found,
1649*9e39c5baSBill Taylor * allocate (if necessary) and add an entry (in the "tdb_priv"
1650*9e39c5baSBill Taylor * field) to indicate that further processing may be needed during
1651*9e39c5baSBill Taylor * Tavor's close() handling.
1652*9e39c5baSBill Taylor */
1653*9e39c5baSBill Taylor mutex_enter(&tavor_userland_rsrc_db.tdl_umapdb_lock);
1654*9e39c5baSBill Taylor status = tavor_umap_db_find_nolock(instance, dev,
1655*9e39c5baSBill Taylor MLNX_UMAP_PID_RSRC, &value, 0, &umapdb);
1656*9e39c5baSBill Taylor if (status != DDI_SUCCESS) {
1657*9e39c5baSBill Taylor mutex_exit(&tavor_userland_rsrc_db.tdl_umapdb_lock);
1658*9e39c5baSBill Taylor return (DDI_FAILURE);
1659*9e39c5baSBill Taylor }
1660*9e39c5baSBill Taylor
1661*9e39c5baSBill Taylor priv = (tavor_umap_db_priv_t *)umapdb->tdbe_common.tdb_priv;
1662*9e39c5baSBill Taylor if (priv == NULL) {
1663*9e39c5baSBill Taylor priv = (tavor_umap_db_priv_t *)kmem_zalloc(
1664*9e39c5baSBill Taylor sizeof (tavor_umap_db_priv_t), KM_NOSLEEP);
1665*9e39c5baSBill Taylor if (priv == NULL) {
1666*9e39c5baSBill Taylor mutex_exit(&tavor_userland_rsrc_db.tdl_umapdb_lock);
1667*9e39c5baSBill Taylor return (DDI_FAILURE);
1668*9e39c5baSBill Taylor }
1669*9e39c5baSBill Taylor }
1670*9e39c5baSBill Taylor
1671*9e39c5baSBill Taylor /*
1672*9e39c5baSBill Taylor * Save away the callback and argument to be used during Tavor's
1673*9e39c5baSBill Taylor * close() processing.
1674*9e39c5baSBill Taylor */
1675*9e39c5baSBill Taylor priv->tdp_cb = callback;
1676*9e39c5baSBill Taylor priv->tdp_arg = arg;
1677*9e39c5baSBill Taylor
1678*9e39c5baSBill Taylor umapdb->tdbe_common.tdb_priv = (void *)priv;
1679*9e39c5baSBill Taylor mutex_exit(&tavor_userland_rsrc_db.tdl_umapdb_lock);
1680*9e39c5baSBill Taylor
1681*9e39c5baSBill Taylor return (DDI_SUCCESS);
1682*9e39c5baSBill Taylor }
1683*9e39c5baSBill Taylor
1684*9e39c5baSBill Taylor
1685*9e39c5baSBill Taylor /*
1686*9e39c5baSBill Taylor * tavor_umap_db_clear_onclose_cb()
1687*9e39c5baSBill Taylor * Context: Can be called from user or kernel context.
1688*9e39c5baSBill Taylor */
1689*9e39c5baSBill Taylor int
tavor_umap_db_clear_onclose_cb(dev_t dev,uint64_t flag)1690*9e39c5baSBill Taylor tavor_umap_db_clear_onclose_cb(dev_t dev, uint64_t flag)
1691*9e39c5baSBill Taylor {
1692*9e39c5baSBill Taylor tavor_umap_db_priv_t *priv;
1693*9e39c5baSBill Taylor tavor_umap_db_entry_t *umapdb;
1694*9e39c5baSBill Taylor minor_t instance;
1695*9e39c5baSBill Taylor uint64_t value;
1696*9e39c5baSBill Taylor int status;
1697*9e39c5baSBill Taylor
1698*9e39c5baSBill Taylor instance = TAVOR_DEV_INSTANCE(dev);
1699*9e39c5baSBill Taylor if (instance == -1) {
1700*9e39c5baSBill Taylor return (DDI_FAILURE);
1701*9e39c5baSBill Taylor }
1702*9e39c5baSBill Taylor
1703*9e39c5baSBill Taylor if (flag != TAVOR_ONCLOSE_FLASH_INPROGRESS) {
1704*9e39c5baSBill Taylor return (DDI_FAILURE);
1705*9e39c5baSBill Taylor }
1706*9e39c5baSBill Taylor
1707*9e39c5baSBill Taylor /*
1708*9e39c5baSBill Taylor * Grab the lock for the "userland resources database" and find
1709*9e39c5baSBill Taylor * the entry corresponding to this minor number. Once it's found,
1710*9e39c5baSBill Taylor * remove the entry (in the "tdb_priv" field) that indicated the
1711*9e39c5baSBill Taylor * need for further processing during Tavor's close(). Free the
1712*9e39c5baSBill Taylor * entry, if appropriate.
1713*9e39c5baSBill Taylor */
1714*9e39c5baSBill Taylor mutex_enter(&tavor_userland_rsrc_db.tdl_umapdb_lock);
1715*9e39c5baSBill Taylor status = tavor_umap_db_find_nolock(instance, dev,
1716*9e39c5baSBill Taylor MLNX_UMAP_PID_RSRC, &value, 0, &umapdb);
1717*9e39c5baSBill Taylor if (status != DDI_SUCCESS) {
1718*9e39c5baSBill Taylor mutex_exit(&tavor_userland_rsrc_db.tdl_umapdb_lock);
1719*9e39c5baSBill Taylor return (DDI_FAILURE);
1720*9e39c5baSBill Taylor }
1721*9e39c5baSBill Taylor
1722*9e39c5baSBill Taylor priv = (tavor_umap_db_priv_t *)umapdb->tdbe_common.tdb_priv;
1723*9e39c5baSBill Taylor if (priv != NULL) {
1724*9e39c5baSBill Taylor kmem_free(priv, sizeof (tavor_umap_db_priv_t));
1725*9e39c5baSBill Taylor priv = NULL;
1726*9e39c5baSBill Taylor }
1727*9e39c5baSBill Taylor
1728*9e39c5baSBill Taylor umapdb->tdbe_common.tdb_priv = (void *)priv;
1729*9e39c5baSBill Taylor mutex_exit(&tavor_userland_rsrc_db.tdl_umapdb_lock);
1730*9e39c5baSBill Taylor return (DDI_SUCCESS);
1731*9e39c5baSBill Taylor }
1732*9e39c5baSBill Taylor
1733*9e39c5baSBill Taylor
1734*9e39c5baSBill Taylor /*
1735*9e39c5baSBill Taylor * tavor_umap_db_clear_onclose_cb()
1736*9e39c5baSBill Taylor * Context: Can be called from user or kernel context.
1737*9e39c5baSBill Taylor */
1738*9e39c5baSBill Taylor void
tavor_umap_db_handle_onclose_cb(tavor_umap_db_priv_t * priv)1739*9e39c5baSBill Taylor tavor_umap_db_handle_onclose_cb(tavor_umap_db_priv_t *priv)
1740*9e39c5baSBill Taylor {
1741*9e39c5baSBill Taylor void (*callback)(void *);
1742*9e39c5baSBill Taylor
1743*9e39c5baSBill Taylor ASSERT(MUTEX_HELD(&tavor_userland_rsrc_db.tdl_umapdb_lock));
1744*9e39c5baSBill Taylor
1745*9e39c5baSBill Taylor /*
1746*9e39c5baSBill Taylor * Call the callback.
1747*9e39c5baSBill Taylor * Note: Currently there is only one callback (in "tdp_cb"), but
1748*9e39c5baSBill Taylor * in the future there may be more, depending on what other types
1749*9e39c5baSBill Taylor * of interaction there are between userland processes and the
1750*9e39c5baSBill Taylor * driver.
1751*9e39c5baSBill Taylor */
1752*9e39c5baSBill Taylor callback = priv->tdp_cb;
1753*9e39c5baSBill Taylor callback(priv->tdp_arg);
1754*9e39c5baSBill Taylor }
1755