Module Name: src
Committed By: matt
Date: Mon Aug 13 00:52:46 UTC 2012
Modified Files:
src/sys/arch/powerpc/booke/pci: pq3pci.c
Log Message:
Deal with PCIe/PCI hoses with more than one window so the bus_space
encompasses all of it and reserves those portions not assigned so
no one can allocate from them.
To generate a diff of this commit:
cvs rdiff -u -r1.13 -r1.14 src/sys/arch/powerpc/booke/pci/pq3pci.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/powerpc/booke/pci/pq3pci.c
diff -u src/sys/arch/powerpc/booke/pci/pq3pci.c:1.13 src/sys/arch/powerpc/booke/pci/pq3pci.c:1.14
--- src/sys/arch/powerpc/booke/pci/pq3pci.c:1.13 Wed Jul 18 19:38:26 2012
+++ src/sys/arch/powerpc/booke/pci/pq3pci.c Mon Aug 13 00:52:45 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: pq3pci.c,v 1.13 2012/07/18 19:38:26 matt Exp $ */
+/* $NetBSD: pq3pci.c,v 1.14 2012/08/13 00:52:45 matt Exp $ */
/*-
* Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -44,7 +44,7 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pq3pci.c,v 1.13 2012/07/18 19:38:26 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pq3pci.c,v 1.14 2012/08/13 00:52:45 matt Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -193,6 +193,10 @@ static const struct e500_truthtab pq3pci
struct pq3pci_bst {
struct powerpc_bus_space bs_tag;
+ uint8_t bs_numwin;
+ bus_addr_t bs_base[3];
+ bus_addr_t bs_offset[3];
+ bus_addr_t bs_limit[3];
char bs_name[16];
char bs_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8)] __aligned(8);
};
@@ -381,8 +385,8 @@ struct pq3pci_owin {
uint32_t powar;
};
-static bool
-pq3pci_owin_setup(struct pq3pci_softc *sc, u_int winnum,
+static void
+pq3pci_owin_record(struct pq3pci_softc *sc, u_int winnum,
const struct pq3pci_owin *owin)
{
const bool io_win = (owin->powar & PEXOWAR_RTT) == PEXOWAR_RTT_IO;
@@ -391,12 +395,25 @@ pq3pci_owin_setup(struct pq3pci_softc *s
| ((uint64_t)owin->potear << (32+12));
const uint64_t local_base = (uint64_t)owin->powbar << 12;
const u_int win_size_log2 = PEXIWAR_IWS_GET(owin->powar) + 1;
+ u_int slot;
bs->bs_tag.pbs_flags = _BUS_SPACE_LITTLE_ENDIAN
| (io_win ? _BUS_SPACE_IO_TYPE : _BUS_SPACE_MEM_TYPE);
- bs->bs_tag.pbs_base = pci_base;
- bs->bs_tag.pbs_offset = local_base - pci_base;
- bs->bs_tag.pbs_limit = bs->bs_tag.pbs_base + (1ULL << win_size_log2);
+
+ for (slot = 0; slot < bs->bs_numwin; slot++) {
+ if (pci_base < bs->bs_base[slot]) {
+ for (size_t j = slot; j < bs->bs_numwin; j++) {
+ bs->bs_base[j+1] = bs->bs_base[j];
+ bs->bs_offset[j+1] = bs->bs_offset[j];
+ bs->bs_limit[j+1] = bs->bs_limit[j];
+ }
+ break;
+ }
+ }
+ bs->bs_base[slot] = pci_base;
+ bs->bs_offset[slot] = local_base - pci_base;
+ bs->bs_limit[slot] = pci_base + (1ULL << win_size_log2);
+ bs->bs_numwin++;
#if 0
const char units[] = " KMGTP";
@@ -409,9 +426,20 @@ pq3pci_owin_setup(struct pq3pci_softc *s
(owin->powar & PEXOWAR_RTT) == PEXOWAR_RTT_IO ? "I/O" : "memory",
local_base, pci_base);
#endif
+}
+
+static bool
+pq3pci_owin_init(struct pq3pci_softc *sc, struct pq3pci_bst *bs, bool io_win)
+{
+ if (bs->bs_numwin == 0)
+ return true;
+
+ bs->bs_tag.pbs_base = bs->bs_base[0];
+ bs->bs_tag.pbs_offset = bs->bs_offset[0];
+ bs->bs_tag.pbs_limit = bs->bs_limit[bs->bs_numwin - 1];
- snprintf(bs->bs_name, sizeof(bs->bs_name), "%s-%s@%u",
- device_xname(sc->sc_dev), io_win ? "io" : "mem", winnum);
+ snprintf(bs->bs_name, sizeof(bs->bs_name), "%s-%s",
+ device_xname(sc->sc_dev), io_win ? "io" : "mem");
#if 0
printf("%s: %s: base=%#x offset=%#x limit=%#x\n", __func__, bs->bs_name,
@@ -425,6 +453,19 @@ pq3pci_owin_setup(struct pq3pci_softc *s
bs->bs_name, error);
return false;
}
+ for (size_t slot = 1; slot < bs->bs_numwin; slot++) {
+ if (bs->bs_limit[slot - 1] < bs->bs_base[slot]) {
+ error = extent_alloc_region(bs->bs_tag.pbs_extent,
+ bs->bs_limit[slot - 1],
+ bs->bs_base[slot] - bs->bs_limit[slot - 1],
+ EX_WAITOK);
+ if (error) {
+ aprint_error(": failed to hole in %s bus space: %d\n",
+ bs->bs_name, error);
+ return false;
+ }
+ }
+ }
aprint_debug_dev(sc->sc_dev, "bus space %s created\n", bs->bs_name);
sc->sc_pba_flags |=
io_win ? PCI_FLAGS_IO_OKAY : PCI_FLAGS_MEM_OKAY;
@@ -732,10 +773,13 @@ pq3pci_cpunode_attach(device_t parent, d
#endif
if (owin.powar & PEXOWAR_EN) {
valid_owins++;
- if (!pq3pci_owin_setup(sc, i, &owin))
- return;
+ pq3pci_owin_record(sc, i, &owin);
}
}
+ if (!pq3pci_owin_init(sc, &sc->sc_pci_io_bst, true)
+ || !pq3pci_owin_init(sc, &sc->sc_pci_mem_bst, false)) {
+ return;
+ }
#ifndef PCI_NETBSD_CONFIGURE
if (valid_owins == 0) {
aprint_normal(": %s controller%s\n", buf,
@@ -837,10 +881,8 @@ pq3pci_cpunode_attach(device_t parent, d
bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXOTEAR1, owin1.potear);
bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXOWBAR1, owin1.powbar);
bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXOWAR1, owin1.powar);
- if (!pq3pci_owin_setup(sc, 1, &owin1)) {
- aprint_error(
- ": error creating bus space for %s\n",
- "PCI memory");
+ pq3pci_owin_record(sc, 1, &owin1);
+ if (!pq3pci_owin_init(sc, &sc->sc_pci_mem_bst, false) {
return;
}
@@ -864,10 +906,8 @@ pq3pci_cpunode_attach(device_t parent, d
bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXOTEAR2, owin2.potear);
bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXOWBAR2, owin2.powbar);
bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXOWAR2, owin2.powar);
- if (!pq3pci_owin_setup(sc, 2, &owin2)) {
- aprint_error(
- ": error creating bus space for %s\n",
- "PCI I/O space");
+ pq3pci_owin_record(sc, 2, &owin1);
+ if (!pq3pci_owin_init(sc, &sc->sc_pci_io_bst, true) {
return;
}