aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor_core@ameritech.net>2006-04-29 01:11:23 -0400
committerDmitry Torokhov <dtor_core@ameritech.net>2006-04-29 01:11:23 -0400
commit7b7e394185014e0f3bd8989cac937003f20ef9ce (patch)
tree3beda5f979bba0aa9822534e239cf1b45f3be69c /drivers/mtd
parentddc5d3414593e4d7ad7fbd33e7f7517fcc234544 (diff)
parent693f7d362055261882659475d2ef022e32edbff1 (diff)
Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/chips/Kconfig21
-rw-r--r--drivers/mtd/devices/Kconfig13
-rw-r--r--drivers/mtd/devices/Makefile1
-rw-r--r--drivers/mtd/devices/blkmtd.c819
-rw-r--r--drivers/mtd/maps/pcmciamtd.c115
5 files changed, 50 insertions, 919 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
203config 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
215config 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
224config MTD_CFI_STAA 203config 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/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
132config MTD_BLKMTD 132config 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
144config 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
153comment "Disk-On-Chip Device Drivers" 144comment "Disk-On-Chip Device Drivers"
154 145
155config MTD_DOC2000 146config 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
21obj-$(CONFIG_MTD_MS02NV) += ms02-nv.o 21obj-$(CONFIG_MTD_MS02NV) += ms02-nv.o
22obj-$(CONFIG_MTD_MTDRAM) += mtdram.o 22obj-$(CONFIG_MTD_MTDRAM) += mtdram.o
23obj-$(CONFIG_MTD_LART) += lart.o 23obj-$(CONFIG_MTD_LART) += lart.o
24obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o
25obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o 24obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o
26obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o 25obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
27obj-$(CONFIG_MTD_M25P80) += m25p80.o 26obj-$(CONFIG_MTD_M25P80) += m25p80.o
diff --git a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c
deleted file mode 100644
index 79f2e1f23ebd..000000000000
--- a/drivers/mtd/devices/blkmtd.c
+++ /dev/null
@@ -1,819 +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/mount.h>
32#include <linux/mtd/mtd.h>
33#include <linux/mutex.h>
34
35#define err(format, arg...) printk(KERN_ERR "blkmtd: " format "\n" , ## arg)
36#define info(format, arg...) printk(KERN_INFO "blkmtd: " format "\n" , ## arg)
37#define warn(format, arg...) printk(KERN_WARNING "blkmtd: " format "\n" , ## arg)
38#define crit(format, arg...) printk(KERN_CRIT "blkmtd: " format "\n" , ## arg)
39
40
41/* Default erase size in K, always make it a multiple of PAGE_SIZE */
42#define CONFIG_MTD_BLKDEV_ERASESIZE (128 << 10) /* 128KiB */
43#define VERSION "$Revision: 1.27 $"
44
45/* Info for the block device */
46struct blkmtd_dev {
47 struct list_head list;
48 struct block_device *blkdev;
49 struct mtd_info mtd_info;
50 struct mutex wrbuf_mutex;
51};
52
53
54/* Static info about the MTD, used in cleanup_module */
55static LIST_HEAD(blkmtd_device_list);
56
57
58static void blkmtd_sync(struct mtd_info *mtd);
59
60#define MAX_DEVICES 4
61
62/* Module parameters passed by insmod/modprobe */
63static char *device[MAX_DEVICES]; /* the block device to use */
64static int erasesz[MAX_DEVICES]; /* optional default erase size */
65static int ro[MAX_DEVICES]; /* optional read only flag */
66static int sync;
67
68
69MODULE_LICENSE("GPL");
70MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");
71MODULE_DESCRIPTION("Emulate an MTD using a block device");
72module_param_array(device, charp, NULL, 0);
73MODULE_PARM_DESC(device, "block device to use");
74module_param_array(erasesz, int, NULL, 0);
75MODULE_PARM_DESC(erasesz, "optional erase size to use in KiB. eg 4=4KiB.");
76module_param_array(ro, bool, NULL, 0);
77MODULE_PARM_DESC(ro, "1=Read only, writes and erases cause errors");
78module_param(sync, bool, 0);
79MODULE_PARM_DESC(sync, "1=Synchronous writes");
80
81
82/* completion handler for BIO reads */
83static int bi_read_complete(struct bio *bio, unsigned int bytes_done, int error)
84{
85 if (bio->bi_size)
86 return 1;
87
88 complete((struct completion*)bio->bi_private);
89 return 0;
90}
91
92
93/* completion handler for BIO writes */
94static int bi_write_complete(struct bio *bio, unsigned int bytes_done, int error)
95{
96 const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
97 struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
98
99 if (bio->bi_size)
100 return 1;
101
102 if(!uptodate)
103 err("bi_write_complete: not uptodate\n");
104
105 do {
106 struct page *page = bvec->bv_page;
107 DEBUG(3, "Cleaning up page %ld\n", page->index);
108 if (--bvec >= bio->bi_io_vec)
109 prefetchw(&bvec->bv_page->flags);
110
111 if (uptodate) {
112 SetPageUptodate(page);
113 } else {
114 ClearPageUptodate(page);
115 SetPageError(page);
116 }
117 clear_page_dirty(page);
118 unlock_page(page);
119 page_cache_release(page);
120 } while (bvec >= bio->bi_io_vec);
121
122 complete((struct completion*)bio->bi_private);
123 return 0;
124}
125
126
127/* read one page from the block device */
128static int blkmtd_readpage(struct blkmtd_dev *dev, struct page *page)
129{
130 struct bio *bio;
131 struct completion event;
132 int err = -ENOMEM;
133
134 if(PageUptodate(page)) {
135 DEBUG(2, "blkmtd: readpage page %ld is already upto date\n", page->index);
136 unlock_page(page);
137 return 0;
138 }
139
140 ClearPageUptodate(page);
141 ClearPageError(page);
142
143 bio = bio_alloc(GFP_KERNEL, 1);
144 if(bio) {
145 init_completion(&event);
146 bio->bi_bdev = dev->blkdev;
147 bio->bi_sector = page->index << (PAGE_SHIFT-9);
148 bio->bi_private = &event;
149 bio->bi_end_io = bi_read_complete;
150 if(bio_add_page(bio, page, PAGE_SIZE, 0) == PAGE_SIZE) {
151 submit_bio(READ_SYNC, bio);
152 wait_for_completion(&event);
153 err = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : -EIO;
154 bio_put(bio);
155 }
156 }
157
158 if(err)
159 SetPageError(page);
160 else
161 SetPageUptodate(page);
162 flush_dcache_page(page);
163 unlock_page(page);
164 return err;
165}
166
167
168/* write out the current BIO and wait for it to finish */
169static int blkmtd_write_out(struct bio *bio)
170{
171 struct completion event;
172 int err;
173
174 if(!bio->bi_vcnt) {
175 bio_put(bio);
176 return 0;
177 }
178
179 init_completion(&event);
180 bio->bi_private = &event;
181 bio->bi_end_io = bi_write_complete;
182 submit_bio(WRITE_SYNC, bio);
183 wait_for_completion(&event);
184 DEBUG(3, "submit_bio completed, bi_vcnt = %d\n", bio->bi_vcnt);
185 err = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : -EIO;
186 bio_put(bio);
187 return err;
188}
189
190
191/**
192 * blkmtd_add_page - add a page to the current BIO
193 * @bio: bio to add to (NULL to alloc initial bio)
194 * @blkdev: block device
195 * @page: page to add
196 * @pagecnt: pages left to add
197 *
198 * Adds a page to the current bio, allocating it if necessary. If it cannot be
199 * added, the current bio is written out and a new one is allocated. Returns
200 * the new bio to add or NULL on error
201 */
202static struct bio *blkmtd_add_page(struct bio *bio, struct block_device *blkdev,
203 struct page *page, int pagecnt)
204{
205
206 retry:
207 if(!bio) {
208 bio = bio_alloc(GFP_KERNEL, pagecnt);
209 if(!bio)
210 return NULL;
211 bio->bi_sector = page->index << (PAGE_SHIFT-9);
212 bio->bi_bdev = blkdev;
213 }
214
215 if(bio_add_page(bio, page, PAGE_SIZE, 0) != PAGE_SIZE) {
216 blkmtd_write_out(bio);
217 bio = NULL;
218 goto retry;
219 }
220 return bio;
221}
222
223
224/**
225 * write_pages - write block of data to device via the page cache
226 * @dev: device to write to
227 * @buf: data source or NULL if erase (output is set to 0xff)
228 * @to: offset into output device
229 * @len: amount to data to write
230 * @retlen: amount of data written
231 *
232 * Grab pages from the page cache and fill them with the source data.
233 * Non page aligned start and end result in a readin of the page and
234 * part of the page being modified. Pages are added to the bio and then written
235 * out.
236 */
237static int write_pages(struct blkmtd_dev *dev, const u_char *buf, loff_t to,
238 size_t len, size_t *retlen)
239{
240 int pagenr, offset;
241 size_t start_len = 0, end_len;
242 int pagecnt = 0;
243 int err = 0;
244 struct bio *bio = NULL;
245 size_t thislen = 0;
246
247 pagenr = to >> PAGE_SHIFT;
248 offset = to & ~PAGE_MASK;
249
250 DEBUG(2, "blkmtd: write_pages: buf = %p to = %ld len = %zd pagenr = %d offset = %d\n",
251 buf, (long)to, len, pagenr, offset);
252
253 /* see if we have to do a partial write at the start */
254 if(offset) {
255 start_len = ((offset + len) > PAGE_SIZE) ? PAGE_SIZE - offset : len;
256 len -= start_len;
257 }
258
259 /* calculate the length of the other two regions */
260 end_len = len & ~PAGE_MASK;
261 len -= end_len;
262
263 if(start_len)
264 pagecnt++;
265
266 if(len)
267 pagecnt += len >> PAGE_SHIFT;
268
269 if(end_len)
270 pagecnt++;
271
272 mutex_lock(&dev->wrbuf_mutex);
273
274 DEBUG(3, "blkmtd: write: start_len = %zd len = %zd end_len = %zd pagecnt = %d\n",
275 start_len, len, end_len, pagecnt);
276
277 if(start_len) {
278 /* do partial start region */
279 struct page *page;
280
281 DEBUG(3, "blkmtd: write: doing partial start, page = %d len = %zd offset = %d\n",
282 pagenr, start_len, offset);
283
284 BUG_ON(!buf);
285 page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev);
286 lock_page(page);
287 if(PageDirty(page)) {
288 err("to = %lld start_len = %zd len = %zd end_len = %zd pagenr = %d\n",
289 to, start_len, len, end_len, pagenr);
290 BUG();
291 }
292 memcpy(page_address(page)+offset, buf, start_len);
293 set_page_dirty(page);
294 SetPageUptodate(page);
295 buf += start_len;
296 thislen = start_len;
297 bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt);
298 if(!bio) {
299 err = -ENOMEM;
300 err("bio_add_page failed\n");
301 goto write_err;
302 }
303 pagecnt--;
304 pagenr++;
305 }
306
307 /* Now do the main loop to a page aligned, n page sized output */
308 if(len) {
309 int pagesc = len >> PAGE_SHIFT;
310 DEBUG(3, "blkmtd: write: whole pages start = %d, count = %d\n",
311 pagenr, pagesc);
312 while(pagesc) {
313 struct page *page;
314
315 /* see if page is in the page cache */
316 DEBUG(3, "blkmtd: write: grabbing page %d from page cache\n", pagenr);
317 page = grab_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr);
318 if(PageDirty(page)) {
319 BUG();
320 }
321 if(!page) {
322 warn("write: cannot grab cache page %d", pagenr);
323 err = -ENOMEM;
324 goto write_err;
325 }
326 if(!buf) {
327 memset(page_address(page), 0xff, PAGE_SIZE);
328 } else {
329 memcpy(page_address(page), buf, PAGE_SIZE);
330 buf += PAGE_SIZE;
331 }
332 bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt);
333 if(!bio) {
334 err = -ENOMEM;
335 err("bio_add_page failed\n");
336 goto write_err;
337 }
338 pagenr++;
339 pagecnt--;
340 set_page_dirty(page);
341 SetPageUptodate(page);
342 pagesc--;
343 thislen += PAGE_SIZE;
344 }
345 }
346
347 if(end_len) {
348 /* do the third region */
349 struct page *page;
350 DEBUG(3, "blkmtd: write: doing partial end, page = %d len = %zd\n",
351 pagenr, end_len);
352 BUG_ON(!buf);
353 page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev);
354 lock_page(page);
355 if(PageDirty(page)) {
356 err("to = %lld start_len = %zd len = %zd end_len = %zd pagenr = %d\n",
357 to, start_len, len, end_len, pagenr);
358 BUG();
359 }
360 memcpy(page_address(page), buf, end_len);
361 set_page_dirty(page);
362 SetPageUptodate(page);
363 DEBUG(3, "blkmtd: write: writing out partial end\n");
364 thislen += end_len;
365 bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt);
366 if(!bio) {
367 err = -ENOMEM;
368 err("bio_add_page failed\n");
369 goto write_err;
370 }
371 pagenr++;
372 }
373
374 DEBUG(3, "blkmtd: write: got %d vectors to write\n", bio->bi_vcnt);
375 write_err:
376 if(bio)
377 blkmtd_write_out(bio);
378
379 DEBUG(2, "blkmtd: write: end, retlen = %zd, err = %d\n", *retlen, err);
380 mutex_unlock(&dev->wrbuf_mutex);
381
382 if(retlen)
383 *retlen = thislen;
384 return err;
385}
386
387
388/* erase a specified part of the device */
389static int blkmtd_erase(struct mtd_info *mtd, struct erase_info *instr)
390{
391 struct blkmtd_dev *dev = mtd->priv;
392 struct mtd_erase_region_info *einfo = mtd->eraseregions;
393 int numregions = mtd->numeraseregions;
394 size_t from;
395 u_long len;
396 int err = -EIO;
397 size_t retlen;
398
399 instr->state = MTD_ERASING;
400 from = instr->addr;
401 len = instr->len;
402
403 /* check erase region has valid start and length */
404 DEBUG(2, "blkmtd: erase: dev = `%s' from = 0x%zx len = 0x%lx\n",
405 mtd->name+9, from, len);
406 while(numregions) {
407 DEBUG(3, "blkmtd: checking erase region = 0x%08X size = 0x%X num = 0x%x\n",
408 einfo->offset, einfo->erasesize, einfo->numblocks);
409 if(from >= einfo->offset
410 && from < einfo->offset + (einfo->erasesize * einfo->numblocks)) {
411 if(len == einfo->erasesize
412 && ( (from - einfo->offset) % einfo->erasesize == 0))
413 break;
414 }
415 numregions--;
416 einfo++;
417 }
418
419 if(!numregions) {
420 /* Not a valid erase block */
421 err("erase: invalid erase request 0x%lX @ 0x%08zX", len, from);
422 instr->state = MTD_ERASE_FAILED;
423 err = -EIO;
424 }
425
426 if(instr->state != MTD_ERASE_FAILED) {
427 /* do the erase */
428 DEBUG(3, "Doing erase from = %zd len = %ld\n", from, len);
429 err = write_pages(dev, NULL, from, len, &retlen);
430 if(err || retlen != len) {
431 err("erase failed err = %d", err);
432 instr->state = MTD_ERASE_FAILED;
433 } else {
434 instr->state = MTD_ERASE_DONE;
435 }
436 }
437
438 DEBUG(3, "blkmtd: erase: checking callback\n");
439 mtd_erase_callback(instr);
440 DEBUG(2, "blkmtd: erase: finished (err = %d)\n", err);
441 return err;
442}
443
444
445/* read a range of the data via the page cache */
446static int blkmtd_read(struct mtd_info *mtd, loff_t from, size_t len,
447 size_t *retlen, u_char *buf)
448{
449 struct blkmtd_dev *dev = mtd->priv;
450 int err = 0;
451 int offset;
452 int pagenr, pages;
453 size_t thislen = 0;
454
455 DEBUG(2, "blkmtd: read: dev = `%s' from = %lld len = %zd buf = %p\n",
456 mtd->name+9, from, len, buf);
457
458 if(from > mtd->size)
459 return -EINVAL;
460 if(from + len > mtd->size)
461 len = mtd->size - from;
462
463 pagenr = from >> PAGE_SHIFT;
464 offset = from - (pagenr << PAGE_SHIFT);
465
466 pages = (offset+len+PAGE_SIZE-1) >> PAGE_SHIFT;
467 DEBUG(3, "blkmtd: read: pagenr = %d offset = %d, pages = %d\n",
468 pagenr, offset, pages);
469
470 while(pages) {
471 struct page *page;
472 int cpylen;
473
474 DEBUG(3, "blkmtd: read: looking for page: %d\n", pagenr);
475 page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev);
476 if(IS_ERR(page)) {
477 err = -EIO;
478 goto readerr;
479 }
480
481 cpylen = (PAGE_SIZE > len) ? len : PAGE_SIZE;
482 if(offset+cpylen > PAGE_SIZE)
483 cpylen = PAGE_SIZE-offset;
484
485 memcpy(buf + thislen, page_address(page) + offset, cpylen);
486 offset = 0;
487 len -= cpylen;
488 thislen += cpylen;
489 pagenr++;
490 pages--;
491 if(!PageDirty(page))
492 page_cache_release(page);
493 }
494
495 readerr:
496 if(retlen)
497 *retlen = thislen;
498 DEBUG(2, "blkmtd: end read: retlen = %zd, err = %d\n", thislen, err);
499 return err;
500}
501
502
503/* write data to the underlying device */
504static int blkmtd_write(struct mtd_info *mtd, loff_t to, size_t len,
505 size_t *retlen, const u_char *buf)
506{
507 struct blkmtd_dev *dev = mtd->priv;
508 int err;
509
510 if(!len)
511 return 0;
512
513 DEBUG(2, "blkmtd: write: dev = `%s' to = %lld len = %zd buf = %p\n",
514 mtd->name+9, to, len, buf);
515
516 if(to >= mtd->size) {
517 return -ENOSPC;
518 }
519
520 if(to + len > mtd->size) {
521 len = mtd->size - to;
522 }
523
524 err = write_pages(dev, buf, to, len, retlen);
525 if(err > 0)
526 err = 0;
527 DEBUG(2, "blkmtd: write: end, err = %d\n", err);
528 return err;
529}
530
531
532/* sync the device - wait until the write queue is empty */
533static void blkmtd_sync(struct mtd_info *mtd)
534{
535 /* Currently all writes are synchronous */
536}
537
538
539static void free_device(struct blkmtd_dev *dev)
540{
541 DEBUG(2, "blkmtd: free_device() dev = %p\n", dev);
542 if(dev) {
543 kfree(dev->mtd_info.eraseregions);
544 kfree(dev->mtd_info.name);
545 if(dev->blkdev) {
546 invalidate_inode_pages(dev->blkdev->bd_inode->i_mapping);
547 close_bdev_excl(dev->blkdev);
548 }
549 kfree(dev);
550 }
551}
552
553
554/* For a given size and initial erase size, calculate the number
555 * and size of each erase region. Goes round the loop twice,
556 * once to find out how many regions, then allocates space,
557 * then round the loop again to fill it in.
558 */
559static struct mtd_erase_region_info *calc_erase_regions(
560 size_t erase_size, size_t total_size, int *regions)
561{
562 struct mtd_erase_region_info *info = NULL;
563
564 DEBUG(2, "calc_erase_regions, es = %zd size = %zd regions = %d\n",
565 erase_size, total_size, *regions);
566 /* Make any user specified erasesize be a power of 2
567 and at least PAGE_SIZE */
568 if(erase_size) {
569 int es = erase_size;
570 erase_size = 1;
571 while(es != 1) {
572 es >>= 1;
573 erase_size <<= 1;
574 }
575 if(erase_size < PAGE_SIZE)
576 erase_size = PAGE_SIZE;
577 } else {
578 erase_size = CONFIG_MTD_BLKDEV_ERASESIZE;
579 }
580
581 *regions = 0;
582
583 do {
584 int tot_size = total_size;
585 int er_size = erase_size;
586 int count = 0, offset = 0, regcnt = 0;
587
588 while(tot_size) {
589 count = tot_size / er_size;
590 if(count) {
591 tot_size = tot_size % er_size;
592 if(info) {
593 DEBUG(2, "adding to erase info off=%d er=%d cnt=%d\n",
594 offset, er_size, count);
595 (info+regcnt)->offset = offset;
596 (info+regcnt)->erasesize = er_size;
597 (info+regcnt)->numblocks = count;
598 (*regions)++;
599 }
600 regcnt++;
601 offset += (count * er_size);
602 }
603 while(er_size > tot_size)
604 er_size >>= 1;
605 }
606 if(info == NULL) {
607 info = kmalloc(regcnt * sizeof(struct mtd_erase_region_info), GFP_KERNEL);
608 if(!info)
609 break;
610 }
611 } while(!(*regions));
612 DEBUG(2, "calc_erase_regions done, es = %zd size = %zd regions = %d\n",
613 erase_size, total_size, *regions);
614 return info;
615}
616
617
618static struct blkmtd_dev *add_device(char *devname, int readonly, int erase_size)
619{
620 struct block_device *bdev;
621 int mode;
622 struct blkmtd_dev *dev;
623
624 if(!devname)
625 return NULL;
626
627 /* Get a handle on the device */
628
629
630#ifdef MODULE
631 mode = (readonly) ? O_RDONLY : O_RDWR;
632 bdev = open_bdev_excl(devname, mode, NULL);
633#else
634 mode = (readonly) ? FMODE_READ : FMODE_WRITE;
635 bdev = open_by_devnum(name_to_dev_t(devname), mode);
636#endif
637 if(IS_ERR(bdev)) {
638 err("error: cannot open device %s", devname);
639 DEBUG(2, "blkmtd: opening bdev returned %ld\n", PTR_ERR(bdev));
640 return NULL;
641 }
642
643 DEBUG(1, "blkmtd: found a block device major = %d, minor = %d\n",
644 MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev));
645
646 if(MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
647 err("attempting to use an MTD device as a block device");
648 blkdev_put(bdev);
649 return NULL;
650 }
651
652 dev = kmalloc(sizeof(struct blkmtd_dev), GFP_KERNEL);
653 if(dev == NULL) {
654 blkdev_put(bdev);
655 return NULL;
656 }
657
658 memset(dev, 0, sizeof(struct blkmtd_dev));
659 dev->blkdev = bdev;
660 if(!readonly) {
661 mutex_init(&dev->wrbuf_mutex);
662 }
663
664 dev->mtd_info.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
665
666 /* Setup the MTD structure */
667 /* make the name contain the block device in */
668 dev->mtd_info.name = kmalloc(sizeof("blkmtd: ") + strlen(devname), GFP_KERNEL);
669 if(dev->mtd_info.name == NULL)
670 goto devinit_err;
671
672 sprintf(dev->mtd_info.name, "blkmtd: %s", devname);
673 dev->mtd_info.eraseregions = calc_erase_regions(erase_size, dev->mtd_info.size,
674 &dev->mtd_info.numeraseregions);
675 if(dev->mtd_info.eraseregions == NULL)
676 goto devinit_err;
677
678 dev->mtd_info.erasesize = dev->mtd_info.eraseregions->erasesize;
679 DEBUG(1, "blkmtd: init: found %d erase regions\n",
680 dev->mtd_info.numeraseregions);
681
682 if(readonly) {
683 dev->mtd_info.type = MTD_ROM;
684 dev->mtd_info.flags = MTD_CAP_ROM;
685 } else {
686 dev->mtd_info.type = MTD_RAM;
687 dev->mtd_info.flags = MTD_CAP_RAM;
688 dev->mtd_info.erase = blkmtd_erase;
689 dev->mtd_info.write = blkmtd_write;
690 dev->mtd_info.writev = default_mtd_writev;
691 dev->mtd_info.sync = blkmtd_sync;
692 }
693 dev->mtd_info.read = blkmtd_read;
694 dev->mtd_info.readv = default_mtd_readv;
695 dev->mtd_info.priv = dev;
696 dev->mtd_info.owner = THIS_MODULE;
697
698 list_add(&dev->list, &blkmtd_device_list);
699 if (add_mtd_device(&dev->mtd_info)) {
700 /* Device didnt get added, so free the entry */
701 list_del(&dev->list);
702 goto devinit_err;
703 } else {
704 info("mtd%d: [%s] erase_size = %dKiB %s",
705 dev->mtd_info.index, dev->mtd_info.name + strlen("blkmtd: "),
706 dev->mtd_info.erasesize >> 10,
707 readonly ? "(read-only)" : "");
708 }
709
710 return dev;
711
712 devinit_err:
713 free_device(dev);
714 return NULL;
715}
716
717
718/* Cleanup and exit - sync the device and kill of the kernel thread */
719static void __devexit cleanup_blkmtd(void)
720{
721 struct list_head *temp1, *temp2;
722
723 /* Remove the MTD devices */
724 list_for_each_safe(temp1, temp2, &blkmtd_device_list) {
725 struct blkmtd_dev *dev = list_entry(temp1, struct blkmtd_dev,
726 list);
727 blkmtd_sync(&dev->mtd_info);
728 del_mtd_device(&dev->mtd_info);
729 info("mtd%d: [%s] removed", dev->mtd_info.index,
730 dev->mtd_info.name + strlen("blkmtd: "));
731 list_del(&dev->list);
732 free_device(dev);
733 }
734}
735
736#ifndef MODULE
737
738/* Handle kernel boot params */
739
740
741static int __init param_blkmtd_device(char *str)
742{
743 int i;
744
745 for(i = 0; i < MAX_DEVICES; i++) {
746 device[i] = str;
747 DEBUG(2, "blkmtd: device setup: %d = %s\n", i, device[i]);
748 strsep(&str, ",");
749 }
750 return 1;
751}
752
753
754static int __init param_blkmtd_erasesz(char *str)
755{
756 int i;
757 for(i = 0; i < MAX_DEVICES; i++) {
758 char *val = strsep(&str, ",");
759 if(val)
760 erasesz[i] = simple_strtoul(val, NULL, 0);
761 DEBUG(2, "blkmtd: erasesz setup: %d = %d\n", i, erasesz[i]);
762 }
763
764 return 1;
765}
766
767
768static int __init param_blkmtd_ro(char *str)
769{
770 int i;
771 for(i = 0; i < MAX_DEVICES; i++) {
772 char *val = strsep(&str, ",");
773 if(val)
774 ro[i] = simple_strtoul(val, NULL, 0);
775 DEBUG(2, "blkmtd: ro setup: %d = %d\n", i, ro[i]);
776 }
777
778 return 1;
779}
780
781
782static int __init param_blkmtd_sync(char *str)
783{
784 if(str[0] == '1')
785 sync = 1;
786 return 1;
787}
788
789__setup("blkmtd_device=", param_blkmtd_device);
790__setup("blkmtd_erasesz=", param_blkmtd_erasesz);
791__setup("blkmtd_ro=", param_blkmtd_ro);
792__setup("blkmtd_sync=", param_blkmtd_sync);
793
794#endif
795
796
797/* Startup */
798static int __init init_blkmtd(void)
799{
800 int i;
801
802 info("version " VERSION);
803 /* Check args - device[0] is the bare minimum*/
804 if(!device[0]) {
805 err("error: missing `device' name\n");
806 return -EINVAL;
807 }
808
809 for(i = 0; i < MAX_DEVICES; i++)
810 add_device(device[i], ro[i], erasesz[i] << 10);
811
812 if(list_empty(&blkmtd_device_list))
813 return -EINVAL;
814
815 return 0;
816}
817
818module_init(init_blkmtd);
819module_exit(cleanup_blkmtd);
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index 8bbc751a6021..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
56struct pcmciamtd_dev { 56struct 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
243static map_word pcmcia_read8(struct map_info *map, unsigned long ofs) 243static 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
319static void pcmciamtd_set_vpp(struct map_info *map, int on) 319static 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
343static void pcmciamtd_release(dev_link_t *link) 343static 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
361static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_name) 360static 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) \
489do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) 488do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
490 489
491static void pcmciamtd_config(dev_link_t *link) 490static 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) {
@@ -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
716static void pcmciamtd_detach(struct pcmcia_device *p_dev) 708static 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
739static int pcmciamtd_attach(struct pcmcia_device *p_dev) 728static 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
766static struct pcmcia_device_id pcmciamtd_ids[] = { 747static 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,