Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mmc: rtsx: add support for async request

Add support for non-blocking request, pre_req() runs dma_map_sg() and
post_req() runs dma_unmap_sg(). This patch can increase card read/write
speed, especially for high speed card and slow speed CPU.

Test on intel i3(800MHz - 2.3GHz) performance mode(2.3GHz), SD card
clock 208MHz

run dd if=/dev/mmcblk0 of=/dev/null bs=64k count=1024
before:
67108864 bytes (67 MB) copied, 0.85427 s, 78.6 MB/s
after:
67108864 bytes (67 MB) copied, 0.74799 s, 89.7 MB/s

Signed-off-by: Micky Ching <micky_ching@realsil.com.cn>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>

authored by

Micky Ching and committed by
Lee Jones
6291e715 8cd11830

+127 -6
+127 -6
drivers/mmc/host/rtsx_pci_sdmmc.c
··· 24 24 #include <linux/highmem.h> 25 25 #include <linux/delay.h> 26 26 #include <linux/platform_device.h> 27 + #include <linux/workqueue.h> 27 28 #include <linux/mmc/host.h> 28 29 #include <linux/mmc/mmc.h> 29 30 #include <linux/mmc/sd.h> ··· 37 36 struct rtsx_pcr *pcr; 38 37 struct mmc_host *mmc; 39 38 struct mmc_request *mrq; 39 + struct workqueue_struct *workq; 40 + #define SDMMC_WORKQ_NAME "rtsx_pci_sdmmc_workq" 40 41 42 + struct work_struct work; 41 43 struct mutex host_mutex; 42 44 43 45 u8 ssc_depth; ··· 52 48 int power_state; 53 49 #define SDMMC_POWER_ON 1 54 50 #define SDMMC_POWER_OFF 0 51 + 52 + unsigned int sg_count; 53 + s32 cookie; 54 + unsigned int cookie_sg_count; 55 + bool using_cookie; 55 56 }; 56 57 57 58 static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host) ··· 94 85 #else 95 86 #define sd_print_debug_regs(host) 96 87 #endif /* DEBUG */ 88 + 89 + /* 90 + * sd_pre_dma_transfer - do dma_map_sg() or using cookie 91 + * 92 + * @pre: if called in pre_req() 93 + * return: 94 + * 0 - do dma_map_sg() 95 + * 1 - using cookie 96 + */ 97 + static int sd_pre_dma_transfer(struct realtek_pci_sdmmc *host, 98 + struct mmc_data *data, bool pre) 99 + { 100 + struct rtsx_pcr *pcr = host->pcr; 101 + int read = data->flags & MMC_DATA_READ; 102 + int count = 0; 103 + int using_cookie = 0; 104 + 105 + if (!pre && data->host_cookie && data->host_cookie != host->cookie) { 106 + dev_err(sdmmc_dev(host), 107 + "error: data->host_cookie = %d, host->cookie = %d\n", 108 + data->host_cookie, host->cookie); 109 + data->host_cookie = 0; 110 + } 111 + 112 + if (pre || data->host_cookie != host->cookie) { 113 + count = rtsx_pci_dma_map_sg(pcr, data->sg, data->sg_len, read); 114 + } else { 115 + count = host->cookie_sg_count; 116 + using_cookie = 1; 117 + } 118 + 119 + if (pre) { 120 + host->cookie_sg_count = count; 121 + if (++host->cookie < 0) 122 + host->cookie = 1; 123 + data->host_cookie = host->cookie; 124 + } else { 125 + host->sg_count = count; 126 + } 127 + 128 + return using_cookie; 129 + } 130 + 131 + static void sdmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq, 132 + bool is_first_req) 133 + { 134 + struct realtek_pci_sdmmc *host = mmc_priv(mmc); 135 + struct mmc_data *data = mrq->data; 136 + 137 + if (data->host_cookie) { 138 + dev_err(sdmmc_dev(host), 139 + "error: reset data->host_cookie = %d\n", 140 + data->host_cookie); 141 + data->host_cookie = 0; 142 + } 143 + 144 + sd_pre_dma_transfer(host, data, true); 145 + dev_dbg(sdmmc_dev(host), "pre dma sg: %d\n", host->cookie_sg_count); 146 + } 147 + 148 + static void sdmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, 149 + int err) 150 + { 151 + struct realtek_pci_sdmmc *host = mmc_priv(mmc); 152 + struct rtsx_pcr *pcr = host->pcr; 153 + struct mmc_data *data = mrq->data; 154 + int read = data->flags & MMC_DATA_READ; 155 + 156 + rtsx_pci_dma_unmap_sg(pcr, data->sg, data->sg_len, read); 157 + data->host_cookie = 0; 158 + } 97 159 98 160 static int sd_read_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt, 99 161 u8 *buf, int buf_len, int timeout) ··· 495 415 496 416 rtsx_pci_send_cmd_no_wait(pcr); 497 417 498 - err = rtsx_pci_transfer_data(pcr, data->sg, data->sg_len, read, 10000); 418 + err = rtsx_pci_dma_transfer(pcr, data->sg, host->sg_count, read, 10000); 499 419 if (err < 0) { 500 420 sd_clear_error(host); 501 421 return err; ··· 720 640 return 0; 721 641 } 722 642 723 - static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) 643 + static inline int sd_rw_cmd(struct mmc_command *cmd) 724 644 { 725 - struct realtek_pci_sdmmc *host = mmc_priv(mmc); 645 + return mmc_op_multi(cmd->opcode) || 646 + (cmd->opcode == MMC_READ_SINGLE_BLOCK) || 647 + (cmd->opcode == MMC_WRITE_BLOCK); 648 + } 649 + 650 + static void sd_request(struct work_struct *work) 651 + { 652 + struct realtek_pci_sdmmc *host = container_of(work, 653 + struct realtek_pci_sdmmc, work); 726 654 struct rtsx_pcr *pcr = host->pcr; 655 + 656 + struct mmc_host *mmc = host->mmc; 657 + struct mmc_request *mrq = host->mrq; 727 658 struct mmc_command *cmd = mrq->cmd; 728 659 struct mmc_data *data = mrq->data; 660 + 729 661 unsigned int data_size = 0; 730 662 int err; 731 663 ··· 769 677 if (mrq->data) 770 678 data_size = data->blocks * data->blksz; 771 679 772 - if (!data_size || mmc_op_multi(cmd->opcode) || 773 - (cmd->opcode == MMC_READ_SINGLE_BLOCK) || 774 - (cmd->opcode == MMC_WRITE_BLOCK)) { 680 + if (!data_size || sd_rw_cmd(cmd)) { 775 681 sd_send_cmd_get_rsp(host, cmd); 776 682 777 683 if (!cmd->error && data_size) { 778 684 sd_rw_multi(host, mrq); 685 + if (!host->using_cookie) 686 + sdmmc_post_req(host->mmc, host->mrq, 0); 779 687 780 688 if (mmc_op_multi(cmd->opcode) && mrq->stop) 781 689 sd_send_cmd_get_rsp(host, mrq->stop); ··· 802 710 mutex_unlock(&host->host_mutex); 803 711 804 712 mmc_request_done(mmc, mrq); 713 + } 714 + 715 + static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) 716 + { 717 + struct realtek_pci_sdmmc *host = mmc_priv(mmc); 718 + struct mmc_data *data = mrq->data; 719 + 720 + mutex_lock(&host->host_mutex); 721 + host->mrq = mrq; 722 + mutex_unlock(&host->host_mutex); 723 + 724 + if (sd_rw_cmd(mrq->cmd)) 725 + host->using_cookie = sd_pre_dma_transfer(host, data, false); 726 + 727 + queue_work(host->workq, &host->work); 805 728 } 806 729 807 730 static int sd_set_bus_width(struct realtek_pci_sdmmc *host, ··· 1253 1146 } 1254 1147 1255 1148 static const struct mmc_host_ops realtek_pci_sdmmc_ops = { 1149 + .pre_req = sdmmc_pre_req, 1150 + .post_req = sdmmc_post_req, 1256 1151 .request = sdmmc_request, 1257 1152 .set_ios = sdmmc_set_ios, 1258 1153 .get_ro = sdmmc_get_ro, ··· 1333 1224 return -ENOMEM; 1334 1225 1335 1226 host = mmc_priv(mmc); 1227 + host->workq = create_singlethread_workqueue(SDMMC_WORKQ_NAME); 1228 + if (!host->workq) { 1229 + mmc_free_host(mmc); 1230 + return -ENOMEM; 1231 + } 1336 1232 host->pcr = pcr; 1337 1233 host->mmc = mmc; 1338 1234 host->pdev = pdev; 1339 1235 host->power_state = SDMMC_POWER_OFF; 1236 + INIT_WORK(&host->work, sd_request); 1340 1237 platform_set_drvdata(pdev, host); 1341 1238 pcr->slots[RTSX_SD_CARD].p_dev = pdev; 1342 1239 pcr->slots[RTSX_SD_CARD].card_event = rtsx_pci_sdmmc_card_event; ··· 1370 1255 pcr->slots[RTSX_SD_CARD].card_event = NULL; 1371 1256 mmc = host->mmc; 1372 1257 1258 + cancel_work_sync(&host->work); 1259 + 1373 1260 mutex_lock(&host->host_mutex); 1374 1261 if (host->mrq) { 1375 1262 dev_dbg(&(pdev->dev), ··· 1389 1272 1390 1273 mmc_remove_host(mmc); 1391 1274 host->eject = true; 1275 + 1276 + flush_workqueue(host->workq); 1277 + destroy_workqueue(host->workq); 1278 + host->workq = NULL; 1392 1279 1393 1280 mmc_free_host(mmc); 1394 1281