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

Commit d78dec5b authored by Veerabhadrarao Badiganti's avatar Veerabhadrarao Badiganti
Browse files

mmc: block: Fix issues with mmc ioctl path on 4.14 kernel



On latest kernels, mmc IOCTL commands won't be issued to the driver
directly. Instead, they would be issued through the block layer as
drv_op requests. mmc-cmdq thread process them just like regular
requests by fetching from block layer.

MMC IOCTL commands are getting issued by putting cmdq in halt state.
But when cmdq is in the halt state, cmdq thread won't fetch the
requests until it gets un-halted by other entity (say runtime suspend/
resume). This will result in a delay in processing IOCTL and IO
requests.

Since cmdq thread takes care of halting cq engine when it finds a
drv_op request, no need to halt cmdq anymore in IOCTL path.
It will fix the issue with IOCTL path.

Change-Id: I6636870ddb3f07f594c63045f64821681caaa3ad
Signed-off-by: default avatarVeerabhadrarao Badiganti <vbadigan@codeaurora.org>
parent a6285404
Loading
Loading
Loading
Loading
+4 −56
Original line number Original line Diff line number Diff line
@@ -1066,21 +1066,6 @@ static int mmc_blk_ioctl_cmd(struct mmc_blk_data *md,
		goto cmd_done;
		goto cmd_done;
	}
	}


	mmc_get_card(card);

	if (mmc_card_cmdq(card)) {
		err = mmc_cmdq_halt_on_empty_queue(card->host);
		if (err) {
			pr_err("%s: halt failed while doing %s err (%d)\n",
					mmc_hostname(card->host),
					__func__, err);
			mmc_put_card(card);
			goto cmd_done;
		}
	}

	mmc_put_card(card);

	/*
	/*
	 * Dispatch the ioctl() into the block request queue.
	 * Dispatch the ioctl() into the block request queue.
	 */
	 */
@@ -1101,11 +1086,6 @@ static int mmc_blk_ioctl_cmd(struct mmc_blk_data *md,
	err = mmc_blk_ioctl_copy_to_user(ic_ptr, idata);
	err = mmc_blk_ioctl_copy_to_user(ic_ptr, idata);
	blk_put_request(req);
	blk_put_request(req);


	if (mmc_card_cmdq(card)) {
		if (mmc_cmdq_halt(card->host, false))
			pr_err("%s: %s: cmdq unhalt failed\n",
			       mmc_hostname(card->host), __func__);
	}
cmd_done:
cmd_done:
	kfree(idata->buf);
	kfree(idata->buf);
	kfree(idata);
	kfree(idata);
@@ -3534,16 +3514,11 @@ static int mmc_cmdq_wait_for_small_sector_read(struct mmc_card *card,
	return ret;
	return ret;
}
}


static int mmc_blk_cmdq_issue_drv_op(struct mmc_card *card, struct request *req)
static int mmc_blk_cmdq_issue_drv_op(struct mmc_card *card,
				struct mmc_queue *mq, struct request *req)
{
{
	struct mmc_queue_req *mq_rq;
	u8 **ext_csd;
	u32 status;
	int ret;
	int ret;


	mq_rq = req_to_mmc_queue_req(req);
	ext_csd = mq_rq->drv_op_data;

	ret = mmc_cmdq_halt_on_empty_queue(card->host);
	ret = mmc_cmdq_halt_on_empty_queue(card->host);
	if (ret) {
	if (ret) {
		pr_err("%s: failed to halt on empty queue\n",
		pr_err("%s: failed to halt on empty queue\n",
@@ -3553,35 +3528,8 @@ static int mmc_blk_cmdq_issue_drv_op(struct mmc_card *card, struct request *req)
		return ret;
		return ret;
	}
	}


	switch (mq_rq->drv_op) {
	mmc_blk_issue_drv_op(mq, req);
	case MMC_DRV_OP_GET_EXT_CSD:
		ret = mmc_get_ext_csd(card, ext_csd);
		if (ret) {
			pr_err("%s: failed to get ext_csd\n",
						mmc_hostname(card->host));
			goto out_unhalt;
		}
		break;
	case MMC_DRV_OP_GET_CARD_STATUS:
		ret = mmc_send_status(card, &status);
		if (ret) {
			pr_err("%s: failed to get status\n",
						mmc_hostname(card->host));
			goto out_unhalt;
		}
		ret = status;
		break;
	default:
		pr_err("%s: unknown driver specific operation\n",
					mmc_hostname(card->host));
		ret = -EINVAL;
		break;
	}
	mq_rq->drv_op_result = ret;
	ret = ret ? BLK_STS_IOERR : BLK_STS_OK;


out_unhalt:
	blk_end_request_all(req, ret);
	ret = mmc_cmdq_halt(card->host, false);
	ret = mmc_cmdq_halt(card->host, false);
	if (ret)
	if (ret)
		pr_err("%s: %s: failed to unhalt\n",
		pr_err("%s: %s: failed to unhalt\n",
@@ -3656,7 +3604,7 @@ static int mmc_blk_cmdq_issue_rq(struct mmc_queue *mq, struct request *req)
			break;
			break;
		case REQ_OP_DRV_IN:
		case REQ_OP_DRV_IN:
		case REQ_OP_DRV_OUT:
		case REQ_OP_DRV_OUT:
			ret = mmc_blk_cmdq_issue_drv_op(card, req);
			ret = mmc_blk_cmdq_issue_drv_op(card, mq, req);
			break;
			break;
		default:
		default:
			ret = mmc_blk_cmdq_issue_rw_rq(mq, req);
			ret = mmc_blk_cmdq_issue_rw_rq(mq, req);