Merge tag 'sound-fix-3.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai...
[linux-2.6-block.git] / drivers / mtd / mtdcore.c
index 4c611871d7e6b40aee79bdc90b2fbfc39506c45c..11883bd26d9d35e8234cc7dc74f51b7ed57d7566 100644 (file)
 #include <linux/backing-dev.h>
 #include <linux/gfp.h>
 #include <linux/slab.h>
+#include <linux/reboot.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 
 #include "mtdcore.h"
 
-/*
- * backing device capabilities for non-mappable devices (such as NAND flash)
- * - permits private mappings, copies are taken of the data
- */
-static struct backing_dev_info mtd_bdi_unmappable = {
-       .capabilities   = BDI_CAP_MAP_COPY,
-};
-
-/*
- * backing device capabilities for R/O mappable devices (such as ROM)
- * - permits private mappings, copies are taken of the data
- * - permits non-writable shared mappings
- */
-static struct backing_dev_info mtd_bdi_ro_mappable = {
-       .capabilities   = (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT |
-                          BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP),
-};
-
-/*
- * backing device capabilities for writable mappable devices (such as RAM)
- * - permits private mappings, copies are taken of the data
- * - permits non-writable shared mappings
- */
-static struct backing_dev_info mtd_bdi_rw_mappable = {
-       .capabilities   = (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT |
-                          BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP |
-                          BDI_CAP_WRITE_MAP),
+static struct backing_dev_info mtd_bdi = {
 };
 
 static int mtd_cls_suspend(struct device *dev, pm_message_t state);
@@ -365,6 +340,34 @@ static struct device_type mtd_devtype = {
        .release        = mtd_release,
 };
 
+#ifndef CONFIG_MMU
+unsigned mtd_mmap_capabilities(struct mtd_info *mtd)
+{
+       switch (mtd->type) {
+       case MTD_RAM:
+               return NOMMU_MAP_COPY | NOMMU_MAP_DIRECT | NOMMU_MAP_EXEC |
+                       NOMMU_MAP_READ | NOMMU_MAP_WRITE;
+       case MTD_ROM:
+               return NOMMU_MAP_COPY | NOMMU_MAP_DIRECT | NOMMU_MAP_EXEC |
+                       NOMMU_MAP_READ;
+       default:
+               return NOMMU_MAP_COPY;
+       }
+}
+EXPORT_SYMBOL_GPL(mtd_mmap_capabilities);
+#endif
+
+static int mtd_reboot_notifier(struct notifier_block *n, unsigned long state,
+                              void *cmd)
+{
+       struct mtd_info *mtd;
+
+       mtd = container_of(n, struct mtd_info, reboot_notifier);
+       mtd->_reboot(mtd);
+
+       return NOTIFY_DONE;
+}
+
 /**
  *     add_mtd_device - register an MTD device
  *     @mtd: pointer to new MTD device info structure
@@ -380,19 +383,7 @@ int add_mtd_device(struct mtd_info *mtd)
        struct mtd_notifier *not;
        int i, error;
 
-       if (!mtd->backing_dev_info) {
-               switch (mtd->type) {
-               case MTD_RAM:
-                       mtd->backing_dev_info = &mtd_bdi_rw_mappable;
-                       break;
-               case MTD_ROM:
-                       mtd->backing_dev_info = &mtd_bdi_ro_mappable;
-                       break;
-               default:
-                       mtd->backing_dev_info = &mtd_bdi_unmappable;
-                       break;
-               }
-       }
+       mtd->backing_dev_info = &mtd_bdi;
 
        BUG_ON(mtd->writesize == 0);
        mutex_lock(&mtd_table_mutex);
@@ -565,6 +556,19 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
                        err = -ENODEV;
        }
 
+       /*
+        * FIXME: some drivers unfortunately call this function more than once.
+        * So we have to check if we've already assigned the reboot notifier.
+        *
+        * Generally, we can make multiple calls work for most cases, but it
+        * does cause problems with parse_mtd_partitions() above (e.g.,
+        * cmdlineparts will register partitions more than once).
+        */
+       if (mtd->_reboot && !mtd->reboot_notifier.notifier_call) {
+               mtd->reboot_notifier.notifier_call = mtd_reboot_notifier;
+               register_reboot_notifier(&mtd->reboot_notifier);
+       }
+
        return err;
 }
 EXPORT_SYMBOL_GPL(mtd_device_parse_register);
@@ -579,6 +583,9 @@ int mtd_device_unregister(struct mtd_info *master)
 {
        int err;
 
+       if (master->_reboot)
+               unregister_reboot_notifier(&master->reboot_notifier);
+
        err = del_mtd_partitions(master);
        if (err)
                return err;
@@ -1237,17 +1244,9 @@ static int __init init_mtd(void)
        if (ret)
                goto err_reg;
 
-       ret = mtd_bdi_init(&mtd_bdi_unmappable, "mtd-unmap");
-       if (ret)
-               goto err_bdi1;
-
-       ret = mtd_bdi_init(&mtd_bdi_ro_mappable, "mtd-romap");
-       if (ret)
-               goto err_bdi2;
-
-       ret = mtd_bdi_init(&mtd_bdi_rw_mappable, "mtd-rwmap");
+       ret = mtd_bdi_init(&mtd_bdi, "mtd");
        if (ret)
-               goto err_bdi3;
+               goto err_bdi;
 
        proc_mtd = proc_create("mtd", 0, NULL, &mtd_proc_ops);
 
@@ -1260,11 +1259,7 @@ static int __init init_mtd(void)
 out_procfs:
        if (proc_mtd)
                remove_proc_entry("mtd", NULL);
-err_bdi3:
-       bdi_destroy(&mtd_bdi_ro_mappable);
-err_bdi2:
-       bdi_destroy(&mtd_bdi_unmappable);
-err_bdi1:
+err_bdi:
        class_unregister(&mtd_class);
 err_reg:
        pr_err("Error registering mtd class or bdi: %d\n", ret);
@@ -1277,9 +1272,7 @@ static void __exit cleanup_mtd(void)
        if (proc_mtd)
                remove_proc_entry("mtd", NULL);
        class_unregister(&mtd_class);
-       bdi_destroy(&mtd_bdi_unmappable);
-       bdi_destroy(&mtd_bdi_ro_mappable);
-       bdi_destroy(&mtd_bdi_rw_mappable);
+       bdi_destroy(&mtd_bdi);
 }
 
 module_init(init_mtd);