Raspberry Pi2 kernel warnings

Svatopluk Kraus onwahe at gmail.com
Thu Nov 26 21:20:51 UTC 2015


On Thu, Nov 26, 2015 at 8:08 PM, Karl Denninger <karl at denninger.net> wrote:
> I'm getting these on a fairly consistent basis on a Pi that is talking
> to a Zwave USB stick and a serial USB interface (two instances that both
> show up as serial devices):
>
> bcm_dma0: unused DMA intr CH=3, CS=20f10027
> bcm_dma0: unused DMA intr CH=3, CS=20f10027
> bcm_dma0: unused DMA intr CH=3, CS=20f10027
> bcm_dma0: unused DMA intr CH=3, CS=20f10027
> bcm_dma0: unused DMA intr CH=3, CS=20f10027
> bcm_dma0: unused DMA intr CH=3, CS=20f10027
> bcm_dma0: unused DMA intr CH=3, CS=20f10027
> bcm_dma0: unused DMA intr CH=3, CS=20f10027
> bcm_dma0: unused DMA intr CH=3, CS=20f10027
> bcm_dma0: unused DMA intr CH=3, CS=20f10007
> bcm_dma0: unused DMA intr CH=3, CS=20f10027
> bcm_dma0: unused DMA intr CH=3, CS=20f10027
> bcm_dma0: unused DMA intr CH=3, CS=20f10007
> bcm_dma0: unused DMA intr CH=3, CS=20f10027
> bcm_dma0: unused DMA intr CH=3, CS=20f10027
> bcm_dma0: unused DMA intr CH=3, CS=20f10027
> bcm_dma0: unused DMA intr CH=3, CS=20f10007
>
> They're showing up maybe every half-hour or so.... doesn't appear to be
> doing anything bad, other than displaying the message.....
>

I'm just finished a patch which works well for me. I plan to commit it
after some more testing. The patch is attached if you want to test it
too.

Svatopluk Kraus


> --
> Karl Denninger
> karl at denninger.net <mailto:karl at denninger.net>
> /The Market Ticker/
> /[S/MIME encrypted email preferred]/
-------------- next part --------------
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_dma.c b/sys/arm/broadcom/bcm2835/bcm2835_dma.c
index 6a2967a..28df2b3 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_dma.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_dma.c
@@ -104,6 +104,15 @@ __FBSDID("$FreeBSD$");
 /* relative offset from BCM_VC_DMA0_BASE (p.39) */
 #define	BCM_DMA_CH(n)		(0x100*(n))
 
+/* channels used by GPU */
+#define	BCM_DMA_CH_BULK		0
+#define	BCM_DMA_CH_FAST1	2
+#define	BCM_DMA_CH_FAST2	3
+
+#define	BCM_DMA_CH_GPU_MASK	((1 << BCM_DMA_CH_BULK) |	\
+				 (1 << BCM_DMA_CH_FAST1) |	\
+				 (1 << BCM_DMA_CH_FAST2))
+
 /* DMA Control Block - 256bit aligned (p.40) */
 struct bcm_dma_cb {
 	uint32_t info;		/* Transfer Information */
@@ -143,6 +152,7 @@ struct bcm_dma_softc {
 };
 
 static struct bcm_dma_softc *bcm_dma_sc = NULL;
+static uint32_t bcm_dma_channel_mask;
 
 static void
 bcm_dmamap_cb(void *arg, bus_dma_segment_t *segs,
@@ -205,16 +215,32 @@ static int
 bcm_dma_init(device_t dev)
 {
 	struct bcm_dma_softc *sc = device_get_softc(dev);
-	uint32_t mask;
+	uint32_t reg;
 	struct bcm_dma_ch *ch;
 	void *cb_virt;
 	vm_paddr_t cb_phys;
 	int err;
 	int i;
 
-	/* disable and clear interrupt status */
-	bus_write_4(sc->sc_mem, BCM_DMA_ENABLE, 0);
-	bus_write_4(sc->sc_mem, BCM_DMA_INT_STATUS, 0);
+	/*
+	 * Only channels set in bcm_dma_channel_mask can be controlled by us.
+	 * The others are out of our control as well as the corresponding bits
+	 * in both BCM_DMA_ENABLE and BCM_DMA_INT_STATUS global registers. As
+	 * these registers are RW ones, there is no safe way how to write only
+	 * the bits which can be controlled by us.
+	 *
+	 * Fortunately, after reset, all channels are enabled in BCM_DMA_ENABLE
+	 * register and all statuses are cleared in BCM_DMA_INT_STATUS one.
+	 * Not touching these registers is a trade off between correct
+	 * initialization which does not count on anything and not messing up
+	 * something we have no control over.
+	 */
+	reg = bus_read_4(sc->sc_mem, BCM_DMA_ENABLE);
+	if ((reg & bcm_dma_channel_mask) != bcm_dma_channel_mask)
+		device_printf(dev, "channels are not enabled\n");
+	reg = bus_read_4(sc->sc_mem, BCM_DMA_INT_STATUS);
+	if ((reg & bcm_dma_channel_mask) != 0)
+		device_printf(dev, "statuses are not cleared\n");
 
 	/* Allocate DMA chunks control blocks */
 	/* p.40 of spec - control block should be 32-bit aligned */
@@ -227,7 +253,7 @@ bcm_dma_init(device_t dev)
 	    &sc->sc_dma_tag);
 
 	if (err) {
-		device_printf(dev, "failed allocate DMA tag");
+		device_printf(dev, "failed allocate DMA tag\n");
 		return (err);
 	}
 
@@ -235,6 +261,13 @@ bcm_dma_init(device_t dev)
 	for (i = 0; i < BCM_DMA_CH_MAX; i++) {
 		ch = &sc->sc_dma_ch[i];
 
+		bzero(ch, sizeof(struct bcm_dma_ch));
+		ch->ch = i;
+		ch->flags = BCM_DMA_CH_UNMAP;
+
+		if ((bcm_dma_channel_mask & (1 << i)) == 0)
+			continue;
+
 		err = bus_dmamem_alloc(sc->sc_dma_tag, &cb_virt,
 		    BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO,
 		    &ch->dma_map);
@@ -263,33 +296,15 @@ bcm_dma_init(device_t dev)
 			break;
 		}
 
-		bzero(ch, sizeof(struct bcm_dma_ch));
-		ch->ch = i;
 		ch->cb = cb_virt;
 		ch->vc_cb = cb_phys;
-		ch->intr_func = NULL;
-		ch->intr_arg = NULL;
-		ch->flags = BCM_DMA_CH_UNMAP;
-
 		ch->cb->info = INFO_WAIT_RESP;
+		ch->flags = BCM_DMA_CH_FREE;
 
 		/* reset DMA engine */
-		bcm_dma_reset(dev, i);
+		bus_write_4(sc->sc_mem, BCM_DMA_CS(i), CS_RESET);
 	}
 
-	/* now use DMA2/DMA3 only */
-	sc->sc_dma_ch[2].flags = BCM_DMA_CH_FREE;
-	sc->sc_dma_ch[3].flags = BCM_DMA_CH_FREE;
-
-	/* enable DMAs */
-	mask = 0;
-
-	for (i = 0; i < BCM_DMA_CH_MAX; i++)
-		if (sc->sc_dma_ch[i].flags & BCM_DMA_CH_FREE)
-			mask |= (1 << i);
-
-	bus_write_4(sc->sc_mem, BCM_DMA_ENABLE, mask);
-
 	return (0);
 }
 
@@ -599,8 +614,11 @@ bcm_dma_intr(void *arg)
 	/* my interrupt? */
 	cs = bus_read_4(sc->sc_mem, BCM_DMA_CS(ch->ch));
 
-	if (!(cs & (CS_INT | CS_ERR)))
+	if (!(cs & (CS_INT | CS_ERR))) {
+		device_printf(sc->sc_dev,
+		    "unexpected DMA intr CH=%d, CS=%x\n", ch->ch, cs);
 		return;
+	}
 
 	/* running? */
 	if (!(ch->flags & BCM_DMA_CH_USED)) {
@@ -651,6 +669,7 @@ static int
 bcm_dma_attach(device_t dev)
 {
 	struct bcm_dma_softc *sc = device_get_softc(dev);
+	phandle_t node;
 	int rid, err = 0;
 	int i;
 
@@ -664,6 +683,17 @@ bcm_dma_attach(device_t dev)
 		sc->sc_intrhand[i] = NULL;
 	}
 
+	/* Get DMA channel mask. */
+	node = ofw_bus_get_node(sc->sc_dev);
+	if (OF_getencprop(node, "broadcom,channels", &bcm_dma_channel_mask,
+	    sizeof(bcm_dma_channel_mask)) == -1) {
+		device_printf(dev, "could not get channel mask property\n");
+		return (ENXIO);
+	}
+
+	/* Mask out channels used by GPU. */
+	bcm_dma_channel_mask &= ~BCM_DMA_CH_GPU_MASK;
+
 	/* DMA0 - DMA14 */
 	rid = 0;
 	sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
@@ -674,6 +704,9 @@ bcm_dma_attach(device_t dev)
 
 	/* IRQ DMA0 - DMA11 XXX NOT USE DMA12(spurious?) */
 	for (rid = 0; rid < BCM_DMA_CH_MAX; rid++) {
+		if ((bcm_dma_channel_mask & (1 << rid)) == 0)
+			continue;
+
 		sc->sc_irq[rid] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
 						       RF_ACTIVE);
 		if (sc->sc_irq[rid] == NULL) {
@@ -681,6 +714,7 @@ bcm_dma_attach(device_t dev)
 			err = ENXIO;
 			goto fail;
 		}
+
 		if (bus_setup_intr(dev, sc->sc_irq[rid], INTR_TYPE_MISC | INTR_MPSAFE,
 				   NULL, bcm_dma_intr, &sc->sc_dma_ch[rid],
 				   &sc->sc_intrhand[rid])) {
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_dma.h b/sys/arm/broadcom/bcm2835/bcm2835_dma.h
index 785cf2c..c39344a 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_dma.h
+++ b/sys/arm/broadcom/bcm2835/bcm2835_dma.h
@@ -37,8 +37,6 @@
 /* request CH for any nubmer */
 #define	BCM_DMA_CH_INVALID	(-1)
 #define	BCM_DMA_CH_ANY		(-1)
-#define	BCM_DMA_CH_FAST1	(2)
-#define	BCM_DMA_CH_FAST2	(3)
 
 /* Peripheral DREQ Signals (4.2.1.3) */
 #define	BCM_DMA_DREQ_NONE	0
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
index ace3d74..2b522e2 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
@@ -214,11 +214,7 @@ bcm_sdhci_attach(device_t dev)
  
 	sdhci_init_slot(dev, &sc->sc_slot, 0);
 
-	sc->sc_dma_ch = bcm_dma_allocate(BCM_DMA_CH_FAST1);
-	if (sc->sc_dma_ch == BCM_DMA_CH_INVALID)
-		sc->sc_dma_ch = bcm_dma_allocate(BCM_DMA_CH_FAST2);
-	if (sc->sc_dma_ch == BCM_DMA_CH_INVALID)
-		sc->sc_dma_ch = bcm_dma_allocate(BCM_DMA_CH_ANY);
+	sc->sc_dma_ch = bcm_dma_allocate(BCM_DMA_CH_ANY);
 	if (sc->sc_dma_ch == BCM_DMA_CH_INVALID)
 		goto fail;
 


More information about the freebsd-arm mailing list