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
This commit is contained in:
Bjoern A. Zeeb 2019-06-08 16:15:00 +00:00
parent 901491d025
commit 9c907eb913
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=348804

View File

@ -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);