aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/pending-4.9/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch
blob: 9299e886712401ce4418bd3eb97b509cd4c32de9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
Subject: [PATCH] mtd: bcm47xxpart: check for bad blocks when calculating offsets

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---

--- a/drivers/mtd/parsers/parser_trx.c
+++ b/drivers/mtd/parsers/parser_trx.c
@@ -29,6 +29,33 @@ struct trx_header {
 	uint32_t offset[3];
 } __packed;
 
+/*
+ * Calculate real end offset (address) for a given amount of data. It checks
+ * all blocks skipping bad ones.
+ */
+static size_t parser_trx_real_offset(struct mtd_info *mtd, size_t bytes)
+{
+	size_t real_offset = 0;
+
+	if (mtd_block_isbad(mtd, real_offset))
+		pr_warn("Base offset shouldn't be at bad block");
+
+	while (bytes >= mtd->erasesize) {
+		bytes -= mtd->erasesize;
+		real_offset += mtd->erasesize;
+		while (mtd_block_isbad(mtd, real_offset)) {
+			real_offset += mtd->erasesize;
+
+			if (real_offset >= mtd->size)
+				return real_offset - mtd->erasesize;
+		}
+	}
+
+	real_offset += bytes;
+
+	return real_offset;
+}
+
 static const char *parser_trx_data_part_name(struct mtd_info *master,
 					     size_t offset)
 {
@@ -83,21 +110,21 @@ static int parser_trx_parse(struct mtd_i
 	if (trx.offset[2]) {
 		part = &parts[curr_part++];
 		part->name = "loader";
-		part->offset = trx.offset[i];
+		part->offset = parser_trx_real_offset(mtd, trx.offset[i]);
 		i++;
 	}
 
 	if (trx.offset[i]) {
 		part = &parts[curr_part++];
 		part->name = "linux";
-		part->offset = trx.offset[i];
+		part->offset = parser_trx_real_offset(mtd, trx.offset[i]);
 		i++;
 	}
 
 	if (trx.offset[i]) {
 		part = &parts[curr_part++];
 		part->name = parser_trx_data_part_name(mtd, trx.offset[i]);
-		part->offset = trx.offset[i];
+		part->offset = parser_trx_real_offset(mtd, trx.offset[i]);
 		i++;
 	}
 
n> #define GL_MIFI_GPIO_LED_WLAN 1 #define GL_MIFI_GPIO_LED_NET 0 #define GL_MIFI_GPIO_LED_3GCONTROL 7 #define GL_MIFI_GPIO_BTN_RESET 11 #define GL_MIFI_KEYS_POLL_INTERVAL 20 /* msecs */ #define GL_MIFI_KEYS_DEBOUNCE_INTERVAL (3 * GL_MIFI_KEYS_POLL_INTERVAL) #define GL_MIFI_MAC0_OFFSET 0x0000 #define GL_MIFI_MAC1_OFFSET 0x0000 #define GL_MIFI_CALDATA_OFFSET 0x1000 #define GL_MIFI_WMAC_MAC_OFFSET 0x0000 static struct gpio_led gl_mifi_leds_gpio[] __initdata = { { .name = "gl-mifi:green:wan", .gpio = GL_MIFI_GPIO_LED_WAN, .active_low = 0, }, { .name = "gl-mifi:green:lan", .gpio = GL_MIFI_GPIO_LED_LAN, .active_low = 0, }, { .name = "gl-mifi:green:wlan", .gpio = GL_MIFI_GPIO_LED_WLAN, .active_low = 0, }, { .name = "gl-mifi:green:net", .gpio = GL_MIFI_GPIO_LED_NET, .active_low = 0, }, { .name = "gl-mifi:green:3gcontrol", .gpio = GL_MIFI_GPIO_LED_3GCONTROL, .active_low = 0, } }; static struct gpio_keys_button gl_mifi_gpio_keys[] __initdata = { { .desc = "reset", .type = EV_KEY, .code = KEY_RESTART, .debounce_interval = GL_MIFI_KEYS_DEBOUNCE_INTERVAL, .gpio = GL_MIFI_GPIO_BTN_RESET, .active_low = 0, }, }; static void __init gl_mifi_setup(void) { /* ART base address */ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ ath79_setup_ar933x_phy4_switch(false, false); /* register flash. */ ath79_register_m25p80(NULL); /* register gpio LEDs and keys */ ath79_register_leds_gpio(-1, ARRAY_SIZE(gl_mifi_leds_gpio), gl_mifi_leds_gpio); ath79_register_gpio_keys_polled(-1, GL_MIFI_KEYS_POLL_INTERVAL, ARRAY_SIZE(gl_mifi_gpio_keys), gl_mifi_gpio_keys); /* enable usb */ ath79_register_usb(); /* register eth0 as WAN, eth1 as LAN */ ath79_init_mac(ath79_eth0_data.mac_addr, art+GL_MIFI_MAC0_OFFSET, 0); ath79_init_mac(ath79_eth1_data.mac_addr, art+GL_MIFI_MAC1_OFFSET, 0); ath79_register_mdio(0, 0x0); ath79_register_eth(0); ath79_register_eth(1); /* register wireless mac with cal data */ ath79_register_wmac(art + GL_MIFI_CALDATA_OFFSET, art + GL_MIFI_WMAC_MAC_OFFSET); } MIPS_MACHINE(ATH79_MACH_GL_MIFI, "GL-MIFI", "GL.iNet GL-MIFI", gl_mifi_setup);