Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cf6cb129 authored by Veerabhadrarao Badiganti's avatar Veerabhadrarao Badiganti Committed by Gerrit - the friendly Code Review server
Browse files

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: default avatarVeerabhadrarao Badiganti <vbadigan@codeaurora.org>
parent 7c269f67
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -908,6 +908,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)) {
@@ -1023,6 +1029,8 @@ 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++) {
+2 −0
Original line number Diff line number Diff line
@@ -698,6 +698,8 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
	INIT_DELAYED_WORK(&host->sdio_irq_work, sdio_irq_work);
	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.
+4 −1
Original line number Diff line number Diff line
@@ -84,7 +84,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) &&
@@ -96,6 +98,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)));
}

+3 −0
Original line number Diff line number Diff line
@@ -704,6 +704,9 @@ struct mmc_host {
	 */
	void *cmdq_private;
	struct mmc_request	*err_mrq;

	atomic_t rpmb_req_pending;
	struct mutex		rpmb_req_mutex;
	unsigned long		private[0] ____cacheline_aligned;
};