summaryrefslogtreecommitdiffstats
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2007-03-26 20:18:52 +0000
committerjhb <jhb@FreeBSD.org>2007-03-26 20:18:52 +0000
commit0236cc99b768a2d3425bf954c746f7eace24a26b (patch)
treea608d2e502214caf874677e4817a4ae59cb383ad /sys/dev/pci
parent764339998b0ac37e74d4476c424e7b75c7383880 (diff)
downloadFreeBSD-src-0236cc99b768a2d3425bf954c746f7eace24a26b.zip
FreeBSD-src-0236cc99b768a2d3425bf954c746f7eace24a26b.tar.gz
Change the VPD code to read the VPD data on-demand when a driver asks for
it via pci_get_vpd_*() rather than always reading it for each device during boot. I've left the tunable so that it can still be turned off if a device driver causes a lockup via a query to a broken device, but devices whose drivers do not use VPD (the vast majority) should no longer result in lockups during boot, and most folks should not need to tweak the tunable now. Tested on: bge(4) Silence from: jmg
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/pci.c43
-rw-r--r--sys/dev/pci/pcivar.h1
2 files changed, 14 insertions, 30 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index cefa7f9..43ebd8a 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -574,10 +574,7 @@ pci_read_extcap(device_t pcib, pcicfgregs *cfg)
cfg->msix.msix_pba_offset = val & ~PCIM_MSIX_BIR_MASK;
break;
case PCIY_VPD: /* PCI Vital Product Data */
- if (pci_do_vpd) {
- cfg->vpd.vpd_reg = ptr;
- pci_read_vpd(pcib, cfg);
- }
+ cfg->vpd.vpd_reg = ptr;
break;
case PCIY_SUBVENDOR:
/* Should always be true. */
@@ -690,6 +687,11 @@ pci_read_vpd(device_t pcib, pcicfgregs *cfg)
int cksumvalid;
int dflen;
+ if (!pci_do_vpd) {
+ cfg->vpd.vpd_cached = 1;
+ return;
+ }
+
/* init vpd reader */
vrs.bytesinval = 0;
vrs.off = 0;
@@ -905,6 +907,7 @@ pci_read_vpd(device_t pcib, pcicfgregs *cfg)
free(cfg->vpd.vpd_ros, M_DEVBUF);
cfg->vpd.vpd_ros = NULL;
}
+ cfg->vpd.vpd_cached = 1;
#undef REG
#undef WREG
}
@@ -915,6 +918,9 @@ pci_get_vpd_ident_method(device_t dev, device_t child, const char **identptr)
struct pci_devinfo *dinfo = device_get_ivars(child);
pcicfgregs *cfg = &dinfo->cfg;
+ if (!cfg->vpd.vpd_cached && cfg->vpd.vpd_reg != 0)
+ pci_read_vpd(device_get_parent(dev), cfg);
+
*identptr = cfg->vpd.vpd_ident;
if (*identptr == NULL)
@@ -931,6 +937,9 @@ pci_get_vpd_readonly_method(device_t dev, device_t child, const char *kw,
pcicfgregs *cfg = &dinfo->cfg;
int i;
+ if (!cfg->vpd.vpd_cached && cfg->vpd.vpd_reg != 0)
+ pci_read_vpd(device_get_parent(dev), cfg);
+
for (i = 0; i < cfg->vpd.vpd_rocnt; i++)
if (memcmp(kw, cfg->vpd.vpd_ros[i].keyword,
sizeof cfg->vpd.vpd_ros[i].keyword) == 0) {
@@ -1870,7 +1879,6 @@ pci_disable_io_method(device_t dev, device_t child, int space)
void
pci_print_verbose(struct pci_devinfo *dinfo)
{
- int i;
if (bootverbose) {
pcicfgregs *cfg = &dinfo->cfg;
@@ -1900,31 +1908,6 @@ pci_print_verbose(struct pci_devinfo *dinfo)
cfg->pp.pp_cap & PCIM_PCAP_D2SUPP ? " D2" : "",
status & PCIM_PSTAT_DMASK);
}
- if (cfg->vpd.vpd_reg) {
- printf("\tVPD Ident: %s\n", cfg->vpd.vpd_ident);
- for (i = 0; i < cfg->vpd.vpd_rocnt; i++) {
- struct vpd_readonly *vrop;
- vrop = &cfg->vpd.vpd_ros[i];
- if (strncmp("CP", vrop->keyword, 2) == 0)
- printf("\tCP: id %d, BAR%d, off %#x\n",
- vrop->value[0], vrop->value[1],
- le16toh(
- *(uint16_t *)&vrop->value[2]));
- else if (strncmp("RV", vrop->keyword, 2) == 0)
- printf("\tRV: %#hhx\n", vrop->value[0]);
- else
- printf("\t%.2s: %s\n", vrop->keyword,
- vrop->value);
- }
- for (i = 0; i < cfg->vpd.vpd_wcnt; i++) {
- struct vpd_write *vwp;
- vwp = &cfg->vpd.vpd_w[i];
- if (strncmp("RW", vwp->keyword, 2) != 0)
- printf("\t%.2s(%#x-%#x): %s\n",
- vwp->keyword, vwp->start,
- vwp->start + vwp->len, vwp->value);
- }
- }
if (cfg->msi.msi_location) {
int ctrl;
diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h
index a075745..0b1b5ad 100644
--- a/sys/dev/pci/pcivar.h
+++ b/sys/dev/pci/pcivar.h
@@ -67,6 +67,7 @@ struct vpd_write {
struct pcicfg_vpd {
uint8_t vpd_reg; /* base register, + 2 for addr, + 4 data */
+ char vpd_cached;
char *vpd_ident; /* string identifier */
int vpd_rocnt;
struct vpd_readonly *vpd_ros;
OpenPOWER on IntegriCloud