diff options
| author | thorpej <thorpej@NetBSD.org> | 2020-07-07 03:38:45 +0000 |
|---|---|---|
| committer | thorpej <thorpej@NetBSD.org> | 2020-07-07 03:38:45 +0000 |
| commit | e7fe2d074f6f3128ca55129e1be0e61702d117af (patch) | |
| tree | 1159375e6fb3fd74fe5b1072e94650a5737c47cb /sys/dev | |
| parent | 709a0188090cd36c7daab2dfdd03ae8e9d30f1c0 (diff) | |
Overhaul the interface to pci_configure_bus():
- Don't expose how PCI bus configuration resource management is implemented.
Provide a new resource provider API:
==> pciconf_resource_init() -- Initialize a PCI configuration resources
container.
==> pciconf_resource_add() -- Add a PCI configuration resource to the
container (I/O, MEM, or prefetchable MEM). Multiple resources of
each type may be added.
==> pciconf_resource_fini() -- Tear down the PCI configurtation resources
container once the bus has been configured.
This is much easier to use than the previous method of providing an
extent map for each kind of resource, and works better for e.g. ACPI
platforms that provide potentially multiple PCI resources in tables
provided by firmware.
- Re-implement PCI configuration resource management using vmem arenas,
rather than extent maps.
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/acpi/acpi_mcfg.c | 99 | ||||
| -rw-r--r-- | sys/dev/ic/cpc700.c | 27 | ||||
| -rw-r--r-- | sys/dev/marvell/gtpci.c | 21 | ||||
| -rw-r--r-- | sys/dev/marvell/mvpex.c | 21 | ||||
| -rw-r--r-- | sys/dev/pci/pciconf.c | 351 | ||||
| -rw-r--r-- | sys/dev/pci/pciconf.h | 31 |
6 files changed, 327 insertions, 223 deletions
diff --git a/sys/dev/acpi/acpi_mcfg.c b/sys/dev/acpi/acpi_mcfg.c index f532fc3ba88..3061a9e08e9 100644 --- a/sys/dev/acpi/acpi_mcfg.c +++ b/sys/dev/acpi/acpi_mcfg.c @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_mcfg.c,v 1.19 2020/04/13 12:08:05 jmcneill Exp $ */ +/* $NetBSD: acpi_mcfg.c,v 1.20 2020/07/07 03:38:48 thorpej Exp $ */ /*- * Copyright (C) 2015 NONAKA Kimihiro <nonaka@NetBSD.org> @@ -28,13 +28,12 @@ #include "opt_pci.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_mcfg.c,v 1.19 2020/04/13 12:08:05 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_mcfg.c,v 1.20 2020/07/07 03:38:48 thorpej Exp $"); #include <sys/param.h> #include <sys/device.h> #include <sys/kmem.h> #include <sys/systm.h> -#include <sys/extent.h> #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> @@ -694,17 +693,13 @@ out: } #ifdef PCI_NETBSD_CONFIGURE -struct acpimcfg_resource { - struct extent *ioext; - struct extent *memext; - struct extent *pmemext; -}; - static ACPI_STATUS acpimcfg_configure_bus_cb(ACPI_RESOURCE *res, void *ctx) { - struct acpimcfg_resource *pcires = ctx; - struct extent *ex; + struct pciconf_resources *pcires = ctx; + int type; + bus_addr_t addr; + bus_size_t size; const char *s; int error; @@ -722,48 +717,15 @@ acpimcfg_configure_bus_cb(ACPI_RESOURCE *res, void *ctx) if (res->Data.Address.ResourceType == ACPI_MEMORY_RANGE && res->Data.Address.Info.Mem.Caching == ACPI_PREFETCHABLE_MEMORY) { - if (pcires->pmemext == NULL) { - pcires->pmemext = extent_create("pcipmem", 0, ULONG_MAX, - NULL, 0, EX_WAITOK); - error = extent_alloc_region(pcires->pmemext, 0, ULONG_MAX, - EX_WAITOK); - if (error) { - extent_destroy(pcires->pmemext); - pcires->pmemext = NULL; - return AE_NO_MEMORY; - } - } - ex = pcires->pmemext; + type = PCICONF_RESOURCE_PREFETCHABLE_MEM; s = "prefetchable"; } else if (res->Data.Address.ResourceType == ACPI_MEMORY_RANGE && res->Data.Address.Info.Mem.Caching != ACPI_PREFETCHABLE_MEMORY) { - if (pcires->memext == NULL) { - pcires->memext = extent_create("pcimem", 0, ULONG_MAX, - NULL, 0, EX_WAITOK); - error = extent_alloc_region(pcires->memext, 0, ULONG_MAX, - EX_WAITOK); - if (error) { - extent_destroy(pcires->memext); - pcires->memext = NULL; - return AE_NO_MEMORY; - } - } - ex = pcires->memext; + type = PCICONF_RESOURCE_MEM; s = "non-prefetchable"; } else { KASSERT(res->Data.Address.ResourceType == ACPI_IO_RANGE); - if (pcires->ioext == NULL) { - pcires->ioext = extent_create("pciio", 0, ULONG_MAX, - NULL, 0, EX_WAITOK); - error = extent_alloc_region(pcires->ioext, 0, ULONG_MAX, - EX_WAITOK); - if (error) { - extent_destroy(pcires->ioext); - pcires->ioext = NULL; - return AE_NO_MEMORY; - } - } - ex = pcires->ioext; + type = PCICONF_RESOURCE_IO; s = "i/o"; } @@ -774,10 +736,8 @@ acpimcfg_configure_bus_cb(ACPI_RESOURCE *res, void *ctx) res->Data.Address16.Address.Minimum, res->Data.Address16.Address.AddressLength, s); - error = extent_free(ex, res->Data.Address16.Address.Minimum, - res->Data.Address16.Address.AddressLength, EX_WAITOK); - if (error) - return AE_NO_MEMORY; + addr = res->Data.Address16.Address.Minimum; + size = res->Data.Address16.Address.AddressLength; break; case ACPI_RESOURCE_TYPE_ADDRESS32: aprint_debug( @@ -785,10 +745,8 @@ acpimcfg_configure_bus_cb(ACPI_RESOURCE *res, void *ctx) res->Data.Address32.Address.Minimum, res->Data.Address32.Address.AddressLength, s); - error = extent_free(ex, res->Data.Address32.Address.Minimum, - res->Data.Address32.Address.AddressLength, EX_WAITOK); - if (error) - return AE_NO_MEMORY; + addr = res->Data.Address32.Address.Minimum; + size = res->Data.Address32.Address.AddressLength; break; case ACPI_RESOURCE_TYPE_ADDRESS64: aprint_debug( @@ -796,21 +754,24 @@ acpimcfg_configure_bus_cb(ACPI_RESOURCE *res, void *ctx) res->Data.Address64.Address.Minimum, res->Data.Address64.Address.AddressLength, s); - error = extent_free(ex, res->Data.Address64.Address.Minimum, - res->Data.Address64.Address.AddressLength, EX_WAITOK); - if (error) - return AE_NO_MEMORY; + addr = res->Data.Address64.Address.Minimum; + size = res->Data.Address64.Address.AddressLength; break; + + default: + return AE_OK; } - return AE_OK; + error = pciconf_resource_add(pcires, type, addr, size); + + return error == 0 ? AE_OK : AE_NO_MEMORY; } int acpimcfg_configure_bus(device_t self, pci_chipset_tag_t pc, ACPI_HANDLE handle, int bus, int cacheline_size) { - struct acpimcfg_resource res; + struct pciconf_resources *pcires; struct mcfg_segment *seg; struct mcfg_bus *mb; bus_space_handle_t bsh[256]; @@ -823,6 +784,8 @@ acpimcfg_configure_bus(device_t self, pci_chipset_tag_t pc, ACPI_HANDLE handle, if (seg == NULL) return ENOENT; + pcires = pciconf_resource_init(); + /* * Map config space for all possible busses and mark them valid during * configuration so pci_configure_bus can access them through our chipset @@ -855,15 +818,14 @@ acpimcfg_configure_bus(device_t self, pci_chipset_tag_t pc, ACPI_HANDLE handle, memset(mb->valid_devs, 0xff, sizeof(mb->valid_devs)); } - memset(&res, 0, sizeof(res)); - rv = AcpiWalkResources(handle, "_CRS", acpimcfg_configure_bus_cb, &res); + rv = AcpiWalkResources(handle, "_CRS", acpimcfg_configure_bus_cb, + pcires); if (ACPI_FAILURE(rv)) { error = ENXIO; goto cleanup; } - error = pci_configure_bus(pc, res.ioext, res.memext, res.pmemext, bus, - cacheline_size); + error = pci_configure_bus(pc, pcires, bus, cacheline_size); cleanup: /* @@ -879,12 +841,7 @@ cleanup: bus_space_unmap(seg->ms_bst, bsh[b], ACPIMCFG_SIZE_PER_BUS); } - if (res.ioext) - extent_destroy(res.ioext); - if (res.memext) - extent_destroy(res.memext); - if (res.pmemext) - extent_destroy(res.pmemext); + pciconf_resource_fini(pcires); return error; } diff --git a/sys/dev/ic/cpc700.c b/sys/dev/ic/cpc700.c index ffb0de2df9a..a3b71a7986c 100644 --- a/sys/dev/ic/cpc700.c +++ b/sys/dev/ic/cpc700.c @@ -1,4 +1,4 @@ -/* $NetBSD: cpc700.c,v 1.20 2020/06/14 01:40:06 chs Exp $ */ +/* $NetBSD: cpc700.c,v 1.21 2020/07/07 03:38:49 thorpej Exp $ */ /* * Copyright (c) 2002 The NetBSD Foundation, Inc. @@ -50,13 +50,12 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cpc700.c,v 1.20 2020/06/14 01:40:06 chs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cpc700.c,v 1.21 2020/07/07 03:38:49 thorpej Exp $"); #include "pci.h" #include "opt_pci.h" #include <sys/param.h> -#include <sys/extent.h> #include <sys/device.h> #include <sys/malloc.h> #include <sys/systm.h> @@ -88,6 +87,14 @@ static bus_space_handle_t the_cpc_handle; #define INL(a) bus_space_read_stream_4(the_cpc_tag, the_cpc_handle, (a)) #define OUTL(a, d) bus_space_write_stream_4(the_cpc_tag, the_cpc_handle, (a), d) +#define PCI_IO_START CPC_PCI_IO_START +#define PCI_IO_END CPC_PCI_IO_END +#define PCI_IO_SIZE ((PCI_IO_END - PCI_IO_START) + 1) + +#define PCI_MEM_START CPC_PCI_MEM_BASE +#define PCI_MEM_END CPC_PCI_MEM_END +#define PCI_MEM_SIZE ((PCI_MEM_END - PCI_MEM_START) + 1) + static int cpc_print(void *aux, const char *pnp) { @@ -141,7 +148,6 @@ cpc_attach(device_t self, pci_chipset_tag_t pc, bus_space_tag_t mem, { NULL, 0 } }; #if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE) - struct extent *ioext, *memext; #ifdef PCI_CONFIGURE_VERBOSE extern int pci_conf_debug; @@ -190,15 +196,14 @@ cpc_attach(device_t self, pci_chipset_tag_t pc, bus_space_tag_t mem, pci_conf_write(pc, tag, CPC_BRIDGE_OPTIONS2, v); #if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE) - ioext = extent_create("pciio", CPC_PCI_IO_START, CPC_PCI_IO_END, - NULL, 0, EX_WAITOK); - memext = extent_create("pcimem", CPC_PCI_MEM_BASE, CPC_PCI_MEM_END, - NULL, 0, EX_WAITOK); + struct pciconf_resources *pcires = pciconf_resource_init(); - pci_configure_bus(0, ioext, memext, NULL, 0, 32); + pciconf_resource_add(pcires, PCICONF_RESOURCE_IO, + PCI_IO_START, PCI_IO_SIZE); + pciconf_resource_add(pcires, PCICONF_RESOURCE_MEM, + PCI_MEM_START, PCI_MEM_SIZE); - extent_destroy(ioext); - extent_destroy(memext); + pci_configure_bus(0, pcires, 0, 32); #endif config_found_ia(self, "pcibus", &aa.pba, pcibusprint); diff --git a/sys/dev/marvell/gtpci.c b/sys/dev/marvell/gtpci.c index 7cd9f888dcf..f75761cb1ee 100644 --- a/sys/dev/marvell/gtpci.c +++ b/sys/dev/marvell/gtpci.c @@ -1,4 +1,4 @@ -/* $NetBSD: gtpci.c,v 1.33 2020/06/14 01:40:06 chs Exp $ */ +/* $NetBSD: gtpci.c,v 1.34 2020/07/07 03:38:49 thorpej Exp $ */ /* * Copyright (c) 2008, 2009 KIYOHARA Takashi * All rights reserved. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: gtpci.c,v 1.33 2020/06/14 01:40:06 chs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gtpci.c,v 1.34 2020/07/07 03:38:49 thorpej Exp $"); #include "opt_pci.h" #include "pci.h" @@ -35,7 +35,6 @@ __KERNEL_RCSID(0, "$NetBSD: gtpci.c,v 1.33 2020/06/14 01:40:06 chs Exp $"); #include <sys/bus.h> #include <sys/device.h> #include <sys/errno.h> -#include <sys/extent.h> #include <sys/malloc.h> #include <prop/proplib.h> @@ -446,22 +445,22 @@ gtpci_pci_config(struct gtpci_softc *sc, bus_space_tag_t iot, int cacheline_size) { struct pcibus_attach_args pba; -#ifdef PCI_NETBSD_CONFIGURE - struct extent *ioext = NULL, *memext = NULL; -#endif uint32_t p2pc, command; p2pc = GTPCI_READ(sc, GTPCI_P2PC); #ifdef PCI_NETBSD_CONFIGURE - ioext = extent_create("pciio", iostart, ioend, NULL, 0, EX_WAITOK); - memext = extent_create("pcimem", memstart, memend, NULL, 0, EX_WAITOK); + struct pciconf_resources *pcires = pciconf_resource_init(); + + pciconf_resource_add(pcires, PCICONF_RESOURCE_IO, + iostart, (ioend - iostart) + 1); + pciconf_resource_add(pcires, PCICONF_RESOURCE_MEM, + memstart, (memend - memstart) + 1); - pci_configure_bus(pc, ioext, memext, NULL, + pci_configure_bus(pc, pcires, GTPCI_P2PC_BUSNUMBER(p2pc), cacheline_size); - extent_destroy(ioext); - extent_destroy(memext); + pciconf_resource_fini(pcires); #endif pba.pba_iot = iot; diff --git a/sys/dev/marvell/mvpex.c b/sys/dev/marvell/mvpex.c index 97ae308840a..53f38d3b0e6 100644 --- a/sys/dev/marvell/mvpex.c +++ b/sys/dev/marvell/mvpex.c @@ -1,4 +1,4 @@ -/* $NetBSD: mvpex.c,v 1.19 2020/06/14 01:40:06 chs Exp $ */ +/* $NetBSD: mvpex.c,v 1.20 2020/07/07 03:38:49 thorpej Exp $ */ /* * Copyright (c) 2008 KIYOHARA Takashi * All rights reserved. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mvpex.c,v 1.19 2020/06/14 01:40:06 chs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mvpex.c,v 1.20 2020/07/07 03:38:49 thorpej Exp $"); #include "opt_pci.h" #include "pci.h" @@ -35,7 +35,6 @@ __KERNEL_RCSID(0, "$NetBSD: mvpex.c,v 1.19 2020/06/14 01:40:06 chs Exp $"); #include <sys/bus.h> #include <sys/device.h> #include <sys/errno.h> -#include <sys/extent.h> #include <sys/evcnt.h> #include <sys/malloc.h> #include <sys/systm.h> @@ -409,22 +408,22 @@ mvpex_pci_config(struct mvpex_softc *sc, bus_space_tag_t iot, int cacheline_size) { struct pcibus_attach_args pba; -#ifdef PCI_NETBSD_CONFIGURE - struct extent *ioext = NULL, *memext = NULL; -#endif uint32_t stat; stat = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVPEX_STAT); #ifdef PCI_NETBSD_CONFIGURE - ioext = extent_create("pexio", iostart, ioend, NULL, 0, EX_WAITOK); - memext = extent_create("pexmem", memstart, memend, NULL, 0, EX_WAITOK); + struct pciconf_resources *pcires = pciconf_resource_init(); + + pciconf_resource_add(pcires, PCICONF_RESOURCE_IO, + iostart, (ioend - iostart) + 1); + pciconf_resource_add(pcires, PCICONF_RESOURCE_MEM, + memstart, (memend - memstart) + 1); - pci_configure_bus(pc, ioext, memext, NULL, + pci_configure_bus(pc, pcires, MVPEX_STAT_PEXBUSNUM(stat), cacheline_size); - extent_destroy(ioext); - extent_destroy(memext); + pciconf_resource_fini(pcires); #endif pba.pba_iot = iot; diff --git a/sys/dev/pci/pciconf.c b/sys/dev/pci/pciconf.c index f13bbf5a0d5..cddac5844c9 100644 --- a/sys/dev/pci/pciconf.c +++ b/sys/dev/pci/pciconf.c @@ -1,4 +1,4 @@ -/* $NetBSD: pciconf.c,v 1.46 2020/02/02 14:45:14 jmcneill Exp $ */ +/* $NetBSD: pciconf.c,v 1.47 2020/07/07 03:38:49 thorpej Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -65,23 +65,23 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pciconf.c,v 1.46 2020/02/02 14:45:14 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pciconf.c,v 1.47 2020/07/07 03:38:49 thorpej Exp $"); #include "opt_pci.h" #include <sys/param.h> -#include <sys/extent.h> #include <sys/queue.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/kmem.h> +#include <sys/vmem.h> #include <dev/pci/pcivar.h> #include <dev/pci/pciconf.h> #include <dev/pci/pcidevs.h> #include <dev/pci/pccbbreg.h> -int pci_conf_debug = 0; +int pci_conf_debug = 1; #if !defined(MIN) #define MIN(a,b) (((a)<(b))?(a):(b)) @@ -95,6 +95,28 @@ int pci_conf_debug = 0; struct _s_pciconf_bus_t; /* Forward declaration */ +struct pciconf_resource { + vmem_t *arena; + bus_addr_t min_addr; + bus_addr_t max_addr; + bus_size_t total_size; +}; + +#define PCICONF_RESOURCE_NTYPES 3 +CTASSERT(PCICONF_RESOURCE_IO < PCICONF_RESOURCE_NTYPES); +CTASSERT(PCICONF_RESOURCE_MEM < PCICONF_RESOURCE_NTYPES); +CTASSERT(PCICONF_RESOURCE_PREFETCHABLE_MEM < PCICONF_RESOURCE_NTYPES); + +static const char *pciconf_resource_names[] = { + [PCICONF_RESOURCE_IO] = "pci-io", + [PCICONF_RESOURCE_MEM] = "pci-mem", + [PCICONF_RESOURCE_PREFETCHABLE_MEM] = "pci-pmem", +}; + +struct pciconf_resources { + struct pciconf_resource resources[PCICONF_RESOURCE_NTYPES]; +}; + typedef struct _s_pciconf_dev_t { int ipin; int iline; @@ -149,9 +171,9 @@ typedef struct _s_pciconf_bus_t { bus_size_t mem_total; bus_size_t pmem_total; - struct extent *ioext; - struct extent *memext; - struct extent *pmemext; + struct pciconf_resource io_res; + struct pciconf_resource mem_res; + struct pciconf_resource pmem_res; pci_chipset_tag_t pc; struct _s_pciconf_bus_t *parent_bus; @@ -165,13 +187,57 @@ static int setup_iowins(pciconf_bus_t *); static int setup_memwins(pciconf_bus_t *); static int configure_bridge(pciconf_dev_t *); static int configure_bus(pciconf_bus_t *); -static uint64_t pci_allocate_range(struct extent *, uint64_t, int, bool); +static uint64_t pci_allocate_range(struct pciconf_resource *, uint64_t, int, + bool); static pciconf_win_t *get_io_desc(pciconf_bus_t *, bus_size_t); static pciconf_win_t *get_mem_desc(pciconf_bus_t *, bus_size_t); static pciconf_bus_t *query_bus(pciconf_bus_t *, pciconf_dev_t *, int); static void print_tag(pci_chipset_tag_t, pcitag_t); +static vmem_t * +create_vmem_arena(const char *name, bus_addr_t start, bus_size_t size, + int flags) +{ + KASSERT(start < VMEM_ADDR_MAX); + KASSERT(size == 0 || + (VMEM_ADDR_MAX - start) >= (size - 1)); + + return vmem_create(name, start, size, + 1, /*quantum*/ + NULL, /*importfn*/ + NULL, /*releasefn*/ + NULL, /*source*/ + 0, /*qcache_max*/ + flags, + IPL_NONE); +} + +static int +init_range_resource(struct pciconf_resource *r, const char *name, + bus_addr_t start, bus_addr_t size) +{ + r->arena = create_vmem_arena(name, start, size, VM_NOSLEEP); + if (r->arena == NULL) + return ENOMEM; + + r->min_addr = start; + r->max_addr = start + (size - 1); + r->total_size = size; + + return 0; +} + +static void +fini_range_resource(struct pciconf_resource *r) +{ + if (r->arena) { + vmem_xfreeall(r->arena); + vmem_destroy(r->arena); + } + memset(r, 0, sizeof(*r)); +} + static void print_tag(pci_chipset_tag_t pc, pcitag_t tag) { @@ -339,9 +405,10 @@ query_bus(pciconf_bus_t *parent, pciconf_dev_t *pd, int dev) pb->swiz = parent->swiz + dev; - pb->ioext = NULL; - pb->memext = NULL; - pb->pmemext = NULL; + memset(&pb->io_res, 0, sizeof(pb->io_res)); + memset(&pb->mem_res, 0, sizeof(pb->mem_res)); + memset(&pb->pmem_res, 0, sizeof(pb->pmem_res)); + pb->pc = parent->pc; pb->io_total = pb->mem_total = pb->pmem_total = 0; @@ -709,56 +776,48 @@ pci_do_device_query(pciconf_bus_t *pb, pcitag_t tag, int dev, int func, /************************************************************************/ /************************************************************************/ static uint64_t -pci_allocate_range(struct extent * const ex, const uint64_t amt, +pci_allocate_range(struct pciconf_resource * const r, const uint64_t amt, const int align, const bool ok64 __used_only_lp64) { - int r; - u_long addr; - - u_long end = ex->ex_end; + vmem_size_t const size = (vmem_size_t) amt; + vmem_addr_t result; + int error; #ifdef _LP64 /* - * If a 64-bit range is not OK: - * ==> If the start of the range is > 4GB, allocation not possible. - * ==> If the end of the range is > (4GB-1), constrain the end. - * * If a 64-bit range IS OK, then we prefer allocating above 4GB. * - * XXX We guard this with _LP64 because extent maps use u_long + * XXX We guard this with _LP64 because vmem uses uintptr_t * internally. */ if (!ok64) { - if (ex->ex_start >= (1UL << 32)) { - printf("PCI: 32-BIT RESTRICTION, RANGE BEGINS AT %#lx\n", - ex->ex_start); - return ~0ULL; - } - if (end > 0xffffffffUL) { - end = 0xffffffffUL; - } - } else if (end > (1UL << 32)) { - u_long start4g = ex->ex_start; - if (start4g < (1UL << 32)) { - start4g = (1UL << 32); - } - r = extent_alloc_subregion(ex, start4g, end, amt, align, 0, - EX_NOWAIT, &addr); - if (r == 0) { - return addr; + error = vmem_xalloc(r->arena, size, align, 0, 0, + VMEM_ADDR_MIN, 0xffffffffUL, + VM_BESTFIT | VM_NOSLEEP, + &result); + } else { + error = vmem_xalloc(r->arena, size, align, 0, 0, + (1UL << 32), VMEM_ADDR_MAX, + VM_BESTFIT | VM_NOSLEEP, + &result); + if (error) { + error = vmem_xalloc(r->arena, size, align, 0, 0, + VMEM_ADDR_MIN, VMEM_ADDR_MAX, + VM_BESTFIT | VM_NOSLEEP, + &result); } } +#else + error = vmem_xalloc(r->arena, size, align, 0, 0, + VMEM_ADDR_MIN, 0xffffffffUL, + VM_BESTFIT | VM_NOSLEEP, + &result); #endif /* _L64 */ - r = extent_alloc_subregion(ex, ex->ex_start, end, amt, align, 0, - EX_NOWAIT, &addr); - if (r) { - printf("extent_alloc_subregion(%p, %#lx, %#lx, %#" PRIx64 ", %#x) returned %d\n", - ex, ex->ex_start, end, amt, align, r); - extent_print(ex); + if (error) return ~0ULL; - } - return addr; + + return result; } static int @@ -766,19 +825,20 @@ setup_iowins(pciconf_bus_t *pb) { pciconf_win_t *pi; pciconf_dev_t *pd; + int error; for (pi = pb->pciiowin; pi < &pb->pciiowin[pb->niowin]; pi++) { if (pi->size == 0) continue; pd = pi->dev; - if (pb->ioext == NULL) { + if (pb->io_res.arena == NULL) { /* Bus has no IO ranges, disable IO BAR */ pi->address = 0; pd->enable &= ~PCI_CONF_ENABLE_IO; goto write_ioaddr; } - pi->address = pci_allocate_range(pb->ioext, pi->size, + pi->address = pci_allocate_range(&pb->io_res, pi->size, pi->align, false); if (~pi->address == 0) { print_tag(pd->pc, pd->tag); @@ -787,12 +847,11 @@ setup_iowins(pciconf_bus_t *pb) return -1; } if (pd->ppb && pi->reg == 0) { - pd->ppb->ioext = extent_create("pciconf", pi->address, - pi->address + pi->size, NULL, 0, - EX_NOWAIT); - if (pd->ppb->ioext == NULL) { + error = init_range_resource(&pd->ppb->io_res, + "ppb-io", pi->address, pi->size); + if (error) { print_tag(pd->pc, pd->tag); - printf("Failed to alloc I/O ext. for bus %d\n", + printf("Failed to alloc I/O arena for bus %d\n", pd->ppb->busno); return -1; } @@ -822,8 +881,9 @@ setup_memwins(pciconf_bus_t *pb) pciconf_win_t *pm; pciconf_dev_t *pd; pcireg_t base; - struct extent *ex; + struct pciconf_resource *r; bool ok64; + int error; for (pm = pb->pcimemwin; pm < &pb->pcimemwin[pb->nmemwin]; pm++) { if (pm->size == 0) @@ -832,10 +892,10 @@ setup_memwins(pciconf_bus_t *pb) ok64 = false; pd = pm->dev; if (pm->prefetch) { - ex = pb->pmemext; + r = &pb->pmem_res; ok64 = pb->pmem_64bit; } else { - ex = pb->memext; + r = &pb->mem_res; ok64 = pb->mem_64bit && pd->ppb == NULL; } @@ -852,7 +912,7 @@ setup_memwins(pciconf_bus_t *pb) PCI_MAPREG_MEM_TYPE_64BIT; } - pm->address = pci_allocate_range(ex, pm->size, pm->align, + pm->address = pci_allocate_range(r, pm->size, pm->align, ok64); if (~pm->address == 0) { print_tag(pd->pc, pd->tag); @@ -863,19 +923,18 @@ setup_memwins(pciconf_bus_t *pb) return -1; } if (pd->ppb && pm->reg == 0) { - ex = extent_create("pciconf", pm->address, - pm->address + pm->size, NULL, 0, EX_NOWAIT); - if (ex == NULL) { + const char *name = pm->prefetch ? "ppb-pmem" + : "ppb-mem"; + r = pm->prefetch ? &pd->ppb->pmem_res + : &pd->ppb->mem_res; + error = init_range_resource(r, name, + pm->address, pm->size); + if (error) { print_tag(pd->pc, pd->tag); - printf("Failed to alloc MEM ext. for bus %d\n", + printf("Failed to alloc MEM arena for bus %d\n", pd->ppb->busno); return -1; } - if (pm->prefetch) - pd->ppb->pmemext = ex; - else - pd->ppb->memext = ex; - continue; } if (!ok64 && pm->address > 0xFFFFFFFFULL) { @@ -928,21 +987,21 @@ setup_memwins(pciconf_bus_t *pb) } static bool -constrain_bridge_mem_range(struct extent * const ex, +constrain_bridge_mem_range(struct pciconf_resource * const r, u_long * const base, u_long * const limit, const bool ok64 __used_only_lp64) { - *base = ex->ex_start; - *limit = ex->ex_end; + *base = r->min_addr; + *limit = r->max_addr; #ifdef _LP64 if (!ok64) { - if (ex->ex_start >= (1UL << 32)) { + if (r->min_addr >= (1UL << 32)) { return true; } - if (ex->ex_end > 0xffffffffUL) { + if (r->max_addr > 0xffffffffUL) { *limit = 0xffffffffUL; } } @@ -967,9 +1026,9 @@ configure_bridge(pciconf_dev_t *pd) pb = pd->ppb; /* Configure I/O base & limit*/ - if (pb->ioext) { - io_base = pb->ioext->ex_start; - io_limit = pb->ioext->ex_end; + if (pb->io_res.arena) { + io_base = pb->io_res.min_addr; + io_limit = pb->io_res.max_addr; } else { io_base = 0x1000; /* 4K */ io_limit = 0x0000; @@ -998,8 +1057,8 @@ configure_bridge(pciconf_dev_t *pd) /* Configure mem base & limit */ bad_range = false; - if (pb->memext) { - bad_range = constrain_bridge_mem_range(pb->memext, + if (pb->mem_res.arena) { + bad_range = constrain_bridge_mem_range(&pb->mem_res, &mem_base, &mem_limit, false); @@ -1023,8 +1082,8 @@ configure_bridge(pciconf_dev_t *pd) mem = pci_conf_read(pb->pc, pd->tag, PCI_BRIDGE_PREFETCHMEM_REG); isprefetchmem64 = PCI_BRIDGE_PREFETCHMEM_64BITS(mem); bad_range = false; - if (pb->pmemext) { - bad_range = constrain_bridge_mem_range(pb->pmemext, + if (pb->pmem_res.arena) { + bad_range = constrain_bridge_mem_range(&pb->pmem_res, &mem_base, &mem_limit, isprefetchmem64); @@ -1058,12 +1117,10 @@ configure_bridge(pciconf_dev_t *pd) rv = configure_bus(pb); - if (pb->ioext) - extent_destroy(pb->ioext); - if (pb->memext) - extent_destroy(pb->memext); - if (pb->pmemext) - extent_destroy(pb->pmemext); + fini_range_resource(&pb->io_res); + fini_range_resource(&pb->mem_res); + fini_range_resource(&pb->pmem_res); + if (rv == 0) { cmd = pci_conf_read(pd->pc, pd->tag, PCI_BRIDGE_CONTROL_REG); cmd &= ~PCI_BRIDGE_CONTROL; /* Clear control bit first */ @@ -1191,27 +1248,20 @@ configure_bus(pciconf_bus_t *pb) } static bool -mem_region_ok64(struct extent * const ex __used_only_lp64) +mem_region_ok64(struct pciconf_resource * const r __used_only_lp64) { bool rv = false; #ifdef _LP64 /* - * XXX We need to guard this with _LP64 because - * extent maps use u_long internally. + * XXX We need to guard this with _LP64 because vmem uses + * uintptr_t internally. */ - u_long addr64; - if (ex->ex_end > (1UL << 32) && - extent_alloc_subregion(ex, MAX((1UL << 32), ex->ex_start), - ex->ex_end, - 1 /* size */, - 1 /* alignment */, - 0 /* boundary */, - EX_NOWAIT, - &addr64) == 0) { - (void) extent_free(ex, addr64, - 1 /* size */, - EX_NOWAIT); + vmem_size_t result; + if (vmem_xalloc(r->arena, 1/*size*/, 1/*align*/, 0/*phase*/, + 0/*nocross*/, (1UL << 32), VMEM_ADDR_MAX, + VM_INSTANTFIT | VM_NOSLEEP, &result) == 0) { + vmem_free(r->arena, result, 1); rv = true; } #endif /* _LP64 */ @@ -1220,6 +1270,81 @@ mem_region_ok64(struct extent * const ex __used_only_lp64) } /* + * pciconf_resource_init: + * + * Allocate and initilize a pci configuration resources container. + */ +struct pciconf_resources * +pciconf_resource_init(void) +{ + struct pciconf_resources *rs; + + rs = kmem_zalloc(sizeof(*rs), KM_SLEEP); + + return (rs); +} + +/* + * pciconf_resource_fini: + * + * Dispose of a pci configuration resources container. + */ +void +pciconf_resource_fini(struct pciconf_resources *rs) +{ + int i; + + for (i = 0; i < PCICONF_RESOURCE_NTYPES; i++) { + fini_range_resource(&rs->resources[i]); + } + + kmem_free(rs, sizeof(*rs)); +} + +/* + * pciconf_resource_add: + * + * Add a pci configuration resource to a container. + */ +int +pciconf_resource_add(struct pciconf_resources *rs, int type, + bus_addr_t start, bus_size_t size) +{ + bus_addr_t end = start + (size - 1); + struct pciconf_resource *r; + int error; + bool first; + + if (size == 0 || end <= start) + return EINVAL; + + if (type < 0 || type >= PCICONF_RESOURCE_NTYPES) + return EINVAL; + + r = &rs->resources[type]; + + first = r->arena == NULL; + if (first) { + r->arena = create_vmem_arena(pciconf_resource_names[type], + 0, 0, VM_SLEEP); + r->min_addr = VMEM_ADDR_MAX; + r->max_addr = VMEM_ADDR_MIN; + } + + error = vmem_add(r->arena, start, size, VM_SLEEP); + if (error == 0) { + if (start < r->min_addr) + r->min_addr = start; + if (end > r->max_addr) + r->max_addr = end; + } + + r->total_size += size; + + return 0; +} + +/* * Let's configure the PCI bus. * This consists of basically scanning for all existing devices, * identifying their needs, and then making another pass over them @@ -1247,9 +1372,8 @@ mem_region_ok64(struct extent * const ex __used_only_lp64) * bridges are probed and configured recursively. */ int -pci_configure_bus(pci_chipset_tag_t pc, struct extent *ioext, - struct extent *memext, struct extent *pmemext, int firstbus, - int cacheline_size) +pci_configure_bus(pci_chipset_tag_t pc, struct pciconf_resources *rs, + int firstbus, int cacheline_size) { pciconf_bus_t *pb; int rv; @@ -1262,19 +1386,22 @@ pci_configure_bus(pci_chipset_tag_t pc, struct extent *ioext, pb->parent_bus = NULL; pb->swiz = 0; pb->io_32bit = 1; - pb->ioext = ioext; - pb->memext = memext; - if (pmemext == NULL) - pb->pmemext = memext; - else - pb->pmemext = pmemext; + pb->io_res = rs->resources[PCICONF_RESOURCE_IO]; + + pb->mem_res = rs->resources[PCICONF_RESOURCE_MEM]; + if (pb->mem_res.arena == NULL) + pb->mem_res = rs->resources[PCICONF_RESOURCE_PREFETCHABLE_MEM]; + + pb->pmem_res = rs->resources[PCICONF_RESOURCE_PREFETCHABLE_MEM]; + if (pb->pmem_res.arena == NULL) + pb->pmem_res = rs->resources[PCICONF_RESOURCE_MEM]; /* - * Probe the memory region extent maps to see - * if allocation of 64-bit addresses is possible. + * Probe the memory region arenas to see if allocation of + * 64-bit addresses is possible. */ - pb->mem_64bit = mem_region_ok64(pb->memext); - pb->pmem_64bit = mem_region_ok64(pb->pmemext); + pb->mem_64bit = mem_region_ok64(&pb->mem_res); + pb->pmem_64bit = mem_region_ok64(&pb->pmem_res); pb->pc = pc; pb->io_total = pb->mem_total = pb->pmem_total = 0; diff --git a/sys/dev/pci/pciconf.h b/sys/dev/pci/pciconf.h index 66b563cbf7e..5afad055649 100644 --- a/sys/dev/pci/pciconf.h +++ b/sys/dev/pci/pciconf.h @@ -1,4 +1,4 @@ -/* $NetBSD: pciconf.h,v 1.13 2020/06/17 13:09:16 thorpej Exp $ */ +/* $NetBSD: pciconf.h,v 1.14 2020/07/07 03:38:49 thorpej Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -35,15 +35,30 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/extent.h> +#ifndef _DEV_PCI_PCICONF_H_ +#define _DEV_PCI_PCICONF_H_ + +#include <sys/vmem.h> + +struct pciconf_resources; + +#define PCICONF_RESOURCE_IO 0 +#define PCICONF_RESOURCE_MEM 1 +#define PCICONF_RESOURCE_PREFETCHABLE_MEM 2 + +struct pciconf_resources * + pciconf_resource_init(void); +void pciconf_resource_fini(struct pciconf_resources *); +int pciconf_resource_add(struct pciconf_resources *, int, + bus_addr_t, bus_size_t); /* - * args: pci_chipset_tag_t, io_extent, mem_extent, pmem_extent - * where pmem_extent is "pre-fetchable" memory -- if NULL, mem_extent will - * be used for both + * args: pci_chipset_tag_t, resources, firstbus, cacheline_size + * If no prefetchable memory resources are available, plain memory resources + * will be used for both. */ -int pci_configure_bus(pci_chipset_tag_t, struct extent *, - struct extent *, struct extent *, int, int); +int pci_configure_bus(pci_chipset_tag_t, struct pciconf_resources *, + int, int); /* Defined in machdep code. Returns the interrupt line to set */ /* args: chipset_tag, bus, dev, ipin, swiz, ptr to interrupt line */ @@ -62,3 +77,5 @@ void pci_conf_interrupt(pci_chipset_tag_t, int, int, int, int, int *); #define PCI_CONF_ENABLE_ROM 0x0100 #define PCI_CONF_DEFAULT 0x00ff #define PCI_CONF_ALL 0x01ff + +#endif /* _DEV_PCI_PCICONF_H_ */ |
