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.
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.
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]
22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved.
26 #pragma ident "@(#)iommulib.c 1.6 08/09/07 SMI"
28 #include <sys/sunddi.h>
29 #include <sys/sunndi.h>
30 #include <sys/errno.h>
31 #include <sys/modctl.h>
32 #include <sys/iommulib.h>
34 /* ******** Type definitions private to this file ********************** */
36 /* 1 per IOMMU unit. There may be more than one per dip */
37 typedef struct iommulib_unit
{
42 iommulib_ops_t
*ilu_ops
;
44 struct iommulib_unit
*ilu_next
;
45 struct iommulib_unit
*ilu_prev
;
46 iommulib_nexhandle_t ilu_nex
;
49 typedef struct iommulib_nex
{
51 iommulib_nexops_t nex_ops
;
52 struct iommulib_nex
*nex_next
;
53 struct iommulib_nex
*nex_prev
;
57 /* ********* Globals ************************ */
59 /* For IOMMU drivers */
60 smbios_hdl_t
*iommulib_smbios
;
62 /* IOMMU side: Following data protected by lock */
63 static kmutex_t iommulib_lock
;
64 static iommulib_unit_t
*iommulib_list
;
65 static uint64_t iommulib_unit_ids
= 0;
66 static uint64_t iommulib_num_units
= 0;
68 /* rootnex side data */
70 static kmutex_t iommulib_nexus_lock
;
71 static iommulib_nex_t
*iommulib_nexus_list
;
73 /* can be set atomically without lock */
74 static volatile uint32_t iommulib_fini
;
77 static int iommulib_debug
;
80 * Module linkage information for the kernel.
82 static struct modlmisc modlmisc
= {
83 &mod_miscops
, "IOMMU library module"
86 static struct modlinkage modlinkage
= {
87 MODREV_1
, (void *)&modlmisc
, NULL
93 return (mod_install(&modlinkage
));
99 mutex_enter(&iommulib_lock
);
100 if (iommulib_list
!= NULL
|| iommulib_nexus_list
!= NULL
) {
101 mutex_exit(&iommulib_lock
);
106 mutex_exit(&iommulib_lock
);
107 return (mod_remove(&modlinkage
));
111 _info(struct modinfo
*modinfop
)
113 return (mod_info(&modlinkage
, modinfop
));
117 * Routines with iommulib_iommu_* are invoked from the
119 * Routines with iommulib_nex* are invoked from the
120 * nexus driver (typically rootnex)
124 iommulib_nexus_register(dev_info_t
*dip
, iommulib_nexops_t
*nexops
,
125 iommulib_nexhandle_t
*handle
)
127 iommulib_nex_t
*nexp
;
128 int instance
= ddi_get_instance(dip
);
129 const char *driver
= ddi_driver_name(dip
);
130 dev_info_t
*pdip
= ddi_get_parent(dip
);
131 const char *f
= "iommulib_nexus_register";
139 * Root node is never busy held
141 if (dip
!= ddi_root_node() && (i_ddi_node_state(dip
) < DS_PROBED
||
142 !DEVI_BUSY_OWNED(pdip
))) {
143 cmn_err(CE_WARN
, "%s: NEXUS devinfo node not in DS_PROBED "
144 "or busy held for nexops vector (%p). Failing registration",
146 return (DDI_FAILURE
);
149 if (nexops
->nops_vers
!= IOMMU_NEXOPS_VERSION
) {
150 cmn_err(CE_WARN
, "%s: %s%d: Invalid IOMMULIB nexops version "
151 "in nexops vector (%p). Failing NEXUS registration",
152 f
, driver
, instance
, (void *)nexops
);
153 return (DDI_FAILURE
);
156 ASSERT(nexops
->nops_data
== NULL
);
158 if (nexops
->nops_id
== NULL
) {
159 cmn_err(CE_WARN
, "%s: %s%d: NULL ID field. "
160 "Failing registration for nexops vector: %p",
161 f
, driver
, instance
, (void *)nexops
);
162 return (DDI_FAILURE
);
165 if (nexops
->nops_dma_allochdl
== NULL
) {
166 cmn_err(CE_WARN
, "%s: %s%d: NULL nops_dma_allochdl op. "
167 "Failing registration for ops vector: %p", f
,
168 driver
, instance
, (void *)nexops
);
169 return (DDI_FAILURE
);
172 if (nexops
->nops_dma_freehdl
== NULL
) {
173 cmn_err(CE_WARN
, "%s: %s%d: NULL nops_dma_freehdl op. "
174 "Failing registration for ops vector: %p", f
,
175 driver
, instance
, (void *)nexops
);
176 return (DDI_FAILURE
);
179 if (nexops
->nops_dma_bindhdl
== NULL
) {
180 cmn_err(CE_WARN
, "%s: %s%d: NULL nops_dma_bindhdl op. "
181 "Failing registration for ops vector: %p", f
,
182 driver
, instance
, (void *)nexops
);
183 return (DDI_FAILURE
);
186 if (nexops
->nops_dma_sync
== NULL
) {
187 cmn_err(CE_WARN
, "%s: %s%d: NULL nops_dma_sync op. "
188 "Failing registration for ops vector: %p", f
,
189 driver
, instance
, (void *)nexops
);
190 return (DDI_FAILURE
);
193 if (nexops
->nops_dma_reset_cookies
== NULL
) {
194 cmn_err(CE_WARN
, "%s: %s%d: NULL nops_dma_reset_cookies op. "
195 "Failing registration for ops vector: %p", f
,
196 driver
, instance
, (void *)nexops
);
197 return (DDI_FAILURE
);
200 if (nexops
->nops_dma_get_cookies
== NULL
) {
201 cmn_err(CE_WARN
, "%s: %s%d: NULL nops_dma_get_cookies op. "
202 "Failing registration for ops vector: %p", f
,
203 driver
, instance
, (void *)nexops
);
204 return (DDI_FAILURE
);
207 if (nexops
->nops_dma_set_cookies
== NULL
) {
208 cmn_err(CE_WARN
, "%s: %s%d: NULL nops_dma_set_cookies op. "
209 "Failing registration for ops vector: %p", f
,
210 driver
, instance
, (void *)nexops
);
211 return (DDI_FAILURE
);
214 if (nexops
->nops_dma_clear_cookies
== NULL
) {
215 cmn_err(CE_WARN
, "%s: %s%d: NULL nops_dma_clear_cookies op. "
216 "Failing registration for ops vector: %p", f
,
217 driver
, instance
, (void *)nexops
);
218 return (DDI_FAILURE
);
221 if (nexops
->nops_dma_get_sleep_flags
== NULL
) {
222 cmn_err(CE_WARN
, "%s: %s%d: NULL nops_dma_get_sleep_flags op. "
223 "Failing registration for ops vector: %p", f
,
224 driver
, instance
, (void *)nexops
);
225 return (DDI_FAILURE
);
228 if (nexops
->nops_dma_win
== NULL
) {
229 cmn_err(CE_WARN
, "%s: %s%d: NULL nops_dma_win op. "
230 "Failing registration for ops vector: %p", f
,
231 driver
, instance
, (void *)nexops
);
232 return (DDI_FAILURE
);
235 if (nexops
->nops_dmahdl_setprivate
== NULL
) {
236 cmn_err(CE_WARN
, "%s: %s%d: NULL nops_dmahdl_setprivate op. "
237 "Failing registration for ops vector: %p", f
,
238 driver
, instance
, (void *)nexops
);
239 return (DDI_FAILURE
);
242 if (nexops
->nops_dmahdl_getprivate
== NULL
) {
243 cmn_err(CE_WARN
, "%s: %s%d: NULL nops_dmahdl_getprivate op. "
244 "Failing registration for ops vector: %p", f
,
245 driver
, instance
, (void *)nexops
);
246 return (DDI_FAILURE
);
249 nexp
= kmem_zalloc(sizeof (iommulib_nex_t
), KM_SLEEP
);
251 mutex_enter(&iommulib_lock
);
252 if (iommulib_fini
== 1) {
253 mutex_exit(&iommulib_lock
);
254 cmn_err(CE_WARN
, "%s: IOMMULIB unloading. "
255 "Failing NEXUS register.", f
);
256 kmem_free(nexp
, sizeof (iommulib_nex_t
));
257 return (DDI_FAILURE
);
261 * fini/register race conditions have been handled. Now create the
266 nexp
->nex_ops
= *nexops
;
268 mutex_enter(&iommulib_nexus_lock
);
269 nexp
->nex_next
= iommulib_nexus_list
;
270 iommulib_nexus_list
= nexp
;
271 nexp
->nex_prev
= NULL
;
273 if (nexp
->nex_next
!= NULL
)
274 nexp
->nex_next
->nex_prev
= nexp
;
279 * The nexus device won't be controlled by an IOMMU.
281 DEVI(dip
)->devi_iommulib_handle
= IOMMU_HANDLE_UNUSED
;
283 DEVI(dip
)->devi_iommulib_nex_handle
= nexp
;
285 mutex_exit(&iommulib_nexus_lock
);
286 mutex_exit(&iommulib_lock
);
288 cmn_err(CE_NOTE
, "!%s: %s%d: Succesfully registered NEXUS %s "
289 "nexops=%p", f
, driver
, instance
, ddi_node_name(dip
),
294 return (DDI_SUCCESS
);
298 iommulib_nexus_unregister(iommulib_nexhandle_t handle
)
303 iommulib_nex_t
*nexp
= (iommulib_nex_t
*)handle
;
304 const char *f
= "iommulib_nexus_unregister";
308 if (nexp
->nex_ref
!= 0)
309 return (DDI_FAILURE
);
311 mutex_enter(&iommulib_nexus_lock
);
314 driver
= ddi_driver_name(dip
);
315 instance
= ddi_get_instance(dip
);
317 /* A future enhancement would be to add ref-counts */
319 if (nexp
->nex_prev
== NULL
) {
320 iommulib_nexus_list
= nexp
->nex_next
;
322 nexp
->nex_prev
->nex_next
= nexp
->nex_next
;
325 if (nexp
->nex_next
!= NULL
)
326 nexp
->nex_next
->nex_prev
= nexp
->nex_prev
;
328 mutex_exit(&iommulib_nexus_lock
);
330 kmem_free(nexp
, sizeof (iommulib_nex_t
));
332 cmn_err(CE_NOTE
, "!%s: %s%d: NEXUS (%s) handle successfully "
333 "unregistered from IOMMULIB", f
, driver
, instance
,
338 return (DDI_SUCCESS
);
342 iommulib_iommu_register(dev_info_t
*dip
, iommulib_ops_t
*ops
,
343 iommulib_handle_t
*handle
)
346 iommulib_unit_t
*unitp
;
347 int instance
= ddi_get_instance(dip
);
348 const char *driver
= ddi_driver_name(dip
);
349 const char *f
= "iommulib_register";
354 if (ops
->ilops_vers
!= IOMMU_OPS_VERSION
) {
355 cmn_err(CE_WARN
, "%s: %s%d: Invalid IOMMULIB ops version "
356 "in ops vector (%p). Failing registration", f
, driver
,
357 instance
, (void *)ops
);
358 return (DDI_FAILURE
);
361 switch (ops
->ilops_vendor
) {
369 cmn_err(CE_WARN
, "%s: %s%d: vendor field (%x) not initialized. "
370 "Failing registration for ops vector: %p", f
,
371 driver
, instance
, ops
->ilops_vendor
, (void *)ops
);
372 return (DDI_FAILURE
);
374 cmn_err(CE_WARN
, "%s: %s%d: Invalid vendor field (%x). "
375 "Failing registration for ops vector: %p", f
,
376 driver
, instance
, ops
->ilops_vendor
, (void *)ops
);
377 return (DDI_FAILURE
);
380 cmn_err(CE_NOTE
, "!%s: %s%d: Detected IOMMU registration from vendor"
381 " %s", f
, driver
, instance
, vendor
);
383 if (ops
->ilops_data
== NULL
) {
384 cmn_err(CE_WARN
, "%s: %s%d: NULL IOMMU data field. "
385 "Failing registration for ops vector: %p", f
,
386 driver
, instance
, (void *)ops
);
387 return (DDI_FAILURE
);
390 if (ops
->ilops_id
== NULL
) {
391 cmn_err(CE_WARN
, "%s: %s%d: NULL ID field. "
392 "Failing registration for ops vector: %p", f
,
393 driver
, instance
, (void *)ops
);
394 return (DDI_FAILURE
);
397 if (ops
->ilops_probe
== NULL
) {
398 cmn_err(CE_WARN
, "%s: %s%d: NULL probe op. "
399 "Failing registration for ops vector: %p", f
,
400 driver
, instance
, (void *)ops
);
401 return (DDI_FAILURE
);
404 if (ops
->ilops_dma_allochdl
== NULL
) {
405 cmn_err(CE_WARN
, "%s: %s%d: NULL dma_allochdl op. "
406 "Failing registration for ops vector: %p", f
,
407 driver
, instance
, (void *)ops
);
408 return (DDI_FAILURE
);
411 if (ops
->ilops_dma_freehdl
== NULL
) {
412 cmn_err(CE_WARN
, "%s: %s%d: NULL dma_freehdl op. "
413 "Failing registration for ops vector: %p", f
,
414 driver
, instance
, (void *)ops
);
415 return (DDI_FAILURE
);
418 if (ops
->ilops_dma_bindhdl
== NULL
) {
419 cmn_err(CE_WARN
, "%s: %s%d: NULL dma_bindhdl op. "
420 "Failing registration for ops vector: %p", f
,
421 driver
, instance
, (void *)ops
);
422 return (DDI_FAILURE
);
425 if (ops
->ilops_dma_sync
== NULL
) {
426 cmn_err(CE_WARN
, "%s: %s%d: NULL dma_sync op. "
427 "Failing registration for ops vector: %p", f
,
428 driver
, instance
, (void *)ops
);
429 return (DDI_FAILURE
);
432 if (ops
->ilops_dma_win
== NULL
) {
433 cmn_err(CE_WARN
, "%s: %s%d: NULL dma_win op. "
434 "Failing registration for ops vector: %p", f
,
435 driver
, instance
, (void *)ops
);
436 return (DDI_FAILURE
);
439 unitp
= kmem_zalloc(sizeof (iommulib_unit_t
), KM_SLEEP
);
440 mutex_enter(&iommulib_lock
);
441 if (iommulib_fini
== 1) {
442 mutex_exit(&iommulib_lock
);
443 cmn_err(CE_WARN
, "%s: IOMMULIB unloading. Failing register.",
445 kmem_free(unitp
, sizeof (iommulib_unit_t
));
446 return (DDI_FAILURE
);
450 * fini/register race conditions have been handled. Now create the
453 mutex_init(&unitp
->ilu_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
455 mutex_enter(&unitp
->ilu_lock
);
456 unitp
->ilu_unitid
= ++iommulib_unit_ids
;
459 unitp
->ilu_dip
= dip
;
460 unitp
->ilu_ops
= ops
;
461 unitp
->ilu_data
= ops
->ilops_data
;
463 unitp
->ilu_next
= iommulib_list
;
464 iommulib_list
= unitp
;
465 unitp
->ilu_prev
= NULL
;
467 unitp
->ilu_next
->ilu_prev
= unitp
;
470 * The IOMMU device itself is not controlled by an IOMMU.
472 DEVI(dip
)->devi_iommulib_handle
= IOMMU_HANDLE_UNUSED
;
474 mutex_exit(&unitp
->ilu_lock
);
476 iommulib_num_units
++;
480 mutex_exit(&iommulib_lock
);
482 cmn_err(CE_NOTE
, "!%s: %s%d: Succesfully registered IOMMU unit "
483 "from vendor=%s, ops=%p, data=%p, IOMMULIB unitid=%u",
484 f
, driver
, instance
, vendor
, (void *)ops
, (void *)unitp
->ilu_data
,
487 return (DDI_SUCCESS
);
491 iommulib_iommu_unregister(iommulib_handle_t handle
)
497 iommulib_unit_t
*unitp
= (iommulib_unit_t
*)handle
;
498 const char *f
= "iommulib_unregister";
502 mutex_enter(&iommulib_lock
);
503 mutex_enter(&unitp
->ilu_lock
);
505 unitid
= unitp
->ilu_unitid
;
506 dip
= unitp
->ilu_dip
;
507 driver
= ddi_driver_name(dip
);
508 instance
= ddi_get_instance(dip
);
510 if (unitp
->ilu_ref
!= 0) {
511 mutex_exit(&unitp
->ilu_lock
);
512 mutex_exit(&iommulib_lock
);
513 cmn_err(CE_WARN
, "%s: %s%d: IOMMULIB handle is busy. Cannot "
514 "unregister IOMMULIB unitid %u",
515 f
, driver
, instance
, unitid
);
516 return (DDI_FAILURE
);
518 unitp
->ilu_unitid
= 0;
519 ASSERT(unitp
->ilu_ref
== 0);
521 if (unitp
->ilu_prev
== NULL
) {
522 iommulib_list
= unitp
->ilu_next
;
523 unitp
->ilu_next
->ilu_prev
= NULL
;
525 unitp
->ilu_prev
->ilu_next
= unitp
->ilu_next
;
526 unitp
->ilu_next
->ilu_prev
= unitp
->ilu_prev
;
529 iommulib_num_units
--;
531 mutex_exit(&unitp
->ilu_lock
);
533 mutex_destroy(&unitp
->ilu_lock
);
534 kmem_free(unitp
, sizeof (iommulib_unit_t
));
536 mutex_exit(&iommulib_lock
);
538 cmn_err(CE_WARN
, "%s: %s%d: IOMMULIB handle (unitid=%u) successfully "
539 "unregistered", f
, driver
, instance
, unitid
);
543 return (DDI_SUCCESS
);
547 iommulib_nex_open(dev_info_t
*dip
, dev_info_t
*rdip
)
549 iommulib_unit_t
*unitp
;
550 int instance
= ddi_get_instance(rdip
);
551 const char *driver
= ddi_driver_name(rdip
);
552 const char *f
= "iommulib_nex_open";
554 ASSERT(DEVI(dip
)->devi_iommulib_nex_handle
!= NULL
);
555 ASSERT(DEVI(rdip
)->devi_iommulib_handle
== NULL
);
557 /* prevent use of IOMMU for AMD IOMMU's DMA */
558 if (strcmp(driver
, "amd_iommu") == 0) {
559 DEVI(rdip
)->devi_iommulib_handle
= IOMMU_HANDLE_UNUSED
;
560 return (DDI_ENOTSUP
);
564 * Use the probe entry point to determine in a hardware specific
565 * manner whether this dip is controlled by an IOMMU. If yes,
566 * return the handle corresponding to the IOMMU unit.
569 mutex_enter(&iommulib_lock
);
570 for (unitp
= iommulib_list
; unitp
; unitp
= unitp
->ilu_next
) {
571 if (unitp
->ilu_ops
->ilops_probe(unitp
, rdip
) == DDI_SUCCESS
)
576 mutex_exit(&iommulib_lock
);
577 if (iommulib_debug
) {
578 char *buf
= kmem_alloc(MAXPATHLEN
, KM_SLEEP
);
579 cmn_err(CE_WARN
, "%s: %s%d: devinfo node (%p): is not "
580 "controlled by an IOMMU: path=%s", f
, driver
,
581 instance
, (void *)rdip
, ddi_pathname(rdip
, buf
));
582 kmem_free(buf
, MAXPATHLEN
);
584 DEVI(rdip
)->devi_iommulib_handle
= IOMMU_HANDLE_UNUSED
;
585 return (DDI_ENOTSUP
);
588 mutex_enter(&unitp
->ilu_lock
);
589 unitp
->ilu_nex
= DEVI(dip
)->devi_iommulib_nex_handle
;
591 DEVI(rdip
)->devi_iommulib_handle
= unitp
;
592 mutex_exit(&unitp
->ilu_lock
);
593 mutex_exit(&iommulib_lock
);
595 atomic_inc_uint(&DEVI(dip
)->devi_iommulib_nex_handle
->nex_ref
);
597 return (DDI_SUCCESS
);
601 iommulib_nex_close(dev_info_t
*rdip
)
603 iommulib_unit_t
*unitp
;
607 iommulib_nex_t
*nexp
;
608 const char *f
= "iommulib_nex_close";
610 ASSERT(IOMMU_USED(rdip
));
612 unitp
= DEVI(rdip
)->devi_iommulib_handle
;
614 mutex_enter(&iommulib_lock
);
615 mutex_enter(&unitp
->ilu_lock
);
617 nexp
= (iommulib_nex_t
*)unitp
->ilu_nex
;
618 DEVI(rdip
)->devi_iommulib_handle
= NULL
;
620 unitid
= unitp
->ilu_unitid
;
621 driver
= ddi_driver_name(unitp
->ilu_dip
);
622 instance
= ddi_get_instance(unitp
->ilu_dip
);
625 mutex_exit(&unitp
->ilu_lock
);
626 mutex_exit(&iommulib_lock
);
628 atomic_dec_uint(&nexp
->nex_ref
);
630 if (iommulib_debug
) {
631 char *buf
= kmem_alloc(MAXPATHLEN
, KM_SLEEP
);
632 (void) ddi_pathname(rdip
, buf
);
633 cmn_err(CE_NOTE
, "%s: %s%d: closing IOMMU for dip (%p), "
634 "unitid=%u rdip path = %s", f
, driver
, instance
,
635 (void *)rdip
, unitid
, buf
);
636 kmem_free(buf
, MAXPATHLEN
);
641 iommulib_nexdma_allochdl(dev_info_t
*dip
, dev_info_t
*rdip
,
642 ddi_dma_attr_t
*attr
, int (*waitfp
)(caddr_t
),
643 caddr_t arg
, ddi_dma_handle_t
*dma_handlep
)
645 iommulib_handle_t handle
= DEVI(rdip
)->devi_iommulib_handle
;
646 iommulib_unit_t
*unitp
= (iommulib_unit_t
*)handle
;
650 /* No need to grab lock - the handle is reference counted */
651 return (unitp
->ilu_ops
->ilops_dma_allochdl(handle
, dip
, rdip
,
652 attr
, waitfp
, arg
, dma_handlep
));
656 iommulib_nexdma_freehdl(dev_info_t
*dip
, dev_info_t
*rdip
,
657 ddi_dma_handle_t dma_handle
)
660 iommulib_handle_t handle
= DEVI(rdip
)->devi_iommulib_handle
;
661 iommulib_unit_t
*unitp
= (iommulib_unit_t
*)handle
;
665 /* No need to grab lock - the handle is reference counted */
666 error
= unitp
->ilu_ops
->ilops_dma_freehdl(handle
, dip
,
673 iommulib_nexdma_bindhdl(dev_info_t
*dip
, dev_info_t
*rdip
,
674 ddi_dma_handle_t dma_handle
, struct ddi_dma_req
*dmareq
,
675 ddi_dma_cookie_t
*cookiep
, uint_t
*ccountp
)
677 iommulib_handle_t handle
= DEVI(rdip
)->devi_iommulib_handle
;
678 iommulib_unit_t
*unitp
= (iommulib_unit_t
*)handle
;
682 /* No need to grab lock - the handle is reference counted */
683 return (unitp
->ilu_ops
->ilops_dma_bindhdl(handle
, dip
, rdip
, dma_handle
,
684 dmareq
, cookiep
, ccountp
));
688 iommulib_nexdma_unbindhdl(dev_info_t
*dip
, dev_info_t
*rdip
,
689 ddi_dma_handle_t dma_handle
)
691 iommulib_handle_t handle
= DEVI(rdip
)->devi_iommulib_handle
;
692 iommulib_unit_t
*unitp
= (iommulib_unit_t
*)handle
;
696 /* No need to grab lock - the handle is reference counted */
697 return (unitp
->ilu_ops
->ilops_dma_unbindhdl(handle
, dip
, rdip
,
702 iommulib_nexdma_sync(dev_info_t
*dip
, dev_info_t
*rdip
,
703 ddi_dma_handle_t dma_handle
, off_t off
, size_t len
,
706 iommulib_handle_t handle
= DEVI(rdip
)->devi_iommulib_handle
;
707 iommulib_unit_t
*unitp
= (iommulib_unit_t
*)handle
;
711 /* No need to grab lock - the handle is reference counted */
712 return (unitp
->ilu_ops
->ilops_dma_sync(handle
, dip
, rdip
, dma_handle
,
713 off
, len
, cache_flags
));
717 iommulib_nexdma_win(dev_info_t
*dip
, dev_info_t
*rdip
,
718 ddi_dma_handle_t dma_handle
, uint_t win
, off_t
*offp
, size_t *lenp
,
719 ddi_dma_cookie_t
*cookiep
, uint_t
*ccountp
)
721 iommulib_handle_t handle
= DEVI(rdip
)->devi_iommulib_handle
;
722 iommulib_unit_t
*unitp
= (iommulib_unit_t
*)handle
;
726 /* No need to grab lock - the handle is reference counted */
727 return (unitp
->ilu_ops
->ilops_dma_win(handle
, dip
, rdip
, dma_handle
,
728 win
, offp
, lenp
, cookiep
, ccountp
));
732 iommulib_nexdma_mapobject(dev_info_t
*dip
, dev_info_t
*rdip
,
733 ddi_dma_handle_t dma_handle
, struct ddi_dma_req
*dmareq
,
736 iommulib_handle_t handle
= DEVI(rdip
)->devi_iommulib_handle
;
737 iommulib_unit_t
*unitp
= (iommulib_unit_t
*)handle
;
739 return (unitp
->ilu_ops
->ilops_dma_mapobject(handle
, dip
, rdip
,
740 dma_handle
, dmareq
, dmao
));
744 iommulib_nexdma_unmapobject(dev_info_t
*dip
, dev_info_t
*rdip
,
745 ddi_dma_handle_t dma_handle
, ddi_dma_obj_t
*dmao
)
747 iommulib_handle_t handle
= DEVI(rdip
)->devi_iommulib_handle
;
748 iommulib_unit_t
*unitp
= (iommulib_unit_t
*)handle
;
750 return (unitp
->ilu_ops
->ilops_dma_unmapobject(handle
, dip
, rdip
,
754 /* Utility routines invoked by IOMMU drivers */
756 iommulib_iommu_dma_allochdl(dev_info_t
*dip
, dev_info_t
*rdip
,
757 ddi_dma_attr_t
*attr
, int (*waitfp
)(caddr_t
), caddr_t arg
,
758 ddi_dma_handle_t
*handlep
)
760 iommulib_nexops_t
*nexops
;
762 nexops
= &DEVI(dip
)->devi_iommulib_nex_handle
->nex_ops
;
763 return (nexops
->nops_dma_allochdl(dip
, rdip
, attr
, waitfp
, arg
,
768 iommulib_iommu_dma_freehdl(dev_info_t
*dip
, dev_info_t
*rdip
,
769 ddi_dma_handle_t handle
)
771 iommulib_nexops_t
*nexops
;
773 nexops
= &DEVI(dip
)->devi_iommulib_nex_handle
->nex_ops
;
775 return (nexops
->nops_dma_freehdl(dip
, rdip
, handle
));
779 iommulib_iommu_dma_bindhdl(dev_info_t
*dip
, dev_info_t
*rdip
,
780 ddi_dma_handle_t handle
, struct ddi_dma_req
*dmareq
,
781 ddi_dma_cookie_t
*cookiep
, uint_t
*ccountp
)
783 iommulib_nexops_t
*nexops
;
785 nexops
= &DEVI(dip
)->devi_iommulib_nex_handle
->nex_ops
;
786 return (nexops
->nops_dma_bindhdl(dip
, rdip
, handle
, dmareq
,
791 iommulib_iommu_dma_unbindhdl(dev_info_t
*dip
, dev_info_t
*rdip
,
792 ddi_dma_handle_t handle
)
794 iommulib_nexops_t
*nexops
;
796 nexops
= &DEVI(dip
)->devi_iommulib_nex_handle
->nex_ops
;
797 return (nexops
->nops_dma_unbindhdl(dip
, rdip
, handle
));
801 iommulib_iommu_dma_reset_cookies(dev_info_t
*dip
, ddi_dma_handle_t handle
)
803 iommulib_nexops_t
*nexops
;
805 nexops
= &DEVI(dip
)->devi_iommulib_nex_handle
->nex_ops
;
806 nexops
->nops_dma_reset_cookies(dip
, handle
);
810 iommulib_iommu_dma_get_cookies(dev_info_t
*dip
, ddi_dma_handle_t handle
,
811 ddi_dma_cookie_t
**cookiepp
, uint_t
*ccountp
)
813 iommulib_nexops_t
*nexops
;
815 nexops
= &DEVI(dip
)->devi_iommulib_nex_handle
->nex_ops
;
816 return (nexops
->nops_dma_get_cookies(dip
, handle
, cookiepp
, ccountp
));
820 iommulib_iommu_dma_set_cookies(dev_info_t
*dip
, ddi_dma_handle_t handle
,
821 ddi_dma_cookie_t
*cookiep
, uint_t ccount
)
823 iommulib_nexops_t
*nexops
;
825 nexops
= &DEVI(dip
)->devi_iommulib_nex_handle
->nex_ops
;
826 return (nexops
->nops_dma_set_cookies(dip
, handle
, cookiep
, ccount
));
830 iommulib_iommu_dma_clear_cookies(dev_info_t
*dip
, ddi_dma_handle_t handle
)
832 iommulib_nexops_t
*nexops
;
834 nexops
= &DEVI(dip
)->devi_iommulib_nex_handle
->nex_ops
;
835 return (nexops
->nops_dma_clear_cookies(dip
, handle
));
839 iommulib_iommu_dma_get_sleep_flags(dev_info_t
*dip
, ddi_dma_handle_t handle
)
841 iommulib_nexops_t
*nexops
;
843 nexops
= &DEVI(dip
)->devi_iommulib_nex_handle
->nex_ops
;
844 return (nexops
->nops_dma_get_sleep_flags(handle
));
848 iommulib_iommu_dma_sync(dev_info_t
*dip
, dev_info_t
*rdip
,
849 ddi_dma_handle_t handle
, off_t off
, size_t len
, uint_t cache_flags
)
851 iommulib_nexops_t
*nexops
;
853 nexops
= &DEVI(dip
)->devi_iommulib_nex_handle
->nex_ops
;
854 return (nexops
->nops_dma_sync(dip
, rdip
, handle
, off
, len
,
859 iommulib_iommu_dma_win(dev_info_t
*dip
, dev_info_t
*rdip
,
860 ddi_dma_handle_t handle
, uint_t win
, off_t
*offp
, size_t *lenp
,
861 ddi_dma_cookie_t
*cookiep
, uint_t
*ccountp
)
863 iommulib_nexops_t
*nexops
;
865 nexops
= &DEVI(dip
)->devi_iommulib_nex_handle
->nex_ops
;
866 return (nexops
->nops_dma_win(dip
, rdip
, handle
, win
, offp
, lenp
,
871 iommulib_iommu_dmahdl_setprivate(dev_info_t
*dip
, dev_info_t
*rdip
,
872 ddi_dma_handle_t handle
, void *priv
)
874 iommulib_nexops_t
*nexops
;
876 nexops
= &DEVI(dip
)->devi_iommulib_nex_handle
->nex_ops
;
877 return (nexops
->nops_dmahdl_setprivate(dip
, rdip
, handle
, priv
));
881 iommulib_iommu_dmahdl_getprivate(dev_info_t
*dip
, dev_info_t
*rdip
,
882 ddi_dma_handle_t handle
)
884 iommulib_nexops_t
*nexops
;
886 nexops
= &DEVI(dip
)->devi_iommulib_nex_handle
->nex_ops
;
887 return (nexops
->nops_dmahdl_getprivate(dip
, rdip
, handle
));
891 iommulib_iommu_getunitid(iommulib_handle_t handle
, uint64_t *unitidp
)
893 iommulib_unit_t
*unitp
;
896 unitp
= (iommulib_unit_t
*)handle
;
901 mutex_enter(&unitp
->ilu_lock
);
902 unitid
= unitp
->ilu_unitid
;
903 mutex_exit(&unitp
->ilu_lock
);
906 *unitidp
= (uint64_t)unitid
;
908 return (DDI_SUCCESS
);
912 iommulib_iommu_getdip(iommulib_handle_t handle
)
914 iommulib_unit_t
*unitp
;
917 unitp
= (iommulib_unit_t
*)handle
;
921 mutex_enter(&unitp
->ilu_lock
);
922 dip
= unitp
->ilu_dip
;
925 mutex_exit(&unitp
->ilu_lock
);
931 iommulib_iommu_getops(iommulib_handle_t handle
)
933 iommulib_unit_t
*unitp
;
936 unitp
= (iommulib_unit_t
*)handle
;
940 mutex_enter(&unitp
->ilu_lock
);
941 ops
= unitp
->ilu_ops
;
942 mutex_exit(&unitp
->ilu_lock
);
950 iommulib_iommu_getdata(iommulib_handle_t handle
)
952 iommulib_unit_t
*unitp
;
955 unitp
= (iommulib_unit_t
*)handle
;
959 mutex_enter(&unitp
->ilu_lock
);
960 data
= unitp
->ilu_data
;
961 mutex_exit(&unitp
->ilu_lock
);