From e0ee5ff565543bcc9f91635e27090c229c7e4750 Mon Sep 17 00:00:00 2001 From: Ritesh Harjani Date: Mon, 13 Jul 2015 10:52:36 +0530 Subject: [PATCH] mmc: core: Fix debugfs and IOCTL calls in cmdq mode Currently getting status/ext_csd using debugfs or IOCTL calls in cmdq mode is not working. Fix it by halting the cmdq engine and making sure that card queue is empty before issuing these cmds. Change-Id: Idb89def9ff5c2fee6866759b9a8c652049552933 Signed-off-by: Ritesh Harjani [subhashj@codeaurora.org: fixed merge conflicts] Signed-off-by: Subhash Jadavani --- drivers/mmc/card/block.c | 17 +++++++++++++++++ drivers/mmc/core/core.c | 3 ++- drivers/mmc/core/debugfs.c | 39 ++++++++++++++++++++++++++++++++++++++ include/linux/mmc/core.h | 1 + 4 files changed, 59 insertions(+), 1 deletion(-) 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,