1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* x86 specific code used by the pcieb driver */ 27 28 #include <sys/types.h> 29 #include <sys/ddi.h> 30 #include <sys/kmem.h> 31 #include <sys/sysmacros.h> 32 #include <sys/sunddi.h> 33 #include <sys/sunndi.h> 34 #include <sys/pcie.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> 41 42 /* Flag to turn off intel error handling workarounds */ 43 int pcieb_intel_workaround_disable = 0; 44 45 void 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)); 50 } 51 52 void 53 pcieb_set_prot_scan(dev_info_t *dip, ddi_acc_impl_t *hdlp) 54 { 55 pcieb_devstate_t *pcieb = ddi_get_soft_state(pcieb_state, 56 ddi_get_instance(dip)); 57 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; 62 } 63 64 int 65 pcieb_plat_peekpoke(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop, 66 void *arg, void *result) 67 { 68 pcieb_devstate_t *pcieb = ddi_get_soft_state(pcieb_state, 69 ddi_get_instance(dip)); 70 71 if (!PCIE_IS_RP(PCIE_DIP2BUS(dip))) 72 return (ddi_ctlops(dip, rdip, ctlop, arg, result)); 73 74 return (pci_peekpoke_check(dip, rdip, ctlop, arg, result, 75 ddi_ctlops, &pcieb->pcieb_err_mutex, 76 &pcieb->pcieb_peek_poke_mutex, 77 pcieb_peekpoke_cb)); 78 } 79 80 /* x86 specific workarounds needed at the end of pcieb attach */ 81 void 82 pcieb_plat_attach_workaround(dev_info_t *dip) 83 { 84 /* Must apply workaround only after all initialization is done */ 85 pcieb_intel_error_workaround(dip); 86 pcieb_intel_mps_workaround(dip); 87 88 } 89 90 /* Workarounds to enable error handling on certain Intel chipsets */ 91 void 92 pcieb_intel_error_workaround(dev_info_t *dip) 93 { 94 pcieb_devstate_t *pcieb = ddi_get_soft_state(pcieb_state, 95 ddi_get_instance(dip)); 96 97 pcieb_intel_serr_workaround(dip, pcieb->pcieb_no_aer_msi); 98 pcieb_intel_rber_workaround(dip); 99 pcieb_intel_sw_workaround(dip); 100 } 101 102 int 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) 105 { 106 return (i_ddi_intr_ops(dip, rdip, intr_op, hdlp, result)); 107 } 108 109 /* shpc is not supported on x86 */ 110 /*ARGSUSED*/ 111 int 112 pcieb_plat_pcishpc_probe(dev_info_t *dip, ddi_acc_handle_t config_handle) 113 { 114 return (DDI_FAILURE); 115 } 116 117 /* 118 * Dummy functions to get around the fact that there's no shpc module on x86 119 * today 120 */ 121 /*ARGSUSED*/ 122 int 123 pcishpc_init(dev_info_t *dip) 124 { 125 return (DDI_FAILURE); 126 } 127 128 /*ARGSUSED*/ 129 int 130 pcishpc_uninit(dev_info_t *dip) 131 { 132 return (DDI_FAILURE); 133 } 134 135 /*ARGSUSED*/ 136 int 137 pcishpc_intr(dev_info_t *dip) 138 { 139 return (DDI_INTR_UNCLAIMED); 140 } 141 142 /*ARGSUSED*/ 143 boolean_t 144 pcieb_plat_pwr_disable(dev_info_t *dip) 145 { 146 /* Always disable on x86 */ 147 return (B_TRUE); 148 } 149 150 boolean_t 151 pcieb_plat_msi_supported(dev_info_t *dip) 152 { 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; 157 158 /* 159 * Intel ESB2 switches have a errata which prevents using MSIs 160 * for hotplug. 161 */ 162 return (((vendor_id == INTEL_VENDOR_ID) && 163 INTEL_ESB2_SW_PCIE_DEV_ID(device_id)) ? B_FALSE : B_TRUE); 164 } 165 166 void 167 pcieb_plat_intr_attach(pcieb_devstate_t *pcieb) 168 { 169 /* 170 * _OSC initialization needs to be done before interrupts are 171 * initialized. 172 */ 173 pcieb_init_osc(pcieb->pcieb_dip); 174 } 175 176 void 177 pcieb_plat_initchild(dev_info_t *child) 178 { 179 struct ddi_parent_private_data *pdptr; 180 if (ddi_getprop(DDI_DEV_T_NONE, child, DDI_PROP_DONTPASS, "interrupts", 181 -1) != -1) { 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); 187 } else 188 ddi_set_parent_data(child, NULL); 189 } 190 191 void 192 pcieb_plat_uninitchild(dev_info_t *child) 193 { 194 struct ddi_parent_private_data *pdptr; 195 196 if ((pdptr = ddi_get_parent_data(child)) != NULL) 197 kmem_free(pdptr, (sizeof (*pdptr) + sizeof (struct intrspec))); 198 199 ddi_set_parent_data(child, NULL); 200 } 201 202 /* _OSC related */ 203 void 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; 207 208 /* 209 * Call _OSC method for 2 reasons: 210 * 1. Hotplug: To determine if it is native or ACPI mode. 211 * 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 215 * supported. 216 * 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). 221 */ 222 if (!pcie_is_osc(devi) && PCIE_IS_RP(bus_p) && PCIE_HAS_AER(bus_p)) 223 (void) pcie_acpi_osc(devi, &osc_flags); 224 } 225 226 /* 227 * Intel chip specific workarounds. Right now they're limited to the 5000, 5400 228 * and 7300 series chipsets. 229 */ 230 typedef struct x86_error_reg { 231 uint32_t offset; 232 uint_t size; 233 uint32_t mask; 234 uint32_t value1; /* Value for MSI case */ 235 uint32_t value2; /* Value for machinecheck case */ 236 } x86_error_reg_t; 237 238 typedef struct x86_error_tbl { 239 uint16_t vendor_id; 240 uint16_t device_id_low; 241 uint16_t device_id_high; 242 uint8_t rev_id_low; 243 uint8_t rev_id_high; 244 x86_error_reg_t *error_regs; 245 int error_regs_len; 246 } x86_error_tbl_t; 247 248 /* 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. 252 * 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. 259 * 260 * PCIE errors from the ESB2 Southbridge RPs are simply fowarded to the ESI 261 * port on the Northbridge. 262 * 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). 266 */ 267 268 /* 269 * 7300 Northbridge Root Ports 270 */ 271 static x86_error_reg_t intel_7300_rp_regs[] = { 272 /* Command Register - Enable SERR */ 273 {0x4, 16, 0xFFFF, 0x0, PCI_COMM_SERR_ENABLE}, 274 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}, 278 279 /* AER UE Mask - Mask UR */ 280 {0x108, 32, 0x0, PCIE_AER_UCE_UR, PCIE_AER_UCE_UR}, 281 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}, 286 287 /* PEX_ERR_DOCMD[7:0] */ 288 {0x144, 8, 0x0, 0x0, 0xF0}, 289 290 /* EMASK_UNCOR_PEX[21:0] UE mask */ 291 {0x148, 32, 0x0, PCIE_AER_UCE_UR, PCIE_AER_UCE_UR}, 292 293 /* EMASK_RP_PEX[2:0] FE, UE, CE message detect mask */ 294 {0x150, 8, 0x0, 0x0, 0x1}, 295 }; 296 #define INTEL_7300_RP_REGS_LEN \ 297 (sizeof (intel_7300_rp_regs) / sizeof (x86_error_reg_t)) 298 299 /* 300 * 5000 Northbridge Root Ports 301 */ 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}, 305 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}, 312 313 /* AER UE Mask - Mask UR */ 314 {0x108, 32, 0x0, PCIE_AER_UCE_UR, PCIE_AER_UCE_UR}, 315 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}, 320 321 /* PEX_ERR_DOCMD[7:0] */ 322 {0x144, 8, 0x0, 0x0, 0xF0}, 323 324 /* EMASK_UNCOR_PEX[21:0] UE mask */ 325 {0x148, 32, 0x0, PCIE_AER_UCE_UR, PCIE_AER_UCE_UR}, 326 327 /* EMASK_RP_PEX[2:0] FE, UE, CE message detect mask */ 328 {0x150, 8, 0x0, 0x0, 0x1}, 329 }; 330 #define INTEL_5000_RP_REGS_LEN \ 331 (sizeof (intel_5000_rp_regs) / sizeof (x86_error_reg_t)) 332 333 /* 334 * 5400 Northbridge Root Ports. 335 */ 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}, 339 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}, 346 347 /* AER UE Mask - Mask UR */ 348 {0x108, 32, 0x0, PCIE_AER_UCE_UR, PCIE_AER_UCE_UR}, 349 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}, 354 355 /* PEX_ERR_DOCMD[11:0] */ 356 {0x144, 16, 0x0, 0x0, 0xFF0}, 357 358 /* PEX_ERR_PIN_MASK[4:0] do not mask ERR[2:0] pins used by DOCMD */ 359 {0x146, 16, 0x0, 0x10, 0x10}, 360 361 /* EMASK_UNCOR_PEX[21:0] UE mask */ 362 {0x148, 32, 0x0, PCIE_AER_UCE_UR, PCIE_AER_UCE_UR}, 363 364 /* EMASK_RP_PEX[2:0] FE, UE, CE message detect mask */ 365 {0x150, 8, 0x0, 0x0, 0x1}, 366 }; 367 #define INTEL_5400_RP_REGS_LEN \ 368 (sizeof (intel_5400_rp_regs) / sizeof (x86_error_reg_t)) 369 370 371 /* 372 * ESB2 Southbridge Root Ports 373 */ 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}, 377 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}, 384 385 /* UEM[20:0] UE mask (write-once) */ 386 {0x148, 32, 0x0, PCIE_AER_UCE_UR, PCIE_AER_UCE_UR}, 387 }; 388 #define INTEL_ESB2_RP_REGS_LEN \ 389 (sizeof (intel_esb2_rp_regs) / sizeof (x86_error_reg_t)) 390 391 392 /* 393 * ESB2 Southbridge Switch Ports 394 */ 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}, 398 399 /* AER UE Mask - Mask UR */ 400 {0x108, 32, 0x0, PCIE_AER_UCE_UR, PCIE_AER_UCE_UR}, 401 }; 402 #define INTEL_ESB2_SW_REGS_LEN \ 403 (sizeof (intel_esb2_sw_regs) / sizeof (x86_error_reg_t)) 404 405 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}, 412 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}, 422 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}, 428 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}, 436 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}, 440 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}, 446 447 /* XXX Intel PCIe-PCIx on esb2: 350C */ 448 }; 449 static int x86_error_init_tbl_len = 450 sizeof (x86_error_init_tbl) / sizeof (x86_error_tbl_t); 451 452 /* 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. 456 */ 457 void 458 pcieb_intel_serr_workaround(dev_info_t *dip, boolean_t mcheck) 459 { 460 uint16_t vid, did; 461 uint8_t rid; 462 int i, j; 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; 468 469 if (pcieb_intel_workaround_disable) 470 return; 471 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; 475 476 PCIEB_DEBUG(DBG_ATTACH, dip, "VID:0x%x DID:0x%x RID:0x%x bdf=0x%x\n", 477 vid, did, rid, bdf); 478 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))) 486 continue; 487 488 if (mcheck && PCIE_IS_RP(bus_p)) 489 pcie_set_rber_fatal(dip, B_TRUE); 490 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; 495 switch (reg->size) { 496 case 32: 497 data = (uint32_t)pci_config_get32(cfg_hdl, 498 reg->offset); 499 value = (mcheck ? 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, 504 reg->offset); 505 break; 506 case 16: 507 data = (uint32_t)pci_config_get16(cfg_hdl, 508 reg->offset); 509 value = (mcheck ? 510 ((data & reg->mask) | reg->value2) : 511 ((data & reg->mask) | reg->value1)); 512 pci_config_put16(cfg_hdl, reg->offset, 513 (uint16_t)value); 514 value = (uint32_t)pci_config_get16(cfg_hdl, 515 reg->offset); 516 break; 517 case 8: 518 data = (uint32_t)pci_config_get8(cfg_hdl, 519 reg->offset); 520 value = (mcheck ? 521 ((data & reg->mask) | reg->value2) : 522 ((data & reg->mask) | reg->value1)); 523 pci_config_put8(cfg_hdl, reg->offset, 524 (uint8_t)value); 525 value = (uint32_t)pci_config_get8(cfg_hdl, 526 reg->offset); 527 break; 528 } 529 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), 534 data, value); 535 } 536 } 537 } 538 539 /* 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. 543 */ 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); 547 548 void 549 pcieb_intel_rber_workaround(dev_info_t *dip) 550 { 551 uint32_t rber; 552 pcie_bus_t *bus_p = PCIE_DIP2UPBUS(dip); 553 554 if (pcieb_intel_workaround_disable) 555 return; 556 557 /* 558 * Check Root Port's machinecheck setting to determine if this 559 * workaround is needed or not. 560 */ 561 if (!pcie_get_rber_fatal(dip)) 562 return; 563 564 if (!PCIE_IS_PCIE(bus_p) || !PCIE_HAS_AER(bus_p)) 565 return; 566 567 rber = PCIE_CAP_GET(16, bus_p, PCIE_DEVCAP) & 568 PCIE_DEVCAP_ROLE_BASED_ERR_REP; 569 if (!rber) 570 return; 571 572 PCIE_AER_PUT(32, bus_p, PCIE_AER_UCE_SERV, pcieb_rber_sev); 573 } 574 575 /* 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. 578 */ 579 void 580 pcieb_intel_mps_workaround(dev_info_t *dip) 581 { 582 uint16_t vid, did; 583 uint32_t pexctrl; 584 pcie_bus_t *bus_p = PCIE_DIP2UPBUS(dip); 585 586 vid = bus_p->bus_dev_ven_id & 0xFFFF; 587 did = bus_p->bus_dev_ven_id >> 16; 588 589 if ((vid == INTEL_VENDOR_ID) && (INTEL_NB5000_PCIE_DEV_ID(did) || 590 INTEL_NB5100_PCIE_DEV_ID(did))) { 591 592 pexctrl = pci_config_get32(bus_p->bus_cfg_hdl, 593 INTEL_NB5000_PEXCTRL_OFFSET); 594 /* 595 * Turn off coalescing (bit 10) 596 */ 597 pexctrl &= ~INTEL_NB5000_PEXCTRL_COALESCE_EN; 598 599 pci_config_put32(bus_p->bus_cfg_hdl, 600 INTEL_NB5000_PEXCTRL_OFFSET, pexctrl); 601 } 602 } 603 604 /* 605 * Workaround for certain switches regardless of platform 606 */ 607 void 608 pcieb_intel_sw_workaround(dev_info_t *dip) 609 { 610 uint16_t vid, regw; 611 pcie_bus_t *bus_p = PCIE_DIP2UPBUS(dip); 612 ddi_acc_handle_t cfg_hdl = bus_p->bus_cfg_hdl; 613 614 if (pcieb_intel_workaround_disable) 615 return; 616 617 if (!PCIE_IS_SW(PCIE_DIP2BUS(dip))) 618 return; 619 620 vid = bus_p->bus_dev_ven_id & 0xFFFF; 621 /* 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. 627 */ 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); 632 } 633 } 634 635 int 636 pcieb_plat_ctlops(dev_info_t *rdip, ddi_ctl_enum_t ctlop, void *arg) 637 { 638 struct detachspec *ds; 639 struct attachspec *as; 640 641 switch (ctlop) { 642 case DDI_CTLOPS_DETACH: 643 ds = (struct detachspec *)arg; 644 switch (ds->when) { 645 case DDI_POST: 646 if (ds->cmd == DDI_SUSPEND) { 647 if (pci_post_suspend(rdip) != DDI_SUCCESS) 648 return (DDI_FAILURE); 649 } 650 break; 651 default: 652 break; 653 } 654 break; 655 case DDI_CTLOPS_ATTACH: 656 as = (struct attachspec *)arg; 657 switch (as->when) { 658 case DDI_PRE: 659 if (as->cmd == DDI_RESUME) { 660 if (pci_pre_resume(rdip) != DDI_SUCCESS) 661 return (DDI_FAILURE); 662 } 663 break; 664 case DDI_POST: 665 /* 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 670 * currently 671 */ 672 pcieb_intel_rber_workaround(rdip); 673 break; 674 default: 675 break; 676 } 677 break; 678 default: 679 break; 680 } 681 682 return (DDI_SUCCESS); 683 } 684