aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ioctl/ioctl-number.txt1
-rw-r--r--drivers/mmc/card/block.c201
-rw-r--r--drivers/mmc/core/sd_ops.c3
-rw-r--r--include/linux/Kbuild1
-rw-r--r--include/linux/mmc/Kbuild1
-rw-r--r--include/linux/mmc/core.h1
-rw-r--r--include/linux/mmc/ioctl.h54
7 files changed, 261 insertions, 1 deletions
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index a0a5d82b6b0..2a34d822e6d 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -304,6 +304,7 @@ Code Seq#(hex) Include File Comments
3040xB0 all RATIO devices in development: 3040xB0 all RATIO devices in development:
305 <mailto:vgo@ratio.de> 305 <mailto:vgo@ratio.de>
3060xB1 00-1F PPPoX <mailto:mostrows@styx.uwaterloo.ca> 3060xB1 00-1F PPPoX <mailto:mostrows@styx.uwaterloo.ca>
3070xB3 00 linux/mmc/ioctl.h
3070xC0 00-0F linux/usb/iowarrior.h 3080xC0 00-0F linux/usb/iowarrior.h
3080xCB 00-1F CBM serial IEC bus in development: 3090xCB 00-1F CBM serial IEC bus in development:
309 <mailto:michael.klein@puffin.lb.shuttle.de> 310 <mailto:michael.klein@puffin.lb.shuttle.de>
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index e7efd6faeaf..407836d5571 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -31,7 +31,11 @@
31#include <linux/mutex.h> 31#include <linux/mutex.h>
32#include <linux/scatterlist.h> 32#include <linux/scatterlist.h>
33#include <linux/string_helpers.h> 33#include <linux/string_helpers.h>
34#include <linux/delay.h>
35#include <linux/capability.h>
36#include <linux/compat.h>
34 37
38#include <linux/mmc/ioctl.h>
35#include <linux/mmc/card.h> 39#include <linux/mmc/card.h>
36#include <linux/mmc/host.h> 40#include <linux/mmc/host.h>
37#include <linux/mmc/mmc.h> 41#include <linux/mmc/mmc.h>
@@ -218,11 +222,208 @@ mmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
218 return 0; 222 return 0;
219} 223}
220 224
225struct mmc_blk_ioc_data {
226 struct mmc_ioc_cmd ic;
227 unsigned char *buf;
228 u64 buf_bytes;
229};
230
231static struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user(
232 struct mmc_ioc_cmd __user *user)
233{
234 struct mmc_blk_ioc_data *idata;
235 int err;
236
237 idata = kzalloc(sizeof(*idata), GFP_KERNEL);
238 if (!idata) {
239 err = -ENOMEM;
240 goto copy_err;
241 }
242
243 if (copy_from_user(&idata->ic, user, sizeof(idata->ic))) {
244 err = -EFAULT;
245 goto copy_err;
246 }
247
248 idata->buf_bytes = (u64) idata->ic.blksz * idata->ic.blocks;
249 if (idata->buf_bytes > MMC_IOC_MAX_BYTES) {
250 err = -EOVERFLOW;
251 goto copy_err;
252 }
253
254 idata->buf = kzalloc(idata->buf_bytes, GFP_KERNEL);
255 if (!idata->buf) {
256 err = -ENOMEM;
257 goto copy_err;
258 }
259
260 if (copy_from_user(idata->buf, (void __user *)(unsigned long)
261 idata->ic.data_ptr, idata->buf_bytes)) {
262 err = -EFAULT;
263 goto copy_err;
264 }
265
266 return idata;
267
268copy_err:
269 kfree(idata->buf);
270 kfree(idata);
271 return ERR_PTR(err);
272
273}
274
275static int mmc_blk_ioctl_cmd(struct block_device *bdev,
276 struct mmc_ioc_cmd __user *ic_ptr)
277{
278 struct mmc_blk_ioc_data *idata;
279 struct mmc_blk_data *md;
280 struct mmc_card *card;
281 struct mmc_command cmd = {0};
282 struct mmc_data data = {0};
283 struct mmc_request mrq = {0};
284 struct scatterlist sg;
285 int err;
286
287 /*
288 * The caller must have CAP_SYS_RAWIO, and must be calling this on the
289 * whole block device, not on a partition. This prevents overspray
290 * between sibling partitions.
291 */
292 if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains))
293 return -EPERM;
294
295 idata = mmc_blk_ioctl_copy_from_user(ic_ptr);
296 if (IS_ERR(idata))
297 return PTR_ERR(idata);
298
299 cmd.opcode = idata->ic.opcode;
300 cmd.arg = idata->ic.arg;
301 cmd.flags = idata->ic.flags;
302
303 data.sg = &sg;
304 data.sg_len = 1;
305 data.blksz = idata->ic.blksz;
306 data.blocks = idata->ic.blocks;
307
308 sg_init_one(data.sg, idata->buf, idata->buf_bytes);
309
310 if (idata->ic.write_flag)
311 data.flags = MMC_DATA_WRITE;
312 else
313 data.flags = MMC_DATA_READ;
314
315 mrq.cmd = &cmd;
316 mrq.data = &data;
317
318 md = mmc_blk_get(bdev->bd_disk);
319 if (!md) {
320 err = -EINVAL;
321 goto cmd_done;
322 }
323
324 card = md->queue.card;
325 if (IS_ERR(card)) {
326 err = PTR_ERR(card);
327 goto cmd_done;
328 }
329
330 mmc_claim_host(card->host);
331
332 if (idata->ic.is_acmd) {
333 err = mmc_app_cmd(card->host, card);
334 if (err)
335 goto cmd_rel_host;
336 }
337
338 /* data.flags must already be set before doing this. */
339 mmc_set_data_timeout(&data, card);
340 /* Allow overriding the timeout_ns for empirical tuning. */
341 if (idata->ic.data_timeout_ns)
342 data.timeout_ns = idata->ic.data_timeout_ns;
343
344 if ((cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
345 /*
346 * Pretend this is a data transfer and rely on the host driver
347 * to compute timeout. When all host drivers support
348 * cmd.cmd_timeout for R1B, this can be changed to:
349 *
350 * mrq.data = NULL;
351 * cmd.cmd_timeout = idata->ic.cmd_timeout_ms;
352 */
353 data.timeout_ns = idata->ic.cmd_timeout_ms * 1000000;
354 }
355
356 mmc_wait_for_req(card->host, &mrq);
357
358 if (cmd.error) {
359 dev_err(mmc_dev(card->host), "%s: cmd error %d\n",
360 __func__, cmd.error);
361 err = cmd.error;
362 goto cmd_rel_host;
363 }
364 if (data.error) {
365 dev_err(mmc_dev(card->host), "%s: data error %d\n",
366 __func__, data.error);
367 err = data.error;
368 goto cmd_rel_host;
369 }
370
371 /*
372 * According to the SD specs, some commands require a delay after
373 * issuing the command.
374 */
375 if (idata->ic.postsleep_min_us)
376 usleep_range(idata->ic.postsleep_min_us, idata->ic.postsleep_max_us);
377
378 if (copy_to_user(&(ic_ptr->response), cmd.resp, sizeof(cmd.resp))) {
379 err = -EFAULT;
380 goto cmd_rel_host;
381 }
382
383 if (!idata->ic.write_flag) {
384 if (copy_to_user((void __user *)(unsigned long) idata->ic.data_ptr,
385 idata->buf, idata->buf_bytes)) {
386 err = -EFAULT;
387 goto cmd_rel_host;
388 }
389 }
390
391cmd_rel_host:
392 mmc_release_host(card->host);
393
394cmd_done:
395 mmc_blk_put(md);
396 kfree(idata->buf);
397 kfree(idata);
398 return err;
399}
400
401static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode,
402 unsigned int cmd, unsigned long arg)
403{
404 int ret = -EINVAL;
405 if (cmd == MMC_IOC_CMD)
406 ret = mmc_blk_ioctl_cmd(bdev, (struct mmc_ioc_cmd __user *)arg);
407 return ret;
408}
409
410#ifdef CONFIG_COMPAT
411static int mmc_blk_compat_ioctl(struct block_device *bdev, fmode_t mode,
412 unsigned int cmd, unsigned long arg)
413{
414 return mmc_blk_ioctl(bdev, mode, cmd, (unsigned long) compat_ptr(arg));
415}
416#endif
417
221static const struct block_device_operations mmc_bdops = { 418static const struct block_device_operations mmc_bdops = {
222 .open = mmc_blk_open, 419 .open = mmc_blk_open,
223 .release = mmc_blk_release, 420 .release = mmc_blk_release,
224 .getgeo = mmc_blk_getgeo, 421 .getgeo = mmc_blk_getgeo,
225 .owner = THIS_MODULE, 422 .owner = THIS_MODULE,
423 .ioctl = mmc_blk_ioctl,
424#ifdef CONFIG_COMPAT
425 .compat_ioctl = mmc_blk_compat_ioctl,
426#endif
226}; 427};
227 428
228struct mmc_blk_request { 429struct mmc_blk_request {
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c
index a206aea5360..021fed15380 100644
--- a/drivers/mmc/core/sd_ops.c
+++ b/drivers/mmc/core/sd_ops.c
@@ -21,7 +21,7 @@
21#include "core.h" 21#include "core.h"
22#include "sd_ops.h" 22#include "sd_ops.h"
23 23
24static int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card) 24int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card)
25{ 25{
26 int err; 26 int err;
27 struct mmc_command cmd = {0}; 27 struct mmc_command cmd = {0};
@@ -49,6 +49,7 @@ static int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card)
49 49
50 return 0; 50 return 0;
51} 51}
52EXPORT_SYMBOL_GPL(mmc_app_cmd);
52 53
53/** 54/**
54 * mmc_wait_for_app_cmd - start an application command and wait for 55 * mmc_wait_for_app_cmd - start an application command and wait for
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 75cf611641e..ed38527599e 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -4,6 +4,7 @@ header-y += caif/
4header-y += dvb/ 4header-y += dvb/
5header-y += hdlc/ 5header-y += hdlc/
6header-y += isdn/ 6header-y += isdn/
7header-y += mmc/
7header-y += nfsd/ 8header-y += nfsd/
8header-y += raid/ 9header-y += raid/
9header-y += spi/ 10header-y += spi/
diff --git a/include/linux/mmc/Kbuild b/include/linux/mmc/Kbuild
new file mode 100644
index 00000000000..1fb26448faa
--- /dev/null
+++ b/include/linux/mmc/Kbuild
@@ -0,0 +1 @@
header-y += ioctl.h
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index f8e4bcbd284..cbe8d55f64c 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -133,6 +133,7 @@ struct mmc_card;
133 133
134extern void mmc_wait_for_req(struct mmc_host *, struct mmc_request *); 134extern void mmc_wait_for_req(struct mmc_host *, struct mmc_request *);
135extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int); 135extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int);
136extern int mmc_app_cmd(struct mmc_host *, struct mmc_card *);
136extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *, 137extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *,
137 struct mmc_command *, int); 138 struct mmc_command *, int);
138extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int); 139extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int);
diff --git a/include/linux/mmc/ioctl.h b/include/linux/mmc/ioctl.h
new file mode 100644
index 00000000000..5baf2983a12
--- /dev/null
+++ b/include/linux/mmc/ioctl.h
@@ -0,0 +1,54 @@
1#ifndef LINUX_MMC_IOCTL_H
2#define LINUX_MMC_IOCTL_H
3struct mmc_ioc_cmd {
4 /* Implies direction of data. true = write, false = read */
5 int write_flag;
6
7 /* Application-specific command. true = precede with CMD55 */
8 int is_acmd;
9
10 __u32 opcode;
11 __u32 arg;
12 __u32 response[4]; /* CMD response */
13 unsigned int flags;
14 unsigned int blksz;
15 unsigned int blocks;
16
17 /*
18 * Sleep at least postsleep_min_us useconds, and at most
19 * postsleep_max_us useconds *after* issuing command. Needed for
20 * some read commands for which cards have no other way of indicating
21 * they're ready for the next command (i.e. there is no equivalent of
22 * a "busy" indicator for read operations).
23 */
24 unsigned int postsleep_min_us;
25 unsigned int postsleep_max_us;
26
27 /*
28 * Override driver-computed timeouts. Note the difference in units!
29 */
30 unsigned int data_timeout_ns;
31 unsigned int cmd_timeout_ms;
32
33 /*
34 * For 64-bit machines, the next member, ``__u64 data_ptr``, wants to
35 * be 8-byte aligned. Make sure this struct is the same size when
36 * built for 32-bit.
37 */
38 __u32 __pad;
39
40 /* DAT buffer */
41 __u64 data_ptr;
42};
43#define mmc_ioc_cmd_set_data(ic, ptr) ic.data_ptr = (__u64)(unsigned long) ptr
44
45#define MMC_IOC_CMD _IOWR(MMC_BLOCK_MAJOR, 0, struct mmc_ioc_cmd)
46
47/*
48 * Since this ioctl is only meant to enhance (and not replace) normal access
49 * to the mmc bus device, an upper data transfer limit of MMC_IOC_MAX_BYTES
50 * is enforced per ioctl call. For larger data transfers, use the normal
51 * block device operations.
52 */
53#define MMC_IOC_MAX_BYTES (512L * 256)
54#endif /* LINUX_MMC_IOCTL_H */