#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);
.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
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);
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);
{
int err;
+ if (master->_reboot)
+ unregister_reboot_notifier(&master->reboot_notifier);
+
err = del_mtd_partitions(master);
if (err)
return err;
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);
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);
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);