120906b23SVikram Hegde /* 220906b23SVikram Hegde * CDDL HEADER START 320906b23SVikram Hegde * 420906b23SVikram Hegde * The contents of this file are subject to the terms of the 520906b23SVikram Hegde * Common Development and Distribution License (the "License"). 620906b23SVikram Hegde * You may not use this file except in compliance with the License. 720906b23SVikram Hegde * 820906b23SVikram Hegde * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 920906b23SVikram Hegde * or http://www.opensolaris.org/os/licensing. 1020906b23SVikram Hegde * See the License for the specific language governing permissions 1120906b23SVikram Hegde * and limitations under the License. 1220906b23SVikram Hegde * 1320906b23SVikram Hegde * When distributing Covered Code, include this CDDL HEADER in each 1420906b23SVikram Hegde * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1520906b23SVikram Hegde * If applicable, add the following below this CDDL HEADER, with the 1620906b23SVikram Hegde * fields enclosed by brackets "[]" replaced with your own identifying 1720906b23SVikram Hegde * information: Portions Copyright [yyyy] [name of copyright owner] 1820906b23SVikram Hegde * 1920906b23SVikram Hegde * CDDL HEADER END 2020906b23SVikram Hegde */ 2120906b23SVikram Hegde /* 22*50200e77SFrank Van Der Linden * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 2320906b23SVikram Hegde */ 2420906b23SVikram Hegde 2520906b23SVikram Hegde #pragma ident "@(#)iommulib.c 1.6 08/09/07 SMI" 2620906b23SVikram Hegde 2720906b23SVikram Hegde #include <sys/sunddi.h> 2820906b23SVikram Hegde #include <sys/sunndi.h> 2920906b23SVikram Hegde #include <sys/errno.h> 3020906b23SVikram Hegde #include <sys/modctl.h> 3120906b23SVikram Hegde #include <sys/iommulib.h> 3220906b23SVikram Hegde 3320906b23SVikram Hegde /* ******** Type definitions private to this file ********************** */ 3420906b23SVikram Hegde 3520906b23SVikram Hegde /* 1 per IOMMU unit. There may be more than one per dip */ 3620906b23SVikram Hegde typedef struct iommulib_unit { 3720906b23SVikram Hegde kmutex_t ilu_lock; 3820906b23SVikram Hegde uint64_t ilu_ref; 3920906b23SVikram Hegde uint32_t ilu_unitid; 4020906b23SVikram Hegde dev_info_t *ilu_dip; 4120906b23SVikram Hegde iommulib_ops_t *ilu_ops; 4220906b23SVikram Hegde void* ilu_data; 4320906b23SVikram Hegde struct iommulib_unit *ilu_next; 4420906b23SVikram Hegde struct iommulib_unit *ilu_prev; 45*50200e77SFrank Van Der Linden iommulib_nexhandle_t ilu_nex; 4620906b23SVikram Hegde } iommulib_unit_t; 4720906b23SVikram Hegde 4820906b23SVikram Hegde typedef struct iommulib_nex { 4920906b23SVikram Hegde dev_info_t *nex_dip; 5020906b23SVikram Hegde iommulib_nexops_t nex_ops; 5120906b23SVikram Hegde struct iommulib_nex *nex_next; 5220906b23SVikram Hegde struct iommulib_nex *nex_prev; 53*50200e77SFrank Van Der Linden uint_t nex_ref; 5420906b23SVikram Hegde } iommulib_nex_t; 5520906b23SVikram Hegde 5620906b23SVikram Hegde /* ********* Globals ************************ */ 5720906b23SVikram Hegde 5865cf7c95SVikram Hegde /* For IOMMU drivers */ 5965cf7c95SVikram Hegde smbios_hdl_t *iommulib_smbios; 6065cf7c95SVikram Hegde 6120906b23SVikram Hegde /* IOMMU side: Following data protected by lock */ 6220906b23SVikram Hegde static kmutex_t iommulib_lock; 6320906b23SVikram Hegde static iommulib_unit_t *iommulib_list; 6420906b23SVikram Hegde static uint64_t iommulib_unit_ids = 0; 6520906b23SVikram Hegde static uint64_t iommulib_num_units = 0; 6620906b23SVikram Hegde 6720906b23SVikram Hegde /* rootnex side data */ 6820906b23SVikram Hegde 6920906b23SVikram Hegde static kmutex_t iommulib_nexus_lock; 7020906b23SVikram Hegde static iommulib_nex_t *iommulib_nexus_list; 7120906b23SVikram Hegde 7220906b23SVikram Hegde /* can be set atomically without lock */ 7320906b23SVikram Hegde static volatile uint32_t iommulib_fini; 7420906b23SVikram Hegde 7520906b23SVikram Hegde /* debug flag */ 7620906b23SVikram Hegde static int iommulib_debug; 7720906b23SVikram Hegde 7820906b23SVikram Hegde /* 7920906b23SVikram Hegde * Module linkage information for the kernel. 8020906b23SVikram Hegde */ 8120906b23SVikram Hegde static struct modlmisc modlmisc = { 8220906b23SVikram Hegde &mod_miscops, "IOMMU library module" 8320906b23SVikram Hegde }; 8420906b23SVikram Hegde 8520906b23SVikram Hegde static struct modlinkage modlinkage = { 8620906b23SVikram Hegde MODREV_1, (void *)&modlmisc, NULL 8720906b23SVikram Hegde }; 8820906b23SVikram Hegde 8920906b23SVikram Hegde int 9020906b23SVikram Hegde _init(void) 9120906b23SVikram Hegde { 9220906b23SVikram Hegde return (mod_install(&modlinkage)); 9320906b23SVikram Hegde } 9420906b23SVikram Hegde 9520906b23SVikram Hegde int 9620906b23SVikram Hegde _fini(void) 9720906b23SVikram Hegde { 9820906b23SVikram Hegde mutex_enter(&iommulib_lock); 9920906b23SVikram Hegde if (iommulib_list != NULL || iommulib_nexus_list != NULL) { 10020906b23SVikram Hegde mutex_exit(&iommulib_lock); 10120906b23SVikram Hegde return (EBUSY); 10220906b23SVikram Hegde } 10320906b23SVikram Hegde iommulib_fini = 1; 10420906b23SVikram Hegde 10520906b23SVikram Hegde mutex_exit(&iommulib_lock); 10620906b23SVikram Hegde return (mod_remove(&modlinkage)); 10720906b23SVikram Hegde } 10820906b23SVikram Hegde 10920906b23SVikram Hegde int 11020906b23SVikram Hegde _info(struct modinfo *modinfop) 11120906b23SVikram Hegde { 11220906b23SVikram Hegde return (mod_info(&modlinkage, modinfop)); 11320906b23SVikram Hegde } 11420906b23SVikram Hegde 11520906b23SVikram Hegde /* 11620906b23SVikram Hegde * Routines with iommulib_iommu_* are invoked from the 11720906b23SVikram Hegde * IOMMU driver. 11820906b23SVikram Hegde * Routines with iommulib_nex* are invoked from the 11920906b23SVikram Hegde * nexus driver (typically rootnex) 12020906b23SVikram Hegde */ 12120906b23SVikram Hegde 12220906b23SVikram Hegde int 12320906b23SVikram Hegde iommulib_nexus_register(dev_info_t *dip, iommulib_nexops_t *nexops, 12420906b23SVikram Hegde iommulib_nexhandle_t *handle) 12520906b23SVikram Hegde { 12620906b23SVikram Hegde iommulib_nex_t *nexp; 12720906b23SVikram Hegde int instance = ddi_get_instance(dip); 12820906b23SVikram Hegde const char *driver = ddi_driver_name(dip); 12920906b23SVikram Hegde dev_info_t *pdip = ddi_get_parent(dip); 13020906b23SVikram Hegde const char *f = "iommulib_nexus_register"; 13120906b23SVikram Hegde 13220906b23SVikram Hegde ASSERT(nexops); 13320906b23SVikram Hegde ASSERT(handle); 13420906b23SVikram Hegde 13520906b23SVikram Hegde *handle = NULL; 13620906b23SVikram Hegde 13720906b23SVikram Hegde /* 13820906b23SVikram Hegde * Root node is never busy held 13920906b23SVikram Hegde */ 14020906b23SVikram Hegde if (dip != ddi_root_node() && (i_ddi_node_state(dip) < DS_PROBED || 14120906b23SVikram Hegde !DEVI_BUSY_OWNED(pdip))) { 14220906b23SVikram Hegde cmn_err(CE_WARN, "%s: NEXUS devinfo node not in DS_PROBED " 14320906b23SVikram Hegde "or busy held for nexops vector (%p). Failing registration", 14420906b23SVikram Hegde f, (void *)nexops); 14520906b23SVikram Hegde return (DDI_FAILURE); 14620906b23SVikram Hegde } 14720906b23SVikram Hegde 14820906b23SVikram Hegde if (nexops->nops_vers != IOMMU_NEXOPS_VERSION) { 14920906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: Invalid IOMMULIB nexops version " 15020906b23SVikram Hegde "in nexops vector (%p). Failing NEXUS registration", 15120906b23SVikram Hegde f, driver, instance, (void *)nexops); 15220906b23SVikram Hegde return (DDI_FAILURE); 15320906b23SVikram Hegde } 15420906b23SVikram Hegde 15520906b23SVikram Hegde ASSERT(nexops->nops_data == NULL); 15620906b23SVikram Hegde 15720906b23SVikram Hegde if (nexops->nops_id == NULL) { 15820906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL ID field. " 15920906b23SVikram Hegde "Failing registration for nexops vector: %p", 16020906b23SVikram Hegde f, driver, instance, (void *)nexops); 16120906b23SVikram Hegde return (DDI_FAILURE); 16220906b23SVikram Hegde } 16320906b23SVikram Hegde 16420906b23SVikram Hegde if (nexops->nops_dma_allochdl == NULL) { 16520906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_allochdl op. " 16620906b23SVikram Hegde "Failing registration for ops vector: %p", f, 16720906b23SVikram Hegde driver, instance, (void *)nexops); 16820906b23SVikram Hegde return (DDI_FAILURE); 16920906b23SVikram Hegde } 17020906b23SVikram Hegde 17120906b23SVikram Hegde if (nexops->nops_dma_freehdl == NULL) { 17220906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_freehdl op. " 17320906b23SVikram Hegde "Failing registration for ops vector: %p", f, 17420906b23SVikram Hegde driver, instance, (void *)nexops); 17520906b23SVikram Hegde return (DDI_FAILURE); 17620906b23SVikram Hegde } 17720906b23SVikram Hegde 17820906b23SVikram Hegde if (nexops->nops_dma_bindhdl == NULL) { 17920906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_bindhdl op. " 18020906b23SVikram Hegde "Failing registration for ops vector: %p", f, 18120906b23SVikram Hegde driver, instance, (void *)nexops); 18220906b23SVikram Hegde return (DDI_FAILURE); 18320906b23SVikram Hegde } 18420906b23SVikram Hegde 18520906b23SVikram Hegde if (nexops->nops_dma_sync == NULL) { 18620906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_sync op. " 18720906b23SVikram Hegde "Failing registration for ops vector: %p", f, 18820906b23SVikram Hegde driver, instance, (void *)nexops); 18920906b23SVikram Hegde return (DDI_FAILURE); 19020906b23SVikram Hegde } 19120906b23SVikram Hegde 19220906b23SVikram Hegde if (nexops->nops_dma_reset_cookies == NULL) { 19320906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_reset_cookies op. " 19420906b23SVikram Hegde "Failing registration for ops vector: %p", f, 19520906b23SVikram Hegde driver, instance, (void *)nexops); 19620906b23SVikram Hegde return (DDI_FAILURE); 19720906b23SVikram Hegde } 19820906b23SVikram Hegde 19920906b23SVikram Hegde if (nexops->nops_dma_get_cookies == NULL) { 20020906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_get_cookies op. " 20120906b23SVikram Hegde "Failing registration for ops vector: %p", f, 20220906b23SVikram Hegde driver, instance, (void *)nexops); 20320906b23SVikram Hegde return (DDI_FAILURE); 20420906b23SVikram Hegde } 20520906b23SVikram Hegde 20694f1124eSVikram Hegde if (nexops->nops_dma_set_cookies == NULL) { 20794f1124eSVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_set_cookies op. " 20894f1124eSVikram Hegde "Failing registration for ops vector: %p", f, 20994f1124eSVikram Hegde driver, instance, (void *)nexops); 21094f1124eSVikram Hegde return (DDI_FAILURE); 21194f1124eSVikram Hegde } 21294f1124eSVikram Hegde 21394f1124eSVikram Hegde if (nexops->nops_dma_clear_cookies == NULL) { 21494f1124eSVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_clear_cookies op. " 21594f1124eSVikram Hegde "Failing registration for ops vector: %p", f, 21694f1124eSVikram Hegde driver, instance, (void *)nexops); 21794f1124eSVikram Hegde return (DDI_FAILURE); 21894f1124eSVikram Hegde } 21994f1124eSVikram Hegde 22094f1124eSVikram Hegde if (nexops->nops_dma_get_sleep_flags == NULL) { 22194f1124eSVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_get_sleep_flags op. " 22294f1124eSVikram Hegde "Failing registration for ops vector: %p", f, 22394f1124eSVikram Hegde driver, instance, (void *)nexops); 22494f1124eSVikram Hegde return (DDI_FAILURE); 22594f1124eSVikram Hegde } 22694f1124eSVikram Hegde 22720906b23SVikram Hegde if (nexops->nops_dma_win == NULL) { 22820906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_win op. " 22920906b23SVikram Hegde "Failing registration for ops vector: %p", f, 23020906b23SVikram Hegde driver, instance, (void *)nexops); 23120906b23SVikram Hegde return (DDI_FAILURE); 23220906b23SVikram Hegde } 23320906b23SVikram Hegde 234*50200e77SFrank Van Der Linden if (nexops->nops_dmahdl_setprivate == NULL) { 235*50200e77SFrank Van Der Linden cmn_err(CE_WARN, "%s: %s%d: NULL nops_dmahdl_setprivate op. " 236*50200e77SFrank Van Der Linden "Failing registration for ops vector: %p", f, 237*50200e77SFrank Van Der Linden driver, instance, (void *)nexops); 238*50200e77SFrank Van Der Linden return (DDI_FAILURE); 239*50200e77SFrank Van Der Linden } 240*50200e77SFrank Van Der Linden 241*50200e77SFrank Van Der Linden if (nexops->nops_dmahdl_getprivate == NULL) { 242*50200e77SFrank Van Der Linden cmn_err(CE_WARN, "%s: %s%d: NULL nops_dmahdl_getprivate op. " 243*50200e77SFrank Van Der Linden "Failing registration for ops vector: %p", f, 244*50200e77SFrank Van Der Linden driver, instance, (void *)nexops); 245*50200e77SFrank Van Der Linden return (DDI_FAILURE); 246*50200e77SFrank Van Der Linden } 247*50200e77SFrank Van Der Linden 24820906b23SVikram Hegde /* Check for legacy ops */ 24920906b23SVikram Hegde if (nexops->nops_dma_map == NULL) { 25020906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL legacy nops_dma_map op. " 25120906b23SVikram Hegde "Failing registration for ops vector: %p", f, 25220906b23SVikram Hegde driver, instance, (void *)nexops); 25320906b23SVikram Hegde return (DDI_FAILURE); 25420906b23SVikram Hegde } 25520906b23SVikram Hegde 25620906b23SVikram Hegde if (nexops->nops_dma_mctl == NULL) { 25720906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL legacy nops_dma_mctl op. " 25820906b23SVikram Hegde "Failing registration for ops vector: %p", f, 25920906b23SVikram Hegde driver, instance, (void *)nexops); 26020906b23SVikram Hegde return (DDI_FAILURE); 26120906b23SVikram Hegde } 26220906b23SVikram Hegde 26320906b23SVikram Hegde nexp = kmem_zalloc(sizeof (iommulib_nex_t), KM_SLEEP); 26420906b23SVikram Hegde 26520906b23SVikram Hegde mutex_enter(&iommulib_lock); 26620906b23SVikram Hegde if (iommulib_fini == 1) { 26720906b23SVikram Hegde mutex_exit(&iommulib_lock); 26820906b23SVikram Hegde cmn_err(CE_WARN, "%s: IOMMULIB unloading. " 26920906b23SVikram Hegde "Failing NEXUS register.", f); 27020906b23SVikram Hegde kmem_free(nexp, sizeof (iommulib_nex_t)); 27120906b23SVikram Hegde return (DDI_FAILURE); 27220906b23SVikram Hegde } 27320906b23SVikram Hegde 27420906b23SVikram Hegde /* 27520906b23SVikram Hegde * fini/register race conditions have been handled. Now create the 27620906b23SVikram Hegde * nexus struct 27720906b23SVikram Hegde */ 27820906b23SVikram Hegde ndi_hold_devi(dip); 27920906b23SVikram Hegde nexp->nex_dip = dip; 28020906b23SVikram Hegde nexp->nex_ops = *nexops; 28120906b23SVikram Hegde 28220906b23SVikram Hegde mutex_enter(&iommulib_nexus_lock); 28320906b23SVikram Hegde nexp->nex_next = iommulib_nexus_list; 28420906b23SVikram Hegde iommulib_nexus_list = nexp; 28520906b23SVikram Hegde nexp->nex_prev = NULL; 28620906b23SVikram Hegde 28720906b23SVikram Hegde if (nexp->nex_next != NULL) 28820906b23SVikram Hegde nexp->nex_next->nex_prev = nexp; 28920906b23SVikram Hegde 290*50200e77SFrank Van Der Linden nexp->nex_ref = 0; 291*50200e77SFrank Van Der Linden 292*50200e77SFrank Van Der Linden /* 293*50200e77SFrank Van Der Linden * The nexus device won't be controlled by an IOMMU. 294*50200e77SFrank Van Der Linden */ 295*50200e77SFrank Van Der Linden DEVI(dip)->devi_iommulib_handle = IOMMU_HANDLE_UNUSED; 296*50200e77SFrank Van Der Linden 297*50200e77SFrank Van Der Linden DEVI(dip)->devi_iommulib_nex_handle = nexp; 298*50200e77SFrank Van Der Linden 29920906b23SVikram Hegde mutex_exit(&iommulib_nexus_lock); 30020906b23SVikram Hegde mutex_exit(&iommulib_lock); 30120906b23SVikram Hegde 30220906b23SVikram Hegde cmn_err(CE_NOTE, "!%s: %s%d: Succesfully registered NEXUS %s " 30320906b23SVikram Hegde "nexops=%p", f, driver, instance, ddi_node_name(dip), 30420906b23SVikram Hegde (void *)nexops); 30520906b23SVikram Hegde 30620906b23SVikram Hegde *handle = nexp; 30720906b23SVikram Hegde 30820906b23SVikram Hegde return (DDI_SUCCESS); 30920906b23SVikram Hegde } 31020906b23SVikram Hegde 31120906b23SVikram Hegde int 31220906b23SVikram Hegde iommulib_nexus_unregister(iommulib_nexhandle_t handle) 31320906b23SVikram Hegde { 31420906b23SVikram Hegde dev_info_t *dip; 31520906b23SVikram Hegde int instance; 31620906b23SVikram Hegde const char *driver; 31720906b23SVikram Hegde iommulib_nex_t *nexp = (iommulib_nex_t *)handle; 31820906b23SVikram Hegde const char *f = "iommulib_nexus_unregister"; 31920906b23SVikram Hegde 32020906b23SVikram Hegde ASSERT(nexp); 32120906b23SVikram Hegde 322*50200e77SFrank Van Der Linden if (nexp->nex_ref != 0) 323*50200e77SFrank Van Der Linden return (DDI_FAILURE); 324*50200e77SFrank Van Der Linden 32520906b23SVikram Hegde mutex_enter(&iommulib_nexus_lock); 32620906b23SVikram Hegde 32720906b23SVikram Hegde dip = nexp->nex_dip; 32820906b23SVikram Hegde driver = ddi_driver_name(dip); 32920906b23SVikram Hegde instance = ddi_get_instance(dip); 33020906b23SVikram Hegde 33120906b23SVikram Hegde /* A future enhancement would be to add ref-counts */ 33220906b23SVikram Hegde 33320906b23SVikram Hegde if (nexp->nex_prev == NULL) { 33420906b23SVikram Hegde iommulib_nexus_list = nexp->nex_next; 33520906b23SVikram Hegde } else { 33620906b23SVikram Hegde nexp->nex_prev->nex_next = nexp->nex_next; 33720906b23SVikram Hegde } 33820906b23SVikram Hegde 33920906b23SVikram Hegde if (nexp->nex_next != NULL) 34020906b23SVikram Hegde nexp->nex_next->nex_prev = nexp->nex_prev; 34120906b23SVikram Hegde 34220906b23SVikram Hegde mutex_exit(&iommulib_nexus_lock); 34320906b23SVikram Hegde 34420906b23SVikram Hegde kmem_free(nexp, sizeof (iommulib_nex_t)); 34520906b23SVikram Hegde 34694f1124eSVikram Hegde cmn_err(CE_NOTE, "!%s: %s%d: NEXUS (%s) handle successfully " 34720906b23SVikram Hegde "unregistered from IOMMULIB", f, driver, instance, 34820906b23SVikram Hegde ddi_node_name(dip)); 34920906b23SVikram Hegde 35020906b23SVikram Hegde ndi_rele_devi(dip); 35120906b23SVikram Hegde 35220906b23SVikram Hegde return (DDI_SUCCESS); 35320906b23SVikram Hegde } 35420906b23SVikram Hegde 35520906b23SVikram Hegde int 35620906b23SVikram Hegde iommulib_iommu_register(dev_info_t *dip, iommulib_ops_t *ops, 35720906b23SVikram Hegde iommulib_handle_t *handle) 35820906b23SVikram Hegde { 35920906b23SVikram Hegde const char *vendor; 36020906b23SVikram Hegde iommulib_unit_t *unitp; 36120906b23SVikram Hegde int instance = ddi_get_instance(dip); 36220906b23SVikram Hegde const char *driver = ddi_driver_name(dip); 36320906b23SVikram Hegde dev_info_t *pdip = ddi_get_parent(dip); 36420906b23SVikram Hegde const char *f = "iommulib_register"; 36520906b23SVikram Hegde 36620906b23SVikram Hegde ASSERT(ops); 36720906b23SVikram Hegde ASSERT(handle); 36820906b23SVikram Hegde 36920906b23SVikram Hegde if (ops->ilops_vers != IOMMU_OPS_VERSION) { 37020906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: Invalid IOMMULIB ops version " 37120906b23SVikram Hegde "in ops vector (%p). Failing registration", f, driver, 37220906b23SVikram Hegde instance, (void *)ops); 37320906b23SVikram Hegde return (DDI_FAILURE); 37420906b23SVikram Hegde } 37520906b23SVikram Hegde 37620906b23SVikram Hegde switch (ops->ilops_vendor) { 37720906b23SVikram Hegde case AMD_IOMMU: 37820906b23SVikram Hegde vendor = "AMD"; 37920906b23SVikram Hegde break; 38020906b23SVikram Hegde case INTEL_IOMMU: 38120906b23SVikram Hegde vendor = "Intel"; 38220906b23SVikram Hegde break; 38320906b23SVikram Hegde case INVALID_VENDOR: 38420906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: vendor field (%x) not initialized. " 38520906b23SVikram Hegde "Failing registration for ops vector: %p", f, 38620906b23SVikram Hegde driver, instance, ops->ilops_vendor, (void *)ops); 38720906b23SVikram Hegde return (DDI_FAILURE); 38820906b23SVikram Hegde default: 38920906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: Invalid vendor field (%x). " 39020906b23SVikram Hegde "Failing registration for ops vector: %p", f, 39120906b23SVikram Hegde driver, instance, ops->ilops_vendor, (void *)ops); 39220906b23SVikram Hegde return (DDI_FAILURE); 39320906b23SVikram Hegde } 39420906b23SVikram Hegde 39594f1124eSVikram Hegde cmn_err(CE_NOTE, "!%s: %s%d: Detected IOMMU registration from vendor" 39694f1124eSVikram Hegde " %s", f, driver, instance, vendor); 39720906b23SVikram Hegde 39820906b23SVikram Hegde if (ops->ilops_data == NULL) { 39920906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL IOMMU data field. " 40020906b23SVikram Hegde "Failing registration for ops vector: %p", f, 40120906b23SVikram Hegde driver, instance, (void *)ops); 40220906b23SVikram Hegde return (DDI_FAILURE); 40320906b23SVikram Hegde } 40420906b23SVikram Hegde 40520906b23SVikram Hegde if (ops->ilops_id == NULL) { 40620906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL ID field. " 40720906b23SVikram Hegde "Failing registration for ops vector: %p", f, 40820906b23SVikram Hegde driver, instance, (void *)ops); 40920906b23SVikram Hegde return (DDI_FAILURE); 41020906b23SVikram Hegde } 41120906b23SVikram Hegde 41220906b23SVikram Hegde if (ops->ilops_probe == NULL) { 41320906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL probe op. " 41420906b23SVikram Hegde "Failing registration for ops vector: %p", f, 41520906b23SVikram Hegde driver, instance, (void *)ops); 41620906b23SVikram Hegde return (DDI_FAILURE); 41720906b23SVikram Hegde } 41820906b23SVikram Hegde 41920906b23SVikram Hegde if (ops->ilops_dma_allochdl == NULL) { 42020906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL dma_allochdl op. " 42120906b23SVikram Hegde "Failing registration for ops vector: %p", f, 42220906b23SVikram Hegde driver, instance, (void *)ops); 42320906b23SVikram Hegde return (DDI_FAILURE); 42420906b23SVikram Hegde } 42520906b23SVikram Hegde 42620906b23SVikram Hegde if (ops->ilops_dma_freehdl == NULL) { 42720906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL dma_freehdl op. " 42820906b23SVikram Hegde "Failing registration for ops vector: %p", f, 42920906b23SVikram Hegde driver, instance, (void *)ops); 43020906b23SVikram Hegde return (DDI_FAILURE); 43120906b23SVikram Hegde } 43220906b23SVikram Hegde 43320906b23SVikram Hegde if (ops->ilops_dma_bindhdl == NULL) { 43420906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL dma_bindhdl op. " 43520906b23SVikram Hegde "Failing registration for ops vector: %p", f, 43620906b23SVikram Hegde driver, instance, (void *)ops); 43720906b23SVikram Hegde return (DDI_FAILURE); 43820906b23SVikram Hegde } 43920906b23SVikram Hegde 44020906b23SVikram Hegde if (ops->ilops_dma_sync == NULL) { 44120906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL dma_sync op. " 44220906b23SVikram Hegde "Failing registration for ops vector: %p", f, 44320906b23SVikram Hegde driver, instance, (void *)ops); 44420906b23SVikram Hegde return (DDI_FAILURE); 44520906b23SVikram Hegde } 44620906b23SVikram Hegde 44720906b23SVikram Hegde if (ops->ilops_dma_win == NULL) { 44820906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL dma_win op. " 44920906b23SVikram Hegde "Failing registration for ops vector: %p", f, 45020906b23SVikram Hegde driver, instance, (void *)ops); 45120906b23SVikram Hegde return (DDI_FAILURE); 45220906b23SVikram Hegde } 45320906b23SVikram Hegde 45420906b23SVikram Hegde /* Check for legacy ops */ 45520906b23SVikram Hegde if (ops->ilops_dma_map == NULL) { 45620906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL legacy dma_map op. " 45720906b23SVikram Hegde "Failing registration for ops vector: %p", f, 45820906b23SVikram Hegde driver, instance, (void *)ops); 45920906b23SVikram Hegde return (DDI_FAILURE); 46020906b23SVikram Hegde } 46120906b23SVikram Hegde 46220906b23SVikram Hegde if (ops->ilops_dma_mctl == NULL) { 46320906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: NULL legacy dma_mctl op. " 46420906b23SVikram Hegde "Failing registration for ops vector: %p", f, 46520906b23SVikram Hegde driver, instance, (void *)ops); 46620906b23SVikram Hegde return (DDI_FAILURE); 46720906b23SVikram Hegde } 46820906b23SVikram Hegde 46920906b23SVikram Hegde unitp = kmem_zalloc(sizeof (iommulib_unit_t), KM_SLEEP); 47020906b23SVikram Hegde mutex_enter(&iommulib_lock); 47120906b23SVikram Hegde if (iommulib_fini == 1) { 47220906b23SVikram Hegde mutex_exit(&iommulib_lock); 47320906b23SVikram Hegde cmn_err(CE_WARN, "%s: IOMMULIB unloading. Failing register.", 47420906b23SVikram Hegde f); 47520906b23SVikram Hegde kmem_free(unitp, sizeof (iommulib_unit_t)); 47620906b23SVikram Hegde return (DDI_FAILURE); 47720906b23SVikram Hegde } 47820906b23SVikram Hegde 47920906b23SVikram Hegde /* 48020906b23SVikram Hegde * fini/register race conditions have been handled. Now create the 48120906b23SVikram Hegde * IOMMU unit 48220906b23SVikram Hegde */ 48320906b23SVikram Hegde mutex_init(&unitp->ilu_lock, NULL, MUTEX_DEFAULT, NULL); 48420906b23SVikram Hegde 48520906b23SVikram Hegde mutex_enter(&unitp->ilu_lock); 48620906b23SVikram Hegde unitp->ilu_unitid = ++iommulib_unit_ids; 48720906b23SVikram Hegde unitp->ilu_ref = 0; 48820906b23SVikram Hegde ndi_hold_devi(dip); 48920906b23SVikram Hegde unitp->ilu_dip = dip; 49020906b23SVikram Hegde unitp->ilu_ops = ops; 49120906b23SVikram Hegde unitp->ilu_data = ops->ilops_data; 49220906b23SVikram Hegde 49320906b23SVikram Hegde unitp->ilu_next = iommulib_list; 49420906b23SVikram Hegde iommulib_list = unitp; 49594f1124eSVikram Hegde unitp->ilu_prev = NULL; 49694f1124eSVikram Hegde if (unitp->ilu_next) 49794f1124eSVikram Hegde unitp->ilu_next->ilu_prev = unitp; 49820906b23SVikram Hegde 499*50200e77SFrank Van Der Linden /* 500*50200e77SFrank Van Der Linden * The IOMMU device itself is not controlled by an IOMMU. 501*50200e77SFrank Van Der Linden */ 502*50200e77SFrank Van Der Linden DEVI(dip)->devi_iommulib_handle = IOMMU_HANDLE_UNUSED; 503*50200e77SFrank Van Der Linden 50420906b23SVikram Hegde mutex_exit(&unitp->ilu_lock); 50520906b23SVikram Hegde 50620906b23SVikram Hegde iommulib_num_units++; 50720906b23SVikram Hegde 50820906b23SVikram Hegde *handle = unitp; 50920906b23SVikram Hegde 51020906b23SVikram Hegde mutex_exit(&iommulib_lock); 51120906b23SVikram Hegde 51294f1124eSVikram Hegde cmn_err(CE_NOTE, "!%s: %s%d: Succesfully registered IOMMU unit " 51320906b23SVikram Hegde "from vendor=%s, ops=%p, data=%p, IOMMULIB unitid=%u", 51420906b23SVikram Hegde f, driver, instance, vendor, (void *)ops, (void *)unitp->ilu_data, 51520906b23SVikram Hegde unitp->ilu_unitid); 51620906b23SVikram Hegde 51720906b23SVikram Hegde return (DDI_SUCCESS); 51820906b23SVikram Hegde } 51920906b23SVikram Hegde 52020906b23SVikram Hegde int 52120906b23SVikram Hegde iommulib_iommu_unregister(iommulib_handle_t handle) 52220906b23SVikram Hegde { 52320906b23SVikram Hegde uint32_t unitid; 52420906b23SVikram Hegde dev_info_t *dip; 52520906b23SVikram Hegde int instance; 52620906b23SVikram Hegde const char *driver; 52720906b23SVikram Hegde iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 52820906b23SVikram Hegde const char *f = "iommulib_unregister"; 52920906b23SVikram Hegde 53020906b23SVikram Hegde ASSERT(unitp); 53120906b23SVikram Hegde 53220906b23SVikram Hegde mutex_enter(&iommulib_lock); 53320906b23SVikram Hegde mutex_enter(&unitp->ilu_lock); 53420906b23SVikram Hegde 53520906b23SVikram Hegde unitid = unitp->ilu_unitid; 53620906b23SVikram Hegde dip = unitp->ilu_dip; 53720906b23SVikram Hegde driver = ddi_driver_name(dip); 53820906b23SVikram Hegde instance = ddi_get_instance(dip); 53920906b23SVikram Hegde 54020906b23SVikram Hegde if (unitp->ilu_ref != 0) { 54120906b23SVikram Hegde mutex_exit(&unitp->ilu_lock); 54220906b23SVikram Hegde mutex_exit(&iommulib_lock); 54320906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: IOMMULIB handle is busy. Cannot " 54420906b23SVikram Hegde "unregister IOMMULIB unitid %u", 54520906b23SVikram Hegde f, driver, instance, unitid); 54620906b23SVikram Hegde return (DDI_FAILURE); 54720906b23SVikram Hegde } 54820906b23SVikram Hegde unitp->ilu_unitid = 0; 54920906b23SVikram Hegde ASSERT(unitp->ilu_ref == 0); 55020906b23SVikram Hegde 55120906b23SVikram Hegde if (unitp->ilu_prev == NULL) { 55220906b23SVikram Hegde iommulib_list = unitp->ilu_next; 55320906b23SVikram Hegde unitp->ilu_next->ilu_prev = NULL; 55420906b23SVikram Hegde } else { 55520906b23SVikram Hegde unitp->ilu_prev->ilu_next = unitp->ilu_next; 55620906b23SVikram Hegde unitp->ilu_next->ilu_prev = unitp->ilu_prev; 55720906b23SVikram Hegde } 55820906b23SVikram Hegde 55920906b23SVikram Hegde iommulib_num_units--; 56020906b23SVikram Hegde 56120906b23SVikram Hegde mutex_exit(&unitp->ilu_lock); 56220906b23SVikram Hegde 56320906b23SVikram Hegde mutex_destroy(&unitp->ilu_lock); 56420906b23SVikram Hegde kmem_free(unitp, sizeof (iommulib_unit_t)); 56520906b23SVikram Hegde 56620906b23SVikram Hegde mutex_exit(&iommulib_lock); 56720906b23SVikram Hegde 56820906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: IOMMULIB handle (unitid=%u) successfully " 56920906b23SVikram Hegde "unregistered", f, driver, instance, unitid); 57020906b23SVikram Hegde 57120906b23SVikram Hegde ndi_rele_devi(dip); 57220906b23SVikram Hegde 57320906b23SVikram Hegde return (DDI_SUCCESS); 57420906b23SVikram Hegde } 57520906b23SVikram Hegde 57620906b23SVikram Hegde int 577*50200e77SFrank Van Der Linden iommulib_nex_open(dev_info_t *dip, dev_info_t *rdip) 57820906b23SVikram Hegde { 57920906b23SVikram Hegde iommulib_unit_t *unitp; 58020906b23SVikram Hegde int instance = ddi_get_instance(rdip); 58120906b23SVikram Hegde const char *driver = ddi_driver_name(rdip); 58220906b23SVikram Hegde const char *f = "iommulib_nex_open"; 58320906b23SVikram Hegde 584*50200e77SFrank Van Der Linden ASSERT(DEVI(dip)->devi_iommulib_nex_handle != NULL); 58594f1124eSVikram Hegde ASSERT(DEVI(rdip)->devi_iommulib_handle == NULL); 58620906b23SVikram Hegde 58720906b23SVikram Hegde /* prevent use of IOMMU for AMD IOMMU's DMA */ 58820906b23SVikram Hegde if (strcmp(driver, "amd_iommu") == 0) { 589*50200e77SFrank Van Der Linden DEVI(rdip)->devi_iommulib_handle = IOMMU_HANDLE_UNUSED; 590*50200e77SFrank Van Der Linden return (DDI_ENOTSUP); 59120906b23SVikram Hegde } 59220906b23SVikram Hegde 59320906b23SVikram Hegde /* 59494f1124eSVikram Hegde * Use the probe entry point to determine in a hardware specific 59594f1124eSVikram Hegde * manner whether this dip is controlled by an IOMMU. If yes, 59694f1124eSVikram Hegde * return the handle corresponding to the IOMMU unit. 59720906b23SVikram Hegde */ 59820906b23SVikram Hegde 59920906b23SVikram Hegde mutex_enter(&iommulib_lock); 60020906b23SVikram Hegde for (unitp = iommulib_list; unitp; unitp = unitp->ilu_next) { 60194f1124eSVikram Hegde if (unitp->ilu_ops->ilops_probe(unitp, rdip) == DDI_SUCCESS) 60220906b23SVikram Hegde break; 60320906b23SVikram Hegde } 60420906b23SVikram Hegde 60520906b23SVikram Hegde if (unitp == NULL) { 60620906b23SVikram Hegde mutex_exit(&iommulib_lock); 60720906b23SVikram Hegde if (iommulib_debug) { 608d8fc7d07SVikram Hegde char *buf = kmem_alloc(MAXPATHLEN, KM_SLEEP); 60920906b23SVikram Hegde cmn_err(CE_WARN, "%s: %s%d: devinfo node (%p): is not " 61020906b23SVikram Hegde "controlled by an IOMMU: path=%s", f, driver, 61120906b23SVikram Hegde instance, (void *)rdip, ddi_pathname(rdip, buf)); 612d8fc7d07SVikram Hegde kmem_free(buf, MAXPATHLEN); 61320906b23SVikram Hegde } 614*50200e77SFrank Van Der Linden DEVI(rdip)->devi_iommulib_handle = IOMMU_HANDLE_UNUSED; 615*50200e77SFrank Van Der Linden return (DDI_ENOTSUP); 61620906b23SVikram Hegde } 61720906b23SVikram Hegde 61820906b23SVikram Hegde mutex_enter(&unitp->ilu_lock); 619*50200e77SFrank Van Der Linden unitp->ilu_nex = DEVI(dip)->devi_iommulib_nex_handle; 62020906b23SVikram Hegde unitp->ilu_ref++; 621*50200e77SFrank Van Der Linden DEVI(rdip)->devi_iommulib_handle = unitp; 62220906b23SVikram Hegde mutex_exit(&unitp->ilu_lock); 62320906b23SVikram Hegde mutex_exit(&iommulib_lock); 62420906b23SVikram Hegde 625*50200e77SFrank Van Der Linden atomic_inc_uint(&DEVI(dip)->devi_iommulib_nex_handle->nex_ref); 62620906b23SVikram Hegde 62720906b23SVikram Hegde return (DDI_SUCCESS); 62820906b23SVikram Hegde } 62920906b23SVikram Hegde 63020906b23SVikram Hegde void 63120906b23SVikram Hegde iommulib_nex_close(dev_info_t *rdip) 63220906b23SVikram Hegde { 63320906b23SVikram Hegde iommulib_unit_t *unitp; 63420906b23SVikram Hegde const char *driver; 63520906b23SVikram Hegde int instance; 63620906b23SVikram Hegde uint32_t unitid; 637*50200e77SFrank Van Der Linden iommulib_nex_t *nexp; 63820906b23SVikram Hegde const char *f = "iommulib_nex_close"; 63920906b23SVikram Hegde 640*50200e77SFrank Van Der Linden ASSERT(IOMMU_USED(rdip)); 64120906b23SVikram Hegde 642*50200e77SFrank Van Der Linden unitp = DEVI(rdip)->devi_iommulib_handle; 64320906b23SVikram Hegde 64420906b23SVikram Hegde mutex_enter(&iommulib_lock); 64520906b23SVikram Hegde mutex_enter(&unitp->ilu_lock); 646*50200e77SFrank Van Der Linden 647*50200e77SFrank Van Der Linden nexp = (iommulib_nex_t *)unitp->ilu_nex; 648*50200e77SFrank Van Der Linden DEVI(rdip)->devi_iommulib_handle = NULL; 649*50200e77SFrank Van Der Linden 65020906b23SVikram Hegde unitid = unitp->ilu_unitid; 65120906b23SVikram Hegde driver = ddi_driver_name(unitp->ilu_dip); 65220906b23SVikram Hegde instance = ddi_get_instance(unitp->ilu_dip); 653*50200e77SFrank Van Der Linden 65420906b23SVikram Hegde unitp->ilu_ref--; 65520906b23SVikram Hegde mutex_exit(&unitp->ilu_lock); 65620906b23SVikram Hegde mutex_exit(&iommulib_lock); 65720906b23SVikram Hegde 658*50200e77SFrank Van Der Linden atomic_dec_uint(&nexp->nex_ref); 659*50200e77SFrank Van Der Linden 66020906b23SVikram Hegde if (iommulib_debug) { 661d8fc7d07SVikram Hegde char *buf = kmem_alloc(MAXPATHLEN, KM_SLEEP); 662d8fc7d07SVikram Hegde (void) ddi_pathname(rdip, buf); 66320906b23SVikram Hegde cmn_err(CE_NOTE, "%s: %s%d: closing IOMMU for dip (%p), " 66420906b23SVikram Hegde "unitid=%u rdip path = %s", f, driver, instance, 66520906b23SVikram Hegde (void *)rdip, unitid, buf); 666d8fc7d07SVikram Hegde kmem_free(buf, MAXPATHLEN); 66720906b23SVikram Hegde } 66820906b23SVikram Hegde } 66920906b23SVikram Hegde 67020906b23SVikram Hegde int 67120906b23SVikram Hegde iommulib_nexdma_allochdl(dev_info_t *dip, dev_info_t *rdip, 67220906b23SVikram Hegde ddi_dma_attr_t *attr, int (*waitfp)(caddr_t), 67320906b23SVikram Hegde caddr_t arg, ddi_dma_handle_t *dma_handlep) 67420906b23SVikram Hegde { 67520906b23SVikram Hegde iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 67620906b23SVikram Hegde iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 67720906b23SVikram Hegde 67820906b23SVikram Hegde ASSERT(unitp); 67920906b23SVikram Hegde 68020906b23SVikram Hegde /* No need to grab lock - the handle is reference counted */ 68120906b23SVikram Hegde return (unitp->ilu_ops->ilops_dma_allochdl(handle, dip, rdip, 68220906b23SVikram Hegde attr, waitfp, arg, dma_handlep)); 68320906b23SVikram Hegde } 68420906b23SVikram Hegde 68520906b23SVikram Hegde int 68620906b23SVikram Hegde iommulib_nexdma_freehdl(dev_info_t *dip, dev_info_t *rdip, 68720906b23SVikram Hegde ddi_dma_handle_t dma_handle) 68820906b23SVikram Hegde { 68920906b23SVikram Hegde int error; 69020906b23SVikram Hegde iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 69120906b23SVikram Hegde iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 69220906b23SVikram Hegde 69320906b23SVikram Hegde ASSERT(unitp); 69420906b23SVikram Hegde 69520906b23SVikram Hegde /* No need to grab lock - the handle is reference counted */ 69620906b23SVikram Hegde error = unitp->ilu_ops->ilops_dma_freehdl(handle, dip, 69720906b23SVikram Hegde rdip, dma_handle); 69820906b23SVikram Hegde 69920906b23SVikram Hegde return (error); 70020906b23SVikram Hegde } 70120906b23SVikram Hegde 70220906b23SVikram Hegde int 70320906b23SVikram Hegde iommulib_nexdma_bindhdl(dev_info_t *dip, dev_info_t *rdip, 70420906b23SVikram Hegde ddi_dma_handle_t dma_handle, struct ddi_dma_req *dmareq, 70520906b23SVikram Hegde ddi_dma_cookie_t *cookiep, uint_t *ccountp) 70620906b23SVikram Hegde { 70720906b23SVikram Hegde iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 70820906b23SVikram Hegde iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 70920906b23SVikram Hegde 71020906b23SVikram Hegde ASSERT(unitp); 71120906b23SVikram Hegde 71220906b23SVikram Hegde /* No need to grab lock - the handle is reference counted */ 71320906b23SVikram Hegde return (unitp->ilu_ops->ilops_dma_bindhdl(handle, dip, rdip, dma_handle, 71420906b23SVikram Hegde dmareq, cookiep, ccountp)); 71520906b23SVikram Hegde } 71620906b23SVikram Hegde 71720906b23SVikram Hegde int 71820906b23SVikram Hegde iommulib_nexdma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, 71920906b23SVikram Hegde ddi_dma_handle_t dma_handle) 72020906b23SVikram Hegde { 72120906b23SVikram Hegde iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 72220906b23SVikram Hegde iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 72320906b23SVikram Hegde 72420906b23SVikram Hegde ASSERT(unitp); 72520906b23SVikram Hegde 72620906b23SVikram Hegde /* No need to grab lock - the handle is reference counted */ 72720906b23SVikram Hegde return (unitp->ilu_ops->ilops_dma_unbindhdl(handle, dip, rdip, 72820906b23SVikram Hegde dma_handle)); 72920906b23SVikram Hegde } 73020906b23SVikram Hegde 73120906b23SVikram Hegde int 73220906b23SVikram Hegde iommulib_nexdma_sync(dev_info_t *dip, dev_info_t *rdip, 73320906b23SVikram Hegde ddi_dma_handle_t dma_handle, off_t off, size_t len, 73420906b23SVikram Hegde uint_t cache_flags) 73520906b23SVikram Hegde { 73620906b23SVikram Hegde iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 73720906b23SVikram Hegde iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 73820906b23SVikram Hegde 73920906b23SVikram Hegde ASSERT(unitp); 74020906b23SVikram Hegde 74120906b23SVikram Hegde /* No need to grab lock - the handle is reference counted */ 74220906b23SVikram Hegde return (unitp->ilu_ops->ilops_dma_sync(handle, dip, rdip, dma_handle, 74320906b23SVikram Hegde off, len, cache_flags)); 74420906b23SVikram Hegde } 74520906b23SVikram Hegde 74620906b23SVikram Hegde int 74720906b23SVikram Hegde iommulib_nexdma_win(dev_info_t *dip, dev_info_t *rdip, 74820906b23SVikram Hegde ddi_dma_handle_t dma_handle, uint_t win, off_t *offp, size_t *lenp, 74920906b23SVikram Hegde ddi_dma_cookie_t *cookiep, uint_t *ccountp) 75020906b23SVikram Hegde { 75120906b23SVikram Hegde iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 75220906b23SVikram Hegde iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 75320906b23SVikram Hegde 75420906b23SVikram Hegde ASSERT(unitp); 75520906b23SVikram Hegde 75620906b23SVikram Hegde /* No need to grab lock - the handle is reference counted */ 75720906b23SVikram Hegde return (unitp->ilu_ops->ilops_dma_win(handle, dip, rdip, dma_handle, 75820906b23SVikram Hegde win, offp, lenp, cookiep, ccountp)); 75920906b23SVikram Hegde } 76020906b23SVikram Hegde 76120906b23SVikram Hegde /* Obsolete DMA routines */ 76220906b23SVikram Hegde 76320906b23SVikram Hegde int 76420906b23SVikram Hegde iommulib_nexdma_map(dev_info_t *dip, dev_info_t *rdip, 76520906b23SVikram Hegde struct ddi_dma_req *dmareq, ddi_dma_handle_t *dma_handle) 76620906b23SVikram Hegde { 76720906b23SVikram Hegde iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 76820906b23SVikram Hegde iommulib_unit_t *unitp = handle; 76920906b23SVikram Hegde 77020906b23SVikram Hegde ASSERT(unitp); 77120906b23SVikram Hegde 77220906b23SVikram Hegde /* No need to grab lock - the handle is reference counted */ 77320906b23SVikram Hegde return (unitp->ilu_ops->ilops_dma_map(handle, dip, rdip, dmareq, 77420906b23SVikram Hegde dma_handle)); 77520906b23SVikram Hegde } 77620906b23SVikram Hegde 77720906b23SVikram Hegde int 77820906b23SVikram Hegde iommulib_nexdma_mctl(dev_info_t *dip, dev_info_t *rdip, 77920906b23SVikram Hegde ddi_dma_handle_t dma_handle, enum ddi_dma_ctlops request, 78020906b23SVikram Hegde off_t *offp, size_t *lenp, caddr_t *objpp, uint_t cache_flags) 78120906b23SVikram Hegde { 78220906b23SVikram Hegde iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 78320906b23SVikram Hegde iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 78420906b23SVikram Hegde 78520906b23SVikram Hegde ASSERT(unitp); 78620906b23SVikram Hegde 78720906b23SVikram Hegde /* No need to grab lock - the handle is reference counted */ 78820906b23SVikram Hegde return (unitp->ilu_ops->ilops_dma_mctl(handle, dip, rdip, dma_handle, 78920906b23SVikram Hegde request, offp, lenp, objpp, cache_flags)); 79020906b23SVikram Hegde } 79120906b23SVikram Hegde 792*50200e77SFrank Van Der Linden int 793*50200e77SFrank Van Der Linden iommulib_nexdma_mapobject(dev_info_t *dip, dev_info_t *rdip, 794*50200e77SFrank Van Der Linden ddi_dma_handle_t dma_handle, struct ddi_dma_req *dmareq, 795*50200e77SFrank Van Der Linden ddi_dma_obj_t *dmao) 796*50200e77SFrank Van Der Linden { 797*50200e77SFrank Van Der Linden iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 798*50200e77SFrank Van Der Linden iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 799*50200e77SFrank Van Der Linden 800*50200e77SFrank Van Der Linden return (unitp->ilu_ops->ilops_dma_mapobject(handle, dip, rdip, 801*50200e77SFrank Van Der Linden dma_handle, dmareq, dmao)); 802*50200e77SFrank Van Der Linden } 803*50200e77SFrank Van Der Linden 804*50200e77SFrank Van Der Linden int 805*50200e77SFrank Van Der Linden iommulib_nexdma_unmapobject(dev_info_t *dip, dev_info_t *rdip, 806*50200e77SFrank Van Der Linden ddi_dma_handle_t dma_handle, ddi_dma_obj_t *dmao) 807*50200e77SFrank Van Der Linden { 808*50200e77SFrank Van Der Linden iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 809*50200e77SFrank Van Der Linden iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 810*50200e77SFrank Van Der Linden 811*50200e77SFrank Van Der Linden return (unitp->ilu_ops->ilops_dma_unmapobject(handle, dip, rdip, 812*50200e77SFrank Van Der Linden dma_handle, dmao)); 813*50200e77SFrank Van Der Linden } 814*50200e77SFrank Van Der Linden 81520906b23SVikram Hegde /* Utility routines invoked by IOMMU drivers */ 81620906b23SVikram Hegde int 81720906b23SVikram Hegde iommulib_iommu_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, 81820906b23SVikram Hegde ddi_dma_attr_t *attr, int (*waitfp)(caddr_t), caddr_t arg, 81920906b23SVikram Hegde ddi_dma_handle_t *handlep) 82020906b23SVikram Hegde { 821*50200e77SFrank Van Der Linden iommulib_nexops_t *nexops; 822*50200e77SFrank Van Der Linden 823*50200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 82420906b23SVikram Hegde return (nexops->nops_dma_allochdl(dip, rdip, attr, waitfp, arg, 82520906b23SVikram Hegde handlep)); 82620906b23SVikram Hegde } 82720906b23SVikram Hegde 82820906b23SVikram Hegde int 82920906b23SVikram Hegde iommulib_iommu_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, 83020906b23SVikram Hegde ddi_dma_handle_t handle) 83120906b23SVikram Hegde { 832*50200e77SFrank Van Der Linden iommulib_nexops_t *nexops; 833*50200e77SFrank Van Der Linden 834*50200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 835*50200e77SFrank Van Der Linden ASSERT(nexops); 83620906b23SVikram Hegde return (nexops->nops_dma_freehdl(dip, rdip, handle)); 83720906b23SVikram Hegde } 83820906b23SVikram Hegde 83920906b23SVikram Hegde int 84020906b23SVikram Hegde iommulib_iommu_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip, 84120906b23SVikram Hegde ddi_dma_handle_t handle, struct ddi_dma_req *dmareq, 84220906b23SVikram Hegde ddi_dma_cookie_t *cookiep, uint_t *ccountp) 84320906b23SVikram Hegde { 844*50200e77SFrank Van Der Linden iommulib_nexops_t *nexops; 845*50200e77SFrank Van Der Linden 846*50200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 84720906b23SVikram Hegde return (nexops->nops_dma_bindhdl(dip, rdip, handle, dmareq, 84820906b23SVikram Hegde cookiep, ccountp)); 84920906b23SVikram Hegde } 85020906b23SVikram Hegde 85120906b23SVikram Hegde int 85220906b23SVikram Hegde iommulib_iommu_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, 85320906b23SVikram Hegde ddi_dma_handle_t handle) 85420906b23SVikram Hegde { 855*50200e77SFrank Van Der Linden iommulib_nexops_t *nexops; 856*50200e77SFrank Van Der Linden 857*50200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 85820906b23SVikram Hegde return (nexops->nops_dma_unbindhdl(dip, rdip, handle)); 85920906b23SVikram Hegde } 86020906b23SVikram Hegde 86120906b23SVikram Hegde void 86220906b23SVikram Hegde iommulib_iommu_dma_reset_cookies(dev_info_t *dip, ddi_dma_handle_t handle) 86320906b23SVikram Hegde { 864*50200e77SFrank Van Der Linden iommulib_nexops_t *nexops; 865*50200e77SFrank Van Der Linden 866*50200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 86720906b23SVikram Hegde nexops->nops_dma_reset_cookies(dip, handle); 86820906b23SVikram Hegde } 86920906b23SVikram Hegde 87020906b23SVikram Hegde int 87120906b23SVikram Hegde iommulib_iommu_dma_get_cookies(dev_info_t *dip, ddi_dma_handle_t handle, 87294f1124eSVikram Hegde ddi_dma_cookie_t **cookiepp, uint_t *ccountp) 87320906b23SVikram Hegde { 874*50200e77SFrank Van Der Linden iommulib_nexops_t *nexops; 875*50200e77SFrank Van Der Linden 876*50200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 87794f1124eSVikram Hegde return (nexops->nops_dma_get_cookies(dip, handle, cookiepp, ccountp)); 87894f1124eSVikram Hegde } 87994f1124eSVikram Hegde 88094f1124eSVikram Hegde int 88194f1124eSVikram Hegde iommulib_iommu_dma_set_cookies(dev_info_t *dip, ddi_dma_handle_t handle, 88294f1124eSVikram Hegde ddi_dma_cookie_t *cookiep, uint_t ccount) 88394f1124eSVikram Hegde { 884*50200e77SFrank Van Der Linden iommulib_nexops_t *nexops; 885*50200e77SFrank Van Der Linden 886*50200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 88794f1124eSVikram Hegde return (nexops->nops_dma_set_cookies(dip, handle, cookiep, ccount)); 88894f1124eSVikram Hegde } 88994f1124eSVikram Hegde 89094f1124eSVikram Hegde int 89194f1124eSVikram Hegde iommulib_iommu_dma_clear_cookies(dev_info_t *dip, ddi_dma_handle_t handle) 89294f1124eSVikram Hegde { 893*50200e77SFrank Van Der Linden iommulib_nexops_t *nexops; 894*50200e77SFrank Van Der Linden 895*50200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 89694f1124eSVikram Hegde return (nexops->nops_dma_clear_cookies(dip, handle)); 89794f1124eSVikram Hegde } 89894f1124eSVikram Hegde 89994f1124eSVikram Hegde int 90094f1124eSVikram Hegde iommulib_iommu_dma_get_sleep_flags(dev_info_t *dip, ddi_dma_handle_t handle) 90194f1124eSVikram Hegde { 902*50200e77SFrank Van Der Linden iommulib_nexops_t *nexops; 903*50200e77SFrank Van Der Linden 904*50200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 90594f1124eSVikram Hegde return (nexops->nops_dma_get_sleep_flags(handle)); 90620906b23SVikram Hegde } 90720906b23SVikram Hegde 90820906b23SVikram Hegde int 90920906b23SVikram Hegde iommulib_iommu_dma_sync(dev_info_t *dip, dev_info_t *rdip, 91020906b23SVikram Hegde ddi_dma_handle_t handle, off_t off, size_t len, uint_t cache_flags) 91120906b23SVikram Hegde { 912*50200e77SFrank Van Der Linden iommulib_nexops_t *nexops; 913*50200e77SFrank Van Der Linden 914*50200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 91520906b23SVikram Hegde return (nexops->nops_dma_sync(dip, rdip, handle, off, len, 91620906b23SVikram Hegde cache_flags)); 91720906b23SVikram Hegde } 91820906b23SVikram Hegde 91920906b23SVikram Hegde int 92020906b23SVikram Hegde iommulib_iommu_dma_win(dev_info_t *dip, dev_info_t *rdip, 92120906b23SVikram Hegde ddi_dma_handle_t handle, uint_t win, off_t *offp, size_t *lenp, 92220906b23SVikram Hegde ddi_dma_cookie_t *cookiep, uint_t *ccountp) 92320906b23SVikram Hegde { 924*50200e77SFrank Van Der Linden iommulib_nexops_t *nexops; 925*50200e77SFrank Van Der Linden 926*50200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 92720906b23SVikram Hegde return (nexops->nops_dma_win(dip, rdip, handle, win, offp, lenp, 92820906b23SVikram Hegde cookiep, ccountp)); 92920906b23SVikram Hegde } 93020906b23SVikram Hegde 93120906b23SVikram Hegde int 93220906b23SVikram Hegde iommulib_iommu_dma_map(dev_info_t *dip, dev_info_t *rdip, 93320906b23SVikram Hegde struct ddi_dma_req *dmareq, ddi_dma_handle_t *handlep) 93420906b23SVikram Hegde { 935*50200e77SFrank Van Der Linden iommulib_nexops_t *nexops; 936*50200e77SFrank Van Der Linden 937*50200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 93820906b23SVikram Hegde return (nexops->nops_dma_map(dip, rdip, dmareq, handlep)); 93920906b23SVikram Hegde } 94020906b23SVikram Hegde 94120906b23SVikram Hegde int 94220906b23SVikram Hegde iommulib_iommu_dma_mctl(dev_info_t *dip, dev_info_t *rdip, 94320906b23SVikram Hegde ddi_dma_handle_t handle, enum ddi_dma_ctlops request, off_t *offp, 94420906b23SVikram Hegde size_t *lenp, caddr_t *objpp, uint_t cache_flags) 94520906b23SVikram Hegde { 946*50200e77SFrank Van Der Linden iommulib_nexops_t *nexops; 947*50200e77SFrank Van Der Linden 948*50200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 94920906b23SVikram Hegde return (nexops->nops_dma_mctl(dip, rdip, handle, request, offp, lenp, 95020906b23SVikram Hegde objpp, cache_flags)); 95120906b23SVikram Hegde } 95220906b23SVikram Hegde 95320906b23SVikram Hegde int 954*50200e77SFrank Van Der Linden iommulib_iommu_dmahdl_setprivate(dev_info_t *dip, dev_info_t *rdip, 955*50200e77SFrank Van Der Linden ddi_dma_handle_t handle, void *priv) 956*50200e77SFrank Van Der Linden { 957*50200e77SFrank Van Der Linden iommulib_nexops_t *nexops; 958*50200e77SFrank Van Der Linden 959*50200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 960*50200e77SFrank Van Der Linden return (nexops->nops_dmahdl_setprivate(dip, rdip, handle, priv)); 961*50200e77SFrank Van Der Linden } 962*50200e77SFrank Van Der Linden 963*50200e77SFrank Van Der Linden void * 964*50200e77SFrank Van Der Linden iommulib_iommu_dmahdl_getprivate(dev_info_t *dip, dev_info_t *rdip, 965*50200e77SFrank Van Der Linden ddi_dma_handle_t handle) 966*50200e77SFrank Van Der Linden { 967*50200e77SFrank Van Der Linden iommulib_nexops_t *nexops; 968*50200e77SFrank Van Der Linden 969*50200e77SFrank Van Der Linden nexops = &DEVI(dip)->devi_iommulib_nex_handle->nex_ops; 970*50200e77SFrank Van Der Linden return (nexops->nops_dmahdl_getprivate(dip, rdip, handle)); 971*50200e77SFrank Van Der Linden } 972*50200e77SFrank Van Der Linden 973*50200e77SFrank Van Der Linden int 97420906b23SVikram Hegde iommulib_iommu_getunitid(iommulib_handle_t handle, uint64_t *unitidp) 97520906b23SVikram Hegde { 97620906b23SVikram Hegde iommulib_unit_t *unitp; 97720906b23SVikram Hegde uint64_t unitid; 97820906b23SVikram Hegde 97920906b23SVikram Hegde unitp = (iommulib_unit_t *)handle; 98020906b23SVikram Hegde 98120906b23SVikram Hegde ASSERT(unitp); 98220906b23SVikram Hegde ASSERT(unitidp); 98320906b23SVikram Hegde 98420906b23SVikram Hegde mutex_enter(&unitp->ilu_lock); 98520906b23SVikram Hegde unitid = unitp->ilu_unitid; 98620906b23SVikram Hegde mutex_exit(&unitp->ilu_lock); 98720906b23SVikram Hegde 98820906b23SVikram Hegde ASSERT(unitid > 0); 98920906b23SVikram Hegde *unitidp = (uint64_t)unitid; 99020906b23SVikram Hegde 99120906b23SVikram Hegde return (DDI_SUCCESS); 99220906b23SVikram Hegde } 99320906b23SVikram Hegde 99420906b23SVikram Hegde dev_info_t * 99520906b23SVikram Hegde iommulib_iommu_getdip(iommulib_handle_t handle) 99620906b23SVikram Hegde { 99720906b23SVikram Hegde iommulib_unit_t *unitp; 99820906b23SVikram Hegde dev_info_t *dip; 99920906b23SVikram Hegde 100020906b23SVikram Hegde unitp = (iommulib_unit_t *)handle; 100120906b23SVikram Hegde 100220906b23SVikram Hegde ASSERT(unitp); 100320906b23SVikram Hegde 100420906b23SVikram Hegde mutex_enter(&unitp->ilu_lock); 100520906b23SVikram Hegde dip = unitp->ilu_dip; 100620906b23SVikram Hegde ASSERT(dip); 100720906b23SVikram Hegde ndi_hold_devi(dip); 100820906b23SVikram Hegde mutex_exit(&unitp->ilu_lock); 100920906b23SVikram Hegde 101020906b23SVikram Hegde return (dip); 101120906b23SVikram Hegde } 101220906b23SVikram Hegde 101320906b23SVikram Hegde iommulib_ops_t * 101420906b23SVikram Hegde iommulib_iommu_getops(iommulib_handle_t handle) 101520906b23SVikram Hegde { 101620906b23SVikram Hegde iommulib_unit_t *unitp; 101720906b23SVikram Hegde iommulib_ops_t *ops; 101820906b23SVikram Hegde 101920906b23SVikram Hegde unitp = (iommulib_unit_t *)handle; 102020906b23SVikram Hegde 102120906b23SVikram Hegde ASSERT(unitp); 102220906b23SVikram Hegde 102320906b23SVikram Hegde mutex_enter(&unitp->ilu_lock); 102420906b23SVikram Hegde ops = unitp->ilu_ops; 102520906b23SVikram Hegde mutex_exit(&unitp->ilu_lock); 102620906b23SVikram Hegde 102720906b23SVikram Hegde ASSERT(ops); 102820906b23SVikram Hegde 102920906b23SVikram Hegde return (ops); 103020906b23SVikram Hegde } 103120906b23SVikram Hegde 103220906b23SVikram Hegde void * 103320906b23SVikram Hegde iommulib_iommu_getdata(iommulib_handle_t handle) 103420906b23SVikram Hegde { 103520906b23SVikram Hegde iommulib_unit_t *unitp; 103620906b23SVikram Hegde void *data; 103720906b23SVikram Hegde 103820906b23SVikram Hegde unitp = (iommulib_unit_t *)handle; 103920906b23SVikram Hegde 104020906b23SVikram Hegde ASSERT(unitp); 104120906b23SVikram Hegde 104220906b23SVikram Hegde mutex_enter(&unitp->ilu_lock); 104320906b23SVikram Hegde data = unitp->ilu_data; 104420906b23SVikram Hegde mutex_exit(&unitp->ilu_lock); 104520906b23SVikram Hegde 104620906b23SVikram Hegde ASSERT(data); 104720906b23SVikram Hegde 104820906b23SVikram Hegde return (data); 104920906b23SVikram Hegde } 1050