aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-05-19 19:40:30 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-05-19 19:40:30 -0400
commit8033c6e9736c29cce5f0d0abbca9a44dffb20c39 (patch)
tree7691061eecc2884c617f56ab69af1e0592268d61
parent2d3cf588e9bf6df0a22581baece7edeacfbbc9f5 (diff)
parente5c0ef90e6cfd40c819bd70748d675067ff862e7 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc: at91_mci: minor cleanup mmc: mmc host test driver mmc: Fix omap compile by replacing dev_name with dma_dev_name
-rw-r--r--drivers/mmc/card/Kconfig12
-rw-r--r--drivers/mmc/card/Makefile1
-rw-r--r--drivers/mmc/card/mmc_test.c892
-rw-r--r--drivers/mmc/host/at91_mci.c5
-rw-r--r--drivers/mmc/host/omap.c12
5 files changed, 915 insertions, 7 deletions
diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig
index aa8a4e461942..dd0f398ee2f5 100644
--- a/drivers/mmc/card/Kconfig
+++ b/drivers/mmc/card/Kconfig
@@ -39,3 +39,15 @@ config SDIO_UART
39 SDIO function driver for SDIO cards that implements the UART 39 SDIO function driver for SDIO cards that implements the UART
40 class, as well as the GPS class which appears like a UART. 40 class, as well as the GPS class which appears like a UART.
41 41
42config MMC_TEST
43 tristate "MMC host test driver"
44 default n
45 help
46 Development driver that performs a series of reads and writes
47 to a memory card in order to expose certain well known bugs
48 in host controllers. The tests are executed by writing to the
49 "test" file in sysfs under each card. Note that whatever is
50 on your card will be overwritten by these tests.
51
52 This driver is only of interest to those developing or
53 testing a host driver. Most people should say N here.
diff --git a/drivers/mmc/card/Makefile b/drivers/mmc/card/Makefile
index fc5a784cfa1a..0d407514f67d 100644
--- a/drivers/mmc/card/Makefile
+++ b/drivers/mmc/card/Makefile
@@ -8,6 +8,7 @@ endif
8 8
9obj-$(CONFIG_MMC_BLOCK) += mmc_block.o 9obj-$(CONFIG_MMC_BLOCK) += mmc_block.o
10mmc_block-objs := block.o queue.o 10mmc_block-objs := block.o queue.o
11obj-$(CONFIG_MMC_TEST) += mmc_test.o
11 12
12obj-$(CONFIG_SDIO_UART) += sdio_uart.o 13obj-$(CONFIG_SDIO_UART) += sdio_uart.o
13 14
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
new file mode 100644
index 000000000000..ffadee549a41
--- /dev/null
+++ b/drivers/mmc/card/mmc_test.c
@@ -0,0 +1,892 @@
1/*
2 * linux/drivers/mmc/card/mmc_test.c
3 *
4 * Copyright 2007 Pierre Ossman
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or (at
9 * your option) any later version.
10 */
11
12#include <linux/mmc/core.h>
13#include <linux/mmc/card.h>
14#include <linux/mmc/host.h>
15#include <linux/mmc/mmc.h>
16
17#include <linux/scatterlist.h>
18
19#define RESULT_OK 0
20#define RESULT_FAIL 1
21#define RESULT_UNSUP_HOST 2
22#define RESULT_UNSUP_CARD 3
23
24#define BUFFER_SIZE (PAGE_SIZE * 4)
25
26struct mmc_test_card {
27 struct mmc_card *card;
28
29 u8 *buffer;
30};
31
32/*******************************************************************/
33/* Helper functions */
34/*******************************************************************/
35
36static int mmc_test_set_blksize(struct mmc_test_card *test, unsigned size)
37{
38 struct mmc_command cmd;
39 int ret;
40
41 cmd.opcode = MMC_SET_BLOCKLEN;
42 cmd.arg = size;
43 cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
44 ret = mmc_wait_for_cmd(test->card->host, &cmd, 0);
45 if (ret)
46 return ret;
47
48 return 0;
49}
50
51static int __mmc_test_transfer(struct mmc_test_card *test, int write,
52 unsigned broken_xfer, u8 *buffer, unsigned addr,
53 unsigned blocks, unsigned blksz)
54{
55 int ret, busy;
56
57 struct mmc_request mrq;
58 struct mmc_command cmd;
59 struct mmc_command stop;
60 struct mmc_data data;
61
62 struct scatterlist sg;
63
64 memset(&mrq, 0, sizeof(struct mmc_request));
65
66 mrq.cmd = &cmd;
67 mrq.data = &data;
68
69 memset(&cmd, 0, sizeof(struct mmc_command));
70
71 if (broken_xfer) {
72 if (blocks > 1) {
73 cmd.opcode = write ?
74 MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK;
75 } else {
76 cmd.opcode = MMC_SEND_STATUS;
77 }
78 } else {
79 if (blocks > 1) {
80 cmd.opcode = write ?
81 MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK;
82 } else {
83 cmd.opcode = write ?
84 MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK;
85 }
86 }
87
88 if (broken_xfer && blocks == 1)
89 cmd.arg = test->card->rca << 16;
90 else
91 cmd.arg = addr;
92 cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
93
94 memset(&stop, 0, sizeof(struct mmc_command));
95
96 if (!broken_xfer && (blocks > 1)) {
97 stop.opcode = MMC_STOP_TRANSMISSION;
98 stop.arg = 0;
99 stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
100
101 mrq.stop = &stop;
102 }
103
104 memset(&data, 0, sizeof(struct mmc_data));
105
106 data.blksz = blksz;
107 data.blocks = blocks;
108 data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
109 data.sg = &sg;
110 data.sg_len = 1;
111
112 sg_init_one(&sg, buffer, blocks * blksz);
113
114 mmc_set_data_timeout(&data, test->card);
115
116 mmc_wait_for_req(test->card->host, &mrq);
117
118 ret = 0;
119
120 if (broken_xfer) {
121 if (!ret && cmd.error)
122 ret = cmd.error;
123 if (!ret && data.error == 0)
124 ret = RESULT_FAIL;
125 if (!ret && data.error != -ETIMEDOUT)
126 ret = data.error;
127 if (!ret && stop.error)
128 ret = stop.error;
129 if (blocks > 1) {
130 if (!ret && data.bytes_xfered > blksz)
131 ret = RESULT_FAIL;
132 } else {
133 if (!ret && data.bytes_xfered > 0)
134 ret = RESULT_FAIL;
135 }
136 } else {
137 if (!ret && cmd.error)
138 ret = cmd.error;
139 if (!ret && data.error)
140 ret = data.error;
141 if (!ret && stop.error)
142 ret = stop.error;
143 if (!ret && data.bytes_xfered != blocks * blksz)
144 ret = RESULT_FAIL;
145 }
146
147 if (ret == -EINVAL)
148 ret = RESULT_UNSUP_HOST;
149
150 busy = 0;
151 do {
152 int ret2;
153
154 memset(&cmd, 0, sizeof(struct mmc_command));
155
156 cmd.opcode = MMC_SEND_STATUS;
157 cmd.ar