Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 270238
b: refs/heads/master
c: 1b676f7
h: refs/heads/master
v: v3
  • Loading branch information
Per Forlin authored and Chris Ball committed Oct 26, 2011
1 parent 103a865 commit 5daaba8
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: df87ecbf19109bab04a92df047a9949838206abc
refs/heads/master: 1b676f70c108cda90cf9d114d16c677584400efc
41 changes: 41 additions & 0 deletions trunk/drivers/mmc/core/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/suspend.h>
#include <linux/fault-inject.h>
#include <linux/random.h>

#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
Expand Down Expand Up @@ -83,6 +85,43 @@ static void mmc_flush_scheduled_work(void)
flush_workqueue(workqueue);
}

#ifdef CONFIG_FAIL_MMC_REQUEST

/*
* Internal function. Inject random data errors.
* If mmc_data is NULL no errors are injected.
*/
static void mmc_should_fail_request(struct mmc_host *host,
struct mmc_request *mrq)
{
struct mmc_command *cmd = mrq->cmd;
struct mmc_data *data = mrq->data;
static const int data_errors[] = {
-ETIMEDOUT,
-EILSEQ,
-EIO,
};

if (!data)
return;

if (cmd->error || data->error ||
!should_fail(&host->fail_mmc_request, data->blksz * data->blocks))
return;

data->error = data_errors[random32() % ARRAY_SIZE(data_errors)];
data->bytes_xfered = (random32() % (data->bytes_xfered >> 9)) << 9;
}

#else /* CONFIG_FAIL_MMC_REQUEST */

static inline void mmc_should_fail_request(struct mmc_host *host,
struct mmc_request *mrq)
{
}

#endif /* CONFIG_FAIL_MMC_REQUEST */

/**
* mmc_request_done - finish processing an MMC request
* @host: MMC host which completed request
Expand All @@ -109,6 +148,8 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
cmd->error = 0;
host->ops->request(host, mrq);
} else {
mmc_should_fail_request(host, mrq);

led_trigger_event(host->led, LED_OFF);

pr_debug("%s: req done (CMD%u): %d: %08x %08x %08x %08x\n",
Expand Down
25 changes: 25 additions & 0 deletions trunk/drivers/mmc/core/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/fault-inject.h>

#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
Expand Down Expand Up @@ -158,6 +159,23 @@ static int mmc_clock_opt_set(void *data, u64 val)
return 0;
}

#ifdef CONFIG_FAIL_MMC_REQUEST

static DECLARE_FAULT_ATTR(fail_mmc_request);

#ifdef KERNEL
/*
* Internal function. Pass the boot param fail_mmc_request to
* the setup fault injection attributes routine.
*/
static int __init setup_fail_mmc_request(char *str)
{
return setup_fault_attr(&fail_mmc_request, str);
}
__setup("fail_mmc_request=", setup_fail_mmc_request);
#endif /* KERNEL */
#endif /* CONFIG_FAIL_MMC_REQUEST */

DEFINE_SIMPLE_ATTRIBUTE(mmc_clock_fops, mmc_clock_opt_get, mmc_clock_opt_set,
"%llu\n");

Expand Down Expand Up @@ -187,6 +205,13 @@ void mmc_add_host_debugfs(struct mmc_host *host)
if (!debugfs_create_u32("clk_delay", (S_IRUSR | S_IWUSR),
root, &host->clk_delay))
goto err_node;
#endif
#ifdef CONFIG_FAIL_MMC_REQUEST
host->fail_mmc_request = fail_mmc_request;
if (IS_ERR(fault_create_debugfs_attr("fail_mmc_request",
root,
&host->fail_mmc_request)))
goto err_node;
#endif
return;

Expand Down
5 changes: 5 additions & 0 deletions trunk/include/linux/mmc/host.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include <linux/leds.h>
#include <linux/sched.h>
#include <linux/fault-inject.h>

#include <linux/mmc/core.h>
#include <linux/mmc/pm.h>
Expand Down Expand Up @@ -302,6 +303,10 @@ struct mmc_host {

struct mmc_async_req *areq; /* active async req */

#ifdef CONFIG_FAIL_MMC_REQUEST
struct fault_attr fail_mmc_request;
#endif

unsigned long private[0] ____cacheline_aligned;
};

Expand Down
11 changes: 11 additions & 0 deletions trunk/lib/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -1070,6 +1070,17 @@ config FAIL_IO_TIMEOUT
Only works with drivers that use the generic timeout handling,
for others it wont do anything.

config FAIL_MMC_REQUEST
bool "Fault-injection capability for MMC IO"
select DEBUG_FS
depends on FAULT_INJECTION && MMC
help
Provide fault-injection capability for MMC IO.
This will make the mmc core return data errors. This is
useful to test the error handling in the mmc block device
and to test how the mmc host driver handles retries from
the block device.

config FAULT_INJECTION_DEBUG_FS
bool "Debugfs entries for fault-injection capabilities"
depends on FAULT_INJECTION && SYSFS && DEBUG_FS
Expand Down

0 comments on commit 5daaba8

Please sign in to comment.