Browse Source

mmc: block: move multi-ioctl() to use block layer

This switches also the multiple-command ioctl() call to issue
all ioctl()s through the block layer instead of going directly
to the device.

We extend the passed argument with an argument count and loop
over all passed commands in the ioctl() issue function called
from the block layer.

By doing this we are again loosening the grip on the big host
lock, since two calls to mmc_get_card()/mmc_put_card() are
removed.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Tested-by: Avri Altman <Avri.Altman@sandisk.com>
Linus Walleij 8 years ago
parent
commit
3ecd8cf23f
2 changed files with 27 additions and 14 deletions
  1. 25 13
      drivers/mmc/core/block.c
  2. 2 1
      drivers/mmc/core/queue.h

+ 25 - 13
drivers/mmc/core/block.c

@@ -563,6 +563,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
 			     struct mmc_ioc_cmd __user *ic_ptr)
 			     struct mmc_ioc_cmd __user *ic_ptr)
 {
 {
 	struct mmc_blk_ioc_data *idata;
 	struct mmc_blk_ioc_data *idata;
+	struct mmc_blk_ioc_data *idatas[1];
 	struct mmc_blk_data *md;
 	struct mmc_blk_data *md;
 	struct mmc_queue *mq;
 	struct mmc_queue *mq;
 	struct mmc_card *card;
 	struct mmc_card *card;
@@ -600,7 +601,9 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
 	req = blk_get_request(mq->queue,
 	req = blk_get_request(mq->queue,
 		idata->ic.write_flag ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN,
 		idata->ic.write_flag ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN,
 		__GFP_RECLAIM);
 		__GFP_RECLAIM);
-	req_to_mmc_queue_req(req)->idata = idata;
+	idatas[0] = idata;
+	req_to_mmc_queue_req(req)->idata = idatas;
+	req_to_mmc_queue_req(req)->ioc_count = 1;
 	blk_execute_rq(mq->queue, NULL, req, 0);
 	blk_execute_rq(mq->queue, NULL, req, 0);
 	ioc_err = req_to_mmc_queue_req(req)->ioc_result;
 	ioc_err = req_to_mmc_queue_req(req)->ioc_result;
 	err = mmc_blk_ioctl_copy_to_user(ic_ptr, idata);
 	err = mmc_blk_ioctl_copy_to_user(ic_ptr, idata);
@@ -622,14 +625,17 @@ cmd_err:
 static void mmc_blk_ioctl_cmd_issue(struct mmc_queue *mq, struct request *req)
 static void mmc_blk_ioctl_cmd_issue(struct mmc_queue *mq, struct request *req)
 {
 {
 	struct mmc_queue_req *mq_rq;
 	struct mmc_queue_req *mq_rq;
-	struct mmc_blk_ioc_data *idata;
 	struct mmc_card *card = mq->card;
 	struct mmc_card *card = mq->card;
 	struct mmc_blk_data *md = mq->blkdata;
 	struct mmc_blk_data *md = mq->blkdata;
 	int ioc_err;
 	int ioc_err;
+	int i;
 
 
 	mq_rq = req_to_mmc_queue_req(req);
 	mq_rq = req_to_mmc_queue_req(req);
-	idata = mq_rq->idata;
-	ioc_err = __mmc_blk_ioctl_cmd(card, md, idata);
+	for (i = 0; i < mq_rq->ioc_count; i++) {
+		ioc_err = __mmc_blk_ioctl_cmd(card, md, mq_rq->idata[i]);
+		if (ioc_err)
+			break;
+	}
 	mq_rq->ioc_result = ioc_err;
 	mq_rq->ioc_result = ioc_err;
 
 
 	/* Always switch back to main area after RPMB access */
 	/* Always switch back to main area after RPMB access */
@@ -646,8 +652,10 @@ static int mmc_blk_ioctl_multi_cmd(struct block_device *bdev,
 	struct mmc_ioc_cmd __user *cmds = user->cmds;
 	struct mmc_ioc_cmd __user *cmds = user->cmds;
 	struct mmc_card *card;
 	struct mmc_card *card;
 	struct mmc_blk_data *md;
 	struct mmc_blk_data *md;
+	struct mmc_queue *mq;
 	int i, err = 0, ioc_err = 0;
 	int i, err = 0, ioc_err = 0;
 	__u64 num_of_cmds;
 	__u64 num_of_cmds;
+	struct request *req;
 
 
 	/*
 	/*
 	 * The caller must have CAP_SYS_RAWIO, and must be calling this on the
 	 * The caller must have CAP_SYS_RAWIO, and must be calling this on the
@@ -689,21 +697,25 @@ static int mmc_blk_ioctl_multi_cmd(struct block_device *bdev,
 		goto cmd_done;
 		goto cmd_done;
 	}
 	}
 
 
-	mmc_get_card(card);
-
-	for (i = 0; i < num_of_cmds && !ioc_err; i++)
-		ioc_err = __mmc_blk_ioctl_cmd(card, md, idata[i]);
-
-	/* Always switch back to main area after RPMB access */
-	if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
-		mmc_blk_part_switch(card, dev_get_drvdata(&card->dev));
 
 
-	mmc_put_card(card);
+	/*
+	 * Dispatch the ioctl()s into the block request queue.
+	 */
+	mq = &md->queue;
+	req = blk_get_request(mq->queue,
+		idata[0]->ic.write_flag ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN,
+		__GFP_RECLAIM);
+	req_to_mmc_queue_req(req)->idata = idata;
+	req_to_mmc_queue_req(req)->ioc_count = num_of_cmds;
+	blk_execute_rq(mq->queue, NULL, req, 0);
+	ioc_err = req_to_mmc_queue_req(req)->ioc_result;
 
 
 	/* copy to user if data and response */
 	/* copy to user if data and response */
 	for (i = 0; i < num_of_cmds && !err; i++)
 	for (i = 0; i < num_of_cmds && !err; i++)
 		err = mmc_blk_ioctl_copy_to_user(&cmds[i], idata[i]);
 		err = mmc_blk_ioctl_copy_to_user(&cmds[i], idata[i]);
 
 
+	blk_put_request(req);
+
 cmd_done:
 cmd_done:
 	mmc_blk_put(md);
 	mmc_blk_put(md);
 cmd_err:
 cmd_err:

+ 2 - 1
drivers/mmc/core/queue.h

@@ -42,7 +42,8 @@ struct mmc_queue_req {
 	unsigned int		bounce_sg_len;
 	unsigned int		bounce_sg_len;
 	struct mmc_async_req	areq;
 	struct mmc_async_req	areq;
 	int			ioc_result;
 	int			ioc_result;
-	struct mmc_blk_ioc_data	*idata;
+	struct mmc_blk_ioc_data	**idata;
+	unsigned int		ioc_count;
 };
 };
 
 
 struct mmc_queue {
 struct mmc_queue {