17613SVikram.Hegde@Sun.COM /* 27613SVikram.Hegde@Sun.COM * CDDL HEADER START 37613SVikram.Hegde@Sun.COM * 47613SVikram.Hegde@Sun.COM * The contents of this file are subject to the terms of the 57613SVikram.Hegde@Sun.COM * Common Development and Distribution License (the "License"). 67613SVikram.Hegde@Sun.COM * You may not use this file except in compliance with the License. 77613SVikram.Hegde@Sun.COM * 87613SVikram.Hegde@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97613SVikram.Hegde@Sun.COM * or http://www.opensolaris.org/os/licensing. 107613SVikram.Hegde@Sun.COM * See the License for the specific language governing permissions 117613SVikram.Hegde@Sun.COM * and limitations under the License. 127613SVikram.Hegde@Sun.COM * 137613SVikram.Hegde@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 147613SVikram.Hegde@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157613SVikram.Hegde@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 167613SVikram.Hegde@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 177613SVikram.Hegde@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 187613SVikram.Hegde@Sun.COM * 197613SVikram.Hegde@Sun.COM * CDDL HEADER END 207613SVikram.Hegde@Sun.COM */ 217613SVikram.Hegde@Sun.COM /* 22*13050Sfrank.van.der.linden@oracle.com * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 237613SVikram.Hegde@Sun.COM */ 247613SVikram.Hegde@Sun.COM 257613SVikram.Hegde@Sun.COM #pragma ident "@(#)iommulib.c 1.6 08/09/07 SMI" 267613SVikram.Hegde@Sun.COM 277613SVikram.Hegde@Sun.COM #include <sys/sunddi.h> 287613SVikram.Hegde@Sun.COM #include <sys/sunndi.h> 297613SVikram.Hegde@Sun.COM #include <sys/errno.h> 307613SVikram.Hegde@Sun.COM #include <sys/modctl.h> 317613SVikram.Hegde@Sun.COM #include <sys/iommulib.h> 327613SVikram.Hegde@Sun.COM 337613SVikram.Hegde@Sun.COM /* ******** Type definitions private to this file ********************** */ 347613SVikram.Hegde@Sun.COM 357613SVikram.Hegde@Sun.COM /* 1 per IOMMU unit. There may be more than one per dip */ 367613SVikram.Hegde@Sun.COM typedef struct iommulib_unit { 377613SVikram.Hegde@Sun.COM kmutex_t ilu_lock; 387613SVikram.Hegde@Sun.COM uint64_t ilu_ref; 397613SVikram.Hegde@Sun.COM uint32_t ilu_unitid; 407613SVikram.Hegde@Sun.COM dev_info_t *ilu_dip; 417613SVikram.Hegde@Sun.COM iommulib_ops_t *ilu_ops; 427613SVikram.Hegde@Sun.COM void* ilu_data; 437613SVikram.Hegde@Sun.COM struct iommulib_unit *ilu_next; 447613SVikram.Hegde@Sun.COM struct iommulib_unit *ilu_prev; 45*13050Sfrank.van.der.linden@oracle.com iommulib_nexhandle_t ilu_nex; 467613SVikram.Hegde@Sun.COM } iommulib_unit_t; 477613SVikram.Hegde@Sun.COM 487613SVikram.Hegde@Sun.COM typedef struct iommulib_nex { 497613SVikram.Hegde@Sun.COM dev_info_t *nex_dip; 507613SVikram.Hegde@Sun.COM iommulib_nexops_t nex_ops; 517613SVikram.Hegde@Sun.COM struct iommulib_nex *nex_next; 527613SVikram.Hegde@Sun.COM struct iommulib_nex *nex_prev; 53*13050Sfrank.van.der.linden@oracle.com uint_t nex_ref; 547613SVikram.Hegde@Sun.COM } iommulib_nex_t; 557613SVikram.Hegde@Sun.COM 567613SVikram.Hegde@Sun.COM /* ********* Globals ************************ */ 577613SVikram.Hegde@Sun.COM 588371SVikram.Hegde@Sun.COM /* For IOMMU drivers */ 598371SVikram.Hegde@Sun.COM smbios_hdl_t *iommulib_smbios; 608371SVikram.Hegde@Sun.COM 617613SVikram.Hegde@Sun.COM /* IOMMU side: Following data protected by lock */ 627613SVikram.Hegde@Sun.COM static kmutex_t iommulib_lock; 637613SVikram.Hegde@Sun.COM static iommulib_unit_t *iommulib_list; 647613SVikram.Hegde@Sun.COM static uint64_t iommulib_unit_ids = 0; 657613SVikram.Hegde@Sun.COM static uint64_t iommulib_num_units = 0; 667613SVikram.Hegde@Sun.COM 677613SVikram.Hegde@Sun.COM /* rootnex side data */ 687613SVikram.Hegde@Sun.COM 697613SVikram.Hegde@Sun.COM static kmutex_t iommulib_nexus_lock; 707613SVikram.Hegde@Sun.COM static iommulib_nex_t *iommulib_nexus_list; 717613SVikram.Hegde@Sun.COM 727613SVikram.Hegde@Sun.COM /* can be set atomically without lock */ 737613SVikram.Hegde@Sun.COM static volatile uint32_t iommulib_fini; 747613SVikram.Hegde@Sun.COM 757613SVikram.Hegde@Sun.COM /* debug flag */ 767613SVikram.Hegde@Sun.COM static int iommulib_debug; 777613SVikram.Hegde@Sun.COM 787613SVikram.Hegde@Sun.COM /* 797613SVikram.Hegde@Sun.COM * Module linkage information for the kernel. 807613SVikram.Hegde@Sun.COM */ 817613SVikram.Hegde@Sun.COM static struct modlmisc modlmisc = { 827613SVikram.Hegde@Sun.COM &mod_miscops, "IOMMU library module" 837613SVikram.Hegde@Sun.COM }; 847613SVikram.Hegde@Sun.COM 857613SVikram.Hegde@Sun.COM static struct modlinkage modlinkage = { 867613SVikram.Hegde@Sun.COM MODREV_1, (void *)&modlmisc, NULL 877613SVikram.Hegde@Sun.COM }; 887613SVikram.Hegde@Sun.COM 897613SVikram.Hegde@Sun.COM int 907613SVikram.Hegde@Sun.COM _init(void) 917613SVikram.Hegde@Sun.COM { 927613SVikram.Hegde@Sun.COM return (mod_install(&modlinkage)); 937613SVikram.Hegde@Sun.COM } 947613SVikram.Hegde@Sun.COM 957613SVikram.Hegde@Sun.COM int 967613SVikram.Hegde@Sun.COM _fini(void) 977613SVikram.Hegde@Sun.COM { 987613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 997613SVikram.Hegde@Sun.COM if (iommulib_list != NULL || iommulib_nexus_list != NULL) { 1007613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 1017613SVikram.Hegde@Sun.COM return (EBUSY); 1027613SVikram.Hegde@Sun.COM } 1037613SVikram.Hegde@Sun.COM iommulib_fini = 1; 1047613SVikram.Hegde@Sun.COM 1057613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 1067613SVikram.Hegde@Sun.COM return (mod_remove(&modlinkage)); 1077613SVikram.Hegde@Sun.COM } 1087613SVikram.Hegde@Sun.COM 1097613SVikram.Hegde@Sun.COM int 1107613SVikram.Hegde@Sun.COM _info(struct modinfo *modinfop) 1117613SVikram.Hegde@Sun.COM { 1127613SVikram.Hegde@Sun.COM return (mod_info(&modlinkage, modinfop)); 1137613SVikram.Hegde@Sun.COM } 1147613SVikram.Hegde@Sun.COM 1157613SVikram.Hegde@Sun.COM /* 1167613SVikram.Hegde@Sun.COM * Routines with iommulib_iommu_* are invoked from the 1177613SVikram.Hegde@Sun.COM * IOMMU driver. 1187613SVikram.Hegde@Sun.COM * Routines with iommulib_nex* are invoked from the 1197613SVikram.Hegde@Sun.COM * nexus driver (typically rootnex) 1207613SVikram.Hegde@Sun.COM */ 1217613SVikram.Hegde@Sun.COM 1227613SVikram.Hegde@Sun.COM int 1237613SVikram.Hegde@Sun.COM iommulib_nexus_register(dev_info_t *dip, iommulib_nexops_t *nexops, 1247613SVikram.Hegde@Sun.COM iommulib_nexhandle_t *handle) 1257613SVikram.Hegde@Sun.COM { 1267613SVikram.Hegde@Sun.COM iommulib_nex_t *nexp; 1277613SVikram.Hegde@Sun.COM int instance = ddi_get_instance(dip); 1287613SVikram.Hegde@Sun.COM const char *driver = ddi_driver_name(dip); 1297613SVikram.Hegde@Sun.COM dev_info_t *pdip = ddi_get_parent(dip); 1307613SVikram.Hegde@Sun.COM const char *f = "iommulib_nexus_register"; 1317613SVikram.Hegde@Sun.COM 1327613SVikram.Hegde@Sun.COM ASSERT(nexops); 1337613SVikram.Hegde@Sun.COM ASSERT(handle); 1347613SVikram.Hegde@Sun.COM 1357613SVikram.Hegde@Sun.COM *handle = NULL; 1367613SVikram.Hegde@Sun.COM 1377613SVikram.Hegde@Sun.COM /* 1387613SVikram.Hegde@Sun.COM * Root node is never busy held 1397613SVikram.Hegde@Sun.COM */ 1407613SVikram.Hegde@Sun.COM if (dip != ddi_root_node() && (i_ddi_node_state(dip) < DS_PROBED || 1417613SVikram.Hegde@Sun.COM !DEVI_BUSY_OWNED(pdip))) { 1427613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: NEXUS devinfo node not in DS_PROBED " 1437613SVikram.Hegde@Sun.COM "or busy held for nexops vector (%p). Failing registration", 1447613SVikram.Hegde@Sun.COM f, (void *)nexops); 1457613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1467613SVikram.Hegde@Sun.COM } 1477613SVikram.Hegde@Sun.COM 1487613SVikram.Hegde@Sun.COM if (nexops->nops_vers != IOMMU_NEXOPS_VERSION) { 1497613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: Invalid IOMMULIB nexops version " 1507613SVikram.Hegde@Sun.COM "in nexops vector (%p). Failing NEXUS registration", 1517613SVikram.Hegde@Sun.COM f, driver, instance, (void *)nexops); 1527613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1537613SVikram.Hegde@Sun.COM } 1547613SVikram.Hegde@Sun.COM 1557613SVikram.Hegde@Sun.COM ASSERT(nexops->nops_data == NULL); 1567613SVikram.Hegde@Sun.COM 1577613SVikram.Hegde@Sun.COM if (nexops->nops_id == NULL) { 1587613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL ID field. " 1597613SVikram.Hegde@Sun.COM "Failing registration for nexops vector: %p", 1607613SVikram.Hegde@Sun.COM f, driver, instance, (void *)nexops); 1617613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1627613SVikram.Hegde@Sun.COM } 1637613SVikram.Hegde@Sun.COM 1647613SVikram.Hegde@Sun.COM if (nexops->nops_dma_allochdl == NULL) { 1657613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_allochdl op. " 1667613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 1677613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 1687613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1697613SVikram.Hegde@Sun.COM } 1707613SVikram.Hegde@Sun.COM 1717613SVikram.Hegde@Sun.COM if (nexops->nops_dma_freehdl == NULL) { 1727613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_freehdl op. " 1737613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 1747613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 1757613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1767613SVikram.Hegde@Sun.COM } 1777613SVikram.Hegde@Sun.COM 1787613SVikram.Hegde@Sun.COM if (nexops->nops_dma_bindhdl == NULL) { 1797613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_bindhdl op. " 1807613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 1817613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 1827613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1837613SVikram.Hegde@Sun.COM } 1847613SVikram.Hegde@Sun.COM 1857613SVikram.Hegde@Sun.COM if (nexops->nops_dma_sync == NULL) { 1867613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_sync op. " 1877613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 1887613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 1897613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1907613SVikram.Hegde@Sun.COM } 1917613SVikram.Hegde@Sun.COM 1927613SVikram.Hegde@Sun.COM if (nexops->nops_dma_reset_cookies == NULL) { 1937613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_reset_cookies op. " 1947613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 1957613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 1967613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1977613SVikram.Hegde@Sun.COM } 1987613SVikram.Hegde@Sun.COM 1997613SVikram.Hegde@Sun.COM if (nexops->nops_dma_get_cookies == NULL) { 2007613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_get_cookies op. " 2017613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 2027613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 2037613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 2047613SVikram.Hegde@Sun.COM } 2057613SVikram.Hegde@Sun.COM 2068215SVikram.Hegde@Sun.COM if (nexops->nops_dma_set_cookies == NULL) { 2078215SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_set_cookies op. " 2088215SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 2098215SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 2108215SVikram.Hegde@Sun.COM return (DDI_FAILURE); 2118215SVikram.Hegde@Sun.COM } 2128215SVikram.Hegde@Sun.COM 2138215SVikram.Hegde@Sun.COM if (nexops->nops_dma_clear_cookies == NULL) { 2148215SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_clear_cookies op. " 2158215SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 2168215SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 2178215SVikram.Hegde@Sun.COM return (DDI_FAILURE); 2188215SVikram.Hegde@Sun.COM } 2198215SVikram.Hegde@Sun.COM 2208215SVikram.Hegde@Sun.COM if (nexops->nops_dma_get_sleep_flags == NULL) { 2218215SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_get_sleep_flags op. " 2228215SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 2238215SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 2248215SVikram.Hegde@Sun.COM return (DDI_FAILURE); 2258215SVikram.Hegde@Sun.COM } 2268215SVikram.Hegde@Sun.COM 2277613SVikram.Hegde@Sun.COM if (nexops->nops_dma_win == NULL) { 2287613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_win op. " 2297613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 2307613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 2317613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 2327613SVikram.Hegde@Sun.COM } 2337613SVikram.Hegde@Sun.COM 234*13050Sfrank.van.der.linden@oracle.com if (nexops->nops_dmahdl_setprivate == NULL) { 235*13050Sfrank.van.der.linden@oracle.com cmn_err(CE_WARN, "%s: %s%d: NULL nops_dmahdl_setprivate op. " 236*13050Sfrank.van.der.linden@oracle.com "Failing registration for ops vector: %p", f, 237*13050Sfrank.van.der.linden@oracle.com driver, instance, (void *)nexops); 238*13050Sfrank.van.der.linden@oracle.com return (DDI_FAILURE); 239*13050Sfrank.van.der.linden@oracle.com } 240*13050Sfrank.van.der.linden@oracle.com 241*13050Sfrank.van.der.linden@oracle.com if (nexops->nops_dmahdl_getprivate == NULL) { 242*13050Sfrank.van.der.linden@oracle.com cmn_err(CE_WARN, "%s: %s%d: NULL nops_dmahdl_getprivate op. " 243*13050Sfrank.van.der.linden@oracle.com "Failing registration for ops vector: %p", f, 244*13050Sfrank.van.der.linden@oracle.com driver, instance, (void *)nexops); 245*13050Sfrank.van.der.linden@oracle.com return (DDI_FAILURE); 246*13050Sfrank.van.der.linden@oracle.com } 247*13050Sfrank.van.der.linden@oracle.com 2487613SVikram.Hegde@Sun.COM /* Check for legacy ops */ 2497613SVikram.Hegde@Sun.COM if (nexops->nops_dma_map == NULL) { 2507613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL legacy nops_dma_map op. " 2517613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 2527613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 2537613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 2547613SVikram.Hegde@Sun.COM } 2557613SVikram.Hegde@Sun.COM 2567613SVikram.Hegde@Sun.COM if (nexops->nops_dma_mctl == NULL) { 2577613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL legacy nops_dma_mctl op. " 2587613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 2597613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 2607613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 2617613SVikram.Hegde@Sun.COM } 2627613SVikram.Hegde@Sun.COM 2637613SVikram.Hegde@Sun.COM nexp = kmem_zalloc(sizeof (iommulib_nex_t), KM_SLEEP); 2647613SVikram.Hegde@Sun.COM 2657613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 2667613SVikram.Hegde@Sun.COM if (iommulib_fini == 1) { 2677613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 2687613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: IOMMULIB unloading. " 2697613SVikram.Hegde@Sun.COM "Failing NEXUS register.", f); 2707613SVikram.Hegde@Sun.COM kmem_free(nexp, sizeof (iommulib_nex_t)); 2717613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 2727613SVikram.Hegde@Sun.COM } 2737613SVikram.Hegde@Sun.COM 2747613SVikram.Hegde@Sun.COM /* 2757613SVikram.Hegde@Sun.COM * fini/register race conditions have been handled. Now create the 2767613SVikram.Hegde@Sun.COM * nexus struct 2777613SVikram.Hegde@Sun.COM */ 2787613SVikram.Hegde@Sun.COM ndi_hold_devi(dip); 2797613SVikram.Hegde@Sun.COM nexp->nex_dip = dip; 2807613SVikram.Hegde@Sun.COM nexp->nex_ops = *nexops; 2817613SVikram.Hegde@Sun.COM 2827613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_nexus_lock); 2837613SVikram.Hegde@Sun.COM nexp->nex_next = iommulib_nexus_list; 2847613SVikram.Hegde@Sun.COM iommulib_nexus_list = nexp; 2857613SVikram.Hegde@Sun.COM nexp->nex_prev = NULL; 2867613SVikram.Hegde@Sun.COM 2877613SVikram.Hegde@Sun.COM if (nexp->nex_next != NULL) 2887613SVikram.Hegde@Sun.COM nexp->nex_next->nex_prev = nexp; 2897613SVikram.Hegde@Sun.COM 290*13050Sfrank.van.der.linden@oracle.com nexp->nex_ref = 0; 291*13050Sfrank.van.der.linden@oracle.com 292*13050Sfrank.van.der.linden@oracle.com /* 293*13050Sfrank.van.der.linden@oracle.com * The nexus device won't be controlled by an IOMMU. 294*13050Sfrank.van.der.linden@oracle.com */ 295*13050Sfrank.van.der.linden@oracle.com DEVI(dip)->devi_iommulib_handle = IOMMU_HANDLE_UNUSED; 296*13050Sfrank.van.der.linden@oracle.com 297*13050Sfrank.van.der.linden@oracle.com DEVI(dip)->devi_iommulib_nex_handle = nexp; 298*13050Sfrank.van.der.linden@oracle.com 2997613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_nexus_lock); 3007613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 3017613SVikram.Hegde@Sun.COM 3027613SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "!%s: %s%d: Succesfully registered NEXUS %s " 3037613SVikram.Hegde@Sun.COM "nexops=%p", f, driver, instance, ddi_node_name(dip), 3047613SVikram.Hegde@Sun.COM (void *)nexops); 3057613SVikram.Hegde@Sun.COM 3067613SVikram.Hegde@Sun.COM *handle = nexp; 3077613SVikram.Hegde@Sun.COM 3087613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 3097613SVikram.Hegde@Sun.COM } 3107613SVikram.Hegde@Sun.COM 3117613SVikram.Hegde@Sun.COM int 3127613SVikram.Hegde@Sun.COM iommulib_nexus_unregister(iommulib_nexhandle_t handle) 3137613SVikram.Hegde@Sun.COM { 3147613SVikram.Hegde@Sun.COM dev_info_t *dip; 3157613SVikram.Hegde@Sun.COM int instance; 3167613SVikram.Hegde@Sun.COM const char *driver; 3177613SVikram.Hegde@Sun.COM iommulib_nex_t *nexp = (iommulib_nex_t *)handle; 3187613SVikram.Hegde@Sun.COM const char *f = "iommulib_nexus_unregister"; 3197613SVikram.Hegde@Sun.COM 3207613SVikram.Hegde@Sun.COM ASSERT(nexp); 3217613SVikram.Hegde@Sun.COM 322*13050Sfrank.van.der.linden@oracle.com if (nexp->nex_ref != 0) 323*13050Sfrank.van.der.linden@oracle.com return (DDI_FAILURE); 324*13050Sfrank.van.der.linden@oracle.com 3257613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_nexus_lock); 3267613SVikram.Hegde@Sun.COM 3277613SVikram.Hegde@Sun.COM dip = nexp->nex_dip; 3287613SVikram.Hegde@Sun.COM driver = ddi_driver_name(dip); 3297613SVikram.Hegde@Sun.COM instance = ddi_get_instance(dip); 3307613SVikram.Hegde@Sun.COM 3317613SVikram.Hegde@Sun.COM /* A future enhancement would be to add ref-counts */ 3327613SVikram.Hegde@Sun.COM 3337613SVikram.Hegde@Sun.COM if (nexp->nex_prev == NULL) { 3347613SVikram.Hegde@Sun.COM iommulib_nexus_list = nexp->nex_next; 3357613SVikram.Hegde@Sun.COM } else { 3367613SVikram.Hegde@Sun.COM nexp->nex_prev->nex_next = nexp->nex_next; 3377613SVikram.Hegde@Sun.COM } 3387613SVikram.Hegde@Sun.COM 3397613SVikram.Hegde@Sun.COM if (nexp->nex_next != NULL) 3407613SVikram.Hegde@Sun.COM nexp->nex_next->nex_prev = nexp->nex_prev; 3417613SVikram.Hegde@Sun.COM 3427613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_nexus_lock); 3437613SVikram.Hegde@Sun.COM 3447613SVikram.Hegde@Sun.COM kmem_free(nexp, sizeof (iommulib_nex_t)); 3457613SVikram.Hegde@Sun.COM 3468215SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "!%s: %s%d: NEXUS (%s) handle successfully " 3477613SVikram.Hegde@Sun.COM "unregistered from IOMMULIB", f, driver, instance, 3487613SVikram.Hegde@Sun.COM ddi_node_name(dip)); 3497613SVikram.Hegde@Sun.COM 3507613SVikram.Hegde@Sun.COM ndi_rele_devi(dip); 3517613SVikram.Hegde@Sun.COM 3527613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 3537613SVikram.Hegde@Sun.COM } 3547613SVikram.Hegde@Sun.COM 3557613SVikram.Hegde@Sun.COM int 3567613SVikram.Hegde@Sun.COM iommulib_iommu_register(dev_info_t *dip, iommulib_ops_t *ops, 3577613SVikram.Hegde@Sun.COM iommulib_handle_t *handle) 3587613SVikram.Hegde@Sun.COM { 3597613SVikram.Hegde@Sun.COM const char *vendor; 3607613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 3617613SVikram.Hegde@Sun.COM int instance = ddi_get_instance(dip); 3627613SVikram.Hegde@Sun.COM const char *driver = ddi_driver_name(dip); 3637613SVikram.Hegde@Sun.COM dev_info_t *pdip = ddi_get_parent(dip); 3647613SVikram.Hegde@Sun.COM const char *f = "iommulib_register"; 3657613SVikram.Hegde@Sun.COM 3667613SVikram.Hegde@Sun.COM ASSERT(ops); 3677613SVikram.Hegde@Sun.COM ASSERT(handle); 3687613SVikram.Hegde@Sun.COM 3697613SVikram.Hegde@Sun.COM if (ops->ilops_vers != IOMMU_OPS_VERSION) { 3707613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: Invalid IOMMULIB ops version " 3717613SVikram.Hegde@Sun.COM "in ops vector (%p). Failing registration", f, driver, 3727613SVikram.Hegde@Sun.COM instance, (void *)ops); 3737613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 3747613SVikram.Hegde@Sun.COM } 3757613SVikram.Hegde@Sun.COM 3767613SVikram.Hegde@Sun.COM switch (ops->ilops_vendor) { 3777613SVikram.Hegde@Sun.COM case AMD_IOMMU: 3787613SVikram.Hegde@Sun.COM vendor = "AMD"; 3797613SVikram.Hegde@Sun.COM break; 3807613SVikram.Hegde@Sun.COM case INTEL_IOMMU: 3817613SVikram.Hegde@Sun.COM vendor = "Intel"; 3827613SVikram.Hegde@Sun.COM break; 3837613SVikram.Hegde@Sun.COM case INVALID_VENDOR: 3847613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: vendor field (%x) not initialized. " 3857613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 3867613SVikram.Hegde@Sun.COM driver, instance, ops->ilops_vendor, (void *)ops); 3877613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 3887613SVikram.Hegde@Sun.COM default: 3897613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: Invalid vendor field (%x). " 3907613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 3917613SVikram.Hegde@Sun.COM driver, instance, ops->ilops_vendor, (void *)ops); 3927613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 3937613SVikram.Hegde@Sun.COM } 3947613SVikram.Hegde@Sun.COM 3958215SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "!%s: %s%d: Detected IOMMU registration from vendor" 3968215SVikram.Hegde@Sun.COM " %s", f, driver, instance, vendor); 3977613SVikram.Hegde@Sun.COM 3987613SVikram.Hegde@Sun.COM if (ops->ilops_data == NULL) { 3997613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL IOMMU data field. " 4007613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4017613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4027613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4037613SVikram.Hegde@Sun.COM } 4047613SVikram.Hegde@Sun.COM 4057613SVikram.Hegde@Sun.COM if (ops->ilops_id == NULL) { 4067613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL ID field. " 4077613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4087613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4097613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4107613SVikram.Hegde@Sun.COM } 4117613SVikram.Hegde@Sun.COM 4127613SVikram.Hegde@Sun.COM if (ops->ilops_probe == NULL) { 4137613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL probe op. " 4147613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4157613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4167613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4177613SVikram.Hegde@Sun.COM } 4187613SVikram.Hegde@Sun.COM 4197613SVikram.Hegde@Sun.COM if (ops->ilops_dma_allochdl == NULL) { 4207613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL dma_allochdl op. " 4217613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4227613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4237613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4247613SVikram.Hegde@Sun.COM } 4257613SVikram.Hegde@Sun.COM 4267613SVikram.Hegde@Sun.COM if (ops->ilops_dma_freehdl == NULL) { 4277613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL dma_freehdl op. " 4287613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4297613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4307613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4317613SVikram.Hegde@Sun.COM } 4327613SVikram.Hegde@Sun.COM 4337613SVikram.Hegde@Sun.COM if (ops->ilops_dma_bindhdl == NULL) { 4347613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL dma_bindhdl op. " 4357613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4367613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4377613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4387613SVikram.Hegde@Sun.COM } 4397613SVikram.Hegde@Sun.COM 4407613SVikram.Hegde@Sun.COM if (ops->ilops_dma_sync == NULL) { 4417613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL dma_sync op. " 4427613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4437613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4447613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4457613SVikram.Hegde@Sun.COM } 4467613SVikram.Hegde@Sun.COM 4477613SVikram.Hegde@Sun.COM if (ops->ilops_dma_win == NULL) { 4487613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL dma_win op. " 4497613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4507613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4517613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4527613SVikram.Hegde@Sun.COM } 4537613SVikram.Hegde@Sun.COM 4547613SVikram.Hegde@Sun.COM /* Check for legacy ops */ 4557613SVikram.Hegde@Sun.COM if (ops->ilops_dma_map == NULL) { 4567613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL legacy dma_map op. " 4577613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4587613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4597613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4607613SVikram.Hegde@Sun.COM } 4617613SVikram.Hegde@Sun.COM 4627613SVikram.Hegde@Sun.COM if (ops->ilops_dma_mctl == NULL) { 4637613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL legacy dma_mctl op. " 4647613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4657613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4667613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4677613SVikram.Hegde@Sun.COM } 4687613SVikram.Hegde@Sun.COM 4697613SVikram.Hegde@Sun.COM unitp = kmem_zalloc(sizeof (iommulib_unit_t), KM_SLEEP); 4707613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 4717613SVikram.Hegde@Sun.COM if (iommulib_fini == 1) { 4727613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 4737613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: IOMMULIB unloading. Failing register.", 4747613SVikram.Hegde@Sun.COM f); 4757613SVikram.Hegde@Sun.COM kmem_free(unitp, sizeof (iommulib_unit_t)); 4767613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4777613SVikram.Hegde@Sun.COM } 4787613SVikram.Hegde@Sun.COM 4797613SVikram.Hegde@Sun.COM /* 4807613SVikram.Hegde@Sun.COM * fini/register race conditions have been handled. Now create the 4817613SVikram.Hegde@Sun.COM * IOMMU unit 4827613SVikram.Hegde@Sun.COM */ 4837613SVikram.Hegde@Sun.COM mutex_init(&unitp->ilu_lock, NULL, MUTEX_DEFAULT, NULL); 4847613SVikram.Hegde@Sun.COM 4857613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 4867613SVikram.Hegde@Sun.COM unitp->ilu_unitid = ++iommulib_unit_ids; 4877613SVikram.Hegde@Sun.COM unitp->ilu_ref = 0; 4887613SVikram.Hegde@Sun.COM ndi_hold_devi(dip); 4897613SVikram.Hegde@Sun.COM unitp->ilu_dip = dip; 4907613SVikram.Hegde@Sun.COM unitp->ilu_ops = ops; 4917613SVikram.Hegde@Sun.COM unitp->ilu_data = ops->ilops_data; 4927613SVikram.Hegde@Sun.COM 4937613SVikram.Hegde@Sun.COM unitp->ilu_next = iommulib_list; 4948215SVikram.Hegde@Sun.COM iommulib_list = unitp; 4957613SVikram.Hegde@Sun.COM unitp->ilu_prev = NULL; 4968215SVikram.Hegde@Sun.COM if (unitp->ilu_next) 4978215SVikram.Hegde@Sun.COM unitp->ilu_next->ilu_prev = unitp; 4987613SVikram.Hegde@Sun.COM 499*13050Sfrank.van.der.linden@oracle.com /* 500*13050Sfrank.van.der.linden@oracle.com * The IOMMU device itself is not controlled by an IOMMU. 501*13050Sfrank.van.der.linden@oracle.com */ 502*13050Sfrank.van.der.linden@oracle.com DEVI(dip)->devi_iommulib_handle = IOMMU_HANDLE_UNUSED; 503*13050Sfrank.van.der.linden@oracle.com 5047613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 5057613SVikram.Hegde@Sun.COM 5067613SVikram.Hegde@Sun.COM iommulib_num_units++; 5077613SVikram.Hegde@Sun.COM 5087613SVikram.Hegde@Sun.COM *handle = unitp; 5097613SVikram.Hegde@Sun.COM 5107613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 5117613SVikram.Hegde@Sun.COM 5128215SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "!%s: %s%d: Succesfully registered IOMMU unit " 5137613SVikram.Hegde@Sun.COM "from vendor=%s, ops=%p, data=%p, IOMMULIB unitid=%u", 5147613SVikram.Hegde@Sun.COM f, driver, instance, vendor, (void *)ops, (void *)unitp->ilu_data, 5157613SVikram.Hegde@Sun.COM unitp->ilu_unitid); 5167613SVikram.Hegde@Sun.COM 5177613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 5187613SVikram.Hegde@Sun.COM } 5197613SVikram.Hegde@Sun.COM 5207613SVikram.Hegde@Sun.COM int 5217613SVikram.Hegde@Sun.COM iommulib_iommu_unregister(iommulib_handle_t handle) 5227613SVikram.Hegde@Sun.COM { 5237613SVikram.Hegde@Sun.COM uint32_t unitid; 5247613SVikram.Hegde@Sun.COM dev_info_t *dip; 5257613SVikram.Hegde@Sun.COM int instance; 5267613SVikram.Hegde@Sun.COM const char *driver; 5277613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 5287613SVikram.Hegde@Sun.COM const char *f = "iommulib_unregister"; 5297613SVikram.Hegde@Sun.COM 5307613SVikram.Hegde@Sun.COM ASSERT(unitp); 5317613SVikram.Hegde@Sun.COM 5327613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 5337613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 5347613SVikram.Hegde@Sun.COM 5357613SVikram.Hegde@Sun.COM unitid = unitp->ilu_unitid; 5367613SVikram.Hegde@Sun.COM dip = unitp->ilu_dip; 5377613SVikram.Hegde@Sun.COM driver = ddi_driver_name(dip); 5387613SVikram.Hegde@Sun.COM instance = ddi_get_instance(dip); 5397613SVikram.Hegde@Sun.COM 5407613SVikram.Hegde@Sun.COM if (unitp->ilu_ref != 0) { 5417613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 5427613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 5437613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: IOMMULIB handle is busy. Cannot " 5447613SVikram.Hegde@Sun.COM "unregister IOMMULIB unitid %u", 5457613SVikram.Hegde@Sun.COM f, driver, instance, unitid); 5467613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 5477613SVikram.Hegde@Sun.COM } 5487613SVikram.Hegde@Sun.COM unitp->ilu_unitid = 0; 5497613SVikram.Hegde@Sun.COM ASSERT(unitp->ilu_ref == 0); 5507613SVikram.Hegde@Sun.COM 5517613SVikram.Hegde@Sun.COM if (unitp->ilu_prev == NULL) { 5527613SVikram.Hegde@Sun.COM iommulib_list = unitp->ilu_next; 5537613SVikram.Hegde@Sun.COM unitp->ilu_next->ilu_prev = NULL; 5547613SVikram.Hegde@Sun.COM } else { 5557613SVikram.Hegde@Sun.COM unitp->ilu_prev->ilu_next = unitp->ilu_next; 5567613SVikram.Hegde@Sun.COM unitp->ilu_next->ilu_prev = unitp->ilu_prev; 5577613SVikram.Hegde@Sun.COM } 5587613SVikram.Hegde@Sun.COM 5597613SVikram.Hegde@Sun.COM iommulib_num_units--; 5607613SVikram.Hegde@Sun.COM 5617613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 5627613SVikram.Hegde@Sun.COM 5637613SVikram.Hegde@Sun.COM mutex_destroy(&unitp->ilu_lock); 5647613SVikram.Hegde@Sun.COM kmem_free(unitp, sizeof (iommulib_unit_t)); 5657613SVikram.Hegde@Sun.COM 5667613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 5677613SVikram.Hegde@Sun.COM 5687613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: IOMMULIB handle (unitid=%u) successfully " 5697613SVikram.Hegde@Sun.COM "unregistered", f, driver, instance, unitid); 5707613SVikram.Hegde@Sun.COM 5717613SVikram.Hegde@Sun.COM ndi_rele_devi(dip); 5727613SVikram.Hegde@Sun.COM 5737613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 5747613SVikram.Hegde@Sun.COM } 5757613SVikram.Hegde@Sun.COM 5767613SVikram.Hegde@Sun.COM int 577*13050Sfrank.van.der.linden@oracle.com iommulib_nex_open(dev_info_t *dip, dev_info_t *rdip) 5787613SVikram.Hegde@Sun.COM { 5797613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 5807613SVikram.Hegde@Sun.COM int instance = ddi_get_instance(rdip); 5817613SVikram.Hegde@Sun.COM const char *driver = ddi_driver_name(rdip); 5827613SVikram.Hegde@Sun.COM const char *f = "iommulib_nex_open"; 5837613SVikram.Hegde@Sun.COM 584*13050Sfrank.van.der.linden@oracle.com ASSERT(DEVI(dip)->devi_iommulib_nex_handle != NULL); 5858215SVikram.Hegde@Sun.COM ASSERT(DEVI(rdip)->devi_iommulib_handle == NULL); 5867613SVikram.Hegde@Sun.COM 5877613SVikram.Hegde@Sun.COM /* prevent use of IOMMU for AMD IOMMU's DMA */ 5887613SVikram.Hegde@Sun.COM if (strcmp(driver, "amd_iommu") == 0) { 589*13050Sfrank.van.der.linden@oracle.com DEVI(rdip)->devi_iommulib_handle = IOMMU_HANDLE_UNUSED; 590*13050Sfrank.van.der.linden@oracle.com return (DDI_ENOTSUP); 5917613SVikram.Hegde@Sun.COM } 5927613SVikram.Hegde@Sun.COM 5937613SVikram.Hegde@Sun.COM /* 5948215SVikram.Hegde@Sun.COM * Use the probe entry point to determine in a hardware specific 5958215SVikram.Hegde@Sun.COM * manner whether this dip is controlled by an IOMMU. If yes, 5968215SVikram.Hegde@Sun.COM * return the handle corresponding to the IOMMU unit. 5977613SVikram.Hegde@Sun.COM */ 5987613SVikram.Hegde@Sun.COM 5997613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 6007613SVikram.Hegde@Sun.COM for (unitp = iommulib_list; unitp; unitp = unitp->ilu_next) { 6018215SVikram.Hegde@Sun.COM if (unitp->ilu_ops->ilops_probe(unitp, rdip) == DDI_SUCCESS) 6027613SVikram.Hegde@Sun.COM break; 6037613SVikram.Hegde@Sun.COM } 6047613SVikram.Hegde@Sun.COM 6057613SVikram.Hegde@Sun.COM if (unitp == NULL) { 6067613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 6077613SVikram.Hegde@Sun.COM if (iommulib_debug) { 6087717SVikram.Hegde@Sun.COM char *buf = kmem_alloc(MAXPATHLEN, KM_SLEEP); 6097613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: devinfo node (%p): is not " 6107613SVikram.Hegde@Sun.COM "controlled by an IOMMU: path=%s", f, driver, 6117613SVikram.Hegde@Sun.COM instance, (void *)rdip, ddi_pathname(rdip, buf)); 6127717SVikram.Hegde@Sun.COM kmem_free(buf, MAXPATHLEN); 6137613SVikram.Hegde@Sun.COM } 614*13050Sfrank.van.der.linden@oracle.com DEVI(rdip)->devi_iommulib_handle = IOMMU_HANDLE_UNUSED; 615*13050Sfrank.van.der.linden@oracle.com return (DDI_ENOTSUP); 6167613SVikram.Hegde@Sun.COM } 6177613SVikram.Hegde@Sun.COM 6187613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 619*13050Sfrank.van.der.linden@oracle.com unitp->ilu_nex = DEVI(dip)->devi_iommulib_nex_handle; 6207613SVikram.Hegde@Sun.COM unitp->ilu_ref++; 621*13050Sfrank.van.der.linden@oracle.com DEVI(rdip)->devi_iommulib_handle = unitp; 6227613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 6237613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 6247613SVikram.Hegde@Sun.COM 625*13050Sfrank.van.der.linden@oracle.com atomic_inc_uint(&DEVI(dip)->devi_iommulib_nex_handle->nex_ref); 6267613SVikram.Hegde@Sun.COM 6277613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 6287613SVikram.Hegde@Sun.COM } 6297613SVikram.Hegde@Sun.COM 6307613SVikram.Hegde@Sun.COM void 6317613SVikram.Hegde@Sun.COM iommulib_nex_close(dev_info_t *rdip) 6327613SVikram.Hegde@Sun.COM { 6337613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 6347613SVikram.Hegde@Sun.COM const char *driver; 6357613SVikram.Hegde@Sun.COM int instance; 6367613SVikram.Hegde@Sun.COM uint32_t unitid; 637*13050Sfrank.van.der.linden@oracle.com iommulib_nex_t *nexp; 6387613SVikram.Hegde@Sun.COM const char *f = "iommulib_nex_close"; 6397613SVikram.Hegde@Sun.COM 640*13050Sfrank.van.der.linden@oracle.com ASSERT(IOMMU_USED(rdip)); 6417613SVikram.Hegde@Sun.COM 642*13050Sfrank.van.der.linden@oracle.com unitp = DEVI(rdip)->devi_iommulib_handle; 6437613SVikram.Hegde@Sun.COM 6447613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 6457613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 646*13050Sfrank.van.der.linden@oracle.com 647*13050Sfrank.van.der.linden@oracle.com nexp = (iommulib_nex_t *)unitp->ilu_nex; 648*13050Sfrank.van.der.linden@oracle.com DEVI(rdip)->devi_iommulib_handle = NULL; 649*13050Sfrank.van.der.linden@oracle.com 6507613SVikram.Hegde@Sun.COM unitid = unitp->ilu_unitid; 6517613SVikram.Hegde@Sun.COM driver = ddi_driver_name(unitp->ilu_dip); 6527613SVikram.Hegde@Sun.COM instance = ddi_get_instance(unitp->ilu_dip); 653*13050Sfrank.van.der.linden@oracle.com 6547613SVikram.Hegde@Sun.COM unitp->ilu_ref--; 6557613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 6567613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 6577613SVikram.Hegde@Sun.COM 658*13050Sfrank.van.der.linden@oracle.com atomic_dec_uint(&nexp->nex_ref); 659*13050Sfrank.van.der.linden@oracle.com 6607613SVikram.Hegde@Sun.COM if (iommulib_debug) { 6617717SVikram.Hegde@Sun.COM char *buf = kmem_alloc(MAXPATHLEN, KM_SLEEP); 6627717SVikram.Hegde@Sun.COM (void) ddi_pathname(rdip, buf); 6637613SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "%s: %s%d: closing IOMMU for dip (%p), " 6647613SVikram.Hegde@Sun.COM "unitid=%u rdip path = %s", f, driver, instance, 6657613SVikram.Hegde@Sun.COM (void *)rdip, unitid, buf); 6667717SVikram.Hegde@Sun.COM kmem_free(buf, MAXPATHLEN); 6677613SVikram.Hegde@Sun.COM } 6687613SVikram.Hegde@Sun.COM } 6697613SVikram.Hegde@Sun.COM 6707613SVikram.Hegde@Sun.COM int 6717613SVikram.Hegde@Sun.COM iommulib_nexdma_allochdl(dev_info_t *dip, dev_info_t *rdip, 6727613SVikram.Hegde@Sun.COM ddi_dma_attr_t *attr, int (*waitfp)(caddr_t), 6737613SVikram.Hegde@Sun.COM caddr_t arg, ddi_dma_handle_t *dma_handlep) 6747613SVikram.Hegde@Sun.COM { 6757613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 6767613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 6777613SVikram.Hegde@Sun.COM 6787613SVikram.Hegde@Sun.COM ASSERT(unitp); 6797613SVikram.Hegde@Sun.COM 6807613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 6817613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_allochdl(handle, dip, rdip, 6827613SVikram.Hegde@Sun.COM attr, waitfp, arg, dma_handlep)); 6837613SVikram.Hegde@Sun.COM } 6847613SVikram.Hegde@Sun.COM 6857613SVikram.Hegde@Sun.COM int 6867613SVikram.Hegde@Sun.COM iommulib_nexdma_freehdl(dev_info_t *dip, dev_info_t *rdip, 6877613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle) 6887613SVikram.Hegde@Sun.COM { 6897613SVikram.Hegde@Sun.COM int error; 6907613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 6917613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 6927613SVikram.Hegde@Sun.COM 6937613SVikram.Hegde@Sun.COM ASSERT(unitp); 6947613SVikram.Hegde@Sun.COM 6957613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 6967613SVikram.Hegde@Sun.COM error = unitp->ilu_ops->ilops_dma_freehdl(handle, dip, 6977613SVikram.Hegde@Sun.COM rdip, dma_handle); 6987613SVikram.Hegde@Sun.COM 6997613SVikram.Hegde@Sun.COM return (error); 7007613SVikram.Hegde@Sun.COM } 7017613SVikram.Hegde@Sun.COM 7027613SVikram.Hegde@Sun.COM int 7037613SVikram.Hegde@Sun.COM iommulib_nexdma_bindhdl(dev_info_t *dip, dev_info_t *rdip, 7047613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle, struct ddi_dma_req *dmareq, 7057613SVikram.Hegde@Sun.COM ddi_dma_cookie_t *cookiep, uint_t *ccountp) 7067613SVikram.Hegde@Sun.COM { 7077613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 7087613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 7097613SVikram.Hegde@Sun.COM 7107613SVikram.Hegde@Sun.COM ASSERT(unitp); 7117613SVikram.Hegde@Sun.COM 7127613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 7137613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_bindhdl(handle, dip, rdip, dma_handle, 7147613SVikram.Hegde@Sun.COM dmareq, cookiep, ccountp)); 7157613SVikram.Hegde@Sun.COM } 7167613SVikram.Hegde@Sun.COM 7177613SVikram.Hegde@Sun.COM int 7187613SVikram.Hegde@Sun.COM iommulib_nexdma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, 7197613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle) 7207613SVikram.Hegde@Sun.COM { 7217613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 7227613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 7237613SVikram.Hegde@Sun.COM 7247613SVikram.Hegde@Sun.COM ASSERT(unitp); 7257613SVikram.Hegde@Sun.COM 7267613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 7277613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_unbindhdl(handle, dip, rdip, 7287613SVikram.Hegde@Sun.COM dma_handle)); 7297613SVikram.Hegde@Sun.COM } 7307613SVikram.Hegde@Sun.COM 7317613SVikram.Hegde@Sun.COM int 7327613SVikram.Hegde@Sun.COM iommulib_nexdma_sync(dev_info_t *dip, dev_info_t *rdip, 7337613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle, off_t off, size_t len, 7347613SVikram.Hegde@Sun.COM uint_t cache_flags) 7357613SVikram.Hegde@Sun.COM { 7367613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 7377613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 7387613SVikram.Hegde@Sun.COM 7397613SVikram.Hegde@Sun.COM ASSERT(unitp); 7407613SVikram.Hegde@Sun.COM 7417613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 7427613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_sync(handle, dip, rdip, dma_handle, 7437613SVikram.Hegde@Sun.COM off, len, cache_flags)); 7447613SVikram.Hegde@Sun.COM } 7457613SVikram.Hegde@Sun.COM 7467613SVikram.Hegde@Sun.COM int 7477613SVikram.Hegde@Sun.COM iommulib_nexdma_win(dev_info_t *dip, dev_info_t *rdip, 7487613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle, uint_t win, off_t *offp, size_t *lenp, 7497613SVikram.Hegde@Sun.COM ddi_dma_cookie_t *cookiep, uint_t *ccountp) 7507613SVikram.Hegde@Sun.COM { 7517613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 7527613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 7537613SVikram.Hegde@Sun.COM 7547613SVikram.Hegde@Sun.COM ASSERT(unitp); 7557613SVikram.Hegde@Sun.COM 7567613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 7577613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_win(handle, dip, rdip, dma_handle, 7587613SVikram.Hegde@Sun.COM win, offp, lenp, cookiep, ccountp)); 7597613SVikram.Hegde@Sun.COM } 7607613SVikram.Hegde@Sun.COM 7617613SVikram.Hegde@Sun.COM /* Obsolete DMA routines */ 7627613SVikram.Hegde@Sun.COM 7637613SVikram.Hegde@Sun.COM int 7647613SVikram.Hegde@Sun.COM iommulib_nexdma_map(dev_info_t *dip, dev_info_t *rdip, 7657613SVikram.Hegde@Sun.COM struct ddi_dma_req *dmareq, ddi_dma_handle_t *dma_handle) 7667613SVikram.Hegde@Sun.COM { 7677613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 7687613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = handle; 7697613SVikram.Hegde@Sun.COM 7707613SVikram.Hegde@Sun.COM ASSERT(unitp); 7717613SVikram.Hegde@Sun.COM 7727613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 7737613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_map(handle, dip, rdip, dmareq, 7747613SVikram.Hegde@Sun.COM dma_handle)); 7757613SVikram.Hegde@Sun.COM } 7767613SVikram.Hegde@Sun.COM 7777613SVikram.Hegde@Sun.COM int 7787613SVikram.Hegde@Sun.COM iommulib_nexdma_mctl(dev_info_t *dip, dev_info_t *rdip, 7797613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle, enum ddi_dma_ctlops request, 7807613SVikram.Hegde@Sun.COM off_t *offp, size_t *lenp, caddr_t *objpp, uint_t cache_flags) 7817613SVikram.Hegde@Sun.COM { 7827613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 7837613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 7847613SVikram.Hegde@Sun.COM 7857613SVikram.Hegde@Sun.COM ASSERT(unitp); 7867613SVikram.Hegde@Sun.COM 7877613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 7887613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_mctl(handle, dip, rdip, dma_handle, 7897613SVikram.Hegde@Sun.COM request, offp, lenp, objpp, cache_flags)); 7907613SVikram.Hegde@Sun.COM } 7917613SVikram.Hegde@Sun.COM 792*13050Sfrank.van.der.linden@oracle.com int 793*13050Sfrank.van.der.linden@oracle.com iommulib_nexdma_mapobject(dev_info_t *dip, dev_info_t *rdip, 794*13050Sfrank.van.der.linden@oracle.com ddi_dma_handle_t dma_handle, struct ddi_dma_req *dmareq, 795*13050Sfrank.van.der.linden@oracle.com ddi_dma_obj_t *dmao) 796*13050Sfrank.van.der.linden@oracle.com { 797*13050Sfrank.van.der.linden@oracle.com iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 798*13050Sfrank.van.der.linden@oracle.com iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 799*13050Sfrank.van.der.linden@oracle.com 800*13050Sfrank.van.der.linden@oracle.com return (unitp->ilu_ops->ilops_dma_mapobject(handle, dip, rdip, 801*13050Sfrank.van.der.linden@oracle.com dma_handle, dmareq, dmao)); 802*13050Sfrank.van.der.linden@oracle.com } 803*13050Sfrank.van.der.linden@oracle.com 804*13050Sfrank.van.der.linden@oracle.com int 805*13050Sfrank.van.der.linden@oracle.com iommulib_nexdma_unmapobject(dev_info_t *dip, dev_info_t *rdip, 806*13050Sfrank.van.der.linden@oracle.com ddi_dma_handle_t dma_handle, ddi_dma_obj_t *dmao) 807*13050Sfrank.van.der.linden@oracle.com { 808*13050Sfrank.van.der.linden@oracle.com iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 809*13050Sfrank.van.der.linden@oracle.com iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 810*13050Sfrank.van.der.linden@oracle.com 811*13050Sfrank.van.der.linden@oracle.com return (unitp->ilu_ops->ilops_dma_unmapobject(handle, dip, rdip, 812*13050Sfrank.van.der.linden@oracle.com dma_handle, dmao)); 813*13050Sfrank.van.der.linden@oracle.com } 814*13050Sfrank.van.der.linden@oracle.com 8157613SVikram.Hegde@Sun.COM /* Utility routines invoked by IOMMU drivers */ 8167613SVikram.Hegde@Sun.COM int 8177613SVikram.Hegde@Sun.COM iommulib_iommu_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, 8187613SVikram.Hegde@Sun.COM ddi_dma_attr_t *attr, int (*waitfp)(caddr_t), caddr_t arg, 8197613SVikram.Hegde@Sun.COM ddi_dma_handle_t *handlep) 8207613SVikram.Hegde@Sun.COM { 821*13050Sfrank.van.der.linden@oracle.com iommulib_nexops_t *nexops; 822*13050Sfrank.van.der.linden@oracle.com 823*13050Sfrank.van.der.linden@oracle.com nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 8247613SVikram.Hegde@Sun.COM return (nexops->nops_dma_allochdl(dip, rdip, attr, waitfp, arg, 8257613SVikram.Hegde@Sun.COM handlep)); 8267613SVikram.Hegde@Sun.COM } 8277613SVikram.Hegde@Sun.COM 8287613SVikram.Hegde@Sun.COM int 8297613SVikram.Hegde@Sun.COM iommulib_iommu_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, 8307613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle) 8317613SVikram.Hegde@Sun.COM { 832*13050Sfrank.van.der.linden@oracle.com iommulib_nexops_t *nexops; 833*13050Sfrank.van.der.linden@oracle.com 834*13050Sfrank.van.der.linden@oracle.com nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 835*13050Sfrank.van.der.linden@oracle.com ASSERT(nexops); 8367613SVikram.Hegde@Sun.COM return (nexops->nops_dma_freehdl(dip, rdip, handle)); 8377613SVikram.Hegde@Sun.COM } 8387613SVikram.Hegde@Sun.COM 8397613SVikram.Hegde@Sun.COM int 8407613SVikram.Hegde@Sun.COM iommulib_iommu_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip, 8417613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle, struct ddi_dma_req *dmareq, 8427613SVikram.Hegde@Sun.COM ddi_dma_cookie_t *cookiep, uint_t *ccountp) 8437613SVikram.Hegde@Sun.COM { 844*13050Sfrank.van.der.linden@oracle.com iommulib_nexops_t *nexops; 845*13050Sfrank.van.der.linden@oracle.com 846*13050Sfrank.van.der.linden@oracle.com nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 8477613SVikram.Hegde@Sun.COM return (nexops->nops_dma_bindhdl(dip, rdip, handle, dmareq, 8487613SVikram.Hegde@Sun.COM cookiep, ccountp)); 8497613SVikram.Hegde@Sun.COM } 8507613SVikram.Hegde@Sun.COM 8517613SVikram.Hegde@Sun.COM int 8527613SVikram.Hegde@Sun.COM iommulib_iommu_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, 8537613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle) 8547613SVikram.Hegde@Sun.COM { 855*13050Sfrank.van.der.linden@oracle.com iommulib_nexops_t *nexops; 856*13050Sfrank.van.der.linden@oracle.com 857*13050Sfrank.van.der.linden@oracle.com nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 8587613SVikram.Hegde@Sun.COM return (nexops->nops_dma_unbindhdl(dip, rdip, handle)); 8597613SVikram.Hegde@Sun.COM } 8607613SVikram.Hegde@Sun.COM 8617613SVikram.Hegde@Sun.COM void 8627613SVikram.Hegde@Sun.COM iommulib_iommu_dma_reset_cookies(dev_info_t *dip, ddi_dma_handle_t handle) 8637613SVikram.Hegde@Sun.COM { 864*13050Sfrank.van.der.linden@oracle.com iommulib_nexops_t *nexops; 865*13050Sfrank.van.der.linden@oracle.com 866*13050Sfrank.van.der.linden@oracle.com nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 8677613SVikram.Hegde@Sun.COM nexops->nops_dma_reset_cookies(dip, handle); 8687613SVikram.Hegde@Sun.COM } 8697613SVikram.Hegde@Sun.COM 8707613SVikram.Hegde@Sun.COM int 8717613SVikram.Hegde@Sun.COM iommulib_iommu_dma_get_cookies(dev_info_t *dip, ddi_dma_handle_t handle, 8728215SVikram.Hegde@Sun.COM ddi_dma_cookie_t **cookiepp, uint_t *ccountp) 8738215SVikram.Hegde@Sun.COM { 874*13050Sfrank.van.der.linden@oracle.com iommulib_nexops_t *nexops; 875*13050Sfrank.van.der.linden@oracle.com 876*13050Sfrank.van.der.linden@oracle.com nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 8778215SVikram.Hegde@Sun.COM return (nexops->nops_dma_get_cookies(dip, handle, cookiepp, ccountp)); 8788215SVikram.Hegde@Sun.COM } 8798215SVikram.Hegde@Sun.COM 8808215SVikram.Hegde@Sun.COM int 8818215SVikram.Hegde@Sun.COM iommulib_iommu_dma_set_cookies(dev_info_t *dip, ddi_dma_handle_t handle, 8828215SVikram.Hegde@Sun.COM ddi_dma_cookie_t *cookiep, uint_t ccount) 8837613SVikram.Hegde@Sun.COM { 884*13050Sfrank.van.der.linden@oracle.com iommulib_nexops_t *nexops; 885*13050Sfrank.van.der.linden@oracle.com 886*13050Sfrank.van.der.linden@oracle.com nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 8878215SVikram.Hegde@Sun.COM return (nexops->nops_dma_set_cookies(dip, handle, cookiep, ccount)); 8888215SVikram.Hegde@Sun.COM } 8898215SVikram.Hegde@Sun.COM 8908215SVikram.Hegde@Sun.COM int 8918215SVikram.Hegde@Sun.COM iommulib_iommu_dma_clear_cookies(dev_info_t *dip, ddi_dma_handle_t handle) 8928215SVikram.Hegde@Sun.COM { 893*13050Sfrank.van.der.linden@oracle.com iommulib_nexops_t *nexops; 894*13050Sfrank.van.der.linden@oracle.com 895*13050Sfrank.van.der.linden@oracle.com nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 8968215SVikram.Hegde@Sun.COM return (nexops->nops_dma_clear_cookies(dip, handle)); 8978215SVikram.Hegde@Sun.COM } 8988215SVikram.Hegde@Sun.COM 8998215SVikram.Hegde@Sun.COM int 9008215SVikram.Hegde@Sun.COM iommulib_iommu_dma_get_sleep_flags(dev_info_t *dip, ddi_dma_handle_t handle) 9018215SVikram.Hegde@Sun.COM { 902*13050Sfrank.van.der.linden@oracle.com iommulib_nexops_t *nexops; 903*13050Sfrank.van.der.linden@oracle.com 904*13050Sfrank.van.der.linden@oracle.com nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 9058215SVikram.Hegde@Sun.COM return (nexops->nops_dma_get_sleep_flags(handle)); 9067613SVikram.Hegde@Sun.COM } 9077613SVikram.Hegde@Sun.COM 9087613SVikram.Hegde@Sun.COM int 9097613SVikram.Hegde@Sun.COM iommulib_iommu_dma_sync(dev_info_t *dip, dev_info_t *rdip, 9107613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle, off_t off, size_t len, uint_t cache_flags) 9117613SVikram.Hegde@Sun.COM { 912*13050Sfrank.van.der.linden@oracle.com iommulib_nexops_t *nexops; 913*13050Sfrank.van.der.linden@oracle.com 914*13050Sfrank.van.der.linden@oracle.com nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 9157613SVikram.Hegde@Sun.COM return (nexops->nops_dma_sync(dip, rdip, handle, off, len, 9167613SVikram.Hegde@Sun.COM cache_flags)); 9177613SVikram.Hegde@Sun.COM } 9187613SVikram.Hegde@Sun.COM 9197613SVikram.Hegde@Sun.COM int 9207613SVikram.Hegde@Sun.COM iommulib_iommu_dma_win(dev_info_t *dip, dev_info_t *rdip, 9217613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle, uint_t win, off_t *offp, size_t *lenp, 9227613SVikram.Hegde@Sun.COM ddi_dma_cookie_t *cookiep, uint_t *ccountp) 9237613SVikram.Hegde@Sun.COM { 924*13050Sfrank.van.der.linden@oracle.com iommulib_nexops_t *nexops; 925*13050Sfrank.van.der.linden@oracle.com 926*13050Sfrank.van.der.linden@oracle.com nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 9277613SVikram.Hegde@Sun.COM return (nexops->nops_dma_win(dip, rdip, handle, win, offp, lenp, 9287613SVikram.Hegde@Sun.COM cookiep, ccountp)); 9297613SVikram.Hegde@Sun.COM } 9307613SVikram.Hegde@Sun.COM 9317613SVikram.Hegde@Sun.COM int 9327613SVikram.Hegde@Sun.COM iommulib_iommu_dma_map(dev_info_t *dip, dev_info_t *rdip, 9337613SVikram.Hegde@Sun.COM struct ddi_dma_req *dmareq, ddi_dma_handle_t *handlep) 9347613SVikram.Hegde@Sun.COM { 935*13050Sfrank.van.der.linden@oracle.com iommulib_nexops_t *nexops; 936*13050Sfrank.van.der.linden@oracle.com 937*13050Sfrank.van.der.linden@oracle.com nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 9387613SVikram.Hegde@Sun.COM return (nexops->nops_dma_map(dip, rdip, dmareq, handlep)); 9397613SVikram.Hegde@Sun.COM } 9407613SVikram.Hegde@Sun.COM 9417613SVikram.Hegde@Sun.COM int 9427613SVikram.Hegde@Sun.COM iommulib_iommu_dma_mctl(dev_info_t *dip, dev_info_t *rdip, 9437613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle, enum ddi_dma_ctlops request, off_t *offp, 9447613SVikram.Hegde@Sun.COM size_t *lenp, caddr_t *objpp, uint_t cache_flags) 9457613SVikram.Hegde@Sun.COM { 946*13050Sfrank.van.der.linden@oracle.com iommulib_nexops_t *nexops; 947*13050Sfrank.van.der.linden@oracle.com 948*13050Sfrank.van.der.linden@oracle.com nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 9497613SVikram.Hegde@Sun.COM return (nexops->nops_dma_mctl(dip, rdip, handle, request, offp, lenp, 9507613SVikram.Hegde@Sun.COM objpp, cache_flags)); 9517613SVikram.Hegde@Sun.COM } 9527613SVikram.Hegde@Sun.COM 9537613SVikram.Hegde@Sun.COM int 954*13050Sfrank.van.der.linden@oracle.com iommulib_iommu_dmahdl_setprivate(dev_info_t *dip, dev_info_t *rdip, 955*13050Sfrank.van.der.linden@oracle.com ddi_dma_handle_t handle, void *priv) 956*13050Sfrank.van.der.linden@oracle.com { 957*13050Sfrank.van.der.linden@oracle.com iommulib_nexops_t *nexops; 958*13050Sfrank.van.der.linden@oracle.com 959*13050Sfrank.van.der.linden@oracle.com nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 960*13050Sfrank.van.der.linden@oracle.com return (nexops->nops_dmahdl_setprivate(dip, rdip, handle, priv)); 961*13050Sfrank.van.der.linden@oracle.com } 962*13050Sfrank.van.der.linden@oracle.com 963*13050Sfrank.van.der.linden@oracle.com void * 964*13050Sfrank.van.der.linden@oracle.com iommulib_iommu_dmahdl_getprivate(dev_info_t *dip, dev_info_t *rdip, 965*13050Sfrank.van.der.linden@oracle.com ddi_dma_handle_t handle) 966*13050Sfrank.van.der.linden@oracle.com { 967*13050Sfrank.van.der.linden@oracle.com iommulib_nexops_t *nexops; 968*13050Sfrank.van.der.linden@oracle.com 969*13050Sfrank.van.der.linden@oracle.com nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 970*13050Sfrank.van.der.linden@oracle.com return (nexops->nops_dmahdl_getprivate(dip, rdip, handle)); 971*13050Sfrank.van.der.linden@oracle.com } 972*13050Sfrank.van.der.linden@oracle.com 973*13050Sfrank.van.der.linden@oracle.com int 9747613SVikram.Hegde@Sun.COM iommulib_iommu_getunitid(iommulib_handle_t handle, uint64_t *unitidp) 9757613SVikram.Hegde@Sun.COM { 9767613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 9777613SVikram.Hegde@Sun.COM uint64_t unitid; 9787613SVikram.Hegde@Sun.COM 9797613SVikram.Hegde@Sun.COM unitp = (iommulib_unit_t *)handle; 9807613SVikram.Hegde@Sun.COM 9817613SVikram.Hegde@Sun.COM ASSERT(unitp); 9827613SVikram.Hegde@Sun.COM ASSERT(unitidp); 9837613SVikram.Hegde@Sun.COM 9847613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 9857613SVikram.Hegde@Sun.COM unitid = unitp->ilu_unitid; 9867613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 9877613SVikram.Hegde@Sun.COM 9887613SVikram.Hegde@Sun.COM ASSERT(unitid > 0); 9897613SVikram.Hegde@Sun.COM *unitidp = (uint64_t)unitid; 9907613SVikram.Hegde@Sun.COM 9917613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 9927613SVikram.Hegde@Sun.COM } 9937613SVikram.Hegde@Sun.COM 9947613SVikram.Hegde@Sun.COM dev_info_t * 9957613SVikram.Hegde@Sun.COM iommulib_iommu_getdip(iommulib_handle_t handle) 9967613SVikram.Hegde@Sun.COM { 9977613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 9987613SVikram.Hegde@Sun.COM dev_info_t *dip; 9997613SVikram.Hegde@Sun.COM 10007613SVikram.Hegde@Sun.COM unitp = (iommulib_unit_t *)handle; 10017613SVikram.Hegde@Sun.COM 10027613SVikram.Hegde@Sun.COM ASSERT(unitp); 10037613SVikram.Hegde@Sun.COM 10047613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 10057613SVikram.Hegde@Sun.COM dip = unitp->ilu_dip; 10067613SVikram.Hegde@Sun.COM ASSERT(dip); 10077613SVikram.Hegde@Sun.COM ndi_hold_devi(dip); 10087613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 10097613SVikram.Hegde@Sun.COM 10107613SVikram.Hegde@Sun.COM return (dip); 10117613SVikram.Hegde@Sun.COM } 10127613SVikram.Hegde@Sun.COM 10137613SVikram.Hegde@Sun.COM iommulib_ops_t * 10147613SVikram.Hegde@Sun.COM iommulib_iommu_getops(iommulib_handle_t handle) 10157613SVikram.Hegde@Sun.COM { 10167613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 10177613SVikram.Hegde@Sun.COM iommulib_ops_t *ops; 10187613SVikram.Hegde@Sun.COM 10197613SVikram.Hegde@Sun.COM unitp = (iommulib_unit_t *)handle; 10207613SVikram.Hegde@Sun.COM 10217613SVikram.Hegde@Sun.COM ASSERT(unitp); 10227613SVikram.Hegde@Sun.COM 10237613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 10247613SVikram.Hegde@Sun.COM ops = unitp->ilu_ops; 10257613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 10267613SVikram.Hegde@Sun.COM 10277613SVikram.Hegde@Sun.COM ASSERT(ops); 10287613SVikram.Hegde@Sun.COM 10297613SVikram.Hegde@Sun.COM return (ops); 10307613SVikram.Hegde@Sun.COM } 10317613SVikram.Hegde@Sun.COM 10327613SVikram.Hegde@Sun.COM void * 10337613SVikram.Hegde@Sun.COM iommulib_iommu_getdata(iommulib_handle_t handle) 10347613SVikram.Hegde@Sun.COM { 10357613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 10367613SVikram.Hegde@Sun.COM void *data; 10377613SVikram.Hegde@Sun.COM 10387613SVikram.Hegde@Sun.COM unitp = (iommulib_unit_t *)handle; 10397613SVikram.Hegde@Sun.COM 10407613SVikram.Hegde@Sun.COM ASSERT(unitp); 10417613SVikram.Hegde@Sun.COM 10427613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 10437613SVikram.Hegde@Sun.COM data = unitp->ilu_data; 10447613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 10457613SVikram.Hegde@Sun.COM 10467613SVikram.Hegde@Sun.COM ASSERT(data); 10477613SVikram.Hegde@Sun.COM 10487613SVikram.Hegde@Sun.COM return (data); 10497613SVikram.Hegde@Sun.COM } 1050