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

Commit d51367a4 authored by Sahitya Tummala's avatar Sahitya Tummala Committed by Gerrit - the friendly Code Review server
Browse files

mmc: Fix err-handling path when there is active Discard (DCMD)



In case of Discard requests, currently the error handler was
not waking up the cmdq-thread which is waiting for completion
even of discard requests. This was happening when the error
requests is non-discard requests.
So this patch adds a way to wake up the issue thread waiting
on discard completion event

Change-Id: Ia663a2cf41004ce18a409b5a29f715e672c8a7ae
Signed-off-by: default avatarSahitya Tummala <stummala@codeaurora.org>
Signed-off-by: default avatarRitesh Harjani <riteshh@codeaurora.org>
parent 94adca08
Loading
Loading
Loading
Loading
+45 −24
Original line number Diff line number Diff line
@@ -2429,17 +2429,17 @@ static struct mmc_cmdq_req *mmc_blk_cmdq_prep_discard_req(struct mmc_queue *mq,
	struct mmc_cmdq_req *cmdq_req;
	struct mmc_queue_req *active_mqrq;

	BUG_ON(req->tag > card->ext_csd.cmdq_depth);
	BUG_ON(test_and_set_bit(req->tag, &host->cmdq_ctx.active_reqs));

	set_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx_info->curr_state);

	active_mqrq = req_to_mmc_queue_req(req);

	cmdq_req = mmc_cmdq_prep_dcmd(active_mqrq, mq);
	cmdq_req->cmdq_req_flags |= QBR;
	cmdq_req->mrq.cmd = &cmdq_req->cmd;
	cmdq_req->tag = req->tag;

	init_completion(&cmdq_req->mrq.completion);
	BUG_ON(req->tag > card->ext_csd.cmdq_depth);
	BUG_ON(test_and_set_bit(req->tag, &host->cmdq_ctx.active_reqs));
	set_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx_info->curr_state);
	return cmdq_req;
}

@@ -2483,8 +2483,13 @@ static int mmc_blk_cmdq_issue_discard_rq(struct mmc_queue *mq,
	}
	err = mmc_cmdq_erase(cmdq_req, card, from, nr, arg);
clear_dcmd:
	if (err != -EAGAIN) {
		mmc_host_clk_hold(card->host);
		blk_complete_request(req);
	} else {
		pr_err("%s: err(%d) handled by cmdq-error handler\n",
			__func__, err);
	}
out:
	return err ? 1 : 0;
}
@@ -2546,8 +2551,13 @@ static int mmc_blk_cmdq_issue_secdiscard_rq(struct mmc_queue *mq,
				MMC_SECURE_TRIM2_ARG);
	}
clear_dcmd:
	if (err != -EAGAIN) {
		mmc_host_clk_hold(card->host);
		blk_complete_request(req);
	} else {
		pr_err("%s: err(%d) handled by cmdq-error handler\n",
			__func__, err);
	}
out:
	return err ? 1 : 0;
}
@@ -2807,20 +2817,17 @@ static void mmc_blk_cmdq_reset(struct mmc_host *host, bool clear_all)
}

/**
 * is_cmdq_dcmd_req - Checks if tag belongs to DCMD request.
 * get_cmdq_req_by_tag - returns cmdq_rq based on tag.
 * @q:		request_queue pointer.
 * @tag:	tag number of request to check.
 *
 * This function checks if the request with tag number "tag"
 * is a DCMD request or not based on cmdq_req_flags set.
 *
 * returns true if DCMD req, otherwise false.
 */
static bool is_cmdq_dcmd_req(struct request_queue *q, int tag)
static struct mmc_cmdq_req *get_cmdq_req_by_tag(struct request_queue *q,
						int tag)
{
	struct request *req;
	struct mmc_queue_req *mq_rq;
	struct mmc_cmdq_req *cmdq_req;
	struct mmc_cmdq_req *cmdq_req = NULL;

	req = blk_queue_find_tag(q, tag);
	if (WARN_ON(!req))
@@ -2829,9 +2836,8 @@ static bool is_cmdq_dcmd_req(struct request_queue *q, int tag)
	if (WARN_ON(!mq_rq))
		goto out;
	cmdq_req = &(mq_rq->cmdq_req);
	return (cmdq_req->cmdq_req_flags & DCMD);
out:
	return -ENOENT;
	return cmdq_req;
}

/**
@@ -2851,7 +2857,9 @@ static void mmc_blk_cmdq_reset_all(struct mmc_host *host, int err)
	struct mmc_cmdq_context_info *ctx_info = &host->cmdq_ctx;
	struct request_queue *q;
	int itag = 0;
	int ret = 0;
	struct mmc_cmdq_req *cmdq_req = NULL;
	struct mmc_request *dcmd_mrq;
	bool is_err_mrq_dcmd = false;

	if (WARN_ON(!mrq))
		return;
@@ -2867,18 +2875,31 @@ static void mmc_blk_cmdq_reset_all(struct mmc_host *host, int err)

	mmc_blk_cmdq_reset(host, false);

	if (mrq->cmdq_req->cmdq_req_flags & DCMD)
		is_err_mrq_dcmd = true;

	for_each_set_bit(itag, &ctx_info->active_reqs,
			host->num_cq_slots) {
		ret = is_cmdq_dcmd_req(q, itag);
		if (WARN_ON(ret == -ENOENT))
		cmdq_req = get_cmdq_req_by_tag(q, itag);
		if (WARN_ON(!cmdq_req))
			continue;
		if (!ret) {
		if (!(cmdq_req->cmdq_req_flags & DCMD)) {
			WARN_ON(!test_and_clear_bit(itag,
				 &ctx_info->data_active_reqs));
			mmc_cmdq_post_req(host, itag, err);
		} else {
			clear_bit(CMDQ_STATE_DCMD_ACTIVE,
					&ctx_info->curr_state);
			dcmd_mrq = &cmdq_req->mrq;
			WARN_ON(!test_and_clear_bit(CMDQ_STATE_DCMD_ACTIVE,
					&ctx_info->curr_state));
			pr_debug("%s: cmd(%u), req_op(%llu)\n", __func__,
				 dcmd_mrq->cmd->opcode, req_op(dcmd_mrq->req));
			if (!is_err_mrq_dcmd && !dcmd_mrq->cmd->error &&
				(req_op(dcmd_mrq->req) == REQ_OP_SECURE_ERASE ||
				 req_op(dcmd_mrq->req) == REQ_OP_DISCARD)) {
				dcmd_mrq->cmd->error = -EAGAIN;
				complete(&dcmd_mrq->completion);
			}

		}
		WARN_ON(!test_and_clear_bit(itag,
					&ctx_info->active_reqs));
+1 −2
Original line number Diff line number Diff line
@@ -1854,7 +1854,6 @@ int mmc_cmdq_wait_for_dcmd(struct mmc_host *host,
	struct mmc_command *cmd = mrq->cmd;
	int err = 0;

	init_completion(&mrq->completion);
	mrq->done = mmc_cmdq_dcmd_req_done;
	err = mmc_cmdq_start_req(host, cmdq_req);
	if (err)
@@ -3553,7 +3552,7 @@ static int mmc_cmdq_send_erase_cmd(struct mmc_cmdq_req *cmdq_req,
	if (err) {
		pr_err("mmc_erase: group start error %d, status %#x\n",
				err, cmd->resp[0]);
		return -EIO;
		return err;
	}
	return 0;
}