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