* [PATCH 0/5] mmc: meson-gx: add cmd23 and descriptor chain mode @ 2017-03-15 19:16 Heiner Kallweit 2017-03-15 19:33 ` [PATCH 1/5] mmc: meson-gx: switch irq name to DT node name Heiner Kallweit ` (5 more replies) 0 siblings, 6 replies; 9+ messages in thread From: Heiner Kallweit @ 2017-03-15 19:16 UTC (permalink / raw) To: linus-amlogic Apart from three minor improvements this patch series adds support for CMD23 mode and switches the driver to descriptor chain mode. On my system with a 128GB eMMC card this increased the read performance from 10 - 15 MB/s to 140 MB/s. Successfully tested on a Odroid C2 with custom uboot based on recent mainline uboot. Behavior might be different with vendor uboot. Heiner Kallweit (5): mmc: meson-gx: switch irq name to DT node name mmc: meson-gx: improve response reading mmc: meson-gx: use block mode also for just one block mmc: meson-gx: add support for CMD23 mode mmc: meson-gx: switch to descriptor chain mode drivers/mmc/host/meson-gx-mmc.c | 258 ++++++++++++++++++++++------------------ 1 file changed, 142 insertions(+), 116 deletions(-) -- 2.12.0 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/5] mmc: meson-gx: switch irq name to DT node name 2017-03-15 19:16 [PATCH 0/5] mmc: meson-gx: add cmd23 and descriptor chain mode Heiner Kallweit @ 2017-03-15 19:33 ` Heiner Kallweit 2017-03-15 19:33 ` [PATCH 2/5] mmc: meson-gx: improve response reading Heiner Kallweit ` (4 subsequent siblings) 5 siblings, 0 replies; 9+ messages in thread From: Heiner Kallweit @ 2017-03-15 19:33 UTC (permalink / raw) To: linus-amlogic So far it wasn't easy to check which interrupt belongs to which SD/eMMC port (e.g. in /proc/interrupts) because the driver name was used as description for all ports. Change this to the default which is the device name (DT node name). Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> --- drivers/mmc/host/meson-gx-mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index 62597638..f2d4486a 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -758,7 +758,7 @@ static int meson_mmc_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(&pdev->dev, irq, meson_mmc_irq, meson_mmc_irq_thread, IRQF_SHARED, - DRIVER_NAME, host); + NULL, host); if (ret) goto err_div_clk; -- 2.12.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/5] mmc: meson-gx: improve response reading 2017-03-15 19:16 [PATCH 0/5] mmc: meson-gx: add cmd23 and descriptor chain mode Heiner Kallweit 2017-03-15 19:33 ` [PATCH 1/5] mmc: meson-gx: switch irq name to DT node name Heiner Kallweit @ 2017-03-15 19:33 ` Heiner Kallweit 2017-03-15 19:34 ` [PATCH 3/5] mmc: meson-gx: use block mode also for just one block Heiner Kallweit ` (3 subsequent siblings) 5 siblings, 0 replies; 9+ messages in thread From: Heiner Kallweit @ 2017-03-15 19:33 UTC (permalink / raw) To: linus-amlogic Response is read in the main irq handler and in the threaded irq handler as well. We can slightly improve this by reading the response unconditionally at the beginning of the main irq handler only. Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> --- drivers/mmc/host/meson-gx-mmc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index f2d4486a..e675601e 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -573,6 +573,8 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) goto out; } + meson_mmc_read_resp(host->mmc, cmd); + cmd->error = 0; if (status & IRQ_RXD_ERR_MASK) { dev_dbg(host->dev, "Unhandled IRQ: RXD error\n"); @@ -619,10 +621,8 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) /* ack all (enabled) interrupts */ writel(status, host->regs + SD_EMMC_STATUS); - if (ret == IRQ_HANDLED) { - meson_mmc_read_resp(host->mmc, cmd); + if (ret == IRQ_HANDLED) meson_mmc_request_done(host->mmc, cmd->mrq); - } spin_unlock(&host->lock); return ret; @@ -647,7 +647,6 @@ static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id) data->bytes_xfered = xfer_bytes; } - meson_mmc_read_resp(host->mmc, cmd); if (!data || !data->stop || cmd->mrq->sbc) meson_mmc_request_done(host->mmc, cmd->mrq); else -- 2.12.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/5] mmc: meson-gx: use block mode also for just one block 2017-03-15 19:16 [PATCH 0/5] mmc: meson-gx: add cmd23 and descriptor chain mode Heiner Kallweit 2017-03-15 19:33 ` [PATCH 1/5] mmc: meson-gx: switch irq name to DT node name Heiner Kallweit 2017-03-15 19:33 ` [PATCH 2/5] mmc: meson-gx: improve response reading Heiner Kallweit @ 2017-03-15 19:34 ` Heiner Kallweit 2017-03-15 19:34 ` [PATCH 4/5] mmc: meson-gx: add support for CMD23 mode Heiner Kallweit ` (2 subsequent siblings) 5 siblings, 0 replies; 9+ messages in thread From: Heiner Kallweit @ 2017-03-15 19:34 UTC (permalink / raw) To: linus-amlogic Currently block mode isn't used if just one block has to be transferred. Change this to use block mode also in this case. This helps to simplify the code in function meson_mmc_start_cmd which is quite (too?) complex currently. Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> --- drivers/mmc/host/meson-gx-mmc.c | 40 +++++++++++++++------------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index e675601e..b0dc2cdd 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -458,31 +458,21 @@ static void meson_mmc_start_cmd(struct mmc_host *mmc, struct mmc_command *cmd) /* data? */ if (cmd->data) { - desc->cmd_cfg |= CMD_CFG_DATA_IO; - if (cmd->data->blocks > 1) { - desc->cmd_cfg |= CMD_CFG_BLOCK_MODE; - desc->cmd_cfg |= - (cmd->data->blocks & CMD_CFG_LENGTH_MASK) << - CMD_CFG_LENGTH_SHIFT; - - /* check if block-size matches, if not update */ - cfg = readl(host->regs + SD_EMMC_CFG); - blk_len = cfg & (CFG_BLK_LEN_MASK << CFG_BLK_LEN_SHIFT); - blk_len >>= CFG_BLK_LEN_SHIFT; - if (blk_len != ilog2(cmd->data->blksz)) { - dev_dbg(host->dev, "%s: update blk_len %d -> %d\n", - __func__, blk_len, - ilog2(cmd->data->blksz)); - blk_len = ilog2(cmd->data->blksz); - cfg &= ~(CFG_BLK_LEN_MASK << CFG_BLK_LEN_SHIFT); - cfg |= blk_len << CFG_BLK_LEN_SHIFT; - writel(cfg, host->regs + SD_EMMC_CFG); - } - } else { - desc->cmd_cfg &= ~CMD_CFG_BLOCK_MODE; - desc->cmd_cfg |= - (cmd->data->blksz & CMD_CFG_LENGTH_MASK) << - CMD_CFG_LENGTH_SHIFT; + desc->cmd_cfg |= CMD_CFG_DATA_IO | CMD_CFG_BLOCK_MODE; + desc->cmd_cfg |= (cmd->data->blocks & CMD_CFG_LENGTH_MASK) << + CMD_CFG_LENGTH_SHIFT; + + /* check if block-size matches, if not update */ + cfg = readl(host->regs + SD_EMMC_CFG); + blk_len = cfg & (CFG_BLK_LEN_MASK << CFG_BLK_LEN_SHIFT); + blk_len >>= CFG_BLK_LEN_SHIFT; + if (blk_len != ilog2(cmd->data->blksz)) { + dev_dbg(host->dev, "%s: update blk_len %d -> %d\n", + __func__, blk_len, ilog2(cmd->data->blksz)); + blk_len = ilog2(cmd->data->blksz); + cfg &= ~(CFG_BLK_LEN_MASK << CFG_BLK_LEN_SHIFT); + cfg |= blk_len << CFG_BLK_LEN_SHIFT; + writel(cfg, host->regs + SD_EMMC_CFG); } cmd->data->bytes_xfered = 0; -- 2.12.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/5] mmc: meson-gx: add support for CMD23 mode 2017-03-15 19:16 [PATCH 0/5] mmc: meson-gx: add cmd23 and descriptor chain mode Heiner Kallweit ` (2 preceding siblings ...) 2017-03-15 19:34 ` [PATCH 3/5] mmc: meson-gx: use block mode also for just one block Heiner Kallweit @ 2017-03-15 19:34 ` Heiner Kallweit 2017-03-15 19:34 ` [PATCH 5/5] mmc: meson-gx: switch to descriptor chain mode Heiner Kallweit 2017-03-24 7:27 ` [PATCH 0/5] mmc: meson-gx: add cmd23 and " Ulf Hansson 5 siblings, 0 replies; 9+ messages in thread From: Heiner Kallweit @ 2017-03-15 19:34 UTC (permalink / raw) To: linus-amlogic This patch adds CMD23 support to the meson-gx driver. Typically it's more performant if host and card know upfront how many blocks to transfer. Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> --- drivers/mmc/host/meson-gx-mmc.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index b0dc2cdd..425060da 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -175,6 +175,16 @@ struct sd_emmc_desc { #define CMD_RESP_MASK (~0x1) #define CMD_RESP_SRAM BIT(0) +static struct mmc_command *meson_mmc_get_next_command(struct mmc_command *cmd) +{ + if (cmd->opcode == MMC_SET_BLOCK_COUNT && !cmd->error) + return cmd->mrq->cmd; + else if (mmc_op_multi(cmd->opcode) && (!cmd->mrq->sbc || cmd->error)) + return cmd->mrq->stop; + else + return NULL; +} + static int meson_mmc_clk_set(struct meson_host *host, unsigned long clk_rate) { struct mmc_host *mmc = host->mmc; @@ -621,7 +631,7 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id) { struct meson_host *host = dev_id; - struct mmc_command *cmd = host->cmd; + struct mmc_command *next_cmd, *cmd = host->cmd; struct mmc_data *data; unsigned int xfer_bytes; @@ -637,10 +647,11 @@ static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id) data->bytes_xfered = xfer_bytes; } - if (!data || !data->stop || cmd->mrq->sbc) - meson_mmc_request_done(host->mmc, cmd->mrq); + next_cmd = meson_mmc_get_next_command(cmd); + if (next_cmd) + meson_mmc_start_cmd(host->mmc, next_cmd); else - meson_mmc_start_cmd(host->mmc, data->stop); + meson_mmc_request_done(host->mmc, cmd->mrq); return IRQ_HANDLED; } @@ -751,6 +762,7 @@ static int meson_mmc_probe(struct platform_device *pdev) if (ret) goto err_div_clk; + mmc->caps |= MMC_CAP_CMD23; mmc->max_blk_count = CMD_CFG_LENGTH_MASK; mmc->max_req_size = mmc->max_blk_count * mmc->max_blk_size; -- 2.12.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 5/5] mmc: meson-gx: switch to descriptor chain mode 2017-03-15 19:16 [PATCH 0/5] mmc: meson-gx: add cmd23 and descriptor chain mode Heiner Kallweit ` (3 preceding siblings ...) 2017-03-15 19:34 ` [PATCH 4/5] mmc: meson-gx: add support for CMD23 mode Heiner Kallweit @ 2017-03-15 19:34 ` Heiner Kallweit 2017-03-24 19:04 ` Kevin Hilman 2017-03-24 7:27 ` [PATCH 0/5] mmc: meson-gx: add cmd23 and " Ulf Hansson 5 siblings, 1 reply; 9+ messages in thread From: Heiner Kallweit @ 2017-03-15 19:34 UTC (permalink / raw) To: linus-amlogic Switch the driver from using a linearized bounce buffer to descriptor chain mode. This drastically improves performance. Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> --- drivers/mmc/host/meson-gx-mmc.c | 207 ++++++++++++++++++++++------------------ 1 file changed, 116 insertions(+), 91 deletions(-) diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index 425060da..d561065b 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -121,6 +121,13 @@ #define SD_EMMC_CFG_CMD_GAP 16 /* in clock cycles */ #define MUX_CLK_NUM_PARENTS 2 +struct sd_emmc_desc { + u32 cmd_cfg; + u32 cmd_arg; + u32 cmd_data; + u32 cmd_resp; +}; + struct meson_host { struct device *dev; struct mmc_host *mmc; @@ -136,19 +143,12 @@ struct meson_host { struct clk_divider cfg_div; struct clk *cfg_div_clk; - unsigned int bounce_buf_size; - void *bounce_buf; - dma_addr_t bounce_dma_addr; + struct sd_emmc_desc *descs; + dma_addr_t descs_dma_addr; bool vqmmc_enabled; }; -struct sd_emmc_desc { - u32 cmd_cfg; - u32 cmd_arg; - u32 cmd_data; - u32 cmd_resp; -}; #define CMD_CFG_LENGTH_SHIFT 0 #define CMD_CFG_LENGTH_MASK 0x1ff #define CMD_CFG_BLOCK_MODE BIT(9) @@ -185,6 +185,36 @@ static struct mmc_command *meson_mmc_get_next_command(struct mmc_command *cmd) return NULL; } +static enum dma_data_direction meson_mmc_get_data_dir(struct mmc_data *data) +{ + return data->flags & MMC_DATA_WRITE ? DMA_TO_DEVICE : DMA_FROM_DEVICE; +} + +static void meson_mmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq) +{ + struct mmc_data *data = mrq->data; + + if (!data) + return; + + data->host_cookie = true; + + data->sg_count = dma_map_sg(mmc_dev(mmc), data->sg, data->sg_len, + meson_mmc_get_data_dir(data)); + if (!data->sg_count) + dev_err(mmc_dev(mmc), "dma_map_sg failed"); +} + +static void meson_mmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, + int err) +{ + struct mmc_data *data = mrq->data; + + if (data && data->sg_count) + dma_unmap_sg(mmc_dev(mmc), data->sg, data->sg_len, + meson_mmc_get_data_dir(data)); +} + static int meson_mmc_clk_set(struct meson_host *host, unsigned long clk_rate) { struct mmc_host *mmc = host->mmc; @@ -434,94 +464,91 @@ static void meson_mmc_request_done(struct mmc_host *mmc, static void meson_mmc_start_cmd(struct mmc_host *mmc, struct mmc_command *cmd) { struct meson_host *host = mmc_priv(mmc); - struct sd_emmc_desc *desc, desc_tmp; - u32 cfg; - u8 blk_len, cmd_cfg_timeout; - unsigned int xfer_bytes = 0; - - /* Setup descriptors */ - dma_rmb(); - desc = &desc_tmp; - memset(desc, 0, sizeof(struct sd_emmc_desc)); + struct sd_emmc_desc *desc = host->descs; + struct mmc_data *data; + struct scatterlist *sg; + u32 cfg, cmd_cfg = 0; + u8 blk_len; + int i; - desc->cmd_cfg |= (cmd->opcode & CMD_CFG_CMD_INDEX_MASK) << - CMD_CFG_CMD_INDEX_SHIFT; - desc->cmd_cfg |= CMD_CFG_OWNER; /* owned by CPU */ - desc->cmd_arg = cmd->arg; + cmd_cfg |= (cmd->opcode & CMD_CFG_CMD_INDEX_MASK) << + CMD_CFG_CMD_INDEX_SHIFT; + cmd_cfg |= CMD_CFG_OWNER; /* owned by CPU */ /* Response */ if (cmd->flags & MMC_RSP_PRESENT) { - desc->cmd_cfg &= ~CMD_CFG_NO_RESP; + cmd_cfg &= ~CMD_CFG_NO_RESP; if (cmd->flags & MMC_RSP_136) - desc->cmd_cfg |= CMD_CFG_RESP_128; - desc->cmd_cfg |= CMD_CFG_RESP_NUM; - desc->cmd_resp = 0; + cmd_cfg |= CMD_CFG_RESP_128; + cmd_cfg |= CMD_CFG_RESP_NUM; if (!(cmd->flags & MMC_RSP_CRC)) - desc->cmd_cfg |= CMD_CFG_RESP_NOCRC; + cmd_cfg |= CMD_CFG_RESP_NOCRC; if (cmd->flags & MMC_RSP_BUSY) - desc->cmd_cfg |= CMD_CFG_R1B; + cmd_cfg |= CMD_CFG_R1B; } else { - desc->cmd_cfg |= CMD_CFG_NO_RESP; + cmd_cfg |= CMD_CFG_NO_RESP; } - /* data? */ - if (cmd->data) { - desc->cmd_cfg |= CMD_CFG_DATA_IO | CMD_CFG_BLOCK_MODE; - desc->cmd_cfg |= (cmd->data->blocks & CMD_CFG_LENGTH_MASK) << - CMD_CFG_LENGTH_SHIFT; + data = cmd->data; + if (data) { + data->bytes_xfered = 0; + cmd_cfg |= CMD_CFG_DATA_IO | CMD_CFG_BLOCK_MODE; + cmd_cfg |= ilog2(SD_EMMC_CMD_TIMEOUT_DATA) << + CMD_CFG_TIMEOUT_SHIFT; + + if (data->flags & MMC_DATA_WRITE) + cmd_cfg |= CMD_CFG_DATA_WR; /* check if block-size matches, if not update */ cfg = readl(host->regs + SD_EMMC_CFG); blk_len = cfg & (CFG_BLK_LEN_MASK << CFG_BLK_LEN_SHIFT); blk_len >>= CFG_BLK_LEN_SHIFT; - if (blk_len != ilog2(cmd->data->blksz)) { + if (blk_len != ilog2(data->blksz)) { dev_dbg(host->dev, "%s: update blk_len %d -> %d\n", - __func__, blk_len, ilog2(cmd->data->blksz)); - blk_len = ilog2(cmd->data->blksz); + __func__, blk_len, ilog2(data->blksz)); + blk_len = ilog2(data->blksz); cfg &= ~(CFG_BLK_LEN_MASK << CFG_BLK_LEN_SHIFT); cfg |= blk_len << CFG_BLK_LEN_SHIFT; writel(cfg, host->regs + SD_EMMC_CFG); } - cmd->data->bytes_xfered = 0; - xfer_bytes = cmd->data->blksz * cmd->data->blocks; - if (cmd->data->flags & MMC_DATA_WRITE) { - desc->cmd_cfg |= CMD_CFG_DATA_WR; - WARN_ON(xfer_bytes > host->bounce_buf_size); - sg_copy_to_buffer(cmd->data->sg, cmd->data->sg_len, - host->bounce_buf, xfer_bytes); - cmd->data->bytes_xfered = xfer_bytes; - dma_wmb(); - } else { - desc->cmd_cfg &= ~CMD_CFG_DATA_WR; + for_each_sg(data->sg, sg, data->sg_len, i) { + desc[i].cmd_cfg = cmd_cfg; + sg_dma_len(sg) = sg->length; + desc[i].cmd_cfg |= (sg_dma_len(sg) / data->blksz) + << CMD_CFG_LENGTH_SHIFT; + if (i > 0) + desc[i].cmd_cfg |= CMD_CFG_NO_CMD; + desc[i].cmd_arg = cmd->arg; + desc[i].cmd_resp = 0; + desc[i].cmd_data = sg_dma_address(sg); } - - desc->cmd_data = host->bounce_dma_addr & CMD_DATA_MASK; - - cmd_cfg_timeout = ilog2(SD_EMMC_CMD_TIMEOUT_DATA); + desc[data->sg_len - 1].cmd_cfg |= CMD_CFG_END_OF_CHAIN; } else { - desc->cmd_cfg &= ~CMD_CFG_DATA_IO; - cmd_cfg_timeout = ilog2(SD_EMMC_CMD_TIMEOUT); + cmd_cfg |= ilog2(SD_EMMC_CMD_TIMEOUT) << CMD_CFG_TIMEOUT_SHIFT; + cmd_cfg |= CMD_CFG_END_OF_CHAIN; + desc[0].cmd_cfg = cmd_cfg; + desc[0].cmd_arg = cmd->arg; + desc[0].cmd_resp = 0; + desc[0].cmd_data = 0; } - desc->cmd_cfg |= (cmd_cfg_timeout & CMD_CFG_TIMEOUT_MASK) << - CMD_CFG_TIMEOUT_SHIFT; host->cmd = cmd; - /* Last descriptor */ - desc->cmd_cfg |= CMD_CFG_END_OF_CHAIN; - writel(desc->cmd_cfg, host->regs + SD_EMMC_CMD_CFG); - writel(desc->cmd_data, host->regs + SD_EMMC_CMD_DAT); - writel(desc->cmd_resp, host->regs + SD_EMMC_CMD_RSP); wmb(); /* ensure descriptor is written before kicked */ - writel(desc->cmd_arg, host->regs + SD_EMMC_CMD_ARG); + cfg = host->descs_dma_addr | START_DESC_BUSY; + writel(cfg, host->regs + SD_EMMC_START); } static void meson_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) { struct meson_host *host = mmc_priv(mmc); + bool needs_pre_post_req = mrq->data && !mrq->data->host_cookie; + + if (needs_pre_post_req) + meson_mmc_pre_req(mmc, mrq); /* Stop execution */ writel(0, host->regs + SD_EMMC_START); @@ -530,6 +557,9 @@ static void meson_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) meson_mmc_start_cmd(mmc, mrq->sbc); else meson_mmc_start_cmd(mmc, mrq->cmd); + + if (needs_pre_post_req) + meson_mmc_post_req(mmc, mrq, 0); } static void meson_mmc_read_resp(struct mmc_host *mmc, struct mmc_command *cmd) @@ -550,6 +580,7 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) { struct meson_host *host = dev_id; struct mmc_command *cmd; + struct mmc_data *data; u32 irq_en, status, raw_status; irqreturn_t ret = IRQ_HANDLED; @@ -561,6 +592,8 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) if (WARN_ON(!cmd)) return IRQ_NONE; + data = cmd->data; + spin_lock(&host->lock); irq_en = readl(host->regs + SD_EMMC_IRQ_EN); raw_status = readl(host->regs + SD_EMMC_STATUS); @@ -598,12 +631,17 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) dev_dbg(host->dev, "Unhandled IRQ: Descriptor timeout\n"); cmd->error = -ETIMEDOUT; } + + if (data && !cmd->error) + data->bytes_xfered = data->blksz * data->blocks; + if (status & IRQ_SDIO) dev_dbg(host->dev, "Unhandled IRQ: SDIO.\n"); - if (status & (IRQ_END_OF_CHAIN | IRQ_RESP_STATUS)) - ret = IRQ_WAKE_THREAD; - else { + if (status & (IRQ_END_OF_CHAIN | IRQ_RESP_STATUS)) { + if (meson_mmc_get_next_command(cmd)) + ret = IRQ_WAKE_THREAD; + } else { dev_warn(host->dev, "Unknown IRQ! status=0x%04x: MMC CMD%u arg=0x%08x flags=0x%08x stop=%d\n", status, cmd->opcode, cmd->arg, cmd->flags, cmd->mrq->stop ? 1 : 0); @@ -632,26 +670,12 @@ static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id) { struct meson_host *host = dev_id; struct mmc_command *next_cmd, *cmd = host->cmd; - struct mmc_data *data; - unsigned int xfer_bytes; if (WARN_ON(!cmd)) return IRQ_NONE; - data = cmd->data; - if (data && data->flags & MMC_DATA_READ) { - xfer_bytes = data->blksz * data->blocks; - WARN_ON(xfer_bytes > host->bounce_buf_size); - sg_copy_from_buffer(data->sg, data->sg_len, - host->bounce_buf, xfer_bytes); - data->bytes_xfered = xfer_bytes; - } - next_cmd = meson_mmc_get_next_command(cmd); - if (next_cmd) - meson_mmc_start_cmd(host->mmc, next_cmd); - else - meson_mmc_request_done(host->mmc, cmd->mrq); + meson_mmc_start_cmd(host->mmc, next_cmd); return IRQ_HANDLED; } @@ -685,6 +709,8 @@ static const struct mmc_host_ops meson_mmc_ops = { .request = meson_mmc_request, .set_ios = meson_mmc_set_ios, .get_cd = meson_mmc_get_cd, + .pre_req = meson_mmc_pre_req, + .post_req = meson_mmc_post_req, }; static int meson_mmc_probe(struct platform_device *pdev) @@ -764,15 +790,14 @@ static int meson_mmc_probe(struct platform_device *pdev) mmc->caps |= MMC_CAP_CMD23; mmc->max_blk_count = CMD_CFG_LENGTH_MASK; - mmc->max_req_size = mmc->max_blk_count * mmc->max_blk_size; - - /* data bounce buffer */ - host->bounce_buf_size = mmc->max_req_size; - host->bounce_buf = - dma_alloc_coherent(host->dev, host->bounce_buf_size, - &host->bounce_dma_addr, GFP_KERNEL); - if (host->bounce_buf == NULL) { - dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n"); + mmc->max_segs = PAGE_SIZE / sizeof(struct sd_emmc_desc); + mmc->max_seg_size = mmc->max_blk_count * mmc->max_blk_size; + mmc->max_req_size = mmc->max_seg_size * mmc->max_segs; + + host->descs = dma_alloc_coherent(host->dev, PAGE_SIZE, + &host->descs_dma_addr, GFP_KERNEL); + if (!host->descs) { + dev_err(host->dev, "Allocating descriptor DMA buffer failed\n"); ret = -ENOMEM; goto err_div_clk; } @@ -797,8 +822,8 @@ static int meson_mmc_remove(struct platform_device *pdev) /* disable interrupts */ writel(0, host->regs + SD_EMMC_IRQ_EN); - dma_free_coherent(host->dev, host->bounce_buf_size, - host->bounce_buf, host->bounce_dma_addr); + dma_free_coherent(host->dev, PAGE_SIZE, host->descs, + host->descs_dma_addr); clk_disable_unprepare(host->cfg_div_clk); clk_disable_unprepare(host->core_clk); -- 2.12.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 5/5] mmc: meson-gx: switch to descriptor chain mode 2017-03-15 19:34 ` [PATCH 5/5] mmc: meson-gx: switch to descriptor chain mode Heiner Kallweit @ 2017-03-24 19:04 ` Kevin Hilman 0 siblings, 0 replies; 9+ messages in thread From: Kevin Hilman @ 2017-03-24 19:04 UTC (permalink / raw) To: linus-amlogic Hi Heiner, Heiner Kallweit <hkallweit1@gmail.com> writes: > Switch the driver from using a linearized bounce buffer to descriptor > chain mode. This drastically improves performance. > > Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> I know this series needs a respin on top of your other cleanups, and I'll have a closer look at it then, but one comment for the respin... [...] > static int meson_mmc_probe(struct platform_device *pdev) > @@ -764,15 +790,14 @@ static int meson_mmc_probe(struct platform_device *pdev) > > mmc->caps |= MMC_CAP_CMD23; > mmc->max_blk_count = CMD_CFG_LENGTH_MASK; > - mmc->max_req_size = mmc->max_blk_count * mmc->max_blk_size; > - > - /* data bounce buffer */ > - host->bounce_buf_size = mmc->max_req_size; > - host->bounce_buf = > - dma_alloc_coherent(host->dev, host->bounce_buf_size, > - &host->bounce_dma_addr, GFP_KERNEL); > - if (host->bounce_buf == NULL) { > - dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n"); > + mmc->max_segs = PAGE_SIZE / sizeof(struct sd_emmc_desc); > + mmc->max_seg_size = mmc->max_blk_count * mmc->max_blk_size; > + mmc->max_req_size = mmc->max_seg_size * mmc->max_segs; > + > + host->descs = dma_alloc_coherent(host->dev, PAGE_SIZE, > + &host->descs_dma_addr, GFP_KERNEL); > + if (!host->descs) { > + dev_err(host->dev, "Allocating descriptor DMA buffer failed\n"); > ret = -ENOMEM; > goto err_div_clk; > } > @@ -797,8 +822,8 @@ static int meson_mmc_remove(struct platform_device *pdev) > /* disable interrupts */ > writel(0, host->regs + SD_EMMC_IRQ_EN); > > - dma_free_coherent(host->dev, host->bounce_buf_size, > - host->bounce_buf, host->bounce_dma_addr); > + dma_free_coherent(host->dev, PAGE_SIZE, host->descs, > + host->descs_dma_addr); > > clk_disable_unprepare(host->cfg_div_clk); > clk_disable_unprepare(host->core_clk); Please replace the usage of PAGE_SIZE above with a #define at the top of the driver for the max number of descriptors/segments. Right now, if you wanted to change that, you'd have to change it in at least three places. Kevin ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 0/5] mmc: meson-gx: add cmd23 and descriptor chain mode 2017-03-15 19:16 [PATCH 0/5] mmc: meson-gx: add cmd23 and descriptor chain mode Heiner Kallweit ` (4 preceding siblings ...) 2017-03-15 19:34 ` [PATCH 5/5] mmc: meson-gx: switch to descriptor chain mode Heiner Kallweit @ 2017-03-24 7:27 ` Ulf Hansson 2017-03-24 18:00 ` Heiner Kallweit 5 siblings, 1 reply; 9+ messages in thread From: Ulf Hansson @ 2017-03-24 7:27 UTC (permalink / raw) To: linus-amlogic On 15 March 2017 at 20:16, Heiner Kallweit <hkallweit1@gmail.com> wrote: > Apart from three minor improvements this patch series adds support > for CMD23 mode and switches the driver to descriptor chain mode. > > On my system with a 128GB eMMC card this increased the read > performance from 10 - 15 MB/s to 140 MB/s. > > Successfully tested on a Odroid C2 with custom uboot based on recent > mainline uboot. Behavior might be different with vendor uboot. > > Heiner Kallweit (5): > mmc: meson-gx: switch irq name to DT node name > mmc: meson-gx: improve response reading > mmc: meson-gx: use block mode also for just one block > mmc: meson-gx: add support for CMD23 mode > mmc: meson-gx: switch to descriptor chain mode > > drivers/mmc/host/meson-gx-mmc.c | 258 ++++++++++++++++++++++------------------ > 1 file changed, 142 insertions(+), 116 deletions(-) > > -- > 2.12.0 > Heiner, As I just applied the series for the "small refactoring", how do you want me to handle this one. Is it safe to apply on top or do you need to re-base it? Kind regards Uffe ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 0/5] mmc: meson-gx: add cmd23 and descriptor chain mode 2017-03-24 7:27 ` [PATCH 0/5] mmc: meson-gx: add cmd23 and " Ulf Hansson @ 2017-03-24 18:00 ` Heiner Kallweit 0 siblings, 0 replies; 9+ messages in thread From: Heiner Kallweit @ 2017-03-24 18:00 UTC (permalink / raw) To: linus-amlogic Am 24.03.2017 um 08:27 schrieb Ulf Hansson: > On 15 March 2017 at 20:16, Heiner Kallweit <hkallweit1@gmail.com> wrote: >> Apart from three minor improvements this patch series adds support >> for CMD23 mode and switches the driver to descriptor chain mode. >> >> On my system with a 128GB eMMC card this increased the read >> performance from 10 - 15 MB/s to 140 MB/s. >> >> Successfully tested on a Odroid C2 with custom uboot based on recent >> mainline uboot. Behavior might be different with vendor uboot. >> >> Heiner Kallweit (5): >> mmc: meson-gx: switch irq name to DT node name >> mmc: meson-gx: improve response reading >> mmc: meson-gx: use block mode also for just one block >> mmc: meson-gx: add support for CMD23 mode >> mmc: meson-gx: switch to descriptor chain mode >> >> drivers/mmc/host/meson-gx-mmc.c | 258 ++++++++++++++++++++++------------------ >> 1 file changed, 142 insertions(+), 116 deletions(-) >> >> -- >> 2.12.0 >> > > Heiner, > > As I just applied the series for the "small refactoring", how do you > want me to handle this one. Is it safe to apply on top or do you need > to re-base it? > This series is superseded. I have reports that introducing descriptor chain mode breaks SDIO. I'm working on a fixed version which will need some more testing before I submit it. Thanks for asking! Rgds, Heiner > Kind regards > Uffe > ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2017-03-24 19:04 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2017-03-15 19:16 [PATCH 0/5] mmc: meson-gx: add cmd23 and descriptor chain mode Heiner Kallweit 2017-03-15 19:33 ` [PATCH 1/5] mmc: meson-gx: switch irq name to DT node name Heiner Kallweit 2017-03-15 19:33 ` [PATCH 2/5] mmc: meson-gx: improve response reading Heiner Kallweit 2017-03-15 19:34 ` [PATCH 3/5] mmc: meson-gx: use block mode also for just one block Heiner Kallweit 2017-03-15 19:34 ` [PATCH 4/5] mmc: meson-gx: add support for CMD23 mode Heiner Kallweit 2017-03-15 19:34 ` [PATCH 5/5] mmc: meson-gx: switch to descriptor chain mode Heiner Kallweit 2017-03-24 19:04 ` Kevin Hilman 2017-03-24 7:27 ` [PATCH 0/5] mmc: meson-gx: add cmd23 and " Ulf Hansson 2017-03-24 18:00 ` Heiner Kallweit
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).