aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/ubi/debug.c')
-rw-r--r--drivers/mtd/ubi/debug.c269
1 files changed, 259 insertions, 10 deletions
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index 2224cbe41ddf..ab80c0debac8 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -27,17 +27,9 @@
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>
32
33unsigned int ubi_chk_flags;
34unsigned int ubi_tst_flags;
35
36module_param_named(debug_chks, ubi_chk_flags, uint, S_IRUGO | S_IWUSR);
37module_param_named(debug_tsts, ubi_chk_flags, uint, S_IRUGO | S_IWUSR);
38
39MODULE_PARM_DESC(debug_chks, "Debug check flags");
40MODULE_PARM_DESC(debug_tsts, "Debug special test flags");
41 33
42/** 34/**
43 * ubi_dbg_dump_ec_hdr - dump an erase counter header. 35 * ubi_dbg_dump_ec_hdr - dump an erase counter header.
@@ -239,4 +231,261 @@ out:
239 return; 231 return;
240} 232}
241 233
234/**
235 * ubi_debugging_init_dev - initialize debugging for an UBI device.
236 * @ubi: UBI device description object
237 *
238 * This function initializes debugging-related data for UBI device @ubi.
239 * Returns zero in case of success and a negative error code in case of
240 * failure.
241 */
242int ubi_debugging_init_dev(struct ubi_device *ubi)
243{
244 ubi->dbg = kzalloc(sizeof(struct ubi_debug_info), GFP_KERNEL);
245 if (!ubi->dbg)
246 return -ENOMEM;
247
248 return 0;
249}
250
251/**
252 * ubi_debugging_exit_dev - free debugging data for an UBI device.
253 * @ubi: UBI device description object
254 */
255void ubi_debugging_exit_dev(struct ubi_device *ubi)
256{
257 kfree(ubi->dbg);
258}
259
260/*
261 * Root directory for UBI stuff in debugfs. Contains sub-directories which
262 * contain the stuff specific to particular UBI devices.
263 */
264static struct dentry *dfs_rootdir;
265
266/**
267 * ubi_debugfs_init - create UBI debugfs directory.
268 *
269 * Create UBI debugfs directory. Returns zero in case of success and a negative
270 * error code in case of failure.
271 */
272int ubi_debugfs_init(void)
273{
274 dfs_rootdir = debugfs_create_dir("ubi", NULL);
275 if (IS_ERR_OR_NULL(dfs_rootdir)) {
276 int err = dfs_rootdir ? -ENODEV : PTR_ERR(dfs_rootdir);
277
278 ubi_err("cannot create \"ubi\" debugfs directory, error %d\n",
279 err);
280 return err;
281 }
282
283 return 0;
284}
285
286/**
287 * ubi_debugfs_exit - remove UBI debugfs directory.
288 */
289void ubi_debugfs_exit(void)
290{
291 debugfs_remove(dfs_rootdir);
292}
293
294/* Read an UBI debugfs file */
295static ssize_t dfs_file_read(struct file *file, char __user *user_buf,
296 size_t count, loff_t *ppos)
297{
298 unsigned long ubi_num = (unsigned long)file->private_data;
299 struct dentry *dent = file->f_path.dentry;
300 struct ubi_device *ubi;
301 struct ubi_debug_info *d;
302 char buf[3];
303 int val;
304
305 ubi = ubi_get_device(ubi_num);
306 if (!ubi)
307 return -ENODEV;
308 d = ubi->dbg;
309
310 if (dent == d->dfs_chk_gen)
311 val = d->chk_gen;
312 else if (dent == d->dfs_chk_io)
313 val = d->chk_io;
314 else if (dent == d->dfs_disable_bgt)
315 val = d->disable_bgt;
316 else if (dent == d->dfs_emulate_bitflips)
317 val = d->emulate_bitflips;
318 else if (dent == d->dfs_emulate_io_failures)
319 val = d->emulate_io_failures;
320 else {
321 count = -EINVAL;
322 goto out;
323 }
324
325 if (val)
326 buf[0] = '1';
327 else
328 buf[0] = '0';
329 buf[1] = '\n';
330 buf[2] = 0x00;
331
332 count = simple_read_from_buffer(user_buf, count, ppos, buf, 2);
333
334out:
335 ubi_put_device(ubi);
336 return count;
337}
338
339/* Write an UBI debugfs file */
340static ssize_t dfs_file_write(struct file *file, const char __user *user_buf,
341 size_t count, loff_t *ppos)
342{
343 unsigned long ubi_num = (unsigned long)file->private_data;
344 struct dentry *dent = file->f_path.dentry;
345 struct ubi_device *ubi;
346 struct ubi_debug_info *d;
347 size_t buf_size;
348 char buf[8];
349 int val;
350
351 ubi = ubi_get_device(ubi_num);
352 if (!ubi)
353 return -ENODEV;
354 d = ubi->dbg;
355
356 buf_size = min_t(size_t, count, (sizeof(buf) - 1));
357 if (copy_from_user(buf, user_buf, buf_size)) {
358 count = -EFAULT;
359 goto out;
360 }
361
362 if (buf[0] == '1')
363 val = 1;
364 else if (buf[0] == '0')
365 val = 0;
366 else {
367 count = -EINVAL;
368 goto out;
369 }
370
371 if (dent == d->dfs_chk_gen)
372 d->chk_gen = val;
373 else if (dent == d->dfs_chk_io)
374 d->chk_io = val;
375 else if (dent == d->dfs_disable_bgt)
376 d->disable_bgt = val;
377 else if (dent == d->dfs_emulate_bitflips)
378 d->emulate_bitflips = val;
379 else if (dent == d->dfs_emulate_io_failures)
380 d->emulate_io_failures = val;
381 else
382 count = -EINVAL;
383
384out:
385 ubi_put_device(ubi);
386 return count;
387}
388
389static int default_open(struct inode *inode, struct file *file)
390{
391 if (inode->i_private)
392 file->private_data = inode->i_private;
393
394 return 0;
395}
396
397/* File operations for all UBI debugfs files */
398static const struct file_operations dfs_fops = {
399 .read = dfs_file_read,
400 .write = dfs_file_write,
401 .open = default_open,
402 .llseek = no_llseek,
403 .owner = THIS_MODULE,
404};
405
406/**
407 * ubi_debugfs_init_dev - initialize debugfs for an UBI device.
408 * @ubi: UBI device description object
409 *
410 * This function creates all debugfs files for UBI device @ubi. Returns zero in
411 * case of success and a negative error code in case of failure.
412 */
413int ubi_debugfs_init_dev(struct ubi_device *ubi)
414{
415 int err, n;
416 unsigned long ubi_num = ubi->ubi_num;
417 const char *fname;
418 struct dentry *dent;
419 struct ubi_debug_info *d = ubi->dbg;
420
421 n = snprintf(d->dfs_dir_name, UBI_DFS_DIR_LEN + 1, UBI_DFS_DIR_NAME,
422 ubi->ubi_num);
423 if (n == UBI_DFS_DIR_LEN) {
424 /* The array size is too small */
425 fname = UBI_DFS_DIR_NAME;
426 dent = ERR_PTR(-EINVAL);
427 goto out;
428 }
429
430 fname = d->dfs_dir_name;
431 dent = debugfs_create_dir(fname, dfs_rootdir);
432 if (IS_ERR_OR_NULL(dent))
433 goto out;
434 d->dfs_dir = dent;
435
436 fname = "chk_gen";
437 dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
438 &dfs_fops);
439 if (IS_ERR_OR_NULL(dent))
440 goto out_remove;
441 d->dfs_chk_gen = dent;
442
443 fname = "chk_io";
444 dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
445 &dfs_fops);
446 if (IS_ERR_OR_NULL(dent))
447 goto out_remove;
448 d->dfs_chk_io = dent;
449
450 fname = "tst_disable_bgt";
451 dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
452 &dfs_fops);
453 if (IS_ERR_OR_NULL(dent))
454 goto out_remove;
455 d->dfs_disable_bgt = dent;
456
457 fname = "tst_emulate_bitflips";
458 dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
459 &dfs_fops);
460 if (IS_ERR_OR_NULL(dent))
461 goto out_remove;
462 d->dfs_emulate_bitflips = dent;
463
464 fname = "tst_emulate_io_failures";
465 dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
466 &dfs_fops);
467 if (IS_ERR_OR_NULL(dent))
468 goto out_remove;
469 d->dfs_emulate_io_failures = dent;
470
471 return 0;
472
473out_remove:
474 debugfs_remove_recursive(d->dfs_dir);
475out:
476 err = dent ? PTR_ERR(dent) : -ENODEV;
477 ubi_err("cannot create \"%s\" debugfs file or directory, error %d\n",
478 fname, err);
479 return err;
480}
481
482/**
483 * dbg_debug_exit_dev - free all debugfs files corresponding to device @ubi
484 * @ubi: UBI device description object
485 */
486void ubi_debugfs_exit_dev(struct ubi_device *ubi)
487{
488 debugfs_remove_recursive(ubi->dbg->dfs_dir);
489}
490
242#endif /* CONFIG_MTD_UBI_DEBUG */ 491#endif /* CONFIG_MTD_UBI_DEBUG */