Skip to content

Commit f0c393e

Browse files
ahunter6storulf
authored andcommitted
mmc: sdio: Use mmc_pre_req() / mmc_post_req()
SDHCI changed from using a tasklet to finish requests, to using an IRQ thread i.e. commit c07a48c ("mmc: sdhci: Remove finish_tasklet"). Because this increased the latency to complete requests, a preparatory change was made to complete the request from the IRQ handler if possible i.e. commit 19d2f69 ("mmc: sdhci: Call mmc_request_done() from IRQ handler if possible"). That alleviated the situation for MMC block devices because the MMC block driver makes use of mmc_pre_req() and mmc_post_req() so that successful requests are completed in the IRQ handler and any DMA unmapping is handled separately in mmc_post_req(). However SDIO was still affected, and an example has been reported with up to 20% degradation in performance. Looking at SDIO I/O helper functions, sdio_io_rw_ext_helper() appeared to be a possible candidate for making use of asynchronous requests within its I/O loops, but analysis revealed that these loops almost never iterate more than once, so the complexity of the change would not be warrented. Instead, mmc_pre_req() and mmc_post_req() are added before and after I/O submission (mmc_wait_for_req) in mmc_io_rw_extended(). This still has the potential benefit of reducing the duration of interrupt handlers, as well as addressing the latency issue for SDHCI. It also seems a more reasonable solution than forcing drivers to do everything in the IRQ handler. Reported-by: Dmitry Osipenko <[email protected]> Fixes: c07a48c ("mmc: sdhci: Remove finish_tasklet") Signed-off-by: Adrian Hunter <[email protected]> Tested-by: Dmitry Osipenko <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Ulf Hansson <[email protected]>
1 parent 060522d commit f0c393e

File tree

1 file changed

+22
-17
lines changed

1 file changed

+22
-17
lines changed

drivers/mmc/core/sdio_ops.c

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
121121
struct sg_table sgtable;
122122
unsigned int nents, left_size, i;
123123
unsigned int seg_size = card->host->max_seg_size;
124+
int err;
124125

125126
WARN_ON(blksz == 0);
126127

@@ -170,28 +171,32 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
170171

171172
mmc_set_data_timeout(&data, card);
172173

173-
mmc_wait_for_req(card->host, &mrq);
174+
mmc_pre_req(card->host, &mrq);
174175

175-
if (nents > 1)
176-
sg_free_table(&sgtable);
176+
mmc_wait_for_req(card->host, &mrq);
177177

178178
if (cmd.error)
179-
return cmd.error;
180-
if (data.error)
181-
return data.error;
182-
183-
if (mmc_host_is_spi(card->host)) {
179+
err = cmd.error;
180+
else if (data.error)
181+
err = data.error;
182+
else if (mmc_host_is_spi(card->host))
184183
/* host driver already reported errors */
185-
} else {
186-
if (cmd.resp[0] & R5_ERROR)
187-
return -EIO;
188-
if (cmd.resp[0] & R5_FUNCTION_NUMBER)
189-
return -EINVAL;
190-
if (cmd.resp[0] & R5_OUT_OF_RANGE)
191-
return -ERANGE;
192-
}
184+
err = 0;
185+
else if (cmd.resp[0] & R5_ERROR)
186+
err = -EIO;
187+
else if (cmd.resp[0] & R5_FUNCTION_NUMBER)
188+
err = -EINVAL;
189+
else if (cmd.resp[0] & R5_OUT_OF_RANGE)
190+
err = -ERANGE;
191+
else
192+
err = 0;
193193

194-
return 0;
194+
mmc_post_req(card->host, &mrq, err);
195+
196+
if (nents > 1)
197+
sg_free_table(&sgtable);
198+
199+
return err;
195200
}
196201

197202
int sdio_reset(struct mmc_host *host)

0 commit comments

Comments
 (0)