diff options
author | David S. Miller <davem@davemloft.net> | 2009-08-10 00:29:47 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-08-10 00:29:47 -0400 |
commit | f222e8b40f2177b1c4cac015b117744c1d3fa3e9 (patch) | |
tree | 7c5fc22c08da900e21b0e7ab2376e8e8e44a63c0 /drivers/mtd | |
parent | 819ae6a389d4acfab9a7bb874fa1977aa464d14b (diff) | |
parent | f4b9a988685da6386d7f9a72df3098bcc3270526 (diff) |
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/cmdlinepart.c | 2 | ||||
-rw-r--r-- | drivers/mtd/devices/m25p80.c | 2 | ||||
-rw-r--r-- | drivers/mtd/inftlcore.c | 11 | ||||
-rw-r--r-- | drivers/mtd/maps/Kconfig | 7 | ||||
-rw-r--r-- | drivers/mtd/maps/Makefile | 1 | ||||
-rw-r--r-- | drivers/mtd/maps/integrator-flash.c | 22 | ||||
-rw-r--r-- | drivers/mtd/maps/sbc8240.c | 250 | ||||
-rw-r--r-- | drivers/mtd/mtd_blkdevs.c | 6 | ||||
-rw-r--r-- | drivers/mtd/mtdblock.c | 16 | ||||
-rw-r--r-- | drivers/mtd/mtdcore.c | 7 | ||||
-rw-r--r-- | drivers/mtd/nand/atmel_nand.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/omap2.c | 7 | ||||
-rw-r--r-- | drivers/mtd/nftlcore.c | 16 | ||||
-rw-r--r-- | drivers/mtd/onenand/omap2.c | 3 | ||||
-rw-r--r-- | drivers/mtd/ubi/build.c | 6 | ||||
-rw-r--r-- | drivers/mtd/ubi/debug.c | 2 | ||||
-rw-r--r-- | drivers/mtd/ubi/debug.h | 7 | ||||
-rw-r--r-- | drivers/mtd/ubi/eba.c | 1 | ||||
-rw-r--r-- | drivers/mtd/ubi/gluebi.c | 1 | ||||
-rw-r--r-- | drivers/mtd/ubi/io.c | 157 | ||||
-rw-r--r-- | drivers/mtd/ubi/scan.c | 25 | ||||
-rw-r--r-- | drivers/mtd/ubi/scan.h | 2 | ||||
-rw-r--r-- | drivers/mtd/ubi/ubi-media.h | 12 | ||||
-rw-r--r-- | drivers/mtd/ubi/ubi.h | 6 | ||||
-rw-r--r-- | drivers/mtd/ubi/wl.c | 8 |
25 files changed, 189 insertions, 390 deletions
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c index 5011fa73f918..1479da6d3aa6 100644 --- a/drivers/mtd/cmdlinepart.c +++ b/drivers/mtd/cmdlinepart.c | |||
@@ -194,7 +194,7 @@ static struct mtd_partition * newpart(char *s, | |||
194 | parts[this_part].name = extra_mem; | 194 | parts[this_part].name = extra_mem; |
195 | extra_mem += name_len + 1; | 195 | extra_mem += name_len + 1; |
196 | 196 | ||
197 | dbg(("partition %d: name <%s>, offset %x, size %x, mask flags %x\n", | 197 | dbg(("partition %d: name <%s>, offset %llx, size %llx, mask flags %x\n", |
198 | this_part, | 198 | this_part, |
199 | parts[this_part].name, | 199 | parts[this_part].name, |
200 | parts[this_part].offset, | 200 | parts[this_part].offset, |
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 59c46126a5ce..ae5fe91867e1 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -54,7 +54,7 @@ | |||
54 | #define SR_SRWD 0x80 /* SR write protect */ | 54 | #define SR_SRWD 0x80 /* SR write protect */ |
55 | 55 | ||
56 | /* Define max times to check status register before we give up. */ | 56 | /* Define max times to check status register before we give up. */ |
57 | #define MAX_READY_WAIT_JIFFIES (10 * HZ) /* eg. M25P128 specs 6s max sector erase */ | 57 | #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ |
58 | #define CMD_SIZE 4 | 58 | #define CMD_SIZE 4 |
59 | 59 | ||
60 | #ifdef CONFIG_M25PXX_USE_FAST_READ | 60 | #ifdef CONFIG_M25PXX_USE_FAST_READ |
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c index 73f05227dc8c..d8cf29c01cc4 100644 --- a/drivers/mtd/inftlcore.c +++ b/drivers/mtd/inftlcore.c | |||
@@ -226,7 +226,7 @@ static u16 INFTL_findfreeblock(struct INFTLrecord *inftl, int desperate) | |||
226 | if (!desperate && inftl->numfreeEUNs < 2) { | 226 | if (!desperate && inftl->numfreeEUNs < 2) { |
227 | DEBUG(MTD_DEBUG_LEVEL1, "INFTL: there are too few free " | 227 | DEBUG(MTD_DEBUG_LEVEL1, "INFTL: there are too few free " |
228 | "EUNs (%d)\n", inftl->numfreeEUNs); | 228 | "EUNs (%d)\n", inftl->numfreeEUNs); |
229 | return 0xffff; | 229 | return BLOCK_NIL; |
230 | } | 230 | } |
231 | 231 | ||
232 | /* Scan for a free block */ | 232 | /* Scan for a free block */ |
@@ -281,7 +281,8 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned | |||
281 | silly = MAX_LOOPS; | 281 | silly = MAX_LOOPS; |
282 | while (thisEUN < inftl->nb_blocks) { | 282 | while (thisEUN < inftl->nb_blocks) { |
283 | for (block = 0; block < inftl->EraseSize/SECTORSIZE; block ++) { | 283 | for (block = 0; block < inftl->EraseSize/SECTORSIZE; block ++) { |
284 | if ((BlockMap[block] != 0xffff) || BlockDeleted[block]) | 284 | if ((BlockMap[block] != BLOCK_NIL) || |
285 | BlockDeleted[block]) | ||
285 | continue; | 286 | continue; |
286 | 287 | ||
287 | if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) | 288 | if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) |
@@ -525,7 +526,7 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block) | |||
525 | if (!silly--) { | 526 | if (!silly--) { |
526 | printk(KERN_WARNING "INFTL: infinite loop in " | 527 | printk(KERN_WARNING "INFTL: infinite loop in " |
527 | "Virtual Unit Chain 0x%x\n", thisVUC); | 528 | "Virtual Unit Chain 0x%x\n", thisVUC); |
528 | return 0xffff; | 529 | return BLOCK_NIL; |
529 | } | 530 | } |
530 | 531 | ||
531 | /* Skip to next block in chain */ | 532 | /* Skip to next block in chain */ |
@@ -549,7 +550,7 @@ hitused: | |||
549 | * waiting to be picked up. We're going to have to fold | 550 | * waiting to be picked up. We're going to have to fold |
550 | * a chain to make room. | 551 | * a chain to make room. |
551 | */ | 552 | */ |
552 | thisEUN = INFTL_makefreeblock(inftl, 0xffff); | 553 | thisEUN = INFTL_makefreeblock(inftl, BLOCK_NIL); |
553 | 554 | ||
554 | /* | 555 | /* |
555 | * Hopefully we free something, lets try again. | 556 | * Hopefully we free something, lets try again. |
@@ -631,7 +632,7 @@ hitused: | |||
631 | 632 | ||
632 | printk(KERN_WARNING "INFTL: error folding to make room for Virtual " | 633 | printk(KERN_WARNING "INFTL: error folding to make room for Virtual " |
633 | "Unit Chain 0x%x\n", thisVUC); | 634 | "Unit Chain 0x%x\n", thisVUC); |
634 | return 0xffff; | 635 | return BLOCK_NIL; |
635 | } | 636 | } |
636 | 637 | ||
637 | /* | 638 | /* |
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 0b98654d8eed..7a58bd5522fd 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig | |||
@@ -284,13 +284,6 @@ config MTD_L440GX | |||
284 | 284 | ||
285 | BE VERY CAREFUL. | 285 | BE VERY CAREFUL. |
286 | 286 | ||
287 | config MTD_SBC8240 | ||
288 | tristate "Flash device on SBC8240" | ||
289 | depends on MTD_JEDECPROBE && 8260 | ||
290 | help | ||
291 | Flash access on the SBC8240 board from Wind River. See | ||
292 | <http://www.windriver.com/products/sbc8240/> | ||
293 | |||
294 | config MTD_TQM8XXL | 287 | config MTD_TQM8XXL |
295 | tristate "CFI Flash device mapped on TQM8XXL" | 288 | tristate "CFI Flash device mapped on TQM8XXL" |
296 | depends on MTD_CFI && TQM8xxL | 289 | depends on MTD_CFI && TQM8xxL |
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index 8bae7f9850c0..5beb0662d724 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile | |||
@@ -50,7 +50,6 @@ obj-$(CONFIG_MTD_UCLINUX) += uclinux.o | |||
50 | obj-$(CONFIG_MTD_NETtel) += nettel.o | 50 | obj-$(CONFIG_MTD_NETtel) += nettel.o |
51 | obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o | 51 | obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o |
52 | obj-$(CONFIG_MTD_H720X) += h720x-flash.o | 52 | obj-$(CONFIG_MTD_H720X) += h720x-flash.o |
53 | obj-$(CONFIG_MTD_SBC8240) += sbc8240.o | ||
54 | obj-$(CONFIG_MTD_IXP4XX) += ixp4xx.o | 53 | obj-$(CONFIG_MTD_IXP4XX) += ixp4xx.o |
55 | obj-$(CONFIG_MTD_IXP2000) += ixp2000.o | 54 | obj-$(CONFIG_MTD_IXP2000) += ixp2000.o |
56 | obj-$(CONFIG_MTD_WRSBC8260) += wr_sbc82xx_flash.o | 55 | obj-$(CONFIG_MTD_WRSBC8260) += wr_sbc82xx_flash.o |
diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c index b08a798ee254..2aac41bde8b3 100644 --- a/drivers/mtd/maps/integrator-flash.c +++ b/drivers/mtd/maps/integrator-flash.c | |||
@@ -42,10 +42,8 @@ | |||
42 | #include <mach/hardware.h> | 42 | #include <mach/hardware.h> |
43 | #include <asm/system.h> | 43 | #include <asm/system.h> |
44 | 44 | ||
45 | #define SUBDEV_NAME_SIZE (BUS_ID_SIZE + 2) | ||
46 | |||
47 | struct armflash_subdev_info { | 45 | struct armflash_subdev_info { |
48 | char name[SUBDEV_NAME_SIZE]; | 46 | char *name; |
49 | struct mtd_info *mtd; | 47 | struct mtd_info *mtd; |
50 | struct map_info map; | 48 | struct map_info map; |
51 | struct flash_platform_data *plat; | 49 | struct flash_platform_data *plat; |
@@ -134,6 +132,8 @@ static void armflash_subdev_remove(struct armflash_subdev_info *subdev) | |||
134 | map_destroy(subdev->mtd); | 132 | map_destroy(subdev->mtd); |
135 | if (subdev->map.virt) | 133 | if (subdev->map.virt) |
136 | iounmap(subdev->map.virt); | 134 | iounmap(subdev->map.virt); |
135 | kfree(subdev->name); | ||
136 | subdev->name = NULL; | ||
137 | release_mem_region(subdev->map.phys, subdev->map.size); | 137 | release_mem_region(subdev->map.phys, subdev->map.size); |
138 | } | 138 | } |
139 | 139 | ||
@@ -177,16 +177,22 @@ static int armflash_probe(struct platform_device *dev) | |||
177 | 177 | ||
178 | if (nr == 1) | 178 | if (nr == 1) |
179 | /* No MTD concatenation, just use the default name */ | 179 | /* No MTD concatenation, just use the default name */ |
180 | snprintf(subdev->name, SUBDEV_NAME_SIZE, "%s", | 180 | subdev->name = kstrdup(dev_name(&dev->dev), GFP_KERNEL); |
181 | dev_name(&dev->dev)); | ||
182 | else | 181 | else |
183 | snprintf(subdev->name, SUBDEV_NAME_SIZE, "%s-%d", | 182 | subdev->name = kasprintf(GFP_KERNEL, "%s-%d", |
184 | dev_name(&dev->dev), i); | 183 | dev_name(&dev->dev), i); |
184 | if (!subdev->name) { | ||
185 | err = -ENOMEM; | ||
186 | break; | ||
187 | } | ||
185 | subdev->plat = plat; | 188 | subdev->plat = plat; |
186 | 189 | ||
187 | err = armflash_subdev_probe(subdev, res); | 190 | err = armflash_subdev_probe(subdev, res); |
188 | if (err) | 191 | if (err) { |
192 | kfree(subdev->name); | ||
193 | subdev->name = NULL; | ||
189 | break; | 194 | break; |
195 | } | ||
190 | } | 196 | } |
191 | info->nr_subdev = i; | 197 | info->nr_subdev = i; |
192 | 198 | ||
diff --git a/drivers/mtd/maps/sbc8240.c b/drivers/mtd/maps/sbc8240.c index d5374cdcb163..e69de29bb2d1 100644 --- a/drivers/mtd/maps/sbc8240.c +++ b/drivers/mtd/maps/sbc8240.c | |||
@@ -1,250 +0,0 @@ | |||
1 | /* | ||
2 | * Handle mapping of the flash memory access routines on the SBC8240 board. | ||
3 | * | ||
4 | * Carolyn Smith, Tektronix, Inc. | ||
5 | * | ||
6 | * This code is GPLed | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * The SBC8240 has 2 flash banks. | ||
11 | * Bank 0 is a 512 KiB AMD AM29F040B; 8 x 64 KiB sectors. | ||
12 | * It contains the U-Boot code (7 sectors) and the environment (1 sector). | ||
13 | * Bank 1 is 4 x 1 MiB AMD AM29LV800BT; 15 x 64 KiB sectors, 1 x 32 KiB sector, | ||
14 | * 2 x 8 KiB sectors, 1 x 16 KiB sectors. | ||
15 | * Both parts are JEDEC compatible. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/types.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <asm/io.h> | ||
22 | |||
23 | #include <linux/mtd/mtd.h> | ||
24 | #include <linux/mtd/map.h> | ||
25 | #include <linux/mtd/cfi.h> | ||
26 | |||
27 | #ifdef CONFIG_MTD_PARTITIONS | ||
28 | #include <linux/mtd/partitions.h> | ||
29 | #endif | ||
30 | |||
31 | #define DEBUG | ||
32 | |||
33 | #ifdef DEBUG | ||
34 | # define debugk(fmt,args...) printk(fmt ,##args) | ||
35 | #else | ||
36 | # define debugk(fmt,args...) | ||
37 | #endif | ||
38 | |||
39 | |||
40 | #define WINDOW_ADDR0 0xFFF00000 /* 512 KiB */ | ||
41 | #define WINDOW_SIZE0 0x00080000 | ||
42 | #define BUSWIDTH0 1 | ||
43 | |||
44 | #define WINDOW_ADDR1 0xFF000000 /* 4 MiB */ | ||
45 | #define WINDOW_SIZE1 0x00400000 | ||
46 | #define BUSWIDTH1 8 | ||
47 | |||
48 | #define MSG_PREFIX "sbc8240:" /* prefix for our printk()'s */ | ||
49 | #define MTDID "sbc8240-%d" /* for mtdparts= partitioning */ | ||
50 | |||
51 | |||
52 | static struct map_info sbc8240_map[2] = { | ||
53 | { | ||
54 | .name = "sbc8240 Flash Bank #0", | ||
55 | .size = WINDOW_SIZE0, | ||
56 | .bankwidth = BUSWIDTH0, | ||
57 | }, | ||
58 | { | ||
59 | .name = "sbc8240 Flash Bank #1", | ||
60 | .size = WINDOW_SIZE1, | ||
61 | .bankwidth = BUSWIDTH1, | ||
62 | } | ||
63 | }; | ||
64 | |||
65 | #define NUM_FLASH_BANKS ARRAY_SIZE(sbc8240_map) | ||
66 | |||
67 | /* | ||
68 | * The following defines the partition layout of SBC8240 boards. | ||
69 | * | ||
70 | * See include/linux/mtd/partitions.h for definition of the | ||
71 | * mtd_partition structure. | ||
72 | * | ||
73 | * The *_max_flash_size is the maximum possible mapped flash size | ||
74 | * which is not necessarily the actual flash size. It must correspond | ||
75 | * to the value specified in the mapping definition defined by the | ||
76 | * "struct map_desc *_io_desc" for the corresponding machine. | ||
77 | */ | ||
78 | |||
79 | #ifdef CONFIG_MTD_PARTITIONS | ||
80 | |||
81 | static struct mtd_partition sbc8240_uboot_partitions [] = { | ||
82 | /* Bank 0 */ | ||
83 | { | ||
84 | .name = "U-boot", /* U-Boot Firmware */ | ||
85 | .offset = 0, | ||
86 | .size = 0x00070000, /* 7 x 64 KiB sectors */ | ||
87 | .mask_flags = MTD_WRITEABLE, /* force read-only */ | ||
88 | }, | ||
89 | { | ||
90 | .name = "environment", /* U-Boot environment */ | ||
91 | .offset = 0x00070000, | ||
92 | .size = 0x00010000, /* 1 x 64 KiB sector */ | ||
93 | }, | ||
94 | }; | ||
95 | |||
96 | static struct mtd_partition sbc8240_fs_partitions [] = { | ||
97 | { | ||
98 | .name = "jffs", /* JFFS filesystem */ | ||
99 | .offset = 0, | ||
100 | .size = 0x003C0000, /* 4 * 15 * 64KiB */ | ||
101 | }, | ||
102 | { | ||
103 | .name = "tmp32", | ||
104 | .offset = 0x003C0000, | ||
105 | .size = 0x00020000, /* 4 * 32KiB */ | ||
106 | }, | ||
107 | { | ||
108 | .name = "tmp8a", | ||
109 | .offset = 0x003E0000, | ||
110 | .size = 0x00008000, /* 4 * 8KiB */ | ||
111 | }, | ||
112 | { | ||
113 | .name = "tmp8b", | ||
114 | .offset = 0x003E8000, | ||
115 | .size = 0x00008000, /* 4 * 8KiB */ | ||
116 | }, | ||
117 | { | ||
118 | .name = "tmp16", | ||
119 | .offset = 0x003F0000, | ||
120 | .size = 0x00010000, /* 4 * 16KiB */ | ||
121 | } | ||
122 | }; | ||
123 | |||
124 | /* trivial struct to describe partition information */ | ||
125 | struct mtd_part_def | ||
126 | { | ||
127 | int nums; | ||
128 | unsigned char *type; | ||
129 | struct mtd_partition* mtd_part; | ||
130 | }; | ||
131 | |||
132 | static struct mtd_info *sbc8240_mtd[NUM_FLASH_BANKS]; | ||
133 | static struct mtd_part_def sbc8240_part_banks[NUM_FLASH_BANKS]; | ||
134 | |||
135 | |||
136 | #endif /* CONFIG_MTD_PARTITIONS */ | ||
137 | |||
138 | |||
139 | static int __init init_sbc8240_mtd (void) | ||
140 | { | ||
141 | static struct _cjs { | ||
142 | u_long addr; | ||
143 | u_long size; | ||
144 | } pt[NUM_FLASH_BANKS] = { | ||
145 | { | ||
146 | .addr = WINDOW_ADDR0, | ||
147 | .size = WINDOW_SIZE0 | ||
148 | }, | ||
149 | { | ||
150 | .addr = WINDOW_ADDR1, | ||
151 | .size = WINDOW_SIZE1 | ||
152 | }, | ||
153 | }; | ||
154 | |||
155 | int devicesfound = 0; | ||
156 | int i,j; | ||
157 | |||
158 | for (i = 0; i < NUM_FLASH_BANKS; i++) { | ||
159 | printk (KERN_NOTICE MSG_PREFIX | ||
160 | "Probing 0x%08lx at 0x%08lx\n", pt[i].size, pt[i].addr); | ||
161 | |||
162 | sbc8240_map[i].map_priv_1 = | ||
163 | (unsigned long) ioremap (pt[i].addr, pt[i].size); | ||
164 | if (!sbc8240_map[i].map_priv_1) { | ||
165 | printk (MSG_PREFIX "failed to ioremap\n"); | ||
166 | for (j = 0; j < i; j++) { | ||
167 | iounmap((void *) sbc8240_map[j].map_priv_1); | ||
168 | sbc8240_map[j].map_priv_1 = 0; | ||
169 | } | ||
170 | return -EIO; | ||
171 | } | ||
172 | simple_map_init(&sbc8240_mtd[i]); | ||
173 | |||
174 | sbc8240_mtd[i] = do_map_probe("jedec_probe", &sbc8240_map[i]); | ||
175 | |||
176 | if (sbc8240_mtd[i]) { | ||
177 | sbc8240_mtd[i]->module = THIS_MODULE; | ||
178 | devicesfound++; | ||
179 | } else { | ||
180 | if (sbc8240_map[i].map_priv_1) { | ||
181 | iounmap((void *) sbc8240_map[i].map_priv_1); | ||
182 | sbc8240_map[i].map_priv_1 = 0; | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | |||
187 | if (!devicesfound) { | ||
188 | printk(KERN_NOTICE MSG_PREFIX | ||
189 | "No suppported flash chips found!\n"); | ||
190 | return -ENXIO; | ||
191 | } | ||
192 | |||
193 | #ifdef CONFIG_MTD_PARTITIONS | ||
194 | sbc8240_part_banks[0].mtd_part = sbc8240_uboot_partitions; | ||
195 | sbc8240_part_banks[0].type = "static image"; | ||
196 | sbc8240_part_banks[0].nums = ARRAY_SIZE(sbc8240_uboot_partitions); | ||
197 | sbc8240_part_banks[1].mtd_part = sbc8240_fs_partitions; | ||
198 | sbc8240_part_banks[1].type = "static file system"; | ||
199 | sbc8240_part_banks[1].nums = ARRAY_SIZE(sbc8240_fs_partitions); | ||
200 | |||
201 | for (i = 0; i < NUM_FLASH_BANKS; i++) { | ||
202 | |||
203 | if (!sbc8240_mtd[i]) continue; | ||
204 | if (sbc8240_part_banks[i].nums == 0) { | ||
205 | printk (KERN_NOTICE MSG_PREFIX | ||
206 | "No partition info available, registering whole device\n"); | ||
207 | add_mtd_device(sbc8240_mtd[i]); | ||
208 | } else { | ||
209 | printk (KERN_NOTICE MSG_PREFIX | ||
210 | "Using %s partition definition\n", sbc8240_part_banks[i].mtd_part->name); | ||
211 | add_mtd_partitions (sbc8240_mtd[i], | ||
212 | sbc8240_part_banks[i].mtd_part, | ||
213 | sbc8240_part_banks[i].nums); | ||
214 | } | ||
215 | } | ||
216 | #else | ||
217 | printk(KERN_NOTICE MSG_PREFIX | ||
218 | "Registering %d flash banks at once\n", devicesfound); | ||
219 | |||
220 | for (i = 0; i < devicesfound; i++) { | ||
221 | add_mtd_device(sbc8240_mtd[i]); | ||
222 | } | ||
223 | #endif /* CONFIG_MTD_PARTITIONS */ | ||
224 | |||
225 | return devicesfound == 0 ? -ENXIO : 0; | ||
226 | } | ||
227 | |||
228 | static void __exit cleanup_sbc8240_mtd (void) | ||
229 | { | ||
230 | int i; | ||
231 | |||
232 | for (i = 0; i < NUM_FLASH_BANKS; i++) { | ||
233 | if (sbc8240_mtd[i]) { | ||
234 | del_mtd_device (sbc8240_mtd[i]); | ||
235 | map_destroy (sbc8240_mtd[i]); | ||
236 | } | ||
237 | if (sbc8240_map[i].map_priv_1) { | ||
238 | iounmap ((void *) sbc8240_map[i].map_priv_1); | ||
239 | sbc8240_map[i].map_priv_1 = 0; | ||
240 | } | ||
241 | } | ||
242 | } | ||
243 | |||
244 | module_init (init_sbc8240_mtd); | ||
245 | module_exit (cleanup_sbc8240_mtd); | ||
246 | |||
247 | MODULE_LICENSE ("GPL"); | ||
248 | MODULE_AUTHOR ("Carolyn Smith <carolyn.smith@tektronix.com>"); | ||
249 | MODULE_DESCRIPTION ("MTD map driver for SBC8240 boards"); | ||
250 | |||
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index c3f62654b6df..7baba40c1ed2 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c | |||
@@ -144,7 +144,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode) | |||
144 | struct mtd_blktrans_ops *tr = dev->tr; | 144 | struct mtd_blktrans_ops *tr = dev->tr; |
145 | int ret = -ENODEV; | 145 | int ret = -ENODEV; |
146 | 146 | ||
147 | if (!try_module_get(dev->mtd->owner)) | 147 | if (!get_mtd_device(NULL, dev->mtd->index)) |
148 | goto out; | 148 | goto out; |
149 | 149 | ||
150 | if (!try_module_get(tr->owner)) | 150 | if (!try_module_get(tr->owner)) |
@@ -158,7 +158,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode) | |||
158 | ret = 0; | 158 | ret = 0; |
159 | if (tr->open && (ret = tr->open(dev))) { | 159 | if (tr->open && (ret = tr->open(dev))) { |
160 | dev->mtd->usecount--; | 160 | dev->mtd->usecount--; |
161 | module_put(dev->mtd->owner); | 161 | put_mtd_device(dev->mtd); |
162 | out_tr: | 162 | out_tr: |
163 | module_put(tr->owner); | 163 | module_put(tr->owner); |
164 | } | 164 | } |
@@ -177,7 +177,7 @@ static int blktrans_release(struct gendisk *disk, fmode_t mode) | |||
177 | 177 | ||
178 | if (!ret) { | 178 | if (!ret) { |
179 | dev->mtd->usecount--; | 179 | dev->mtd->usecount--; |
180 | module_put(dev->mtd->owner); | 180 | put_mtd_device(dev->mtd); |
181 | module_put(tr->owner); | 181 | module_put(tr->owner); |
182 | } | 182 | } |
183 | 183 | ||
diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c index 208c6faa0358..77db5ce24d92 100644 --- a/drivers/mtd/mtdblock.c +++ b/drivers/mtd/mtdblock.c | |||
@@ -29,6 +29,8 @@ static struct mtdblk_dev { | |||
29 | enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state; | 29 | enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state; |
30 | } *mtdblks[MAX_MTD_DEVICES]; | 30 | } *mtdblks[MAX_MTD_DEVICES]; |
31 | 31 | ||
32 | static struct mutex mtdblks_lock; | ||
33 | |||
32 | /* | 34 | /* |
33 | * Cache stuff... | 35 | * Cache stuff... |
34 | * | 36 | * |
@@ -270,15 +272,19 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd) | |||
270 | 272 | ||
271 | DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n"); | 273 | DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n"); |
272 | 274 | ||
275 | mutex_lock(&mtdblks_lock); | ||
273 | if (mtdblks[dev]) { | 276 | if (mtdblks[dev]) { |
274 | mtdblks[dev]->count++; | 277 | mtdblks[dev]->count++; |
278 | mutex_unlock(&mtdblks_lock); | ||
275 | return 0; | 279 | return 0; |
276 | } | 280 | } |
277 | 281 | ||
278 | /* OK, it's not open. Create cache info for it */ | 282 | /* OK, it's not open. Create cache info for it */ |
279 | mtdblk = kzalloc(sizeof(struct mtdblk_dev), GFP_KERNEL); | 283 | mtdblk = kzalloc(sizeof(struct mtdblk_dev), GFP_KERNEL); |
280 | if (!mtdblk) | 284 | if (!mtdblk) { |
285 | mutex_unlock(&mtdblks_lock); | ||
281 | return -ENOMEM; | 286 | return -ENOMEM; |
287 | } | ||
282 | 288 | ||
283 | mtdblk->count = 1; | 289 | mtdblk->count = 1; |
284 | mtdblk->mtd = mtd; | 290 | mtdblk->mtd = mtd; |
@@ -291,6 +297,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd) | |||
291 | } | 297 | } |
292 | 298 | ||
293 | mtdblks[dev] = mtdblk; | 299 | mtdblks[dev] = mtdblk; |
300 | mutex_unlock(&mtdblks_lock); | ||
294 | 301 | ||
295 | DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); | 302 | DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); |
296 | 303 | ||
@@ -304,6 +311,8 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd) | |||
304 | 311 | ||
305 | DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n"); | 312 | DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n"); |
306 | 313 | ||
314 | mutex_lock(&mtdblks_lock); | ||
315 | |||
307 | mutex_lock(&mtdblk->cache_mutex); | 316 | mutex_lock(&mtdblk->cache_mutex); |
308 | write_cached_data(mtdblk); | 317 | write_cached_data(mtdblk); |
309 | mutex_unlock(&mtdblk->cache_mutex); | 318 | mutex_unlock(&mtdblk->cache_mutex); |
@@ -316,6 +325,9 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd) | |||
316 | vfree(mtdblk->cache_data); | 325 | vfree(mtdblk->cache_data); |
317 | kfree(mtdblk); | 326 | kfree(mtdblk); |
318 | } | 327 | } |
328 | |||
329 | mutex_unlock(&mtdblks_lock); | ||
330 | |||
319 | DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); | 331 | DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); |
320 | 332 | ||
321 | return 0; | 333 | return 0; |
@@ -376,6 +388,8 @@ static struct mtd_blktrans_ops mtdblock_tr = { | |||
376 | 388 | ||
377 | static int __init init_mtdblock(void) | 389 | static int __init init_mtdblock(void) |
378 | { | 390 | { |
391 | mutex_init(&mtdblks_lock); | ||
392 | |||
379 | return register_mtd_blktrans(&mtdblock_tr); | 393 | return register_mtd_blktrans(&mtdblock_tr); |
380 | } | 394 | } |
381 | 395 | ||
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index fac54a3fa3f1..00ebf7af7467 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c | |||
@@ -65,8 +65,8 @@ static void mtd_release(struct device *dev) | |||
65 | static int mtd_cls_suspend(struct device *dev, pm_message_t state) | 65 | static int mtd_cls_suspend(struct device *dev, pm_message_t state) |
66 | { | 66 | { |
67 | struct mtd_info *mtd = dev_to_mtd(dev); | 67 | struct mtd_info *mtd = dev_to_mtd(dev); |
68 | 68 | ||
69 | if (mtd->suspend) | 69 | if (mtd && mtd->suspend) |
70 | return mtd->suspend(mtd); | 70 | return mtd->suspend(mtd); |
71 | else | 71 | else |
72 | return 0; | 72 | return 0; |
@@ -76,7 +76,7 @@ static int mtd_cls_resume(struct device *dev) | |||
76 | { | 76 | { |
77 | struct mtd_info *mtd = dev_to_mtd(dev); | 77 | struct mtd_info *mtd = dev_to_mtd(dev); |
78 | 78 | ||
79 | if (mtd->resume) | 79 | if (mtd && mtd->resume) |
80 | mtd->resume(mtd); | 80 | mtd->resume(mtd); |
81 | return 0; | 81 | return 0; |
82 | } | 82 | } |
@@ -298,6 +298,7 @@ int add_mtd_device(struct mtd_info *mtd) | |||
298 | mtd->dev.class = &mtd_class; | 298 | mtd->dev.class = &mtd_class; |
299 | mtd->dev.devt = MTD_DEVT(i); | 299 | mtd->dev.devt = MTD_DEVT(i); |
300 | dev_set_name(&mtd->dev, "mtd%d", i); | 300 | dev_set_name(&mtd->dev, "mtd%d", i); |
301 | dev_set_drvdata(&mtd->dev, mtd); | ||
301 | if (device_register(&mtd->dev) != 0) { | 302 | if (device_register(&mtd->dev) != 0) { |
302 | mtd_table[i] = NULL; | 303 | mtd_table[i] = NULL; |
303 | break; | 304 | break; |
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 2802992b39da..20c828ba9405 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c | |||
@@ -534,7 +534,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
534 | &num_partitions); | 534 | &num_partitions); |
535 | 535 | ||
536 | if ((!partitions) || (num_partitions == 0)) { | 536 | if ((!partitions) || (num_partitions == 0)) { |
537 | printk(KERN_ERR "atmel_nand: No parititions defined, or unsupported device.\n"); | 537 | printk(KERN_ERR "atmel_nand: No partitions defined, or unsupported device.\n"); |
538 | res = ENXIO; | 538 | res = ENXIO; |
539 | goto err_no_partitions; | 539 | goto err_no_partitions; |
540 | } | 540 | } |
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 0cd76f89f4b0..ebd07e95b814 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c | |||
@@ -11,6 +11,8 @@ | |||
11 | #include <linux/platform_device.h> | 11 | #include <linux/platform_device.h> |
12 | #include <linux/dma-mapping.h> | 12 | #include <linux/dma-mapping.h> |
13 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
14 | #include <linux/jiffies.h> | ||
15 | #include <linux/sched.h> | ||
14 | #include <linux/mtd/mtd.h> | 16 | #include <linux/mtd/mtd.h> |
15 | #include <linux/mtd/nand.h> | 17 | #include <linux/mtd/nand.h> |
16 | #include <linux/mtd/partitions.h> | 18 | #include <linux/mtd/partitions.h> |
@@ -541,7 +543,7 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
541 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | 543 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, |
542 | mtd); | 544 | mtd); |
543 | unsigned long timeo = jiffies; | 545 | unsigned long timeo = jiffies; |
544 | int status, state = this->state; | 546 | int status = NAND_STATUS_FAIL, state = this->state; |
545 | 547 | ||
546 | if (state == FL_ERASING) | 548 | if (state == FL_ERASING) |
547 | timeo += (HZ * 400) / 1000; | 549 | timeo += (HZ * 400) / 1000; |
@@ -556,8 +558,9 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
556 | 558 | ||
557 | while (time_before(jiffies, timeo)) { | 559 | while (time_before(jiffies, timeo)) { |
558 | status = __raw_readb(this->IO_ADDR_R); | 560 | status = __raw_readb(this->IO_ADDR_R); |
559 | if (!(status & 0x40)) | 561 | if (status & NAND_STATUS_READY) |
560 | break; | 562 | break; |
563 | cond_resched(); | ||
561 | } | 564 | } |
562 | return status; | 565 | return status; |
563 | } | 566 | } |
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index e3f8495a94c2..fb86cacd5bdb 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c | |||
@@ -208,7 +208,7 @@ static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate ) | |||
208 | /* Normally, we force a fold to happen before we run out of free blocks completely */ | 208 | /* Normally, we force a fold to happen before we run out of free blocks completely */ |
209 | if (!desperate && nftl->numfreeEUNs < 2) { | 209 | if (!desperate && nftl->numfreeEUNs < 2) { |
210 | DEBUG(MTD_DEBUG_LEVEL1, "NFTL_findfreeblock: there are too few free EUNs\n"); | 210 | DEBUG(MTD_DEBUG_LEVEL1, "NFTL_findfreeblock: there are too few free EUNs\n"); |
211 | return 0xffff; | 211 | return BLOCK_NIL; |
212 | } | 212 | } |
213 | 213 | ||
214 | /* Scan for a free block */ | 214 | /* Scan for a free block */ |
@@ -230,11 +230,11 @@ static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate ) | |||
230 | printk("Argh! No free blocks found! LastFreeEUN = %d, " | 230 | printk("Argh! No free blocks found! LastFreeEUN = %d, " |
231 | "FirstEUN = %d\n", nftl->LastFreeEUN, | 231 | "FirstEUN = %d\n", nftl->LastFreeEUN, |
232 | le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN)); | 232 | le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN)); |
233 | return 0xffff; | 233 | return BLOCK_NIL; |
234 | } | 234 | } |
235 | } while (pot != nftl->LastFreeEUN); | 235 | } while (pot != nftl->LastFreeEUN); |
236 | 236 | ||
237 | return 0xffff; | 237 | return BLOCK_NIL; |
238 | } | 238 | } |
239 | 239 | ||
240 | static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock ) | 240 | static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock ) |
@@ -431,7 +431,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p | |||
431 | 431 | ||
432 | /* add the header so that it is now a valid chain */ | 432 | /* add the header so that it is now a valid chain */ |
433 | oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); | 433 | oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); |
434 | oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff; | 434 | oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = BLOCK_NIL; |
435 | 435 | ||
436 | nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 8, | 436 | nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 8, |
437 | 8, &retlen, (char *)&oob.u); | 437 | 8, &retlen, (char *)&oob.u); |
@@ -515,7 +515,7 @@ static u16 NFTL_makefreeblock( struct NFTLrecord *nftl , unsigned pendingblock) | |||
515 | if (ChainLength < 2) { | 515 | if (ChainLength < 2) { |
516 | printk(KERN_WARNING "No Virtual Unit Chains available for folding. " | 516 | printk(KERN_WARNING "No Virtual Unit Chains available for folding. " |
517 | "Failing request\n"); | 517 | "Failing request\n"); |
518 | return 0xffff; | 518 | return BLOCK_NIL; |
519 | } | 519 | } |
520 | 520 | ||
521 | return NFTL_foldchain (nftl, LongestChain, pendingblock); | 521 | return NFTL_foldchain (nftl, LongestChain, pendingblock); |
@@ -578,7 +578,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) | |||
578 | printk(KERN_WARNING | 578 | printk(KERN_WARNING |
579 | "Infinite loop in Virtual Unit Chain 0x%x\n", | 579 | "Infinite loop in Virtual Unit Chain 0x%x\n", |
580 | thisVUC); | 580 | thisVUC); |
581 | return 0xffff; | 581 | return BLOCK_NIL; |
582 | } | 582 | } |
583 | 583 | ||
584 | /* Skip to next block in chain */ | 584 | /* Skip to next block in chain */ |
@@ -601,7 +601,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) | |||
601 | //u16 startEUN = nftl->EUNtable[thisVUC]; | 601 | //u16 startEUN = nftl->EUNtable[thisVUC]; |
602 | 602 | ||
603 | //printk("Write to VirtualUnitChain %d, calling makefreeblock()\n", thisVUC); | 603 | //printk("Write to VirtualUnitChain %d, calling makefreeblock()\n", thisVUC); |
604 | writeEUN = NFTL_makefreeblock(nftl, 0xffff); | 604 | writeEUN = NFTL_makefreeblock(nftl, BLOCK_NIL); |
605 | 605 | ||
606 | if (writeEUN == BLOCK_NIL) { | 606 | if (writeEUN == BLOCK_NIL) { |
607 | /* OK, we accept that the above comment is | 607 | /* OK, we accept that the above comment is |
@@ -673,7 +673,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) | |||
673 | 673 | ||
674 | printk(KERN_WARNING "Error folding to make room for Virtual Unit Chain 0x%x\n", | 674 | printk(KERN_WARNING "Error folding to make room for Virtual Unit Chain 0x%x\n", |
675 | thisVUC); | 675 | thisVUC); |
676 | return 0xffff; | 676 | return BLOCK_NIL; |
677 | } | 677 | } |
678 | 678 | ||
679 | static int nftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block, | 679 | static int nftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block, |
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index 38d656b9b2ee..0108ed42e877 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c | |||
@@ -266,7 +266,7 @@ static inline int omap2_onenand_bufferram_offset(struct mtd_info *mtd, int area) | |||
266 | 266 | ||
267 | if (ONENAND_CURRENT_BUFFERRAM(this)) { | 267 | if (ONENAND_CURRENT_BUFFERRAM(this)) { |
268 | if (area == ONENAND_DATARAM) | 268 | if (area == ONENAND_DATARAM) |
269 | return mtd->writesize; | 269 | return this->writesize; |
270 | if (area == ONENAND_SPARERAM) | 270 | if (area == ONENAND_SPARERAM) |
271 | return mtd->oobsize; | 271 | return mtd->oobsize; |
272 | } | 272 | } |
@@ -770,6 +770,7 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev) | |||
770 | } | 770 | } |
771 | iounmap(c->onenand.base); | 771 | iounmap(c->onenand.base); |
772 | release_mem_region(c->phys_base, ONENAND_IO_SIZE); | 772 | release_mem_region(c->phys_base, ONENAND_IO_SIZE); |
773 | gpmc_cs_free(c->gpmc_cs); | ||
773 | kfree(c); | 774 | kfree(c); |
774 | 775 | ||
775 | return 0; | 776 | return 0; |
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 286ed594e5a0..e1f7d0a78b9d 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c | |||
@@ -657,6 +657,11 @@ static int io_init(struct ubi_device *ubi) | |||
657 | if (ubi->mtd->block_isbad && ubi->mtd->block_markbad) | 657 | if (ubi->mtd->block_isbad && ubi->mtd->block_markbad) |
658 | ubi->bad_allowed = 1; | 658 | ubi->bad_allowed = 1; |
659 | 659 | ||
660 | if (ubi->mtd->type == MTD_NORFLASH) { | ||
661 | ubi_assert(ubi->mtd->writesize == 1); | ||
662 | ubi->nor_flash = 1; | ||
663 | } | ||
664 | |||
660 | ubi->min_io_size = ubi->mtd->writesize; | 665 | ubi->min_io_size = ubi->mtd->writesize; |
661 | ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft; | 666 | ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft; |
662 | 667 | ||
@@ -996,6 +1001,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) | |||
996 | ubi_msg("number of PEBs reserved for bad PEB handling: %d", | 1001 | ubi_msg("number of PEBs reserved for bad PEB handling: %d", |
997 | ubi->beb_rsvd_pebs); | 1002 | ubi->beb_rsvd_pebs); |
998 | ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec); | 1003 | ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec); |
1004 | ubi_msg("image sequence number: %d", ubi->image_seq); | ||
999 | 1005 | ||
1000 | /* | 1006 | /* |
1001 | * The below lock makes sure we do not race with 'ubi_thread()' which | 1007 | * The below lock makes sure we do not race with 'ubi_thread()' which |
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c index c0ed60e8ade9..54b0186915fb 100644 --- a/drivers/mtd/ubi/debug.c +++ b/drivers/mtd/ubi/debug.c | |||
@@ -44,6 +44,8 @@ void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr) | |||
44 | be32_to_cpu(ec_hdr->vid_hdr_offset)); | 44 | be32_to_cpu(ec_hdr->vid_hdr_offset)); |
45 | printk(KERN_DEBUG "\tdata_offset %d\n", | 45 | printk(KERN_DEBUG "\tdata_offset %d\n", |
46 | be32_to_cpu(ec_hdr->data_offset)); | 46 | be32_to_cpu(ec_hdr->data_offset)); |
47 | printk(KERN_DEBUG "\timage_seq %d\n", | ||
48 | be32_to_cpu(ec_hdr->image_seq)); | ||
47 | printk(KERN_DEBUG "\thdr_crc %#08x\n", | 49 | printk(KERN_DEBUG "\thdr_crc %#08x\n", |
48 | be32_to_cpu(ec_hdr->hdr_crc)); | 50 | be32_to_cpu(ec_hdr->hdr_crc)); |
49 | printk(KERN_DEBUG "erase counter header hexdump:\n"); | 51 | printk(KERN_DEBUG "erase counter header hexdump:\n"); |
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index 13777e5beac9..a4da7a09b949 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h | |||
@@ -93,6 +93,12 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req); | |||
93 | #define UBI_IO_DEBUG 0 | 93 | #define UBI_IO_DEBUG 0 |
94 | #endif | 94 | #endif |
95 | 95 | ||
96 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID | ||
97 | int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len); | ||
98 | #else | ||
99 | #define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0 | ||
100 | #endif | ||
101 | |||
96 | #ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT | 102 | #ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT |
97 | #define DBG_DISABLE_BGT 1 | 103 | #define DBG_DISABLE_BGT 1 |
98 | #else | 104 | #else |
@@ -167,6 +173,7 @@ static inline int ubi_dbg_is_erase_failure(void) | |||
167 | #define ubi_dbg_is_bitflip() 0 | 173 | #define ubi_dbg_is_bitflip() 0 |
168 | #define ubi_dbg_is_write_failure() 0 | 174 | #define ubi_dbg_is_write_failure() 0 |
169 | #define ubi_dbg_is_erase_failure() 0 | 175 | #define ubi_dbg_is_erase_failure() 0 |
176 | #define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0 | ||
170 | 177 | ||
171 | #endif /* !CONFIG_MTD_UBI_DEBUG */ | 178 | #endif /* !CONFIG_MTD_UBI_DEBUG */ |
172 | #endif /* !__UBI_DEBUG_H__ */ | 179 | #endif /* !__UBI_DEBUG_H__ */ |
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 0f2034c3ed2f..e4d9ef0c965a 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c | |||
@@ -1254,6 +1254,7 @@ out_free: | |||
1254 | if (!ubi->volumes[i]) | 1254 | if (!ubi->volumes[i]) |
1255 | continue; | 1255 | continue; |
1256 | kfree(ubi->volumes[i]->eba_tbl); | 1256 | kfree(ubi->volumes[i]->eba_tbl); |
1257 | ubi->volumes[i]->eba_tbl = NULL; | ||
1257 | } | 1258 | } |
1258 | return err; | 1259 | return err; |
1259 | } | 1260 | } |
diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c index 95aaac03f938..b5e478fa2661 100644 --- a/drivers/mtd/ubi/gluebi.c +++ b/drivers/mtd/ubi/gluebi.c | |||
@@ -332,6 +332,7 @@ static int gluebi_create(struct ubi_device_info *di, | |||
332 | } | 332 | } |
333 | 333 | ||
334 | gluebi->vol_id = vi->vol_id; | 334 | gluebi->vol_id = vi->vol_id; |
335 | gluebi->ubi_num = vi->ubi_num; | ||
335 | mtd->type = MTD_UBIVOLUME; | 336 | mtd->type = MTD_UBIVOLUME; |
336 | if (!di->ro_mode) | 337 | if (!di->ro_mode) |
337 | mtd->flags = MTD_WRITEABLE; | 338 | mtd->flags = MTD_WRITEABLE; |
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index effaff28bab1..4cb69925d8d9 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c | |||
@@ -98,17 +98,12 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum, | |||
98 | static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum); | 98 | static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum); |
99 | static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum, | 99 | static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum, |
100 | const struct ubi_vid_hdr *vid_hdr); | 100 | const struct ubi_vid_hdr *vid_hdr); |
101 | static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset, | ||
102 | int len); | ||
103 | static int paranoid_check_empty(struct ubi_device *ubi, int pnum); | ||
104 | #else | 101 | #else |
105 | #define paranoid_check_not_bad(ubi, pnum) 0 | 102 | #define paranoid_check_not_bad(ubi, pnum) 0 |
106 | #define paranoid_check_peb_ec_hdr(ubi, pnum) 0 | 103 | #define paranoid_check_peb_ec_hdr(ubi, pnum) 0 |
107 | #define paranoid_check_ec_hdr(ubi, pnum, ec_hdr) 0 | 104 | #define paranoid_check_ec_hdr(ubi, pnum, ec_hdr) 0 |
108 | #define paranoid_check_peb_vid_hdr(ubi, pnum) 0 | 105 | #define paranoid_check_peb_vid_hdr(ubi, pnum) 0 |
109 | #define paranoid_check_vid_hdr(ubi, pnum, vid_hdr) 0 | 106 | #define paranoid_check_vid_hdr(ubi, pnum, vid_hdr) 0 |
110 | #define paranoid_check_all_ff(ubi, pnum, offset, len) 0 | ||
111 | #define paranoid_check_empty(ubi, pnum) 0 | ||
112 | #endif | 107 | #endif |
113 | 108 | ||
114 | /** | 109 | /** |
@@ -244,7 +239,7 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, | |||
244 | return err > 0 ? -EINVAL : err; | 239 | return err > 0 ? -EINVAL : err; |
245 | 240 | ||
246 | /* The area we are writing to has to contain all 0xFF bytes */ | 241 | /* The area we are writing to has to contain all 0xFF bytes */ |
247 | err = paranoid_check_all_ff(ubi, pnum, offset, len); | 242 | err = ubi_dbg_check_all_ff(ubi, pnum, offset, len); |
248 | if (err) | 243 | if (err) |
249 | return err > 0 ? -EINVAL : err; | 244 | return err > 0 ? -EINVAL : err; |
250 | 245 | ||
@@ -271,8 +266,8 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, | |||
271 | addr = (loff_t)pnum * ubi->peb_size + offset; | 266 | addr = (loff_t)pnum * ubi->peb_size + offset; |
272 | err = ubi->mtd->write(ubi->mtd, addr, len, &written, buf); | 267 | err = ubi->mtd->write(ubi->mtd, addr, len, &written, buf); |
273 | if (err) { | 268 | if (err) { |
274 | ubi_err("error %d while writing %d bytes to PEB %d:%d, written" | 269 | ubi_err("error %d while writing %d bytes to PEB %d:%d, written " |
275 | " %zd bytes", err, len, pnum, offset, written); | 270 | "%zd bytes", err, len, pnum, offset, written); |
276 | ubi_dbg_dump_stack(); | 271 | ubi_dbg_dump_stack(); |
277 | } else | 272 | } else |
278 | ubi_assert(written == len); | 273 | ubi_assert(written == len); |
@@ -350,7 +345,7 @@ retry: | |||
350 | return -EIO; | 345 | return -EIO; |
351 | } | 346 | } |
352 | 347 | ||
353 | err = paranoid_check_all_ff(ubi, pnum, 0, ubi->peb_size); | 348 | err = ubi_dbg_check_all_ff(ubi, pnum, 0, ubi->peb_size); |
354 | if (err) | 349 | if (err) |
355 | return err > 0 ? -EINVAL : err; | 350 | return err > 0 ? -EINVAL : err; |
356 | 351 | ||
@@ -459,6 +454,54 @@ out: | |||
459 | } | 454 | } |
460 | 455 | ||
461 | /** | 456 | /** |
457 | * nor_erase_prepare - prepare a NOR flash PEB for erasure. | ||
458 | * @ubi: UBI device description object | ||
459 | * @pnum: physical eraseblock number to prepare | ||
460 | * | ||
461 | * NOR flash, or at least some of them, have peculiar embedded PEB erasure | ||
462 | * algorithm: the PEB is first filled with zeroes, then it is erased. And | ||
463 | * filling with zeroes starts from the end of the PEB. This was observed with | ||
464 | * Spansion S29GL512N NOR flash. | ||
465 | * | ||
466 | * This means that in case of a power cut we may end up with intact data at the | ||
467 | * beginning of the PEB, and all zeroes at the end of PEB. In other words, the | ||
468 | * EC and VID headers are OK, but a large chunk of data at the end of PEB is | ||
469 | * zeroed. This makes UBI mistakenly treat this PEB as used and associate it | ||
470 | * with an LEB, which leads to subsequent failures (e.g., UBIFS fails). | ||
471 | * | ||
472 | * This function is called before erasing NOR PEBs and it zeroes out EC and VID | ||
473 | * magic numbers in order to invalidate them and prevent the failures. Returns | ||
474 | * zero in case of success and a negative error code in case of failure. | ||
475 | */ | ||
476 | static int nor_erase_prepare(struct ubi_device *ubi, int pnum) | ||
477 | { | ||
478 | int err; | ||
479 | size_t written; | ||
480 | loff_t addr; | ||
481 | uint32_t data = 0; | ||
482 | |||
483 | addr = (loff_t)pnum * ubi->peb_size; | ||
484 | err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data); | ||
485 | if (err) { | ||
486 | ubi_err("error %d while writing 4 bytes to PEB %d:%d, written " | ||
487 | "%zd bytes", err, pnum, 0, written); | ||
488 | ubi_dbg_dump_stack(); | ||
489 | return err; | ||
490 | } | ||
491 | |||
492 | addr += ubi->vid_hdr_aloffset; | ||
493 | err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data); | ||
494 | if (err) { | ||
495 | ubi_err("error %d while writing 4 bytes to PEB %d:%d, written " | ||
496 | "%zd bytes", err, pnum, ubi->vid_hdr_aloffset, written); | ||
497 | ubi_dbg_dump_stack(); | ||
498 | return err; | ||
499 | } | ||
500 | |||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | /** | ||
462 | * ubi_io_sync_erase - synchronously erase a physical eraseblock. | 505 | * ubi_io_sync_erase - synchronously erase a physical eraseblock. |
463 | * @ubi: UBI device description object | 506 | * @ubi: UBI device description object |
464 | * @pnum: physical eraseblock number to erase | 507 | * @pnum: physical eraseblock number to erase |
@@ -489,6 +532,12 @@ int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture) | |||
489 | return -EROFS; | 532 | return -EROFS; |
490 | } | 533 | } |
491 | 534 | ||
535 | if (ubi->nor_flash) { | ||
536 | err = nor_erase_prepare(ubi, pnum); | ||
537 | if (err) | ||
538 | return err; | ||
539 | } | ||
540 | |||
492 | if (torture) { | 541 | if (torture) { |
493 | ret = torture_peb(ubi, pnum); | 542 | ret = torture_peb(ubi, pnum); |
494 | if (ret < 0) | 543 | if (ret < 0) |
@@ -672,11 +721,6 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, | |||
672 | if (read_err != -EBADMSG && | 721 | if (read_err != -EBADMSG && |
673 | check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) { | 722 | check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) { |
674 | /* The physical eraseblock is supposedly empty */ | 723 | /* The physical eraseblock is supposedly empty */ |
675 | err = paranoid_check_all_ff(ubi, pnum, 0, | ||
676 | ubi->peb_size); | ||
677 | if (err) | ||
678 | return err > 0 ? UBI_IO_BAD_EC_HDR : err; | ||
679 | |||
680 | if (verbose) | 724 | if (verbose) |
681 | ubi_warn("no EC header found at PEB %d, " | 725 | ubi_warn("no EC header found at PEB %d, " |
682 | "only 0xFF bytes", pnum); | 726 | "only 0xFF bytes", pnum); |
@@ -752,6 +796,7 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum, | |||
752 | ec_hdr->version = UBI_VERSION; | 796 | ec_hdr->version = UBI_VERSION; |
753 | ec_hdr->vid_hdr_offset = cpu_to_be32(ubi->vid_hdr_offset); | 797 | ec_hdr->vid_hdr_offset = cpu_to_be32(ubi->vid_hdr_offset); |
754 | ec_hdr->data_offset = cpu_to_be32(ubi->leb_start); | 798 | ec_hdr->data_offset = cpu_to_be32(ubi->leb_start); |
799 | ec_hdr->image_seq = cpu_to_be32(ubi->image_seq); | ||
755 | crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC); | 800 | crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC); |
756 | ec_hdr->hdr_crc = cpu_to_be32(crc); | 801 | ec_hdr->hdr_crc = cpu_to_be32(crc); |
757 | 802 | ||
@@ -947,15 +992,6 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, | |||
947 | if (read_err != -EBADMSG && | 992 | if (read_err != -EBADMSG && |
948 | check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) { | 993 | check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) { |
949 | /* The physical eraseblock is supposedly free */ | 994 | /* The physical eraseblock is supposedly free */ |
950 | |||
951 | /* | ||
952 | * The below is just a paranoid check, it has to be | ||
953 | * compiled out if paranoid checks are disabled. | ||
954 | */ | ||
955 | err = paranoid_check_empty(ubi, pnum); | ||
956 | if (err) | ||
957 | return err > 0 ? UBI_IO_BAD_VID_HDR : err; | ||
958 | |||
959 | if (verbose) | 995 | if (verbose) |
960 | ubi_warn("no VID header found at PEB %d, " | 996 | ubi_warn("no VID header found at PEB %d, " |
961 | "only 0xFF bytes", pnum); | 997 | "only 0xFF bytes", pnum); |
@@ -1229,7 +1265,7 @@ exit: | |||
1229 | } | 1265 | } |
1230 | 1266 | ||
1231 | /** | 1267 | /** |
1232 | * paranoid_check_all_ff - check that a region of flash is empty. | 1268 | * ubi_dbg_check_all_ff - check that a region of flash is empty. |
1233 | * @ubi: UBI device description object | 1269 | * @ubi: UBI device description object |
1234 | * @pnum: the physical eraseblock number to check | 1270 | * @pnum: the physical eraseblock number to check |
1235 | * @offset: the starting offset within the physical eraseblock to check | 1271 | * @offset: the starting offset within the physical eraseblock to check |
@@ -1239,8 +1275,7 @@ exit: | |||
1239 | * @offset of the physical eraseblock @pnum, %1 if not, and a negative error | 1275 | * @offset of the physical eraseblock @pnum, %1 if not, and a negative error |
1240 | * code if an error occurred. | 1276 | * code if an error occurred. |
1241 | */ | 1277 | */ |
1242 | static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset, | 1278 | int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) |
1243 | int len) | ||
1244 | { | 1279 | { |
1245 | size_t read; | 1280 | size_t read; |
1246 | int err; | 1281 | int err; |
@@ -1276,74 +1311,4 @@ error: | |||
1276 | return err; | 1311 | return err; |
1277 | } | 1312 | } |
1278 | 1313 | ||
1279 | /** | ||
1280 | * paranoid_check_empty - whether a PEB is empty. | ||
1281 | * @ubi: UBI device description object | ||
1282 | * @pnum: the physical eraseblock number to check | ||
1283 | * | ||
1284 | * This function makes sure PEB @pnum is empty, which means it contains only | ||
1285 | * %0xFF data bytes. Returns zero if the PEB is empty, %1 if not, and a | ||
1286 | * negative error code in case of failure. | ||
1287 | * | ||
1288 | * Empty PEBs have the EC header, and do not have the VID header. The caller of | ||
1289 | * this function should have already made sure the PEB does not have the VID | ||
1290 | * header. However, this function re-checks that, because it is possible that | ||
1291 | * the header and data has already been written to the PEB. | ||
1292 | * | ||
1293 | * Let's consider a possible scenario. Suppose there are 2 tasks - A and B. | ||
1294 | * Task A is in 'wear_leveling_worker()'. It is reading VID header of PEB X to | ||
1295 | * find which LEB it corresponds to. PEB X is currently unmapped, and has no | ||
1296 | * VID header. Task B is trying to write to PEB X. | ||
1297 | * | ||
1298 | * Task A: in 'ubi_io_read_vid_hdr()': reads the VID header from PEB X. The | ||
1299 | * read data contain all 0xFF bytes; | ||
1300 | * Task B: writes VID header and some data to PEB X; | ||
1301 | * Task A: assumes PEB X is empty, calls 'paranoid_check_empty()'. And if we | ||
1302 | * do not re-read the VID header, and do not cancel the checking if it | ||
1303 | * is there, we fail. | ||
1304 | */ | ||
1305 | static int paranoid_check_empty(struct ubi_device *ubi, int pnum) | ||
1306 | { | ||
1307 | int err, offs = ubi->vid_hdr_aloffset, len = ubi->vid_hdr_alsize; | ||
1308 | size_t read; | ||
1309 | uint32_t magic; | ||
1310 | const struct ubi_vid_hdr *vid_hdr; | ||
1311 | |||
1312 | mutex_lock(&ubi->dbg_buf_mutex); | ||
1313 | err = ubi->mtd->read(ubi->mtd, offs, len, &read, ubi->dbg_peb_buf); | ||
1314 | if (err && err != -EUCLEAN) { | ||
1315 | ubi_err("error %d while reading %d bytes from PEB %d:%d, " | ||
1316 | "read %zd bytes", err, len, pnum, offs, read); | ||
1317 | goto error; | ||
1318 | } | ||
1319 | |||
1320 | vid_hdr = ubi->dbg_peb_buf; | ||
1321 | magic = be32_to_cpu(vid_hdr->magic); | ||
1322 | if (magic == UBI_VID_HDR_MAGIC) | ||
1323 | /* The PEB contains VID header, so it is not empty */ | ||
1324 | goto out; | ||
1325 | |||
1326 | err = check_pattern(ubi->dbg_peb_buf, 0xFF, len); | ||
1327 | if (err == 0) { | ||
1328 | ubi_err("flash region at PEB %d:%d, length %d does not " | ||
1329 | "contain all 0xFF bytes", pnum, offs, len); | ||
1330 | goto fail; | ||
1331 | } | ||
1332 | |||
1333 | out: | ||
1334 | mutex_unlock(&ubi->dbg_buf_mutex); | ||
1335 | return 0; | ||
1336 | |||
1337 | fail: | ||
1338 | ubi_err("paranoid check failed for PEB %d", pnum); | ||
1339 | ubi_msg("hex dump of the %d-%d region", offs, offs + len); | ||
1340 | print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, | ||
1341 | ubi->dbg_peb_buf, len, 1); | ||
1342 | err = 1; | ||
1343 | error: | ||
1344 | ubi_dbg_dump_stack(); | ||
1345 | mutex_unlock(&ubi->dbg_buf_mutex); | ||
1346 | return err; | ||
1347 | } | ||
1348 | |||
1349 | #endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */ | 1314 | #endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */ |
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index c3d653ba5ca0..b847745394b4 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c | |||
@@ -757,6 +757,8 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, | |||
757 | si->is_empty = 0; | 757 | si->is_empty = 0; |
758 | 758 | ||
759 | if (!ec_corr) { | 759 | if (!ec_corr) { |
760 | int image_seq; | ||
761 | |||
760 | /* Make sure UBI version is OK */ | 762 | /* Make sure UBI version is OK */ |
761 | if (ech->version != UBI_VERSION) { | 763 | if (ech->version != UBI_VERSION) { |
762 | ubi_err("this UBI version is %d, image version is %d", | 764 | ubi_err("this UBI version is %d, image version is %d", |
@@ -778,6 +780,29 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, | |||
778 | ubi_dbg_dump_ec_hdr(ech); | 780 | ubi_dbg_dump_ec_hdr(ech); |
779 | return -EINVAL; | 781 | return -EINVAL; |
780 | } | 782 | } |
783 | |||
784 | /* | ||
785 | * Make sure that all PEBs have the same image sequence number. | ||
786 | * This allows us to detect situations when users flash UBI | ||
787 | * images incorrectly, so that the flash has the new UBI image | ||
788 | * and leftovers from the old one. This feature was added | ||
789 | * relatively recently, and the sequence number was always | ||
790 | * zero, because old UBI implementations always set it to zero. | ||
791 | * For this reasons, we do not panic if some PEBs have zero | ||
792 | * sequence number, while other PEBs have non-zero sequence | ||
793 | * number. | ||
794 | */ | ||
795 | image_seq = be32_to_cpu(ech->image_seq); | ||
796 | if (!si->image_seq_set) { | ||
797 | ubi->image_seq = image_seq; | ||
798 | si->image_seq_set = 1; | ||
799 | } else if (ubi->image_seq && ubi->image_seq != image_seq) { | ||
800 | ubi_err("bad image sequence number %d in PEB %d, " | ||
801 | "expected %d", image_seq, pnum, ubi->image_seq); | ||
802 | ubi_dbg_dump_ec_hdr(ech); | ||
803 | return -EINVAL; | ||
804 | } | ||
805 | |||
781 | } | 806 | } |
782 | 807 | ||
783 | /* OK, we've done with the EC header, let's look at the VID header */ | 808 | /* OK, we've done with the EC header, let's look at the VID header */ |
diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h index 61df208e2f20..1017cf12def5 100644 --- a/drivers/mtd/ubi/scan.h +++ b/drivers/mtd/ubi/scan.h | |||
@@ -102,6 +102,7 @@ struct ubi_scan_volume { | |||
102 | * @mean_ec: mean erase counter value | 102 | * @mean_ec: mean erase counter value |
103 | * @ec_sum: a temporary variable used when calculating @mean_ec | 103 | * @ec_sum: a temporary variable used when calculating @mean_ec |
104 | * @ec_count: a temporary variable used when calculating @mean_ec | 104 | * @ec_count: a temporary variable used when calculating @mean_ec |
105 | * @image_seq_set: indicates @ubi->image_seq is known | ||
105 | * | 106 | * |
106 | * This data structure contains the result of scanning and may be used by other | 107 | * This data structure contains the result of scanning and may be used by other |
107 | * UBI sub-systems to build final UBI data structures, further error-recovery | 108 | * UBI sub-systems to build final UBI data structures, further error-recovery |
@@ -124,6 +125,7 @@ struct ubi_scan_info { | |||
124 | int mean_ec; | 125 | int mean_ec; |
125 | uint64_t ec_sum; | 126 | uint64_t ec_sum; |
126 | int ec_count; | 127 | int ec_count; |
128 | int image_seq_set; | ||
127 | }; | 129 | }; |
128 | 130 | ||
129 | struct ubi_device; | 131 | struct ubi_device; |
diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h index 8419fdccc79c..503ea9b27309 100644 --- a/drivers/mtd/ubi/ubi-media.h +++ b/drivers/mtd/ubi/ubi-media.h | |||
@@ -129,6 +129,7 @@ enum { | |||
129 | * @ec: the erase counter | 129 | * @ec: the erase counter |
130 | * @vid_hdr_offset: where the VID header starts | 130 | * @vid_hdr_offset: where the VID header starts |
131 | * @data_offset: where the user data start | 131 | * @data_offset: where the user data start |
132 | * @image_seq: image sequence number | ||
132 | * @padding2: reserved for future, zeroes | 133 | * @padding2: reserved for future, zeroes |
133 | * @hdr_crc: erase counter header CRC checksum | 134 | * @hdr_crc: erase counter header CRC checksum |
134 | * | 135 | * |
@@ -144,6 +145,14 @@ enum { | |||
144 | * volume identifier header and user data, relative to the beginning of the | 145 | * volume identifier header and user data, relative to the beginning of the |
145 | * physical eraseblock. These values have to be the same for all physical | 146 | * physical eraseblock. These values have to be the same for all physical |
146 | * eraseblocks. | 147 | * eraseblocks. |
148 | * | ||
149 | * The @image_seq field is used to validate a UBI image that has been prepared | ||
150 | * for a UBI device. The @image_seq value can be any value, but it must be the | ||
151 | * same on all eraseblocks. UBI will ensure that all new erase counter headers | ||
152 | * also contain this value, and will check the value when scanning at start-up. | ||
153 | * One way to make use of @image_seq is to increase its value by one every time | ||
154 | * an image is flashed over an existing image, then, if the flashing does not | ||
155 | * complete, UBI will detect the error when scanning. | ||
147 | */ | 156 | */ |
148 | struct ubi_ec_hdr { | 157 | struct ubi_ec_hdr { |
149 | __be32 magic; | 158 | __be32 magic; |
@@ -152,7 +161,8 @@ struct ubi_ec_hdr { | |||
152 | __be64 ec; /* Warning: the current limit is 31-bit anyway! */ | 161 | __be64 ec; /* Warning: the current limit is 31-bit anyway! */ |
153 | __be32 vid_hdr_offset; | 162 | __be32 vid_hdr_offset; |
154 | __be32 data_offset; | 163 | __be32 data_offset; |
155 | __u8 padding2[36]; | 164 | __be32 image_seq; |
165 | __u8 padding2[32]; | ||
156 | __be32 hdr_crc; | 166 | __be32 hdr_crc; |
157 | } __attribute__ ((packed)); | 167 | } __attribute__ ((packed)); |
158 | 168 | ||
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 28acd133c997..6a5fe9633783 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h | |||
@@ -301,6 +301,7 @@ struct ubi_wl_entry; | |||
301 | * @vol->readers, @vol->writers, @vol->exclusive, | 301 | * @vol->readers, @vol->writers, @vol->exclusive, |
302 | * @vol->ref_count, @vol->mapping and @vol->eba_tbl. | 302 | * @vol->ref_count, @vol->mapping and @vol->eba_tbl. |
303 | * @ref_count: count of references on the UBI device | 303 | * @ref_count: count of references on the UBI device |
304 | * @image_seq: image sequence number recorded on EC headers | ||
304 | * | 305 | * |
305 | * @rsvd_pebs: count of reserved physical eraseblocks | 306 | * @rsvd_pebs: count of reserved physical eraseblocks |
306 | * @avail_pebs: count of available physical eraseblocks | 307 | * @avail_pebs: count of available physical eraseblocks |
@@ -372,6 +373,7 @@ struct ubi_wl_entry; | |||
372 | * @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset | 373 | * @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset |
373 | * @bad_allowed: whether the MTD device admits of bad physical eraseblocks or | 374 | * @bad_allowed: whether the MTD device admits of bad physical eraseblocks or |
374 | * not | 375 | * not |
376 | * @nor_flash: non-zero if working on top of NOR flash | ||
375 | * @mtd: MTD device descriptor | 377 | * @mtd: MTD device descriptor |
376 | * | 378 | * |
377 | * @peb_buf1: a buffer of PEB size used for different purposes | 379 | * @peb_buf1: a buffer of PEB size used for different purposes |
@@ -390,6 +392,7 @@ struct ubi_device { | |||
390 | struct ubi_volume *volumes[UBI_MAX_VOLUMES+UBI_INT_VOL_COUNT]; | 392 | struct ubi_volume *volumes[UBI_MAX_VOLUMES+UBI_INT_VOL_COUNT]; |
391 | spinlock_t volumes_lock; | 393 | spinlock_t volumes_lock; |
392 | int ref_count; | 394 | int ref_count; |
395 | int image_seq; | ||
393 | 396 | ||
394 | int rsvd_pebs; | 397 | int rsvd_pebs; |
395 | int avail_pebs; | 398 | int avail_pebs; |
@@ -452,7 +455,8 @@ struct ubi_device { | |||
452 | int vid_hdr_offset; | 455 | int vid_hdr_offset; |
453 | int vid_hdr_aloffset; | 456 | int vid_hdr_aloffset; |
454 | int vid_hdr_shift; | 457 | int vid_hdr_shift; |
455 | int bad_allowed; | 458 | unsigned int bad_allowed:1; |
459 | unsigned int nor_flash:1; | ||
456 | struct mtd_info *mtd; | 460 | struct mtd_info *mtd; |
457 | 461 | ||
458 | void *peb_buf1; | 462 | void *peb_buf1; |
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 2b2472300610..600c7229d5cf 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c | |||
@@ -459,6 +459,14 @@ retry: | |||
459 | dbg_wl("PEB %d EC %d", e->pnum, e->ec); | 459 | dbg_wl("PEB %d EC %d", e->pnum, e->ec); |
460 | prot_queue_add(ubi, e); | 460 | prot_queue_add(ubi, e); |
461 | spin_unlock(&ubi->wl_lock); | 461 | spin_unlock(&ubi->wl_lock); |
462 | |||
463 | err = ubi_dbg_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset, | ||
464 | ubi->peb_size - ubi->vid_hdr_aloffset); | ||
465 | if (err) { | ||
466 | ubi_err("new PEB %d does not contain all 0xFF bytes", e->pnum); | ||
467 | return err > 0 ? -EINVAL : err; | ||
468 | } | ||
469 | |||
462 | return e->pnum; | 470 | return e->pnum; |
463 | } | 471 | } |
464 | 472 | ||