summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2008-08-15 20:17:08 +0000
committerjhb <jhb@FreeBSD.org>2008-08-15 20:17:08 +0000
commit783727042f78886c22e3bd88aa740287b5842e43 (patch)
treea6a8dd0ada0ef5107b0f5973fe37a23a18c926b1 /sys/dev
parentc44491b181b0cc6cc5f3cd9990c9d7f9aea7dcf0 (diff)
downloadFreeBSD-src-783727042f78886c22e3bd88aa740287b5842e43.zip
FreeBSD-src-783727042f78886c22e3bd88aa740287b5842e43.tar.gz
MFC: If the kernel fails to allocate resources for the initial value of a
PCI BAR, then zero the BAR and clear the resource list entry so that a new resource will be allocated by the device driver.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/pci.c24
1 files changed, 19 insertions, 5 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 0b23594..40dae33 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -1749,7 +1749,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;
@@ -1758,13 +1758,27 @@ 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, &reg, start, end, count,
prefetch ? RF_PREFETCHABLE : 0);
- if (res != NULL)
- pci_write_config(dev, reg, rman_get_start(res), 4);
+ 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);
+ pci_write_config(dev, reg, start, 4);
+ if (ln2range == 64)
+ pci_write_config(dev, reg + 4, start >> 32, 4);
return (barlen);
}
OpenPOWER on IntegriCloud