aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorAndy Shevchenko <andy.shevchenko@gmail.com>2010-09-10 03:10:50 -0400
committerChris Ball <cjb@laptop.org>2010-10-23 09:11:13 -0400
commit130067ed15f6e8a1209898646878f5bc0a17d3dd (patch)
tree80108295840277210d1bdb8199d4ed60bd6b170e /drivers/mmc
parent3183aa1534de4e98ffb0527d4f2be7ac9f019a4e (diff)
mmc_test: move files from sysfs to debugfs
As proposed by Greg K-H it is more logical to keep files for the mmc_test driver under debugfs. Additionally this patch brings seq_file API for show() method. It allows to write unlimited data to the file. Example of usage: # mount -t debugfs none /sys/kernel/debug # modprobe mmc_test [ 581.395843] mmc_test mmc0:0001: Card claimed for testing. # echo 25 > /sys/kernel/debug/mmc0/mmc0\:0001/test [ 604.568542] mmc0: Starting tests of card mmc0:0001... [ 604.582733] mmc0: Test case 25. Best-case read performance into scattered pages... [ 604.923553] mmc0: Transfer of 8192 sectors (4096 KiB) took 0.124664314 seconds (33644 kB/s, 32856 KiB/s) [ 604.933227] mmc0: Result: OK [ 604.936248] mmc0: Tests completed. # cat /sys/kernel/debug/mmc0/mmc0\:0001/test Test 25: 0 1 8192 0.124664314 33644784 Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko@nokia.com> Cc: Greg KH <greg@kroah.com> Cc: Adrian Hunter <adrian.hunter@nokia.com> Cc: Chris Ball <cjb@laptop.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/card/mmc_test.c142
1 files changed, 107 insertions, 35 deletions
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index 0c8b5685d4b7..6580af7b7cb8 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -19,6 +19,10 @@
19#include <linux/swap.h> /* For nr_free_buffer_pages() */ 19#include <linux/swap.h> /* For nr_free_buffer_pages() */
20#include <linux/list.h> 20#include <linux/list.h>
21 21
22#include <linux/debugfs.h>
23#include <linux/uaccess.h>
24#include <linux/seq_file.h>
25
22#define RESULT_OK 0 26#define RESULT_OK 0
23#define RESULT_FAIL 1 27#define RESULT_FAIL 1
24#define RESULT_UNSUP_HOST 2 28#define RESULT_UNSUP_HOST 2
@@ -110,6 +114,18 @@ struct mmc_test_general_result {
110}; 114};
111 115
112/** 116/**
117 * struct mmc_test_dbgfs_file - debugfs related file.
118 * @link: double-linked list
119 * @card: card under test
120 * @file: file created under debugfs
121 */
122struct mmc_test_dbgfs_file {
123 struct list_head link;
124 struct mmc_card *card;
125 struct dentry *file;
126};
127
128/**
113 * struct mmc_test_card - test information. 129 * struct mmc_test_card - test information.
114 * @card: card under test 130 * @card: card under test
115 * @scratch: transfer buffer 131 * @scratch: transfer buffer
@@ -2124,14 +2140,12 @@ static void mmc_test_free_result(struct mmc_card *card)
2124 mutex_unlock(&mmc_test_lock); 2140 mutex_unlock(&mmc_test_lock);
2125} 2141}
2126 2142
2127static ssize_t mmc_test_show(struct device *dev, 2143static LIST_HEAD(mmc_test_file_test);
2128 struct device_attribute *attr, char *buf) 2144
2145static int mtf_test_show(struct seq_file *sf, void *data)
2129{ 2146{
2130 struct mmc_card *card = mmc_dev_to_card(dev); 2147 struct mmc_card *card = (struct mmc_card *)sf->private;
2131 struct mmc_test_general_result *gr; 2148 struct mmc_test_general_result *gr;
2132 char *p = buf;
2133 size_t len = PAGE_SIZE;
2134 int ret;
2135 2149
2136 mutex_lock(&mmc_test_lock); 2150 mutex_lock(&mmc_test_lock);
2137 2151
@@ -2141,49 +2155,44 @@ static ssize_t mmc_test_show(struct device *dev,
2141 if (gr->card != card) 2155 if (gr->card != card)
2142 continue; 2156 continue;
2143 2157
2144 ret = snprintf(p, len, "Test %d: %d\n", gr->testcase + 1, 2158 seq_printf(sf, "Test %d: %d\n", gr->testcase + 1, gr->result);
2145 gr->result);
2146 if (ret < 0)
2147 goto err;
2148 if (ret >= len) {
2149 ret = -ENOBUFS;
2150 goto err;
2151 }
2152 p += ret;
2153 len -= ret;
2154 2159
2155 list_for_each_entry(tr, &gr->tr_lst, link) { 2160 list_for_each_entry(tr, &gr->tr_lst, link) {
2156 ret = snprintf(p, len, "%u %d %lu.%09lu %u\n", 2161 seq_printf(sf, "%u %d %lu.%09lu %u\n",
2157 tr->count, tr->sectors, 2162 tr->count, tr->sectors,
2158 (unsigned long)tr->ts.tv_sec, 2163 (unsigned long)tr->ts.tv_sec,
2159 (unsigned long)tr->ts.tv_nsec, 2164 (unsigned long)tr->ts.tv_nsec,
2160 tr->rate); 2165 tr->rate);
2161 if (ret < 0)
2162 goto err;
2163 if (ret >= len) {
2164 ret = -ENOBUFS;
2165 goto err;
2166 }
2167 p += ret;
2168 len -= ret;
2169 } 2166 }
2170 } 2167 }
2171 2168
2172 ret = PAGE_SIZE - len;
2173err:
2174 mutex_unlock(&mmc_test_lock); 2169 mutex_unlock(&mmc_test_lock);
2175 2170
2176 return ret; 2171 return 0;
2177} 2172}
2178 2173
2179static ssize_t mmc_test_store(struct device *dev, 2174static int mtf_test_open(struct inode *inode, struct file *file)
2180 struct device_attribute *attr, const char *buf, size_t count)
2181{ 2175{
2182 struct mmc_card *card = mmc_dev_to_card(dev); 2176 return single_open(file, mtf_test_show, inode->i_private);
2177}
2178
2179static ssize_t mtf_test_write(struct file *file, const char __user *buf,
2180 size_t count, loff_t *pos)
2181{
2182 struct seq_file *sf = (struct seq_file *)file->private_data;
2183 struct mmc_card *card = (struct mmc_card *)sf->private;
2183 struct mmc_test_card *test; 2184 struct mmc_test_card *test;
2185 char lbuf[12];
2184 long testcase; 2186 long testcase;
2185 2187
2186 if (strict_strtol(buf, 10, &testcase)) 2188 if (count >= sizeof(lbuf))
2189 return -EINVAL;
2190
2191 if (copy_from_user(lbuf, buf, count))
2192 return -EFAULT;
2193 lbuf[count] = '\0';
2194
2195 if (strict_strtol(lbuf, 10, &testcase))
2187 return -EINVAL; 2196 return -EINVAL;
2188 2197
2189 test = kzalloc(sizeof(struct mmc_test_card), GFP_KERNEL); 2198 test = kzalloc(sizeof(struct mmc_test_card), GFP_KERNEL);
@@ -2222,7 +2231,69 @@ static ssize_t mmc_test_store(struct device *dev,
2222 return count; 2231 return count;
2223} 2232}
2224 2233
2225static DEVICE_ATTR(test, S_IWUSR | S_IRUGO, mmc_test_show, mmc_test_store); 2234static const struct file_operations mmc_test_fops_test = {
2235 .open = mtf_test_open,
2236 .read = seq_read,
2237 .write = mtf_test_write,
2238 .llseek = seq_lseek,
2239 .release = single_release,
2240};
2241
2242static void mmc_test_free_file_test(struct mmc_card *card)
2243{
2244 struct mmc_test_dbgfs_file *df, *dfs;
2245
2246 mutex_lock(&mmc_test_lock);
2247
2248 list_for_each_entry_safe(df, dfs, &mmc_test_file_test, link) {
2249 if (card && df->card != card)
2250 continue;
2251 debugfs_remove(df->file);
2252 list_del(&df->link);
2253 kfree(df);
2254 }
2255
2256 mutex_unlock(&mmc_test_lock);
2257}
2258
2259static int mmc_test_register_file_test(struct mmc_card *card)
2260{
2261 struct dentry *file = NULL;
2262 struct mmc_test_dbgfs_file *df;
2263 int ret = 0;
2264
2265 mutex_lock(&mmc_test_lock);
2266
2267 if (card->debugfs_root)
2268 file = debugfs_create_file("test", S_IWUSR | S_IRUGO,
2269 card->debugfs_root, card, &mmc_test_fops_test);
2270
2271 if (IS_ERR_OR_NULL(file)) {
2272 dev_err(&card->dev,
2273 "Can't create file. Perhaps debugfs is disabled.\n");
2274 ret = -ENODEV;
2275 goto err;
2276 }
2277
2278 df = kmalloc(sizeof(struct mmc_test_dbgfs_file), GFP_KERNEL);
2279 if (!df) {
2280 debugfs_remove(file);
2281 dev_err(&card->dev,
2282 "Can't allocate memory for internal usage.\n");
2283 ret = -ENOMEM;
2284 goto err;
2285 }
2286
2287 df->card = card;
2288 df->file = file;
2289
2290 list_add(&df->link, &mmc_test_file_test);
2291
2292err:
2293 mutex_unlock(&mmc_test_lock);
2294
2295 return ret;
2296}
2226 2297
2227static int mmc_test_probe(struct mmc_card *card) 2298static int mmc_test_probe(struct mmc_card *card)
2228{ 2299{
@@ -2231,7 +2302,7 @@ static int mmc_test_probe(struct mmc_card *card)
2231 if (!mmc_card_mmc(card) && !mmc_card_sd(card)) 2302 if (!mmc_card_mmc(card) && !mmc_card_sd(card))
2232 return -ENODEV; 2303 return -ENODEV;
2233 2304
2234 ret = device_create_file(&card->dev, &dev_attr_test); 2305 ret = mmc_test_register_file_test(card);
2235 if (ret) 2306 if (ret)
2236 return ret; 2307 return ret;
2237 2308
@@ -2243,7 +2314,7 @@ static int mmc_test_probe(struct mmc_card *card)
2243static void mmc_test_remove(struct mmc_card *card) 2314static void mmc_test_remove(struct mmc_card *card)
2244{ 2315{
2245 mmc_test_free_result(card); 2316 mmc_test_free_result(card);
2246 device_remove_file(&card->dev, &dev_attr_test); 2317 mmc_test_free_file_test(card);
2247} 2318}
2248 2319
2249static struct mmc_driver mmc_driver = { 2320static struct mmc_driver mmc_driver = {
@@ -2263,6 +2334,7 @@ static void __exit mmc_test_exit(void)
2263{ 2334{
2264 /* Clear stalled data if card is still plugged */ 2335 /* Clear stalled data if card is still plugged */
2265 mmc_test_free_result(NULL); 2336 mmc_test_free_result(NULL);
2337 mmc_test_free_file_test(NULL);
2266 2338
2267 mmc_unregister_driver(&mmc_driver); 2339 mmc_unregister_driver(&mmc_driver);
2268} 2340}