> -----Original Message----- > From: linux-mmc-owner@xxxxxxxxxxxxxxx [mailto:linux-mmc- > owner@xxxxxxxxxxxxxxx] On Behalf Of Linus Walleij > Sent: Wednesday, May 10, 2017 11:24 AM > To: linux-mmc@xxxxxxxxxxxxxxx; Ulf Hansson <ulf.hansson@xxxxxxxxxx>; > Adrian Hunter <adrian.hunter@xxxxxxxxx> > Cc: linux-block@xxxxxxxxxxxxxxx; Jens Axboe <axboe@xxxxxxxxx>; Christoph > Hellwig <hch@xxxxxx>; Arnd Bergmann <arnd@xxxxxxxx>; Bartlomiej > Zolnierkiewicz <b.zolnierkie@xxxxxxxxxxx>; Paolo Valente > <paolo.valente@xxxxxxxxxx>; Linus Walleij <linus.walleij@xxxxxxxxxx> > 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 <linus.walleij@xxxxxxxxxx> > --- > 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at > http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html