diff options
author | jhb <jhb@FreeBSD.org> | 2007-03-26 20:18:52 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2007-03-26 20:18:52 +0000 |
commit | 0236cc99b768a2d3425bf954c746f7eace24a26b (patch) | |
tree | a608d2e502214caf874677e4817a4ae59cb383ad /sys/dev/pci | |
parent | 764339998b0ac37e74d4476c424e7b75c7383880 (diff) | |
download | FreeBSD-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.c | 43 | ||||
-rw-r--r-- | sys/dev/pci/pcivar.h | 1 |
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; |