blob: dce1227929f1b8daa18d42cf1d66fac9270573cf [file] [log] [blame]
Artem B. Bityutskiy801c1352006-06-27 12:22:22 +04001/*
2 * Copyright (c) International Business Machines Corp., 2006
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12 * the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Artem Bityutskiy (Битюцкий Артём)
19 */
20
21/*
22 * Here we keep all the UBI debugging stuff which should normally be disabled
23 * and compiled-out, but it is extremely helpful when hunting bugs or doing big
24 * changes.
25 */
26
Artem Bityutskiyc8566352008-07-16 17:40:22 +030027#ifdef CONFIG_MTD_UBI_DEBUG
Artem B. Bityutskiy801c1352006-06-27 12:22:22 +040028
29#include "ubi.h"
Artem Bityutskiy2a734bb2011-05-18 14:53:05 +030030#include <linux/debugfs.h>
31#include <linux/uaccess.h>
Artem Bityutskiyb342efd2011-03-11 14:33:23 +020032#include <linux/module.h>
33#include <linux/moduleparam.h>
34
Artem Bityutskiy28237e42011-03-15 10:30:40 +020035unsigned int ubi_tst_flags;
Artem Bityutskiyb342efd2011-03-11 14:33:23 +020036
Artem Bityutskiy2a734bb2011-05-18 14:53:05 +030037module_param_named(debug_tsts, ubi_tst_flags, uint, S_IRUGO | S_IWUSR);
Artem Bityutskiyb342efd2011-03-11 14:33:23 +020038
Artem Bityutskiy28237e42011-03-15 10:30:40 +020039MODULE_PARM_DESC(debug_tsts, "Debug special test flags");
Artem B. Bityutskiy801c1352006-06-27 12:22:22 +040040
41/**
42 * ubi_dbg_dump_ec_hdr - dump an erase counter header.
43 * @ec_hdr: the erase counter header to dump
44 */
45void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
46{
Artem Bityutskiyc8566352008-07-16 17:40:22 +030047 printk(KERN_DEBUG "Erase counter header dump:\n");
48 printk(KERN_DEBUG "\tmagic %#08x\n",
49 be32_to_cpu(ec_hdr->magic));
50 printk(KERN_DEBUG "\tversion %d\n", (int)ec_hdr->version);
51 printk(KERN_DEBUG "\tec %llu\n",
52 (long long)be64_to_cpu(ec_hdr->ec));
53 printk(KERN_DEBUG "\tvid_hdr_offset %d\n",
54 be32_to_cpu(ec_hdr->vid_hdr_offset));
55 printk(KERN_DEBUG "\tdata_offset %d\n",
56 be32_to_cpu(ec_hdr->data_offset));
Adrian Hunter0c6c7fa2009-06-26 14:58:01 +030057 printk(KERN_DEBUG "\timage_seq %d\n",
58 be32_to_cpu(ec_hdr->image_seq));
Artem Bityutskiyc8566352008-07-16 17:40:22 +030059 printk(KERN_DEBUG "\thdr_crc %#08x\n",
60 be32_to_cpu(ec_hdr->hdr_crc));
61 printk(KERN_DEBUG "erase counter header hexdump:\n");
Artem Bityutskiy69866462007-08-29 14:56:20 +030062 print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
63 ec_hdr, UBI_EC_HDR_SIZE, 1);
Artem B. Bityutskiy801c1352006-06-27 12:22:22 +040064}
65
66/**
67 * ubi_dbg_dump_vid_hdr - dump a volume identifier header.
68 * @vid_hdr: the volume identifier header to dump
69 */
70void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr)
71{
Artem Bityutskiyc8566352008-07-16 17:40:22 +030072 printk(KERN_DEBUG "Volume identifier header dump:\n");
73 printk(KERN_DEBUG "\tmagic %08x\n", be32_to_cpu(vid_hdr->magic));
Artem Bityutskiyfeddbb32011-03-28 10:12:25 +030074 printk(KERN_DEBUG "\tversion %d\n", (int)vid_hdr->version);
75 printk(KERN_DEBUG "\tvol_type %d\n", (int)vid_hdr->vol_type);
76 printk(KERN_DEBUG "\tcopy_flag %d\n", (int)vid_hdr->copy_flag);
77 printk(KERN_DEBUG "\tcompat %d\n", (int)vid_hdr->compat);
78 printk(KERN_DEBUG "\tvol_id %d\n", be32_to_cpu(vid_hdr->vol_id));
79 printk(KERN_DEBUG "\tlnum %d\n", be32_to_cpu(vid_hdr->lnum));
80 printk(KERN_DEBUG "\tdata_size %d\n", be32_to_cpu(vid_hdr->data_size));
81 printk(KERN_DEBUG "\tused_ebs %d\n", be32_to_cpu(vid_hdr->used_ebs));
82 printk(KERN_DEBUG "\tdata_pad %d\n", be32_to_cpu(vid_hdr->data_pad));
Artem Bityutskiyc8566352008-07-16 17:40:22 +030083 printk(KERN_DEBUG "\tsqnum %llu\n",
Christoph Hellwig3261ebd2007-05-21 17:41:46 +030084 (unsigned long long)be64_to_cpu(vid_hdr->sqnum));
Artem Bityutskiyc8566352008-07-16 17:40:22 +030085 printk(KERN_DEBUG "\thdr_crc %08x\n", be32_to_cpu(vid_hdr->hdr_crc));
86 printk(KERN_DEBUG "Volume identifier header hexdump:\n");
87 print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
88 vid_hdr, UBI_VID_HDR_SIZE, 1);
Artem B. Bityutskiy801c1352006-06-27 12:22:22 +040089}
90
91/**
92 * ubi_dbg_dump_vol_info- dump volume information.
93 * @vol: UBI volume description object
94 */
95void ubi_dbg_dump_vol_info(const struct ubi_volume *vol)
96{
Artem Bityutskiyc8566352008-07-16 17:40:22 +030097 printk(KERN_DEBUG "Volume information dump:\n");
98 printk(KERN_DEBUG "\tvol_id %d\n", vol->vol_id);
99 printk(KERN_DEBUG "\treserved_pebs %d\n", vol->reserved_pebs);
100 printk(KERN_DEBUG "\talignment %d\n", vol->alignment);
101 printk(KERN_DEBUG "\tdata_pad %d\n", vol->data_pad);
102 printk(KERN_DEBUG "\tvol_type %d\n", vol->vol_type);
103 printk(KERN_DEBUG "\tname_len %d\n", vol->name_len);
104 printk(KERN_DEBUG "\tusable_leb_size %d\n", vol->usable_leb_size);
105 printk(KERN_DEBUG "\tused_ebs %d\n", vol->used_ebs);
106 printk(KERN_DEBUG "\tused_bytes %lld\n", vol->used_bytes);
107 printk(KERN_DEBUG "\tlast_eb_bytes %d\n", vol->last_eb_bytes);
108 printk(KERN_DEBUG "\tcorrupted %d\n", vol->corrupted);
109 printk(KERN_DEBUG "\tupd_marker %d\n", vol->upd_marker);
Artem B. Bityutskiy801c1352006-06-27 12:22:22 +0400110
111 if (vol->name_len <= UBI_VOL_NAME_MAX &&
112 strnlen(vol->name, vol->name_len + 1) == vol->name_len) {
Artem Bityutskiyc8566352008-07-16 17:40:22 +0300113 printk(KERN_DEBUG "\tname %s\n", vol->name);
Artem B. Bityutskiy801c1352006-06-27 12:22:22 +0400114 } else {
Artem Bityutskiyc8566352008-07-16 17:40:22 +0300115 printk(KERN_DEBUG "\t1st 5 characters of name: %c%c%c%c%c\n",
116 vol->name[0], vol->name[1], vol->name[2],
117 vol->name[3], vol->name[4]);
Artem B. Bityutskiy801c1352006-06-27 12:22:22 +0400118 }
119}
120
121/**
122 * ubi_dbg_dump_vtbl_record - dump a &struct ubi_vtbl_record object.
123 * @r: the object to dump
124 * @idx: volume table index
125 */
126void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx)
127{
Christoph Hellwig3261ebd2007-05-21 17:41:46 +0300128 int name_len = be16_to_cpu(r->name_len);
Artem B. Bityutskiy801c1352006-06-27 12:22:22 +0400129
Artem Bityutskiyc8566352008-07-16 17:40:22 +0300130 printk(KERN_DEBUG "Volume table record %d dump:\n", idx);
131 printk(KERN_DEBUG "\treserved_pebs %d\n",
132 be32_to_cpu(r->reserved_pebs));
133 printk(KERN_DEBUG "\talignment %d\n", be32_to_cpu(r->alignment));
134 printk(KERN_DEBUG "\tdata_pad %d\n", be32_to_cpu(r->data_pad));
135 printk(KERN_DEBUG "\tvol_type %d\n", (int)r->vol_type);
136 printk(KERN_DEBUG "\tupd_marker %d\n", (int)r->upd_marker);
137 printk(KERN_DEBUG "\tname_len %d\n", name_len);
Artem B. Bityutskiy801c1352006-06-27 12:22:22 +0400138
139 if (r->name[0] == '\0') {
Artem Bityutskiyc8566352008-07-16 17:40:22 +0300140 printk(KERN_DEBUG "\tname NULL\n");
Artem B. Bityutskiy801c1352006-06-27 12:22:22 +0400141 return;
142 }
143
144 if (name_len <= UBI_VOL_NAME_MAX &&
145 strnlen(&r->name[0], name_len + 1) == name_len) {
Artem Bityutskiyc8566352008-07-16 17:40:22 +0300146 printk(KERN_DEBUG "\tname %s\n", &r->name[0]);
Artem B. Bityutskiy801c1352006-06-27 12:22:22 +0400147 } else {
Artem Bityutskiyc8566352008-07-16 17:40:22 +0300148 printk(KERN_DEBUG "\t1st 5 characters of name: %c%c%c%c%c\n",
Artem B. Bityutskiy801c1352006-06-27 12:22:22 +0400149 r->name[0], r->name[1], r->name[2], r->name[3],
150 r->name[4]);
151 }
Artem Bityutskiyc8566352008-07-16 17:40:22 +0300152 printk(KERN_DEBUG "\tcrc %#08x\n", be32_to_cpu(r->crc));
Artem B. Bityutskiy801c1352006-06-27 12:22:22 +0400153}
154
155/**
156 * ubi_dbg_dump_sv - dump a &struct ubi_scan_volume object.
157 * @sv: the object to dump
158 */
159void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv)
160{
Artem Bityutskiyc8566352008-07-16 17:40:22 +0300161 printk(KERN_DEBUG "Volume scanning information dump:\n");
162 printk(KERN_DEBUG "\tvol_id %d\n", sv->vol_id);
163 printk(KERN_DEBUG "\thighest_lnum %d\n", sv->highest_lnum);
164 printk(KERN_DEBUG "\tleb_count %d\n", sv->leb_count);
165 printk(KERN_DEBUG "\tcompat %d\n", sv->compat);
166 printk(KERN_DEBUG "\tvol_type %d\n", sv->vol_type);
167 printk(KERN_DEBUG "\tused_ebs %d\n", sv->used_ebs);
168 printk(KERN_DEBUG "\tlast_data_size %d\n", sv->last_data_size);
169 printk(KERN_DEBUG "\tdata_pad %d\n", sv->data_pad);
Artem B. Bityutskiy801c1352006-06-27 12:22:22 +0400170}
171
172/**
173 * ubi_dbg_dump_seb - dump a &struct ubi_scan_leb object.
174 * @seb: the object to dump
175 * @type: object type: 0 - not corrupted, 1 - corrupted
176 */
177void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type)
178{
Artem Bityutskiyc8566352008-07-16 17:40:22 +0300179 printk(KERN_DEBUG "eraseblock scanning information dump:\n");
180 printk(KERN_DEBUG "\tec %d\n", seb->ec);
181 printk(KERN_DEBUG "\tpnum %d\n", seb->pnum);
Artem B. Bityutskiy801c1352006-06-27 12:22:22 +0400182 if (type == 0) {
Artem Bityutskiyc8566352008-07-16 17:40:22 +0300183 printk(KERN_DEBUG "\tlnum %d\n", seb->lnum);
184 printk(KERN_DEBUG "\tscrub %d\n", seb->scrub);
185 printk(KERN_DEBUG "\tsqnum %llu\n", seb->sqnum);
Artem B. Bityutskiy801c1352006-06-27 12:22:22 +0400186 }
187}
188
189/**
190 * ubi_dbg_dump_mkvol_req - dump a &struct ubi_mkvol_req object.
191 * @req: the object to dump
192 */
193void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req)
194{
195 char nm[17];
196
Artem Bityutskiyc8566352008-07-16 17:40:22 +0300197 printk(KERN_DEBUG "Volume creation request dump:\n");
198 printk(KERN_DEBUG "\tvol_id %d\n", req->vol_id);
199 printk(KERN_DEBUG "\talignment %d\n", req->alignment);
200 printk(KERN_DEBUG "\tbytes %lld\n", (long long)req->bytes);
201 printk(KERN_DEBUG "\tvol_type %d\n", req->vol_type);
202 printk(KERN_DEBUG "\tname_len %d\n", req->name_len);
Artem B. Bityutskiy801c1352006-06-27 12:22:22 +0400203
204 memcpy(nm, req->name, 16);
205 nm[16] = 0;
Artem Bityutskiyc8566352008-07-16 17:40:22 +0300206 printk(KERN_DEBUG "\t1st 16 characters of name: %s\n", nm);
Artem B. Bityutskiy801c1352006-06-27 12:22:22 +0400207}
208
Artem Bityutskiy867996b2009-07-24 15:31:33 +0300209/**
210 * ubi_dbg_dump_flash - dump a region of flash.
211 * @ubi: UBI device description object
212 * @pnum: the physical eraseblock number to dump
213 * @offset: the starting offset within the physical eraseblock to dump
214 * @len: the length of the region to dump
215 */
216void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len)
217{
218 int err;
219 size_t read;
220 void *buf;
221 loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
222
223 buf = vmalloc(len);
224 if (!buf)
225 return;
226 err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);
227 if (err && err != -EUCLEAN) {
228 ubi_err("error %d while reading %d bytes from PEB %d:%d, "
229 "read %zd bytes", err, len, pnum, offset, read);
230 goto out;
231 }
232
233 dbg_msg("dumping %d bytes of data from PEB %d, offset %d",
234 len, pnum, offset);
235 print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1);
236out:
237 vfree(buf);
238 return;
239}
240
Artem Bityutskiy2a734bb2011-05-18 14:53:05 +0300241/**
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
Artem Bityutskiyc8566352008-07-16 17:40:22 +0300465#endif /* CONFIG_MTD_UBI_DEBUG */