xref: /illumos-gate/usr/src/uts/common/sys/ib/adapters/hermon/hermon_mr.h (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef	_SYS_IB_ADAPTERS_HERMON_MR_H
28 #define	_SYS_IB_ADAPTERS_HERMON_MR_H
29 
30 /*
31  * hermon_mr.h
32  *    Contains all of the prototypes, #defines, and structures necessary
33  *    for the Hermon Memory Region/Window routines.
34  *    Specifically it contains #defines, macros, and prototypes for each of
35  *    the required memory region/window verbs that can be accessed through
36  *    the IBTF's CI interfaces.  In particular each of the prototypes defined
37  *    below is called from a corresponding CI interface routine (as specified
38  *    in the hermon_ci.c file).
39  */
40 
41 #include <sys/types.h>
42 #include <sys/conf.h>
43 #include <sys/ddi.h>
44 #include <sys/sunddi.h>
45 
46 #ifdef __cplusplus
47 extern "C" {
48 #endif
49 
50 /*
51  * The following defines specify the default number of MPT entries to
52  * configure. This value is controllable through the "hermon_log_num_mpt"
53  * configuration variable.
54  */
55 #define	HERMON_NUM_DMPT_SHIFT		0x16
56 
57 /*
58  * The following defines specify the default number of MPT entries to
59  * configure. This value is controllable through the "hermon_log_num_mtt"
60  * configuration variable. This default value expects an averages of 8
61  * MTTs per MPT. We also define a log MTT size, since it's not likely
62  * to change.
63  */
64 #define	HERMON_NUM_MTT_SHIFT		0x1a
65 #define	HERMON_MTT_SIZE_SHIFT		0x3
66 
67 /*
68  * This define is the maximum size of a memory region or window (log 2), which
69  * is used to initialize the "hermon_log_max_mrw_sz" configuration variable.
70  */
71 #define	HERMON_MAX_MEM_MPT_SHIFT			0x24
72 
73 /*
74  * Defines used by hermon_mr_deregister() to specify how much/to what extent
75  * a given memory regions resources should be freed up.  HERMON_MR_DEREG_ALL
76  * says what it means, free up all the resources associated with the region.
77  * HERMON_MR_DEREG_NO_HW2SW_MPT indicates that it is unnecessary to attempt
78  * the ownership transfer (from hardware to software) for the given MPT entry.
79  * And HERMON_MR_DEREG_NO_HW2SW_MPT_OR_UNBIND indicates that it is not only
80  * unnecessary to attempt the ownership transfer for MPT, but it is also
81  * unnecessary to attempt to unbind the memory.
82  * In general, these last two are specified when hermon_mr_deregister() is
83  * called from hermon_mr_reregister(), where the MPT ownership transfer or
84  * memory unbinding may have already been successfully performed.
85  */
86 #define	HERMON_MR_DEREG_ALL			3
87 #define	HERMON_MR_DEREG_NO_HW2SW_MPT		2
88 #define	HERMON_MR_DEREG_NO_HW2SW_MPT_OR_UNBIND	1
89 
90 /*
91  * The following define is used by hermon_mr_rereg_xlat_helper() to determine
92  * whether or not a given DMA handle can be reused.  If the DMA handle was
93  * previously initialized for IOMMU bypass mapping, then it can not be reused
94  * to reregister a region for DDI_DMA_STREAMING access.
95  */
96 #define	HERMON_MR_REUSE_DMAHDL(mr, flags)				\
97 	(((mr)->mr_bindinfo.bi_bypass != HERMON_BINDMEM_BYPASS) ||	\
98 	    !((flags) & IBT_MR_NONCOHERENT))
99 
100 /*
101  * The hermon_sw_refcnt_t structure is used internally by the Hermon driver to
102  * track all the information necessary to manage shared memory regions.  Since
103  * a shared memory region _will_ have its own distinct MPT entry, but will
104  * _share_ its MTT entries with another region, it is necessary to track the
105  * number of times a given MTT structure is shared.  This ensures that it will
106  * not be prematurely freed up and that can be destroyed only when it is
107  * appropriate to do so.
108  *
109  * Each hermon_sw_refcnt_t structure contains a lock and a reference count
110  * variable which are used to track the necessary information.
111  *
112  * The following macros (below) are used to manipulate and query the MTT
113  * reference count parameters.  HERMON_MTT_REFCNT_INIT() is used to initialize
114  * a newly allocated hermon_sw_refcnt_t struct (setting the "swrc_refcnt" to 1).
115  * And the HERMON_MTT_IS_NOT_SHARED() and HERMON_MTT_IS_SHARED() macros are
116  * used to query the current status of hermon_sw_refcnt_t struct to determine
117  * if its "swrc_refcnt" is one or not.
118  */
119 typedef struct hermon_sw_refcnt_s {
120 	kmutex_t		swrc_lock;
121 	uint_t			swrc_refcnt;
122 } hermon_sw_refcnt_t;
123 _NOTE(DATA_READABLE_WITHOUT_LOCK(hermon_sw_refcnt_t::swrc_refcnt))
124 _NOTE(MUTEX_PROTECTS_DATA(hermon_sw_refcnt_t::swrc_lock,
125     hermon_sw_refcnt_t::swrc_refcnt))
126 #define	HERMON_MTT_REFCNT_INIT(swrc_tmp)	((swrc_tmp)->swrc_refcnt = 1)
127 #define	HERMON_MTT_IS_NOT_SHARED(swrc_tmp)	((swrc_tmp)->swrc_refcnt == 1)
128 #define	HERMON_MTT_IS_SHARED(swrc_tmp)		((swrc_tmp)->swrc_refcnt != 1)
129 
130 
131 /*
132  * The hermon_bind_info_t structure is used internally by the Hermon driver to
133  * track all the information necessary to perform the DMA mappings necessary
134  * for memory registration.  It is specifically passed into both the
135  * hermon_mr_mem_bind() and hermon_mr_mtt_write() functions which perform most
136  * of the necessary operations for Hermon memory registration.
137  *
138  * This structure is used to pass all the information necessary for a call
139  * to either ddi_dma_addr_bind_handle() or ddi_dma_buf_bind_handle().  Note:
140  * the fields which need to be valid for each type of binding are slightly
141  * different and that it indicated by the value in the "bi_type" field.  The
142  * "bi_type" field may be set to either of the following defined values:
143  * HERMON_BINDHDL_VADDR (to indicate an "addr" bind) or HERMON_BINDHDL_BUF (to
144  * indicate a "buf" bind).
145  *
146  * Upon return from hermon_mr_mem_bind(), the hermon_bind_info_t struct will
147  * have its "bi_dmahdl", "bi_dmacookie", and "bi_cookiecnt" fields filled in.
148  * It is these values which are of particular interest to the
149  * hermon_mr_mtt_write() routine (they hold the PCI mapped addresses).
150  *
151  * Once initialized and used in this way, the hermon_bind_info_t will not to be
152  * modified in anyway until it is subsequently passed to hermon_mr_mem_unbind()
153  * where the memory and resources will be unbound and reclaimed.  Note:  the
154  * "bi_free_dmahdl" flag indicated whether the ddi_dma_handle_t should be
155  * freed as part of the hermon_mr_mem_unbind() operation or whether it will
156  * be freed later elsewhere.
157  */
158 typedef struct hermon_bind_info_s {
159 	uint64_t		bi_addr;
160 	uint64_t		bi_len;
161 	struct as		*bi_as;
162 	struct buf		*bi_buf;
163 	ddi_dma_handle_t	bi_dmahdl;
164 	ddi_dma_cookie_t	bi_dmacookie;
165 	uint_t			bi_cookiecnt;
166 	uint_t			bi_type;
167 	uint_t			bi_flags;
168 	uint_t			bi_bypass;
169 	uint_t			bi_free_dmahdl;
170 } hermon_bind_info_t;
171 #define	HERMON_BINDHDL_NONE		0
172 #define	HERMON_BINDHDL_VADDR		1
173 #define	HERMON_BINDHDL_BUF		2
174 #define	HERMON_BINDHDL_UBUF		3
175 
176 /*
177  * The hermon_sw_mr_s structure is also referred to using the "hermon_mrhdl_t"
178  * typedef (see hermon_typedef.h).  It encodes all the information necessary
179  * to track the various resources needed to register, reregister, deregister,
180  * and perform all the myriad other operations on both memory regions _and_
181  * memory windows.
182  *
183  * A pointer to this structure is returned from many of the IBTF's CI verbs
184  * interfaces for memory registration.
185  *
186  * It contains pointers to the various resources allocated for a memory
187  * region, i.e. MPT resource, MTT resource, and MTT reference count resource.
188  * In addition it contains the hermon_bind_info_t struct used for the memory
189  * bind operation on a given memory region.
190  *
191  * It also has a pointers to the associated PD handle, placeholders for access
192  * flags, memory keys, and suggested page size for the region.  It also has
193  * the necessary backpointer to the resource that corresponds to the structure
194  * itself.  And lastly, it contains a placeholder for a callback which should
195  * be called on memory region unpinning.
196  */
197 struct hermon_sw_mr_s {
198 	kmutex_t		mr_lock;
199 	hermon_rsrc_t		*mr_mptrsrcp;
200 	hermon_rsrc_t		*mr_mttrsrcp;
201 	hermon_rsrc_t		*mr_mttrefcntp;
202 	hermon_pdhdl_t		mr_pdhdl;
203 	hermon_bind_info_t	mr_bindinfo;
204 	ibt_mr_attr_flags_t	mr_accflag;
205 	uint32_t		mr_lkey;
206 	uint32_t		mr_rkey;
207 	uint32_t		mr_logmttpgsz;
208 	hermon_mpt_rsrc_type_t	mr_mpt_type;
209 	uint64_t		mr_mttaddr;	/* for cMPTs */
210 	uint64_t		mr_log2_pgsz;
211 				/* entity_size (in bytes), for cMPTS */
212 	hermon_rsrc_t		*mr_rsrcp;
213 	uint_t			mr_is_fmr;
214 	hermon_fmr_list_t	*mr_fmr;
215 	uint_t			mr_is_umem;
216 	ddi_umem_cookie_t	mr_umemcookie;
217 	void 			(*mr_umem_cbfunc)(void *, void *);
218 	void			*mr_umem_cbarg1;
219 	void			*mr_umem_cbarg2;
220 };
221 _NOTE(DATA_READABLE_WITHOUT_LOCK(hermon_sw_mr_s::mr_bindinfo
222     hermon_sw_mr_s::mr_lkey
223     hermon_sw_mr_s::mr_is_umem
224     hermon_sw_mr_s::mr_is_fmr
225     hermon_sw_mr_s::mr_fmr))
226 _NOTE(MUTEX_PROTECTS_DATA(hermon_sw_mr_s::mr_lock,
227     hermon_sw_mr_s::mr_mptrsrcp
228     hermon_sw_mr_s::mr_mttrsrcp
229     hermon_sw_mr_s::mr_mttrefcntp
230     hermon_sw_mr_s::mr_bindinfo
231     hermon_sw_mr_s::mr_lkey
232     hermon_sw_mr_s::mr_rkey
233     hermon_sw_mr_s::mr_logmttpgsz
234     hermon_sw_mr_s::mr_rsrcp
235     hermon_sw_mr_s::mr_is_umem
236     hermon_sw_mr_s::mr_umemcookie
237     hermon_sw_mr_s::mr_umem_cbfunc
238     hermon_sw_mr_s::mr_umem_cbarg1
239     hermon_sw_mr_s::mr_umem_cbarg2))
240 
241 /*
242  * The hermon_mr_options_t structure is used in several of the Hermon memory
243  * registration routines to provide additional option functionality.  When
244  * a NULL pointer is passed in place of a pointer to this struct, it is a
245  * way of specifying the "default" behavior.  Using this structure, however,
246  * is a way of controlling any extended behavior.
247  *
248  * Currently, the only defined "extended" behaviors are for specifying whether
249  * a given memory region should bypass the PCI IOMMU (HERMON_BINDMEM_BYPASS)
250  * or be mapped into the IOMMU (HERMON_BINDMEM_NORMAL), for specifying whether
251  * a given ddi_dma_handle_t should be used in the bind operation, and for
252  * specifying whether a memory registration should attempt to return an IB
253  * vaddr which is "zero-based" (aids in alignment contraints for QPs).
254  *
255  * This defaults today to always bypassing the IOMMU (can be changed by using
256  * the "hermon_iommu_bypass" configuration variable), to always allocating
257  * a new dma handle, and to using the virtual address passed in (i.e. not
258  * "zero-based").
259  */
260 typedef struct hermon_mr_options_s {
261 	ddi_dma_handle_t	mro_bind_dmahdl;
262 	uint_t			mro_bind_type;
263 	uint_t			mro_bind_override_addr;
264 } hermon_mr_options_t;
265 #define	HERMON_BINDMEM_NORMAL		1
266 #define	HERMON_BINDMEM_BYPASS		0
267 
268 #define	HERMON_NO_MPT_OWNERSHIP		0	/* for cMPTs */
269 #define	HERMON_PASS_MPT_OWNERSHIP	1
270 
271 /*
272  * Memory Allocation/Deallocation
273  *
274  * Although this is not strictly related to "memory regions", this is
275  * the most logical place to define the struct used for the memory
276  * allocation/deallocation CI entry points.
277  *
278  * ibc_mem_alloc_s structure is used to store DMA handles for
279  * for these allocations.
280  */
281 struct ibc_mem_alloc_s {
282 	ddi_dma_handle_t ibc_dma_hdl;
283 	ddi_acc_handle_t ibc_acc_hdl;
284 };
285 _NOTE(SCHEME_PROTECTS_DATA("safe sharing",
286     ibc_mem_alloc_s::ibc_dma_hdl
287     ibc_mem_alloc_s::ibc_acc_hdl))
288 
289 int hermon_mr_register(hermon_state_t *state, hermon_pdhdl_t pdhdl,
290     ibt_mr_attr_t *attr_p, hermon_mrhdl_t *mrhdl, hermon_mr_options_t *op,
291     hermon_mpt_rsrc_type_t mpt_type);
292 int hermon_mr_register_buf(hermon_state_t *state, hermon_pdhdl_t pdhdl,
293     ibt_smr_attr_t *attrp, struct buf *buf, hermon_mrhdl_t *mrhdl,
294     hermon_mr_options_t *op, hermon_mpt_rsrc_type_t mpt_type);
295 int hermon_mr_mtt_bind(hermon_state_t *state, hermon_bind_info_t *bind,
296     ddi_dma_handle_t bind_dmahdl, hermon_rsrc_t **mtt, uint_t *mtt_pgsz_bits,
297     uint_t is_buffer);
298 int hermon_mr_mtt_unbind(hermon_state_t *state, hermon_bind_info_t *bind,
299     hermon_rsrc_t *mtt);
300 int hermon_mr_register_shared(hermon_state_t *state, hermon_mrhdl_t mrhdl,
301     hermon_pdhdl_t pdhdl, ibt_smr_attr_t *attr_p, hermon_mrhdl_t *mrhdl_new);
302 int hermon_mr_deregister(hermon_state_t *state, hermon_mrhdl_t *mrhdl,
303     uint_t level, uint_t sleep);
304 int hermon_mr_query(hermon_state_t *state, hermon_mrhdl_t mrhdl,
305     ibt_mr_query_attr_t *attr);
306 int hermon_mr_reregister(hermon_state_t *state, hermon_mrhdl_t mrhdl,
307     hermon_pdhdl_t pdhdl, ibt_mr_attr_t *attr_p, hermon_mrhdl_t *mrhdl_new,
308     hermon_mr_options_t *op);
309 int hermon_mr_reregister_buf(hermon_state_t *state, hermon_mrhdl_t mr,
310     hermon_pdhdl_t pd, ibt_smr_attr_t *mr_attr, struct buf *buf,
311     hermon_mrhdl_t *mrhdl_new, hermon_mr_options_t *op);
312 int hermon_mr_sync(hermon_state_t *state, ibt_mr_sync_t *mr_segs,
313     size_t num_segs);
314 int hermon_mw_alloc(hermon_state_t *state, hermon_pdhdl_t pdhdl,
315     ibt_mw_flags_t flags, hermon_mwhdl_t *mwhdl);
316 int hermon_mw_free(hermon_state_t *state, hermon_mwhdl_t *mwhdl, uint_t sleep);
317 uint32_t hermon_mr_keycalc(uint32_t indx);
318 uint32_t hermon_mr_key_swap(uint32_t indx);
319 uint32_t hermon_index_to_mkey(uint32_t indx);
320 int hermon_mr_alloc_fmr(hermon_state_t *state, hermon_pdhdl_t pd,
321     hermon_fmrhdl_t fmr_pool, hermon_mrhdl_t *mrhdl);
322 int hermon_mr_dealloc_fmr(hermon_state_t *state, hermon_mrhdl_t *mrhdl);
323 int hermon_mr_register_physical_fmr(hermon_state_t *state,
324     ibt_pmr_attr_t *mem_pattr_p, hermon_mrhdl_t mr, ibt_pmr_desc_t *mem_desc_p);
325 int hermon_mr_invalidate_fmr(hermon_state_t *state, hermon_mrhdl_t mr);
326 int hermon_mr_deregister_fmr(hermon_state_t *state, hermon_mrhdl_t mr);
327 
328 
329 #ifdef __cplusplus
330 }
331 #endif
332 
333 #endif	/* _SYS_IB_ADAPTERS_HERMON_MR_H */
334