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

Commit b413fc08 authored by Asutosh Das's avatar Asutosh Das Committed by Matt Wagantall
Browse files

mmc: core: fix shutdown in cmdq mode



During the shutdown process,
	- Stop the queue
	- Flush all the pending requests
	- Halt the Controller
	- Put the card in legacy mode

Change-Id: I5fe4e998bc04bfd8f50de63f3beae3cb25f1c8ba
Signed-off-by: default avatarAsutosh Das <asutoshd@codeaurora.org>
Signed-off-by: default avatarVenkat Gopalakrishnan <venkatg@codeaurora.org>
parent a5edf8e3
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -2633,6 +2633,34 @@ reset:
	clear_bit(CMDQ_STATE_HALT, &host->cmdq_ctx.curr_state);
}

static void mmc_blk_cmdq_shutdown(struct mmc_queue *mq)
{
	int err;
	struct mmc_card *card = mq->card;
	struct mmc_host *host = card->host;

	err = mmc_cmdq_halt(host, true);
	if (err) {
		pr_err("%s: halt: failed: %d\n", __func__, err);
		return;
	}

	mmc_claim_host(card->host);
	/* disable CQ mode in card */
	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
			 EXT_CSD_CMDQ, 0,
			 card->ext_csd.generic_cmd6_time);
	if (err) {
		pr_err("%s: failed to switch card to legacy mode: %d\n",
		       __func__, err);
		goto out;
	} else {
		host->card->cmdq_init = false;
	}
out:
	mmc_release_host(card->host);
}

static enum blk_eh_timer_return mmc_blk_cmdq_req_timed_out(struct request *req)
{
	struct mmc_queue *mq = req->q->queuedata;
@@ -2778,6 +2806,9 @@ out:
			test_and_clear_bit(0, &ctx_info->req_starved))
		blk_run_queue(mq->queue);
	mmc_release_host(host);

	if (blk_queue_stopped(mq->queue) && !ctx_info->active_reqs)
		complete(&mq->cmdq_shutdown_complete);
	return;
}

@@ -3251,6 +3282,7 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
		md->queue.cmdq_issue_fn = mmc_blk_cmdq_issue_rq;
		md->queue.cmdq_error_fn = mmc_blk_cmdq_err;
		md->queue.cmdq_req_timed_out = mmc_blk_cmdq_req_timed_out;
		md->queue.cmdq_shutdown = mmc_blk_cmdq_shutdown;
	}

	if (mmc_card_mmc(card) && !card->cmdq_init &&
+29 −0
Original line number Diff line number Diff line
@@ -622,6 +622,7 @@ int mmc_cmdq_init(struct mmc_queue *mq, struct mmc_card *card)

	blk_queue_softirq_done(mq->queue, mmc_cmdq_softirq_done);
	INIT_WORK(&mq->cmdq_err_work, mmc_cmdq_error_work);
	init_completion(&mq->cmdq_shutdown_complete);

	blk_queue_rq_timed_out(mq->queue, mmc_cmdq_rq_timed_out);
	blk_queue_rq_timeout(mq->queue, 120 * HZ);
@@ -653,6 +654,12 @@ void mmc_cmdq_clean(struct mmc_queue *mq, struct mmc_card *card)
	mq->mqrq_cmdq = NULL;
}

static void mmc_wait_for_pending_reqs(struct mmc_queue *mq)
{
	wait_for_completion(&mq->cmdq_shutdown_complete);
	mq->cmdq_shutdown(mq);
}

/**
 * mmc_queue_suspend - suspend a MMC request queue
 * @mq: MMC queue to suspend
@@ -667,6 +674,27 @@ int mmc_queue_suspend(struct mmc_queue *mq, int wait)
	struct request_queue *q = mq->queue;
	unsigned long flags;
	int rc = 0;
	struct mmc_card *card = mq->card;

	if (card->cmdq_init) {
		struct mmc_host *host = card->host;
		unsigned long flags;

		spin_lock_irqsave(q->queue_lock, flags);
		blk_stop_queue(q);
		spin_unlock_irqrestore(q->queue_lock, flags);

		if (host->cmdq_ctx.active_reqs) {
			if (!wait)
				rc = -EBUSY;
			else
				mmc_wait_for_pending_reqs(mq);
		} else {
			mq->cmdq_shutdown(mq);
		}

		goto out;
	}

	if (!(test_and_set_bit(MMC_QUEUE_SUSPENDED, &mq->flags))) {
		spin_lock_irqsave(q->queue_lock, flags);
@@ -689,6 +717,7 @@ int mmc_queue_suspend(struct mmc_queue *mq, int wait)
			rc = 0;
		}
	}
out:
	return rc;
}

+2 −0
Original line number Diff line number Diff line
@@ -69,9 +69,11 @@ struct mmc_queue {
	int			num_wr_reqs_to_start_packing;
	bool			no_pack_for_random;
	struct work_struct	cmdq_err_work;
	struct completion	cmdq_shutdown_complete;

	int (*err_check_fn) (struct mmc_card *, struct mmc_async_req *);
	void (*packed_test_fn) (struct request_queue *, struct mmc_queue_req *);
	void (*cmdq_shutdown)(struct mmc_queue *);
};

extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *,