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