mmc: block: Unhalt the command queue before releasing mmc host
In the IOCTL path, the command queue is halted before servicing the ioctl requests. Once the ioctl request is serviced, the ioctl context releases mmc host and then unhalts the controller. This can cause race conditions where mmc driver would end up in a bad state. If another context B, which wants to send a legacy command, comes up between the time ioctl releases the host and unhalts the controller. Then the context B will see that cmdq is already halted and will prepare a legacy command. Once context B sends the legacy command, the ioctl context may unhalt the cmdq. This will mask the legacy interrupts and context B will never receive interrupts for the command it sent. To prevent this, unhalt the controller before the ioctl context releases the host. Change-Id: I65d3b4a709813549e7e5d48d94065a753164f9d0 Signed-off-by: Vijay Viswanath <vviswana@codeaurora.org>
This commit is contained in:
parent
14f6bfeeeb
commit
6cc74e75a0
1 changed files with 4 additions and 4 deletions
|
@ -1224,16 +1224,16 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
|
||||||
|
|
||||||
ioc_err = __mmc_blk_ioctl_cmd(card, md, idata);
|
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_card_cmdq(card)) {
|
||||||
if (mmc_cmdq_halt(card->host, false))
|
if (mmc_cmdq_halt(card->host, false))
|
||||||
pr_err("%s: %s: cmdq unhalt failed\n",
|
pr_err("%s: %s: cmdq unhalt failed\n",
|
||||||
mmc_hostname(card->host), __func__);
|
mmc_hostname(card->host), __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mmc_put_card(card);
|
||||||
|
|
||||||
|
err = mmc_blk_ioctl_copy_to_user(ic_ptr, idata);
|
||||||
|
|
||||||
cmd_done:
|
cmd_done:
|
||||||
mmc_blk_put(md);
|
mmc_blk_put(md);
|
||||||
cmd_err:
|
cmd_err:
|
||||||
|
|
Loading…
Add table
Reference in a new issue