aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/core/core.c41
-rw-r--r--drivers/mmc/core/debugfs.c25
-rw-r--r--include/linux/mmc/host.h5
-rw-r--r--lib/Kconfig.debug11
4 files changed, 82 insertions, 0 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index b27b94078c21..eb3069dfea8e 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -24,6 +24,8 @@
24#include <linux/regulator/consumer.h> 24#include <linux/regulator/consumer.h>
25#include <linux/pm_runtime.h> 25#include <linux/pm_runtime.h>
26#include <linux/suspend.h> 26#include <linux/suspend.h>
27#include <linux/fault-inject.h>
28#include <linux/random.h>
27 29
28#include <linux/mmc/card.h> 30#include <linux/mmc/card.h>
29#include <linux/mmc/host.h> 31#include <linux/mmc/host.h>
@@ -83,6 +85,43 @@ static void mmc_flush_scheduled_work(void)
83 flush_workqueue(workqueue); 85 flush_workqueue(workqueue);
84} 86}
85 87
88#ifdef CONFIG_FAIL_MMC_REQUEST
89
90/*
91 * Internal function. Inject random data errors.
92 * If mmc_data is NULL no errors are injected.
93 */
94static void mmc_should_fail_request(struct mmc_host *host,
95 struct mmc_request *mrq)
96{
97 struct mmc_command *cmd = mrq->cmd;
98 struct mmc_data *data = mrq->data;
99 static const int data_errors[] = {
100 -ETIMEDOUT,
101 -EILSEQ,
102 -EIO,
103 };
104
105 if (!data)
106 return;
107
108 if (cmd->error || data->error ||
109 !should_fail(&host->fail_mmc_request, data->blksz * data->blocks))
110 return;
111
112 data->error = data_errors[random32() % ARRAY_SIZE(data_errors)];
113 data->bytes_xfered = (random32() % (data->bytes_xfered >> 9)) << 9;
114}
115
116#else /* CONFIG_FAIL_MMC_REQUEST */
117
118static inline void mmc_should_fail_request(struct mmc_host *host,
119 struct mmc_request *mrq)
120{
121}
122
123#endif /* CONFIG_FAIL_MMC_REQUEST */
124
86/** 125/**
87 * mmc_request_done - finish processing an MMC request 126 * mmc_request_done - finish processing an MMC request
88 * @host: MMC host which completed request 127 * @host: MMC host which completed request
@@ -109,6 +148,8 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
109 cmd->error = 0; 148 cmd->error = 0;
110 host->ops->request(host, mrq); 149 host->ops->request(host, mrq);
111 } else { 150 } else {
151 mmc_should_fail_request(host, mrq);
152
112 led_trigger_event(host->led, LED_OFF); 153 led_trigger_event(host->led, LED_OFF);
113 154
114 pr_debug("%s: req done (CMD%u): %d: %08x %08x %08x %08x\n", 155 pr_debug("%s: req done (CMD%u): %d: %08x %08x %08x %08x\n",
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index 998797ed67a6..5acd707699c9 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -12,6 +12,7 @@
12#include <linux/seq_file.h> 12#include <linux/seq_file.h>
13#include <linux/slab.h> 13#include <linux/slab.h>
14#include <linux/stat.h> 14#include <linux/stat.h>
15#include <linux/fault-inject.h>
15 16
16#include <linux/mmc/card.h> 17#include <linux/mmc/card.h>
17#include <linux/mmc/host.h> 18#include <linux/mmc/host.h>
@@ -158,6 +159,23 @@ static int mmc_clock_opt_set(void *data, u64 val)
158 return 0; 159 return 0;
159} 160}
160 161
162#ifdef CONFIG_FAIL_MMC_REQUEST
163
164static DECLARE_FAULT_ATTR(fail_mmc_request);
165
166#ifdef KERNEL
167/*
168 * Internal function. Pass the boot param fail_mmc_request to
169 * the setup fault injection attributes routine.
170 */
171static int __init setup_fail_mmc_request(char *str)
172{
173 return setup_fault_attr(&fail_mmc_request, str);
174}
175__setup("fail_mmc_request=", setup_fail_mmc_request);
176#endif /* KERNEL */
177#endif /* CONFIG_FAIL_MMC_REQUEST */
178
161DEFINE_SIMPLE_ATTRIBUTE(mmc_clock_fops, mmc_clock_opt_get, mmc_clock_opt_set, 179DEFINE_SIMPLE_ATTRIBUTE(mmc_clock_fops, mmc_clock_opt_get, mmc_clock_opt_set,
162 "%llu\n"); 180 "%llu\n");
163 181
@@ -188,6 +206,13 @@ void mmc_add_host_debugfs(struct mmc_host *host)
188 root, &host->clk_delay)) 206 root, &host->clk_delay))
189 goto err_node; 207 goto err_node;
190#endif 208#endif
209#ifdef CONFIG_FAIL_MMC_REQUEST
210 host->fail_mmc_request = fail_mmc_request;
211 if (IS_ERR(fault_create_debugfs_attr("fail_mmc_request",
212 root,
213 &host->fail_mmc_request)))
214 goto err_node;
215#endif
191 return; 216 return;
192 217
193err_node: 218err_node:
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 1d09562ccf73..4c4bddf5ef61 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -12,6 +12,7 @@
12 12
13#include <linux/leds.h> 13#include <linux/leds.h>
14#include <linux/sched.h> 14#include <linux/sched.h>
15#include <linux/fault-inject.h>
15 16
16#include <linux/mmc/core.h> 17#include <linux/mmc/core.h>
17#include <linux/mmc/pm.h> 18#include <linux/mmc/pm.h>
@@ -302,6 +303,10 @@ struct mmc_host {
302 303
303 struct mmc_async_req *areq; /* active async req */ 304 struct mmc_async_req *areq; /* active async req */
304 305
306#ifdef CONFIG_FAIL_MMC_REQUEST
307 struct fault_attr fail_mmc_request;
308#endif
309
305 unsigned long private[0] ____cacheline_aligned; 310 unsigned long private[0] ____cacheline_aligned;
306}; 311};
307 312
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index c0cb9c4bc46d..1c7dbbf9e449 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1070,6 +1070,17 @@ config FAIL_IO_TIMEOUT
1070 Only works with drivers that use the generic timeout handling, 1070 Only works with drivers that use the generic timeout handling,
1071 for others it wont do anything. 1071 for others it wont do anything.
1072 1072
1073config FAIL_MMC_REQUEST
1074 bool "Fault-injection capability for MMC IO"
1075 select DEBUG_FS
1076 depends on FAULT_INJECTION && MMC
1077 help
1078 Provide fault-injection capability for MMC IO.
1079 This will make the mmc core return data errors. This is
1080 useful to test the error handling in the mmc block device
1081 and to test how the mmc host driver handles retries from
1082 the block device.
1083
1073config FAULT_INJECTION_DEBUG_FS 1084config FAULT_INJECTION_DEBUG_FS
1074 bool "Debugfs entries for fault-injection capabilities" 1085 bool "Debugfs entries for fault-injection capabilities"
1075 depends on FAULT_INJECTION && SYSFS && DEBUG_FS 1086 depends on FAULT_INJECTION && SYSFS && DEBUG_FS