diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index b9febc75c64e..b083cdd2b0e5 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -921,12 +921,29 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, mmc_get_card(card); + if (mmc_card_cmdq(card)) { + err = mmc_cmdq_halt_on_empty_queue(card->host); + if (err) { + pr_err("%s: halt failed while doing %s err (%d)\n", + mmc_hostname(card->host), + __func__, err); + mmc_put_card(card); + goto cmd_done; + } + } + ioc_err = __mmc_blk_ioctl_cmd(card, md, idata); mmc_put_card(card); err = mmc_blk_ioctl_copy_to_user(ic_ptr, idata); + if (mmc_card_cmdq(card)) { + if (mmc_cmdq_halt(card->host, false)) + pr_err("%s: %s: cmdq unhalt failed\n", + mmc_hostname(card->host), __func__); + } + cmd_done: mmc_blk_put(md); cmd_err: diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index dfd6ea38d522..7531de320c31 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -366,7 +366,7 @@ static bool mmc_is_valid_state_for_clk_scaling(struct mmc_host *host) return R1_CURRENT_STATE(status) == R1_STATE_TRAN; } -static int mmc_cmdq_halt_on_empty_queue(struct mmc_host *host) +int mmc_cmdq_halt_on_empty_queue(struct mmc_host *host) { int err = 0; @@ -389,6 +389,7 @@ static int mmc_cmdq_halt_on_empty_queue(struct mmc_host *host) out: return err; } +EXPORT_SYMBOL(mmc_cmdq_halt_on_empty_queue); int mmc_clk_update_freq(struct mmc_host *host, unsigned long freq, enum mmc_load state) diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index 374458c9fd6f..98b9e90e667a 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c @@ -383,11 +383,26 @@ static int mmc_dbg_card_status_get(void *data, u64 *val) int ret; mmc_get_card(card); + if (mmc_card_cmdq(card)) { + ret = mmc_cmdq_halt_on_empty_queue(card->host); + if (ret) { + pr_err("%s: halt failed while doing %s err (%d)\n", + mmc_hostname(card->host), __func__, + ret); + goto out; + } + } ret = mmc_send_status(data, &status); if (!ret) *val = status; + if (mmc_card_cmdq(card)) { + if (mmc_cmdq_halt(card->host, false)) + pr_err("%s: %s: cmdq unhalt failed\n", + mmc_hostname(card->host), __func__); + } +out: mmc_put_card(card); return ret; @@ -410,6 +425,17 @@ static int mmc_ext_csd_open(struct inode *inode, struct file *filp) return -ENOMEM; mmc_get_card(card); + if (mmc_card_cmdq(card)) { + err = mmc_cmdq_halt_on_empty_queue(card->host); + if (err) { + pr_err("%s: halt failed while doing %s err (%d)\n", + mmc_hostname(card->host), __func__, + err); + mmc_put_card(card); + goto out_free_halt; + } + } + err = mmc_get_ext_csd(card, &ext_csd); mmc_put_card(card); if (err) @@ -421,10 +447,23 @@ static int mmc_ext_csd_open(struct inode *inode, struct file *filp) BUG_ON(n != EXT_CSD_STR_LEN); filp->private_data = buf; + + if (mmc_card_cmdq(card)) { + if (mmc_cmdq_halt(card->host, false)) + pr_err("%s: %s: cmdq unhalt failed\n", + mmc_hostname(card->host), __func__); + } + kfree(ext_csd); return 0; out_free: + if (mmc_card_cmdq(card)) { + if (mmc_cmdq_halt(card->host, false)) + pr_err("%s: %s: cmdq unhalt failed\n", + mmc_hostname(card->host), __func__); + } +out_free_halt: kfree(buf); return err; } diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index 2f797fb527b0..87332656e0fd 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h @@ -135,6 +135,7 @@ struct mmc_cmdq_req; extern int mmc_cmdq_discard_queue(struct mmc_host *host, u32 tasks); extern int mmc_cmdq_halt(struct mmc_host *host, bool enable); +extern int mmc_cmdq_halt_on_empty_queue(struct mmc_host *host); extern void mmc_cmdq_post_req(struct mmc_host *host, struct mmc_request *mrq, int err); extern int mmc_cmdq_start_req(struct mmc_host *host,