mmc: card: fix active data requests handling
Clock scaling logic relies on active data request tracking variable to
start/stop counting the bus busy period and we are also crashing the
system if this tracking variable shows that new request tag is already
in use. Set/Clear logic of this tracking variable is done only if
clock scaling is enabled but consider following sequence of events:
1. Clock scaling is enabled
2. New request comes in which sets the appropriate tag in tracking
variable.
3. Clock scaling gets disabled (for some reason) before the request
completion.
4. Request gets completed but it doesn't clear the corresponding tag
in tracking variable.
5. Clock scaling gets re-enabled.
6. New request is issued with the same tag which was never cleared from
tracking variable hence we would hit the BUG_ON and system will crash.
Fix this issue by doing set/clear of tracking variable irrespective of
clock scaling state.
Change-Id: Idffd1247ec1275e782e1ad9eb91faa81bc3ba347
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 3e8352b..e425ee3 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -3163,13 +3163,11 @@
struct mmc_cmdq_req *mc_rq;
int ret = 0;
- if (host->clk_scaling.enable) {
- mmc_deferred_scaling(host);
- mmc_cmdq_clk_scaling_start_busy(host, true);
- BUG_ON(test_and_set_bit(req->tag,
- &host->cmdq_ctx.data_active_reqs));
- }
+ mmc_deferred_scaling(host);
+ mmc_cmdq_clk_scaling_start_busy(host, true);
+
BUG_ON((req->tag < 0) || (req->tag > card->ext_csd.cmdq_depth));
+ BUG_ON(test_and_set_bit(req->tag, &host->cmdq_ctx.data_active_reqs));
BUG_ON(test_and_set_bit(req->tag, &host->cmdq_ctx.active_reqs));
active_mqrq = &mq->mqrq_cmdq[req->tag];
@@ -3401,13 +3399,11 @@
BUG_ON(!test_and_clear_bit(cmdq_req->tag,
&ctx_info->active_reqs));
- if (host->clk_scaling.enable) {
- if (cmdq_req->cmdq_req_flags & DCMD)
- is_dcmd = true;
- else
- BUG_ON(!test_and_clear_bit(cmdq_req->tag,
- &ctx_info->data_active_reqs));
- }
+ if (cmdq_req->cmdq_req_flags & DCMD)
+ is_dcmd = true;
+ else
+ BUG_ON(!test_and_clear_bit(cmdq_req->tag,
+ &ctx_info->data_active_reqs));
mmc_cmdq_post_req(host, mrq, err);
if (err) {