1*7613SVikram.Hegde@Sun.COM /* 2*7613SVikram.Hegde@Sun.COM * CDDL HEADER START 3*7613SVikram.Hegde@Sun.COM * 4*7613SVikram.Hegde@Sun.COM * The contents of this file are subject to the terms of the 5*7613SVikram.Hegde@Sun.COM * Common Development and Distribution License (the "License"). 6*7613SVikram.Hegde@Sun.COM * You may not use this file except in compliance with the License. 7*7613SVikram.Hegde@Sun.COM * 8*7613SVikram.Hegde@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*7613SVikram.Hegde@Sun.COM * or http://www.opensolaris.org/os/licensing. 10*7613SVikram.Hegde@Sun.COM * See the License for the specific language governing permissions 11*7613SVikram.Hegde@Sun.COM * and limitations under the License. 12*7613SVikram.Hegde@Sun.COM * 13*7613SVikram.Hegde@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 14*7613SVikram.Hegde@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*7613SVikram.Hegde@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 16*7613SVikram.Hegde@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 17*7613SVikram.Hegde@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 18*7613SVikram.Hegde@Sun.COM * 19*7613SVikram.Hegde@Sun.COM * CDDL HEADER END 20*7613SVikram.Hegde@Sun.COM */ 21*7613SVikram.Hegde@Sun.COM /* 22*7613SVikram.Hegde@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*7613SVikram.Hegde@Sun.COM * Use is subject to license terms. 24*7613SVikram.Hegde@Sun.COM */ 25*7613SVikram.Hegde@Sun.COM 26*7613SVikram.Hegde@Sun.COM #pragma ident "@(#)iommulib.c 1.6 08/09/07 SMI" 27*7613SVikram.Hegde@Sun.COM 28*7613SVikram.Hegde@Sun.COM #include <sys/sunddi.h> 29*7613SVikram.Hegde@Sun.COM #include <sys/sunndi.h> 30*7613SVikram.Hegde@Sun.COM #include <sys/errno.h> 31*7613SVikram.Hegde@Sun.COM #include <sys/modctl.h> 32*7613SVikram.Hegde@Sun.COM #include <sys/iommulib.h> 33*7613SVikram.Hegde@Sun.COM 34*7613SVikram.Hegde@Sun.COM /* ******** Type definitions private to this file ********************** */ 35*7613SVikram.Hegde@Sun.COM 36*7613SVikram.Hegde@Sun.COM /* 1 per IOMMU unit. There may be more than one per dip */ 37*7613SVikram.Hegde@Sun.COM typedef struct iommulib_unit { 38*7613SVikram.Hegde@Sun.COM kmutex_t ilu_lock; 39*7613SVikram.Hegde@Sun.COM uint64_t ilu_ref; 40*7613SVikram.Hegde@Sun.COM uint32_t ilu_unitid; 41*7613SVikram.Hegde@Sun.COM dev_info_t *ilu_dip; 42*7613SVikram.Hegde@Sun.COM iommulib_ops_t *ilu_ops; 43*7613SVikram.Hegde@Sun.COM void* ilu_data; 44*7613SVikram.Hegde@Sun.COM struct iommulib_unit *ilu_next; 45*7613SVikram.Hegde@Sun.COM struct iommulib_unit *ilu_prev; 46*7613SVikram.Hegde@Sun.COM } iommulib_unit_t; 47*7613SVikram.Hegde@Sun.COM 48*7613SVikram.Hegde@Sun.COM typedef struct iommulib_cache { 49*7613SVikram.Hegde@Sun.COM dev_info_t *cache_rdip; 50*7613SVikram.Hegde@Sun.COM iommulib_unit_t *cache_unit; 51*7613SVikram.Hegde@Sun.COM struct iommulib_cache *cache_next; 52*7613SVikram.Hegde@Sun.COM struct iommulib_cache *cache_prev; 53*7613SVikram.Hegde@Sun.COM } iommulib_cache_t; 54*7613SVikram.Hegde@Sun.COM 55*7613SVikram.Hegde@Sun.COM typedef struct iommulib_nex { 56*7613SVikram.Hegde@Sun.COM dev_info_t *nex_dip; 57*7613SVikram.Hegde@Sun.COM iommulib_nexops_t nex_ops; 58*7613SVikram.Hegde@Sun.COM struct iommulib_nex *nex_next; 59*7613SVikram.Hegde@Sun.COM struct iommulib_nex *nex_prev; 60*7613SVikram.Hegde@Sun.COM } iommulib_nex_t; 61*7613SVikram.Hegde@Sun.COM 62*7613SVikram.Hegde@Sun.COM /* ********* Function prototypes ********************* */ 63*7613SVikram.Hegde@Sun.COM static int lookup_cache(dev_info_t *rdip, iommulib_unit_t **unitpp); 64*7613SVikram.Hegde@Sun.COM static void insert_cache(dev_info_t *rdip, iommulib_unit_t *unitp); 65*7613SVikram.Hegde@Sun.COM 66*7613SVikram.Hegde@Sun.COM 67*7613SVikram.Hegde@Sun.COM /* ********* Globals ************************ */ 68*7613SVikram.Hegde@Sun.COM 69*7613SVikram.Hegde@Sun.COM /* IOMMU side: Following data protected by lock */ 70*7613SVikram.Hegde@Sun.COM static kmutex_t iommulib_lock; 71*7613SVikram.Hegde@Sun.COM static iommulib_unit_t *iommulib_list; 72*7613SVikram.Hegde@Sun.COM static uint64_t iommulib_unit_ids = 0; 73*7613SVikram.Hegde@Sun.COM static uint64_t iommulib_num_units = 0; 74*7613SVikram.Hegde@Sun.COM 75*7613SVikram.Hegde@Sun.COM /* rootnex side data */ 76*7613SVikram.Hegde@Sun.COM 77*7613SVikram.Hegde@Sun.COM static kmutex_t iommulib_nexus_lock; 78*7613SVikram.Hegde@Sun.COM static iommulib_nex_t *iommulib_nexus_list; 79*7613SVikram.Hegde@Sun.COM 80*7613SVikram.Hegde@Sun.COM #define IOMMULIB_CACHE_SIZE 256 81*7613SVikram.Hegde@Sun.COM static kmutex_t iommulib_cache_lock; 82*7613SVikram.Hegde@Sun.COM static iommulib_cache_t **iommulib_cache; 83*7613SVikram.Hegde@Sun.COM 84*7613SVikram.Hegde@Sun.COM /* tunable via /etc/system */ 85*7613SVikram.Hegde@Sun.COM static uint_t iommulib_cache_size = IOMMULIB_CACHE_SIZE; 86*7613SVikram.Hegde@Sun.COM 87*7613SVikram.Hegde@Sun.COM /* can be set atomically without lock */ 88*7613SVikram.Hegde@Sun.COM static volatile uint32_t iommulib_fini; 89*7613SVikram.Hegde@Sun.COM 90*7613SVikram.Hegde@Sun.COM /* debug flag */ 91*7613SVikram.Hegde@Sun.COM static int iommulib_debug; 92*7613SVikram.Hegde@Sun.COM 93*7613SVikram.Hegde@Sun.COM /* 94*7613SVikram.Hegde@Sun.COM * Module linkage information for the kernel. 95*7613SVikram.Hegde@Sun.COM */ 96*7613SVikram.Hegde@Sun.COM static struct modlmisc modlmisc = { 97*7613SVikram.Hegde@Sun.COM &mod_miscops, "IOMMU library module" 98*7613SVikram.Hegde@Sun.COM }; 99*7613SVikram.Hegde@Sun.COM 100*7613SVikram.Hegde@Sun.COM static struct modlinkage modlinkage = { 101*7613SVikram.Hegde@Sun.COM MODREV_1, (void *)&modlmisc, NULL 102*7613SVikram.Hegde@Sun.COM }; 103*7613SVikram.Hegde@Sun.COM 104*7613SVikram.Hegde@Sun.COM int 105*7613SVikram.Hegde@Sun.COM _init(void) 106*7613SVikram.Hegde@Sun.COM { 107*7613SVikram.Hegde@Sun.COM /* 108*7613SVikram.Hegde@Sun.COM * static mutexes automagically initialized 109*7613SVikram.Hegde@Sun.COM * by being allocated in zeroed memory 110*7613SVikram.Hegde@Sun.COM */ 111*7613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_cache_lock); 112*7613SVikram.Hegde@Sun.COM iommulib_cache = kmem_zalloc( 113*7613SVikram.Hegde@Sun.COM sizeof (iommulib_cache_t *) * iommulib_cache_size, KM_SLEEP); 114*7613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_cache_lock); 115*7613SVikram.Hegde@Sun.COM 116*7613SVikram.Hegde@Sun.COM return (mod_install(&modlinkage)); 117*7613SVikram.Hegde@Sun.COM } 118*7613SVikram.Hegde@Sun.COM 119*7613SVikram.Hegde@Sun.COM int 120*7613SVikram.Hegde@Sun.COM _fini(void) 121*7613SVikram.Hegde@Sun.COM { 122*7613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 123*7613SVikram.Hegde@Sun.COM if (iommulib_list != NULL || iommulib_nexus_list != NULL) { 124*7613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 125*7613SVikram.Hegde@Sun.COM return (EBUSY); 126*7613SVikram.Hegde@Sun.COM } 127*7613SVikram.Hegde@Sun.COM iommulib_fini = 1; 128*7613SVikram.Hegde@Sun.COM 129*7613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_cache_lock); 130*7613SVikram.Hegde@Sun.COM kmem_free(iommulib_cache, 131*7613SVikram.Hegde@Sun.COM sizeof (iommulib_cache_t *) * iommulib_cache_size); 132*7613SVikram.Hegde@Sun.COM iommulib_cache = NULL; 133*7613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_cache_lock); 134*7613SVikram.Hegde@Sun.COM 135*7613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 136*7613SVikram.Hegde@Sun.COM return (mod_remove(&modlinkage)); 137*7613SVikram.Hegde@Sun.COM } 138*7613SVikram.Hegde@Sun.COM 139*7613SVikram.Hegde@Sun.COM int 140*7613SVikram.Hegde@Sun.COM _info(struct modinfo *modinfop) 141*7613SVikram.Hegde@Sun.COM { 142*7613SVikram.Hegde@Sun.COM return (mod_info(&modlinkage, modinfop)); 143*7613SVikram.Hegde@Sun.COM } 144*7613SVikram.Hegde@Sun.COM 145*7613SVikram.Hegde@Sun.COM /* 146*7613SVikram.Hegde@Sun.COM * Routines with iommulib_iommu_* are invoked from the 147*7613SVikram.Hegde@Sun.COM * IOMMU driver. 148*7613SVikram.Hegde@Sun.COM * Routines with iommulib_nex* are invoked from the 149*7613SVikram.Hegde@Sun.COM * nexus driver (typically rootnex) 150*7613SVikram.Hegde@Sun.COM */ 151*7613SVikram.Hegde@Sun.COM 152*7613SVikram.Hegde@Sun.COM int 153*7613SVikram.Hegde@Sun.COM iommulib_nexus_register(dev_info_t *dip, iommulib_nexops_t *nexops, 154*7613SVikram.Hegde@Sun.COM iommulib_nexhandle_t *handle) 155*7613SVikram.Hegde@Sun.COM { 156*7613SVikram.Hegde@Sun.COM iommulib_nex_t *nexp; 157*7613SVikram.Hegde@Sun.COM int instance = ddi_get_instance(dip); 158*7613SVikram.Hegde@Sun.COM const char *driver = ddi_driver_name(dip); 159*7613SVikram.Hegde@Sun.COM dev_info_t *pdip = ddi_get_parent(dip); 160*7613SVikram.Hegde@Sun.COM const char *f = "iommulib_nexus_register"; 161*7613SVikram.Hegde@Sun.COM 162*7613SVikram.Hegde@Sun.COM ASSERT(nexops); 163*7613SVikram.Hegde@Sun.COM ASSERT(handle); 164*7613SVikram.Hegde@Sun.COM 165*7613SVikram.Hegde@Sun.COM *handle = NULL; 166*7613SVikram.Hegde@Sun.COM 167*7613SVikram.Hegde@Sun.COM /* 168*7613SVikram.Hegde@Sun.COM * Root node is never busy held 169*7613SVikram.Hegde@Sun.COM */ 170*7613SVikram.Hegde@Sun.COM if (dip != ddi_root_node() && (i_ddi_node_state(dip) < DS_PROBED || 171*7613SVikram.Hegde@Sun.COM !DEVI_BUSY_OWNED(pdip))) { 172*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: NEXUS devinfo node not in DS_PROBED " 173*7613SVikram.Hegde@Sun.COM "or busy held for nexops vector (%p). Failing registration", 174*7613SVikram.Hegde@Sun.COM f, (void *)nexops); 175*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 176*7613SVikram.Hegde@Sun.COM } 177*7613SVikram.Hegde@Sun.COM 178*7613SVikram.Hegde@Sun.COM if (nexops->nops_vers != IOMMU_NEXOPS_VERSION) { 179*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: Invalid IOMMULIB nexops version " 180*7613SVikram.Hegde@Sun.COM "in nexops vector (%p). Failing NEXUS registration", 181*7613SVikram.Hegde@Sun.COM f, driver, instance, (void *)nexops); 182*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 183*7613SVikram.Hegde@Sun.COM } 184*7613SVikram.Hegde@Sun.COM 185*7613SVikram.Hegde@Sun.COM ASSERT(nexops->nops_data == NULL); 186*7613SVikram.Hegde@Sun.COM 187*7613SVikram.Hegde@Sun.COM if (nexops->nops_id == NULL) { 188*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL ID field. " 189*7613SVikram.Hegde@Sun.COM "Failing registration for nexops vector: %p", 190*7613SVikram.Hegde@Sun.COM f, driver, instance, (void *)nexops); 191*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 192*7613SVikram.Hegde@Sun.COM } 193*7613SVikram.Hegde@Sun.COM 194*7613SVikram.Hegde@Sun.COM if (nexops->nops_dma_allochdl == NULL) { 195*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_allochdl op. " 196*7613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 197*7613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 198*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 199*7613SVikram.Hegde@Sun.COM } 200*7613SVikram.Hegde@Sun.COM 201*7613SVikram.Hegde@Sun.COM if (nexops->nops_dma_freehdl == NULL) { 202*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_freehdl op. " 203*7613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 204*7613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 205*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 206*7613SVikram.Hegde@Sun.COM } 207*7613SVikram.Hegde@Sun.COM 208*7613SVikram.Hegde@Sun.COM if (nexops->nops_dma_bindhdl == NULL) { 209*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_bindhdl op. " 210*7613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 211*7613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 212*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 213*7613SVikram.Hegde@Sun.COM } 214*7613SVikram.Hegde@Sun.COM 215*7613SVikram.Hegde@Sun.COM if (nexops->nops_dma_sync == NULL) { 216*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_sync op. " 217*7613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 218*7613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 219*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 220*7613SVikram.Hegde@Sun.COM } 221*7613SVikram.Hegde@Sun.COM 222*7613SVikram.Hegde@Sun.COM 223*7613SVikram.Hegde@Sun.COM if (nexops->nops_dma_reset_cookies == NULL) { 224*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_reset_cookies op. " 225*7613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 226*7613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 227*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 228*7613SVikram.Hegde@Sun.COM } 229*7613SVikram.Hegde@Sun.COM 230*7613SVikram.Hegde@Sun.COM if (nexops->nops_dma_get_cookies == NULL) { 231*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_get_cookies op. " 232*7613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 233*7613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 234*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 235*7613SVikram.Hegde@Sun.COM } 236*7613SVikram.Hegde@Sun.COM 237*7613SVikram.Hegde@Sun.COM if (nexops->nops_dma_win == NULL) { 238*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_win op. " 239*7613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 240*7613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 241*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 242*7613SVikram.Hegde@Sun.COM } 243*7613SVikram.Hegde@Sun.COM 244*7613SVikram.Hegde@Sun.COM /* Check for legacy ops */ 245*7613SVikram.Hegde@Sun.COM if (nexops->nops_dma_map == NULL) { 246*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL legacy nops_dma_map op. " 247*7613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 248*7613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 249*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 250*7613SVikram.Hegde@Sun.COM } 251*7613SVikram.Hegde@Sun.COM 252*7613SVikram.Hegde@Sun.COM if (nexops->nops_dma_mctl == NULL) { 253*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL legacy nops_dma_mctl op. " 254*7613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 255*7613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 256*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 257*7613SVikram.Hegde@Sun.COM } 258*7613SVikram.Hegde@Sun.COM 259*7613SVikram.Hegde@Sun.COM nexp = kmem_zalloc(sizeof (iommulib_nex_t), KM_SLEEP); 260*7613SVikram.Hegde@Sun.COM 261*7613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 262*7613SVikram.Hegde@Sun.COM if (iommulib_fini == 1) { 263*7613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 264*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: IOMMULIB unloading. " 265*7613SVikram.Hegde@Sun.COM "Failing NEXUS register.", f); 266*7613SVikram.Hegde@Sun.COM kmem_free(nexp, sizeof (iommulib_nex_t)); 267*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 268*7613SVikram.Hegde@Sun.COM } 269*7613SVikram.Hegde@Sun.COM 270*7613SVikram.Hegde@Sun.COM /* 271*7613SVikram.Hegde@Sun.COM * fini/register race conditions have been handled. Now create the 272*7613SVikram.Hegde@Sun.COM * nexus struct 273*7613SVikram.Hegde@Sun.COM */ 274*7613SVikram.Hegde@Sun.COM ndi_hold_devi(dip); 275*7613SVikram.Hegde@Sun.COM nexp->nex_dip = dip; 276*7613SVikram.Hegde@Sun.COM nexp->nex_ops = *nexops; 277*7613SVikram.Hegde@Sun.COM 278*7613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_nexus_lock); 279*7613SVikram.Hegde@Sun.COM nexp->nex_next = iommulib_nexus_list; 280*7613SVikram.Hegde@Sun.COM iommulib_nexus_list = nexp; 281*7613SVikram.Hegde@Sun.COM nexp->nex_prev = NULL; 282*7613SVikram.Hegde@Sun.COM 283*7613SVikram.Hegde@Sun.COM if (nexp->nex_next != NULL) 284*7613SVikram.Hegde@Sun.COM nexp->nex_next->nex_prev = nexp; 285*7613SVikram.Hegde@Sun.COM 286*7613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_nexus_lock); 287*7613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 288*7613SVikram.Hegde@Sun.COM 289*7613SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "!%s: %s%d: Succesfully registered NEXUS %s " 290*7613SVikram.Hegde@Sun.COM "nexops=%p", f, driver, instance, ddi_node_name(dip), 291*7613SVikram.Hegde@Sun.COM (void *)nexops); 292*7613SVikram.Hegde@Sun.COM 293*7613SVikram.Hegde@Sun.COM *handle = nexp; 294*7613SVikram.Hegde@Sun.COM 295*7613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 296*7613SVikram.Hegde@Sun.COM } 297*7613SVikram.Hegde@Sun.COM 298*7613SVikram.Hegde@Sun.COM int 299*7613SVikram.Hegde@Sun.COM iommulib_nexus_unregister(iommulib_nexhandle_t handle) 300*7613SVikram.Hegde@Sun.COM { 301*7613SVikram.Hegde@Sun.COM dev_info_t *dip; 302*7613SVikram.Hegde@Sun.COM int instance; 303*7613SVikram.Hegde@Sun.COM const char *driver; 304*7613SVikram.Hegde@Sun.COM iommulib_nex_t *nexp = (iommulib_nex_t *)handle; 305*7613SVikram.Hegde@Sun.COM const char *f = "iommulib_nexus_unregister"; 306*7613SVikram.Hegde@Sun.COM 307*7613SVikram.Hegde@Sun.COM ASSERT(nexp); 308*7613SVikram.Hegde@Sun.COM 309*7613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_nexus_lock); 310*7613SVikram.Hegde@Sun.COM 311*7613SVikram.Hegde@Sun.COM dip = nexp->nex_dip; 312*7613SVikram.Hegde@Sun.COM driver = ddi_driver_name(dip); 313*7613SVikram.Hegde@Sun.COM instance = ddi_get_instance(dip); 314*7613SVikram.Hegde@Sun.COM 315*7613SVikram.Hegde@Sun.COM /* A future enhancement would be to add ref-counts */ 316*7613SVikram.Hegde@Sun.COM 317*7613SVikram.Hegde@Sun.COM if (nexp->nex_prev == NULL) { 318*7613SVikram.Hegde@Sun.COM iommulib_nexus_list = nexp->nex_next; 319*7613SVikram.Hegde@Sun.COM } else { 320*7613SVikram.Hegde@Sun.COM nexp->nex_prev->nex_next = nexp->nex_next; 321*7613SVikram.Hegde@Sun.COM } 322*7613SVikram.Hegde@Sun.COM 323*7613SVikram.Hegde@Sun.COM if (nexp->nex_next != NULL) 324*7613SVikram.Hegde@Sun.COM nexp->nex_next->nex_prev = nexp->nex_prev; 325*7613SVikram.Hegde@Sun.COM 326*7613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_nexus_lock); 327*7613SVikram.Hegde@Sun.COM 328*7613SVikram.Hegde@Sun.COM kmem_free(nexp, sizeof (iommulib_nex_t)); 329*7613SVikram.Hegde@Sun.COM 330*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NEXUS (%s) handle successfully " 331*7613SVikram.Hegde@Sun.COM "unregistered from IOMMULIB", f, driver, instance, 332*7613SVikram.Hegde@Sun.COM ddi_node_name(dip)); 333*7613SVikram.Hegde@Sun.COM 334*7613SVikram.Hegde@Sun.COM ndi_rele_devi(dip); 335*7613SVikram.Hegde@Sun.COM 336*7613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 337*7613SVikram.Hegde@Sun.COM } 338*7613SVikram.Hegde@Sun.COM 339*7613SVikram.Hegde@Sun.COM static iommulib_nexops_t * 340*7613SVikram.Hegde@Sun.COM lookup_nexops(dev_info_t *dip) 341*7613SVikram.Hegde@Sun.COM { 342*7613SVikram.Hegde@Sun.COM iommulib_nex_t *nexp; 343*7613SVikram.Hegde@Sun.COM 344*7613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_nexus_lock); 345*7613SVikram.Hegde@Sun.COM nexp = iommulib_nexus_list; 346*7613SVikram.Hegde@Sun.COM while (nexp) { 347*7613SVikram.Hegde@Sun.COM if (nexp->nex_dip == dip) 348*7613SVikram.Hegde@Sun.COM break; 349*7613SVikram.Hegde@Sun.COM nexp = nexp->nex_next; 350*7613SVikram.Hegde@Sun.COM } 351*7613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_nexus_lock); 352*7613SVikram.Hegde@Sun.COM 353*7613SVikram.Hegde@Sun.COM return (nexp ? &nexp->nex_ops : NULL); 354*7613SVikram.Hegde@Sun.COM } 355*7613SVikram.Hegde@Sun.COM 356*7613SVikram.Hegde@Sun.COM int 357*7613SVikram.Hegde@Sun.COM iommulib_iommu_register(dev_info_t *dip, iommulib_ops_t *ops, 358*7613SVikram.Hegde@Sun.COM iommulib_handle_t *handle) 359*7613SVikram.Hegde@Sun.COM { 360*7613SVikram.Hegde@Sun.COM const char *vendor; 361*7613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 362*7613SVikram.Hegde@Sun.COM int instance = ddi_get_instance(dip); 363*7613SVikram.Hegde@Sun.COM const char *driver = ddi_driver_name(dip); 364*7613SVikram.Hegde@Sun.COM dev_info_t *pdip = ddi_get_parent(dip); 365*7613SVikram.Hegde@Sun.COM const char *f = "iommulib_register"; 366*7613SVikram.Hegde@Sun.COM 367*7613SVikram.Hegde@Sun.COM ASSERT(ops); 368*7613SVikram.Hegde@Sun.COM ASSERT(handle); 369*7613SVikram.Hegde@Sun.COM 370*7613SVikram.Hegde@Sun.COM if (i_ddi_node_state(dip) < DS_PROBED || !DEVI_BUSY_OWNED(pdip)) { 371*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: devinfo node not in DS_PROBED or " 372*7613SVikram.Hegde@Sun.COM "busy held for ops vector (%p). Failing registration", 373*7613SVikram.Hegde@Sun.COM f, (void *)ops); 374*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 375*7613SVikram.Hegde@Sun.COM } 376*7613SVikram.Hegde@Sun.COM 377*7613SVikram.Hegde@Sun.COM 378*7613SVikram.Hegde@Sun.COM if (ops->ilops_vers != IOMMU_OPS_VERSION) { 379*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: Invalid IOMMULIB ops version " 380*7613SVikram.Hegde@Sun.COM "in ops vector (%p). Failing registration", f, driver, 381*7613SVikram.Hegde@Sun.COM instance, (void *)ops); 382*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 383*7613SVikram.Hegde@Sun.COM } 384*7613SVikram.Hegde@Sun.COM 385*7613SVikram.Hegde@Sun.COM switch (ops->ilops_vendor) { 386*7613SVikram.Hegde@Sun.COM case AMD_IOMMU: 387*7613SVikram.Hegde@Sun.COM vendor = "AMD"; 388*7613SVikram.Hegde@Sun.COM break; 389*7613SVikram.Hegde@Sun.COM case INTEL_IOMMU: 390*7613SVikram.Hegde@Sun.COM vendor = "Intel"; 391*7613SVikram.Hegde@Sun.COM break; 392*7613SVikram.Hegde@Sun.COM case INVALID_VENDOR: 393*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: vendor field (%x) not initialized. " 394*7613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 395*7613SVikram.Hegde@Sun.COM driver, instance, ops->ilops_vendor, (void *)ops); 396*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 397*7613SVikram.Hegde@Sun.COM default: 398*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: Invalid vendor field (%x). " 399*7613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 400*7613SVikram.Hegde@Sun.COM driver, instance, ops->ilops_vendor, (void *)ops); 401*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 402*7613SVikram.Hegde@Sun.COM } 403*7613SVikram.Hegde@Sun.COM 404*7613SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "%s: %s%d: Detected IOMMU registration from vendor %s", 405*7613SVikram.Hegde@Sun.COM f, driver, instance, vendor); 406*7613SVikram.Hegde@Sun.COM 407*7613SVikram.Hegde@Sun.COM if (ops->ilops_data == NULL) { 408*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL IOMMU data field. " 409*7613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 410*7613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 411*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 412*7613SVikram.Hegde@Sun.COM } 413*7613SVikram.Hegde@Sun.COM 414*7613SVikram.Hegde@Sun.COM if (ops->ilops_id == NULL) { 415*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL ID field. " 416*7613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 417*7613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 418*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 419*7613SVikram.Hegde@Sun.COM } 420*7613SVikram.Hegde@Sun.COM 421*7613SVikram.Hegde@Sun.COM if (ops->ilops_probe == NULL) { 422*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL probe op. " 423*7613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 424*7613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 425*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 426*7613SVikram.Hegde@Sun.COM } 427*7613SVikram.Hegde@Sun.COM 428*7613SVikram.Hegde@Sun.COM if (ops->ilops_dma_allochdl == NULL) { 429*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL dma_allochdl op. " 430*7613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 431*7613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 432*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 433*7613SVikram.Hegde@Sun.COM } 434*7613SVikram.Hegde@Sun.COM 435*7613SVikram.Hegde@Sun.COM if (ops->ilops_dma_freehdl == NULL) { 436*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL dma_freehdl op. " 437*7613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 438*7613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 439*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 440*7613SVikram.Hegde@Sun.COM } 441*7613SVikram.Hegde@Sun.COM 442*7613SVikram.Hegde@Sun.COM if (ops->ilops_dma_bindhdl == NULL) { 443*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL dma_bindhdl op. " 444*7613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 445*7613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 446*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 447*7613SVikram.Hegde@Sun.COM } 448*7613SVikram.Hegde@Sun.COM 449*7613SVikram.Hegde@Sun.COM if (ops->ilops_dma_sync == NULL) { 450*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL dma_sync op. " 451*7613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 452*7613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 453*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 454*7613SVikram.Hegde@Sun.COM } 455*7613SVikram.Hegde@Sun.COM 456*7613SVikram.Hegde@Sun.COM if (ops->ilops_dma_win == NULL) { 457*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL dma_win op. " 458*7613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 459*7613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 460*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 461*7613SVikram.Hegde@Sun.COM } 462*7613SVikram.Hegde@Sun.COM 463*7613SVikram.Hegde@Sun.COM /* Check for legacy ops */ 464*7613SVikram.Hegde@Sun.COM if (ops->ilops_dma_map == NULL) { 465*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL legacy dma_map op. " 466*7613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 467*7613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 468*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 469*7613SVikram.Hegde@Sun.COM } 470*7613SVikram.Hegde@Sun.COM 471*7613SVikram.Hegde@Sun.COM if (ops->ilops_dma_mctl == NULL) { 472*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL legacy dma_mctl op. " 473*7613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 474*7613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 475*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 476*7613SVikram.Hegde@Sun.COM } 477*7613SVikram.Hegde@Sun.COM 478*7613SVikram.Hegde@Sun.COM unitp = kmem_zalloc(sizeof (iommulib_unit_t), KM_SLEEP); 479*7613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 480*7613SVikram.Hegde@Sun.COM if (iommulib_fini == 1) { 481*7613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 482*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: IOMMULIB unloading. Failing register.", 483*7613SVikram.Hegde@Sun.COM f); 484*7613SVikram.Hegde@Sun.COM kmem_free(unitp, sizeof (iommulib_unit_t)); 485*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 486*7613SVikram.Hegde@Sun.COM } 487*7613SVikram.Hegde@Sun.COM 488*7613SVikram.Hegde@Sun.COM /* 489*7613SVikram.Hegde@Sun.COM * fini/register race conditions have been handled. Now create the 490*7613SVikram.Hegde@Sun.COM * IOMMU unit 491*7613SVikram.Hegde@Sun.COM */ 492*7613SVikram.Hegde@Sun.COM mutex_init(&unitp->ilu_lock, NULL, MUTEX_DEFAULT, NULL); 493*7613SVikram.Hegde@Sun.COM 494*7613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 495*7613SVikram.Hegde@Sun.COM unitp->ilu_unitid = ++iommulib_unit_ids; 496*7613SVikram.Hegde@Sun.COM unitp->ilu_ref = 0; 497*7613SVikram.Hegde@Sun.COM ndi_hold_devi(dip); 498*7613SVikram.Hegde@Sun.COM unitp->ilu_dip = dip; 499*7613SVikram.Hegde@Sun.COM unitp->ilu_ops = ops; 500*7613SVikram.Hegde@Sun.COM unitp->ilu_data = ops->ilops_data; 501*7613SVikram.Hegde@Sun.COM 502*7613SVikram.Hegde@Sun.COM unitp->ilu_next = iommulib_list; 503*7613SVikram.Hegde@Sun.COM unitp->ilu_prev = NULL; 504*7613SVikram.Hegde@Sun.COM iommulib_list->ilu_prev = unitp; 505*7613SVikram.Hegde@Sun.COM iommulib_list = unitp; 506*7613SVikram.Hegde@Sun.COM 507*7613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 508*7613SVikram.Hegde@Sun.COM 509*7613SVikram.Hegde@Sun.COM iommulib_num_units++; 510*7613SVikram.Hegde@Sun.COM 511*7613SVikram.Hegde@Sun.COM *handle = unitp; 512*7613SVikram.Hegde@Sun.COM 513*7613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 514*7613SVikram.Hegde@Sun.COM 515*7613SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "%s: %s%d: Succesfully registered IOMMU unit " 516*7613SVikram.Hegde@Sun.COM "from vendor=%s, ops=%p, data=%p, IOMMULIB unitid=%u", 517*7613SVikram.Hegde@Sun.COM f, driver, instance, vendor, (void *)ops, (void *)unitp->ilu_data, 518*7613SVikram.Hegde@Sun.COM unitp->ilu_unitid); 519*7613SVikram.Hegde@Sun.COM 520*7613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 521*7613SVikram.Hegde@Sun.COM } 522*7613SVikram.Hegde@Sun.COM 523*7613SVikram.Hegde@Sun.COM int 524*7613SVikram.Hegde@Sun.COM iommulib_iommu_unregister(iommulib_handle_t handle) 525*7613SVikram.Hegde@Sun.COM { 526*7613SVikram.Hegde@Sun.COM uint32_t unitid; 527*7613SVikram.Hegde@Sun.COM dev_info_t *dip; 528*7613SVikram.Hegde@Sun.COM int instance; 529*7613SVikram.Hegde@Sun.COM const char *driver; 530*7613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 531*7613SVikram.Hegde@Sun.COM const char *f = "iommulib_unregister"; 532*7613SVikram.Hegde@Sun.COM 533*7613SVikram.Hegde@Sun.COM ASSERT(unitp); 534*7613SVikram.Hegde@Sun.COM 535*7613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 536*7613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 537*7613SVikram.Hegde@Sun.COM 538*7613SVikram.Hegde@Sun.COM unitid = unitp->ilu_unitid; 539*7613SVikram.Hegde@Sun.COM dip = unitp->ilu_dip; 540*7613SVikram.Hegde@Sun.COM driver = ddi_driver_name(dip); 541*7613SVikram.Hegde@Sun.COM instance = ddi_get_instance(dip); 542*7613SVikram.Hegde@Sun.COM 543*7613SVikram.Hegde@Sun.COM if (unitp->ilu_ref != 0) { 544*7613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 545*7613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 546*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: IOMMULIB handle is busy. Cannot " 547*7613SVikram.Hegde@Sun.COM "unregister IOMMULIB unitid %u", 548*7613SVikram.Hegde@Sun.COM f, driver, instance, unitid); 549*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 550*7613SVikram.Hegde@Sun.COM } 551*7613SVikram.Hegde@Sun.COM unitp->ilu_unitid = 0; 552*7613SVikram.Hegde@Sun.COM ASSERT(unitp->ilu_ref == 0); 553*7613SVikram.Hegde@Sun.COM 554*7613SVikram.Hegde@Sun.COM if (unitp->ilu_prev == NULL) { 555*7613SVikram.Hegde@Sun.COM iommulib_list = unitp->ilu_next; 556*7613SVikram.Hegde@Sun.COM unitp->ilu_next->ilu_prev = NULL; 557*7613SVikram.Hegde@Sun.COM } else { 558*7613SVikram.Hegde@Sun.COM unitp->ilu_prev->ilu_next = unitp->ilu_next; 559*7613SVikram.Hegde@Sun.COM unitp->ilu_next->ilu_prev = unitp->ilu_prev; 560*7613SVikram.Hegde@Sun.COM } 561*7613SVikram.Hegde@Sun.COM 562*7613SVikram.Hegde@Sun.COM iommulib_num_units--; 563*7613SVikram.Hegde@Sun.COM 564*7613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 565*7613SVikram.Hegde@Sun.COM 566*7613SVikram.Hegde@Sun.COM mutex_destroy(&unitp->ilu_lock); 567*7613SVikram.Hegde@Sun.COM kmem_free(unitp, sizeof (iommulib_unit_t)); 568*7613SVikram.Hegde@Sun.COM 569*7613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 570*7613SVikram.Hegde@Sun.COM 571*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: IOMMULIB handle (unitid=%u) successfully " 572*7613SVikram.Hegde@Sun.COM "unregistered", f, driver, instance, unitid); 573*7613SVikram.Hegde@Sun.COM 574*7613SVikram.Hegde@Sun.COM ndi_rele_devi(dip); 575*7613SVikram.Hegde@Sun.COM 576*7613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 577*7613SVikram.Hegde@Sun.COM } 578*7613SVikram.Hegde@Sun.COM 579*7613SVikram.Hegde@Sun.COM int 580*7613SVikram.Hegde@Sun.COM iommulib_nex_open(dev_info_t *rdip, uint_t *errorp) 581*7613SVikram.Hegde@Sun.COM { 582*7613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 583*7613SVikram.Hegde@Sun.COM int instance = ddi_get_instance(rdip); 584*7613SVikram.Hegde@Sun.COM const char *driver = ddi_driver_name(rdip); 585*7613SVikram.Hegde@Sun.COM const char *f = "iommulib_nex_open"; 586*7613SVikram.Hegde@Sun.COM 587*7613SVikram.Hegde@Sun.COM *errorp = 0; 588*7613SVikram.Hegde@Sun.COM DEVI(rdip)->devi_iommulib_handle = NULL; 589*7613SVikram.Hegde@Sun.COM 590*7613SVikram.Hegde@Sun.COM /* prevent use of IOMMU for AMD IOMMU's DMA */ 591*7613SVikram.Hegde@Sun.COM if (strcmp(driver, "amd_iommu") == 0) { 592*7613SVikram.Hegde@Sun.COM *errorp = ENOTSUP; 593*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 594*7613SVikram.Hegde@Sun.COM } 595*7613SVikram.Hegde@Sun.COM 596*7613SVikram.Hegde@Sun.COM if (lookup_cache(rdip, &unitp) == DDI_SUCCESS) { 597*7613SVikram.Hegde@Sun.COM DEVI(rdip)->devi_iommulib_handle = 598*7613SVikram.Hegde@Sun.COM (iommulib_handle_t)unitp; 599*7613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 600*7613SVikram.Hegde@Sun.COM } 601*7613SVikram.Hegde@Sun.COM 602*7613SVikram.Hegde@Sun.COM 603*7613SVikram.Hegde@Sun.COM /* 604*7613SVikram.Hegde@Sun.COM * Ok this dip is not in the cache. Use the probe entry point 605*7613SVikram.Hegde@Sun.COM * to determine in a hardware specific manner whether this 606*7613SVikram.Hegde@Sun.COM * dip is controlled by an IOMMU. If yes, insert it into the 607*7613SVikram.Hegde@Sun.COM * cache and return the handle corresponding to the IOMMU unit. 608*7613SVikram.Hegde@Sun.COM */ 609*7613SVikram.Hegde@Sun.COM 610*7613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 611*7613SVikram.Hegde@Sun.COM for (unitp = iommulib_list; unitp; unitp = unitp->ilu_next) { 612*7613SVikram.Hegde@Sun.COM if (unitp->ilu_ops->ilops_probe(rdip) == DDI_SUCCESS) 613*7613SVikram.Hegde@Sun.COM break; 614*7613SVikram.Hegde@Sun.COM } 615*7613SVikram.Hegde@Sun.COM 616*7613SVikram.Hegde@Sun.COM if (unitp == NULL) { 617*7613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 618*7613SVikram.Hegde@Sun.COM if (iommulib_debug) { 619*7613SVikram.Hegde@Sun.COM char buf[MAXPATHLEN]; 620*7613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: devinfo node (%p): is not " 621*7613SVikram.Hegde@Sun.COM "controlled by an IOMMU: path=%s", f, driver, 622*7613SVikram.Hegde@Sun.COM instance, (void *)rdip, ddi_pathname(rdip, buf)); 623*7613SVikram.Hegde@Sun.COM } 624*7613SVikram.Hegde@Sun.COM *errorp = ENOTSUP; 625*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 626*7613SVikram.Hegde@Sun.COM } 627*7613SVikram.Hegde@Sun.COM 628*7613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 629*7613SVikram.Hegde@Sun.COM unitp->ilu_ref++; 630*7613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 631*7613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 632*7613SVikram.Hegde@Sun.COM 633*7613SVikram.Hegde@Sun.COM insert_cache(rdip, unitp); 634*7613SVikram.Hegde@Sun.COM 635*7613SVikram.Hegde@Sun.COM DEVI(rdip)->devi_iommulib_handle = unitp; 636*7613SVikram.Hegde@Sun.COM 637*7613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 638*7613SVikram.Hegde@Sun.COM } 639*7613SVikram.Hegde@Sun.COM 640*7613SVikram.Hegde@Sun.COM void 641*7613SVikram.Hegde@Sun.COM iommulib_nex_close(dev_info_t *rdip) 642*7613SVikram.Hegde@Sun.COM { 643*7613SVikram.Hegde@Sun.COM char buf[MAXPATHLEN]; 644*7613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 645*7613SVikram.Hegde@Sun.COM const char *driver; 646*7613SVikram.Hegde@Sun.COM int instance; 647*7613SVikram.Hegde@Sun.COM uint32_t unitid; 648*7613SVikram.Hegde@Sun.COM const char *f = "iommulib_nex_close"; 649*7613SVikram.Hegde@Sun.COM 650*7613SVikram.Hegde@Sun.COM unitp = (iommulib_unit_t *)DEVI(rdip)->devi_iommulib_handle; 651*7613SVikram.Hegde@Sun.COM if (unitp == NULL) 652*7613SVikram.Hegde@Sun.COM return; 653*7613SVikram.Hegde@Sun.COM 654*7613SVikram.Hegde@Sun.COM DEVI(rdip)->devi_iommulib_handle = NULL; 655*7613SVikram.Hegde@Sun.COM 656*7613SVikram.Hegde@Sun.COM /* 657*7613SVikram.Hegde@Sun.COM * Assume we don't support DR of IOMMUs. The mapping of 658*7613SVikram.Hegde@Sun.COM * dips to IOMMU units should not change. Let the mapping 659*7613SVikram.Hegde@Sun.COM * persist in the cache. 660*7613SVikram.Hegde@Sun.COM */ 661*7613SVikram.Hegde@Sun.COM 662*7613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 663*7613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 664*7613SVikram.Hegde@Sun.COM unitid = unitp->ilu_unitid; 665*7613SVikram.Hegde@Sun.COM driver = ddi_driver_name(unitp->ilu_dip); 666*7613SVikram.Hegde@Sun.COM instance = ddi_get_instance(unitp->ilu_dip); 667*7613SVikram.Hegde@Sun.COM (void) ddi_pathname(rdip, buf); 668*7613SVikram.Hegde@Sun.COM unitp->ilu_ref--; 669*7613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 670*7613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 671*7613SVikram.Hegde@Sun.COM 672*7613SVikram.Hegde@Sun.COM if (iommulib_debug) { 673*7613SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "%s: %s%d: closing IOMMU for dip (%p), " 674*7613SVikram.Hegde@Sun.COM "unitid=%u rdip path = %s", f, driver, instance, 675*7613SVikram.Hegde@Sun.COM (void *)rdip, unitid, buf); 676*7613SVikram.Hegde@Sun.COM } 677*7613SVikram.Hegde@Sun.COM } 678*7613SVikram.Hegde@Sun.COM 679*7613SVikram.Hegde@Sun.COM int 680*7613SVikram.Hegde@Sun.COM iommulib_nexdma_allochdl(dev_info_t *dip, dev_info_t *rdip, 681*7613SVikram.Hegde@Sun.COM ddi_dma_attr_t *attr, int (*waitfp)(caddr_t), 682*7613SVikram.Hegde@Sun.COM caddr_t arg, ddi_dma_handle_t *dma_handlep) 683*7613SVikram.Hegde@Sun.COM { 684*7613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 685*7613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 686*7613SVikram.Hegde@Sun.COM 687*7613SVikram.Hegde@Sun.COM ASSERT(unitp); 688*7613SVikram.Hegde@Sun.COM 689*7613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 690*7613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_allochdl(handle, dip, rdip, 691*7613SVikram.Hegde@Sun.COM attr, waitfp, arg, dma_handlep)); 692*7613SVikram.Hegde@Sun.COM } 693*7613SVikram.Hegde@Sun.COM 694*7613SVikram.Hegde@Sun.COM int 695*7613SVikram.Hegde@Sun.COM iommulib_nexdma_freehdl(dev_info_t *dip, dev_info_t *rdip, 696*7613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle) 697*7613SVikram.Hegde@Sun.COM { 698*7613SVikram.Hegde@Sun.COM int error; 699*7613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 700*7613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 701*7613SVikram.Hegde@Sun.COM 702*7613SVikram.Hegde@Sun.COM ASSERT(unitp); 703*7613SVikram.Hegde@Sun.COM 704*7613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 705*7613SVikram.Hegde@Sun.COM error = unitp->ilu_ops->ilops_dma_freehdl(handle, dip, 706*7613SVikram.Hegde@Sun.COM rdip, dma_handle); 707*7613SVikram.Hegde@Sun.COM 708*7613SVikram.Hegde@Sun.COM iommulib_nex_close(rdip); 709*7613SVikram.Hegde@Sun.COM 710*7613SVikram.Hegde@Sun.COM return (error); 711*7613SVikram.Hegde@Sun.COM } 712*7613SVikram.Hegde@Sun.COM 713*7613SVikram.Hegde@Sun.COM int 714*7613SVikram.Hegde@Sun.COM iommulib_nexdma_bindhdl(dev_info_t *dip, dev_info_t *rdip, 715*7613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle, struct ddi_dma_req *dmareq, 716*7613SVikram.Hegde@Sun.COM ddi_dma_cookie_t *cookiep, uint_t *ccountp) 717*7613SVikram.Hegde@Sun.COM { 718*7613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 719*7613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 720*7613SVikram.Hegde@Sun.COM 721*7613SVikram.Hegde@Sun.COM ASSERT(unitp); 722*7613SVikram.Hegde@Sun.COM 723*7613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 724*7613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_bindhdl(handle, dip, rdip, dma_handle, 725*7613SVikram.Hegde@Sun.COM dmareq, cookiep, ccountp)); 726*7613SVikram.Hegde@Sun.COM } 727*7613SVikram.Hegde@Sun.COM 728*7613SVikram.Hegde@Sun.COM int 729*7613SVikram.Hegde@Sun.COM iommulib_nexdma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, 730*7613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle) 731*7613SVikram.Hegde@Sun.COM { 732*7613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 733*7613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 734*7613SVikram.Hegde@Sun.COM 735*7613SVikram.Hegde@Sun.COM ASSERT(unitp); 736*7613SVikram.Hegde@Sun.COM 737*7613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 738*7613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_unbindhdl(handle, dip, rdip, 739*7613SVikram.Hegde@Sun.COM dma_handle)); 740*7613SVikram.Hegde@Sun.COM } 741*7613SVikram.Hegde@Sun.COM 742*7613SVikram.Hegde@Sun.COM int 743*7613SVikram.Hegde@Sun.COM iommulib_nexdma_sync(dev_info_t *dip, dev_info_t *rdip, 744*7613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle, off_t off, size_t len, 745*7613SVikram.Hegde@Sun.COM uint_t cache_flags) 746*7613SVikram.Hegde@Sun.COM { 747*7613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 748*7613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 749*7613SVikram.Hegde@Sun.COM 750*7613SVikram.Hegde@Sun.COM ASSERT(unitp); 751*7613SVikram.Hegde@Sun.COM 752*7613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 753*7613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_sync(handle, dip, rdip, dma_handle, 754*7613SVikram.Hegde@Sun.COM off, len, cache_flags)); 755*7613SVikram.Hegde@Sun.COM } 756*7613SVikram.Hegde@Sun.COM 757*7613SVikram.Hegde@Sun.COM int 758*7613SVikram.Hegde@Sun.COM iommulib_nexdma_win(dev_info_t *dip, dev_info_t *rdip, 759*7613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle, uint_t win, off_t *offp, size_t *lenp, 760*7613SVikram.Hegde@Sun.COM ddi_dma_cookie_t *cookiep, uint_t *ccountp) 761*7613SVikram.Hegde@Sun.COM { 762*7613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 763*7613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 764*7613SVikram.Hegde@Sun.COM 765*7613SVikram.Hegde@Sun.COM ASSERT(unitp); 766*7613SVikram.Hegde@Sun.COM 767*7613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 768*7613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_win(handle, dip, rdip, dma_handle, 769*7613SVikram.Hegde@Sun.COM win, offp, lenp, cookiep, ccountp)); 770*7613SVikram.Hegde@Sun.COM } 771*7613SVikram.Hegde@Sun.COM 772*7613SVikram.Hegde@Sun.COM /* Obsolete DMA routines */ 773*7613SVikram.Hegde@Sun.COM 774*7613SVikram.Hegde@Sun.COM int 775*7613SVikram.Hegde@Sun.COM iommulib_nexdma_map(dev_info_t *dip, dev_info_t *rdip, 776*7613SVikram.Hegde@Sun.COM struct ddi_dma_req *dmareq, ddi_dma_handle_t *dma_handle) 777*7613SVikram.Hegde@Sun.COM { 778*7613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 779*7613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = handle; 780*7613SVikram.Hegde@Sun.COM 781*7613SVikram.Hegde@Sun.COM ASSERT(unitp); 782*7613SVikram.Hegde@Sun.COM 783*7613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 784*7613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_map(handle, dip, rdip, dmareq, 785*7613SVikram.Hegde@Sun.COM dma_handle)); 786*7613SVikram.Hegde@Sun.COM } 787*7613SVikram.Hegde@Sun.COM 788*7613SVikram.Hegde@Sun.COM int 789*7613SVikram.Hegde@Sun.COM iommulib_nexdma_mctl(dev_info_t *dip, dev_info_t *rdip, 790*7613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle, enum ddi_dma_ctlops request, 791*7613SVikram.Hegde@Sun.COM off_t *offp, size_t *lenp, caddr_t *objpp, uint_t cache_flags) 792*7613SVikram.Hegde@Sun.COM { 793*7613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 794*7613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 795*7613SVikram.Hegde@Sun.COM 796*7613SVikram.Hegde@Sun.COM ASSERT(unitp); 797*7613SVikram.Hegde@Sun.COM 798*7613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 799*7613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_mctl(handle, dip, rdip, dma_handle, 800*7613SVikram.Hegde@Sun.COM request, offp, lenp, objpp, cache_flags)); 801*7613SVikram.Hegde@Sun.COM } 802*7613SVikram.Hegde@Sun.COM 803*7613SVikram.Hegde@Sun.COM /* Utility routines invoked by IOMMU drivers */ 804*7613SVikram.Hegde@Sun.COM int 805*7613SVikram.Hegde@Sun.COM iommulib_iommu_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, 806*7613SVikram.Hegde@Sun.COM ddi_dma_attr_t *attr, int (*waitfp)(caddr_t), caddr_t arg, 807*7613SVikram.Hegde@Sun.COM ddi_dma_handle_t *handlep) 808*7613SVikram.Hegde@Sun.COM { 809*7613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 810*7613SVikram.Hegde@Sun.COM if (nexops == NULL) 811*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 812*7613SVikram.Hegde@Sun.COM return (nexops->nops_dma_allochdl(dip, rdip, attr, waitfp, arg, 813*7613SVikram.Hegde@Sun.COM handlep)); 814*7613SVikram.Hegde@Sun.COM } 815*7613SVikram.Hegde@Sun.COM 816*7613SVikram.Hegde@Sun.COM int 817*7613SVikram.Hegde@Sun.COM iommulib_iommu_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, 818*7613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle) 819*7613SVikram.Hegde@Sun.COM { 820*7613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 821*7613SVikram.Hegde@Sun.COM if (nexops == NULL) 822*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 823*7613SVikram.Hegde@Sun.COM return (nexops->nops_dma_freehdl(dip, rdip, handle)); 824*7613SVikram.Hegde@Sun.COM } 825*7613SVikram.Hegde@Sun.COM 826*7613SVikram.Hegde@Sun.COM int 827*7613SVikram.Hegde@Sun.COM iommulib_iommu_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip, 828*7613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle, struct ddi_dma_req *dmareq, 829*7613SVikram.Hegde@Sun.COM ddi_dma_cookie_t *cookiep, uint_t *ccountp) 830*7613SVikram.Hegde@Sun.COM { 831*7613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 832*7613SVikram.Hegde@Sun.COM if (nexops == NULL) 833*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 834*7613SVikram.Hegde@Sun.COM return (nexops->nops_dma_bindhdl(dip, rdip, handle, dmareq, 835*7613SVikram.Hegde@Sun.COM cookiep, ccountp)); 836*7613SVikram.Hegde@Sun.COM } 837*7613SVikram.Hegde@Sun.COM 838*7613SVikram.Hegde@Sun.COM int 839*7613SVikram.Hegde@Sun.COM iommulib_iommu_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, 840*7613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle) 841*7613SVikram.Hegde@Sun.COM { 842*7613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 843*7613SVikram.Hegde@Sun.COM if (nexops == NULL) 844*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 845*7613SVikram.Hegde@Sun.COM return (nexops->nops_dma_unbindhdl(dip, rdip, handle)); 846*7613SVikram.Hegde@Sun.COM } 847*7613SVikram.Hegde@Sun.COM 848*7613SVikram.Hegde@Sun.COM void 849*7613SVikram.Hegde@Sun.COM iommulib_iommu_dma_reset_cookies(dev_info_t *dip, ddi_dma_handle_t handle) 850*7613SVikram.Hegde@Sun.COM { 851*7613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 852*7613SVikram.Hegde@Sun.COM nexops->nops_dma_reset_cookies(dip, handle); 853*7613SVikram.Hegde@Sun.COM } 854*7613SVikram.Hegde@Sun.COM 855*7613SVikram.Hegde@Sun.COM int 856*7613SVikram.Hegde@Sun.COM iommulib_iommu_dma_get_cookies(dev_info_t *dip, ddi_dma_handle_t handle, 857*7613SVikram.Hegde@Sun.COM ddi_dma_cookie_t *cookiep, uint_t *ccountp) 858*7613SVikram.Hegde@Sun.COM { 859*7613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 860*7613SVikram.Hegde@Sun.COM if (nexops == NULL) 861*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 862*7613SVikram.Hegde@Sun.COM return (nexops->nops_dma_get_cookies(dip, handle, cookiep, ccountp)); 863*7613SVikram.Hegde@Sun.COM } 864*7613SVikram.Hegde@Sun.COM 865*7613SVikram.Hegde@Sun.COM int 866*7613SVikram.Hegde@Sun.COM iommulib_iommu_dma_sync(dev_info_t *dip, dev_info_t *rdip, 867*7613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle, off_t off, size_t len, uint_t cache_flags) 868*7613SVikram.Hegde@Sun.COM { 869*7613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 870*7613SVikram.Hegde@Sun.COM if (nexops == NULL) 871*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 872*7613SVikram.Hegde@Sun.COM return (nexops->nops_dma_sync(dip, rdip, handle, off, len, 873*7613SVikram.Hegde@Sun.COM cache_flags)); 874*7613SVikram.Hegde@Sun.COM } 875*7613SVikram.Hegde@Sun.COM 876*7613SVikram.Hegde@Sun.COM int 877*7613SVikram.Hegde@Sun.COM iommulib_iommu_dma_win(dev_info_t *dip, dev_info_t *rdip, 878*7613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle, uint_t win, off_t *offp, size_t *lenp, 879*7613SVikram.Hegde@Sun.COM ddi_dma_cookie_t *cookiep, uint_t *ccountp) 880*7613SVikram.Hegde@Sun.COM { 881*7613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 882*7613SVikram.Hegde@Sun.COM if (nexops == NULL) 883*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 884*7613SVikram.Hegde@Sun.COM return (nexops->nops_dma_win(dip, rdip, handle, win, offp, lenp, 885*7613SVikram.Hegde@Sun.COM cookiep, ccountp)); 886*7613SVikram.Hegde@Sun.COM } 887*7613SVikram.Hegde@Sun.COM 888*7613SVikram.Hegde@Sun.COM int 889*7613SVikram.Hegde@Sun.COM iommulib_iommu_dma_map(dev_info_t *dip, dev_info_t *rdip, 890*7613SVikram.Hegde@Sun.COM struct ddi_dma_req *dmareq, ddi_dma_handle_t *handlep) 891*7613SVikram.Hegde@Sun.COM { 892*7613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 893*7613SVikram.Hegde@Sun.COM if (nexops == NULL) 894*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 895*7613SVikram.Hegde@Sun.COM return (nexops->nops_dma_map(dip, rdip, dmareq, handlep)); 896*7613SVikram.Hegde@Sun.COM } 897*7613SVikram.Hegde@Sun.COM 898*7613SVikram.Hegde@Sun.COM int 899*7613SVikram.Hegde@Sun.COM iommulib_iommu_dma_mctl(dev_info_t *dip, dev_info_t *rdip, 900*7613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle, enum ddi_dma_ctlops request, off_t *offp, 901*7613SVikram.Hegde@Sun.COM size_t *lenp, caddr_t *objpp, uint_t cache_flags) 902*7613SVikram.Hegde@Sun.COM { 903*7613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 904*7613SVikram.Hegde@Sun.COM if (nexops == NULL) 905*7613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 906*7613SVikram.Hegde@Sun.COM return (nexops->nops_dma_mctl(dip, rdip, handle, request, offp, lenp, 907*7613SVikram.Hegde@Sun.COM objpp, cache_flags)); 908*7613SVikram.Hegde@Sun.COM } 909*7613SVikram.Hegde@Sun.COM 910*7613SVikram.Hegde@Sun.COM int 911*7613SVikram.Hegde@Sun.COM iommulib_iommu_getunitid(iommulib_handle_t handle, uint64_t *unitidp) 912*7613SVikram.Hegde@Sun.COM { 913*7613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 914*7613SVikram.Hegde@Sun.COM uint64_t unitid; 915*7613SVikram.Hegde@Sun.COM 916*7613SVikram.Hegde@Sun.COM unitp = (iommulib_unit_t *)handle; 917*7613SVikram.Hegde@Sun.COM 918*7613SVikram.Hegde@Sun.COM ASSERT(unitp); 919*7613SVikram.Hegde@Sun.COM ASSERT(unitidp); 920*7613SVikram.Hegde@Sun.COM 921*7613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 922*7613SVikram.Hegde@Sun.COM unitid = unitp->ilu_unitid; 923*7613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 924*7613SVikram.Hegde@Sun.COM 925*7613SVikram.Hegde@Sun.COM ASSERT(unitid > 0); 926*7613SVikram.Hegde@Sun.COM *unitidp = (uint64_t)unitid; 927*7613SVikram.Hegde@Sun.COM 928*7613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 929*7613SVikram.Hegde@Sun.COM } 930*7613SVikram.Hegde@Sun.COM 931*7613SVikram.Hegde@Sun.COM dev_info_t * 932*7613SVikram.Hegde@Sun.COM iommulib_iommu_getdip(iommulib_handle_t handle) 933*7613SVikram.Hegde@Sun.COM { 934*7613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 935*7613SVikram.Hegde@Sun.COM dev_info_t *dip; 936*7613SVikram.Hegde@Sun.COM 937*7613SVikram.Hegde@Sun.COM unitp = (iommulib_unit_t *)handle; 938*7613SVikram.Hegde@Sun.COM 939*7613SVikram.Hegde@Sun.COM ASSERT(unitp); 940*7613SVikram.Hegde@Sun.COM 941*7613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 942*7613SVikram.Hegde@Sun.COM dip = unitp->ilu_dip; 943*7613SVikram.Hegde@Sun.COM ASSERT(dip); 944*7613SVikram.Hegde@Sun.COM ndi_hold_devi(dip); 945*7613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 946*7613SVikram.Hegde@Sun.COM 947*7613SVikram.Hegde@Sun.COM return (dip); 948*7613SVikram.Hegde@Sun.COM } 949*7613SVikram.Hegde@Sun.COM 950*7613SVikram.Hegde@Sun.COM iommulib_ops_t * 951*7613SVikram.Hegde@Sun.COM iommulib_iommu_getops(iommulib_handle_t handle) 952*7613SVikram.Hegde@Sun.COM { 953*7613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 954*7613SVikram.Hegde@Sun.COM iommulib_ops_t *ops; 955*7613SVikram.Hegde@Sun.COM 956*7613SVikram.Hegde@Sun.COM unitp = (iommulib_unit_t *)handle; 957*7613SVikram.Hegde@Sun.COM 958*7613SVikram.Hegde@Sun.COM ASSERT(unitp); 959*7613SVikram.Hegde@Sun.COM 960*7613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 961*7613SVikram.Hegde@Sun.COM ops = unitp->ilu_ops; 962*7613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 963*7613SVikram.Hegde@Sun.COM 964*7613SVikram.Hegde@Sun.COM ASSERT(ops); 965*7613SVikram.Hegde@Sun.COM 966*7613SVikram.Hegde@Sun.COM return (ops); 967*7613SVikram.Hegde@Sun.COM } 968*7613SVikram.Hegde@Sun.COM 969*7613SVikram.Hegde@Sun.COM void * 970*7613SVikram.Hegde@Sun.COM iommulib_iommu_getdata(iommulib_handle_t handle) 971*7613SVikram.Hegde@Sun.COM { 972*7613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 973*7613SVikram.Hegde@Sun.COM void *data; 974*7613SVikram.Hegde@Sun.COM 975*7613SVikram.Hegde@Sun.COM unitp = (iommulib_unit_t *)handle; 976*7613SVikram.Hegde@Sun.COM 977*7613SVikram.Hegde@Sun.COM ASSERT(unitp); 978*7613SVikram.Hegde@Sun.COM 979*7613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 980*7613SVikram.Hegde@Sun.COM data = unitp->ilu_data; 981*7613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 982*7613SVikram.Hegde@Sun.COM 983*7613SVikram.Hegde@Sun.COM ASSERT(data); 984*7613SVikram.Hegde@Sun.COM 985*7613SVikram.Hegde@Sun.COM return (data); 986*7613SVikram.Hegde@Sun.COM } 987*7613SVikram.Hegde@Sun.COM 988*7613SVikram.Hegde@Sun.COM /* 989*7613SVikram.Hegde@Sun.COM * Internal routines 990*7613SVikram.Hegde@Sun.COM */ 991*7613SVikram.Hegde@Sun.COM 992*7613SVikram.Hegde@Sun.COM static uint32_t 993*7613SVikram.Hegde@Sun.COM hashfn(uint64_t ptr) 994*7613SVikram.Hegde@Sun.COM { 995*7613SVikram.Hegde@Sun.COM return (ptr % iommulib_cache_size); 996*7613SVikram.Hegde@Sun.COM } 997*7613SVikram.Hegde@Sun.COM 998*7613SVikram.Hegde@Sun.COM static int 999*7613SVikram.Hegde@Sun.COM lookup_cache(dev_info_t *rdip, iommulib_unit_t **unitpp) 1000*7613SVikram.Hegde@Sun.COM { 1001*7613SVikram.Hegde@Sun.COM uint64_t idx; 1002*7613SVikram.Hegde@Sun.COM iommulib_cache_t *cachep; 1003*7613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 1004*7613SVikram.Hegde@Sun.COM int retval = DDI_FAILURE; 1005*7613SVikram.Hegde@Sun.COM 1006*7613SVikram.Hegde@Sun.COM *unitpp = NULL; 1007*7613SVikram.Hegde@Sun.COM 1008*7613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 1009*7613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_cache_lock); 1010*7613SVikram.Hegde@Sun.COM 1011*7613SVikram.Hegde@Sun.COM ASSERT(iommulib_cache); 1012*7613SVikram.Hegde@Sun.COM 1013*7613SVikram.Hegde@Sun.COM idx = hashfn((uint64_t)(uintptr_t)rdip); 1014*7613SVikram.Hegde@Sun.COM 1015*7613SVikram.Hegde@Sun.COM ASSERT(idx < iommulib_cache_size); 1016*7613SVikram.Hegde@Sun.COM 1017*7613SVikram.Hegde@Sun.COM for (cachep = iommulib_cache[idx]; cachep; 1018*7613SVikram.Hegde@Sun.COM cachep = cachep->cache_next) { 1019*7613SVikram.Hegde@Sun.COM if (cachep->cache_rdip == rdip) 1020*7613SVikram.Hegde@Sun.COM break; 1021*7613SVikram.Hegde@Sun.COM } 1022*7613SVikram.Hegde@Sun.COM 1023*7613SVikram.Hegde@Sun.COM if (cachep != NULL) { 1024*7613SVikram.Hegde@Sun.COM unitp = cachep->cache_unit; 1025*7613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 1026*7613SVikram.Hegde@Sun.COM unitp->ilu_ref++; 1027*7613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 1028*7613SVikram.Hegde@Sun.COM *unitpp = unitp; 1029*7613SVikram.Hegde@Sun.COM retval = DDI_SUCCESS; 1030*7613SVikram.Hegde@Sun.COM } 1031*7613SVikram.Hegde@Sun.COM 1032*7613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_cache_lock); 1033*7613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 1034*7613SVikram.Hegde@Sun.COM return (retval); 1035*7613SVikram.Hegde@Sun.COM } 1036*7613SVikram.Hegde@Sun.COM 1037*7613SVikram.Hegde@Sun.COM static void 1038*7613SVikram.Hegde@Sun.COM insert_cache(dev_info_t *rdip, iommulib_unit_t *unitp) 1039*7613SVikram.Hegde@Sun.COM { 1040*7613SVikram.Hegde@Sun.COM uint32_t idx; 1041*7613SVikram.Hegde@Sun.COM iommulib_cache_t *cachep; 1042*7613SVikram.Hegde@Sun.COM 1043*7613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 1044*7613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_cache_lock); 1045*7613SVikram.Hegde@Sun.COM 1046*7613SVikram.Hegde@Sun.COM ASSERT(iommulib_cache); 1047*7613SVikram.Hegde@Sun.COM 1048*7613SVikram.Hegde@Sun.COM idx = hashfn((uint64_t)(uintptr_t)rdip); 1049*7613SVikram.Hegde@Sun.COM 1050*7613SVikram.Hegde@Sun.COM ASSERT(idx < iommulib_cache_size); 1051*7613SVikram.Hegde@Sun.COM 1052*7613SVikram.Hegde@Sun.COM for (cachep = iommulib_cache[idx]; cachep; 1053*7613SVikram.Hegde@Sun.COM cachep = cachep->cache_next) { 1054*7613SVikram.Hegde@Sun.COM if (cachep->cache_rdip == rdip) 1055*7613SVikram.Hegde@Sun.COM break; 1056*7613SVikram.Hegde@Sun.COM } 1057*7613SVikram.Hegde@Sun.COM 1058*7613SVikram.Hegde@Sun.COM if (cachep == NULL) { 1059*7613SVikram.Hegde@Sun.COM cachep = kmem_zalloc(sizeof (iommulib_cache_t), KM_SLEEP); 1060*7613SVikram.Hegde@Sun.COM cachep->cache_rdip = rdip; 1061*7613SVikram.Hegde@Sun.COM cachep->cache_unit = unitp; /* ref-count set by caller */ 1062*7613SVikram.Hegde@Sun.COM cachep->cache_prev = NULL; 1063*7613SVikram.Hegde@Sun.COM cachep->cache_next = iommulib_cache[idx]; 1064*7613SVikram.Hegde@Sun.COM if (cachep->cache_next) 1065*7613SVikram.Hegde@Sun.COM cachep->cache_next->cache_prev = cachep; 1066*7613SVikram.Hegde@Sun.COM iommulib_cache[idx] = cachep; 1067*7613SVikram.Hegde@Sun.COM } 1068*7613SVikram.Hegde@Sun.COM 1069*7613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_cache_lock); 1070*7613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 1071*7613SVikram.Hegde@Sun.COM } 1072