> -----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

Reply via email to