From b2bfac4c0642e69fdd0c0eacaf4533ed11b6da71 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Mon, 26 Mar 2007 20:18:52 +0000 Subject: [PATCH] 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 --- sys/dev/pci/pci.c | 43 +++++++++++++------------------------------ 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 cefa7f90c22e..43ebd8ad5982 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 a0757454c14c..0b1b5ade9fd4 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;