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 */

Reply via email to