170025d76Sjohnny /* 270025d76Sjohnny * CDDL HEADER START 370025d76Sjohnny * 470025d76Sjohnny * The contents of this file are subject to the terms of the 57a23d100Sanish * Common Development and Distribution License (the "License"). 67a23d100Sanish * You may not use this file except in compliance with the License. 770025d76Sjohnny * 870025d76Sjohnny * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 970025d76Sjohnny * or http://www.opensolaris.org/os/licensing. 1070025d76Sjohnny * See the License for the specific language governing permissions 1170025d76Sjohnny * and limitations under the License. 1270025d76Sjohnny * 1370025d76Sjohnny * When distributing Covered Code, include this CDDL HEADER in each 1470025d76Sjohnny * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1570025d76Sjohnny * If applicable, add the following below this CDDL HEADER, with the 1670025d76Sjohnny * fields enclosed by brackets "[]" replaced with your own identifying 1770025d76Sjohnny * information: Portions Copyright [yyyy] [name of copyright owner] 1870025d76Sjohnny * 1970025d76Sjohnny * CDDL HEADER END 2070025d76Sjohnny */ 2170025d76Sjohnny 2270025d76Sjohnny /* 23c92fa3b5SJimmy Vetayases * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24*bf4de67dSJoshua M. Clulow * Copyright 2015 Joyent, Inc. 2570025d76Sjohnny */ 2670025d76Sjohnny 2770025d76Sjohnny /* 2870025d76Sjohnny * Library file that has miscellaneous support for npe(7d) 2970025d76Sjohnny */ 3070025d76Sjohnny 3170025d76Sjohnny #include <sys/conf.h> 3270025d76Sjohnny #include <sys/pci.h> 3370025d76Sjohnny #include <sys/sunndi.h> 3470025d76Sjohnny #include <sys/acpi/acpi.h> 3570025d76Sjohnny #include <sys/acpi/acpi_pci.h> 3670025d76Sjohnny #include <sys/acpica.h> 37eae2e508Skrishnae #include <sys/pci_cap.h> 38eae2e508Skrishnae #include <sys/pcie_impl.h> 3949fbdd30SErwin T Tsaur #include <sys/x86_archext.h> 408a5a0d1eSanish #include <io/pciex/pcie_nvidia.h> 415c0a55ffSet142600 #include <io/pciex/pcie_nb5000.h> 42c0da6274SZhi-Jun Robin Fu #include <sys/pci_cfgacc_x86.h> 43c92fa3b5SJimmy Vetayases #include <sys/cpuvar.h> 4470025d76Sjohnny 4570025d76Sjohnny /* 4670025d76Sjohnny * Prototype declaration 4770025d76Sjohnny */ 4870025d76Sjohnny void npe_query_acpi_mcfg(dev_info_t *dip); 49337fc9e2Sanish void npe_ck804_fix_aer_ptr(ddi_acc_handle_t cfg_hdl); 507a23d100Sanish int npe_disable_empty_bridges_workaround(dev_info_t *child); 51a2de976fSPavel Potoplyak void npe_nvidia_error_workaround(ddi_acc_handle_t cfg_hdl); 52a2de976fSPavel Potoplyak void npe_intel_error_workaround(ddi_acc_handle_t cfg_hdl); 5349fbdd30SErwin T Tsaur boolean_t npe_is_child_pci(dev_info_t *dip); 54c92fa3b5SJimmy Vetayases int npe_enable_htmsi(ddi_acc_handle_t cfg_hdl); 55c92fa3b5SJimmy Vetayases void npe_enable_htmsi_children(dev_info_t *dip); 56c92fa3b5SJimmy Vetayases 57c92fa3b5SJimmy Vetayases int npe_enable_htmsi_flag = 1; 5870025d76Sjohnny 59eae2e508Skrishnae extern uint32_t npe_aer_uce_mask; 60eae2e508Skrishnae 6170025d76Sjohnny /* 62*bf4de67dSJoshua M. Clulow * Query the MCFG table using ACPI. If MCFG is found, setup the 'ecfg' 63*bf4de67dSJoshua M. Clulow * property accordingly. If no table is found, the property remains unset; the 64*bf4de67dSJoshua M. Clulow * system will not make use of memory-mapped access to PCI Express 65*bf4de67dSJoshua M. Clulow * configuration space. 6670025d76Sjohnny */ 6770025d76Sjohnny void 6870025d76Sjohnny npe_query_acpi_mcfg(dev_info_t *dip) 6970025d76Sjohnny { 7070025d76Sjohnny MCFG_TABLE *mcfgp; 7170025d76Sjohnny CFG_BASE_ADDR_ALLOC *cfg_baap; 7270025d76Sjohnny char *cfg_baa_endp; 735c59319bSDan Mick int64_t ecfginfo[4]; 7470025d76Sjohnny 7570025d76Sjohnny /* Query the MCFG table using ACPI */ 76c1381f44SDana Myers if (AcpiGetTable(ACPI_SIG_MCFG, 1, 77c1381f44SDana Myers (ACPI_TABLE_HEADER **)&mcfgp) == AE_OK) { 7870025d76Sjohnny 7970025d76Sjohnny cfg_baap = (CFG_BASE_ADDR_ALLOC *)mcfgp->CfgBaseAddrAllocList; 8070025d76Sjohnny cfg_baa_endp = ((char *)mcfgp) + mcfgp->Length; 8170025d76Sjohnny 8270025d76Sjohnny while ((char *)cfg_baap < cfg_baa_endp) { 835c59319bSDan Mick if (cfg_baap->base_addr != (uint64_t)0 && 845c59319bSDan Mick cfg_baap->segment == 0) { 8570025d76Sjohnny /* 865c59319bSDan Mick * Set up the 'ecfg' property to hold 875c59319bSDan Mick * base_addr, segment, and first/last bus. 885c59319bSDan Mick * We only do the first entry that maps 895c59319bSDan Mick * segment 0; nonzero segments are not yet 905c59319bSDan Mick * known, or handled. If they appear, 915c59319bSDan Mick * we'll need to figure out which bus node 925c59319bSDan Mick * should have which entry by examining the 935c59319bSDan Mick * ACPI _SEG method on each bus node. 9470025d76Sjohnny */ 955c59319bSDan Mick ecfginfo[0] = cfg_baap->base_addr; 965c59319bSDan Mick ecfginfo[1] = cfg_baap->segment; 975c59319bSDan Mick ecfginfo[2] = cfg_baap->start_bno; 985c59319bSDan Mick ecfginfo[3] = cfg_baap->end_bno; 995c59319bSDan Mick (void) ndi_prop_update_int64_array( 1005c59319bSDan Mick DDI_DEV_T_NONE, dip, "ecfg", 1015c59319bSDan Mick ecfginfo, 4); 1025c59319bSDan Mick break; 10370025d76Sjohnny } 10470025d76Sjohnny cfg_baap++; 10570025d76Sjohnny } 10670025d76Sjohnny } 10770025d76Sjohnny } 10870025d76Sjohnny 10970025d76Sjohnny /* 11070025d76Sjohnny * Enable reporting of AER capability next pointer. 11170025d76Sjohnny * This needs to be done only for CK8-04 devices 11270025d76Sjohnny * by setting NV_XVR_VEND_CYA1 (offset 0xf40) bit 13 11370025d76Sjohnny * NOTE: BIOS is disabling this, it needs to be enabled temporarily 11470025d76Sjohnny */ 11570025d76Sjohnny void 116337fc9e2Sanish npe_ck804_fix_aer_ptr(ddi_acc_handle_t cfg_hdl) 11770025d76Sjohnny { 1188a5a0d1eSanish ushort_t cya1; 11970025d76Sjohnny 1202f15eac9Sanish if ((pci_config_get16(cfg_hdl, PCI_CONF_VENID) == NVIDIA_VENDOR_ID) && 1212f15eac9Sanish (pci_config_get16(cfg_hdl, PCI_CONF_DEVID) == 1222f15eac9Sanish NVIDIA_CK804_DEVICE_ID) && 1232f15eac9Sanish (pci_config_get8(cfg_hdl, PCI_CONF_REVID) >= 1242f15eac9Sanish NVIDIA_CK804_AER_VALID_REVID)) { 125337fc9e2Sanish cya1 = pci_config_get16(cfg_hdl, NVIDIA_CK804_VEND_CYA1_OFF); 12670025d76Sjohnny if (!(cya1 & ~NVIDIA_CK804_VEND_CYA1_ERPT_MASK)) 1272f15eac9Sanish (void) pci_config_put16(cfg_hdl, 1282f15eac9Sanish NVIDIA_CK804_VEND_CYA1_OFF, 12970025d76Sjohnny cya1 | NVIDIA_CK804_VEND_CYA1_ERPT_VAL); 13070025d76Sjohnny } 1312f15eac9Sanish } 1327a23d100Sanish 1337a23d100Sanish /* 1347a23d100Sanish * If the bridge is empty, disable it 1357a23d100Sanish */ 1367a23d100Sanish int 1377a23d100Sanish npe_disable_empty_bridges_workaround(dev_info_t *child) 1387a23d100Sanish { 1397a23d100Sanish /* 1407a23d100Sanish * Do not bind drivers to empty bridges. 1417a23d100Sanish * Fail above, if the bridge is found to be hotplug capable 1427a23d100Sanish */ 143d4bc0535SKrishna Elango if (ddi_driver_major(child) == ddi_name_to_major("pcieb") && 1447a23d100Sanish ddi_get_child(child) == NULL && 1457a23d100Sanish ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 1467a23d100Sanish "pci-hotplug-type", INBAND_HPC_NONE) == INBAND_HPC_NONE) 1477a23d100Sanish return (1); 1487a23d100Sanish 1497a23d100Sanish return (0); 1507a23d100Sanish } 151eae2e508Skrishnae 152eae2e508Skrishnae void 153a2de976fSPavel Potoplyak npe_nvidia_error_workaround(ddi_acc_handle_t cfg_hdl) { 154eae2e508Skrishnae uint32_t regs; 155eae2e508Skrishnae uint16_t vendor_id = pci_config_get16(cfg_hdl, PCI_CONF_VENID); 156eae2e508Skrishnae uint16_t dev_id = pci_config_get16(cfg_hdl, PCI_CONF_DEVID); 157eae2e508Skrishnae 158eae2e508Skrishnae if ((vendor_id == NVIDIA_VENDOR_ID) && NVIDIA_PCIE_RC_DEV_ID(dev_id)) { 159eae2e508Skrishnae /* Disable ECRC for all devices */ 160eae2e508Skrishnae regs = pcie_get_aer_uce_mask() | npe_aer_uce_mask | 161eae2e508Skrishnae PCIE_AER_UCE_ECRC; 162eae2e508Skrishnae pcie_set_aer_uce_mask(regs); 163eae2e508Skrishnae 164eae2e508Skrishnae /* 165eae2e508Skrishnae * Turn full scan on since the Error Source ID register may not 166eae2e508Skrishnae * have the correct ID. 167eae2e508Skrishnae */ 168a2de976fSPavel Potoplyak pcie_force_fullscan(); 169eae2e508Skrishnae } 170eae2e508Skrishnae } 1715c0a55ffSet142600 1725c0a55ffSet142600 void 173a2de976fSPavel Potoplyak npe_intel_error_workaround(ddi_acc_handle_t cfg_hdl) { 1745c0a55ffSet142600 uint32_t regs; 1755c0a55ffSet142600 uint16_t vendor_id = pci_config_get16(cfg_hdl, PCI_CONF_VENID); 176a2de976fSPavel Potoplyak uint16_t dev_id = pci_config_get16(cfg_hdl, PCI_CONF_DEVID); 1775c0a55ffSet142600 1785c0a55ffSet142600 if (vendor_id == INTEL_VENDOR_ID) { 1795c0a55ffSet142600 /* 1805c0a55ffSet142600 * Due to an errata in Intel's ESB2 southbridge, all ECRCs 1815c0a55ffSet142600 * generation/checking need to be disabled. There is a 1825c0a55ffSet142600 * workaround by setting a proprietary bit in the ESB2, but it 1835c0a55ffSet142600 * is not well documented or understood. If that bit is set in 1845c0a55ffSet142600 * the future, then ECRC generation/checking should be enabled 1855c0a55ffSet142600 * again. 1865c0a55ffSet142600 * 1875c0a55ffSet142600 * Disable ECRC generation/checking by masking ECRC in the AER 1885c0a55ffSet142600 * UE Mask. The pcie misc module would then automatically 1895c0a55ffSet142600 * disable ECRC generation/checking in the AER Control register. 1905c0a55ffSet142600 */ 1915c0a55ffSet142600 regs = pcie_get_aer_uce_mask() | PCIE_AER_UCE_ECRC; 1925c0a55ffSet142600 pcie_set_aer_uce_mask(regs); 193a2de976fSPavel Potoplyak 194a2de976fSPavel Potoplyak if (INTEL_NB5500_PCIE_DEV_ID(dev_id) || 195a2de976fSPavel Potoplyak INTEL_NB5520_PCIE_DEV_ID(dev_id)) { 196a2de976fSPavel Potoplyak /* 197a2de976fSPavel Potoplyak * Turn full scan on since the Error Source ID register 198a2de976fSPavel Potoplyak * may not have the correct ID. See Intel 5520 and 199a2de976fSPavel Potoplyak * Intel 5500 Chipsets errata #34 and #54 in the August 200a2de976fSPavel Potoplyak * 2009 specification update, document number 201a2de976fSPavel Potoplyak * 321329-006. 202a2de976fSPavel Potoplyak */ 203a2de976fSPavel Potoplyak pcie_force_fullscan(); 204a2de976fSPavel Potoplyak } 2055c0a55ffSet142600 } 2065c0a55ffSet142600 } 20749fbdd30SErwin T Tsaur 20849fbdd30SErwin T Tsaur /* 20949fbdd30SErwin T Tsaur * Check's if this child is a PCI device. 21049fbdd30SErwin T Tsaur * Child is a PCI device if: 21149fbdd30SErwin T Tsaur * parent has a dev_type of "pci" 21249fbdd30SErwin T Tsaur * -and- 21349fbdd30SErwin T Tsaur * child does not have a dev_type of "pciex" 21449fbdd30SErwin T Tsaur * 21549fbdd30SErwin T Tsaur * If the parent is not of dev_type "pci", then assume it is "pciex" and all 21649fbdd30SErwin T Tsaur * children should support using PCIe style MMCFG access. 21749fbdd30SErwin T Tsaur * 21849fbdd30SErwin T Tsaur * If parent's dev_type is "pci" and child is "pciex", then also enable using 21949fbdd30SErwin T Tsaur * PCIe style MMCFG access. This covers the case where NPE is "pci" and a PCIe 22049fbdd30SErwin T Tsaur * RP is beneath. 22149fbdd30SErwin T Tsaur */ 22249fbdd30SErwin T Tsaur boolean_t 22349fbdd30SErwin T Tsaur npe_child_is_pci(dev_info_t *dip) { 22449fbdd30SErwin T Tsaur char *dev_type; 22549fbdd30SErwin T Tsaur boolean_t parent_is_pci, child_is_pciex; 22649fbdd30SErwin T Tsaur 22749fbdd30SErwin T Tsaur if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_get_parent(dip), 22849fbdd30SErwin T Tsaur DDI_PROP_DONTPASS, "device_type", &dev_type) == 22949fbdd30SErwin T Tsaur DDI_PROP_SUCCESS) { 23049fbdd30SErwin T Tsaur parent_is_pci = (strcmp(dev_type, "pci") == 0); 23149fbdd30SErwin T Tsaur ddi_prop_free(dev_type); 23249fbdd30SErwin T Tsaur } else { 23349fbdd30SErwin T Tsaur parent_is_pci = B_FALSE; 23449fbdd30SErwin T Tsaur } 23549fbdd30SErwin T Tsaur 23649fbdd30SErwin T Tsaur if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 23749fbdd30SErwin T Tsaur "device_type", &dev_type) == DDI_PROP_SUCCESS) { 23849fbdd30SErwin T Tsaur child_is_pciex = (strcmp(dev_type, "pciex") == 0); 23949fbdd30SErwin T Tsaur ddi_prop_free(dev_type); 24049fbdd30SErwin T Tsaur } else { 24149fbdd30SErwin T Tsaur child_is_pciex = B_FALSE; 24249fbdd30SErwin T Tsaur } 24349fbdd30SErwin T Tsaur 24449fbdd30SErwin T Tsaur return (parent_is_pci && !child_is_pciex); 24549fbdd30SErwin T Tsaur } 24649fbdd30SErwin T Tsaur 24749fbdd30SErwin T Tsaur /* 24814f1dfe8SSeth Goldberg * Checks to see if MMCFG is supported. 24914f1dfe8SSeth Goldberg * Returns: TRUE if MMCFG is supported, FALSE if not. 25049fbdd30SErwin T Tsaur * 25114f1dfe8SSeth Goldberg * If a device is attached to a parent whose "dev_type" is "pciex", 25214f1dfe8SSeth Goldberg * the device will support MMCFG access. Otherwise, use legacy IOCFG access. 25349fbdd30SErwin T Tsaur * 25449fbdd30SErwin T Tsaur * Enable Legacy PCI config space access for AMD K8 north bridges. 25549fbdd30SErwin T Tsaur * Host bridge: AMD HyperTransport Technology Configuration 25649fbdd30SErwin T Tsaur * Host bridge: AMD Address Map 25749fbdd30SErwin T Tsaur * Host bridge: AMD DRAM Controller 25849fbdd30SErwin T Tsaur * Host bridge: AMD Miscellaneous Control 25949fbdd30SErwin T Tsaur * These devices do not support MMCFG access. 26049fbdd30SErwin T Tsaur */ 26149fbdd30SErwin T Tsaur boolean_t 26214f1dfe8SSeth Goldberg npe_is_mmcfg_supported(dev_info_t *dip) 26349fbdd30SErwin T Tsaur { 26449fbdd30SErwin T Tsaur int vendor_id, device_id; 26549fbdd30SErwin T Tsaur 26649fbdd30SErwin T Tsaur vendor_id = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 26749fbdd30SErwin T Tsaur "vendor-id", -1); 26849fbdd30SErwin T Tsaur device_id = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 26949fbdd30SErwin T Tsaur "device-id", -1); 27049fbdd30SErwin T Tsaur 27149fbdd30SErwin T Tsaur return !(npe_child_is_pci(dip) || 27249fbdd30SErwin T Tsaur IS_BAD_AMD_NTBRIDGE(vendor_id, device_id)); 27349fbdd30SErwin T Tsaur } 274cb7ea99dSJimmy Vetayases 275cb7ea99dSJimmy Vetayases int 276cb7ea99dSJimmy Vetayases npe_enable_htmsi(ddi_acc_handle_t cfg_hdl) 277cb7ea99dSJimmy Vetayases { 278cb7ea99dSJimmy Vetayases uint16_t ptr; 279cb7ea99dSJimmy Vetayases uint16_t reg; 280cb7ea99dSJimmy Vetayases 281cb7ea99dSJimmy Vetayases if (pci_htcap_locate(cfg_hdl, PCI_HTCAP_TYPE_MASK, 282cb7ea99dSJimmy Vetayases PCI_HTCAP_MSIMAP_TYPE, &ptr) != DDI_SUCCESS) 283cb7ea99dSJimmy Vetayases return (DDI_FAILURE); 284cb7ea99dSJimmy Vetayases 285cb7ea99dSJimmy Vetayases reg = pci_config_get16(cfg_hdl, ptr + PCI_CAP_ID_REGS_OFF); 286cb7ea99dSJimmy Vetayases reg |= PCI_HTCAP_MSIMAP_ENABLE; 287cb7ea99dSJimmy Vetayases 288cb7ea99dSJimmy Vetayases pci_config_put16(cfg_hdl, ptr + PCI_CAP_ID_REGS_OFF, reg); 289cb7ea99dSJimmy Vetayases return (DDI_SUCCESS); 290cb7ea99dSJimmy Vetayases } 291cb7ea99dSJimmy Vetayases 292cb7ea99dSJimmy Vetayases void 293cb7ea99dSJimmy Vetayases npe_enable_htmsi_children(dev_info_t *dip) 294cb7ea99dSJimmy Vetayases { 295cb7ea99dSJimmy Vetayases dev_info_t *cdip = ddi_get_child(dip); 296cb7ea99dSJimmy Vetayases ddi_acc_handle_t cfg_hdl; 297cb7ea99dSJimmy Vetayases 298c92fa3b5SJimmy Vetayases if (!npe_enable_htmsi_flag) 299c92fa3b5SJimmy Vetayases return; 300c92fa3b5SJimmy Vetayases 301c92fa3b5SJimmy Vetayases /* 302c92fa3b5SJimmy Vetayases * Hypertransport MSI remapping only applies to AMD CPUs using 303c92fa3b5SJimmy Vetayases * Hypertransport (K8 and above) and not other platforms with non-AMD 304c92fa3b5SJimmy Vetayases * CPUs that may be using Hypertransport internally in the chipset(s) 305c92fa3b5SJimmy Vetayases */ 306c92fa3b5SJimmy Vetayases if (!(cpuid_getvendor(CPU) == X86_VENDOR_AMD && 307c92fa3b5SJimmy Vetayases cpuid_getfamily(CPU) >= 0xf)) 308c92fa3b5SJimmy Vetayases return; 309c92fa3b5SJimmy Vetayases 310cb7ea99dSJimmy Vetayases for (; cdip != NULL; cdip = ddi_get_next_sibling(cdip)) { 311cb7ea99dSJimmy Vetayases if (pci_config_setup(cdip, &cfg_hdl) != DDI_SUCCESS) { 312cb7ea99dSJimmy Vetayases cmn_err(CE_NOTE, "!npe_enable_htmsi_children: " 313cb7ea99dSJimmy Vetayases "pci_config_setup failed for %s", 314cb7ea99dSJimmy Vetayases ddi_node_name(cdip)); 315c92fa3b5SJimmy Vetayases return; 316cb7ea99dSJimmy Vetayases } 317cb7ea99dSJimmy Vetayases 318cb7ea99dSJimmy Vetayases (void) npe_enable_htmsi(cfg_hdl); 319cb7ea99dSJimmy Vetayases pci_config_teardown(&cfg_hdl); 320cb7ea99dSJimmy Vetayases } 321cb7ea99dSJimmy Vetayases } 322cb7ea99dSJimmy Vetayases 323cb7ea99dSJimmy Vetayases /* 324cb7ea99dSJimmy Vetayases * save config regs for HyperTransport devices without drivers of classes: 325cb7ea99dSJimmy Vetayases * memory controller and hostbridge 326cb7ea99dSJimmy Vetayases */ 327cb7ea99dSJimmy Vetayases int 328cb7ea99dSJimmy Vetayases npe_save_htconfig_children(dev_info_t *dip) 329cb7ea99dSJimmy Vetayases { 330cb7ea99dSJimmy Vetayases dev_info_t *cdip = ddi_get_child(dip); 331cb7ea99dSJimmy Vetayases ddi_acc_handle_t cfg_hdl; 332cb7ea99dSJimmy Vetayases uint16_t ptr; 333cb7ea99dSJimmy Vetayases int rval = DDI_SUCCESS; 334cb7ea99dSJimmy Vetayases uint8_t cl, scl; 335cb7ea99dSJimmy Vetayases 336cb7ea99dSJimmy Vetayases for (; cdip != NULL; cdip = ddi_get_next_sibling(cdip)) { 337cb7ea99dSJimmy Vetayases if (ddi_driver_major(cdip) != DDI_MAJOR_T_NONE) 338cb7ea99dSJimmy Vetayases continue; 339cb7ea99dSJimmy Vetayases 340cb7ea99dSJimmy Vetayases if (pci_config_setup(cdip, &cfg_hdl) != DDI_SUCCESS) 341cb7ea99dSJimmy Vetayases return (DDI_FAILURE); 342cb7ea99dSJimmy Vetayases 343cb7ea99dSJimmy Vetayases cl = pci_config_get8(cfg_hdl, PCI_CONF_BASCLASS); 344cb7ea99dSJimmy Vetayases scl = pci_config_get8(cfg_hdl, PCI_CONF_SUBCLASS); 345cb7ea99dSJimmy Vetayases 346cb7ea99dSJimmy Vetayases if (((cl == PCI_CLASS_MEM && scl == PCI_MEM_RAM) || 347cb7ea99dSJimmy Vetayases (cl == PCI_CLASS_BRIDGE && scl == PCI_BRIDGE_HOST)) && 348cb7ea99dSJimmy Vetayases pci_htcap_locate(cfg_hdl, 0, 0, &ptr) == DDI_SUCCESS) { 349cb7ea99dSJimmy Vetayases 350cb7ea99dSJimmy Vetayases if (pci_save_config_regs(cdip) != DDI_SUCCESS) { 351cb7ea99dSJimmy Vetayases cmn_err(CE_WARN, "Failed to save HT config " 352cb7ea99dSJimmy Vetayases "regs for %s\n", ddi_node_name(cdip)); 353cb7ea99dSJimmy Vetayases rval = DDI_FAILURE; 354cb7ea99dSJimmy Vetayases 355cb7ea99dSJimmy Vetayases } else if (ddi_prop_update_int(DDI_DEV_T_NONE, cdip, 356cb7ea99dSJimmy Vetayases "htconfig-saved", 1) != DDI_SUCCESS) { 357cb7ea99dSJimmy Vetayases cmn_err(CE_WARN, "Failed to set htconfig-saved " 358cb7ea99dSJimmy Vetayases "property for %s\n", ddi_node_name(cdip)); 359cb7ea99dSJimmy Vetayases rval = DDI_FAILURE; 360cb7ea99dSJimmy Vetayases } 361cb7ea99dSJimmy Vetayases } 362cb7ea99dSJimmy Vetayases 363cb7ea99dSJimmy Vetayases pci_config_teardown(&cfg_hdl); 364cb7ea99dSJimmy Vetayases } 365cb7ea99dSJimmy Vetayases 366cb7ea99dSJimmy Vetayases return (rval); 367cb7ea99dSJimmy Vetayases } 368cb7ea99dSJimmy Vetayases 369cb7ea99dSJimmy Vetayases int 370cb7ea99dSJimmy Vetayases npe_restore_htconfig_children(dev_info_t *dip) 371cb7ea99dSJimmy Vetayases { 372cb7ea99dSJimmy Vetayases dev_info_t *cdip = ddi_get_child(dip); 373cb7ea99dSJimmy Vetayases int rval = DDI_SUCCESS; 374cb7ea99dSJimmy Vetayases 375cb7ea99dSJimmy Vetayases for (; cdip != NULL; cdip = ddi_get_next_sibling(cdip)) { 376cb7ea99dSJimmy Vetayases if (ddi_prop_get_int(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, 377cb7ea99dSJimmy Vetayases "htconfig-saved", 0) == 0) 378cb7ea99dSJimmy Vetayases continue; 379cb7ea99dSJimmy Vetayases 380cb7ea99dSJimmy Vetayases if (pci_restore_config_regs(cdip) != DDI_SUCCESS) { 381cb7ea99dSJimmy Vetayases cmn_err(CE_WARN, "Failed to restore HT config " 382cb7ea99dSJimmy Vetayases "regs for %s\n", ddi_node_name(cdip)); 383cb7ea99dSJimmy Vetayases rval = DDI_FAILURE; 384cb7ea99dSJimmy Vetayases } 385cb7ea99dSJimmy Vetayases } 386cb7ea99dSJimmy Vetayases 387cb7ea99dSJimmy Vetayases return (rval); 388cb7ea99dSJimmy Vetayases } 389