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

Commit b4737e02 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "mmc: queue: Fix queue_lock spinlock bug from CMDQ shutdown path" into msm-4.9

parents fee94c6c 7a61087e
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -3610,6 +3610,9 @@ void mmc_blk_cmdq_complete_rq(struct request *rq)
	if (!ctx_info->active_reqs)
		wake_up_interruptible(&host->cmdq_ctx.queue_empty_wq);

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

	return;
}

+22 −3
Original line number Diff line number Diff line
@@ -100,7 +100,8 @@ static inline void mmc_cmdq_ready_wait(struct mmc_host *host,
	 * 4. cmdq state shouldn't be in error state.
	 * 5. free tag available to process the new request.
	 */
	wait_event(ctx->wait, mmc_peek_request(mq) &&
	wait_event(ctx->wait, kthread_should_stop()
		|| (mmc_peek_request(mq) &&
		!(((req_op(mq->cmdq_req_peeked) == REQ_OP_FLUSH) ||
		   (req_op(mq->cmdq_req_peeked) == REQ_OP_DISCARD))
		  && test_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx->curr_state))
@@ -109,7 +110,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)
		&& !mmc_check_blk_queue_start_tag(q, mq->cmdq_req_peeked));
		&& !mmc_check_blk_queue_start_tag(q, mq->cmdq_req_peeked)));
}

static int mmc_cmdq_thread(void *d)
@@ -127,6 +128,8 @@ static int mmc_cmdq_thread(void *d)
		int ret = 0;

		mmc_cmdq_ready_wait(host, mq);
		if (kthread_should_stop())
			break;

		ret = mq->cmdq_issue_fn(mq, mq->cmdq_req_peeked);
		/*
@@ -668,6 +671,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);
	init_completion(&mq->cmdq_pending_req_done);

	blk_queue_rq_timed_out(mq->queue, mmc_cmdq_rq_timed_out);
@@ -724,7 +728,22 @@ int mmc_queue_suspend(struct mmc_queue *mq, int wait)
			goto out;

		if (wait) {
			blk_cleanup_queue(q);

			/*
			 * After blk_stop_queue is called, wait for all
			 * active_reqs to complete.
			 * Then wait for cmdq thread to exit before calling
			 * cmdq shutdown to avoid race between issuing
			 * requests and shutdown of cmdq.
			 */
			spin_lock_irqsave(q->queue_lock, flags);
			blk_stop_queue(q);
			spin_unlock_irqrestore(q->queue_lock, flags);

			if (host->cmdq_ctx.active_reqs)
				wait_for_completion(
						&mq->cmdq_shutdown_complete);
			kthread_stop(mq->thread);
			mq->cmdq_shutdown(mq);
		} else {
			spin_lock_irqsave(q->queue_lock, flags);
+1 −0
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ struct mmc_queue {
	struct work_struct	cmdq_err_work;

	struct completion	cmdq_pending_req_done;
	struct completion	cmdq_shutdown_complete;
	struct request		*cmdq_req_peeked;
	int (*err_check_fn)(struct mmc_card *, struct mmc_async_req *);
	void (*packed_test_fn)(struct request_queue *, struct mmc_queue_req *);