If the kernel fails to allocate resources for the initial value of a BAR
for a PCI device during the boot-time probe of the parent PCI bus, then zero the BAR and clear the resource list entry for that BAR. This forces the PCI bus driver to request a valid resource range from the parent bridge driver when the device driver tries to allocate the BAR. Similarly, if the initial value of a BAR is a valid range but it is > 4GB and the current OS only has 32-bit longs, then do a full teardown of the initial value of the BAR to force a reallocation. Reviewed by: imp MFC after: 1 week
This commit is contained in:
parent
9e58d59f41
commit
e29bfa9ed9
@ -2379,7 +2379,7 @@ pci_add_map(device_t pcib, device_t bus, device_t dev,
|
||||
|
||||
count = 1 << ln2size;
|
||||
if (base == 0 || base == pci_mapbase(testval)) {
|
||||
start = 0; /* Let the parent deside */
|
||||
start = 0; /* Let the parent decide. */
|
||||
end = ~0ULL;
|
||||
} else {
|
||||
start = base;
|
||||
@ -2388,21 +2388,41 @@ pci_add_map(device_t pcib, device_t bus, device_t dev,
|
||||
resource_list_add(rl, type, reg, start, end, count);
|
||||
|
||||
/*
|
||||
* Not quite sure what to do on failure of allocating the resource
|
||||
* since I can postulate several right answers.
|
||||
* Try to allocate the resource for this BAR from our parent
|
||||
* so that this resource range is already reserved. The
|
||||
* driver for this device will later inherit this resource in
|
||||
* pci_alloc_resource().
|
||||
*/
|
||||
res = resource_list_alloc(rl, bus, dev, type, ®, start, end, count,
|
||||
prefetch ? RF_PREFETCHABLE : 0);
|
||||
if (res == NULL)
|
||||
return (barlen);
|
||||
start = rman_get_start(res);
|
||||
if ((u_long)start != start) {
|
||||
/* Wait a minute! this platform can't do this address. */
|
||||
device_printf(bus,
|
||||
"pci%d:%d.%d.%x bar %#x start %#jx, too many bits.",
|
||||
pci_get_domain(dev), b, s, f, reg, (uintmax_t)start);
|
||||
resource_list_release(rl, bus, dev, type, reg, res);
|
||||
return (barlen);
|
||||
if (res == NULL) {
|
||||
/*
|
||||
* If the allocation fails, clear the BAR and delete
|
||||
* the resource list entry to force
|
||||
* pci_alloc_resource() to allocate resources from the
|
||||
* parent.
|
||||
*/
|
||||
resource_list_delete(rl, type, reg);
|
||||
start = 0;
|
||||
} else {
|
||||
start = rman_get_start(res);
|
||||
if ((u_long)start != start) {
|
||||
/*
|
||||
* Wait a minute! This platform can't do this
|
||||
* address.
|
||||
*/
|
||||
device_printf(bus,
|
||||
"pci%d:%d.%d.%x bar %#x start %#jx, too many bits.",
|
||||
pci_get_domain(dev), b, s, f, reg,
|
||||
(uintmax_t)start);
|
||||
|
||||
/*
|
||||
* Delete this resource and zero the BAR.
|
||||
*/
|
||||
resource_list_release(rl, bus, dev, type, reg, res);
|
||||
resource_list_delete(rl, type, reg);
|
||||
start = 0;
|
||||
}
|
||||
}
|
||||
pci_write_config(dev, reg, start, 4);
|
||||
if (ln2range == 64)
|
||||
|
Loading…
x
Reference in New Issue
Block a user