xref: /illumos-gate/usr/src/uts/common/io/ib/ibtl/ibtl_mem.c (revision 43ed929a6988c3778f00123f4a4a8541e515ec16)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/ib/ibtl/impl/ibtl.h>
30 
31 /*
32  * ibtl_mem.c
33  *    These routines implement all of the Memory Region verbs and the alloc/
34  *    query/free Memory Window verbs at the TI interface.
35  */
36 
37 static char ibtl_mem[] = "ibtl_mem";
38 
39 /*
40  * Function:
41  *	ibt_register_mr()
42  * Input:
43  *	hca_hdl   - HCA Handle.
44  *	pd        - Protection Domain Handle.
45  *	mem_attr  - Requested memory region attributes.
46  * Output:
47  *	mr_hdl_p  - The returned IBT memory region handle.
48  *	mem_desc  - Returned memory descriptor.
49  * Returns:
50  *      IBT_SUCCESS
51  *	IBT_CHAN_HDL_INVALID
52  *	IBT_MR_VA_INVALID
53  *	IBT_MR_LEN_INVALID
54  *	IBT_MR_ACCESS_REQ_INVALID
55  *	IBT_PD_HDL_INVALID
56  *	IBT_INSUFF_RESOURCE
57  * Description:
58  *    Prepares a virtually addressed memory region for use by a HCA. A
59  *    description of the registered memory suitable for use in Work Requests
60  *    (WRs) is returned in the ibt_mr_desc_t parameter.
61  */
62 ibt_status_t
63 ibt_register_mr(ibt_hca_hdl_t hca_hdl, ibt_pd_hdl_t pd, ibt_mr_attr_t *mem_attr,
64     ibt_mr_hdl_t *mr_hdl_p, ibt_mr_desc_t *mem_desc)
65 {
66 	ib_vaddr_t 	vaddr;
67 	ibt_status_t 	status;
68 
69 	IBTF_DPRINTF_L3(ibtl_mem, "ibt_register_mr(%p, %p, %p)",
70 	    hca_hdl, pd, mem_attr);
71 
72 	vaddr = mem_attr->mr_vaddr;
73 
74 	status = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_register_mr(
75 	    IBTL_HCA2CIHCA(hca_hdl), pd, mem_attr, IBTL_HCA2CLNT(hca_hdl),
76 	    mr_hdl_p, mem_desc);
77 	if (status == IBT_SUCCESS) {
78 		mem_desc->md_vaddr = vaddr;
79 		mutex_enter(&hca_hdl->ha_mutex);
80 		hca_hdl->ha_mr_cnt++;
81 		mutex_exit(&hca_hdl->ha_mutex);
82 	}
83 
84 	return (status);
85 }
86 
87 
88 /*
89  * Function:
90  *	ibt_register_buf()
91  * Input:
92  *	hca_hdl		HCA Handle.
93  *	pd		Protection Domain Handle.
94  *	mem_bpattr	Memory Registration attributes (IOVA and flags).
95  *	bp		A pointer to a buf(9S) struct.
96  * Output:
97  *	mr_hdl_p	The returned IBT memory region handle.
98  *	mem_desc	Returned memory descriptor.
99  * Returns:
100  *      IBT_SUCCESS
101  *	IBT_CHAN_HDL_INVALID
102  *	IBT_MR_VA_INVALID
103  *	IBT_MR_LEN_INVALID
104  *	IBT_MR_ACCESS_REQ_INVALID
105  *	IBT_PD_HDL_INVALID
106  *	IBT_INSUFF_RESOURCE
107  * Description:
108  *	Prepares a memory region described by a buf(9S) struct for use by a HCA.
109  *	A description of the registered memory suitable for use in
110  *	Work Requests (WRs) is returned in the ibt_mr_desc_t parameter.
111  */
112 ibt_status_t
113 ibt_register_buf(ibt_hca_hdl_t hca_hdl, ibt_pd_hdl_t pd,
114     ibt_smr_attr_t *mem_bpattr, struct buf *bp, ibt_mr_hdl_t *mr_hdl_p,
115     ibt_mr_desc_t *mem_desc)
116 {
117 	ibt_status_t 	status;
118 
119 	IBTF_DPRINTF_L3(ibtl_mem, "ibt_register_buf(%p, %p, %p, %p)",
120 	    hca_hdl, pd, mem_bpattr, bp);
121 
122 	status = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_register_buf(
123 	    IBTL_HCA2CIHCA(hca_hdl), pd, mem_bpattr, bp, IBTL_HCA2CLNT(hca_hdl),
124 	    mr_hdl_p, mem_desc);
125 	if (status == IBT_SUCCESS) {
126 		mutex_enter(&hca_hdl->ha_mutex);
127 		hca_hdl->ha_mr_cnt++;
128 		mutex_exit(&hca_hdl->ha_mutex);
129 	}
130 
131 	return (status);
132 }
133 
134 
135 /*
136  * Function:
137  *	ibt_query_mr()
138  * Input:
139  *	hca_hdl   - HCA Handle.
140  *	mr_hdl    - The IBT Memory Region handle.
141  * Output:
142  *      attr      - The pointer to Memory region attributes structure.
143  * Returns:
144  *      IBT_SUCCESS
145  *	IBT_CHAN_HDL_INVALID
146  *	IBT_MR_HDL_INVALID
147  * Description:
148  *    Retrieves information about a specified memory region.
149  */
150 ibt_status_t
151 ibt_query_mr(ibt_hca_hdl_t hca_hdl, ibt_mr_hdl_t mr_hdl,
152     ibt_mr_query_attr_t *attr)
153 {
154 	IBTF_DPRINTF_L3(ibtl_mem, "ibt_query_mr(%p, %p)", hca_hdl, mr_hdl);
155 
156 	return (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_query_mr(
157 	    IBTL_HCA2CIHCA(hca_hdl), mr_hdl, attr));
158 }
159 
160 
161 /*
162  * Function:
163  *	ibt_deregister_mr()
164  * Input:
165  *	hca_hdl   - HCA Handle.
166  *	mr_hdl    - The IBT Memory Region handle.
167  * Output:
168  *      none.
169  * Returns:
170  *      IBT_SUCCESS
171  *	IBT_CHAN_HDL_INVALID
172  *	IBT_MR_HDL_INVALID
173  *	IBT_MR_IN_USE
174  * Description:
175  *    De-register the registered memory region. Remove a memory region from a
176  *    HCA translation table, and free all resources associated with the
177  *    memory region.
178  */
179 ibt_status_t
180 ibt_deregister_mr(ibt_hca_hdl_t hca_hdl, ibt_mr_hdl_t mr_hdl)
181 {
182 	ibt_status_t 	status;
183 
184 	IBTF_DPRINTF_L3(ibtl_mem, "ibt_deregister_mr(%p, %p)", hca_hdl, mr_hdl);
185 
186 	status = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_deregister_mr(
187 	    IBTL_HCA2CIHCA(hca_hdl), mr_hdl);
188 	if (status == IBT_SUCCESS) {
189 		mutex_enter(&hca_hdl->ha_mutex);
190 		hca_hdl->ha_mr_cnt--;
191 		mutex_exit(&hca_hdl->ha_mutex);
192 	}
193 	return (status);
194 }
195 
196 
197 /*
198  * Function:
199  *	ibt_reregister_mr()
200  * Input:
201  *	hca_hdl   - HCA Handle.
202  *	mr_hdl    - The IBT Memory Region handle.
203  *	pd        - Optional Protection Domain Handle.
204  *	mem_attr  - Requested memory region attributes.
205  * Output:
206  *	mr_hdl_p  - The reregistered IBT memory region handle.
207  *	mem_desc  - Returned memory descriptor for the new memory region.
208  * Returns:
209  *      IBT_SUCCESS
210  *	IBT_CHAN_HDL_INVALID
211  *	IBT_MR_HDL_INVALID
212  *	IBT_MR_VA_INVALID
213  *	IBT_MR_LEN_INVALID
214  *	IBT_MR_ACCESS_REQ_INVALID
215  *	IBT_PD_HDL_INVALID
216  *	IBT_INSUFF_RESOURCE
217  *	IBT_MR_IN_USE
218  * Description:
219  *    Modify the attributes of an existing memory region.
220  */
221 ibt_status_t
222 ibt_reregister_mr(ibt_hca_hdl_t hca_hdl, ibt_mr_hdl_t mr_hdl, ibt_pd_hdl_t pd,
223     ibt_mr_attr_t *mem_attr, ibt_mr_hdl_t *mr_hdl_p, ibt_mr_desc_t *mem_desc)
224 {
225 	ibt_status_t 	status;
226 	ib_vaddr_t 	vaddr = mem_attr->mr_vaddr;
227 
228 	IBTF_DPRINTF_L3(ibtl_mem, "ibt_reregister_mr(%p, %p, %p, %p)",
229 	    hca_hdl, mr_hdl, pd, mem_attr);
230 
231 	status = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_reregister_mr(
232 	    IBTL_HCA2CIHCA(hca_hdl), mr_hdl, pd, mem_attr,
233 	    IBTL_HCA2CLNT(hca_hdl), mr_hdl_p, mem_desc);
234 
235 	if (status == IBT_SUCCESS)
236 		mem_desc->md_vaddr = vaddr;
237 	else if (!(status == IBT_MR_IN_USE || status == IBT_HCA_HDL_INVALID ||
238 	    status == IBT_MR_HDL_INVALID)) {
239 
240 		IBTF_DPRINTF_L2(ibtl_mem, "ibt_reregister_mr: "
241 		    "Re-registration Failed: %d", status);
242 
243 		/* we lost one memory region resource */
244 		mutex_enter(&hca_hdl->ha_mutex);
245 		hca_hdl->ha_mr_cnt--;
246 		mutex_exit(&hca_hdl->ha_mutex);
247 	}
248 
249 	return (status);
250 }
251 
252 
253 /*
254  * Function:
255  *	ibt_reregister_buf()
256  * Input:
257  *	hca_hdl		HCA Handle.
258  *	mr_hdl		The IBT Memory Region handle.
259  *	pd		Optional Protection Domain Handle.
260  *	mem_bpattr	Memory Registration attributes (IOVA and flags).
261  *	bp		A pointer to a buf(9S) struct.
262  * Output:
263  *	mr_hdl_p	The reregistered IBT memory region handle.
264  *	mem_desc	Returned memory descriptor for the new memory region.
265  * Returns:
266  *      IBT_SUCCESS
267  *	IBT_CHAN_HDL_INVALID
268  *	IBT_MR_HDL_INVALID
269  *	IBT_MR_VA_INVALID
270  *	IBT_MR_LEN_INVALID
271  *	IBT_MR_ACCESS_REQ_INVALID
272  *	IBT_PD_HDL_INVALID
273  *	IBT_INSUFF_RESOURCE
274  *	IBT_MR_IN_USE
275  * Description:
276  *	Modify the attributes of an existing memory region as described by a
277  *	buf(9S) struct for use by a HCA.  A description of the registered
278  *	memory suitable for use in Work Requests (WRs) is returned in the
279  *	ibt_mr_desc_t parameter.
280  */
281 ibt_status_t
282 ibt_reregister_buf(ibt_hca_hdl_t hca_hdl, ibt_mr_hdl_t mr_hdl,
283     ibt_pd_hdl_t pd, ibt_smr_attr_t *mem_bpattr, struct buf *bp,
284     ibt_mr_hdl_t *mr_hdl_p, ibt_mr_desc_t *mem_desc)
285 {
286 	ibt_status_t 		status;
287 
288 	IBTF_DPRINTF_L3(ibtl_mem, "ibt_reregister_buf(%p, %p, %p, %p, %p)",
289 	    hca_hdl, mr_hdl, pd, mem_bpattr, bp);
290 
291 	status = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_reregister_buf(
292 	    IBTL_HCA2CIHCA(hca_hdl), mr_hdl, pd, mem_bpattr, bp,
293 	    IBTL_HCA2CLNT(hca_hdl), mr_hdl_p, mem_desc);
294 
295 	if (!(status == IBT_SUCCESS || status == IBT_MR_IN_USE ||
296 	    status == IBT_HCA_HDL_INVALID || status == IBT_MR_HDL_INVALID)) {
297 
298 		IBTF_DPRINTF_L2(ibtl_mem, "ibt_reregister_buf: "
299 		    "Re-registration Mem Failed: %d", status);
300 
301 		/* we lost one memory region resource */
302 		mutex_enter(&hca_hdl->ha_mutex);
303 		hca_hdl->ha_mr_cnt--;
304 		mutex_exit(&hca_hdl->ha_mutex);
305 	}
306 	return (status);
307 }
308 
309 
310 /*
311  * Function:
312  *	ibt_register_shared_mr()
313  * Input:
314  *	hca_hdl   - HCA Handle.
315  *	mr_hdl    - The IBT Memory Region handle.
316  *	pd        - Protection Domain Handle.
317  *	mem_sattr - Requested memory region shared attributes.
318  * Output:
319  *	mr_hdl_p  - The reregistered IBT memory region handle.
320  *	mem_desc  - Returned memory descriptor for the new memory region.
321  * Returns:
322  *      IBT_SUCCESS
323  *	IBT_INSUFF_RESOURCE
324  *	IBT_CHAN_HDL_INVALID
325  *	IBT_MR_HDL_INVALID
326  *	IBT_PD_HDL_INVALID
327  *	IBT_MR_ACCESS_REQ_INVALID
328  * Description:
329  *    Given an existing memory region, a new memory region associated with
330  *    the same physical locations is created.
331  */
332 ibt_status_t
333 ibt_register_shared_mr(ibt_hca_hdl_t hca_hdl, ibt_mr_hdl_t mr_hdl,
334     ibt_pd_hdl_t pd, ibt_smr_attr_t *mem_sattr, ibt_mr_hdl_t *mr_hdl_p,
335     ibt_mr_desc_t *mem_desc)
336 {
337 	ibt_status_t		status;
338 
339 	IBTF_DPRINTF_L3(ibtl_mem, "ibt_register_shared_mr(%p, %p, %p, %p)",
340 	    hca_hdl, mr_hdl, pd, mem_sattr);
341 
342 	status = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_register_shared_mr(
343 	    IBTL_HCA2CIHCA(hca_hdl), mr_hdl, pd, mem_sattr,
344 	    IBTL_HCA2CLNT(hca_hdl), mr_hdl_p, mem_desc);
345 	if (status == IBT_SUCCESS) {
346 		mutex_enter(&hca_hdl->ha_mutex);
347 		hca_hdl->ha_mr_cnt++;
348 		mutex_exit(&hca_hdl->ha_mutex);
349 	}
350 	return (status);
351 }
352 
353 /*
354  * Function:
355  *	ibt_sync_mr()
356  * Input:
357  *	hca_hdl		- HCA Handle.
358  *	mr_segments	- A pointer to an array of ibt_mr_sync_t that describes
359  *			  the memory regions to sync.
360  *	num_segments	- The length of the mr_segments array.
361  * Output:
362  *	NONE
363  * Returns:
364  *      IBT_SUCCESS
365  *	IBT_HCA_HDL_INVALID
366  *	IBT_MR_HDL_INVALID
367  *	IBT_INVALID_PARAM
368  *	IBT_MR_VA_INVALID
369  *	IBT_MR_LEN_INVALID
370  * Description:
371  *	Make memory changes visible to incoming RDMA reads, or make the affects
372  *	of an incoming RDMA writes visible to the consumer.
373  */
374 ibt_status_t
375 ibt_sync_mr(ibt_hca_hdl_t hca_hdl, ibt_mr_sync_t *mr_segments,
376     size_t num_segments)
377 
378 {
379 	IBTF_DPRINTF_L3(ibtl_mem, "ibt_sync_mr(%p, %p, %d)", hca_hdl,
380 	    mr_segments, num_segments);
381 
382 	return (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_sync_mr(
383 	    IBTL_HCA2CIHCA(hca_hdl), mr_segments, num_segments));
384 }
385 
386 
387 /*
388  * Function:
389  *	ibt_alloc_mw()
390  * Input:
391  *	hca_hdl   - HCA Handle.
392  *	pd        - Protection Domain Handle.
393  *	flags     - Memory Window alloc flags.
394  * Output:
395  *	mw_hdl_p  - The returned IBT Memory Window handle.
396  *	rkey      - The IBT R_Key handle.
397  * Returns:
398  *      IBT_SUCCESS
399  *	IBT_INSUFF_RESOURCE
400  *	IBT_CHAN_HDL_INVALID
401  *	IBT_PD_HDL_INVALID
402  * Description:
403  *    Allocate a memory window from the HCA.
404  */
405 ibt_status_t
406 ibt_alloc_mw(ibt_hca_hdl_t hca_hdl, ibt_pd_hdl_t pd, ibt_mw_flags_t flags,
407     ibt_mw_hdl_t *mw_hdl_p, ibt_rkey_t *rkey)
408 {
409 	ibt_status_t		status;
410 
411 	IBTF_DPRINTF_L3(ibtl_mem, "ibt_alloc_mw(%p, %p, 0x%x)",
412 	    hca_hdl, pd, flags);
413 
414 	status = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_mw(
415 	    IBTL_HCA2CIHCA(hca_hdl), pd, flags, mw_hdl_p, rkey);
416 
417 	/*
418 	 * XXX - We should be able to allocate state and have a IBTF Memory
419 	 * Window Handle. Memory Windows are meant to be rebound on the fly
420 	 * (using a post) to make them fast. It is expected that alloc memory
421 	 * window will be done in a relatively static manner. But, we don't have
422 	 * a good reason to have local MW state at this point, so we won't.
423 	 */
424 	if (status == IBT_SUCCESS) {
425 		mutex_enter(&hca_hdl->ha_mutex);
426 		hca_hdl->ha_mw_cnt++;
427 		mutex_exit(&hca_hdl->ha_mutex);
428 	}
429 	return (status);
430 }
431 
432 
433 /*
434  * Function:
435  *	ibt_query_mw()
436  * Input:
437  *	hca_hdl   - HCA Handle.
438  *	mw_hdl    - The IBT Memory Window handle.
439  * Output:
440  *	pd        - Protection Domain Handle.
441  *	rkey      - The IBT R_Key handle.
442  * Returns:
443  *      IBT_SUCCESS
444  *	IBT_CHAN_HDL_INVALID
445  *	IBT_MW_HDL_INVALID
446  * Description:
447  *    Retrieves information about a specified memory region.
448  */
449 ibt_status_t
450 ibt_query_mw(ibt_hca_hdl_t hca_hdl, ibt_mw_hdl_t mw_hdl,
451     ibt_mw_query_attr_t *mw_attr_p)
452 {
453 	IBTF_DPRINTF_L3(ibtl_mem, "ibt_query_mw(%p, %p)", hca_hdl, mw_hdl);
454 
455 	return (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_query_mw(
456 	    IBTL_HCA2CIHCA(hca_hdl), mw_hdl, mw_attr_p));
457 }
458 
459 
460 /*
461  * Function:
462  *	ibt_free_mw()
463  * Input:
464  *      hca_hdl   - HCA Handle
465  *	mw_hdl    - The IBT Memory Window handle.
466  * Output:
467  *	none.
468  * Returns:
469  *      IBT_SUCCESS
470  *	IBT_CHAN_HDL_INVALID
471  *	IBT_MW_HDL_INVALID
472  * Description:
473  *    De-allocate the Memory Window.
474  */
475 ibt_status_t
476 ibt_free_mw(ibt_hca_hdl_t hca_hdl, ibt_mw_hdl_t mw_hdl)
477 {
478 	ibt_status_t		status;
479 
480 	IBTF_DPRINTF_L3(ibtl_mem, "ibt_free_mw(%p, %p)", hca_hdl, mw_hdl);
481 
482 	status = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_free_mw(
483 	    IBTL_HCA2CIHCA(hca_hdl), mw_hdl);
484 
485 	if (status == IBT_SUCCESS) {
486 		mutex_enter(&hca_hdl->ha_mutex);
487 		hca_hdl->ha_mw_cnt--;
488 		mutex_exit(&hca_hdl->ha_mutex);
489 	}
490 	return (status);
491 }
492 
493 
494 /*
495  * Function:
496  *	ibt_map_mem_area()
497  * Input:
498  *      hca_hdl		HCA Handle
499  *	va_attrs	A pointer to an ibt_va_attr_t that describes the
500  *			VA to be translated.
501  *	paddr_list_len	The number of entries in the 'paddr_list_p' array.
502  * Output:
503  *	paddr_list_p	Array of ibt_phys_buf_t (allocated by the caller),
504  *			in which the physical buffers that map the virtual
505  *			buffer are returned.
506  *	num_paddr_p	The actual number of ibt_phys_buf_t that were
507  *			returned in the 'paddr_list_p' array.
508  *	ma_hdl_p	Memory Area Handle.
509  * Returns:
510  *      IBT_SUCCESS
511  * Description:
512  * 	Translate a kernel virtual address range into HCA physical addresses.
513  *	A set of physical addresses, that can be used with "Reserved L_Key",
514  *	register physical,  and "Fast Registration Work Request" operations
515  *	is returned.
516  */
517 ibt_status_t
518 ibt_map_mem_area(ibt_hca_hdl_t hca_hdl, ibt_va_attr_t *va_attrs,
519     uint_t paddr_list_len, ibt_phys_buf_t *paddr_list_p, uint_t *num_paddr_p,
520     size_t *paddr_bufsz_p, ib_memlen_t *paddr_offset_p, ibt_ma_hdl_t *ma_hdl_p)
521 {
522 	ibt_status_t 	status;
523 
524 	IBTF_DPRINTF_L3(ibtl_mem, "ibt_map_mem_area(%p, %p, %d)",
525 	    hca_hdl, va_attrs, paddr_list_len);
526 
527 	status = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_map_mem_area(
528 	    IBTL_HCA2CIHCA(hca_hdl), va_attrs,
529 	    NULL, /* IBTL_HCA2MODI_P(hca_hdl)->mi_reserved */
530 	    paddr_list_len, paddr_list_p, num_paddr_p,  paddr_bufsz_p,
531 	    paddr_offset_p, ma_hdl_p);
532 	if (status == IBT_SUCCESS) {
533 		mutex_enter(&hca_hdl->ha_mutex);
534 		hca_hdl->ha_ma_cnt++;
535 		mutex_exit(&hca_hdl->ha_mutex);
536 	}
537 
538 	return (status);
539 }
540 
541 
542 /*
543  * Function:
544  *	ibt_unmap_mem_area()
545  * Input:
546  *      hca_hdl		HCA Handle
547  *	ma_hdl		Memory Area Handle.
548  * Output:
549  *	None.
550  * Returns:
551  *      IBT_SUCCESS
552  * Description:
553  * 	Un pin physical pages pinned during an ibt_map_mem_area() call.
554  */
555 ibt_status_t
556 ibt_unmap_mem_area(ibt_hca_hdl_t hca_hdl, ibt_ma_hdl_t ma_hdl)
557 {
558 	ibt_status_t 	status;
559 
560 	IBTF_DPRINTF_L3(ibtl_mem, "ibt_unmap_mem_area(%p, %p)",
561 	    hca_hdl, ma_hdl);
562 
563 	status = (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_unmap_mem_area(
564 	    IBTL_HCA2CIHCA(hca_hdl), ma_hdl));
565 	if (status == IBT_SUCCESS) {
566 		mutex_enter(&hca_hdl->ha_mutex);
567 		hca_hdl->ha_ma_cnt--;
568 		mutex_exit(&hca_hdl->ha_mutex);
569 	}
570 
571 	return (status);
572 }
573 
574 
575 /*
576  * Function:
577  *	ibt_alloc_lkey()
578  * Input:
579  *      hca_hdl			HCA Handle
580  *	pd			A protection domain handle.
581  *	flags			Access control.
582  *	phys_buf_list_sz	Requested size of Physical Buffer List (PBL)
583  *				resources to be allocated.
584  * Output:
585  *	mr_hdl_p		The returned IBT memory region handle.
586  *	mem_desc_p		Returned memory descriptor.
587  * Returns:
588  *      IBT_SUCCESS
589  * Description:
590  * 	Allocates physical buffer list resources for use in memory
591  *	registrations.
592  */
593 ibt_status_t
594 ibt_alloc_lkey(ibt_hca_hdl_t hca_hdl, ibt_pd_hdl_t pd, ibt_lkey_flags_t flags,
595     uint_t phys_buf_list_sz, ibt_mr_hdl_t *mr_hdl_p,
596     ibt_pmr_desc_t *mem_desc_p)
597 {
598 	ibt_status_t 	status;
599 
600 	IBTF_DPRINTF_L3(ibtl_mem, "ibt_alloc_lkey(%p, %p, 0x%X, %d)",
601 	    hca_hdl, pd, flags, phys_buf_list_sz);
602 
603 	status = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_lkey(
604 	    IBTL_HCA2CIHCA(hca_hdl), pd, flags, phys_buf_list_sz, mr_hdl_p,
605 	    mem_desc_p);
606 	if (status == IBT_SUCCESS) {
607 		mutex_enter(&hca_hdl->ha_mutex);
608 		hca_hdl->ha_mr_cnt++;
609 		mutex_exit(&hca_hdl->ha_mutex);
610 	}
611 
612 	return (status);
613 }
614 
615 
616 /*
617  * Function:
618  *	ibt_register_phys_mr()
619  * Input:
620  *      hca_hdl		HCA Handle
621  *	pd		A protection domain handle.
622  *	mem_pattr	Requested memory region physical attributes.
623  * Output:
624  *	mr_hdl_p	The returned IBT memory region handle.
625  *	mem_desc_p	Returned memory descriptor.
626  * Returns:
627  *      IBT_SUCCESS
628  * Description:
629  * 	Prepares a physically addressed memory region for use by a HCA.
630  */
631 ibt_status_t
632 ibt_register_phys_mr(ibt_hca_hdl_t hca_hdl, ibt_pd_hdl_t pd,
633     ibt_pmr_attr_t *mem_pattr, ibt_mr_hdl_t *mr_hdl_p,
634     ibt_pmr_desc_t *mem_desc_p)
635 {
636 	ibt_status_t 	status;
637 
638 	IBTF_DPRINTF_L3(ibtl_mem, "ibt_register_phys_mr(%p, %p, %p)",
639 	    hca_hdl, pd, mem_pattr);
640 
641 	status = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_register_physical_mr(
642 	    IBTL_HCA2CIHCA(hca_hdl), pd, mem_pattr,
643 	    NULL, /* IBTL_HCA2MODI_P(hca_hdl)->mi_reserved */
644 	    mr_hdl_p, mem_desc_p);
645 	if (status == IBT_SUCCESS) {
646 		mutex_enter(&hca_hdl->ha_mutex);
647 		hca_hdl->ha_mr_cnt++;
648 		mutex_exit(&hca_hdl->ha_mutex);
649 	}
650 
651 	return (status);
652 }
653 
654 
655 /*
656  * Function:
657  *	ibt_reregister_phys_mr()
658  * Input:
659  *      hca_hdl		HCA Handle
660  *	mr_hdl		The IBT memory region handle.
661  *	pd		A protection domain handle.
662  *	mem_pattr	Requested memory region physical attributes.
663  * Output:
664  *	mr_hdl_p	The returned IBT memory region handle.
665  *	mem_desc_p	Returned memory descriptor.
666  * Returns:
667  *      IBT_SUCCESS
668  * Description:
669  * 	Prepares a physically addressed memory region for use by a HCA.
670  */
671 ibt_status_t
672 ibt_reregister_phys_mr(ibt_hca_hdl_t hca_hdl, ibt_mr_hdl_t mr_hdl,
673     ibt_pd_hdl_t pd, ibt_pmr_attr_t *mem_pattr, ibt_mr_hdl_t *mr_hdl_p,
674     ibt_pmr_desc_t *mem_desc_p)
675 {
676 	ibt_status_t 	status;
677 
678 	IBTF_DPRINTF_L3(ibtl_mem, "ibt_reregister_phys_mr(%p, %p, %p, %p)",
679 	    hca_hdl, mr_hdl, pd, mem_pattr);
680 
681 	status = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_reregister_physical_mr(
682 	    IBTL_HCA2CIHCA(hca_hdl), mr_hdl, pd, mem_pattr,
683 	    NULL, /* IBTL_HCA2MODI_P(hca_hdl)->mi_reserved */
684 	    mr_hdl_p, mem_desc_p);
685 
686 	if (!(status == IBT_SUCCESS || status == IBT_MR_IN_USE ||
687 	    status == IBT_HCA_HDL_INVALID || status == IBT_MR_HDL_INVALID)) {
688 		IBTF_DPRINTF_L2(ibtl_mem, "ibt_reregister_phys_mr: "
689 		    "Re-registration Mem Failed: %d", status);
690 
691 		/* we lost one memory region resource */
692 		mutex_enter(&hca_hdl->ha_mutex);
693 		hca_hdl->ha_mr_cnt--;
694 		mutex_exit(&hca_hdl->ha_mutex);
695 
696 	}
697 	return (status);
698 }
699 
700 
701 /*
702  * Fast Memory Registration (FMR).
703  *
704  * ibt_create_fmr_pool
705  *      Not fast-path.
706  *      ibt_create_fmr_pool() verifies that the HCA supports FMR and allocates
707  *      and initializes an "FMR pool".  This pool contains state specific to
708  *      this registration, including the watermark setting to determine when
709  *      to sync, and the total number of FMR regions available within this pool.
710  *
711  */
712 ibt_status_t
713 ibt_create_fmr_pool(ibt_hca_hdl_t hca_hdl, ibt_pd_hdl_t pd,
714     ibt_fmr_pool_attr_t *fmr_params, ibt_fmr_pool_hdl_t *fmr_pool_p)
715 {
716 	ibt_status_t 		status;
717 
718 	IBTF_DPRINTF_L3(ibtl_mem, "ibt_create_fmr_pool(%p, %p, %p)",
719 	    hca_hdl, pd, fmr_params);
720 
721 	status = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_create_fmr_pool(
722 	    IBTL_HCA2CIHCA(hca_hdl), pd, fmr_params, fmr_pool_p);
723 	if (status != IBT_SUCCESS) {
724 		*fmr_pool_p = NULL;
725 		return (status);
726 	}
727 
728 	/* Update the FMR resource count */
729 	mutex_enter(&hca_hdl->ha_mutex);
730 	hca_hdl->ha_fmr_pool_cnt++;
731 	mutex_exit(&hca_hdl->ha_mutex);
732 
733 	return (status);
734 }
735 
736 
737 /*
738  * ibt_destroy_fmr_pool
739  *      ibt_destroy_fmr_pool() deallocates all of the FMR regions in a specific
740  *      pool.  All state and information regarding the pool are destroyed and
741  *      returned as free space once again.  No more use of FMR regions in this
742  *      pool are possible without a subsequent call to ibt_create_fmr_pool().
743  */
744 ibt_status_t
745 ibt_destroy_fmr_pool(ibt_hca_hdl_t hca_hdl, ibt_fmr_pool_hdl_t fmr_pool)
746 {
747 	ibt_status_t 	status;
748 
749 	IBTF_DPRINTF_L3(ibtl_mem, "ibt_destroy_fmr_pool(%p, %p)",
750 	    hca_hdl, fmr_pool);
751 
752 	status = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_destroy_fmr_pool(
753 	    IBTL_HCA2CIHCA(hca_hdl), fmr_pool);
754 	if (status != IBT_SUCCESS) {
755 		IBTF_DPRINTF_L2(ibtl_mem, "ibt_destroy_fmr_pool: "
756 		    "CI FMR Pool destroy failed (%d)", status);
757 		return (status);
758 	}
759 
760 	mutex_enter(&hca_hdl->ha_mutex);
761 	hca_hdl->ha_fmr_pool_cnt--;
762 	mutex_exit(&hca_hdl->ha_mutex);
763 
764 	return (status);
765 }
766 
767 /*
768  * ibt_flush_fmr_pool
769  *      ibt_flush_fmr_pool forces a flush to occur.  At the client's request,
770  *      any unmapped FMR regions (See 'ibt_deregister_mr())') are returned to
771  *      a free state.  This function allows for an asynchronous cleanup of
772  *      formerly used FMR regions.  Sync operation is also performed internally
773  *      by HCA driver, when 'watermark' settings for the number of free FMR
774  *      regions left in the "pool" is reached.
775  */
776 ibt_status_t
777 ibt_flush_fmr_pool(ibt_hca_hdl_t hca_hdl, ibt_fmr_pool_hdl_t fmr_pool)
778 {
779 	IBTF_DPRINTF_L3(ibtl_mem, "ibt_flush_fmr_pool(%p, %p)",
780 	    hca_hdl, fmr_pool);
781 
782 	return (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_flush_fmr_pool(
783 	    IBTL_HCA2CIHCA(hca_hdl), fmr_pool));
784 }
785 
786 /*
787  * ibt_register_physical_fmr
788  *      ibt_register_physical_fmr() assigns a "free" entry from the FMR Pool.
789  *      It first consults the "FMR cache" to see if this is a duplicate memory
790  *      registration to something already in use.  If not, then a free entry
791  *      in the "pool" is marked used.
792  */
793 ibt_status_t
794 ibt_register_physical_fmr(ibt_hca_hdl_t hca_hdl, ibt_fmr_pool_hdl_t fmr_pool,
795     ibt_pmr_attr_t *mem_pattr, ibt_mr_hdl_t *mr_hdl_p,
796     ibt_pmr_desc_t *mem_desc_p)
797 {
798 	IBTF_DPRINTF_L3(ibtl_mem, "ibt_register_physical_fmr(%p, %p, %p, %p)",
799 	    hca_hdl, fmr_pool, mem_pattr, mem_desc_p);
800 
801 	return (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_register_physical_fmr(
802 	    IBTL_HCA2CIHCA(hca_hdl), fmr_pool, mem_pattr,
803 	    NULL, /* IBTL_HCA2MODI_P(hca_hdl)->mi_reserved */
804 	    mr_hdl_p, mem_desc_p));
805 }
806 
807 /*
808  * ibt_deregister_fmr
809  *	The ibt_deregister_fmr un-maps the resources reserved from the FMR
810  *	pool by ibt_register_physical_fmr().   The ibt_deregister_fmr() will
811  *	mark the region as free in the FMR Pool.
812  */
813 ibt_status_t
814 ibt_deregister_fmr(ibt_hca_hdl_t hca, ibt_mr_hdl_t mr_hdl)
815 {
816 	IBTF_DPRINTF_L3(ibtl_mem, "ibt_deregister_fmr(%p, %p)", hca, mr_hdl);
817 
818 	return (IBTL_HCA2CIHCAOPS_P(hca)->ibc_deregister_fmr(
819 	    IBTL_HCA2CIHCA(hca), mr_hdl));
820 }
821