diff options
Diffstat (limited to 'drivers/mtd')
40 files changed, 212 insertions, 1069 deletions
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig index 0f6bb2e625d8..a7ec5954caf5 100644 --- a/drivers/mtd/chips/Kconfig +++ b/drivers/mtd/chips/Kconfig | |||
@@ -200,27 +200,6 @@ config MTD_CFI_AMDSTD | |||
200 | provides support for one of those command sets, used on chips | 200 | provides support for one of those command sets, used on chips |
201 | including the AMD Am29LV320. | 201 | including the AMD Am29LV320. |
202 | 202 | ||
203 | config MTD_CFI_AMDSTD_RETRY | ||
204 | int "Retry failed commands (erase/program)" | ||
205 | depends on MTD_CFI_AMDSTD | ||
206 | default "0" | ||
207 | help | ||
208 | Some chips, when attached to a shared bus, don't properly filter | ||
209 | bus traffic that is destined to other devices. This broken | ||
210 | behavior causes erase and program sequences to be aborted when | ||
211 | the sequences are mixed with traffic for other devices. | ||
212 | |||
213 | SST49LF040 (and related) chips are know to be broken. | ||
214 | |||
215 | config MTD_CFI_AMDSTD_RETRY_MAX | ||
216 | int "Max retries of failed commands (erase/program)" | ||
217 | depends on MTD_CFI_AMDSTD_RETRY | ||
218 | default "0" | ||
219 | help | ||
220 | If you have an SST49LF040 (or related chip) then this value should | ||
221 | be set to at least 1. This can also be adjusted at driver load | ||
222 | time with the retry_cmd_max module parameter. | ||
223 | |||
224 | config MTD_CFI_STAA | 203 | config MTD_CFI_STAA |
225 | tristate "Support for ST (Advanced Architecture) flash chips" | 204 | tristate "Support for ST (Advanced Architecture) flash chips" |
226 | depends on MTD_GEN_PROBE | 205 | depends on MTD_GEN_PROBE |
diff --git a/drivers/mtd/chips/amd_flash.c b/drivers/mtd/chips/amd_flash.c index fdb91b6f1d97..57115618c496 100644 --- a/drivers/mtd/chips/amd_flash.c +++ b/drivers/mtd/chips/amd_flash.c | |||
@@ -664,7 +664,7 @@ static struct mtd_info *amd_flash_probe(struct map_info *map) | |||
664 | printk("%s: Probing for AMD compatible flash...\n", map->name); | 664 | printk("%s: Probing for AMD compatible flash...\n", map->name); |
665 | 665 | ||
666 | if ((table_pos[0] = probe_new_chip(mtd, 0, NULL, &temp, table, | 666 | if ((table_pos[0] = probe_new_chip(mtd, 0, NULL, &temp, table, |
667 | sizeof(table)/sizeof(table[0]))) | 667 | ARRAY_SIZE(table))) |
668 | == -1) { | 668 | == -1) { |
669 | printk(KERN_WARNING | 669 | printk(KERN_WARNING |
670 | "%s: Found no AMD compatible device at location zero\n", | 670 | "%s: Found no AMD compatible device at location zero\n", |
@@ -696,7 +696,7 @@ static struct mtd_info *amd_flash_probe(struct map_info *map) | |||
696 | base += (1 << temp.chipshift)) { | 696 | base += (1 << temp.chipshift)) { |
697 | int numchips = temp.numchips; | 697 | int numchips = temp.numchips; |
698 | table_pos[numchips] = probe_new_chip(mtd, base, chips, | 698 | table_pos[numchips] = probe_new_chip(mtd, base, chips, |
699 | &temp, table, sizeof(table)/sizeof(table[0])); | 699 | &temp, table, ARRAY_SIZE(table)); |
700 | } | 700 | } |
701 | 701 | ||
702 | mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) * | 702 | mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) * |
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index edb306c03c0a..517ea33e7260 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #define MANUFACTURER_MACRONIX 0x00C2 | 34 | #define MANUFACTURER_MACRONIX 0x00C2 |
35 | #define MANUFACTURER_NEC 0x0010 | 35 | #define MANUFACTURER_NEC 0x0010 |
36 | #define MANUFACTURER_PMC 0x009D | 36 | #define MANUFACTURER_PMC 0x009D |
37 | #define MANUFACTURER_SHARP 0x00b0 | ||
37 | #define MANUFACTURER_SST 0x00BF | 38 | #define MANUFACTURER_SST 0x00BF |
38 | #define MANUFACTURER_ST 0x0020 | 39 | #define MANUFACTURER_ST 0x0020 |
39 | #define MANUFACTURER_TOSHIBA 0x0098 | 40 | #define MANUFACTURER_TOSHIBA 0x0098 |
@@ -124,6 +125,9 @@ | |||
124 | #define PM49FL004 0x006E | 125 | #define PM49FL004 0x006E |
125 | #define PM49FL008 0x006A | 126 | #define PM49FL008 0x006A |
126 | 127 | ||
128 | /* Sharp */ | ||
129 | #define LH28F640BF 0x00b0 | ||
130 | |||
127 | /* ST - www.st.com */ | 131 | /* ST - www.st.com */ |
128 | #define M29W800DT 0x00D7 | 132 | #define M29W800DT 0x00D7 |
129 | #define M29W800DB 0x005B | 133 | #define M29W800DB 0x005B |
@@ -1267,6 +1271,19 @@ static const struct amd_flash_info jedec_table[] = { | |||
1267 | .regions = { | 1271 | .regions = { |
1268 | ERASEINFO( 0x01000, 256 ) | 1272 | ERASEINFO( 0x01000, 256 ) |
1269 | } | 1273 | } |
1274 | }, { | ||
1275 | .mfr_id = MANUFACTURER_SHARP, | ||
1276 | .dev_id = LH28F640BF, | ||
1277 | .name = "LH28F640BF", | ||
1278 | .uaddr = { | ||
1279 | [0] = MTD_UADDR_UNNECESSARY, /* x8 */ | ||
1280 | }, | ||
1281 | .DevSize = SIZE_4MiB, | ||
1282 | .CmdSet = P_ID_INTEL_STD, | ||
1283 | .NumEraseRegions= 1, | ||
1284 | .regions = { | ||
1285 | ERASEINFO(0x40000,16), | ||
1286 | } | ||
1270 | }, { | 1287 | }, { |
1271 | .mfr_id = MANUFACTURER_SST, | 1288 | .mfr_id = MANUFACTURER_SST, |
1272 | .dev_id = SST39LF512, | 1289 | .dev_id = SST39LF512, |
@@ -2035,7 +2052,7 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, | |||
2035 | DEBUG(MTD_DEBUG_LEVEL3, | 2052 | DEBUG(MTD_DEBUG_LEVEL3, |
2036 | "Search for id:(%02x %02x) interleave(%d) type(%d)\n", | 2053 | "Search for id:(%02x %02x) interleave(%d) type(%d)\n", |
2037 | cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type); | 2054 | cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type); |
2038 | for (i=0; i<sizeof(jedec_table)/sizeof(jedec_table[0]); i++) { | 2055 | for (i = 0; i < ARRAY_SIZE(jedec_table); i++) { |
2039 | if ( jedec_match( base, map, cfi, &jedec_table[i] ) ) { | 2056 | if ( jedec_match( base, map, cfi, &jedec_table[i] ) ) { |
2040 | DEBUG( MTD_DEBUG_LEVEL3, | 2057 | DEBUG( MTD_DEBUG_LEVEL3, |
2041 | "MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n", | 2058 | "MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n", |
diff --git a/drivers/mtd/chips/sharp.c b/drivers/mtd/chips/sharp.c index 36f61a6a766e..3cc0b23c5865 100644 --- a/drivers/mtd/chips/sharp.c +++ b/drivers/mtd/chips/sharp.c | |||
@@ -64,7 +64,7 @@ | |||
64 | 64 | ||
65 | #undef AUTOUNLOCK /* automatically unlocks blocks before erasing */ | 65 | #undef AUTOUNLOCK /* automatically unlocks blocks before erasing */ |
66 | 66 | ||
67 | struct mtd_info *sharp_probe(struct map_info *); | 67 | static struct mtd_info *sharp_probe(struct map_info *); |
68 | 68 | ||
69 | static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd); | 69 | static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd); |
70 | 70 | ||
@@ -96,7 +96,6 @@ struct sharp_info{ | |||
96 | struct flchip chips[1]; | 96 | struct flchip chips[1]; |
97 | }; | 97 | }; |
98 | 98 | ||
99 | struct mtd_info *sharp_probe(struct map_info *map); | ||
100 | static void sharp_destroy(struct mtd_info *mtd); | 99 | static void sharp_destroy(struct mtd_info *mtd); |
101 | 100 | ||
102 | static struct mtd_chip_driver sharp_chipdrv = { | 101 | static struct mtd_chip_driver sharp_chipdrv = { |
@@ -107,7 +106,7 @@ static struct mtd_chip_driver sharp_chipdrv = { | |||
107 | }; | 106 | }; |
108 | 107 | ||
109 | 108 | ||
110 | struct mtd_info *sharp_probe(struct map_info *map) | 109 | static struct mtd_info *sharp_probe(struct map_info *map) |
111 | { | 110 | { |
112 | struct mtd_info *mtd = NULL; | 111 | struct mtd_info *mtd = NULL; |
113 | struct sharp_info *sharp = NULL; | 112 | struct sharp_info *sharp = NULL; |
@@ -581,7 +580,7 @@ static void sharp_destroy(struct mtd_info *mtd) | |||
581 | 580 | ||
582 | } | 581 | } |
583 | 582 | ||
584 | int __init sharp_probe_init(void) | 583 | static int __init sharp_probe_init(void) |
585 | { | 584 | { |
586 | printk("MTD Sharp chip driver <ds@lineo.com>\n"); | 585 | printk("MTD Sharp chip driver <ds@lineo.com>\n"); |
587 | 586 | ||
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c index 6b8bb2e4dcfd..a7a7bfe33879 100644 --- a/drivers/mtd/cmdlinepart.c +++ b/drivers/mtd/cmdlinepart.c | |||
@@ -42,7 +42,8 @@ | |||
42 | 42 | ||
43 | 43 | ||
44 | /* special size referring to all the remaining space in a partition */ | 44 | /* special size referring to all the remaining space in a partition */ |
45 | #define SIZE_REMAINING 0xffffffff | 45 | #define SIZE_REMAINING UINT_MAX |
46 | #define OFFSET_CONTINUOUS UINT_MAX | ||
46 | 47 | ||
47 | struct cmdline_mtd_partition { | 48 | struct cmdline_mtd_partition { |
48 | struct cmdline_mtd_partition *next; | 49 | struct cmdline_mtd_partition *next; |
@@ -75,7 +76,7 @@ static struct mtd_partition * newpart(char *s, | |||
75 | { | 76 | { |
76 | struct mtd_partition *parts; | 77 | struct mtd_partition *parts; |
77 | unsigned long size; | 78 | unsigned long size; |
78 | unsigned long offset = 0; | 79 | unsigned long offset = OFFSET_CONTINUOUS; |
79 | char *name; | 80 | char *name; |
80 | int name_len; | 81 | int name_len; |
81 | unsigned char *extra_mem; | 82 | unsigned char *extra_mem; |
@@ -314,7 +315,7 @@ static int parse_cmdline_partitions(struct mtd_info *master, | |||
314 | { | 315 | { |
315 | for(i = 0, offset = 0; i < part->num_parts; i++) | 316 | for(i = 0, offset = 0; i < part->num_parts; i++) |
316 | { | 317 | { |
317 | if (!part->parts[i].offset) | 318 | if (part->parts[i].offset == OFFSET_CONTINUOUS) |
318 | part->parts[i].offset = offset; | 319 | part->parts[i].offset = offset; |
319 | else | 320 | else |
320 | offset = part->parts[i].offset; | 321 | offset = part->parts[i].offset; |
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index dd628cb51e31..7fac438b5c32 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig | |||
@@ -129,8 +129,8 @@ config MTDRAM_ABS_POS | |||
129 | allocating space from Linux's available memory. Otherwise, leave | 129 | allocating space from Linux's available memory. Otherwise, leave |
130 | this set to zero. Most people will want to leave this as zero. | 130 | this set to zero. Most people will want to leave this as zero. |
131 | 131 | ||
132 | config MTD_BLKMTD | 132 | config MTD_BLOCK2MTD |
133 | tristate "MTD emulation using block device" | 133 | tristate "MTD using block device" |
134 | depends on MTD | 134 | depends on MTD |
135 | help | 135 | help |
136 | This driver allows a block device to appear as an MTD. It would | 136 | This driver allows a block device to appear as an MTD. It would |
@@ -141,15 +141,6 @@ config MTD_BLKMTD | |||
141 | Testing MTD users (eg JFFS2) on large media and media that might | 141 | Testing MTD users (eg JFFS2) on large media and media that might |
142 | be removed during a write (using the floppy drive). | 142 | be removed during a write (using the floppy drive). |
143 | 143 | ||
144 | config MTD_BLOCK2MTD | ||
145 | tristate "MTD using block device (rewrite)" | ||
146 | depends on MTD && EXPERIMENTAL | ||
147 | help | ||
148 | This driver is basically the same at MTD_BLKMTD above, but | ||
149 | experienced some interface changes plus serious speedups. In | ||
150 | the long term, it should replace MTD_BLKMTD. Right now, you | ||
151 | shouldn't entrust important data to it yet. | ||
152 | |||
153 | comment "Disk-On-Chip Device Drivers" | 144 | comment "Disk-On-Chip Device Drivers" |
154 | 145 | ||
155 | config MTD_DOC2000 | 146 | config MTD_DOC2000 |
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index 7c5ed2178380..b6573670316f 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile | |||
@@ -21,7 +21,6 @@ obj-$(CONFIG_MTD_PMC551) += pmc551.o | |||
21 | obj-$(CONFIG_MTD_MS02NV) += ms02-nv.o | 21 | obj-$(CONFIG_MTD_MS02NV) += ms02-nv.o |
22 | obj-$(CONFIG_MTD_MTDRAM) += mtdram.o | 22 | obj-$(CONFIG_MTD_MTDRAM) += mtdram.o |
23 | obj-$(CONFIG_MTD_LART) += lart.o | 23 | obj-$(CONFIG_MTD_LART) += lart.o |
24 | obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o | ||
25 | obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o | 24 | obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o |
26 | obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o | 25 | obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o |
27 | obj-$(CONFIG_MTD_M25P80) += m25p80.o | 26 | obj-$(CONFIG_MTD_M25P80) += m25p80.o |
diff --git a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c deleted file mode 100644 index 04f864d238db..000000000000 --- a/drivers/mtd/devices/blkmtd.c +++ /dev/null | |||
@@ -1,820 +0,0 @@ | |||
1 | /* | ||
2 | * $Id: blkmtd.c,v 1.27 2005/11/07 11:14:24 gleixner Exp $ | ||
3 | * | ||
4 | * blkmtd.c - use a block device as a fake MTD | ||
5 | * | ||
6 | * Author: Simon Evans <spse@secret.org.uk> | ||
7 | * | ||
8 | * Copyright (C) 2001,2002 Simon Evans | ||
9 | * | ||
10 | * Licence: GPL | ||
11 | * | ||
12 | * How it works: | ||
13 | * The driver uses raw/io to read/write the device and the page | ||
14 | * cache to cache access. Writes update the page cache with the | ||
15 | * new data and mark it dirty and add the page into a BIO which | ||
16 | * is then written out. | ||
17 | * | ||
18 | * It can be loaded Read-Only to prevent erases and writes to the | ||
19 | * medium. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/config.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/fs.h> | ||
26 | #include <linux/blkdev.h> | ||
27 | #include <linux/bio.h> | ||
28 | #include <linux/pagemap.h> | ||
29 | #include <linux/list.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/mtd/mtd.h> | ||
32 | |||
33 | |||
34 | #define err(format, arg...) printk(KERN_ERR "blkmtd: " format "\n" , ## arg) | ||
35 | #define info(format, arg...) printk(KERN_INFO "blkmtd: " format "\n" , ## arg) | ||
36 | #define warn(format, arg...) printk(KERN_WARNING "blkmtd: " format "\n" , ## arg) | ||
37 | #define crit(format, arg...) printk(KERN_CRIT "blkmtd: " format "\n" , ## arg) | ||
38 | |||
39 | |||
40 | /* Default erase size in K, always make it a multiple of PAGE_SIZE */ | ||
41 | #define CONFIG_MTD_BLKDEV_ERASESIZE (128 << 10) /* 128KiB */ | ||
42 | #define VERSION "$Revision: 1.27 $" | ||
43 | |||
44 | /* Info for the block device */ | ||
45 | struct blkmtd_dev { | ||
46 | struct list_head list; | ||
47 | struct block_device *blkdev; | ||
48 | struct mtd_info mtd_info; | ||
49 | struct semaphore wrbuf_mutex; | ||
50 | }; | ||
51 | |||
52 | |||
53 | /* Static info about the MTD, used in cleanup_module */ | ||
54 | static LIST_HEAD(blkmtd_device_list); | ||
55 | |||
56 | |||
57 | static void blkmtd_sync(struct mtd_info *mtd); | ||
58 | |||
59 | #define MAX_DEVICES 4 | ||
60 | |||
61 | /* Module parameters passed by insmod/modprobe */ | ||
62 | static char *device[MAX_DEVICES]; /* the block device to use */ | ||
63 | static int erasesz[MAX_DEVICES]; /* optional default erase size */ | ||
64 | static int ro[MAX_DEVICES]; /* optional read only flag */ | ||
65 | static int sync; | ||
66 | |||
67 | |||
68 | MODULE_LICENSE("GPL"); | ||
69 | MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>"); | ||
70 | MODULE_DESCRIPTION("Emulate an MTD using a block device"); | ||
71 | module_param_array(device, charp, NULL, 0); | ||
72 | MODULE_PARM_DESC(device, "block device to use"); | ||
73 | module_param_array(erasesz, int, NULL, 0); | ||
74 | MODULE_PARM_DESC(erasesz, "optional erase size to use in KiB. eg 4=4KiB."); | ||
75 | module_param_array(ro, bool, NULL, 0); | ||
76 | MODULE_PARM_DESC(ro, "1=Read only, writes and erases cause errors"); | ||
77 | module_param(sync, bool, 0); | ||
78 | MODULE_PARM_DESC(sync, "1=Synchronous writes"); | ||
79 | |||
80 | |||
81 | /* completion handler for BIO reads */ | ||
82 | static int bi_read_complete(struct bio *bio, unsigned int bytes_done, int error) | ||
83 | { | ||
84 | if (bio->bi_size) | ||
85 | return 1; | ||
86 | |||
87 | complete((struct completion*)bio->bi_private); | ||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | |||
92 | /* completion handler for BIO writes */ | ||
93 | static int bi_write_complete(struct bio *bio, unsigned int bytes_done, int error) | ||
94 | { | ||
95 | const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); | ||
96 | struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; | ||
97 | |||
98 | if (bio->bi_size) | ||
99 | return 1; | ||
100 | |||
101 | if(!uptodate) | ||
102 | err("bi_write_complete: not uptodate\n"); | ||
103 | |||
104 | do { | ||
105 | struct page *page = bvec->bv_page; | ||
106 | DEBUG(3, "Cleaning up page %ld\n", page->index); | ||
107 | if (--bvec >= bio->bi_io_vec) | ||
108 | prefetchw(&bvec->bv_page->flags); | ||
109 | |||
110 | if (uptodate) { | ||
111 | SetPageUptodate(page); | ||
112 | } else { | ||
113 | ClearPageUptodate(page); | ||
114 | SetPageError(page); | ||
115 | } | ||
116 | clear_page_dirty(page); | ||
117 | unlock_page(page); | ||
118 | page_cache_release(page); | ||
119 | } while (bvec >= bio->bi_io_vec); | ||
120 | |||
121 | complete((struct completion*)bio->bi_private); | ||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | |||
126 | /* read one page from the block device */ | ||
127 | static int blkmtd_readpage(struct blkmtd_dev *dev, struct page *page) | ||
128 | { | ||
129 | struct bio *bio; | ||
130 | struct completion event; | ||
131 | int err = -ENOMEM; | ||
132 | |||
133 | if(PageUptodate(page)) { | ||
134 | DEBUG(2, "blkmtd: readpage page %ld is already upto date\n", page->index); | ||
135 | unlock_page(page); | ||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | ClearPageUptodate(page); | ||
140 | ClearPageError(page); | ||
141 | |||
142 | bio = bio_alloc(GFP_KERNEL, 1); | ||
143 | if(bio) { | ||
144 | init_completion(&event); | ||
145 | bio->bi_bdev = dev->blkdev; | ||
146 | bio->bi_sector = page->index << (PAGE_SHIFT-9); | ||
147 | bio->bi_private = &event; | ||
148 | bio->bi_end_io = bi_read_complete; | ||
149 | if(bio_add_page(bio, page, PAGE_SIZE, 0) == PAGE_SIZE) { | ||
150 | submit_bio(READ_SYNC, bio); | ||
151 | wait_for_completion(&event); | ||
152 | err = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : -EIO; | ||
153 | bio_put(bio); | ||
154 | } | ||
155 | } | ||
156 | |||
157 | if(err) | ||
158 | SetPageError(page); | ||
159 | else | ||
160 | SetPageUptodate(page); | ||
161 | flush_dcache_page(page); | ||
162 | unlock_page(page); | ||
163 | return err; | ||
164 | } | ||
165 | |||
166 | |||
167 | /* write out the current BIO and wait for it to finish */ | ||
168 | static int blkmtd_write_out(struct bio *bio) | ||
169 | { | ||
170 | struct completion event; | ||
171 | int err; | ||
172 | |||
173 | if(!bio->bi_vcnt) { | ||
174 | bio_put(bio); | ||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | init_completion(&event); | ||
179 | bio->bi_private = &event; | ||
180 | bio->bi_end_io = bi_write_complete; | ||
181 | submit_bio(WRITE_SYNC, bio); | ||
182 | wait_for_completion(&event); | ||
183 | DEBUG(3, "submit_bio completed, bi_vcnt = %d\n", bio->bi_vcnt); | ||
184 | err = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : -EIO; | ||
185 | bio_put(bio); | ||
186 | return err; | ||
187 | } | ||
188 | |||
189 | |||
190 | /** | ||
191 | * blkmtd_add_page - add a page to the current BIO | ||
192 | * @bio: bio to add to (NULL to alloc initial bio) | ||
193 | * @blkdev: block device | ||
194 | * @page: page to add | ||
195 | * @pagecnt: pages left to add | ||
196 | * | ||
197 | * Adds a page to the current bio, allocating it if necessary. If it cannot be | ||
198 | * added, the current bio is written out and a new one is allocated. Returns | ||
199 | * the new bio to add or NULL on error | ||
200 | */ | ||
201 | static struct bio *blkmtd_add_page(struct bio *bio, struct block_device *blkdev, | ||
202 | struct page *page, int pagecnt) | ||
203 | { | ||
204 | |||
205 | retry: | ||
206 | if(!bio) { | ||
207 | bio = bio_alloc(GFP_KERNEL, pagecnt); | ||
208 | if(!bio) | ||
209 | return NULL; | ||
210 | bio->bi_sector = page->index << (PAGE_SHIFT-9); | ||
211 | bio->bi_bdev = blkdev; | ||
212 | } | ||
213 | |||
214 | if(bio_add_page(bio, page, PAGE_SIZE, 0) != PAGE_SIZE) { | ||
215 | blkmtd_write_out(bio); | ||
216 | bio = NULL; | ||
217 | goto retry; | ||
218 | } | ||
219 | return bio; | ||
220 | } | ||
221 | |||
222 | |||
223 | /** | ||
224 | * write_pages - write block of data to device via the page cache | ||
225 | * @dev: device to write to | ||
226 | * @buf: data source or NULL if erase (output is set to 0xff) | ||
227 | * @to: offset into output device | ||
228 | * @len: amount to data to write | ||
229 | * @retlen: amount of data written | ||
230 | * | ||
231 | * Grab pages from the page cache and fill them with the source data. | ||
232 | * Non page aligned start and end result in a readin of the page and | ||
233 | * part of the page being modified. Pages are added to the bio and then written | ||
234 | * out. | ||
235 | */ | ||
236 | static int write_pages(struct blkmtd_dev *dev, const u_char *buf, loff_t to, | ||
237 | size_t len, size_t *retlen) | ||
238 | { | ||
239 | int pagenr, offset; | ||
240 | size_t start_len = 0, end_len; | ||
241 | int pagecnt = 0; | ||
242 | int err = 0; | ||
243 | struct bio *bio = NULL; | ||
244 | size_t thislen = 0; | ||
245 | |||
246 | pagenr = to >> PAGE_SHIFT; | ||
247 | offset = to & ~PAGE_MASK; | ||
248 | |||
249 | DEBUG(2, "blkmtd: write_pages: buf = %p to = %ld len = %zd pagenr = %d offset = %d\n", | ||
250 | buf, (long)to, len, pagenr, offset); | ||
251 | |||
252 | /* see if we have to do a partial write at the start */ | ||
253 | if(offset) { | ||
254 | start_len = ((offset + len) > PAGE_SIZE) ? PAGE_SIZE - offset : len; | ||
255 | len -= start_len; | ||
256 | } | ||
257 | |||
258 | /* calculate the length of the other two regions */ | ||
259 | end_len = len & ~PAGE_MASK; | ||
260 | len -= end_len; | ||
261 | |||
262 | if(start_len) | ||
263 | pagecnt++; | ||
264 | |||
265 | if(len) | ||
266 | pagecnt += len >> PAGE_SHIFT; | ||
267 | |||
268 | if(end_len) | ||
269 | pagecnt++; | ||
270 | |||
271 | down(&dev->wrbuf_mutex); | ||
272 | |||
273 | DEBUG(3, "blkmtd: write: start_len = %zd len = %zd end_len = %zd pagecnt = %d\n", | ||
274 | start_len, len, end_len, pagecnt); | ||
275 | |||
276 | if(start_len) { | ||
277 | /* do partial start region */ | ||
278 | struct page *page; | ||
279 | |||
280 | DEBUG(3, "blkmtd: write: doing partial start, page = %d len = %zd offset = %d\n", | ||
281 | pagenr, start_len, offset); | ||
282 | |||
283 | BUG_ON(!buf); | ||
284 | page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev); | ||
285 | lock_page(page); | ||
286 | if(PageDirty(page)) { | ||
287 | err("to = %lld start_len = %zd len = %zd end_len = %zd pagenr = %d\n", | ||
288 | to, start_len, len, end_len, pagenr); | ||
289 | BUG(); | ||
290 | } | ||
291 | memcpy(page_address(page)+offset, buf, start_len); | ||
292 | set_page_dirty(page); | ||
293 | SetPageUptodate(page); | ||
294 | buf += start_len; | ||
295 | thislen = start_len; | ||
296 | bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt); | ||
297 | if(!bio) { | ||
298 | err = -ENOMEM; | ||
299 | err("bio_add_page failed\n"); | ||
300 | goto write_err; | ||
301 | } | ||
302 | pagecnt--; | ||
303 | pagenr++; | ||
304 | } | ||
305 | |||
306 | /* Now do the main loop to a page aligned, n page sized output */ | ||
307 | if(len) { | ||
308 | int pagesc = len >> PAGE_SHIFT; | ||
309 | DEBUG(3, "blkmtd: write: whole pages start = %d, count = %d\n", | ||
310 | pagenr, pagesc); | ||
311 | while(pagesc) { | ||
312 | struct page *page; | ||
313 | |||
314 | /* see if page is in the page cache */ | ||
315 | DEBUG(3, "blkmtd: write: grabbing page %d from page cache\n", pagenr); | ||
316 | page = grab_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr); | ||
317 | if(PageDirty(page)) { | ||
318 | BUG(); | ||
319 | } | ||
320 | if(!page) { | ||
321 | warn("write: cannot grab cache page %d", pagenr); | ||
322 | err = -ENOMEM; | ||
323 | goto write_err; | ||
324 | } | ||
325 | if(!buf) { | ||
326 | memset(page_address(page), 0xff, PAGE_SIZE); | ||
327 | } else { | ||
328 | memcpy(page_address(page), buf, PAGE_SIZE); | ||
329 | buf += PAGE_SIZE; | ||
330 | } | ||
331 | bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt); | ||
332 | if(!bio) { | ||
333 | err = -ENOMEM; | ||
334 | err("bio_add_page failed\n"); | ||
335 | goto write_err; | ||
336 | } | ||
337 | pagenr++; | ||
338 | pagecnt--; | ||
339 | set_page_dirty(page); | ||
340 | SetPageUptodate(page); | ||
341 | pagesc--; | ||
342 | thislen += PAGE_SIZE; | ||
343 | } | ||
344 | } | ||
345 | |||
346 | if(end_len) { | ||
347 | /* do the third region */ | ||
348 | struct page *page; | ||
349 | DEBUG(3, "blkmtd: write: doing partial end, page = %d len = %zd\n", | ||
350 | pagenr, end_len); | ||
351 | BUG_ON(!buf); | ||
352 | page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev); | ||
353 | lock_page(page); | ||
354 | if(PageDirty(page)) { | ||
355 | err("to = %lld start_len = %zd len = %zd end_len = %zd pagenr = %d\n", | ||
356 | to, start_len, len, end_len, pagenr); | ||
357 | BUG(); | ||
358 | } | ||
359 | memcpy(page_address(page), buf, end_len); | ||
360 | set_page_dirty(page); | ||
361 | SetPageUptodate(page); | ||
362 | DEBUG(3, "blkmtd: write: writing out partial end\n"); | ||
363 | thislen += end_len; | ||
364 | bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt); | ||
365 | if(!bio) { | ||
366 | err = -ENOMEM; | ||
367 | err("bio_add_page failed\n"); | ||
368 | goto write_err; | ||
369 | } | ||
370 | pagenr++; | ||
371 | } | ||
372 | |||
373 | DEBUG(3, "blkmtd: write: got %d vectors to write\n", bio->bi_vcnt); | ||
374 | write_err: | ||
375 | if(bio) | ||
376 | blkmtd_write_out(bio); | ||
377 | |||
378 | DEBUG(2, "blkmtd: write: end, retlen = %zd, err = %d\n", *retlen, err); | ||
379 | up(&dev->wrbuf_mutex); | ||
380 | |||
381 | if(retlen) | ||
382 | *retlen = thislen; | ||
383 | return err; | ||
384 | } | ||
385 | |||
386 | |||
387 | /* erase a specified part of the device */ | ||
388 | static int blkmtd_erase(struct mtd_info *mtd, struct erase_info *instr) | ||
389 | { | ||
390 | struct blkmtd_dev *dev = mtd->priv; | ||
391 | struct mtd_erase_region_info *einfo = mtd->eraseregions; | ||
392 | int numregions = mtd->numeraseregions; | ||
393 | size_t from; | ||
394 | u_long len; | ||
395 | int err = -EIO; | ||
396 | size_t retlen; | ||
397 | |||
398 | instr->state = MTD_ERASING; | ||
399 | from = instr->addr; | ||
400 | len = instr->len; | ||
401 | |||
402 | /* check erase region has valid start and length */ | ||
403 | DEBUG(2, "blkmtd: erase: dev = `%s' from = 0x%zx len = 0x%lx\n", | ||
404 | mtd->name+9, from, len); | ||
405 | while(numregions) { | ||
406 | DEBUG(3, "blkmtd: checking erase region = 0x%08X size = 0x%X num = 0x%x\n", | ||
407 | einfo->offset, einfo->erasesize, einfo->numblocks); | ||
408 | if(from >= einfo->offset | ||
409 | && from < einfo->offset + (einfo->erasesize * einfo->numblocks)) { | ||
410 | if(len == einfo->erasesize | ||
411 | && ( (from - einfo->offset) % einfo->erasesize == 0)) | ||
412 | break; | ||
413 | } | ||
414 | numregions--; | ||
415 | einfo++; | ||
416 | } | ||
417 | |||
418 | if(!numregions) { | ||
419 | /* Not a valid erase block */ | ||
420 | err("erase: invalid erase request 0x%lX @ 0x%08zX", len, from); | ||
421 | instr->state = MTD_ERASE_FAILED; | ||
422 | err = -EIO; | ||
423 | } | ||
424 | |||
425 | if(instr->state != MTD_ERASE_FAILED) { | ||
426 | /* do the erase */ | ||
427 | DEBUG(3, "Doing erase from = %zd len = %ld\n", from, len); | ||
428 | err = write_pages(dev, NULL, from, len, &retlen); | ||
429 | if(err || retlen != len) { | ||
430 | err("erase failed err = %d", err); | ||
431 | instr->state = MTD_ERASE_FAILED; | ||
432 | } else { | ||
433 | instr->state = MTD_ERASE_DONE; | ||
434 | } | ||
435 | } | ||
436 | |||
437 | DEBUG(3, "blkmtd: erase: checking callback\n"); | ||
438 | mtd_erase_callback(instr); | ||
439 | DEBUG(2, "blkmtd: erase: finished (err = %d)\n", err); | ||
440 | return err; | ||
441 | } | ||
442 | |||
443 | |||
444 | /* read a range of the data via the page cache */ | ||
445 | static int blkmtd_read(struct mtd_info *mtd, loff_t from, size_t len, | ||
446 | size_t *retlen, u_char *buf) | ||
447 | { | ||
448 | struct blkmtd_dev *dev = mtd->priv; | ||
449 | int err = 0; | ||
450 | int offset; | ||
451 | int pagenr, pages; | ||
452 | size_t thislen = 0; | ||
453 | |||
454 | DEBUG(2, "blkmtd: read: dev = `%s' from = %lld len = %zd buf = %p\n", | ||
455 | mtd->name+9, from, len, buf); | ||
456 | |||
457 | if(from > mtd->size) | ||
458 | return -EINVAL; | ||
459 | if(from + len > mtd->size) | ||
460 | len = mtd->size - from; | ||
461 | |||
462 | pagenr = from >> PAGE_SHIFT; | ||
463 | offset = from - (pagenr << PAGE_SHIFT); | ||
464 | |||
465 | pages = (offset+len+PAGE_SIZE-1) >> PAGE_SHIFT; | ||
466 | DEBUG(3, "blkmtd: read: pagenr = %d offset = %d, pages = %d\n", | ||
467 | pagenr, offset, pages); | ||
468 | |||
469 | while(pages) { | ||
470 | struct page *page; | ||
471 | int cpylen; | ||
472 | |||
473 | DEBUG(3, "blkmtd: read: looking for page: %d\n", pagenr); | ||
474 | page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev); | ||
475 | if(IS_ERR(page)) { | ||
476 | err = -EIO; | ||
477 | goto readerr; | ||
478 | } | ||
479 | |||
480 | cpylen = (PAGE_SIZE > len) ? len : PAGE_SIZE; | ||
481 | if(offset+cpylen > PAGE_SIZE) | ||
482 | cpylen = PAGE_SIZE-offset; | ||
483 | |||
484 | memcpy(buf + thislen, page_address(page) + offset, cpylen); | ||
485 | offset = 0; | ||
486 | len -= cpylen; | ||
487 | thislen += cpylen; | ||
488 | pagenr++; | ||
489 | pages--; | ||
490 | if(!PageDirty(page)) | ||
491 | page_cache_release(page); | ||
492 | } | ||
493 | |||
494 | readerr: | ||
495 | if(retlen) | ||
496 | *retlen = thislen; | ||
497 | DEBUG(2, "blkmtd: end read: retlen = %zd, err = %d\n", thislen, err); | ||
498 | return err; | ||
499 | } | ||
500 | |||
501 | |||
502 | /* write data to the underlying device */ | ||
503 | static int blkmtd_write(struct mtd_info *mtd, loff_t to, size_t len, | ||
504 | size_t *retlen, const u_char *buf) | ||
505 | { | ||
506 | struct blkmtd_dev *dev = mtd->priv; | ||
507 | int err; | ||
508 | |||
509 | if(!len) | ||
510 | return 0; | ||
511 | |||
512 | DEBUG(2, "blkmtd: write: dev = `%s' to = %lld len = %zd buf = %p\n", | ||
513 | mtd->name+9, to, len, buf); | ||
514 | |||
515 | if(to >= mtd->size) { | ||
516 | return -ENOSPC; | ||
517 | } | ||
518 | |||
519 | if(to + len > mtd->size) { | ||
520 | len = mtd->size - to; | ||
521 | } | ||
522 | |||
523 | err = write_pages(dev, buf, to, len, retlen); | ||
524 | if(err > 0) | ||
525 | err = 0; | ||
526 | DEBUG(2, "blkmtd: write: end, err = %d\n", err); | ||
527 | return err; | ||
528 | } | ||
529 | |||
530 | |||
531 | /* sync the device - wait until the write queue is empty */ | ||
532 | static void blkmtd_sync(struct mtd_info *mtd) | ||
533 | { | ||
534 | /* Currently all writes are synchronous */ | ||
535 | } | ||
536 | |||
537 | |||
538 | static void free_device(struct blkmtd_dev *dev) | ||
539 | { | ||
540 | DEBUG(2, "blkmtd: free_device() dev = %p\n", dev); | ||
541 | if(dev) { | ||
542 | kfree(dev->mtd_info.eraseregions); | ||
543 | kfree(dev->mtd_info.name); | ||
544 | if(dev->blkdev) { | ||
545 | invalidate_inode_pages(dev->blkdev->bd_inode->i_mapping); | ||
546 | close_bdev_excl(dev->blkdev); | ||
547 | } | ||
548 | kfree(dev); | ||
549 | } | ||
550 | } | ||
551 | |||
552 | |||
553 | /* For a given size and initial erase size, calculate the number | ||
554 | * and size of each erase region. Goes round the loop twice, | ||
555 | * once to find out how many regions, then allocates space, | ||
556 | * then round the loop again to fill it in. | ||
557 | */ | ||
558 | static struct mtd_erase_region_info *calc_erase_regions( | ||
559 | size_t erase_size, size_t total_size, int *regions) | ||
560 | { | ||
561 | struct mtd_erase_region_info *info = NULL; | ||
562 | |||
563 | DEBUG(2, "calc_erase_regions, es = %zd size = %zd regions = %d\n", | ||
564 | erase_size, total_size, *regions); | ||
565 | /* Make any user specified erasesize be a power of 2 | ||
566 | and at least PAGE_SIZE */ | ||
567 | if(erase_size) { | ||
568 | int es = erase_size; | ||
569 | erase_size = 1; | ||
570 | while(es != 1) { | ||
571 | es >>= 1; | ||
572 | erase_size <<= 1; | ||
573 | } | ||
574 | if(erase_size < PAGE_SIZE) | ||
575 | erase_size = PAGE_SIZE; | ||
576 | } else { | ||
577 | erase_size = CONFIG_MTD_BLKDEV_ERASESIZE; | ||
578 | } | ||
579 | |||
580 | *regions = 0; | ||
581 | |||
582 | do { | ||
583 | int tot_size = total_size; | ||
584 | int er_size = erase_size; | ||
585 | int count = 0, offset = 0, regcnt = 0; | ||
586 | |||
587 | while(tot_size) { | ||
588 | count = tot_size / er_size; | ||
589 | if(count) { | ||
590 | tot_size = tot_size % er_size; | ||
591 | if(info) { | ||
592 | DEBUG(2, "adding to erase info off=%d er=%d cnt=%d\n", | ||
593 | offset, er_size, count); | ||
594 | (info+regcnt)->offset = offset; | ||
595 | (info+regcnt)->erasesize = er_size; | ||
596 | (info+regcnt)->numblocks = count; | ||
597 | (*regions)++; | ||
598 | } | ||
599 | regcnt++; | ||
600 | offset += (count * er_size); | ||
601 | } | ||
602 | while(er_size > tot_size) | ||
603 | er_size >>= 1; | ||
604 | } | ||
605 | if(info == NULL) { | ||
606 | info = kmalloc(regcnt * sizeof(struct mtd_erase_region_info), GFP_KERNEL); | ||
607 | if(!info) | ||
608 | break; | ||
609 | } | ||
610 | } while(!(*regions)); | ||
611 | DEBUG(2, "calc_erase_regions done, es = %zd size = %zd regions = %d\n", | ||
612 | erase_size, total_size, *regions); | ||
613 | return info; | ||
614 | } | ||
615 | |||
616 | |||
617 | extern dev_t __init name_to_dev_t(const char *line); | ||
618 | |||
619 | static struct blkmtd_dev *add_device(char *devname, int readonly, int erase_size) | ||
620 | { | ||
621 | struct block_device *bdev; | ||
622 | int mode; | ||
623 | struct blkmtd_dev *dev; | ||
624 | |||
625 | if(!devname) | ||
626 | return NULL; | ||
627 | |||
628 | /* Get a handle on the device */ | ||
629 | |||
630 | |||
631 | #ifdef MODULE | ||
632 | mode = (readonly) ? O_RDONLY : O_RDWR; | ||
633 | bdev = open_bdev_excl(devname, mode, NULL); | ||
634 | #else | ||
635 | mode = (readonly) ? FMODE_READ : FMODE_WRITE; | ||
636 | bdev = open_by_devnum(name_to_dev_t(devname), mode); | ||
637 | #endif | ||
638 | if(IS_ERR(bdev)) { | ||
639 | err("error: cannot open device %s", devname); | ||
640 | DEBUG(2, "blkmtd: opening bdev returned %ld\n", PTR_ERR(bdev)); | ||
641 | return NULL; | ||
642 | } | ||
643 | |||
644 | DEBUG(1, "blkmtd: found a block device major = %d, minor = %d\n", | ||
645 | MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev)); | ||
646 | |||
647 | if(MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) { | ||
648 | err("attempting to use an MTD device as a block device"); | ||
649 | blkdev_put(bdev); | ||
650 | return NULL; | ||
651 | } | ||
652 | |||
653 | dev = kmalloc(sizeof(struct blkmtd_dev), GFP_KERNEL); | ||
654 | if(dev == NULL) { | ||
655 | blkdev_put(bdev); | ||
656 | return NULL; | ||
657 | } | ||
658 | |||
659 | memset(dev, 0, sizeof(struct blkmtd_dev)); | ||
660 | dev->blkdev = bdev; | ||
661 | if(!readonly) { | ||
662 | init_MUTEX(&dev->wrbuf_mutex); | ||
663 | } | ||
664 | |||
665 | dev->mtd_info.size = dev->blkdev->bd_inode->i_size & PAGE_MASK; | ||
666 | |||
667 | /* Setup the MTD structure */ | ||
668 | /* make the name contain the block device in */ | ||
669 | dev->mtd_info.name = kmalloc(sizeof("blkmtd: ") + strlen(devname), GFP_KERNEL); | ||
670 | if(dev->mtd_info.name == NULL) | ||
671 | goto devinit_err; | ||
672 | |||
673 | sprintf(dev->mtd_info.name, "blkmtd: %s", devname); | ||
674 | dev->mtd_info.eraseregions = calc_erase_regions(erase_size, dev->mtd_info.size, | ||
675 | &dev->mtd_info.numeraseregions); | ||
676 | if(dev->mtd_info.eraseregions == NULL) | ||
677 | goto devinit_err; | ||
678 | |||
679 | dev->mtd_info.erasesize = dev->mtd_info.eraseregions->erasesize; | ||
680 | DEBUG(1, "blkmtd: init: found %d erase regions\n", | ||
681 | dev->mtd_info.numeraseregions); | ||
682 | |||
683 | if(readonly) { | ||
684 | dev->mtd_info.type = MTD_ROM; | ||
685 | dev->mtd_info.flags = MTD_CAP_ROM; | ||
686 | } else { | ||
687 | dev->mtd_info.type = MTD_RAM; | ||
688 | dev->mtd_info.flags = MTD_CAP_RAM; | ||
689 | dev->mtd_info.erase = blkmtd_erase; | ||
690 | dev->mtd_info.write = blkmtd_write; | ||
691 | dev->mtd_info.writev = default_mtd_writev; | ||
692 | dev->mtd_info.sync = blkmtd_sync; | ||
693 | } | ||
694 | dev->mtd_info.read = blkmtd_read; | ||
695 | dev->mtd_info.readv = default_mtd_readv; | ||
696 | dev->mtd_info.priv = dev; | ||
697 | dev->mtd_info.owner = THIS_MODULE; | ||
698 | |||
699 | list_add(&dev->list, &blkmtd_device_list); | ||
700 | if (add_mtd_device(&dev->mtd_info)) { | ||
701 | /* Device didnt get added, so free the entry */ | ||
702 | list_del(&dev->list); | ||
703 | goto devinit_err; | ||
704 | } else { | ||
705 | info("mtd%d: [%s] erase_size = %dKiB %s", | ||
706 | dev->mtd_info.index, dev->mtd_info.name + strlen("blkmtd: "), | ||
707 | dev->mtd_info.erasesize >> 10, | ||
708 | readonly ? "(read-only)" : ""); | ||
709 | } | ||
710 | |||
711 | return dev; | ||
712 | |||
713 | devinit_err: | ||
714 | free_device(dev); | ||
715 | return NULL; | ||
716 | } | ||
717 | |||
718 | |||
719 | /* Cleanup and exit - sync the device and kill of the kernel thread */ | ||
720 | static void __devexit cleanup_blkmtd(void) | ||
721 | { | ||
722 | struct list_head *temp1, *temp2; | ||
723 | |||
724 | /* Remove the MTD devices */ | ||
725 | list_for_each_safe(temp1, temp2, &blkmtd_device_list) { | ||
726 | struct blkmtd_dev *dev = list_entry(temp1, struct blkmtd_dev, | ||
727 | list); | ||
728 | blkmtd_sync(&dev->mtd_info); | ||
729 | del_mtd_device(&dev->mtd_info); | ||
730 | info("mtd%d: [%s] removed", dev->mtd_info.index, | ||
731 | dev->mtd_info.name + strlen("blkmtd: ")); | ||
732 | list_del(&dev->list); | ||
733 | free_device(dev); | ||
734 | } | ||
735 | } | ||
736 | |||
737 | #ifndef MODULE | ||
738 | |||
739 | /* Handle kernel boot params */ | ||
740 | |||
741 | |||
742 | static int __init param_blkmtd_device(char *str) | ||
743 | { | ||
744 | int i; | ||
745 | |||
746 | for(i = 0; i < MAX_DEVICES; i++) { | ||
747 | device[i] = str; | ||
748 | DEBUG(2, "blkmtd: device setup: %d = %s\n", i, device[i]); | ||
749 | strsep(&str, ","); | ||
750 | } | ||
751 | return 1; | ||
752 | } | ||
753 | |||
754 | |||
755 | static int __init param_blkmtd_erasesz(char *str) | ||
756 | { | ||
757 | int i; | ||
758 | for(i = 0; i < MAX_DEVICES; i++) { | ||
759 | char *val = strsep(&str, ","); | ||
760 | if(val) | ||
761 | erasesz[i] = simple_strtoul(val, NULL, 0); | ||
762 | DEBUG(2, "blkmtd: erasesz setup: %d = %d\n", i, erasesz[i]); | ||
763 | } | ||
764 | |||
765 | return 1; | ||
766 | } | ||
767 | |||
768 | |||
769 | static int __init param_blkmtd_ro(char *str) | ||
770 | { | ||
771 | int i; | ||
772 | for(i = 0; i < MAX_DEVICES; i++) { | ||
773 | char *val = strsep(&str, ","); | ||
774 | if(val) | ||
775 | ro[i] = simple_strtoul(val, NULL, 0); | ||
776 | DEBUG(2, "blkmtd: ro setup: %d = %d\n", i, ro[i]); | ||
777 | } | ||
778 | |||
779 | return 1; | ||
780 | } | ||
781 | |||
782 | |||
783 | static int __init param_blkmtd_sync(char *str) | ||
784 | { | ||
785 | if(str[0] == '1') | ||
786 | sync = 1; | ||
787 | return 1; | ||
788 | } | ||
789 | |||
790 | __setup("blkmtd_device=", param_blkmtd_device); | ||
791 | __setup("blkmtd_erasesz=", param_blkmtd_erasesz); | ||
792 | __setup("blkmtd_ro=", param_blkmtd_ro); | ||
793 | __setup("blkmtd_sync=", param_blkmtd_sync); | ||
794 | |||
795 | #endif | ||
796 | |||
797 | |||
798 | /* Startup */ | ||
799 | static int __init init_blkmtd(void) | ||
800 | { | ||
801 | int i; | ||
802 | |||
803 | info("version " VERSION); | ||
804 | /* Check args - device[0] is the bare minimum*/ | ||
805 | if(!device[0]) { | ||
806 | err("error: missing `device' name\n"); | ||
807 | return -EINVAL; | ||
808 | } | ||
809 | |||
810 | for(i = 0; i < MAX_DEVICES; i++) | ||
811 | add_device(device[i], ro[i], erasesz[i] << 10); | ||
812 | |||
813 | if(list_empty(&blkmtd_device_list)) | ||
814 | return -EINVAL; | ||
815 | |||
816 | return 0; | ||
817 | } | ||
818 | |||
819 | module_init(init_blkmtd); | ||
820 | module_exit(cleanup_blkmtd); | ||
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index 7ff403b2a0a0..4160b8334c53 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/mtd/mtd.h> | 19 | #include <linux/mtd/mtd.h> |
20 | #include <linux/buffer_head.h> | 20 | #include <linux/buffer_head.h> |
21 | #include <linux/mutex.h> | ||
21 | 22 | ||
22 | #define VERSION "$Revision: 1.30 $" | 23 | #define VERSION "$Revision: 1.30 $" |
23 | 24 | ||
@@ -31,7 +32,7 @@ struct block2mtd_dev { | |||
31 | struct list_head list; | 32 | struct list_head list; |
32 | struct block_device *blkdev; | 33 | struct block_device *blkdev; |
33 | struct mtd_info mtd; | 34 | struct mtd_info mtd; |
34 | struct semaphore write_mutex; | 35 | struct mutex write_mutex; |
35 | }; | 36 | }; |
36 | 37 | ||
37 | 38 | ||
@@ -134,9 +135,9 @@ static int block2mtd_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
134 | int err; | 135 | int err; |
135 | 136 | ||
136 | instr->state = MTD_ERASING; | 137 | instr->state = MTD_ERASING; |
137 | down(&dev->write_mutex); | 138 | mutex_lock(&dev->write_mutex); |
138 | err = _block2mtd_erase(dev, from, len); | 139 | err = _block2mtd_erase(dev, from, len); |
139 | up(&dev->write_mutex); | 140 | mutex_unlock(&dev->write_mutex); |
140 | if (err) { | 141 | if (err) { |
141 | ERROR("erase failed err = %d", err); | 142 | ERROR("erase failed err = %d", err); |
142 | instr->state = MTD_ERASE_FAILED; | 143 | instr->state = MTD_ERASE_FAILED; |
@@ -249,9 +250,9 @@ static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
249 | if (to + len > mtd->size) | 250 | if (to + len > mtd->size) |
250 | len = mtd->size - to; | 251 | len = mtd->size - to; |
251 | 252 | ||
252 | down(&dev->write_mutex); | 253 | mutex_lock(&dev->write_mutex); |
253 | err = _block2mtd_write(dev, buf, to, len, retlen); | 254 | err = _block2mtd_write(dev, buf, to, len, retlen); |
254 | up(&dev->write_mutex); | 255 | mutex_unlock(&dev->write_mutex); |
255 | if (err > 0) | 256 | if (err > 0) |
256 | err = 0; | 257 | err = 0; |
257 | return err; | 258 | return err; |
@@ -310,7 +311,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) | |||
310 | goto devinit_err; | 311 | goto devinit_err; |
311 | } | 312 | } |
312 | 313 | ||
313 | init_MUTEX(&dev->write_mutex); | 314 | mutex_init(&dev->write_mutex); |
314 | 315 | ||
315 | /* Setup the MTD structure */ | 316 | /* Setup the MTD structure */ |
316 | /* make the name contain the block device in */ | 317 | /* make the name contain the block device in */ |
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c index e4345cf744a2..23e7a5c7d2c1 100644 --- a/drivers/mtd/devices/doc2000.c +++ b/drivers/mtd/devices/doc2000.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/types.h> | 21 | #include <linux/types.h> |
22 | #include <linux/bitops.h> | 22 | #include <linux/bitops.h> |
23 | #include <linux/mutex.h> | ||
23 | 24 | ||
24 | #include <linux/mtd/mtd.h> | 25 | #include <linux/mtd/mtd.h> |
25 | #include <linux/mtd/nand.h> | 26 | #include <linux/mtd/nand.h> |
@@ -605,7 +606,7 @@ static void DoC2k_init(struct mtd_info *mtd) | |||
605 | 606 | ||
606 | this->curfloor = -1; | 607 | this->curfloor = -1; |
607 | this->curchip = -1; | 608 | this->curchip = -1; |
608 | init_MUTEX(&this->lock); | 609 | mutex_init(&this->lock); |
609 | 610 | ||
610 | /* Ident all the chips present. */ | 611 | /* Ident all the chips present. */ |
611 | DoC_ScanChips(this, maxchips); | 612 | DoC_ScanChips(this, maxchips); |
@@ -645,7 +646,7 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, | |||
645 | if (from >= this->totlen) | 646 | if (from >= this->totlen) |
646 | return -EINVAL; | 647 | return -EINVAL; |
647 | 648 | ||
648 | down(&this->lock); | 649 | mutex_lock(&this->lock); |
649 | 650 | ||
650 | *retlen = 0; | 651 | *retlen = 0; |
651 | while (left) { | 652 | while (left) { |
@@ -774,7 +775,7 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, | |||
774 | buf += len; | 775 | buf += len; |
775 | } | 776 | } |
776 | 777 | ||
777 | up(&this->lock); | 778 | mutex_unlock(&this->lock); |
778 | 779 | ||
779 | return ret; | 780 | return ret; |
780 | } | 781 | } |
@@ -803,7 +804,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, | |||
803 | if (to >= this->totlen) | 804 | if (to >= this->totlen) |
804 | return -EINVAL; | 805 | return -EINVAL; |
805 | 806 | ||
806 | down(&this->lock); | 807 | mutex_lock(&this->lock); |
807 | 808 | ||
808 | *retlen = 0; | 809 | *retlen = 0; |
809 | while (left) { | 810 | while (left) { |
@@ -873,7 +874,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, | |||
873 | printk(KERN_ERR "Error programming flash\n"); | 874 | printk(KERN_ERR "Error programming flash\n"); |
874 | /* Error in programming */ | 875 | /* Error in programming */ |
875 | *retlen = 0; | 876 | *retlen = 0; |
876 | up(&this->lock); | 877 | mutex_unlock(&this->lock); |
877 | return -EIO; | 878 | return -EIO; |
878 | } | 879 | } |
879 | 880 | ||
@@ -935,7 +936,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, | |||
935 | printk(KERN_ERR "Error programming flash\n"); | 936 | printk(KERN_ERR "Error programming flash\n"); |
936 | /* Error in programming */ | 937 | /* Error in programming */ |
937 | *retlen = 0; | 938 | *retlen = 0; |
938 | up(&this->lock); | 939 | mutex_unlock(&this->lock); |
939 | return -EIO; | 940 | return -EIO; |
940 | } | 941 | } |
941 | 942 | ||
@@ -956,7 +957,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, | |||
956 | 957 | ||
957 | ret = doc_write_oob_nolock(mtd, to, 8, &dummy, x); | 958 | ret = doc_write_oob_nolock(mtd, to, 8, &dummy, x); |
958 | if (ret) { | 959 | if (ret) { |
959 | up(&this->lock); | 960 | mutex_unlock(&this->lock); |
960 | return ret; | 961 | return ret; |
961 | } | 962 | } |
962 | } | 963 | } |
@@ -966,7 +967,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, | |||
966 | buf += len; | 967 | buf += len; |
967 | } | 968 | } |
968 | 969 | ||
969 | up(&this->lock); | 970 | mutex_unlock(&this->lock); |
970 | return 0; | 971 | return 0; |
971 | } | 972 | } |
972 | 973 | ||
@@ -975,13 +976,13 @@ static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, | |||
975 | u_char *eccbuf, struct nand_oobinfo *oobsel) | 976 | u_char *eccbuf, struct nand_oobinfo *oobsel) |
976 | { | 977 | { |
977 | static char static_buf[512]; | 978 | static char static_buf[512]; |
978 | static DECLARE_MUTEX(writev_buf_sem); | 979 | static DEFINE_MUTEX(writev_buf_mutex); |
979 | 980 | ||
980 | size_t totretlen = 0; | 981 | size_t totretlen = 0; |
981 | size_t thisvecofs = 0; | 982 | size_t thisvecofs = 0; |
982 | int ret= 0; | 983 | int ret= 0; |
983 | 984 | ||
984 | down(&writev_buf_sem); | 985 | mutex_lock(&writev_buf_mutex); |
985 | 986 | ||
986 | while(count) { | 987 | while(count) { |
987 | size_t thislen, thisretlen; | 988 | size_t thislen, thisretlen; |
@@ -1024,7 +1025,7 @@ static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, | |||
1024 | to += thislen; | 1025 | to += thislen; |
1025 | } | 1026 | } |
1026 | 1027 | ||
1027 | up(&writev_buf_sem); | 1028 | mutex_unlock(&writev_buf_mutex); |
1028 | *retlen = totretlen; | 1029 | *retlen = totretlen; |
1029 | return ret; | 1030 | return ret; |
1030 | } | 1031 | } |
@@ -1037,7 +1038,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, | |||
1037 | int len256 = 0, ret; | 1038 | int len256 = 0, ret; |
1038 | struct Nand *mychip; | 1039 | struct Nand *mychip; |
1039 | 1040 | ||
1040 | down(&this->lock); | 1041 | mutex_lock(&this->lock); |
1041 | 1042 | ||
1042 | mychip = &this->chips[ofs >> this->chipshift]; | 1043 | mychip = &this->chips[ofs >> this->chipshift]; |
1043 | 1044 | ||
@@ -1083,7 +1084,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, | |||
1083 | 1084 | ||
1084 | ret = DoC_WaitReady(this); | 1085 | ret = DoC_WaitReady(this); |
1085 | 1086 | ||
1086 | up(&this->lock); | 1087 | mutex_unlock(&this->lock); |
1087 | return ret; | 1088 | return ret; |
1088 | 1089 | ||
1089 | } | 1090 | } |
@@ -1197,10 +1198,10 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, | |||
1197 | struct DiskOnChip *this = mtd->priv; | 1198 | struct DiskOnChip *this = mtd->priv; |
1198 | int ret; | 1199 | int ret; |
1199 | 1200 | ||
1200 | down(&this->lock); | 1201 | mutex_lock(&this->lock); |
1201 | ret = doc_write_oob_nolock(mtd, ofs, len, retlen, buf); | 1202 | ret = doc_write_oob_nolock(mtd, ofs, len, retlen, buf); |
1202 | 1203 | ||
1203 | up(&this->lock); | 1204 | mutex_unlock(&this->lock); |
1204 | return ret; | 1205 | return ret; |
1205 | } | 1206 | } |
1206 | 1207 | ||
@@ -1214,10 +1215,10 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
1214 | struct Nand *mychip; | 1215 | struct Nand *mychip; |
1215 | int status; | 1216 | int status; |
1216 | 1217 | ||
1217 | down(&this->lock); | 1218 | mutex_lock(&this->lock); |
1218 | 1219 | ||
1219 | if (ofs & (mtd->erasesize-1) || len & (mtd->erasesize-1)) { | 1220 | if (ofs & (mtd->erasesize-1) || len & (mtd->erasesize-1)) { |
1220 | up(&this->lock); | 1221 | mutex_unlock(&this->lock); |
1221 | return -EINVAL; | 1222 | return -EINVAL; |
1222 | } | 1223 | } |
1223 | 1224 | ||
@@ -1265,7 +1266,7 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
1265 | callback: | 1266 | callback: |
1266 | mtd_erase_callback(instr); | 1267 | mtd_erase_callback(instr); |
1267 | 1268 | ||
1268 | up(&this->lock); | 1269 | mutex_unlock(&this->lock); |
1269 | return 0; | 1270 | return 0; |
1270 | } | 1271 | } |
1271 | 1272 | ||
diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c index 1e876fcb0408..29b0ddaa324e 100644 --- a/drivers/mtd/devices/lart.c +++ b/drivers/mtd/devices/lart.c | |||
@@ -581,8 +581,6 @@ static int flash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen | |||
581 | 581 | ||
582 | /***************************************************************************************************/ | 582 | /***************************************************************************************************/ |
583 | 583 | ||
584 | #define NB_OF(x) (sizeof (x) / sizeof (x[0])) | ||
585 | |||
586 | static struct mtd_info mtd; | 584 | static struct mtd_info mtd; |
587 | 585 | ||
588 | static struct mtd_erase_region_info erase_regions[] = { | 586 | static struct mtd_erase_region_info erase_regions[] = { |
@@ -640,7 +638,7 @@ int __init lart_flash_init (void) | |||
640 | mtd.flags = MTD_CAP_NORFLASH; | 638 | mtd.flags = MTD_CAP_NORFLASH; |
641 | mtd.size = FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM + FLASH_BLOCKSIZE_MAIN * FLASH_NUMBLOCKS_16m_MAIN; | 639 | mtd.size = FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM + FLASH_BLOCKSIZE_MAIN * FLASH_NUMBLOCKS_16m_MAIN; |
642 | mtd.erasesize = FLASH_BLOCKSIZE_MAIN; | 640 | mtd.erasesize = FLASH_BLOCKSIZE_MAIN; |
643 | mtd.numeraseregions = NB_OF (erase_regions); | 641 | mtd.numeraseregions = ARRAY_SIZE(erase_regions); |
644 | mtd.eraseregions = erase_regions; | 642 | mtd.eraseregions = erase_regions; |
645 | mtd.erase = flash_erase; | 643 | mtd.erase = flash_erase; |
646 | mtd.read = flash_read; | 644 | mtd.read = flash_read; |
@@ -670,9 +668,9 @@ int __init lart_flash_init (void) | |||
670 | result,mtd.eraseregions[result].numblocks); | 668 | result,mtd.eraseregions[result].numblocks); |
671 | 669 | ||
672 | #ifdef HAVE_PARTITIONS | 670 | #ifdef HAVE_PARTITIONS |
673 | printk ("\npartitions = %d\n",NB_OF (lart_partitions)); | 671 | printk ("\npartitions = %d\n", ARRAY_SIZE(lart_partitions)); |
674 | 672 | ||
675 | for (result = 0; result < NB_OF (lart_partitions); result++) | 673 | for (result = 0; result < ARRAY_SIZE(lart_partitions); result++) |
676 | printk (KERN_DEBUG | 674 | printk (KERN_DEBUG |
677 | "\n\n" | 675 | "\n\n" |
678 | "lart_partitions[%d].name = %s\n" | 676 | "lart_partitions[%d].name = %s\n" |
@@ -687,7 +685,7 @@ int __init lart_flash_init (void) | |||
687 | #ifndef HAVE_PARTITIONS | 685 | #ifndef HAVE_PARTITIONS |
688 | result = add_mtd_device (&mtd); | 686 | result = add_mtd_device (&mtd); |
689 | #else | 687 | #else |
690 | result = add_mtd_partitions (&mtd,lart_partitions,NB_OF (lart_partitions)); | 688 | result = add_mtd_partitions (&mtd,lart_partitions, ARRAY_SIZE(lart_partitions)); |
691 | #endif | 689 | #endif |
692 | 690 | ||
693 | return (result); | 691 | return (result); |
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index d5f24089be71..04e65d5dae00 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -186,7 +186,7 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
186 | struct m25p *flash = mtd_to_m25p(mtd); | 186 | struct m25p *flash = mtd_to_m25p(mtd); |
187 | u32 addr,len; | 187 | u32 addr,len; |
188 | 188 | ||
189 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", | 189 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n", |
190 | flash->spi->dev.bus_id, __FUNCTION__, "at", | 190 | flash->spi->dev.bus_id, __FUNCTION__, "at", |
191 | (u32)instr->addr, instr->len); | 191 | (u32)instr->addr, instr->len); |
192 | 192 | ||
diff --git a/drivers/mtd/devices/ms02-nv.c b/drivers/mtd/devices/ms02-nv.c index 0ff2e4378244..485f663493d2 100644 --- a/drivers/mtd/devices/ms02-nv.c +++ b/drivers/mtd/devices/ms02-nv.c | |||
@@ -308,7 +308,7 @@ static int __init ms02nv_init(void) | |||
308 | break; | 308 | break; |
309 | } | 309 | } |
310 | 310 | ||
311 | for (i = 0; i < (sizeof(ms02nv_addrs) / sizeof(*ms02nv_addrs)); i++) | 311 | for (i = 0; i < ARRAY_SIZE(ms02nv_addrs); i++) |
312 | if (!ms02nv_init_one(ms02nv_addrs[i] << stride)) | 312 | if (!ms02nv_init_one(ms02nv_addrs[i] << stride)) |
313 | count++; | 313 | count++; |
314 | 314 | ||
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c index 8a544890173d..a3b92479719d 100644 --- a/drivers/mtd/inftlcore.c +++ b/drivers/mtd/inftlcore.c | |||
@@ -47,9 +47,6 @@ | |||
47 | */ | 47 | */ |
48 | #define MAX_LOOPS 10000 | 48 | #define MAX_LOOPS 10000 |
49 | 49 | ||
50 | extern void INFTL_dumptables(struct INFTLrecord *inftl); | ||
51 | extern void INFTL_dumpVUchains(struct INFTLrecord *inftl); | ||
52 | |||
53 | static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) | 50 | static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) |
54 | { | 51 | { |
55 | struct INFTLrecord *inftl; | 52 | struct INFTLrecord *inftl; |
@@ -132,7 +129,7 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) | |||
132 | return; | 129 | return; |
133 | } | 130 | } |
134 | #ifdef PSYCHO_DEBUG | 131 | #ifdef PSYCHO_DEBUG |
135 | printk(KERN_INFO "INFTL: Found new nftl%c\n", nftl->mbd.devnum + 'a'); | 132 | printk(KERN_INFO "INFTL: Found new inftl%c\n", inftl->mbd.devnum + 'a'); |
136 | #endif | 133 | #endif |
137 | return; | 134 | return; |
138 | } | 135 | } |
@@ -885,8 +882,6 @@ static struct mtd_blktrans_ops inftl_tr = { | |||
885 | .owner = THIS_MODULE, | 882 | .owner = THIS_MODULE, |
886 | }; | 883 | }; |
887 | 884 | ||
888 | extern char inftlmountrev[]; | ||
889 | |||
890 | static int __init init_inftl(void) | 885 | static int __init init_inftl(void) |
891 | { | 886 | { |
892 | printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.19 $, " | 887 | printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.19 $, " |
diff --git a/drivers/mtd/maps/alchemy-flash.c b/drivers/mtd/maps/alchemy-flash.c index a57791a6ce40..b933a2a27b18 100644 --- a/drivers/mtd/maps/alchemy-flash.c +++ b/drivers/mtd/maps/alchemy-flash.c | |||
@@ -126,8 +126,6 @@ static struct mtd_partition alchemy_partitions[] = { | |||
126 | } | 126 | } |
127 | }; | 127 | }; |
128 | 128 | ||
129 | #define NB_OF(x) (sizeof(x)/sizeof(x[0])) | ||
130 | |||
131 | static struct mtd_info *mymtd; | 129 | static struct mtd_info *mymtd; |
132 | 130 | ||
133 | int __init alchemy_mtd_init(void) | 131 | int __init alchemy_mtd_init(void) |
@@ -154,7 +152,7 @@ int __init alchemy_mtd_init(void) | |||
154 | * Static partition definition selection | 152 | * Static partition definition selection |
155 | */ | 153 | */ |
156 | parts = alchemy_partitions; | 154 | parts = alchemy_partitions; |
157 | nb_parts = NB_OF(alchemy_partitions); | 155 | nb_parts = ARRAY_SIZE(alchemy_partitions); |
158 | alchemy_map.size = window_size; | 156 | alchemy_map.size = window_size; |
159 | 157 | ||
160 | /* | 158 | /* |
diff --git a/drivers/mtd/maps/cfi_flagadm.c b/drivers/mtd/maps/cfi_flagadm.c index 6a8c0415bde8..fd0f0d3187de 100644 --- a/drivers/mtd/maps/cfi_flagadm.c +++ b/drivers/mtd/maps/cfi_flagadm.c | |||
@@ -86,7 +86,7 @@ struct mtd_partition flagadm_parts[] = { | |||
86 | } | 86 | } |
87 | }; | 87 | }; |
88 | 88 | ||
89 | #define PARTITION_COUNT (sizeof(flagadm_parts)/sizeof(struct mtd_partition)) | 89 | #define PARTITION_COUNT ARRAY_SIZE(flagadm_parts) |
90 | 90 | ||
91 | static struct mtd_info *mymtd; | 91 | static struct mtd_info *mymtd; |
92 | 92 | ||
diff --git a/drivers/mtd/maps/dbox2-flash.c b/drivers/mtd/maps/dbox2-flash.c index 49d90542fc75..652813cd6c2d 100644 --- a/drivers/mtd/maps/dbox2-flash.c +++ b/drivers/mtd/maps/dbox2-flash.c | |||
@@ -57,7 +57,7 @@ static struct mtd_partition partition_info[]= { | |||
57 | } | 57 | } |
58 | }; | 58 | }; |
59 | 59 | ||
60 | #define NUM_PARTITIONS (sizeof(partition_info) / sizeof(partition_info[0])) | 60 | #define NUM_PARTITIONS ARRAY_SIZE(partition_info) |
61 | 61 | ||
62 | #define WINDOW_ADDR 0x10000000 | 62 | #define WINDOW_ADDR 0x10000000 |
63 | #define WINDOW_SIZE 0x800000 | 63 | #define WINDOW_SIZE 0x800000 |
diff --git a/drivers/mtd/maps/dilnetpc.c b/drivers/mtd/maps/dilnetpc.c index efb221692641..c299d10b33e6 100644 --- a/drivers/mtd/maps/dilnetpc.c +++ b/drivers/mtd/maps/dilnetpc.c | |||
@@ -300,7 +300,7 @@ static struct mtd_partition partition_info[]= | |||
300 | }, | 300 | }, |
301 | }; | 301 | }; |
302 | 302 | ||
303 | #define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0])) | 303 | #define NUM_PARTITIONS ARRAY_SIZE(partition_info) |
304 | 304 | ||
305 | static struct mtd_info *mymtd; | 305 | static struct mtd_info *mymtd; |
306 | static struct mtd_info *lowlvl_parts[NUM_PARTITIONS]; | 306 | static struct mtd_info *lowlvl_parts[NUM_PARTITIONS]; |
@@ -345,7 +345,7 @@ static struct mtd_partition higlvl_partition_info[]= | |||
345 | }, | 345 | }, |
346 | }; | 346 | }; |
347 | 347 | ||
348 | #define NUM_HIGHLVL_PARTITIONS (sizeof(higlvl_partition_info)/sizeof(partition_info[0])) | 348 | #define NUM_HIGHLVL_PARTITIONS ARRAY_SIZE(higlvl_partition_info) |
349 | 349 | ||
350 | 350 | ||
351 | static int dnp_adnp_probe(void) | 351 | static int dnp_adnp_probe(void) |
diff --git a/drivers/mtd/maps/dmv182.c b/drivers/mtd/maps/dmv182.c index b993ac01a9a5..2bb3c0f0f970 100644 --- a/drivers/mtd/maps/dmv182.c +++ b/drivers/mtd/maps/dmv182.c | |||
@@ -99,7 +99,7 @@ static struct mtd_info *this_mtd; | |||
99 | static int __init init_svme182(void) | 99 | static int __init init_svme182(void) |
100 | { | 100 | { |
101 | struct mtd_partition *partitions; | 101 | struct mtd_partition *partitions; |
102 | int num_parts = sizeof(svme182_partitions) / sizeof(struct mtd_partition); | 102 | int num_parts = ARRAY_SIZE(svme182_partitions); |
103 | 103 | ||
104 | partitions = svme182_partitions; | 104 | partitions = svme182_partitions; |
105 | 105 | ||
diff --git a/drivers/mtd/maps/h720x-flash.c b/drivers/mtd/maps/h720x-flash.c index 319094821101..0667101ccbe1 100644 --- a/drivers/mtd/maps/h720x-flash.c +++ b/drivers/mtd/maps/h720x-flash.c | |||
@@ -59,7 +59,7 @@ static struct mtd_partition h720x_partitions[] = { | |||
59 | } | 59 | } |
60 | }; | 60 | }; |
61 | 61 | ||
62 | #define NUM_PARTITIONS (sizeof(h720x_partitions)/sizeof(h720x_partitions[0])) | 62 | #define NUM_PARTITIONS ARRAY_SIZE(h720x_partitions) |
63 | 63 | ||
64 | static int nr_mtd_parts; | 64 | static int nr_mtd_parts; |
65 | static struct mtd_partition *mtd_parts; | 65 | static struct mtd_partition *mtd_parts; |
diff --git a/drivers/mtd/maps/netsc520.c b/drivers/mtd/maps/netsc520.c index 33060a315722..ed215470158b 100644 --- a/drivers/mtd/maps/netsc520.c +++ b/drivers/mtd/maps/netsc520.c | |||
@@ -76,7 +76,7 @@ static struct mtd_partition partition_info[]={ | |||
76 | .size = 0x80000 | 76 | .size = 0x80000 |
77 | }, | 77 | }, |
78 | }; | 78 | }; |
79 | #define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0])) | 79 | #define NUM_PARTITIONS ARRAY_SIZE(partition_info) |
80 | 80 | ||
81 | #define WINDOW_SIZE 0x00100000 | 81 | #define WINDOW_SIZE 0x00100000 |
82 | #define WINDOW_ADDR 0x00200000 | 82 | #define WINDOW_ADDR 0x00200000 |
@@ -88,7 +88,7 @@ static struct map_info netsc520_map = { | |||
88 | .phys = WINDOW_ADDR, | 88 | .phys = WINDOW_ADDR, |
89 | }; | 89 | }; |
90 | 90 | ||
91 | #define NUM_FLASH_BANKS (sizeof(netsc520_map)/sizeof(struct map_info)) | 91 | #define NUM_FLASH_BANKS ARRAY_SIZE(netsc520_map) |
92 | 92 | ||
93 | static struct mtd_info *mymtd; | 93 | static struct mtd_info *mymtd; |
94 | 94 | ||
diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c index 632eb2aa968f..54a3102ab19a 100644 --- a/drivers/mtd/maps/nettel.c +++ b/drivers/mtd/maps/nettel.c | |||
@@ -128,8 +128,7 @@ static struct mtd_partition nettel_amd_partitions[] = { | |||
128 | } | 128 | } |
129 | }; | 129 | }; |
130 | 130 | ||
131 | #define NUM_AMD_PARTITIONS \ | 131 | #define NUM_AMD_PARTITIONS ARRAY_SIZE(nettel_amd_partitions) |
132 | (sizeof(nettel_amd_partitions)/sizeof(nettel_amd_partitions[0])) | ||
133 | 132 | ||
134 | /****************************************************************************/ | 133 | /****************************************************************************/ |
135 | 134 | ||
diff --git a/drivers/mtd/maps/ocotea.c b/drivers/mtd/maps/ocotea.c index c223514ca2eb..a21fcd195ab4 100644 --- a/drivers/mtd/maps/ocotea.c +++ b/drivers/mtd/maps/ocotea.c | |||
@@ -58,8 +58,6 @@ static struct mtd_partition ocotea_large_partitions[] = { | |||
58 | } | 58 | } |
59 | }; | 59 | }; |
60 | 60 | ||
61 | #define NB_OF(x) (sizeof(x)/sizeof(x[0])) | ||
62 | |||
63 | int __init init_ocotea(void) | 61 | int __init init_ocotea(void) |
64 | { | 62 | { |
65 | u8 fpga0_reg; | 63 | u8 fpga0_reg; |
@@ -97,7 +95,7 @@ int __init init_ocotea(void) | |||
97 | if (flash) { | 95 | if (flash) { |
98 | flash->owner = THIS_MODULE; | 96 | flash->owner = THIS_MODULE; |
99 | add_mtd_partitions(flash, ocotea_small_partitions, | 97 | add_mtd_partitions(flash, ocotea_small_partitions, |
100 | NB_OF(ocotea_small_partitions)); | 98 | ARRAY_SIZE(ocotea_small_partitions)); |
101 | } else { | 99 | } else { |
102 | printk("map probe failed for flash\n"); | 100 | printk("map probe failed for flash\n"); |
103 | return -ENXIO; | 101 | return -ENXIO; |
@@ -118,7 +116,7 @@ int __init init_ocotea(void) | |||
118 | if (flash) { | 116 | if (flash) { |
119 | flash->owner = THIS_MODULE; | 117 | flash->owner = THIS_MODULE; |
120 | add_mtd_partitions(flash, ocotea_large_partitions, | 118 | add_mtd_partitions(flash, ocotea_large_partitions, |
121 | NB_OF(ocotea_large_partitions)); | 119 | ARRAY_SIZE(ocotea_large_partitions)); |
122 | } else { | 120 | } else { |
123 | printk("map probe failed for flash\n"); | 121 | printk("map probe failed for flash\n"); |
124 | return -ENXIO; | 122 | return -ENXIO; |
diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c index 21822c2edbe4..d2ab1bae9c34 100644 --- a/drivers/mtd/maps/pci.c +++ b/drivers/mtd/maps/pci.c | |||
@@ -334,9 +334,6 @@ mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
334 | return 0; | 334 | return 0; |
335 | 335 | ||
336 | release: | 336 | release: |
337 | if (mtd) | ||
338 | map_destroy(mtd); | ||
339 | |||
340 | if (map) { | 337 | if (map) { |
341 | map->exit(dev, map); | 338 | map->exit(dev, map); |
342 | kfree(map); | 339 | kfree(map); |
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index f988c817e196..d27f4129afd3 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c | |||
@@ -54,7 +54,7 @@ static const int debug = 0; | |||
54 | #define MAX_PCMCIA_ADDR 0x4000000 | 54 | #define MAX_PCMCIA_ADDR 0x4000000 |
55 | 55 | ||
56 | struct pcmciamtd_dev { | 56 | struct pcmciamtd_dev { |
57 | dev_link_t link; /* PCMCIA link */ | 57 | struct pcmcia_device *p_dev; |
58 | dev_node_t node; /* device node */ | 58 | dev_node_t node; /* device node */ |
59 | caddr_t win_base; /* ioremapped address of PCMCIA window */ | 59 | caddr_t win_base; /* ioremapped address of PCMCIA window */ |
60 | unsigned int win_size; /* size of window */ | 60 | unsigned int win_size; /* size of window */ |
@@ -111,8 +111,8 @@ static caddr_t remap_window(struct map_info *map, unsigned long to) | |||
111 | memreq_t mrq; | 111 | memreq_t mrq; |
112 | int ret; | 112 | int ret; |
113 | 113 | ||
114 | if(!(dev->link.state & DEV_PRESENT)) { | 114 | if (!pcmcia_dev_present(dev->p_dev)) { |
115 | DEBUG(1, "device removed state = 0x%4.4X", dev->link.state); | 115 | DEBUG(1, "device removed"); |
116 | return 0; | 116 | return 0; |
117 | } | 117 | } |
118 | 118 | ||
@@ -122,7 +122,7 @@ static caddr_t remap_window(struct map_info *map, unsigned long to) | |||
122 | dev->offset, mrq.CardOffset); | 122 | dev->offset, mrq.CardOffset); |
123 | mrq.Page = 0; | 123 | mrq.Page = 0; |
124 | if( (ret = pcmcia_map_mem_page(win, &mrq)) != CS_SUCCESS) { | 124 | if( (ret = pcmcia_map_mem_page(win, &mrq)) != CS_SUCCESS) { |
125 | cs_error(dev->link.handle, MapMemPage, ret); | 125 | cs_error(dev->p_dev, MapMemPage, ret); |
126 | return NULL; | 126 | return NULL; |
127 | } | 127 | } |
128 | dev->offset = mrq.CardOffset; | 128 | dev->offset = mrq.CardOffset; |
@@ -238,7 +238,7 @@ static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const v | |||
238 | 238 | ||
239 | /* read/write{8,16} copy_{from,to} routines with direct access */ | 239 | /* read/write{8,16} copy_{from,to} routines with direct access */ |
240 | 240 | ||
241 | #define DEV_REMOVED(x) (!(*(u_int *)x->map_priv_1 & DEV_PRESENT)) | 241 | #define DEV_REMOVED(x) (!(pcmcia_dev_present(((struct pcmciamtd_dev *)map->map_priv_1)->p_dev))) |
242 | 242 | ||
243 | static map_word pcmcia_read8(struct map_info *map, unsigned long ofs) | 243 | static map_word pcmcia_read8(struct map_info *map, unsigned long ofs) |
244 | { | 244 | { |
@@ -319,7 +319,7 @@ static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *f | |||
319 | static void pcmciamtd_set_vpp(struct map_info *map, int on) | 319 | static void pcmciamtd_set_vpp(struct map_info *map, int on) |
320 | { | 320 | { |
321 | struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; | 321 | struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; |
322 | dev_link_t *link = &dev->link; | 322 | struct pcmcia_device *link = dev->p_dev; |
323 | modconf_t mod; | 323 | modconf_t mod; |
324 | int ret; | 324 | int ret; |
325 | 325 | ||
@@ -328,9 +328,9 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on) | |||
328 | mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0; | 328 | mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0; |
329 | 329 | ||
330 | DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp); | 330 | DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp); |
331 | ret = pcmcia_modify_configuration(link->handle, &mod); | 331 | ret = pcmcia_modify_configuration(link, &mod); |
332 | if(ret != CS_SUCCESS) { | 332 | if(ret != CS_SUCCESS) { |
333 | cs_error(link->handle, ModifyConfiguration, ret); | 333 | cs_error(link, ModifyConfiguration, ret); |
334 | } | 334 | } |
335 | } | 335 | } |
336 | 336 | ||
@@ -340,7 +340,7 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on) | |||
340 | * still open, this will be postponed until it is closed. | 340 | * still open, this will be postponed until it is closed. |
341 | */ | 341 | */ |
342 | 342 | ||
343 | static void pcmciamtd_release(dev_link_t *link) | 343 | static void pcmciamtd_release(struct pcmcia_device *link) |
344 | { | 344 | { |
345 | struct pcmciamtd_dev *dev = link->priv; | 345 | struct pcmciamtd_dev *dev = link->priv; |
346 | 346 | ||
@@ -353,12 +353,11 @@ static void pcmciamtd_release(dev_link_t *link) | |||
353 | } | 353 | } |
354 | pcmcia_release_window(link->win); | 354 | pcmcia_release_window(link->win); |
355 | } | 355 | } |
356 | pcmcia_release_configuration(link->handle); | 356 | pcmcia_disable_device(link); |
357 | link->state &= ~DEV_CONFIG; | ||
358 | } | 357 | } |
359 | 358 | ||
360 | 359 | ||
361 | static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_name) | 360 | static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *link, int *new_name) |
362 | { | 361 | { |
363 | int rc; | 362 | int rc; |
364 | tuple_t tuple; | 363 | tuple_t tuple; |
@@ -371,16 +370,16 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_ | |||
371 | tuple.TupleOffset = 0; | 370 | tuple.TupleOffset = 0; |
372 | tuple.DesiredTuple = RETURN_FIRST_TUPLE; | 371 | tuple.DesiredTuple = RETURN_FIRST_TUPLE; |
373 | 372 | ||
374 | rc = pcmcia_get_first_tuple(link->handle, &tuple); | 373 | rc = pcmcia_get_first_tuple(link, &tuple); |
375 | while(rc == CS_SUCCESS) { | 374 | while(rc == CS_SUCCESS) { |
376 | rc = pcmcia_get_tuple_data(link->handle, &tuple); | 375 | rc = pcmcia_get_tuple_data(link, &tuple); |
377 | if(rc != CS_SUCCESS) { | 376 | if(rc != CS_SUCCESS) { |
378 | cs_error(link->handle, GetTupleData, rc); | 377 | cs_error(link, GetTupleData, rc); |
379 | break; | 378 | break; |
380 | } | 379 | } |
381 | rc = pcmcia_parse_tuple(link->handle, &tuple, &parse); | 380 | rc = pcmcia_parse_tuple(link, &tuple, &parse); |
382 | if(rc != CS_SUCCESS) { | 381 | if(rc != CS_SUCCESS) { |
383 | cs_error(link->handle, ParseTuple, rc); | 382 | cs_error(link, ParseTuple, rc); |
384 | break; | 383 | break; |
385 | } | 384 | } |
386 | 385 | ||
@@ -451,7 +450,7 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_ | |||
451 | DEBUG(2, "Unknown tuple code %d", tuple.TupleCode); | 450 | DEBUG(2, "Unknown tuple code %d", tuple.TupleCode); |
452 | } | 451 | } |
453 | 452 | ||
454 | rc = pcmcia_get_next_tuple(link->handle, &tuple); | 453 | rc = pcmcia_get_next_tuple(link, &tuple); |
455 | } | 454 | } |
456 | if(!dev->pcmcia_map.size) | 455 | if(!dev->pcmcia_map.size) |
457 | dev->pcmcia_map.size = MAX_PCMCIA_ADDR; | 456 | dev->pcmcia_map.size = MAX_PCMCIA_ADDR; |
@@ -488,7 +487,7 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_ | |||
488 | #define CS_CHECK(fn, ret) \ | 487 | #define CS_CHECK(fn, ret) \ |
489 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 488 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
490 | 489 | ||
491 | static void pcmciamtd_config(dev_link_t *link) | 490 | static int pcmciamtd_config(struct pcmcia_device *link) |
492 | { | 491 | { |
493 | struct pcmciamtd_dev *dev = link->priv; | 492 | struct pcmciamtd_dev *dev = link->priv; |
494 | struct mtd_info *mtd = NULL; | 493 | struct mtd_info *mtd = NULL; |
@@ -504,13 +503,10 @@ static void pcmciamtd_config(dev_link_t *link) | |||
504 | 503 | ||
505 | DEBUG(3, "link=0x%p", link); | 504 | DEBUG(3, "link=0x%p", link); |
506 | 505 | ||
507 | /* Configure card */ | ||
508 | link->state |= DEV_CONFIG; | ||
509 | |||
510 | DEBUG(2, "Validating CIS"); | 506 | DEBUG(2, "Validating CIS"); |
511 | ret = pcmcia_validate_cis(link->handle, &cisinfo); | 507 | ret = pcmcia_validate_cis(link, &cisinfo); |
512 | if(ret != CS_SUCCESS) { | 508 | if(ret != CS_SUCCESS) { |
513 | cs_error(link->handle, GetTupleData, ret); | 509 | cs_error(link, GetTupleData, ret); |
514 | } else { | 510 | } else { |
515 | DEBUG(2, "ValidateCIS found %d chains", cisinfo.Chains); | 511 | DEBUG(2, "ValidateCIS found %d chains", cisinfo.Chains); |
516 | } | 512 | } |
@@ -538,7 +534,7 @@ static void pcmciamtd_config(dev_link_t *link) | |||
538 | req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16; | 534 | req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16; |
539 | req.Base = 0; | 535 | req.Base = 0; |
540 | req.AccessSpeed = mem_speed; | 536 | req.AccessSpeed = mem_speed; |
541 | link->win = (window_handle_t)link->handle; | 537 | link->win = (window_handle_t)link; |
542 | req.Size = (force_size) ? force_size << 20 : MAX_PCMCIA_ADDR; | 538 | req.Size = (force_size) ? force_size << 20 : MAX_PCMCIA_ADDR; |
543 | dev->win_size = 0; | 539 | dev->win_size = 0; |
544 | 540 | ||
@@ -546,7 +542,7 @@ static void pcmciamtd_config(dev_link_t *link) | |||
546 | int ret; | 542 | int ret; |
547 | DEBUG(2, "requesting window with size = %dKiB memspeed = %d", | 543 | DEBUG(2, "requesting window with size = %dKiB memspeed = %d", |
548 | req.Size >> 10, req.AccessSpeed); | 544 | req.Size >> 10, req.AccessSpeed); |
549 | ret = pcmcia_request_window(&link->handle, &req, &link->win); | 545 | ret = pcmcia_request_window(&link, &req, &link->win); |
550 | DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size); | 546 | DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size); |
551 | if(ret) { | 547 | if(ret) { |
552 | req.Size >>= 1; | 548 | req.Size >>= 1; |
@@ -562,19 +558,19 @@ static void pcmciamtd_config(dev_link_t *link) | |||
562 | if(!dev->win_size) { | 558 | if(!dev->win_size) { |
563 | err("Cant allocate memory window"); | 559 | err("Cant allocate memory window"); |
564 | pcmciamtd_release(link); | 560 | pcmciamtd_release(link); |
565 | return; | 561 | return -ENODEV; |
566 | } | 562 | } |
567 | DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10); | 563 | DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10); |
568 | 564 | ||
569 | /* Get write protect status */ | 565 | /* Get write protect status */ |
570 | CS_CHECK(GetStatus, pcmcia_get_status(link->handle, &status)); | 566 | CS_CHECK(GetStatus, pcmcia_get_status(link, &status)); |
571 | DEBUG(2, "status value: 0x%x window handle = 0x%8.8lx", | 567 | DEBUG(2, "status value: 0x%x window handle = 0x%8.8lx", |
572 | status.CardState, (unsigned long)link->win); | 568 | status.CardState, (unsigned long)link->win); |
573 | dev->win_base = ioremap(req.Base, req.Size); | 569 | dev->win_base = ioremap(req.Base, req.Size); |
574 | if(!dev->win_base) { | 570 | if(!dev->win_base) { |
575 | err("ioremap(%lu, %u) failed", req.Base, req.Size); | 571 | err("ioremap(%lu, %u) failed", req.Base, req.Size); |
576 | pcmciamtd_release(link); | 572 | pcmciamtd_release(link); |
577 | return; | 573 | return -ENODEV; |
578 | } | 574 | } |
579 | DEBUG(1, "mapped window dev = %p req.base = 0x%lx base = %p size = 0x%x", | 575 | DEBUG(1, "mapped window dev = %p req.base = 0x%lx base = %p size = 0x%x", |
580 | dev, req.Base, dev->win_base, req.Size); | 576 | dev, req.Base, dev->win_base, req.Size); |
@@ -584,17 +580,14 @@ static void pcmciamtd_config(dev_link_t *link) | |||
584 | dev->pcmcia_map.map_priv_2 = (unsigned long)link->win; | 580 | dev->pcmcia_map.map_priv_2 = (unsigned long)link->win; |
585 | 581 | ||
586 | DEBUG(2, "Getting configuration"); | 582 | DEBUG(2, "Getting configuration"); |
587 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link->handle, &t)); | 583 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &t)); |
588 | DEBUG(2, "Vcc = %d Vpp1 = %d Vpp2 = %d", t.Vcc, t.Vpp1, t.Vpp2); | 584 | DEBUG(2, "Vcc = %d Vpp1 = %d Vpp2 = %d", t.Vcc, t.Vpp1, t.Vpp2); |
589 | dev->vpp = (vpp) ? vpp : t.Vpp1; | 585 | dev->vpp = (vpp) ? vpp : t.Vpp1; |
590 | link->conf.Attributes = 0; | 586 | link->conf.Attributes = 0; |
591 | link->conf.Vcc = t.Vcc; | ||
592 | if(setvpp == 2) { | 587 | if(setvpp == 2) { |
593 | link->conf.Vpp1 = dev->vpp; | 588 | link->conf.Vpp = dev->vpp; |
594 | link->conf.Vpp2 = dev->vpp; | ||
595 | } else { | 589 | } else { |
596 | link->conf.Vpp1 = 0; | 590 | link->conf.Vpp = 0; |
597 | link->conf.Vpp2 = 0; | ||
598 | } | 591 | } |
599 | 592 | ||
600 | link->conf.IntType = INT_MEMORY; | 593 | link->conf.IntType = INT_MEMORY; |
@@ -606,9 +599,10 @@ static void pcmciamtd_config(dev_link_t *link) | |||
606 | link->conf.ConfigIndex = 0; | 599 | link->conf.ConfigIndex = 0; |
607 | link->conf.Present = t.Present; | 600 | link->conf.Present = t.Present; |
608 | DEBUG(2, "Setting Configuration"); | 601 | DEBUG(2, "Setting Configuration"); |
609 | ret = pcmcia_request_configuration(link->handle, &link->conf); | 602 | ret = pcmcia_request_configuration(link, &link->conf); |
610 | if(ret != CS_SUCCESS) { | 603 | if(ret != CS_SUCCESS) { |
611 | cs_error(link->handle, RequestConfiguration, ret); | 604 | cs_error(link, RequestConfiguration, ret); |
605 | return -ENODEV; | ||
612 | } | 606 | } |
613 | 607 | ||
614 | if(mem_type == 1) { | 608 | if(mem_type == 1) { |
@@ -616,7 +610,7 @@ static void pcmciamtd_config(dev_link_t *link) | |||
616 | } else if(mem_type == 2) { | 610 | } else if(mem_type == 2) { |
617 | mtd = do_map_probe("map_rom", &dev->pcmcia_map); | 611 | mtd = do_map_probe("map_rom", &dev->pcmcia_map); |
618 | } else { | 612 | } else { |
619 | for(i = 0; i < sizeof(probes) / sizeof(char *); i++) { | 613 | for(i = 0; i < ARRAY_SIZE(probes); i++) { |
620 | DEBUG(1, "Trying %s", probes[i]); | 614 | DEBUG(1, "Trying %s", probes[i]); |
621 | mtd = do_map_probe(probes[i], &dev->pcmcia_map); | 615 | mtd = do_map_probe(probes[i], &dev->pcmcia_map); |
622 | if(mtd) | 616 | if(mtd) |
@@ -629,7 +623,7 @@ static void pcmciamtd_config(dev_link_t *link) | |||
629 | if(!mtd) { | 623 | if(!mtd) { |
630 | DEBUG(1, "Cant find an MTD"); | 624 | DEBUG(1, "Cant find an MTD"); |
631 | pcmciamtd_release(link); | 625 | pcmciamtd_release(link); |
632 | return; | 626 | return -ENODEV; |
633 | } | 627 | } |
634 | 628 | ||
635 | dev->mtd_info = mtd; | 629 | dev->mtd_info = mtd; |
@@ -654,7 +648,6 @@ static void pcmciamtd_config(dev_link_t *link) | |||
654 | use the faster non-remapping read/write functions */ | 648 | use the faster non-remapping read/write functions */ |
655 | if(mtd->size <= dev->win_size) { | 649 | if(mtd->size <= dev->win_size) { |
656 | DEBUG(1, "Using non remapping memory functions"); | 650 | DEBUG(1, "Using non remapping memory functions"); |
657 | dev->pcmcia_map.map_priv_1 = (unsigned long)&(dev->link.state); | ||
658 | dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base; | 651 | dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base; |
659 | if (dev->pcmcia_map.bankwidth == 1) { | 652 | if (dev->pcmcia_map.bankwidth == 1) { |
660 | dev->pcmcia_map.read = pcmcia_read8; | 653 | dev->pcmcia_map.read = pcmcia_read8; |
@@ -672,19 +665,18 @@ static void pcmciamtd_config(dev_link_t *link) | |||
672 | dev->mtd_info = NULL; | 665 | dev->mtd_info = NULL; |
673 | err("Couldnt register MTD device"); | 666 | err("Couldnt register MTD device"); |
674 | pcmciamtd_release(link); | 667 | pcmciamtd_release(link); |
675 | return; | 668 | return -ENODEV; |
676 | } | 669 | } |
677 | snprintf(dev->node.dev_name, sizeof(dev->node.dev_name), "mtd%d", mtd->index); | 670 | snprintf(dev->node.dev_name, sizeof(dev->node.dev_name), "mtd%d", mtd->index); |
678 | info("mtd%d: %s", mtd->index, mtd->name); | 671 | info("mtd%d: %s", mtd->index, mtd->name); |
679 | link->state &= ~DEV_CONFIG_PENDING; | 672 | link->dev_node = &dev->node; |
680 | link->dev = &dev->node; | 673 | return 0; |
681 | return; | ||
682 | 674 | ||
683 | cs_failed: | 675 | cs_failed: |
684 | cs_error(link->handle, last_fn, last_ret); | 676 | cs_error(link, last_fn, last_ret); |
685 | err("CS Error, exiting"); | 677 | err("CS Error, exiting"); |
686 | pcmciamtd_release(link); | 678 | pcmciamtd_release(link); |
687 | return; | 679 | return -ENODEV; |
688 | } | 680 | } |
689 | 681 | ||
690 | 682 | ||
@@ -713,21 +705,18 @@ static int pcmciamtd_resume(struct pcmcia_device *dev) | |||
713 | * when the device is released. | 705 | * when the device is released. |
714 | */ | 706 | */ |
715 | 707 | ||
716 | static void pcmciamtd_detach(struct pcmcia_device *p_dev) | 708 | static void pcmciamtd_detach(struct pcmcia_device *link) |
717 | { | 709 | { |
718 | dev_link_t *link = dev_to_instance(p_dev); | 710 | struct pcmciamtd_dev *dev = link->priv; |
719 | 711 | ||
720 | DEBUG(3, "link=0x%p", link); | 712 | DEBUG(3, "link=0x%p", link); |
721 | 713 | ||
722 | if(link->state & DEV_CONFIG) { | 714 | if(dev->mtd_info) { |
723 | struct pcmciamtd_dev *dev = link->priv; | 715 | del_mtd_device(dev->mtd_info); |
724 | if(dev->mtd_info) { | 716 | info("mtd%d: Removed", dev->mtd_info->index); |
725 | del_mtd_device(dev->mtd_info); | ||
726 | info("mtd%d: Removed", dev->mtd_info->index); | ||
727 | } | ||
728 | |||
729 | pcmciamtd_release(link); | ||
730 | } | 717 | } |
718 | |||
719 | pcmciamtd_release(link); | ||
731 | } | 720 | } |
732 | 721 | ||
733 | 722 | ||
@@ -736,10 +725,9 @@ static void pcmciamtd_detach(struct pcmcia_device *p_dev) | |||
736 | * with Card Services. | 725 | * with Card Services. |
737 | */ | 726 | */ |
738 | 727 | ||
739 | static int pcmciamtd_attach(struct pcmcia_device *p_dev) | 728 | static int pcmciamtd_probe(struct pcmcia_device *link) |
740 | { | 729 | { |
741 | struct pcmciamtd_dev *dev; | 730 | struct pcmciamtd_dev *dev; |
742 | dev_link_t *link; | ||
743 | 731 | ||
744 | /* Create new memory card device */ | 732 | /* Create new memory card device */ |
745 | dev = kmalloc(sizeof(*dev), GFP_KERNEL); | 733 | dev = kmalloc(sizeof(*dev), GFP_KERNEL); |
@@ -747,20 +735,13 @@ static int pcmciamtd_attach(struct pcmcia_device *p_dev) | |||
747 | DEBUG(1, "dev=0x%p", dev); | 735 | DEBUG(1, "dev=0x%p", dev); |
748 | 736 | ||
749 | memset(dev, 0, sizeof(*dev)); | 737 | memset(dev, 0, sizeof(*dev)); |
750 | link = &dev->link; | 738 | dev->p_dev = link; |
751 | link->priv = dev; | 739 | link->priv = dev; |
752 | 740 | ||
753 | link->conf.Attributes = 0; | 741 | link->conf.Attributes = 0; |
754 | link->conf.IntType = INT_MEMORY; | 742 | link->conf.IntType = INT_MEMORY; |
755 | 743 | ||
756 | link->next = NULL; | 744 | return pcmciamtd_config(link); |
757 | link->handle = p_dev; | ||
758 | p_dev->instance = link; | ||
759 | |||
760 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
761 | pcmciamtd_config(link); | ||
762 | |||
763 | return 0; | ||
764 | } | 745 | } |
765 | 746 | ||
766 | static struct pcmcia_device_id pcmciamtd_ids[] = { | 747 | static struct pcmcia_device_id pcmciamtd_ids[] = { |
@@ -794,7 +775,7 @@ static struct pcmcia_driver pcmciamtd_driver = { | |||
794 | .drv = { | 775 | .drv = { |
795 | .name = "pcmciamtd" | 776 | .name = "pcmciamtd" |
796 | }, | 777 | }, |
797 | .probe = pcmciamtd_attach, | 778 | .probe = pcmciamtd_probe, |
798 | .remove = pcmciamtd_detach, | 779 | .remove = pcmciamtd_detach, |
799 | .owner = THIS_MODULE, | 780 | .owner = THIS_MODULE, |
800 | .id_table = pcmciamtd_ids, | 781 | .id_table = pcmciamtd_ids, |
diff --git a/drivers/mtd/maps/redwood.c b/drivers/mtd/maps/redwood.c index 5b76ed886185..50b14033613f 100644 --- a/drivers/mtd/maps/redwood.c +++ b/drivers/mtd/maps/redwood.c | |||
@@ -121,8 +121,7 @@ struct map_info redwood_flash_map = { | |||
121 | }; | 121 | }; |
122 | 122 | ||
123 | 123 | ||
124 | #define NUM_REDWOOD_FLASH_PARTITIONS \ | 124 | #define NUM_REDWOOD_FLASH_PARTITIONS ARRAY_SIZE(redwood_flash_partitions) |
125 | (sizeof(redwood_flash_partitions)/sizeof(redwood_flash_partitions[0])) | ||
126 | 125 | ||
127 | static struct mtd_info *redwood_mtd; | 126 | static struct mtd_info *redwood_mtd; |
128 | 127 | ||
diff --git a/drivers/mtd/maps/sbc8240.c b/drivers/mtd/maps/sbc8240.c index 225cdd9ba5b2..350286dc1d2e 100644 --- a/drivers/mtd/maps/sbc8240.c +++ b/drivers/mtd/maps/sbc8240.c | |||
@@ -66,7 +66,7 @@ static struct map_info sbc8240_map[2] = { | |||
66 | } | 66 | } |
67 | }; | 67 | }; |
68 | 68 | ||
69 | #define NUM_FLASH_BANKS (sizeof(sbc8240_map) / sizeof(struct map_info)) | 69 | #define NUM_FLASH_BANKS ARRAY_SIZE(sbc8240_map) |
70 | 70 | ||
71 | /* | 71 | /* |
72 | * The following defines the partition layout of SBC8240 boards. | 72 | * The following defines the partition layout of SBC8240 boards. |
@@ -125,8 +125,6 @@ static struct mtd_partition sbc8240_fs_partitions [] = { | |||
125 | } | 125 | } |
126 | }; | 126 | }; |
127 | 127 | ||
128 | #define NB_OF(x) (sizeof (x) / sizeof (x[0])) | ||
129 | |||
130 | /* trivial struct to describe partition information */ | 128 | /* trivial struct to describe partition information */ |
131 | struct mtd_part_def | 129 | struct mtd_part_def |
132 | { | 130 | { |
@@ -190,10 +188,10 @@ int __init init_sbc8240_mtd (void) | |||
190 | #ifdef CONFIG_MTD_PARTITIONS | 188 | #ifdef CONFIG_MTD_PARTITIONS |
191 | sbc8240_part_banks[0].mtd_part = sbc8240_uboot_partitions; | 189 | sbc8240_part_banks[0].mtd_part = sbc8240_uboot_partitions; |
192 | sbc8240_part_banks[0].type = "static image"; | 190 | sbc8240_part_banks[0].type = "static image"; |
193 | sbc8240_part_banks[0].nums = NB_OF(sbc8240_uboot_partitions); | 191 | sbc8240_part_banks[0].nums = ARRAY_SIZE(sbc8240_uboot_partitions); |
194 | sbc8240_part_banks[1].mtd_part = sbc8240_fs_partitions; | 192 | sbc8240_part_banks[1].mtd_part = sbc8240_fs_partitions; |
195 | sbc8240_part_banks[1].type = "static file system"; | 193 | sbc8240_part_banks[1].type = "static file system"; |
196 | sbc8240_part_banks[1].nums = NB_OF(sbc8240_fs_partitions); | 194 | sbc8240_part_banks[1].nums = ARRAY_SIZE(sbc8240_fs_partitions); |
197 | 195 | ||
198 | for (i = 0; i < NUM_FLASH_BANKS; i++) { | 196 | for (i = 0; i < NUM_FLASH_BANKS; i++) { |
199 | 197 | ||
diff --git a/drivers/mtd/maps/sc520cdp.c b/drivers/mtd/maps/sc520cdp.c index ed92afadd8a9..e8c130e1efd3 100644 --- a/drivers/mtd/maps/sc520cdp.c +++ b/drivers/mtd/maps/sc520cdp.c | |||
@@ -107,7 +107,7 @@ static struct map_info sc520cdp_map[] = { | |||
107 | }, | 107 | }, |
108 | }; | 108 | }; |
109 | 109 | ||
110 | #define NUM_FLASH_BANKS (sizeof(sc520cdp_map)/sizeof(struct map_info)) | 110 | #define NUM_FLASH_BANKS ARRAY_SIZE(sc520cdp_map) |
111 | 111 | ||
112 | static struct mtd_info *mymtd[NUM_FLASH_BANKS]; | 112 | static struct mtd_info *mymtd[NUM_FLASH_BANKS]; |
113 | static struct mtd_info *merged_mtd; | 113 | static struct mtd_info *merged_mtd; |
diff --git a/drivers/mtd/maps/scx200_docflash.c b/drivers/mtd/maps/scx200_docflash.c index 2c91dff8bb60..28b8a571a91a 100644 --- a/drivers/mtd/maps/scx200_docflash.c +++ b/drivers/mtd/maps/scx200_docflash.c | |||
@@ -70,7 +70,7 @@ static struct mtd_partition partition_info[] = { | |||
70 | .size = 0x80000 | 70 | .size = 0x80000 |
71 | }, | 71 | }, |
72 | }; | 72 | }; |
73 | #define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0])) | 73 | #define NUM_PARTITIONS ARRAY_SIZE(partition_info) |
74 | #endif | 74 | #endif |
75 | 75 | ||
76 | 76 | ||
diff --git a/drivers/mtd/maps/sharpsl-flash.c b/drivers/mtd/maps/sharpsl-flash.c index 999f4bb3d845..12fe53c0d2fc 100644 --- a/drivers/mtd/maps/sharpsl-flash.c +++ b/drivers/mtd/maps/sharpsl-flash.c | |||
@@ -49,8 +49,6 @@ static struct mtd_partition sharpsl_partitions[1] = { | |||
49 | } | 49 | } |
50 | }; | 50 | }; |
51 | 51 | ||
52 | #define NB_OF(x) (sizeof(x)/sizeof(x[0])) | ||
53 | |||
54 | int __init init_sharpsl(void) | 52 | int __init init_sharpsl(void) |
55 | { | 53 | { |
56 | struct mtd_partition *parts; | 54 | struct mtd_partition *parts; |
@@ -92,7 +90,7 @@ int __init init_sharpsl(void) | |||
92 | } | 90 | } |
93 | 91 | ||
94 | parts = sharpsl_partitions; | 92 | parts = sharpsl_partitions; |
95 | nb_parts = NB_OF(sharpsl_partitions); | 93 | nb_parts = ARRAY_SIZE(sharpsl_partitions); |
96 | 94 | ||
97 | printk(KERN_NOTICE "Using %s partision definition\n", part_type); | 95 | printk(KERN_NOTICE "Using %s partision definition\n", part_type); |
98 | add_mtd_partitions(mymtd, parts, nb_parts); | 96 | add_mtd_partitions(mymtd, parts, nb_parts); |
diff --git a/drivers/mtd/maps/ts5500_flash.c b/drivers/mtd/maps/ts5500_flash.c index 4b372bcb17f1..a7422c200567 100644 --- a/drivers/mtd/maps/ts5500_flash.c +++ b/drivers/mtd/maps/ts5500_flash.c | |||
@@ -64,7 +64,7 @@ static struct mtd_partition ts5500_partitions[] = { | |||
64 | } | 64 | } |
65 | }; | 65 | }; |
66 | 66 | ||
67 | #define NUM_PARTITIONS (sizeof(ts5500_partitions)/sizeof(struct mtd_partition)) | 67 | #define NUM_PARTITIONS ARRAY_SIZE(ts5500_partitions) |
68 | 68 | ||
69 | static struct mtd_info *mymtd; | 69 | static struct mtd_info *mymtd; |
70 | 70 | ||
diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c index 79d92808b766..f7264dc2ac9b 100644 --- a/drivers/mtd/maps/uclinux.c +++ b/drivers/mtd/maps/uclinux.c | |||
@@ -37,7 +37,7 @@ struct mtd_partition uclinux_romfs[] = { | |||
37 | { .name = "ROMfs" } | 37 | { .name = "ROMfs" } |
38 | }; | 38 | }; |
39 | 39 | ||
40 | #define NUM_PARTITIONS (sizeof(uclinux_romfs) / sizeof(uclinux_romfs[0])) | 40 | #define NUM_PARTITIONS ARRAY_SIZE(uclinux_romfs) |
41 | 41 | ||
42 | /****************************************************************************/ | 42 | /****************************************************************************/ |
43 | 43 | ||
diff --git a/drivers/mtd/maps/vmax301.c b/drivers/mtd/maps/vmax301.c index e0063941c0df..b3e487395435 100644 --- a/drivers/mtd/maps/vmax301.c +++ b/drivers/mtd/maps/vmax301.c | |||
@@ -182,7 +182,7 @@ int __init init_vmax301(void) | |||
182 | } | 182 | } |
183 | } | 183 | } |
184 | 184 | ||
185 | if (!vmax_mtd[1] && !vmax_mtd[2]) { | 185 | if (!vmax_mtd[0] && !vmax_mtd[1]) { |
186 | iounmap((void *)iomapadr); | 186 | iounmap((void *)iomapadr); |
187 | return -ENXIO; | 187 | return -ENXIO; |
188 | } | 188 | } |
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 840dd66ce2dc..458d3c8ae1ee 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c | |||
@@ -19,12 +19,12 @@ | |||
19 | #include <linux/spinlock.h> | 19 | #include <linux/spinlock.h> |
20 | #include <linux/hdreg.h> | 20 | #include <linux/hdreg.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <asm/semaphore.h> | 22 | #include <linux/mutex.h> |
23 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
24 | 24 | ||
25 | static LIST_HEAD(blktrans_majors); | 25 | static LIST_HEAD(blktrans_majors); |
26 | 26 | ||
27 | extern struct semaphore mtd_table_mutex; | 27 | extern struct mutex mtd_table_mutex; |
28 | extern struct mtd_info *mtd_table[]; | 28 | extern struct mtd_info *mtd_table[]; |
29 | 29 | ||
30 | struct mtd_blkcore_priv { | 30 | struct mtd_blkcore_priv { |
@@ -122,9 +122,9 @@ static int mtd_blktrans_thread(void *arg) | |||
122 | 122 | ||
123 | spin_unlock_irq(rq->queue_lock); | 123 | spin_unlock_irq(rq->queue_lock); |
124 | 124 | ||
125 | down(&dev->sem); | 125 | mutex_lock(&dev->lock); |
126 | res = do_blktrans_request(tr, dev, req); | 126 | res = do_blktrans_request(tr, dev, req); |
127 | up(&dev->sem); | 127 | mutex_unlock(&dev->lock); |
128 | 128 | ||
129 | spin_lock_irq(rq->queue_lock); | 129 | spin_lock_irq(rq->queue_lock); |
130 | 130 | ||
@@ -235,8 +235,8 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) | |||
235 | int last_devnum = -1; | 235 | int last_devnum = -1; |
236 | struct gendisk *gd; | 236 | struct gendisk *gd; |
237 | 237 | ||
238 | if (!down_trylock(&mtd_table_mutex)) { | 238 | if (!!mutex_trylock(&mtd_table_mutex)) { |
239 | up(&mtd_table_mutex); | 239 | mutex_unlock(&mtd_table_mutex); |
240 | BUG(); | 240 | BUG(); |
241 | } | 241 | } |
242 | 242 | ||
@@ -267,7 +267,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) | |||
267 | return -EBUSY; | 267 | return -EBUSY; |
268 | } | 268 | } |
269 | 269 | ||
270 | init_MUTEX(&new->sem); | 270 | mutex_init(&new->lock); |
271 | list_add_tail(&new->list, &tr->devs); | 271 | list_add_tail(&new->list, &tr->devs); |
272 | added: | 272 | added: |
273 | if (!tr->writesect) | 273 | if (!tr->writesect) |
@@ -313,8 +313,8 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) | |||
313 | 313 | ||
314 | int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) | 314 | int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) |
315 | { | 315 | { |
316 | if (!down_trylock(&mtd_table_mutex)) { | 316 | if (!!mutex_trylock(&mtd_table_mutex)) { |
317 | up(&mtd_table_mutex); | 317 | mutex_unlock(&mtd_table_mutex); |
318 | BUG(); | 318 | BUG(); |
319 | } | 319 | } |
320 | 320 | ||
@@ -378,14 +378,14 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) | |||
378 | 378 | ||
379 | memset(tr->blkcore_priv, 0, sizeof(*tr->blkcore_priv)); | 379 | memset(tr->blkcore_priv, 0, sizeof(*tr->blkcore_priv)); |
380 | 380 | ||
381 | down(&mtd_table_mutex); | 381 | mutex_lock(&mtd_table_mutex); |
382 | 382 | ||
383 | ret = register_blkdev(tr->major, tr->name); | 383 | ret = register_blkdev(tr->major, tr->name); |
384 | if (ret) { | 384 | if (ret) { |
385 | printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n", | 385 | printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n", |
386 | tr->name, tr->major, ret); | 386 | tr->name, tr->major, ret); |
387 | kfree(tr->blkcore_priv); | 387 | kfree(tr->blkcore_priv); |
388 | up(&mtd_table_mutex); | 388 | mutex_unlock(&mtd_table_mutex); |
389 | return ret; | 389 | return ret; |
390 | } | 390 | } |
391 | spin_lock_init(&tr->blkcore_priv->queue_lock); | 391 | spin_lock_init(&tr->blkcore_priv->queue_lock); |
@@ -396,7 +396,7 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) | |||
396 | if (!tr->blkcore_priv->rq) { | 396 | if (!tr->blkcore_priv->rq) { |
397 | unregister_blkdev(tr->major, tr->name); | 397 | unregister_blkdev(tr->major, tr->name); |
398 | kfree(tr->blkcore_priv); | 398 | kfree(tr->blkcore_priv); |
399 | up(&mtd_table_mutex); | 399 | mutex_unlock(&mtd_table_mutex); |
400 | return -ENOMEM; | 400 | return -ENOMEM; |
401 | } | 401 | } |
402 | 402 | ||
@@ -407,7 +407,7 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) | |||
407 | blk_cleanup_queue(tr->blkcore_priv->rq); | 407 | blk_cleanup_queue(tr->blkcore_priv->rq); |
408 | unregister_blkdev(tr->major, tr->name); | 408 | unregister_blkdev(tr->major, tr->name); |
409 | kfree(tr->blkcore_priv); | 409 | kfree(tr->blkcore_priv); |
410 | up(&mtd_table_mutex); | 410 | mutex_unlock(&mtd_table_mutex); |
411 | return ret; | 411 | return ret; |
412 | } | 412 | } |
413 | 413 | ||
@@ -419,7 +419,7 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) | |||
419 | tr->add_mtd(tr, mtd_table[i]); | 419 | tr->add_mtd(tr, mtd_table[i]); |
420 | } | 420 | } |
421 | 421 | ||
422 | up(&mtd_table_mutex); | 422 | mutex_unlock(&mtd_table_mutex); |
423 | 423 | ||
424 | return 0; | 424 | return 0; |
425 | } | 425 | } |
@@ -428,7 +428,7 @@ int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr) | |||
428 | { | 428 | { |
429 | struct list_head *this, *next; | 429 | struct list_head *this, *next; |
430 | 430 | ||
431 | down(&mtd_table_mutex); | 431 | mutex_lock(&mtd_table_mutex); |
432 | 432 | ||
433 | /* Clean up the kernel thread */ | 433 | /* Clean up the kernel thread */ |
434 | tr->blkcore_priv->exiting = 1; | 434 | tr->blkcore_priv->exiting = 1; |
@@ -446,7 +446,7 @@ int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr) | |||
446 | blk_cleanup_queue(tr->blkcore_priv->rq); | 446 | blk_cleanup_queue(tr->blkcore_priv->rq); |
447 | unregister_blkdev(tr->major, tr->name); | 447 | unregister_blkdev(tr->major, tr->name); |
448 | 448 | ||
449 | up(&mtd_table_mutex); | 449 | mutex_unlock(&mtd_table_mutex); |
450 | 450 | ||
451 | kfree(tr->blkcore_priv); | 451 | kfree(tr->blkcore_priv); |
452 | 452 | ||
diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c index e84756644fd1..2cef280e388c 100644 --- a/drivers/mtd/mtdblock.c +++ b/drivers/mtd/mtdblock.c | |||
@@ -19,11 +19,13 @@ | |||
19 | 19 | ||
20 | #include <linux/mtd/mtd.h> | 20 | #include <linux/mtd/mtd.h> |
21 | #include <linux/mtd/blktrans.h> | 21 | #include <linux/mtd/blktrans.h> |
22 | #include <linux/mutex.h> | ||
23 | |||
22 | 24 | ||
23 | static struct mtdblk_dev { | 25 | static struct mtdblk_dev { |
24 | struct mtd_info *mtd; | 26 | struct mtd_info *mtd; |
25 | int count; | 27 | int count; |
26 | struct semaphore cache_sem; | 28 | struct mutex cache_mutex; |
27 | unsigned char *cache_data; | 29 | unsigned char *cache_data; |
28 | unsigned long cache_offset; | 30 | unsigned long cache_offset; |
29 | unsigned int cache_size; | 31 | unsigned int cache_size; |
@@ -284,7 +286,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd) | |||
284 | mtdblk->count = 1; | 286 | mtdblk->count = 1; |
285 | mtdblk->mtd = mtd; | 287 | mtdblk->mtd = mtd; |
286 | 288 | ||
287 | init_MUTEX (&mtdblk->cache_sem); | 289 | mutex_init(&mtdblk->cache_mutex); |
288 | mtdblk->cache_state = STATE_EMPTY; | 290 | mtdblk->cache_state = STATE_EMPTY; |
289 | if ((mtdblk->mtd->flags & MTD_CAP_RAM) != MTD_CAP_RAM && | 291 | if ((mtdblk->mtd->flags & MTD_CAP_RAM) != MTD_CAP_RAM && |
290 | mtdblk->mtd->erasesize) { | 292 | mtdblk->mtd->erasesize) { |
@@ -306,9 +308,9 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd) | |||
306 | 308 | ||
307 | DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n"); | 309 | DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n"); |
308 | 310 | ||
309 | down(&mtdblk->cache_sem); | 311 | mutex_lock(&mtdblk->cache_mutex); |
310 | write_cached_data(mtdblk); | 312 | write_cached_data(mtdblk); |
311 | up(&mtdblk->cache_sem); | 313 | mutex_unlock(&mtdblk->cache_mutex); |
312 | 314 | ||
313 | if (!--mtdblk->count) { | 315 | if (!--mtdblk->count) { |
314 | /* It was the last usage. Free the device */ | 316 | /* It was the last usage. Free the device */ |
@@ -327,9 +329,9 @@ static int mtdblock_flush(struct mtd_blktrans_dev *dev) | |||
327 | { | 329 | { |
328 | struct mtdblk_dev *mtdblk = mtdblks[dev->devnum]; | 330 | struct mtdblk_dev *mtdblk = mtdblks[dev->devnum]; |
329 | 331 | ||
330 | down(&mtdblk->cache_sem); | 332 | mutex_lock(&mtdblk->cache_mutex); |
331 | write_cached_data(mtdblk); | 333 | write_cached_data(mtdblk); |
332 | up(&mtdblk->cache_sem); | 334 | mutex_unlock(&mtdblk->cache_mutex); |
333 | 335 | ||
334 | if (mtdblk->mtd->sync) | 336 | if (mtdblk->mtd->sync) |
335 | mtdblk->mtd->sync(mtdblk->mtd); | 337 | mtdblk->mtd->sync(mtdblk->mtd); |
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index dade02ab0687..9905870f56e5 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c | |||
@@ -19,15 +19,13 @@ | |||
19 | #include <linux/ioctl.h> | 19 | #include <linux/ioctl.h> |
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/mtd/compatmac.h> | 21 | #include <linux/mtd/compatmac.h> |
22 | #ifdef CONFIG_PROC_FS | ||
23 | #include <linux/proc_fs.h> | 22 | #include <linux/proc_fs.h> |
24 | #endif | ||
25 | 23 | ||
26 | #include <linux/mtd/mtd.h> | 24 | #include <linux/mtd/mtd.h> |
27 | 25 | ||
28 | /* These are exported solely for the purpose of mtd_blkdevs.c. You | 26 | /* These are exported solely for the purpose of mtd_blkdevs.c. You |
29 | should not use them for _anything_ else */ | 27 | should not use them for _anything_ else */ |
30 | DECLARE_MUTEX(mtd_table_mutex); | 28 | DEFINE_MUTEX(mtd_table_mutex); |
31 | struct mtd_info *mtd_table[MAX_MTD_DEVICES]; | 29 | struct mtd_info *mtd_table[MAX_MTD_DEVICES]; |
32 | 30 | ||
33 | EXPORT_SYMBOL_GPL(mtd_table_mutex); | 31 | EXPORT_SYMBOL_GPL(mtd_table_mutex); |
@@ -49,7 +47,7 @@ int add_mtd_device(struct mtd_info *mtd) | |||
49 | { | 47 | { |
50 | int i; | 48 | int i; |
51 | 49 | ||
52 | down(&mtd_table_mutex); | 50 | mutex_lock(&mtd_table_mutex); |
53 | 51 | ||
54 | for (i=0; i < MAX_MTD_DEVICES; i++) | 52 | for (i=0; i < MAX_MTD_DEVICES; i++) |
55 | if (!mtd_table[i]) { | 53 | if (!mtd_table[i]) { |
@@ -67,7 +65,7 @@ int add_mtd_device(struct mtd_info *mtd) | |||
67 | not->add(mtd); | 65 | not->add(mtd); |
68 | } | 66 | } |
69 | 67 | ||
70 | up(&mtd_table_mutex); | 68 | mutex_unlock(&mtd_table_mutex); |
71 | /* We _know_ we aren't being removed, because | 69 | /* We _know_ we aren't being removed, because |
72 | our caller is still holding us here. So none | 70 | our caller is still holding us here. So none |
73 | of this try_ nonsense, and no bitching about it | 71 | of this try_ nonsense, and no bitching about it |
@@ -76,7 +74,7 @@ int add_mtd_device(struct mtd_info *mtd) | |||
76 | return 0; | 74 | return 0; |
77 | } | 75 | } |
78 | 76 | ||
79 | up(&mtd_table_mutex); | 77 | mutex_unlock(&mtd_table_mutex); |
80 | return 1; | 78 | return 1; |
81 | } | 79 | } |
82 | 80 | ||
@@ -94,7 +92,7 @@ int del_mtd_device (struct mtd_info *mtd) | |||
94 | { | 92 | { |
95 | int ret; | 93 | int ret; |
96 | 94 | ||
97 | down(&mtd_table_mutex); | 95 | mutex_lock(&mtd_table_mutex); |
98 | 96 | ||
99 | if (mtd_table[mtd->index] != mtd) { | 97 | if (mtd_table[mtd->index] != mtd) { |
100 | ret = -ENODEV; | 98 | ret = -ENODEV; |
@@ -118,7 +116,7 @@ int del_mtd_device (struct mtd_info *mtd) | |||
118 | ret = 0; | 116 | ret = 0; |
119 | } | 117 | } |
120 | 118 | ||
121 | up(&mtd_table_mutex); | 119 | mutex_unlock(&mtd_table_mutex); |
122 | return ret; | 120 | return ret; |
123 | } | 121 | } |
124 | 122 | ||
@@ -135,7 +133,7 @@ void register_mtd_user (struct mtd_notifier *new) | |||
135 | { | 133 | { |
136 | int i; | 134 | int i; |
137 | 135 | ||
138 | down(&mtd_table_mutex); | 136 | mutex_lock(&mtd_table_mutex); |
139 | 137 | ||
140 | list_add(&new->list, &mtd_notifiers); | 138 | list_add(&new->list, &mtd_notifiers); |
141 | 139 | ||
@@ -145,7 +143,7 @@ void register_mtd_user (struct mtd_notifier *new) | |||
145 | if (mtd_table[i]) | 143 | if (mtd_table[i]) |
146 | new->add(mtd_table[i]); | 144 | new->add(mtd_table[i]); |
147 | 145 | ||
148 | up(&mtd_table_mutex); | 146 | mutex_unlock(&mtd_table_mutex); |
149 | } | 147 | } |
150 | 148 | ||
151 | /** | 149 | /** |
@@ -162,7 +160,7 @@ int unregister_mtd_user (struct mtd_notifier *old) | |||
162 | { | 160 | { |
163 | int i; | 161 | int i; |
164 | 162 | ||
165 | down(&mtd_table_mutex); | 163 | mutex_lock(&mtd_table_mutex); |
166 | 164 | ||
167 | module_put(THIS_MODULE); | 165 | module_put(THIS_MODULE); |
168 | 166 | ||
@@ -171,7 +169,7 @@ int unregister_mtd_user (struct mtd_notifier *old) | |||
171 | old->remove(mtd_table[i]); | 169 | old->remove(mtd_table[i]); |
172 | 170 | ||
173 | list_del(&old->list); | 171 | list_del(&old->list); |
174 | up(&mtd_table_mutex); | 172 | mutex_unlock(&mtd_table_mutex); |
175 | return 0; | 173 | return 0; |
176 | } | 174 | } |
177 | 175 | ||
@@ -193,7 +191,7 @@ struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) | |||
193 | struct mtd_info *ret = NULL; | 191 | struct mtd_info *ret = NULL; |
194 | int i; | 192 | int i; |
195 | 193 | ||
196 | down(&mtd_table_mutex); | 194 | mutex_lock(&mtd_table_mutex); |
197 | 195 | ||
198 | if (num == -1) { | 196 | if (num == -1) { |
199 | for (i=0; i< MAX_MTD_DEVICES; i++) | 197 | for (i=0; i< MAX_MTD_DEVICES; i++) |
@@ -211,7 +209,7 @@ struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) | |||
211 | if (ret) | 209 | if (ret) |
212 | ret->usecount++; | 210 | ret->usecount++; |
213 | 211 | ||
214 | up(&mtd_table_mutex); | 212 | mutex_unlock(&mtd_table_mutex); |
215 | return ret; | 213 | return ret; |
216 | } | 214 | } |
217 | 215 | ||
@@ -219,9 +217,9 @@ void put_mtd_device(struct mtd_info *mtd) | |||
219 | { | 217 | { |
220 | int c; | 218 | int c; |
221 | 219 | ||
222 | down(&mtd_table_mutex); | 220 | mutex_lock(&mtd_table_mutex); |
223 | c = --mtd->usecount; | 221 | c = --mtd->usecount; |
224 | up(&mtd_table_mutex); | 222 | mutex_unlock(&mtd_table_mutex); |
225 | BUG_ON(c < 0); | 223 | BUG_ON(c < 0); |
226 | 224 | ||
227 | module_put(mtd->owner); | 225 | module_put(mtd->owner); |
@@ -296,10 +294,11 @@ EXPORT_SYMBOL(unregister_mtd_user); | |||
296 | EXPORT_SYMBOL(default_mtd_writev); | 294 | EXPORT_SYMBOL(default_mtd_writev); |
297 | EXPORT_SYMBOL(default_mtd_readv); | 295 | EXPORT_SYMBOL(default_mtd_readv); |
298 | 296 | ||
297 | #ifdef CONFIG_PROC_FS | ||
298 | |||
299 | /*====================================================================*/ | 299 | /*====================================================================*/ |
300 | /* Support for /proc/mtd */ | 300 | /* Support for /proc/mtd */ |
301 | 301 | ||
302 | #ifdef CONFIG_PROC_FS | ||
303 | static struct proc_dir_entry *proc_mtd; | 302 | static struct proc_dir_entry *proc_mtd; |
304 | 303 | ||
305 | static inline int mtd_proc_info (char *buf, int i) | 304 | static inline int mtd_proc_info (char *buf, int i) |
@@ -319,7 +318,7 @@ static int mtd_read_proc (char *page, char **start, off_t off, int count, | |||
319 | int len, l, i; | 318 | int len, l, i; |
320 | off_t begin = 0; | 319 | off_t begin = 0; |
321 | 320 | ||
322 | down(&mtd_table_mutex); | 321 | mutex_lock(&mtd_table_mutex); |
323 | 322 | ||
324 | len = sprintf(page, "dev: size erasesize name\n"); | 323 | len = sprintf(page, "dev: size erasesize name\n"); |
325 | for (i=0; i< MAX_MTD_DEVICES; i++) { | 324 | for (i=0; i< MAX_MTD_DEVICES; i++) { |
@@ -337,38 +336,34 @@ static int mtd_read_proc (char *page, char **start, off_t off, int count, | |||
337 | *eof = 1; | 336 | *eof = 1; |
338 | 337 | ||
339 | done: | 338 | done: |
340 | up(&mtd_table_mutex); | 339 | mutex_unlock(&mtd_table_mutex); |
341 | if (off >= len+begin) | 340 | if (off >= len+begin) |
342 | return 0; | 341 | return 0; |
343 | *start = page + (off-begin); | 342 | *start = page + (off-begin); |
344 | return ((count < begin+len-off) ? count : begin+len-off); | 343 | return ((count < begin+len-off) ? count : begin+len-off); |
345 | } | 344 | } |
346 | 345 | ||
347 | #endif /* CONFIG_PROC_FS */ | ||
348 | |||
349 | /*====================================================================*/ | 346 | /*====================================================================*/ |
350 | /* Init code */ | 347 | /* Init code */ |
351 | 348 | ||
352 | static int __init init_mtd(void) | 349 | static int __init init_mtd(void) |
353 | { | 350 | { |
354 | #ifdef CONFIG_PROC_FS | ||
355 | if ((proc_mtd = create_proc_entry( "mtd", 0, NULL ))) | 351 | if ((proc_mtd = create_proc_entry( "mtd", 0, NULL ))) |
356 | proc_mtd->read_proc = mtd_read_proc; | 352 | proc_mtd->read_proc = mtd_read_proc; |
357 | #endif | ||
358 | return 0; | 353 | return 0; |
359 | } | 354 | } |
360 | 355 | ||
361 | static void __exit cleanup_mtd(void) | 356 | static void __exit cleanup_mtd(void) |
362 | { | 357 | { |
363 | #ifdef CONFIG_PROC_FS | ||
364 | if (proc_mtd) | 358 | if (proc_mtd) |
365 | remove_proc_entry( "mtd", NULL); | 359 | remove_proc_entry( "mtd", NULL); |
366 | #endif | ||
367 | } | 360 | } |
368 | 361 | ||
369 | module_init(init_mtd); | 362 | module_init(init_mtd); |
370 | module_exit(cleanup_mtd); | 363 | module_exit(cleanup_mtd); |
371 | 364 | ||
365 | #endif /* CONFIG_PROC_FS */ | ||
366 | |||
372 | 367 | ||
373 | MODULE_LICENSE("GPL"); | 368 | MODULE_LICENSE("GPL"); |
374 | MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); | 369 | MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); |
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 1fc4c134d939..cfe288a6e853 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -178,17 +178,16 @@ config MTD_NAND_DISKONCHIP_BBTWRITE | |||
178 | Even if you leave this disabled, you can enable BBT writes at module | 178 | Even if you leave this disabled, you can enable BBT writes at module |
179 | load time (assuming you build diskonchip as a module) with the module | 179 | load time (assuming you build diskonchip as a module) with the module |
180 | parameter "inftl_bbt_write=1". | 180 | parameter "inftl_bbt_write=1". |
181 | |||
182 | config MTD_NAND_SHARPSL | ||
183 | bool "Support for NAND Flash on Sharp SL Series (C7xx + others)" | ||
184 | depends on MTD_NAND && ARCH_PXA | ||
185 | |||
186 | config MTD_NAND_NANDSIM | ||
187 | bool "Support for NAND Flash Simulator" | ||
188 | depends on MTD_NAND && MTD_PARTITIONS | ||
189 | 181 | ||
182 | config MTD_NAND_SHARPSL | ||
183 | tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)" | ||
184 | depends on MTD_NAND && ARCH_PXA | ||
185 | |||
186 | config MTD_NAND_NANDSIM | ||
187 | tristate "Support for NAND Flash Simulator" | ||
188 | depends on MTD_NAND && MTD_PARTITIONS | ||
190 | help | 189 | help |
191 | The simulator may simulate verious NAND flash chips for the | 190 | The simulator may simulate verious NAND flash chips for the |
192 | MTD nand layer. | 191 | MTD nand layer. |
193 | 192 | ||
194 | endmenu | 193 | endmenu |
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 201e1362da14..bde3550910a2 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c | |||
@@ -55,8 +55,6 @@ static const struct mtd_partition partition_info[] = { | |||
55 | .size = MTDPART_SIZ_FULL | 55 | .size = MTDPART_SIZ_FULL |
56 | } | 56 | } |
57 | }; | 57 | }; |
58 | #define NB_OF(x) (sizeof(x)/sizeof(x[0])) | ||
59 | |||
60 | 58 | ||
61 | /** | 59 | /** |
62 | * au_read_byte - read one byte from the chip | 60 | * au_read_byte - read one byte from the chip |
@@ -462,7 +460,7 @@ int __init au1xxx_nand_init (void) | |||
462 | } | 460 | } |
463 | 461 | ||
464 | /* Register the partitions */ | 462 | /* Register the partitions */ |
465 | add_mtd_partitions(au1550_mtd, partition_info, NB_OF(partition_info)); | 463 | add_mtd_partitions(au1550_mtd, partition_info, ARRAY_SIZE(partition_info)); |
466 | 464 | ||
467 | return 0; | 465 | return 0; |
468 | 466 | ||
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 5d222460b42a..95e96fa1fceb 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -80,6 +80,7 @@ | |||
80 | #include <linux/mtd/compatmac.h> | 80 | #include <linux/mtd/compatmac.h> |
81 | #include <linux/interrupt.h> | 81 | #include <linux/interrupt.h> |
82 | #include <linux/bitops.h> | 82 | #include <linux/bitops.h> |
83 | #include <linux/leds.h> | ||
83 | #include <asm/io.h> | 84 | #include <asm/io.h> |
84 | 85 | ||
85 | #ifdef CONFIG_MTD_PARTITIONS | 86 | #ifdef CONFIG_MTD_PARTITIONS |
@@ -515,6 +516,8 @@ static int nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, i | |||
515 | return nand_isbad_bbt (mtd, ofs, allowbbt); | 516 | return nand_isbad_bbt (mtd, ofs, allowbbt); |
516 | } | 517 | } |
517 | 518 | ||
519 | DEFINE_LED_TRIGGER(nand_led_trigger); | ||
520 | |||
518 | /* | 521 | /* |
519 | * Wait for the ready pin, after a command | 522 | * Wait for the ready pin, after a command |
520 | * The timeout is catched later. | 523 | * The timeout is catched later. |
@@ -524,12 +527,14 @@ static void nand_wait_ready(struct mtd_info *mtd) | |||
524 | struct nand_chip *this = mtd->priv; | 527 | struct nand_chip *this = mtd->priv; |
525 | unsigned long timeo = jiffies + 2; | 528 | unsigned long timeo = jiffies + 2; |
526 | 529 | ||
530 | led_trigger_event(nand_led_trigger, LED_FULL); | ||
527 | /* wait until command is processed or timeout occures */ | 531 | /* wait until command is processed or timeout occures */ |
528 | do { | 532 | do { |
529 | if (this->dev_ready(mtd)) | 533 | if (this->dev_ready(mtd)) |
530 | return; | 534 | break; |
531 | touch_softlockup_watchdog(); | 535 | touch_softlockup_watchdog(); |
532 | } while (time_before(jiffies, timeo)); | 536 | } while (time_before(jiffies, timeo)); |
537 | led_trigger_event(nand_led_trigger, LED_OFF); | ||
533 | } | 538 | } |
534 | 539 | ||
535 | /** | 540 | /** |
@@ -817,6 +822,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) | |||
817 | else | 822 | else |
818 | timeo += (HZ * 20) / 1000; | 823 | timeo += (HZ * 20) / 1000; |
819 | 824 | ||
825 | led_trigger_event(nand_led_trigger, LED_FULL); | ||
826 | |||
820 | /* Apply this short delay always to ensure that we do wait tWB in | 827 | /* Apply this short delay always to ensure that we do wait tWB in |
821 | * any case on any machine. */ | 828 | * any case on any machine. */ |
822 | ndelay (100); | 829 | ndelay (100); |
@@ -840,6 +847,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) | |||
840 | } | 847 | } |
841 | cond_resched(); | 848 | cond_resched(); |
842 | } | 849 | } |
850 | led_trigger_event(nand_led_trigger, LED_OFF); | ||
851 | |||
843 | status = (int) this->read_byte(mtd); | 852 | status = (int) this->read_byte(mtd); |
844 | return status; | 853 | return status; |
845 | } | 854 | } |
@@ -2724,6 +2733,21 @@ void nand_release (struct mtd_info *mtd) | |||
2724 | EXPORT_SYMBOL_GPL (nand_scan); | 2733 | EXPORT_SYMBOL_GPL (nand_scan); |
2725 | EXPORT_SYMBOL_GPL (nand_release); | 2734 | EXPORT_SYMBOL_GPL (nand_release); |
2726 | 2735 | ||
2736 | |||
2737 | static int __init nand_base_init(void) | ||
2738 | { | ||
2739 | led_trigger_register_simple("nand-disk", &nand_led_trigger); | ||
2740 | return 0; | ||
2741 | } | ||
2742 | |||
2743 | static void __exit nand_base_exit(void) | ||
2744 | { | ||
2745 | led_trigger_unregister_simple(nand_led_trigger); | ||
2746 | } | ||
2747 | |||
2748 | module_init(nand_base_init); | ||
2749 | module_exit(nand_base_exit); | ||
2750 | |||
2727 | MODULE_LICENSE ("GPL"); | 2751 | MODULE_LICENSE ("GPL"); |
2728 | MODULE_AUTHOR ("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>"); | 2752 | MODULE_AUTHOR ("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>"); |
2729 | MODULE_DESCRIPTION ("Generic NAND flash driver code"); | 2753 | MODULE_DESCRIPTION ("Generic NAND flash driver code"); |
diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c index 8815c8dbef2d..c077d2ec9cdd 100644 --- a/drivers/mtd/redboot.c +++ b/drivers/mtd/redboot.c | |||
@@ -85,10 +85,6 @@ static int parse_redboot_partitions(struct mtd_info *master, | |||
85 | 85 | ||
86 | numslots = (master->erasesize / sizeof(struct fis_image_desc)); | 86 | numslots = (master->erasesize / sizeof(struct fis_image_desc)); |
87 | for (i = 0; i < numslots; i++) { | 87 | for (i = 0; i < numslots; i++) { |
88 | if (buf[i].name[0] == 0xff) { | ||
89 | i = numslots; | ||
90 | break; | ||
91 | } | ||
92 | if (!memcmp(buf[i].name, "FIS directory", 14)) { | 88 | if (!memcmp(buf[i].name, "FIS directory", 14)) { |
93 | /* This is apparently the FIS directory entry for the | 89 | /* This is apparently the FIS directory entry for the |
94 | * FIS directory itself. The FIS directory size is | 90 | * FIS directory itself. The FIS directory size is |
@@ -128,7 +124,7 @@ static int parse_redboot_partitions(struct mtd_info *master, | |||
128 | struct fis_list *new_fl, **prev; | 124 | struct fis_list *new_fl, **prev; |
129 | 125 | ||
130 | if (buf[i].name[0] == 0xff) | 126 | if (buf[i].name[0] == 0xff) |
131 | break; | 127 | continue; |
132 | if (!redboot_checksum(&buf[i])) | 128 | if (!redboot_checksum(&buf[i])) |
133 | break; | 129 | break; |
134 | 130 | ||