4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* x86 specific code used by the pcieb driver */
28 #include <sys/types.h>
31 #include <sys/sysmacros.h>
32 #include <sys/sunddi.h>
33 #include <sys/sunndi.h>
35 #include <sys/pci_cap.h>
36 #include <sys/pcie_impl.h>
37 #include <sys/pcie_acpi.h>
38 #include <sys/hotplug/hpctrl.h>
39 #include <io/pciex/pcieb.h>
40 #include <io/pciex/pcie_nb5000.h>
42 /* Flag to turn off intel error handling workarounds */
43 int pcieb_intel_workaround_disable
= 0;
46 pcieb_peekpoke_cb(dev_info_t
*dip
, ddi_fm_error_t
*derr
) {
47 pf_eh_enter(PCIE_DIP2BUS(dip
));
48 (void) pf_scan_fabric(dip
, derr
, NULL
);
49 pf_eh_exit(PCIE_DIP2BUS(dip
));
53 pcieb_set_prot_scan(dev_info_t
*dip
, ddi_acc_impl_t
*hdlp
)
55 pcieb_devstate_t
*pcieb
= ddi_get_soft_state(pcieb_state
,
56 ddi_get_instance(dip
));
58 hdlp
->ahi_err_mutexp
= &pcieb
->pcieb_err_mutex
;
59 hdlp
->ahi_peekpoke_mutexp
= &pcieb
->pcieb_peek_poke_mutex
;
60 hdlp
->ahi_scan_dip
= dip
;
61 hdlp
->ahi_scan
= pcieb_peekpoke_cb
;
65 pcieb_plat_peekpoke(dev_info_t
*dip
, dev_info_t
*rdip
, ddi_ctl_enum_t ctlop
,
66 void *arg
, void *result
)
68 pcieb_devstate_t
*pcieb
= ddi_get_soft_state(pcieb_state
,
69 ddi_get_instance(dip
));
71 if (!PCIE_IS_RP(PCIE_DIP2BUS(dip
)))
72 return (ddi_ctlops(dip
, rdip
, ctlop
, arg
, result
));
74 return (pci_peekpoke_check(dip
, rdip
, ctlop
, arg
, result
,
75 ddi_ctlops
, &pcieb
->pcieb_err_mutex
,
76 &pcieb
->pcieb_peek_poke_mutex
,
80 /* x86 specific workarounds needed at the end of pcieb attach */
82 pcieb_plat_attach_workaround(dev_info_t
*dip
)
84 /* Must apply workaround only after all initialization is done */
85 pcieb_intel_error_workaround(dip
);
86 pcieb_intel_mps_workaround(dip
);
90 /* Workarounds to enable error handling on certain Intel chipsets */
92 pcieb_intel_error_workaround(dev_info_t
*dip
)
94 pcieb_devstate_t
*pcieb
= ddi_get_soft_state(pcieb_state
,
95 ddi_get_instance(dip
));
97 pcieb_intel_serr_workaround(dip
, pcieb
->pcieb_no_aer_msi
);
98 pcieb_intel_rber_workaround(dip
);
99 pcieb_intel_sw_workaround(dip
);
103 pcieb_plat_intr_ops(dev_info_t
*dip
, dev_info_t
*rdip
, ddi_intr_op_t intr_op
,
104 ddi_intr_handle_impl_t
*hdlp
, void *result
)
106 return (i_ddi_intr_ops(dip
, rdip
, intr_op
, hdlp
, result
));
109 /* shpc is not supported on x86 */
112 pcieb_plat_pcishpc_probe(dev_info_t
*dip
, ddi_acc_handle_t config_handle
)
114 return (DDI_FAILURE
);
118 * Dummy functions to get around the fact that there's no shpc module on x86
123 pcishpc_init(dev_info_t
*dip
)
125 return (DDI_FAILURE
);
130 pcishpc_uninit(dev_info_t
*dip
)
132 return (DDI_FAILURE
);
137 pcishpc_intr(dev_info_t
*dip
)
139 return (DDI_INTR_UNCLAIMED
);
144 pcieb_plat_pwr_disable(dev_info_t
*dip
)
146 /* Always disable on x86 */
151 pcieb_plat_msi_supported(dev_info_t
*dip
)
153 pcie_bus_t
*bus_p
= PCIE_DIP2UPBUS(dip
);
154 uint16_t vendor_id
, device_id
;
155 vendor_id
= bus_p
->bus_dev_ven_id
& 0xFFFF;
156 device_id
= bus_p
->bus_dev_ven_id
>> 16;
159 * Intel ESB2 switches have a errata which prevents using MSIs
162 return (((vendor_id
== INTEL_VENDOR_ID
) &&
163 INTEL_ESB2_SW_PCIE_DEV_ID(device_id
)) ? B_FALSE
: B_TRUE
);
167 pcieb_plat_intr_attach(pcieb_devstate_t
*pcieb
)
170 * _OSC initialization needs to be done before interrupts are
173 pcieb_init_osc(pcieb
->pcieb_dip
);
177 pcieb_plat_initchild(dev_info_t
*child
)
179 struct ddi_parent_private_data
*pdptr
;
180 if (ddi_getprop(DDI_DEV_T_NONE
, child
, DDI_PROP_DONTPASS
, "interrupts",
182 pdptr
= kmem_zalloc((sizeof (struct ddi_parent_private_data
) +
183 sizeof (struct intrspec
)), KM_SLEEP
);
184 pdptr
->par_intr
= (struct intrspec
*)(pdptr
+ 1);
185 pdptr
->par_nintr
= 1;
186 ddi_set_parent_data(child
, pdptr
);
188 ddi_set_parent_data(child
, NULL
);
192 pcieb_plat_uninitchild(dev_info_t
*child
)
194 struct ddi_parent_private_data
*pdptr
;
196 if ((pdptr
= ddi_get_parent_data(child
)) != NULL
)
197 kmem_free(pdptr
, (sizeof (*pdptr
) + sizeof (struct intrspec
)));
199 ddi_set_parent_data(child
, NULL
);
204 pcieb_init_osc(dev_info_t
*devi
) {
205 pcie_bus_t
*bus_p
= PCIE_DIP2UPBUS(devi
);
206 uint32_t osc_flags
= OSC_CONTROL_PCIE_ADV_ERR
;
209 * Call _OSC method for 2 reasons:
210 * 1. Hotplug: To determine if it is native or ACPI mode.
212 * 2. Error handling: Inform firmware that OS can support AER error
213 * handling. Currently we don't care for what the BIOS response was
214 * and instead setup interrupts for error handling as if it were
217 * For hotpluggable slots the _OSC method has already been called as
218 * part of the hotplug initialization.
219 * For non-hotpluggable slots we need to call the _OSC method only for
220 * Root Ports (for AER support).
222 if (!pcie_is_osc(devi
) && PCIE_IS_RP(bus_p
) && PCIE_HAS_AER(bus_p
))
223 (void) pcie_acpi_osc(devi
, &osc_flags
);
227 * Intel chip specific workarounds. Right now they're limited to the 5000, 5400
228 * and 7300 series chipsets.
230 typedef struct x86_error_reg
{
234 uint32_t value1
; /* Value for MSI case */
235 uint32_t value2
; /* Value for machinecheck case */
238 typedef struct x86_error_tbl
{
240 uint16_t device_id_low
;
241 uint16_t device_id_high
;
244 x86_error_reg_t
*error_regs
;
249 * Chipset and device specific settings that are required for error handling
250 * (reporting, fowarding, and response at the RC) beyond the standard
251 * registers in the PCIE and AER caps.
253 * The Northbridge Root Port settings also apply to the ESI port. The ESI
254 * port is a special leaf device but functions like a root port connected
255 * to the Southbridge and receives all the onboard Southbridge errors
256 * including those from Southbridge Root Ports. However, this does not
257 * include the Southbridge Switch Ports which act like normal switch ports
258 * and is connected to the Northbridge through a separate link.
260 * PCIE errors from the ESB2 Southbridge RPs are simply fowarded to the ESI
261 * port on the Northbridge.
263 * If MSIs don't work we want UEs (Fatal and Non-Fatal) to panic the system,
264 * except for URs. We do this by having the Root Ports respond with a System
265 * Error and having that trigger a Machine Check (MCE).
269 * 7300 Northbridge Root Ports
271 static x86_error_reg_t intel_7300_rp_regs
[] = {
272 /* Command Register - Enable SERR */
273 {0x4, 16, 0xFFFF, 0x0, PCI_COMM_SERR_ENABLE
},
275 /* Root Control Register - SERR on NFE/FE */
276 {0x88, 16, 0x0, 0x0, PCIE_ROOTCTL_SYS_ERR_ON_NFE_EN
|
277 PCIE_ROOTCTL_SYS_ERR_ON_FE_EN
},
279 /* AER UE Mask - Mask UR */
280 {0x108, 32, 0x0, PCIE_AER_UCE_UR
, PCIE_AER_UCE_UR
},
282 /* PEXCTRL[21] check for certain malformed TLP types and MSI enable */
283 {0x48, 32, 0xFFFFFFFF, 0xC0200000, 0x200000},
284 /* PEXCTRL3[7]. MSI RAS error enable */
285 {0x4D, 32, 0xFFFFFFFF, 0x1, 0x0},
287 /* PEX_ERR_DOCMD[7:0] */
288 {0x144, 8, 0x0, 0x0, 0xF0},
290 /* EMASK_UNCOR_PEX[21:0] UE mask */
291 {0x148, 32, 0x0, PCIE_AER_UCE_UR
, PCIE_AER_UCE_UR
},
293 /* EMASK_RP_PEX[2:0] FE, UE, CE message detect mask */
294 {0x150, 8, 0x0, 0x0, 0x1},
296 #define INTEL_7300_RP_REGS_LEN \
297 (sizeof (intel_7300_rp_regs) / sizeof (x86_error_reg_t))
300 * 5000 Northbridge Root Ports
302 static x86_error_reg_t intel_5000_rp_regs
[] = {
303 /* Command Register - Enable SERR */
304 {0x4, 16, 0xFFFF, PCI_COMM_SERR_ENABLE
, PCI_COMM_SERR_ENABLE
},
306 /* Root Control Register - SERR on NFE/FE/CE */
307 {0x88, 16, 0x0, PCIE_ROOTCTL_SYS_ERR_ON_NFE_EN
|
308 PCIE_ROOTCTL_SYS_ERR_ON_FE_EN
|
309 PCIE_ROOTCTL_SYS_ERR_ON_CE_EN
,
310 PCIE_ROOTCTL_SYS_ERR_ON_NFE_EN
|
311 PCIE_ROOTCTL_SYS_ERR_ON_FE_EN
},
313 /* AER UE Mask - Mask UR */
314 {0x108, 32, 0x0, PCIE_AER_UCE_UR
, PCIE_AER_UCE_UR
},
316 /* PEXCTRL[21] check for certain malformed TLP type */
317 {0x48, 32, 0xFFFFFFFF, 0xC0200000, 0x200000},
318 /* PEXCTRL3[7]. MSI RAS error enable. */
319 {0x4D, 32, 0xFFFFFFFF, 0x1, 0x0},
321 /* PEX_ERR_DOCMD[7:0] */
322 {0x144, 8, 0x0, 0x0, 0xF0},
324 /* EMASK_UNCOR_PEX[21:0] UE mask */
325 {0x148, 32, 0x0, PCIE_AER_UCE_UR
, PCIE_AER_UCE_UR
},
327 /* EMASK_RP_PEX[2:0] FE, UE, CE message detect mask */
328 {0x150, 8, 0x0, 0x0, 0x1},
330 #define INTEL_5000_RP_REGS_LEN \
331 (sizeof (intel_5000_rp_regs) / sizeof (x86_error_reg_t))
334 * 5400 Northbridge Root Ports.
336 static x86_error_reg_t intel_5400_rp_regs
[] = {
337 /* Command Register - Enable SERR */
338 {0x4, 16, 0xFFFF, PCI_COMM_SERR_ENABLE
, PCI_COMM_SERR_ENABLE
},
340 /* Root Control Register - SERR on NFE/FE */
341 {0x88, 16, 0x0, PCIE_ROOTCTL_SYS_ERR_ON_NFE_EN
|
342 PCIE_ROOTCTL_SYS_ERR_ON_FE_EN
|
343 PCIE_ROOTCTL_SYS_ERR_ON_CE_EN
,
344 PCIE_ROOTCTL_SYS_ERR_ON_NFE_EN
|
345 PCIE_ROOTCTL_SYS_ERR_ON_FE_EN
},
347 /* AER UE Mask - Mask UR */
348 {0x108, 32, 0x0, PCIE_AER_UCE_UR
, PCIE_AER_UCE_UR
},
350 /* PEXCTRL[21] check for certain malformed TLP types */
351 {0x48, 32, 0xFFFFFFFF, 0xC0200000, 0x200000},
352 /* PEXCTRL3. MSI RAS error enable. */
353 {0x4E, 8, 0x0, 0x1, 0x0},
355 /* PEX_ERR_DOCMD[11:0] */
356 {0x144, 16, 0x0, 0x0, 0xFF0},
358 /* PEX_ERR_PIN_MASK[4:0] do not mask ERR[2:0] pins used by DOCMD */
359 {0x146, 16, 0x0, 0x10, 0x10},
361 /* EMASK_UNCOR_PEX[21:0] UE mask */
362 {0x148, 32, 0x0, PCIE_AER_UCE_UR
, PCIE_AER_UCE_UR
},
364 /* EMASK_RP_PEX[2:0] FE, UE, CE message detect mask */
365 {0x150, 8, 0x0, 0x0, 0x1},
367 #define INTEL_5400_RP_REGS_LEN \
368 (sizeof (intel_5400_rp_regs) / sizeof (x86_error_reg_t))
372 * ESB2 Southbridge Root Ports
374 static x86_error_reg_t intel_esb2_rp_regs
[] = {
375 /* Command Register - Enable SERR */
376 {0x4, 16, 0xFFFF, PCI_COMM_SERR_ENABLE
, PCI_COMM_SERR_ENABLE
},
378 /* Root Control Register - SERR on NFE/FE */
379 {0x5c, 16, 0x0, PCIE_ROOTCTL_SYS_ERR_ON_NFE_EN
|
380 PCIE_ROOTCTL_SYS_ERR_ON_FE_EN
|
381 PCIE_ROOTCTL_SYS_ERR_ON_CE_EN
,
382 PCIE_ROOTCTL_SYS_ERR_ON_NFE_EN
|
383 PCIE_ROOTCTL_SYS_ERR_ON_FE_EN
},
385 /* UEM[20:0] UE mask (write-once) */
386 {0x148, 32, 0x0, PCIE_AER_UCE_UR
, PCIE_AER_UCE_UR
},
388 #define INTEL_ESB2_RP_REGS_LEN \
389 (sizeof (intel_esb2_rp_regs) / sizeof (x86_error_reg_t))
393 * ESB2 Southbridge Switch Ports
395 static x86_error_reg_t intel_esb2_sw_regs
[] = {
396 /* Command Register - Enable SERR */
397 {0x4, 16, 0xFFFF, PCI_COMM_SERR_ENABLE
, PCI_COMM_SERR_ENABLE
},
399 /* AER UE Mask - Mask UR */
400 {0x108, 32, 0x0, PCIE_AER_UCE_UR
, PCIE_AER_UCE_UR
},
402 #define INTEL_ESB2_SW_REGS_LEN \
403 (sizeof (intel_esb2_sw_regs) / sizeof (x86_error_reg_t))
406 x86_error_tbl_t x86_error_init_tbl
[] = {
407 /* Intel 7300: 3600 = ESI, 3604-360A = NB root ports */
408 {0x8086, 0x3600, 0x3600, 0x0, 0xFF,
409 intel_7300_rp_regs
, INTEL_7300_RP_REGS_LEN
},
410 {0x8086, 0x3604, 0x360A, 0x0, 0xFF,
411 intel_7300_rp_regs
, INTEL_7300_RP_REGS_LEN
},
413 /* Intel 5000: 25C0, 25D0, 25D4, 25D8 = ESI */
414 {0x8086, 0x25C0, 0x25C0, 0x0, 0xFF,
415 intel_5000_rp_regs
, INTEL_5000_RP_REGS_LEN
},
416 {0x8086, 0x25D0, 0x25D0, 0x0, 0xFF,
417 intel_5000_rp_regs
, INTEL_5000_RP_REGS_LEN
},
418 {0x8086, 0x25D4, 0x25D4, 0x0, 0xFF,
419 intel_5000_rp_regs
, INTEL_5000_RP_REGS_LEN
},
420 {0x8086, 0x25D8, 0x25D8, 0x0, 0xFF,
421 intel_5000_rp_regs
, INTEL_5000_RP_REGS_LEN
},
423 /* Intel 5000: 25E2-25E7 and 25F7-25FA = NB root ports */
424 {0x8086, 0x25E2, 0x25E7, 0x0, 0xFF,
425 intel_5000_rp_regs
, INTEL_5000_RP_REGS_LEN
},
426 {0x8086, 0x25F7, 0x25FA, 0x0, 0xFF,
427 intel_5000_rp_regs
, INTEL_5000_RP_REGS_LEN
},
429 /* Intel 5400: 4000-4001, 4003 = ESI and 4021-4029 = NB root ports */
430 {0x8086, 0x4000, 0x4001, 0x0, 0xFF,
431 intel_5400_rp_regs
, INTEL_5400_RP_REGS_LEN
},
432 {0x8086, 0x4003, 0x4003, 0x0, 0xFF,
433 intel_5400_rp_regs
, INTEL_5400_RP_REGS_LEN
},
434 {0x8086, 0x4021, 0x4029, 0x0, 0xFF,
435 intel_5400_rp_regs
, INTEL_5400_RP_REGS_LEN
},
437 /* Intel 631xESB/632xESB aka ESB2: 2690-2697 = SB root ports */
438 {0x8086, 0x2690, 0x2697, 0x0, 0xFF,
439 intel_esb2_rp_regs
, INTEL_ESB2_RP_REGS_LEN
},
441 /* Intel Switches on esb2: 3500-3503, 3510-351B */
442 {0x8086, 0x3500, 0x3503, 0x0, 0xFF,
443 intel_esb2_sw_regs
, INTEL_ESB2_SW_REGS_LEN
},
444 {0x8086, 0x3510, 0x351B, 0x0, 0xFF,
445 intel_esb2_sw_regs
, INTEL_ESB2_SW_REGS_LEN
},
447 /* XXX Intel PCIe-PCIx on esb2: 350C */
449 static int x86_error_init_tbl_len
=
450 sizeof (x86_error_init_tbl
) / sizeof (x86_error_tbl_t
);
453 * The main goal of this workaround is to set chipset specific settings if
454 * MSIs happen to be enabled on this device. Otherwise make the system
455 * Machine Check/Panic if an UE is detected in the fabric.
458 pcieb_intel_serr_workaround(dev_info_t
*dip
, boolean_t mcheck
)
463 x86_error_tbl_t
*tbl
;
464 x86_error_reg_t
*reg
;
465 pcie_bus_t
*bus_p
= PCIE_DIP2UPBUS(dip
);
466 ddi_acc_handle_t cfg_hdl
= bus_p
->bus_cfg_hdl
;
467 uint16_t bdf
= bus_p
->bus_bdf
;
469 if (pcieb_intel_workaround_disable
)
472 vid
= bus_p
->bus_dev_ven_id
& 0xFFFF;
473 did
= bus_p
->bus_dev_ven_id
>> 16;
474 rid
= bus_p
->bus_rev_id
;
476 PCIEB_DEBUG(DBG_ATTACH
, dip
, "VID:0x%x DID:0x%x RID:0x%x bdf=0x%x\n",
479 tbl
= x86_error_init_tbl
;
480 for (i
= 0; i
< x86_error_init_tbl_len
; i
++, tbl
++) {
481 if (!((vid
== tbl
->vendor_id
) &&
482 (did
>= tbl
->device_id_low
) &&
483 (did
<= tbl
->device_id_high
) &&
484 (rid
>= tbl
->rev_id_low
) &&
485 (rid
<= tbl
->rev_id_high
)))
488 if (mcheck
&& PCIE_IS_RP(bus_p
))
489 pcie_set_rber_fatal(dip
, B_TRUE
);
491 reg
= tbl
->error_regs
;
492 for (j
= 0; j
< tbl
->error_regs_len
; j
++, reg
++) {
493 uint32_t data
= 0xDEADBEEF;
494 uint32_t value
= 0xDEADBEEF;
497 data
= (uint32_t)pci_config_get32(cfg_hdl
,
500 ((data
& reg
->mask
) | reg
->value2
) :
501 ((data
& reg
->mask
) | reg
->value1
));
502 pci_config_put32(cfg_hdl
, reg
->offset
, value
);
503 value
= (uint32_t)pci_config_get32(cfg_hdl
,
507 data
= (uint32_t)pci_config_get16(cfg_hdl
,
510 ((data
& reg
->mask
) | reg
->value2
) :
511 ((data
& reg
->mask
) | reg
->value1
));
512 pci_config_put16(cfg_hdl
, reg
->offset
,
514 value
= (uint32_t)pci_config_get16(cfg_hdl
,
518 data
= (uint32_t)pci_config_get8(cfg_hdl
,
521 ((data
& reg
->mask
) | reg
->value2
) :
522 ((data
& reg
->mask
) | reg
->value1
));
523 pci_config_put8(cfg_hdl
, reg
->offset
,
525 value
= (uint32_t)pci_config_get8(cfg_hdl
,
530 PCIEB_DEBUG(DBG_ATTACH
, dip
, "bdf:%x mcheck:%d size:%d "
531 "off:0x%x mask:0x%x value:0x%x + orig:0x%x -> "
532 "0x%x\n", bdf
, mcheck
, reg
->size
, reg
->offset
,
533 reg
->mask
, (mcheck
? reg
->value2
: reg
->value1
),
540 * For devices that support Role Base Errors, make several UE have a FATAL
541 * severity. That way a Fatal Message will be sent instead of a Correctable
542 * Message. Without full FMA support, CEs will be ignored.
544 uint32_t pcieb_rber_sev
= (PCIE_AER_UCE_TRAINING
| PCIE_AER_UCE_DLP
|
545 PCIE_AER_UCE_SD
| PCIE_AER_UCE_PTLP
| PCIE_AER_UCE_FCP
| PCIE_AER_UCE_TO
|
546 PCIE_AER_UCE_CA
| PCIE_AER_UCE_RO
| PCIE_AER_UCE_MTLP
| PCIE_AER_UCE_ECRC
);
549 pcieb_intel_rber_workaround(dev_info_t
*dip
)
552 pcie_bus_t
*bus_p
= PCIE_DIP2UPBUS(dip
);
554 if (pcieb_intel_workaround_disable
)
558 * Check Root Port's machinecheck setting to determine if this
559 * workaround is needed or not.
561 if (!pcie_get_rber_fatal(dip
))
564 if (!PCIE_IS_PCIE(bus_p
) || !PCIE_HAS_AER(bus_p
))
567 rber
= PCIE_CAP_GET(16, bus_p
, PCIE_DEVCAP
) &
568 PCIE_DEVCAP_ROLE_BASED_ERR_REP
;
572 PCIE_AER_PUT(32, bus_p
, PCIE_AER_UCE_SERV
, pcieb_rber_sev
);
576 * The Intel 5000 Chipset has an errata that requires read completion
577 * coalescing to be disabled if the Max Payload Size is set to 256 bytes.
580 pcieb_intel_mps_workaround(dev_info_t
*dip
)
584 pcie_bus_t
*bus_p
= PCIE_DIP2UPBUS(dip
);
586 vid
= bus_p
->bus_dev_ven_id
& 0xFFFF;
587 did
= bus_p
->bus_dev_ven_id
>> 16;
589 if ((vid
== INTEL_VENDOR_ID
) && (INTEL_NB5000_PCIE_DEV_ID(did
) ||
590 INTEL_NB5100_PCIE_DEV_ID(did
))) {
592 pexctrl
= pci_config_get32(bus_p
->bus_cfg_hdl
,
593 INTEL_NB5000_PEXCTRL_OFFSET
);
595 * Turn off coalescing (bit 10)
597 pexctrl
&= ~INTEL_NB5000_PEXCTRL_COALESCE_EN
;
599 pci_config_put32(bus_p
->bus_cfg_hdl
,
600 INTEL_NB5000_PEXCTRL_OFFSET
, pexctrl
);
605 * Workaround for certain switches regardless of platform
608 pcieb_intel_sw_workaround(dev_info_t
*dip
)
611 pcie_bus_t
*bus_p
= PCIE_DIP2UPBUS(dip
);
612 ddi_acc_handle_t cfg_hdl
= bus_p
->bus_cfg_hdl
;
614 if (pcieb_intel_workaround_disable
)
617 if (!PCIE_IS_SW(PCIE_DIP2BUS(dip
)))
620 vid
= bus_p
->bus_dev_ven_id
& 0xFFFF;
622 * Intel and PLX switches require SERR in CMD reg to foward error
623 * messages, though this is not PCIE spec-compliant behavior.
624 * To prevent the switches themselves from reporting errors on URs
625 * when the CMD reg has SERR enabled (which is expected according to
626 * the PCIE spec) we rely on masking URs in the AER cap.
628 if (vid
== 0x8086 || vid
== 0x10B5) {
629 regw
= pci_config_get16(cfg_hdl
, PCI_CONF_COMM
);
630 pci_config_put16(cfg_hdl
, PCI_CONF_COMM
,
631 regw
| PCI_COMM_SERR_ENABLE
);
636 pcieb_plat_ctlops(dev_info_t
*rdip
, ddi_ctl_enum_t ctlop
, void *arg
)
638 struct detachspec
*ds
;
639 struct attachspec
*as
;
642 case DDI_CTLOPS_DETACH
:
643 ds
= (struct detachspec
*)arg
;
646 if (ds
->cmd
== DDI_SUSPEND
) {
647 if (pci_post_suspend(rdip
) != DDI_SUCCESS
)
648 return (DDI_FAILURE
);
655 case DDI_CTLOPS_ATTACH
:
656 as
= (struct attachspec
*)arg
;
659 if (as
->cmd
== DDI_RESUME
) {
660 if (pci_pre_resume(rdip
) != DDI_SUCCESS
)
661 return (DDI_FAILURE
);
666 * For leaf devices supporting RBER and AER, we
667 * need to apply this workaround on them after
668 * attach to be notified of UEs that would
669 * otherwise be ignored as CEs on Intel chipsets
672 pcieb_intel_rber_workaround(rdip
);
682 return (DDI_SUCCESS
);