From d3643ee7ff29a469859977d70a13ca641e52c323 Mon Sep 17 00:00:00 2001 From: Veerabhadrarao Badiganti Date: Mon, 9 Oct 2017 22:49:49 +0530 Subject: [PATCH] mmc: card: Service RPMB requests with priority over other requests RPMB requests are initiated from TZ and TZ gets blocked from servicing other tasks/requests till it completes RPMB request. Delays in servicing RPMB request may result in system-level stability/performance issues. Below is the issue observed: 1. TZ rpmb API is called to update TA rollback information. TZ forwards the request to HLOS mmc driver via rpmb-service. 2. mmc driver services the rpmb requests only after finishing the outstanding IO requests. 3. As part of handling an IO requests, mmc driver makes ICE call for getting encryption keys, which in-turn makes call to TZ. 4. Since ICE driver finds TZ is busy/blocked it returns ice request with -EBUSY error. 5. The failed requests with -EBUSY error would re-queued back. 6. The IO requests keep getting failed and keep getting re-queued and mmc driver never gets a chance to service rpmb requests. 7. This results in a deadlock senario. So RPMB requests need to be serviced immediately. If there is any outstanding RPMB request, then mmc driver should stop pulling any more new requests. The moment its done with serving ongoing requests, It should start processing RPMB request. Change-Id: I2d0f98a11716ef946551cc1a967e70a38e91d6ac Signed-off-by: Veerabhadrarao Badiganti --- drivers/mmc/card/block.c | 9 +++++++++ drivers/mmc/card/queue.c | 5 ++++- drivers/mmc/core/host.c | 2 ++ include/linux/mmc/host.h | 2 ++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 7d2ceda7f80e..2d391fa888ef 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1048,6 +1048,12 @@ static int mmc_blk_ioctl_rpmb_cmd(struct block_device *bdev, goto idata_free; } + /* + * Ensure rpmb_req_pending flag is synchronized between multiple + * entities which may use rpmb ioclts with a lock. + */ + mutex_lock(&card->host->rpmb_req_mutex); + atomic_set(&card->host->rpmb_req_pending, 1); mmc_get_card(card); if (mmc_card_doing_bkops(card)) { @@ -1163,6 +1169,9 @@ static int mmc_blk_ioctl_rpmb_cmd(struct block_device *bdev, cmd_rel_host: mmc_put_card(card); + atomic_set(&card->host->rpmb_req_pending, 0); + mutex_unlock(&card->host->rpmb_req_mutex); + idata_free: for (i = 0; i < MMC_IOC_MAX_RPMB_CMD; i++) { diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index ccf22eb5bdc0..397bbd09034d 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -95,7 +95,9 @@ static inline void mmc_cmdq_ready_wait(struct mmc_host *host, * be any other direct command active. * 3. cmdq state should be unhalted. * 4. cmdq state shouldn't be in error state. - * 5. free tag available to process the new request. + * 5. There is no outstanding RPMB request pending. + * 6. free tag available to process the new request. + * (This must be the last condtion to check) */ wait_event(ctx->wait, kthread_should_stop() || (mmc_peek_request(mq) && @@ -106,6 +108,7 @@ static inline void mmc_cmdq_ready_wait(struct mmc_host *host, && !(!host->card->part_curr && mmc_host_cq_disable(host) && !mmc_card_suspended(host->card)) && !test_bit(CMDQ_STATE_ERR, &ctx->curr_state) + && !atomic_read(&host->rpmb_req_pending) && !mmc_check_blk_queue_start_tag(q, mq->cmdq_req_peeked))); } diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 88699f852aa2..e63ec61fed3c 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -635,6 +635,8 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) #endif setup_timer(&host->retune_timer, mmc_retune_timer, (unsigned long)host); + mutex_init(&host->rpmb_req_mutex); + /* * By default, hosts do not support SGIO or large requests. * They have to set these according to their abilities. diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 34da10bff4e1..c9e252bc4c2c 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -600,6 +600,8 @@ struct mmc_host { #endif bool sdr104_wa; + atomic_t rpmb_req_pending; + struct mutex rpmb_req_mutex; unsigned long private[0] ____cacheline_aligned; }; -- 2.11.0