svn commit: r348804 - head/sys/arm/broadcom/bcm2835

Bjoern A. Zeeb bz at FreeBSD.org
Sat Jun 8 16:15:01 UTC 2019


Author: bz
Date: Sat Jun  8 16:15:00 2019
New Revision: 348804
URL: https://svnweb.freebsd.org/changeset/base/348804

Log:
  bcm2835_sdhci.c: exit DMA if not enough data left to avoid timeout errors
  
  In the DMA case, given we disable the data interrupts, we never seem
  to get DATA_END.  Given we are relying on DMA interrupts we are not
  using the SDHCI state machine and hence only call into
  sdhci_platform_will_handle() for the first check of data.
  We do not call "will handle" for any following round trips of the same
  transaction if block size * count > BCM_DMA_BLOCK_SIZE.
  Manually check "left" in the DMA interrupt handler to see if we have at
  least another full BCM_DMA_BLOCK_SIZE to handle.
  Without this change we would DMA that and then even start a DMA with
  left == 0 which would lead to a timeout and error.
  Now we re-enable data interrupts and return and let the SDHCI generic
  interrupt handler and state machine pick the SPACE_AVAIL up and then
  find that it should punt to the pio_handler for the remaining bytes
  or finish the data transaction.
  
  With this change block mode seems to work beyond 7 * 64byte blocks,
  which worked as it was below BCM_DMA_BLOCK_SIZE.
  
  MFC after:		2 weeks
  Differential Revision:	https://reviews.freebsd.org/D20199

Modified:
  head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c

Modified: head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
==============================================================================
--- head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c	Sat Jun  8 16:05:43 2019	(r348803)
+++ head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c	Sat Jun  8 16:15:00 2019	(r348804)
@@ -539,6 +539,22 @@ bcm_sdhci_dma_intr(int ch, void *arg)
 	left = min(BCM_SDHCI_BUFFER_SIZE,
 	    slot->curcmd->data->len - slot->offset);
 
+	/*
+	 * If there is less than buffer size outstanding, we would not handle
+	 * it anymore using DMA if bcm_sdhci_will_handle_transfer() were asked.
+	 * Re-enable interrupts and return and let the SDHCI state machine
+	 * finish the job.
+	 */
+	if (left < BCM_SDHCI_BUFFER_SIZE) {
+		/* Re-enable data interrupts. */
+		slot->intmask |= SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL |
+		    SDHCI_INT_DATA_END;
+		bcm_sdhci_write_4(slot->bus, slot, SDHCI_SIGNAL_ENABLE,
+		    slot->intmask);
+		mtx_unlock(&slot->mtx);
+		return;
+	}
+
 	/* DATA END? */
 	reg = bcm_sdhci_read_4(slot->bus, slot, SDHCI_INT_STATUS);
 


More information about the svn-src-head mailing list