summaryrefslogtreecommitdiff
path: root/usr/src/uts/sun4/io
diff options
context:
space:
mode:
authorkrishnae <none@none>2008-03-28 12:11:52 -0700
committerkrishnae <none@none>2008-03-28 12:11:52 -0700
commiteae2e508a8e70b1ec407b10bd068c080651bbe5c (patch)
tree997c76ef99a46a31e13e027aae4085ea65f05e1d /usr/src/uts/sun4/io
parentc45cbb52ab3d9544ffb196de6b0a1c5f332c93a4 (diff)
downloadillumos-joyent-eae2e508a8e70b1ec407b10bd068c080651bbe5c.tar.gz
PSARC 2008/157 PCIe Fabric portfolio for SPARC and x86
6510830 SPARC and x86 PCIe IO error handling should be merged --HG-- rename : usr/src/uts/intel/io/pciex/pcie_error.c => deleted_files/usr/src/uts/intel/io/pciex/pcie_error.c rename : usr/src/uts/intel/io/pciex/pcie_error.h => deleted_files/usr/src/uts/intel/io/pciex/pcie_error.h rename : deleted_files/usr/src/cmd/fm/modules/common/fabric-xlate/Makefile => usr/src/cmd/fm/modules/common/fabric-xlate/Makefile rename : deleted_files/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.c => usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.c rename : deleted_files/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.conf => usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.conf
Diffstat (limited to 'usr/src/uts/sun4/io')
-rw-r--r--usr/src/uts/sun4/io/pcicfg.e.c2
-rw-r--r--usr/src/uts/sun4/io/px/pcie_pwr.c64
-rw-r--r--usr/src/uts/sun4/io/px/px.c93
-rw-r--r--usr/src/uts/sun4/io/px/px_fm.c624
-rw-r--r--usr/src/uts/sun4/io/px/px_fm.h19
-rw-r--r--usr/src/uts/sun4/io/px/px_pci.c135
-rw-r--r--usr/src/uts/sun4/io/px/px_pci.h6
-rw-r--r--usr/src/uts/sun4/io/px/px_space.c82
-rw-r--r--usr/src/uts/sun4/io/px/px_space.h19
-rw-r--r--usr/src/uts/sun4/io/px/px_util.c26
-rw-r--r--usr/src/uts/sun4/io/px/px_var.h10
11 files changed, 583 insertions, 497 deletions
diff --git a/usr/src/uts/sun4/io/pcicfg.e.c b/usr/src/uts/sun4/io/pcicfg.e.c
index 8575829b7a..5d7e161af2 100644
--- a/usr/src/uts/sun4/io/pcicfg.e.c
+++ b/usr/src/uts/sun4/io/pcicfg.e.c
@@ -3634,7 +3634,7 @@ pcicfg_enable_bridge_probe_err(dev_info_t *dip, ddi_acc_handle_t h,
/* restore original settings */
if (regs->pcie_dev) {
- pcie_clear_errors(dip, h);
+ pcie_clear_errors(dip);
pci_config_put16(h, regs->pcie_cap_off + PCIE_DEVCTL,
regs->devctl);
}
diff --git a/usr/src/uts/sun4/io/px/pcie_pwr.c b/usr/src/uts/sun4/io/px/pcie_pwr.c
index 0b8e47b150..fe96966b3a 100644
--- a/usr/src/uts/sun4/io/px/pcie_pwr.c
+++ b/usr/src/uts/sun4/io/px/pcie_pwr.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -103,7 +103,7 @@ static void pcie_add_comps(dev_info_t *dip, dev_info_t *cdip,
static void pcie_remove_comps(dev_info_t *dip, dev_info_t *cdip,
pcie_pwr_t *pwr_p);
static void pcie_pm_subrelease(dev_info_t *dip, pcie_pwr_t *pwr_p);
-static boolean_t pcie_is_pcie(ddi_acc_handle_t config_handle);
+static boolean_t pcie_is_pcie(dev_info_t *dip);
#ifdef DEBUG
static char *pcie_decode_pwr_op(pm_bus_power_op_t op);
#else
@@ -528,7 +528,7 @@ pcie_add_comps(dev_info_t *dip, dev_info_t *cdip, pcie_pwr_t *pwr_p)
PCIE_SET_PMINFO(cdip, pcie_pm_p);
}
cpwr_p = (pcie_pwr_child_t *)kmem_zalloc(sizeof (pcie_pwr_child_t),
- KM_SLEEP);
+ KM_SLEEP);
pcie_pm_p->pcie_par_pminfo = cpwr_p;
(cpwr_p->pwr_child_counters)[PCIE_UNKNOWN_INDEX] += comps;
}
@@ -631,7 +631,7 @@ pwr_common_teardown(dev_info_t *dip)
return;
(void) ddi_prop_remove(DDI_DEV_T_NONE, dip,
- "pm-want-child-notification?");
+ "pm-want-child-notification?");
mutex_destroy(&pwr_p->pwr_lock);
pcie_pm_p->pcie_pwr_p = NULL;
kmem_free(pwr_p, sizeof (pcie_pwr_t));
@@ -794,8 +794,8 @@ pcie_pm_remove_child(dev_info_t *dip, dev_info_t *cdip)
return (DDI_SUCCESS);
}
total = (counters[PCIE_D0_INDEX] + counters[PCIE_UNKNOWN_INDEX] +
- counters[PCIE_D1_INDEX] + counters[PCIE_D2_INDEX] +
- counters[PCIE_D3_INDEX]);
+ counters[PCIE_D1_INDEX] + counters[PCIE_D2_INDEX] +
+ counters[PCIE_D3_INDEX]);
/*
* Mark idle if either there are no children or our lowest
* possible level is less than the current level. Mark idle
@@ -814,19 +814,11 @@ pcie_pm_remove_child(dev_info_t *dip, dev_info_t *cdip)
}
boolean_t
-pcie_is_pcie(ddi_acc_handle_t config_handle)
+pcie_is_pcie(dev_info_t *dip)
{
- uint8_t cap_ptr, cap_id;
-
- cap_ptr = pci_config_get8(config_handle, PCI_BCNF_CAP_PTR);
- while (cap_ptr != PCI_CAP_NEXT_PTR_NULL) {
- cap_id = pci_config_get8(config_handle, cap_ptr + PCI_CAP_ID);
- if (cap_id == PCI_CAP_ID_PCI_E)
- return (B_TRUE);
- cap_ptr = pci_config_get8(config_handle,
- cap_ptr + PCI_CAP_NEXT_PTR);
- }
- return (B_FALSE);
+ pcie_bus_t *bus_p = PCIE_DIP2BUS(dip);
+ ASSERT(bus_p);
+ return (bus_p->bus_pcie_off != 0);
}
/*
@@ -837,7 +829,6 @@ pcie_pwr_resume(dev_info_t *dip)
{
dev_info_t *cdip;
pcie_pwr_t *pwr_p = NULL;
- ddi_acc_handle_t config_handle;
if (PCIE_PMINFO(dip))
pwr_p = PCIE_NEXUS_PMINFO(dip);
@@ -884,25 +875,17 @@ pcie_pwr_resume(dev_info_t *dip)
"DDI_RESUME: nexus restoring %s%d config regs\n",
ddi_driver_name(cdip), ddi_get_instance(cdip));
- if (pci_config_setup(cdip, &config_handle) != DDI_SUCCESS) {
- DBG(dip, "DDI_RESUME: "
- "pci_config_setup for %s%d failed\n",
- ddi_driver_name(cdip), ddi_get_instance(cdip));
- continue;
- }
-
/* clear errors left by OBP scrubbing */
- pcie_clear_errors(cdip, config_handle);
+ pcie_clear_errors(cdip);
/* PCIe workaround: disable errors during 4K config resore */
- if (is_pcie = pcie_is_pcie(config_handle))
- pcie_disable_errors(cdip, config_handle);
+ if (is_pcie = pcie_is_pcie(cdip))
+ pcie_disable_errors(cdip);
(void) pci_restore_config_regs(cdip);
if (is_pcie) {
- pcie_enable_errors(cdip, config_handle);
- (void) pcie_enable_ce(cdip, config_handle);
+ pcie_enable_errors(cdip);
+ (void) pcie_enable_ce(cdip);
}
- pci_config_teardown(&config_handle);
if (ndi_prop_remove(DDI_DEV_T_NONE, cdip,
"nexus-saved-config-regs") != DDI_PROP_SUCCESS) {
@@ -921,7 +904,6 @@ int
pcie_pwr_suspend(dev_info_t *dip)
{
dev_info_t *cdip;
- ddi_acc_handle_t config_handle;
int i, *counters; /* per nexus counters */
int *child_counters = NULL; /* per child dip counters */
pcie_pwr_t *pwr_p = NULL;
@@ -1020,21 +1002,13 @@ pcie_pwr_suspend(dev_info_t *dip)
" %s%d\n", ddi_driver_name(cdip), ddi_get_instance(cdip));
/* PCIe workaround: disable errors during 4K config save */
- if (pci_config_setup(cdip, &config_handle) != DDI_SUCCESS) {
- DBG(dip, "DDI_SUSPEND: pci_config_setup "
- "for %s%d failed\n",
- ddi_driver_name(cdip), ddi_get_instance(cdip));
- continue;
- }
-
- if (is_pcie = pcie_is_pcie(config_handle))
- pcie_disable_errors(cdip, config_handle);
+ if (is_pcie = pcie_is_pcie(cdip))
+ pcie_disable_errors(cdip);
(void) pci_save_config_regs(cdip);
if (is_pcie) {
- pcie_enable_errors(cdip, config_handle);
- (void) pcie_enable_ce(cdip, config_handle);
+ pcie_enable_errors(cdip);
+ (void) pcie_enable_ce(cdip);
}
- pci_config_teardown(&config_handle);
}
return (DDI_SUCCESS);
}
diff --git a/usr/src/uts/sun4/io/px/px.c b/usr/src/uts/sun4/io/px/px.c
index 0f790b052e..707fecb753 100644
--- a/usr/src/uts/sun4/io/px/px.c
+++ b/usr/src/uts/sun4/io/px/px.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -245,7 +245,7 @@ px_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
if (ddi_soft_state_zalloc(px_state_p, instance)
!= DDI_SUCCESS) {
cmn_err(CE_WARN, "%s%d: can't allocate px state",
- ddi_driver_name(dip), instance);
+ ddi_driver_name(dip), instance);
goto err_bad_px_softstate;
}
px_p = INST_TO_STATE(instance);
@@ -255,7 +255,7 @@ px_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
px_p->px_open_count = 0;
(void) ddi_prop_update_string(DDI_DEV_T_NONE, dip,
- "device_type", "pciex");
+ "device_type", "pciex");
/* Initialize px_dbg for high pil printing */
px_dbg_attach(dip, &px_p->px_dbg_hdl);
@@ -276,12 +276,6 @@ px_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
/* Cache the BDF of the root port nexus */
px_p->px_bdf = px_lib_get_bdf(px_p);
- px_p->px_dq_p = (pf_data_t *)
- kmem_zalloc(sizeof (pf_data_t) * pf_get_dq_size(),
- KM_SLEEP);
-
- px_p->px_dq_tail = -1;
-
/*
* Initialize interrupt block. Note that this
* initialize error handling for the PEC as well.
@@ -482,9 +476,6 @@ px_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
px_ib_detach(px_p);
(void) px_lib_dev_fini(dip);
- kmem_free(px_p->px_dq_p, sizeof (pf_data_t) *
- pf_get_dq_size());
-
/*
* Free the px soft state structure and the rest of the
* resources it's using.
@@ -494,7 +485,8 @@ px_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
mutex_exit(&px_p->px_mutex);
mutex_destroy(&px_p->px_mutex);
- /* Free the interrupt-priorities prop if we created it. */ {
+ /* Free the interrupt-priorities prop if we created it. */
+ {
int len;
if (ddi_getproplen(DDI_DEV_T_ANY, dip,
@@ -683,7 +675,7 @@ px_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
pci_regspec_t reloc_reg, *rp = &reloc_reg;
DBG(DBG_MAP, dip, "rdip=%s%d:",
- ddi_driver_name(rdip), ddi_get_instance(rdip));
+ ddi_driver_name(rdip), ddi_get_instance(rdip));
if (mp->map_flags & DDI_MF_USER_MAPPING)
return (DDI_ME_UNIMPLEMENTED);
@@ -698,8 +690,8 @@ px_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
DBG(DBG_MAP | DBG_CONT, dip, " r#=%x", r_no);
if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS,
- "reg", (caddr_t)&rp, &reglen) != DDI_SUCCESS)
- return (DDI_ME_RNUMBER_RANGE);
+ "reg", (caddr_t)&rp, &reglen) != DDI_SUCCESS)
+ return (DDI_ME_RNUMBER_RANGE);
if (r_no < 0 || r_no >= reglen / sizeof (pci_regspec_t)) {
kmem_free(rp, reglen);
@@ -721,8 +713,8 @@ px_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
* px_pci bridge nexus driver.
*/
if ((off >= PCIE_CONF_HDR_SIZE) ||
- (len > PCIE_CONF_HDR_SIZE) ||
- (off + len > PCIE_CONF_HDR_SIZE))
+ (len > PCIE_CONF_HDR_SIZE) ||
+ (off + len > PCIE_CONF_HDR_SIZE))
return (DDI_ME_INVAL);
/*
* the following function returning a DDI_FAILURE assumes
@@ -763,10 +755,8 @@ px_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
/*
* Set-up access functions for FM access error capable drivers.
*/
- if (DDI_FM_ACC_ERR_CAP(ddi_fm_capable(rdip)) &&
- mp->map_handlep->ah_acc.devacc_attr_access !=
- DDI_DEFAULT_ACC)
- px_fm_acc_setup(mp, rdip);
+ if (DDI_FM_ACC_ERR_CAP(ddi_fm_capable(rdip)))
+ px_fm_acc_setup(mp, rdip, rp);
}
done:
@@ -796,8 +786,8 @@ px_dma_setup(dev_info_t *dip, dev_info_t *rdip, ddi_dma_req_t *dmareq,
int ret;
DBG(DBG_DMA_MAP, dip, "mapping - rdip=%s%d type=%s\n",
- ddi_driver_name(rdip), ddi_get_instance(rdip),
- handlep ? "alloc" : "advisory");
+ ddi_driver_name(rdip), ddi_get_instance(rdip),
+ handlep ? "alloc" : "advisory");
if (!(mp = px_dma_lmts2hdl(dip, rdip, mmu_p, dmareq)))
return (DDI_DMA_NORESOURCES);
@@ -831,8 +821,8 @@ px_dma_setup(dev_info_t *dip, dev_info_t *rdip, ddi_dma_req_t *dmareq,
case PX_DMAI_FLAGS_BYPASS:
default:
cmn_err(CE_PANIC, "%s%d: px_dma_setup: bad dma type 0x%x",
- ddi_driver_name(rdip), ddi_get_instance(rdip),
- PX_DMA_TYPE(mp));
+ ddi_driver_name(rdip), ddi_get_instance(rdip),
+ PX_DMA_TYPE(mp));
/*NOTREACHED*/
}
*handlep = (ddi_dma_handle_t)mp;
@@ -861,7 +851,7 @@ px_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attrp,
int rval;
DBG(DBG_DMA_ALLOCH, dip, "rdip=%s%d\n",
- ddi_driver_name(rdip), ddi_get_instance(rdip));
+ ddi_driver_name(rdip), ddi_get_instance(rdip));
if (attrp->dma_attr_version != DMA_ATTR_V0)
return (DDI_DMA_BADATTR);
@@ -895,7 +885,7 @@ int
px_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle)
{
DBG(DBG_DMA_FREEH, dip, "rdip=%s%d mp=%p\n",
- ddi_driver_name(rdip), ddi_get_instance(rdip), handle);
+ ddi_driver_name(rdip), ddi_get_instance(rdip), handle);
px_dma_freemp((ddi_dma_impl_t *)handle);
if (px_kmem_clid) {
@@ -920,7 +910,7 @@ px_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
int ret;
DBG(DBG_DMA_BINDH, dip, "rdip=%s%d mp=%p dmareq=%p\n",
- ddi_driver_name(rdip), ddi_get_instance(rdip), mp, dmareq);
+ ddi_driver_name(rdip), ddi_get_instance(rdip), mp, dmareq);
if (mp->dmai_flags & PX_DMAI_FLAGS_INUSE)
return (DDI_DMA_INUSE);
@@ -961,17 +951,17 @@ mapped:
break;
default:
cmn_err(CE_PANIC, "%s%d: px_dma_bindhdl(%p): bad dma type",
- ddi_driver_name(rdip), ddi_get_instance(rdip), mp);
+ ddi_driver_name(rdip), ddi_get_instance(rdip), mp);
/*NOTREACHED*/
}
DBG(DBG_DMA_BINDH, dip, "cookie %" PRIx64 "+%x\n",
- cookiep->dmac_address, cookiep->dmac_size);
+ cookiep->dmac_address, cookiep->dmac_size);
px_dump_dma_handle(DBG_DMA_MAP, dip, mp);
/* insert dma handle into FMA cache */
if (mp->dmai_attr.dma_attr_flags & DDI_DMA_FLAGERR) {
(void) ndi_fmc_insert(rdip, DMA_HANDLE, mp, NULL);
- mp->dmai_error.err_cf = impl_dma_check;
+ mp->dmai_error.err_cf = px_err_dma_hdl_check;
}
return (mp->dmai_nwin == 1 ? DDI_DMA_MAPPED : DDI_DMA_PARTIAL_MAP);
@@ -995,7 +985,7 @@ px_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle)
px_mmu_t *mmu_p = px_p->px_mmu_p;
DBG(DBG_DMA_UNBINDH, dip, "rdip=%s%d, mp=%p\n",
- ddi_driver_name(rdip), ddi_get_instance(rdip), handle);
+ ddi_driver_name(rdip), ddi_get_instance(rdip), handle);
if ((mp->dmai_flags & PX_DMAI_FLAGS_INUSE) == 0) {
DBG(DBG_DMA_UNBINDH, dip, "handle not inuse\n");
return (DDI_FAILURE);
@@ -1025,7 +1015,7 @@ px_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle)
break;
default:
cmn_err(CE_PANIC, "%s%d: px_dma_unbindhdl:bad dma type %p",
- ddi_driver_name(rdip), ddi_get_instance(rdip), mp);
+ ddi_driver_name(rdip), ddi_get_instance(rdip), mp);
/*NOTREACHED*/
}
if (mmu_p->mmu_dvma_clid != 0) {
@@ -1053,7 +1043,7 @@ px_dma_win(dev_info_t *dip, dev_info_t *rdip,
int ret;
DBG(DBG_DMA_WIN, dip, "rdip=%s%d\n",
- ddi_driver_name(rdip), ddi_get_instance(rdip));
+ ddi_driver_name(rdip), ddi_get_instance(rdip));
px_dump_dma_handle(DBG_DMA_WIN, dip, mp);
if (win >= mp->dmai_nwin) {
@@ -1076,7 +1066,7 @@ px_dma_win(dev_info_t *dip, dev_info_t *rdip,
}
if (cookiep)
MAKE_DMA_COOKIE(cookiep, mp->dmai_mapping,
- mp->dmai_size);
+ mp->dmai_size);
if (ccountp)
*ccountp = 1;
break;
@@ -1086,7 +1076,7 @@ px_dma_win(dev_info_t *dip, dev_info_t *rdip,
ddi_dma_cookie_t *ck_p;
px_dma_win_t *win_p = mp->dmai_winlst;
- for (i = 0; i < win; win_p = win_p->win_next, i++);
+ for (i = 0; i < win; win_p = win_p->win_next, i++) {};
ck_p = (ddi_dma_cookie_t *)(win_p + 1);
*cookiep = *ck_p;
mp->dmai_offset = win_p->win_offset;
@@ -1100,14 +1090,14 @@ px_dma_win(dev_info_t *dip, dev_info_t *rdip,
break;
default:
cmn_err(CE_WARN, "%s%d: px_dma_win:bad dma type 0x%x",
- ddi_driver_name(rdip), ddi_get_instance(rdip),
- PX_DMA_TYPE(mp));
+ ddi_driver_name(rdip), ddi_get_instance(rdip),
+ PX_DMA_TYPE(mp));
return (DDI_FAILURE);
}
if (cookiep)
DBG(DBG_DMA_WIN, dip,
- "cookie - dmac_address=%x dmac_size=%x\n",
- cookiep->dmac_address, cookiep->dmac_size);
+ "cookie - dmac_address=%x dmac_size=%x\n",
+ cookiep->dmac_address, cookiep->dmac_size);
if (offp)
*offp = (off_t)mp->dmai_offset;
if (lenp)
@@ -1153,7 +1143,7 @@ px_dma_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle,
#ifdef DEBUG
DBG(DBG_DMA_CTL, dip, "%s: rdip=%s%d\n", px_dmactl_str[cmd],
- ddi_driver_name(rdip), ddi_get_instance(rdip));
+ ddi_driver_name(rdip), ddi_get_instance(rdip));
#endif /* DEBUG */
switch (cmd) {
@@ -1164,7 +1154,7 @@ px_dma_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle,
case DDI_DMA_RESERVE: {
px_t *px_p = DIP_TO_STATE(dip);
return (px_fdvma_reserve(dip, rdip, px_p,
- (ddi_dma_req_t *)offp, (ddi_dma_handle_t *)objp));
+ (ddi_dma_req_t *)offp, (ddi_dma_handle_t *)objp));
}
case DDI_DMA_RELEASE: {
px_t *px_p = DIP_TO_STATE(dip);
@@ -1177,15 +1167,15 @@ px_dma_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle,
switch (PX_DMA_TYPE(mp)) {
case PX_DMAI_FLAGS_DVMA:
return (px_dvma_ctl(dip, rdip, mp, cmd, offp, lenp, objp,
- cache_flags));
+ cache_flags));
case PX_DMAI_FLAGS_PTP:
case PX_DMAI_FLAGS_BYPASS:
return (px_dma_ctl(dip, rdip, mp, cmd, offp, lenp, objp,
- cache_flags));
+ cache_flags));
default:
cmn_err(CE_PANIC, "%s%d: px_dma_ctlops(%x):bad dma type %x",
- ddi_driver_name(rdip), ddi_get_instance(rdip), cmd,
- mp->dmai_flags);
+ ddi_driver_name(rdip), ddi_get_instance(rdip), cmd,
+ mp->dmai_flags);
/*NOTREACHED*/
}
return (0);
@@ -1236,16 +1226,11 @@ px_ctlops(dev_info_t *dip, dev_info_t *rdip,
return (pcie_pm_hold(dip));
}
if (as->cmd == DDI_RESUME) {
- ddi_acc_handle_t config_handle;
DBG(DBG_PWR, dip, "PRE_RESUME for %s@%d\n",
ddi_driver_name(rdip),
ddi_get_instance(rdip));
- if (pci_config_setup(rdip, &config_handle) ==
- DDI_SUCCESS) {
- pcie_clear_errors(rdip, config_handle);
- pci_config_teardown(&config_handle);
- }
+ pcie_clear_errors(rdip);
}
return (DDI_SUCCESS);
@@ -1324,7 +1309,7 @@ px_ctlops(dev_info_t *dip, dev_info_t *rdip,
* Now pass the request up to our parent.
*/
DBG(DBG_CTLOPS, dip, "passing request to parent: rdip=%s%d\n",
- ddi_driver_name(rdip), ddi_get_instance(rdip));
+ ddi_driver_name(rdip), ddi_get_instance(rdip));
return (ddi_ctlops(dip, rdip, op, arg, result));
}
diff --git a/usr/src/uts/sun4/io/px/px_fm.c b/usr/src/uts/sun4/io/px/px_fm.c
index 727d0351a6..65c1d78d29 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 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -33,6 +33,7 @@
#include <sys/sunddi.h>
#include <sys/fm/protocol.h>
#include <sys/fm/util.h>
+#include <sys/fm/io/pci.h>
#include <sys/membar.h>
#include "px_obj.h"
@@ -43,26 +44,35 @@
(PCIE_AER_UCE_TRAINING | PCIE_AER_UCE_SD | PCIE_AER_UCE_CA | \
PCIE_AER_UCE_UC | PCIE_AER_UCE_UR)
-static void px_err_fill_pfd(dev_info_t *rpdip, px_err_pcie_t *regs);
+/*
+ * Global panicing state variabled used to control if further error handling
+ * should occur. If the system is already panic'ing or if PX itself has
+ * recommended panic'ing the system, no further error handling should occur to
+ * prevent the system from hanging.
+ */
+boolean_t px_panicing = B_FALSE;
+
+static pf_data_t *px_get_pfd(px_t *px_p);
+
static int px_pcie_ptlp(dev_info_t *dip, ddi_fm_error_t *derr,
px_err_pcie_t *regs);
#if defined(DEBUG)
-static void px_pcie_log(dev_info_t *dip, px_err_pcie_t *regs, int severity);
+static void px_pcie_log(dev_info_t *dip, px_err_pcie_t *regs);
#else /* DEBUG */
#define px_pcie_log 0 &&
#endif /* DEBUG */
-/* external functions */
-extern int pci_xcap_locate(ddi_acc_handle_t h, uint16_t id, uint16_t *base_p);
-extern int pci_lcap_locate(ddi_acc_handle_t h, uint8_t id, uint16_t *base_p);
-
/*
* Initialize px FMA support
*/
int
px_fm_attach(px_t *px_p)
{
+ int i;
+ dev_info_t *dip = px_p->px_dip;
+ pcie_bus_t *bus_p;
+
px_p->px_fm_cap = DDI_FM_EREPORT_CAPABLE | DDI_FM_ERRCB_CAPABLE |
DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE;
@@ -75,7 +85,7 @@ px_fm_attach(px_t *px_p)
/*
* check parents' capability
*/
- ddi_fm_init(px_p->px_dip, &px_p->px_fm_cap, &px_p->px_fm_ibc);
+ ddi_fm_init(dip, &px_p->px_fm_cap, &px_p->px_fm_ibc);
/*
* parents need to be ereport and error handling capable
@@ -89,10 +99,22 @@ px_fm_attach(px_t *px_p)
mutex_init(&px_p->px_fm_mutex, NULL, MUTEX_DRIVER,
(void *)px_p->px_fm_ibc);
+
+ pcie_rc_init_bus(dip);
+
+ px_p->px_pfd_idx = 0;
+ for (i = 0; i < 5; i++)
+ pcie_rc_init_pfd(dip, &px_p->px_pfd_arr[i]);
+ PCIE_DIP2PFD(dip) = px_p->px_pfd_arr;
+
+ bus_p = PCIE_DIP2BUS(dip);
+ bus_p->bus_rp_bdf = px_p->px_bdf;
+ bus_p->bus_rp_dip = dip;
+
/*
* register error callback in parent
*/
- ddi_fm_handler_register(px_p->px_dip, px_fm_callback, px_p);
+ ddi_fm_handler_register(dip, px_fm_callback, px_p);
return (DDI_SUCCESS);
}
@@ -103,9 +125,14 @@ px_fm_attach(px_t *px_p)
void
px_fm_detach(px_t *px_p)
{
+ int i;
+
ddi_fm_handler_unregister(px_p->px_dip);
mutex_destroy(&px_p->px_fm_mutex);
ddi_fm_fini(px_p->px_dip);
+ for (i = 0; i < 5; i++)
+ pcie_rc_fini_pfd(&px_p->px_pfd_arr[i]);
+ pcie_rc_fini_bus(px_p->px_dip);
}
/*
@@ -113,9 +140,10 @@ px_fm_detach(px_t *px_p)
* protection.
*/
void
-px_fm_acc_setup(ddi_map_req_t *mp, dev_info_t *rdip)
+px_fm_acc_setup(ddi_map_req_t *mp, dev_info_t *rdip, pci_regspec_t *rp)
{
uchar_t fflag;
+ ndi_err_t *errp;
ddi_acc_hdl_t *hp;
ddi_acc_impl_t *ap;
@@ -143,6 +171,13 @@ px_fm_acc_setup(ddi_map_req_t *mp, dev_info_t *rdip)
ap->ahi_rep_put16 = i_ddi_prot_rep_put16;
ap->ahi_rep_put32 = i_ddi_prot_rep_put32;
ap->ahi_rep_put64 = i_ddi_prot_rep_put64;
+ impl_acc_err_init(hp);
+ errp = ((ddi_acc_impl_t *)hp)->ahi_err;
+ if ((rp->pci_phys_hi & PCI_REG_ADDR_M) ==
+ PCI_ADDR_CONFIG)
+ errp->err_cf = px_err_cfg_hdl_check;
+ else
+ errp->err_cf = px_err_pio_hdl_check;
break;
case DDI_CAUTIOUS_ACC :
ap->ahi_get8 = i_ddi_caut_get8;
@@ -161,6 +196,13 @@ px_fm_acc_setup(ddi_map_req_t *mp, dev_info_t *rdip)
ap->ahi_rep_put16 = i_ddi_caut_rep_put16;
ap->ahi_rep_put32 = i_ddi_caut_rep_put32;
ap->ahi_rep_put64 = i_ddi_caut_rep_put64;
+ impl_acc_err_init(hp);
+ errp = ((ddi_acc_impl_t *)hp)->ahi_err;
+ if ((rp->pci_phys_hi & PCI_REG_ADDR_M) ==
+ PCI_ADDR_CONFIG)
+ errp->err_cf = px_err_cfg_hdl_check;
+ else
+ errp->err_cf = px_err_pio_hdl_check;
break;
default:
break;
@@ -221,6 +263,24 @@ px_bus_exit(dev_info_t *dip, ddi_acc_handle_t handle)
mutex_exit(&pec_p->pec_pokefault_mutex);
}
+static uint64_t
+px_in_addr_range(dev_info_t *dip, px_ranges_t *ranges_p, uint64_t addr)
+{
+ uint64_t addr_low, addr_high;
+
+ addr_low = ((uint64_t)ranges_p->parent_high << 32) |
+ (uint64_t)ranges_p->parent_low;
+ addr_high = addr_low + ((uint64_t)ranges_p->size_high << 32) +
+ (uint64_t)ranges_p->size_low;
+
+ DBG(DBG_ERR_INTR, dip, "Addr: 0x%llx high: 0x%llx low: 0x%llx\n",
+ addr, addr_high, addr_low);
+
+ if ((addr < addr_high) && (addr >= addr_low))
+ return (addr_low);
+
+ return (0);
+}
/*
* PCI error callback which is registered with our parent to call
@@ -234,8 +294,9 @@ px_fm_callback(dev_info_t *dip, ddi_fm_error_t *derr, const void *impl_data)
dev_info_t *pdip = ddi_get_parent(dip);
px_t *px_p = (px_t *)impl_data;
int i, acc_type = 0;
- int lookup, rc_err, fab_err = PF_NO_PANIC;
- uint32_t addr, addr_high, addr_low;
+ 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;
px_ranges_t *ranges_p;
int range_len;
@@ -250,11 +311,10 @@ px_fm_callback(dev_info_t *dip, ddi_fm_error_t *derr, const void *impl_data)
return (DDI_FM_FATAL);
i_ddi_fm_handler_exit(pdip);
- mutex_enter(&px_p->px_fm_mutex);
- px_p->px_fm_mutex_owner = curthread;
-
- addr_high = (uint32_t)((uint64_t)derr->fme_bus_specific >> 32);
- addr_low = (uint32_t)((uint64_t)derr->fme_bus_specific);
+ if (px_fm_enter(px_p) != DDI_SUCCESS) {
+ i_ddi_fm_handler_enter(pdip);
+ return (DDI_FM_FATAL);
+ }
/*
* Make sure this failed load came from this PCIe port. Check by
@@ -263,21 +323,20 @@ px_fm_callback(dev_info_t *dip, ddi_fm_error_t *derr, const void *impl_data)
range_len = px_p->px_ranges_length / sizeof (px_ranges_t);
i = 0;
for (ranges_p = px_p->px_ranges_p; i < range_len; i++, ranges_p++) {
- if (ranges_p->parent_high == addr_high) {
+ base_addr = px_in_addr_range(dip, ranges_p, fault_addr);
+ if (base_addr) {
switch (ranges_p->child_high & PCI_ADDR_MASK) {
case PCI_ADDR_CONFIG:
- acc_type = PF_CFG_ADDR;
+ acc_type = PF_ADDR_CFG;
addr = NULL;
- bdf = (pcie_req_id_t)(addr_low >> 12);
+ bdf = (pcie_req_id_t)((fault_addr >> 12) &
+ 0xFFFF);
break;
case PCI_ADDR_IO:
- acc_type = PF_IO_ADDR;
- addr = addr_low;
- bdf = NULL;
- break;
+ case PCI_ADDR_MEM64:
case PCI_ADDR_MEM32:
- acc_type = PF_DMA_ADDR;
- addr = addr_low;
+ acc_type = PF_ADDR_PIO;
+ addr = fault_addr - base_addr;
bdf = NULL;
break;
}
@@ -287,39 +346,31 @@ px_fm_callback(dev_info_t *dip, ddi_fm_error_t *derr, const void *impl_data)
/* This address doesn't belong to this leaf, just return with OK */
if (!acc_type) {
- px_p->px_fm_mutex_owner = NULL;
- mutex_exit(&px_p->px_fm_mutex);
+ px_fm_exit(px_p);
i_ddi_fm_handler_enter(pdip);
return (DDI_FM_OK);
- } else if (acc_type == PF_IO_ADDR) {
- px_p->px_fm_mutex_owner = NULL;
- mutex_exit(&px_p->px_fm_mutex);
- i_ddi_fm_handler_enter(pdip);
- return (DDI_FM_FATAL);
}
rc_err = px_err_cmn_intr(px_p, derr, PX_TRAP_CALL, PX_FM_BLOCK_ALL);
- lookup = pf_hdl_lookup(dip, derr->fme_ena, acc_type, addr, bdf);
+ lookup = pf_hdl_lookup(dip, derr->fme_ena, acc_type, (uint64_t)addr,
+ bdf);
- if (!px_lib_is_in_drain_state(px_p)) {
- /*
- * This is to ensure that device corresponding to the addr of
- * the failed PIO/CFG load gets scanned.
- */
- px_rp_en_q(px_p, bdf, addr,
- (PCI_STAT_R_MAST_AB | PCI_STAT_R_TARG_AB));
- fab_err = pf_scan_fabric(dip, derr, px_p->px_dq_p,
- &px_p->px_dq_tail);
- }
+ px_rp_en_q(px_p, bdf, addr,
+ (PCI_STAT_R_MAST_AB | PCI_STAT_R_TARG_AB));
- px_p->px_fm_mutex_owner = NULL;
- mutex_exit(&px_p->px_fm_mutex);
+ fab_err = px_scan_fabric(px_p, dip, derr);
+
+ px_fm_exit(px_p);
i_ddi_fm_handler_enter(pdip);
- if ((rc_err & (PX_PANIC | PX_PROTECTED)) || (fab_err & PF_PANIC) ||
+ if (!px_die)
+ return (DDI_FM_OK);
+
+ if ((rc_err & (PX_PANIC | PX_PROTECTED)) ||
+ (fab_err & PF_ERR_FATAL_FLAGS) ||
(lookup == PF_HDL_NOTFOUND))
return (DDI_FM_FATAL);
- else if ((rc_err == PX_NO_ERROR) && (fab_err == PF_NO_ERROR))
+ else if ((rc_err == PX_NO_ERROR) && (fab_err == PF_ERR_NO_ERROR))
return (DDI_FM_OK);
return (DDI_FM_NONFATAL);
@@ -341,11 +392,13 @@ uint_t
px_err_fabric_intr(px_t *px_p, msgcode_t msg_code, pcie_req_id_t rid)
{
dev_info_t *rpdip = px_p->px_dip;
- int rc_err, fab_err = PF_NO_PANIC;
+ int rc_err, fab_err;
ddi_fm_error_t derr;
+ uint32_t rp_status;
+ uint16_t ce_source, ue_source;
- mutex_enter(&px_p->px_fm_mutex);
- px_p->px_fm_mutex_owner = curthread;
+ if (px_fm_enter(px_p) != DDI_SUCCESS)
+ goto done;
/* Create the derr */
bzero(&derr, sizeof (ddi_fm_error_t));
@@ -353,26 +406,72 @@ px_err_fabric_intr(px_t *px_p, msgcode_t msg_code, pcie_req_id_t rid)
derr.fme_ena = fm_ena_generate(0, FM_ENA_FMT1);
derr.fme_flag = DDI_FM_ERR_UNEXPECTED;
+ px_err_safeacc_check(px_p, &derr);
+
+ if (msg_code == PCIE_MSG_CODE_ERR_COR) {
+ rp_status = PCIE_AER_RE_STS_CE_RCVD;
+ ce_source = rid;
+ ue_source = 0;
+ } else {
+ rp_status = PCIE_AER_RE_STS_FE_NFE_RCVD;
+ ce_source = 0;
+ ue_source = rid;
+ if (msg_code == PCIE_MSG_CODE_ERR_NONFATAL)
+ rp_status |= PCIE_AER_RE_STS_NFE_MSGS_RCVD;
+ else {
+ rp_status |= PCIE_AER_RE_STS_FE_MSGS_RCVD;
+ rp_status |= PCIE_AER_RE_STS_FIRST_UC_FATAL;
+ }
+ }
+
+ if (derr.fme_flag == DDI_FM_ERR_UNEXPECTED) {
+ ddi_fm_ereport_post(rpdip, PCI_ERROR_SUBCLASS "." PCIEX_FABRIC,
+ derr.fme_ena,
+ DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
+ FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
+ "pcie_adv_rp_status", DATA_TYPE_UINT32, rp_status,
+ "pcie_adv_rp_command", DATA_TYPE_UINT32, 0,
+ "pcie_adv_rp_ce_src_id", DATA_TYPE_UINT16, ce_source,
+ "pcie_adv_rp_ue_src_id", DATA_TYPE_UINT16, ue_source,
+ NULL);
+ }
+
/* Ensure that the rid of the fabric message will get scanned. */
px_rp_en_q(px_p, rid, NULL, NULL);
rc_err = px_err_cmn_intr(px_p, &derr, PX_INTR_CALL, PX_FM_BLOCK_PCIE);
/* call rootport dispatch */
- if (!px_lib_is_in_drain_state(px_p)) {
- fab_err = pf_scan_fabric(rpdip, &derr, px_p->px_dq_p,
- &px_p->px_dq_tail);
- }
-
- px_p->px_fm_mutex_owner = NULL;
- mutex_exit(&px_p->px_fm_mutex);
+ fab_err = px_scan_fabric(px_p, rpdip, &derr);
- px_err_panic(rc_err, PX_RC, fab_err);
+ px_err_panic(rc_err, PX_RC, fab_err, B_TRUE);
+ px_fm_exit(px_p);
+ px_err_panic(rc_err, PX_RC, fab_err, B_FALSE);
+done:
return (DDI_INTR_CLAIMED);
}
/*
+ * px_scan_fabric:
+ *
+ * Check for drain state and if there is anything to scan.
+ */
+int
+px_scan_fabric(px_t *px_p, dev_info_t *rpdip, ddi_fm_error_t *derr) {
+ int fab_err = 0;
+
+ ASSERT(MUTEX_HELD(&px_p->px_fm_mutex));
+
+ if (!px_lib_is_in_drain_state(px_p) && px_p->px_pfd_idx) {
+ fab_err = pf_scan_fabric(rpdip, derr, px_p->px_pfd_arr);
+ px_p->px_pfd_idx = 0;
+ }
+
+ return (fab_err);
+}
+
+/*
* px_err_safeacc_check:
* Check to see if a peek/poke and cautious access is currently being
* done on a particular leaf.
@@ -456,103 +555,79 @@ px_err_check_eq(dev_info_t *dip)
return (PX_NO_PANIC);
}
-static void
-px_err_fill_pfd(dev_info_t *rpdip, px_err_pcie_t *regs)
+/* ARGSUSED */
+int
+px_err_check_pcie(dev_info_t *dip, ddi_fm_error_t *derr, px_err_pcie_t *regs)
{
- px_t *px_p = DIP_TO_STATE(rpdip);
- pf_data_t pf_data = {0};
- pcie_req_id_t fault_bdf = 0;
- uint32_t fault_addr = 0;
- uint16_t s_status = 0;
-
- pf_data.rp_bdf = px_p->px_bdf;
+ px_t *px_p = DIP_TO_STATE(dip);
+ pf_data_t *pfd_p = px_get_pfd(px_p);
+ int i;
+ pf_pcie_adv_err_regs_t *adv_reg = PCIE_ADV_REG(pfd_p);
/*
* set RC s_status in PCI term to coordinate with downstream fabric
* errors ananlysis.
*/
if (regs->primary_ue & PCIE_AER_UCE_UR)
- s_status = PCI_STAT_R_MAST_AB;
+ PCI_BDG_ERR_REG(pfd_p)->pci_bdg_sec_stat = PCI_STAT_R_MAST_AB;
if (regs->primary_ue & PCIE_AER_UCE_CA)
- s_status = PCI_STAT_R_TARG_AB;
+ PCI_BDG_ERR_REG(pfd_p)->pci_bdg_sec_stat = PCI_STAT_R_TARG_AB;
if (regs->primary_ue & (PCIE_AER_UCE_PTLP | PCIE_AER_UCE_ECRC))
- s_status = PCI_STAT_PERROR;
-
- if (regs->primary_ue & (PCIE_AER_UCE_UR | PCIE_AER_UCE_CA)) {
- pf_data.aer_h0 = regs->rx_hdr1;
- pf_data.aer_h1 = regs->rx_hdr2;
- pf_data.aer_h2 = regs->rx_hdr3;
- pf_data.aer_h3 = regs->rx_hdr4;
-
- pf_tlp_decode(rpdip, &pf_data, &fault_bdf, NULL, NULL);
- } else if (regs->primary_ue & PCIE_AER_UCE_PTLP) {
- pcie_tlp_hdr_t *tlp_p;
-
- pf_data.aer_h0 = regs->rx_hdr1;
- pf_data.aer_h1 = regs->rx_hdr2;
- pf_data.aer_h2 = regs->rx_hdr3;
- pf_data.aer_h3 = regs->rx_hdr4;
-
- tlp_p = (pcie_tlp_hdr_t *)&pf_data.aer_h0;
- if (tlp_p->type == PCIE_TLP_TYPE_CPL)
- pf_tlp_decode(rpdip, &pf_data, &fault_bdf, NULL, NULL);
-
- pf_data.aer_h0 = regs->tx_hdr1;
- pf_data.aer_h1 = regs->tx_hdr2;
- pf_data.aer_h2 = regs->tx_hdr3;
- pf_data.aer_h3 = regs->tx_hdr4;
-
- pf_tlp_decode(rpdip, &pf_data, NULL, &fault_addr, NULL);
- }
+ PCI_BDG_ERR_REG(pfd_p)->pci_bdg_sec_stat = PCI_STAT_PERROR;
- px_rp_en_q(px_p, fault_bdf, fault_addr, s_status);
-}
-
-int
-px_err_check_pcie(dev_info_t *dip, ddi_fm_error_t *derr, px_err_pcie_t *regs)
-{
- uint32_t ce_reg, ue_reg;
- int err = PX_NO_ERROR;
-
- ce_reg = regs->ce_reg;
- if (ce_reg)
- err |= (ce_reg & px_fabric_die_rc_ce) ? PX_PANIC : PX_NO_ERROR;
-
- ue_reg = regs->ue_reg;
- if (!ue_reg)
+ if (!regs->primary_ue)
goto done;
- if (ue_reg & PCIE_AER_UCE_PTLP)
- err |= px_pcie_ptlp(dip, derr, regs);
+ adv_reg->pcie_ce_status = regs->ce_reg;
+ adv_reg->pcie_ue_status = regs->ue_reg | regs->primary_ue;
+ PCIE_ADV_HDR(pfd_p, 0) = regs->rx_hdr1;
+ PCIE_ADV_HDR(pfd_p, 1) = regs->rx_hdr2;
+ PCIE_ADV_HDR(pfd_p, 2) = regs->rx_hdr3;
+ PCIE_ADV_HDR(pfd_p, 3) = regs->rx_hdr4;
+ for (i = regs->primary_ue; i != 1; i = i >> 1)
+ adv_reg->pcie_adv_ctl++;
- if (ue_reg & PX_PCIE_PANIC_BITS)
- err |= PX_PANIC;
+ 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 =
+ 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 =
+ adv_reg->pcie_ue_tgt_bdf;
+ if (adv_reg->pcie_ue_tgt_trans ==
+ PF_ADDR_PIO)
+ PCIE_ROOT_FAULT(pfd_p)->fault_addr =
+ adv_reg->pcie_ue_tgt_addr;
+ }
- if (ue_reg & PX_PCIE_NO_PANIC_BITS)
- err |= PX_NO_PANIC;
+ /*
+ * Normally for Poisoned Completion TLPs we can look at the
+ * transmit log header for the original request and the original
+ * address, however this doesn't seem to be working. HW BUG.
+ */
+ }
- /* Scan the fabric to clean up error bits, for the following errors. */
- if (ue_reg & (PCIE_AER_UCE_PTLP | PCIE_AER_UCE_CA | PCIE_AER_UCE_UR))
- px_err_fill_pfd(dip, regs);
done:
- px_pcie_log(dip, regs, err);
- return (err);
+ px_pcie_log(dip, regs);
+
+ /* Return No Error here and let the pcie misc module analyse it */
+ return (PX_NO_ERROR);
}
#if defined(DEBUG)
static void
-px_pcie_log(dev_info_t *dip, px_err_pcie_t *regs, int severity)
+px_pcie_log(dev_info_t *dip, px_err_pcie_t *regs)
{
DBG(DBG_ERR_INTR, dip,
- "A PCIe RC error has occured with a severity of \"%s\"\n"
+ "A PCIe RC error has occured\n"
"\tCE: 0x%x UE: 0x%x Primary UE: 0x%x\n"
"\tTX Hdr: 0x%x 0x%x 0x%x 0x%x\n\tRX Hdr: 0x%x 0x%x 0x%x 0x%x\n",
- (severity & PX_PANIC) ? "PANIC" : "NO PANIC", regs->ce_reg,
- regs->ue_reg, regs->primary_ue, regs->tx_hdr1, regs->tx_hdr2,
- regs->tx_hdr3, regs->tx_hdr4, regs->rx_hdr1, regs->rx_hdr2,
- regs->rx_hdr3, regs->rx_hdr4);
+ regs->ce_reg, regs->ue_reg, regs->primary_ue,
+ regs->tx_hdr1, regs->tx_hdr2, regs->tx_hdr3, regs->tx_hdr4,
+ regs->rx_hdr1, regs->rx_hdr2, regs->rx_hdr3, regs->rx_hdr4);
}
-#endif /* DEBUG */
+#endif
/*
* look through poisoned TLP cases and suggest panic/no panic depend on
@@ -561,12 +636,12 @@ px_pcie_log(dev_info_t *dip, px_err_pcie_t *regs, int severity)
static int
px_pcie_ptlp(dev_info_t *dip, ddi_fm_error_t *derr, px_err_pcie_t *regs)
{
- px_t *px_p = DIP_TO_STATE(dip);
- pf_data_t pf_data;
+ pf_pcie_adv_err_regs_t adv_reg;
pcie_req_id_t bdf;
- uint32_t addr, trans_type;
+ uint64_t addr;
+ uint32_t trans_type;
int tlp_sts, tlp_cmd;
- int sts = PF_HDL_NOTFOUND;
+ int lookup = PF_HDL_NOTFOUND;
if (regs->primary_ue != PCIE_AER_UCE_PTLP)
return (PX_PANIC);
@@ -574,18 +649,21 @@ px_pcie_ptlp(dev_info_t *dip, ddi_fm_error_t *derr, px_err_pcie_t *regs)
if (!regs->rx_hdr1)
goto done;
- pf_data.rp_bdf = px_p->px_bdf;
- pf_data.aer_h0 = regs->rx_hdr1;
- pf_data.aer_h1 = regs->rx_hdr2;
- pf_data.aer_h2 = regs->rx_hdr3;
- pf_data.aer_h3 = regs->rx_hdr4;
+ adv_reg.pcie_ue_hdr[0] = regs->rx_hdr1;
+ adv_reg.pcie_ue_hdr[1] = regs->rx_hdr2;
+ adv_reg.pcie_ue_hdr[2] = regs->rx_hdr3;
+ adv_reg.pcie_ue_hdr[3] = regs->rx_hdr4;
- tlp_sts = pf_tlp_decode(dip, &pf_data, &bdf, &addr, &trans_type);
- tlp_cmd = ((pcie_tlp_hdr_t *)(&pf_data.aer_h0))->type;
+ tlp_sts = pf_tlp_decode(PCIE_DIP2BUS(dip), &adv_reg);
+ tlp_cmd = ((pcie_tlp_hdr_t *)(adv_reg.pcie_ue_hdr))->type;
if (tlp_sts == DDI_FAILURE)
goto done;
+ bdf = adv_reg.pcie_ue_tgt_bdf;
+ addr = adv_reg.pcie_ue_tgt_addr;
+ trans_type = adv_reg.pcie_ue_tgt_trans;
+
switch (tlp_cmd) {
case PCIE_TLP_TYPE_CPL:
case PCIE_TLP_TYPE_CPLLK:
@@ -594,24 +672,58 @@ px_pcie_ptlp(dev_info_t *dip, ddi_fm_error_t *derr, px_err_pcie_t *regs)
* from the RX TLP, and the original address from the TX TLP.
*/
if (regs->tx_hdr1) {
- pf_data.aer_h0 = regs->tx_hdr1;
- pf_data.aer_h1 = regs->tx_hdr2;
- pf_data.aer_h2 = regs->tx_hdr3;
- pf_data.aer_h3 = regs->tx_hdr4;
+ adv_reg.pcie_ue_hdr[0] = regs->tx_hdr1;
+ adv_reg.pcie_ue_hdr[1] = regs->tx_hdr2;
+ adv_reg.pcie_ue_hdr[2] = regs->tx_hdr3;
+ adv_reg.pcie_ue_hdr[3] = regs->tx_hdr4;
- sts = pf_tlp_decode(dip, &pf_data, NULL, &addr,
- &trans_type);
+ lookup = pf_tlp_decode(PCIE_DIP2BUS(dip), &adv_reg);
+ if (lookup != DDI_SUCCESS)
+ break;
+ addr = adv_reg.pcie_ue_tgt_addr;
+ trans_type = adv_reg.pcie_ue_tgt_trans;
} /* FALLTHRU */
case PCIE_TLP_TYPE_IO:
case PCIE_TLP_TYPE_MEM:
case PCIE_TLP_TYPE_MEMLK:
- sts = pf_hdl_lookup(dip, derr->fme_ena, trans_type, addr, bdf);
+ lookup = pf_hdl_lookup(dip, derr->fme_ena, trans_type, addr,
+ bdf);
break;
default:
- sts = PF_HDL_NOTFOUND;
+ lookup = PF_HDL_NOTFOUND;
}
done:
- return (sts == PF_HDL_NOTFOUND ? PX_PANIC : PX_NO_PANIC);
+ return (lookup == PF_HDL_FOUND ? PX_NO_PANIC : PX_PANIC);
+}
+
+/*
+ * px_get_pdf automatically allocates a RC pf_data_t and returns a pointer to
+ * it. This function should be used when an error requires a fabric scan.
+ */
+static pf_data_t *
+px_get_pfd(px_t *px_p) {
+ int idx = px_p->px_pfd_idx++;
+ 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;
+ 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;
+
+ pfd_p->pe_next = NULL;
+
+ if (idx > 0) {
+ px_p->px_pfd_arr[idx - 1].pe_next = pfd_p;
+ pfd_p->pe_prev = &px_p->px_pfd_arr[idx - 1];
+ } else {
+ pfd_p->pe_prev = NULL;
+ }
+
+ pfd_p->pe_valid = B_TRUE;
+
+ return (pfd_p);
}
/*
@@ -627,47 +739,208 @@ done:
* (ie S-TA/MA, R-TA)
* Either the fault bdf or addr may be NULL, but not both.
*/
-int px_foo = 0;
void
px_rp_en_q(px_t *px_p, pcie_req_id_t fault_bdf, uint32_t fault_addr,
uint16_t s_status)
{
- pf_data_t pf_data = {0};
+ pf_data_t *pfd_p;
if (!fault_bdf && !fault_addr)
return;
- pf_data.dev_type = PCIE_PCIECAP_DEV_TYPE_ROOT;
- if (px_foo) {
- pf_data.fault_bdf = px_foo;
- px_foo = 0;
- } else
- pf_data.fault_bdf = fault_bdf;
+ 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;
+ PCI_BDG_ERR_REG(pfd_p)->pci_bdg_sec_stat = s_status;
+}
+
+
+/*
+ * Find and Mark CFG Handles as failed associated with the given BDF. We should
+ * always know the BDF for CFG accesses, since it is encoded in the address of
+ * the TLP. Since there can be multiple cfg handles, mark them all as failed.
+ */
+/* ARGSUSED */
+int
+px_err_cfg_hdl_check(dev_info_t *dip, const void *handle, const void *arg1,
+ const void *arg2)
+{
+ int status = DDI_FM_FATAL;
+ uint32_t addr = *(uint32_t *)arg1;
+ uint16_t bdf = *(uint16_t *)arg2;
+ pcie_bus_t *bus_p;
+
+ DBG(DBG_ERR_INTR, dip, "Check CFG Hdl: dip 0x%p addr 0x%x bdf=0x%x\n",
+ dip, addr, bdf);
- pf_data.bdf = px_p->px_bdf;
- pf_data.rp_bdf = px_p->px_bdf;
- pf_data.fault_addr = fault_addr;
- pf_data.s_status = s_status;
- pf_data.send_erpt = PF_SEND_ERPT_NO;
+ bus_p = PCIE_DIP2BUS(dip);
- (void) pf_en_dq(&pf_data, px_p->px_dq_p, &px_p->px_dq_tail, -1);
+ /*
+ * Because CFG and IO Acc Handlers are on the same cache list and both
+ * types of hdls gets called for both types of errors. For this checker
+ * 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;
+
+ return (status);
+}
+
+/*
+ * Find and Mark all ACC Handles associated with a give address and BDF as
+ * failed. If the BDF != NULL, then check to see if the device has a ACC Handle
+ * associated with ADDR. If the handle is not found, mark all the handles as
+ * failed. If the BDF == NULL, mark the handle as failed if it is associated
+ * with ADDR.
+ */
+int
+px_err_pio_hdl_check(dev_info_t *dip, const void *handle, const void *arg1,
+ const void *arg2)
+{
+ dev_info_t *px_dip = PCIE_DIP2BUS(dip)->bus_rp_dip;
+ px_t *px_p = INST_TO_STATE(ddi_get_instance(px_dip));
+ px_ranges_t *ranges_p;
+ int range_len;
+ ddi_acc_handle_t ap = (ddi_acc_handle_t)handle;
+ ddi_acc_hdl_t *hp = impl_acc_hdl_get(ap);
+ int i, status = DDI_FM_FATAL;
+ uint64_t fault_addr = *(uint64_t *)arg1;
+ uint16_t bdf = *(uint16_t *)arg2;
+ uint64_t base_addr, range_addr;
+ uint_t size;
+
+ DBG(DBG_ERR_INTR, dip, "Check PIO Hdl: dip 0x%x addr 0x%x bdf=0x%x\n",
+ dip, fault_addr, bdf);
+
+ /* Normalize the base addr to the addr and strip off the HB info. */
+ base_addr = (hp->ah_pfn << MMU_PAGESHIFT) + hp->ah_offset;
+ range_len = px_p->px_ranges_length / sizeof (px_ranges_t);
+ i = 0;
+ for (ranges_p = px_p->px_ranges_p; i < range_len; i++, ranges_p++) {
+ range_addr = px_in_addr_range(dip, ranges_p, base_addr);
+ if (range_addr) {
+ switch (ranges_p->child_high & PCI_ADDR_MASK) {
+ case PCI_ADDR_IO:
+ case PCI_ADDR_MEM64:
+ case PCI_ADDR_MEM32:
+ base_addr = base_addr - range_addr;
+ break;
+ }
+ break;
+ }
+ }
+
+ /*
+ * Mark the handle as failed if the ADDR is mapped, or if we
+ * know the BDF and ADDR == 0.
+ */
+ size = hp->ah_len;
+ if (((fault_addr >= base_addr) && (fault_addr < (base_addr + size))) ||
+ ((fault_addr == NULL) && (bdf == PCIE_DIP2BUS(dip)->bus_bdf)))
+ status = DDI_FM_NONFATAL;
+
+ return (status);
+}
+
+/*
+ * Find and Mark all DNA Handles associated with a give address and BDF as
+ * failed. If the BDF != NULL, then check to see if the device has a DMA Handle
+ * associated with ADDR. If the handle is not found, mark all the handles as
+ * failed. If the BDF == NULL, mark the handle as failed if it is associated
+ * with ADDR.
+ */
+int
+px_err_dma_hdl_check(dev_info_t *dip, const void *handle, const void *arg1,
+ const void *arg2)
+{
+ ddi_dma_impl_t *pcie_dp;
+ int status = DDI_FM_FATAL;
+ uint32_t addr = *(uint32_t *)arg1;
+ uint16_t bdf = *(uint16_t *)arg2;
+ uint32_t base_addr;
+ uint_t size;
+
+ DBG(DBG_ERR_INTR, dip, "Check PIO Hdl: dip 0x%x addr 0x%x bdf=0x%x\n",
+ dip, addr, bdf);
+
+ pcie_dp = (ddi_dma_impl_t *)handle;
+ base_addr = (uint32_t)pcie_dp->dmai_mapping;
+ size = pcie_dp->dmai_size;
+
+ /*
+ * Mark the handle as failed if the ADDR is mapped, or if we
+ * know the BDF and ADDR == 0.
+ */
+ if (((addr >= base_addr) && (addr < (base_addr + size))) ||
+ ((addr == NULL) && (bdf != NULL)))
+ status = DDI_FM_NONFATAL;
+
+ return (status);
+}
+
+int
+px_fm_enter(px_t *px_p) {
+ if (px_panicing || (px_p->px_fm_mutex_owner == curthread))
+ return (DDI_FAILURE);
+
+ mutex_enter(&px_p->px_fm_mutex);
+ /*
+ * In rare cases when trap occurs and in the middle of scanning the
+ * fabric, a PIO will fail in the scan fabric. The CPU error handling
+ * code will correctly panic the system, while a mondo for the failed
+ * PIO may also show up. Normally the mondo will try to grab the mutex
+ * and wait until the callback finishes. But in this rare case,
+ * mutex_enter actually suceeds also continues to scan the fabric.
+ *
+ * This code below is designed specifically to check for this case. If
+ * we successfully grab the px_fm_mutex, the px_fm_mutex_owner better be
+ * NULL. If it isn't that means we are in the rare corner case. Return
+ * DDI_FAILURE, this should prevent PX from doing anymore error
+ * handling.
+ */
+ if (px_p->px_fm_mutex_owner) {
+ return (DDI_FAILURE);
+ }
+
+ px_p->px_fm_mutex_owner = curthread;
+
+ if (px_panicing) {
+ px_fm_exit(px_p);
+ return (DDI_FAILURE);
+ }
+ return (DDI_SUCCESS);
+}
+
+void
+px_fm_exit(px_t *px_p) {
+ px_p->px_fm_mutex_owner = NULL;
+ mutex_exit(&px_p->px_fm_mutex);
}
/*
* Panic if the err tunable is set and that we are not already in the middle
* of panic'ing.
+ *
+ * rc_err = Error severity of PX specific errors
+ * msg = Where the error was detected
+ * fabric_err = Error severity of PCIe Fabric errors
+ * isTest = Test if error severity causes panic
*/
#define MSZ (sizeof (fm_msg) -strlen(fm_msg) - 1)
void
-px_err_panic(int err, int msg, int fab_err)
+px_err_panic(int rc_err, int msg, int fabric_err, boolean_t isTest)
{
char fm_msg[96] = "";
int ferr = PX_NO_ERROR;
- if (panicstr)
+ if (panicstr) {
+ px_panicing = B_TRUE;
return;
+ }
- if (!(err & px_die))
+ if (!(rc_err & px_die))
goto fabric;
if (msg & PX_RC)
(void) strncat(fm_msg, px_panic_rc_msg, MSZ);
@@ -677,17 +950,22 @@ px_err_panic(int err, int msg, int fab_err)
(void) strncat(fm_msg, px_panic_hb_msg, MSZ);
fabric:
- if (fab_err & PF_PANIC)
+ if (fabric_err & PF_ERR_FATAL_FLAGS)
ferr = PX_PANIC;
- else if (fab_err & ~(PF_PANIC | PF_NO_ERROR))
+ else if (fabric_err & ~(PF_ERR_FATAL_FLAGS | PF_ERR_NO_ERROR))
ferr = PX_NO_PANIC;
if (ferr & px_die) {
- if (strlen(fm_msg))
+ if (strlen(fm_msg)) {
(void) strncat(fm_msg, " and", MSZ);
+ }
(void) strncat(fm_msg, px_panic_fab_msg, MSZ);
}
- if (strlen(fm_msg))
- fm_panic("Fatal error has occured in:%s.", fm_msg);
+ if (strlen(fm_msg)) {
+ px_panicing = B_TRUE;
+ if (!isTest)
+ fm_panic("Fatal error has occured in:%s.(0x%x)(0x%x)",
+ fm_msg, rc_err, fabric_err);
+ }
}
diff --git a/usr/src/uts/sun4/io/px/px_fm.h b/usr/src/uts/sun4/io/px/px_fm.h
index df98ee552a..e1b40d3582 100644
--- a/usr/src/uts/sun4/io/px/px_fm.h
+++ b/usr/src/uts/sun4/io/px/px_fm.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -103,7 +103,7 @@ extern int px_fm_attach(px_t *px_p);
extern void px_fm_detach(px_t *px_p);
extern int px_fm_init_child(dev_info_t *, dev_info_t *, int,
ddi_iblock_cookie_t *);
-extern void px_fm_acc_setup(ddi_map_req_t *, dev_info_t *);
+extern void px_fm_acc_setup(ddi_map_req_t *, dev_info_t *, pci_regspec_t *rp);
extern int px_fm_callback(dev_info_t *, ddi_fm_error_t *, const void *);
extern int px_err_cmn_intr(px_t *, ddi_fm_error_t *, int, int);
@@ -118,14 +118,27 @@ extern uint_t px_err_fabric_intr(px_t *px_p, msgcode_t msg_code,
/*
* Common error handling functions
*/
+extern int px_scan_fabric(px_t *px_p, dev_info_t *rdip, ddi_fm_error_t *derr);
extern void px_err_safeacc_check(px_t *px_p, ddi_fm_error_t *derr);
extern int px_err_check_eq(dev_info_t *dip);
extern int px_err_check_pcie(dev_info_t *dip, ddi_fm_error_t *derr,
px_err_pcie_t *regs);
-extern void px_err_panic(int err, int msg, int fab_err);
+extern int px_fm_enter(px_t *px_p);
+extern void px_fm_exit(px_t *px_p);
+extern void px_err_panic(int err, int msg, int fab_err, boolean_t isTest);
extern void px_rp_en_q(px_t *px_p, pcie_req_id_t fault_bdf,
uint32_t fault_addr, uint16_t s_status);
+/*
+ * Sparc specific cfg, pio and dma handle lookup/check functions
+ */
+extern int px_err_cfg_hdl_check(dev_info_t *dip, const void *handle,
+ const void *addr, const void *not_used);
+extern int px_err_pio_hdl_check(dev_info_t *dip, const void *handle,
+ const void *addr, const void *not_used);
+extern int px_err_dma_hdl_check(dev_info_t *dip, const void *handle,
+ const void *addr, const void *not_used);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/uts/sun4/io/px/px_pci.c b/usr/src/uts/sun4/io/px/px_pci.c
index b2af17fba6..286feee297 100644
--- a/usr/src/uts/sun4/io/px/px_pci.c
+++ b/usr/src/uts/sun4/io/px/px_pci.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -111,10 +111,7 @@ static int pxb_fm_init(pxb_devstate_t *pxb_p);
static void pxb_fm_fini(pxb_devstate_t *pxb_p);
static int pxb_fm_init_child(dev_info_t *dip, dev_info_t *cdip, int cap,
ddi_iblock_cookie_t *ibc_p);
-static int pxb_fm_err_callback(dev_info_t *dip, ddi_fm_error_t *derr,
- const void *impl_data);
-static int pxb_pcie_device_type(pxb_devstate_t *pxb_p);
static void pxb_set_pci_perf_parameters(dev_info_t *dip,
ddi_acc_handle_t config_handle);
#ifdef PRINT_PLX_SEEPROM_CRC
@@ -319,11 +316,12 @@ pxb_probe(register dev_info_t *devi)
static int
pxb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
{
+ pcie_bus_t *bus_p = PCIE_DIP2BUS(devi);
int instance;
pxb_devstate_t *pxb;
ddi_acc_handle_t config_handle;
char device_type[8];
- uint16_t cap_ptr;
+ uint8_t dev_type = bus_p->bus_dev_type;
#ifdef PX_PLX
uint_t bus_num, primary, secondary;
#endif /* PX_PLX */
@@ -336,8 +334,7 @@ pxb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
/*
* Get the soft state structure for the bridge.
*/
- pxb = (pxb_devstate_t *)
- ddi_get_soft_state(pxb_state, instance);
+ pxb = (pxb_devstate_t *)ddi_get_soft_state(pxb_state, instance);
(void) pcie_pwr_resume(devi);
return (DDI_SUCCESS);
@@ -402,18 +399,7 @@ pxb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
goto fail;
}
- if ((PCI_CAP_LOCATE(pxb->pxb_config_handle, PCI_CAP_ID_PCI_E,
- &cap_ptr)) != DDI_FAILURE)
- pxb->pxb_port_type = PCI_CAP_GET16(config_handle, NULL, cap_ptr,
- PCIE_PCIECAP) & PCIE_PCIECAP_DEV_TYPE_MASK;
- else
- pxb->pxb_port_type = PCIE_PCIECAP_DEV_TYPE_PCIE_DEV;
-
- if ((pxb->pxb_port_type != PCIE_PCIECAP_DEV_TYPE_UP) &&
- (pxb->pxb_port_type != PCIE_PCIECAP_DEV_TYPE_DOWN) &&
- (pxb->pxb_port_type != PCIE_PCIECAP_DEV_TYPE_ROOT) &&
- (pxb->pxb_port_type != PCIE_PCIECAP_DEV_TYPE_PCIE2PCI) &&
- (pxb->pxb_port_type != PCIE_PCIECAP_DEV_TYPE_PCI2PCIE)) {
+ if (!(PCIE_IS_BDG(bus_p))) {
DBG(DBG_ATTACH, devi, "This is not a switch or bridge\n");
goto fail;
}
@@ -421,10 +407,13 @@ pxb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
/*
* Make sure the "device_type" property exists.
*/
- if (pxb_pcie_device_type(pxb) == DDI_SUCCESS)
+ if ((bus_p->bus_dev_type == PCIE_PCIECAP_DEV_TYPE_UP) ||
+ (bus_p->bus_dev_type == PCIE_PCIECAP_DEV_TYPE_DOWN) ||
+ (bus_p->bus_dev_type == PCIE_PCIECAP_DEV_TYPE_PCI2PCIE))
(void) strcpy(device_type, "pciex");
else
(void) strcpy(device_type, "pci");
+
(void) ddi_prop_update_string(DDI_DEV_T_NONE, devi,
"device_type", device_type);
@@ -444,7 +433,7 @@ pxb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
* PCI and PCI-X device driver's parent private data structure
* as part of their init child function.
*/
- if (pxb->pxb_port_type == PCIE_PCIECAP_DEV_TYPE_PCIE2PCI) {
+ if (PCIE_IS_PCI_BDG(bus_p)) {
if (ndi_prop_update_int(DDI_DEV_T_NONE, pxb->pxb_dip,
"pcie2pci-sec-bus", pci_config_get8(config_handle,
PCI_BCNF_SECBUS)) != DDI_PROP_SUCCESS) {
@@ -498,10 +487,10 @@ pxb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
goto hotplug_done;
#endif /* PX_PLX */
- if ((pxb->pxb_port_type == PCIE_PCIECAP_DEV_TYPE_DOWN) ||
- (pxb->pxb_port_type == PCIE_PCIECAP_DEV_TYPE_ROOT) ||
- (pxb->pxb_port_type == PCIE_PCIECAP_DEV_TYPE_PCIE2PCI) ||
- (pxb->pxb_port_type == PCIE_PCIECAP_DEV_TYPE_PCI2PCIE)) {
+ if ((dev_type == PCIE_PCIECAP_DEV_TYPE_DOWN) ||
+ (dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) ||
+ (dev_type == PCIE_PCIECAP_DEV_TYPE_PCIE2PCI) ||
+ (dev_type == PCIE_PCIECAP_DEV_TYPE_PCI2PCIE)) {
#ifdef PX_PLX
/*
* Workaround for a race condition between hotplug
@@ -692,22 +681,15 @@ pxb_ctlops(dev_info_t *dip, dev_info_t *rdip,
return (pcie_pm_hold(dip));
}
if (as->cmd == DDI_RESUME) {
- ddi_acc_handle_t config_handle;
DBG(DBG_PWR, dip, "PRE_RESUME for %s@%d\n",
ddi_driver_name(rdip),
ddi_get_instance(rdip));
-
- if (pci_config_setup(rdip, &config_handle) ==
- DDI_SUCCESS) {
- pcie_clear_errors(rdip, config_handle);
- pci_config_teardown(&config_handle);
- }
+ pcie_clear_errors(rdip);
}
return (DDI_SUCCESS);
case DDI_POST: {
- ddi_acc_handle_t config_handle;
DBG(DBG_PWR, dip, "POST_ATTACH for %s@%d\n",
ddi_driver_name(rdip), ddi_get_instance(rdip));
if (as->cmd == DDI_ATTACH && as->result != DDI_SUCCESS)
@@ -729,11 +711,7 @@ pxb_ctlops(dev_info_t *dip, dev_info_t *rdip,
return (DDI_SUCCESS);
}
- if (pci_config_setup(rdip, &config_handle) ==
- DDI_SUCCESS) {
- pcie_disable_errors(rdip, config_handle);
- pci_config_teardown(&config_handle);
- }
+ pcie_disable_errors(rdip);
return (DDI_SUCCESS);
}
@@ -1007,7 +985,7 @@ pxb_initchild(dev_info_t *child)
"INITCHILD: config regs setup for %s@%s\n",
ddi_node_name(child), ddi_get_name_addr(child));
- if (pcie_initchild(child) != DDI_SUCCESS) {
+ if (!pcie_init_bus(child) || pcie_initchild(child) != DDI_SUCCESS) {
result = DDI_FAILURE;
goto cleanup;
}
@@ -1038,7 +1016,7 @@ pxb_initchild(dev_info_t *child)
for (i = 0; i < pxb_tlp_count; i += 1)
reg |= pci_config_get16(config_handle, PCI_CONF_VENID);
- if (pxb->pxb_port_type == PCIE_PCIECAP_DEV_TYPE_PCIE2PCI)
+ if (PCIE_IS_PCIE_BDG(PCIE_DIP2BUS(pxb->pxb_dip)))
pxb_set_pci_perf_parameters(child, config_handle);
pci_config_teardown(&config_handle);
@@ -1288,8 +1266,8 @@ pxb_intr(caddr_t arg1, caddr_t arg2)
if (pxb->pxb_hpc_type == HPC_SHPC)
rval = pcishpc_intr(pxb->pxb_dip);
}
- if ((rval == DDI_INTR_UNCLAIMED) && (pxb->pxb_intr_type ==
- DDI_INTR_TYPE_MSI))
+ if ((rval == DDI_INTR_UNCLAIMED) &&
+ (pxb->pxb_intr_type == DDI_INTR_TYPE_MSI))
cmn_err(CE_WARN, "%s%d: Cannot handle interrupt",
ddi_driver_name(dip), ddi_get_instance(dip));
@@ -1321,14 +1299,15 @@ static int
pxb_init_hotplug(pxb_devstate_t *pxb)
{
int rv = DDI_FAILURE;
+ uint8_t dev_type = PCIE_DIP2BUS(pxb->pxb_dip)->bus_dev_type;
- if (((pxb->pxb_port_type == PCIE_PCIECAP_DEV_TYPE_DOWN) ||
- (pxb->pxb_port_type == PCIE_PCIECAP_DEV_TYPE_ROOT) ||
- (pxb->pxb_port_type == PCIE_PCIECAP_DEV_TYPE_PCI2PCIE)) &&
+ if (((dev_type == PCIE_PCIECAP_DEV_TYPE_DOWN) ||
+ (dev_type == PCIE_PCIECAP_DEV_TYPE_PCI2PCIE) ||
+ (dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT)) &&
(pxb_pciehpc_probe(pxb->pxb_dip,
pxb->pxb_config_handle) == DDI_SUCCESS)) {
pxb->pxb_hpc_type = HPC_PCIE;
- } else if ((pxb->pxb_port_type == PCIE_PCIECAP_DEV_TYPE_PCIE2PCI) &&
+ } else if ((dev_type == PCIE_PCIECAP_DEV_TYPE_PCIE2PCI) &&
(pxb_pcishpc_probe(pxb->pxb_dip,
pxb->pxb_config_handle) == DDI_SUCCESS)) {
pxb->pxb_hpc_type = HPC_SHPC;
@@ -1393,8 +1372,7 @@ pxb_create_ranges_prop(dev_info_t *dip,
* Create ranges for IO space
*/
ranges[i].size_low = ranges[i].size_high = 0;
- ranges[i].parent_mid = ranges[i].child_mid =
- ranges[i].parent_high = 0;
+ ranges[i].parent_mid = ranges[i].child_mid = ranges[i].parent_high = 0;
ranges[i].child_high = ranges[i].parent_high |=
(PCI_REG_REL_M | PCI_ADDR_IO);
base = PXB_16bit_IOADDR(io_base_lo);
@@ -1418,8 +1396,7 @@ pxb_create_ranges_prop(dev_info_t *dip,
base = PXB_32bit_MEMADDR(mem_base);
limit = PXB_32bit_MEMADDR(mem_limit);
ranges[i].size_low = ranges[i].size_high = 0;
- ranges[i].parent_mid = ranges[i].child_mid =
- ranges[i].parent_high = 0;
+ ranges[i].parent_mid = ranges[i].child_mid = ranges[i].parent_high = 0;
ranges[i].child_high = ranges[i].parent_high |=
(PCI_REG_REL_M | PCI_ADDR_MEM32);
ranges[i].child_low = ranges[i].parent_low = base;
@@ -1663,8 +1640,8 @@ pxb_pwr_setup(dev_info_t *dip)
/*
* Walk the capabilities searching for a PM entry.
*/
- if ((PCI_CAP_LOCATE(conf_hdl, PCI_CAP_ID_PM, &cap_ptr))
- == DDI_FAILURE) {
+ if ((PCI_CAP_LOCATE(conf_hdl, PCI_CAP_ID_PM, &cap_ptr)) ==
+ DDI_FAILURE) {
DBG(DBG_PWR, dip, "switch/bridge does not support PM. PCI"
" PM data structure not found in config header\n");
pci_config_teardown(&conf_hdl);
@@ -1768,23 +1745,17 @@ static int
pxb_fm_init(pxb_devstate_t *pxb_p)
{
dev_info_t *dip = pxb_p->pxb_dip;
-
- pxb_p->pxb_fm_cap = DDI_FM_EREPORT_CAPABLE | DDI_FM_ERRCB_CAPABLE |
+ int fm_cap = DDI_FM_EREPORT_CAPABLE |
DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE;
/*
* Request our capability level and get our parents capability
* and ibc.
*/
- ddi_fm_init(dip, &pxb_p->pxb_fm_cap, &pxb_p->pxb_fm_ibc);
+ ddi_fm_init(dip, &fm_cap, &pxb_p->pxb_fm_ibc);
pci_ereport_setup(dip);
- /*
- * Register error callback with our parent.
- */
- ddi_fm_handler_register(pxb_p->pxb_dip, pxb_fm_err_callback,
- (void *)&pxb_p->pxb_config_handle);
return (DDI_SUCCESS);
}
@@ -1798,8 +1769,6 @@ pxb_fm_fini(pxb_devstate_t *pxb_p)
/*
* Clean up allocated fm structures
*/
- ddi_fm_handler_unregister(dip);
- pci_ereport_teardown(dip);
ddi_fm_fini(dip);
}
@@ -1815,19 +1784,7 @@ pxb_fm_init_child(dev_info_t *dip, dev_info_t *cdip, int cap,
pxb_devstate_t *pxb_p = (pxb_devstate_t *)
ddi_get_soft_state(pxb_state, ddi_get_instance(dip));
*ibc_p = pxb_p->pxb_fm_ibc;
- return (pxb_p->pxb_fm_cap | DDI_FM_DMACHK_CAPABLE);
-}
-
-/*
- * FMA Error callback handler.
- * Need to revisit when pcie fm is supported.
- */
-/*ARGSUSED*/
-static int
-pxb_fm_err_callback(dev_info_t *dip, ddi_fm_error_t *derr,
- const void *impl_data)
-{
- return (DDI_FM_OK);
+ return (DEVI(dip)->devi_fmhdl->fh_cap | DDI_FM_DMACHK_CAPABLE);
}
/*
@@ -1851,8 +1808,8 @@ static int pxb_pciehpc_probe(dev_info_t *dip, ddi_acc_handle_t config_handle)
{
uint16_t cap_ptr;
- if ((PCI_CAP_LOCATE(config_handle, PCI_CAP_ID_PCI_E, &cap_ptr))
- != DDI_FAILURE) {
+ if ((PCI_CAP_LOCATE(config_handle, PCI_CAP_ID_PCI_E, &cap_ptr)) !=
+ DDI_FAILURE) {
uint16_t slotimpl = PCI_CAP_GET16(config_handle, NULL, cap_ptr,
PCIE_PCIECAP) & PCIE_PCIECAP_SLOT_IMPL;
if (slotimpl)
@@ -1870,8 +1827,8 @@ static int pxb_pcishpc_probe(dev_info_t *dip, ddi_acc_handle_t config_handle)
{
uint16_t cap_ptr;
- if ((PCI_CAP_LOCATE(config_handle, PCI_CAP_ID_PCI_HOTPLUG, &cap_ptr))
- != DDI_FAILURE) {
+ if ((PCI_CAP_LOCATE(config_handle, PCI_CAP_ID_PCI_HOTPLUG, &cap_ptr)) !=
+ DDI_FAILURE) {
return (DDI_SUCCESS);
}
@@ -1879,26 +1836,6 @@ static int pxb_pcishpc_probe(dev_info_t *dip, ddi_acc_handle_t config_handle)
}
-/* check if this device has PCIe link underneath. */
-static int
-pxb_pcie_device_type(pxb_devstate_t *pxb_p)
-{
- int port_type = pxb_p->pxb_port_type;
-
- /* No PCIe CAP regs, we are not PCIe device_type */
- if (port_type < 0)
- return (DDI_FAILURE);
-
- /* check for all PCIe device_types */
- if ((port_type == PCIE_PCIECAP_DEV_TYPE_UP) ||
- (port_type == PCIE_PCIECAP_DEV_TYPE_DOWN) ||
- (port_type == PCIE_PCIECAP_DEV_TYPE_ROOT) ||
- (port_type == PCIE_PCIECAP_DEV_TYPE_PCI2PCIE))
- return (DDI_SUCCESS);
-
- return (DDI_FAILURE);
-}
-
/*
* For PCI and PCI-X devices including PCIe2PCI bridge, initialize
* cache-line-size and latency timer configuration registers.
diff --git a/usr/src/uts/sun4/io/px/px_pci.h b/usr/src/uts/sun4/io/px/px_pci.h
index 13cc4cc1f8..1303de878b 100644
--- a/usr/src/uts/sun4/io/px/px_pci.h
+++ b/usr/src/uts/sun4/io/px/px_pci.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -100,9 +100,6 @@ typedef struct {
ddi_acc_handle_t pxb_config_handle;
- /* Bridge or Switch, upstream or downstream */
- int pxb_port_type;
-
/* Interrupt */
ddi_intr_handle_t *pxb_htable; /* Intr Handlers */
int pxb_htable_size; /* htable size */
@@ -123,7 +120,6 @@ typedef struct {
int pxb_init_flags;
/* FMA */
- int pxb_fm_cap;
ddi_iblock_cookie_t pxb_fm_ibc;
/* Vendor Device Id */
diff --git a/usr/src/uts/sun4/io/px/px_space.c b/usr/src/uts/sun4/io/px/px_space.c
index 838fc9ffe0..a153c2b233 100644
--- a/usr/src/uts/sun4/io/px/px_space.c
+++ b/usr/src/uts/sun4/io/px/px_space.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -164,83 +164,3 @@ uint32_t px_log = PX_PANIC | PX_NO_PANIC | PX_PROTECTED | PX_HW_RESET;
uint32_t px_log = PX_PANIC;
#endif
uint32_t px_die = PX_PANIC | PX_PROTECTED | PX_HW_RESET;
-
-/* Fire PCIe Error that should cause panics */
-boolean_t px_fabric_die = B_TRUE;
-
-/* Root Complex PCIe Error bit flags that should cause panics */
-uint32_t px_fabric_die_rc_ce = 0;
-uint32_t px_fabric_die_rc_ue = 0;
-
-/* Root Complex PCIe Error bit flags that should cause forgiven */
-uint32_t px_fabric_forgive_rc_ce = 0;
-uint32_t px_fabric_forgive_rc_ue = 0;
-
-/* Fabric Error that should cause panics */
-uint32_t px_fabric_die_ce = 0;
-uint32_t px_fabric_die_ue = PCIE_AER_UCE_UR |
- PCIE_AER_UCE_UC |
- PCIE_AER_UCE_TO |
- PCIE_AER_UCE_RO |
- PCIE_AER_UCE_FCP |
- PCIE_AER_UCE_DLP |
- PCIE_AER_UCE_TRAINING;
-
-/* Fabric Error that should cause panics even under protected access */
-uint32_t px_fabric_die_ce_gos = 0;
-uint32_t px_fabric_die_ue_gos = PCIE_AER_UCE_UC |
- PCIE_AER_UCE_TO |
- PCIE_AER_UCE_RO |
- PCIE_AER_UCE_FCP |
- PCIE_AER_UCE_DLP |
- PCIE_AER_UCE_TRAINING;
-
-/* Fabric Bridge Sec. Error that should cause panics */
-uint16_t px_fabric_die_bdg_sts = PCI_STAT_S_PERROR |
- PCI_STAT_R_TARG_AB |
- PCI_STAT_R_MAST_AB |
- PCI_STAT_S_SYSERR |
- PCI_STAT_PERROR;
-
-/*
- * Fabric Bridge Sec. Error that should cause panics even under
- * protected access
- */
-uint16_t px_fabric_die_bdg_sts_gos = PCI_STAT_S_PERROR |
- PCI_STAT_PERROR;
-
-/* Fabric Switch Sec. Error that should cause panics */
-uint16_t px_fabric_die_sw_sts = PCI_STAT_R_TARG_AB |
- PCI_STAT_R_MAST_AB;
-
-/*
- * Fabric Switch Sec. Error that should cause panics even under
- * protected access
- */
-uint16_t px_fabric_die_sw_sts_gos = 0;
-
-uint32_t px_fabric_die_sue = PCIE_AER_SUCE_TA_ON_SC |
- PCIE_AER_SUCE_MA_ON_SC |
- PCIE_AER_SUCE_RCVD_TA |
- PCIE_AER_SUCE_RCVD_MA |
- PCIE_AER_SUCE_USC_ERR |
- PCIE_AER_SUCE_USC_MSG_DATA_ERR |
- PCIE_AER_SUCE_UC_DATA_ERR |
- PCIE_AER_SUCE_UC_ATTR_ERR |
- PCIE_AER_SUCE_UC_ADDR_ERR |
- PCIE_AER_SUCE_TIMER_EXPIRED |
- PCIE_AER_SUCE_PERR_ASSERT |
- PCIE_AER_SUCE_SERR_ASSERT |
- PCIE_AER_SUCE_INTERNAL_ERR;
-
-uint32_t px_fabric_die_sue_gos = PCIE_AER_SUCE_TA_ON_SC |
- PCIE_AER_SUCE_MA_ON_SC |
- PCIE_AER_SUCE_USC_ERR |
- PCIE_AER_SUCE_USC_MSG_DATA_ERR |
- PCIE_AER_SUCE_UC_DATA_ERR |
- PCIE_AER_SUCE_UC_ATTR_ERR |
- PCIE_AER_SUCE_UC_ADDR_ERR |
- PCIE_AER_SUCE_TIMER_EXPIRED |
- PCIE_AER_SUCE_PERR_ASSERT |
- PCIE_AER_SUCE_SERR_ASSERT |
- PCIE_AER_SUCE_INTERNAL_ERR;
diff --git a/usr/src/uts/sun4/io/px/px_space.h b/usr/src/uts/sun4/io/px/px_space.h
index e49e2adb84..2551175510 100644
--- a/usr/src/uts/sun4/io/px/px_space.h
+++ b/usr/src/uts/sun4/io/px/px_space.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -114,23 +114,6 @@ extern uint32_t px_max_l1_tries;
extern uint32_t px_log;
extern uint32_t px_die;
-/* Fabric Error that should cause panics */
-extern boolean_t px_fabric_die;
-extern uint32_t px_fabric_die_rc_ce;
-extern uint32_t px_fabric_die_rc_ue;
-extern uint32_t px_fabric_forgive_rc_ce;
-extern uint32_t px_fabric_forgive_rc_ue;
-extern uint32_t px_fabric_die_ce;
-extern uint32_t px_fabric_die_ue;
-extern uint32_t px_fabric_die_ce_gos;
-extern uint32_t px_fabric_die_ue_gos;
-extern uint16_t px_fabric_die_bdg_sts;
-extern uint16_t px_fabric_die_bdg_sts_gos;
-extern uint16_t px_fabric_die_sw_sts;
-extern uint16_t px_fabric_die_sw_sts_gos;
-extern uint32_t px_fabric_die_sue;
-extern uint32_t px_fabric_die_sue_gos;
-
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/uts/sun4/io/px/px_util.c b/usr/src/uts/sun4/io/px/px_util.c
index af466b5d19..ef2b2c8ea5 100644
--- a/usr/src/uts/sun4/io/px/px_util.c
+++ b/usr/src/uts/sun4/io/px/px_util.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -71,17 +71,17 @@ px_get_props(px_t *px_p, dev_info_t *dip)
return (DDI_FAILURE);
}
DBG(DBG_ATTACH, dip, "get_px_properties: bus-range (%x,%x)\n",
- px_p->px_bus_range.lo, px_p->px_bus_range.hi);
+ px_p->px_bus_range.lo, px_p->px_bus_range.hi);
/*
* Get the interrupts property.
*/
if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
- "interrupts", (caddr_t)&px_p->px_inos,
- &px_p->px_inos_len) != DDI_SUCCESS) {
+ "interrupts", (caddr_t)&px_p->px_inos,
+ &px_p->px_inos_len) != DDI_SUCCESS) {
cmn_err(CE_WARN, "%s%d: no interrupts property\n",
- ddi_driver_name(dip), ddi_get_instance(dip));
+ ddi_driver_name(dip), ddi_get_instance(dip));
return (DDI_FAILURE);
}
@@ -99,11 +99,11 @@ px_get_props(px_t *px_p, dev_info_t *dip)
* Get the ranges property.
*/
if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ranges",
- (caddr_t)&px_p->px_ranges_p, &px_p->px_ranges_length) !=
- DDI_SUCCESS) {
+ (caddr_t)&px_p->px_ranges_p, &px_p->px_ranges_length) !=
+ DDI_SUCCESS) {
cmn_err(CE_WARN, "%s%d: no ranges property\n",
- ddi_driver_name(dip), ddi_get_instance(dip));
+ ddi_driver_name(dip), ddi_get_instance(dip));
kmem_free(px_p->px_inos, px_p->px_inos_len);
return (DDI_FAILURE);
}
@@ -151,8 +151,8 @@ px_reloc_reg(dev_info_t *dip, dev_info_t *rdip, px_t *px_p,
uint32_t space_type = phys_hi & PCI_REG_ADDR_M; /* 28-bit */
DBG(DBG_MAP | DBG_CONT, dip, "\tpx_reloc_reg fr: %x.%x.%x %x.%x\n",
- rp->pci_phys_hi, rp->pci_phys_mid, rp->pci_phys_low,
- rp->pci_size_hi, rp->pci_size_low);
+ rp->pci_phys_hi, rp->pci_phys_mid, rp->pci_phys_low,
+ rp->pci_size_hi, rp->pci_size_low);
if (space_type == PCI_ADDR_CONFIG || phys_hi & PCI_RELOCAT_B)
return (DDI_SUCCESS);
@@ -508,7 +508,9 @@ px_init_child(px_t *px_p, dev_info_t *child)
"INITCHILD: config regs setup for %s@%s\n",
ddi_node_name(child), ddi_get_name_addr(child));
- pcie_initchild(child);
+ ddi_set_parent_data(child, NULL);
+ if (pcie_init_bus(child))
+ (void) pcie_initchild(child);
/*
* Handle chip specific init-child tasks.
@@ -549,7 +551,7 @@ px_get_reg_set_size(dev_info_t *child, int rnumber)
goto done;
size = pci_rp[rnumber].pci_size_low |
- ((uint64_t)pci_rp[rnumber].pci_size_hi << 32);
+ ((uint64_t)pci_rp[rnumber].pci_size_hi << 32);
done:
kmem_free(pci_rp, i);
return (size);
diff --git a/usr/src/uts/sun4/io/px/px_var.h b/usr/src/uts/sun4/io/px/px_var.h
index 048a10c65b..ba395d8b9d 100644
--- a/usr/src/uts/sun4/io/px/px_var.h
+++ b/usr/src/uts/sun4/io/px/px_var.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -130,11 +130,13 @@ struct px {
kmutex_t px_fm_mutex;
kthread_t *px_fm_mutex_owner;
ddi_iblock_cookie_t px_fm_ibc;
+ pf_data_t px_pfd_arr[5];
+ int px_pfd_idx;
uint32_t px_dev_caps;
/* Platform specific information */
- void *px_plat_p;
+ void *px_plat_p;
/* Power Management fields */
kmutex_t px_l23ready_lock; /* used in PME_To_ACK interrupt */
@@ -150,10 +152,6 @@ struct px {
/* Handle for soft intr */
ddi_softint_handle_t px_dbg_hdl; /* HDL for dbg printing */
-
- /* array to keep track of register snapshots during error handling */
- int px_dq_tail; /* last valid index in cs array */
- pf_data_t *px_dq_p;
};
/* px soft state flag */