summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorShridhar Rasal <srasal@nvidia.com>2012-02-03 19:44:00 +0530
committerSimone Willett <swillett@nvidia.com>2012-03-06 17:39:31 -0800
commited2b019ac7479518c5569102585a6ffe1ea9e36a (patch)
tree8117a1bfad3cb5f2557c638f58e434eda7d80eab /drivers/mmc
parent4ceba6488d041960f4d619e526c226a3e7a1cdc5 (diff)
mmc: mmc_test support to set ios parameters
support to change *ios* parameteres bug 930113 Change-Id: I469db49ec9e4ca533ba3be654455ae6b4b052d1c Signed-off-by: Shridhar Rasal <srasal@nvidia.com> Reviewed-on: http://git-master/r/79238 Reviewed-by: Sachin Nikam <snikam@nvidia.com>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/card/mmc_test.c191
1 files changed, 184 insertions, 7 deletions
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index 2bf229acd3b8..440b97d9e44b 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -169,6 +169,96 @@ struct mmc_test_async_req {
struct mmc_test_card *test;
};
+struct mmc_test_parameter {
+ const char *name;
+ long value;
+ long (*exec)(struct mmc_test_card *);
+ const char *input;
+};
+
+static long mmc_test_set_testcase(struct mmc_test_card *test);
+static long mmc_test_set_clock(struct mmc_test_card *test);
+static long mmc_test_set_bus_width(struct mmc_test_card *test);
+static long mmc_test_set_timing(struct mmc_test_card *test);
+
+
+static struct mmc_test_parameter mmc_test_parameter[] = {
+ {
+ .name = "Testcase Number",
+ .value = 1,
+ .exec = mmc_test_set_testcase,
+ .input = "-n",
+ },
+ {
+ .name = "Clock Rate",
+ .value = -1,
+ .exec = mmc_test_set_clock,
+ .input = "-c",
+ },
+ {
+ .name = "Bus Width",
+ .value = -1,
+ .exec = mmc_test_set_bus_width,
+ .input = "-b",
+ },
+ {
+ .name = "Timing",
+ .value = -1,
+ .exec = mmc_test_set_timing,
+ .input = "-t",
+ },
+};
+
+static long mmc_test_set_testcase(struct mmc_test_card *test)
+{
+ return 0;
+}
+
+static long mmc_test_set_clock(struct mmc_test_card *test)
+{
+ long clock = mmc_test_parameter[1].value;
+ if (-1 == clock)
+ return test->card->host->ios.clock;
+ WARN_ON(clock < test->card->host->f_min);
+ if (clock > test->card->host->f_max)
+ clock = test->card->host->f_max;
+
+ test->card->host->ios.clock = clock;
+
+ return test->card->host->ios.clock;
+}
+
+static long mmc_test_set_bus_width(struct mmc_test_card *test)
+{
+ long bus_width = mmc_test_parameter[2].value;
+ if (-1 == bus_width)
+ return test->card->host->ios.bus_width;
+
+ test->card->host->ios.bus_width = bus_width;
+
+ return test->card->host->ios.bus_width = bus_width;
+}
+
+static long mmc_test_set_timing(struct mmc_test_card *test)
+{
+ long timing = mmc_test_parameter[3].value;
+ if (-1 == timing)
+ return test->card->host->ios.timing;
+ test->card->host->ios.timing = timing;
+
+ return test->card->host->ios.timing;
+}
+
+static void mmc_test_set_parameters(struct mmc_test_card *test)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(mmc_test_parameter); i++) {
+ printk(KERN_INFO "Parameter[%s] set to [%ld]\n",
+ mmc_test_parameter[i].name,
+ mmc_test_parameter[i].exec(test));
+ }
+}
+
/*******************************************************************/
/* General helper functions */
/*******************************************************************/
@@ -2665,6 +2755,8 @@ static void mmc_test_run(struct mmc_test_card *test, int testcase)
mmc_claim_host(test->card->host);
+ mmc_test_set_parameters(test);
+
for (i = 0;i < ARRAY_SIZE(mmc_test_cases);i++) {
struct mmc_test_general_result *gr;
@@ -2777,6 +2869,23 @@ static void mmc_test_free_result(struct mmc_card *card)
static LIST_HEAD(mmc_test_file_test);
+static void mmc_test_usage(struct seq_file *sf)
+{
+ int i = 0;
+
+ seq_printf(sf, "\nHow to run test:"
+ "\necho <testcase> [[param1 value1].... ] > test"
+ "\nExample:: echo 1 -b 4 -c 2500000 -t 2"
+ "\n\nSupported parameters in sequence\n");
+
+ for (i = 0; i < ARRAY_SIZE(mmc_test_parameter); i++) {
+ seq_printf(sf, "Parameter%d Name:[%s] option:[%s]\n",
+ i + 1, mmc_test_parameter[i].name,
+ mmc_test_parameter[i].input);
+ }
+ seq_printf(sf, "\'-1\' passed to take default value\n\n\n");
+}
+
static int mtf_test_show(struct seq_file *sf, void *data)
{
struct mmc_card *card = (struct mmc_card *)sf->private;
@@ -2811,24 +2920,92 @@ static int mtf_test_open(struct inode *inode, struct file *file)
return single_open(file, mtf_test_show, inode->i_private);
}
+static int mmc_test_extract_parameters(char *data_buf)
+{
+ char *running = NULL;
+ char *token = NULL;
+ const char delimiters[] = " ";
+ long value;
+ int i;
+ int set = 0;
+
+ running = data_buf;
+
+ /*Example:
+ * echo <testcasenumber> [[param1 value1] [param1 value1]] > test
+ * $] echo 1 > test | Execute testcase 1
+ * $] echo 1 -c 2500000 | execute tesecase 1 and set clock to 2500000
+ * $] echo 1 -b 4 -c 2500000 -t 2 |
+ * execute tesecase 1, set clock to 2500000, set bus_width 4,
+ * and set timing to 2
+ */
+
+ while ((token = strsep(&running, delimiters))) {
+ if (strict_strtol(token, 10, &value)) {
+ /* [Param1 value1] combination
+ * Compare with available param list
+ */
+ for (i = 0; i < ARRAY_SIZE(mmc_test_parameter); i++) {
+ if (!strcmp(mmc_test_parameter[i].input,
+ token)) {
+ /* Valid Option, extract following
+ * value and save it
+ */
+ token = strsep(&running, delimiters);
+ if (strict_strtol(token, 10,
+ &(mmc_test_parameter[i].value))) {
+
+ printk(KERN_ERR "wrong parameter value\n");
+ return -EINVAL;
+ } else {
+ break;
+ }
+ }
+ }
+ if (i == ARRAY_SIZE(mmc_test_parameter)) {
+ printk(KERN_ERR "uknown mmc_test option\n");
+ return -EINVAL;
+ }
+ } else {
+ /* Testcase number */
+ if (!set) {
+ mmc_test_parameter[0].value = value;
+ set = 1;
+ } else {
+ printk(KERN_ERR "invalid options");
+ return -EINVAL;
+ }
+ }
+ }
+ return 0;
+}
+
static ssize_t mtf_test_write(struct file *file, const char __user *buf,
size_t count, loff_t *pos)
{
struct seq_file *sf = (struct seq_file *)file->private_data;
struct mmc_card *card = (struct mmc_card *)sf->private;
struct mmc_test_card *test;
- char lbuf[12];
+ char *data_buf = NULL;
long testcase;
- if (count >= sizeof(lbuf))
- return -EINVAL;
+ data_buf = kzalloc(count, GFP_KERNEL);
+ if (data_buf == NULL)
+ return -ENOMEM;
- if (copy_from_user(lbuf, buf, count))
+ if (copy_from_user(data_buf, buf, count)) {
+ kfree(data_buf);
+ return -EFAULT;
+ }
+ data_buf[strlen(data_buf) - 1] = '\0';
+ if (mmc_test_extract_parameters(data_buf)) {
+ mmc_test_usage(sf);
return -EFAULT;
- lbuf[count] = '\0';
+ }
- if (strict_strtol(lbuf, 10, &testcase))
- return -EINVAL;
+ kfree(data_buf);
+
+ testcase = mmc_test_parameter[0].value;
test = kzalloc(sizeof(struct mmc_test_card), GFP_KERNEL);
if (!test)