diff options
author | Wolfgang Muees <wolfgang.mues@auerswald.de> | 2010-03-05 16:43:40 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-06 14:26:41 -0500 |
commit | 3780d90602dfef6df3d8b39b203d6bf7fb99f22a (patch) | |
tree | a61cd2a3e8925e0a60e6fb21a973154a9c63d45b /drivers/mmc | |
parent | a04ac5b9b45a7adec7d3ee3968e677b6e4b98f25 (diff) |
mmc: at91_mci: use one coherent DMA buffer
The TX DMA buffer is allocated only once, because the
allocation/deallocation of the buffer for EACH chunk of data is
time-consuming and prone to memory fragmentation.
Using a coherent DMA buffer avoids extra data cache calls.
[nicolas.ferre@atmel.com: coding style modifications]
Signed-off-by: Wolfgang Muees <wolfgang.mues@auerswald.de>
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Cc: Andrew Victor <avictor.za@gmail.com>
Cc: <linux-mmc@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/at91_mci.c | 49 |
1 files changed, 24 insertions, 25 deletions
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c index 37efe6b3f12d..76cb05ab9341 100644 --- a/drivers/mmc/host/at91_mci.c +++ b/drivers/mmc/host/at91_mci.c | |||
@@ -88,6 +88,10 @@ | |||
88 | #define at91_mci_read(host, reg) __raw_readl((host)->baseaddr + (reg)) | 88 | #define at91_mci_read(host, reg) __raw_readl((host)->baseaddr + (reg)) |
89 | #define at91_mci_write(host, reg, val) __raw_writel((val), (host)->baseaddr + (reg)) | 89 | #define at91_mci_write(host, reg, val) __raw_writel((val), (host)->baseaddr + (reg)) |
90 | 90 | ||
91 | #define MCI_BLKSIZE 512 | ||
92 | #define MCI_MAXBLKSIZE 4095 | ||
93 | #define MCI_BLKATONCE 256 | ||
94 | #define MCI_BUFSIZE (MCI_BLKSIZE * MCI_BLKATONCE) | ||
91 | 95 | ||
92 | /* | 96 | /* |
93 | * Low level type for this driver | 97 | * Low level type for this driver |
@@ -604,7 +608,6 @@ static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command | |||
604 | /* | 608 | /* |
605 | * Handle a read | 609 | * Handle a read |
606 | */ | 610 | */ |
607 | host->buffer = NULL; | ||
608 | host->total_length = 0; | 611 | host->total_length = 0; |
609 | 612 | ||
610 | at91_mci_pre_dma_read(host); | 613 | at91_mci_pre_dma_read(host); |
@@ -623,20 +626,8 @@ static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command | |||
623 | if (host->total_length < 12) | 626 | if (host->total_length < 12) |
624 | host->total_length = 12; | 627 | host->total_length = 12; |
625 | 628 | ||
626 | host->buffer = kmalloc(host->total_length, GFP_KERNEL); | ||
627 | if (!host->buffer) { | ||
628 | pr_debug("Can't alloc tx buffer\n"); | ||
629 | cmd->error = -ENOMEM; | ||
630 | mmc_request_done(host->mmc, host->request); | ||
631 | return; | ||
632 | } | ||
633 | |||
634 | at91_mci_sg_to_dma(host, data); | 629 | at91_mci_sg_to_dma(host, data); |
635 | 630 | ||
636 | host->physical_address = dma_map_single(NULL, | ||
637 | host->buffer, host->total_length, | ||
638 | DMA_TO_DEVICE); | ||
639 | |||
640 | pr_debug("Transmitting %d bytes\n", host->total_length); | 631 | pr_debug("Transmitting %d bytes\n", host->total_length); |
641 | 632 | ||
642 | at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address); | 633 | at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address); |
@@ -703,14 +694,6 @@ static void at91_mci_completed_command(struct at91mci_host *host, unsigned int s | |||
703 | cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2)); | 694 | cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2)); |
704 | cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3)); | 695 | cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3)); |
705 | 696 | ||
706 | if (host->buffer) { | ||
707 | dma_unmap_single(NULL, | ||
708 | host->physical_address, host->total_length, | ||
709 | DMA_TO_DEVICE); | ||
710 | kfree(host->buffer); | ||
711 | host->buffer = NULL; | ||
712 | } | ||
713 | |||
714 | pr_debug("Status = %08X/%08x [%08X %08X %08X %08X]\n", | 697 | pr_debug("Status = %08X/%08x [%08X %08X %08X %08X]\n", |
715 | status, at91_mci_read(host, AT91_MCI_SR), | 698 | status, at91_mci_read(host, AT91_MCI_SR), |
716 | cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); | 699 | cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); |
@@ -1012,12 +995,12 @@ static int __init at91_mci_probe(struct platform_device *pdev) | |||
1012 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | 995 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; |
1013 | mmc->caps = MMC_CAP_SDIO_IRQ; | 996 | mmc->caps = MMC_CAP_SDIO_IRQ; |
1014 | 997 | ||
1015 | mmc->max_blk_size = 4095; | 998 | mmc->max_blk_size = MCI_MAXBLKSIZE; |
1016 | mmc->max_blk_count = mmc->max_req_size; | 999 | mmc->max_blk_count = MCI_BLKATONCE; |
1000 | mmc->max_req_size = MCI_BUFSIZE; | ||
1017 | 1001 | ||
1018 | host = mmc_priv(mmc); | 1002 | host = mmc_priv(mmc); |
1019 | host->mmc = mmc; | 1003 | host->mmc = mmc; |
1020 | host->buffer = NULL; | ||
1021 | host->bus_mode = 0; | 1004 | host->bus_mode = 0; |
1022 | host->board = pdev->dev.platform_data; | 1005 | host->board = pdev->dev.platform_data; |
1023 | if (host->board->wire4) { | 1006 | if (host->board->wire4) { |
@@ -1028,6 +1011,14 @@ static int __init at91_mci_probe(struct platform_device *pdev) | |||
1028 | " - using 1 wire\n"); | 1011 | " - using 1 wire\n"); |
1029 | } | 1012 | } |
1030 | 1013 | ||
1014 | host->buffer = dma_alloc_coherent(&pdev->dev, MCI_BUFSIZE, | ||
1015 | &host->physical_address, GFP_KERNEL); | ||
1016 | if (!host->buffer) { | ||
1017 | ret = -ENOMEM; | ||
1018 | dev_err(&pdev->dev, "Can't allocate transmit buffer\n"); | ||
1019 | goto fail5; | ||
1020 | } | ||
1021 | |||
1031 | /* | 1022 | /* |
1032 | * Reserve GPIOs ... board init code makes sure these pins are set | 1023 | * Reserve GPIOs ... board init code makes sure these pins are set |
1033 | * up as GPIOs with the right direction (input, except for vcc) | 1024 | * up as GPIOs with the right direction (input, except for vcc) |
@@ -1036,7 +1027,7 @@ static int __init at91_mci_probe(struct platform_device *pdev) | |||
1036 | ret = gpio_request(host->board->det_pin, "mmc_detect"); | 1027 | ret = gpio_request(host->board->det_pin, "mmc_detect"); |
1037 | if (ret < 0) { | 1028 | if (ret < 0) { |
1038 | dev_dbg(&pdev->dev, "couldn't claim card detect pin\n"); | 1029 | dev_dbg(&pdev->dev, "couldn't claim card detect pin\n"); |
1039 | goto fail5; | 1030 | goto fail4b; |
1040 | } | 1031 | } |
1041 | } | 1032 | } |
1042 | if (host->board->wp_pin) { | 1033 | if (host->board->wp_pin) { |
@@ -1136,6 +1127,10 @@ fail3: | |||
1136 | fail4: | 1127 | fail4: |
1137 | if (host->board->det_pin) | 1128 | if (host->board->det_pin) |
1138 | gpio_free(host->board->det_pin); | 1129 | gpio_free(host->board->det_pin); |
1130 | fail4b: | ||
1131 | if (host->buffer) | ||
1132 | dma_free_coherent(&pdev->dev, MCI_BUFSIZE, | ||
1133 | host->buffer, host->physical_address); | ||
1139 | fail5: | 1134 | fail5: |
1140 | mmc_free_host(mmc); | 1135 | mmc_free_host(mmc); |
1141 | fail6: | 1136 | fail6: |
@@ -1158,6 +1153,10 @@ static int __exit at91_mci_remove(struct platform_device *pdev) | |||
1158 | 1153 | ||
1159 | host = mmc_priv(mmc); | 1154 | host = mmc_priv(mmc); |
1160 | 1155 | ||
1156 | if (host->buffer) | ||
1157 | dma_free_coherent(&pdev->dev, MCI_BUFSIZE, | ||
1158 | host->buffer, host->physical_address); | ||
1159 | |||
1161 | if (host->board->det_pin) { | 1160 | if (host->board->det_pin) { |
1162 | if (device_can_wakeup(&pdev->dev)) | 1161 | if (device_can_wakeup(&pdev->dev)) |
1163 | free_irq(gpio_to_irq(host->board->det_pin), host); | 1162 | free_irq(gpio_to_irq(host->board->det_pin), host); |