Module Name:    src
Committed By:   jmcneill
Date:           Sat Sep 29 18:27:36 UTC 2018

Modified Files:
        src/sys/arch/arm/fdt: gicv3_fdt.c

Log Message:
Stop searching for redistributors in a region after we find a redistributor
with the Last bit set in GICR_TYPER.


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/fdt/gicv3_fdt.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/arm/fdt/gicv3_fdt.c
diff -u src/sys/arch/arm/fdt/gicv3_fdt.c:1.2 src/sys/arch/arm/fdt/gicv3_fdt.c:1.3
--- src/sys/arch/arm/fdt/gicv3_fdt.c:1.2	Sun Aug 12 21:44:17 2018
+++ src/sys/arch/arm/fdt/gicv3_fdt.c	Sat Sep 29 18:27:36 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: gicv3_fdt.c,v 1.2 2018/08/12 21:44:17 jmcneill Exp $ */
+/* $NetBSD: gicv3_fdt.c,v 1.3 2018/09/29 18:27:36 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015-2018 Jared McNeill <jmcne...@invisible.ca>
@@ -29,7 +29,7 @@
 #define	_INTR_PRIVATE
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: gicv3_fdt.c,v 1.2 2018/08/12 21:44:17 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gicv3_fdt.c,v 1.3 2018/09/29 18:27:36 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -44,6 +44,7 @@ __KERNEL_RCSID(0, "$NetBSD: gicv3_fdt.c,
 #include <dev/fdt/fdtvar.h>
 
 #include <arm/cortex/gicv3.h>
+#include <arm/cortex/gic_reg.h>
 
 #define	GICV3_MAXIRQ	1020
 
@@ -163,7 +164,7 @@ gicv3_fdt_map_registers(struct gicv3_fdt
 	bus_size_t size, region_off;
 	bus_addr_t addr;
 	size_t reg_off;
-	int n, r;
+	int n, r, max_redist, redist;
 
 	if (of_getprop_uint32(phandle, "#redistributor-regions", &redistributor_regions))
 		redistributor_regions = 1;
@@ -185,15 +186,15 @@ gicv3_fdt_map_registers(struct gicv3_fdt
 	/*
 	 * GIC Redistributors (GICR)
 	 */
-	for (reg_off = 1, n = 0; n < redistributor_regions; n++, reg_off++) {
+	for (reg_off = 1, max_redist = 0, n = 0; n < redistributor_regions; n++, reg_off++) {
 		if (fdtbus_get_reg(phandle, reg_off, NULL, &size) != 0) {
 			aprint_error_dev(gic->sc_dev, "couldn't get redistributor registers\n");
 			return ENXIO;
 		}
-		gic->sc_bsh_r_count += howmany(size, redistributor_stride);
+		max_redist += howmany(size, redistributor_stride);
 	}
-	gic->sc_bsh_r = kmem_alloc(sizeof(bus_space_handle_t) * gic->sc_bsh_r_count, KM_SLEEP);
-	for (reg_off = 1, n = 0; n < redistributor_regions; n++, reg_off++) {
+	gic->sc_bsh_r = kmem_alloc(sizeof(bus_space_handle_t) * max_redist, KM_SLEEP);
+	for (reg_off = 1, redist = 0, n = 0; n < redistributor_regions; n++, reg_off++) {
 		if (fdtbus_get_reg(phandle, reg_off, &addr, &size) != 0) {
 			aprint_error_dev(gic->sc_dev, "couldn't get redistributor registers\n");
 			return ENXIO;
@@ -204,12 +205,18 @@ gicv3_fdt_map_registers(struct gicv3_fdt
 		}
 		const int count = howmany(size, redistributor_stride);
 		for (r = 0, region_off = 0; r < count; r++, region_off += redistributor_stride) {
-			if (bus_space_subregion(sc->sc_gic.sc_bst, bsh, region_off, redistributor_stride, &gic->sc_bsh_r[r]) != 0) {
+			if (bus_space_subregion(sc->sc_gic.sc_bst, bsh, region_off, redistributor_stride, &gic->sc_bsh_r[redist++]) != 0) {
 				aprint_error_dev(gic->sc_dev, "couldn't subregion redistributor registers\n");
 				return ENXIO;
 			}
+
+			/* If this is the last redist in this region, skip to the next one */
+			const uint32_t typer = bus_space_read_4(sc->sc_gic.sc_bst, gic->sc_bsh_r[redist - 1], GICR_TYPER);
+			if (typer & GICR_TYPER_Last)
+				break;
 		}
 	}
+	gic->sc_bsh_r_count = redist;
 
 	return 0;
 }

Reply via email to