mmc: cmdq_hci: fix race between req completion and clearing CQTCN
CQ irq handler first calls completion path for every notified tag and then clears CQTCN register for all completed tags. This approach could cause following problem: 1) issue context (unblocked by tag completion) issues next request, CQE successfully completes it and notifies task completion through CQTCN again for the same tag. 2) CQ irq handler proceeds to clear CQTCN for the original request. In the above scenario clear of CQTCN register will mask next request completion and issue context will be never unblocked. Hence clear CQTCN first and then notify the request completion. Change-Id: Ie644e24279ca30de42bbc9f8e1ae4326609d38a5 Signed-off-by: Konstantin Dorfman <kdorfman@codeaurora.org> Signed-off-by: Venkat Gopalakrishnan <venkatg@codeaurora.org>
This commit is contained in:
parent
0044c4d39c
commit
9a4df9847e
1 changed files with 13 additions and 3 deletions
|
@ -737,18 +737,28 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status & CQIS_TCC) {
|
if (status & CQIS_TCC) {
|
||||||
/* read QCTCN and complete the request */
|
/* read CQTCN and complete the request */
|
||||||
comp_status = cmdq_readl(cq_host, CQTCN);
|
comp_status = cmdq_readl(cq_host, CQTCN);
|
||||||
if (!comp_status)
|
if (!comp_status)
|
||||||
goto out;
|
goto out;
|
||||||
|
/*
|
||||||
|
* The CQTCN must be cleared before notifying req completion
|
||||||
|
* to upper layers to avoid missing completion notification
|
||||||
|
* of new requests with the same tag.
|
||||||
|
*/
|
||||||
|
cmdq_writel(cq_host, comp_status, CQTCN);
|
||||||
|
/*
|
||||||
|
* A write memory barrier is necessary to guarantee that CQTCN
|
||||||
|
* gets cleared first before next doorbell for the same tag is
|
||||||
|
* set but that is already achieved by the barrier present
|
||||||
|
* before setting doorbell, hence one is not needed here.
|
||||||
|
*/
|
||||||
for_each_set_bit(tag, &comp_status, cq_host->num_slots) {
|
for_each_set_bit(tag, &comp_status, cq_host->num_slots) {
|
||||||
/* complete the corresponding mrq */
|
/* complete the corresponding mrq */
|
||||||
pr_debug("%s: completing tag -> %lu\n",
|
pr_debug("%s: completing tag -> %lu\n",
|
||||||
mmc_hostname(mmc), tag);
|
mmc_hostname(mmc), tag);
|
||||||
cmdq_finish_data(mmc, tag);
|
cmdq_finish_data(mmc, tag);
|
||||||
}
|
}
|
||||||
cmdq_writel(cq_host, comp_status, CQTCN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status & CQIS_HAC) {
|
if (status & CQIS_HAC) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue