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
This commit is contained in:
jhb 2007-03-26 20:18:52 +00:00
parent 764339998b
commit 0236cc99b7
2 changed files with 14 additions and 30 deletions

View File

@ -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;

View File

@ -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;