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 /* 227613SVikram.Hegde@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237613SVikram.Hegde@Sun.COM * Use is subject to license terms. 247613SVikram.Hegde@Sun.COM */ 257613SVikram.Hegde@Sun.COM 267613SVikram.Hegde@Sun.COM #pragma ident "@(#)iommulib.c 1.6 08/09/07 SMI" 277613SVikram.Hegde@Sun.COM 287613SVikram.Hegde@Sun.COM #include <sys/sunddi.h> 297613SVikram.Hegde@Sun.COM #include <sys/sunndi.h> 307613SVikram.Hegde@Sun.COM #include <sys/errno.h> 317613SVikram.Hegde@Sun.COM #include <sys/modctl.h> 327613SVikram.Hegde@Sun.COM #include <sys/iommulib.h> 337613SVikram.Hegde@Sun.COM 347613SVikram.Hegde@Sun.COM /* ******** Type definitions private to this file ********************** */ 357613SVikram.Hegde@Sun.COM 367613SVikram.Hegde@Sun.COM /* 1 per IOMMU unit. There may be more than one per dip */ 377613SVikram.Hegde@Sun.COM typedef struct iommulib_unit { 387613SVikram.Hegde@Sun.COM kmutex_t ilu_lock; 397613SVikram.Hegde@Sun.COM uint64_t ilu_ref; 407613SVikram.Hegde@Sun.COM uint32_t ilu_unitid; 417613SVikram.Hegde@Sun.COM dev_info_t *ilu_dip; 427613SVikram.Hegde@Sun.COM iommulib_ops_t *ilu_ops; 437613SVikram.Hegde@Sun.COM void* ilu_data; 447613SVikram.Hegde@Sun.COM struct iommulib_unit *ilu_next; 457613SVikram.Hegde@Sun.COM struct iommulib_unit *ilu_prev; 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; 537613SVikram.Hegde@Sun.COM } iommulib_nex_t; 547613SVikram.Hegde@Sun.COM 557613SVikram.Hegde@Sun.COM /* ********* Globals ************************ */ 567613SVikram.Hegde@Sun.COM 577613SVikram.Hegde@Sun.COM /* IOMMU side: Following data protected by lock */ 587613SVikram.Hegde@Sun.COM static kmutex_t iommulib_lock; 597613SVikram.Hegde@Sun.COM static iommulib_unit_t *iommulib_list; 607613SVikram.Hegde@Sun.COM static uint64_t iommulib_unit_ids = 0; 617613SVikram.Hegde@Sun.COM static uint64_t iommulib_num_units = 0; 627613SVikram.Hegde@Sun.COM 637613SVikram.Hegde@Sun.COM /* rootnex side data */ 647613SVikram.Hegde@Sun.COM 657613SVikram.Hegde@Sun.COM static kmutex_t iommulib_nexus_lock; 667613SVikram.Hegde@Sun.COM static iommulib_nex_t *iommulib_nexus_list; 677613SVikram.Hegde@Sun.COM 687613SVikram.Hegde@Sun.COM /* can be set atomically without lock */ 697613SVikram.Hegde@Sun.COM static volatile uint32_t iommulib_fini; 707613SVikram.Hegde@Sun.COM 717613SVikram.Hegde@Sun.COM /* debug flag */ 727613SVikram.Hegde@Sun.COM static int iommulib_debug; 737613SVikram.Hegde@Sun.COM 747613SVikram.Hegde@Sun.COM /* 757613SVikram.Hegde@Sun.COM * Module linkage information for the kernel. 767613SVikram.Hegde@Sun.COM */ 777613SVikram.Hegde@Sun.COM static struct modlmisc modlmisc = { 787613SVikram.Hegde@Sun.COM &mod_miscops, "IOMMU library module" 797613SVikram.Hegde@Sun.COM }; 807613SVikram.Hegde@Sun.COM 817613SVikram.Hegde@Sun.COM static struct modlinkage modlinkage = { 827613SVikram.Hegde@Sun.COM MODREV_1, (void *)&modlmisc, NULL 837613SVikram.Hegde@Sun.COM }; 847613SVikram.Hegde@Sun.COM 857613SVikram.Hegde@Sun.COM int 867613SVikram.Hegde@Sun.COM _init(void) 877613SVikram.Hegde@Sun.COM { 887613SVikram.Hegde@Sun.COM return (mod_install(&modlinkage)); 897613SVikram.Hegde@Sun.COM } 907613SVikram.Hegde@Sun.COM 917613SVikram.Hegde@Sun.COM int 927613SVikram.Hegde@Sun.COM _fini(void) 937613SVikram.Hegde@Sun.COM { 947613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 957613SVikram.Hegde@Sun.COM if (iommulib_list != NULL || iommulib_nexus_list != NULL) { 967613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 977613SVikram.Hegde@Sun.COM return (EBUSY); 987613SVikram.Hegde@Sun.COM } 997613SVikram.Hegde@Sun.COM iommulib_fini = 1; 1007613SVikram.Hegde@Sun.COM 1017613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 1027613SVikram.Hegde@Sun.COM return (mod_remove(&modlinkage)); 1037613SVikram.Hegde@Sun.COM } 1047613SVikram.Hegde@Sun.COM 1057613SVikram.Hegde@Sun.COM int 1067613SVikram.Hegde@Sun.COM _info(struct modinfo *modinfop) 1077613SVikram.Hegde@Sun.COM { 1087613SVikram.Hegde@Sun.COM return (mod_info(&modlinkage, modinfop)); 1097613SVikram.Hegde@Sun.COM } 1107613SVikram.Hegde@Sun.COM 1117613SVikram.Hegde@Sun.COM /* 1127613SVikram.Hegde@Sun.COM * Routines with iommulib_iommu_* are invoked from the 1137613SVikram.Hegde@Sun.COM * IOMMU driver. 1147613SVikram.Hegde@Sun.COM * Routines with iommulib_nex* are invoked from the 1157613SVikram.Hegde@Sun.COM * nexus driver (typically rootnex) 1167613SVikram.Hegde@Sun.COM */ 1177613SVikram.Hegde@Sun.COM 1187613SVikram.Hegde@Sun.COM int 1197613SVikram.Hegde@Sun.COM iommulib_nexus_register(dev_info_t *dip, iommulib_nexops_t *nexops, 1207613SVikram.Hegde@Sun.COM iommulib_nexhandle_t *handle) 1217613SVikram.Hegde@Sun.COM { 1227613SVikram.Hegde@Sun.COM iommulib_nex_t *nexp; 1237613SVikram.Hegde@Sun.COM int instance = ddi_get_instance(dip); 1247613SVikram.Hegde@Sun.COM const char *driver = ddi_driver_name(dip); 1257613SVikram.Hegde@Sun.COM dev_info_t *pdip = ddi_get_parent(dip); 1267613SVikram.Hegde@Sun.COM const char *f = "iommulib_nexus_register"; 1277613SVikram.Hegde@Sun.COM 1287613SVikram.Hegde@Sun.COM ASSERT(nexops); 1297613SVikram.Hegde@Sun.COM ASSERT(handle); 1307613SVikram.Hegde@Sun.COM 1317613SVikram.Hegde@Sun.COM *handle = NULL; 1327613SVikram.Hegde@Sun.COM 1337613SVikram.Hegde@Sun.COM /* 1347613SVikram.Hegde@Sun.COM * Root node is never busy held 1357613SVikram.Hegde@Sun.COM */ 1367613SVikram.Hegde@Sun.COM if (dip != ddi_root_node() && (i_ddi_node_state(dip) < DS_PROBED || 1377613SVikram.Hegde@Sun.COM !DEVI_BUSY_OWNED(pdip))) { 1387613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: NEXUS devinfo node not in DS_PROBED " 1397613SVikram.Hegde@Sun.COM "or busy held for nexops vector (%p). Failing registration", 1407613SVikram.Hegde@Sun.COM f, (void *)nexops); 1417613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1427613SVikram.Hegde@Sun.COM } 1437613SVikram.Hegde@Sun.COM 1447613SVikram.Hegde@Sun.COM if (nexops->nops_vers != IOMMU_NEXOPS_VERSION) { 1457613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: Invalid IOMMULIB nexops version " 1467613SVikram.Hegde@Sun.COM "in nexops vector (%p). Failing NEXUS registration", 1477613SVikram.Hegde@Sun.COM f, driver, instance, (void *)nexops); 1487613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1497613SVikram.Hegde@Sun.COM } 1507613SVikram.Hegde@Sun.COM 1517613SVikram.Hegde@Sun.COM ASSERT(nexops->nops_data == NULL); 1527613SVikram.Hegde@Sun.COM 1537613SVikram.Hegde@Sun.COM if (nexops->nops_id == NULL) { 1547613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL ID field. " 1557613SVikram.Hegde@Sun.COM "Failing registration for nexops vector: %p", 1567613SVikram.Hegde@Sun.COM f, driver, instance, (void *)nexops); 1577613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1587613SVikram.Hegde@Sun.COM } 1597613SVikram.Hegde@Sun.COM 1607613SVikram.Hegde@Sun.COM if (nexops->nops_dma_allochdl == NULL) { 1617613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_allochdl op. " 1627613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 1637613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 1647613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1657613SVikram.Hegde@Sun.COM } 1667613SVikram.Hegde@Sun.COM 1677613SVikram.Hegde@Sun.COM if (nexops->nops_dma_freehdl == NULL) { 1687613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_freehdl op. " 1697613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 1707613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 1717613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1727613SVikram.Hegde@Sun.COM } 1737613SVikram.Hegde@Sun.COM 1747613SVikram.Hegde@Sun.COM if (nexops->nops_dma_bindhdl == NULL) { 1757613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_bindhdl op. " 1767613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 1777613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 1787613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1797613SVikram.Hegde@Sun.COM } 1807613SVikram.Hegde@Sun.COM 1817613SVikram.Hegde@Sun.COM if (nexops->nops_dma_sync == NULL) { 1827613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_sync op. " 1837613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 1847613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 1857613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1867613SVikram.Hegde@Sun.COM } 1877613SVikram.Hegde@Sun.COM 1887613SVikram.Hegde@Sun.COM if (nexops->nops_dma_reset_cookies == NULL) { 1897613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_reset_cookies op. " 1907613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 1917613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 1927613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1937613SVikram.Hegde@Sun.COM } 1947613SVikram.Hegde@Sun.COM 1957613SVikram.Hegde@Sun.COM if (nexops->nops_dma_get_cookies == NULL) { 1967613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_get_cookies op. " 1977613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 1987613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 1997613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 2007613SVikram.Hegde@Sun.COM } 2017613SVikram.Hegde@Sun.COM 202*8215SVikram.Hegde@Sun.COM if (nexops->nops_dma_set_cookies == NULL) { 203*8215SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_set_cookies op. " 204*8215SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 205*8215SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 206*8215SVikram.Hegde@Sun.COM return (DDI_FAILURE); 207*8215SVikram.Hegde@Sun.COM } 208*8215SVikram.Hegde@Sun.COM 209*8215SVikram.Hegde@Sun.COM if (nexops->nops_dma_clear_cookies == NULL) { 210*8215SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_clear_cookies op. " 211*8215SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 212*8215SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 213*8215SVikram.Hegde@Sun.COM return (DDI_FAILURE); 214*8215SVikram.Hegde@Sun.COM } 215*8215SVikram.Hegde@Sun.COM 216*8215SVikram.Hegde@Sun.COM if (nexops->nops_dma_get_sleep_flags == NULL) { 217*8215SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_get_sleep_flags op. " 218*8215SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 219*8215SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 220*8215SVikram.Hegde@Sun.COM return (DDI_FAILURE); 221*8215SVikram.Hegde@Sun.COM } 222*8215SVikram.Hegde@Sun.COM 2237613SVikram.Hegde@Sun.COM if (nexops->nops_dma_win == NULL) { 2247613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_win op. " 2257613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 2267613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 2277613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 2287613SVikram.Hegde@Sun.COM } 2297613SVikram.Hegde@Sun.COM 2307613SVikram.Hegde@Sun.COM /* Check for legacy ops */ 2317613SVikram.Hegde@Sun.COM if (nexops->nops_dma_map == NULL) { 2327613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL legacy nops_dma_map op. " 2337613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 2347613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 2357613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 2367613SVikram.Hegde@Sun.COM } 2377613SVikram.Hegde@Sun.COM 2387613SVikram.Hegde@Sun.COM if (nexops->nops_dma_mctl == NULL) { 2397613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL legacy nops_dma_mctl op. " 2407613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 2417613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 2427613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 2437613SVikram.Hegde@Sun.COM } 2447613SVikram.Hegde@Sun.COM 2457613SVikram.Hegde@Sun.COM nexp = kmem_zalloc(sizeof (iommulib_nex_t), KM_SLEEP); 2467613SVikram.Hegde@Sun.COM 2477613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 2487613SVikram.Hegde@Sun.COM if (iommulib_fini == 1) { 2497613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 2507613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: IOMMULIB unloading. " 2517613SVikram.Hegde@Sun.COM "Failing NEXUS register.", f); 2527613SVikram.Hegde@Sun.COM kmem_free(nexp, sizeof (iommulib_nex_t)); 2537613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 2547613SVikram.Hegde@Sun.COM } 2557613SVikram.Hegde@Sun.COM 2567613SVikram.Hegde@Sun.COM /* 2577613SVikram.Hegde@Sun.COM * fini/register race conditions have been handled. Now create the 2587613SVikram.Hegde@Sun.COM * nexus struct 2597613SVikram.Hegde@Sun.COM */ 2607613SVikram.Hegde@Sun.COM ndi_hold_devi(dip); 2617613SVikram.Hegde@Sun.COM nexp->nex_dip = dip; 2627613SVikram.Hegde@Sun.COM nexp->nex_ops = *nexops; 2637613SVikram.Hegde@Sun.COM 2647613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_nexus_lock); 2657613SVikram.Hegde@Sun.COM nexp->nex_next = iommulib_nexus_list; 2667613SVikram.Hegde@Sun.COM iommulib_nexus_list = nexp; 2677613SVikram.Hegde@Sun.COM nexp->nex_prev = NULL; 2687613SVikram.Hegde@Sun.COM 2697613SVikram.Hegde@Sun.COM if (nexp->nex_next != NULL) 2707613SVikram.Hegde@Sun.COM nexp->nex_next->nex_prev = nexp; 2717613SVikram.Hegde@Sun.COM 2727613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_nexus_lock); 2737613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 2747613SVikram.Hegde@Sun.COM 2757613SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "!%s: %s%d: Succesfully registered NEXUS %s " 2767613SVikram.Hegde@Sun.COM "nexops=%p", f, driver, instance, ddi_node_name(dip), 2777613SVikram.Hegde@Sun.COM (void *)nexops); 2787613SVikram.Hegde@Sun.COM 2797613SVikram.Hegde@Sun.COM *handle = nexp; 2807613SVikram.Hegde@Sun.COM 2817613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 2827613SVikram.Hegde@Sun.COM } 2837613SVikram.Hegde@Sun.COM 2847613SVikram.Hegde@Sun.COM int 2857613SVikram.Hegde@Sun.COM iommulib_nexus_unregister(iommulib_nexhandle_t handle) 2867613SVikram.Hegde@Sun.COM { 2877613SVikram.Hegde@Sun.COM dev_info_t *dip; 2887613SVikram.Hegde@Sun.COM int instance; 2897613SVikram.Hegde@Sun.COM const char *driver; 2907613SVikram.Hegde@Sun.COM iommulib_nex_t *nexp = (iommulib_nex_t *)handle; 2917613SVikram.Hegde@Sun.COM const char *f = "iommulib_nexus_unregister"; 2927613SVikram.Hegde@Sun.COM 2937613SVikram.Hegde@Sun.COM ASSERT(nexp); 2947613SVikram.Hegde@Sun.COM 2957613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_nexus_lock); 2967613SVikram.Hegde@Sun.COM 2977613SVikram.Hegde@Sun.COM dip = nexp->nex_dip; 2987613SVikram.Hegde@Sun.COM driver = ddi_driver_name(dip); 2997613SVikram.Hegde@Sun.COM instance = ddi_get_instance(dip); 3007613SVikram.Hegde@Sun.COM 3017613SVikram.Hegde@Sun.COM /* A future enhancement would be to add ref-counts */ 3027613SVikram.Hegde@Sun.COM 3037613SVikram.Hegde@Sun.COM if (nexp->nex_prev == NULL) { 3047613SVikram.Hegde@Sun.COM iommulib_nexus_list = nexp->nex_next; 3057613SVikram.Hegde@Sun.COM } else { 3067613SVikram.Hegde@Sun.COM nexp->nex_prev->nex_next = nexp->nex_next; 3077613SVikram.Hegde@Sun.COM } 3087613SVikram.Hegde@Sun.COM 3097613SVikram.Hegde@Sun.COM if (nexp->nex_next != NULL) 3107613SVikram.Hegde@Sun.COM nexp->nex_next->nex_prev = nexp->nex_prev; 3117613SVikram.Hegde@Sun.COM 3127613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_nexus_lock); 3137613SVikram.Hegde@Sun.COM 3147613SVikram.Hegde@Sun.COM kmem_free(nexp, sizeof (iommulib_nex_t)); 3157613SVikram.Hegde@Sun.COM 316*8215SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "!%s: %s%d: NEXUS (%s) handle successfully " 3177613SVikram.Hegde@Sun.COM "unregistered from IOMMULIB", f, driver, instance, 3187613SVikram.Hegde@Sun.COM ddi_node_name(dip)); 3197613SVikram.Hegde@Sun.COM 3207613SVikram.Hegde@Sun.COM ndi_rele_devi(dip); 3217613SVikram.Hegde@Sun.COM 3227613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 3237613SVikram.Hegde@Sun.COM } 3247613SVikram.Hegde@Sun.COM 3257613SVikram.Hegde@Sun.COM static iommulib_nexops_t * 3267613SVikram.Hegde@Sun.COM lookup_nexops(dev_info_t *dip) 3277613SVikram.Hegde@Sun.COM { 3287613SVikram.Hegde@Sun.COM iommulib_nex_t *nexp; 3297613SVikram.Hegde@Sun.COM 3307613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_nexus_lock); 3317613SVikram.Hegde@Sun.COM nexp = iommulib_nexus_list; 3327613SVikram.Hegde@Sun.COM while (nexp) { 3337613SVikram.Hegde@Sun.COM if (nexp->nex_dip == dip) 3347613SVikram.Hegde@Sun.COM break; 3357613SVikram.Hegde@Sun.COM nexp = nexp->nex_next; 3367613SVikram.Hegde@Sun.COM } 3377613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_nexus_lock); 3387613SVikram.Hegde@Sun.COM 3397613SVikram.Hegde@Sun.COM return (nexp ? &nexp->nex_ops : NULL); 3407613SVikram.Hegde@Sun.COM } 3417613SVikram.Hegde@Sun.COM 3427613SVikram.Hegde@Sun.COM int 3437613SVikram.Hegde@Sun.COM iommulib_iommu_register(dev_info_t *dip, iommulib_ops_t *ops, 3447613SVikram.Hegde@Sun.COM iommulib_handle_t *handle) 3457613SVikram.Hegde@Sun.COM { 3467613SVikram.Hegde@Sun.COM const char *vendor; 3477613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 3487613SVikram.Hegde@Sun.COM int instance = ddi_get_instance(dip); 3497613SVikram.Hegde@Sun.COM const char *driver = ddi_driver_name(dip); 3507613SVikram.Hegde@Sun.COM dev_info_t *pdip = ddi_get_parent(dip); 3517613SVikram.Hegde@Sun.COM const char *f = "iommulib_register"; 3527613SVikram.Hegde@Sun.COM 3537613SVikram.Hegde@Sun.COM ASSERT(ops); 3547613SVikram.Hegde@Sun.COM ASSERT(handle); 3557613SVikram.Hegde@Sun.COM 3567613SVikram.Hegde@Sun.COM if (i_ddi_node_state(dip) < DS_PROBED || !DEVI_BUSY_OWNED(pdip)) { 3577613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: devinfo node not in DS_PROBED or " 3587613SVikram.Hegde@Sun.COM "busy held for ops vector (%p). Failing registration", 3597613SVikram.Hegde@Sun.COM f, (void *)ops); 3607613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 3617613SVikram.Hegde@Sun.COM } 3627613SVikram.Hegde@Sun.COM 3637613SVikram.Hegde@Sun.COM 3647613SVikram.Hegde@Sun.COM if (ops->ilops_vers != IOMMU_OPS_VERSION) { 3657613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: Invalid IOMMULIB ops version " 3667613SVikram.Hegde@Sun.COM "in ops vector (%p). Failing registration", f, driver, 3677613SVikram.Hegde@Sun.COM instance, (void *)ops); 3687613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 3697613SVikram.Hegde@Sun.COM } 3707613SVikram.Hegde@Sun.COM 3717613SVikram.Hegde@Sun.COM switch (ops->ilops_vendor) { 3727613SVikram.Hegde@Sun.COM case AMD_IOMMU: 3737613SVikram.Hegde@Sun.COM vendor = "AMD"; 3747613SVikram.Hegde@Sun.COM break; 3757613SVikram.Hegde@Sun.COM case INTEL_IOMMU: 3767613SVikram.Hegde@Sun.COM vendor = "Intel"; 3777613SVikram.Hegde@Sun.COM break; 3787613SVikram.Hegde@Sun.COM case INVALID_VENDOR: 3797613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: vendor field (%x) not initialized. " 3807613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 3817613SVikram.Hegde@Sun.COM driver, instance, ops->ilops_vendor, (void *)ops); 3827613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 3837613SVikram.Hegde@Sun.COM default: 3847613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: Invalid vendor field (%x). " 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 } 3897613SVikram.Hegde@Sun.COM 390*8215SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "!%s: %s%d: Detected IOMMU registration from vendor" 391*8215SVikram.Hegde@Sun.COM " %s", f, driver, instance, vendor); 3927613SVikram.Hegde@Sun.COM 3937613SVikram.Hegde@Sun.COM if (ops->ilops_data == NULL) { 3947613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL IOMMU data field. " 3957613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 3967613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 3977613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 3987613SVikram.Hegde@Sun.COM } 3997613SVikram.Hegde@Sun.COM 4007613SVikram.Hegde@Sun.COM if (ops->ilops_id == NULL) { 4017613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL ID field. " 4027613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4037613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4047613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4057613SVikram.Hegde@Sun.COM } 4067613SVikram.Hegde@Sun.COM 4077613SVikram.Hegde@Sun.COM if (ops->ilops_probe == NULL) { 4087613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL probe op. " 4097613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4107613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4117613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4127613SVikram.Hegde@Sun.COM } 4137613SVikram.Hegde@Sun.COM 4147613SVikram.Hegde@Sun.COM if (ops->ilops_dma_allochdl == NULL) { 4157613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL dma_allochdl op. " 4167613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4177613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4187613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4197613SVikram.Hegde@Sun.COM } 4207613SVikram.Hegde@Sun.COM 4217613SVikram.Hegde@Sun.COM if (ops->ilops_dma_freehdl == NULL) { 4227613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL dma_freehdl op. " 4237613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4247613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4257613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4267613SVikram.Hegde@Sun.COM } 4277613SVikram.Hegde@Sun.COM 4287613SVikram.Hegde@Sun.COM if (ops->ilops_dma_bindhdl == NULL) { 4297613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL dma_bindhdl op. " 4307613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4317613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4327613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4337613SVikram.Hegde@Sun.COM } 4347613SVikram.Hegde@Sun.COM 4357613SVikram.Hegde@Sun.COM if (ops->ilops_dma_sync == NULL) { 4367613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL dma_sync op. " 4377613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4387613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4397613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4407613SVikram.Hegde@Sun.COM } 4417613SVikram.Hegde@Sun.COM 4427613SVikram.Hegde@Sun.COM if (ops->ilops_dma_win == NULL) { 4437613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL dma_win op. " 4447613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4457613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4467613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4477613SVikram.Hegde@Sun.COM } 4487613SVikram.Hegde@Sun.COM 4497613SVikram.Hegde@Sun.COM /* Check for legacy ops */ 4507613SVikram.Hegde@Sun.COM if (ops->ilops_dma_map == NULL) { 4517613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL legacy dma_map op. " 4527613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4537613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4547613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4557613SVikram.Hegde@Sun.COM } 4567613SVikram.Hegde@Sun.COM 4577613SVikram.Hegde@Sun.COM if (ops->ilops_dma_mctl == NULL) { 4587613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL legacy dma_mctl op. " 4597613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4607613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4617613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4627613SVikram.Hegde@Sun.COM } 4637613SVikram.Hegde@Sun.COM 4647613SVikram.Hegde@Sun.COM unitp = kmem_zalloc(sizeof (iommulib_unit_t), KM_SLEEP); 4657613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 4667613SVikram.Hegde@Sun.COM if (iommulib_fini == 1) { 4677613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 4687613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: IOMMULIB unloading. Failing register.", 4697613SVikram.Hegde@Sun.COM f); 4707613SVikram.Hegde@Sun.COM kmem_free(unitp, sizeof (iommulib_unit_t)); 4717613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4727613SVikram.Hegde@Sun.COM } 4737613SVikram.Hegde@Sun.COM 4747613SVikram.Hegde@Sun.COM /* 4757613SVikram.Hegde@Sun.COM * fini/register race conditions have been handled. Now create the 4767613SVikram.Hegde@Sun.COM * IOMMU unit 4777613SVikram.Hegde@Sun.COM */ 4787613SVikram.Hegde@Sun.COM mutex_init(&unitp->ilu_lock, NULL, MUTEX_DEFAULT, NULL); 4797613SVikram.Hegde@Sun.COM 4807613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 4817613SVikram.Hegde@Sun.COM unitp->ilu_unitid = ++iommulib_unit_ids; 4827613SVikram.Hegde@Sun.COM unitp->ilu_ref = 0; 4837613SVikram.Hegde@Sun.COM ndi_hold_devi(dip); 4847613SVikram.Hegde@Sun.COM unitp->ilu_dip = dip; 4857613SVikram.Hegde@Sun.COM unitp->ilu_ops = ops; 4867613SVikram.Hegde@Sun.COM unitp->ilu_data = ops->ilops_data; 4877613SVikram.Hegde@Sun.COM 4887613SVikram.Hegde@Sun.COM unitp->ilu_next = iommulib_list; 489*8215SVikram.Hegde@Sun.COM iommulib_list = unitp; 4907613SVikram.Hegde@Sun.COM unitp->ilu_prev = NULL; 491*8215SVikram.Hegde@Sun.COM if (unitp->ilu_next) 492*8215SVikram.Hegde@Sun.COM unitp->ilu_next->ilu_prev = unitp; 4937613SVikram.Hegde@Sun.COM 4947613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 4957613SVikram.Hegde@Sun.COM 4967613SVikram.Hegde@Sun.COM iommulib_num_units++; 4977613SVikram.Hegde@Sun.COM 4987613SVikram.Hegde@Sun.COM *handle = unitp; 4997613SVikram.Hegde@Sun.COM 5007613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 5017613SVikram.Hegde@Sun.COM 502*8215SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "!%s: %s%d: Succesfully registered IOMMU unit " 5037613SVikram.Hegde@Sun.COM "from vendor=%s, ops=%p, data=%p, IOMMULIB unitid=%u", 5047613SVikram.Hegde@Sun.COM f, driver, instance, vendor, (void *)ops, (void *)unitp->ilu_data, 5057613SVikram.Hegde@Sun.COM unitp->ilu_unitid); 5067613SVikram.Hegde@Sun.COM 5077613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 5087613SVikram.Hegde@Sun.COM } 5097613SVikram.Hegde@Sun.COM 5107613SVikram.Hegde@Sun.COM int 5117613SVikram.Hegde@Sun.COM iommulib_iommu_unregister(iommulib_handle_t handle) 5127613SVikram.Hegde@Sun.COM { 5137613SVikram.Hegde@Sun.COM uint32_t unitid; 5147613SVikram.Hegde@Sun.COM dev_info_t *dip; 5157613SVikram.Hegde@Sun.COM int instance; 5167613SVikram.Hegde@Sun.COM const char *driver; 5177613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 5187613SVikram.Hegde@Sun.COM const char *f = "iommulib_unregister"; 5197613SVikram.Hegde@Sun.COM 5207613SVikram.Hegde@Sun.COM ASSERT(unitp); 5217613SVikram.Hegde@Sun.COM 5227613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 5237613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 5247613SVikram.Hegde@Sun.COM 5257613SVikram.Hegde@Sun.COM unitid = unitp->ilu_unitid; 5267613SVikram.Hegde@Sun.COM dip = unitp->ilu_dip; 5277613SVikram.Hegde@Sun.COM driver = ddi_driver_name(dip); 5287613SVikram.Hegde@Sun.COM instance = ddi_get_instance(dip); 5297613SVikram.Hegde@Sun.COM 5307613SVikram.Hegde@Sun.COM if (unitp->ilu_ref != 0) { 5317613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 5327613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 5337613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: IOMMULIB handle is busy. Cannot " 5347613SVikram.Hegde@Sun.COM "unregister IOMMULIB unitid %u", 5357613SVikram.Hegde@Sun.COM f, driver, instance, unitid); 5367613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 5377613SVikram.Hegde@Sun.COM } 5387613SVikram.Hegde@Sun.COM unitp->ilu_unitid = 0; 5397613SVikram.Hegde@Sun.COM ASSERT(unitp->ilu_ref == 0); 5407613SVikram.Hegde@Sun.COM 5417613SVikram.Hegde@Sun.COM if (unitp->ilu_prev == NULL) { 5427613SVikram.Hegde@Sun.COM iommulib_list = unitp->ilu_next; 5437613SVikram.Hegde@Sun.COM unitp->ilu_next->ilu_prev = NULL; 5447613SVikram.Hegde@Sun.COM } else { 5457613SVikram.Hegde@Sun.COM unitp->ilu_prev->ilu_next = unitp->ilu_next; 5467613SVikram.Hegde@Sun.COM unitp->ilu_next->ilu_prev = unitp->ilu_prev; 5477613SVikram.Hegde@Sun.COM } 5487613SVikram.Hegde@Sun.COM 5497613SVikram.Hegde@Sun.COM iommulib_num_units--; 5507613SVikram.Hegde@Sun.COM 5517613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 5527613SVikram.Hegde@Sun.COM 5537613SVikram.Hegde@Sun.COM mutex_destroy(&unitp->ilu_lock); 5547613SVikram.Hegde@Sun.COM kmem_free(unitp, sizeof (iommulib_unit_t)); 5557613SVikram.Hegde@Sun.COM 5567613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 5577613SVikram.Hegde@Sun.COM 5587613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: IOMMULIB handle (unitid=%u) successfully " 5597613SVikram.Hegde@Sun.COM "unregistered", f, driver, instance, unitid); 5607613SVikram.Hegde@Sun.COM 5617613SVikram.Hegde@Sun.COM ndi_rele_devi(dip); 5627613SVikram.Hegde@Sun.COM 5637613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 5647613SVikram.Hegde@Sun.COM } 5657613SVikram.Hegde@Sun.COM 5667613SVikram.Hegde@Sun.COM int 5677613SVikram.Hegde@Sun.COM iommulib_nex_open(dev_info_t *rdip, uint_t *errorp) 5687613SVikram.Hegde@Sun.COM { 5697613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 5707613SVikram.Hegde@Sun.COM int instance = ddi_get_instance(rdip); 5717613SVikram.Hegde@Sun.COM const char *driver = ddi_driver_name(rdip); 5727613SVikram.Hegde@Sun.COM const char *f = "iommulib_nex_open"; 5737613SVikram.Hegde@Sun.COM 5747613SVikram.Hegde@Sun.COM *errorp = 0; 575*8215SVikram.Hegde@Sun.COM 576*8215SVikram.Hegde@Sun.COM if (IOMMU_USED(rdip)) 577*8215SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 578*8215SVikram.Hegde@Sun.COM 579*8215SVikram.Hegde@Sun.COM ASSERT(DEVI(rdip)->devi_iommulib_handle == NULL); 5807613SVikram.Hegde@Sun.COM 5817613SVikram.Hegde@Sun.COM /* prevent use of IOMMU for AMD IOMMU's DMA */ 5827613SVikram.Hegde@Sun.COM if (strcmp(driver, "amd_iommu") == 0) { 5837613SVikram.Hegde@Sun.COM *errorp = ENOTSUP; 5847613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 5857613SVikram.Hegde@Sun.COM } 5867613SVikram.Hegde@Sun.COM 5877613SVikram.Hegde@Sun.COM /* 588*8215SVikram.Hegde@Sun.COM * Use the probe entry point to determine in a hardware specific 589*8215SVikram.Hegde@Sun.COM * manner whether this dip is controlled by an IOMMU. If yes, 590*8215SVikram.Hegde@Sun.COM * return the handle corresponding to the IOMMU unit. 5917613SVikram.Hegde@Sun.COM */ 5927613SVikram.Hegde@Sun.COM 5937613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 5947613SVikram.Hegde@Sun.COM for (unitp = iommulib_list; unitp; unitp = unitp->ilu_next) { 595*8215SVikram.Hegde@Sun.COM if (unitp->ilu_ops->ilops_probe(unitp, rdip) == DDI_SUCCESS) 5967613SVikram.Hegde@Sun.COM break; 5977613SVikram.Hegde@Sun.COM } 5987613SVikram.Hegde@Sun.COM 5997613SVikram.Hegde@Sun.COM if (unitp == NULL) { 6007613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 6017613SVikram.Hegde@Sun.COM if (iommulib_debug) { 6027717SVikram.Hegde@Sun.COM char *buf = kmem_alloc(MAXPATHLEN, KM_SLEEP); 6037613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: devinfo node (%p): is not " 6047613SVikram.Hegde@Sun.COM "controlled by an IOMMU: path=%s", f, driver, 6057613SVikram.Hegde@Sun.COM instance, (void *)rdip, ddi_pathname(rdip, buf)); 6067717SVikram.Hegde@Sun.COM kmem_free(buf, MAXPATHLEN); 6077613SVikram.Hegde@Sun.COM } 6087613SVikram.Hegde@Sun.COM *errorp = ENOTSUP; 6097613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 6107613SVikram.Hegde@Sun.COM } 6117613SVikram.Hegde@Sun.COM 6127613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 6137613SVikram.Hegde@Sun.COM unitp->ilu_ref++; 6147613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 6157613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 6167613SVikram.Hegde@Sun.COM 6177613SVikram.Hegde@Sun.COM DEVI(rdip)->devi_iommulib_handle = unitp; 6187613SVikram.Hegde@Sun.COM 6197613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 6207613SVikram.Hegde@Sun.COM } 6217613SVikram.Hegde@Sun.COM 6227613SVikram.Hegde@Sun.COM void 6237613SVikram.Hegde@Sun.COM iommulib_nex_close(dev_info_t *rdip) 6247613SVikram.Hegde@Sun.COM { 6257613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 6267613SVikram.Hegde@Sun.COM const char *driver; 6277613SVikram.Hegde@Sun.COM int instance; 6287613SVikram.Hegde@Sun.COM uint32_t unitid; 6297613SVikram.Hegde@Sun.COM const char *f = "iommulib_nex_close"; 6307613SVikram.Hegde@Sun.COM 6317613SVikram.Hegde@Sun.COM unitp = (iommulib_unit_t *)DEVI(rdip)->devi_iommulib_handle; 6327613SVikram.Hegde@Sun.COM if (unitp == NULL) 6337613SVikram.Hegde@Sun.COM return; 6347613SVikram.Hegde@Sun.COM 6357613SVikram.Hegde@Sun.COM DEVI(rdip)->devi_iommulib_handle = NULL; 6367613SVikram.Hegde@Sun.COM 6377613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 6387613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 6397613SVikram.Hegde@Sun.COM unitid = unitp->ilu_unitid; 6407613SVikram.Hegde@Sun.COM driver = ddi_driver_name(unitp->ilu_dip); 6417613SVikram.Hegde@Sun.COM instance = ddi_get_instance(unitp->ilu_dip); 6427613SVikram.Hegde@Sun.COM unitp->ilu_ref--; 6437613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 6447613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 6457613SVikram.Hegde@Sun.COM 6467613SVikram.Hegde@Sun.COM if (iommulib_debug) { 6477717SVikram.Hegde@Sun.COM char *buf = kmem_alloc(MAXPATHLEN, KM_SLEEP); 6487717SVikram.Hegde@Sun.COM (void) ddi_pathname(rdip, buf); 6497613SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "%s: %s%d: closing IOMMU for dip (%p), " 6507613SVikram.Hegde@Sun.COM "unitid=%u rdip path = %s", f, driver, instance, 6517613SVikram.Hegde@Sun.COM (void *)rdip, unitid, buf); 6527717SVikram.Hegde@Sun.COM kmem_free(buf, MAXPATHLEN); 6537613SVikram.Hegde@Sun.COM } 6547613SVikram.Hegde@Sun.COM } 6557613SVikram.Hegde@Sun.COM 6567613SVikram.Hegde@Sun.COM int 6577613SVikram.Hegde@Sun.COM iommulib_nexdma_allochdl(dev_info_t *dip, dev_info_t *rdip, 6587613SVikram.Hegde@Sun.COM ddi_dma_attr_t *attr, int (*waitfp)(caddr_t), 6597613SVikram.Hegde@Sun.COM caddr_t arg, ddi_dma_handle_t *dma_handlep) 6607613SVikram.Hegde@Sun.COM { 6617613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 6627613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 6637613SVikram.Hegde@Sun.COM 6647613SVikram.Hegde@Sun.COM ASSERT(unitp); 6657613SVikram.Hegde@Sun.COM 6667613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 6677613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_allochdl(handle, dip, rdip, 6687613SVikram.Hegde@Sun.COM attr, waitfp, arg, dma_handlep)); 6697613SVikram.Hegde@Sun.COM } 6707613SVikram.Hegde@Sun.COM 6717613SVikram.Hegde@Sun.COM int 6727613SVikram.Hegde@Sun.COM iommulib_nexdma_freehdl(dev_info_t *dip, dev_info_t *rdip, 6737613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle) 6747613SVikram.Hegde@Sun.COM { 6757613SVikram.Hegde@Sun.COM int error; 6767613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 6777613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 6787613SVikram.Hegde@Sun.COM 6797613SVikram.Hegde@Sun.COM ASSERT(unitp); 6807613SVikram.Hegde@Sun.COM 6817613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 6827613SVikram.Hegde@Sun.COM error = unitp->ilu_ops->ilops_dma_freehdl(handle, dip, 6837613SVikram.Hegde@Sun.COM rdip, dma_handle); 6847613SVikram.Hegde@Sun.COM 6857613SVikram.Hegde@Sun.COM return (error); 6867613SVikram.Hegde@Sun.COM } 6877613SVikram.Hegde@Sun.COM 6887613SVikram.Hegde@Sun.COM int 6897613SVikram.Hegde@Sun.COM iommulib_nexdma_bindhdl(dev_info_t *dip, dev_info_t *rdip, 6907613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle, struct ddi_dma_req *dmareq, 6917613SVikram.Hegde@Sun.COM ddi_dma_cookie_t *cookiep, uint_t *ccountp) 6927613SVikram.Hegde@Sun.COM { 6937613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 6947613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 6957613SVikram.Hegde@Sun.COM 6967613SVikram.Hegde@Sun.COM ASSERT(unitp); 6977613SVikram.Hegde@Sun.COM 6987613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 6997613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_bindhdl(handle, dip, rdip, dma_handle, 7007613SVikram.Hegde@Sun.COM dmareq, cookiep, ccountp)); 7017613SVikram.Hegde@Sun.COM } 7027613SVikram.Hegde@Sun.COM 7037613SVikram.Hegde@Sun.COM int 7047613SVikram.Hegde@Sun.COM iommulib_nexdma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, 7057613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle) 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_unbindhdl(handle, dip, rdip, 7147613SVikram.Hegde@Sun.COM dma_handle)); 7157613SVikram.Hegde@Sun.COM } 7167613SVikram.Hegde@Sun.COM 7177613SVikram.Hegde@Sun.COM int 7187613SVikram.Hegde@Sun.COM iommulib_nexdma_sync(dev_info_t *dip, dev_info_t *rdip, 7197613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle, off_t off, size_t len, 7207613SVikram.Hegde@Sun.COM uint_t cache_flags) 7217613SVikram.Hegde@Sun.COM { 7227613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 7237613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 7247613SVikram.Hegde@Sun.COM 7257613SVikram.Hegde@Sun.COM ASSERT(unitp); 7267613SVikram.Hegde@Sun.COM 7277613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 7287613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_sync(handle, dip, rdip, dma_handle, 7297613SVikram.Hegde@Sun.COM off, len, cache_flags)); 7307613SVikram.Hegde@Sun.COM } 7317613SVikram.Hegde@Sun.COM 7327613SVikram.Hegde@Sun.COM int 7337613SVikram.Hegde@Sun.COM iommulib_nexdma_win(dev_info_t *dip, dev_info_t *rdip, 7347613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle, uint_t win, off_t *offp, size_t *lenp, 7357613SVikram.Hegde@Sun.COM ddi_dma_cookie_t *cookiep, uint_t *ccountp) 7367613SVikram.Hegde@Sun.COM { 7377613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 7387613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 7397613SVikram.Hegde@Sun.COM 7407613SVikram.Hegde@Sun.COM ASSERT(unitp); 7417613SVikram.Hegde@Sun.COM 7427613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 7437613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_win(handle, dip, rdip, dma_handle, 7447613SVikram.Hegde@Sun.COM win, offp, lenp, cookiep, ccountp)); 7457613SVikram.Hegde@Sun.COM } 7467613SVikram.Hegde@Sun.COM 7477613SVikram.Hegde@Sun.COM /* Obsolete DMA routines */ 7487613SVikram.Hegde@Sun.COM 7497613SVikram.Hegde@Sun.COM int 7507613SVikram.Hegde@Sun.COM iommulib_nexdma_map(dev_info_t *dip, dev_info_t *rdip, 7517613SVikram.Hegde@Sun.COM struct ddi_dma_req *dmareq, ddi_dma_handle_t *dma_handle) 7527613SVikram.Hegde@Sun.COM { 7537613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 7547613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = handle; 7557613SVikram.Hegde@Sun.COM 7567613SVikram.Hegde@Sun.COM ASSERT(unitp); 7577613SVikram.Hegde@Sun.COM 7587613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 7597613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_map(handle, dip, rdip, dmareq, 7607613SVikram.Hegde@Sun.COM dma_handle)); 7617613SVikram.Hegde@Sun.COM } 7627613SVikram.Hegde@Sun.COM 7637613SVikram.Hegde@Sun.COM int 7647613SVikram.Hegde@Sun.COM iommulib_nexdma_mctl(dev_info_t *dip, dev_info_t *rdip, 7657613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle, enum ddi_dma_ctlops request, 7667613SVikram.Hegde@Sun.COM off_t *offp, size_t *lenp, caddr_t *objpp, uint_t cache_flags) 7677613SVikram.Hegde@Sun.COM { 7687613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 7697613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 7707613SVikram.Hegde@Sun.COM 7717613SVikram.Hegde@Sun.COM ASSERT(unitp); 7727613SVikram.Hegde@Sun.COM 7737613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 7747613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_mctl(handle, dip, rdip, dma_handle, 7757613SVikram.Hegde@Sun.COM request, offp, lenp, objpp, cache_flags)); 7767613SVikram.Hegde@Sun.COM } 7777613SVikram.Hegde@Sun.COM 7787613SVikram.Hegde@Sun.COM /* Utility routines invoked by IOMMU drivers */ 7797613SVikram.Hegde@Sun.COM int 7807613SVikram.Hegde@Sun.COM iommulib_iommu_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, 7817613SVikram.Hegde@Sun.COM ddi_dma_attr_t *attr, int (*waitfp)(caddr_t), caddr_t arg, 7827613SVikram.Hegde@Sun.COM ddi_dma_handle_t *handlep) 7837613SVikram.Hegde@Sun.COM { 7847613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 7857613SVikram.Hegde@Sun.COM if (nexops == NULL) 7867613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 7877613SVikram.Hegde@Sun.COM return (nexops->nops_dma_allochdl(dip, rdip, attr, waitfp, arg, 7887613SVikram.Hegde@Sun.COM handlep)); 7897613SVikram.Hegde@Sun.COM } 7907613SVikram.Hegde@Sun.COM 7917613SVikram.Hegde@Sun.COM int 7927613SVikram.Hegde@Sun.COM iommulib_iommu_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, 7937613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle) 7947613SVikram.Hegde@Sun.COM { 7957613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 7967613SVikram.Hegde@Sun.COM if (nexops == NULL) 7977613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 7987613SVikram.Hegde@Sun.COM return (nexops->nops_dma_freehdl(dip, rdip, handle)); 7997613SVikram.Hegde@Sun.COM } 8007613SVikram.Hegde@Sun.COM 8017613SVikram.Hegde@Sun.COM int 8027613SVikram.Hegde@Sun.COM iommulib_iommu_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip, 8037613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle, struct ddi_dma_req *dmareq, 8047613SVikram.Hegde@Sun.COM ddi_dma_cookie_t *cookiep, uint_t *ccountp) 8057613SVikram.Hegde@Sun.COM { 8067613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 8077613SVikram.Hegde@Sun.COM if (nexops == NULL) 8087613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 8097613SVikram.Hegde@Sun.COM return (nexops->nops_dma_bindhdl(dip, rdip, handle, dmareq, 8107613SVikram.Hegde@Sun.COM cookiep, ccountp)); 8117613SVikram.Hegde@Sun.COM } 8127613SVikram.Hegde@Sun.COM 8137613SVikram.Hegde@Sun.COM int 8147613SVikram.Hegde@Sun.COM iommulib_iommu_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, 8157613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle) 8167613SVikram.Hegde@Sun.COM { 8177613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 8187613SVikram.Hegde@Sun.COM if (nexops == NULL) 8197613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 8207613SVikram.Hegde@Sun.COM return (nexops->nops_dma_unbindhdl(dip, rdip, handle)); 8217613SVikram.Hegde@Sun.COM } 8227613SVikram.Hegde@Sun.COM 8237613SVikram.Hegde@Sun.COM void 8247613SVikram.Hegde@Sun.COM iommulib_iommu_dma_reset_cookies(dev_info_t *dip, ddi_dma_handle_t handle) 8257613SVikram.Hegde@Sun.COM { 8267613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 8277613SVikram.Hegde@Sun.COM nexops->nops_dma_reset_cookies(dip, handle); 8287613SVikram.Hegde@Sun.COM } 8297613SVikram.Hegde@Sun.COM 8307613SVikram.Hegde@Sun.COM int 8317613SVikram.Hegde@Sun.COM iommulib_iommu_dma_get_cookies(dev_info_t *dip, ddi_dma_handle_t handle, 832*8215SVikram.Hegde@Sun.COM ddi_dma_cookie_t **cookiepp, uint_t *ccountp) 833*8215SVikram.Hegde@Sun.COM { 834*8215SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 835*8215SVikram.Hegde@Sun.COM if (nexops == NULL) 836*8215SVikram.Hegde@Sun.COM return (DDI_FAILURE); 837*8215SVikram.Hegde@Sun.COM return (nexops->nops_dma_get_cookies(dip, handle, cookiepp, ccountp)); 838*8215SVikram.Hegde@Sun.COM } 839*8215SVikram.Hegde@Sun.COM 840*8215SVikram.Hegde@Sun.COM int 841*8215SVikram.Hegde@Sun.COM iommulib_iommu_dma_set_cookies(dev_info_t *dip, ddi_dma_handle_t handle, 842*8215SVikram.Hegde@Sun.COM ddi_dma_cookie_t *cookiep, uint_t ccount) 8437613SVikram.Hegde@Sun.COM { 8447613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 8457613SVikram.Hegde@Sun.COM if (nexops == NULL) 8467613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 847*8215SVikram.Hegde@Sun.COM return (nexops->nops_dma_set_cookies(dip, handle, cookiep, ccount)); 848*8215SVikram.Hegde@Sun.COM } 849*8215SVikram.Hegde@Sun.COM 850*8215SVikram.Hegde@Sun.COM int 851*8215SVikram.Hegde@Sun.COM iommulib_iommu_dma_clear_cookies(dev_info_t *dip, ddi_dma_handle_t handle) 852*8215SVikram.Hegde@Sun.COM { 853*8215SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 854*8215SVikram.Hegde@Sun.COM if (nexops == NULL) 855*8215SVikram.Hegde@Sun.COM return (DDI_FAILURE); 856*8215SVikram.Hegde@Sun.COM return (nexops->nops_dma_clear_cookies(dip, handle)); 857*8215SVikram.Hegde@Sun.COM } 858*8215SVikram.Hegde@Sun.COM 859*8215SVikram.Hegde@Sun.COM int 860*8215SVikram.Hegde@Sun.COM iommulib_iommu_dma_get_sleep_flags(dev_info_t *dip, ddi_dma_handle_t handle) 861*8215SVikram.Hegde@Sun.COM { 862*8215SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 863*8215SVikram.Hegde@Sun.COM if (nexops == NULL) 864*8215SVikram.Hegde@Sun.COM return (DDI_FAILURE); 865*8215SVikram.Hegde@Sun.COM return (nexops->nops_dma_get_sleep_flags(handle)); 8667613SVikram.Hegde@Sun.COM } 8677613SVikram.Hegde@Sun.COM 8687613SVikram.Hegde@Sun.COM int 8697613SVikram.Hegde@Sun.COM iommulib_iommu_dma_sync(dev_info_t *dip, dev_info_t *rdip, 8707613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle, off_t off, size_t len, uint_t cache_flags) 8717613SVikram.Hegde@Sun.COM { 8727613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 8737613SVikram.Hegde@Sun.COM if (nexops == NULL) 8747613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 8757613SVikram.Hegde@Sun.COM return (nexops->nops_dma_sync(dip, rdip, handle, off, len, 8767613SVikram.Hegde@Sun.COM cache_flags)); 8777613SVikram.Hegde@Sun.COM } 8787613SVikram.Hegde@Sun.COM 8797613SVikram.Hegde@Sun.COM int 8807613SVikram.Hegde@Sun.COM iommulib_iommu_dma_win(dev_info_t *dip, dev_info_t *rdip, 8817613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle, uint_t win, off_t *offp, size_t *lenp, 8827613SVikram.Hegde@Sun.COM ddi_dma_cookie_t *cookiep, uint_t *ccountp) 8837613SVikram.Hegde@Sun.COM { 8847613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 8857613SVikram.Hegde@Sun.COM if (nexops == NULL) 8867613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 8877613SVikram.Hegde@Sun.COM return (nexops->nops_dma_win(dip, rdip, handle, win, offp, lenp, 8887613SVikram.Hegde@Sun.COM cookiep, ccountp)); 8897613SVikram.Hegde@Sun.COM } 8907613SVikram.Hegde@Sun.COM 8917613SVikram.Hegde@Sun.COM int 8927613SVikram.Hegde@Sun.COM iommulib_iommu_dma_map(dev_info_t *dip, dev_info_t *rdip, 8937613SVikram.Hegde@Sun.COM struct ddi_dma_req *dmareq, ddi_dma_handle_t *handlep) 8947613SVikram.Hegde@Sun.COM { 8957613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 8967613SVikram.Hegde@Sun.COM if (nexops == NULL) 8977613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 8987613SVikram.Hegde@Sun.COM return (nexops->nops_dma_map(dip, rdip, dmareq, handlep)); 8997613SVikram.Hegde@Sun.COM } 9007613SVikram.Hegde@Sun.COM 9017613SVikram.Hegde@Sun.COM int 9027613SVikram.Hegde@Sun.COM iommulib_iommu_dma_mctl(dev_info_t *dip, dev_info_t *rdip, 9037613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle, enum ddi_dma_ctlops request, off_t *offp, 9047613SVikram.Hegde@Sun.COM size_t *lenp, caddr_t *objpp, uint_t cache_flags) 9057613SVikram.Hegde@Sun.COM { 9067613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 9077613SVikram.Hegde@Sun.COM if (nexops == NULL) 9087613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 9097613SVikram.Hegde@Sun.COM return (nexops->nops_dma_mctl(dip, rdip, handle, request, offp, lenp, 9107613SVikram.Hegde@Sun.COM objpp, cache_flags)); 9117613SVikram.Hegde@Sun.COM } 9127613SVikram.Hegde@Sun.COM 9137613SVikram.Hegde@Sun.COM int 9147613SVikram.Hegde@Sun.COM iommulib_iommu_getunitid(iommulib_handle_t handle, uint64_t *unitidp) 9157613SVikram.Hegde@Sun.COM { 9167613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 9177613SVikram.Hegde@Sun.COM uint64_t unitid; 9187613SVikram.Hegde@Sun.COM 9197613SVikram.Hegde@Sun.COM unitp = (iommulib_unit_t *)handle; 9207613SVikram.Hegde@Sun.COM 9217613SVikram.Hegde@Sun.COM ASSERT(unitp); 9227613SVikram.Hegde@Sun.COM ASSERT(unitidp); 9237613SVikram.Hegde@Sun.COM 9247613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 9257613SVikram.Hegde@Sun.COM unitid = unitp->ilu_unitid; 9267613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 9277613SVikram.Hegde@Sun.COM 9287613SVikram.Hegde@Sun.COM ASSERT(unitid > 0); 9297613SVikram.Hegde@Sun.COM *unitidp = (uint64_t)unitid; 9307613SVikram.Hegde@Sun.COM 9317613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 9327613SVikram.Hegde@Sun.COM } 9337613SVikram.Hegde@Sun.COM 9347613SVikram.Hegde@Sun.COM dev_info_t * 9357613SVikram.Hegde@Sun.COM iommulib_iommu_getdip(iommulib_handle_t handle) 9367613SVikram.Hegde@Sun.COM { 9377613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 9387613SVikram.Hegde@Sun.COM dev_info_t *dip; 9397613SVikram.Hegde@Sun.COM 9407613SVikram.Hegde@Sun.COM unitp = (iommulib_unit_t *)handle; 9417613SVikram.Hegde@Sun.COM 9427613SVikram.Hegde@Sun.COM ASSERT(unitp); 9437613SVikram.Hegde@Sun.COM 9447613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 9457613SVikram.Hegde@Sun.COM dip = unitp->ilu_dip; 9467613SVikram.Hegde@Sun.COM ASSERT(dip); 9477613SVikram.Hegde@Sun.COM ndi_hold_devi(dip); 9487613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 9497613SVikram.Hegde@Sun.COM 9507613SVikram.Hegde@Sun.COM return (dip); 9517613SVikram.Hegde@Sun.COM } 9527613SVikram.Hegde@Sun.COM 9537613SVikram.Hegde@Sun.COM iommulib_ops_t * 9547613SVikram.Hegde@Sun.COM iommulib_iommu_getops(iommulib_handle_t handle) 9557613SVikram.Hegde@Sun.COM { 9567613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 9577613SVikram.Hegde@Sun.COM iommulib_ops_t *ops; 9587613SVikram.Hegde@Sun.COM 9597613SVikram.Hegde@Sun.COM unitp = (iommulib_unit_t *)handle; 9607613SVikram.Hegde@Sun.COM 9617613SVikram.Hegde@Sun.COM ASSERT(unitp); 9627613SVikram.Hegde@Sun.COM 9637613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 9647613SVikram.Hegde@Sun.COM ops = unitp->ilu_ops; 9657613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 9667613SVikram.Hegde@Sun.COM 9677613SVikram.Hegde@Sun.COM ASSERT(ops); 9687613SVikram.Hegde@Sun.COM 9697613SVikram.Hegde@Sun.COM return (ops); 9707613SVikram.Hegde@Sun.COM } 9717613SVikram.Hegde@Sun.COM 9727613SVikram.Hegde@Sun.COM void * 9737613SVikram.Hegde@Sun.COM iommulib_iommu_getdata(iommulib_handle_t handle) 9747613SVikram.Hegde@Sun.COM { 9757613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 9767613SVikram.Hegde@Sun.COM void *data; 9777613SVikram.Hegde@Sun.COM 9787613SVikram.Hegde@Sun.COM unitp = (iommulib_unit_t *)handle; 9797613SVikram.Hegde@Sun.COM 9807613SVikram.Hegde@Sun.COM ASSERT(unitp); 9817613SVikram.Hegde@Sun.COM 9827613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 9837613SVikram.Hegde@Sun.COM data = unitp->ilu_data; 9847613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 9857613SVikram.Hegde@Sun.COM 9867613SVikram.Hegde@Sun.COM ASSERT(data); 9877613SVikram.Hegde@Sun.COM 9887613SVikram.Hegde@Sun.COM return (data); 9897613SVikram.Hegde@Sun.COM } 990