mtdcore.c revision 447d9bd82020f159456ee00b011486205205aaa7
1/* 2 * Core registration and callback routines for MTD 3 * drivers and users. 4 * 5 * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> 6 * Copyright © 2006 Red Hat UK Limited 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 * 22 */ 23 24#include <linux/module.h> 25#include <linux/kernel.h> 26#include <linux/ptrace.h> 27#include <linux/seq_file.h> 28#include <linux/string.h> 29#include <linux/timer.h> 30#include <linux/major.h> 31#include <linux/fs.h> 32#include <linux/err.h> 33#include <linux/ioctl.h> 34#include <linux/init.h> 35#include <linux/proc_fs.h> 36#include <linux/idr.h> 37#include <linux/backing-dev.h> 38#include <linux/gfp.h> 39 40#include <linux/mtd/mtd.h> 41 42#include "mtdcore.h" 43/* 44 * backing device capabilities for non-mappable devices (such as NAND flash) 45 * - permits private mappings, copies are taken of the data 46 */ 47static struct backing_dev_info mtd_bdi_unmappable = { 48 .capabilities = BDI_CAP_MAP_COPY, 49}; 50 51/* 52 * backing device capabilities for R/O mappable devices (such as ROM) 53 * - permits private mappings, copies are taken of the data 54 * - permits non-writable shared mappings 55 */ 56static struct backing_dev_info mtd_bdi_ro_mappable = { 57 .capabilities = (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT | 58 BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP), 59}; 60 61/* 62 * backing device capabilities for writable mappable devices (such as RAM) 63 * - permits private mappings, copies are taken of the data 64 * - permits non-writable shared mappings 65 */ 66static struct backing_dev_info mtd_bdi_rw_mappable = { 67 .capabilities = (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT | 68 BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP | 69 BDI_CAP_WRITE_MAP), 70}; 71 72static int mtd_cls_suspend(struct device *dev, pm_message_t state); 73static int mtd_cls_resume(struct device *dev); 74 75static struct class mtd_class = { 76 .name = "mtd", 77 .owner = THIS_MODULE, 78 .suspend = mtd_cls_suspend, 79 .resume = mtd_cls_resume, 80}; 81 82static DEFINE_IDR(mtd_idr); 83 84/* These are exported solely for the purpose of mtd_blkdevs.c. You 85 should not use them for _anything_ else */ 86DEFINE_MUTEX(mtd_table_mutex); 87EXPORT_SYMBOL_GPL(mtd_table_mutex); 88 89struct mtd_info *__mtd_next_device(int i) 90{ 91 return idr_get_next(&mtd_idr, &i); 92} 93EXPORT_SYMBOL_GPL(__mtd_next_device); 94 95static LIST_HEAD(mtd_notifiers); 96 97 98#if defined(CONFIG_MTD_CHAR) || defined(CONFIG_MTD_CHAR_MODULE) 99#define MTD_DEVT(index) MKDEV(MTD_CHAR_MAJOR, (index)*2) 100#else 101#define MTD_DEVT(index) 0 102#endif 103 104/* REVISIT once MTD uses the driver model better, whoever allocates 105 * the mtd_info will probably want to use the release() hook... 106 */ 107static void mtd_release(struct device *dev) 108{ 109 dev_t index = MTD_DEVT(dev_to_mtd(dev)->index); 110 111 /* remove /dev/mtdXro node if needed */ 112 if (index) 113 device_destroy(&mtd_class, index + 1); 114} 115 116static int mtd_cls_suspend(struct device *dev, pm_message_t state) 117{ 118 struct mtd_info *mtd = dev_to_mtd(dev); 119 120 if (mtd && mtd->suspend) 121 return mtd->suspend(mtd); 122 else 123 return 0; 124} 125 126static int mtd_cls_resume(struct device *dev) 127{ 128 struct mtd_info *mtd = dev_to_mtd(dev); 129 130 if (mtd && mtd->resume) 131 mtd->resume(mtd); 132 return 0; 133} 134 135static ssize_t mtd_type_show(struct device *dev, 136 struct device_attribute *attr, char *buf) 137{ 138 struct mtd_info *mtd = dev_to_mtd(dev); 139 char *type; 140 141 switch (mtd->type) { 142 case MTD_ABSENT: 143 type = "absent"; 144 break; 145 case MTD_RAM: 146 type = "ram"; 147 break; 148 case MTD_ROM: 149 type = "rom"; 150 break; 151 case MTD_NORFLASH: 152 type = "nor"; 153 break; 154 case MTD_NANDFLASH: 155 type = "nand"; 156 break; 157 case MTD_DATAFLASH: 158 type = "dataflash"; 159 break; 160 case MTD_UBIVOLUME: 161 type = "ubi"; 162 break; 163 default: 164 type = "unknown"; 165 } 166 167 return snprintf(buf, PAGE_SIZE, "%s\n", type); 168} 169static DEVICE_ATTR(type, S_IRUGO, mtd_type_show, NULL); 170 171static ssize_t mtd_flags_show(struct device *dev, 172 struct device_attribute *attr, char *buf) 173{ 174 struct mtd_info *mtd = dev_to_mtd(dev); 175 176 return snprintf(buf, PAGE_SIZE, "0x%lx\n", (unsigned long)mtd->flags); 177 178} 179static DEVICE_ATTR(flags, S_IRUGO, mtd_flags_show, NULL); 180 181static ssize_t mtd_size_show(struct device *dev, 182 struct device_attribute *attr, char *buf) 183{ 184 struct mtd_info *mtd = dev_to_mtd(dev); 185 186 return snprintf(buf, PAGE_SIZE, "%llu\n", 187 (unsigned long long)mtd->size); 188 189} 190static DEVICE_ATTR(size, S_IRUGO, mtd_size_show, NULL); 191 192static ssize_t mtd_erasesize_show(struct device *dev, 193 struct device_attribute *attr, char *buf) 194{ 195 struct mtd_info *mtd = dev_to_mtd(dev); 196 197 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->erasesize); 198 199} 200static DEVICE_ATTR(erasesize, S_IRUGO, mtd_erasesize_show, NULL); 201 202static ssize_t mtd_writesize_show(struct device *dev, 203 struct device_attribute *attr, char *buf) 204{ 205 struct mtd_info *mtd = dev_to_mtd(dev); 206 207 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->writesize); 208 209} 210static DEVICE_ATTR(writesize, S_IRUGO, mtd_writesize_show, NULL); 211 212static ssize_t mtd_subpagesize_show(struct device *dev, 213 struct device_attribute *attr, char *buf) 214{ 215 struct mtd_info *mtd = dev_to_mtd(dev); 216 unsigned int subpagesize = mtd->writesize >> mtd->subpage_sft; 217 218 return snprintf(buf, PAGE_SIZE, "%u\n", subpagesize); 219 220} 221static DEVICE_ATTR(subpagesize, S_IRUGO, mtd_subpagesize_show, NULL); 222 223static ssize_t mtd_oobsize_show(struct device *dev, 224 struct device_attribute *attr, char *buf) 225{ 226 struct mtd_info *mtd = dev_to_mtd(dev); 227 228 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->oobsize); 229 230} 231static DEVICE_ATTR(oobsize, S_IRUGO, mtd_oobsize_show, NULL); 232 233static ssize_t mtd_numeraseregions_show(struct device *dev, 234 struct device_attribute *attr, char *buf) 235{ 236 struct mtd_info *mtd = dev_to_mtd(dev); 237 238 return snprintf(buf, PAGE_SIZE, "%u\n", mtd->numeraseregions); 239 240} 241static DEVICE_ATTR(numeraseregions, S_IRUGO, mtd_numeraseregions_show, 242 NULL); 243 244static ssize_t mtd_name_show(struct device *dev, 245 struct device_attribute *attr, char *buf) 246{ 247 struct mtd_info *mtd = dev_to_mtd(dev); 248 249 return snprintf(buf, PAGE_SIZE, "%s\n", mtd->name); 250 251} 252static DEVICE_ATTR(name, S_IRUGO, mtd_name_show, NULL); 253 254static struct attribute *mtd_attrs[] = { 255 &dev_attr_type.attr, 256 &dev_attr_flags.attr, 257 &dev_attr_size.attr, 258 &dev_attr_erasesize.attr, 259 &dev_attr_writesize.attr, 260 &dev_attr_subpagesize.attr, 261 &dev_attr_oobsize.attr, 262 &dev_attr_numeraseregions.attr, 263 &dev_attr_name.attr, 264 NULL, 265}; 266 267static struct attribute_group mtd_group = { 268 .attrs = mtd_attrs, 269}; 270 271static const struct attribute_group *mtd_groups[] = { 272 &mtd_group, 273 NULL, 274}; 275 276static struct device_type mtd_devtype = { 277 .name = "mtd", 278 .groups = mtd_groups, 279 .release = mtd_release, 280}; 281 282/** 283 * add_mtd_device - register an MTD device 284 * @mtd: pointer to new MTD device info structure 285 * 286 * Add a device to the list of MTD devices present in the system, and 287 * notify each currently active MTD 'user' of its arrival. Returns 288 * zero on success or 1 on failure, which currently will only happen 289 * if there is insufficient memory or a sysfs error. 290 */ 291 292int add_mtd_device(struct mtd_info *mtd) 293{ 294 struct mtd_notifier *not; 295 int i, error; 296 297 if (!mtd->backing_dev_info) { 298 switch (mtd->type) { 299 case MTD_RAM: 300 mtd->backing_dev_info = &mtd_bdi_rw_mappable; 301 break; 302 case MTD_ROM: 303 mtd->backing_dev_info = &mtd_bdi_ro_mappable; 304 break; 305 default: 306 mtd->backing_dev_info = &mtd_bdi_unmappable; 307 break; 308 } 309 } 310 311 BUG_ON(mtd->writesize == 0); 312 mutex_lock(&mtd_table_mutex); 313 314 do { 315 if (!idr_pre_get(&mtd_idr, GFP_KERNEL)) 316 goto fail_locked; 317 error = idr_get_new(&mtd_idr, mtd, &i); 318 } while (error == -EAGAIN); 319 320 if (error) 321 goto fail_locked; 322 323 mtd->index = i; 324 mtd->usecount = 0; 325 326 if (is_power_of_2(mtd->erasesize)) 327 mtd->erasesize_shift = ffs(mtd->erasesize) - 1; 328 else 329 mtd->erasesize_shift = 0; 330 331 if (is_power_of_2(mtd->writesize)) 332 mtd->writesize_shift = ffs(mtd->writesize) - 1; 333 else 334 mtd->writesize_shift = 0; 335 336 mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1; 337 mtd->writesize_mask = (1 << mtd->writesize_shift) - 1; 338 339 /* Some chips always power up locked. Unlock them now */ 340 if ((mtd->flags & MTD_WRITEABLE) 341 && (mtd->flags & MTD_POWERUP_LOCK) && mtd->unlock) { 342 if (mtd->unlock(mtd, 0, mtd->size)) 343 printk(KERN_WARNING 344 "%s: unlock failed, writes may not work\n", 345 mtd->name); 346 } 347 348 /* Caller should have set dev.parent to match the 349 * physical device. 350 */ 351 mtd->dev.type = &mtd_devtype; 352 mtd->dev.class = &mtd_class; 353 mtd->dev.devt = MTD_DEVT(i); 354 dev_set_name(&mtd->dev, "mtd%d", i); 355 dev_set_drvdata(&mtd->dev, mtd); 356 if (device_register(&mtd->dev) != 0) 357 goto fail_added; 358 359 if (MTD_DEVT(i)) 360 device_create(&mtd_class, mtd->dev.parent, 361 MTD_DEVT(i) + 1, 362 NULL, "mtd%dro", i); 363 364 DEBUG(0, "mtd: Giving out device %d to %s\n", i, mtd->name); 365 /* No need to get a refcount on the module containing 366 the notifier, since we hold the mtd_table_mutex */ 367 list_for_each_entry(not, &mtd_notifiers, list) 368 not->add(mtd); 369 370 mutex_unlock(&mtd_table_mutex); 371 /* We _know_ we aren't being removed, because 372 our caller is still holding us here. So none 373 of this try_ nonsense, and no bitching about it 374 either. :) */ 375 __module_get(THIS_MODULE); 376 return 0; 377 378fail_added: 379 idr_remove(&mtd_idr, i); 380fail_locked: 381 mutex_unlock(&mtd_table_mutex); 382 return 1; 383} 384 385/** 386 * del_mtd_device - unregister an MTD device 387 * @mtd: pointer to MTD device info structure 388 * 389 * Remove a device from the list of MTD devices present in the system, 390 * and notify each currently active MTD 'user' of its departure. 391 * Returns zero on success or 1 on failure, which currently will happen 392 * if the requested device does not appear to be present in the list. 393 */ 394 395int del_mtd_device (struct mtd_info *mtd) 396{ 397 int ret; 398 struct mtd_notifier *not; 399 400 mutex_lock(&mtd_table_mutex); 401 402 if (idr_find(&mtd_idr, mtd->index) != mtd) { 403 ret = -ENODEV; 404 goto out_error; 405 } 406 407 /* No need to get a refcount on the module containing 408 the notifier, since we hold the mtd_table_mutex */ 409 list_for_each_entry(not, &mtd_notifiers, list) 410 not->remove(mtd); 411 412 if (mtd->usecount) { 413 printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n", 414 mtd->index, mtd->name, mtd->usecount); 415 ret = -EBUSY; 416 } else { 417 device_unregister(&mtd->dev); 418 419 idr_remove(&mtd_idr, mtd->index); 420 421 module_put(THIS_MODULE); 422 ret = 0; 423 } 424 425out_error: 426 mutex_unlock(&mtd_table_mutex); 427 return ret; 428} 429 430/** 431 * register_mtd_user - register a 'user' of MTD devices. 432 * @new: pointer to notifier info structure 433 * 434 * Registers a pair of callbacks function to be called upon addition 435 * or removal of MTD devices. Causes the 'add' callback to be immediately 436 * invoked for each MTD device currently present in the system. 437 */ 438 439void register_mtd_user (struct mtd_notifier *new) 440{ 441 struct mtd_info *mtd; 442 443 mutex_lock(&mtd_table_mutex); 444 445 list_add(&new->list, &mtd_notifiers); 446 447 __module_get(THIS_MODULE); 448 449 mtd_for_each_device(mtd) 450 new->add(mtd); 451 452 mutex_unlock(&mtd_table_mutex); 453} 454 455/** 456 * unregister_mtd_user - unregister a 'user' of MTD devices. 457 * @old: pointer to notifier info structure 458 * 459 * Removes a callback function pair from the list of 'users' to be 460 * notified upon addition or removal of MTD devices. Causes the 461 * 'remove' callback to be immediately invoked for each MTD device 462 * currently present in the system. 463 */ 464 465int unregister_mtd_user (struct mtd_notifier *old) 466{ 467 struct mtd_info *mtd; 468 469 mutex_lock(&mtd_table_mutex); 470 471 module_put(THIS_MODULE); 472 473 mtd_for_each_device(mtd) 474 old->remove(mtd); 475 476 list_del(&old->list); 477 mutex_unlock(&mtd_table_mutex); 478 return 0; 479} 480 481 482/** 483 * get_mtd_device - obtain a validated handle for an MTD device 484 * @mtd: last known address of the required MTD device 485 * @num: internal device number of the required MTD device 486 * 487 * Given a number and NULL address, return the num'th entry in the device 488 * table, if any. Given an address and num == -1, search the device table 489 * for a device with that address and return if it's still present. Given 490 * both, return the num'th driver only if its address matches. Return 491 * error code if not. 492 */ 493 494struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) 495{ 496 struct mtd_info *ret = NULL, *other; 497 int err = -ENODEV; 498 499 mutex_lock(&mtd_table_mutex); 500 501 if (num == -1) { 502 mtd_for_each_device(other) { 503 if (other == mtd) { 504 ret = mtd; 505 break; 506 } 507 } 508 } else if (num >= 0) { 509 ret = idr_find(&mtd_idr, num); 510 if (mtd && mtd != ret) 511 ret = NULL; 512 } 513 514 if (!ret) { 515 ret = ERR_PTR(err); 516 goto out; 517 } 518 519 err = __get_mtd_device(ret); 520 if (err) 521 ret = ERR_PTR(err); 522out: 523 mutex_unlock(&mtd_table_mutex); 524 return ret; 525} 526 527 528int __get_mtd_device(struct mtd_info *mtd) 529{ 530 int err; 531 532 if (!try_module_get(mtd->owner)) 533 return -ENODEV; 534 535 if (mtd->get_device) { 536 537 err = mtd->get_device(mtd); 538 539 if (err) { 540 module_put(mtd->owner); 541 return err; 542 } 543 } 544 mtd->usecount++; 545 return 0; 546} 547 548/** 549 * get_mtd_device_nm - obtain a validated handle for an MTD device by 550 * device name 551 * @name: MTD device name to open 552 * 553 * This function returns MTD device description structure in case of 554 * success and an error code in case of failure. 555 */ 556 557struct mtd_info *get_mtd_device_nm(const char *name) 558{ 559 int err = -ENODEV; 560 struct mtd_info *mtd = NULL, *other; 561 562 mutex_lock(&mtd_table_mutex); 563 564 mtd_for_each_device(other) { 565 if (!strcmp(name, other->name)) { 566 mtd = other; 567 break; 568 } 569 } 570 571 if (!mtd) 572 goto out_unlock; 573 574 if (!try_module_get(mtd->owner)) 575 goto out_unlock; 576 577 if (mtd->get_device) { 578 err = mtd->get_device(mtd); 579 if (err) 580 goto out_put; 581 } 582 583 mtd->usecount++; 584 mutex_unlock(&mtd_table_mutex); 585 return mtd; 586 587out_put: 588 module_put(mtd->owner); 589out_unlock: 590 mutex_unlock(&mtd_table_mutex); 591 return ERR_PTR(err); 592} 593 594void put_mtd_device(struct mtd_info *mtd) 595{ 596 mutex_lock(&mtd_table_mutex); 597 __put_mtd_device(mtd); 598 mutex_unlock(&mtd_table_mutex); 599 600} 601 602void __put_mtd_device(struct mtd_info *mtd) 603{ 604 --mtd->usecount; 605 BUG_ON(mtd->usecount < 0); 606 607 if (mtd->put_device) 608 mtd->put_device(mtd); 609 610 module_put(mtd->owner); 611} 612 613/* default_mtd_writev - default mtd writev method for MTD devices that 614 * don't implement their own 615 */ 616 617int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, 618 unsigned long count, loff_t to, size_t *retlen) 619{ 620 unsigned long i; 621 size_t totlen = 0, thislen; 622 int ret = 0; 623 624 if(!mtd->write) { 625 ret = -EROFS; 626 } else { 627 for (i=0; i<count; i++) { 628 if (!vecs[i].iov_len) 629 continue; 630 ret = mtd->write(mtd, to, vecs[i].iov_len, &thislen, vecs[i].iov_base); 631 totlen += thislen; 632 if (ret || thislen != vecs[i].iov_len) 633 break; 634 to += vecs[i].iov_len; 635 } 636 } 637 if (retlen) 638 *retlen = totlen; 639 return ret; 640} 641 642/** 643 * mtd_kmalloc_up_to - allocate a contiguous buffer up to the specified size 644 * @size: A pointer to the ideal or maximum size of the allocation. Points 645 * to the actual allocation size on success. 646 * 647 * This routine attempts to allocate a contiguous kernel buffer up to 648 * the specified size, backing off the size of the request exponentially 649 * until the request succeeds or until the allocation size falls below 650 * the system page size. This attempts to make sure it does not adversely 651 * impact system performance, so when allocating more than one page, we 652 * ask the memory allocator to avoid re-trying, swapping, writing back 653 * or performing I/O. 654 * 655 * Note, this function also makes sure that the allocated buffer is aligned to 656 * the MTD device's min. I/O unit, i.e. the "mtd->writesize" value. 657 * 658 * This is called, for example by mtd_{read,write} and jffs2_scan_medium, 659 * to handle smaller (i.e. degraded) buffer allocations under low- or 660 * fragmented-memory situations where such reduced allocations, from a 661 * requested ideal, are allowed. 662 * 663 * Returns a pointer to the allocated buffer on success; otherwise, NULL. 664 */ 665void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size) 666{ 667 gfp_t flags = __GFP_NOWARN | __GFP_WAIT | 668 __GFP_NORETRY | __GFP_NO_KSWAPD; 669 size_t min_alloc = max_t(size_t, mtd->writesize, PAGE_SIZE); 670 void *kbuf; 671 672 *size = min_t(size_t, *size, KMALLOC_MAX_SIZE); 673 674 while (*size > min_alloc) { 675 kbuf = kmalloc(*size, flags); 676 if (kbuf) 677 return kbuf; 678 679 *size >>= 1; 680 *size = ALIGN(*size, mtd->writesize); 681 } 682 683 /* 684 * For the last resort allocation allow 'kmalloc()' to do all sorts of 685 * things (write-back, dropping caches, etc) by using GFP_KERNEL. 686 */ 687 return kmalloc(*size, GFP_KERNEL); 688} 689 690EXPORT_SYMBOL_GPL(add_mtd_device); 691EXPORT_SYMBOL_GPL(del_mtd_device); 692EXPORT_SYMBOL_GPL(get_mtd_device); 693EXPORT_SYMBOL_GPL(get_mtd_device_nm); 694EXPORT_SYMBOL_GPL(__get_mtd_device); 695EXPORT_SYMBOL_GPL(put_mtd_device); 696EXPORT_SYMBOL_GPL(__put_mtd_device); 697EXPORT_SYMBOL_GPL(register_mtd_user); 698EXPORT_SYMBOL_GPL(unregister_mtd_user); 699EXPORT_SYMBOL_GPL(default_mtd_writev); 700EXPORT_SYMBOL_GPL(mtd_kmalloc_up_to); 701 702#ifdef CONFIG_PROC_FS 703 704/*====================================================================*/ 705/* Support for /proc/mtd */ 706 707static struct proc_dir_entry *proc_mtd; 708 709static int mtd_proc_show(struct seq_file *m, void *v) 710{ 711 struct mtd_info *mtd; 712 713 seq_puts(m, "dev: size erasesize name\n"); 714 mutex_lock(&mtd_table_mutex); 715 mtd_for_each_device(mtd) { 716 seq_printf(m, "mtd%d: %8.8llx %8.8x \"%s\"\n", 717 mtd->index, (unsigned long long)mtd->size, 718 mtd->erasesize, mtd->name); 719 } 720 mutex_unlock(&mtd_table_mutex); 721 return 0; 722} 723 724static int mtd_proc_open(struct inode *inode, struct file *file) 725{ 726 return single_open(file, mtd_proc_show, NULL); 727} 728 729static const struct file_operations mtd_proc_ops = { 730 .open = mtd_proc_open, 731 .read = seq_read, 732 .llseek = seq_lseek, 733 .release = single_release, 734}; 735#endif /* CONFIG_PROC_FS */ 736 737/*====================================================================*/ 738/* Init code */ 739 740static int __init mtd_bdi_init(struct backing_dev_info *bdi, const char *name) 741{ 742 int ret; 743 744 ret = bdi_init(bdi); 745 if (!ret) 746 ret = bdi_register(bdi, NULL, name); 747 748 if (ret) 749 bdi_destroy(bdi); 750 751 return ret; 752} 753 754static int __init init_mtd(void) 755{ 756 int ret; 757 758 ret = class_register(&mtd_class); 759 if (ret) 760 goto err_reg; 761 762 ret = mtd_bdi_init(&mtd_bdi_unmappable, "mtd-unmap"); 763 if (ret) 764 goto err_bdi1; 765 766 ret = mtd_bdi_init(&mtd_bdi_ro_mappable, "mtd-romap"); 767 if (ret) 768 goto err_bdi2; 769 770 ret = mtd_bdi_init(&mtd_bdi_rw_mappable, "mtd-rwmap"); 771 if (ret) 772 goto err_bdi3; 773 774#ifdef CONFIG_PROC_FS 775 proc_mtd = proc_create("mtd", 0, NULL, &mtd_proc_ops); 776#endif /* CONFIG_PROC_FS */ 777 return 0; 778 779err_bdi3: 780 bdi_destroy(&mtd_bdi_ro_mappable); 781err_bdi2: 782 bdi_destroy(&mtd_bdi_unmappable); 783err_bdi1: 784 class_unregister(&mtd_class); 785err_reg: 786 pr_err("Error registering mtd class or bdi: %d\n", ret); 787 return ret; 788} 789 790static void __exit cleanup_mtd(void) 791{ 792#ifdef CONFIG_PROC_FS 793 if (proc_mtd) 794 remove_proc_entry( "mtd", NULL); 795#endif /* CONFIG_PROC_FS */ 796 class_unregister(&mtd_class); 797 bdi_destroy(&mtd_bdi_unmappable); 798 bdi_destroy(&mtd_bdi_ro_mappable); 799 bdi_destroy(&mtd_bdi_rw_mappable); 800} 801 802module_init(init_mtd); 803module_exit(cleanup_mtd); 804 805MODULE_LICENSE("GPL"); 806MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); 807MODULE_DESCRIPTION("Core MTD registration and access routines"); 808