xref: /illumos-gate/usr/src/uts/i86pc/io/pciex/npe_misc.c (revision bd97c7ce)
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.
2499abc823SJoshua M. Clulow  * Copyright 2015 Joyent, Inc.
2570025d76Sjohnny  */
2670025d76Sjohnny 
2770025d76Sjohnny /*
28bbf21555SRichard Lowe  *	Library file that has miscellaneous support for npe(4D)
2970025d76Sjohnny  */
3070025d76Sjohnny 
3170025d76Sjohnny #include <sys/conf.h>
3270025d76Sjohnny #include <sys/pci.h>
3370025d76Sjohnny #include <sys/sunndi.h>
34eae2e508Skrishnae #include <sys/pci_cap.h>
35eae2e508Skrishnae #include <sys/pcie_impl.h>
3649fbdd30SErwin T Tsaur #include <sys/x86_archext.h>
378a5a0d1eSanish #include <io/pciex/pcie_nvidia.h>
385c0a55ffSet #include <io/pciex/pcie_nb5000.h>
39c0da6274SZhi-Jun Robin Fu #include <sys/pci_cfgacc_x86.h>
40c92fa3b5SJimmy Vetayases #include <sys/cpuvar.h>
4170025d76Sjohnny 
4270025d76Sjohnny /*
4370025d76Sjohnny  * Prototype declaration
4470025d76Sjohnny  */
45337fc9e2Sanish void	npe_ck804_fix_aer_ptr(ddi_acc_handle_t cfg_hdl);
467a23d100Sanish int	npe_disable_empty_bridges_workaround(dev_info_t *child);
47a2de976fSPavel Potoplyak void	npe_nvidia_error_workaround(ddi_acc_handle_t cfg_hdl);
48a2de976fSPavel Potoplyak void	npe_intel_error_workaround(ddi_acc_handle_t cfg_hdl);
4949fbdd30SErwin T Tsaur boolean_t npe_is_child_pci(dev_info_t *dip);
50c92fa3b5SJimmy Vetayases int	npe_enable_htmsi(ddi_acc_handle_t cfg_hdl);
51c92fa3b5SJimmy Vetayases void	npe_enable_htmsi_children(dev_info_t *dip);
52c92fa3b5SJimmy Vetayases 
53c92fa3b5SJimmy Vetayases int	npe_enable_htmsi_flag = 1;
5470025d76Sjohnny 
55a2de976fSPavel Potoplyak extern uint32_t npe_aer_uce_mask;
56eae2e508Skrishnae 
5770025d76Sjohnny /*
5870025d76Sjohnny  * Enable reporting of AER capability next pointer.
5970025d76Sjohnny  * This needs to be done only for CK8-04 devices
6070025d76Sjohnny  * by setting NV_XVR_VEND_CYA1 (offset 0xf40) bit 13
6170025d76Sjohnny  * NOTE: BIOS is disabling this, it needs to be enabled temporarily
6270025d76Sjohnny  */
6370025d76Sjohnny void
npe_ck804_fix_aer_ptr(ddi_acc_handle_t cfg_hdl)64337fc9e2Sanish npe_ck804_fix_aer_ptr(ddi_acc_handle_t cfg_hdl)
6570025d76Sjohnny {
66337fc9e2Sanish 	ushort_t cya1;
6770025d76Sjohnny 
682f15eac9Sanish 	if ((pci_config_get16(cfg_hdl, PCI_CONF_VENID) == NVIDIA_VENDOR_ID) &&
692f15eac9Sanish 	    (pci_config_get16(cfg_hdl, PCI_CONF_DEVID) ==
702f15eac9Sanish 	    NVIDIA_CK804_DEVICE_ID) &&
712f15eac9Sanish 	    (pci_config_get8(cfg_hdl, PCI_CONF_REVID) >=
722f15eac9Sanish 	    NVIDIA_CK804_AER_VALID_REVID)) {
732f15eac9Sanish 		cya1 =  pci_config_get16(cfg_hdl, NVIDIA_CK804_VEND_CYA1_OFF);
742f15eac9Sanish 		if (!(cya1 & ~NVIDIA_CK804_VEND_CYA1_ERPT_MASK))
752f15eac9Sanish 			(void) pci_config_put16(cfg_hdl,
762f15eac9Sanish 			    NVIDIA_CK804_VEND_CYA1_OFF,
772f15eac9Sanish 			    cya1 | NVIDIA_CK804_VEND_CYA1_ERPT_VAL);
782f15eac9Sanish 	}
7970025d76Sjohnny }
807a23d100Sanish 
817a23d100Sanish /*
827a23d100Sanish  * If the bridge is empty, disable it
837a23d100Sanish  */
847a23d100Sanish int
npe_disable_empty_bridges_workaround(dev_info_t * child)857a23d100Sanish npe_disable_empty_bridges_workaround(dev_info_t *child)
867a23d100Sanish {
87*bd97c7ceSRobert Mustacchi 	pcie_bus_t *bus_p = PCIE_DIP2BUS(child);
88*bd97c7ceSRobert Mustacchi 
897a23d100Sanish 	/*
907a23d100Sanish 	 * Do not bind drivers to empty bridges.
917a23d100Sanish 	 * Fail above, if the bridge is found to be hotplug capable
927a23d100Sanish 	 */
93d4bc0535SKrishna Elango 	if (ddi_driver_major(child) == ddi_name_to_major("pcieb") &&
94*bd97c7ceSRobert Mustacchi 	    ddi_get_child(child) == NULL && bus_p->bus_hp_sup_modes ==
95*bd97c7ceSRobert Mustacchi 	    PCIE_NONE_HP_MODE) {
967a23d100Sanish 		return (1);
97*bd97c7ceSRobert Mustacchi 	}
987a23d100Sanish 
997a23d100Sanish 	return (0);
1007a23d100Sanish }
101eae2e508Skrishnae 
102eae2e508Skrishnae void
npe_nvidia_error_workaround(ddi_acc_handle_t cfg_hdl)103097e441fSRobert Mustacchi npe_nvidia_error_workaround(ddi_acc_handle_t cfg_hdl)
104097e441fSRobert Mustacchi {
105eae2e508Skrishnae 	uint32_t regs;
106eae2e508Skrishnae 	uint16_t vendor_id = pci_config_get16(cfg_hdl, PCI_CONF_VENID);
107eae2e508Skrishnae 	uint16_t dev_id = pci_config_get16(cfg_hdl, PCI_CONF_DEVID);
108eae2e508Skrishnae 
109eae2e508Skrishnae 	if ((vendor_id == NVIDIA_VENDOR_ID) && NVIDIA_PCIE_RC_DEV_ID(dev_id)) {
110eae2e508Skrishnae 		/* Disable ECRC for all devices */
111eae2e508Skrishnae 		regs = pcie_get_aer_uce_mask() | npe_aer_uce_mask |
112eae2e508Skrishnae 		    PCIE_AER_UCE_ECRC;
113eae2e508Skrishnae 		pcie_set_aer_uce_mask(regs);
114eae2e508Skrishnae 
115eae2e508Skrishnae 		/*
116eae2e508Skrishnae 		 * Turn full scan on since the Error Source ID register may not
117eae2e508Skrishnae 		 * have the correct ID.
118eae2e508Skrishnae 		 */
119a2de976fSPavel Potoplyak 		pcie_force_fullscan();
120eae2e508Skrishnae 	}
121eae2e508Skrishnae }
1225c0a55ffSet 
1235c0a55ffSet void
npe_intel_error_workaround(ddi_acc_handle_t cfg_hdl)124097e441fSRobert Mustacchi npe_intel_error_workaround(ddi_acc_handle_t cfg_hdl)
125097e441fSRobert Mustacchi {
1265c0a55ffSet 	uint32_t regs;
1275c0a55ffSet 	uint16_t vendor_id = pci_config_get16(cfg_hdl, PCI_CONF_VENID);
128a2de976fSPavel Potoplyak 	uint16_t dev_id = pci_config_get16(cfg_hdl, PCI_CONF_DEVID);
1295c0a55ffSet 
1305c0a55ffSet 	if (vendor_id == INTEL_VENDOR_ID) {
1315c0a55ffSet 		/*
1325c0a55ffSet 		 * Due to an errata in Intel's ESB2 southbridge, all ECRCs
1335c0a55ffSet 		 * generation/checking need to be disabled.  There is a
1345c0a55ffSet 		 * workaround by setting a proprietary bit in the ESB2, but it
1355c0a55ffSet 		 * is not well documented or understood.  If that bit is set in
1365c0a55ffSet 		 * the future, then ECRC generation/checking should be enabled
1375c0a55ffSet 		 * again.
1385c0a55ffSet 		 *
1395c0a55ffSet 		 * Disable ECRC generation/checking by masking ECRC in the AER
1405c0a55ffSet 		 * UE Mask.  The pcie misc module would then automatically
1415c0a55ffSet 		 * disable ECRC generation/checking in the AER Control register.
1425c0a55ffSet 		 */
1435c0a55ffSet 		regs = pcie_get_aer_uce_mask() | PCIE_AER_UCE_ECRC;
1445c0a55ffSet 		pcie_set_aer_uce_mask(regs);
145a2de976fSPavel Potoplyak 
146a2de976fSPavel Potoplyak 		if (INTEL_NB5500_PCIE_DEV_ID(dev_id) ||
147a2de976fSPavel Potoplyak 		    INTEL_NB5520_PCIE_DEV_ID(dev_id)) {
148a2de976fSPavel Potoplyak 			/*
149a2de976fSPavel Potoplyak 			 * Turn full scan on since the Error Source ID register
150a2de976fSPavel Potoplyak 			 * may not have the correct ID. See Intel 5520 and
151a2de976fSPavel Potoplyak 			 * Intel 5500 Chipsets errata #34 and #54 in the August
152a2de976fSPavel Potoplyak 			 * 2009 specification update, document number
153a2de976fSPavel Potoplyak 			 * 321329-006.
154a2de976fSPavel Potoplyak 			 */
155a2de976fSPavel Potoplyak 			pcie_force_fullscan();
156a2de976fSPavel Potoplyak 		}
1575c0a55ffSet 	}
1585c0a55ffSet }
15949fbdd30SErwin T Tsaur 
16049fbdd30SErwin T Tsaur /*
16149fbdd30SErwin T Tsaur  * Check's if this child is a PCI device.
16249fbdd30SErwin T Tsaur  * Child is a PCI device if:
16349fbdd30SErwin T Tsaur  * parent has a dev_type of "pci"
16449fbdd30SErwin T Tsaur  * -and-
16549fbdd30SErwin T Tsaur  * child does not have a dev_type of "pciex"
16649fbdd30SErwin T Tsaur  *
16749fbdd30SErwin T Tsaur  * If the parent is not of dev_type "pci", then assume it is "pciex" and all
16849fbdd30SErwin T Tsaur  * children should support using PCIe style MMCFG access.
16949fbdd30SErwin T Tsaur  *
17049fbdd30SErwin T Tsaur  * If parent's dev_type is "pci" and child is "pciex", then also enable using
17149fbdd30SErwin T Tsaur  * PCIe style MMCFG access.  This covers the case where NPE is "pci" and a PCIe
17249fbdd30SErwin T Tsaur  * RP is beneath.
17349fbdd30SErwin T Tsaur  */
17449fbdd30SErwin T Tsaur boolean_t
npe_child_is_pci(dev_info_t * dip)175097e441fSRobert Mustacchi npe_child_is_pci(dev_info_t *dip)
176097e441fSRobert Mustacchi {
17749fbdd30SErwin T Tsaur 	char *dev_type;
17849fbdd30SErwin T Tsaur 	boolean_t parent_is_pci, child_is_pciex;
17949fbdd30SErwin T Tsaur 
18049fbdd30SErwin T Tsaur 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_get_parent(dip),
18149fbdd30SErwin T Tsaur 	    DDI_PROP_DONTPASS, "device_type", &dev_type) ==
18249fbdd30SErwin T Tsaur 	    DDI_PROP_SUCCESS) {
18349fbdd30SErwin T Tsaur 		parent_is_pci = (strcmp(dev_type, "pci") == 0);
18449fbdd30SErwin T Tsaur 		ddi_prop_free(dev_type);
18549fbdd30SErwin T Tsaur 	} else {
18649fbdd30SErwin T Tsaur 		parent_is_pci = B_FALSE;
18749fbdd30SErwin T Tsaur 	}
18849fbdd30SErwin T Tsaur 
18949fbdd30SErwin T Tsaur 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
19049fbdd30SErwin T Tsaur 	    "device_type", &dev_type) == DDI_PROP_SUCCESS) {
19149fbdd30SErwin T Tsaur 		child_is_pciex = (strcmp(dev_type, "pciex") == 0);
19249fbdd30SErwin T Tsaur 		ddi_prop_free(dev_type);
19349fbdd30SErwin T Tsaur 	} else {
19449fbdd30SErwin T Tsaur 		child_is_pciex = B_FALSE;
19549fbdd30SErwin T Tsaur 	}
19649fbdd30SErwin T Tsaur 
19749fbdd30SErwin T Tsaur 	return (parent_is_pci && !child_is_pciex);
19849fbdd30SErwin T Tsaur }
19949fbdd30SErwin T Tsaur 
20049fbdd30SErwin T Tsaur /*
20114f1dfe8SSeth Goldberg  * Checks to see if MMCFG is supported.
20214f1dfe8SSeth Goldberg  * Returns: TRUE if MMCFG is supported, FALSE if not.
20349fbdd30SErwin T Tsaur  *
20414f1dfe8SSeth Goldberg  * If a device is attached to a parent whose "dev_type" is "pciex",
20514f1dfe8SSeth Goldberg  * the device will support MMCFG access.  Otherwise, use legacy IOCFG access.
20649fbdd30SErwin T Tsaur  *
20749fbdd30SErwin T Tsaur  * Enable Legacy PCI config space access for AMD K8 north bridges.
20849fbdd30SErwin T Tsaur  *	Host bridge: AMD HyperTransport Technology Configuration
20949fbdd30SErwin T Tsaur  *	Host bridge: AMD Address Map
21049fbdd30SErwin T Tsaur  *	Host bridge: AMD DRAM Controller
21149fbdd30SErwin T Tsaur  *	Host bridge: AMD Miscellaneous Control
21249fbdd30SErwin T Tsaur  * These devices do not support MMCFG access.
21349fbdd30SErwin T Tsaur  */
21449fbdd30SErwin T Tsaur boolean_t
npe_is_mmcfg_supported(dev_info_t * dip)21514f1dfe8SSeth Goldberg npe_is_mmcfg_supported(dev_info_t *dip)
21649fbdd30SErwin T Tsaur {
21749fbdd30SErwin T Tsaur 	int vendor_id, device_id;
21849fbdd30SErwin T Tsaur 
21949fbdd30SErwin T Tsaur 	vendor_id = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
22049fbdd30SErwin T Tsaur 	    "vendor-id", -1);
22149fbdd30SErwin T Tsaur 	device_id = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
22249fbdd30SErwin T Tsaur 	    "device-id", -1);
22349fbdd30SErwin T Tsaur 
22449fbdd30SErwin T Tsaur 	return !(npe_child_is_pci(dip) ||
22549fbdd30SErwin T Tsaur 	    IS_BAD_AMD_NTBRIDGE(vendor_id, device_id));
22649fbdd30SErwin T Tsaur }
227cb7ea99dSJimmy Vetayases 
228cb7ea99dSJimmy Vetayases int
npe_enable_htmsi(ddi_acc_handle_t cfg_hdl)229cb7ea99dSJimmy Vetayases npe_enable_htmsi(ddi_acc_handle_t cfg_hdl)
230cb7ea99dSJimmy Vetayases {
231cb7ea99dSJimmy Vetayases 	uint16_t ptr;
232cb7ea99dSJimmy Vetayases 	uint16_t reg;
233cb7ea99dSJimmy Vetayases 
234cb7ea99dSJimmy Vetayases 	if (pci_htcap_locate(cfg_hdl, PCI_HTCAP_TYPE_MASK,
235cb7ea99dSJimmy Vetayases 	    PCI_HTCAP_MSIMAP_TYPE, &ptr) != DDI_SUCCESS)
236cb7ea99dSJimmy Vetayases 		return (DDI_FAILURE);
237cb7ea99dSJimmy Vetayases 
238cb7ea99dSJimmy Vetayases 	reg = pci_config_get16(cfg_hdl, ptr + PCI_CAP_ID_REGS_OFF);
239cb7ea99dSJimmy Vetayases 	reg |= PCI_HTCAP_MSIMAP_ENABLE;
240cb7ea99dSJimmy Vetayases 
241cb7ea99dSJimmy Vetayases 	pci_config_put16(cfg_hdl, ptr + PCI_CAP_ID_REGS_OFF, reg);
242cb7ea99dSJimmy Vetayases 	return (DDI_SUCCESS);
243cb7ea99dSJimmy Vetayases }
244cb7ea99dSJimmy Vetayases 
245cb7ea99dSJimmy Vetayases void
npe_enable_htmsi_children(dev_info_t * dip)246cb7ea99dSJimmy Vetayases npe_enable_htmsi_children(dev_info_t *dip)
247cb7ea99dSJimmy Vetayases {
248cb7ea99dSJimmy Vetayases 	dev_info_t *cdip = ddi_get_child(dip);
249cb7ea99dSJimmy Vetayases 	ddi_acc_handle_t cfg_hdl;
250cb7ea99dSJimmy Vetayases 
251c92fa3b5SJimmy Vetayases 	if (!npe_enable_htmsi_flag)
252c92fa3b5SJimmy Vetayases 		return;
253c92fa3b5SJimmy Vetayases 
254c92fa3b5SJimmy Vetayases 	/*
255c92fa3b5SJimmy Vetayases 	 * Hypertransport MSI remapping only applies to AMD CPUs using
256c92fa3b5SJimmy Vetayases 	 * Hypertransport (K8 and above) and not other platforms with non-AMD
257c92fa3b5SJimmy Vetayases 	 * CPUs that may be using Hypertransport internally in the chipset(s)
258c92fa3b5SJimmy Vetayases 	 */
259c92fa3b5SJimmy Vetayases 	if (!(cpuid_getvendor(CPU) == X86_VENDOR_AMD &&
260c92fa3b5SJimmy Vetayases 	    cpuid_getfamily(CPU) >= 0xf))
261c92fa3b5SJimmy Vetayases 		return;
262c92fa3b5SJimmy Vetayases 
263cb7ea99dSJimmy Vetayases 	for (; cdip != NULL; cdip = ddi_get_next_sibling(cdip)) {
264cb7ea99dSJimmy Vetayases 		if (pci_config_setup(cdip, &cfg_hdl) != DDI_SUCCESS) {
265cb7ea99dSJimmy Vetayases 			cmn_err(CE_NOTE, "!npe_enable_htmsi_children: "
266cb7ea99dSJimmy Vetayases 			    "pci_config_setup failed for %s",
267cb7ea99dSJimmy Vetayases 			    ddi_node_name(cdip));
268c92fa3b5SJimmy Vetayases 			return;
269cb7ea99dSJimmy Vetayases 		}
270cb7ea99dSJimmy Vetayases 
271cb7ea99dSJimmy Vetayases 		(void) npe_enable_htmsi(cfg_hdl);
272cb7ea99dSJimmy Vetayases 		pci_config_teardown(&cfg_hdl);
273cb7ea99dSJimmy Vetayases 	}
274cb7ea99dSJimmy Vetayases }
275cb7ea99dSJimmy Vetayases 
276cb7ea99dSJimmy Vetayases /*
277cb7ea99dSJimmy Vetayases  * save config regs for HyperTransport devices without drivers of classes:
278cb7ea99dSJimmy Vetayases  * memory controller and hostbridge
279cb7ea99dSJimmy Vetayases  */
280cb7ea99dSJimmy Vetayases int
npe_save_htconfig_children(dev_info_t * dip)281cb7ea99dSJimmy Vetayases npe_save_htconfig_children(dev_info_t *dip)
282cb7ea99dSJimmy Vetayases {
283cb7ea99dSJimmy Vetayases 	dev_info_t *cdip = ddi_get_child(dip);
284cb7ea99dSJimmy Vetayases 	ddi_acc_handle_t cfg_hdl;
285cb7ea99dSJimmy Vetayases 	uint16_t ptr;
286cb7ea99dSJimmy Vetayases 	int rval = DDI_SUCCESS;
287cb7ea99dSJimmy Vetayases 	uint8_t cl, scl;
288cb7ea99dSJimmy Vetayases 
289cb7ea99dSJimmy Vetayases 	for (; cdip != NULL; cdip = ddi_get_next_sibling(cdip)) {
290cb7ea99dSJimmy Vetayases 		if (ddi_driver_major(cdip) != DDI_MAJOR_T_NONE)
291cb7ea99dSJimmy Vetayases 			continue;
292cb7ea99dSJimmy Vetayases 
293cb7ea99dSJimmy Vetayases 		if (pci_config_setup(cdip, &cfg_hdl) != DDI_SUCCESS)
294cb7ea99dSJimmy Vetayases 			return (DDI_FAILURE);
295cb7ea99dSJimmy Vetayases 
296cb7ea99dSJimmy Vetayases 		cl = pci_config_get8(cfg_hdl, PCI_CONF_BASCLASS);
297cb7ea99dSJimmy Vetayases 		scl = pci_config_get8(cfg_hdl, PCI_CONF_SUBCLASS);
298cb7ea99dSJimmy Vetayases 
299cb7ea99dSJimmy Vetayases 		if (((cl == PCI_CLASS_MEM && scl == PCI_MEM_RAM) ||
300cb7ea99dSJimmy Vetayases 		    (cl == PCI_CLASS_BRIDGE && scl == PCI_BRIDGE_HOST)) &&
301cb7ea99dSJimmy Vetayases 		    pci_htcap_locate(cfg_hdl, 0, 0, &ptr) == DDI_SUCCESS) {
302cb7ea99dSJimmy Vetayases 
303cb7ea99dSJimmy Vetayases 			if (pci_save_config_regs(cdip) != DDI_SUCCESS) {
304cb7ea99dSJimmy Vetayases 				cmn_err(CE_WARN, "Failed to save HT config "
305cb7ea99dSJimmy Vetayases 				    "regs for %s\n", ddi_node_name(cdip));
306cb7ea99dSJimmy Vetayases 				rval = DDI_FAILURE;
307cb7ea99dSJimmy Vetayases 
308cb7ea99dSJimmy Vetayases 			} else if (ddi_prop_update_int(DDI_DEV_T_NONE, cdip,
309cb7ea99dSJimmy Vetayases 			    "htconfig-saved", 1) != DDI_SUCCESS) {
310cb7ea99dSJimmy Vetayases 				cmn_err(CE_WARN, "Failed to set htconfig-saved "
311cb7ea99dSJimmy Vetayases 				    "property for %s\n", ddi_node_name(cdip));
312cb7ea99dSJimmy Vetayases 				rval = DDI_FAILURE;
313cb7ea99dSJimmy Vetayases 			}
314cb7ea99dSJimmy Vetayases 		}
315cb7ea99dSJimmy Vetayases 
316cb7ea99dSJimmy Vetayases 		pci_config_teardown(&cfg_hdl);
317cb7ea99dSJimmy Vetayases 	}
318cb7ea99dSJimmy Vetayases 
319cb7ea99dSJimmy Vetayases 	return (rval);
320cb7ea99dSJimmy Vetayases }
321cb7ea99dSJimmy Vetayases 
322cb7ea99dSJimmy Vetayases int
npe_restore_htconfig_children(dev_info_t * dip)323cb7ea99dSJimmy Vetayases npe_restore_htconfig_children(dev_info_t *dip)
324cb7ea99dSJimmy Vetayases {
325cb7ea99dSJimmy Vetayases 	dev_info_t *cdip = ddi_get_child(dip);
326cb7ea99dSJimmy Vetayases 	int rval = DDI_SUCCESS;
327cb7ea99dSJimmy Vetayases 
328cb7ea99dSJimmy Vetayases 	for (; cdip != NULL; cdip = ddi_get_next_sibling(cdip)) {
329cb7ea99dSJimmy Vetayases 		if (ddi_prop_get_int(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS,
330cb7ea99dSJimmy Vetayases 		    "htconfig-saved", 0) == 0)
331cb7ea99dSJimmy Vetayases 			continue;
332cb7ea99dSJimmy Vetayases 
333cb7ea99dSJimmy Vetayases 		if (pci_restore_config_regs(cdip) != DDI_SUCCESS) {
334cb7ea99dSJimmy Vetayases 			cmn_err(CE_WARN, "Failed to restore HT config "
335cb7ea99dSJimmy Vetayases 			    "regs for %s\n", ddi_node_name(cdip));
336cb7ea99dSJimmy Vetayases 			rval = DDI_FAILURE;
337cb7ea99dSJimmy Vetayases 		}
338cb7ea99dSJimmy Vetayases 	}
339cb7ea99dSJimmy Vetayases 
340cb7ea99dSJimmy Vetayases 	return (rval);
341cb7ea99dSJimmy Vetayases }
342