summaryrefslogtreecommitdiffstats
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2014-02-19 18:34:47 +0000
committerjhb <jhb@FreeBSD.org>2014-02-19 18:34:47 +0000
commit169a4e8371dd1f60ac3b3e9d6fbb216c7d19accd (patch)
treedc277e84571c2b0f6bc689012acba796c548c4f8 /sys/dev/pci
parent690ab44de324d5cd9aee67eed6f81effd837b070 (diff)
downloadFreeBSD-src-169a4e8371dd1f60ac3b3e9d6fbb216c7d19accd.zip
FreeBSD-src-169a4e8371dd1f60ac3b3e9d6fbb216c7d19accd.tar.gz
MFC 261524,261526,261527:
- Properly set the alignment flags when allocating the initial range for a BAR. This only really matters when pci_do_realloc_bars is enabled and the initial allocation of a specific range fails. - Simplify pci_reserve_map() by calling resource_list_reserve() to allocate the resource after creating a resource list entry rather than reimplementing it by hand. - Add two tunables to ignore certain firmware-assigned resources. These are mostly useful for debugging. - hw.pci.clear_bars ignores all firmware-assigned ranges for BARs when set. - hw.pci.clear_pcib ignores all firmware-assigned ranges for PCI-PCI bridge I/O windows when set.
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/pci.c32
-rw-r--r--sys/dev/pci/pci_pci.c19
2 files changed, 35 insertions, 16 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 84aab9d..f1cbe6c 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -332,6 +332,11 @@ SYSCTL_INT(_hw_pci, OID_AUTO, usb_early_takeover, CTLFLAG_RDTUN,
Disable this if you depend on BIOS emulation of USB devices, that is\n\
you use USB devices (like keyboard or mouse) but do not load USB drivers");
+static int pci_clear_bars;
+TUNABLE_INT("hw.pci.clear_bars", &pci_clear_bars);
+SYSCTL_INT(_hw_pci, OID_AUTO, clear_bars, CTLFLAG_RDTUN, &pci_clear_bars, 0,
+ "Ignore firmware-assigned resources for BARs.");
+
static int
pci_has_quirk(uint32_t devid, int quirk)
{
@@ -2742,7 +2747,7 @@ pci_add_map(device_t bus, device_t dev, int reg, struct resource_list *rl,
struct pci_map *pm;
pci_addr_t base, map, testval;
pci_addr_t start, end, count;
- int barlen, basezero, maprange, mapsize, type;
+ int barlen, basezero, flags, maprange, mapsize, type;
uint16_t cmd;
struct resource *res;
@@ -2848,7 +2853,10 @@ pci_add_map(device_t bus, device_t dev, int reg, struct resource_list *rl,
}
count = (pci_addr_t)1 << mapsize;
- if (basezero || base == pci_mapbase(testval)) {
+ flags = RF_ALIGNMENT_LOG2(mapsize);
+ if (prefetch)
+ flags |= RF_PREFETCHABLE;
+ if (basezero || base == pci_mapbase(testval) || pci_clear_bars) {
start = 0; /* Let the parent decide. */
end = ~0ul;
} else {
@@ -2864,7 +2872,7 @@ pci_add_map(device_t bus, device_t dev, int reg, struct resource_list *rl,
* pci_alloc_resource().
*/
res = resource_list_reserve(rl, bus, dev, type, &reg, start, end, count,
- prefetch ? RF_PREFETCHABLE : 0);
+ flags);
if (pci_do_realloc_bars && res == NULL && (start != 0 || end != ~0ul)) {
/*
* If the allocation fails, try to allocate a resource for
@@ -2875,7 +2883,7 @@ pci_add_map(device_t bus, device_t dev, int reg, struct resource_list *rl,
resource_list_delete(rl, type, reg);
resource_list_add(rl, type, reg, 0, ~0ul, count);
res = resource_list_reserve(rl, bus, dev, type, &reg, 0, ~0ul,
- count, prefetch ? RF_PREFETCHABLE : 0);
+ count, flags);
}
if (res == NULL) {
/*
@@ -4174,7 +4182,6 @@ pci_reserve_map(device_t dev, device_t child, int type, int *rid,
{
struct pci_devinfo *dinfo = device_get_ivars(child);
struct resource_list *rl = &dinfo->resources;
- struct resource_list_entry *rle;
struct resource *res;
struct pci_map *pm;
pci_addr_t map, testval;
@@ -4247,23 +4254,16 @@ pci_reserve_map(device_t dev, device_t child, int type, int *rid,
* Allocate enough resource, and then write back the
* appropriate BAR for that resource.
*/
- res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, type, rid,
- start, end, count, flags & ~RF_ACTIVE);
+ resource_list_add(rl, type, *rid, start, end, count);
+ res = resource_list_reserve(rl, dev, child, type, rid, start, end,
+ count, flags & ~RF_ACTIVE);
if (res == NULL) {
+ resource_list_delete(rl, type, *rid);
device_printf(child,
"%#lx bytes of rid %#x res %d failed (%#lx, %#lx).\n",
count, *rid, type, start, end);
goto out;
}
- resource_list_add(rl, type, *rid, start, end, count);
- rle = resource_list_find(rl, type, *rid);
- if (rle == NULL)
- panic("pci_reserve_map: unexpectedly can't find resource.");
- rle->res = res;
- rle->start = rman_get_start(res);
- rle->end = rman_get_end(res);
- rle->count = count;
- rle->flags = RLE_RESERVED;
if (bootverbose)
device_printf(child,
"Lazy allocation of %#lx bytes rid %#x type %d at %#lx\n",
diff --git a/sys/dev/pci/pci_pci.c b/sys/dev/pci/pci_pci.c
index 3fa3d5a..5fa886e 100644
--- a/sys/dev/pci/pci_pci.c
+++ b/sys/dev/pci/pci_pci.c
@@ -103,6 +103,12 @@ DEFINE_CLASS_0(pcib, pcib_driver, pcib_methods, sizeof(struct pcib_softc));
DRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclass, NULL, NULL);
#ifdef NEW_PCIB
+SYSCTL_DECL(_hw_pci);
+
+static int pci_clear_pcib;
+TUNABLE_INT("hw.pci.clear_pcib", &pci_clear_pcib);
+SYSCTL_INT(_hw_pci, OID_AUTO, clear_pcib, CTLFLAG_RDTUN, &pci_clear_pcib, 0,
+ "Clear firmware-assigned resources for PCI-PCI bridge I/O windows.");
/*
* Is a resource from a child device sub-allocated from one of our
@@ -416,6 +422,19 @@ pcib_probe_windows(struct pcib_softc *sc)
dev = sc->dev;
+ if (pci_clear_pcib) {
+ pci_write_config(dev, PCIR_IOBASEL_1, 0xff, 1);
+ pci_write_config(dev, PCIR_IOBASEH_1, 0xffff, 2);
+ pci_write_config(dev, PCIR_IOLIMITL_1, 0, 1);
+ pci_write_config(dev, PCIR_IOLIMITH_1, 0, 2);
+ pci_write_config(dev, PCIR_MEMBASE_1, 0xffff, 2);
+ pci_write_config(dev, PCIR_MEMLIMIT_1, 0, 2);
+ pci_write_config(dev, PCIR_PMBASEL_1, 0xffff, 2);
+ pci_write_config(dev, PCIR_PMBASEH_1, 0xffffffff, 4);
+ pci_write_config(dev, PCIR_PMLIMITL_1, 0, 2);
+ pci_write_config(dev, PCIR_PMLIMITH_1, 0, 4);
+ }
+
/* Determine if the I/O port window is implemented. */
val = pci_read_config(dev, PCIR_IOBASEL_1, 1);
if (val == 0) {
OpenPOWER on IntegriCloud