sdhci: Enable only relevant (DMA/PIO) interrupts during transfers
authorAnton Vorontsov <avorontsov@ru.mvista.com>
Mon, 16 Mar 2009 21:13:50 +0000 (00:13 +0300)
committerPierre Ossman <drzeus@drzeus.cx>
Tue, 24 Mar 2009 20:30:08 +0000 (21:30 +0100)
Some hosts (that is, FSL eSDHC) throw PIO interrupts during DMA
transfers, this causes tons of unneeded interrupts, and thus highly
degraded speed.

This patch modifies the driver so that now we only enable relevant
(DMA or PIO) interrupts during transfers.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
drivers/mmc/host/sdhci.c

index bd5acfb0c1b826f00c1478ca9b0b33b7d5e9df7a..6fbbc005dd7f39d515bbe70e06c38917f73575da 100644 (file)
@@ -167,9 +167,7 @@ static void sdhci_init(struct sdhci_host *host)
                SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
                SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
                SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
-               SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL |
-               SDHCI_INT_DMA_END | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE |
-               SDHCI_INT_ADMA_ERROR);
+               SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE);
 }
 
 static void sdhci_reinit(struct sdhci_host *host)
@@ -603,6 +601,17 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data)
        return count;
 }
 
+static void sdhci_set_transfer_irqs(struct sdhci_host *host)
+{
+       u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL;
+       u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR;
+
+       if (host->flags & SDHCI_REQ_USE_DMA)
+               sdhci_clear_set_irqs(host, pio_irqs, dma_irqs);
+       else
+               sdhci_clear_set_irqs(host, dma_irqs, pio_irqs);
+}
+
 static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
 {
        u8 count;
@@ -751,6 +760,8 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
                host->blocks = data->blocks;
        }
 
+       sdhci_set_transfer_irqs(host);
+
        /* We do not handle DMA boundaries, so set it to max (512 KiB) */
        sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, data->blksz), SDHCI_BLOCK_SIZE);
        sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT);