120906b23SVikram Hegde /*
220906b23SVikram Hegde * CDDL HEADER START
320906b23SVikram Hegde *
420906b23SVikram Hegde * The contents of this file are subject to the terms of the
520906b23SVikram Hegde * Common Development and Distribution License (the "License").
620906b23SVikram Hegde * You may not use this file except in compliance with the License.
720906b23SVikram Hegde *
820906b23SVikram Hegde * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
920906b23SVikram Hegde * or http://www.opensolaris.org/os/licensing.
1020906b23SVikram Hegde * See the License for the specific language governing permissions
1120906b23SVikram Hegde * and limitations under the License.
1220906b23SVikram Hegde *
1320906b23SVikram Hegde * When distributing Covered Code, include this CDDL HEADER in each
1420906b23SVikram Hegde * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1520906b23SVikram Hegde * If applicable, add the following below this CDDL HEADER, with the
1620906b23SVikram Hegde * fields enclosed by brackets "[]" replaced with your own identifying
1720906b23SVikram Hegde * information: Portions Copyright [yyyy] [name of copyright owner]
1820906b23SVikram Hegde *
1920906b23SVikram Hegde * CDDL HEADER END
2020906b23SVikram Hegde */
2120906b23SVikram Hegde /*
2250200e77SFrank Van Der Linden * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23*cd21e7c5SGarrett D'Amore * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved.
2420906b23SVikram Hegde */
2520906b23SVikram Hegde
2620906b23SVikram Hegde #include <sys/sunddi.h>
2720906b23SVikram Hegde #include <sys/sunndi.h>
2820906b23SVikram Hegde #include <sys/errno.h>
2920906b23SVikram Hegde #include <sys/modctl.h>
3020906b23SVikram Hegde #include <sys/iommulib.h>
3120906b23SVikram Hegde
3220906b23SVikram Hegde /* ******** Type definitions private to this file ********************** */
3320906b23SVikram Hegde
3420906b23SVikram Hegde /* 1 per IOMMU unit. There may be more than one per dip */
3520906b23SVikram Hegde typedef struct iommulib_unit {
3620906b23SVikram Hegde kmutex_t ilu_lock;
3720906b23SVikram Hegde uint64_t ilu_ref;
3820906b23SVikram Hegde uint32_t ilu_unitid;
3920906b23SVikram Hegde dev_info_t *ilu_dip;
4020906b23SVikram Hegde iommulib_ops_t *ilu_ops;
4120906b23SVikram Hegde void* ilu_data;
4220906b23SVikram Hegde struct iommulib_unit *ilu_next;
4320906b23SVikram Hegde struct iommulib_unit *ilu_prev;
4450200e77SFrank Van Der Linden iommulib_nexhandle_t ilu_nex;
4520906b23SVikram Hegde } iommulib_unit_t;
4620906b23SVikram Hegde
4720906b23SVikram Hegde typedef struct iommulib_nex {
4820906b23SVikram Hegde dev_info_t *nex_dip;
4920906b23SVikram Hegde iommulib_nexops_t nex_ops;
5020906b23SVikram Hegde struct iommulib_nex *nex_next;
5120906b23SVikram Hegde struct iommulib_nex *nex_prev;
5250200e77SFrank Van Der Linden uint_t nex_ref;
5320906b23SVikram Hegde } iommulib_nex_t;
5420906b23SVikram Hegde
5520906b23SVikram Hegde /* ********* Globals ************************ */
5620906b23SVikram Hegde
5765cf7c95SVikram Hegde /* For IOMMU drivers */
5865cf7c95SVikram Hegde smbios_hdl_t *iommulib_smbios;
5965cf7c95SVikram Hegde
6020906b23SVikram Hegde /* IOMMU side: Following data protected by lock */
6120906b23SVikram Hegde static kmutex_t iommulib_lock;
6220906b23SVikram Hegde static iommulib_unit_t *iommulib_list;
6320906b23SVikram Hegde static uint64_t iommulib_unit_ids = 0;
6420906b23SVikram Hegde static uint64_t iommulib_num_units = 0;
6520906b23SVikram Hegde
6620906b23SVikram Hegde /* rootnex side data */
6720906b23SVikram Hegde
6820906b23SVikram Hegde static kmutex_t iommulib_nexus_lock;
6920906b23SVikram Hegde static iommulib_nex_t *iommulib_nexus_list;
7020906b23SVikram Hegde
7120906b23SVikram Hegde /* can be set atomically without lock */
7220906b23SVikram Hegde static volatile uint32_t iommulib_fini;
7320906b23SVikram Hegde
7420906b23SVikram Hegde /* debug flag */
7520906b23SVikram Hegde static int iommulib_debug;
7620906b23SVikram Hegde
7720906b23SVikram Hegde /*
7820906b23SVikram Hegde * Module linkage information for the kernel.
7920906b23SVikram Hegde */
8020906b23SVikram Hegde static struct modlmisc modlmisc = {
8120906b23SVikram Hegde &mod_miscops, "IOMMU library module"
8220906b23SVikram Hegde };
8320906b23SVikram Hegde
8420906b23SVikram Hegde static struct modlinkage modlinkage = {
8520906b23SVikram Hegde MODREV_1, (void *)&modlmisc, NULL
8620906b23SVikram Hegde };
8720906b23SVikram Hegde
8820906b23SVikram Hegde int
_init(void)8920906b23SVikram Hegde _init(void)
9020906b23SVikram Hegde {
9120906b23SVikram Hegde return (mod_install(&modlinkage));
9220906b23SVikram Hegde }
9320906b23SVikram Hegde
9420906b23SVikram Hegde int
_fini(void)9520906b23SVikram Hegde _fini(void)
9620906b23SVikram Hegde {
9720906b23SVikram Hegde mutex_enter(&iommulib_lock);
9820906b23SVikram Hegde if (iommulib_list != NULL || iommulib_nexus_list != NULL) {
9920906b23SVikram Hegde mutex_exit(&iommulib_lock);
10020906b23SVikram Hegde return (EBUSY);
10120906b23SVikram Hegde }
10220906b23SVikram Hegde iommulib_fini = 1;
10320906b23SVikram Hegde
10420906b23SVikram Hegde mutex_exit(&iommulib_lock);
10520906b23SVikram Hegde return (mod_remove(&modlinkage));
10620906b23SVikram Hegde }
10720906b23SVikram Hegde
10820906b23SVikram Hegde int
_info(struct modinfo * modinfop)10920906b23SVikram Hegde _info(struct modinfo *modinfop)
11020906b23SVikram Hegde {
11120906b23SVikram Hegde return (mod_info(&modlinkage, modinfop));
11220906b23SVikram Hegde }
11320906b23SVikram Hegde
11420906b23SVikram Hegde /*
11520906b23SVikram Hegde * Routines with iommulib_iommu_* are invoked from the
11620906b23SVikram Hegde * IOMMU driver.
11720906b23SVikram Hegde * Routines with iommulib_nex* are invoked from the
11820906b23SVikram Hegde * nexus driver (typically rootnex)
11920906b23SVikram Hegde */
12020906b23SVikram Hegde
12120906b23SVikram Hegde int
iommulib_nexus_register(dev_info_t * dip,iommulib_nexops_t * nexops,iommulib_nexhandle_t * handle)12220906b23SVikram Hegde iommulib_nexus_register(dev_info_t *dip, iommulib_nexops_t *nexops,
12320906b23SVikram Hegde iommulib_nexhandle_t *handle)
12420906b23SVikram Hegde {
12520906b23SVikram Hegde iommulib_nex_t *nexp;
12620906b23SVikram Hegde int instance = ddi_get_instance(dip);
12720906b23SVikram Hegde const char *driver = ddi_driver_name(dip);
12820906b23SVikram Hegde dev_info_t *pdip = ddi_get_parent(dip);
12920906b23SVikram Hegde const char *f = "iommulib_nexus_register";
13020906b23SVikram Hegde
13120906b23SVikram Hegde ASSERT(nexops);
13220906b23SVikram Hegde ASSERT(handle);
13320906b23SVikram Hegde
13420906b23SVikram Hegde *handle = NULL;
13520906b23SVikram Hegde
13620906b23SVikram Hegde /*
13720906b23SVikram Hegde * Root node is never busy held
13820906b23SVikram Hegde */
13920906b23SVikram Hegde if (dip != ddi_root_node() && (i_ddi_node_state(dip) < DS_PROBED ||
14020906b23SVikram Hegde !DEVI_BUSY_OWNED(pdip))) {
14120906b23SVikram Hegde cmn_err(CE_WARN, "%s: NEXUS devinfo node not in DS_PROBED "
14220906b23SVikram Hegde "or busy held for nexops vector (%p). Failing registration",
14320906b23SVikram Hegde f, (void *)nexops);
14420906b23SVikram Hegde return (DDI_FAILURE);
14520906b23SVikram Hegde }
14620906b23SVikram Hegde
14720906b23SVikram Hegde if (nexops->nops_vers != IOMMU_NEXOPS_VERSION) {
14820906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: Invalid IOMMULIB nexops version "
14920906b23SVikram Hegde "in nexops vector (%p). Failing NEXUS registration",
15020906b23SVikram Hegde f, driver, instance, (void *)nexops);
15120906b23SVikram Hegde return (DDI_FAILURE);
15220906b23SVikram Hegde }
15320906b23SVikram Hegde
15420906b23SVikram Hegde ASSERT(nexops->nops_data == NULL);
15520906b23SVikram Hegde
15620906b23SVikram Hegde if (nexops->nops_id == NULL) {
15720906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL ID field. "
15820906b23SVikram Hegde "Failing registration for nexops vector: %p",
15920906b23SVikram Hegde f, driver, instance, (void *)nexops);
16020906b23SVikram Hegde return (DDI_FAILURE);
16120906b23SVikram Hegde }
16220906b23SVikram Hegde
16320906b23SVikram Hegde if (nexops->nops_dma_allochdl == NULL) {
16420906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_allochdl op. "
16520906b23SVikram Hegde "Failing registration for ops vector: %p", f,
16620906b23SVikram Hegde driver, instance, (void *)nexops);
16720906b23SVikram Hegde return (DDI_FAILURE);
16820906b23SVikram Hegde }
16920906b23SVikram Hegde
17020906b23SVikram Hegde if (nexops->nops_dma_freehdl == NULL) {
17120906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_freehdl op. "
17220906b23SVikram Hegde "Failing registration for ops vector: %p", f,
17320906b23SVikram Hegde driver, instance, (void *)nexops);
17420906b23SVikram Hegde return (DDI_FAILURE);
17520906b23SVikram Hegde }
17620906b23SVikram Hegde
17720906b23SVikram Hegde if (nexops->nops_dma_bindhdl == NULL) {
17820906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_bindhdl op. "
17920906b23SVikram Hegde "Failing registration for ops vector: %p", f,
18020906b23SVikram Hegde driver, instance, (void *)nexops);
18120906b23SVikram Hegde return (DDI_FAILURE);
18220906b23SVikram Hegde }
18320906b23SVikram Hegde
18420906b23SVikram Hegde if (nexops->nops_dma_sync == NULL) {
18520906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_sync op. "
18620906b23SVikram Hegde "Failing registration for ops vector: %p", f,
18720906b23SVikram Hegde driver, instance, (void *)nexops);
18820906b23SVikram Hegde return (DDI_FAILURE);
18920906b23SVikram Hegde }
19020906b23SVikram Hegde
19120906b23SVikram Hegde if (nexops->nops_dma_reset_cookies == NULL) {
19220906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_reset_cookies op. "
19320906b23SVikram Hegde "Failing registration for ops vector: %p", f,
19420906b23SVikram Hegde driver, instance, (void *)nexops);
19520906b23SVikram Hegde return (DDI_FAILURE);
19620906b23SVikram Hegde }
19720906b23SVikram Hegde
19820906b23SVikram Hegde if (nexops->nops_dma_get_cookies == NULL) {
19920906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_get_cookies op. "
20020906b23SVikram Hegde "Failing registration for ops vector: %p", f,
20120906b23SVikram Hegde driver, instance, (void *)nexops);
20220906b23SVikram Hegde return (DDI_FAILURE);
20320906b23SVikram Hegde }
20420906b23SVikram Hegde
20594f1124eSVikram Hegde if (nexops->nops_dma_set_cookies == NULL) {
20694f1124eSVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_set_cookies op. "
20794f1124eSVikram Hegde "Failing registration for ops vector: %p", f,
20894f1124eSVikram Hegde driver, instance, (void *)nexops);
20994f1124eSVikram Hegde return (DDI_FAILURE);
21094f1124eSVikram Hegde }
21194f1124eSVikram Hegde
21294f1124eSVikram Hegde if (nexops->nops_dma_clear_cookies == NULL) {
21394f1124eSVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_clear_cookies op. "
21494f1124eSVikram Hegde "Failing registration for ops vector: %p", f,
21594f1124eSVikram Hegde driver, instance, (void *)nexops);
21694f1124eSVikram Hegde return (DDI_FAILURE);
21794f1124eSVikram Hegde }
21894f1124eSVikram Hegde
21994f1124eSVikram Hegde if (nexops->nops_dma_get_sleep_flags == NULL) {
22094f1124eSVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_get_sleep_flags op. "
22194f1124eSVikram Hegde "Failing registration for ops vector: %p", f,
22294f1124eSVikram Hegde driver, instance, (void *)nexops);
22394f1124eSVikram Hegde return (DDI_FAILURE);
22494f1124eSVikram Hegde }
22594f1124eSVikram Hegde
22620906b23SVikram Hegde if (nexops->nops_dma_win == NULL) {
22720906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_win op. "
22820906b23SVikram Hegde "Failing registration for ops vector: %p", f,
22920906b23SVikram Hegde driver, instance, (void *)nexops);
23020906b23SVikram Hegde return (DDI_FAILURE);
23120906b23SVikram Hegde }
23220906b23SVikram Hegde
23350200e77SFrank Van Der Linden if (nexops->nops_dmahdl_setprivate == NULL) {
23450200e77SFrank Van Der Linden cmn_err(CE_WARN, "%s: %s%d: NULL nops_dmahdl_setprivate op. "
23550200e77SFrank Van Der Linden "Failing registration for ops vector: %p", f,
23650200e77SFrank Van Der Linden driver, instance, (void *)nexops);
23750200e77SFrank Van Der Linden return (DDI_FAILURE);
23850200e77SFrank Van Der Linden }
23950200e77SFrank Van Der Linden
24050200e77SFrank Van Der Linden if (nexops->nops_dmahdl_getprivate == NULL) {
24150200e77SFrank Van Der Linden cmn_err(CE_WARN, "%s: %s%d: NULL nops_dmahdl_getprivate op. "
24250200e77SFrank Van Der Linden "Failing registration for ops vector: %p", f,
24350200e77SFrank Van Der Linden driver, instance, (void *)nexops);
24450200e77SFrank Van Der Linden return (DDI_FAILURE);
24550200e77SFrank Van Der Linden }
24650200e77SFrank Van Der Linden
24720906b23SVikram Hegde nexp = kmem_zalloc(sizeof (iommulib_nex_t), KM_SLEEP);
24820906b23SVikram Hegde
24920906b23SVikram Hegde mutex_enter(&iommulib_lock);
25020906b23SVikram Hegde if (iommulib_fini == 1) {
25120906b23SVikram Hegde mutex_exit(&iommulib_lock);
25220906b23SVikram Hegde cmn_err(CE_WARN, "%s: IOMMULIB unloading. "
25320906b23SVikram Hegde "Failing NEXUS register.", f);
25420906b23SVikram Hegde kmem_free(nexp, sizeof (iommulib_nex_t));
25520906b23SVikram Hegde return (DDI_FAILURE);
25620906b23SVikram Hegde }
25720906b23SVikram Hegde
25820906b23SVikram Hegde /*
25920906b23SVikram Hegde * fini/register race conditions have been handled. Now create the
26020906b23SVikram Hegde * nexus struct
26120906b23SVikram Hegde */
26220906b23SVikram Hegde ndi_hold_devi(dip);
26320906b23SVikram Hegde nexp->nex_dip = dip;
26420906b23SVikram Hegde nexp->nex_ops = *nexops;
26520906b23SVikram Hegde
26620906b23SVikram Hegde mutex_enter(&iommulib_nexus_lock);
26720906b23SVikram Hegde nexp->nex_next = iommulib_nexus_list;
26820906b23SVikram Hegde iommulib_nexus_list = nexp;
26920906b23SVikram Hegde nexp->nex_prev = NULL;
27020906b23SVikram Hegde
27120906b23SVikram Hegde if (nexp->nex_next != NULL)
27220906b23SVikram Hegde nexp->nex_next->nex_prev = nexp;
27320906b23SVikram Hegde
27450200e77SFrank Van Der Linden nexp->nex_ref = 0;
27550200e77SFrank Van Der Linden
27650200e77SFrank Van Der Linden /*
27750200e77SFrank Van Der Linden * The nexus device won't be controlled by an IOMMU.
27850200e77SFrank Van Der Linden */
27950200e77SFrank Van Der Linden DEVI(dip)->devi_iommulib_handle = IOMMU_HANDLE_UNUSED;
28050200e77SFrank Van Der Linden
28150200e77SFrank Van Der Linden DEVI(dip)->devi_iommulib_nex_handle = nexp;
28250200e77SFrank Van Der Linden
28320906b23SVikram Hegde mutex_exit(&iommulib_nexus_lock);
28420906b23SVikram Hegde mutex_exit(&iommulib_lock);
28520906b23SVikram Hegde
28620906b23SVikram Hegde cmn_err(CE_NOTE, "!%s: %s%d: Succesfully registered NEXUS %s "
28720906b23SVikram Hegde "nexops=%p", f, driver, instance, ddi_node_name(dip),
28820906b23SVikram Hegde (void *)nexops);
28920906b23SVikram Hegde
29020906b23SVikram Hegde *handle = nexp;
29120906b23SVikram Hegde
29220906b23SVikram Hegde return (DDI_SUCCESS);
29320906b23SVikram Hegde }
29420906b23SVikram Hegde
29520906b23SVikram Hegde int
iommulib_nexus_unregister(iommulib_nexhandle_t handle)29620906b23SVikram Hegde iommulib_nexus_unregister(iommulib_nexhandle_t handle)
29720906b23SVikram Hegde {
29820906b23SVikram Hegde dev_info_t *dip;
29920906b23SVikram Hegde int instance;
30020906b23SVikram Hegde const char *driver;
30120906b23SVikram Hegde iommulib_nex_t *nexp = (iommulib_nex_t *)handle;
30220906b23SVikram Hegde const char *f = "iommulib_nexus_unregister";
30320906b23SVikram Hegde
30420906b23SVikram Hegde ASSERT(nexp);
30520906b23SVikram Hegde
30650200e77SFrank Van Der Linden if (nexp->nex_ref != 0)
30750200e77SFrank Van Der Linden return (DDI_FAILURE);
30850200e77SFrank Van Der Linden
30920906b23SVikram Hegde mutex_enter(&iommulib_nexus_lock);
31020906b23SVikram Hegde
31120906b23SVikram Hegde dip = nexp->nex_dip;
31220906b23SVikram Hegde driver = ddi_driver_name(dip);
31320906b23SVikram Hegde instance = ddi_get_instance(dip);
31420906b23SVikram Hegde
31520906b23SVikram Hegde /* A future enhancement would be to add ref-counts */
31620906b23SVikram Hegde
31720906b23SVikram Hegde if (nexp->nex_prev == NULL) {
31820906b23SVikram Hegde iommulib_nexus_list = nexp->nex_next;
31920906b23SVikram Hegde } else {
32020906b23SVikram Hegde nexp->nex_prev->nex_next = nexp->nex_next;
32120906b23SVikram Hegde }
32220906b23SVikram Hegde
32320906b23SVikram Hegde if (nexp->nex_next != NULL)
32420906b23SVikram Hegde nexp->nex_next->nex_prev = nexp->nex_prev;
32520906b23SVikram Hegde
32620906b23SVikram Hegde mutex_exit(&iommulib_nexus_lock);
32720906b23SVikram Hegde
32820906b23SVikram Hegde kmem_free(nexp, sizeof (iommulib_nex_t));
32920906b23SVikram Hegde
33094f1124eSVikram Hegde cmn_err(CE_NOTE, "!%s: %s%d: NEXUS (%s) handle successfully "
33120906b23SVikram Hegde "unregistered from IOMMULIB", f, driver, instance,
33220906b23SVikram Hegde ddi_node_name(dip));
33320906b23SVikram Hegde
33420906b23SVikram Hegde ndi_rele_devi(dip);
33520906b23SVikram Hegde
33620906b23SVikram Hegde return (DDI_SUCCESS);
33720906b23SVikram Hegde }
33820906b23SVikram Hegde
33920906b23SVikram Hegde int
iommulib_iommu_register(dev_info_t * dip,iommulib_ops_t * ops,iommulib_handle_t * handle)34020906b23SVikram Hegde iommulib_iommu_register(dev_info_t *dip, iommulib_ops_t *ops,
34120906b23SVikram Hegde iommulib_handle_t *handle)
34220906b23SVikram Hegde {
34320906b23SVikram Hegde const char *vendor;
34420906b23SVikram Hegde iommulib_unit_t *unitp;
34520906b23SVikram Hegde int instance = ddi_get_instance(dip);
34620906b23SVikram Hegde const char *driver = ddi_driver_name(dip);
34720906b23SVikram Hegde const char *f = "iommulib_register";
34820906b23SVikram Hegde
34920906b23SVikram Hegde ASSERT(ops);
35020906b23SVikram Hegde ASSERT(handle);
35120906b23SVikram Hegde
35220906b23SVikram Hegde if (ops->ilops_vers != IOMMU_OPS_VERSION) {
35320906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: Invalid IOMMULIB ops version "
35420906b23SVikram Hegde "in ops vector (%p). Failing registration", f, driver,
35520906b23SVikram Hegde instance, (void *)ops);
35620906b23SVikram Hegde return (DDI_FAILURE);
35720906b23SVikram Hegde }
35820906b23SVikram Hegde
35920906b23SVikram Hegde switch (ops->ilops_vendor) {
36020906b23SVikram Hegde case AMD_IOMMU:
36120906b23SVikram Hegde vendor = "AMD";
36220906b23SVikram Hegde break;
36320906b23SVikram Hegde case INTEL_IOMMU:
36420906b23SVikram Hegde vendor = "Intel";
36520906b23SVikram Hegde break;
36620906b23SVikram Hegde case INVALID_VENDOR:
36720906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: vendor field (%x) not initialized. "
36820906b23SVikram Hegde "Failing registration for ops vector: %p", f,
36920906b23SVikram Hegde driver, instance, ops->ilops_vendor, (void *)ops);
37020906b23SVikram Hegde return (DDI_FAILURE);
37120906b23SVikram Hegde default:
37220906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: Invalid vendor field (%x). "
37320906b23SVikram Hegde "Failing registration for ops vector: %p", f,
37420906b23SVikram Hegde driver, instance, ops->ilops_vendor, (void *)ops);
37520906b23SVikram Hegde return (DDI_FAILURE);
37620906b23SVikram Hegde }
37720906b23SVikram Hegde
37894f1124eSVikram Hegde cmn_err(CE_NOTE, "!%s: %s%d: Detected IOMMU registration from vendor"
37994f1124eSVikram Hegde " %s", f, driver, instance, vendor);
38020906b23SVikram Hegde
38120906b23SVikram Hegde if (ops->ilops_data == NULL) {
38220906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL IOMMU data field. "
38320906b23SVikram Hegde "Failing registration for ops vector: %p", f,
38420906b23SVikram Hegde driver, instance, (void *)ops);
38520906b23SVikram Hegde return (DDI_FAILURE);
38620906b23SVikram Hegde }
38720906b23SVikram Hegde
38820906b23SVikram Hegde if (ops->ilops_id == NULL) {
38920906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL ID field. "
39020906b23SVikram Hegde "Failing registration for ops vector: %p", f,
39120906b23SVikram Hegde driver, instance, (void *)ops);
39220906b23SVikram Hegde return (DDI_FAILURE);
39320906b23SVikram Hegde }
39420906b23SVikram Hegde
39520906b23SVikram Hegde if (ops->ilops_probe == NULL) {
39620906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL probe op. "
39720906b23SVikram Hegde "Failing registration for ops vector: %p", f,
39820906b23SVikram Hegde driver, instance, (void *)ops);
39920906b23SVikram Hegde return (DDI_FAILURE);
40020906b23SVikram Hegde }
40120906b23SVikram Hegde
40220906b23SVikram Hegde if (ops->ilops_dma_allochdl == NULL) {
40320906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL dma_allochdl op. "
40420906b23SVikram Hegde "Failing registration for ops vector: %p", f,
40520906b23SVikram Hegde driver, instance, (void *)ops);
40620906b23SVikram Hegde return (DDI_FAILURE);
40720906b23SVikram Hegde }
40820906b23SVikram Hegde
40920906b23SVikram Hegde if (ops->ilops_dma_freehdl == NULL) {
41020906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL dma_freehdl op. "
41120906b23SVikram Hegde "Failing registration for ops vector: %p", f,
41220906b23SVikram Hegde driver, instance, (void *)ops);
41320906b23SVikram Hegde return (DDI_FAILURE);
41420906b23SVikram Hegde }
41520906b23SVikram Hegde
41620906b23SVikram Hegde if (ops->ilops_dma_bindhdl == NULL) {
41720906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL dma_bindhdl op. "
41820906b23SVikram Hegde "Failing registration for ops vector: %p", f,
41920906b23SVikram Hegde driver, instance, (void *)ops);
42020906b23SVikram Hegde return (DDI_FAILURE);
42120906b23SVikram Hegde }
42220906b23SVikram Hegde
42320906b23SVikram Hegde if (ops->ilops_dma_sync == NULL) {
42420906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL dma_sync op. "
42520906b23SVikram Hegde "Failing registration for ops vector: %p", f,
42620906b23SVikram Hegde driver, instance, (void *)ops);
42720906b23SVikram Hegde return (DDI_FAILURE);
42820906b23SVikram Hegde }
42920906b23SVikram Hegde
43020906b23SVikram Hegde if (ops->ilops_dma_win == NULL) {
43120906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL dma_win op. "
43220906b23SVikram Hegde "Failing registration for ops vector: %p", f,
43320906b23SVikram Hegde driver, instance, (void *)ops);
43420906b23SVikram Hegde return (DDI_FAILURE);
43520906b23SVikram Hegde }
43620906b23SVikram Hegde
43720906b23SVikram Hegde unitp = kmem_zalloc(sizeof (iommulib_unit_t), KM_SLEEP);
43820906b23SVikram Hegde mutex_enter(&iommulib_lock);
43920906b23SVikram Hegde if (iommulib_fini == 1) {
44020906b23SVikram Hegde mutex_exit(&iommulib_lock);
44120906b23SVikram Hegde cmn_err(CE_WARN, "%s: IOMMULIB unloading. Failing register.",
44220906b23SVikram Hegde f);
44320906b23SVikram Hegde kmem_free(unitp, sizeof (iommulib_unit_t));
44420906b23SVikram Hegde return (DDI_FAILURE);
44520906b23SVikram Hegde }
44620906b23SVikram Hegde
44720906b23SVikram Hegde /*
44820906b23SVikram Hegde * fini/register race conditions have been handled. Now create the
44920906b23SVikram Hegde * IOMMU unit
45020906b23SVikram Hegde */
45120906b23SVikram Hegde mutex_init(&unitp->ilu_lock, NULL, MUTEX_DEFAULT, NULL);
45220906b23SVikram Hegde
45320906b23SVikram Hegde mutex_enter(&unitp->ilu_lock);
45420906b23SVikram Hegde unitp->ilu_unitid = ++iommulib_unit_ids;
45520906b23SVikram Hegde unitp->ilu_ref = 0;
45620906b23SVikram Hegde ndi_hold_devi(dip);
45720906b23SVikram Hegde unitp->ilu_dip = dip;
45820906b23SVikram Hegde unitp->ilu_ops = ops;
45920906b23SVikram Hegde unitp->ilu_data = ops->ilops_data;
46020906b23SVikram Hegde
46120906b23SVikram Hegde unitp->ilu_next = iommulib_list;
46220906b23SVikram Hegde iommulib_list = unitp;
46394f1124eSVikram Hegde unitp->ilu_prev = NULL;
46494f1124eSVikram Hegde if (unitp->ilu_next)
46594f1124eSVikram Hegde unitp->ilu_next->ilu_prev = unitp;
46620906b23SVikram Hegde
46750200e77SFrank Van Der Linden /*
46850200e77SFrank Van Der Linden * The IOMMU device itself is not controlled by an IOMMU.
46950200e77SFrank Van Der Linden */
47050200e77SFrank Van Der Linden DEVI(dip)->devi_iommulib_handle = IOMMU_HANDLE_UNUSED;
47150200e77SFrank Van Der Linden
47220906b23SVikram Hegde mutex_exit(&unitp->ilu_lock);
47320906b23SVikram Hegde
47420906b23SVikram Hegde iommulib_num_units++;
47520906b23SVikram Hegde
47620906b23SVikram Hegde *handle = unitp;
47720906b23SVikram Hegde
47820906b23SVikram Hegde mutex_exit(&iommulib_lock);
47920906b23SVikram Hegde
48094f1124eSVikram Hegde cmn_err(CE_NOTE, "!%s: %s%d: Succesfully registered IOMMU unit "
48120906b23SVikram Hegde "from vendor=%s, ops=%p, data=%p, IOMMULIB unitid=%u",
48220906b23SVikram Hegde f, driver, instance, vendor, (void *)ops, (void *)unitp->ilu_data,
48320906b23SVikram Hegde unitp->ilu_unitid);
48420906b23SVikram Hegde
48520906b23SVikram Hegde return (DDI_SUCCESS);
48620906b23SVikram Hegde }
48720906b23SVikram Hegde
48820906b23SVikram Hegde int
iommulib_iommu_unregister(iommulib_handle_t handle)48920906b23SVikram Hegde iommulib_iommu_unregister(iommulib_handle_t handle)
49020906b23SVikram Hegde {
49120906b23SVikram Hegde uint32_t unitid;
49220906b23SVikram Hegde dev_info_t *dip;
49320906b23SVikram Hegde int instance;
49420906b23SVikram Hegde const char *driver;
49520906b23SVikram Hegde iommulib_unit_t *unitp = (iommulib_unit_t *)handle;
49620906b23SVikram Hegde const char *f = "iommulib_unregister";
49720906b23SVikram Hegde
49820906b23SVikram Hegde ASSERT(unitp);
49920906b23SVikram Hegde
50020906b23SVikram Hegde mutex_enter(&iommulib_lock);
50120906b23SVikram Hegde mutex_enter(&unitp->ilu_lock);
50220906b23SVikram Hegde
50320906b23SVikram Hegde unitid = unitp->ilu_unitid;
50420906b23SVikram Hegde dip = unitp->ilu_dip;
50520906b23SVikram Hegde driver = ddi_driver_name(dip);
50620906b23SVikram Hegde instance = ddi_get_instance(dip);
50720906b23SVikram Hegde
50820906b23SVikram Hegde if (unitp->ilu_ref != 0) {
50920906b23SVikram Hegde mutex_exit(&unitp->ilu_lock);
51020906b23SVikram Hegde mutex_exit(&iommulib_lock);
51120906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: IOMMULIB handle is busy. Cannot "
51220906b23SVikram Hegde "unregister IOMMULIB unitid %u",
51320906b23SVikram Hegde f, driver, instance, unitid);
51420906b23SVikram Hegde return (DDI_FAILURE);
51520906b23SVikram Hegde }
51620906b23SVikram Hegde unitp->ilu_unitid = 0;
51720906b23SVikram Hegde ASSERT(unitp->ilu_ref == 0);
51820906b23SVikram Hegde
51920906b23SVikram Hegde if (unitp->ilu_prev == NULL) {
52020906b23SVikram Hegde iommulib_list = unitp->ilu_next;
52120906b23SVikram Hegde unitp->ilu_next->ilu_prev = NULL;
52220906b23SVikram Hegde } else {
52320906b23SVikram Hegde unitp->ilu_prev->ilu_next = unitp->ilu_next;
52420906b23SVikram Hegde unitp->ilu_next->ilu_prev = unitp->ilu_prev;
52520906b23SVikram Hegde }
52620906b23SVikram Hegde
52720906b23SVikram Hegde iommulib_num_units--;
52820906b23SVikram Hegde
52920906b23SVikram Hegde mutex_exit(&unitp->ilu_lock);
53020906b23SVikram Hegde
53120906b23SVikram Hegde mutex_destroy(&unitp->ilu_lock);
53220906b23SVikram Hegde kmem_free(unitp, sizeof (iommulib_unit_t));
53320906b23SVikram Hegde
53420906b23SVikram Hegde mutex_exit(&iommulib_lock);
53520906b23SVikram Hegde
53620906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: IOMMULIB handle (unitid=%u) successfully "
53720906b23SVikram Hegde "unregistered", f, driver, instance, unitid);
53820906b23SVikram Hegde
53920906b23SVikram Hegde ndi_rele_devi(dip);
54020906b23SVikram Hegde
54120906b23SVikram Hegde return (DDI_SUCCESS);
54220906b23SVikram Hegde }
54320906b23SVikram Hegde
54420906b23SVikram Hegde int
iommulib_nex_open(dev_info_t * dip,dev_info_t * rdip)54550200e77SFrank Van Der Linden iommulib_nex_open(dev_info_t *dip, dev_info_t *rdip)
54620906b23SVikram Hegde {
54720906b23SVikram Hegde iommulib_unit_t *unitp;
54820906b23SVikram Hegde int instance = ddi_get_instance(rdip);
54920906b23SVikram Hegde const char *driver = ddi_driver_name(rdip);
55020906b23SVikram Hegde const char *f = "iommulib_nex_open";
55120906b23SVikram Hegde
55250200e77SFrank Van Der Linden ASSERT(DEVI(dip)->devi_iommulib_nex_handle != NULL);
55394f1124eSVikram Hegde ASSERT(DEVI(rdip)->devi_iommulib_handle == NULL);
55420906b23SVikram Hegde
55520906b23SVikram Hegde /* prevent use of IOMMU for AMD IOMMU's DMA */
55620906b23SVikram Hegde if (strcmp(driver, "amd_iommu") == 0) {
55750200e77SFrank Van Der Linden DEVI(rdip)->devi_iommulib_handle = IOMMU_HANDLE_UNUSED;
55850200e77SFrank Van Der Linden return (DDI_ENOTSUP);
55920906b23SVikram Hegde }
56020906b23SVikram Hegde
56120906b23SVikram Hegde /*
56294f1124eSVikram Hegde * Use the probe entry point to determine in a hardware specific
56394f1124eSVikram Hegde * manner whether this dip is controlled by an IOMMU. If yes,
56494f1124eSVikram Hegde * return the handle corresponding to the IOMMU unit.
56520906b23SVikram Hegde */
56620906b23SVikram Hegde
56720906b23SVikram Hegde mutex_enter(&iommulib_lock);
56820906b23SVikram Hegde for (unitp = iommulib_list; unitp; unitp = unitp->ilu_next) {
56994f1124eSVikram Hegde if (unitp->ilu_ops->ilops_probe(unitp, rdip) == DDI_SUCCESS)
57020906b23SVikram Hegde break;
57120906b23SVikram Hegde }
57220906b23SVikram Hegde
57320906b23SVikram Hegde if (unitp == NULL) {
57420906b23SVikram Hegde mutex_exit(&iommulib_lock);
57520906b23SVikram Hegde if (iommulib_debug) {
576d8fc7d07SVikram Hegde char *buf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
57720906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: devinfo node (%p): is not "
57820906b23SVikram Hegde "controlled by an IOMMU: path=%s", f, driver,
57920906b23SVikram Hegde instance, (void *)rdip, ddi_pathname(rdip, buf));
580d8fc7d07SVikram Hegde kmem_free(buf, MAXPATHLEN);
58120906b23SVikram Hegde }
58250200e77SFrank Van Der Linden DEVI(rdip)->devi_iommulib_handle = IOMMU_HANDLE_UNUSED;
58350200e77SFrank Van Der Linden return (DDI_ENOTSUP);
58420906b23SVikram Hegde }
58520906b23SVikram Hegde
58620906b23SVikram Hegde mutex_enter(&unitp->ilu_lock);
58750200e77SFrank Van Der Linden unitp->ilu_nex = DEVI(dip)->devi_iommulib_nex_handle;
58820906b23SVikram Hegde unitp->ilu_ref++;
58950200e77SFrank Van Der Linden DEVI(rdip)->devi_iommulib_handle = unitp;
59020906b23SVikram Hegde mutex_exit(&unitp->ilu_lock);
59120906b23SVikram Hegde mutex_exit(&iommulib_lock);
59220906b23SVikram Hegde
59350200e77SFrank Van Der Linden atomic_inc_uint(&DEVI(dip)->devi_iommulib_nex_handle->nex_ref);
59420906b23SVikram Hegde
59520906b23SVikram Hegde return (DDI_SUCCESS);
59620906b23SVikram Hegde }
59720906b23SVikram Hegde
59820906b23SVikram Hegde void
iommulib_nex_close(dev_info_t * rdip)59920906b23SVikram Hegde iommulib_nex_close(dev_info_t *rdip)
60020906b23SVikram Hegde {
60120906b23SVikram Hegde iommulib_unit_t *unitp;
60220906b23SVikram Hegde const char *driver;
60320906b23SVikram Hegde int instance;
60420906b23SVikram Hegde uint32_t unitid;
60550200e77SFrank Van Der Linden iommulib_nex_t *nexp;
60620906b23SVikram Hegde const char *f = "iommulib_nex_close";
60720906b23SVikram Hegde
60850200e77SFrank Van Der Linden ASSERT(IOMMU_USED(rdip));
60920906b23SVikram Hegde
61050200e77SFrank Van Der Linden unitp = DEVI(rdip)->devi_iommulib_handle;
61120906b23SVikram Hegde
61220906b23SVikram Hegde mutex_enter(&iommulib_lock);
61320906b23SVikram Hegde mutex_enter(&unitp->ilu_lock);
61450200e77SFrank Van Der Linden
61550200e77SFrank Van Der Linden nexp = (iommulib_nex_t *)unitp->ilu_nex;
61650200e77SFrank Van Der Linden DEVI(rdip)->devi_iommulib_handle = NULL;
61750200e77SFrank Van Der Linden
61820906b23SVikram Hegde unitid = unitp->ilu_unitid;
61920906b23SVikram Hegde driver = ddi_driver_name(unitp->ilu_dip);
62020906b23SVikram Hegde instance = ddi_get_instance(unitp->ilu_dip);
62150200e77SFrank Van Der Linden
62220906b23SVikram Hegde unitp->ilu_ref--;
62320906b23SVikram Hegde mutex_exit(&unitp->ilu_lock);
62420906b23SVikram Hegde mutex_exit(&iommulib_lock);
62520906b23SVikram Hegde
62650200e77SFrank Van Der Linden atomic_dec_uint(&nexp->nex_ref);
62750200e77SFrank Van Der Linden
62820906b23SVikram Hegde if (iommulib_debug) {
629d8fc7d07SVikram Hegde char *buf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
630d8fc7d07SVikram Hegde (void) ddi_pathname(rdip, buf);
63120906b23SVikram Hegde cmn_err(CE_NOTE, "%s: %s%d: closing IOMMU for dip (%p), "
63220906b23SVikram Hegde "unitid=%u rdip path = %s", f, driver, instance,
63320906b23SVikram Hegde (void *)rdip, unitid, buf);
634d8fc7d07SVikram Hegde kmem_free(buf, MAXPATHLEN);
63520906b23SVikram Hegde }
63620906b23SVikram Hegde }
63720906b23SVikram Hegde
63820906b23SVikram Hegde int
iommulib_nexdma_allochdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_attr_t * attr,int (* waitfp)(caddr_t),caddr_t arg,ddi_dma_handle_t * dma_handlep)63920906b23SVikram Hegde iommulib_nexdma_allochdl(dev_info_t *dip, dev_info_t *rdip,
64020906b23SVikram Hegde ddi_dma_attr_t *attr, int (*waitfp)(caddr_t),
64120906b23SVikram Hegde caddr_t arg, ddi_dma_handle_t *dma_handlep)
64220906b23SVikram Hegde {
64320906b23SVikram Hegde iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle;
64420906b23SVikram Hegde iommulib_unit_t *unitp = (iommulib_unit_t *)handle;
64520906b23SVikram Hegde
64620906b23SVikram Hegde ASSERT(unitp);
64720906b23SVikram Hegde
64820906b23SVikram Hegde /* No need to grab lock - the handle is reference counted */
64920906b23SVikram Hegde return (unitp->ilu_ops->ilops_dma_allochdl(handle, dip, rdip,
65020906b23SVikram Hegde attr, waitfp, arg, dma_handlep));
65120906b23SVikram Hegde }
65220906b23SVikram Hegde
65320906b23SVikram Hegde int
iommulib_nexdma_freehdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t dma_handle)65420906b23SVikram Hegde iommulib_nexdma_freehdl(dev_info_t *dip, dev_info_t *rdip,
65520906b23SVikram Hegde ddi_dma_handle_t dma_handle)
65620906b23SVikram Hegde {
65720906b23SVikram Hegde int error;
65820906b23SVikram Hegde iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle;
65920906b23SVikram Hegde iommulib_unit_t *unitp = (iommulib_unit_t *)handle;
66020906b23SVikram Hegde
66120906b23SVikram Hegde ASSERT(unitp);
66220906b23SVikram Hegde
66320906b23SVikram Hegde /* No need to grab lock - the handle is reference counted */
66420906b23SVikram Hegde error = unitp->ilu_ops->ilops_dma_freehdl(handle, dip,
66520906b23SVikram Hegde rdip, dma_handle);
66620906b23SVikram Hegde
66720906b23SVikram Hegde return (error);
66820906b23SVikram Hegde }
66920906b23SVikram Hegde
67020906b23SVikram Hegde int
iommulib_nexdma_bindhdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t dma_handle,struct ddi_dma_req * dmareq,ddi_dma_cookie_t * cookiep,uint_t * ccountp)67120906b23SVikram Hegde iommulib_nexdma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
67220906b23SVikram Hegde ddi_dma_handle_t dma_handle, struct ddi_dma_req *dmareq,
67320906b23SVikram Hegde ddi_dma_cookie_t *cookiep, uint_t *ccountp)
67420906b23SVikram Hegde {
67520906b23SVikram Hegde iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle;
67620906b23SVikram Hegde iommulib_unit_t *unitp = (iommulib_unit_t *)handle;
67720906b23SVikram Hegde
67820906b23SVikram Hegde ASSERT(unitp);
67920906b23SVikram Hegde
68020906b23SVikram Hegde /* No need to grab lock - the handle is reference counted */
68120906b23SVikram Hegde return (unitp->ilu_ops->ilops_dma_bindhdl(handle, dip, rdip, dma_handle,
68220906b23SVikram Hegde dmareq, cookiep, ccountp));
68320906b23SVikram Hegde }
68420906b23SVikram Hegde
68520906b23SVikram Hegde int
iommulib_nexdma_unbindhdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t dma_handle)68620906b23SVikram Hegde iommulib_nexdma_unbindhdl(dev_info_t *dip, dev_info_t *rdip,
68720906b23SVikram Hegde ddi_dma_handle_t dma_handle)
68820906b23SVikram Hegde {
68920906b23SVikram Hegde iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle;
69020906b23SVikram Hegde iommulib_unit_t *unitp = (iommulib_unit_t *)handle;
69120906b23SVikram Hegde
69220906b23SVikram Hegde ASSERT(unitp);
69320906b23SVikram Hegde
69420906b23SVikram Hegde /* No need to grab lock - the handle is reference counted */
69520906b23SVikram Hegde return (unitp->ilu_ops->ilops_dma_unbindhdl(handle, dip, rdip,
69620906b23SVikram Hegde dma_handle));
69720906b23SVikram Hegde }
69820906b23SVikram Hegde
69920906b23SVikram Hegde int
iommulib_nexdma_sync(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t dma_handle,off_t off,size_t len,uint_t cache_flags)70020906b23SVikram Hegde iommulib_nexdma_sync(dev_info_t *dip, dev_info_t *rdip,
70120906b23SVikram Hegde ddi_dma_handle_t dma_handle, off_t off, size_t len,
70220906b23SVikram Hegde uint_t cache_flags)
70320906b23SVikram Hegde {
70420906b23SVikram Hegde iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle;
70520906b23SVikram Hegde iommulib_unit_t *unitp = (iommulib_unit_t *)handle;
70620906b23SVikram Hegde
70720906b23SVikram Hegde ASSERT(unitp);
70820906b23SVikram Hegde
70920906b23SVikram Hegde /* No need to grab lock - the handle is reference counted */
71020906b23SVikram Hegde return (unitp->ilu_ops->ilops_dma_sync(handle, dip, rdip, dma_handle,
71120906b23SVikram Hegde off, len, cache_flags));
71220906b23SVikram Hegde }
71320906b23SVikram Hegde
71420906b23SVikram Hegde int
iommulib_nexdma_win(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t dma_handle,uint_t win,off_t * offp,size_t * lenp,ddi_dma_cookie_t * cookiep,uint_t * ccountp)71520906b23SVikram Hegde iommulib_nexdma_win(dev_info_t *dip, dev_info_t *rdip,
71620906b23SVikram Hegde ddi_dma_handle_t dma_handle, uint_t win, off_t *offp, size_t *lenp,
71720906b23SVikram Hegde ddi_dma_cookie_t *cookiep, uint_t *ccountp)
71820906b23SVikram Hegde {
71920906b23SVikram Hegde iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle;
72020906b23SVikram Hegde iommulib_unit_t *unitp = (iommulib_unit_t *)handle;
72120906b23SVikram Hegde
72220906b23SVikram Hegde ASSERT(unitp);
72320906b23SVikram Hegde
72420906b23SVikram Hegde /* No need to grab lock - the handle is reference counted */
72520906b23SVikram Hegde return (unitp->ilu_ops->ilops_dma_win(handle, dip, rdip, dma_handle,
72620906b23SVikram Hegde win, offp, lenp, cookiep, ccountp));
72720906b23SVikram Hegde }
72820906b23SVikram Hegde
72950200e77SFrank Van Der Linden int
iommulib_nexdma_mapobject(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t dma_handle,struct ddi_dma_req * dmareq,ddi_dma_obj_t * dmao)73050200e77SFrank Van Der Linden iommulib_nexdma_mapobject(dev_info_t *dip, dev_info_t *rdip,
73150200e77SFrank Van Der Linden ddi_dma_handle_t dma_handle, struct ddi_dma_req *dmareq,
73250200e77SFrank Van Der Linden ddi_dma_obj_t *dmao)
73350200e77SFrank Van Der Linden {
73450200e77SFrank Van Der Linden iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle;
73550200e77SFrank Van Der Linden iommulib_unit_t *unitp = (iommulib_unit_t *)handle;
73650200e77SFrank Van Der Linden
73750200e77SFrank Van Der Linden return (unitp->ilu_ops->ilops_dma_mapobject(handle, dip, rdip,
73850200e77SFrank Van Der Linden dma_handle, dmareq, dmao));
73950200e77SFrank Van Der Linden }
74050200e77SFrank Van Der Linden
74150200e77SFrank Van Der Linden int
iommulib_nexdma_unmapobject(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t dma_handle,ddi_dma_obj_t * dmao)74250200e77SFrank Van Der Linden iommulib_nexdma_unmapobject(dev_info_t *dip, dev_info_t *rdip,
74350200e77SFrank Van Der Linden ddi_dma_handle_t dma_handle, ddi_dma_obj_t *dmao)
74450200e77SFrank Van Der Linden {
74550200e77SFrank Van Der Linden iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle;
74650200e77SFrank Van Der Linden iommulib_unit_t *unitp = (iommulib_unit_t *)handle;
74750200e77SFrank Van Der Linden
74850200e77SFrank Van Der Linden return (unitp->ilu_ops->ilops_dma_unmapobject(handle, dip, rdip,
74950200e77SFrank Van Der Linden dma_handle, dmao));
75050200e77SFrank Van Der Linden }
75150200e77SFrank Van Der Linden
75220906b23SVikram Hegde /* Utility routines invoked by IOMMU drivers */
75320906b23SVikram Hegde int
iommulib_iommu_dma_allochdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_attr_t * attr,int (* waitfp)(caddr_t),caddr_t arg,ddi_dma_handle_t * handlep)75420906b23SVikram Hegde iommulib_iommu_dma_allochdl(dev_info_t *dip, dev_info_t *rdip,
75520906b23SVikram Hegde ddi_dma_attr_t *attr, int (*waitfp)(caddr_t), caddr_t arg,
75620906b23SVikram Hegde ddi_dma_handle_t *handlep)
75720906b23SVikram Hegde {
75850200e77SFrank Van Der Linden iommulib_nexops_t *nexops;
75950200e77SFrank Van Der Linden
76050200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops;
76120906b23SVikram Hegde return (nexops->nops_dma_allochdl(dip, rdip, attr, waitfp, arg,
76220906b23SVikram Hegde handlep));
76320906b23SVikram Hegde }
76420906b23SVikram Hegde
76520906b23SVikram Hegde int
iommulib_iommu_dma_freehdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle)76620906b23SVikram Hegde iommulib_iommu_dma_freehdl(dev_info_t *dip, dev_info_t *rdip,
76720906b23SVikram Hegde ddi_dma_handle_t handle)
76820906b23SVikram Hegde {
76950200e77SFrank Van Der Linden iommulib_nexops_t *nexops;
77050200e77SFrank Van Der Linden
77150200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops;
77250200e77SFrank Van Der Linden ASSERT(nexops);
77320906b23SVikram Hegde return (nexops->nops_dma_freehdl(dip, rdip, handle));
77420906b23SVikram Hegde }
77520906b23SVikram Hegde
77620906b23SVikram Hegde int
iommulib_iommu_dma_bindhdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle,struct ddi_dma_req * dmareq,ddi_dma_cookie_t * cookiep,uint_t * ccountp)77720906b23SVikram Hegde iommulib_iommu_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
77820906b23SVikram Hegde ddi_dma_handle_t handle, struct ddi_dma_req *dmareq,
77920906b23SVikram Hegde ddi_dma_cookie_t *cookiep, uint_t *ccountp)
78020906b23SVikram Hegde {
78150200e77SFrank Van Der Linden iommulib_nexops_t *nexops;
78250200e77SFrank Van Der Linden
78350200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops;
78420906b23SVikram Hegde return (nexops->nops_dma_bindhdl(dip, rdip, handle, dmareq,
78520906b23SVikram Hegde cookiep, ccountp));
78620906b23SVikram Hegde }
78720906b23SVikram Hegde
78820906b23SVikram Hegde int
iommulib_iommu_dma_unbindhdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle)78920906b23SVikram Hegde iommulib_iommu_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip,
79020906b23SVikram Hegde ddi_dma_handle_t handle)
79120906b23SVikram Hegde {
79250200e77SFrank Van Der Linden iommulib_nexops_t *nexops;
79350200e77SFrank Van Der Linden
79450200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops;
79520906b23SVikram Hegde return (nexops->nops_dma_unbindhdl(dip, rdip, handle));
79620906b23SVikram Hegde }
79720906b23SVikram Hegde
79820906b23SVikram Hegde void
iommulib_iommu_dma_reset_cookies(dev_info_t * dip,ddi_dma_handle_t handle)79920906b23SVikram Hegde iommulib_iommu_dma_reset_cookies(dev_info_t *dip, ddi_dma_handle_t handle)
80020906b23SVikram Hegde {
80150200e77SFrank Van Der Linden iommulib_nexops_t *nexops;
80250200e77SFrank Van Der Linden
80350200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops;
80420906b23SVikram Hegde nexops->nops_dma_reset_cookies(dip, handle);
80520906b23SVikram Hegde }
80620906b23SVikram Hegde
80720906b23SVikram Hegde int
iommulib_iommu_dma_get_cookies(dev_info_t * dip,ddi_dma_handle_t handle,ddi_dma_cookie_t ** cookiepp,uint_t * ccountp)80820906b23SVikram Hegde iommulib_iommu_dma_get_cookies(dev_info_t *dip, ddi_dma_handle_t handle,
80994f1124eSVikram Hegde ddi_dma_cookie_t **cookiepp, uint_t *ccountp)
81094f1124eSVikram Hegde {
81150200e77SFrank Van Der Linden iommulib_nexops_t *nexops;
81250200e77SFrank Van Der Linden
81350200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops;
81494f1124eSVikram Hegde return (nexops->nops_dma_get_cookies(dip, handle, cookiepp, ccountp));
81594f1124eSVikram Hegde }
81694f1124eSVikram Hegde
81794f1124eSVikram Hegde int
iommulib_iommu_dma_set_cookies(dev_info_t * dip,ddi_dma_handle_t handle,ddi_dma_cookie_t * cookiep,uint_t ccount)81894f1124eSVikram Hegde iommulib_iommu_dma_set_cookies(dev_info_t *dip, ddi_dma_handle_t handle,
81994f1124eSVikram Hegde ddi_dma_cookie_t *cookiep, uint_t ccount)
82020906b23SVikram Hegde {
82150200e77SFrank Van Der Linden iommulib_nexops_t *nexops;
82250200e77SFrank Van Der Linden
82350200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops;
82494f1124eSVikram Hegde return (nexops->nops_dma_set_cookies(dip, handle, cookiep, ccount));
82594f1124eSVikram Hegde }
82694f1124eSVikram Hegde
82794f1124eSVikram Hegde int
iommulib_iommu_dma_clear_cookies(dev_info_t * dip,ddi_dma_handle_t handle)82894f1124eSVikram Hegde iommulib_iommu_dma_clear_cookies(dev_info_t *dip, ddi_dma_handle_t handle)
82994f1124eSVikram Hegde {
83050200e77SFrank Van Der Linden iommulib_nexops_t *nexops;
83150200e77SFrank Van Der Linden
83250200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops;
83394f1124eSVikram Hegde return (nexops->nops_dma_clear_cookies(dip, handle));
83494f1124eSVikram Hegde }
83594f1124eSVikram Hegde
83694f1124eSVikram Hegde int
iommulib_iommu_dma_get_sleep_flags(dev_info_t * dip,ddi_dma_handle_t handle)83794f1124eSVikram Hegde iommulib_iommu_dma_get_sleep_flags(dev_info_t *dip, ddi_dma_handle_t handle)
83894f1124eSVikram Hegde {
83950200e77SFrank Van Der Linden iommulib_nexops_t *nexops;
84050200e77SFrank Van Der Linden
84150200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops;
84294f1124eSVikram Hegde return (nexops->nops_dma_get_sleep_flags(handle));
84320906b23SVikram Hegde }
84420906b23SVikram Hegde
84520906b23SVikram Hegde int
iommulib_iommu_dma_sync(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle,off_t off,size_t len,uint_t cache_flags)84620906b23SVikram Hegde iommulib_iommu_dma_sync(dev_info_t *dip, dev_info_t *rdip,
84720906b23SVikram Hegde ddi_dma_handle_t handle, off_t off, size_t len, uint_t cache_flags)
84820906b23SVikram Hegde {
84950200e77SFrank Van Der Linden iommulib_nexops_t *nexops;
85050200e77SFrank Van Der Linden
85150200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops;
85220906b23SVikram Hegde return (nexops->nops_dma_sync(dip, rdip, handle, off, len,
85320906b23SVikram Hegde cache_flags));
85420906b23SVikram Hegde }
85520906b23SVikram Hegde
85620906b23SVikram Hegde int
iommulib_iommu_dma_win(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle,uint_t win,off_t * offp,size_t * lenp,ddi_dma_cookie_t * cookiep,uint_t * ccountp)85720906b23SVikram Hegde iommulib_iommu_dma_win(dev_info_t *dip, dev_info_t *rdip,
85820906b23SVikram Hegde ddi_dma_handle_t handle, uint_t win, off_t *offp, size_t *lenp,
85920906b23SVikram Hegde ddi_dma_cookie_t *cookiep, uint_t *ccountp)
86020906b23SVikram Hegde {
86150200e77SFrank Van Der Linden iommulib_nexops_t *nexops;
86250200e77SFrank Van Der Linden
86350200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops;
86420906b23SVikram Hegde return (nexops->nops_dma_win(dip, rdip, handle, win, offp, lenp,
86520906b23SVikram Hegde cookiep, ccountp));
86620906b23SVikram Hegde }
86720906b23SVikram Hegde
86850200e77SFrank Van Der Linden int
iommulib_iommu_dmahdl_setprivate(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle,void * priv)86950200e77SFrank Van Der Linden iommulib_iommu_dmahdl_setprivate(dev_info_t *dip, dev_info_t *rdip,
87050200e77SFrank Van Der Linden ddi_dma_handle_t handle, void *priv)
87150200e77SFrank Van Der Linden {
87250200e77SFrank Van Der Linden iommulib_nexops_t *nexops;
87350200e77SFrank Van Der Linden
87450200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops;
87550200e77SFrank Van Der Linden return (nexops->nops_dmahdl_setprivate(dip, rdip, handle, priv));
87650200e77SFrank Van Der Linden }
87750200e77SFrank Van Der Linden
87850200e77SFrank Van Der Linden void *
iommulib_iommu_dmahdl_getprivate(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle)87950200e77SFrank Van Der Linden iommulib_iommu_dmahdl_getprivate(dev_info_t *dip, dev_info_t *rdip,
88050200e77SFrank Van Der Linden ddi_dma_handle_t handle)
88150200e77SFrank Van Der Linden {
88250200e77SFrank Van Der Linden iommulib_nexops_t *nexops;
88350200e77SFrank Van Der Linden
88450200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops;
88550200e77SFrank Van Der Linden return (nexops->nops_dmahdl_getprivate(dip, rdip, handle));
88650200e77SFrank Van Der Linden }
88750200e77SFrank Van Der Linden
88820906b23SVikram Hegde int
iommulib_iommu_getunitid(iommulib_handle_t handle,uint64_t * unitidp)88920906b23SVikram Hegde iommulib_iommu_getunitid(iommulib_handle_t handle, uint64_t *unitidp)
89020906b23SVikram Hegde {
89120906b23SVikram Hegde iommulib_unit_t *unitp;
89220906b23SVikram Hegde uint64_t unitid;
89320906b23SVikram Hegde
89420906b23SVikram Hegde unitp = (iommulib_unit_t *)handle;
89520906b23SVikram Hegde
89620906b23SVikram Hegde ASSERT(unitp);
89720906b23SVikram Hegde ASSERT(unitidp);
89820906b23SVikram Hegde
89920906b23SVikram Hegde mutex_enter(&unitp->ilu_lock);
90020906b23SVikram Hegde unitid = unitp->ilu_unitid;
90120906b23SVikram Hegde mutex_exit(&unitp->ilu_lock);
90220906b23SVikram Hegde
90320906b23SVikram Hegde ASSERT(unitid > 0);
90420906b23SVikram Hegde *unitidp = (uint64_t)unitid;
90520906b23SVikram Hegde
90620906b23SVikram Hegde return (DDI_SUCCESS);
90720906b23SVikram Hegde }
90820906b23SVikram Hegde
90920906b23SVikram Hegde dev_info_t *
iommulib_iommu_getdip(iommulib_handle_t handle)91020906b23SVikram Hegde iommulib_iommu_getdip(iommulib_handle_t handle)
91120906b23SVikram Hegde {
91220906b23SVikram Hegde iommulib_unit_t *unitp;
91320906b23SVikram Hegde dev_info_t *dip;
91420906b23SVikram Hegde
91520906b23SVikram Hegde unitp = (iommulib_unit_t *)handle;
91620906b23SVikram Hegde
91720906b23SVikram Hegde ASSERT(unitp);
91820906b23SVikram Hegde
91920906b23SVikram Hegde mutex_enter(&unitp->ilu_lock);
92020906b23SVikram Hegde dip = unitp->ilu_dip;
92120906b23SVikram Hegde ASSERT(dip);
92220906b23SVikram Hegde ndi_hold_devi(dip);
92320906b23SVikram Hegde mutex_exit(&unitp->ilu_lock);
92420906b23SVikram Hegde
92520906b23SVikram Hegde return (dip);
92620906b23SVikram Hegde }
92720906b23SVikram Hegde
92820906b23SVikram Hegde iommulib_ops_t *
iommulib_iommu_getops(iommulib_handle_t handle)92920906b23SVikram Hegde iommulib_iommu_getops(iommulib_handle_t handle)
93020906b23SVikram Hegde {
93120906b23SVikram Hegde iommulib_unit_t *unitp;
93220906b23SVikram Hegde iommulib_ops_t *ops;
93320906b23SVikram Hegde
93420906b23SVikram Hegde unitp = (iommulib_unit_t *)handle;
93520906b23SVikram Hegde
93620906b23SVikram Hegde ASSERT(unitp);
93720906b23SVikram Hegde
93820906b23SVikram Hegde mutex_enter(&unitp->ilu_lock);
93920906b23SVikram Hegde ops = unitp->ilu_ops;
94020906b23SVikram Hegde mutex_exit(&unitp->ilu_lock);
94120906b23SVikram Hegde
94220906b23SVikram Hegde ASSERT(ops);
94320906b23SVikram Hegde
94420906b23SVikram Hegde return (ops);
94520906b23SVikram Hegde }
94620906b23SVikram Hegde
94720906b23SVikram Hegde void *
iommulib_iommu_getdata(iommulib_handle_t handle)94820906b23SVikram Hegde iommulib_iommu_getdata(iommulib_handle_t handle)
94920906b23SVikram Hegde {
95020906b23SVikram Hegde iommulib_unit_t *unitp;
95120906b23SVikram Hegde void *data;
95220906b23SVikram Hegde
95320906b23SVikram Hegde unitp = (iommulib_unit_t *)handle;
95420906b23SVikram Hegde
95520906b23SVikram Hegde ASSERT(unitp);
95620906b23SVikram Hegde
95720906b23SVikram Hegde mutex_enter(&unitp->ilu_lock);
95820906b23SVikram Hegde data = unitp->ilu_data;
95920906b23SVikram Hegde mutex_exit(&unitp->ilu_lock);
96020906b23SVikram Hegde
96120906b23SVikram Hegde ASSERT(data);
96220906b23SVikram Hegde
96320906b23SVikram Hegde return (data);
96420906b23SVikram Hegde }
965