xref: /onnv-gate/usr/src/uts/intel/io/pciex/pcieb_x86.c (revision 10187:ad62e2dfbe0c)
1*10187SKrishna.Elango@Sun.COM /*
2*10187SKrishna.Elango@Sun.COM  * CDDL HEADER START
3*10187SKrishna.Elango@Sun.COM  *
4*10187SKrishna.Elango@Sun.COM  * The contents of this file are subject to the terms of the
5*10187SKrishna.Elango@Sun.COM  * Common Development and Distribution License (the "License").
6*10187SKrishna.Elango@Sun.COM  * You may not use this file except in compliance with the License.
7*10187SKrishna.Elango@Sun.COM  *
8*10187SKrishna.Elango@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*10187SKrishna.Elango@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*10187SKrishna.Elango@Sun.COM  * See the License for the specific language governing permissions
11*10187SKrishna.Elango@Sun.COM  * and limitations under the License.
12*10187SKrishna.Elango@Sun.COM  *
13*10187SKrishna.Elango@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*10187SKrishna.Elango@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*10187SKrishna.Elango@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*10187SKrishna.Elango@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*10187SKrishna.Elango@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*10187SKrishna.Elango@Sun.COM  *
19*10187SKrishna.Elango@Sun.COM  * CDDL HEADER END
20*10187SKrishna.Elango@Sun.COM  */
21*10187SKrishna.Elango@Sun.COM /*
22*10187SKrishna.Elango@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23*10187SKrishna.Elango@Sun.COM  * Use is subject to license terms.
24*10187SKrishna.Elango@Sun.COM  */
25*10187SKrishna.Elango@Sun.COM 
26*10187SKrishna.Elango@Sun.COM /* x86 specific code used by the pcieb driver */
27*10187SKrishna.Elango@Sun.COM 
28*10187SKrishna.Elango@Sun.COM #include <sys/types.h>
29*10187SKrishna.Elango@Sun.COM #include <sys/ddi.h>
30*10187SKrishna.Elango@Sun.COM #include <sys/kmem.h>
31*10187SKrishna.Elango@Sun.COM #include <sys/sysmacros.h>
32*10187SKrishna.Elango@Sun.COM #include <sys/sunddi.h>
33*10187SKrishna.Elango@Sun.COM #include <sys/sunndi.h>
34*10187SKrishna.Elango@Sun.COM #include <sys/pcie.h>
35*10187SKrishna.Elango@Sun.COM #include <sys/pci_cap.h>
36*10187SKrishna.Elango@Sun.COM #include <sys/pcie_impl.h>
37*10187SKrishna.Elango@Sun.COM #include <sys/pcie_acpi.h>
38*10187SKrishna.Elango@Sun.COM #include <sys/hotplug/hpctrl.h>
39*10187SKrishna.Elango@Sun.COM #include <io/pciex/pcieb.h>
40*10187SKrishna.Elango@Sun.COM #include <io/pciex/pcie_nb5000.h>
41*10187SKrishna.Elango@Sun.COM 
42*10187SKrishna.Elango@Sun.COM /* Flag to turn off intel error handling workarounds */
43*10187SKrishna.Elango@Sun.COM int pcieb_intel_workaround_disable = 0;
44*10187SKrishna.Elango@Sun.COM 
45*10187SKrishna.Elango@Sun.COM void
46*10187SKrishna.Elango@Sun.COM pcieb_peekpoke_cb(dev_info_t *dip, ddi_fm_error_t *derr) {
47*10187SKrishna.Elango@Sun.COM 	(void) pf_scan_fabric(dip, derr, NULL);
48*10187SKrishna.Elango@Sun.COM }
49*10187SKrishna.Elango@Sun.COM 
50*10187SKrishna.Elango@Sun.COM int
51*10187SKrishna.Elango@Sun.COM pcieb_plat_peekpoke(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
52*10187SKrishna.Elango@Sun.COM     void *arg, void *result)
53*10187SKrishna.Elango@Sun.COM {
54*10187SKrishna.Elango@Sun.COM 	pcieb_devstate_t *pcieb = ddi_get_soft_state(pcieb_state,
55*10187SKrishna.Elango@Sun.COM 	    ddi_get_instance(dip));
56*10187SKrishna.Elango@Sun.COM 
57*10187SKrishna.Elango@Sun.COM 	if (!PCIE_IS_RP(PCIE_DIP2BUS(dip)))
58*10187SKrishna.Elango@Sun.COM 		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
59*10187SKrishna.Elango@Sun.COM 
60*10187SKrishna.Elango@Sun.COM 	return (pci_peekpoke_check(dip, rdip, ctlop, arg, result,
61*10187SKrishna.Elango@Sun.COM 	    ddi_ctlops, &pcieb->pcieb_err_mutex,
62*10187SKrishna.Elango@Sun.COM 	    &pcieb->pcieb_peek_poke_mutex,
63*10187SKrishna.Elango@Sun.COM 	    pcieb_peekpoke_cb));
64*10187SKrishna.Elango@Sun.COM }
65*10187SKrishna.Elango@Sun.COM 
66*10187SKrishna.Elango@Sun.COM /* x86 specific workarounds needed at the end of pcieb attach */
67*10187SKrishna.Elango@Sun.COM void
68*10187SKrishna.Elango@Sun.COM pcieb_plat_attach_workaround(dev_info_t *dip)
69*10187SKrishna.Elango@Sun.COM {
70*10187SKrishna.Elango@Sun.COM 	/* Must apply workaround only after all initialization is done */
71*10187SKrishna.Elango@Sun.COM 	pcieb_intel_error_workaround(dip);
72*10187SKrishna.Elango@Sun.COM 	pcieb_intel_mps_workaround(dip);
73*10187SKrishna.Elango@Sun.COM 
74*10187SKrishna.Elango@Sun.COM }
75*10187SKrishna.Elango@Sun.COM 
76*10187SKrishna.Elango@Sun.COM /* Workarounds to enable error handling on certain Intel chipsets */
77*10187SKrishna.Elango@Sun.COM void
78*10187SKrishna.Elango@Sun.COM pcieb_intel_error_workaround(dev_info_t *dip)
79*10187SKrishna.Elango@Sun.COM {
80*10187SKrishna.Elango@Sun.COM 	pcieb_devstate_t *pcieb = ddi_get_soft_state(pcieb_state,
81*10187SKrishna.Elango@Sun.COM 	    ddi_get_instance(dip));
82*10187SKrishna.Elango@Sun.COM 
83*10187SKrishna.Elango@Sun.COM 	pcieb_intel_serr_workaround(dip, pcieb->pcieb_no_aer_msi);
84*10187SKrishna.Elango@Sun.COM 	pcieb_intel_rber_workaround(dip);
85*10187SKrishna.Elango@Sun.COM 	pcieb_intel_sw_workaround(dip);
86*10187SKrishna.Elango@Sun.COM }
87*10187SKrishna.Elango@Sun.COM 
88*10187SKrishna.Elango@Sun.COM int
89*10187SKrishna.Elango@Sun.COM pcieb_plat_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
90*10187SKrishna.Elango@Sun.COM     ddi_intr_handle_impl_t *hdlp, void *result)
91*10187SKrishna.Elango@Sun.COM {
92*10187SKrishna.Elango@Sun.COM 	return (i_ddi_intr_ops(dip, rdip, intr_op, hdlp, result));
93*10187SKrishna.Elango@Sun.COM }
94*10187SKrishna.Elango@Sun.COM 
95*10187SKrishna.Elango@Sun.COM /* shpc is not supported on x86 */
96*10187SKrishna.Elango@Sun.COM /*ARGSUSED*/
97*10187SKrishna.Elango@Sun.COM int
98*10187SKrishna.Elango@Sun.COM pcieb_plat_pcishpc_probe(dev_info_t *dip, ddi_acc_handle_t config_handle)
99*10187SKrishna.Elango@Sun.COM {
100*10187SKrishna.Elango@Sun.COM 	return (DDI_FAILURE);
101*10187SKrishna.Elango@Sun.COM }
102*10187SKrishna.Elango@Sun.COM 
103*10187SKrishna.Elango@Sun.COM /*
104*10187SKrishna.Elango@Sun.COM  * Dummy functions to get around the fact that there's no shpc module on x86
105*10187SKrishna.Elango@Sun.COM  * today
106*10187SKrishna.Elango@Sun.COM  */
107*10187SKrishna.Elango@Sun.COM /*ARGSUSED*/
108*10187SKrishna.Elango@Sun.COM int
109*10187SKrishna.Elango@Sun.COM pcishpc_init(dev_info_t *dip)
110*10187SKrishna.Elango@Sun.COM {
111*10187SKrishna.Elango@Sun.COM 	return (DDI_FAILURE);
112*10187SKrishna.Elango@Sun.COM }
113*10187SKrishna.Elango@Sun.COM 
114*10187SKrishna.Elango@Sun.COM /*ARGSUSED*/
115*10187SKrishna.Elango@Sun.COM int
116*10187SKrishna.Elango@Sun.COM pcishpc_uninit(dev_info_t *dip)
117*10187SKrishna.Elango@Sun.COM {
118*10187SKrishna.Elango@Sun.COM 	return (DDI_FAILURE);
119*10187SKrishna.Elango@Sun.COM }
120*10187SKrishna.Elango@Sun.COM 
121*10187SKrishna.Elango@Sun.COM /*ARGSUSED*/
122*10187SKrishna.Elango@Sun.COM int
123*10187SKrishna.Elango@Sun.COM pcishpc_intr(dev_info_t *dip)
124*10187SKrishna.Elango@Sun.COM {
125*10187SKrishna.Elango@Sun.COM 	return (DDI_INTR_UNCLAIMED);
126*10187SKrishna.Elango@Sun.COM }
127*10187SKrishna.Elango@Sun.COM 
128*10187SKrishna.Elango@Sun.COM /*ARGSUSED*/
129*10187SKrishna.Elango@Sun.COM boolean_t
130*10187SKrishna.Elango@Sun.COM pcieb_plat_pwr_disable(dev_info_t *dip)
131*10187SKrishna.Elango@Sun.COM {
132*10187SKrishna.Elango@Sun.COM 	/* Always disable on x86 */
133*10187SKrishna.Elango@Sun.COM 	return (B_TRUE);
134*10187SKrishna.Elango@Sun.COM }
135*10187SKrishna.Elango@Sun.COM 
136*10187SKrishna.Elango@Sun.COM boolean_t
137*10187SKrishna.Elango@Sun.COM pcieb_plat_msi_supported(dev_info_t *dip)
138*10187SKrishna.Elango@Sun.COM {
139*10187SKrishna.Elango@Sun.COM 	pcie_bus_t *bus_p = PCIE_DIP2UPBUS(dip);
140*10187SKrishna.Elango@Sun.COM 	uint16_t vendor_id, device_id;
141*10187SKrishna.Elango@Sun.COM 	vendor_id = bus_p->bus_dev_ven_id & 0xFFFF;
142*10187SKrishna.Elango@Sun.COM 	device_id = bus_p->bus_dev_ven_id >> 16;
143*10187SKrishna.Elango@Sun.COM 
144*10187SKrishna.Elango@Sun.COM 	/*
145*10187SKrishna.Elango@Sun.COM 	 * Intel ESB2 switches have a errata which prevents using MSIs
146*10187SKrishna.Elango@Sun.COM 	 * for hotplug.
147*10187SKrishna.Elango@Sun.COM 	 */
148*10187SKrishna.Elango@Sun.COM 	return (((vendor_id == INTEL_VENDOR_ID) &&
149*10187SKrishna.Elango@Sun.COM 	    INTEL_ESB2_SW_PCIE_DEV_ID(device_id)) ? B_FALSE : B_TRUE);
150*10187SKrishna.Elango@Sun.COM }
151*10187SKrishna.Elango@Sun.COM 
152*10187SKrishna.Elango@Sun.COM void
153*10187SKrishna.Elango@Sun.COM pcieb_plat_intr_attach(pcieb_devstate_t *pcieb)
154*10187SKrishna.Elango@Sun.COM {
155*10187SKrishna.Elango@Sun.COM 	/*
156*10187SKrishna.Elango@Sun.COM 	 *  _OSC initialization needs to be done before interrupts are
157*10187SKrishna.Elango@Sun.COM 	 *  initialized.
158*10187SKrishna.Elango@Sun.COM 	 */
159*10187SKrishna.Elango@Sun.COM 	pcieb_init_osc(pcieb->pcieb_dip);
160*10187SKrishna.Elango@Sun.COM }
161*10187SKrishna.Elango@Sun.COM 
162*10187SKrishna.Elango@Sun.COM void
163*10187SKrishna.Elango@Sun.COM pcieb_plat_initchild(dev_info_t *child)
164*10187SKrishna.Elango@Sun.COM {
165*10187SKrishna.Elango@Sun.COM 	struct ddi_parent_private_data *pdptr;
166*10187SKrishna.Elango@Sun.COM 	if (ddi_getprop(DDI_DEV_T_NONE, child, DDI_PROP_DONTPASS, "interrupts",
167*10187SKrishna.Elango@Sun.COM 	    -1) != -1) {
168*10187SKrishna.Elango@Sun.COM 		pdptr = kmem_zalloc((sizeof (struct ddi_parent_private_data) +
169*10187SKrishna.Elango@Sun.COM 		    sizeof (struct intrspec)), KM_SLEEP);
170*10187SKrishna.Elango@Sun.COM 		pdptr->par_intr = (struct intrspec *)(pdptr + 1);
171*10187SKrishna.Elango@Sun.COM 		pdptr->par_nintr = 1;
172*10187SKrishna.Elango@Sun.COM 		ddi_set_parent_data(child, pdptr);
173*10187SKrishna.Elango@Sun.COM 	} else
174*10187SKrishna.Elango@Sun.COM 		ddi_set_parent_data(child, NULL);
175*10187SKrishna.Elango@Sun.COM }
176*10187SKrishna.Elango@Sun.COM 
177*10187SKrishna.Elango@Sun.COM void
178*10187SKrishna.Elango@Sun.COM pcieb_plat_uninitchild(dev_info_t *child)
179*10187SKrishna.Elango@Sun.COM {
180*10187SKrishna.Elango@Sun.COM 	struct ddi_parent_private_data	*pdptr;
181*10187SKrishna.Elango@Sun.COM 
182*10187SKrishna.Elango@Sun.COM 	if ((pdptr = ddi_get_parent_data(child)) != NULL)
183*10187SKrishna.Elango@Sun.COM 		kmem_free(pdptr, (sizeof (*pdptr) + sizeof (struct intrspec)));
184*10187SKrishna.Elango@Sun.COM 
185*10187SKrishna.Elango@Sun.COM 	ddi_set_parent_data(child, NULL);
186*10187SKrishna.Elango@Sun.COM }
187*10187SKrishna.Elango@Sun.COM 
188*10187SKrishna.Elango@Sun.COM /* _OSC related */
189*10187SKrishna.Elango@Sun.COM void
190*10187SKrishna.Elango@Sun.COM pcieb_init_osc(dev_info_t *devi) {
191*10187SKrishna.Elango@Sun.COM 	pcie_bus_t	*bus_p = PCIE_DIP2UPBUS(devi);
192*10187SKrishna.Elango@Sun.COM 	uint32_t	osc_flags = OSC_CONTROL_PCIE_ADV_ERR;
193*10187SKrishna.Elango@Sun.COM 
194*10187SKrishna.Elango@Sun.COM 	/*
195*10187SKrishna.Elango@Sun.COM 	 * Call _OSC method for 2 reasons:
196*10187SKrishna.Elango@Sun.COM 	 * 1. Hotplug: To determine if it is native or ACPI mode.
197*10187SKrishna.Elango@Sun.COM 	 *
198*10187SKrishna.Elango@Sun.COM 	 * 2. Error handling: Inform firmware that OS can support AER error
199*10187SKrishna.Elango@Sun.COM 	 * handling. Currently we don't care for what the BIOS response was
200*10187SKrishna.Elango@Sun.COM 	 * and instead setup interrupts for error handling as if it were
201*10187SKrishna.Elango@Sun.COM 	 * supported.
202*10187SKrishna.Elango@Sun.COM 	 *
203*10187SKrishna.Elango@Sun.COM 	 * For hotpluggable slots the _OSC method has already been called as
204*10187SKrishna.Elango@Sun.COM 	 * part of the hotplug initialization.
205*10187SKrishna.Elango@Sun.COM 	 * For non-hotpluggable slots we need to call the _OSC method only for
206*10187SKrishna.Elango@Sun.COM 	 * Root Ports (for AER support).
207*10187SKrishna.Elango@Sun.COM 	 */
208*10187SKrishna.Elango@Sun.COM 	if (!pcie_is_osc(devi) && PCIE_IS_RP(bus_p) && PCIE_HAS_AER(bus_p))
209*10187SKrishna.Elango@Sun.COM 		(void) pcie_acpi_osc(devi, &osc_flags);
210*10187SKrishna.Elango@Sun.COM }
211*10187SKrishna.Elango@Sun.COM 
212*10187SKrishna.Elango@Sun.COM /*
213*10187SKrishna.Elango@Sun.COM  * Intel chip specific workarounds. Right now they're limited to the 5000, 5400
214*10187SKrishna.Elango@Sun.COM  * and 7300 series chipsets.
215*10187SKrishna.Elango@Sun.COM  */
216*10187SKrishna.Elango@Sun.COM typedef struct x86_error_reg {
217*10187SKrishna.Elango@Sun.COM 	uint32_t	offset;
218*10187SKrishna.Elango@Sun.COM 	uint_t		size;
219*10187SKrishna.Elango@Sun.COM 	uint32_t	mask;
220*10187SKrishna.Elango@Sun.COM 	uint32_t	value1;	/* Value for MSI case */
221*10187SKrishna.Elango@Sun.COM 	uint32_t	value2; /* Value for machinecheck case */
222*10187SKrishna.Elango@Sun.COM } x86_error_reg_t;
223*10187SKrishna.Elango@Sun.COM 
224*10187SKrishna.Elango@Sun.COM typedef struct x86_error_tbl {
225*10187SKrishna.Elango@Sun.COM 	uint16_t	vendor_id;
226*10187SKrishna.Elango@Sun.COM 	uint16_t	device_id_low;
227*10187SKrishna.Elango@Sun.COM 	uint16_t	device_id_high;
228*10187SKrishna.Elango@Sun.COM 	uint8_t		rev_id_low;
229*10187SKrishna.Elango@Sun.COM 	uint8_t		rev_id_high;
230*10187SKrishna.Elango@Sun.COM 	x86_error_reg_t	*error_regs;
231*10187SKrishna.Elango@Sun.COM 	int		error_regs_len;
232*10187SKrishna.Elango@Sun.COM } x86_error_tbl_t;
233*10187SKrishna.Elango@Sun.COM 
234*10187SKrishna.Elango@Sun.COM /*
235*10187SKrishna.Elango@Sun.COM  * Chipset and device specific settings that are required for error handling
236*10187SKrishna.Elango@Sun.COM  * (reporting, fowarding, and response at the RC) beyond the standard
237*10187SKrishna.Elango@Sun.COM  * registers in the PCIE and AER caps.
238*10187SKrishna.Elango@Sun.COM  *
239*10187SKrishna.Elango@Sun.COM  * The Northbridge Root Port settings also apply to the ESI port.  The ESI
240*10187SKrishna.Elango@Sun.COM  * port is a special leaf device but functions like a root port connected
241*10187SKrishna.Elango@Sun.COM  * to the Southbridge and receives all the onboard Southbridge errors
242*10187SKrishna.Elango@Sun.COM  * including those from Southbridge Root Ports.  However, this does not
243*10187SKrishna.Elango@Sun.COM  * include the Southbridge Switch Ports which act like normal switch ports
244*10187SKrishna.Elango@Sun.COM  * and is connected to the Northbridge through a separate link.
245*10187SKrishna.Elango@Sun.COM  *
246*10187SKrishna.Elango@Sun.COM  * PCIE errors from the ESB2 Southbridge RPs are simply fowarded to the ESI
247*10187SKrishna.Elango@Sun.COM  * port on the Northbridge.
248*10187SKrishna.Elango@Sun.COM  *
249*10187SKrishna.Elango@Sun.COM  * If MSIs don't work we want UEs (Fatal and Non-Fatal) to panic the system,
250*10187SKrishna.Elango@Sun.COM  * except for URs.  We do this by having the Root Ports respond with a System
251*10187SKrishna.Elango@Sun.COM  * Error and having that trigger a Machine Check (MCE).
252*10187SKrishna.Elango@Sun.COM  */
253*10187SKrishna.Elango@Sun.COM 
254*10187SKrishna.Elango@Sun.COM /*
255*10187SKrishna.Elango@Sun.COM  * 7300 Northbridge Root Ports
256*10187SKrishna.Elango@Sun.COM  */
257*10187SKrishna.Elango@Sun.COM static x86_error_reg_t intel_7300_rp_regs[] = {
258*10187SKrishna.Elango@Sun.COM 	/* Command Register - Enable SERR */
259*10187SKrishna.Elango@Sun.COM 	{0x4,   16, 0xFFFF,	0x0,	PCI_COMM_SERR_ENABLE},
260*10187SKrishna.Elango@Sun.COM 
261*10187SKrishna.Elango@Sun.COM 	/* Root Control Register - SERR on NFE/FE */
262*10187SKrishna.Elango@Sun.COM 	{0x88,  16, 0x0,	0x0,	PCIE_ROOTCTL_SYS_ERR_ON_NFE_EN |
263*10187SKrishna.Elango@Sun.COM 					PCIE_ROOTCTL_SYS_ERR_ON_FE_EN},
264*10187SKrishna.Elango@Sun.COM 
265*10187SKrishna.Elango@Sun.COM 	/* AER UE Mask - Mask UR */
266*10187SKrishna.Elango@Sun.COM 	{0x108, 32, 0x0, PCIE_AER_UCE_UR, PCIE_AER_UCE_UR},
267*10187SKrishna.Elango@Sun.COM 
268*10187SKrishna.Elango@Sun.COM 	/* PEXCTRL[21] check for certain malformed TLP types and MSI enable */
269*10187SKrishna.Elango@Sun.COM 	{0x48,	32, 0xFFFFFFFF, 0xC0200000, 0x200000},
270*10187SKrishna.Elango@Sun.COM 	/* PEXCTRL3[7]. MSI RAS error enable */
271*10187SKrishna.Elango@Sun.COM 	{0x4D,	32, 0xFFFFFFFF, 0x1, 0x0},
272*10187SKrishna.Elango@Sun.COM 
273*10187SKrishna.Elango@Sun.COM 	/* PEX_ERR_DOCMD[7:0] */
274*10187SKrishna.Elango@Sun.COM 	{0x144,	8,  0x0,	0x0,	0xF0},
275*10187SKrishna.Elango@Sun.COM 
276*10187SKrishna.Elango@Sun.COM 	/* EMASK_UNCOR_PEX[21:0] UE mask */
277*10187SKrishna.Elango@Sun.COM 	{0x148,	32, 0x0, PCIE_AER_UCE_UR, PCIE_AER_UCE_UR},
278*10187SKrishna.Elango@Sun.COM 
279*10187SKrishna.Elango@Sun.COM 	/* EMASK_RP_PEX[2:0] FE, UE, CE message detect mask */
280*10187SKrishna.Elango@Sun.COM 	{0x150,	8,  0x0,	0x0,	0x1},
281*10187SKrishna.Elango@Sun.COM };
282*10187SKrishna.Elango@Sun.COM #define	INTEL_7300_RP_REGS_LEN \
283*10187SKrishna.Elango@Sun.COM 	(sizeof (intel_7300_rp_regs) / sizeof (x86_error_reg_t))
284*10187SKrishna.Elango@Sun.COM 
285*10187SKrishna.Elango@Sun.COM /*
286*10187SKrishna.Elango@Sun.COM  * 5000 Northbridge Root Ports
287*10187SKrishna.Elango@Sun.COM  */
288*10187SKrishna.Elango@Sun.COM static x86_error_reg_t intel_5000_rp_regs[] = {
289*10187SKrishna.Elango@Sun.COM 	/* Command Register - Enable SERR */
290*10187SKrishna.Elango@Sun.COM 	{0x4,   16, 0xFFFF,	PCI_COMM_SERR_ENABLE,	PCI_COMM_SERR_ENABLE},
291*10187SKrishna.Elango@Sun.COM 
292*10187SKrishna.Elango@Sun.COM 	/* Root Control Register - SERR on NFE/FE/CE */
293*10187SKrishna.Elango@Sun.COM 	{0x88,  16, 0x0,	PCIE_ROOTCTL_SYS_ERR_ON_NFE_EN |
294*10187SKrishna.Elango@Sun.COM 				PCIE_ROOTCTL_SYS_ERR_ON_FE_EN |
295*10187SKrishna.Elango@Sun.COM 				PCIE_ROOTCTL_SYS_ERR_ON_CE_EN,
296*10187SKrishna.Elango@Sun.COM 				PCIE_ROOTCTL_SYS_ERR_ON_NFE_EN |
297*10187SKrishna.Elango@Sun.COM 				PCIE_ROOTCTL_SYS_ERR_ON_FE_EN},
298*10187SKrishna.Elango@Sun.COM 
299*10187SKrishna.Elango@Sun.COM 	/* AER UE Mask - Mask UR */
300*10187SKrishna.Elango@Sun.COM 	{0x108, 32, 0x0,	PCIE_AER_UCE_UR,	PCIE_AER_UCE_UR},
301*10187SKrishna.Elango@Sun.COM 
302*10187SKrishna.Elango@Sun.COM 	/* PEXCTRL[21] check for certain malformed TLP type */
303*10187SKrishna.Elango@Sun.COM 	{0x48,	32, 0xFFFFFFFF, 0xC0200000, 0x200000},
304*10187SKrishna.Elango@Sun.COM 	/* PEXCTRL3[7]. MSI RAS error enable. */
305*10187SKrishna.Elango@Sun.COM 	{0x4D,	32, 0xFFFFFFFF,	0x1,	0x0},
306*10187SKrishna.Elango@Sun.COM 
307*10187SKrishna.Elango@Sun.COM 	/* PEX_ERR_DOCMD[7:0] */
308*10187SKrishna.Elango@Sun.COM 	{0x144,	8,  0x0,	0x0,	0xF0},
309*10187SKrishna.Elango@Sun.COM 
310*10187SKrishna.Elango@Sun.COM 	/* EMASK_UNCOR_PEX[21:0] UE mask */
311*10187SKrishna.Elango@Sun.COM 	{0x148,	32, 0x0, 	PCIE_AER_UCE_UR,	PCIE_AER_UCE_UR},
312*10187SKrishna.Elango@Sun.COM 
313*10187SKrishna.Elango@Sun.COM 	/* EMASK_RP_PEX[2:0] FE, UE, CE message detect mask */
314*10187SKrishna.Elango@Sun.COM 	{0x150,	8,  0x0, 	0x0,	0x1},
315*10187SKrishna.Elango@Sun.COM };
316*10187SKrishna.Elango@Sun.COM #define	INTEL_5000_RP_REGS_LEN \
317*10187SKrishna.Elango@Sun.COM 	(sizeof (intel_5000_rp_regs) / sizeof (x86_error_reg_t))
318*10187SKrishna.Elango@Sun.COM 
319*10187SKrishna.Elango@Sun.COM /*
320*10187SKrishna.Elango@Sun.COM  * 5400 Northbridge Root Ports.
321*10187SKrishna.Elango@Sun.COM  */
322*10187SKrishna.Elango@Sun.COM static x86_error_reg_t intel_5400_rp_regs[] = {
323*10187SKrishna.Elango@Sun.COM 	/* Command Register - Enable SERR */
324*10187SKrishna.Elango@Sun.COM 	{0x4,   16, 0xFFFF,	PCI_COMM_SERR_ENABLE, PCI_COMM_SERR_ENABLE},
325*10187SKrishna.Elango@Sun.COM 
326*10187SKrishna.Elango@Sun.COM 	/* Root Control Register - SERR on NFE/FE */
327*10187SKrishna.Elango@Sun.COM 	{0x88,  16, 0x0, PCIE_ROOTCTL_SYS_ERR_ON_NFE_EN |
328*10187SKrishna.Elango@Sun.COM 			    PCIE_ROOTCTL_SYS_ERR_ON_FE_EN |
329*10187SKrishna.Elango@Sun.COM 			    PCIE_ROOTCTL_SYS_ERR_ON_CE_EN,
330*10187SKrishna.Elango@Sun.COM 			    PCIE_ROOTCTL_SYS_ERR_ON_NFE_EN |
331*10187SKrishna.Elango@Sun.COM 			    PCIE_ROOTCTL_SYS_ERR_ON_FE_EN},
332*10187SKrishna.Elango@Sun.COM 
333*10187SKrishna.Elango@Sun.COM 	/* AER UE Mask - Mask UR */
334*10187SKrishna.Elango@Sun.COM 	{0x108, 32, 0x0,	PCIE_AER_UCE_UR,	PCIE_AER_UCE_UR},
335*10187SKrishna.Elango@Sun.COM 
336*10187SKrishna.Elango@Sun.COM 	/* PEXCTRL[21] check for certain malformed TLP types */
337*10187SKrishna.Elango@Sun.COM 	{0x48,	32, 0xFFFFFFFF,	0xC0200000, 0x200000},
338*10187SKrishna.Elango@Sun.COM 	/* PEXCTRL3. MSI RAS error enable. */
339*10187SKrishna.Elango@Sun.COM 	{0x4E,	8, 0x0,	0x1,	0x0},
340*10187SKrishna.Elango@Sun.COM 
341*10187SKrishna.Elango@Sun.COM 	/* PEX_ERR_DOCMD[11:0] */
342*10187SKrishna.Elango@Sun.COM 	{0x144,	16,  0x0, 	0x0,	0xFF0},
343*10187SKrishna.Elango@Sun.COM 
344*10187SKrishna.Elango@Sun.COM 	/* PEX_ERR_PIN_MASK[4:0] do not mask ERR[2:0] pins used by DOCMD */
345*10187SKrishna.Elango@Sun.COM 	{0x146,	16,  0x0,	0x10,	0x10},
346*10187SKrishna.Elango@Sun.COM 
347*10187SKrishna.Elango@Sun.COM 	/* EMASK_UNCOR_PEX[21:0] UE mask */
348*10187SKrishna.Elango@Sun.COM 	{0x148,	32, 0x0, 	PCIE_AER_UCE_UR,	PCIE_AER_UCE_UR},
349*10187SKrishna.Elango@Sun.COM 
350*10187SKrishna.Elango@Sun.COM 	/* EMASK_RP_PEX[2:0] FE, UE, CE message detect mask */
351*10187SKrishna.Elango@Sun.COM 	{0x150,	8,  0x0, 	0x0,	0x1},
352*10187SKrishna.Elango@Sun.COM };
353*10187SKrishna.Elango@Sun.COM #define	INTEL_5400_RP_REGS_LEN \
354*10187SKrishna.Elango@Sun.COM 	(sizeof (intel_5400_rp_regs) / sizeof (x86_error_reg_t))
355*10187SKrishna.Elango@Sun.COM 
356*10187SKrishna.Elango@Sun.COM 
357*10187SKrishna.Elango@Sun.COM /*
358*10187SKrishna.Elango@Sun.COM  * ESB2 Southbridge Root Ports
359*10187SKrishna.Elango@Sun.COM  */
360*10187SKrishna.Elango@Sun.COM static x86_error_reg_t intel_esb2_rp_regs[] = {
361*10187SKrishna.Elango@Sun.COM 	/* Command Register - Enable SERR */
362*10187SKrishna.Elango@Sun.COM 	{0x4,   16, 0xFFFF,	PCI_COMM_SERR_ENABLE,	PCI_COMM_SERR_ENABLE},
363*10187SKrishna.Elango@Sun.COM 
364*10187SKrishna.Elango@Sun.COM 	/* Root Control Register - SERR on NFE/FE */
365*10187SKrishna.Elango@Sun.COM 	{0x5c,  16, 0x0,	PCIE_ROOTCTL_SYS_ERR_ON_NFE_EN |
366*10187SKrishna.Elango@Sun.COM 				PCIE_ROOTCTL_SYS_ERR_ON_FE_EN |
367*10187SKrishna.Elango@Sun.COM 				PCIE_ROOTCTL_SYS_ERR_ON_CE_EN,
368*10187SKrishna.Elango@Sun.COM 				PCIE_ROOTCTL_SYS_ERR_ON_NFE_EN |
369*10187SKrishna.Elango@Sun.COM 				PCIE_ROOTCTL_SYS_ERR_ON_FE_EN},
370*10187SKrishna.Elango@Sun.COM 
371*10187SKrishna.Elango@Sun.COM 	/* UEM[20:0] UE mask (write-once) */
372*10187SKrishna.Elango@Sun.COM 	{0x148, 32, 0x0,	PCIE_AER_UCE_UR,	PCIE_AER_UCE_UR},
373*10187SKrishna.Elango@Sun.COM };
374*10187SKrishna.Elango@Sun.COM #define	INTEL_ESB2_RP_REGS_LEN \
375*10187SKrishna.Elango@Sun.COM 	(sizeof (intel_esb2_rp_regs) / sizeof (x86_error_reg_t))
376*10187SKrishna.Elango@Sun.COM 
377*10187SKrishna.Elango@Sun.COM 
378*10187SKrishna.Elango@Sun.COM /*
379*10187SKrishna.Elango@Sun.COM  * ESB2 Southbridge Switch Ports
380*10187SKrishna.Elango@Sun.COM  */
381*10187SKrishna.Elango@Sun.COM static x86_error_reg_t intel_esb2_sw_regs[] = {
382*10187SKrishna.Elango@Sun.COM 	/* Command Register - Enable SERR */
383*10187SKrishna.Elango@Sun.COM 	{0x4,   16, 0xFFFF,	PCI_COMM_SERR_ENABLE,	PCI_COMM_SERR_ENABLE},
384*10187SKrishna.Elango@Sun.COM 
385*10187SKrishna.Elango@Sun.COM 	/* AER UE Mask - Mask UR */
386*10187SKrishna.Elango@Sun.COM 	{0x108, 32, 0x0,	PCIE_AER_UCE_UR,	PCIE_AER_UCE_UR},
387*10187SKrishna.Elango@Sun.COM };
388*10187SKrishna.Elango@Sun.COM #define	INTEL_ESB2_SW_REGS_LEN \
389*10187SKrishna.Elango@Sun.COM 	(sizeof (intel_esb2_sw_regs) / sizeof (x86_error_reg_t))
390*10187SKrishna.Elango@Sun.COM 
391*10187SKrishna.Elango@Sun.COM 
392*10187SKrishna.Elango@Sun.COM x86_error_tbl_t x86_error_init_tbl[] = {
393*10187SKrishna.Elango@Sun.COM 	/* Intel 7300: 3600 = ESI, 3604-360A = NB root ports */
394*10187SKrishna.Elango@Sun.COM 	{0x8086, 0x3600, 0x3600, 0x0, 0xFF,
395*10187SKrishna.Elango@Sun.COM 		intel_7300_rp_regs, INTEL_7300_RP_REGS_LEN},
396*10187SKrishna.Elango@Sun.COM 	{0x8086, 0x3604, 0x360A, 0x0, 0xFF,
397*10187SKrishna.Elango@Sun.COM 		intel_7300_rp_regs, INTEL_7300_RP_REGS_LEN},
398*10187SKrishna.Elango@Sun.COM 
399*10187SKrishna.Elango@Sun.COM 	/* Intel 5000: 25C0, 25D0, 25D4, 25D8 = ESI */
400*10187SKrishna.Elango@Sun.COM 	{0x8086, 0x25C0, 0x25C0, 0x0, 0xFF,
401*10187SKrishna.Elango@Sun.COM 		intel_5000_rp_regs, INTEL_5000_RP_REGS_LEN},
402*10187SKrishna.Elango@Sun.COM 	{0x8086, 0x25D0, 0x25D0, 0x0, 0xFF,
403*10187SKrishna.Elango@Sun.COM 		intel_5000_rp_regs, INTEL_5000_RP_REGS_LEN},
404*10187SKrishna.Elango@Sun.COM 	{0x8086, 0x25D4, 0x25D4, 0x0, 0xFF,
405*10187SKrishna.Elango@Sun.COM 		intel_5000_rp_regs, INTEL_5000_RP_REGS_LEN},
406*10187SKrishna.Elango@Sun.COM 	{0x8086, 0x25D8, 0x25D8, 0x0, 0xFF,
407*10187SKrishna.Elango@Sun.COM 		intel_5000_rp_regs, INTEL_5000_RP_REGS_LEN},
408*10187SKrishna.Elango@Sun.COM 
409*10187SKrishna.Elango@Sun.COM 	/* Intel 5000: 25E2-25E7 and 25F7-25FA = NB root ports */
410*10187SKrishna.Elango@Sun.COM 	{0x8086, 0x25E2, 0x25E7, 0x0, 0xFF,
411*10187SKrishna.Elango@Sun.COM 		intel_5000_rp_regs, INTEL_5000_RP_REGS_LEN},
412*10187SKrishna.Elango@Sun.COM 	{0x8086, 0x25F7, 0x25FA, 0x0, 0xFF,
413*10187SKrishna.Elango@Sun.COM 		intel_5000_rp_regs, INTEL_5000_RP_REGS_LEN},
414*10187SKrishna.Elango@Sun.COM 
415*10187SKrishna.Elango@Sun.COM 	/* Intel 5400: 4000-4001, 4003 = ESI and 4021-4029 = NB root ports */
416*10187SKrishna.Elango@Sun.COM 	{0x8086, 0x4000, 0x4001, 0x0, 0xFF,
417*10187SKrishna.Elango@Sun.COM 		intel_5400_rp_regs, INTEL_5400_RP_REGS_LEN},
418*10187SKrishna.Elango@Sun.COM 	{0x8086, 0x4003, 0x4003, 0x0, 0xFF,
419*10187SKrishna.Elango@Sun.COM 		intel_5400_rp_regs, INTEL_5400_RP_REGS_LEN},
420*10187SKrishna.Elango@Sun.COM 	{0x8086, 0x4021, 0x4029, 0x0, 0xFF,
421*10187SKrishna.Elango@Sun.COM 		intel_5400_rp_regs, INTEL_5400_RP_REGS_LEN},
422*10187SKrishna.Elango@Sun.COM 
423*10187SKrishna.Elango@Sun.COM 	/* Intel 631xESB/632xESB aka ESB2: 2690-2697 = SB root ports */
424*10187SKrishna.Elango@Sun.COM 	{0x8086, 0x2690, 0x2697, 0x0, 0xFF,
425*10187SKrishna.Elango@Sun.COM 		intel_esb2_rp_regs, INTEL_ESB2_RP_REGS_LEN},
426*10187SKrishna.Elango@Sun.COM 
427*10187SKrishna.Elango@Sun.COM 	/* Intel Switches on esb2: 3500-3503, 3510-351B */
428*10187SKrishna.Elango@Sun.COM 	{0x8086, 0x3500, 0x3503, 0x0, 0xFF,
429*10187SKrishna.Elango@Sun.COM 		intel_esb2_sw_regs, INTEL_ESB2_SW_REGS_LEN},
430*10187SKrishna.Elango@Sun.COM 	{0x8086, 0x3510, 0x351B, 0x0, 0xFF,
431*10187SKrishna.Elango@Sun.COM 		intel_esb2_sw_regs, INTEL_ESB2_SW_REGS_LEN},
432*10187SKrishna.Elango@Sun.COM 
433*10187SKrishna.Elango@Sun.COM 	/* XXX Intel PCIe-PCIx on esb2: 350C */
434*10187SKrishna.Elango@Sun.COM };
435*10187SKrishna.Elango@Sun.COM static int x86_error_init_tbl_len =
436*10187SKrishna.Elango@Sun.COM 	sizeof (x86_error_init_tbl) / sizeof (x86_error_tbl_t);
437*10187SKrishna.Elango@Sun.COM 
438*10187SKrishna.Elango@Sun.COM /*
439*10187SKrishna.Elango@Sun.COM  * The main goal of this workaround is to set chipset specific settings if
440*10187SKrishna.Elango@Sun.COM  * MSIs happen to be enabled on this device. Otherwise make the system
441*10187SKrishna.Elango@Sun.COM  * Machine Check/Panic if an UE is detected in the fabric.
442*10187SKrishna.Elango@Sun.COM  */
443*10187SKrishna.Elango@Sun.COM void
444*10187SKrishna.Elango@Sun.COM pcieb_intel_serr_workaround(dev_info_t *dip, boolean_t mcheck)
445*10187SKrishna.Elango@Sun.COM {
446*10187SKrishna.Elango@Sun.COM 	uint16_t		vid, did;
447*10187SKrishna.Elango@Sun.COM 	uint8_t			rid;
448*10187SKrishna.Elango@Sun.COM 	int			i, j;
449*10187SKrishna.Elango@Sun.COM 	x86_error_tbl_t		*tbl;
450*10187SKrishna.Elango@Sun.COM 	x86_error_reg_t		*reg;
451*10187SKrishna.Elango@Sun.COM 	pcie_bus_t		*bus_p = PCIE_DIP2UPBUS(dip);
452*10187SKrishna.Elango@Sun.COM 	ddi_acc_handle_t	cfg_hdl = bus_p->bus_cfg_hdl;
453*10187SKrishna.Elango@Sun.COM 	uint16_t		bdf = bus_p->bus_bdf;
454*10187SKrishna.Elango@Sun.COM 
455*10187SKrishna.Elango@Sun.COM 	if (pcieb_intel_workaround_disable)
456*10187SKrishna.Elango@Sun.COM 		return;
457*10187SKrishna.Elango@Sun.COM 
458*10187SKrishna.Elango@Sun.COM 	vid = bus_p->bus_dev_ven_id & 0xFFFF;
459*10187SKrishna.Elango@Sun.COM 	did = bus_p->bus_dev_ven_id >> 16;
460*10187SKrishna.Elango@Sun.COM 	rid = bus_p->bus_rev_id;
461*10187SKrishna.Elango@Sun.COM 
462*10187SKrishna.Elango@Sun.COM 	PCIEB_DEBUG(DBG_ATTACH, dip, "VID:0x%x DID:0x%x RID:0x%x bdf=0x%x\n",
463*10187SKrishna.Elango@Sun.COM 	    vid, did, rid, bdf);
464*10187SKrishna.Elango@Sun.COM 
465*10187SKrishna.Elango@Sun.COM 	tbl = x86_error_init_tbl;
466*10187SKrishna.Elango@Sun.COM 	for (i = 0; i < x86_error_init_tbl_len; i++, tbl++) {
467*10187SKrishna.Elango@Sun.COM 		if (!((vid == tbl->vendor_id) &&
468*10187SKrishna.Elango@Sun.COM 		    (did >= tbl->device_id_low) &&
469*10187SKrishna.Elango@Sun.COM 		    (did <= tbl->device_id_high) &&
470*10187SKrishna.Elango@Sun.COM 		    (rid >= tbl->rev_id_low) &&
471*10187SKrishna.Elango@Sun.COM 		    (rid <= tbl->rev_id_high)))
472*10187SKrishna.Elango@Sun.COM 			continue;
473*10187SKrishna.Elango@Sun.COM 
474*10187SKrishna.Elango@Sun.COM 		if (mcheck && PCIE_IS_RP(bus_p))
475*10187SKrishna.Elango@Sun.COM 			pcie_set_rber_fatal(dip, B_TRUE);
476*10187SKrishna.Elango@Sun.COM 
477*10187SKrishna.Elango@Sun.COM 		reg = tbl->error_regs;
478*10187SKrishna.Elango@Sun.COM 		for (j = 0; j < tbl->error_regs_len; j++, reg++) {
479*10187SKrishna.Elango@Sun.COM 			uint32_t data = 0xDEADBEEF;
480*10187SKrishna.Elango@Sun.COM 			uint32_t value = 0xDEADBEEF;
481*10187SKrishna.Elango@Sun.COM 			switch (reg->size) {
482*10187SKrishna.Elango@Sun.COM 			case 32:
483*10187SKrishna.Elango@Sun.COM 				data = (uint32_t)pci_config_get32(cfg_hdl,
484*10187SKrishna.Elango@Sun.COM 				    reg->offset);
485*10187SKrishna.Elango@Sun.COM 				value = (mcheck ?
486*10187SKrishna.Elango@Sun.COM 				    ((data & reg->mask) | reg->value2) :
487*10187SKrishna.Elango@Sun.COM 				    ((data & reg->mask) | reg->value1));
488*10187SKrishna.Elango@Sun.COM 				pci_config_put32(cfg_hdl, reg->offset, value);
489*10187SKrishna.Elango@Sun.COM 				value = (uint32_t)pci_config_get32(cfg_hdl,
490*10187SKrishna.Elango@Sun.COM 				    reg->offset);
491*10187SKrishna.Elango@Sun.COM 				break;
492*10187SKrishna.Elango@Sun.COM 			case 16:
493*10187SKrishna.Elango@Sun.COM 				data = (uint32_t)pci_config_get16(cfg_hdl,
494*10187SKrishna.Elango@Sun.COM 				    reg->offset);
495*10187SKrishna.Elango@Sun.COM 				value = (mcheck ?
496*10187SKrishna.Elango@Sun.COM 				    ((data & reg->mask) | reg->value2) :
497*10187SKrishna.Elango@Sun.COM 				    ((data & reg->mask) | reg->value1));
498*10187SKrishna.Elango@Sun.COM 				pci_config_put16(cfg_hdl, reg->offset,
499*10187SKrishna.Elango@Sun.COM 				    (uint16_t)value);
500*10187SKrishna.Elango@Sun.COM 				value = (uint32_t)pci_config_get16(cfg_hdl,
501*10187SKrishna.Elango@Sun.COM 				    reg->offset);
502*10187SKrishna.Elango@Sun.COM 				break;
503*10187SKrishna.Elango@Sun.COM 			case 8:
504*10187SKrishna.Elango@Sun.COM 				data = (uint32_t)pci_config_get8(cfg_hdl,
505*10187SKrishna.Elango@Sun.COM 				    reg->offset);
506*10187SKrishna.Elango@Sun.COM 				value = (mcheck ?
507*10187SKrishna.Elango@Sun.COM 				    ((data & reg->mask) | reg->value2) :
508*10187SKrishna.Elango@Sun.COM 				    ((data & reg->mask) | reg->value1));
509*10187SKrishna.Elango@Sun.COM 				pci_config_put8(cfg_hdl, reg->offset,
510*10187SKrishna.Elango@Sun.COM 				    (uint8_t)value);
511*10187SKrishna.Elango@Sun.COM 				value = (uint32_t)pci_config_get8(cfg_hdl,
512*10187SKrishna.Elango@Sun.COM 				    reg->offset);
513*10187SKrishna.Elango@Sun.COM 				break;
514*10187SKrishna.Elango@Sun.COM 			}
515*10187SKrishna.Elango@Sun.COM 
516*10187SKrishna.Elango@Sun.COM 			PCIEB_DEBUG(DBG_ATTACH, dip, "bdf:%x mcheck:%d size:%d "
517*10187SKrishna.Elango@Sun.COM 			    "off:0x%x mask:0x%x value:0x%x + orig:0x%x -> "
518*10187SKrishna.Elango@Sun.COM 			    "0x%x\n", bdf, mcheck, reg->size, reg->offset,
519*10187SKrishna.Elango@Sun.COM 			    reg->mask, (mcheck ?  reg->value2 : reg->value1),
520*10187SKrishna.Elango@Sun.COM 			    data, value);
521*10187SKrishna.Elango@Sun.COM 		}
522*10187SKrishna.Elango@Sun.COM 	}
523*10187SKrishna.Elango@Sun.COM }
524*10187SKrishna.Elango@Sun.COM 
525*10187SKrishna.Elango@Sun.COM /*
526*10187SKrishna.Elango@Sun.COM  * For devices that support Role Base Errors, make several UE have a FATAL
527*10187SKrishna.Elango@Sun.COM  * severity.  That way a Fatal Message will be sent instead of a Correctable
528*10187SKrishna.Elango@Sun.COM  * Message.  Without full FMA support, CEs will be ignored.
529*10187SKrishna.Elango@Sun.COM  */
530*10187SKrishna.Elango@Sun.COM uint32_t pcieb_rber_sev = (PCIE_AER_UCE_TRAINING | PCIE_AER_UCE_DLP |
531*10187SKrishna.Elango@Sun.COM     PCIE_AER_UCE_SD | PCIE_AER_UCE_PTLP | PCIE_AER_UCE_FCP | PCIE_AER_UCE_TO |
532*10187SKrishna.Elango@Sun.COM     PCIE_AER_UCE_CA | PCIE_AER_UCE_RO | PCIE_AER_UCE_MTLP | PCIE_AER_UCE_ECRC);
533*10187SKrishna.Elango@Sun.COM 
534*10187SKrishna.Elango@Sun.COM void
535*10187SKrishna.Elango@Sun.COM pcieb_intel_rber_workaround(dev_info_t *dip)
536*10187SKrishna.Elango@Sun.COM {
537*10187SKrishna.Elango@Sun.COM 	uint32_t rber;
538*10187SKrishna.Elango@Sun.COM 	pcie_bus_t *bus_p = PCIE_DIP2UPBUS(dip);
539*10187SKrishna.Elango@Sun.COM 
540*10187SKrishna.Elango@Sun.COM 	if (pcieb_intel_workaround_disable)
541*10187SKrishna.Elango@Sun.COM 		return;
542*10187SKrishna.Elango@Sun.COM 
543*10187SKrishna.Elango@Sun.COM 	/*
544*10187SKrishna.Elango@Sun.COM 	 * Check Root Port's machinecheck setting to determine if this
545*10187SKrishna.Elango@Sun.COM 	 * workaround is needed or not.
546*10187SKrishna.Elango@Sun.COM 	 */
547*10187SKrishna.Elango@Sun.COM 	if (!pcie_get_rber_fatal(dip))
548*10187SKrishna.Elango@Sun.COM 		return;
549*10187SKrishna.Elango@Sun.COM 
550*10187SKrishna.Elango@Sun.COM 	if (!PCIE_IS_PCIE(bus_p) || !PCIE_HAS_AER(bus_p))
551*10187SKrishna.Elango@Sun.COM 		return;
552*10187SKrishna.Elango@Sun.COM 
553*10187SKrishna.Elango@Sun.COM 	rber = PCIE_CAP_GET(16, bus_p, PCIE_DEVCAP) &
554*10187SKrishna.Elango@Sun.COM 	    PCIE_DEVCAP_ROLE_BASED_ERR_REP;
555*10187SKrishna.Elango@Sun.COM 	if (!rber)
556*10187SKrishna.Elango@Sun.COM 		return;
557*10187SKrishna.Elango@Sun.COM 
558*10187SKrishna.Elango@Sun.COM 	PCIE_AER_PUT(32, bus_p, PCIE_AER_UCE_SERV, pcieb_rber_sev);
559*10187SKrishna.Elango@Sun.COM }
560*10187SKrishna.Elango@Sun.COM 
561*10187SKrishna.Elango@Sun.COM /*
562*10187SKrishna.Elango@Sun.COM  * The Intel 5000 Chipset has an errata that requires read completion
563*10187SKrishna.Elango@Sun.COM  * coalescing to be disabled if the Max Payload Size is set to 256 bytes.
564*10187SKrishna.Elango@Sun.COM  */
565*10187SKrishna.Elango@Sun.COM void
566*10187SKrishna.Elango@Sun.COM pcieb_intel_mps_workaround(dev_info_t *dip)
567*10187SKrishna.Elango@Sun.COM {
568*10187SKrishna.Elango@Sun.COM 	uint16_t		vid, did;
569*10187SKrishna.Elango@Sun.COM 	uint32_t		pexctrl;
570*10187SKrishna.Elango@Sun.COM 	pcie_bus_t		*bus_p = PCIE_DIP2UPBUS(dip);
571*10187SKrishna.Elango@Sun.COM 
572*10187SKrishna.Elango@Sun.COM 	vid = bus_p->bus_dev_ven_id & 0xFFFF;
573*10187SKrishna.Elango@Sun.COM 	did = bus_p->bus_dev_ven_id >> 16;
574*10187SKrishna.Elango@Sun.COM 
575*10187SKrishna.Elango@Sun.COM 	if ((vid == INTEL_VENDOR_ID) && INTEL_NB5000_PCIE_DEV_ID(did)) {
576*10187SKrishna.Elango@Sun.COM 		pexctrl = pci_config_get32(bus_p->bus_cfg_hdl,
577*10187SKrishna.Elango@Sun.COM 		    INTEL_NB5000_PEXCTRL_OFFSET);
578*10187SKrishna.Elango@Sun.COM 		/*
579*10187SKrishna.Elango@Sun.COM 		 * Turn off coalescing (bit 10)
580*10187SKrishna.Elango@Sun.COM 		 */
581*10187SKrishna.Elango@Sun.COM 		pexctrl &= ~INTEL_NB5000_PEXCTRL_COALESCE_EN;
582*10187SKrishna.Elango@Sun.COM 
583*10187SKrishna.Elango@Sun.COM 		pci_config_put32(bus_p->bus_cfg_hdl,
584*10187SKrishna.Elango@Sun.COM 		    INTEL_NB5000_PEXCTRL_OFFSET, pexctrl);
585*10187SKrishna.Elango@Sun.COM 	}
586*10187SKrishna.Elango@Sun.COM }
587*10187SKrishna.Elango@Sun.COM 
588*10187SKrishna.Elango@Sun.COM /*
589*10187SKrishna.Elango@Sun.COM  * Workaround for certain switches regardless of platform
590*10187SKrishna.Elango@Sun.COM  */
591*10187SKrishna.Elango@Sun.COM void
592*10187SKrishna.Elango@Sun.COM pcieb_intel_sw_workaround(dev_info_t *dip)
593*10187SKrishna.Elango@Sun.COM {
594*10187SKrishna.Elango@Sun.COM 	uint16_t		vid, regw;
595*10187SKrishna.Elango@Sun.COM 	pcie_bus_t		*bus_p = PCIE_DIP2UPBUS(dip);
596*10187SKrishna.Elango@Sun.COM 	ddi_acc_handle_t	cfg_hdl = bus_p->bus_cfg_hdl;
597*10187SKrishna.Elango@Sun.COM 
598*10187SKrishna.Elango@Sun.COM 	if (pcieb_intel_workaround_disable)
599*10187SKrishna.Elango@Sun.COM 		return;
600*10187SKrishna.Elango@Sun.COM 
601*10187SKrishna.Elango@Sun.COM 	if (!PCIE_IS_SW(PCIE_DIP2BUS(dip)))
602*10187SKrishna.Elango@Sun.COM 		return;
603*10187SKrishna.Elango@Sun.COM 
604*10187SKrishna.Elango@Sun.COM 	vid = bus_p->bus_dev_ven_id & 0xFFFF;
605*10187SKrishna.Elango@Sun.COM 	/*
606*10187SKrishna.Elango@Sun.COM 	 * Intel and PLX switches require SERR in CMD reg to foward error
607*10187SKrishna.Elango@Sun.COM 	 * messages, though this is not PCIE spec-compliant behavior.
608*10187SKrishna.Elango@Sun.COM 	 * To prevent the switches themselves from reporting errors on URs
609*10187SKrishna.Elango@Sun.COM 	 * when the CMD reg has SERR enabled (which is expected according to
610*10187SKrishna.Elango@Sun.COM 	 * the PCIE spec) we rely on masking URs in the AER cap.
611*10187SKrishna.Elango@Sun.COM 	 */
612*10187SKrishna.Elango@Sun.COM 	if (vid == 0x8086 || vid == 0x10B5) {
613*10187SKrishna.Elango@Sun.COM 		regw = pci_config_get16(cfg_hdl, PCI_CONF_COMM);
614*10187SKrishna.Elango@Sun.COM 		pci_config_put16(cfg_hdl, PCI_CONF_COMM,
615*10187SKrishna.Elango@Sun.COM 		    regw | PCI_COMM_SERR_ENABLE);
616*10187SKrishna.Elango@Sun.COM 	}
617*10187SKrishna.Elango@Sun.COM }
618*10187SKrishna.Elango@Sun.COM 
619*10187SKrishna.Elango@Sun.COM int
620*10187SKrishna.Elango@Sun.COM pcieb_plat_ctlops(dev_info_t *rdip, ddi_ctl_enum_t ctlop, void *arg)
621*10187SKrishna.Elango@Sun.COM {
622*10187SKrishna.Elango@Sun.COM 	struct detachspec *ds;
623*10187SKrishna.Elango@Sun.COM 	struct attachspec *as;
624*10187SKrishna.Elango@Sun.COM 
625*10187SKrishna.Elango@Sun.COM 	switch (ctlop) {
626*10187SKrishna.Elango@Sun.COM 	case DDI_CTLOPS_DETACH:
627*10187SKrishna.Elango@Sun.COM 		ds = (struct detachspec *)arg;
628*10187SKrishna.Elango@Sun.COM 		switch (ds->when) {
629*10187SKrishna.Elango@Sun.COM 		case DDI_POST:
630*10187SKrishna.Elango@Sun.COM 			if (ds->cmd == DDI_SUSPEND) {
631*10187SKrishna.Elango@Sun.COM 				if (pci_post_suspend(rdip) != DDI_SUCCESS)
632*10187SKrishna.Elango@Sun.COM 					return (DDI_FAILURE);
633*10187SKrishna.Elango@Sun.COM 			}
634*10187SKrishna.Elango@Sun.COM 			break;
635*10187SKrishna.Elango@Sun.COM 		default:
636*10187SKrishna.Elango@Sun.COM 			break;
637*10187SKrishna.Elango@Sun.COM 		}
638*10187SKrishna.Elango@Sun.COM 		break;
639*10187SKrishna.Elango@Sun.COM 	case DDI_CTLOPS_ATTACH:
640*10187SKrishna.Elango@Sun.COM 		as = (struct attachspec *)arg;
641*10187SKrishna.Elango@Sun.COM 		switch (as->when) {
642*10187SKrishna.Elango@Sun.COM 		case DDI_PRE:
643*10187SKrishna.Elango@Sun.COM 			if (as->cmd == DDI_RESUME) {
644*10187SKrishna.Elango@Sun.COM 				if (pci_pre_resume(rdip) != DDI_SUCCESS)
645*10187SKrishna.Elango@Sun.COM 					return (DDI_FAILURE);
646*10187SKrishna.Elango@Sun.COM 			}
647*10187SKrishna.Elango@Sun.COM 			break;
648*10187SKrishna.Elango@Sun.COM 		case DDI_POST:
649*10187SKrishna.Elango@Sun.COM 			/*
650*10187SKrishna.Elango@Sun.COM 			 * For leaf devices supporting RBER and AER, we
651*10187SKrishna.Elango@Sun.COM 			 * need to apply this workaround on them after
652*10187SKrishna.Elango@Sun.COM 			 * attach to be notified of UEs that would
653*10187SKrishna.Elango@Sun.COM 			 * otherwise be ignored as CEs on Intel chipsets
654*10187SKrishna.Elango@Sun.COM 			 * currently
655*10187SKrishna.Elango@Sun.COM 			 */
656*10187SKrishna.Elango@Sun.COM 			pcieb_intel_rber_workaround(rdip);
657*10187SKrishna.Elango@Sun.COM 			break;
658*10187SKrishna.Elango@Sun.COM 		default:
659*10187SKrishna.Elango@Sun.COM 			break;
660*10187SKrishna.Elango@Sun.COM 		}
661*10187SKrishna.Elango@Sun.COM 		break;
662*10187SKrishna.Elango@Sun.COM 	default:
663*10187SKrishna.Elango@Sun.COM 		break;
664*10187SKrishna.Elango@Sun.COM 	}
665*10187SKrishna.Elango@Sun.COM 
666*10187SKrishna.Elango@Sun.COM 	return (DDI_SUCCESS);
667*10187SKrishna.Elango@Sun.COM }
668*10187SKrishna.Elango@Sun.COM 
669*10187SKrishna.Elango@Sun.COM void
670*10187SKrishna.Elango@Sun.COM pcieb_plat_ioctl_hotplug(dev_info_t *dip, int rv, int cmd)
671*10187SKrishna.Elango@Sun.COM {
672*10187SKrishna.Elango@Sun.COM 	/*
673*10187SKrishna.Elango@Sun.COM 	 * like in attach, since hotplugging can change error registers,
674*10187SKrishna.Elango@Sun.COM 	 * we need to ensure that the proper bits are set on this port
675*10187SKrishna.Elango@Sun.COM 	 * after a configure operation
676*10187SKrishna.Elango@Sun.COM 	 */
677*10187SKrishna.Elango@Sun.COM 	if ((rv == HPC_SUCCESS) && (cmd == DEVCTL_AP_CONFIGURE))
678*10187SKrishna.Elango@Sun.COM 		pcieb_intel_error_workaround(dip);
679*10187SKrishna.Elango@Sun.COM }
680