Module Name: src Committed By: jmcneill Date: Mon Oct 14 22:59:15 UTC 2019
Modified Files: src/sys/arch/arm/acpi: acpi_pci_machdep.c acpi_pci_machdep.h acpipchb.c Log Message: More Amazon Graviton quirks: - Ignore devno > 0 on the PCIe root port. - Fixup PCIe bridge bus number register on the root port. - Move quirk handling to acpipchb so it can be applied before the bus is configured. To generate a diff of this commit: cvs rdiff -u -r1.10 -r1.11 src/sys/arch/arm/acpi/acpi_pci_machdep.c \ src/sys/arch/arm/acpi/acpipchb.c cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/acpi/acpi_pci_machdep.h 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/arm/acpi/acpi_pci_machdep.c diff -u src/sys/arch/arm/acpi/acpi_pci_machdep.c:1.10 src/sys/arch/arm/acpi/acpi_pci_machdep.c:1.11 --- src/sys/arch/arm/acpi/acpi_pci_machdep.c:1.10 Mon Oct 14 00:16:29 2019 +++ src/sys/arch/arm/acpi/acpi_pci_machdep.c Mon Oct 14 22:59:15 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_pci_machdep.c,v 1.10 2019/10/14 00:16:29 jmcneill Exp $ */ +/* $NetBSD: acpi_pci_machdep.c,v 1.11 2019/10/14 22:59:15 jmcneill Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_pci_machdep.c,v 1.10 2019/10/14 00:16:29 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_pci_machdep.c,v 1.11 2019/10/14 22:59:15 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -60,120 +60,6 @@ __KERNEL_RCSID(0, "$NetBSD: acpi_pci_mac #include <arm/pci/pci_msi_machdep.h> -static int -acpi_pci_amazon_graviton_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t *data) -{ - struct acpi_pci_context *ap = pc->pc_conf_v; - bus_size_t off; - int b, d, f; - - pci_decompose_tag(pc, tag, &b, &d, &f); - - if (ap->ap_bus == b) { - if (d > 0) { - *data = -1; - return EINVAL; - } - off = f * PCI_EXTCONF_SIZE + reg; - *data = bus_space_read_4(ap->ap_bst, ap->ap_conf_bsh, off); - return 0; - } - - return acpimcfg_conf_read(pc, tag, reg, data); -} - -static int -acpi_pci_amazon_graviton_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) -{ - struct acpi_pci_context *ap = pc->pc_conf_v; - bus_size_t off; - int b, d, f; - - pci_decompose_tag(pc, tag, &b, &d, &f); - - if (ap->ap_bus == b) { - if (d > 0) { - return EINVAL; - } - off = f * PCI_EXTCONF_SIZE + reg; - bus_space_write_4(ap->ap_bst, ap->ap_conf_bsh, off, data); - return 0; - } - - return acpimcfg_conf_write(pc, tag, reg, data); -} - -static ACPI_STATUS -acpi_pci_amazon_graviton_map(ACPI_HANDLE handle, UINT32 level, void *ctx, void **retval) -{ - struct acpi_pci_context *ap = ctx; - struct acpi_resources res; - struct acpi_mem *mem; - ACPI_STATUS rv; - int error; - - rv = acpi_resource_parse(ap->ap_dev, handle, "_CRS", &res, &acpi_resource_parse_ops_quiet); - if (ACPI_FAILURE(rv)) - return rv; - - mem = acpi_res_mem(&res, 0); - if (mem == NULL) { - acpi_resource_cleanup(&res); - return AE_NOT_FOUND; - } - - error = bus_space_map(ap->ap_bst, mem->ar_base, mem->ar_length, 0, &ap->ap_conf_bsh); - if (error != 0) - return AE_NO_MEMORY; - - return AE_CTRL_TERMINATE; -} - -static void -acpi_pci_amazon_graviton_init(struct pcibus_attach_args *pba) -{ - struct acpi_pci_context *ap = pba->pba_pc->pc_conf_v; - ACPI_STATUS rv; - - rv = AcpiGetDevices(__UNCONST("AMZN0001"), acpi_pci_amazon_graviton_map, ap, NULL); - if (ACPI_FAILURE(rv)) - return; - - ap->ap_conf_read = acpi_pci_amazon_graviton_conf_read; - ap->ap_conf_write = acpi_pci_amazon_graviton_conf_write; -} - -static const struct acpi_pci_quirk { - const char q_oemid[ACPI_OEM_ID_SIZE+1]; - const char q_oemtableid[ACPI_OEM_TABLE_ID_SIZE+1]; - uint32_t q_oemrevision; - void (*q_init)(struct pcibus_attach_args *); -} acpi_pci_quirks[] = { - { "AMAZON", "GRAVITON", 0, acpi_pci_amazon_graviton_init }, -}; - -static const struct acpi_pci_quirk * -acpi_pci_find_quirk(void) -{ - ACPI_STATUS rv; - ACPI_TABLE_MCFG *mcfg; - u_int n; - - rv = AcpiGetTable(ACPI_SIG_MCFG, 0, (ACPI_TABLE_HEADER **)&mcfg); - if (ACPI_FAILURE(rv)) - return NULL; - - for (n = 0; n < __arraycount(acpi_pci_quirks); n++) { - const struct acpi_pci_quirk *q = &acpi_pci_quirks[n]; - if (memcmp(q->q_oemid, mcfg->Header.OemId, ACPI_OEM_ID_SIZE) == 0 && - memcmp(q->q_oemtableid, mcfg->Header.OemTableId, ACPI_OEM_TABLE_ID_SIZE) == 0 && - q->q_oemrevision == mcfg->Header.OemRevision) - return q; - } - - return NULL; -} - struct acpi_pci_prt { u_int prt_segment; u_int prt_bus; @@ -274,7 +160,6 @@ acpi_pci_md_attach_hook(device_t parent, { struct acpi_pci_context *ap = pba->pba_pc->pc_conf_v; struct acpi_pci_prt *prt, *prtp; - const struct acpi_pci_quirk *q; struct acpi_devnode *ad; ACPI_HANDLE handle; int seg, bus, dev, func; @@ -317,10 +202,6 @@ acpi_pci_md_attach_hook(device_t parent, TAILQ_INSERT_TAIL(&acpi_pci_irq_routes, prt, prt_list); } - q = acpi_pci_find_quirk(); - if (q != NULL) - q->q_init(pba); - acpimcfg_map_bus(self, pba->pba_pc, pba->pba_bus); if (ad != NULL) { @@ -334,6 +215,11 @@ acpi_pci_md_attach_hook(device_t parent, static int acpi_pci_md_bus_maxdevs(void *v, int busno) { + struct acpi_pci_context * const ap = v; + + if (ap->ap_bus_maxdevs != NULL) + return ap->ap_bus_maxdevs(ap, busno); + return 32; } Index: src/sys/arch/arm/acpi/acpipchb.c diff -u src/sys/arch/arm/acpi/acpipchb.c:1.10 src/sys/arch/arm/acpi/acpipchb.c:1.11 --- src/sys/arch/arm/acpi/acpipchb.c:1.10 Mon Oct 14 00:16:29 2019 +++ src/sys/arch/arm/acpi/acpipchb.c Mon Oct 14 22:59:15 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: acpipchb.c,v 1.10 2019/10/14 00:16:29 jmcneill Exp $ */ +/* $NetBSD: acpipchb.c,v 1.11 2019/10/14 22:59:15 jmcneill Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpipchb.c,v 1.10 2019/10/14 00:16:29 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpipchb.c,v 1.11 2019/10/14 22:59:15 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -92,6 +92,174 @@ struct acpipchb_softc { struct acpipchb_bus_space sc_pciio_bst; }; +static int +acpipchb_amazon_graviton_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t *data) +{ + struct acpi_pci_context *ap = pc->pc_conf_v; + int b, d, f; + + pci_decompose_tag(pc, tag, &b, &d, &f); + + if (ap->ap_bus == b) { + if (d > 0 || f > 0) { + *data = -1; + return EINVAL; + } + *data = bus_space_read_4(ap->ap_bst, ap->ap_conf_bsh, reg); + return 0; + } + + return acpimcfg_conf_read(pc, tag, reg, data); +} + +static int +acpipchb_amazon_graviton_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) +{ + struct acpi_pci_context *ap = pc->pc_conf_v; + int b, d, f; + + pci_decompose_tag(pc, tag, &b, &d, &f); + + if (ap->ap_bus == b) { + if (d > 0 || f > 0) { + return EINVAL; + } + bus_space_write_4(ap->ap_bst, ap->ap_conf_bsh, reg, data); + return 0; + } + + return acpimcfg_conf_write(pc, tag, reg, data); +} + +static int +acpipchb_amazon_graviton_bus_maxdevs(struct acpi_pci_context *ap, int busno) +{ + if (busno == ap->ap_bus + 1) + return 1; + + return 32; +} + +static ACPI_STATUS +acpipchb_amazon_graviton_map(ACPI_HANDLE handle, UINT32 level, void *ctx, void **retval) +{ + struct acpi_pci_context *ap = ctx; + struct acpi_resources res; + struct acpi_mem *mem; + ACPI_STATUS rv; + int error; + + rv = acpi_resource_parse(ap->ap_dev, handle, "_CRS", &res, &acpi_resource_parse_ops_quiet); + if (ACPI_FAILURE(rv)) + return rv; + + mem = acpi_res_mem(&res, 0); + if (mem == NULL) { + acpi_resource_cleanup(&res); + return AE_NOT_FOUND; + } + + error = bus_space_map(ap->ap_bst, mem->ar_base, mem->ar_length, 0, &ap->ap_conf_bsh); + if (error != 0) + return AE_NO_MEMORY; + + return AE_CTRL_TERMINATE; +} + +static ACPI_STATUS +acpipchb_amazon_graviton_busres(ACPI_RESOURCE *res, void *context) +{ + if (res->Type != ACPI_RESOURCE_TYPE_ADDRESS16) + return AE_OK; + if (res->Data.Address16.ResourceType != ACPI_BUS_NUMBER_RANGE) + return AE_OK; + + *(ACPI_RESOURCE *)context = *res; + return AE_CTRL_TERMINATE; +} + +static void +acpipchb_amazon_graviton_init(struct acpi_pci_context *ap) +{ + ACPI_STATUS rv; + ACPI_RESOURCE res; + pcitag_t tag; + pcireg_t busdata; + + rv = AcpiGetDevices(__UNCONST("AMZN0001"), acpipchb_amazon_graviton_map, ap, NULL); + if (ACPI_FAILURE(rv)) + return; + + ap->ap_conf_read = acpipchb_amazon_graviton_conf_read; + ap->ap_conf_write = acpipchb_amazon_graviton_conf_write; + ap->ap_bus_maxdevs = acpipchb_amazon_graviton_bus_maxdevs; + + /* + * The root port's may not have the correct bus information. Fix this up... + */ + /* Find bus number range */ + memset(&res, 0, sizeof(res)); + rv = AcpiWalkResources(ap->ap_handle, "_CRS", acpipchb_amazon_graviton_busres, &res); + if (ACPI_FAILURE(rv) || res.Type != ACPI_RESOURCE_TYPE_ADDRESS16) + return; + + const int bus_primary = res.Data.Address16.Address.Minimum; + const int bus_secondary = bus_primary + 1; + const int bus_subordinate = res.Data.Address16.Address.Maximum; + + tag = pci_make_tag(&ap->ap_pc, ap->ap_bus, 0, 0); + busdata = pci_conf_read(&ap->ap_pc, tag, PCI_BRIDGE_BUS_REG); + if (PCI_BRIDGE_BUS_NUM_PRIMARY(busdata) != bus_primary || + PCI_BRIDGE_BUS_NUM_SECONDARY(busdata) != bus_secondary || + PCI_BRIDGE_BUS_NUM_SUBORDINATE(busdata) != bus_subordinate) { + + aprint_normal_dev(ap->ap_dev, + "fixup bridge bus numbers %#x/%#x/%#x -> %#x/%#x/%#x\n", + PCI_BRIDGE_BUS_NUM_PRIMARY(busdata), + PCI_BRIDGE_BUS_NUM_SECONDARY(busdata), + PCI_BRIDGE_BUS_NUM_SUBORDINATE(busdata), + bus_primary, bus_secondary, bus_subordinate); + busdata &= ~PCI_BRIDGE_BUS_PRIMARY; + busdata |= __SHIFTIN(bus_primary, PCI_BRIDGE_BUS_PRIMARY); + busdata &= ~PCI_BRIDGE_BUS_SECONDARY; + busdata |= __SHIFTIN(bus_secondary, PCI_BRIDGE_BUS_SECONDARY); + busdata &= ~PCI_BRIDGE_BUS_SUBORDINATE; + busdata |= __SHIFTIN(bus_subordinate, PCI_BRIDGE_BUS_SUBORDINATE); + pci_conf_write(&ap->ap_pc, tag, PCI_BRIDGE_BUS_REG, busdata); + } +} + +static const struct acpipchb_quirk { + const char q_oemid[ACPI_OEM_ID_SIZE+1]; + const char q_oemtableid[ACPI_OEM_TABLE_ID_SIZE+1]; + uint32_t q_oemrevision; + void (*q_init)(struct acpi_pci_context *); +} acpipchb_quirks[] = { + { "AMAZON", "GRAVITON", 0, acpipchb_amazon_graviton_init }, +}; + +static const struct acpipchb_quirk * +acpipchb_find_quirk(void) +{ + ACPI_STATUS rv; + ACPI_TABLE_MCFG *mcfg; + u_int n; + + rv = AcpiGetTable(ACPI_SIG_MCFG, 0, (ACPI_TABLE_HEADER **)&mcfg); + if (ACPI_FAILURE(rv)) + return NULL; + + for (n = 0; n < __arraycount(acpipchb_quirks); n++) { + const struct acpipchb_quirk *q = &acpipchb_quirks[n]; + if (memcmp(q->q_oemid, mcfg->Header.OemId, ACPI_OEM_ID_SIZE) == 0 && + memcmp(q->q_oemtableid, mcfg->Header.OemTableId, ACPI_OEM_TABLE_ID_SIZE) == 0 && + q->q_oemrevision == mcfg->Header.OemRevision) + return q; + } + + return NULL; +} + static int acpipchb_match(device_t, cfdata_t, void *); static void acpipchb_attach(device_t, device_t, void *); @@ -122,6 +290,7 @@ acpipchb_attach(device_t parent, device_ struct acpipchb_softc * const sc = device_private(self); struct acpi_attach_args *aa = aux; struct pcibus_attach_args pba; + const struct acpipchb_quirk *q; ACPI_INTEGER cca, seg; sc->sc_dev = self; @@ -148,9 +317,14 @@ acpipchb_attach(device_t parent, device_ sc->sc_ap.ap_pc = *aa->aa_pc; sc->sc_ap.ap_pc.pc_conf_v = &sc->sc_ap; sc->sc_ap.ap_seg = seg; + sc->sc_ap.ap_handle = sc->sc_handle; sc->sc_ap.ap_bus = sc->sc_bus; sc->sc_ap.ap_bst = sc->sc_memt; + q = acpipchb_find_quirk(); + if (q != NULL) + q->q_init(&sc->sc_ap); + if (acpi_pci_ignore_boot_config(sc->sc_handle)) { if (acpimcfg_configure_bus(self, &sc->sc_ap.ap_pc, sc->sc_handle, sc->sc_bus, PCIHOST_CACHELINE_SIZE) != 0) aprint_error_dev(self, "failed to configure bus\n"); Index: src/sys/arch/arm/acpi/acpi_pci_machdep.h diff -u src/sys/arch/arm/acpi/acpi_pci_machdep.h:1.3 src/sys/arch/arm/acpi/acpi_pci_machdep.h:1.4 --- src/sys/arch/arm/acpi/acpi_pci_machdep.h:1.3 Mon Oct 14 00:16:29 2019 +++ src/sys/arch/arm/acpi/acpi_pci_machdep.h Mon Oct 14 22:59:15 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_pci_machdep.h,v 1.3 2019/10/14 00:16:29 jmcneill Exp $ */ +/* $NetBSD: acpi_pci_machdep.h,v 1.4 2019/10/14 22:59:15 jmcneill Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -39,10 +39,12 @@ struct acpi_pci_context { device_t ap_dev; u_int ap_seg; int ap_bus; + ACPI_HANDLE ap_handle; bus_space_tag_t ap_bst; bus_space_handle_t ap_conf_bsh; int (*ap_conf_read)(pci_chipset_tag_t, pcitag_t, int, pcireg_t *); int (*ap_conf_write)(pci_chipset_tag_t, pcitag_t, int, pcireg_t); + int (*ap_bus_maxdevs)(struct acpi_pci_context *, int); }; #endif /* !_ARM_ACPI_PCI_MACHDEP_H */