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; }