> -----Original Message-----
> From: [email protected] [mailto:linux-mmc-
> [email protected]] On Behalf Of Linus Walleij
> Sent: Wednesday, May 10, 2017 11:24 AM
> To: [email protected]; Ulf Hansson <[email protected]>;
> Adrian Hunter <[email protected]>
> Cc: [email protected]; Jens Axboe <[email protected]>; Christoph
> Hellwig <[email protected]>; Arnd Bergmann <[email protected]>; Bartlomiej
> Zolnierkiewicz <[email protected]>; Paolo Valente
> <[email protected]>; Linus Walleij <[email protected]>
> Subject: [PATCH 5/5] 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 <[email protected]>
> ---
> drivers/mmc/core/block.c | 38 +++++++++++++++++++++++++-------------
> drivers/mmc/core/queue.h | 3 ++-
> 2 files changed, 27 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index
> 640db4f57a31..152de904d5e4 100644
> --- a/drivers/mmc/core/block.c
> +++ b/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_blk_ioc_data *idata;
> + struct mmc_blk_ioc_data *idatas[1];
> struct mmc_blk_data *md;
> struct mmc_queue *mq;
> struct mmc_card *card;
> @@ -600,7 +601,9 @@ static int mmc_blk_ioctl_cmd(struct block_device
> *bdev,
> req = blk_get_request(mq->queue,
> idata->ic.write_flag ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN,
> __GFP_RECLAIM);
> - req_to_mq_rq(req)->idata = idata;
> + idatas[0] = idata;
> + req_to_mq_rq(req)->idata = idatas;
> + req_to_mq_rq(req)->ioc_count = 1;
> blk_execute_rq(mq->queue, NULL, req, 0);
> ioc_err = req_to_mq_rq(req)->ioc_result;
> err = mmc_blk_ioctl_copy_to_user(ic_ptr, idata); @@ -622,14 +625,17
> @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, static void
> mmc_blk_ioctl_cmd_issue(struct mmc_queue *mq, struct request *req) {
> struct mmc_queue_req *mq_rq;
> - struct mmc_blk_ioc_data *idata;
> struct mmc_card *card = mq->card;
> struct mmc_blk_data *md = mq->blkdata;
> int ioc_err;
> + int i;
>
> mq_rq = req_to_mq_rq(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;
>
> /* 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_card *card;
> struct mmc_blk_data *md;
> + struct mmc_queue *mq;
> int i, err = 0, ioc_err = 0;
> __u64 num_of_cmds;
> + struct request *req;
>
> /*
> * 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;
> }
>
> - 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);
It is possible, e.g. as in RPMB access, that some commands are read and some
are write.
Not sure that it makes any difference, because once it get back to
mmc_blk_ioctl_cmd_issue(),
The correct mmc requests will be issued anyway?
> + req_to_mq_rq(req)->idata = idata;
> + req_to_mq_rq(req)->ioc_count = num_of_cmds;
> + blk_execute_rq(mq->queue, NULL, req, 0);
> + ioc_err = req_to_mq_rq(req)->ioc_result;
>
> /* copy to user if data and response */
> for (i = 0; i < num_of_cmds && !err; i++)
> err = mmc_blk_ioctl_copy_to_user(&cmds[i], idata[i]);
>
> + blk_put_request(req);
> +
> cmd_done:
> mmc_blk_put(md);
> cmd_err:
> diff --git a/drivers/mmc/core/queue.h b/drivers/mmc/core/queue.h index
> aeb3408dc85e..7015df6681c3 100644
> --- a/drivers/mmc/core/queue.h
> +++ b/drivers/mmc/core/queue.h
> @@ -42,7 +42,8 @@ struct mmc_queue_req {
> unsigned int bounce_sg_len;
> struct mmc_async_req areq;
> int ioc_result;
> - struct mmc_blk_ioc_data *idata;
> + struct mmc_blk_ioc_data **idata;
> + unsigned int ioc_count;
> };
>
> struct mmc_queue {
> --
> 2.9.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the
> body of a message to [email protected] More majordomo info at
> http://vger.kernel.org/majordomo-info.html