diff mbox

mmc: block: Add new ioctl to send multi commands

Message ID 1441811161-18513-1-git-send-email-jonathanh@nvidia.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jon Hunter Sept. 9, 2015, 3:06 p.m. UTC
From: Seshagiri Holi <sholi@nvidia.com>

Certain eMMC devices allow vendor specific device information to be read
via a sequence of vendor commands. These vendor commands must be issued
in sequence and an atomic fashion. One way to support this would be to
add an ioctl function for sending a sequence of commands to the device
atomically as proposed here. These multi commands are simple array of
the existing mmc_ioc_cmd structure.

Signed-off-by: Seshagiri Holi <sholi@nvidia.com>
[ jonathanh@nvidia.com: Rebased on linux-next from v3.18. Changed
  userspace pointer type for multi command to be a u64. Renamed
  from combo commands to multi commands. Updated patch based upon
  feedback review comments received. Updated commit message ]
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
---
 drivers/mmc/card/block.c       | 198 ++++++++++++++++++++++++++++++++---------
 include/uapi/linux/mmc/ioctl.h |  17 +++-
 2 files changed, 170 insertions(+), 45 deletions(-)

Comments

Arnd Bergmann Sept. 9, 2015, 3:56 p.m. UTC | #1
On Wednesday 09 September 2015 16:06:01 Jon Hunter wrote:
> +
> +       idata = kcalloc(mcci.num_of_cmds, sizeof(*idata), GFP_KERNEL);
> +       if (!idata) {
> +               err = -ENOMEM;
> +               goto cmd_err;
> +       }
> +
> +       cmds = (struct mmc_ioc_cmd __user *)(unsigned long)mcci.cmds_ptr;
> +       for (n_cmds = 0; n_cmds < mcci.num_of_cmds; n_cmds++) {
> +               idata[n_cmds] = mmc_blk_ioctl_copy_from_user(&cmds[n_cmds]);
> +               if (IS_ERR(idata[n_cmds])) {
> +                       err = PTR_ERR(idata[n_cmds]);
> +                       goto cmd_err;
> +               }
> +       }
> +

You have no upper bound on the number of commands, which means you end
up catching overly large arguments only through -ENOMEM. Can you come
up with an upper bound that is guaranteed to succeed with the allocation?

Or would it be possible to process the user data one at a time while
going through the commands?

> +struct mmc_ioc_multi_cmd {
> +       __u64 cmds_ptr;
> +       uint8_t num_of_cmds;
> +};
 
complex commands are always nasty in one way or another. Can you describe
in the patch description why you picked an indirect pointer over something
like

struct mmc_ioc_multi_cmd {
	__u64 num_of_cmds;
	struct mmc_ioc_cmd cmds[0];
};

as I said, both are ugly. My first choice would have been the other one,
but I'm sure you have some reasons yourself.

	Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jon Hunter Sept. 9, 2015, 4:44 p.m. UTC | #2
On 09/09/15 16:56, Arnd Bergmann wrote:
> On Wednesday 09 September 2015 16:06:01 Jon Hunter wrote:
>> +
>> +       idata = kcalloc(mcci.num_of_cmds, sizeof(*idata), GFP_KERNEL);
>> +       if (!idata) {
>> +               err = -ENOMEM;
>> +               goto cmd_err;
>> +       }
>> +
>> +       cmds = (struct mmc_ioc_cmd __user *)(unsigned long)mcci.cmds_ptr;
>> +       for (n_cmds = 0; n_cmds < mcci.num_of_cmds; n_cmds++) {
>> +               idata[n_cmds] = mmc_blk_ioctl_copy_from_user(&cmds[n_cmds]);
>> +               if (IS_ERR(idata[n_cmds])) {
>> +                       err = PTR_ERR(idata[n_cmds]);
>> +                       goto cmd_err;
>> +               }
>> +       }
>> +
> 
> You have no upper bound on the number of commands, which means you end
> up catching overly large arguments only through -ENOMEM. Can you come
> up with an upper bound that is guaranteed to succeed with the allocation?

The uint8 type would limit you to 256 commands (if you have the memory),
although admittedly that is probably overkill.
 
> Or would it be possible to process the user data one at a time while
> going through the commands?

Yes, I think that could be a good option, I will take a look.
 
>> +struct mmc_ioc_multi_cmd {
>> +       __u64 cmds_ptr;
>> +       uint8_t num_of_cmds;
>> +};
>  
> complex commands are always nasty in one way or another. Can you describe
> in the patch description why you picked an indirect pointer over something
> like
> 
> struct mmc_ioc_multi_cmd {
> 	__u64 num_of_cmds;
> 	struct mmc_ioc_cmd cmds[0];
> };
> 
> as I said, both are ugly. My first choice would have been the other one,
> but I'm sure you have some reasons yourself.

It was a suggestion from Olof to ensure the structure size is constant for
both 32-bit and 64-bit userspaces. I am not sure if it is worth adding a
macro similar to the below for this?

#define mmc_ioc_cmd_set_data(ic, ptr) ic.data_ptr = (__u64)(unsigned long) ptr

However, yes can update the changelog.

Cheers
Jon
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Arnd Bergmann Sept. 9, 2015, 8:22 p.m. UTC | #3
On Wednesday 09 September 2015 17:44:54 Jon Hunter wrote:
> 
> On 09/09/15 16:56, Arnd Bergmann wrote:
> > On Wednesday 09 September 2015 16:06:01 Jon Hunter wrote:
> >> +
> >> +       idata = kcalloc(mcci.num_of_cmds, sizeof(*idata), GFP_KERNEL);
> >> +       if (!idata) {
> >> +               err = -ENOMEM;
> >> +               goto cmd_err;
> >> +       }
> >> +
> >> +       cmds = (struct mmc_ioc_cmd __user *)(unsigned long)mcci.cmds_ptr;
> >> +       for (n_cmds = 0; n_cmds < mcci.num_of_cmds; n_cmds++) {
> >> +               idata[n_cmds] = mmc_blk_ioctl_copy_from_user(&cmds[n_cmds]);
> >> +               if (IS_ERR(idata[n_cmds])) {
> >> +                       err = PTR_ERR(idata[n_cmds]);
> >> +                       goto cmd_err;
> >> +               }
> >> +       }
> >> +
> > 
> > You have no upper bound on the number of commands, which means you end
> > up catching overly large arguments only through -ENOMEM. Can you come
> > up with an upper bound that is guaranteed to succeed with the allocation?
> 
> The uint8 type would limit you to 256 commands (if you have the memory),
> although admittedly that is probably overkill.

Good point.

Please note a few details here:

- in uabi headers, we need to use __u8 instead of uint8, because we cannot
  rely on libc header file inclusion for kernel headers.

- you have some implicit padding after the structure and should replace that
  with explictit pad bytes to extend the structure to a multiple of its
  alignment (8 bytes).

> >> +struct mmc_ioc_multi_cmd {
> >> +       __u64 cmds_ptr;
> >> +       uint8_t num_of_cmds;
> >> +};
> >  
> > complex commands are always nasty in one way or another. Can you describe
> > in the patch description why you picked an indirect pointer over something
> > like
> > 
> > struct mmc_ioc_multi_cmd {
> > 	__u64 num_of_cmds;
> > 	struct mmc_ioc_cmd cmds[0];
> > };
> > 
> > as I said, both are ugly. My first choice would have been the other one,
> > but I'm sure you have some reasons yourself.
> 
> It was a suggestion from Olof to ensure the structure size is constant for
> both 32-bit and 64-bit userspaces. I am not sure if it is worth adding a
> macro similar to the below for this?
> 
> #define mmc_ioc_cmd_set_data(ic, ptr) ic.data_ptr = (__u64)(unsigned long) ptr
> 
> However, yes can update the changelog.

I was not referring to the use of an __u64 variable to pass a pointer, that
is expected (and the macro would make it harder to understand).

What I meant instead was the use of a pointer to an array as opposed to
passing the array itself. With the definition I gave above, the size would
still be the same on all architectures (you can replace the __u64 with
an __u8 plus padding if you like), as sizeof(struct mmc_ioc_multi_cmd)
is just '8' here.

Alternatively, you could just use an array of struct mmc_ioc_cmd by
itself and encode the length in the ioctl command:

#define MMC_COMBO_IOC_CMD(n) _IOC(_IOC_READ|_IOC_WRITE, 1, sizeof(struct mmc_ioc_cmd) * (n))

This is of course also ugly because the ioctl command number is not
fixed, and because the limit for the number of mmc command blocks
is architecture dependent, depending on the definition of the _IOC
macro that can have either 13 or 14 bits to encode the argument length
in bytes.

	Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jon Hunter Sept. 10, 2015, 8:24 a.m. UTC | #4
Hi Arnd,

On 09/09/15 21:22, Arnd Bergmann wrote:
> On Wednesday 09 September 2015 17:44:54 Jon Hunter wrote:
>>
>> On 09/09/15 16:56, Arnd Bergmann wrote:
>>> On Wednesday 09 September 2015 16:06:01 Jon Hunter wrote:
>>>> +
>>>> +       idata = kcalloc(mcci.num_of_cmds, sizeof(*idata), GFP_KERNEL);
>>>> +       if (!idata) {
>>>> +               err = -ENOMEM;
>>>> +               goto cmd_err;
>>>> +       }
>>>> +
>>>> +       cmds = (struct mmc_ioc_cmd __user *)(unsigned long)mcci.cmds_ptr;
>>>> +       for (n_cmds = 0; n_cmds < mcci.num_of_cmds; n_cmds++) {
>>>> +               idata[n_cmds] = mmc_blk_ioctl_copy_from_user(&cmds[n_cmds]);
>>>> +               if (IS_ERR(idata[n_cmds])) {
>>>> +                       err = PTR_ERR(idata[n_cmds]);
>>>> +                       goto cmd_err;
>>>> +               }
>>>> +       }
>>>> +
>>>
>>> You have no upper bound on the number of commands, which means you end
>>> up catching overly large arguments only through -ENOMEM. Can you come
>>> up with an upper bound that is guaranteed to succeed with the allocation?
>>
>> The uint8 type would limit you to 256 commands (if you have the memory),
>> although admittedly that is probably overkill.
> 
> Good point.
> 
> Please note a few details here:
> 
> - in uabi headers, we need to use __u8 instead of uint8, because we cannot
>   rely on libc header file inclusion for kernel headers.

Ok.

> - you have some implicit padding after the structure and should replace that
>   with explictit pad bytes to extend the structure to a multiple of its
>   alignment (8 bytes).

Would padding with __u32 at the end be sufficient here? I assume the
__u32 would be 32-bit aligned. However, was not sure if this would
always be the case.

>>>> +struct mmc_ioc_multi_cmd {
>>>> +       __u64 cmds_ptr;
>>>> +       uint8_t num_of_cmds;
>>>> +};
>>>  
>>> complex commands are always nasty in one way or another. Can you describe
>>> in the patch description why you picked an indirect pointer over something
>>> like
>>>
>>> struct mmc_ioc_multi_cmd {
>>> 	__u64 num_of_cmds;
>>> 	struct mmc_ioc_cmd cmds[0];
>>> };
>>>
>>> as I said, both are ugly. My first choice would have been the other one,
>>> but I'm sure you have some reasons yourself.
>>
>> It was a suggestion from Olof to ensure the structure size is constant for
>> both 32-bit and 64-bit userspaces. I am not sure if it is worth adding a
>> macro similar to the below for this?
>>
>> #define mmc_ioc_cmd_set_data(ic, ptr) ic.data_ptr = (__u64)(unsigned long) ptr
>>
>> However, yes can update the changelog.
> 
> I was not referring to the use of an __u64 variable to pass a pointer, that
> is expected (and the macro would make it harder to understand).
> 
> What I meant instead was the use of a pointer to an array as opposed to
> passing the array itself. With the definition I gave above, the size would
> still be the same on all architectures (you can replace the __u64 with
> an __u8 plus padding if you like), as sizeof(struct mmc_ioc_multi_cmd)
> is just '8' here.

Do you have any strong preference here? I guess I don't and agree
neither are ideal.

> Alternatively, you could just use an array of struct mmc_ioc_cmd by
> itself and encode the length in the ioctl command:
> 
> #define MMC_COMBO_IOC_CMD(n) _IOC(_IOC_READ|_IOC_WRITE, 1, sizeof(struct mmc_ioc_cmd) * (n))
> 
> This is of course also ugly because the ioctl command number is not
> fixed, and because the limit for the number of mmc command blocks
> is architecture dependent, depending on the definition of the _IOC
> macro that can have either 13 or 14 bits to encode the argument length
> in bytes.

Interesting idea. However, given your comments above, I think that I
would rather place the size in the structure.

Cheers
Jon
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Arnd Bergmann Sept. 10, 2015, 8:38 a.m. UTC | #5
On Thursday 10 September 2015 09:24:19 Jon Hunter wrote:
> On 09/09/15 21:22, Arnd Bergmann wrote:
> > On Wednesday 09 September 2015 17:44:54 Jon Hunter wrote:
> >> On 09/09/15 16:56, Arnd Bergmann wrote:
> >>> On Wednesday 09 September 2015 16:06:01 Jon Hunter wrote:
> 
> > - you have some implicit padding after the structure and should replace that
> >   with explictit pad bytes to extend the structure to a multiple of its
> >   alignment (8 bytes).
> 
> Would padding with __u32 at the end be sufficient here? I assume the
> __u32 would be 32-bit aligned. However, was not sure if this would
> always be the case.

If you have a layout of 

	__u64 pointer; 
	__u8 size;
	__u32 pad;

you still get three bytes of implied padding between size and pad. It's
better to just have '__u8 __pad[7]' in that case.

> > I was not referring to the use of an __u64 variable to pass a pointer, that
> > is expected (and the macro would make it harder to understand).
> > 
> > What I meant instead was the use of a pointer to an array as opposed to
> > passing the array itself. With the definition I gave above, the size would
> > still be the same on all architectures (you can replace the __u64 with
> > an __u8 plus padding if you like), as sizeof(struct mmc_ioc_multi_cmd)
> > is just '8' here.
> 
> Do you have any strong preference here? I guess I don't and agree
> neither are ideal.
> 
> > Alternatively, you could just use an array of struct mmc_ioc_cmd by
> > itself and encode the length in the ioctl command:
> > 
> > #define MMC_COMBO_IOC_CMD(n) _IOC(_IOC_READ|_IOC_WRITE, 1, sizeof(struct mmc_ioc_cmd) * (n))
> > 
> > This is of course also ugly because the ioctl command number is not
> > fixed, and because the limit for the number of mmc command blocks
> > is architecture dependent, depending on the definition of the _IOC
> > macro that can have either 13 or 14 bits to encode the argument length
> > in bytes.
> 
> Interesting idea. However, given your comments above, I think that I
> would rather place the size in the structure.

I don't have a strong preference here. If there is a slight chance that
you might need more than ((1<<13) / sizeof(struct mmc_ioc_cmd)) mmc commands
in one ioctl, you can rule out that last solution.

If you can prove that this length would always be sufficient, I'd probably
pick that approach. Otherwise, I'd pick the one the size followed by
an an open array.

	Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Grant Grundler Sept. 10, 2015, 5:10 p.m. UTC | #6
On Thu, Sep 10, 2015 at 1:24 AM, Jon Hunter <jonathanh@nvidia.com> wrote:
...
>> - you have some implicit padding after the structure and should replace that
>>   with explictit pad bytes to extend the structure to a multiple of its
>>   alignment (8 bytes).
>
> Would padding with __u32 at the end be sufficient here? I assume the
> __u32 would be 32-bit aligned. However, was not sure if this would
> always be the case.

Is there something wrong with implicit padding?
Only one copy of the structure is passed to the kernel for any given call.

>>>> struct mmc_ioc_multi_cmd {
>>>>     __u64 num_of_cmds;
>>>>     struct mmc_ioc_cmd cmds[0];
>>>> };

I think this would work just as well. But doesn't "pointer to an
array" require 32-bit ioctl compat handling?
We were trying to avoid a 32-bit user space compatibility handler.

>>>> as I said, both are ugly. My first choice would have been the other one,
>>>> but I'm sure you have some reasons yourself.

Why do you prefer the alternative you proposed?

My guess is better type checking (and I would like that too). But
maybe there is something else?

cheers,
grant
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jon Hunter Sept. 10, 2015, 6:20 p.m. UTC | #7
On 10/09/15 18:10, Grant Grundler wrote:
> On Thu, Sep 10, 2015 at 1:24 AM, Jon Hunter <jonathanh@nvidia.com> wrote:
> ...
>>> - you have some implicit padding after the structure and should replace that
>>>   with explictit pad bytes to extend the structure to a multiple of its
>>>   alignment (8 bytes).
>>
>> Would padding with __u32 at the end be sufficient here? I assume the
>> __u32 would be 32-bit aligned. However, was not sure if this would
>> always be the case.
> 
> Is there something wrong with implicit padding?
> Only one copy of the structure is passed to the kernel for any given call.
> 
>>>>> struct mmc_ioc_multi_cmd {
>>>>>     __u64 num_of_cmds;
>>>>>     struct mmc_ioc_cmd cmds[0];
>>>>> };
> 
> I think this would work just as well. But doesn't "pointer to an
> array" require 32-bit ioctl compat handling?
> We were trying to avoid a 32-bit user space compatibility handler.

I think that this is fine as it is a zero length array [0] and not a
pointer.

Cheers
Jon

[0] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Grant Grundler Sept. 10, 2015, 8:26 p.m. UTC | #8
On Thu, Sep 10, 2015 at 11:20 AM, Jon Hunter <jonathanh@nvidia.com> wrote:
>
> On 10/09/15 18:10, Grant Grundler wrote:
...
>>>>>> struct mmc_ioc_multi_cmd {
>>>>>>     __u64 num_of_cmds;
>>>>>>     struct mmc_ioc_cmd cmds[0];
>>>>>> };
>>
>> I think this would work just as well. But doesn't "pointer to an
>> array" require 32-bit ioctl compat handling?
>> We were trying to avoid a 32-bit user space compatibility handler.
>
> I think that this is fine as it is a zero length array [0] and not a
> pointer.

Doh, yes. Thanks for correcting. I knew this was a gcc special but
forgot it's not actually allocating any space.

cheers,
grant

>
> Cheers
> Jon
>
> [0] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index c742cfd7674e..738bfd037209 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -387,6 +387,24 @@  out:
 	return ERR_PTR(err);
 }
 
+static int mmc_blk_ioctl_copy_to_user(struct mmc_ioc_cmd __user *ic_ptr,
+				      struct mmc_blk_ioc_data *idata)
+{
+	struct mmc_ioc_cmd *ic = &idata->ic;
+
+	if (copy_to_user(&(ic_ptr->response), ic->response,
+			 sizeof(ic->response)))
+		return -EFAULT;
+
+	if (!idata->ic.write_flag) {
+		if (copy_to_user((void __user *)(unsigned long)ic->data_ptr,
+				 idata->buf, idata->buf_bytes))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
 static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
 				       u32 retries_max)
 {
@@ -447,12 +465,9 @@  out:
 	return err;
 }
 
-static int mmc_blk_ioctl_cmd(struct block_device *bdev,
-	struct mmc_ioc_cmd __user *ic_ptr)
+static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
+			       struct mmc_blk_ioc_data *idata)
 {
-	struct mmc_blk_ioc_data *idata;
-	struct mmc_blk_data *md;
-	struct mmc_card *card;
 	struct mmc_command cmd = {0};
 	struct mmc_data data = {0};
 	struct mmc_request mrq = {NULL};
@@ -461,33 +476,12 @@  static int mmc_blk_ioctl_cmd(struct block_device *bdev,
 	int is_rpmb = false;
 	u32 status = 0;
 
-	/*
-	 * The caller must have CAP_SYS_RAWIO, and must be calling this on the
-	 * whole block device, not on a partition.  This prevents overspray
-	 * between sibling partitions.
-	 */
-	if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains))
-		return -EPERM;
-
-	idata = mmc_blk_ioctl_copy_from_user(ic_ptr);
-	if (IS_ERR(idata))
-		return PTR_ERR(idata);
-
-	md = mmc_blk_get(bdev->bd_disk);
-	if (!md) {
-		err = -EINVAL;
-		goto cmd_err;
-	}
+	if (!card || !md || !idata)
+		return -EINVAL;
 
 	if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
 		is_rpmb = true;
 
-	card = md->queue.card;
-	if (IS_ERR(card)) {
-		err = PTR_ERR(card);
-		goto cmd_done;
-	}
-
 	cmd.opcode = idata->ic.opcode;
 	cmd.arg = idata->ic.arg;
 	cmd.flags = idata->ic.flags;
@@ -582,18 +576,7 @@  static int mmc_blk_ioctl_cmd(struct block_device *bdev,
 	if (idata->ic.postsleep_min_us)
 		usleep_range(idata->ic.postsleep_min_us, idata->ic.postsleep_max_us);
 
-	if (copy_to_user(&(ic_ptr->response), cmd.resp, sizeof(cmd.resp))) {
-		err = -EFAULT;
-		goto cmd_rel_host;
-	}
-
-	if (!idata->ic.write_flag) {
-		if (copy_to_user((void __user *)(unsigned long) idata->ic.data_ptr,
-						idata->buf, idata->buf_bytes)) {
-			err = -EFAULT;
-			goto cmd_rel_host;
-		}
-	}
+	memcpy(&(idata->ic.response), cmd.resp, sizeof(cmd.resp));
 
 	if (is_rpmb) {
 		/*
@@ -609,6 +592,46 @@  static int mmc_blk_ioctl_cmd(struct block_device *bdev,
 
 cmd_rel_host:
 	mmc_put_card(card);
+	return err;
+}
+
+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_data *md;
+	struct mmc_card *card;
+	int err;
+
+	/*
+	 * The caller must have CAP_SYS_RAWIO, and must be calling this on the
+	 * whole block device, not on a partition.  This prevents overspray
+	 * between sibling partitions.
+	 */
+	if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains))
+		return -EPERM;
+
+	idata = mmc_blk_ioctl_copy_from_user(ic_ptr);
+	if (IS_ERR(idata))
+		return PTR_ERR(idata);
+
+	md = mmc_blk_get(bdev->bd_disk);
+	if (!md) {
+		err = -EINVAL;
+		goto cmd_err;
+	}
+
+	card = md->queue.card;
+	if (IS_ERR(card)) {
+		err = PTR_ERR(card);
+		goto cmd_done;
+	}
+
+	err = __mmc_blk_ioctl_cmd(card, md, idata);
+	if (err)
+		goto cmd_done;
+
+	err = mmc_blk_ioctl_copy_to_user(ic_ptr, idata);
 
 cmd_done:
 	mmc_blk_put(md);
@@ -618,13 +641,100 @@  cmd_err:
 	return err;
 }
 
+static int mmc_blk_ioctl_multi_cmd(struct block_device *bdev,
+				   struct mmc_ioc_multi_cmd __user *user)
+{
+	struct mmc_ioc_multi_cmd mcci = {0};
+	struct mmc_blk_ioc_data **idata = NULL;
+	struct mmc_ioc_cmd __user *cmds;
+	struct mmc_card *card;
+	struct mmc_blk_data *md;
+	int i, err = -EFAULT;
+	u8 n_cmds = 0;
+
+	/*
+	 * The caller must have CAP_SYS_RAWIO, and must be calling this on the
+	 * whole block device, not on a partition.  This prevents overspray
+	 * between sibling partitions.
+	 */
+	if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains))
+		return -EPERM;
+
+	if (copy_from_user(&mcci, user, sizeof(struct mmc_ioc_multi_cmd)))
+		return -EFAULT;
+
+	if (!mcci.num_of_cmds) {
+		err = -EINVAL;
+		goto cmd_err;
+	}
+
+	idata = kcalloc(mcci.num_of_cmds, sizeof(*idata), GFP_KERNEL);
+	if (!idata) {
+		err = -ENOMEM;
+		goto cmd_err;
+	}
+
+	cmds = (struct mmc_ioc_cmd __user *)(unsigned long)mcci.cmds_ptr;
+	for (n_cmds = 0; n_cmds < mcci.num_of_cmds; n_cmds++) {
+		idata[n_cmds] = mmc_blk_ioctl_copy_from_user(&cmds[n_cmds]);
+		if (IS_ERR(idata[n_cmds])) {
+			err = PTR_ERR(idata[n_cmds]);
+			goto cmd_err;
+		}
+	}
+
+	md = mmc_blk_get(bdev->bd_disk);
+	if (!md)
+		goto cmd_err;
+
+	card = md->queue.card;
+	if (IS_ERR(card)) {
+		err = PTR_ERR(card);
+		goto cmd_done;
+	}
+
+	mmc_get_card(card);
+	for (i = 0; i < n_cmds; i++) {
+		err = __mmc_blk_ioctl_cmd(card, md, idata[i]);
+		if (err) {
+			mmc_release_host(card->host);
+			goto cmd_done;
+		}
+	}
+
+	mmc_put_card(card);
+
+	/* copy to user if data and response */
+	for (i = 0; i < n_cmds; i++) {
+		err = mmc_blk_ioctl_copy_to_user(&cmds[i], idata[i]);
+		if (err)
+			break;
+	}
+
+cmd_done:
+	mmc_blk_put(md);
+cmd_err:
+	for (i = 0; i < n_cmds; i++) {
+		kfree(idata[i]->buf);
+		kfree(idata[i]);
+	}
+	kfree(idata);
+	return err;
+}
+
 static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode,
 	unsigned int cmd, unsigned long arg)
 {
-	int ret = -EINVAL;
-	if (cmd == MMC_IOC_CMD)
-		ret = mmc_blk_ioctl_cmd(bdev, (struct mmc_ioc_cmd __user *)arg);
-	return ret;
+	switch (cmd) {
+	case MMC_IOC_CMD:
+		return mmc_blk_ioctl_cmd(bdev,
+				(struct mmc_ioc_cmd __user *)arg);
+	case MMC_IOC_MULTI_CMD:
+		return mmc_blk_ioctl_multi_cmd(bdev,
+				(struct mmc_ioc_multi_cmd __user *)arg);
+	default:
+		return -EINVAL;
+	}
 }
 
 #ifdef CONFIG_COMPAT
diff --git a/include/uapi/linux/mmc/ioctl.h b/include/uapi/linux/mmc/ioctl.h
index 1f5e68923929..6b9a962dbee3 100644
--- a/include/uapi/linux/mmc/ioctl.h
+++ b/include/uapi/linux/mmc/ioctl.h
@@ -45,8 +45,23 @@  struct mmc_ioc_cmd {
 };
 #define mmc_ioc_cmd_set_data(ic, ptr) ic.data_ptr = (__u64)(unsigned long) ptr
 
-#define MMC_IOC_CMD _IOWR(MMC_BLOCK_MAJOR, 0, struct mmc_ioc_cmd)
+/**
+ * struct mmc_ioc_multi_cmd - multi command information
+ * @cmds_ptr: Address of the location where the list of commands resides
+ * @num_of_cmds: number of commands to send
+ */
+struct mmc_ioc_multi_cmd {
+	__u64 cmds_ptr;
+	uint8_t num_of_cmds;
+};
 
+#define MMC_IOC_CMD _IOWR(MMC_BLOCK_MAJOR, 0, struct mmc_ioc_cmd)
+/*
+ * MMC_IOC_MULTI_CMD: Used to send an array of MMC commands described by
+ *	the structure mmc_ioc_multi_cmd. The MMC driver will issue all
+ *	commands in array in sequence to card.
+ */
+#define MMC_IOC_MULTI_CMD _IOWR(MMC_BLOCK_MAJOR, 1, struct mmc_ioc_multi_cmd)
 /*
  * Since this ioctl is only meant to enhance (and not replace) normal access
  * to the mmc bus device, an upper data transfer limit of MMC_IOC_MAX_BYTES