aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/debug.c
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2011-05-18 07:53:05 -0400
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2011-06-01 04:21:47 -0400
commit2a734bb8d502b645c061fa329e87c5d651498e68 (patch)
treed87ee3ddd7c5ccee224044e2178aaf131407b91a /drivers/mtd/ubi/debug.c
parentd99383b00eba9c6ac3dea462d718b2849012ee03 (diff)
UBI: use debugfs for the extra checks knobs
This patch introduces debugfs support to UBI. All the UBI stuff is kept in the "ubi" debugfs directory, which contains per-UBI device "ubi/ubiX" sub-directories, containing debugging files. This file also creates "ubi/ubiX/chk_gen" and "ubi/ubiX/chk_io" knobs for switching general and I/O extra checks on and off. And it removes the 'debug_chks' UBI module parameters. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'drivers/mtd/ubi/debug.c')
-rw-r--r--drivers/mtd/ubi/debug.c231
1 files changed, 227 insertions, 4 deletions
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index 2224cbe41ddf..dce1227929f1 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -27,16 +27,15 @@
27#ifdef CONFIG_MTD_UBI_DEBUG 27#ifdef CONFIG_MTD_UBI_DEBUG
28 28
29#include "ubi.h" 29#include "ubi.h"
30#include <linux/debugfs.h>
31#include <linux/uaccess.h>
30#include <linux/module.h> 32#include <linux/module.h>
31#include <linux/moduleparam.h> 33#include <linux/moduleparam.h>
32 34
33unsigned int ubi_chk_flags;
34unsigned int ubi_tst_flags; 35unsigned int ubi_tst_flags;
35 36
36module_param_named(debug_chks, ubi_chk_flags, uint, S_IRUGO | S_IWUSR); 37module_param_named(debug_tsts, ubi_tst_flags, uint, S_IRUGO | S_IWUSR);
37module_param_named(debug_tsts, ubi_chk_flags, uint, S_IRUGO | S_IWUSR);
38 38
39MODULE_PARM_DESC(debug_chks, "Debug check flags");
40MODULE_PARM_DESC(debug_tsts, "Debug special test flags"); 39MODULE_PARM_DESC(debug_tsts, "Debug special test flags");
41 40
42/** 41/**
@@ -239,4 +238,228 @@ out:
239 return; 238 return;
240} 239}
241 240
241/**
242 * ubi_debugging_init_dev - initialize debugging for an UBI device.
243 * @ubi: UBI device description object
244 *
245 * This function initializes debugging-related data for UBI device @ubi.
246 * Returns zero in case of success and a negative error code in case of
247 * failure.
248 */
249int ubi_debugging_init_dev(struct ubi_device *ubi)
250{
251 ubi->dbg = kzalloc(sizeof(struct ubi_debug_info), GFP_KERNEL);
252 if (!ubi->dbg)
253 return -ENOMEM;
254
255 return 0;
256}
257
258/**
259 * ubi_debugging_exit_dev - free debugging data for an UBI device.
260 * @ubi: UBI device description object
261 */
262void ubi_debugging_exit_dev(struct ubi_device *ubi)
263{
264 kfree(ubi->dbg);
265}
266
267/*
268 * Root directory for UBI stuff in debugfs. Contains sub-directories which
269 * contain the stuff specific to particular UBI devices.
270 */
271static struct dentry *dfs_rootdir;
272
273/**
274 * ubi_debugfs_init - create UBI debugfs directory.
275 *
276 * Create UBI debugfs directory. Returns zero in case of success and a negative
277 * error code in case of failure.
278 */
279int ubi_debugfs_init(void)
280{
281 dfs_rootdir = debugfs_create_dir("ubi", NULL);
282 if (IS_ERR_OR_NULL(dfs_rootdir)) {
283 int err = dfs_rootdir ? -ENODEV : PTR_ERR(dfs_rootdir);
284
285 ubi_err("cannot create \"ubi\" debugfs directory, error %d\n",
286 err);
287 return err;
288 }
289
290 return 0;
291}
292
293/**
294 * ubi_debugfs_exit - remove UBI debugfs directory.
295 */
296void ubi_debugfs_exit(void)
297{
298 debugfs_remove(dfs_rootdir);
299}
300
301/* Read an UBI debugfs file */
302static ssize_t dfs_file_read(struct file *file, char __user *user_buf,
303 size_t count, loff_t *ppos)
304{
305 unsigned long ubi_num = (unsigned long)file->private_data;
306 struct dentry *dent = file->f_path.dentry;
307 struct ubi_device *ubi;
308 struct ubi_debug_info *d;
309 char buf[3];
310 int val;
311
312 ubi = ubi_get_device(ubi_num);
313 if (!ubi)
314 return -ENODEV;
315 d = ubi->dbg;
316
317 if (dent == d->dfs_chk_gen)
318 val = d->chk_gen;
319 else if (dent == d->dfs_chk_io)
320 val = d->chk_io;
321 else {
322 count = -EINVAL;
323 goto out;
324 }
325
326 if (val)
327 buf[0] = '1';
328 else
329 buf[0] = '0';
330 buf[1] = '\n';
331 buf[2] = 0x00;
332
333 count = simple_read_from_buffer(user_buf, count, ppos, buf, 2);
334
335out:
336 ubi_put_device(ubi);
337 return count;
338}
339
340/* Write an UBI debugfs file */
341static ssize_t dfs_file_write(struct file *file, const char __user *user_buf,
342 size_t count, loff_t *ppos)
343{
344 unsigned long ubi_num = (unsigned long)file->private_data;
345 struct dentry *dent = file->f_path.dentry;
346 struct ubi_device *ubi;
347 struct ubi_debug_info *d;
348 size_t buf_size;
349 char buf[8];
350 int val;
351
352 ubi = ubi_get_device(ubi_num);
353 if (!ubi)
354 return -ENODEV;
355 d = ubi->dbg;
356
357 buf_size = min_t(size_t, count, (sizeof(buf) - 1));
358 if (copy_from_user(buf, user_buf, buf_size)) {
359 count = -EFAULT;
360 goto out;
361 }
362
363 if (buf[0] == '1')
364 val = 1;
365 else if (buf[0] == '0')
366 val = 0;
367 else {
368 count = -EINVAL;
369 goto out;
370 }
371
372 if (dent == d->dfs_chk_gen)
373 d->chk_gen = val;
374 else if (dent == d->dfs_chk_io)
375 d->chk_io = val;
376 else
377 count = -EINVAL;
378
379out:
380 ubi_put_device(ubi);
381 return count;
382}
383
384static int default_open(struct inode *inode, struct file *file)
385{
386 if (inode->i_private)
387 file->private_data = inode->i_private;
388
389 return 0;
390}
391
392/* File operations for all UBI debugfs files */
393static const struct file_operations dfs_fops = {
394 .read = dfs_file_read,
395 .write = dfs_file_write,
396 .open = default_open,
397 .llseek = no_llseek,
398 .owner = THIS_MODULE,
399};
400
401/**
402 * ubi_debugfs_init_dev - initialize debugfs for an UBI device.
403 * @ubi: UBI device description object
404 *
405 * This function creates all debugfs files for UBI device @ubi. Returns zero in
406 * case of success and a negative error code in case of failure.
407 */
408int ubi_debugfs_init_dev(struct ubi_device *ubi)
409{
410 int err, n;
411 unsigned long ubi_num = ubi->ubi_num;
412 const char *fname;
413 struct dentry *dent;
414 struct ubi_debug_info *d = ubi->dbg;
415
416 n = snprintf(d->dfs_dir_name, UBI_DFS_DIR_LEN + 1, UBI_DFS_DIR_NAME,
417 ubi->ubi_num);
418 if (n == UBI_DFS_DIR_LEN) {
419 /* The array size is too small */
420 fname = UBI_DFS_DIR_NAME;
421 dent = ERR_PTR(-EINVAL);
422 goto out;
423 }
424
425 fname = d->dfs_dir_name;
426 dent = debugfs_create_dir(fname, dfs_rootdir);
427 if (IS_ERR_OR_NULL(dent))
428 goto out;
429 d->dfs_dir = dent;
430
431 fname = "chk_gen";
432 dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
433 &dfs_fops);
434 if (IS_ERR_OR_NULL(dent))
435 goto out_remove;
436 d->dfs_chk_gen = dent;
437
438 fname = "chk_io";
439 dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
440 &dfs_fops);
441 if (IS_ERR_OR_NULL(dent))
442 goto out_remove;
443 d->dfs_chk_io = dent;
444
445 return 0;
446
447out_remove:
448 debugfs_remove_recursive(d->dfs_dir);
449out:
450 err = dent ? PTR_ERR(dent) : -ENODEV;
451 ubi_err("cannot create \"%s\" debugfs file or directory, error %d\n",
452 fname, err);
453 return err;
454}
455
456/**
457 * dbg_debug_exit_dev - free all debugfs files corresponding to device @ubi
458 * @ubi: UBI device description object
459 */
460void ubi_debugfs_exit_dev(struct ubi_device *ubi)
461{
462 debugfs_remove_recursive(ubi->dbg->dfs_dir);
463}
464
242#endif /* CONFIG_MTD_UBI_DEBUG */ 465#endif /* CONFIG_MTD_UBI_DEBUG */