^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) International Business Machines Corp., 2006
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Author: Artem Bityutskiy (Битюцкий Артём)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "ubi.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * ubi_dump_flash - dump a region of flash.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * @ubi: UBI device description object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * @pnum: the physical eraseblock number to dump
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * @offset: the starting offset within the physical eraseblock to dump
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * @len: the length of the region to dump
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) void ubi_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) size_t read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) void *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) buf = vmalloc(len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) err = mtd_read(ubi->mtd, addr, len, &read, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (err && err != -EUCLEAN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) ubi_err(ubi, "err %d while reading %d bytes from PEB %d:%d, read %zd bytes",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) err, len, pnum, offset, read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) ubi_msg(ubi, "dumping %d bytes of data from PEB %d, offset %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) len, pnum, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) vfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * ubi_dump_ec_hdr - dump an erase counter header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * @ec_hdr: the erase counter header to dump
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) void ubi_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) pr_err("Erase counter header dump:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) pr_err("\tmagic %#08x\n", be32_to_cpu(ec_hdr->magic));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) pr_err("\tversion %d\n", (int)ec_hdr->version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) pr_err("\tec %llu\n", (long long)be64_to_cpu(ec_hdr->ec));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) pr_err("\tvid_hdr_offset %d\n", be32_to_cpu(ec_hdr->vid_hdr_offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) pr_err("\tdata_offset %d\n", be32_to_cpu(ec_hdr->data_offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) pr_err("\timage_seq %d\n", be32_to_cpu(ec_hdr->image_seq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) pr_err("\thdr_crc %#08x\n", be32_to_cpu(ec_hdr->hdr_crc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) pr_err("erase counter header hexdump:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) ec_hdr, UBI_EC_HDR_SIZE, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * ubi_dump_vid_hdr - dump a volume identifier header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * @vid_hdr: the volume identifier header to dump
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) void ubi_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) pr_err("Volume identifier header dump:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) pr_err("\tmagic %08x\n", be32_to_cpu(vid_hdr->magic));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) pr_err("\tversion %d\n", (int)vid_hdr->version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) pr_err("\tvol_type %d\n", (int)vid_hdr->vol_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) pr_err("\tcopy_flag %d\n", (int)vid_hdr->copy_flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) pr_err("\tcompat %d\n", (int)vid_hdr->compat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) pr_err("\tvol_id %d\n", be32_to_cpu(vid_hdr->vol_id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) pr_err("\tlnum %d\n", be32_to_cpu(vid_hdr->lnum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) pr_err("\tdata_size %d\n", be32_to_cpu(vid_hdr->data_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) pr_err("\tused_ebs %d\n", be32_to_cpu(vid_hdr->used_ebs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) pr_err("\tdata_pad %d\n", be32_to_cpu(vid_hdr->data_pad));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) pr_err("\tsqnum %llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) (unsigned long long)be64_to_cpu(vid_hdr->sqnum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) pr_err("\thdr_crc %08x\n", be32_to_cpu(vid_hdr->hdr_crc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) pr_err("Volume identifier header hexdump:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) vid_hdr, UBI_VID_HDR_SIZE, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * ubi_dump_vol_info - dump volume information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * @vol: UBI volume description object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) void ubi_dump_vol_info(const struct ubi_volume *vol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) pr_err("Volume information dump:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) pr_err("\tvol_id %d\n", vol->vol_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) pr_err("\treserved_pebs %d\n", vol->reserved_pebs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) pr_err("\talignment %d\n", vol->alignment);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) pr_err("\tdata_pad %d\n", vol->data_pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) pr_err("\tvol_type %d\n", vol->vol_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) pr_err("\tname_len %d\n", vol->name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) pr_err("\tusable_leb_size %d\n", vol->usable_leb_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) pr_err("\tused_ebs %d\n", vol->used_ebs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) pr_err("\tused_bytes %lld\n", vol->used_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) pr_err("\tlast_eb_bytes %d\n", vol->last_eb_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) pr_err("\tcorrupted %d\n", vol->corrupted);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) pr_err("\tupd_marker %d\n", vol->upd_marker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) pr_err("\tskip_check %d\n", vol->skip_check);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (vol->name_len <= UBI_VOL_NAME_MAX &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) strnlen(vol->name, vol->name_len + 1) == vol->name_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) pr_err("\tname %s\n", vol->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) pr_err("\t1st 5 characters of name: %c%c%c%c%c\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) vol->name[0], vol->name[1], vol->name[2],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) vol->name[3], vol->name[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * ubi_dump_vtbl_record - dump a &struct ubi_vtbl_record object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * @r: the object to dump
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * @idx: volume table index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) void ubi_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) int name_len = be16_to_cpu(r->name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) pr_err("Volume table record %d dump:\n", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) pr_err("\treserved_pebs %d\n", be32_to_cpu(r->reserved_pebs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) pr_err("\talignment %d\n", be32_to_cpu(r->alignment));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) pr_err("\tdata_pad %d\n", be32_to_cpu(r->data_pad));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) pr_err("\tvol_type %d\n", (int)r->vol_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) pr_err("\tupd_marker %d\n", (int)r->upd_marker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) pr_err("\tname_len %d\n", name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (r->name[0] == '\0') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) pr_err("\tname NULL\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (name_len <= UBI_VOL_NAME_MAX &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) strnlen(&r->name[0], name_len + 1) == name_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) pr_err("\tname %s\n", &r->name[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) pr_err("\t1st 5 characters of name: %c%c%c%c%c\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) r->name[0], r->name[1], r->name[2], r->name[3],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) r->name[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) pr_err("\tcrc %#08x\n", be32_to_cpu(r->crc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * ubi_dump_av - dump a &struct ubi_ainf_volume object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * @av: the object to dump
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) void ubi_dump_av(const struct ubi_ainf_volume *av)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) pr_err("Volume attaching information dump:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) pr_err("\tvol_id %d\n", av->vol_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) pr_err("\thighest_lnum %d\n", av->highest_lnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) pr_err("\tleb_count %d\n", av->leb_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) pr_err("\tcompat %d\n", av->compat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) pr_err("\tvol_type %d\n", av->vol_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) pr_err("\tused_ebs %d\n", av->used_ebs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) pr_err("\tlast_data_size %d\n", av->last_data_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) pr_err("\tdata_pad %d\n", av->data_pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * ubi_dump_aeb - dump a &struct ubi_ainf_peb object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * @aeb: the object to dump
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * @type: object type: 0 - not corrupted, 1 - corrupted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) void ubi_dump_aeb(const struct ubi_ainf_peb *aeb, int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) pr_err("eraseblock attaching information dump:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) pr_err("\tec %d\n", aeb->ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) pr_err("\tpnum %d\n", aeb->pnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (type == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) pr_err("\tlnum %d\n", aeb->lnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) pr_err("\tscrub %d\n", aeb->scrub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) pr_err("\tsqnum %llu\n", aeb->sqnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * ubi_dump_mkvol_req - dump a &struct ubi_mkvol_req object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * @req: the object to dump
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) void ubi_dump_mkvol_req(const struct ubi_mkvol_req *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) char nm[17];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) pr_err("Volume creation request dump:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) pr_err("\tvol_id %d\n", req->vol_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) pr_err("\talignment %d\n", req->alignment);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) pr_err("\tbytes %lld\n", (long long)req->bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) pr_err("\tvol_type %d\n", req->vol_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) pr_err("\tname_len %d\n", req->name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) memcpy(nm, req->name, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) nm[16] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) pr_err("\t1st 16 characters of name: %s\n", nm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * Root directory for UBI stuff in debugfs. Contains sub-directories which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * contain the stuff specific to particular UBI devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static struct dentry *dfs_rootdir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * ubi_debugfs_init - create UBI debugfs directory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * Create UBI debugfs directory. Returns zero in case of success and a negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * error code in case of failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) int ubi_debugfs_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (!IS_ENABLED(CONFIG_DEBUG_FS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) dfs_rootdir = debugfs_create_dir("ubi", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (IS_ERR_OR_NULL(dfs_rootdir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) int err = dfs_rootdir ? PTR_ERR(dfs_rootdir) : -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) pr_err("UBI error: cannot create \"ubi\" debugfs directory, error %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * ubi_debugfs_exit - remove UBI debugfs directory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) void ubi_debugfs_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (IS_ENABLED(CONFIG_DEBUG_FS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) debugfs_remove(dfs_rootdir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /* Read an UBI debugfs file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static ssize_t dfs_file_read(struct file *file, char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) unsigned long ubi_num = (unsigned long)file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct dentry *dent = file->f_path.dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) struct ubi_device *ubi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) struct ubi_debug_info *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) char buf[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) ubi = ubi_get_device(ubi_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (!ubi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) d = &ubi->dbg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (dent == d->dfs_chk_gen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) val = d->chk_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) else if (dent == d->dfs_chk_io)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) val = d->chk_io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) else if (dent == d->dfs_chk_fastmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) val = d->chk_fastmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) else if (dent == d->dfs_disable_bgt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) val = d->disable_bgt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) else if (dent == d->dfs_emulate_bitflips)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) val = d->emulate_bitflips;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) else if (dent == d->dfs_emulate_io_failures)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) val = d->emulate_io_failures;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) else if (dent == d->dfs_emulate_power_cut) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) snprintf(buf, sizeof(buf), "%u\n", d->emulate_power_cut);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) count = simple_read_from_buffer(user_buf, count, ppos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) buf, strlen(buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) } else if (dent == d->dfs_power_cut_min) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) snprintf(buf, sizeof(buf), "%u\n", d->power_cut_min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) count = simple_read_from_buffer(user_buf, count, ppos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) buf, strlen(buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) } else if (dent == d->dfs_power_cut_max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) snprintf(buf, sizeof(buf), "%u\n", d->power_cut_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) count = simple_read_from_buffer(user_buf, count, ppos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) buf, strlen(buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) count = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) buf[0] = '1';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) buf[0] = '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) buf[1] = '\n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) buf[2] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) count = simple_read_from_buffer(user_buf, count, ppos, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) ubi_put_device(ubi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) /* Write an UBI debugfs file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static ssize_t dfs_file_write(struct file *file, const char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) unsigned long ubi_num = (unsigned long)file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) struct dentry *dent = file->f_path.dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) struct ubi_device *ubi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct ubi_debug_info *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) size_t buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) char buf[8] = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) ubi = ubi_get_device(ubi_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (!ubi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) d = &ubi->dbg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) buf_size = min_t(size_t, count, (sizeof(buf) - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (copy_from_user(buf, user_buf, buf_size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) count = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (dent == d->dfs_power_cut_min) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (kstrtouint(buf, 0, &d->power_cut_min) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) count = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) } else if (dent == d->dfs_power_cut_max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (kstrtouint(buf, 0, &d->power_cut_max) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) count = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) } else if (dent == d->dfs_emulate_power_cut) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (kstrtoint(buf, 0, &val) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) count = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) d->emulate_power_cut = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (buf[0] == '1')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) val = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) else if (buf[0] == '0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) count = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (dent == d->dfs_chk_gen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) d->chk_gen = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) else if (dent == d->dfs_chk_io)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) d->chk_io = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) else if (dent == d->dfs_chk_fastmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) d->chk_fastmap = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) else if (dent == d->dfs_disable_bgt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) d->disable_bgt = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) else if (dent == d->dfs_emulate_bitflips)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) d->emulate_bitflips = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) else if (dent == d->dfs_emulate_io_failures)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) d->emulate_io_failures = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) count = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) ubi_put_device(ubi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) /* File operations for all UBI debugfs files except
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) * detailed_erase_block_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) static const struct file_operations dfs_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) .read = dfs_file_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) .write = dfs_file_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) .open = simple_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) .llseek = no_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) /* As long as the position is less then that total number of erase blocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) * we still have more to print.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) static void *eraseblk_count_seq_start(struct seq_file *s, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct ubi_device *ubi = s->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (*pos < ubi->peb_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) return pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) /* Since we are using the position as the iterator, we just need to check if we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * are done and increment the position.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) static void *eraseblk_count_seq_next(struct seq_file *s, void *v, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) struct ubi_device *ubi = s->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) (*pos)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (*pos < ubi->peb_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) return pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) static void eraseblk_count_seq_stop(struct seq_file *s, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) static int eraseblk_count_seq_show(struct seq_file *s, void *iter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) struct ubi_device *ubi = s->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) struct ubi_wl_entry *wl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) int *block_number = iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) int erase_count = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) /* If this is the start, print a header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (*block_number == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) seq_puts(s, "physical_block_number\terase_count\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) err = ubi_io_is_bad(ubi, *block_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) spin_lock(&ubi->wl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) wl = ubi->lookuptbl[*block_number];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (wl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) erase_count = wl->ec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) spin_unlock(&ubi->wl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (erase_count < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) seq_printf(s, "%-22d\t%-11d\n", *block_number, erase_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) static const struct seq_operations eraseblk_count_seq_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) .start = eraseblk_count_seq_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) .next = eraseblk_count_seq_next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) .stop = eraseblk_count_seq_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) .show = eraseblk_count_seq_show
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static int eraseblk_count_open(struct inode *inode, struct file *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) struct seq_file *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) err = seq_open(f, &eraseblk_count_seq_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) s = f->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) s->private = ubi_get_device((unsigned long)inode->i_private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (!s->private)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) static int eraseblk_count_release(struct inode *inode, struct file *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) struct seq_file *s = f->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) struct ubi_device *ubi = s->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) ubi_put_device(ubi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return seq_release(inode, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) static const struct file_operations eraseblk_count_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) .open = eraseblk_count_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) .read = seq_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) .llseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) .release = eraseblk_count_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) * ubi_debugfs_init_dev - initialize debugfs for an UBI device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) * @ubi: UBI device description object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) * This function creates all debugfs files for UBI device @ubi. Returns zero in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) * case of success and a negative error code in case of failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) int ubi_debugfs_init_dev(struct ubi_device *ubi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) unsigned long ubi_num = ubi->ubi_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) struct ubi_debug_info *d = &ubi->dbg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (!IS_ENABLED(CONFIG_DEBUG_FS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) n = snprintf(d->dfs_dir_name, UBI_DFS_DIR_LEN + 1, UBI_DFS_DIR_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) ubi->ubi_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (n == UBI_DFS_DIR_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) /* The array size is too small */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) d->dfs_dir = debugfs_create_dir(d->dfs_dir_name, dfs_rootdir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) d->dfs_chk_gen = debugfs_create_file("chk_gen", S_IWUSR, d->dfs_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) (void *)ubi_num, &dfs_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) d->dfs_chk_io = debugfs_create_file("chk_io", S_IWUSR, d->dfs_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) (void *)ubi_num, &dfs_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) d->dfs_chk_fastmap = debugfs_create_file("chk_fastmap", S_IWUSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) d->dfs_dir, (void *)ubi_num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) &dfs_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) d->dfs_disable_bgt = debugfs_create_file("tst_disable_bgt", S_IWUSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) d->dfs_dir, (void *)ubi_num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) &dfs_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) d->dfs_emulate_bitflips = debugfs_create_file("tst_emulate_bitflips",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) S_IWUSR, d->dfs_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) (void *)ubi_num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) &dfs_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) d->dfs_emulate_io_failures = debugfs_create_file("tst_emulate_io_failures",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) S_IWUSR, d->dfs_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) (void *)ubi_num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) &dfs_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) d->dfs_emulate_power_cut = debugfs_create_file("tst_emulate_power_cut",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) S_IWUSR, d->dfs_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) (void *)ubi_num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) &dfs_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) d->dfs_power_cut_min = debugfs_create_file("tst_emulate_power_cut_min",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) S_IWUSR, d->dfs_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) (void *)ubi_num, &dfs_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) d->dfs_power_cut_max = debugfs_create_file("tst_emulate_power_cut_max",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) S_IWUSR, d->dfs_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) (void *)ubi_num, &dfs_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) debugfs_create_file("detailed_erase_block_info", S_IRUSR, d->dfs_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) (void *)ubi_num, &eraseblk_count_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) * dbg_debug_exit_dev - free all debugfs files corresponding to device @ubi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) * @ubi: UBI device description object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) void ubi_debugfs_exit_dev(struct ubi_device *ubi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (IS_ENABLED(CONFIG_DEBUG_FS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) debugfs_remove_recursive(ubi->dbg.dfs_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) * ubi_dbg_power_cut - emulate a power cut if it is time to do so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * @ubi: UBI device description object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * @caller: Flags set to indicate from where the function is being called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) * Returns non-zero if a power cut was emulated, zero if not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) int ubi_dbg_power_cut(struct ubi_device *ubi, int caller)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) unsigned int range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if ((ubi->dbg.emulate_power_cut & caller) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (ubi->dbg.power_cut_counter == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) ubi->dbg.power_cut_counter = ubi->dbg.power_cut_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) if (ubi->dbg.power_cut_max > ubi->dbg.power_cut_min) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) range = ubi->dbg.power_cut_max - ubi->dbg.power_cut_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) ubi->dbg.power_cut_counter += prandom_u32() % range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) ubi->dbg.power_cut_counter--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (ubi->dbg.power_cut_counter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) ubi_msg(ubi, "XXXXXXXXXXXXXXX emulating a power cut XXXXXXXXXXXXXXXX");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) ubi_ro_mode(ubi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }