aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/files
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2022-01-09 17:27:29 +0100
committerFelix Fietkau <nbd@nbd.name>2022-01-13 18:33:06 +0100
commit31b6cfb28890071acc0c044abf9c48843e4100ce (patch)
treeda99dedf2874afd3553a4fe6f2eb47c0630519fe /target/linux/generic/files
parentfde242159785f5831a9da80a1f88babb6a89cb05 (diff)
downloadupstream-31b6cfb28890071acc0c044abf9c48843e4100ce.tar.gz
upstream-31b6cfb28890071acc0c044abf9c48843e4100ce.tar.bz2
upstream-31b6cfb28890071acc0c044abf9c48843e4100ce.zip
kernel: mtk_bmt: extend debug interface
Add support for showing remapped blocks and garbage collecting old remapped blocks triggered by using the mark_good/mark_bad files Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'target/linux/generic/files')
-rw-r--r--target/linux/generic/files/drivers/mtd/nand/mtk_bmt.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/target/linux/generic/files/drivers/mtd/nand/mtk_bmt.c b/target/linux/generic/files/drivers/mtd/nand/mtk_bmt.c
index 2db31fe066..cb74b4d10f 100644
--- a/target/linux/generic/files/drivers/mtd/nand/mtk_bmt.c
+++ b/target/linux/generic/files/drivers/mtd/nand/mtk_bmt.c
@@ -672,8 +672,103 @@ static int mtk_bmt_debug_mark_bad(void *data, u64 val)
return 0;
}
+static unsigned long *
+mtk_bmt_get_mapping_mask(void)
+{
+ struct bbmt *bbmt = bmt_tbl(bmtd.bbt);
+ int main_blocks = bmtd.mtd->size >> bmtd.blk_shift;
+ unsigned long *used;
+ int i, k;
+
+ used = kcalloc(sizeof(unsigned long), BIT_WORD(bmtd.bmt_blk_idx) + 1, GFP_KERNEL);
+ if (!used)
+ return NULL;
+
+ for (i = 1; i < main_blocks; i++) {
+ if (bmtd.bbt->bb_tbl[i] == i)
+ continue;
+
+ for (k = 0; k < bmtd.bmt_blk_idx; k++) {
+ if (bmtd.bbt->bb_tbl[i] != bbmt[k].block)
+ continue;
+
+ set_bit(k, used);
+ break;
+ }
+ }
+
+ return used;
+}
+
+static int mtk_bmt_debug(void *data, u64 val)
+{
+ struct bbmt *bbmt = bmt_tbl(bmtd.bbt);
+ struct mtd_info *mtd = bmtd.mtd;
+ unsigned long *used;
+ int main_blocks = mtd->size >> bmtd.blk_shift;
+ int n_remap = 0;
+ int i;
+
+ used = mtk_bmt_get_mapping_mask();
+ if (!used)
+ return -ENOMEM;
+
+ switch (val) {
+ case 0:
+ for (i = 1; i < main_blocks; i++) {
+ if (bmtd.bbt->bb_tbl[i] == i)
+ continue;
+
+ printk("remap [%x->%x]\n", i, bmtd.bbt->bb_tbl[i]);
+ n_remap++;
+ }
+ for (i = 0; i <= bmtd.bmt_blk_idx; i++) {
+ char c;
+
+ switch (bbmt[i].mapped) {
+ case NO_MAPPED:
+ continue;
+ case NORMAL_MAPPED:
+ c = 'm';
+ if (test_bit(i, used))
+ c = 'M';
+ break;
+ case BMT_MAPPED:
+ c = 'B';
+ break;
+ default:
+ c = 'X';
+ break;
+ }
+ printk("[%x:%c] = 0x%x\n", i, c, bbmt[i].block);
+ }
+ break;
+ case 100:
+ for (i = 0; i <= bmtd.bmt_blk_idx; i++) {
+ if (bbmt[i].mapped != NORMAL_MAPPED)
+ continue;
+
+ if (test_bit(i, used))
+ continue;
+
+ n_remap++;
+ bbmt[i].mapped = NO_MAPPED;
+ printk("free block [%d:%x]\n", i, bbmt[i].block);
+ }
+ if (n_remap)
+ bmtd.bmt_blk_idx = upload_bmt(bmtd.bbt, bmtd.bmt_blk_idx);
+ break;
+ }
+
+ kfree(used);
+
+ return 0;
+}
+
+
DEFINE_DEBUGFS_ATTRIBUTE(fops_mark_good, NULL, mtk_bmt_debug_mark_good, "%llu\n");
DEFINE_DEBUGFS_ATTRIBUTE(fops_mark_bad, NULL, mtk_bmt_debug_mark_bad, "%llu\n");
+DEFINE_DEBUGFS_ATTRIBUTE(fops_debug, NULL, mtk_bmt_debug, "%llu\n");
static void
mtk_bmt_add_debugfs(void)
@@ -686,6 +781,7 @@ mtk_bmt_add_debugfs(void)
debugfs_create_file_unsafe("mark_good", S_IWUSR, dir, NULL, &fops_mark_good);
debugfs_create_file_unsafe("mark_bad", S_IWUSR, dir, NULL, &fops_mark_bad);
+ debugfs_create_file_unsafe("debug", S_IWUSR, dir, NULL, &fops_debug);
}
void mtk_bmt_detach(struct mtd_info *mtd)