1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Library file that has miscellaneous support for npe(7d) 31 */ 32 33 #include <sys/conf.h> 34 #include <sys/pci.h> 35 #include <sys/sunndi.h> 36 #include <sys/acpi/acpi.h> 37 #include <sys/acpi/acpi_pci.h> 38 #include <sys/acpica.h> 39 #include <sys/pci_cap.h> 40 #include <sys/pcie_impl.h> 41 #include <io/pciex/pcie_nvidia.h> 42 43 /* 44 * Prototype declaration 45 */ 46 void npe_query_acpi_mcfg(dev_info_t *dip); 47 void npe_ck804_fix_aer_ptr(ddi_acc_handle_t cfg_hdl); 48 int npe_disable_empty_bridges_workaround(dev_info_t *child); 49 void npe_nvidia_error_mask(ddi_acc_handle_t cfg_hdl); 50 51 /* 52 * Default ecfga base address 53 */ 54 int64_t npe_default_ecfga_base = 0xE0000000; 55 56 extern uint32_t npe_aer_uce_mask; 57 extern boolean_t pcie_full_scan; 58 59 /* 60 * Query the MCFG table using ACPI. If MCFG is found, setup the 61 * 'ecfga-base-address' (Enhanced Configuration Access base address) 62 * property accordingly. Otherwise, set the value of the property 63 * to the default value. 64 */ 65 void 66 npe_query_acpi_mcfg(dev_info_t *dip) 67 { 68 MCFG_TABLE *mcfgp; 69 CFG_BASE_ADDR_ALLOC *cfg_baap; 70 char *cfg_baa_endp; 71 uint64_t ecfga_base; 72 73 /* Query the MCFG table using ACPI */ 74 if (AcpiGetFirmwareTable(MCFG_SIG, 1, ACPI_LOGICAL_ADDRESSING, 75 (ACPI_TABLE_HEADER **)&mcfgp) == AE_OK) { 76 77 cfg_baap = (CFG_BASE_ADDR_ALLOC *)mcfgp->CfgBaseAddrAllocList; 78 cfg_baa_endp = ((char *)mcfgp) + mcfgp->Length; 79 80 while ((char *)cfg_baap < cfg_baa_endp) { 81 ecfga_base = ACPI_GET_ADDRESS(cfg_baap->base_addr); 82 if (ecfga_base != (uint64_t)0) { 83 /* 84 * Setup the 'ecfga-base-address' property to 85 * the base_addr found in the MCFG and return. 86 */ 87 (void) ndi_prop_update_int64(DDI_DEV_T_NONE, 88 dip, "ecfga-base-address", ecfga_base); 89 return; 90 } 91 cfg_baap++; 92 } 93 } 94 /* 95 * If MCFG is not found or ecfga_base is not found in MCFG table, 96 * set the 'ecfga-base-address' property to the default value. 97 */ 98 (void) ndi_prop_update_int64(DDI_DEV_T_NONE, dip, 99 "ecfga-base-address", npe_default_ecfga_base); 100 } 101 102 103 /* 104 * Enable reporting of AER capability next pointer. 105 * This needs to be done only for CK8-04 devices 106 * by setting NV_XVR_VEND_CYA1 (offset 0xf40) bit 13 107 * NOTE: BIOS is disabling this, it needs to be enabled temporarily 108 */ 109 void 110 npe_ck804_fix_aer_ptr(ddi_acc_handle_t cfg_hdl) 111 { 112 ushort_t cya1; 113 114 if ((pci_config_get16(cfg_hdl, PCI_CONF_VENID) == NVIDIA_VENDOR_ID) && 115 (pci_config_get16(cfg_hdl, PCI_CONF_DEVID) == 116 NVIDIA_CK804_DEVICE_ID) && 117 (pci_config_get8(cfg_hdl, PCI_CONF_REVID) >= 118 NVIDIA_CK804_AER_VALID_REVID)) { 119 cya1 = pci_config_get16(cfg_hdl, NVIDIA_CK804_VEND_CYA1_OFF); 120 if (!(cya1 & ~NVIDIA_CK804_VEND_CYA1_ERPT_MASK)) 121 (void) pci_config_put16(cfg_hdl, 122 NVIDIA_CK804_VEND_CYA1_OFF, 123 cya1 | NVIDIA_CK804_VEND_CYA1_ERPT_VAL); 124 } 125 } 126 127 /* 128 * If the bridge is empty, disable it 129 */ 130 int 131 npe_disable_empty_bridges_workaround(dev_info_t *child) 132 { 133 /* 134 * Do not bind drivers to empty bridges. 135 * Fail above, if the bridge is found to be hotplug capable 136 */ 137 if (ddi_driver_major(child) == ddi_name_to_major("pcie_pci") && 138 ddi_get_child(child) == NULL && 139 ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 140 "pci-hotplug-type", INBAND_HPC_NONE) == INBAND_HPC_NONE) 141 return (1); 142 143 return (0); 144 } 145 146 void 147 npe_nvidia_error_mask(ddi_acc_handle_t cfg_hdl) { 148 uint32_t regs; 149 uint16_t vendor_id = pci_config_get16(cfg_hdl, PCI_CONF_VENID); 150 uint16_t dev_id = pci_config_get16(cfg_hdl, PCI_CONF_DEVID); 151 152 if ((vendor_id == NVIDIA_VENDOR_ID) && NVIDIA_PCIE_RC_DEV_ID(dev_id)) { 153 /* Disable ECRC for all devices */ 154 regs = pcie_get_aer_uce_mask() | npe_aer_uce_mask | 155 PCIE_AER_UCE_ECRC; 156 pcie_set_aer_uce_mask(regs); 157 158 /* 159 * Turn full scan on since the Error Source ID register may not 160 * have the correct ID. 161 */ 162 pcie_full_scan = B_TRUE; 163 } 164 } 165