svn commit: r291424 - head/sys/arm/arm

Michal Meloun mmel at FreeBSD.org
Sat Nov 28 12:09:38 UTC 2015


Author: mmel
Date: Sat Nov 28 12:09:36 2015
New Revision: 291424
URL: https://svnweb.freebsd.org/changeset/base/291424

Log:
  ARM: Cumulative fixes for GIC
   - fix detection of interrupt root controller
   - allow (but warn) unsupported configuration bits
   - dont send EOI for spurious interrupts
   - print more informations for spurious interrupts
   - use device_printf() where appropriate
  
  Reviewed by:	ian (earlier version)
  Approved by:	kib (mentor)

Modified:
  head/sys/arm/arm/gic.c

Modified: head/sys/arm/arm/gic.c
==============================================================================
--- head/sys/arm/arm/gic.c	Sat Nov 28 09:50:52 2015	(r291423)
+++ head/sys/arm/arm/gic.c	Sat Nov 28 12:09:36 2015	(r291424)
@@ -68,6 +68,8 @@ __FBSDID("$FreeBSD$");
 #include "pic_if.h"
 #endif
 
+#define GIC_DEBUG_SPURIOUS
+
 /* We are using GICv2 register naming */
 
 /* Distributor Registers */
@@ -135,6 +137,9 @@ struct arm_gic_softc {
 	uint8_t			ver;
 	struct mtx		mutex;
 	uint32_t		nirqs;
+#ifdef GIC_DEBUG_SPURIOUS
+	uint32_t		last_irq[MAXCPU];
+#endif
 };
 
 static struct resource_spec arm_gic_spec[] = {
@@ -287,7 +292,7 @@ arm_gic_init_secondary(device_t dev)
 }
 #endif /* ARM_INTRNG */
 #endif /* SMP */
- 
+
 #ifndef ARM_INTRNG
 int
 gic_decode_fdt(phandle_t iparent, pcell_t *intr, int *interrupt,
@@ -335,11 +340,10 @@ gic_decode_fdt(phandle_t iparent, pcell_
 		 */
 		if (fdt32_to_cpu(intr[2]) & 0x0a) {
 			printf("unsupported trigger/polarity configuration "
-			    "0x%2x\n", fdt32_to_cpu(intr[2]) & 0x0f);
-			return (ENOTSUP);
+			    "0x%02x\n", fdt32_to_cpu(intr[2]) & 0x0f);
 		}
 		*pol  = INTR_POLARITY_CONFORM;
-		if (fdt32_to_cpu(intr[2]) & 0x01)
+		if (fdt32_to_cpu(intr[2]) & 0x03)
 			*trig = INTR_TRIGGER_EDGE;
 		else
 			*trig = INTR_TRIGGER_LEVEL;
@@ -367,6 +371,7 @@ arm_gic_attach(device_t dev)
 	int		i;
 	uint32_t	icciidr;
 #ifdef ARM_INTRNG
+	phandle_t	pxref;
 	intptr_t	xref = gic_xref(dev);
 #endif
 
@@ -456,7 +461,9 @@ arm_gic_attach(device_t dev)
 		goto cleanup;
 	}
 
-	if (sc->gic_res[2] == NULL) {
+	i = OF_getencprop(ofw_bus_get_node(dev), "interrupt-parent",
+	    &pxref, sizeof(pxref));
+	if (i > 0 && xref == pxref) {
 		if (arm_pic_claim_root(dev, xref, arm_gic_intr, sc,
 		    GIC_LAST_SGI - GIC_FIRST_SGI + 1) != 0) {
 			device_printf(dev, "could not set PIC as a root\n");
@@ -472,6 +479,7 @@ arm_gic_attach(device_t dev)
 		}
 	}
 
+	OF_device_register_xref(xref, dev);
 	return (0);
 
 cleanup:
@@ -516,8 +524,11 @@ arm_gic_intr(void *arg)
 	 */
 
 	if (irq >= sc->nirqs) {
-		device_printf(sc->gic_dev, "Spurious interrupt detected\n");
-		gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
+#ifdef GIC_DEBUG_SPURIOUS
+		device_printf(sc->gic_dev,
+		    "Spurious interrupt detected: last irq: %d on CPU%d\n",
+		    sc->last_irq[PCPU_GET(cpuid)], PCPU_GET(cpuid));
+#endif
 		return (FILTER_HANDLED);
 	}
 
@@ -542,12 +553,16 @@ dispatch_irq:
 		arm_ipi_dispatch(isrc, tf);
 		goto next_irq;
 #else
-		printf("SGI %u on UP system detected\n", irq - GIC_FIRST_SGI);
+		device_printf(sc->gic_dev, "SGI %u on UP system detected\n",
+		    irq - GIC_FIRST_SGI);
 		gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
 		goto next_irq;
 #endif
 	}
 
+#ifdef GIC_DEBUG_SPURIOUS
+	sc->last_irq[PCPU_GET(cpuid)] = irq;
+#endif
 	if (isrc->isrc_trig == INTR_TRIGGER_EDGE)
 		gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
 
@@ -729,12 +744,12 @@ gic_map_fdt(struct arm_gic_softc *sc, st
 		 */
 		tripol = isrc->isrc_cells[2];
 		if (tripol & 0x0a) {
-			printf("unsupported trigger/polarity configuration "
-			    "0x%2x\n", tripol & 0x0f);
-			return (ENOTSUP);
+			device_printf(sc->gic_dev,
+			   "unsupported trigger/polarity configuration "
+			   "0x%02x\n",  tripol & 0x0f);
 		}
 		pol = INTR_POLARITY_CONFORM;
-		if (tripol & 0x01)
+		if (tripol & 0x03)
 			trig = INTR_TRIGGER_EDGE;
 		else
 			trig = INTR_TRIGGER_LEVEL;
@@ -911,7 +926,8 @@ arm_gic_next_irq(struct arm_gic_softc *s
 
 	if (active_irq == 0x3FF) {
 		if (last_irq == -1)
-			printf("Spurious interrupt detected\n");
+			device_printf(sc->gic_dev,
+			    "Spurious interrupt detected\n");
 		return -1;
 	}
 


More information about the svn-src-all mailing list