Skip to content

Commit 5f52c35

Browse files
lyakhcjb
authored andcommitted
mmc: tmio: use PIO for short transfers
This patch allows transferring of some requests in PIO and some in DMA mode and defaults to using DMA only for transfers longer than 8 bytes. This is especially useful with SDIO, which can have lots of 2- and 4-byte transfers, creating unnecessary high overhead, when executed in DMA. Signed-off-by: Guennadi Liakhovetski <[email protected]> Acked-by: Paul Mundt <[email protected]> Signed-off-by: Chris Ball <[email protected]>
1 parent 51fc7b2 commit 5f52c35

File tree

1 file changed

+23
-10
lines changed

1 file changed

+23
-10
lines changed

drivers/mmc/host/tmio_mmc.c

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@
100100
TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT)
101101
#define TMIO_MASK_IRQ (TMIO_MASK_READOP | TMIO_MASK_WRITEOP | TMIO_MASK_CMD)
102102

103+
#define TMIO_MIN_DMA_LEN 8
104+
103105
#define enable_mmc_irqs(host, i) \
104106
do { \
105107
u32 mask;\
@@ -147,6 +149,7 @@ struct tmio_mmc_host {
147149
struct platform_device *pdev;
148150

149151
/* DMA support */
152+
bool force_pio;
150153
struct dma_chan *chan_rx;
151154
struct dma_chan *chan_tx;
152155
struct tasklet_struct dma_complete;
@@ -385,6 +388,7 @@ static void tmio_mmc_reset_work(struct work_struct *work)
385388
host->cmd = NULL;
386389
host->data = NULL;
387390
host->mrq = NULL;
391+
host->force_pio = false;
388392

389393
spin_unlock_irqrestore(&host->lock, flags);
390394

@@ -404,6 +408,7 @@ tmio_mmc_finish_request(struct tmio_mmc_host *host)
404408
host->mrq = NULL;
405409
host->cmd = NULL;
406410
host->data = NULL;
411+
host->force_pio = false;
407412

408413
cancel_delayed_work(&host->delayed_reset_work);
409414

@@ -485,7 +490,7 @@ static void tmio_mmc_pio_irq(struct tmio_mmc_host *host)
485490
unsigned int count;
486491
unsigned long flags;
487492

488-
if (host->chan_tx || host->chan_rx) {
493+
if ((host->chan_tx || host->chan_rx) && !host->force_pio) {
489494
pr_err("PIO IRQ in DMA mode!\n");
490495
return;
491496
} else if (!data) {
@@ -551,15 +556,11 @@ static void tmio_mmc_do_data_irq(struct tmio_mmc_host *host)
551556
*/
552557

553558
if (data->flags & MMC_DATA_READ) {
554-
if (!host->chan_rx)
555-
disable_mmc_irqs(host, TMIO_MASK_READOP);
556-
else
559+
if (host->chan_rx && !host->force_pio)
557560
tmio_check_bounce_buffer(host);
558561
dev_dbg(&host->pdev->dev, "Complete Rx request %p\n",
559562
host->mrq);
560563
} else {
561-
if (!host->chan_tx)
562-
disable_mmc_irqs(host, TMIO_MASK_WRITEOP);
563564
dev_dbg(&host->pdev->dev, "Complete Tx request %p\n",
564565
host->mrq);
565566
}
@@ -583,7 +584,7 @@ static void tmio_mmc_data_irq(struct tmio_mmc_host *host)
583584
if (!data)
584585
goto out;
585586

586-
if (host->chan_tx && (data->flags & MMC_DATA_WRITE)) {
587+
if (host->chan_tx && (data->flags & MMC_DATA_WRITE) && !host->force_pio) {
587588
/*
588589
* Has all data been written out yet? Testing on SuperH showed,
589590
* that in most cases the first interrupt comes already with the
@@ -596,11 +597,12 @@ static void tmio_mmc_data_irq(struct tmio_mmc_host *host)
596597
disable_mmc_irqs(host, TMIO_STAT_DATAEND);
597598
tasklet_schedule(&host->dma_complete);
598599
}
599-
} else if (host->chan_rx && (data->flags & MMC_DATA_READ)) {
600+
} else if (host->chan_rx && (data->flags & MMC_DATA_READ) && !host->force_pio) {
600601
disable_mmc_irqs(host, TMIO_STAT_DATAEND);
601602
tasklet_schedule(&host->dma_complete);
602603
} else {
603604
tmio_mmc_do_data_irq(host);
605+
disable_mmc_irqs(host, TMIO_MASK_READOP | TMIO_MASK_WRITEOP);
604606
}
605607
out:
606608
spin_unlock(&host->lock);
@@ -649,12 +651,12 @@ static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host,
649651
*/
650652
if (host->data && !cmd->error) {
651653
if (host->data->flags & MMC_DATA_READ) {
652-
if (!host->chan_rx)
654+
if (host->force_pio || !host->chan_rx)
653655
enable_mmc_irqs(host, TMIO_MASK_READOP);
654656
else
655657
tasklet_schedule(&host->dma_issue);
656658
} else {
657-
if (!host->chan_tx)
659+
if (host->force_pio || !host->chan_tx)
658660
enable_mmc_irqs(host, TMIO_MASK_WRITEOP);
659661
else
660662
tasklet_schedule(&host->dma_issue);
@@ -810,6 +812,11 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
810812
goto pio;
811813
}
812814

815+
if (sg->length < TMIO_MIN_DMA_LEN) {
816+
host->force_pio = true;
817+
return;
818+
}
819+
813820
disable_mmc_irqs(host, TMIO_STAT_RXRDY);
814821

815822
/* The only sg element can be unaligned, use our bounce buffer then */
@@ -878,6 +885,11 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
878885
goto pio;
879886
}
880887

888+
if (sg->length < TMIO_MIN_DMA_LEN) {
889+
host->force_pio = true;
890+
return;
891+
}
892+
881893
disable_mmc_irqs(host, TMIO_STAT_TXRQ);
882894

883895
/* The only sg element can be unaligned, use our bounce buffer then */
@@ -1119,6 +1131,7 @@ static void tmio_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
11191131

11201132
fail:
11211133
host->mrq = NULL;
1134+
host->force_pio = false;
11221135
mrq->cmd->error = ret;
11231136
mmc_request_done(mmc, mrq);
11241137
}

0 commit comments

Comments
 (0)