diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2014-11-26 09:29:18 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2014-11-26 09:29:18 +0000 |
commit | 2b4133a2043cca8c05f1383f58d2952b012ab177 (patch) | |
tree | 78d9e5f9a0ee2965d7815013889f8f981d2aedd8 | |
parent | e224f050289ce337bbd1d6299f622f27b3c71c91 (diff) |
Seems Sun^H^H^HOracle is doing something naughty and (deliberately) puts
non-prefetchable BARs of the onboard mpii(4) behind a prefetchable memory
range on the bridge it sists behind. Since we rely on the formware to program
BARs for us on sparc64, add a workaround to avoid whacking these BARs and
make the machine panic later when it tries to access the registers.
ok miod@, deraadt@
-rw-r--r-- | sys/dev/pci/pci.c | 42 |
1 files changed, 31 insertions, 11 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index e298e833cbf..65aae5d7ca8 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pci.c,v 1.107 2014/11/24 13:48:49 kettenis Exp $ */ +/* $OpenBSD: pci.c,v 1.108 2014/11/26 09:29:17 kettenis Exp $ */ /* $NetBSD: pci.c,v 1.31 1997/06/06 23:48:04 thorpej Exp $ */ /* @@ -848,21 +848,41 @@ pci_reserve_resources(struct pci_attach_args *pa) break; } if (pa->pa_memex && extent_alloc_region(pa->pa_memex, - base, size, EX_NOWAIT)) { - printf("%d:%d:%d: mem address conflict 0x%lx/0x%lx\n", - bus, dev, func, base, size); - pci_conf_write(pc, tag, reg, 0); - if (type & PCI_MAPREG_MEM_TYPE_64BIT) - pci_conf_write(pc, tag, reg + 4, 0); + base, size, EX_NOWAIT) == 0) { + break; } +#ifdef __sparc64__ + /* + * Certain SPARC T5 systems assign + * non-prefetchable 64-bit BARs of its onboard + * mpii(4) controllers addresses in the + * prefetchable memory range. This is + * (probably) safe, as reads from the device + * registers mapped by these BARs are + * side-effect free. So assume the firmware + * knows what it is doing. + */ + if (base >= 0x100000000 && + pa->pa_pmemex && extent_alloc_region(pa->pa_pmemex, + base, size, EX_NOWAIT) == 0) { + break; + } +#endif + printf("%d:%d:%d: mem address conflict 0x%lx/0x%lx\n", + bus, dev, func, base, size); + pci_conf_write(pc, tag, reg, 0); + if (type & PCI_MAPREG_MEM_TYPE_64BIT) + pci_conf_write(pc, tag, reg + 4, 0); break; case PCI_MAPREG_TYPE_IO: if (pa->pa_ioex && extent_alloc_region(pa->pa_ioex, - base, size, EX_NOWAIT)) { - printf("%d:%d:%d: io address conflict 0x%lx/0x%lx\n", - bus, dev, func, base, size); - pci_conf_write(pc, tag, reg, 0); + base, size, EX_NOWAIT) == 0) { + break; } + + printf("%d:%d:%d: io address conflict 0x%lx/0x%lx\n", + bus, dev, func, base, size); + pci_conf_write(pc, tag, reg, 0); break; } |