summaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/Makefile2
-rw-r--r--[-rwxr-xr-x]drivers/mtd/chips/cfi_util.c0
-rw-r--r--drivers/mtd/chips/jedec_probe.c2
-rw-r--r--drivers/mtd/devices/block2mtd.c1
-rw-r--r--drivers/mtd/devices/m25p80.c1
-rw-r--r--drivers/mtd/devices/sst25l.c1
-rw-r--r--[-rwxr-xr-x]drivers/mtd/inftlcore.c0
-rw-r--r--drivers/mtd/internal.h17
-rw-r--r--drivers/mtd/lpddr/lpddr_cmds.c1
-rw-r--r--drivers/mtd/maps/amd76xrom.c1
-rw-r--r--drivers/mtd/maps/bfin-async-flash.c1
-rw-r--r--drivers/mtd/maps/ck804xrom.c1
-rw-r--r--drivers/mtd/maps/esb2rom.c1
-rw-r--r--drivers/mtd/maps/gpio-addr-flash.c1
-rw-r--r--drivers/mtd/maps/ichxrom.c1
-rw-r--r--drivers/mtd/maps/intel_vr_nor.c1
-rw-r--r--drivers/mtd/maps/octagon-5066.c1
-rw-r--r--drivers/mtd/maps/omap_nor.c0
-rw-r--r--drivers/mtd/maps/physmap_of.c1
-rw-r--r--drivers/mtd/maps/pismo.c3
-rw-r--r--drivers/mtd/maps/plat-ram.c2
-rw-r--r--drivers/mtd/maps/pmcmsp-flash.c1
-rw-r--r--drivers/mtd/maps/pxa2xx-flash.c1
-rw-r--r--drivers/mtd/maps/sbc_gxx.c1
-rw-r--r--drivers/mtd/maps/sun_uflash.c1
-rw-r--r--drivers/mtd/maps/vmax301.c1
-rw-r--r--drivers/mtd/maps/vmu-flash.c1
-rw-r--r--drivers/mtd/mtdbdi.c43
-rw-r--r--drivers/mtd/mtdcore.c80
-rw-r--r--drivers/mtd/mtdsuper.c2
-rw-r--r--drivers/mtd/nand/Kconfig4
-rw-r--r--drivers/mtd/nand/bcm_umi_nand.c5
-rw-r--r--drivers/mtd/nand/cafe_nand.c1
-rw-r--r--drivers/mtd/nand/cmx270_nand.c1
-rw-r--r--drivers/mtd/nand/davinci_nand.c1
-rw-r--r--drivers/mtd/nand/diskonchip.c1
-rw-r--r--drivers/mtd/nand/fsl_upm.c1
-rw-r--r--drivers/mtd/nand/mxc_nand.c2
-rw-r--r--drivers/mtd/nand/ndfc.c1
-rw-r--r--drivers/mtd/nand/nomadik_nand.c1
-rw-r--r--drivers/mtd/nand/omap2.c1
-rw-r--r--drivers/mtd/nand/orion_nand.c8
-rw-r--r--drivers/mtd/nand/pxa3xx_nand.c1
-rw-r--r--drivers/mtd/nand/sh_flctl.c1
-rw-r--r--drivers/mtd/nand/tmio_nand.c1
-rw-r--r--drivers/mtd/ofpart.c1
-rw-r--r--drivers/mtd/onenand/omap2.c1
-rw-r--r--drivers/mtd/onenand/onenand_base.c1
-rw-r--r--drivers/mtd/onenand/onenand_sim.c1
-rw-r--r--drivers/mtd/tests/mtd_nandecctest.c1
-rw-r--r--drivers/mtd/tests/mtd_oobtest.c1
-rw-r--r--drivers/mtd/tests/mtd_pagetest.c1
-rw-r--r--drivers/mtd/tests/mtd_readtest.c1
-rw-r--r--drivers/mtd/tests/mtd_speedtest.c1
-rw-r--r--drivers/mtd/tests/mtd_stresstest.c1
-rw-r--r--drivers/mtd/tests/mtd_subpagetest.c1
-rw-r--r--drivers/mtd/tests/mtd_torturetest.c1
-rw-r--r--drivers/mtd/ubi/build.c137
-rw-r--r--drivers/mtd/ubi/cdev.c1
-rw-r--r--drivers/mtd/ubi/debug.h4
-rw-r--r--drivers/mtd/ubi/gluebi.c1
-rw-r--r--drivers/mtd/ubi/io.c121
-rw-r--r--drivers/mtd/ubi/kapi.c1
-rw-r--r--drivers/mtd/ubi/scan.c12
-rw-r--r--drivers/mtd/ubi/ubi.h1
-rw-r--r--drivers/mtd/ubi/vmt.c1
-rw-r--r--drivers/mtd/ubi/vtbl.c1
-rw-r--r--drivers/mtd/ubi/wl.c17
68 files changed, 341 insertions, 168 deletions
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 82d1e4de475b..4521b1ecce45 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -4,7 +4,7 @@
# Core functionality.
obj-$(CONFIG_MTD) += mtd.o
-mtd-y := mtdcore.o mtdsuper.o mtdbdi.o
+mtd-y := mtdcore.o mtdsuper.o
mtd-$(CONFIG_MTD_PARTITIONS) += mtdpart.o
obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o
diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c
index ca584d0380b4..ca584d0380b4 100755..100644
--- a/drivers/mtd/chips/cfi_util.c
+++ b/drivers/mtd/chips/cfi_util.c
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
index 1bec5e1ce6ac..8db1148dfa47 100644
--- a/drivers/mtd/chips/jedec_probe.c
+++ b/drivers/mtd/chips/jedec_probe.c
@@ -226,7 +226,7 @@ struct unlock_addr {
* exists, but is for MTD_UADDR_NOT_SUPPORTED - and, therefore,
* should not be used. The problem is that structures with
* initializers have extra fields initialized to 0. It is _very_
- * desireable to have the unlock address entries for unsupported
+ * desirable to have the unlock address entries for unsupported
* data widths automatically initialized - that means that
* MTD_UADDR_NOT_SUPPORTED must be 0 and the first entry here
* must go unused.
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index 8c295f40d2ac..ce6424008ed9 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -17,6 +17,7 @@
#include <linux/buffer_head.h>
#include <linux/mutex.h>
#include <linux/mount.h>
+#include <linux/slab.h>
#define ERROR(fmt, args...) printk(KERN_ERR "block2mtd: " fmt "\n" , ## args)
#define INFO(fmt, args...) printk(KERN_INFO "block2mtd: " fmt "\n" , ## args)
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index f3f4768d6e18..81e49a9b017e 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -21,6 +21,7 @@
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/math64.h>
+#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/mod_devicetable.h>
diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c
index 0a11721f146e..fe17054ee2fe 100644
--- a/drivers/mtd/devices/sst25l.c
+++ b/drivers/mtd/devices/sst25l.c
@@ -20,6 +20,7 @@
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/interrupt.h>
+#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/mtd/mtd.h>
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
index 8aca5523a337..8aca5523a337 100755..100644
--- a/drivers/mtd/inftlcore.c
+++ b/drivers/mtd/inftlcore.c
diff --git a/drivers/mtd/internal.h b/drivers/mtd/internal.h
index c658fe7216b5..e69de29bb2d1 100644
--- a/drivers/mtd/internal.h
+++ b/drivers/mtd/internal.h
@@ -1,17 +0,0 @@
-/* Internal MTD definitions
- *
- * Copyright © 2006 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-/*
- * mtdbdi.c
- */
-extern struct backing_dev_info mtd_bdi_unmappable;
-extern struct backing_dev_info mtd_bdi_ro_mappable;
-extern struct backing_dev_info mtd_bdi_rw_mappable;
diff --git a/drivers/mtd/lpddr/lpddr_cmds.c b/drivers/mtd/lpddr/lpddr_cmds.c
index e22ca49583e7..a73ee12aad81 100644
--- a/drivers/mtd/lpddr/lpddr_cmds.c
+++ b/drivers/mtd/lpddr/lpddr_cmds.c
@@ -26,6 +26,7 @@
*/
#include <linux/mtd/pfow.h>
#include <linux/mtd/qinfo.h>
+#include <linux/slab.h>
static int lpddr_read(struct mtd_info *mtd, loff_t adr, size_t len,
size_t *retlen, u_char *buf);
diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c
index 237733d094c4..19fe92db0c46 100644
--- a/drivers/mtd/maps/amd76xrom.c
+++ b/drivers/mtd/maps/amd76xrom.c
@@ -8,6 +8,7 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/slab.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c
index a7c808b577d3..c0fd99b0c525 100644
--- a/drivers/mtd/maps/bfin-async-flash.c
+++ b/drivers/mtd/maps/bfin-async-flash.c
@@ -22,6 +22,7 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/platform_device.h>
+#include <linux/slab.h>
#include <linux/types.h>
#include <asm/blackfin.h>
diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c
index 424f17d6ffd1..ddb462bea9b5 100644
--- a/drivers/mtd/maps/ck804xrom.c
+++ b/drivers/mtd/maps/ck804xrom.c
@@ -11,6 +11,7 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/slab.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c
index 11a2f57df9cf..d12c93dc1aad 100644
--- a/drivers/mtd/maps/esb2rom.c
+++ b/drivers/mtd/maps/esb2rom.c
@@ -14,6 +14,7 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/slab.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c
index 1ad5caf9fe69..32e89d773b4e 100644
--- a/drivers/mtd/maps/gpio-addr-flash.c
+++ b/drivers/mtd/maps/gpio-addr-flash.c
@@ -23,6 +23,7 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/platform_device.h>
+#include <linux/slab.h>
#include <linux/types.h>
#define pr_devinit(fmt, args...) ({ static const __devinitconst char __fmt[] = fmt; printk(__fmt, ## args); })
diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c
index c32bc28920b3..f102bf243a74 100644
--- a/drivers/mtd/maps/ichxrom.c
+++ b/drivers/mtd/maps/ichxrom.c
@@ -8,6 +8,7 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/slab.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
diff --git a/drivers/mtd/maps/intel_vr_nor.c b/drivers/mtd/maps/intel_vr_nor.c
index 1e7814ae212a..fc1998512eb4 100644
--- a/drivers/mtd/maps/intel_vr_nor.c
+++ b/drivers/mtd/maps/intel_vr_nor.c
@@ -29,6 +29,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
diff --git a/drivers/mtd/maps/octagon-5066.c b/drivers/mtd/maps/octagon-5066.c
index 2b2e45093218..23fe1786770f 100644
--- a/drivers/mtd/maps/octagon-5066.c
+++ b/drivers/mtd/maps/octagon-5066.c
@@ -24,7 +24,6 @@
##################################################################### */
#include <linux/module.h>
-#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <asm/io.h>
diff --git a/drivers/mtd/maps/omap_nor.c b/drivers/mtd/maps/omap_nor.c
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/drivers/mtd/maps/omap_nor.c
+++ /dev/null
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index 61e4eb48bb2d..101ee6ead05c 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -23,6 +23,7 @@
#include <linux/mtd/concat.h>
#include <linux/of.h>
#include <linux/of_platform.h>
+#include <linux/slab.h>
struct of_flash_list {
struct mtd_info *mtd;
diff --git a/drivers/mtd/maps/pismo.c b/drivers/mtd/maps/pismo.c
index c48cad271f5d..60c068db452d 100644
--- a/drivers/mtd/maps/pismo.c
+++ b/drivers/mtd/maps/pismo.c
@@ -10,6 +10,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
+#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
@@ -118,7 +119,7 @@ static int __devinit pismo_add_device(struct pismo_data *pismo, int i,
{
struct platform_device *dev;
struct resource res = { };
- phys_addr_t base = region.base;
+ phys_addr_t base = region->base;
int ret;
if (base == ~0)
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c
index dafb91944e70..76a76be5a7bd 100644
--- a/drivers/mtd/maps/plat-ram.c
+++ b/drivers/mtd/maps/plat-ram.c
@@ -4,7 +4,7 @@
* http://www.simtec.co.uk/products/SWLINUX/
* Ben Dooks <ben@simtec.co.uk>
*
- * Generic platfrom device based RAM map
+ * Generic platform device based RAM map
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/drivers/mtd/maps/pmcmsp-flash.c b/drivers/mtd/maps/pmcmsp-flash.c
index c8fd8da4bc87..acb13fa5001c 100644
--- a/drivers/mtd/maps/pmcmsp-flash.c
+++ b/drivers/mtd/maps/pmcmsp-flash.c
@@ -28,6 +28,7 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <linux/slab.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index b13f6417b5b2..91dc6331053f 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/types.h>
+#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
diff --git a/drivers/mtd/maps/sbc_gxx.c b/drivers/mtd/maps/sbc_gxx.c
index 1b1c0b7e11ef..04b2781fc627 100644
--- a/drivers/mtd/maps/sbc_gxx.c
+++ b/drivers/mtd/maps/sbc_gxx.c
@@ -45,7 +45,6 @@ separate MTD devices.
// Includes
#include <linux/module.h>
-#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <asm/io.h>
diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c
index fd7a1017399a..fadc4c45b455 100644
--- a/drivers/mtd/maps/sun_uflash.c
+++ b/drivers/mtd/maps/sun_uflash.c
@@ -15,6 +15,7 @@
#include <linux/ioport.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/slab.h>
#include <asm/prom.h>
#include <asm/uaccess.h>
#include <asm/io.h>
diff --git a/drivers/mtd/maps/vmax301.c b/drivers/mtd/maps/vmax301.c
index 6d452dcdfe34..6adaa6acc193 100644
--- a/drivers/mtd/maps/vmax301.c
+++ b/drivers/mtd/maps/vmax301.c
@@ -16,7 +16,6 @@
##################################################################### */
#include <linux/module.h>
-#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/spinlock.h>
diff --git a/drivers/mtd/maps/vmu-flash.c b/drivers/mtd/maps/vmu-flash.c
index 82afad0ddd72..4afc167731ef 100644
--- a/drivers/mtd/maps/vmu-flash.c
+++ b/drivers/mtd/maps/vmu-flash.c
@@ -8,6 +8,7 @@
* GNU General Public Licence
*/
#include <linux/init.h>
+#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/maple.h>
diff --git a/drivers/mtd/mtdbdi.c b/drivers/mtd/mtdbdi.c
index 5ca5aed0b225..e69de29bb2d1 100644
--- a/drivers/mtd/mtdbdi.c
+++ b/drivers/mtd/mtdbdi.c
@@ -1,43 +0,0 @@
-/* MTD backing device capabilities
- *
- * Copyright © 2006 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/backing-dev.h>
-#include <linux/mtd/mtd.h>
-#include "internal.h"
-
-/*
- * backing device capabilities for non-mappable devices (such as NAND flash)
- * - permits private mappings, copies are taken of the data
- */
-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
- */
-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
- */
-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),
-};
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index c356c0a30c3e..b177e750efc3 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -2,12 +2,14 @@
* Core registration and callback routines for MTD
* drivers and users.
*
+ * bdi bits are:
+ * Copyright © 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/ptrace.h>
-#include <linux/slab.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/major.h>
@@ -17,11 +19,39 @@
#include <linux/init.h>
#include <linux/mtd/compatmac.h>
#include <linux/proc_fs.h>
+#include <linux/backing-dev.h>
#include <linux/mtd/mtd.h>
-#include "internal.h"
#include "mtdcore.h"
+/*
+ * backing device capabilities for non-mappable devices (such as NAND flash)
+ * - permits private mappings, copies are taken of the data
+ */
+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
+ */
+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
+ */
+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 int mtd_cls_suspend(struct device *dev, pm_message_t state);
static int mtd_cls_resume(struct device *dev);
@@ -629,20 +659,55 @@ done:
/*====================================================================*/
/* Init code */
+static int __init mtd_bdi_init(struct backing_dev_info *bdi, const char *name)
+{
+ int ret;
+
+ ret = bdi_init(bdi);
+ if (!ret)
+ ret = bdi_register(bdi, NULL, name);
+
+ if (ret)
+ bdi_destroy(bdi);
+
+ return ret;
+}
+
static int __init init_mtd(void)
{
int ret;
+
ret = class_register(&mtd_class);
+ 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");
+ if (ret)
+ goto err_bdi3;
- if (ret) {
- pr_err("Error registering mtd class: %d\n", ret);
- return ret;
- }
#ifdef CONFIG_PROC_FS
if ((proc_mtd = create_proc_entry( "mtd", 0, NULL )))
proc_mtd->read_proc = mtd_read_proc;
#endif /* CONFIG_PROC_FS */
return 0;
+
+err_bdi3:
+ bdi_destroy(&mtd_bdi_ro_mappable);
+err_bdi2:
+ bdi_destroy(&mtd_bdi_unmappable);
+err_bdi1:
+ class_unregister(&mtd_class);
+err_reg:
+ pr_err("Error registering mtd class or bdi: %d\n", ret);
+ return ret;
}
static void __exit cleanup_mtd(void)
@@ -652,6 +717,9 @@ static void __exit cleanup_mtd(void)
remove_proc_entry( "mtd", NULL);
#endif /* CONFIG_PROC_FS */
class_unregister(&mtd_class);
+ bdi_destroy(&mtd_bdi_unmappable);
+ bdi_destroy(&mtd_bdi_ro_mappable);
+ bdi_destroy(&mtd_bdi_rw_mappable);
}
module_init(init_mtd);
diff --git a/drivers/mtd/mtdsuper.c b/drivers/mtd/mtdsuper.c
index af8b42e0a55b..7c003191fca4 100644
--- a/drivers/mtd/mtdsuper.c
+++ b/drivers/mtd/mtdsuper.c
@@ -13,6 +13,7 @@
#include <linux/mtd/super.h>
#include <linux/namei.h>
#include <linux/ctype.h>
+#include <linux/slab.h>
/*
* compare superblocks to see if they're equivalent
@@ -44,6 +45,7 @@ static int get_sb_mtd_set(struct super_block *sb, void *_mtd)
sb->s_mtd = mtd;
sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, mtd->index);
+ sb->s_bdi = mtd->backing_dev_info;
return 0;
}
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index bb6465604235..42e5ea49e975 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -444,7 +444,7 @@ config MTD_NAND_FSL_UPM
config MTD_NAND_MXC
tristate "MXC NAND support"
- depends on ARCH_MX2 || ARCH_MX3
+ depends on ARCH_MX2 || ARCH_MX25 || ARCH_MX3
help
This enables the driver for the NAND flash controller on the
MXC processors.
@@ -457,7 +457,7 @@ config MTD_NAND_NOMADIK
config MTD_NAND_SH_FLCTL
tristate "Support for NAND on Renesas SuperH FLCTL"
- depends on MTD_NAND && SUPERH
+ depends on MTD_NAND && (SUPERH || ARCH_SHMOBILE)
help
Several Renesas SuperH CPU has FLCTL. This option enables support
for NAND Flash using FLCTL.
diff --git a/drivers/mtd/nand/bcm_umi_nand.c b/drivers/mtd/nand/bcm_umi_nand.c
index 087bcd745bb7..c997f98eeb3d 100644
--- a/drivers/mtd/nand/bcm_umi_nand.c
+++ b/drivers/mtd/nand/bcm_umi_nand.c
@@ -18,6 +18,7 @@
#include <linux/types.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/slab.h>
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/device.h>
@@ -381,7 +382,7 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev)
if (!r)
return -ENXIO;
- /* map physical adress */
+ /* map physical address */
bcm_umi_io_base = ioremap(r->start, r->end - r->start + 1);
if (!bcm_umi_io_base) {
@@ -525,7 +526,7 @@ static int bcm_umi_nand_remove(struct platform_device *pdev)
/* Release resources, unregister device */
nand_release(board_mtd);
- /* unmap physical adress */
+ /* unmap physical address */
iounmap(bcm_umi_io_base);
/* Free the MTD device structure */
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
index c828d9ac7bd7..e5a9f9ccea60 100644
--- a/drivers/mtd/nand/cafe_nand.c
+++ b/drivers/mtd/nand/cafe_nand.c
@@ -20,6 +20,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
+#include <linux/slab.h>
#include <asm/io.h>
#define CAFE_NAND_CTRL1 0x00
diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c
index 826cacffcefc..6e6495278258 100644
--- a/drivers/mtd/nand/cmx270_nand.c
+++ b/drivers/mtd/nand/cmx270_nand.c
@@ -20,6 +20,7 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
+#include <linux/slab.h>
#include <linux/gpio.h>
#include <asm/io.h>
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index fe3eba87de40..76e2dc8e62f7 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -32,6 +32,7 @@
#include <linux/io.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
+#include <linux/slab.h>
#include <mach/nand.h>
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index b126cf887476..47067bc98248 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -23,6 +23,7 @@
#include <linux/delay.h>
#include <linux/rslib.h>
#include <linux/moduleparam.h>
+#include <linux/slab.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 071a60cb4204..4b96296af321 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -21,6 +21,7 @@
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/io.h>
+#include <linux/slab.h>
#include <asm/fsl_lbc.h>
#define FSL_UPM_WAIT_RUN_PATTERN 0x1
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 45dec5770da0..b2900d8406d3 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -507,7 +507,7 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
* MXC NANDFC can only perform full page+spare or
* spare-only read/write. When the upper layers
* layers perform a read/write buf operation,
- * we will used the saved column adress to index into
+ * we will used the saved column address to index into
* the full page.
*/
send_addr(host, 0, page_addr == -1);
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 40b5658bdbe6..b983cae8c298 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -28,6 +28,7 @@
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/ndfc.h>
+#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/of_platform.h>
#include <asm/io.h>
diff --git a/drivers/mtd/nand/nomadik_nand.c b/drivers/mtd/nand/nomadik_nand.c
index 66123419f65d..1f6f741af5da 100644
--- a/drivers/mtd/nand/nomadik_nand.c
+++ b/drivers/mtd/nand/nomadik_nand.c
@@ -30,6 +30,7 @@
#include <linux/platform_device.h>
#include <linux/mtd/partitions.h>
#include <linux/io.h>
+#include <linux/slab.h>
#include <mach/nand.h>
#include <mach/fsmc.h>
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 26aec0080184..7545568fce47 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -17,6 +17,7 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <linux/io.h>
+#include <linux/slab.h>
#include <plat/dma.h>
#include <plat/gpmc.h>
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
index f59c07427af3..d60fc5719fef 100644
--- a/drivers/mtd/nand/orion_nand.c
+++ b/drivers/mtd/nand/orion_nand.c
@@ -60,7 +60,13 @@ static void orion_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
}
buf64 = (uint64_t *)buf;
while (i < len/8) {
- uint64_t x;
+ /*
+ * Since GCC has no proper constraint (PR 43518)
+ * force x variable to r2/r3 registers as ldrd instruction
+ * requires first register to be even.
+ */
+ register uint64_t x asm ("r2");
+
asm volatile ("ldrd\t%0, [%1]" : "=&r" (x) : "r" (io_base));
buf64[i++] = x;
}
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 1a5a0365c983..5d55152162cf 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -21,6 +21,7 @@
#include <linux/mtd/partitions.h>
#include <linux/io.h>
#include <linux/irq.h>
+#include <linux/slab.h>
#include <mach/dma.h>
#include <plat/pxa3xx_nand.h>
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
index 1842df8bdd93..34752fce0793 100644
--- a/drivers/mtd/nand/sh_flctl.c
+++ b/drivers/mtd/nand/sh_flctl.c
@@ -26,6 +26,7 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/platform_device.h>
+#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c
index 92c73344a669..fa28f01ae009 100644
--- a/drivers/mtd/nand/tmio_nand.c
+++ b/drivers/mtd/nand/tmio_nand.c
@@ -37,6 +37,7 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
+#include <linux/slab.h>
/*--------------------------------------------------------------------------*/
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index 62d6a78c4eee..4f0d635674f3 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/of.h>
#include <linux/mtd/mtd.h>
+#include <linux/slab.h>
#include <linux/mtd/partitions.h>
int __devinit of_mtd_parse_partitions(struct device *dev,
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 75f38b95811e..fd406348fdfd 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -34,6 +34,7 @@
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
+#include <linux/slab.h>
#include <asm/mach/flash.h>
#include <plat/gpmc.h>
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index f63b1db3ffb3..32f0ed33afe0 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -23,6 +23,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
+#include <linux/slab.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/delay.h>
diff --git a/drivers/mtd/onenand/onenand_sim.c b/drivers/mtd/onenand/onenand_sim.c
index f6e3c8aebd3a..8b246061d511 100644
--- a/drivers/mtd/onenand/onenand_sim.c
+++ b/drivers/mtd/onenand/onenand_sim.c
@@ -16,6 +16,7 @@
*/
#include <linux/kernel.h>
+#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/vmalloc.h>
diff --git a/drivers/mtd/tests/mtd_nandecctest.c b/drivers/mtd/tests/mtd_nandecctest.c
index c1f31051784c..70d6d7d0d656 100644
--- a/drivers/mtd/tests/mtd_nandecctest.c
+++ b/drivers/mtd/tests/mtd_nandecctest.c
@@ -1,7 +1,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/list.h>
-#include <linux/slab.h>
#include <linux/random.h>
#include <linux/string.h>
#include <linux/bitops.h>
diff --git a/drivers/mtd/tests/mtd_oobtest.c b/drivers/mtd/tests/mtd_oobtest.c
index 5813920e79a5..dec92ae6111a 100644
--- a/drivers/mtd/tests/mtd_oobtest.c
+++ b/drivers/mtd/tests/mtd_oobtest.c
@@ -25,6 +25,7 @@
#include <linux/moduleparam.h>
#include <linux/err.h>
#include <linux/mtd/mtd.h>
+#include <linux/slab.h>
#include <linux/sched.h>
#define PRINT_PREF KERN_INFO "mtd_oobtest: "
diff --git a/drivers/mtd/tests/mtd_pagetest.c b/drivers/mtd/tests/mtd_pagetest.c
index ce17cbe918c5..921a85df9196 100644
--- a/drivers/mtd/tests/mtd_pagetest.c
+++ b/drivers/mtd/tests/mtd_pagetest.c
@@ -25,6 +25,7 @@
#include <linux/moduleparam.h>
#include <linux/err.h>
#include <linux/mtd/mtd.h>
+#include <linux/slab.h>
#include <linux/sched.h>
#define PRINT_PREF KERN_INFO "mtd_pagetest: "
diff --git a/drivers/mtd/tests/mtd_readtest.c b/drivers/mtd/tests/mtd_readtest.c
index 25c5dd03a837..7107fccbc7de 100644
--- a/drivers/mtd/tests/mtd_readtest.c
+++ b/drivers/mtd/tests/mtd_readtest.c
@@ -24,6 +24,7 @@
#include <linux/moduleparam.h>
#include <linux/err.h>
#include <linux/mtd/mtd.h>
+#include <linux/slab.h>
#include <linux/sched.h>
#define PRINT_PREF KERN_INFO "mtd_readtest: "
diff --git a/drivers/mtd/tests/mtd_speedtest.c b/drivers/mtd/tests/mtd_speedtest.c
index 7fbb51d4eabe..56ca62bb96bf 100644
--- a/drivers/mtd/tests/mtd_speedtest.c
+++ b/drivers/mtd/tests/mtd_speedtest.c
@@ -24,6 +24,7 @@
#include <linux/moduleparam.h>
#include <linux/err.h>
#include <linux/mtd/mtd.h>
+#include <linux/slab.h>
#include <linux/sched.h>
#define PRINT_PREF KERN_INFO "mtd_speedtest: "
diff --git a/drivers/mtd/tests/mtd_stresstest.c b/drivers/mtd/tests/mtd_stresstest.c
index a99d3cd737d8..3854afec56d0 100644
--- a/drivers/mtd/tests/mtd_stresstest.c
+++ b/drivers/mtd/tests/mtd_stresstest.c
@@ -24,6 +24,7 @@
#include <linux/moduleparam.h>
#include <linux/err.h>
#include <linux/mtd/mtd.h>
+#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/vmalloc.h>
diff --git a/drivers/mtd/tests/mtd_subpagetest.c b/drivers/mtd/tests/mtd_subpagetest.c
index 5b889724268e..700237a3d120 100644
--- a/drivers/mtd/tests/mtd_subpagetest.c
+++ b/drivers/mtd/tests/mtd_subpagetest.c
@@ -24,6 +24,7 @@
#include <linux/moduleparam.h>
#include <linux/err.h>
#include <linux/mtd/mtd.h>
+#include <linux/slab.h>
#include <linux/sched.h>
#define PRINT_PREF KERN_INFO "mtd_subpagetest: "
diff --git a/drivers/mtd/tests/mtd_torturetest.c b/drivers/mtd/tests/mtd_torturetest.c
index 631a0ab3a33c..5c6c3d248901 100644
--- a/drivers/mtd/tests/mtd_torturetest.c
+++ b/drivers/mtd/tests/mtd_torturetest.c
@@ -28,6 +28,7 @@
#include <linux/moduleparam.h>
#include <linux/err.h>
#include <linux/mtd/mtd.h>
+#include <linux/slab.h>
#include <linux/sched.h>
#define PRINT_PREF KERN_INFO "mtd_torturetest: "
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 14cec04c34f9..55c726dde942 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -37,12 +37,14 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/stringify.h>
+#include <linux/namei.h>
#include <linux/stat.h>
#include <linux/miscdevice.h>
#include <linux/log2.h>
#include <linux/kthread.h>
#include <linux/reboot.h>
#include <linux/kernel.h>
+#include <linux/slab.h>
#include "ubi.h"
/* Maximum length of the 'mtd=' parameter */
@@ -50,7 +52,8 @@
/**
* struct mtd_dev_param - MTD device parameter description data structure.
- * @name: MTD device name or number string
+ * @name: MTD character device node path, MTD device name, or MTD device number
+ * string
* @vid_hdr_offs: VID header offset
*/
struct mtd_dev_param {
@@ -59,10 +62,10 @@ struct mtd_dev_param {
};
/* Numbers of elements set in the @mtd_dev_param array */
-static int mtd_devs;
+static int __initdata mtd_devs;
/* MTD devices specification parameters */
-static struct mtd_dev_param mtd_dev_param[UBI_MAX_DEVICES];
+static struct mtd_dev_param __initdata mtd_dev_param[UBI_MAX_DEVICES];
/* Root UBI "class" object (corresponds to '/<sysfs>/class/ubi/') */
struct class *ubi_class;
@@ -87,7 +90,8 @@ DEFINE_MUTEX(ubi_devices_mutex);
static DEFINE_SPINLOCK(ubi_devices_lock);
/* "Show" method for files in '/<sysfs>/class/ubi/' */
-static ssize_t ubi_version_show(struct class *class, char *buf)
+static ssize_t ubi_version_show(struct class *class, struct class_attribute *attr,
+ char *buf)
{
return sprintf(buf, "%d\n", UBI_VERSION);
}
@@ -363,11 +367,13 @@ static void dev_release(struct device *dev)
/**
* ubi_sysfs_init - initialize sysfs for an UBI device.
* @ubi: UBI device description object
+ * @ref: set to %1 on exit in case of failure if a reference to @ubi->dev was
+ * taken
*
* This function returns zero in case of success and a negative error code in
* case of failure.
*/
-static int ubi_sysfs_init(struct ubi_device *ubi)
+static int ubi_sysfs_init(struct ubi_device *ubi, int *ref)
{
int err;
@@ -379,6 +385,7 @@ static int ubi_sysfs_init(struct ubi_device *ubi)
if (err)
return err;
+ *ref = 1;
err = device_create_file(&ubi->dev, &dev_eraseblock_size);
if (err)
return err;
@@ -434,7 +441,7 @@ static void ubi_sysfs_close(struct ubi_device *ubi)
}
/**
- * kill_volumes - destroy all volumes.
+ * kill_volumes - destroy all user volumes.
* @ubi: UBI device description object
*/
static void kill_volumes(struct ubi_device *ubi)
@@ -447,36 +454,29 @@ static void kill_volumes(struct ubi_device *ubi)
}
/**
- * free_user_volumes - free all user volumes.
- * @ubi: UBI device description object
- *
- * Normally the volumes are freed at the release function of the volume device
- * objects. However, on error paths the volumes have to be freed before the
- * device objects have been initialized.
- */
-static void free_user_volumes(struct ubi_device *ubi)
-{
- int i;
-
- for (i = 0; i < ubi->vtbl_slots; i++)
- if (ubi->volumes[i]) {
- kfree(ubi->volumes[i]->eba_tbl);
- kfree(ubi->volumes[i]);
- }
-}
-
-/**
* uif_init - initialize user interfaces for an UBI device.
* @ubi: UBI device description object
+ * @ref: set to %1 on exit in case of failure if a reference to @ubi->dev was
+ * taken, otherwise set to %0
+ *
+ * This function initializes various user interfaces for an UBI device. If the
+ * initialization fails at an early stage, this function frees all the
+ * resources it allocated, returns an error, and @ref is set to %0. However,
+ * if the initialization fails after the UBI device was registered in the
+ * driver core subsystem, this function takes a reference to @ubi->dev, because
+ * otherwise the release function ('dev_release()') would free whole @ubi
+ * object. The @ref argument is set to %1 in this case. The caller has to put
+ * this reference.
*
* This function returns zero in case of success and a negative error code in
- * case of failure. Note, this function destroys all volumes if it fails.
+ * case of failure.
*/
-static int uif_init(struct ubi_device *ubi)
+static int uif_init(struct ubi_device *ubi, int *ref)
{
int i, err;
dev_t dev;
+ *ref = 0;
sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num);
/*
@@ -504,7 +504,7 @@ static int uif_init(struct ubi_device *ubi)
goto out_unreg;
}
- err = ubi_sysfs_init(ubi);
+ err = ubi_sysfs_init(ubi, ref);
if (err)
goto out_sysfs;
@@ -522,6 +522,8 @@ static int uif_init(struct ubi_device *ubi)
out_volumes:
kill_volumes(ubi);
out_sysfs:
+ if (*ref)
+ get_device(&ubi->dev);
ubi_sysfs_close(ubi);
cdev_del(&ubi->cdev);
out_unreg:
@@ -875,7 +877,7 @@ static int ubi_reboot_notifier(struct notifier_block *n, unsigned long state,
int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
{
struct ubi_device *ubi;
- int i, err, do_free = 1;
+ int i, err, ref = 0;
/*
* Check if we already have the same MTD device attached.
@@ -975,9 +977,9 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
goto out_detach;
}
- err = uif_init(ubi);
+ err = uif_init(ubi, &ref);
if (err)
- goto out_nofree;
+ goto out_detach;
ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name);
if (IS_ERR(ubi->bgt_thread)) {
@@ -1025,12 +1027,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
out_uif:
uif_close(ubi);
-out_nofree:
- do_free = 0;
out_detach:
ubi_wl_close(ubi);
- if (do_free)
- free_user_volumes(ubi);
free_internal_volumes(ubi);
vfree(ubi->vtbl);
out_free:
@@ -1039,7 +1037,10 @@ out_free:
#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
vfree(ubi->dbg_peb_buf);
#endif
- kfree(ubi);
+ if (ref)
+ put_device(&ubi->dev);
+ else
+ kfree(ubi);
return err;
}
@@ -1096,7 +1097,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
/*
* Get a reference to the device in order to prevent 'dev_release()'
- * from freeing @ubi object.
+ * from freeing the @ubi object.
*/
get_device(&ubi->dev);
@@ -1116,13 +1117,50 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
}
/**
- * find_mtd_device - open an MTD device by its name or number.
- * @mtd_dev: name or number of the device
+ * open_mtd_by_chdev - open an MTD device by its character device node path.
+ * @mtd_dev: MTD character device node path
+ *
+ * This helper function opens an MTD device by its character node device path.
+ * Returns MTD device description object in case of success and a negative
+ * error code in case of failure.
+ */
+static struct mtd_info * __init open_mtd_by_chdev(const char *mtd_dev)
+{
+ int err, major, minor, mode;
+ struct path path;
+
+ /* Probably this is an MTD character device node path */
+ err = kern_path(mtd_dev, LOOKUP_FOLLOW, &path);
+ if (err)
+ return ERR_PTR(err);
+
+ /* MTD device number is defined by the major / minor numbers */
+ major = imajor(path.dentry->d_inode);
+ minor = iminor(path.dentry->d_inode);
+ mode = path.dentry->d_inode->i_mode;
+ path_put(&path);
+ if (major != MTD_CHAR_MAJOR || !S_ISCHR(mode))
+ return ERR_PTR(-EINVAL);
+
+ if (minor & 1)
+ /*
+ * Just do not think the "/dev/mtdrX" devices support is need,
+ * so do not support them to avoid doing extra work.
+ */
+ return ERR_PTR(-EINVAL);
+
+ return get_mtd_device(NULL, minor / 2);
+}
+
+/**
+ * open_mtd_device - open MTD device by name, character device path, or number.
+ * @mtd_dev: name, character device node path, or MTD device device number
*
* This function tries to open and MTD device described by @mtd_dev string,
- * which is first treated as an ASCII number, and if it is not true, it is
- * treated as MTD device name. Returns MTD device description object in case of
- * success and a negative error code in case of failure.
+ * which is first treated as ASCII MTD device number, and if it is not true, it
+ * is treated as MTD device name, and if that is also not true, it is treated
+ * as MTD character device node path. Returns MTD device description object in
+ * case of success and a negative error code in case of failure.
*/
static struct mtd_info * __init open_mtd_device(const char *mtd_dev)
{
@@ -1137,6 +1175,9 @@ static struct mtd_info * __init open_mtd_device(const char *mtd_dev)
* MTD device name.
*/
mtd = get_mtd_device_nm(mtd_dev);
+ if (IS_ERR(mtd) && PTR_ERR(mtd) == -ENODEV)
+ /* Probably this is an MTD character device node path */
+ mtd = open_mtd_by_chdev(mtd_dev);
} else
mtd = get_mtd_device(NULL, mtd_num);
@@ -1352,13 +1393,15 @@ static int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp)
module_param_call(mtd, ubi_mtd_param_parse, NULL, NULL, 000);
MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: "
- "mtd=<name|num>[,<vid_hdr_offs>].\n"
+ "mtd=<name|num|path>[,<vid_hdr_offs>].\n"
"Multiple \"mtd\" parameters may be specified.\n"
- "MTD devices may be specified by their number or name.\n"
+ "MTD devices may be specified by their number, name, or "
+ "path to the MTD character device node.\n"
"Optional \"vid_hdr_offs\" parameter specifies UBI VID "
- "header position and data starting position to be used "
- "by UBI.\n"
- "Example: mtd=content,1984 mtd=4 - attach MTD device"
+ "header position to be used by UBI.\n"
+ "Example 1: mtd=/dev/mtd0 - attach MTD device "
+ "/dev/mtd0.\n"
+ "Example 2: mtd=content,1984 mtd=4 - attach MTD device "
"with name \"content\" using VID header offset 1984, and "
"MTD device number 4 with default VID header offset.");
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 111ea41c4ecd..72ebb3f06b86 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -37,6 +37,7 @@
#include <linux/module.h>
#include <linux/stat.h>
+#include <linux/slab.h>
#include <linux/ioctl.h>
#include <linux/capability.h>
#include <linux/uaccess.h>
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
index f30bcb372c05..17a107129726 100644
--- a/drivers/mtd/ubi/debug.h
+++ b/drivers/mtd/ubi/debug.h
@@ -96,8 +96,11 @@ void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len);
#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len);
+int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
+ int offset, int len);
#else
#define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0
+#define ubi_dbg_check_write(ubi, buf, pnum, offset, len) 0
#endif
#ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT
@@ -176,6 +179,7 @@ static inline int ubi_dbg_is_erase_failure(void)
#define ubi_dbg_is_write_failure() 0
#define ubi_dbg_is_erase_failure() 0
#define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0
+#define ubi_dbg_check_write(ubi, buf, pnum, offset, len) 0
#endif /* !CONFIG_MTD_UBI_DEBUG */
#endif /* !__UBI_DEBUG_H__ */
diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c
index b5e478fa2661..9aa81584c8a2 100644
--- a/drivers/mtd/ubi/gluebi.c
+++ b/drivers/mtd/ubi/gluebi.c
@@ -31,6 +31,7 @@
#include <linux/err.h>
#include <linux/list.h>
+#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/math64.h>
#include <linux/module.h>
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 8aa51e7a6a7d..533b1a4b9af1 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -88,6 +88,7 @@
#include <linux/crc32.h>
#include <linux/err.h>
+#include <linux/slab.h>
#include "ubi.h"
#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
@@ -143,7 +144,7 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
err = paranoid_check_not_bad(ubi, pnum);
if (err)
- return err > 0 ? -EINVAL : err;
+ return err;
addr = (loff_t)pnum * ubi->peb_size + offset;
retry:
@@ -236,12 +237,12 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
err = paranoid_check_not_bad(ubi, pnum);
if (err)
- return err > 0 ? -EINVAL : err;
+ return err;
/* The area we are writing to has to contain all 0xFF bytes */
err = ubi_dbg_check_all_ff(ubi, pnum, offset, len);
if (err)
- return err > 0 ? -EINVAL : err;
+ return err;
if (offset >= ubi->leb_start) {
/*
@@ -250,10 +251,10 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
*/
err = paranoid_check_peb_ec_hdr(ubi, pnum);
if (err)
- return err > 0 ? -EINVAL : err;
+ return err;
err = paranoid_check_peb_vid_hdr(ubi, pnum);
if (err)
- return err > 0 ? -EINVAL : err;
+ return err;
}
if (ubi_dbg_is_write_failure()) {
@@ -273,6 +274,21 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
} else
ubi_assert(written == len);
+ if (!err) {
+ err = ubi_dbg_check_write(ubi, buf, pnum, offset, len);
+ if (err)
+ return err;
+
+ /*
+ * Since we always write sequentially, the rest of the PEB has
+ * to contain only 0xFF bytes.
+ */
+ offset += len;
+ len = ubi->peb_size - offset;
+ if (len)
+ err = ubi_dbg_check_all_ff(ubi, pnum, offset, len);
+ }
+
return err;
}
@@ -348,7 +364,7 @@ retry:
err = ubi_dbg_check_all_ff(ubi, pnum, 0, ubi->peb_size);
if (err)
- return err > 0 ? -EINVAL : err;
+ return err;
if (ubi_dbg_is_erase_failure() && !err) {
dbg_err("cannot erase PEB %d (emulated)", pnum);
@@ -542,7 +558,7 @@ int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture)
err = paranoid_check_not_bad(ubi, pnum);
if (err != 0)
- return err > 0 ? -EINVAL : err;
+ return err;
if (ubi->ro_mode) {
ubi_err("read-only mode");
@@ -819,7 +835,7 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum,
err = paranoid_check_ec_hdr(ubi, pnum, ec_hdr);
if (err)
- return -EINVAL;
+ return err;
err = ubi_io_write(ubi, ec_hdr, pnum, 0, ubi->ec_hdr_alsize);
return err;
@@ -1083,7 +1099,7 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
err = paranoid_check_peb_ec_hdr(ubi, pnum);
if (err)
- return err > 0 ? -EINVAL : err;
+ return err;
vid_hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC);
vid_hdr->version = UBI_VERSION;
@@ -1092,7 +1108,7 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
err = paranoid_check_vid_hdr(ubi, pnum, vid_hdr);
if (err)
- return -EINVAL;
+ return err;
p = (char *)vid_hdr - ubi->vid_hdr_shift;
err = ubi_io_write(ubi, p, pnum, ubi->vid_hdr_aloffset,
@@ -1107,8 +1123,8 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
* @ubi: UBI device description object
* @pnum: physical eraseblock number to check
*
- * This function returns zero if the physical eraseblock is good, a positive
- * number if it is bad and a negative error code if an error occurred.
+ * This function returns zero if the physical eraseblock is good, %-EINVAL if
+ * it is bad and a negative error code if an error occurred.
*/
static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum)
{
@@ -1120,7 +1136,7 @@ static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum)
ubi_err("paranoid check failed for PEB %d", pnum);
ubi_dbg_dump_stack();
- return err;
+ return err > 0 ? -EINVAL : err;
}
/**
@@ -1130,7 +1146,7 @@ static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum)
* @ec_hdr: the erase counter header to check
*
* This function returns zero if the erase counter header contains valid
- * values, and %1 if not.
+ * values, and %-EINVAL if not.
*/
static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
const struct ubi_ec_hdr *ec_hdr)
@@ -1156,7 +1172,7 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
fail:
ubi_dbg_dump_ec_hdr(ec_hdr);
ubi_dbg_dump_stack();
- return 1;
+ return -EINVAL;
}
/**
@@ -1164,8 +1180,8 @@ fail:
* @ubi: UBI device description object
* @pnum: the physical eraseblock number to check
*
- * This function returns zero if the erase counter header is all right, %1 if
- * not, and a negative error code if an error occurred.
+ * This function returns zero if the erase counter header is all right and and
+ * a negative error code if not or if an error occurred.
*/
static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)
{
@@ -1188,7 +1204,7 @@ static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)
ubi_err("paranoid check failed for PEB %d", pnum);
ubi_dbg_dump_ec_hdr(ec_hdr);
ubi_dbg_dump_stack();
- err = 1;
+ err = -EINVAL;
goto exit;
}
@@ -1206,7 +1222,7 @@ exit:
* @vid_hdr: the volume identifier header to check
*
* This function returns zero if the volume identifier header is all right, and
- * %1 if not.
+ * %-EINVAL if not.
*/
static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum,
const struct ubi_vid_hdr *vid_hdr)
@@ -1233,7 +1249,7 @@ fail:
ubi_err("paranoid check failed for PEB %d", pnum);
ubi_dbg_dump_vid_hdr(vid_hdr);
ubi_dbg_dump_stack();
- return 1;
+ return -EINVAL;
}
@@ -1243,7 +1259,7 @@ fail:
* @pnum: the physical eraseblock number to check
*
* This function returns zero if the volume identifier header is all right,
- * %1 if not, and a negative error code if an error occurred.
+ * and a negative error code if not or if an error occurred.
*/
static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
{
@@ -1270,7 +1286,7 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
ubi_err("paranoid check failed for PEB %d", pnum);
ubi_dbg_dump_vid_hdr(vid_hdr);
ubi_dbg_dump_stack();
- err = 1;
+ err = -EINVAL;
goto exit;
}
@@ -1282,6 +1298,61 @@ exit:
}
/**
+ * ubi_dbg_check_write - make sure write succeeded.
+ * @ubi: UBI device description object
+ * @buf: buffer with data which were written
+ * @pnum: physical eraseblock number the data were written to
+ * @offset: offset within the physical eraseblock the data were written to
+ * @len: how many bytes were written
+ *
+ * This functions reads data which were recently written and compares it with
+ * the original data buffer - the data have to match. Returns zero if the data
+ * match and a negative error code if not or in case of failure.
+ */
+int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
+ int offset, int len)
+{
+ int err, i;
+
+ mutex_lock(&ubi->dbg_buf_mutex);
+ err = ubi_io_read(ubi, ubi->dbg_peb_buf, pnum, offset, len);
+ if (err)
+ goto out_unlock;
+
+ for (i = 0; i < len; i++) {
+ uint8_t c = ((uint8_t *)buf)[i];
+ uint8_t c1 = ((uint8_t *)ubi->dbg_peb_buf)[i];
+ int dump_len;
+
+ if (c == c1)
+ continue;
+
+ ubi_err("paranoid check failed for PEB %d:%d, len %d",
+ pnum, offset, len);
+ ubi_msg("data differ at position %d", i);
+ dump_len = max_t(int, 128, len - i);
+ ubi_msg("hex dump of the original buffer from %d to %d",
+ i, i + dump_len);
+ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
+ buf + i, dump_len, 1);
+ ubi_msg("hex dump of the read buffer from %d to %d",
+ i, i + dump_len);
+ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
+ ubi->dbg_peb_buf + i, dump_len, 1);
+ ubi_dbg_dump_stack();
+ err = -EINVAL;
+ goto out_unlock;
+ }
+ mutex_unlock(&ubi->dbg_buf_mutex);
+
+ return 0;
+
+out_unlock:
+ mutex_unlock(&ubi->dbg_buf_mutex);
+ return err;
+}
+
+/**
* ubi_dbg_check_all_ff - check that a region of flash is empty.
* @ubi: UBI device description object
* @pnum: the physical eraseblock number to check
@@ -1289,8 +1360,8 @@ exit:
* @len: the length of the region to check
*
* This function returns zero if only 0xFF bytes are present at offset
- * @offset of the physical eraseblock @pnum, %1 if not, and a negative error
- * code if an error occurred.
+ * @offset of the physical eraseblock @pnum, and a negative error code if not
+ * or if an error occurred.
*/
int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
{
@@ -1321,7 +1392,7 @@ fail:
ubi_msg("hex dump of the %d-%d region", offset, offset + len);
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
ubi->dbg_peb_buf, len, 1);
- err = 1;
+ err = -EINVAL;
error:
ubi_dbg_dump_stack();
mutex_unlock(&ubi->dbg_buf_mutex);
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c
index 1361574e2b00..17f287decc36 100644
--- a/drivers/mtd/ubi/kapi.c
+++ b/drivers/mtd/ubi/kapi.c
@@ -22,6 +22,7 @@
#include <linux/module.h>
#include <linux/err.h>
+#include <linux/slab.h>
#include <linux/namei.h>
#include <linux/fs.h>
#include <asm/div64.h>
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index 90af61a2c3e4..dc5f688699da 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -41,6 +41,7 @@
*/
#include <linux/err.h>
+#include <linux/slab.h>
#include <linux/crc32.h>
#include <linux/math64.h>
#include "ubi.h"
@@ -974,11 +975,8 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
seb->ec = si->mean_ec;
err = paranoid_check_si(ubi, si);
- if (err) {
- if (err > 0)
- err = -EINVAL;
+ if (err)
goto out_vidh;
- }
ubi_free_vid_hdr(ubi, vidh);
kfree(ech);
@@ -1086,8 +1084,8 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si)
* @ubi: UBI device description object
* @si: scanning information
*
- * This function returns zero if the scanning information is all right, %1 if
- * not and a negative error code if an error occurred.
+ * This function returns zero if the scanning information is all right, and a
+ * negative error code if not or if an error occurred.
*/
static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si)
{
@@ -1346,7 +1344,7 @@ bad_vid_hdr:
out:
ubi_dbg_dump_stack();
- return 1;
+ return -EINVAL;
}
#endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 1af08178defd..5176d4886518 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -34,6 +34,7 @@
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
+#include <linux/slab.h>
#include <linux/string.h>
#include <linux/vmalloc.h>
#include <linux/notifier.h>
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index ab64cb56df6e..e42afab9a9fe 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -25,6 +25,7 @@
#include <linux/err.h>
#include <linux/math64.h>
+#include <linux/slab.h>
#include "ubi.h"
#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index 40044028d682..cd90ff3b76b1 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -58,6 +58,7 @@
#include <linux/crc32.h>
#include <linux/err.h>
+#include <linux/slab.h>
#include <asm/div64.h>
#include "ubi.h"
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 600c7229d5cf..f64ddabd4ac8 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -464,7 +464,7 @@ retry:
ubi->peb_size - ubi->vid_hdr_aloffset);
if (err) {
ubi_err("new PEB %d does not contain all 0xFF bytes", e->pnum);
- return err > 0 ? -EINVAL : err;
+ return err;
}
return e->pnum;
@@ -513,7 +513,7 @@ static int sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
dbg_wl("erase PEB %d, old EC %llu", e->pnum, ec);
err = paranoid_check_ec(ubi, e->pnum, e->ec);
- if (err > 0)
+ if (err)
return -EINVAL;
ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS);
@@ -1572,8 +1572,7 @@ void ubi_wl_close(struct ubi_device *ubi)
* @ec: the erase counter to check
*
* This function returns zero if the erase counter of physical eraseblock @pnum
- * is equivalent to @ec, %1 if not, and a negative error code if an error
- * occurred.
+ * is equivalent to @ec, and a negative error code if not or if an error occurred.
*/
static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec)
{
@@ -1611,8 +1610,8 @@ out_free:
* @e: the wear-leveling entry to check
* @root: the root of the tree
*
- * This function returns zero if @e is in the @root RB-tree and %1 if it is
- * not.
+ * This function returns zero if @e is in the @root RB-tree and %-EINVAL if it
+ * is not.
*/
static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
struct rb_root *root)
@@ -1623,7 +1622,7 @@ static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
ubi_err("paranoid check failed for PEB %d, EC %d, RB-tree %p ",
e->pnum, e->ec, root);
ubi_dbg_dump_stack();
- return 1;
+ return -EINVAL;
}
/**
@@ -1632,7 +1631,7 @@ static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
* @ubi: UBI device description object
* @e: the wear-leveling entry to check
*
- * This function returns zero if @e is in @ubi->pq and %1 if it is not.
+ * This function returns zero if @e is in @ubi->pq and %-EINVAL if it is not.
*/
static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e)
{
@@ -1647,6 +1646,6 @@ static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e)
ubi_err("paranoid check failed for PEB %d, EC %d, Protect queue",
e->pnum, e->ec);
ubi_dbg_dump_stack();
- return 1;
+ return -EINVAL;
}
#endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */