diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/fm/eversholt/files/sparc/sun4/fire.esc | 17 | ||||
-rw-r--r-- | usr/src/lib/fm/topo/modules/common/pcibus/pcibus.c | 4 | ||||
-rw-r--r-- | usr/src/uts/common/io/pcie.c | 32 | ||||
-rw-r--r-- | usr/src/uts/common/io/pcie_fault.c | 97 | ||||
-rw-r--r-- | usr/src/uts/common/sys/pcie.h | 10 | ||||
-rw-r--r-- | usr/src/uts/common/sys/pcie_impl.h | 34 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/pci/pci_tools.c | 8 | ||||
-rw-r--r-- | usr/src/uts/intel/io/pci/pci_pci.c | 6 | ||||
-rw-r--r-- | usr/src/uts/sun4/io/px/px_dma.c | 4 | ||||
-rw-r--r-- | usr/src/uts/sun4/io/px/px_fdvma.c | 4 | ||||
-rw-r--r-- | usr/src/uts/sun4/io/px/px_fm.c | 39 | ||||
-rw-r--r-- | usr/src/uts/sun4/io/px/px_ioapi.h | 2 | ||||
-rw-r--r-- | usr/src/uts/sun4/io/px/px_pci.c | 160 | ||||
-rw-r--r-- | usr/src/uts/sun4/io/px/pxb_plx.h | 11 | ||||
-rw-r--r-- | usr/src/uts/sun4u/io/pci/pci_pci.c | 6 | ||||
-rw-r--r-- | usr/src/uts/sun4u/io/px/px_err.c | 6 | ||||
-rw-r--r-- | usr/src/uts/sun4u/io/px/px_lib4u.c | 4 | ||||
-rw-r--r-- | usr/src/uts/sun4v/io/px/px_err.c | 10 | ||||
-rw-r--r-- | usr/src/uts/sun4v/io/px/px_lib4v.c | 4 |
19 files changed, 317 insertions, 141 deletions
diff --git a/usr/src/cmd/fm/eversholt/files/sparc/sun4/fire.esc b/usr/src/cmd/fm/eversholt/files/sparc/sun4/fire.esc index 7985960f3b..ce5e9b1755 100644 --- a/usr/src/cmd/fm/eversholt/files/sparc/sun4/fire.esc +++ b/usr/src/cmd/fm/eversholt/files/sparc/sun4/fire.esc @@ -19,11 +19,9 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - -#pragma ident "%Z%%M% %I% %E% SMI" #pragma dictionary "SUN4" @@ -174,6 +172,7 @@ event error.io.fire.fabric@pcibus/pcidev/pcifn; * o HV and Guest are out of sync. ***************/ event ereport.io.fire.epkt@hostbridge/pciexrc {within(5s)}; +event ereport.io.fire.epkt@hostbridge {within(5s)}; /****************************** * Generic Rules Begin Here * @@ -211,6 +210,12 @@ event fault.io.fire.fw-epkt@hostbridge/pciexrc, retire=0, response=0, FITrate=HV_FIT; event fault.io.fire.sw-fw-mismatch@hostbridge/pciexrc, retire=0, response=0, FITrate=SW_HV_MISMATCH_FIT; +event fault.io.fire.sw-epkt@hostbridge, retire=0, response=0, + FITrate=SW_FIT; +event fault.io.fire.fw-epkt@hostbridge, retire=0, response=0, + FITrate=HV_FIT; +event fault.io.fire.sw-fw-mismatch@hostbridge, retire=0, response=0, + FITrate=SW_HV_MISMATCH_FIT; event fault.io.fire.hb.sw-config@hostbridge/pciexrc, retire=0, response=0, FITrate=SW_FIT; event fault.io.fire.dmc.sw-algorithm@hostbridge/pciexrc, retire=0, response=0, @@ -229,6 +234,11 @@ prop fault.io.fire.sw-epkt@hostbridge/pciexrc, fault.io.fire.sw-fw-mismatch@hostbridge/pciexrc->(A) ereport.io.fire.epkt@hostbridge/pciexrc { MATCH_UNRECOGNIZED }; +prop fault.io.fire.sw-epkt@hostbridge, + fault.io.fire.fw-epkt@hostbridge, + fault.io.fire.sw-fw-mismatch@hostbridge->(A) + ereport.io.fire.epkt@hostbridge { MATCH_UNRECOGNIZED }; + prop fault.io.fire.hb.sw-config@hostbridge/pciexrc (0)-> error.io.fire.jbc.driver@hostbridge/pciexrc; @@ -658,4 +668,5 @@ prop upset.io.fire.nodiag@hostbridge/pciexrc (0)-> ereport.io.fire.pec.lup@hostbridge/pciexrc, error.io.fire.dmc.nodiag@hostbridge/pciexrc, error.io.fire.dmc.secondary@hostbridge/pciexrc, + ereport.io.fire.epkt@hostbridge { !MATCH_UNRECOGNIZED }, ereport.io.fire.epkt@hostbridge/pciexrc { !MATCH_UNRECOGNIZED }; diff --git a/usr/src/lib/fm/topo/modules/common/pcibus/pcibus.c b/usr/src/lib/fm/topo/modules/common/pcibus/pcibus.c index 3e8231fade..074c8c98f2 100644 --- a/usr/src/lib/fm/topo/modules/common/pcibus/pcibus.c +++ b/usr/src/lib/fm/topo/modules/common/pcibus/pcibus.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -413,7 +413,7 @@ pci_bridge_declare(topo_mod_t *mod, tnode_t *fn, di_node_t din, int board, devtyp = pci_devtype_get(mod, din); /* Check if the children are PCI or PCIe */ - if (strcmp(devtyp, "pciex") == 0) + if (devtyp && (strcmp(devtyp, "pciex") == 0)) err = pci_children_instantiate(mod, fn, din, board, bridge, rc, TRUST_BDF, depth + 1); else diff --git a/usr/src/uts/common/io/pcie.c b/usr/src/uts/common/io/pcie.c index db8b7c8486..f14d4cb1ea 100644 --- a/usr/src/uts/common/io/pcie.c +++ b/usr/src/uts/common/io/pcie.c @@ -333,8 +333,10 @@ pcie_init_pfd(dev_info_t *dip) pfd_p->pe_valid = B_FALSE; /* Allocate the root fault struct for both RC and RP */ - if (PCIE_IS_ROOT(bus_p)) + if (PCIE_IS_ROOT(bus_p)) { PCIE_ROOT_FAULT(pfd_p) = PCIE_ZALLOC(pf_root_fault_t); + PCIE_ROOT_FAULT(pfd_p)->scan_bdf = PCIE_INVALID_BDF; + } PCI_ERR_REG(pfd_p) = PCIE_ZALLOC(pf_pci_err_regs_t); @@ -349,13 +351,21 @@ pcie_init_pfd(dev_info_t *dip) PCIE_ZALLOC(pf_pcie_rp_err_regs_t); PCIE_ADV_REG(pfd_p) = PCIE_ZALLOC(pf_pcie_adv_err_regs_t); + PCIE_ADV_REG(pfd_p)->pcie_ue_tgt_bdf = PCIE_INVALID_BDF; - if (PCIE_IS_RP(bus_p)) + if (PCIE_IS_RP(bus_p)) { PCIE_ADV_RP_REG(pfd_p) = PCIE_ZALLOC(pf_pcie_adv_rp_err_regs_t); - else if (PCIE_IS_PCIE_BDG(bus_p)) + PCIE_ADV_RP_REG(pfd_p)->pcie_rp_ce_src_id = + PCIE_INVALID_BDF; + PCIE_ADV_RP_REG(pfd_p)->pcie_rp_ue_src_id = + PCIE_INVALID_BDF; + } else if (PCIE_IS_PCIE_BDG(bus_p)) { PCIE_ADV_BDG_REG(pfd_p) = PCIE_ZALLOC(pf_pcie_adv_bdg_err_regs_t); + PCIE_ADV_BDG_REG(pfd_p)->pcie_sue_tgt_bdf = + PCIE_INVALID_BDF; + } if (PCIE_IS_PCIE_BDG(bus_p) && PCIE_IS_PCIX(bus_p)) { PCIX_BDG_ERR_REG(pfd_p) = @@ -472,6 +482,7 @@ pcie_rc_init_pfd(dev_info_t *dip, pf_data_t *pfd_p) pfd_p->pe_valid = B_FALSE; PCIE_ROOT_FAULT(pfd_p) = PCIE_ZALLOC(pf_root_fault_t); + PCIE_ROOT_FAULT(pfd_p)->scan_bdf = PCIE_INVALID_BDF; PCI_ERR_REG(pfd_p) = PCIE_ZALLOC(pf_pci_err_regs_t); PCI_BDG_ERR_REG(pfd_p) = PCIE_ZALLOC(pf_pci_bdg_err_regs_t); PCIE_ERR_REG(pfd_p) = PCIE_ZALLOC(pf_pcie_err_regs_t); @@ -581,7 +592,7 @@ pcie_init_bus(dev_info_t *cdip) bus_p->bus_aer_off = NULL; } else { bus_p->bus_pcie_off = NULL; - bus_p->bus_dev_type = PCIE_PCIECAP_DEV_TYPE_PCI_DEV; + bus_p->bus_dev_type = PCIE_PCIECAP_DEV_TYPE_PCI_PSEUDO; } if ((PCI_CAP_LOCATE(eh, PCI_CAP_ID_PCIX, &bus_p->bus_pcix_off)) @@ -1017,11 +1028,11 @@ pcie_get_bdf_for_dma_xfer(dev_info_t *dip, dev_info_t *rdip) * As part of the probing, the PCI fcode interpreter may setup a DMA * request if a given card has a fcode on it using dip and rdip of the * AP (attachment point) i.e, dip and rdip of px/px_pci driver. In this - * case, return zero for the bdf since we cannot get to the bdf value - * of the actual device which will be initiating this DMA. + * case, return a invalid value for the bdf since we cannot get to the + * bdf value of the actual device which will be initiating this DMA. */ if (rdip == dip) - return (0); + return (PCIE_INVALID_BDF); cdip = pcie_get_my_childs_dip(dip, rdip); @@ -1029,10 +1040,11 @@ pcie_get_bdf_for_dma_xfer(dev_info_t *dip, dev_info_t *rdip) * For a given rdip, return the bdf value of dip's (px or px_pci) * immediate child or secondary bus-id if dip is a PCIe2PCI bridge. * - * XXX - For now, return bdf value of zero for all PCI and PCI-X devices - * since this needs more work. + * XXX - For now, return a invalid bdf value for all PCI and PCI-X + * devices since this needs more work. */ - return (PCI_GET_PCIE2PCI_SECBUS(cdip) ? 0 : PCI_GET_BDF(cdip)); + return (PCI_GET_PCIE2PCI_SECBUS(cdip) ? + PCIE_INVALID_BDF : PCI_GET_BDF(cdip)); } uint32_t diff --git a/usr/src/uts/common/io/pcie_fault.c b/usr/src/uts/common/io/pcie_fault.c index 3110c08953..2dd656a06e 100644 --- a/usr/src/uts/common/io/pcie_fault.c +++ b/usr/src/uts/common/io/pcie_fault.c @@ -212,8 +212,8 @@ pf_scan_fabric(dev_info_t *rdip, ddi_fm_error_t *derr, pf_data_t *root_pfd_p) } /* - * Scan the fabric using the fault_bdf and fault_addr in error q. - * fault_bdf will be valid in the following cases: + * Scan the fabric using the scan_bdf and scan_addr in error q. + * scan_bdf will be valid in the following cases: * - Fabric message * - Poisoned TLP * - Signaled UR/CA @@ -227,8 +227,9 @@ pf_scan_fabric(dev_info_t *rdip, ddi_fm_error_t *derr, pf_data_t *root_pfd_p) if (impl.pf_fault->full_scan) full_scan = B_TRUE; - if (full_scan || impl.pf_fault->fault_bdf || - impl.pf_fault->fault_addr) + if (full_scan || + PCIE_CHECK_VALID_BDF(impl.pf_fault->scan_bdf) || + impl.pf_fault->scan_addr) scan_flag |= pf_dispatch(rdip, &impl, full_scan); if (full_scan) @@ -277,7 +278,7 @@ static int pf_dispatch(dev_info_t *pdip, pf_impl_t *impl, boolean_t full_scan) { dev_info_t *dip; - pcie_req_id_t rid = impl->pf_fault->fault_bdf; + pcie_req_id_t rid = impl->pf_fault->scan_bdf; pcie_bus_t *bus_p; int scan_flag = PF_SCAN_SUCCESS; @@ -300,7 +301,7 @@ pf_dispatch(dev_info_t *pdip, pf_impl_t *impl, boolean_t full_scan) if (full_scan || (bus_p->bus_bdf == rid) || pf_in_bus_range(bus_p, rid) || - pf_in_addr_range(bus_p, impl->pf_fault->fault_addr)) { + pf_in_addr_range(bus_p, impl->pf_fault->scan_addr)) { int hdl_flag = pf_default_hdl(dip, impl); scan_flag |= hdl_flag; @@ -348,8 +349,13 @@ pf_dispatch(dev_info_t *pdip, pf_impl_t *impl, boolean_t full_scan) break; } case PCIE_PCIECAP_DEV_TYPE_PCIE_DEV: - break; case PCIE_PCIECAP_DEV_TYPE_PCI_DEV: + /* + * Reached a PCIe end point so stop. Note dev_type + * PCI_DEV is just a PCIe device that requires IO Space + */ + break; + case PCIE_PCIECAP_DEV_TYPE_PCI_PSEUDO: if (PCIE_IS_BDG(bus_p)) scan_flag |= pf_dispatch(dip, impl, B_TRUE); break; @@ -402,6 +408,7 @@ pf_in_addr_range(pcie_bus_t *bus_p, uint64_t addr) for (i = 0; i < bus_p->bus_addr_entries; i++, ranges_p++) { switch (ranges_p->child_high & PCI_ADDR_MASK) { + case PCI_ADDR_IO: case PCI_ADDR_MEM32: low = ranges_p->child_low; hi = ranges_p->size_low + low; @@ -767,8 +774,8 @@ pf_pci_find_rp_fault(pf_data_t *pfd_p, pcie_bus_t *bus_p) /* Since this data structure is reused, make sure to reset it */ root_fault->full_scan = B_FALSE; - root_fault->fault_bdf = 0; - root_fault->fault_addr = 0; + root_fault->scan_bdf = PCIE_INVALID_BDF; + root_fault->scan_addr = 0; if (!PCIE_HAS_AER(bus_p) && (PCI_BDG_ERR_REG(pfd_p)->pci_bdg_sec_stat & PF_PCI_BDG_ERR)) { @@ -811,19 +818,17 @@ pf_pci_find_rp_fault(pf_data_t *pfd_p, pcie_bus_t *bus_p) } /* By this point, there is only 1 fault detected */ - if ((root_err & PCIE_AER_RE_STS_CE_RCVD) && - rp_regs->pcie_rp_ce_src_id) { - PCIE_ROOT_FAULT(pfd_p)->fault_bdf = rp_regs->pcie_rp_ce_src_id; + if (root_err & PCIE_AER_RE_STS_CE_RCVD) { + PCIE_ROOT_FAULT(pfd_p)->scan_bdf = rp_regs->pcie_rp_ce_src_id; + num_faults--; + } else if (root_err & PCIE_AER_RE_STS_FE_NFE_RCVD) { + PCIE_ROOT_FAULT(pfd_p)->scan_bdf = rp_regs->pcie_rp_ue_src_id; num_faults--; - } else if ((root_err & PCIE_AER_RE_STS_FE_NFE_RCVD) && - rp_regs->pcie_rp_ue_src_id) { - PCIE_ROOT_FAULT(pfd_p)->fault_bdf = rp_regs->pcie_rp_ue_src_id; - num_faults--; } else if ((HAS_AER_LOGS(pfd_p, PCIE_AER_UCE_CA) || HAS_AER_LOGS(pfd_p, PCIE_AER_UCE_UR)) && (pf_tlp_decode(PCIE_PFD2BUS(pfd_p), PCIE_ADV_REG(pfd_p)) == DDI_SUCCESS)) { - PCIE_ROOT_FAULT(pfd_p)->fault_bdf = + PCIE_ROOT_FAULT(pfd_p)->scan_addr = PCIE_ADV_REG(pfd_p)->pcie_ue_tgt_addr; num_faults--; } @@ -1171,6 +1176,12 @@ const pf_fab_err_tbl_t pcie_pci_tbl[] = { NULL, NULL }; +#define PF_MASKED_AER_ERR(pfd_p) \ + (PCIE_ADV_REG(pfd_p)->pcie_ue_status & \ + ((PCIE_ADV_REG(pfd_p)->pcie_ue_mask) ^ 0xFFFFFFFF)) +#define PF_MASKED_SAER_ERR(pfd_p) \ + (PCIE_ADV_BDG_REG(pfd_p)->pcie_sue_status & \ + ((PCIE_ADV_BDG_REG(pfd_p)->pcie_sue_mask) ^ 0xFFFFFFFF)) /* * Analyse all the PCIe Fault Data (erpt) gathered during dispatch in the erpt * Queue. @@ -1186,25 +1197,24 @@ pf_analyse_error(ddi_fm_error_t *derr, pf_impl_t *impl) switch (PCIE_PFD2BUS(pfd_p)->bus_dev_type) { case PCIE_PCIECAP_DEV_TYPE_PCIE_DEV: + case PCIE_PCIECAP_DEV_TYPE_PCI_DEV: if (PCIE_DEVSTS_CE_DETECTED & PCIE_ERR_REG(pfd_p)->pcie_err_status) sts_flags |= PF_ERR_CE; pf_adjust_for_no_aer(pfd_p); sts_flags |= pf_analyse_error_tbl(derr, impl, - pfd_p, pcie_pcie_tbl, - PCIE_ADV_REG(pfd_p)->pcie_ue_status); + pfd_p, pcie_pcie_tbl, PF_MASKED_AER_ERR(pfd_p)); break; case PCIE_PCIECAP_DEV_TYPE_ROOT: pf_adjust_for_no_aer(pfd_p); sts_flags |= pf_analyse_error_tbl(derr, impl, - pfd_p, pcie_rp_tbl, - PCIE_ADV_REG(pfd_p)->pcie_ue_status); + pfd_p, pcie_rp_tbl, PF_MASKED_AER_ERR(pfd_p)); break; case PCIE_PCIECAP_DEV_TYPE_RC_PSEUDO: /* no adjust_for_aer for pseudo RC */ sts_flags |= pf_analyse_error_tbl(derr, impl, pfd_p, - pcie_rp_tbl, PCIE_ADV_REG(pfd_p)->pcie_ue_status); + pcie_rp_tbl, PF_MASKED_AER_ERR(pfd_p)); break; case PCIE_PCIECAP_DEV_TYPE_UP: case PCIE_PCIECAP_DEV_TYPE_DOWN: @@ -1214,8 +1224,7 @@ pf_analyse_error(ddi_fm_error_t *derr, pf_impl_t *impl) pf_adjust_for_no_aer(pfd_p); sts_flags |= pf_analyse_error_tbl(derr, impl, - pfd_p, pcie_sw_tbl, - PCIE_ADV_REG(pfd_p)->pcie_ue_status); + pfd_p, pcie_sw_tbl, PF_MASKED_AER_ERR(pfd_p)); break; case PCIE_PCIECAP_DEV_TYPE_PCIE2PCI: if (PCIE_DEVSTS_CE_DETECTED & @@ -1226,10 +1235,10 @@ pf_analyse_error(ddi_fm_error_t *derr, pf_impl_t *impl) pf_adjust_for_no_saer(pfd_p); sts_flags |= pf_analyse_error_tbl(derr, impl, pfd_p, pcie_pcie_tbl, - PCIE_ADV_REG(pfd_p)->pcie_ue_status); + PF_MASKED_AER_ERR(pfd_p)); sts_flags |= pf_analyse_error_tbl(derr, impl, pfd_p, pcie_pcie_bdg_tbl, - PCIE_ADV_BDG_REG(pfd_p)->pcie_sue_status); + PF_MASKED_SAER_ERR(pfd_p)); /* * Some non-compliant PCIe devices do not utilize PCIe * error registers. So fallthrough and rely on legacy @@ -1239,7 +1248,7 @@ pf_analyse_error(ddi_fm_error_t *derr, pf_impl_t *impl) & PCIE_ERR_REG(pfd_p)->pcie_err_status) break; /* FALLTHROUGH */ - case PCIE_PCIECAP_DEV_TYPE_PCI_DEV: + case PCIE_PCIECAP_DEV_TYPE_PCI_PSEUDO: sts_flags |= pf_analyse_error_tbl(derr, impl, pfd_p, pcie_pci_tbl, PCI_ERR_REG(pfd_p)->pci_err_status); @@ -1612,7 +1621,7 @@ pf_analyse_ptlp(ddi_fm_error_t *derr, uint32_t bit, pf_data_t *dq_head_p, secbus = PCIE_ADV_REG(pfd_p)->pcie_ue_tgt_bdf; - if (secbus & 0xFF) + if (!PCIE_CHECK_VALID_BDF(secbus) || (secbus & 0xFF)) goto done; bdg_pfd_p = pf_get_pcie_bridge(pfd_p, secbus); @@ -1906,7 +1915,7 @@ pf_matched_in_rc(pf_data_t *dq_head_p, pf_data_t *pfd_p, if (!(PCI_BDG_ERR_REG(rc_pfd_p)->pci_bdg_sec_stat & abort_type)) continue; - fault_bdf = PCIE_ROOT_FAULT(rc_pfd_p)->fault_bdf; + fault_bdf = PCIE_ROOT_FAULT(rc_pfd_p)->scan_bdf; /* The Fault BDF = Device's BDF */ if (fault_bdf == bus_p->bus_bdf) @@ -1914,7 +1923,7 @@ pf_matched_in_rc(pf_data_t *dq_head_p, pf_data_t *pfd_p, /* The Fault Addr is in device's address range */ if (pf_in_addr_range(bus_p, - PCIE_ROOT_FAULT(rc_pfd_p)->fault_addr)) + PCIE_ROOT_FAULT(rc_pfd_p)->scan_addr)) return (B_TRUE); /* The Fault BDF is from PCIe-PCI Bridge's secondary bus */ @@ -1943,7 +1952,7 @@ pf_pci_find_trans_type(pf_data_t *pfd_p, uint64_t *addr, uint32_t *trans_type, return; case PCIE_AER_SUCE_RCVD_TA: case PCIE_AER_SUCE_RCVD_MA: - *bdf = 0; + *bdf = PCIE_INVALID_BDF; *trans_type = PF_ADDR_PIO; return; case PCIE_AER_SUCE_USC_ERR: @@ -1952,12 +1961,12 @@ pf_pci_find_trans_type(pf_data_t *pfd_p, uint64_t *addr, uint32_t *trans_type, break; default: *addr = 0; - *bdf = 0; + *bdf = PCIE_INVALID_BDF; *trans_type = 0; return; } - *bdf = 0; + *bdf = PCIE_INVALID_BDF; *trans_type = PF_ADDR_PIO; for (rc_pfd_p = pfd_p->pe_prev; rc_pfd_p; rc_pfd_p = rc_pfd_p->pe_prev) { @@ -1987,7 +1996,7 @@ pf_pci_decode(pf_data_t *pfd_p, uint16_t *cmd) { pcix_attr_t *attr; uint64_t addr; uint32_t trans_type; - pcie_req_id_t bdf; + pcie_req_id_t bdf = PCIE_INVALID_BDF; attr = (pcix_attr_t *)&PCIE_ADV_BDG_HDR(pfd_p, 0); *cmd = GET_SAER_CMD(pfd_p); @@ -2045,7 +2054,7 @@ cmd_switch: /* FALLTHROUGH */ default: PCIE_ADV_BDG_REG(pfd_p)->pcie_sue_tgt_trans = 0; - PCIE_ADV_BDG_REG(pfd_p)->pcie_sue_tgt_bdf = 0; + PCIE_ADV_BDG_REG(pfd_p)->pcie_sue_tgt_bdf = PCIE_INVALID_BDF; PCIE_ADV_BDG_REG(pfd_p)->pcie_sue_tgt_addr = 0; return (DDI_FAILURE); } @@ -2066,7 +2075,7 @@ pf_hdl_lookup(dev_info_t *dip, uint64_t ena, uint32_t flag, uint64_t addr, ddi_fm_error_t derr; /* If we don't know the addr or rid just return with NOTFOUND */ - if (addr == NULL && bdf == NULL) + if ((addr == NULL) && !PCIE_CHECK_VALID_BDF(bdf)) return (PF_HDL_NOTFOUND); if (!(flag & (PF_ADDR_DMA | PF_ADDR_PIO | PF_ADDR_CFG))) { @@ -2110,7 +2119,8 @@ pf_hdl_child_lookup(dev_info_t *dip, ddi_fm_error_t *derr, uint32_t flag, dip_bdf = PCI_GET_BDF(dip); /* Check if dip and BDF match, if not recurse to it's children. */ - if (!PCIE_IS_RC(bus_p) && (bdf == NULL || dip_bdf == bdf)) { + if (!PCIE_IS_RC(bus_p) && (!PCIE_CHECK_VALID_BDF(bdf) || + dip_bdf == bdf)) { if ((flag & PF_ADDR_DMA) && DDI_FM_DMA_ERR_CAP(fmhdl->fh_cap)) fcp = fmhdl->fh_dma_cache; else @@ -2227,7 +2237,7 @@ pf_hdl_compare(dev_info_t *dip, ddi_fm_error_t *derr, uint32_t flag, * If a handler isn't found and we know this is the right device mark * them all failed. */ - if ((addr != NULL) && (bdf != NULL) && (found == 0)) { + if ((addr != NULL) && PCIE_CHECK_VALID_BDF(bdf) && (found == 0)) { status = pf_hdl_compare(dip, derr, flag, addr, bdf, fcp); if (status == PF_HDL_FOUND) found++; @@ -2300,12 +2310,12 @@ pf_log_hdl_lookup(dev_info_t *rpdip, ddi_fm_error_t *derr, pf_data_t *pfd_p, int pf_tlp_decode(pcie_bus_t *bus_p, pf_pcie_adv_err_regs_t *adv_reg_p) { pcie_tlp_hdr_t *tlp_hdr = (pcie_tlp_hdr_t *)adv_reg_p->pcie_ue_hdr; - pcie_req_id_t my_bdf, tlp_bdf, flt_bdf = 0xFFFF; + pcie_req_id_t my_bdf, tlp_bdf, flt_bdf = PCIE_INVALID_BDF; uint64_t flt_addr = 0; uint32_t flt_trans_type = 0; adv_reg_p->pcie_ue_tgt_addr = 0; - adv_reg_p->pcie_ue_tgt_bdf = 0; + adv_reg_p->pcie_ue_tgt_bdf = PCIE_INVALID_BDF; adv_reg_p->pcie_ue_tgt_trans = 0; my_bdf = bus_p->bus_bdf; @@ -2338,7 +2348,7 @@ pf_tlp_decode(pcie_bus_t *bus_p, pf_pcie_adv_err_regs_t *adv_reg_p) { flt_bdf = tlp_bdf; } else { flt_trans_type = PF_ADDR_PIO; - flt_bdf = 0; + flt_bdf = PCIE_INVALID_BDF; } break; case PCIE_TLP_TYPE_CFG0: @@ -2614,7 +2624,7 @@ pf_send_ereport(ddi_fm_error_t *derr, pf_impl_t *impl) /* Clear these values as they no longer valid */ PCIE_ADV_REG(pfd_p)->pcie_ue_tgt_trans = 0; PCIE_ADV_REG(pfd_p)->pcie_ue_tgt_addr = 0; - PCIE_ADV_REG(pfd_p)->pcie_ue_tgt_bdf = 0; + PCIE_ADV_REG(pfd_p)->pcie_ue_tgt_bdf = PCIE_INVALID_BDF; } /* PCIe BDG AER registers */ @@ -2653,7 +2663,8 @@ pf_send_ereport(ddi_fm_error_t *derr, pf_impl_t *impl) /* Clear these values as they no longer valid */ PCIE_ADV_BDG_REG(pfd_p)->pcie_sue_tgt_trans = 0; PCIE_ADV_BDG_REG(pfd_p)->pcie_sue_tgt_addr = 0; - PCIE_ADV_BDG_REG(pfd_p)->pcie_sue_tgt_bdf = 0; + PCIE_ADV_BDG_REG(pfd_p)->pcie_sue_tgt_bdf = + PCIE_INVALID_BDF; } /* PCIe RP registers */ diff --git a/usr/src/uts/common/sys/pcie.h b/usr/src/uts/common/sys/pcie.h index f86b286dd6..6ffa4ac033 100644 --- a/usr/src/uts/common/sys/pcie.h +++ b/usr/src/uts/common/sys/pcie.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -62,7 +62,7 @@ extern "C" { #define PCIE_PCIECAP_VER_1_0 0x1 /* PCI-E spec 1.0 */ #define PCIE_PCIECAP_VER_MASK 0xF /* Version Mask */ #define PCIE_PCIECAP_DEV_TYPE_PCIE_DEV 0x00 /* PCI-E Endpont Device */ -#define PCIE_PCIECAP_DEV_TYPE_PCI_DEV 0x10 /* Leg PCI Endpont Device */ +#define PCIE_PCIECAP_DEV_TYPE_PCI_DEV 0x10 /* "Leg PCI" Endpont Device */ #define PCIE_PCIECAP_DEV_TYPE_ROOT 0x40 /* Root Port of Root Complex */ #define PCIE_PCIECAP_DEV_TYPE_UP 0x50 /* Upstream Port of Switch */ #define PCIE_PCIECAP_DEV_TYPE_DOWN 0x60 /* Downstream Port of Switch */ @@ -216,7 +216,9 @@ extern "C" { #define PCIE_LINKCAP_DLL_ACTIVE_REP_CAPABLE 0x100000 /* DLL Active */ /* Capable bit */ -#define PCIE_LINKCAP_PORT_NUMBER 0xF0000000 /* Port Number */ +#define PCIE_LINKCAP_PORT_NUMBER 0xFF000000 /* Port Number */ +#define PCIE_LINKCAP_PORT_NUMBER_SHIFT 24 /* Port Number Shift */ +#define PCIE_LINKCAP_PORT_NUMBER_MASK 0xFF /* Port Number Mask */ /* * Link Control Register (2 bytes) @@ -590,7 +592,7 @@ typedef uint16_t pcie_req_id_t; #define PCIE_REQ_ID_BUS_SHIFT 8 #define PCIE_REQ_ID_BUS_MASK 0xFF00 #define PCIE_REQ_ID_DEV_SHIFT 3 -#define PCIE_REQ_ID_DEV_MASK 0x00F1 +#define PCIE_REQ_ID_DEV_MASK 0x00F8 #define PCIE_REQ_ID_FUNC_SHIFT 0 #define PCIE_REQ_ID_FUNC_MASK 0x0007 diff --git a/usr/src/uts/common/sys/pcie_impl.h b/usr/src/uts/common/sys/pcie_impl.h index b1b96144f3..817211192f 100644 --- a/usr/src/uts/common/sys/pcie_impl.h +++ b/usr/src/uts/common/sys/pcie_impl.h @@ -61,8 +61,7 @@ extern "C" { #define PCIE_IS_PCIE(bus_p) (bus_p->bus_pcie_off) #define PCIE_IS_PCIX(bus_p) (bus_p->bus_pcix_off) -#define PCIE_IS_PCI(bus_p) \ - (bus_p->bus_dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) +#define PCIE_IS_PCI(bus_p) (!PCIE_IS_PCIE(bus_p)) #define PCIE_HAS_AER(bus_p) (bus_p->bus_aer_off) /* IS_ROOT = is RC or RP */ #define PCIE_IS_ROOT(bus_p) (PCIE_IS_RC(bus_p) || PCIE_IS_RP(bus_p)) @@ -76,13 +75,14 @@ extern "C" { #define PCIE_IS_RP(bus_p) \ ((bus_p->bus_dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) && \ PCIE_IS_PCIE(bus_p)) +#define PCIE_IS_SWU(bus_p) \ + (bus_p->bus_dev_type == PCIE_PCIECAP_DEV_TYPE_UP) +#define PCIE_IS_SWD(bus_p) \ + (bus_p->bus_dev_type == PCIE_PCIECAP_DEV_TYPE_DOWN) #define PCIE_IS_SW(bus_p) \ - ((bus_p->bus_dev_type == PCIE_PCIECAP_DEV_TYPE_UP) || \ - (bus_p->bus_dev_type == PCIE_PCIECAP_DEV_TYPE_DOWN)) + (PCIE_IS_SWU(bus_p) || PCIE_IS_SWD(bus_p)) #define PCIE_IS_BDG(bus_p) (bus_p->bus_hdr_type == PCI_HEADER_ONE) -#define PCIE_IS_PCI_BDG(bus_p) \ - ((bus_p->bus_dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) && \ - PCIE_IS_BDG(bus_p)) +#define PCIE_IS_PCI_BDG(bus_p) (PCIE_IS_PCI(bus_p) && PCIE_IS_BDG(bus_p)) #define PCIE_IS_PCIE_BDG(bus_p) \ (bus_p->bus_dev_type == PCIE_PCIECAP_DEV_TYPE_PCIE2PCI) #define PCIE_IS_PCI2PCIE(bus_p) \ @@ -216,7 +216,7 @@ typedef struct pf_pcie_adv_err_regs { } pcie_ext; uint32_t pcie_ue_tgt_trans; /* Fault trans type from AER Logs */ uint64_t pcie_ue_tgt_addr; /* Fault addr from AER Logs */ - pcie_req_id_t pcie_ue_tgt_bdf; /* Fault bdf from SAER Logs */ + pcie_req_id_t pcie_ue_tgt_bdf; /* Fault bdf from AER Logs */ } pf_pcie_adv_err_regs_t; typedef struct pf_pcie_rp_err_regs { @@ -233,8 +233,8 @@ typedef struct pf_pcie_err_regs { } pf_pcie_err_regs_t; typedef struct pf_root_fault { - pcie_req_id_t fault_bdf; /* Fault BDF of error */ - uint64_t fault_addr; /* Fault Addr of error */ + pcie_req_id_t scan_bdf; /* BDF from error logs */ + uint64_t scan_addr; /* Addr from error logs */ boolean_t full_scan; /* Option to do a full scan */ } pf_root_fault_t; @@ -337,7 +337,19 @@ typedef struct pf_impl { #define PF_HDL_FOUND 1 #define PF_HDL_NOTFOUND 2 -#define PCIE_PCIECAP_DEV_TYPE_RC_PSEUDO 0x100 +/* + * PCIe Capability Device Type Pseudo Definitions. + * + * PCI_PSEUDO is used on real PCI devices. The Legacy PCI definition in the + * PCIe spec really refers to PCIe devices that *require* IO Space access. IO + * Space access is usually frowned upon now in PCIe, but there for legacy + * purposes. + */ +#define PCIE_PCIECAP_DEV_TYPE_RC_PSEUDO 0x100 +#define PCIE_PCIECAP_DEV_TYPE_PCI_PSEUDO 0x101 + +#define PCIE_INVALID_BDF 0xFFFF +#define PCIE_CHECK_VALID_BDF(x) (x != PCIE_INVALID_BDF) typedef struct { dev_info_t *dip; diff --git a/usr/src/uts/i86pc/io/pci/pci_tools.c b/usr/src/uts/i86pc/io/pci/pci_tools.c index bb14b08622..0bfe9e0229 100644 --- a/usr/src/uts/i86pc/io/pci/pci_tools.c +++ b/usr/src/uts/i86pc/io/pci/pci_tools.c @@ -975,7 +975,7 @@ pcitool_dev_reg_ops(dev_info_t *dip, void *arg, int cmd, int mode) /* * Access device. prg is modified. - * First, check for AMD northbridges for I/O access + * First, check for AMD K8 northbridges for I/O access * (This fix will move in future to pcitool user-land) * Next, check for PCIe devices and do * memory-mapped access @@ -983,8 +983,10 @@ pcitool_dev_reg_ops(dev_info_t *dip, void *arg, int cmd, int mode) */ if ((prg.bus_no == 0) && (prg.dev_no >= 0x18) && - (prg.dev_no < (0x18 + ncpus)) && - (cpuid_getvendor(CPU) == X86_VENDOR_AMD)) { + (prg.dev_no < + (0x18 + ncpus/cpuid_get_ncpu_per_chip(CPU))) && + (cpuid_getvendor(CPU) == X86_VENDOR_AMD) && + (cpuid_getfamily(CPU) == 0xf)) { rval = pcitool_cfg_access(dip, &prg, write_flag); } else if (max_cfg_size == PCIE_CONF_HDR_SIZE) { diff --git a/usr/src/uts/intel/io/pci/pci_pci.c b/usr/src/uts/intel/io/pci/pci_pci.c index f28aa8f454..23c174ac7c 100644 --- a/usr/src/uts/intel/io/pci/pci_pci.c +++ b/usr/src/uts/intel/io/pci/pci_pci.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -219,7 +219,7 @@ typedef struct { ushort_t bridge_control; } config_state[PCI_MAX_CHILDREN]; - uint8_t parent_bus; + uint16_t parent_bus; } ppb_devstate_t; @@ -339,7 +339,7 @@ ppb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) return (DDI_FAILURE); } - ppb->parent_bus = PCIE_PCIECAP_DEV_TYPE_PCI_DEV; + ppb->parent_bus = PCIE_PCIECAP_DEV_TYPE_PCI_PSEUDO; for (pdip = ddi_get_parent(devi); pdip && (pdip != root) && (ppb->parent_bus != PCIE_PCIECAP_DEV_TYPE_PCIE_DEV); pdip = ddi_get_parent(pdip)) { diff --git a/usr/src/uts/sun4/io/px/px_dma.c b/usr/src/uts/sun4/io/px/px_dma.c index ce32fcd46a..b6be1f4c79 100644 --- a/usr/src/uts/sun4/io/px/px_dma.c +++ b/usr/src/uts/sun4/io/px/px_dma.c @@ -118,8 +118,8 @@ px_dma_allocmp(dev_info_t *dip, dev_info_t *rdip, int (*waitfp)(caddr_t), * XXX No IOMMU protection for broken devices. */ ASSERT((intptr_t)ddi_get_parent_data(rdip) >> 1 == 0); - mp->dmai_bdf = ((intptr_t)ddi_get_parent_data(rdip) == 1) ? 0 : - pcie_get_bdf_for_dma_xfer(dip, rdip); + mp->dmai_bdf = ((intptr_t)ddi_get_parent_data(rdip) == 1) ? + PCIE_INVALID_BDF : pcie_get_bdf_for_dma_xfer(dip, rdip); return (mp); } diff --git a/usr/src/uts/sun4/io/px/px_fdvma.c b/usr/src/uts/sun4/io/px/px_fdvma.c index bc761960a9..e45d167ee9 100644 --- a/usr/src/uts/sun4/io/px/px_fdvma.c +++ b/usr/src/uts/sun4/io/px/px_fdvma.c @@ -211,8 +211,8 @@ px_fdvma_reserve(dev_info_t *dip, dev_info_t *rdip, px_t *px_p, * XXX No IOMMU protection for broken devices. */ ASSERT((intptr_t)ddi_get_parent_data(rdip) >> 1 == 0); - mp->dmai_bdf = ((intptr_t)ddi_get_parent_data(rdip) == 1) ? 0 : - pcie_get_bdf_for_dma_xfer(dip, rdip); + mp->dmai_bdf = ((intptr_t)ddi_get_parent_data(rdip) == 1) ? + PCIE_INVALID_BDF : pcie_get_bdf_for_dma_xfer(dip, rdip); DBG(DBG_DMA_CTL, dip, "DDI_DMA_RESERVE: mp=%p dvma=%x npages=%x private=%p\n", diff --git a/usr/src/uts/sun4/io/px/px_fm.c b/usr/src/uts/sun4/io/px/px_fm.c index 3e570f16b6..987957ce96 100644 --- a/usr/src/uts/sun4/io/px/px_fm.c +++ b/usr/src/uts/sun4/io/px/px_fm.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -299,7 +299,7 @@ px_fm_callback(dev_info_t *dip, ddi_fm_error_t *derr, const void *impl_data) int lookup, rc_err, fab_err; uint64_t addr, base_addr; uint64_t fault_addr = (uint64_t)derr->fme_bus_specific; - pcie_req_id_t bdf; + pcie_req_id_t bdf = PCIE_INVALID_BDF; px_ranges_t *ranges_p; int range_len; @@ -339,7 +339,7 @@ px_fm_callback(dev_info_t *dip, ddi_fm_error_t *derr, const void *impl_data) case PCI_ADDR_MEM32: acc_type = PF_ADDR_PIO; addr = fault_addr - base_addr; - bdf = NULL; + bdf = PCIE_INVALID_BDF; break; } break; @@ -591,15 +591,15 @@ px_err_check_pcie(dev_info_t *dip, ddi_fm_error_t *derr, px_err_pcie_t *regs) if (regs->primary_ue & (PCIE_AER_UCE_UR | PCIE_AER_UCE_CA)) { if (pf_tlp_decode(PCIE_DIP2BUS(dip), adv_reg) == DDI_SUCCESS) - PCIE_ROOT_FAULT(pfd_p)->fault_bdf = + PCIE_ROOT_FAULT(pfd_p)->scan_bdf = adv_reg->pcie_ue_tgt_bdf; } else if (regs->primary_ue & PCIE_AER_UCE_PTLP) { if (pf_tlp_decode(PCIE_DIP2BUS(dip), adv_reg) == DDI_SUCCESS) { - PCIE_ROOT_FAULT(pfd_p)->fault_bdf = + PCIE_ROOT_FAULT(pfd_p)->scan_bdf = adv_reg->pcie_ue_tgt_bdf; if (adv_reg->pcie_ue_tgt_trans == PF_ADDR_PIO) - PCIE_ROOT_FAULT(pfd_p)->fault_addr = + PCIE_ROOT_FAULT(pfd_p)->scan_addr = adv_reg->pcie_ue_tgt_addr; } @@ -708,8 +708,8 @@ px_get_pfd(px_t *px_p) { pf_data_t *pfd_p = &px_p->px_pfd_arr[idx]; /* Clear Old Data */ - PCIE_ROOT_FAULT(pfd_p)->fault_bdf = 0; - PCIE_ROOT_FAULT(pfd_p)->fault_addr = 0; + PCIE_ROOT_FAULT(pfd_p)->scan_bdf = PCIE_INVALID_BDF; + PCIE_ROOT_FAULT(pfd_p)->scan_addr = 0; PCI_BDG_ERR_REG(pfd_p)->pci_bdg_sec_stat = 0; PCIE_ADV_REG(pfd_p)->pcie_ce_status = 0; PCIE_ADV_REG(pfd_p)->pcie_ue_status = 0; @@ -734,26 +734,26 @@ px_get_pfd(px_t *px_p) { * o errs rcvd in RC, that may have been propagated to/from the fabric * o the fabric scan code should scan the device path of fault bdf/addr * - * fault_bdf: The bdf that caused the fault, which may have error bits set. - * fault_addr: The PIO addr that caused the fault, such as failed PIO, but not + * scan_bdf: The bdf that caused the fault, which may have error bits set. + * scan_addr: The PIO addr that caused the fault, such as failed PIO, but not * failed DMAs. * s_status: Secondary Status equivalent to why the fault occured. * (ie S-TA/MA, R-TA) - * Either the fault bdf or addr may be NULL, but not both. + * Either the scan bdf or addr may be NULL, but not both. */ void -px_rp_en_q(px_t *px_p, pcie_req_id_t fault_bdf, uint32_t fault_addr, +px_rp_en_q(px_t *px_p, pcie_req_id_t scan_bdf, uint32_t scan_addr, uint16_t s_status) { pf_data_t *pfd_p; - if (!fault_bdf && !fault_addr) + if (!PCIE_CHECK_VALID_BDF(scan_bdf) && !scan_addr) return; pfd_p = px_get_pfd(px_p); - PCIE_ROOT_FAULT(pfd_p)->fault_bdf = fault_bdf; - PCIE_ROOT_FAULT(pfd_p)->fault_addr = (uint64_t)fault_addr; + PCIE_ROOT_FAULT(pfd_p)->scan_bdf = scan_bdf; + PCIE_ROOT_FAULT(pfd_p)->scan_addr = (uint64_t)scan_addr; PCI_BDG_ERR_REG(pfd_p)->pci_bdg_sec_stat = s_status; } @@ -784,8 +784,8 @@ px_err_cfg_hdl_check(dev_info_t *dip, const void *handle, const void *arg1, * only mark the device as "Non-Fatal" if the addr == NULL and bdf != * NULL. */ - status = (!addr && (bus_p->bus_bdf == bdf)) ? DDI_FM_NONFATAL : - DDI_FM_FATAL; + status = (!addr && (PCIE_CHECK_VALID_BDF(bdf) && + (bus_p->bus_bdf == bdf))) ? DDI_FM_NONFATAL : DDI_FM_FATAL; return (status); } @@ -840,7 +840,8 @@ px_err_pio_hdl_check(dev_info_t *dip, const void *handle, const void *arg1, */ size = hp->ah_len; if (((fault_addr >= base_addr) && (fault_addr < (base_addr + size))) || - ((fault_addr == NULL) && (bdf == PCIE_DIP2BUS(dip)->bus_bdf))) + ((fault_addr == NULL) && (PCIE_CHECK_VALID_BDF(bdf) && + (bdf == PCIE_DIP2BUS(dip)->bus_bdf)))) status = DDI_FM_NONFATAL; return (status); @@ -876,7 +877,7 @@ px_err_dma_hdl_check(dev_info_t *dip, const void *handle, const void *arg1, * know the BDF and ADDR == 0. */ if (((addr >= base_addr) && (addr < (base_addr + size))) || - ((addr == NULL) && (bdf != NULL))) + ((addr == NULL) && PCIE_CHECK_VALID_BDF(bdf))) status = DDI_FM_NONFATAL; return (status); diff --git a/usr/src/uts/sun4/io/px/px_ioapi.h b/usr/src/uts/sun4/io/px/px_ioapi.h index f84d4e6488..1d5c123185 100644 --- a/usr/src/uts/sun4/io/px/px_ioapi.h +++ b/usr/src/uts/sun4/io/px/px_ioapi.h @@ -225,7 +225,7 @@ typedef uint64_t io_attributes_t; #define PCI_MAP_ATTR_BDF_MASK 0xffff0000 #define PX_ADD_ATTR_EXTNS(attr, bdf) \ - (attr | (bdf << PCI_MAP_ATTR_BDF)) + (attr | (PCIE_CHECK_VALID_BDF(bdf) ? (bdf << PCI_MAP_ATTR_BDF) : 0)) typedef enum io_sync_direction { IO_SYNC_DEVICE = (uint32_t)0x01, diff --git a/usr/src/uts/sun4/io/px/px_pci.c b/usr/src/uts/sun4/io/px/px_pci.c index b981f2a669..d043ecc8c6 100644 --- a/usr/src/uts/sun4/io/px/px_pci.c +++ b/usr/src/uts/sun4/io/px/px_pci.c @@ -2119,31 +2119,159 @@ body: } #endif + #ifdef PX_PLX /* - * Disable PLX specific relaxed ordering mode. Due to PLX + * Disable PLX specific relaxed ordering mode. Due to PLX * erratum #6, use of this mode with Cut-Through Cancellation * can result in dropped Completion type packets. + * + * Clear the Relaxed Ordering Mode on 8533 and 8548 switches. + * To disable RO, clear bit 5 in offset 0x664, an undocumented + * bit in the PLX spec, on Ports 0, 8 and 12. Proprietary PLX + * registers are normally accessible only via memspace from Port + * 0. If port 0 is attached go ahead and disable RO on Port 0, + * 8 and 12, if they exist. */ static void plx_ro_disable(pxb_devstate_t *pxb) { - uint32_t val; - ddi_acc_handle_t hdl = pxb->pxb_config_handle; + pcie_bus_t *bus_p = PCIE_DIP2BUS(pxb->pxb_dip); + dev_info_t *dip = pxb->pxb_dip; + pci_regspec_t *reg_spec, *addr_spec; + int rlen, alen; + int orig_rsize, new_rsize; + uint_t rnum, anum; + ddi_device_acc_attr_t attr; + ddi_acc_handle_t hdl; + caddr_t regsp; + uint32_t val, port_enable; + char *offset; + char *port_offset; + + if (!((pxb->pxb_device_id == PXB_DEVICE_PLX_8533) || + (pxb->pxb_device_id == PXB_DEVICE_PLX_8548))) + return; - switch (pxb->pxb_device_id) { - case PXB_DEVICE_PLX_8533: - case PXB_DEVICE_PLX_8548: - /* - * Clear the Relaxed Ordering Mode bit of the Egress - * Performance Counter register on 8533 and 8548 switches. - */ - val = pci_config_get32(hdl, PLX_EGRESS_PERFCTR_OFFSET); - if (val & PLX_RO_MODE_BIT) { - val ^= PLX_RO_MODE_BIT; - pci_config_put32(hdl, PLX_EGRESS_PERFCTR_OFFSET, val); - } - break; + /* You can also only do this on Port 0 */ + val = PCIE_CAP_GET(32, bus_p, PCIE_LINKCAP); + val = (val >> PCIE_LINKCAP_PORT_NUMBER_SHIFT) & + PCIE_LINKCAP_PORT_NUMBER_MASK; + + DBG(DBG_ATTACH, dip, "PLX RO Disable : bdf=0x%x port=%d\n", + bus_p->bus_bdf, val); + + if (val != 0) + return; + + /* + * Read the reg property, but allocate extra space incase we need to add + * a new entry later. + */ + if (ddi_getproplen(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg", + &orig_rsize) != DDI_SUCCESS) + return; + + new_rsize = orig_rsize + sizeof (pci_regspec_t); + reg_spec = kmem_alloc(new_rsize, KM_SLEEP); + + if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg", + (caddr_t)reg_spec, &orig_rsize) != DDI_SUCCESS) + goto fail; + + /* Find the mem32 reg property */ + rlen = orig_rsize / sizeof (pci_regspec_t); + for (rnum = 0; rnum < rlen; rnum++) { + if ((reg_spec[rnum].pci_phys_hi & PCI_ADDR_MASK) == + PCI_ADDR_MEM32) + goto fix; } + + /* + * Mem32 reg property was not found. + * Look for it in assign-address property. + */ + addr_spec = bus_p->bus_assigned_addr; + alen = bus_p->bus_assigned_entries; + for (anum = 0; anum < alen; anum++) { + if ((addr_spec[anum].pci_phys_hi & PCI_ADDR_MASK) == + PCI_ADDR_MEM32) + goto update; + } + + /* Unable to find mem space assigned address, give up. */ + goto fail; + +update: + /* + * Add the mem32 access to the reg spec. + * Use the last entry which was previously allocated. + */ + reg_spec[rnum].pci_phys_hi = (addr_spec[anum].pci_phys_hi & + ~PCI_REG_REL_M); + reg_spec[rnum].pci_phys_mid = 0; + reg_spec[rnum].pci_phys_low = 0; + reg_spec[rnum].pci_size_hi = addr_spec[anum].pci_size_hi; + reg_spec[rnum].pci_size_low = addr_spec[anum].pci_size_low; + + /* Create the new reg_spec data and update the property */ + if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, "reg", + (int *)reg_spec, (new_rsize / sizeof (int))) != DDI_SUCCESS) + goto fail; + +fix: + attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; + attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; + attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; + + if (ddi_regs_map_setup(dip, rnum, ®sp, 0, 0, &attr, + &hdl) != DDI_SUCCESS) + goto fail; + + /* Grab register which shows which ports are enabled */ + offset = (char *)regsp + PLX_INGRESS_PORT_ENABLE; + port_enable = ddi_get32(hdl, (uint32_t *)offset); + + if ((port_enable == 0xFFFFFFFF) || (port_enable == 0)) + goto done; + + offset = (char *)regsp + PLX_INGRESS_CONTROL_SHADOW; + + /* Disable RO on Port 0 */ + port_offset = 0x0 + offset; + val = ddi_get32(hdl, (uint32_t *)port_offset); + if (val & PLX_RO_MODE_BIT) + val ^= PLX_RO_MODE_BIT; + ddi_put32(hdl, (uint32_t *)port_offset, val); + + /* Disable RO on Port 8, but make sure its enabled */ + if (!(port_enable & (1 << 8))) + goto port12; + + port_offset = (8 * 0x1000) + offset; + val = ddi_get32(hdl, (uint32_t *)port_offset); + if (val & PLX_RO_MODE_BIT) + val ^= PLX_RO_MODE_BIT; + ddi_put32(hdl, (uint32_t *)port_offset, val); + +port12: + /* Disable RO on Port 12, but make sure it exists */ + if (!(port_enable & (1 << 12))) + goto done; + + port_offset = (12 * 0x1000) + offset; + val = ddi_get32(hdl, (uint32_t *)port_offset); + if (val & PLX_RO_MODE_BIT) + val ^= PLX_RO_MODE_BIT; + ddi_put32(hdl, (uint32_t *)port_offset, val); + + goto done; + +fail: + DBG(DBG_ATTACH, dip, "PLX RO Disable failed.\n"); + +done: + ddi_regs_map_free(&hdl); + kmem_free(reg_spec, new_rsize); } #endif /* PX_PLX */ diff --git a/usr/src/uts/sun4/io/px/pxb_plx.h b/usr/src/uts/sun4/io/px/pxb_plx.h index c5de6c5b6c..f2f407a01d 100644 --- a/usr/src/uts/sun4/io/px/pxb_plx.h +++ b/usr/src/uts/sun4/io/px/pxb_plx.h @@ -19,15 +19,13 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_PXB_PLX_H #define _SYS_PXB_PLX_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -47,8 +45,11 @@ extern "C" { #define PXB_DEVICE_PLX_AA_REV 0xAA /* Register offsets and bits specific to the 8548 and 8533 */ -#define PLX_EGRESS_PERFCTR_OFFSET 0x1F0 -#define PLX_RO_MODE_BIT 0x100000 +#define PLX_INGRESS_CONTROL_SHADOW 0x664 +#define PLX_INGRESS_PORT_ENABLE 0x668 +#define PLX_CAM_PORT_8 0x2e8 +#define PLX_CAM_PORT_12 0x2f8 +#define PLX_RO_MODE_BIT 0x20 #ifdef __cplusplus } diff --git a/usr/src/uts/sun4u/io/pci/pci_pci.c b/usr/src/uts/sun4u/io/pci/pci_pci.c index dd204a90de..f68ef8ac5d 100644 --- a/usr/src/uts/sun4u/io/pci/pci_pci.c +++ b/usr/src/uts/sun4u/io/pci/pci_pci.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -244,7 +244,7 @@ typedef struct { int fm_cap; ddi_iblock_cookie_t fm_ibc; - uint8_t parent_bus; + uint16_t parent_bus; } ppb_devstate_t; /* @@ -1711,7 +1711,7 @@ ppb_fm_init(ppb_devstate_t *ppb_p) */ ddi_fm_handler_register(ppb_p->dip, ppb_err_callback, NULL); - ppb_p->parent_bus = PCIE_PCIECAP_DEV_TYPE_PCI_DEV; + ppb_p->parent_bus = PCIE_PCIECAP_DEV_TYPE_PCI_PSEUDO; for (pdip = ddi_get_parent(ppb_p->dip); pdip && (pdip != root) && (ppb_p->parent_bus != PCIE_PCIECAP_DEV_TYPE_PCIE_DEV); pdip = ddi_get_parent(pdip)) { diff --git a/usr/src/uts/sun4u/io/px/px_err.c b/usr/src/uts/sun4u/io/px/px_err.c index 58778ac9da..b5d753a0f5 100644 --- a/usr/src/uts/sun4u/io/px/px_err.c +++ b/usr/src/uts/sun4u/io/px/px_err.c @@ -19,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * sun4u Fire Error Handling */ @@ -1714,7 +1712,7 @@ PX_ERPT_SEND_DEC(mmu_tfar_tfsr) char buf[FM_MAX_CLASS]; boolean_t pri = PX_ERR_IS_PRI(bit); px_t *px_p = DIP_TO_STATE(rpdip); - pcie_req_id_t fault_bdf = 0; + pcie_req_id_t fault_bdf = PCIE_INVALID_BDF; uint16_t s_status = 0; if (pri) { diff --git a/usr/src/uts/sun4u/io/px/px_lib4u.c b/usr/src/uts/sun4u/io/px/px_lib4u.c index db4abbd4d4..f9b98235d4 100644 --- a/usr/src/uts/sun4u/io/px/px_lib4u.c +++ b/usr/src/uts/sun4u/io/px/px_lib4u.c @@ -1498,7 +1498,7 @@ px_lib_clr_errs(px_t *px_p, dev_info_t *rdip, uint64_t addr) px_ranges_t *ranges_p; int range_len; uint32_t addr_high, addr_low; - pcie_req_id_t bdf = 0; + pcie_req_id_t bdf = PCIE_INVALID_BDF; /* Create the derr */ bzero(&derr, sizeof (ddi_fm_error_t)); @@ -1533,7 +1533,7 @@ px_lib_clr_errs(px_t *px_p, dev_info_t *rdip, uint64_t addr) if (rdip) bdf = PCI_GET_BDF(rdip); else - bdf = NULL; + bdf = PCIE_INVALID_BDF; break; } break; diff --git a/usr/src/uts/sun4v/io/px/px_err.c b/usr/src/uts/sun4v/io/px/px_err.c index 77a2c4f2de..1ffb4ac429 100644 --- a/usr/src/uts/sun4v/io/px/px_err.c +++ b/usr/src/uts/sun4v/io/px/px_err.c @@ -19,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * sun4v Fire Error Handling */ @@ -139,7 +137,7 @@ static void px_err_fill_pfd(dev_info_t *dip, px_t *px_p, px_rc_err_t *epkt) { pf_pcie_adv_err_regs_t adv_reg; int sts = DDI_SUCCESS; - pcie_req_id_t fault_bdf = 0; + pcie_req_id_t fault_bdf = PCIE_INVALID_BDF; uint64_t fault_addr = 0; uint16_t s_status = 0; @@ -179,7 +177,7 @@ px_err_fill_pfd(dev_info_t *dip, px_t *px_p, px_rc_err_t *epkt) { sts = pf_tlp_decode(PCIE_DIP2BUS(dip), &adv_reg); fault_bdf = adv_reg.pcie_ue_tgt_bdf; - fault_addr = adv_reg.pcie_ue_tgt_bdf; + fault_addr = adv_reg.pcie_ue_tgt_addr; } if (sts == DDI_SUCCESS) @@ -671,7 +669,7 @@ static int px_mmu_handle_lookup(dev_info_t *dip, ddi_fm_error_t *derr, px_rc_err_t *epkt) { uint64_t addr = (uint64_t)epkt->addr; - pcie_req_id_t bdf = NULL; + pcie_req_id_t bdf = PCIE_INVALID_BDF; if (epkt->rc_descr.H) { bdf = (uint32_t)((epkt->hdr[0] >> 16) && 0xFFFF); diff --git a/usr/src/uts/sun4v/io/px/px_lib4v.c b/usr/src/uts/sun4v/io/px/px_lib4v.c index 129efd58cd..ba3d30a1da 100644 --- a/usr/src/uts/sun4v/io/px/px_lib4v.c +++ b/usr/src/uts/sun4v/io/px/px_lib4v.c @@ -1527,7 +1527,7 @@ px_lib_log_safeacc_err(px_t *px_p, ddi_acc_handle_t handle, int fme_flag, r_addr_t addr) { uint32_t addr_high, addr_low; - pcie_req_id_t bdf; + pcie_req_id_t bdf = PCIE_INVALID_BDF; px_ranges_t *ranges_p; int range_len, i; ddi_acc_impl_t *hp = (ddi_acc_impl_t *)handle; @@ -1557,7 +1557,7 @@ px_lib_log_safeacc_err(px_t *px_p, ddi_acc_handle_t handle, int fme_flag, bdf = (pcie_req_id_t)(addr_low >> 12); break; default: - bdf = NULL; + bdf = PCIE_INVALID_BDF; break; } break; |