110187SKrishna.Elango@Sun.COM /* 210187SKrishna.Elango@Sun.COM * CDDL HEADER START 310187SKrishna.Elango@Sun.COM * 410187SKrishna.Elango@Sun.COM * The contents of this file are subject to the terms of the 510187SKrishna.Elango@Sun.COM * Common Development and Distribution License (the "License"). 610187SKrishna.Elango@Sun.COM * You may not use this file except in compliance with the License. 710187SKrishna.Elango@Sun.COM * 810187SKrishna.Elango@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 910187SKrishna.Elango@Sun.COM * or http://www.opensolaris.org/os/licensing. 1010187SKrishna.Elango@Sun.COM * See the License for the specific language governing permissions 1110187SKrishna.Elango@Sun.COM * and limitations under the License. 1210187SKrishna.Elango@Sun.COM * 1310187SKrishna.Elango@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 1410187SKrishna.Elango@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1510187SKrishna.Elango@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 1610187SKrishna.Elango@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 1710187SKrishna.Elango@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 1810187SKrishna.Elango@Sun.COM * 1910187SKrishna.Elango@Sun.COM * CDDL HEADER END 2010187SKrishna.Elango@Sun.COM */ 2110187SKrishna.Elango@Sun.COM /* 2210187SKrishna.Elango@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2310187SKrishna.Elango@Sun.COM * Use is subject to license terms. 2410187SKrishna.Elango@Sun.COM */ 2510187SKrishna.Elango@Sun.COM 2610187SKrishna.Elango@Sun.COM /* x86 specific code used by the pcieb driver */ 2710187SKrishna.Elango@Sun.COM 2810187SKrishna.Elango@Sun.COM #include <sys/types.h> 2910187SKrishna.Elango@Sun.COM #include <sys/ddi.h> 3010187SKrishna.Elango@Sun.COM #include <sys/kmem.h> 3110187SKrishna.Elango@Sun.COM #include <sys/sysmacros.h> 3210187SKrishna.Elango@Sun.COM #include <sys/sunddi.h> 3310187SKrishna.Elango@Sun.COM #include <sys/sunndi.h> 3410187SKrishna.Elango@Sun.COM #include <sys/pcie.h> 3510187SKrishna.Elango@Sun.COM #include <sys/pci_cap.h> 3610187SKrishna.Elango@Sun.COM #include <sys/pcie_impl.h> 3710187SKrishna.Elango@Sun.COM #include <sys/pcie_acpi.h> 3810187SKrishna.Elango@Sun.COM #include <sys/hotplug/hpctrl.h> 3910187SKrishna.Elango@Sun.COM #include <io/pciex/pcieb.h> 4010187SKrishna.Elango@Sun.COM #include <io/pciex/pcie_nb5000.h> 4110187SKrishna.Elango@Sun.COM 4210187SKrishna.Elango@Sun.COM /* Flag to turn off intel error handling workarounds */ 4310187SKrishna.Elango@Sun.COM int pcieb_intel_workaround_disable = 0; 4410187SKrishna.Elango@Sun.COM 4510187SKrishna.Elango@Sun.COM void 4610187SKrishna.Elango@Sun.COM pcieb_peekpoke_cb(dev_info_t *dip, ddi_fm_error_t *derr) { 4710187SKrishna.Elango@Sun.COM (void) pf_scan_fabric(dip, derr, NULL); 4810187SKrishna.Elango@Sun.COM } 4910187SKrishna.Elango@Sun.COM 5010187SKrishna.Elango@Sun.COM int 5110187SKrishna.Elango@Sun.COM pcieb_plat_peekpoke(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop, 5210187SKrishna.Elango@Sun.COM void *arg, void *result) 5310187SKrishna.Elango@Sun.COM { 5410187SKrishna.Elango@Sun.COM pcieb_devstate_t *pcieb = ddi_get_soft_state(pcieb_state, 5510187SKrishna.Elango@Sun.COM ddi_get_instance(dip)); 5610187SKrishna.Elango@Sun.COM 5710187SKrishna.Elango@Sun.COM if (!PCIE_IS_RP(PCIE_DIP2BUS(dip))) 5810187SKrishna.Elango@Sun.COM return (ddi_ctlops(dip, rdip, ctlop, arg, result)); 5910187SKrishna.Elango@Sun.COM 6010187SKrishna.Elango@Sun.COM return (pci_peekpoke_check(dip, rdip, ctlop, arg, result, 6110187SKrishna.Elango@Sun.COM ddi_ctlops, &pcieb->pcieb_err_mutex, 6210187SKrishna.Elango@Sun.COM &pcieb->pcieb_peek_poke_mutex, 6310187SKrishna.Elango@Sun.COM pcieb_peekpoke_cb)); 6410187SKrishna.Elango@Sun.COM } 6510187SKrishna.Elango@Sun.COM 6610187SKrishna.Elango@Sun.COM /* x86 specific workarounds needed at the end of pcieb attach */ 6710187SKrishna.Elango@Sun.COM void 6810187SKrishna.Elango@Sun.COM pcieb_plat_attach_workaround(dev_info_t *dip) 6910187SKrishna.Elango@Sun.COM { 7010187SKrishna.Elango@Sun.COM /* Must apply workaround only after all initialization is done */ 7110187SKrishna.Elango@Sun.COM pcieb_intel_error_workaround(dip); 7210187SKrishna.Elango@Sun.COM pcieb_intel_mps_workaround(dip); 7310187SKrishna.Elango@Sun.COM 7410187SKrishna.Elango@Sun.COM } 7510187SKrishna.Elango@Sun.COM 7610187SKrishna.Elango@Sun.COM /* Workarounds to enable error handling on certain Intel chipsets */ 7710187SKrishna.Elango@Sun.COM void 7810187SKrishna.Elango@Sun.COM pcieb_intel_error_workaround(dev_info_t *dip) 7910187SKrishna.Elango@Sun.COM { 8010187SKrishna.Elango@Sun.COM pcieb_devstate_t *pcieb = ddi_get_soft_state(pcieb_state, 8110187SKrishna.Elango@Sun.COM ddi_get_instance(dip)); 8210187SKrishna.Elango@Sun.COM 8310187SKrishna.Elango@Sun.COM pcieb_intel_serr_workaround(dip, pcieb->pcieb_no_aer_msi); 8410187SKrishna.Elango@Sun.COM pcieb_intel_rber_workaround(dip); 8510187SKrishna.Elango@Sun.COM pcieb_intel_sw_workaround(dip); 8610187SKrishna.Elango@Sun.COM } 8710187SKrishna.Elango@Sun.COM 8810187SKrishna.Elango@Sun.COM int 8910187SKrishna.Elango@Sun.COM pcieb_plat_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op, 9010187SKrishna.Elango@Sun.COM ddi_intr_handle_impl_t *hdlp, void *result) 9110187SKrishna.Elango@Sun.COM { 9210187SKrishna.Elango@Sun.COM return (i_ddi_intr_ops(dip, rdip, intr_op, hdlp, result)); 9310187SKrishna.Elango@Sun.COM } 9410187SKrishna.Elango@Sun.COM 9510187SKrishna.Elango@Sun.COM /* shpc is not supported on x86 */ 9610187SKrishna.Elango@Sun.COM /*ARGSUSED*/ 9710187SKrishna.Elango@Sun.COM int 9810187SKrishna.Elango@Sun.COM pcieb_plat_pcishpc_probe(dev_info_t *dip, ddi_acc_handle_t config_handle) 9910187SKrishna.Elango@Sun.COM { 10010187SKrishna.Elango@Sun.COM return (DDI_FAILURE); 10110187SKrishna.Elango@Sun.COM } 10210187SKrishna.Elango@Sun.COM 10310187SKrishna.Elango@Sun.COM /* 10410187SKrishna.Elango@Sun.COM * Dummy functions to get around the fact that there's no shpc module on x86 10510187SKrishna.Elango@Sun.COM * today 10610187SKrishna.Elango@Sun.COM */ 10710187SKrishna.Elango@Sun.COM /*ARGSUSED*/ 10810187SKrishna.Elango@Sun.COM int 10910187SKrishna.Elango@Sun.COM pcishpc_init(dev_info_t *dip) 11010187SKrishna.Elango@Sun.COM { 11110187SKrishna.Elango@Sun.COM return (DDI_FAILURE); 11210187SKrishna.Elango@Sun.COM } 11310187SKrishna.Elango@Sun.COM 11410187SKrishna.Elango@Sun.COM /*ARGSUSED*/ 11510187SKrishna.Elango@Sun.COM int 11610187SKrishna.Elango@Sun.COM pcishpc_uninit(dev_info_t *dip) 11710187SKrishna.Elango@Sun.COM { 11810187SKrishna.Elango@Sun.COM return (DDI_FAILURE); 11910187SKrishna.Elango@Sun.COM } 12010187SKrishna.Elango@Sun.COM 12110187SKrishna.Elango@Sun.COM /*ARGSUSED*/ 12210187SKrishna.Elango@Sun.COM int 12310187SKrishna.Elango@Sun.COM pcishpc_intr(dev_info_t *dip) 12410187SKrishna.Elango@Sun.COM { 12510187SKrishna.Elango@Sun.COM return (DDI_INTR_UNCLAIMED); 12610187SKrishna.Elango@Sun.COM } 12710187SKrishna.Elango@Sun.COM 12810187SKrishna.Elango@Sun.COM /*ARGSUSED*/ 12910187SKrishna.Elango@Sun.COM boolean_t 13010187SKrishna.Elango@Sun.COM pcieb_plat_pwr_disable(dev_info_t *dip) 13110187SKrishna.Elango@Sun.COM { 13210187SKrishna.Elango@Sun.COM /* Always disable on x86 */ 13310187SKrishna.Elango@Sun.COM return (B_TRUE); 13410187SKrishna.Elango@Sun.COM } 13510187SKrishna.Elango@Sun.COM 13610187SKrishna.Elango@Sun.COM boolean_t 13710187SKrishna.Elango@Sun.COM pcieb_plat_msi_supported(dev_info_t *dip) 13810187SKrishna.Elango@Sun.COM { 13910187SKrishna.Elango@Sun.COM pcie_bus_t *bus_p = PCIE_DIP2UPBUS(dip); 14010187SKrishna.Elango@Sun.COM uint16_t vendor_id, device_id; 14110187SKrishna.Elango@Sun.COM vendor_id = bus_p->bus_dev_ven_id & 0xFFFF; 14210187SKrishna.Elango@Sun.COM device_id = bus_p->bus_dev_ven_id >> 16; 14310187SKrishna.Elango@Sun.COM 14410187SKrishna.Elango@Sun.COM /* 14510187SKrishna.Elango@Sun.COM * Intel ESB2 switches have a errata which prevents using MSIs 14610187SKrishna.Elango@Sun.COM * for hotplug. 14710187SKrishna.Elango@Sun.COM */ 14810187SKrishna.Elango@Sun.COM return (((vendor_id == INTEL_VENDOR_ID) && 14910187SKrishna.Elango@Sun.COM INTEL_ESB2_SW_PCIE_DEV_ID(device_id)) ? B_FALSE : B_TRUE); 15010187SKrishna.Elango@Sun.COM } 15110187SKrishna.Elango@Sun.COM 15210187SKrishna.Elango@Sun.COM void 15310187SKrishna.Elango@Sun.COM pcieb_plat_intr_attach(pcieb_devstate_t *pcieb) 15410187SKrishna.Elango@Sun.COM { 15510187SKrishna.Elango@Sun.COM /* 15610187SKrishna.Elango@Sun.COM * _OSC initialization needs to be done before interrupts are 15710187SKrishna.Elango@Sun.COM * initialized. 15810187SKrishna.Elango@Sun.COM */ 15910187SKrishna.Elango@Sun.COM pcieb_init_osc(pcieb->pcieb_dip); 16010187SKrishna.Elango@Sun.COM } 16110187SKrishna.Elango@Sun.COM 16210187SKrishna.Elango@Sun.COM void 16310187SKrishna.Elango@Sun.COM pcieb_plat_initchild(dev_info_t *child) 16410187SKrishna.Elango@Sun.COM { 16510187SKrishna.Elango@Sun.COM struct ddi_parent_private_data *pdptr; 16610187SKrishna.Elango@Sun.COM if (ddi_getprop(DDI_DEV_T_NONE, child, DDI_PROP_DONTPASS, "interrupts", 16710187SKrishna.Elango@Sun.COM -1) != -1) { 16810187SKrishna.Elango@Sun.COM pdptr = kmem_zalloc((sizeof (struct ddi_parent_private_data) + 16910187SKrishna.Elango@Sun.COM sizeof (struct intrspec)), KM_SLEEP); 17010187SKrishna.Elango@Sun.COM pdptr->par_intr = (struct intrspec *)(pdptr + 1); 17110187SKrishna.Elango@Sun.COM pdptr->par_nintr = 1; 17210187SKrishna.Elango@Sun.COM ddi_set_parent_data(child, pdptr); 17310187SKrishna.Elango@Sun.COM } else 17410187SKrishna.Elango@Sun.COM ddi_set_parent_data(child, NULL); 17510187SKrishna.Elango@Sun.COM } 17610187SKrishna.Elango@Sun.COM 17710187SKrishna.Elango@Sun.COM void 17810187SKrishna.Elango@Sun.COM pcieb_plat_uninitchild(dev_info_t *child) 17910187SKrishna.Elango@Sun.COM { 18010187SKrishna.Elango@Sun.COM struct ddi_parent_private_data *pdptr; 18110187SKrishna.Elango@Sun.COM 18210187SKrishna.Elango@Sun.COM if ((pdptr = ddi_get_parent_data(child)) != NULL) 18310187SKrishna.Elango@Sun.COM kmem_free(pdptr, (sizeof (*pdptr) + sizeof (struct intrspec))); 18410187SKrishna.Elango@Sun.COM 18510187SKrishna.Elango@Sun.COM ddi_set_parent_data(child, NULL); 18610187SKrishna.Elango@Sun.COM } 18710187SKrishna.Elango@Sun.COM 18810187SKrishna.Elango@Sun.COM /* _OSC related */ 18910187SKrishna.Elango@Sun.COM void 19010187SKrishna.Elango@Sun.COM pcieb_init_osc(dev_info_t *devi) { 19110187SKrishna.Elango@Sun.COM pcie_bus_t *bus_p = PCIE_DIP2UPBUS(devi); 19210187SKrishna.Elango@Sun.COM uint32_t osc_flags = OSC_CONTROL_PCIE_ADV_ERR; 19310187SKrishna.Elango@Sun.COM 19410187SKrishna.Elango@Sun.COM /* 19510187SKrishna.Elango@Sun.COM * Call _OSC method for 2 reasons: 19610187SKrishna.Elango@Sun.COM * 1. Hotplug: To determine if it is native or ACPI mode. 19710187SKrishna.Elango@Sun.COM * 19810187SKrishna.Elango@Sun.COM * 2. Error handling: Inform firmware that OS can support AER error 19910187SKrishna.Elango@Sun.COM * handling. Currently we don't care for what the BIOS response was 20010187SKrishna.Elango@Sun.COM * and instead setup interrupts for error handling as if it were 20110187SKrishna.Elango@Sun.COM * supported. 20210187SKrishna.Elango@Sun.COM * 20310187SKrishna.Elango@Sun.COM * For hotpluggable slots the _OSC method has already been called as 20410187SKrishna.Elango@Sun.COM * part of the hotplug initialization. 20510187SKrishna.Elango@Sun.COM * For non-hotpluggable slots we need to call the _OSC method only for 20610187SKrishna.Elango@Sun.COM * Root Ports (for AER support). 20710187SKrishna.Elango@Sun.COM */ 20810187SKrishna.Elango@Sun.COM if (!pcie_is_osc(devi) && PCIE_IS_RP(bus_p) && PCIE_HAS_AER(bus_p)) 20910187SKrishna.Elango@Sun.COM (void) pcie_acpi_osc(devi, &osc_flags); 21010187SKrishna.Elango@Sun.COM } 21110187SKrishna.Elango@Sun.COM 21210187SKrishna.Elango@Sun.COM /* 21310187SKrishna.Elango@Sun.COM * Intel chip specific workarounds. Right now they're limited to the 5000, 5400 21410187SKrishna.Elango@Sun.COM * and 7300 series chipsets. 21510187SKrishna.Elango@Sun.COM */ 21610187SKrishna.Elango@Sun.COM typedef struct x86_error_reg { 21710187SKrishna.Elango@Sun.COM uint32_t offset; 21810187SKrishna.Elango@Sun.COM uint_t size; 21910187SKrishna.Elango@Sun.COM uint32_t mask; 22010187SKrishna.Elango@Sun.COM uint32_t value1; /* Value for MSI case */ 22110187SKrishna.Elango@Sun.COM uint32_t value2; /* Value for machinecheck case */ 22210187SKrishna.Elango@Sun.COM } x86_error_reg_t; 22310187SKrishna.Elango@Sun.COM 22410187SKrishna.Elango@Sun.COM typedef struct x86_error_tbl { 22510187SKrishna.Elango@Sun.COM uint16_t vendor_id; 22610187SKrishna.Elango@Sun.COM uint16_t device_id_low; 22710187SKrishna.Elango@Sun.COM uint16_t device_id_high; 22810187SKrishna.Elango@Sun.COM uint8_t rev_id_low; 22910187SKrishna.Elango@Sun.COM uint8_t rev_id_high; 23010187SKrishna.Elango@Sun.COM x86_error_reg_t *error_regs; 23110187SKrishna.Elango@Sun.COM int error_regs_len; 23210187SKrishna.Elango@Sun.COM } x86_error_tbl_t; 23310187SKrishna.Elango@Sun.COM 23410187SKrishna.Elango@Sun.COM /* 23510187SKrishna.Elango@Sun.COM * Chipset and device specific settings that are required for error handling 23610187SKrishna.Elango@Sun.COM * (reporting, fowarding, and response at the RC) beyond the standard 23710187SKrishna.Elango@Sun.COM * registers in the PCIE and AER caps. 23810187SKrishna.Elango@Sun.COM * 23910187SKrishna.Elango@Sun.COM * The Northbridge Root Port settings also apply to the ESI port. The ESI 24010187SKrishna.Elango@Sun.COM * port is a special leaf device but functions like a root port connected 24110187SKrishna.Elango@Sun.COM * to the Southbridge and receives all the onboard Southbridge errors 24210187SKrishna.Elango@Sun.COM * including those from Southbridge Root Ports. However, this does not 24310187SKrishna.Elango@Sun.COM * include the Southbridge Switch Ports which act like normal switch ports 24410187SKrishna.Elango@Sun.COM * and is connected to the Northbridge through a separate link. 24510187SKrishna.Elango@Sun.COM * 24610187SKrishna.Elango@Sun.COM * PCIE errors from the ESB2 Southbridge RPs are simply fowarded to the ESI 24710187SKrishna.Elango@Sun.COM * port on the Northbridge. 24810187SKrishna.Elango@Sun.COM * 24910187SKrishna.Elango@Sun.COM * If MSIs don't work we want UEs (Fatal and Non-Fatal) to panic the system, 25010187SKrishna.Elango@Sun.COM * except for URs. We do this by having the Root Ports respond with a System 25110187SKrishna.Elango@Sun.COM * Error and having that trigger a Machine Check (MCE). 25210187SKrishna.Elango@Sun.COM */ 25310187SKrishna.Elango@Sun.COM 25410187SKrishna.Elango@Sun.COM /* 25510187SKrishna.Elango@Sun.COM * 7300 Northbridge Root Ports 25610187SKrishna.Elango@Sun.COM */ 25710187SKrishna.Elango@Sun.COM static x86_error_reg_t intel_7300_rp_regs[] = { 25810187SKrishna.Elango@Sun.COM /* Command Register - Enable SERR */ 25910187SKrishna.Elango@Sun.COM {0x4, 16, 0xFFFF, 0x0, PCI_COMM_SERR_ENABLE}, 26010187SKrishna.Elango@Sun.COM 26110187SKrishna.Elango@Sun.COM /* Root Control Register - SERR on NFE/FE */ 26210187SKrishna.Elango@Sun.COM {0x88, 16, 0x0, 0x0, PCIE_ROOTCTL_SYS_ERR_ON_NFE_EN | 26310187SKrishna.Elango@Sun.COM PCIE_ROOTCTL_SYS_ERR_ON_FE_EN}, 26410187SKrishna.Elango@Sun.COM 26510187SKrishna.Elango@Sun.COM /* AER UE Mask - Mask UR */ 26610187SKrishna.Elango@Sun.COM {0x108, 32, 0x0, PCIE_AER_UCE_UR, PCIE_AER_UCE_UR}, 26710187SKrishna.Elango@Sun.COM 26810187SKrishna.Elango@Sun.COM /* PEXCTRL[21] check for certain malformed TLP types and MSI enable */ 26910187SKrishna.Elango@Sun.COM {0x48, 32, 0xFFFFFFFF, 0xC0200000, 0x200000}, 27010187SKrishna.Elango@Sun.COM /* PEXCTRL3[7]. MSI RAS error enable */ 27110187SKrishna.Elango@Sun.COM {0x4D, 32, 0xFFFFFFFF, 0x1, 0x0}, 27210187SKrishna.Elango@Sun.COM 27310187SKrishna.Elango@Sun.COM /* PEX_ERR_DOCMD[7:0] */ 27410187SKrishna.Elango@Sun.COM {0x144, 8, 0x0, 0x0, 0xF0}, 27510187SKrishna.Elango@Sun.COM 27610187SKrishna.Elango@Sun.COM /* EMASK_UNCOR_PEX[21:0] UE mask */ 27710187SKrishna.Elango@Sun.COM {0x148, 32, 0x0, PCIE_AER_UCE_UR, PCIE_AER_UCE_UR}, 27810187SKrishna.Elango@Sun.COM 27910187SKrishna.Elango@Sun.COM /* EMASK_RP_PEX[2:0] FE, UE, CE message detect mask */ 28010187SKrishna.Elango@Sun.COM {0x150, 8, 0x0, 0x0, 0x1}, 28110187SKrishna.Elango@Sun.COM }; 28210187SKrishna.Elango@Sun.COM #define INTEL_7300_RP_REGS_LEN \ 28310187SKrishna.Elango@Sun.COM (sizeof (intel_7300_rp_regs) / sizeof (x86_error_reg_t)) 28410187SKrishna.Elango@Sun.COM 28510187SKrishna.Elango@Sun.COM /* 28610187SKrishna.Elango@Sun.COM * 5000 Northbridge Root Ports 28710187SKrishna.Elango@Sun.COM */ 28810187SKrishna.Elango@Sun.COM static x86_error_reg_t intel_5000_rp_regs[] = { 28910187SKrishna.Elango@Sun.COM /* Command Register - Enable SERR */ 29010187SKrishna.Elango@Sun.COM {0x4, 16, 0xFFFF, PCI_COMM_SERR_ENABLE, PCI_COMM_SERR_ENABLE}, 29110187SKrishna.Elango@Sun.COM 29210187SKrishna.Elango@Sun.COM /* Root Control Register - SERR on NFE/FE/CE */ 29310187SKrishna.Elango@Sun.COM {0x88, 16, 0x0, PCIE_ROOTCTL_SYS_ERR_ON_NFE_EN | 29410187SKrishna.Elango@Sun.COM PCIE_ROOTCTL_SYS_ERR_ON_FE_EN | 29510187SKrishna.Elango@Sun.COM PCIE_ROOTCTL_SYS_ERR_ON_CE_EN, 29610187SKrishna.Elango@Sun.COM PCIE_ROOTCTL_SYS_ERR_ON_NFE_EN | 29710187SKrishna.Elango@Sun.COM PCIE_ROOTCTL_SYS_ERR_ON_FE_EN}, 29810187SKrishna.Elango@Sun.COM 29910187SKrishna.Elango@Sun.COM /* AER UE Mask - Mask UR */ 30010187SKrishna.Elango@Sun.COM {0x108, 32, 0x0, PCIE_AER_UCE_UR, PCIE_AER_UCE_UR}, 30110187SKrishna.Elango@Sun.COM 30210187SKrishna.Elango@Sun.COM /* PEXCTRL[21] check for certain malformed TLP type */ 30310187SKrishna.Elango@Sun.COM {0x48, 32, 0xFFFFFFFF, 0xC0200000, 0x200000}, 30410187SKrishna.Elango@Sun.COM /* PEXCTRL3[7]. MSI RAS error enable. */ 30510187SKrishna.Elango@Sun.COM {0x4D, 32, 0xFFFFFFFF, 0x1, 0x0}, 30610187SKrishna.Elango@Sun.COM 30710187SKrishna.Elango@Sun.COM /* PEX_ERR_DOCMD[7:0] */ 30810187SKrishna.Elango@Sun.COM {0x144, 8, 0x0, 0x0, 0xF0}, 30910187SKrishna.Elango@Sun.COM 31010187SKrishna.Elango@Sun.COM /* EMASK_UNCOR_PEX[21:0] UE mask */ 31110187SKrishna.Elango@Sun.COM {0x148, 32, 0x0, PCIE_AER_UCE_UR, PCIE_AER_UCE_UR}, 31210187SKrishna.Elango@Sun.COM 31310187SKrishna.Elango@Sun.COM /* EMASK_RP_PEX[2:0] FE, UE, CE message detect mask */ 31410187SKrishna.Elango@Sun.COM {0x150, 8, 0x0, 0x0, 0x1}, 31510187SKrishna.Elango@Sun.COM }; 31610187SKrishna.Elango@Sun.COM #define INTEL_5000_RP_REGS_LEN \ 31710187SKrishna.Elango@Sun.COM (sizeof (intel_5000_rp_regs) / sizeof (x86_error_reg_t)) 31810187SKrishna.Elango@Sun.COM 31910187SKrishna.Elango@Sun.COM /* 32010187SKrishna.Elango@Sun.COM * 5400 Northbridge Root Ports. 32110187SKrishna.Elango@Sun.COM */ 32210187SKrishna.Elango@Sun.COM static x86_error_reg_t intel_5400_rp_regs[] = { 32310187SKrishna.Elango@Sun.COM /* Command Register - Enable SERR */ 32410187SKrishna.Elango@Sun.COM {0x4, 16, 0xFFFF, PCI_COMM_SERR_ENABLE, PCI_COMM_SERR_ENABLE}, 32510187SKrishna.Elango@Sun.COM 32610187SKrishna.Elango@Sun.COM /* Root Control Register - SERR on NFE/FE */ 32710187SKrishna.Elango@Sun.COM {0x88, 16, 0x0, PCIE_ROOTCTL_SYS_ERR_ON_NFE_EN | 32810187SKrishna.Elango@Sun.COM PCIE_ROOTCTL_SYS_ERR_ON_FE_EN | 32910187SKrishna.Elango@Sun.COM PCIE_ROOTCTL_SYS_ERR_ON_CE_EN, 33010187SKrishna.Elango@Sun.COM PCIE_ROOTCTL_SYS_ERR_ON_NFE_EN | 33110187SKrishna.Elango@Sun.COM PCIE_ROOTCTL_SYS_ERR_ON_FE_EN}, 33210187SKrishna.Elango@Sun.COM 33310187SKrishna.Elango@Sun.COM /* AER UE Mask - Mask UR */ 33410187SKrishna.Elango@Sun.COM {0x108, 32, 0x0, PCIE_AER_UCE_UR, PCIE_AER_UCE_UR}, 33510187SKrishna.Elango@Sun.COM 33610187SKrishna.Elango@Sun.COM /* PEXCTRL[21] check for certain malformed TLP types */ 33710187SKrishna.Elango@Sun.COM {0x48, 32, 0xFFFFFFFF, 0xC0200000, 0x200000}, 33810187SKrishna.Elango@Sun.COM /* PEXCTRL3. MSI RAS error enable. */ 33910187SKrishna.Elango@Sun.COM {0x4E, 8, 0x0, 0x1, 0x0}, 34010187SKrishna.Elango@Sun.COM 34110187SKrishna.Elango@Sun.COM /* PEX_ERR_DOCMD[11:0] */ 34210187SKrishna.Elango@Sun.COM {0x144, 16, 0x0, 0x0, 0xFF0}, 34310187SKrishna.Elango@Sun.COM 34410187SKrishna.Elango@Sun.COM /* PEX_ERR_PIN_MASK[4:0] do not mask ERR[2:0] pins used by DOCMD */ 34510187SKrishna.Elango@Sun.COM {0x146, 16, 0x0, 0x10, 0x10}, 34610187SKrishna.Elango@Sun.COM 34710187SKrishna.Elango@Sun.COM /* EMASK_UNCOR_PEX[21:0] UE mask */ 34810187SKrishna.Elango@Sun.COM {0x148, 32, 0x0, PCIE_AER_UCE_UR, PCIE_AER_UCE_UR}, 34910187SKrishna.Elango@Sun.COM 35010187SKrishna.Elango@Sun.COM /* EMASK_RP_PEX[2:0] FE, UE, CE message detect mask */ 35110187SKrishna.Elango@Sun.COM {0x150, 8, 0x0, 0x0, 0x1}, 35210187SKrishna.Elango@Sun.COM }; 35310187SKrishna.Elango@Sun.COM #define INTEL_5400_RP_REGS_LEN \ 35410187SKrishna.Elango@Sun.COM (sizeof (intel_5400_rp_regs) / sizeof (x86_error_reg_t)) 35510187SKrishna.Elango@Sun.COM 35610187SKrishna.Elango@Sun.COM 35710187SKrishna.Elango@Sun.COM /* 35810187SKrishna.Elango@Sun.COM * ESB2 Southbridge Root Ports 35910187SKrishna.Elango@Sun.COM */ 36010187SKrishna.Elango@Sun.COM static x86_error_reg_t intel_esb2_rp_regs[] = { 36110187SKrishna.Elango@Sun.COM /* Command Register - Enable SERR */ 36210187SKrishna.Elango@Sun.COM {0x4, 16, 0xFFFF, PCI_COMM_SERR_ENABLE, PCI_COMM_SERR_ENABLE}, 36310187SKrishna.Elango@Sun.COM 36410187SKrishna.Elango@Sun.COM /* Root Control Register - SERR on NFE/FE */ 36510187SKrishna.Elango@Sun.COM {0x5c, 16, 0x0, PCIE_ROOTCTL_SYS_ERR_ON_NFE_EN | 36610187SKrishna.Elango@Sun.COM PCIE_ROOTCTL_SYS_ERR_ON_FE_EN | 36710187SKrishna.Elango@Sun.COM PCIE_ROOTCTL_SYS_ERR_ON_CE_EN, 36810187SKrishna.Elango@Sun.COM PCIE_ROOTCTL_SYS_ERR_ON_NFE_EN | 36910187SKrishna.Elango@Sun.COM PCIE_ROOTCTL_SYS_ERR_ON_FE_EN}, 37010187SKrishna.Elango@Sun.COM 37110187SKrishna.Elango@Sun.COM /* UEM[20:0] UE mask (write-once) */ 37210187SKrishna.Elango@Sun.COM {0x148, 32, 0x0, PCIE_AER_UCE_UR, PCIE_AER_UCE_UR}, 37310187SKrishna.Elango@Sun.COM }; 37410187SKrishna.Elango@Sun.COM #define INTEL_ESB2_RP_REGS_LEN \ 37510187SKrishna.Elango@Sun.COM (sizeof (intel_esb2_rp_regs) / sizeof (x86_error_reg_t)) 37610187SKrishna.Elango@Sun.COM 37710187SKrishna.Elango@Sun.COM 37810187SKrishna.Elango@Sun.COM /* 37910187SKrishna.Elango@Sun.COM * ESB2 Southbridge Switch Ports 38010187SKrishna.Elango@Sun.COM */ 38110187SKrishna.Elango@Sun.COM static x86_error_reg_t intel_esb2_sw_regs[] = { 38210187SKrishna.Elango@Sun.COM /* Command Register - Enable SERR */ 38310187SKrishna.Elango@Sun.COM {0x4, 16, 0xFFFF, PCI_COMM_SERR_ENABLE, PCI_COMM_SERR_ENABLE}, 38410187SKrishna.Elango@Sun.COM 38510187SKrishna.Elango@Sun.COM /* AER UE Mask - Mask UR */ 38610187SKrishna.Elango@Sun.COM {0x108, 32, 0x0, PCIE_AER_UCE_UR, PCIE_AER_UCE_UR}, 38710187SKrishna.Elango@Sun.COM }; 38810187SKrishna.Elango@Sun.COM #define INTEL_ESB2_SW_REGS_LEN \ 38910187SKrishna.Elango@Sun.COM (sizeof (intel_esb2_sw_regs) / sizeof (x86_error_reg_t)) 39010187SKrishna.Elango@Sun.COM 39110187SKrishna.Elango@Sun.COM 39210187SKrishna.Elango@Sun.COM x86_error_tbl_t x86_error_init_tbl[] = { 39310187SKrishna.Elango@Sun.COM /* Intel 7300: 3600 = ESI, 3604-360A = NB root ports */ 39410187SKrishna.Elango@Sun.COM {0x8086, 0x3600, 0x3600, 0x0, 0xFF, 39510187SKrishna.Elango@Sun.COM intel_7300_rp_regs, INTEL_7300_RP_REGS_LEN}, 39610187SKrishna.Elango@Sun.COM {0x8086, 0x3604, 0x360A, 0x0, 0xFF, 39710187SKrishna.Elango@Sun.COM intel_7300_rp_regs, INTEL_7300_RP_REGS_LEN}, 39810187SKrishna.Elango@Sun.COM 39910187SKrishna.Elango@Sun.COM /* Intel 5000: 25C0, 25D0, 25D4, 25D8 = ESI */ 40010187SKrishna.Elango@Sun.COM {0x8086, 0x25C0, 0x25C0, 0x0, 0xFF, 40110187SKrishna.Elango@Sun.COM intel_5000_rp_regs, INTEL_5000_RP_REGS_LEN}, 40210187SKrishna.Elango@Sun.COM {0x8086, 0x25D0, 0x25D0, 0x0, 0xFF, 40310187SKrishna.Elango@Sun.COM intel_5000_rp_regs, INTEL_5000_RP_REGS_LEN}, 40410187SKrishna.Elango@Sun.COM {0x8086, 0x25D4, 0x25D4, 0x0, 0xFF, 40510187SKrishna.Elango@Sun.COM intel_5000_rp_regs, INTEL_5000_RP_REGS_LEN}, 40610187SKrishna.Elango@Sun.COM {0x8086, 0x25D8, 0x25D8, 0x0, 0xFF, 40710187SKrishna.Elango@Sun.COM intel_5000_rp_regs, INTEL_5000_RP_REGS_LEN}, 40810187SKrishna.Elango@Sun.COM 40910187SKrishna.Elango@Sun.COM /* Intel 5000: 25E2-25E7 and 25F7-25FA = NB root ports */ 41010187SKrishna.Elango@Sun.COM {0x8086, 0x25E2, 0x25E7, 0x0, 0xFF, 41110187SKrishna.Elango@Sun.COM intel_5000_rp_regs, INTEL_5000_RP_REGS_LEN}, 41210187SKrishna.Elango@Sun.COM {0x8086, 0x25F7, 0x25FA, 0x0, 0xFF, 41310187SKrishna.Elango@Sun.COM intel_5000_rp_regs, INTEL_5000_RP_REGS_LEN}, 41410187SKrishna.Elango@Sun.COM 41510187SKrishna.Elango@Sun.COM /* Intel 5400: 4000-4001, 4003 = ESI and 4021-4029 = NB root ports */ 41610187SKrishna.Elango@Sun.COM {0x8086, 0x4000, 0x4001, 0x0, 0xFF, 41710187SKrishna.Elango@Sun.COM intel_5400_rp_regs, INTEL_5400_RP_REGS_LEN}, 41810187SKrishna.Elango@Sun.COM {0x8086, 0x4003, 0x4003, 0x0, 0xFF, 41910187SKrishna.Elango@Sun.COM intel_5400_rp_regs, INTEL_5400_RP_REGS_LEN}, 42010187SKrishna.Elango@Sun.COM {0x8086, 0x4021, 0x4029, 0x0, 0xFF, 42110187SKrishna.Elango@Sun.COM intel_5400_rp_regs, INTEL_5400_RP_REGS_LEN}, 42210187SKrishna.Elango@Sun.COM 42310187SKrishna.Elango@Sun.COM /* Intel 631xESB/632xESB aka ESB2: 2690-2697 = SB root ports */ 42410187SKrishna.Elango@Sun.COM {0x8086, 0x2690, 0x2697, 0x0, 0xFF, 42510187SKrishna.Elango@Sun.COM intel_esb2_rp_regs, INTEL_ESB2_RP_REGS_LEN}, 42610187SKrishna.Elango@Sun.COM 42710187SKrishna.Elango@Sun.COM /* Intel Switches on esb2: 3500-3503, 3510-351B */ 42810187SKrishna.Elango@Sun.COM {0x8086, 0x3500, 0x3503, 0x0, 0xFF, 42910187SKrishna.Elango@Sun.COM intel_esb2_sw_regs, INTEL_ESB2_SW_REGS_LEN}, 43010187SKrishna.Elango@Sun.COM {0x8086, 0x3510, 0x351B, 0x0, 0xFF, 43110187SKrishna.Elango@Sun.COM intel_esb2_sw_regs, INTEL_ESB2_SW_REGS_LEN}, 43210187SKrishna.Elango@Sun.COM 43310187SKrishna.Elango@Sun.COM /* XXX Intel PCIe-PCIx on esb2: 350C */ 43410187SKrishna.Elango@Sun.COM }; 43510187SKrishna.Elango@Sun.COM static int x86_error_init_tbl_len = 43610187SKrishna.Elango@Sun.COM sizeof (x86_error_init_tbl) / sizeof (x86_error_tbl_t); 43710187SKrishna.Elango@Sun.COM 43810187SKrishna.Elango@Sun.COM /* 43910187SKrishna.Elango@Sun.COM * The main goal of this workaround is to set chipset specific settings if 44010187SKrishna.Elango@Sun.COM * MSIs happen to be enabled on this device. Otherwise make the system 44110187SKrishna.Elango@Sun.COM * Machine Check/Panic if an UE is detected in the fabric. 44210187SKrishna.Elango@Sun.COM */ 44310187SKrishna.Elango@Sun.COM void 44410187SKrishna.Elango@Sun.COM pcieb_intel_serr_workaround(dev_info_t *dip, boolean_t mcheck) 44510187SKrishna.Elango@Sun.COM { 44610187SKrishna.Elango@Sun.COM uint16_t vid, did; 44710187SKrishna.Elango@Sun.COM uint8_t rid; 44810187SKrishna.Elango@Sun.COM int i, j; 44910187SKrishna.Elango@Sun.COM x86_error_tbl_t *tbl; 45010187SKrishna.Elango@Sun.COM x86_error_reg_t *reg; 45110187SKrishna.Elango@Sun.COM pcie_bus_t *bus_p = PCIE_DIP2UPBUS(dip); 45210187SKrishna.Elango@Sun.COM ddi_acc_handle_t cfg_hdl = bus_p->bus_cfg_hdl; 45310187SKrishna.Elango@Sun.COM uint16_t bdf = bus_p->bus_bdf; 45410187SKrishna.Elango@Sun.COM 45510187SKrishna.Elango@Sun.COM if (pcieb_intel_workaround_disable) 45610187SKrishna.Elango@Sun.COM return; 45710187SKrishna.Elango@Sun.COM 45810187SKrishna.Elango@Sun.COM vid = bus_p->bus_dev_ven_id & 0xFFFF; 45910187SKrishna.Elango@Sun.COM did = bus_p->bus_dev_ven_id >> 16; 46010187SKrishna.Elango@Sun.COM rid = bus_p->bus_rev_id; 46110187SKrishna.Elango@Sun.COM 46210187SKrishna.Elango@Sun.COM PCIEB_DEBUG(DBG_ATTACH, dip, "VID:0x%x DID:0x%x RID:0x%x bdf=0x%x\n", 46310187SKrishna.Elango@Sun.COM vid, did, rid, bdf); 46410187SKrishna.Elango@Sun.COM 46510187SKrishna.Elango@Sun.COM tbl = x86_error_init_tbl; 46610187SKrishna.Elango@Sun.COM for (i = 0; i < x86_error_init_tbl_len; i++, tbl++) { 46710187SKrishna.Elango@Sun.COM if (!((vid == tbl->vendor_id) && 46810187SKrishna.Elango@Sun.COM (did >= tbl->device_id_low) && 46910187SKrishna.Elango@Sun.COM (did <= tbl->device_id_high) && 47010187SKrishna.Elango@Sun.COM (rid >= tbl->rev_id_low) && 47110187SKrishna.Elango@Sun.COM (rid <= tbl->rev_id_high))) 47210187SKrishna.Elango@Sun.COM continue; 47310187SKrishna.Elango@Sun.COM 47410187SKrishna.Elango@Sun.COM if (mcheck && PCIE_IS_RP(bus_p)) 47510187SKrishna.Elango@Sun.COM pcie_set_rber_fatal(dip, B_TRUE); 47610187SKrishna.Elango@Sun.COM 47710187SKrishna.Elango@Sun.COM reg = tbl->error_regs; 47810187SKrishna.Elango@Sun.COM for (j = 0; j < tbl->error_regs_len; j++, reg++) { 47910187SKrishna.Elango@Sun.COM uint32_t data = 0xDEADBEEF; 48010187SKrishna.Elango@Sun.COM uint32_t value = 0xDEADBEEF; 48110187SKrishna.Elango@Sun.COM switch (reg->size) { 48210187SKrishna.Elango@Sun.COM case 32: 48310187SKrishna.Elango@Sun.COM data = (uint32_t)pci_config_get32(cfg_hdl, 48410187SKrishna.Elango@Sun.COM reg->offset); 48510187SKrishna.Elango@Sun.COM value = (mcheck ? 48610187SKrishna.Elango@Sun.COM ((data & reg->mask) | reg->value2) : 48710187SKrishna.Elango@Sun.COM ((data & reg->mask) | reg->value1)); 48810187SKrishna.Elango@Sun.COM pci_config_put32(cfg_hdl, reg->offset, value); 48910187SKrishna.Elango@Sun.COM value = (uint32_t)pci_config_get32(cfg_hdl, 49010187SKrishna.Elango@Sun.COM reg->offset); 49110187SKrishna.Elango@Sun.COM break; 49210187SKrishna.Elango@Sun.COM case 16: 49310187SKrishna.Elango@Sun.COM data = (uint32_t)pci_config_get16(cfg_hdl, 49410187SKrishna.Elango@Sun.COM reg->offset); 49510187SKrishna.Elango@Sun.COM value = (mcheck ? 49610187SKrishna.Elango@Sun.COM ((data & reg->mask) | reg->value2) : 49710187SKrishna.Elango@Sun.COM ((data & reg->mask) | reg->value1)); 49810187SKrishna.Elango@Sun.COM pci_config_put16(cfg_hdl, reg->offset, 49910187SKrishna.Elango@Sun.COM (uint16_t)value); 50010187SKrishna.Elango@Sun.COM value = (uint32_t)pci_config_get16(cfg_hdl, 50110187SKrishna.Elango@Sun.COM reg->offset); 50210187SKrishna.Elango@Sun.COM break; 50310187SKrishna.Elango@Sun.COM case 8: 50410187SKrishna.Elango@Sun.COM data = (uint32_t)pci_config_get8(cfg_hdl, 50510187SKrishna.Elango@Sun.COM reg->offset); 50610187SKrishna.Elango@Sun.COM value = (mcheck ? 50710187SKrishna.Elango@Sun.COM ((data & reg->mask) | reg->value2) : 50810187SKrishna.Elango@Sun.COM ((data & reg->mask) | reg->value1)); 50910187SKrishna.Elango@Sun.COM pci_config_put8(cfg_hdl, reg->offset, 51010187SKrishna.Elango@Sun.COM (uint8_t)value); 51110187SKrishna.Elango@Sun.COM value = (uint32_t)pci_config_get8(cfg_hdl, 51210187SKrishna.Elango@Sun.COM reg->offset); 51310187SKrishna.Elango@Sun.COM break; 51410187SKrishna.Elango@Sun.COM } 51510187SKrishna.Elango@Sun.COM 51610187SKrishna.Elango@Sun.COM PCIEB_DEBUG(DBG_ATTACH, dip, "bdf:%x mcheck:%d size:%d " 51710187SKrishna.Elango@Sun.COM "off:0x%x mask:0x%x value:0x%x + orig:0x%x -> " 51810187SKrishna.Elango@Sun.COM "0x%x\n", bdf, mcheck, reg->size, reg->offset, 51910187SKrishna.Elango@Sun.COM reg->mask, (mcheck ? reg->value2 : reg->value1), 52010187SKrishna.Elango@Sun.COM data, value); 52110187SKrishna.Elango@Sun.COM } 52210187SKrishna.Elango@Sun.COM } 52310187SKrishna.Elango@Sun.COM } 52410187SKrishna.Elango@Sun.COM 52510187SKrishna.Elango@Sun.COM /* 52610187SKrishna.Elango@Sun.COM * For devices that support Role Base Errors, make several UE have a FATAL 52710187SKrishna.Elango@Sun.COM * severity. That way a Fatal Message will be sent instead of a Correctable 52810187SKrishna.Elango@Sun.COM * Message. Without full FMA support, CEs will be ignored. 52910187SKrishna.Elango@Sun.COM */ 53010187SKrishna.Elango@Sun.COM uint32_t pcieb_rber_sev = (PCIE_AER_UCE_TRAINING | PCIE_AER_UCE_DLP | 53110187SKrishna.Elango@Sun.COM PCIE_AER_UCE_SD | PCIE_AER_UCE_PTLP | PCIE_AER_UCE_FCP | PCIE_AER_UCE_TO | 53210187SKrishna.Elango@Sun.COM PCIE_AER_UCE_CA | PCIE_AER_UCE_RO | PCIE_AER_UCE_MTLP | PCIE_AER_UCE_ECRC); 53310187SKrishna.Elango@Sun.COM 53410187SKrishna.Elango@Sun.COM void 53510187SKrishna.Elango@Sun.COM pcieb_intel_rber_workaround(dev_info_t *dip) 53610187SKrishna.Elango@Sun.COM { 53710187SKrishna.Elango@Sun.COM uint32_t rber; 53810187SKrishna.Elango@Sun.COM pcie_bus_t *bus_p = PCIE_DIP2UPBUS(dip); 53910187SKrishna.Elango@Sun.COM 54010187SKrishna.Elango@Sun.COM if (pcieb_intel_workaround_disable) 54110187SKrishna.Elango@Sun.COM return; 54210187SKrishna.Elango@Sun.COM 54310187SKrishna.Elango@Sun.COM /* 54410187SKrishna.Elango@Sun.COM * Check Root Port's machinecheck setting to determine if this 54510187SKrishna.Elango@Sun.COM * workaround is needed or not. 54610187SKrishna.Elango@Sun.COM */ 54710187SKrishna.Elango@Sun.COM if (!pcie_get_rber_fatal(dip)) 54810187SKrishna.Elango@Sun.COM return; 54910187SKrishna.Elango@Sun.COM 55010187SKrishna.Elango@Sun.COM if (!PCIE_IS_PCIE(bus_p) || !PCIE_HAS_AER(bus_p)) 55110187SKrishna.Elango@Sun.COM return; 55210187SKrishna.Elango@Sun.COM 55310187SKrishna.Elango@Sun.COM rber = PCIE_CAP_GET(16, bus_p, PCIE_DEVCAP) & 55410187SKrishna.Elango@Sun.COM PCIE_DEVCAP_ROLE_BASED_ERR_REP; 55510187SKrishna.Elango@Sun.COM if (!rber) 55610187SKrishna.Elango@Sun.COM return; 55710187SKrishna.Elango@Sun.COM 55810187SKrishna.Elango@Sun.COM PCIE_AER_PUT(32, bus_p, PCIE_AER_UCE_SERV, pcieb_rber_sev); 55910187SKrishna.Elango@Sun.COM } 56010187SKrishna.Elango@Sun.COM 56110187SKrishna.Elango@Sun.COM /* 56210187SKrishna.Elango@Sun.COM * The Intel 5000 Chipset has an errata that requires read completion 56310187SKrishna.Elango@Sun.COM * coalescing to be disabled if the Max Payload Size is set to 256 bytes. 56410187SKrishna.Elango@Sun.COM */ 56510187SKrishna.Elango@Sun.COM void 56610187SKrishna.Elango@Sun.COM pcieb_intel_mps_workaround(dev_info_t *dip) 56710187SKrishna.Elango@Sun.COM { 56810187SKrishna.Elango@Sun.COM uint16_t vid, did; 56910187SKrishna.Elango@Sun.COM uint32_t pexctrl; 57010187SKrishna.Elango@Sun.COM pcie_bus_t *bus_p = PCIE_DIP2UPBUS(dip); 57110187SKrishna.Elango@Sun.COM 57210187SKrishna.Elango@Sun.COM vid = bus_p->bus_dev_ven_id & 0xFFFF; 57310187SKrishna.Elango@Sun.COM did = bus_p->bus_dev_ven_id >> 16; 57410187SKrishna.Elango@Sun.COM 575*10476SAlan.Adamson@Sun.COM if ((vid == INTEL_VENDOR_ID) && (INTEL_NB5000_PCIE_DEV_ID(did) || 576*10476SAlan.Adamson@Sun.COM INTEL_NB5100_PCIE_DEV_ID(did))) { 577*10476SAlan.Adamson@Sun.COM 57810187SKrishna.Elango@Sun.COM pexctrl = pci_config_get32(bus_p->bus_cfg_hdl, 57910187SKrishna.Elango@Sun.COM INTEL_NB5000_PEXCTRL_OFFSET); 58010187SKrishna.Elango@Sun.COM /* 58110187SKrishna.Elango@Sun.COM * Turn off coalescing (bit 10) 58210187SKrishna.Elango@Sun.COM */ 58310187SKrishna.Elango@Sun.COM pexctrl &= ~INTEL_NB5000_PEXCTRL_COALESCE_EN; 58410187SKrishna.Elango@Sun.COM 58510187SKrishna.Elango@Sun.COM pci_config_put32(bus_p->bus_cfg_hdl, 58610187SKrishna.Elango@Sun.COM INTEL_NB5000_PEXCTRL_OFFSET, pexctrl); 58710187SKrishna.Elango@Sun.COM } 58810187SKrishna.Elango@Sun.COM } 58910187SKrishna.Elango@Sun.COM 59010187SKrishna.Elango@Sun.COM /* 59110187SKrishna.Elango@Sun.COM * Workaround for certain switches regardless of platform 59210187SKrishna.Elango@Sun.COM */ 59310187SKrishna.Elango@Sun.COM void 59410187SKrishna.Elango@Sun.COM pcieb_intel_sw_workaround(dev_info_t *dip) 59510187SKrishna.Elango@Sun.COM { 59610187SKrishna.Elango@Sun.COM uint16_t vid, regw; 59710187SKrishna.Elango@Sun.COM pcie_bus_t *bus_p = PCIE_DIP2UPBUS(dip); 59810187SKrishna.Elango@Sun.COM ddi_acc_handle_t cfg_hdl = bus_p->bus_cfg_hdl; 59910187SKrishna.Elango@Sun.COM 60010187SKrishna.Elango@Sun.COM if (pcieb_intel_workaround_disable) 60110187SKrishna.Elango@Sun.COM return; 60210187SKrishna.Elango@Sun.COM 60310187SKrishna.Elango@Sun.COM if (!PCIE_IS_SW(PCIE_DIP2BUS(dip))) 60410187SKrishna.Elango@Sun.COM return; 60510187SKrishna.Elango@Sun.COM 60610187SKrishna.Elango@Sun.COM vid = bus_p->bus_dev_ven_id & 0xFFFF; 60710187SKrishna.Elango@Sun.COM /* 60810187SKrishna.Elango@Sun.COM * Intel and PLX switches require SERR in CMD reg to foward error 60910187SKrishna.Elango@Sun.COM * messages, though this is not PCIE spec-compliant behavior. 61010187SKrishna.Elango@Sun.COM * To prevent the switches themselves from reporting errors on URs 61110187SKrishna.Elango@Sun.COM * when the CMD reg has SERR enabled (which is expected according to 61210187SKrishna.Elango@Sun.COM * the PCIE spec) we rely on masking URs in the AER cap. 61310187SKrishna.Elango@Sun.COM */ 61410187SKrishna.Elango@Sun.COM if (vid == 0x8086 || vid == 0x10B5) { 61510187SKrishna.Elango@Sun.COM regw = pci_config_get16(cfg_hdl, PCI_CONF_COMM); 61610187SKrishna.Elango@Sun.COM pci_config_put16(cfg_hdl, PCI_CONF_COMM, 61710187SKrishna.Elango@Sun.COM regw | PCI_COMM_SERR_ENABLE); 61810187SKrishna.Elango@Sun.COM } 61910187SKrishna.Elango@Sun.COM } 62010187SKrishna.Elango@Sun.COM 62110187SKrishna.Elango@Sun.COM int 62210187SKrishna.Elango@Sun.COM pcieb_plat_ctlops(dev_info_t *rdip, ddi_ctl_enum_t ctlop, void *arg) 62310187SKrishna.Elango@Sun.COM { 62410187SKrishna.Elango@Sun.COM struct detachspec *ds; 62510187SKrishna.Elango@Sun.COM struct attachspec *as; 62610187SKrishna.Elango@Sun.COM 62710187SKrishna.Elango@Sun.COM switch (ctlop) { 62810187SKrishna.Elango@Sun.COM case DDI_CTLOPS_DETACH: 62910187SKrishna.Elango@Sun.COM ds = (struct detachspec *)arg; 63010187SKrishna.Elango@Sun.COM switch (ds->when) { 63110187SKrishna.Elango@Sun.COM case DDI_POST: 63210187SKrishna.Elango@Sun.COM if (ds->cmd == DDI_SUSPEND) { 63310187SKrishna.Elango@Sun.COM if (pci_post_suspend(rdip) != DDI_SUCCESS) 63410187SKrishna.Elango@Sun.COM return (DDI_FAILURE); 63510187SKrishna.Elango@Sun.COM } 63610187SKrishna.Elango@Sun.COM break; 63710187SKrishna.Elango@Sun.COM default: 63810187SKrishna.Elango@Sun.COM break; 63910187SKrishna.Elango@Sun.COM } 64010187SKrishna.Elango@Sun.COM break; 64110187SKrishna.Elango@Sun.COM case DDI_CTLOPS_ATTACH: 64210187SKrishna.Elango@Sun.COM as = (struct attachspec *)arg; 64310187SKrishna.Elango@Sun.COM switch (as->when) { 64410187SKrishna.Elango@Sun.COM case DDI_PRE: 64510187SKrishna.Elango@Sun.COM if (as->cmd == DDI_RESUME) { 64610187SKrishna.Elango@Sun.COM if (pci_pre_resume(rdip) != DDI_SUCCESS) 64710187SKrishna.Elango@Sun.COM return (DDI_FAILURE); 64810187SKrishna.Elango@Sun.COM } 64910187SKrishna.Elango@Sun.COM break; 65010187SKrishna.Elango@Sun.COM case DDI_POST: 65110187SKrishna.Elango@Sun.COM /* 65210187SKrishna.Elango@Sun.COM * For leaf devices supporting RBER and AER, we 65310187SKrishna.Elango@Sun.COM * need to apply this workaround on them after 65410187SKrishna.Elango@Sun.COM * attach to be notified of UEs that would 65510187SKrishna.Elango@Sun.COM * otherwise be ignored as CEs on Intel chipsets 65610187SKrishna.Elango@Sun.COM * currently 65710187SKrishna.Elango@Sun.COM */ 65810187SKrishna.Elango@Sun.COM pcieb_intel_rber_workaround(rdip); 65910187SKrishna.Elango@Sun.COM break; 66010187SKrishna.Elango@Sun.COM default: 66110187SKrishna.Elango@Sun.COM break; 66210187SKrishna.Elango@Sun.COM } 66310187SKrishna.Elango@Sun.COM break; 66410187SKrishna.Elango@Sun.COM default: 66510187SKrishna.Elango@Sun.COM break; 66610187SKrishna.Elango@Sun.COM } 66710187SKrishna.Elango@Sun.COM 66810187SKrishna.Elango@Sun.COM return (DDI_SUCCESS); 66910187SKrishna.Elango@Sun.COM } 67010187SKrishna.Elango@Sun.COM 67110187SKrishna.Elango@Sun.COM void 67210187SKrishna.Elango@Sun.COM pcieb_plat_ioctl_hotplug(dev_info_t *dip, int rv, int cmd) 67310187SKrishna.Elango@Sun.COM { 67410187SKrishna.Elango@Sun.COM /* 67510187SKrishna.Elango@Sun.COM * like in attach, since hotplugging can change error registers, 67610187SKrishna.Elango@Sun.COM * we need to ensure that the proper bits are set on this port 67710187SKrishna.Elango@Sun.COM * after a configure operation 67810187SKrishna.Elango@Sun.COM */ 67910187SKrishna.Elango@Sun.COM if ((rv == HPC_SUCCESS) && (cmd == DEVCTL_AP_CONFIGURE)) 68010187SKrishna.Elango@Sun.COM pcieb_intel_error_workaround(dip); 68110187SKrishna.Elango@Sun.COM } 682