summaryrefslogtreecommitdiff
path: root/drivers/mtd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/Makefile2
-rw-r--r--drivers/mtd/devices/docprobe.c5
-rw-r--r--drivers/mtd/maps/Kconfig8
-rw-r--r--drivers/mtd/maps/Makefile1
-rw-r--r--drivers/mtd/maps/lasat.c103
-rw-r--r--drivers/mtd/maps/lubbock-flash.c6
-rw-r--r--drivers/mtd/maps/mainstone-flash.c5
-rw-r--r--drivers/mtd/mtd_blkdevs.c3
-rw-r--r--drivers/mtd/mtdchar.c1
-rw-r--r--drivers/mtd/mtdpart.c4
-rw-r--r--drivers/mtd/mtdsuper.c2
-rw-r--r--drivers/mtd/nand/at91_nand.c5
-rw-r--r--drivers/mtd/nand/cafe_nand.c3
-rw-r--r--drivers/mtd/nand/diskonchip.c5
-rw-r--r--drivers/mtd/nand/edb7312.c10
-rw-r--r--drivers/mtd/nand/nand_base.c12
-rw-r--r--drivers/mtd/rfd_ftl.c1
-rw-r--r--drivers/mtd/ubi/build.c25
-rw-r--r--drivers/mtd/ubi/cdev.c49
-rw-r--r--drivers/mtd/ubi/debug.c44
-rw-r--r--drivers/mtd/ubi/debug.h2
-rw-r--r--drivers/mtd/ubi/eba.c104
-rw-r--r--drivers/mtd/ubi/gluebi.c27
-rw-r--r--drivers/mtd/ubi/io.c65
-rw-r--r--drivers/mtd/ubi/kapi.c19
-rw-r--r--drivers/mtd/ubi/misc.c4
-rw-r--r--drivers/mtd/ubi/scan.c127
-rw-r--r--drivers/mtd/ubi/scan.h2
-rw-r--r--drivers/mtd/ubi/ubi.h3
-rw-r--r--drivers/mtd/ubi/upd.c4
-rw-r--r--drivers/mtd/ubi/vmt.c53
-rw-r--r--drivers/mtd/ubi/vtbl.c85
-rw-r--r--drivers/mtd/ubi/wl.c96
33 files changed, 404 insertions, 481 deletions
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 451adcc52b3c..6d958a4566ff 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -3,9 +3,9 @@
#
# Core functionality.
+obj-$(CONFIG_MTD) += mtd.o
mtd-y := mtdcore.o mtdsuper.o
mtd-$(CONFIG_MTD_PARTITIONS) += mtdpart.o
-obj-$(CONFIG_MTD) += $(mtd-y)
obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o
obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c
index 78872c3f3760..54aa75907640 100644
--- a/drivers/mtd/devices/docprobe.c
+++ b/drivers/mtd/devices/docprobe.c
@@ -81,10 +81,7 @@ static unsigned long __initdata doc_locations[] = {
#endif /* CONFIG_MTD_DOCPROBE_HIGH */
#elif defined(__PPC__)
0xe4000000,
-#elif defined(CONFIG_MOMENCO_OCELOT)
- 0x2f000000,
- 0xff000000,
-#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
+#elif defined(CONFIG_MOMENCO_OCELOT_G)
0xff000000,
##else
#warning Unknown architecture for DiskOnChip. No default probe locations defined
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 92fe291725dc..0a41debbe1b3 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -103,7 +103,7 @@ config MTD_PMC_MSP_RAMROOT
config MTD_SUN_UFLASH
tristate "Sun Microsystems userflash support"
- depends on SPARC && MTD_CFI
+ depends on SPARC && MTD_CFI && PCI
help
This provides a 'mapping' driver which supports the way in
which user-programmable flash chips are connected on various
@@ -258,12 +258,6 @@ config MTD_TSUNAMI
help
Support for the flash chip on Tsunami TIG bus.
-config MTD_LASAT
- tristate "LASAT flash device"
- depends on LASAT && MTD_CFI
- help
- Support for the flash chips on the Lasat 100 and 200 boards.
-
config MTD_NETtel
tristate "CFI flash device on SnapGear/SecureEdge"
depends on X86 && MTD_PARTITIONS && MTD_JEDECPROBE
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 661f2064c23d..aaf6f35d60ba 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -47,7 +47,6 @@ obj-$(CONFIG_MTD_OCELOT) += ocelot.o
obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o
obj-$(CONFIG_MTD_PCI) += pci.o
obj-$(CONFIG_MTD_ALCHEMY) += alchemy-flash.o
-obj-$(CONFIG_MTD_LASAT) += lasat.o
obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o
obj-$(CONFIG_MTD_EDB7312) += edb7312.o
obj-$(CONFIG_MTD_IMPA7) += impa7.o
diff --git a/drivers/mtd/maps/lasat.c b/drivers/mtd/maps/lasat.c
deleted file mode 100644
index e34376321050..000000000000
--- a/drivers/mtd/maps/lasat.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Flash device on Lasat 100 and 200 boards
- *
- * (C) 2002 Brian Murphy <brian@murphy.dk>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * $Id: lasat.c,v 1.9 2004/11/04 13:24:15 gleixner Exp $
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <asm/lasat/lasat.h>
-
-static struct mtd_info *lasat_mtd;
-
-static struct mtd_partition partition_info[LASAT_MTD_LAST];
-static char *lasat_mtd_partnames[] = {"Bootloader", "Service", "Normal", "Filesystem", "Config"};
-
-static void lasat_set_vpp(struct map_info *map, int vpp)
-{
- if (vpp)
- *lasat_misc->flash_wp_reg |= 1 << lasat_misc->flash_wp_bit;
- else
- *lasat_misc->flash_wp_reg &= ~(1 << lasat_misc->flash_wp_bit);
-}
-
-static struct map_info lasat_map = {
- .name = "LASAT flash",
- .bankwidth = 4,
- .set_vpp = lasat_set_vpp
-};
-
-static int __init init_lasat(void)
-{
- int i;
- /* since we use AMD chips and set_vpp is not implimented
- * for these (yet) we still have to permanently enable flash write */
- printk(KERN_NOTICE "Unprotecting flash\n");
- ENABLE_VPP((&lasat_map));
-
- lasat_map.phys = lasat_flash_partition_start(LASAT_MTD_BOOTLOADER);
- lasat_map.virt = ioremap_nocache(
- lasat_map.phys, lasat_board_info.li_flash_size);
- lasat_map.size = lasat_board_info.li_flash_size;
-
- simple_map_init(&lasat_map);
-
- for (i=0; i < LASAT_MTD_LAST; i++)
- partition_info[i].name = lasat_mtd_partnames[i];
-
- lasat_mtd = do_map_probe("cfi_probe", &lasat_map);
-
- if (!lasat_mtd)
- lasat_mtd = do_map_probe("jedec_probe", &lasat_map);
-
- if (lasat_mtd) {
- u32 size, offset = 0;
-
- lasat_mtd->owner = THIS_MODULE;
-
- for (i=0; i < LASAT_MTD_LAST; i++) {
- size = lasat_flash_partition_size(i);
- partition_info[i].size = size;
- partition_info[i].offset = offset;
- offset += size;
- }
-
- add_mtd_partitions( lasat_mtd, partition_info, LASAT_MTD_LAST );
- return 0;
- }
-
- iounmap(lasat_map.virt);
- return -ENXIO;
-}
-
-static void __exit cleanup_lasat(void)
-{
- if (lasat_mtd) {
- del_mtd_partitions(lasat_mtd);
- map_destroy(lasat_mtd);
- }
- if (lasat_map.virt) {
- iounmap(lasat_map.virt);
- lasat_map.virt = 0;
- }
-}
-
-module_init(init_lasat);
-module_exit(cleanup_lasat);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Brian Murphy <brian@murphy.dk>");
-MODULE_DESCRIPTION("Lasat Safepipe/Masquerade MTD map driver");
diff --git a/drivers/mtd/maps/lubbock-flash.c b/drivers/mtd/maps/lubbock-flash.c
index 1aa0447c5e66..e8560683b973 100644
--- a/drivers/mtd/maps/lubbock-flash.c
+++ b/drivers/mtd/maps/lubbock-flash.c
@@ -15,9 +15,7 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
@@ -26,7 +24,7 @@
#include <asm/hardware.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/lubbock.h>
-
+#include <asm/cacheflush.h>
#define ROM_ADDR 0x00000000
#define FLASH_ADDR 0x04000000
@@ -35,7 +33,7 @@
static void lubbock_map_inval_cache(struct map_info *map, unsigned long from, ssize_t len)
{
- consistent_sync((char *)map->cached + from, len, DMA_FROM_DEVICE);
+ flush_ioremap_region(map->phys, map->cached, from, len);
}
static struct map_info lubbock_maps[2] = { {
diff --git a/drivers/mtd/maps/mainstone-flash.c b/drivers/mtd/maps/mainstone-flash.c
index eaa4bbb868a3..d76487d82dcd 100644
--- a/drivers/mtd/maps/mainstone-flash.c
+++ b/drivers/mtd/maps/mainstone-flash.c
@@ -15,8 +15,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/dma-mapping.h>
-#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
@@ -26,6 +24,7 @@
#include <asm/hardware.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/mainstone.h>
+#include <asm/cacheflush.h>
#define ROM_ADDR 0x00000000
@@ -36,7 +35,7 @@
static void mainstone_map_inval_cache(struct map_info *map, unsigned long from,
ssize_t len)
{
- consistent_sync((char *)map->cached + from, len, DMA_FROM_DEVICE);
+ flush_ioremap_region(map->phys, map->cached, from, len);
}
static struct map_info mainstone_maps[2] = { {
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 51bc7e2f1f22..ef89780eb9d6 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -16,6 +16,7 @@
#include <linux/mtd/mtd.h>
#include <linux/blkdev.h>
#include <linux/blkpg.h>
+#include <linux/freezer.h>
#include <linux/spinlock.h>
#include <linux/hdreg.h>
#include <linux/init.h>
@@ -80,7 +81,7 @@ static int mtd_blktrans_thread(void *arg)
struct request_queue *rq = tr->blkcore_priv->rq;
/* we might get involved when memory gets low, so use PF_MEMALLOC */
- current->flags |= PF_MEMALLOC | PF_NOFREEZE;
+ current->flags |= PF_MEMALLOC;
spin_lock_irq(rq->queue_lock);
while (!kthread_should_stop()) {
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 8c86b802f212..d091b2430b48 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -7,6 +7,7 @@
#include <linux/device.h>
#include <linux/fs.h>
+#include <linux/mm.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 9c6236852942..6174a97d7902 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -560,7 +560,3 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types,
EXPORT_SYMBOL_GPL(parse_mtd_partitions);
EXPORT_SYMBOL_GPL(register_mtd_parser);
EXPORT_SYMBOL_GPL(deregister_mtd_parser);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>");
-MODULE_DESCRIPTION("Generic support for partitioning of MTD devices");
diff --git a/drivers/mtd/mtdsuper.c b/drivers/mtd/mtdsuper.c
index aca331971201..9b430f20b640 100644
--- a/drivers/mtd/mtdsuper.c
+++ b/drivers/mtd/mtdsuper.c
@@ -70,6 +70,8 @@ static int get_sb_mtd_aux(struct file_system_type *fs_type, int flags,
DEBUG(1, "MTDSB: New superblock for device %d (\"%s\")\n",
mtd->index, mtd->name);
+ sb->s_flags = flags;
+
ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
if (ret < 0) {
up_write(&sb->s_umount);
diff --git a/drivers/mtd/nand/at91_nand.c b/drivers/mtd/nand/at91_nand.c
index 512e999177f7..b2a5672df6e0 100644
--- a/drivers/mtd/nand/at91_nand.c
+++ b/drivers/mtd/nand/at91_nand.c
@@ -128,7 +128,10 @@ static int __init at91_nand_probe(struct platform_device *pdev)
nand_chip->IO_ADDR_R = host->io_base;
nand_chip->IO_ADDR_W = host->io_base;
nand_chip->cmd_ctrl = at91_nand_cmd_ctrl;
- nand_chip->dev_ready = at91_nand_device_ready;
+
+ if (host->board->rdy_pin)
+ nand_chip->dev_ready = at91_nand_device_ready;
+
nand_chip->ecc.mode = NAND_ECC_SOFT; /* enable ECC */
nand_chip->chip_delay = 20; /* 20us command delay time */
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
index cff969d05d4a..6f32a35eb106 100644
--- a/drivers/mtd/nand/cafe_nand.c
+++ b/drivers/mtd/nand/cafe_nand.c
@@ -816,7 +816,8 @@ static void __devexit cafe_nand_remove(struct pci_dev *pdev)
}
static struct pci_device_id cafe_nand_tbl[] = {
- { 0x11ab, 0x4100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MEMORY_FLASH << 8, 0xFFFF0 }
+ { 0x11ab, 0x4100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MEMORY_FLASH << 8, 0xFFFF0 },
+ { 0, }
};
MODULE_DEVICE_TABLE(pci, cafe_nand_tbl);
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 595208f965a5..e96259f22cca 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -56,10 +56,7 @@ static unsigned long __initdata doc_locations[] = {
#endif /* CONFIG_MTD_DOCPROBE_HIGH */
#elif defined(__PPC__)
0xe4000000,
-#elif defined(CONFIG_MOMENCO_OCELOT)
- 0x2f000000,
- 0xff000000,
-#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
+#elif defined(CONFIG_MOMENCO_OCELOT_G)
0xff000000,
#else
#warning Unknown architecture for DiskOnChip. No default probe locations defined
diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c
index 1daf8231aaef..0146cdc48039 100644
--- a/drivers/mtd/nand/edb7312.c
+++ b/drivers/mtd/nand/edb7312.c
@@ -74,7 +74,7 @@ static struct mtd_partition partition_info[] = {
/*
* hardware specific access to control-lines
*
- * NAND_NCE: bit 0 -> bit 7
+ * NAND_NCE: bit 0 -> bit 6 (bit 7 = 1)
* NAND_CLE: bit 1 -> bit 4
* NAND_ALE: bit 2 -> bit 5
*/
@@ -83,12 +83,12 @@ static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
struct nand_chip *chip = mtd->priv;
if (ctrl & NAND_CTRL_CHANGE) {
- unsigned char bits;
+ unsigned char bits = 0x80;
- bits = (ctrl & (NAND_CLE | NAND_ALE)) << 3;
- bits = (ctrl & NAND_NCE) << 7;
+ bits |= (ctrl & (NAND_CLE | NAND_ALE)) << 3;
+ bits |= (ctrl & NAND_NCE) ? 0x00 : 0x40;
- clps_writeb((clps_readb(ep7312_pxdr) & 0xB0) | 0x10,
+ clps_writeb((clps_readb(ep7312_pxdr) & 0xF0) | bits,
ep7312_pxdr);
}
if (cmd != NAND_CMD_NONE)
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 7e68203fe1ba..24ac6778b1a8 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -24,6 +24,7 @@
* if we have HW ecc support.
* The AG-AND chips have nice features for speed improvement,
* which are not supported yet. Read / program 4 pages in one go.
+ * BBT table is not serialized, has to be fixed
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -360,6 +361,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
/* We write two bytes, so we dont have to mess with 16 bit
* access
*/
+ nand_get_device(chip, mtd, FL_WRITING);
ofs += mtd->oobsize;
chip->ops.len = chip->ops.ooblen = 2;
chip->ops.datbuf = NULL;
@@ -367,9 +369,11 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
chip->ops.ooboffs = chip->badblockpos & ~0x01;
ret = nand_do_write_oob(mtd, ofs, &chip->ops);
+ nand_release_device(mtd);
}
if (!ret)
mtd->ecc_stats.badblocks++;
+
return ret;
}
@@ -768,7 +772,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *p = buf;
uint8_t *ecc_calc = chip->buffers->ecccalc;
uint8_t *ecc_code = chip->buffers->ecccode;
- int *eccpos = chip->ecc.layout->eccpos;
+ uint32_t *eccpos = chip->ecc.layout->eccpos;
chip->ecc.read_page_raw(mtd, chip, buf);
@@ -810,7 +814,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *p = buf;
uint8_t *ecc_calc = chip->buffers->ecccalc;
uint8_t *ecc_code = chip->buffers->ecccode;
- int *eccpos = chip->ecc.layout->eccpos;
+ uint32_t *eccpos = chip->ecc.layout->eccpos;
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
chip->ecc.hwctl(mtd, NAND_ECC_READ);
@@ -1416,7 +1420,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
int eccsteps = chip->ecc.steps;
uint8_t *ecc_calc = chip->buffers->ecccalc;
const uint8_t *p = buf;
- int *eccpos = chip->ecc.layout->eccpos;
+ uint32_t *eccpos = chip->ecc.layout->eccpos;
/* Software ecc calculation */
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
@@ -1442,7 +1446,7 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
int eccsteps = chip->ecc.steps;
uint8_t *ecc_calc = chip->buffers->ecccalc;
const uint8_t *p = buf;
- int *eccpos = chip->ecc.layout->eccpos;
+ uint32_t *eccpos = chip->ecc.layout->eccpos;
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c
index d4b1ba8f23ef..006c03aacb55 100644
--- a/drivers/mtd/rfd_ftl.c
+++ b/drivers/mtd/rfd_ftl.c
@@ -779,6 +779,7 @@ static void rfd_ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
else {
if (!mtd->erasesize) {
printk(KERN_WARNING PREFIX "please provide block_size");
+ kfree(part);
return;
}
else
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 555d594d1811..1cb22bfae750 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -33,6 +33,7 @@
#include <linux/moduleparam.h>
#include <linux/stringify.h>
#include <linux/stat.h>
+#include <linux/log2.h>
#include "ubi.h"
/* Maximum length of the 'mtd=' parameter */
@@ -369,7 +370,7 @@ static int attach_by_scanning(struct ubi_device *ubi)
out_wl:
ubi_wl_close(ubi);
out_vtbl:
- kfree(ubi->vtbl);
+ vfree(ubi->vtbl);
out_si:
ubi_scan_destroy_si(si);
return err;
@@ -422,8 +423,7 @@ static int io_init(struct ubi_device *ubi)
ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft;
/* Make sure minimal I/O unit is power of 2 */
- if (ubi->min_io_size == 0 ||
- (ubi->min_io_size & (ubi->min_io_size - 1))) {
+ if (!is_power_of_2(ubi->min_io_size)) {
ubi_err("bad min. I/O unit");
return -EINVAL;
}
@@ -593,8 +593,6 @@ static int attach_mtd_dev(const char *mtd_dev, int vid_hdr_offset,
if (err)
goto out_detach;
- ubi_devices_cnt += 1;
-
ubi_msg("attached mtd%d to ubi%d", ubi->mtd->index, ubi_devices_cnt);
ubi_msg("MTD device name: \"%s\"", ubi->mtd->name);
ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20);
@@ -624,12 +622,13 @@ static int attach_mtd_dev(const char *mtd_dev, int vid_hdr_offset,
wake_up_process(ubi->bgt_thread);
}
+ ubi_devices_cnt += 1;
return 0;
out_detach:
ubi_eba_close(ubi);
ubi_wl_close(ubi);
- kfree(ubi->vtbl);
+ vfree(ubi->vtbl);
out_free:
kfree(ubi);
out_mtd:
@@ -650,7 +649,7 @@ static void detach_mtd_dev(struct ubi_device *ubi)
uif_close(ubi);
ubi_eba_close(ubi);
ubi_wl_close(ubi);
- kfree(ubi->vtbl);
+ vfree(ubi->vtbl);
put_mtd_device(ubi->mtd);
kfree(ubi_devices[ubi_num]);
ubi_devices[ubi_num] = NULL;
@@ -686,13 +685,6 @@ static int __init ubi_init(void)
struct mtd_dev_param *p = &mtd_dev_param[i];
cond_resched();
-
- if (!p->name) {
- dbg_err("empty name");
- err = -EINVAL;
- goto out_detach;
- }
-
err = attach_mtd_dev(p->name, p->vid_hdr_offs, p->data_offs);
if (err)
goto out_detach;
@@ -799,7 +791,7 @@ static int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp)
/* Get rid of the final newline */
if (buf[len - 1] == '\n')
- buf[len - 1] = 0;
+ buf[len - 1] = '\0';
for (i = 0; i < 3; i++)
tokens[i] = strsep(&pbuf, ",");
@@ -809,9 +801,6 @@ static int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp)
return -EINVAL;
}
- if (tokens[0] == '\0')
- return -EINVAL;
-
p = &mtd_dev_param[mtd_devs];
strcpy(&p->name[0], tokens[0]);
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 6612eb79bf17..fe4da1e96c52 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -64,6 +64,7 @@ static struct ubi_device *major_to_device(int major)
if (ubi_devices[i] && ubi_devices[i]->major == major)
return ubi_devices[i];
BUG();
+ return NULL;
}
/**
@@ -153,7 +154,7 @@ static int vol_cdev_release(struct inode *inode, struct file *file)
ubi_warn("update of volume %d not finished, volume is damaged",
vol->vol_id);
vol->updating = 0;
- kfree(vol->upd_buf);
+ vfree(vol->upd_buf);
}
ubi_close_volume(desc);
@@ -232,7 +233,7 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count,
tbuf_size = vol->usable_leb_size;
if (count < tbuf_size)
tbuf_size = ALIGN(count, ubi->min_io_size);
- tbuf = kmalloc(tbuf_size, GFP_KERNEL);
+ tbuf = vmalloc(tbuf_size);
if (!tbuf)
return -ENOMEM;
@@ -271,7 +272,7 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count,
len = count > tbuf_size ? tbuf_size : count;
} while (count);
- kfree(tbuf);
+ vfree(tbuf);
return err ? err : count_save - count;
}
@@ -320,7 +321,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
tbuf_size = vol->usable_leb_size;
if (count < tbuf_size)
tbuf_size = ALIGN(count, ubi->min_io_size);
- tbuf = kmalloc(tbuf_size, GFP_KERNEL);
+ tbuf = vmalloc(tbuf_size);
if (!tbuf)
return -ENOMEM;
@@ -355,7 +356,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
len = count > tbuf_size ? tbuf_size : count;
}
- kfree(tbuf);
+ vfree(tbuf);
return err ? err : count_save - count;
}
@@ -397,6 +398,7 @@ static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
vol->corrupted = 1;
}
vol->checked = 1;
+ ubi_gluebi_updated(vol);
revoke_exclusive(desc, UBI_READWRITE);
}
@@ -413,19 +415,7 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
struct ubi_device *ubi = vol->ubi;
void __user *argp = (void __user *)arg;
- if (_IOC_NR(cmd) > VOL_CDEV_IOC_MAX_SEQ ||
- _IOC_TYPE(cmd) != UBI_VOL_IOC_MAGIC)
- return -ENOTTY;
-
- if (_IOC_DIR(cmd) && _IOC_READ)
- err = !access_ok(VERIFY_WRITE, argp, _IOC_SIZE(cmd));
- else if (_IOC_DIR(cmd) && _IOC_WRITE)
- err = !access_ok(VERIFY_READ, argp, _IOC_SIZE(cmd));
- if (err)
- return -EFAULT;
-
switch (cmd) {
-
/* Volume update command */
case UBI_IOCVOLUP:
{
@@ -471,7 +461,7 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
{
int32_t lnum;
- err = __get_user(lnum, (__user int32_t *)argp);
+ err = get_user(lnum, (__user int32_t *)argp);
if (err) {
err = -EFAULT;
break;
@@ -587,17 +577,6 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
struct ubi_volume_desc *desc;
void __user *argp = (void __user *)arg;
- if (_IOC_NR(cmd) > UBI_CDEV_IOC_MAX_SEQ ||
- _IOC_TYPE(cmd) != UBI_IOC_MAGIC)
- return -ENOTTY;
-
- if (_IOC_DIR(cmd) && _IOC_READ)
- err = !access_ok(VERIFY_WRITE, argp, _IOC_SIZE(cmd));
- else if (_IOC_DIR(cmd) && _IOC_WRITE)
- err = !access_ok(VERIFY_READ, argp, _IOC_SIZE(cmd));
- if (err)
- return -EFAULT;
-
if (!capable(CAP_SYS_RESOURCE))
return -EPERM;
@@ -612,7 +591,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
struct ubi_mkvol_req req;
dbg_msg("create volume");
- err = __copy_from_user(&req, argp,
+ err = copy_from_user(&req, argp,
sizeof(struct ubi_mkvol_req));
if (err) {
err = -EFAULT;
@@ -629,7 +608,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
if (err)
break;
- err = __put_user(req.vol_id, (__user int32_t *)argp);
+ err = put_user(req.vol_id, (__user int32_t *)argp);
if (err)
err = -EFAULT;
@@ -642,7 +621,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
int vol_id;
dbg_msg("remove volume");
- err = __get_user(vol_id, (__user int32_t *)argp);
+ err = get_user(vol_id, (__user int32_t *)argp);
if (err) {
err = -EFAULT;
break;
@@ -669,7 +648,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
struct ubi_rsvol_req req;
dbg_msg("re-size volume");
- err = __copy_from_user(&req, argp,
+ err = copy_from_user(&req, argp,
sizeof(struct ubi_rsvol_req));
if (err) {
err = -EFAULT;
@@ -707,7 +686,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
struct file_operations ubi_cdev_operations = {
.owner = THIS_MODULE,
.ioctl = ubi_cdev_ioctl,
- .llseek = no_llseek
+ .llseek = no_llseek,
};
/* UBI volume character device operations */
@@ -718,5 +697,5 @@ struct file_operations ubi_vol_cdev_operations = {
.llseek = vol_cdev_llseek,
.read = vol_cdev_read,
.write = vol_cdev_write,
- .ioctl = vol_cdev_ioctl
+ .ioctl = vol_cdev_ioctl,
};
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index 86364221fafe..310341e5cd43 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -35,12 +35,12 @@
void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
{
dbg_msg("erase counter header dump:");
- dbg_msg("magic %#08x", ubi32_to_cpu(ec_hdr->magic));
+ dbg_msg("magic %#08x", be32_to_cpu(ec_hdr->magic));
dbg_msg("version %d", (int)ec_hdr->version);
- dbg_msg("ec %llu", (long long)ubi64_to_cpu(ec_hdr->ec));
- dbg_msg("vid_hdr_offset %d", ubi32_to_cpu(ec_hdr->vid_hdr_offset));
- dbg_msg("data_offset %d", ubi32_to_cpu(ec_hdr->data_offset));
- dbg_msg("hdr_crc %#08x", ubi32_to_cpu(ec_hdr->hdr_crc));
+ dbg_msg("ec %llu", (long long)be64_to_cpu(ec_hdr->ec));
+ dbg_msg("vid_hdr_offset %d", be32_to_cpu(ec_hdr->vid_hdr_offset));
+ dbg_msg("data_offset %d", be32_to_cpu(ec_hdr->data_offset));
+ dbg_msg("hdr_crc %#08x", be32_to_cpu(ec_hdr->hdr_crc));
dbg_msg("erase counter header hexdump:");
ubi_dbg_hexdump(ec_hdr, UBI_EC_HDR_SIZE);
}
@@ -52,20 +52,20 @@ void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr)
{
dbg_msg("volume identifier header dump:");
- dbg_msg("magic %08x", ubi32_to_cpu(vid_hdr->magic));
+ dbg_msg("magic %08x", be32_to_cpu(vid_hdr->magic));
dbg_msg("version %d", (int)vid_hdr->version);
dbg_msg("vol_type %d", (int)vid_hdr->vol_type);
dbg_msg("copy_flag %d", (int)vid_hdr->copy_flag);
dbg_msg("compat %d", (int)vid_hdr->compat);
- dbg_msg("vol_id %d", ubi32_to_cpu(vid_hdr->vol_id));
- dbg_msg("lnum %d", ubi32_to_cpu(vid_hdr->lnum));
- dbg_msg("leb_ver %u", ubi32_to_cpu(vid_hdr->leb_ver));
- dbg_msg("data_size %d", ubi32_to_cpu(vid_hdr->data_size));
- dbg_msg("used_ebs %d", ubi32_to_cpu(vid_hdr->used_ebs));
- dbg_msg("data_pad %d", ubi32_to_cpu(vid_hdr->data_pad));
+ dbg_msg("vol_id %d", be32_to_cpu(vid_hdr->vol_id));
+ dbg_msg("lnum %d", be32_to_cpu(vid_hdr->lnum));
+ dbg_msg("leb_ver %u", be32_to_cpu(vid_hdr->leb_ver));
+ dbg_msg("data_size %d", be32_to_cpu(vid_hdr->data_size));
+ dbg_msg("used_ebs %d", be32_to_cpu(vid_hdr->used_ebs));
+ dbg_msg("data_pad %d", be32_to_cpu(vid_hdr->data_pad));
dbg_msg("sqnum %llu",
- (unsigned long long)ubi64_to_cpu(vid_hdr->sqnum));
- dbg_msg("hdr_crc %08x", ubi32_to_cpu(vid_hdr->hdr_crc));
+ (unsigned long long)be64_to_cpu(vid_hdr->sqnum));
+ dbg_msg("hdr_crc %08x", be32_to_cpu(vid_hdr->hdr_crc));
dbg_msg("volume identifier header hexdump:");
}
@@ -91,7 +91,7 @@ void ubi_dbg_dump_vol_info(const struct ubi_volume *vol)
if (vol->name_len <= UBI_VOL_NAME_MAX &&
strnlen(vol->name, vol->name_len + 1) == vol->name_len) {
- dbg_msg("name %s", vol->name);
+ dbg_msg("name %s", vol->name);
} else {
dbg_msg("the 1st 5 characters of the name: %c%c%c%c%c",
vol->name[0], vol->name[1], vol->name[2],
@@ -106,30 +106,30 @@ void ubi_dbg_dump_vol_info(const struct ubi_volume *vol)
*/
void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx)
{
- int name_len = ubi16_to_cpu(r->name_len);
+ int name_len = be16_to_cpu(r->name_len);
dbg_msg("volume table record %d dump:", idx);
- dbg_msg("reserved_pebs %d", ubi32_to_cpu(r->reserved_pebs));
- dbg_msg("alignment %d", ubi32_to_cpu(r->alignment));
- dbg_msg("data_pad %d", ubi32_to_cpu(r->data_pad));
+ dbg_msg("reserved_pebs %d", be32_to_cpu(r->reserved_pebs));
+ dbg_msg("alignment %d", be32_to_cpu(r->alignment));
+ dbg_msg("data_pad %d", be32_to_cpu(r->data_pad));
dbg_msg("vol_type %d", (int)r->vol_type);
dbg_msg("upd_marker %d", (int)r->upd_marker);
dbg_msg("name_len %d", name_len);
if (r->name[0] == '\0') {
- dbg_msg("name NULL");
+ dbg_msg("name NULL");
return;
}
if (name_len <= UBI_VOL_NAME_MAX &&
strnlen(&r->name[0], name_len + 1) == name_len) {
- dbg_msg("name %s", &r->name[0]);
+ dbg_msg("name %s", &r->name[0]);
} else {
dbg_msg("1st 5 characters of the name: %c%c%c%c%c",
r->name[0], r->name[1], r->name[2], r->name[3],
r->name[4]);
}
- dbg_msg("crc %#08x", ubi32_to_cpu(r->crc));
+ dbg_msg("crc %#08x", be32_to_cpu(r->crc));
}
/**
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
index f816ad9a36c0..ff8f39548cd8 100644
--- a/drivers/mtd/ubi/debug.h
+++ b/drivers/mtd/ubi/debug.h
@@ -52,7 +52,6 @@ struct ubi_scan_volume;
struct ubi_scan_leb;
struct ubi_mkvol_req;
-void ubi_dbg_print(int type, const char *func, const char *fmt, ...);
void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr);
void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr);
void ubi_dbg_dump_vol_info(const struct ubi_volume *vol);
@@ -66,7 +65,6 @@ void ubi_dbg_hexdump(const void *buf, int size);
#define dbg_msg(fmt, ...) ({})
#define ubi_dbg_dump_stack() ({})
-#define ubi_dbg_print(func, fmt, ...) ({})
#define ubi_dbg_dump_ec_hdr(ec_hdr) ({})
#define ubi_dbg_dump_vid_hdr(vid_hdr) ({})
#define ubi_dbg_dump_vol_info(vol) ({})
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 74002945b71b..7c5e29eaf118 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -368,7 +368,7 @@ int ubi_eba_read_leb(struct ubi_device *ubi, int vol_id, int lnum, void *buf,
int err, pnum, scrub = 0, idx = vol_id2idx(ubi, vol_id);
struct ubi_vid_hdr *vid_hdr;
struct ubi_volume *vol = ubi->volumes[idx];
- uint32_t crc, crc1;
+ uint32_t uninitialized_var(crc);
err = leb_read_lock(ubi, vol_id, lnum);
if (err)
@@ -425,10 +425,10 @@ retry:
} else if (err == UBI_IO_BITFLIPS)
scrub = 1;
- ubi_assert(lnum < ubi32_to_cpu(vid_hdr->used_ebs));
- ubi_assert(len == ubi32_to_cpu(vid_hdr->data_size));
+ ubi_assert(lnum < be32_to_cpu(vid_hdr->used_ebs));
+ ubi_assert(len == be32_to_cpu(vid_hdr->data_size));
- crc = ubi32_to_cpu(vid_hdr->data_crc);
+ crc = be32_to_cpu(vid_hdr->data_crc);
ubi_free_vid_hdr(ubi, vid_hdr);
}
@@ -451,7 +451,7 @@ retry:
}
if (check) {
- crc1 = crc32(UBI_CRC32_INIT, buf, len);
+ uint32_t crc1 = crc32(UBI_CRC32_INIT, buf, len);
if (crc1 != crc) {
ubi_warn("CRC error: calculated %#08x, must be %#08x",
crc1, crc);
@@ -518,13 +518,13 @@ retry:
goto out_put;
}
- vid_hdr->sqnum = cpu_to_ubi64(next_sqnum(ubi));
+ vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi));
err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr);
if (err)
goto write_error;
data_size = offset + len;
- new_buf = kmalloc(data_size, GFP_KERNEL);
+ new_buf = vmalloc(data_size);
if (!new_buf) {
err = -ENOMEM;
goto out_put;
@@ -535,7 +535,7 @@ retry:
if (offset > 0) {
err = ubi_io_read_data(ubi, new_buf, pnum, 0, offset);
if (err && err != UBI_IO_BITFLIPS) {
- kfree(new_buf);
+ vfree(new_buf);
goto out_put;
}
}
@@ -544,11 +544,11 @@ retry:
err = ubi_io_write_data(ubi, new_buf, new_pnum, 0, data_size);
if (err) {
- kfree(new_buf);
+ vfree(new_buf);
goto write_error;
}
- kfree(new_buf);
+ vfree(new_buf);
ubi_free_vid_hdr(ubi, vid_hdr);
vol->eba_tbl[lnum] = new_pnum;
@@ -634,11 +634,11 @@ int ubi_eba_write_leb(struct ubi_device *ubi, int vol_id, int lnum,
}
vid_hdr->vol_type = UBI_VID_DYNAMIC;
- vid_hdr->sqnum = cpu_to_ubi64(next_sqnum(ubi));
- vid_hdr->vol_id = cpu_to_ubi32(vol_id);
- vid_hdr->lnum = cpu_to_ubi32(lnum);
+ vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi));
+ vid_hdr->vol_id = cpu_to_be32(vol_id);
+ vid_hdr->lnum = cpu_to_be32(lnum);
vid_hdr->compat = ubi_get_compat(ubi, vol_id);
- vid_hdr->data_pad = cpu_to_ubi32(vol->data_pad);
+ vid_hdr->data_pad = cpu_to_be32(vol->data_pad);
retry:
pnum = ubi_wl_get_peb(ubi, dtype);
@@ -692,7 +692,7 @@ write_error:
return err;
}
- vid_hdr->sqnum = cpu_to_ubi64(next_sqnum(ubi));
+ vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi));
ubi_msg("try another PEB");
goto retry;
}
@@ -748,17 +748,17 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, int vol_id, int lnum,
return err;
}
- vid_hdr->sqnum = cpu_to_ubi64(next_sqnum(ubi));
- vid_hdr->vol_id = cpu_to_ubi32(vol_id);
- vid_hdr->lnum = cpu_to_ubi32(lnum);
+ vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi));
+ vid_hdr->vol_id = cpu_to_be32(vol_id);
+ vid_hdr->lnum = cpu_to_be32(lnum);
vid_hdr->compat = ubi_get_compat(ubi, vol_id);
- vid_hdr->data_pad = cpu_to_ubi32(vol->data_pad);
+ vid_hdr->data_pad = cpu_to_be32(vol->data_pad);
crc = crc32(UBI_CRC32_INIT, buf, data_size);
vid_hdr->vol_type = UBI_VID_STATIC;
- vid_hdr->data_size = cpu_to_ubi32(data_size);
- vid_hdr->used_ebs = cpu_to_ubi32(used_ebs);
- vid_hdr->data_crc = cpu_to_ubi32(crc);
+ vid_hdr->data_size = cpu_to_be32(data_size);
+ vid_hdr->used_ebs = cpu_to_be32(used_ebs);
+ vid_hdr->data_crc = cpu_to_be32(crc);
retry:
pnum = ubi_wl_get_peb(ubi, dtype);
@@ -813,7 +813,7 @@ write_error:
return err;
}
- vid_hdr->sqnum = cpu_to_ubi64(next_sqnum(ubi));
+ vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi));
ubi_msg("try another PEB");
goto retry;
}
@@ -854,17 +854,17 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, int vol_id, int lnum,
return err;
}
- vid_hdr->sqnum = cpu_to_ubi64(next_sqnum(ubi));
- vid_hdr->vol_id = cpu_to_ubi32(vol_id);
- vid_hdr->lnum = cpu_to_ubi32(lnum);
+ vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi));
+ vid_hdr->vol_id = cpu_to_be32(vol_id);
+ vid_hdr->lnum = cpu_to_be32(lnum);
vid_hdr->compat = ubi_get_compat(ubi, vol_id);
- vid_hdr->data_pad = cpu_to_ubi32(vol->data_pad);
+ vid_hdr->data_pad = cpu_to_be32(vol->data_pad);
crc = crc32(UBI_CRC32_INIT, buf, len);
- vid_hdr->vol_type = UBI_VID_STATIC;
- vid_hdr->data_size = cpu_to_ubi32(len);
+ vid_hdr->vol_type = UBI_VID_DYNAMIC;
+ vid_hdr->data_size = cpu_to_be32(len);
vid_hdr->copy_flag = 1;
- vid_hdr->data_crc = cpu_to_ubi32(crc);
+ vid_hdr->data_crc = cpu_to_be32(crc);
retry:
pnum = ubi_wl_get_peb(ubi, dtype);
@@ -891,11 +891,13 @@ retry:
goto write_error;
}
- err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 1);
- if (err) {
- ubi_free_vid_hdr(ubi, vid_hdr);
- leb_write_unlock(ubi, vol_id, lnum);
- return err;
+ if (vol->eba_tbl[lnum] >= 0) {
+ err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 1);
+ if (err) {
+ ubi_free_vid_hdr(ubi, vid_hdr);
+ leb_write_unlock(ubi, vol_id, lnum);
+ return err;
+ }
}
vol->eba_tbl[lnum] = pnum;
@@ -924,7 +926,7 @@ write_error:
return err;
}
- vid_hdr->sqnum = cpu_to_ubi64(next_sqnum(ubi));
+ vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi));
ubi_msg("try another PEB");
goto retry;
}
@@ -965,19 +967,19 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
uint32_t crc;
void *buf, *buf1 = NULL;
- vol_id = ubi32_to_cpu(vid_hdr->vol_id);
- lnum = ubi32_to_cpu(vid_hdr->lnum);
+ vol_id = be32_to_cpu(vid_hdr->vol_id);
+ lnum = be32_to_cpu(vid_hdr->lnum);
dbg_eba("copy LEB %d:%d, PEB %d to PEB %d", vol_id, lnum, from, to);
if (vid_hdr->vol_type == UBI_VID_STATIC) {
- data_size = ubi32_to_cpu(vid_hdr->data_size);
+ data_size = be32_to_cpu(vid_hdr->data_size);
aldata_size = ALIGN(data_size, ubi->min_io_size);
} else
data_size = aldata_size =
- ubi->leb_size - ubi32_to_cpu(vid_hdr->data_pad);
+ ubi->leb_size - be32_to_cpu(vid_hdr->data_pad);
- buf = kmalloc(aldata_size, GFP_KERNEL);
+ buf = vmalloc(aldata_size);
if (!buf)
return -ENOMEM;
@@ -987,7 +989,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
*/
err = leb_write_lock(ubi, vol_id, lnum);
if (err) {
- kfree(buf);
+ vfree(buf);
return err;
}
@@ -1054,10 +1056,10 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
*/
if (data_size > 0) {
vid_hdr->copy_flag = 1;
- vid_hdr->data_size = cpu_to_ubi32(data_size);
- vid_hdr->data_crc = cpu_to_ubi32(crc);
+ vid_hdr->data_size = cpu_to_be32(data_size);
+ vid_hdr->data_crc = cpu_to_be32(crc);
}
- vid_hdr->sqnum = cpu_to_ubi64(next_sqnum(ubi));
+ vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi));
err = ubi_io_write_vid_hdr(ubi, to, vid_hdr);
if (err)
@@ -1082,7 +1084,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
* We've written the data and are going to read it back to make
* sure it was written correctly.
*/
- buf1 = kmalloc(aldata_size, GFP_KERNEL);
+ buf1 = vmalloc(aldata_size);
if (!buf1) {
err = -ENOMEM;
goto out_unlock;
@@ -1111,15 +1113,15 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
vol->eba_tbl[lnum] = to;
leb_write_unlock(ubi, vol_id, lnum);
- kfree(buf);
- kfree(buf1);
+ vfree(buf);
+ vfree(buf1);
return 0;
out_unlock:
leb_write_unlock(ubi, vol_id, lnum);
- kfree(buf);
- kfree(buf1);
+ vfree(buf);
+ vfree(buf1);
return err;
}
@@ -1147,7 +1149,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
if (ubi_devices_cnt == 0) {
ltree_slab = kmem_cache_create("ubi_ltree_slab",
sizeof(struct ltree_entry), 0,
- 0, &ltree_entry_ctor, NULL);
+ 0, &ltree_entry_ctor);
if (!ltree_slab)
return -ENOMEM;
}
diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c
index fc9478d605ff..41ff74c60e14 100644
--- a/drivers/mtd/ubi/gluebi.c
+++ b/drivers/mtd/ubi/gluebi.c
@@ -282,7 +282,6 @@ int ubi_create_gluebi(struct ubi_device *ubi, struct ubi_volume *vol)
mtd->flags = MTD_WRITEABLE;
mtd->writesize = ubi->min_io_size;
mtd->owner = THIS_MODULE;
- mtd->size = vol->usable_leb_size * vol->reserved_pebs;
mtd->erasesize = vol->usable_leb_size;
mtd->read = gluebi_read;
mtd->write = gluebi_write;
@@ -290,6 +289,15 @@ int ubi_create_gluebi(struct ubi_device *ubi, struct ubi_volume *vol)
mtd->get_device = gluebi_get_device;
mtd->put_device = gluebi_put_device;
+ /*
+ * In case of dynamic volume, MTD device size is just volume size. In
+ * case of a static volume the size is equivalent to the amount of data
+ * bytes, which is zero at this moment and will be changed after volume
+ * update.
+ */
+ if (vol->vol_type == UBI_DYNAMIC_VOLUME)
+ mtd->size = vol->usable_leb_size * vol->reserved_pebs;
+
if (add_mtd_device(mtd)) {
ubi_err("cannot not add MTD device\n");
kfree(mtd->name);
@@ -321,3 +329,20 @@ int ubi_destroy_gluebi(struct ubi_volume *vol)
kfree(mtd->name);
return 0;
}
+
+/**
+ * ubi_gluebi_updated - UBI volume was updated notifier.
+ * @vol: volume description object
+ *
+ * This function is called every time an UBI volume is updated. This function
+ * does nothing if volume @vol is dynamic, and changes MTD device size if the
+ * volume is static. This is needed because static volumes cannot be read past
+ * data they contain.
+ */
+void ubi_gluebi_updated(struct ubi_volume *vol)
+{
+ struct mtd_info *mtd = &vol->gluebi_mtd;
+
+ if (vol->vol_type == UBI_STATIC_VOLUME)
+ mtd->size = vol->used_bytes;
+}
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 438914d05151..b0d8f4cede97 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -125,9 +125,9 @@ static int paranoid_check_all_ff(const struct ubi_device *ubi, int pnum,
* o %UBI_IO_BITFLIPS if all the requested data were successfully read, but
* correctable bit-flips were detected; this is harmless but may indicate
* that this eraseblock may become bad soon (but do not have to);
- * o %-EBADMSG if the MTD subsystem reported about data data integrity
- * problems, for example it can me an ECC error in case of NAND; this most
- * probably means that the data is corrupted;
+ * o %-EBADMSG if the MTD subsystem reported about data integrity problems, for
+ * example it can be an ECC error in case of NAND; this most probably means
+ * that the data is corrupted;
* o %-EIO if some I/O error occurred;
* o other negative error codes in case of other errors.
*/
@@ -298,7 +298,7 @@ retry:
memset(&ei, 0, sizeof(struct erase_info));
ei.mtd = ubi->mtd;
- ei.addr = pnum * ubi->peb_size;
+ ei.addr = (loff_t)pnum * ubi->peb_size;
ei.len = ubi->peb_size;
ei.callback = erase_callback;
ei.priv = (unsigned long)&wq;
@@ -382,7 +382,7 @@ static int torture_peb(const struct ubi_device *ubi, int pnum)
void *buf;
int err, i, patt_count;
- buf = kmalloc(ubi->peb_size, GFP_KERNEL);
+ buf = vmalloc(ubi->peb_size);
if (!buf)
return -ENOMEM;
@@ -437,7 +437,7 @@ out:
* physical eraseblock which means something is wrong with it.
*/
err = -EIO;
- kfree(buf);
+ vfree(buf);
return err;
}
@@ -557,9 +557,9 @@ static int validate_ec_hdr(const struct ubi_device *ubi,
long long ec;
int vid_hdr_offset, leb_start;
- ec = ubi64_to_cpu(ec_hdr->ec);
- vid_hdr_offset = ubi32_to_cpu(ec_hdr->vid_hdr_offset);
- leb_start = ubi32_to_cpu(ec_hdr->data_offset);
+ ec = be64_to_cpu(ec_hdr->ec);
+ vid_hdr_offset = be32_to_cpu(ec_hdr->vid_hdr_offset);
+ leb_start = be32_to_cpu(ec_hdr->data_offset);
if (ec_hdr->version != UBI_VERSION) {
ubi_err("node with incompatible UBI version found: "
@@ -640,7 +640,7 @@ int ubi_io_read_ec_hdr(const struct ubi_device *ubi, int pnum,
read_err = err;
}
- magic = ubi32_to_cpu(ec_hdr->magic);
+ magic = be32_to_cpu(ec_hdr->magic);
if (magic != UBI_EC_HDR_MAGIC) {
/*
* The magic field is wrong. Let's check if we have read all
@@ -684,7 +684,7 @@ int ubi_io_read_ec_hdr(const struct ubi_device *ubi, int pnum,
}
crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC);
- hdr_crc = ubi32_to_cpu(ec_hdr->hdr_crc);
+ hdr_crc = be32_to_cpu(ec_hdr->hdr_crc);
if (hdr_crc != crc) {
if (verbose) {
@@ -729,12 +729,12 @@ int ubi_io_write_ec_hdr(const struct ubi_device *ubi, int pnum,
dbg_io("write EC header to PEB %d", pnum);
ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
- ec_hdr->magic = cpu_to_ubi32(UBI_EC_HDR_MAGIC);
+ ec_hdr->magic = cpu_to_be32(UBI_EC_HDR_MAGIC);
ec_hdr->version = UBI_VERSION;
- ec_hdr->vid_hdr_offset = cpu_to_ubi32(ubi->vid_hdr_offset);
- ec_hdr->data_offset = cpu_to_ubi32(ubi->leb_start);
+ ec_hdr->vid_hdr_offset = cpu_to_be32(ubi->vid_hdr_offset);
+ ec_hdr->data_offset = cpu_to_be32(ubi->leb_start);
crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC);
- ec_hdr->hdr_crc = cpu_to_ubi32(crc);
+ ec_hdr->hdr_crc = cpu_to_be32(crc);
err = paranoid_check_ec_hdr(ubi, pnum, ec_hdr);
if (err)
@@ -757,13 +757,13 @@ static int validate_vid_hdr(const struct ubi_device *ubi,
{
int vol_type = vid_hdr->vol_type;
int copy_flag = vid_hdr->copy_flag;
- int vol_id = ubi32_to_cpu(vid_hdr->vol_id);
- int lnum = ubi32_to_cpu(vid_hdr->lnum);
+ int vol_id = be32_to_cpu(vid_hdr->vol_id);
+ int lnum = be32_to_cpu(vid_hdr->lnum);
int compat = vid_hdr->compat;
- int data_size = ubi32_to_cpu(vid_hdr->data_size);
- int used_ebs = ubi32_to_cpu(vid_hdr->used_ebs);
- int data_pad = ubi32_to_cpu(vid_hdr->data_pad);
- int data_crc = ubi32_to_cpu(vid_hdr->data_crc);
+ int data_size = be32_to_cpu(vid_hdr->data_size);
+ int used_ebs = be32_to_cpu(vid_hdr->used_ebs);
+ int data_pad = be32_to_cpu(vid_hdr->data_pad);
+ int data_crc = be32_to_cpu(vid_hdr->data_crc);
int usable_leb_size = ubi->leb_size - data_pad;
if (copy_flag != 0 && copy_flag != 1) {
@@ -914,7 +914,7 @@ int ubi_io_read_vid_hdr(const struct ubi_device *ubi, int pnum,
read_err = err;
}
- magic = ubi32_to_cpu(vid_hdr->magic);
+ magic = be32_to_cpu(vid_hdr->magic);
if (magic != UBI_VID_HDR_MAGIC) {
/*
* If we have read all 0xFF bytes, the VID header probably does
@@ -957,7 +957,7 @@ int ubi_io_read_vid_hdr(const struct ubi_device *ubi, int pnum,
}
crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_VID_HDR_SIZE_CRC);
- hdr_crc = ubi32_to_cpu(vid_hdr->hdr_crc);
+ hdr_crc = be32_to_cpu(vid_hdr->hdr_crc);
if (hdr_crc != crc) {
if (verbose) {
@@ -1007,10 +1007,10 @@ int ubi_io_write_vid_hdr(const struct ubi_device *ubi, int pnum,
if (err)
return err > 0 ? -EINVAL: err;
- vid_hdr->magic = cpu_to_ubi32(UBI_VID_HDR_MAGIC);
+ vid_hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC);
vid_hdr->version = UBI_VERSION;
crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_VID_HDR_SIZE_CRC);
- vid_hdr->hdr_crc = cpu_to_ubi32(crc);
+ vid_hdr->hdr_crc = cpu_to_be32(crc);
err = paranoid_check_vid_hdr(ubi, pnum, vid_hdr);
if (err)
@@ -1060,7 +1060,7 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
int err;
uint32_t magic;
- magic = ubi32_to_cpu(ec_hdr->magic);
+ magic = be32_to_cpu(ec_hdr->magic);
if (magic != UBI_EC_HDR_MAGIC) {
ubi_err("bad magic %#08x, must be %#08x",
magic, UBI_EC_HDR_MAGIC);
@@ -1105,7 +1105,7 @@ static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)
goto exit;
crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC);
- hdr_crc = ubi32_to_cpu(ec_hdr->hdr_crc);
+ hdr_crc = be32_to_cpu(ec_hdr->hdr_crc);
if (hdr_crc != crc) {
ubi_err("bad CRC, calculated %#08x, read %#08x", crc, hdr_crc);
ubi_err("paranoid check failed for PEB %d", pnum);
@@ -1137,7 +1137,7 @@ static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum,
int err;
uint32_t magic;
- magic = ubi32_to_cpu(vid_hdr->magic);
+ magic = be32_to_cpu(vid_hdr->magic);
if (magic != UBI_VID_HDR_MAGIC) {
ubi_err("bad VID header magic %#08x at PEB %d, must be %#08x",
magic, pnum, UBI_VID_HDR_MAGIC);
@@ -1187,7 +1187,7 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
goto exit;
crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_EC_HDR_SIZE_CRC);
- hdr_crc = ubi32_to_cpu(vid_hdr->hdr_crc);
+ hdr_crc = be32_to_cpu(vid_hdr->hdr_crc);
if (hdr_crc != crc) {
ubi_err("bad VID header CRC at PEB %d, calculated %#08x, "
"read %#08x", pnum, crc, hdr_crc);
@@ -1224,9 +1224,10 @@ static int paranoid_check_all_ff(const struct ubi_device *ubi, int pnum,
void *buf;
loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
- buf = kzalloc(len, GFP_KERNEL);
+ buf = vmalloc(len);
if (!buf)
return -ENOMEM;
+ memset(buf, 0, len);
err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);
if (err && err != -EUCLEAN) {
@@ -1242,7 +1243,7 @@ static int paranoid_check_all_ff(const struct ubi_device *ubi, int pnum,
goto fail;
}
- kfree(buf);
+ vfree(buf);
return 0;
fail:
@@ -1252,7 +1253,7 @@ fail:
err = 1;
error:
ubi_dbg_dump_stack();
- kfree(buf);
+ vfree(buf);
return err;
}
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c
index d352c4575c3d..4a458e83e4e9 100644
--- a/drivers/mtd/ubi/kapi.c
+++ b/drivers/mtd/ubi/kapi.c
@@ -37,14 +37,9 @@ int ubi_get_device_info(int ubi_num, struct ubi_device_info *di)
{
const struct ubi_device *ubi;
- if (!try_module_get(THIS_MODULE))
- return -ENODEV;
-
if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES ||
- !ubi_devices[ubi_num]) {
- module_put(THIS_MODULE);
+ !ubi_devices[ubi_num])
return -ENODEV;
- }
ubi = ubi_devices[ubi_num];
di->ubi_num = ubi->ubi_num;
@@ -52,7 +47,6 @@ int ubi_get_device_info(int ubi_num, struct ubi_device_info *di)
di->min_io_size = ubi->min_io_size;
di->ro_mode = ubi->ro_mode;
di->cdev = MKDEV(ubi->major, 0);
- module_put(THIS_MODULE);
return 0;
}
EXPORT_SYMBOL_GPL(ubi_get_device_info);
@@ -319,9 +313,14 @@ int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
offset + len > vol->usable_leb_size)
return -EINVAL;
- if (vol->vol_type == UBI_STATIC_VOLUME && lnum == vol->used_ebs - 1 &&
- offset + len > vol->last_eb_bytes)
- return -EINVAL;
+ if (vol->vol_type == UBI_STATIC_VOLUME) {
+ if (vol->used_ebs == 0)
+ /* Empty static UBI volume */
+ return 0;
+ if (lnum == vol->used_ebs - 1 &&
+ offset + len > vol->last_eb_bytes)
+ return -EINVAL;
+ }
if (vol->upd_marker)
return -EBADF;
diff --git a/drivers/mtd/ubi/misc.c b/drivers/mtd/ubi/misc.c
index 38d4e6757dc7..9e2338c8e2cf 100644
--- a/drivers/mtd/ubi/misc.c
+++ b/drivers/mtd/ubi/misc.c
@@ -67,7 +67,7 @@ int ubi_check_volume(struct ubi_device *ubi, int vol_id)
if (vol->vol_type != UBI_STATIC_VOLUME)
return 0;
- buf = kmalloc(vol->usable_leb_size, GFP_KERNEL);
+ buf = vmalloc(vol->usable_leb_size);
if (!buf)
return -ENOMEM;
@@ -87,7 +87,7 @@ int ubi_check_volume(struct ubi_device *ubi, int vol_id)
}
}
- kfree(buf);
+ vfree(buf);
return err;
}
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index 473f3200b868..94ee54934411 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -24,7 +24,7 @@
* This unit is responsible for scanning the flash media, checking UBI
* headers and providing complete information about the UBI flash image.
*
- * The scanning information is reoresented by a &struct ubi_scan_info' object.
+ * The scanning information is represented by a &struct ubi_scan_info' object.
* Information about found volumes is represented by &struct ubi_scan_volume
* objects which are kept in volume RB-tree with root at the @volumes field.
* The RB-tree is indexed by the volume ID.
@@ -55,8 +55,19 @@ static int paranoid_check_si(const struct ubi_device *ubi,
static struct ubi_ec_hdr *ech;
static struct ubi_vid_hdr *vidh;
-int ubi_scan_add_to_list(struct ubi_scan_info *si, int pnum, int ec,
- struct list_head *list)
+/**
+ * add_to_list - add physical eraseblock to a list.
+ * @si: scanning information
+ * @pnum: physical eraseblock number to add
+ * @ec: erase counter of the physical eraseblock
+ * @list: the list to add to
+ *
+ * This function adds physical eraseblock @pnum to free, erase, corrupted or
+ * alien lists. Returns zero in case of success and a negative error code in
+ * case of failure.
+ */
+static int add_to_list(struct ubi_scan_info *si, int pnum, int ec,
+ struct list_head *list)
{
struct ubi_scan_leb *seb;
@@ -121,9 +132,9 @@ static int validate_vid_hdr(const struct ubi_vid_hdr *vid_hdr,
const struct ubi_scan_volume *sv, int pnum)
{
int vol_type = vid_hdr->vol_type;
- int vol_id = ubi32_to_cpu(vid_hdr->vol_id);
- int used_ebs = ubi32_to_cpu(vid_hdr->used_ebs);
- int data_pad = ubi32_to_cpu(vid_hdr->data_pad);
+ int vol_id = be32_to_cpu(vid_hdr->vol_id);
+ int used_ebs = be32_to_cpu(vid_hdr->used_ebs);
+ int data_pad = be32_to_cpu(vid_hdr->data_pad);
if (sv->leb_count != 0) {
int sv_vol_type;
@@ -189,7 +200,7 @@ static struct ubi_scan_volume *add_volume(struct ubi_scan_info *si, int vol_id,
struct ubi_scan_volume *sv;
struct rb_node **p = &si->volumes.rb_node, *parent = NULL;
- ubi_assert(vol_id == ubi32_to_cpu(vid_hdr->vol_id));
+ ubi_assert(vol_id == be32_to_cpu(vid_hdr->vol_id));
/* Walk the volume RB-tree to look if this volume is already present */
while (*p) {
@@ -211,11 +222,10 @@ static struct ubi_scan_volume *add_volume(struct ubi_scan_info *si, int vol_id,
return ERR_PTR(-ENOMEM);
sv->highest_lnum = sv->leb_count = 0;
- si->max_sqnum = 0;
sv->vol_id = vol_id;
sv->root = RB_ROOT;
- sv->used_ebs = ubi32_to_cpu(vid_hdr->used_ebs);
- sv->data_pad = ubi32_to_cpu(vid_hdr->data_pad);
+ sv->used_ebs = be32_to_cpu(vid_hdr->used_ebs);
+ sv->data_pad = be32_to_cpu(vid_hdr->data_pad);
sv->compat = vid_hdr->compat;
sv->vol_type = vid_hdr->vol_type == UBI_VID_DYNAMIC ? UBI_DYNAMIC_VOLUME
: UBI_STATIC_VOLUME;
@@ -257,10 +267,10 @@ static int compare_lebs(const struct ubi_device *ubi,
int len, err, second_is_newer, bitflips = 0, corrupted = 0;
uint32_t data_crc, crc;
struct ubi_vid_hdr *vidh = NULL;
- unsigned long long sqnum2 = ubi64_to_cpu(vid_hdr->sqnum);
+ unsigned long long sqnum2 = be64_to_cpu(vid_hdr->sqnum);
if (seb->sqnum == 0 && sqnum2 == 0) {
- long long abs, v1 = seb->leb_ver, v2 = ubi32_to_cpu(vid_hdr->leb_ver);
+ long long abs, v1 = seb->leb_ver, v2 = be32_to_cpu(vid_hdr->leb_ver);
/*
* UBI constantly increases the logical eraseblock version
@@ -344,8 +354,8 @@ static int compare_lebs(const struct ubi_device *ubi,
/* Read the data of the copy and check the CRC */
- len = ubi32_to_cpu(vid_hdr->data_size);
- buf = kmalloc(len, GFP_KERNEL);
+ len = be32_to_cpu(vid_hdr->data_size);
+ buf = vmalloc(len);
if (!buf) {
err = -ENOMEM;
goto out_free_vidh;
@@ -355,7 +365,7 @@ static int compare_lebs(const struct ubi_device *ubi,
if (err && err != UBI_IO_BITFLIPS)
goto out_free_buf;
- data_crc = ubi32_to_cpu(vid_hdr->data_crc);
+ data_crc = be32_to_cpu(vid_hdr->data_crc);
crc = crc32(UBI_CRC32_INIT, buf, len);
if (crc != data_crc) {
dbg_bld("PEB %d CRC error: calculated %#08x, must be %#08x",
@@ -368,7 +378,7 @@ static int compare_lebs(const struct ubi_device *ubi,
bitflips = !!err;
}
- kfree(buf);
+ vfree(buf);
ubi_free_vid_hdr(ubi, vidh);
if (second_is_newer)
@@ -379,7 +389,7 @@ static int compare_lebs(const struct ubi_device *ubi,
return second_is_newer | (bitflips << 1) | (corrupted << 2);
out_free_buf:
- kfree(buf);
+ vfree(buf);
out_free_vidh:
ubi_free_vid_hdr(ubi, vidh);
ubi_assert(err < 0);
@@ -396,8 +406,12 @@ out_free_vidh:
* @vid_hdr: the volume identifier header
* @bitflips: if bit-flips were detected when this physical eraseblock was read
*
- * This function returns zero in case of success and a negative error code in
- * case of failure.
+ * This function adds information about a used physical eraseblock to the
+ * 'used' tree of the corresponding volume. The function is rather complex
+ * because it has to handle cases when this is not the first physical
+ * eraseblock belonging to the same logical eraseblock, and the newer one has
+ * to be picked, while the older one has to be dropped. This function returns
+ * zero in case of success and a negative error code in case of failure.
*/
int ubi_scan_add_used(const struct ubi_device *ubi, struct ubi_scan_info *si,
int pnum, int ec, const struct ubi_vid_hdr *vid_hdr,
@@ -410,10 +424,10 @@ int ubi_scan_add_used(const struct ubi_device *ubi, struct ubi_scan_info *si,
struct ubi_scan_leb *seb;
struct rb_node **p, *parent = NULL;
- vol_id = ubi32_to_cpu(vid_hdr->vol_id);
- lnum = ubi32_to_cpu(vid_hdr->lnum);
- sqnum = ubi64_to_cpu(vid_hdr->sqnum);
- leb_ver = ubi32_to_cpu(vid_hdr->leb_ver);
+ vol_id = be32_to_cpu(vid_hdr->vol_id);
+ lnum = be32_to_cpu(vid_hdr->lnum);
+ sqnum = be64_to_cpu(vid_hdr->sqnum);
+ leb_ver = be32_to_cpu(vid_hdr->leb_ver);
dbg_bld("PEB %d, LEB %d:%d, EC %d, sqnum %llu, ver %u, bitflips %d",
pnum, vol_id, lnum, ec, sqnum, leb_ver, bitflips);
@@ -422,6 +436,9 @@ int ubi_scan_add_used(const struct ubi_device *ubi, struct ubi_scan_info *si,
if (IS_ERR(sv) < 0)
return PTR_ERR(sv);
+ if (si->max_sqnum < sqnum)
+ si->max_sqnum = sqnum;
+
/*
* Walk the RB-tree of logical eraseblocks of volume @vol_id to look
* if this is the first instance of this logical eraseblock or not.
@@ -492,11 +509,11 @@ int ubi_scan_add_used(const struct ubi_device *ubi, struct ubi_scan_info *si,
return err;
if (cmp_res & 4)
- err = ubi_scan_add_to_list(si, seb->pnum,
- seb->ec, &si->corr);
+ err = add_to_list(si, seb->pnum, seb->ec,
+ &si->corr);
else
- err = ubi_scan_add_to_list(si, seb->pnum,
- seb->ec, &si->erase);
+ err = add_to_list(si, seb->pnum, seb->ec,
+ &si->erase);
if (err)
return err;
@@ -508,7 +525,7 @@ int ubi_scan_add_used(const struct ubi_device *ubi, struct ubi_scan_info *si,
if (sv->highest_lnum == lnum)
sv->last_data_size =
- ubi32_to_cpu(vid_hdr->data_size);
+ be32_to_cpu(vid_hdr->data_size);
return 0;
} else {
@@ -517,11 +534,9 @@ int ubi_scan_add_used(const struct ubi_device *ubi, struct ubi_scan_info *si,
* previously.
*/
if (cmp_res & 4)
- return ubi_scan_add_to_list(si, pnum, ec,
- &si->corr);
+ return add_to_list(si, pnum, ec, &si->corr);
else
- return ubi_scan_add_to_list(si, pnum, ec,
- &si->erase);
+ return add_to_list(si, pnum, ec, &si->erase);
}
}
@@ -547,12 +562,9 @@ int ubi_scan_add_used(const struct ubi_device *ubi, struct ubi_scan_info *si,
if (sv->highest_lnum <= lnum) {
sv->highest_lnum = lnum;
- sv->last_data_size = ubi32_to_cpu(vid_hdr->data_size);
+ sv->last_data_size = be32_to_cpu(vid_hdr->data_size);
}
- if (si->max_sqnum < sqnum)
- si->max_sqnum = sqnum;
-
sv->leb_count += 1;
rb_link_node(&seb->u.rb, parent, p);
rb_insert_color(&seb->u.rb, &sv->root);
@@ -674,7 +686,7 @@ int ubi_scan_erase_peb(const struct ubi_device *ubi,
return -EINVAL;
}
- ec_hdr->ec = cpu_to_ubi64(ec);
+ ec_hdr->ec = cpu_to_be64(ec);
err = ubi_io_sync_erase(ubi, pnum, 0);
if (err < 0)
@@ -754,7 +766,7 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(const struct ubi_device *ubi,
* @si: scanning information
* @pnum: the physical eraseblock number
*
- * This function returns a zero if the physical eraseblock was succesfully
+ * This function returns a zero if the physical eraseblock was successfully
* handled and a negative error code in case of failure.
*/
static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum)
@@ -783,8 +795,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum
else if (err == UBI_IO_BITFLIPS)
bitflips = 1;
else if (err == UBI_IO_PEB_EMPTY)
- return ubi_scan_add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC,
- &si->erase);
+ return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, &si->erase);
else if (err == UBI_IO_BAD_EC_HDR) {
/*
* We have to also look at the VID header, possibly it is not
@@ -806,7 +817,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum
return -EINVAL;
}
- ec = ubi64_to_cpu(ech->ec);
+ ec = be64_to_cpu(ech->ec);
if (ec > UBI_MAX_ERASECOUNTER) {
/*
* Erase counter overflow. The EC headers have 64 bits
@@ -832,28 +843,28 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum
else if (err == UBI_IO_BAD_VID_HDR ||
(err == UBI_IO_PEB_FREE && ec_corr)) {
/* VID header is corrupted */
- err = ubi_scan_add_to_list(si, pnum, ec, &si->corr);
+ err = add_to_list(si, pnum, ec, &si->corr);
if (err)
return err;
goto adjust_mean_ec;
} else if (err == UBI_IO_PEB_FREE) {
/* No VID header - the physical eraseblock is free */
- err = ubi_scan_add_to_list(si, pnum, ec, &si->free);
+ err = add_to_list(si, pnum, ec, &si->free);
if (err)
return err;
goto adjust_mean_ec;
}
- vol_id = ubi32_to_cpu(vidh->vol_id);
+ vol_id = be32_to_cpu(vidh->vol_id);
if (vol_id > UBI_MAX_VOLUMES && vol_id != UBI_LAYOUT_VOL_ID) {
- int lnum = ubi32_to_cpu(vidh->lnum);
+ int lnum = be32_to_cpu(vidh->lnum);
/* Unsupported internal volume */
switch (vidh->compat) {
case UBI_COMPAT_DELETE:
ubi_msg("\"delete\" compatible internal volume %d:%d"
" found, remove it", vol_id, lnum);
- err = ubi_scan_add_to_list(si, pnum, ec, &si->corr);
+ err = add_to_list(si, pnum, ec, &si->corr);
if (err)
return err;
break;
@@ -868,7 +879,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum
case UBI_COMPAT_PRESERVE:
ubi_msg("\"preserve\" compatible internal volume %d:%d"
" found", vol_id, lnum);
- err = ubi_scan_add_to_list(si, pnum, ec, &si->alien);
+ err = add_to_list(si, pnum, ec, &si->alien);
if (err)
return err;
si->alien_peb_count += 1;
@@ -1109,7 +1120,7 @@ static int paranoid_check_si(const struct ubi_device *ubi,
uint8_t *buf;
/*
- * At first, check that scanning information is ok.
+ * At first, check that scanning information is OK.
*/
ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) {
int leb_count = 0;
@@ -1249,12 +1260,12 @@ static int paranoid_check_si(const struct ubi_device *ubi,
goto bad_vid_hdr;
}
- if (seb->sqnum != ubi64_to_cpu(vidh->sqnum)) {
+ if (seb->sqnum != be64_to_cpu(vidh->sqnum)) {
ubi_err("bad sqnum %llu", seb->sqnum);
goto bad_vid_hdr;
}
- if (sv->vol_id != ubi32_to_cpu(vidh->vol_id)) {
+ if (sv->vol_id != be32_to_cpu(vidh->vol_id)) {
ubi_err("bad vol_id %d", sv->vol_id);
goto bad_vid_hdr;
}
@@ -1264,22 +1275,22 @@ static int paranoid_check_si(const struct ubi_device *ubi,
goto bad_vid_hdr;
}
- if (seb->lnum != ubi32_to_cpu(vidh->lnum)) {
+ if (seb->lnum != be32_to_cpu(vidh->lnum)) {
ubi_err("bad lnum %d", seb->lnum);
goto bad_vid_hdr;
}
- if (sv->used_ebs != ubi32_to_cpu(vidh->used_ebs)) {
+ if (sv->used_ebs != be32_to_cpu(vidh->used_ebs)) {
ubi_err("bad used_ebs %d", sv->used_ebs);
goto bad_vid_hdr;
}
- if (sv->data_pad != ubi32_to_cpu(vidh->data_pad)) {
+ if (sv->data_pad != be32_to_cpu(vidh->data_pad)) {
ubi_err("bad data_pad %d", sv->data_pad);
goto bad_vid_hdr;
}
- if (seb->leb_ver != ubi32_to_cpu(vidh->leb_ver)) {
+ if (seb->leb_ver != be32_to_cpu(vidh->leb_ver)) {
ubi_err("bad leb_ver %u", seb->leb_ver);
goto bad_vid_hdr;
}
@@ -1288,12 +1299,12 @@ static int paranoid_check_si(const struct ubi_device *ubi,
if (!last_seb)
continue;
- if (sv->highest_lnum != ubi32_to_cpu(vidh->lnum)) {
+ if (sv->highest_lnum != be32_to_cpu(vidh->lnum)) {
ubi_err("bad highest_lnum %d", sv->highest_lnum);
goto bad_vid_hdr;
}
- if (sv->last_data_size != ubi32_to_cpu(vidh->data_size)) {
+ if (sv->last_data_size != be32_to_cpu(vidh->data_size)) {
ubi_err("bad last_data_size %d", sv->last_data_size);
goto bad_vid_hdr;
}
@@ -1310,8 +1321,10 @@ static int paranoid_check_si(const struct ubi_device *ubi,
memset(buf, 1, ubi->peb_count);
for (pnum = 0; pnum < ubi->peb_count; pnum++) {
err = ubi_io_is_bad(ubi, pnum);
- if (err < 0)
+ if (err < 0) {
+ kfree(buf);
return err;
+ }
else if (err)
buf[pnum] = 0;
}
diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h
index 3949f6192c76..140e82e26534 100644
--- a/drivers/mtd/ubi/scan.h
+++ b/drivers/mtd/ubi/scan.h
@@ -147,8 +147,6 @@ static inline void ubi_scan_move_to_list(struct ubi_scan_volume *sv,
list_add_tail(&seb->u.list, list);
}
-int ubi_scan_add_to_list(struct ubi_scan_info *si, int pnum, int ec,
- struct list_head *list);
int ubi_scan_add_used(const struct ubi_device *ubi, struct ubi_scan_info *si,
int pnum, int ec, const struct ubi_vid_hdr *vid_hdr,
int bitflips);
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index feb647f108f0..5959f91be240 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -35,6 +35,7 @@
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/string.h>
+#include <linux/vmalloc.h>
#include <linux/mtd/mtd.h>
#include <mtd/ubi-header.h>
@@ -374,9 +375,11 @@ void ubi_calculate_reserved(struct ubi_device *ubi);
#ifdef CONFIG_MTD_UBI_GLUEBI
int ubi_create_gluebi(struct ubi_device *ubi, struct ubi_volume *vol);
int ubi_destroy_gluebi(struct ubi_volume *vol);
+void ubi_gluebi_updated(struct ubi_volume *vol);
#else
#define ubi_create_gluebi(ubi, vol) 0
#define ubi_destroy_gluebi(vol) 0
+#define ubi_gluebi_updated(vol)
#endif
/* eba.c */
diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c
index 8925b977e3dc..0efc586a8328 100644
--- a/drivers/mtd/ubi/upd.c
+++ b/drivers/mtd/ubi/upd.c
@@ -150,7 +150,7 @@ int ubi_start_update(struct ubi_device *ubi, int vol_id, long long bytes)
vol->updating = 0;
}
- vol->upd_buf = kmalloc(ubi->leb_size, GFP_KERNEL);
+ vol->upd_buf = vmalloc(ubi->leb_size);
if (!vol->upd_buf)
return -ENOMEM;
@@ -339,7 +339,7 @@ int ubi_more_update_data(struct ubi_device *ubi, int vol_id,
err = ubi_wl_flush(ubi);
if (err == 0) {
err = to_write;
- kfree(vol->upd_buf);
+ vfree(vol->upd_buf);
vol->updating = 0;
}
}
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index 622d0d18952c..ea0d5c825ab4 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -228,7 +228,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
for (i = 0; i < ubi->vtbl_slots; i++)
if (ubi->volumes[i] &&
ubi->volumes[i]->name_len == req->name_len &&
- strcmp(ubi->volumes[i]->name, req->name) == 0) {
+ !strcmp(ubi->volumes[i]->name, req->name)) {
dbg_err("volume \"%s\" exists (ID %d)", req->name, i);
goto out_unlock;
}
@@ -243,7 +243,6 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
/* Reserve physical eraseblocks */
if (vol->reserved_pebs > ubi->avail_pebs) {
dbg_err("not enough PEBs, only %d available", ubi->avail_pebs);
- spin_unlock(&ubi->volumes_lock);
err = -ENOSPC;
goto out_unlock;
}
@@ -281,7 +280,8 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
vol->used_ebs = vol->reserved_pebs;
vol->last_eb_bytes = vol->usable_leb_size;
- vol->used_bytes = vol->used_ebs * vol->usable_leb_size;
+ vol->used_bytes =
+ (long long)vol->used_ebs * vol->usable_leb_size;
} else {
bytes = vol->used_bytes;
vol->last_eb_bytes = do_div(bytes, vol->usable_leb_size);
@@ -320,10 +320,10 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
/* Fill volume table record */
memset(&vtbl_rec, 0, sizeof(struct ubi_vtbl_record));
- vtbl_rec.reserved_pebs = cpu_to_ubi32(vol->reserved_pebs);
- vtbl_rec.alignment = cpu_to_ubi32(vol->alignment);
- vtbl_rec.data_pad = cpu_to_ubi32(vol->data_pad);
- vtbl_rec.name_len = cpu_to_ubi16(vol->name_len);
+ vtbl_rec.reserved_pebs = cpu_to_be32(vol->reserved_pebs);
+ vtbl_rec.alignment = cpu_to_be32(vol->alignment);
+ vtbl_rec.data_pad = cpu_to_be32(vol->data_pad);
+ vtbl_rec.name_len = cpu_to_be16(vol->name_len);
if (vol->vol_type == UBI_DYNAMIC_VOLUME)
vtbl_rec.vol_type = UBI_VID_DYNAMIC;
else
@@ -352,6 +352,7 @@ out_acc:
spin_lock(&ubi->volumes_lock);
ubi->rsvd_pebs -= vol->reserved_pebs;
ubi->avail_pebs += vol->reserved_pebs;
+ ubi->volumes[vol_id] = NULL;
out_unlock:
spin_unlock(&ubi->volumes_lock);
kfree(vol);
@@ -368,6 +369,7 @@ out_sysfs:
spin_lock(&ubi->volumes_lock);
ubi->rsvd_pebs -= vol->reserved_pebs;
ubi->avail_pebs += vol->reserved_pebs;
+ ubi->volumes[vol_id] = NULL;
spin_unlock(&ubi->volumes_lock);
volume_sysfs_close(vol);
return err;
@@ -503,7 +505,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
/* Change volume table record */
memcpy(&vtbl_rec, &ubi->vtbl[vol_id], sizeof(struct ubi_vtbl_record));
- vtbl_rec.reserved_pebs = cpu_to_ubi32(reserved_pebs);
+ vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs);
err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
if (err)
goto out_acc;
@@ -537,7 +539,8 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
vol->used_ebs = reserved_pebs;
vol->last_eb_bytes = vol->usable_leb_size;
- vol->used_bytes = vol->used_ebs * vol->usable_leb_size;
+ vol->used_bytes =
+ (long long)vol->used_ebs * vol->usable_leb_size;
}
paranoid_check_volumes(ubi);
@@ -643,21 +646,33 @@ void ubi_free_volume(struct ubi_device *ubi, int vol_id)
* @ubi: UBI device description object
* @vol_id: volume ID
*/
-static void paranoid_check_volume(const struct ubi_device *ubi, int vol_id)
+static void paranoid_check_volume(struct ubi_device *ubi, int vol_id)
{
int idx = vol_id2idx(ubi, vol_id);
int reserved_pebs, alignment, data_pad, vol_type, name_len, upd_marker;
- const struct ubi_volume *vol = ubi->volumes[idx];
+ const struct ubi_volume *vol;
long long n;
const char *name;
- reserved_pebs = ubi32_to_cpu(ubi->vtbl[vol_id].reserved_pebs);
+ spin_lock(&ubi->volumes_lock);
+ reserved_pebs = be32_to_cpu(ubi->vtbl[vol_id].reserved_pebs);
+ vol = ubi->volumes[idx];
if (!vol) {
if (reserved_pebs) {
ubi_err("no volume info, but volume exists");
goto fail;
}
+ spin_unlock(&ubi->volumes_lock);
+ return;
+ }
+
+ if (vol->exclusive) {
+ /*
+ * The volume may be being created at the moment, do not check
+ * it (e.g., it may be in the middle of ubi_create_volume().
+ */
+ spin_unlock(&ubi->volumes_lock);
return;
}
@@ -726,7 +741,7 @@ static void paranoid_check_volume(const struct ubi_device *ubi, int vol_id)
goto fail;
}
- n = vol->used_ebs * vol->usable_leb_size;
+ n = (long long)vol->used_ebs * vol->usable_leb_size;
if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
if (vol->corrupted != 0) {
ubi_err("corrupted dynamic volume");
@@ -765,9 +780,9 @@ static void paranoid_check_volume(const struct ubi_device *ubi, int vol_id)
}
}
- alignment = ubi32_to_cpu(ubi->vtbl[vol_id].alignment);
- data_pad = ubi32_to_cpu(ubi->vtbl[vol_id].data_pad);
- name_len = ubi16_to_cpu(ubi->vtbl[vol_id].name_len);
+ alignment = be32_to_cpu(ubi->vtbl[vol_id].alignment);
+ data_pad = be32_to_cpu(ubi->vtbl[vol_id].data_pad);
+ name_len = be16_to_cpu(ubi->vtbl[vol_id].name_len);
upd_marker = ubi->vtbl[vol_id].upd_marker;
name = &ubi->vtbl[vol_id].name[0];
if (ubi->vtbl[vol_id].vol_type == UBI_VID_DYNAMIC)
@@ -782,12 +797,14 @@ static void paranoid_check_volume(const struct ubi_device *ubi, int vol_id)
goto fail;
}
+ spin_unlock(&ubi->volumes_lock);
return;
fail:
- ubi_err("paranoid check failed");
+ ubi_err("paranoid check failed for volume %d", vol_id);
ubi_dbg_dump_vol_info(vol);
ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id);
+ spin_unlock(&ubi->volumes_lock);
BUG();
}
@@ -800,10 +817,8 @@ static void paranoid_check_volumes(struct ubi_device *ubi)
int i;
mutex_lock(&ubi->vtbl_mutex);
- spin_lock(&ubi->volumes_lock);
for (i = 0; i < ubi->vtbl_slots; i++)
paranoid_check_volume(ubi, i);
- spin_unlock(&ubi->volumes_lock);
mutex_unlock(&ubi->vtbl_mutex);
}
#endif
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index b6fd6bbd941e..bc5df50813d6 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -93,12 +93,9 @@ int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
vtbl_rec = &empty_vtbl_record;
else {
crc = crc32(UBI_CRC32_INIT, vtbl_rec, UBI_VTBL_RECORD_SIZE_CRC);
- vtbl_rec->crc = cpu_to_ubi32(crc);
+ vtbl_rec->crc = cpu_to_be32(crc);
}
- dbg_msg("change record %d", idx);
- ubi_dbg_dump_vtbl_record(vtbl_rec, idx);
-
mutex_lock(&ubi->vtbl_mutex);
memcpy(&ubi->vtbl[idx], vtbl_rec, sizeof(struct ubi_vtbl_record));
for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) {
@@ -141,18 +138,18 @@ static int vtbl_check(const struct ubi_device *ubi,
for (i = 0; i < ubi->vtbl_slots; i++) {
cond_resched();
- reserved_pebs = ubi32_to_cpu(vtbl[i].reserved_pebs);
- alignment = ubi32_to_cpu(vtbl[i].alignment);
- data_pad = ubi32_to_cpu(vtbl[i].data_pad);
+ reserved_pebs = be32_to_cpu(vtbl[i].reserved_pebs);
+ alignment = be32_to_cpu(vtbl[i].alignment);
+ data_pad = be32_to_cpu(vtbl[i].data_pad);
upd_marker = vtbl[i].upd_marker;
vol_type = vtbl[i].vol_type;
- name_len = ubi16_to_cpu(vtbl[i].name_len);
+ name_len = be16_to_cpu(vtbl[i].name_len);
name = &vtbl[i].name[0];
crc = crc32(UBI_CRC32_INIT, &vtbl[i], UBI_VTBL_RECORD_SIZE_CRC);
- if (ubi32_to_cpu(vtbl[i].crc) != crc) {
+ if (be32_to_cpu(vtbl[i].crc) != crc) {
ubi_err("bad CRC at record %u: %#08x, not %#08x",
- i, crc, ubi32_to_cpu(vtbl[i].crc));
+ i, crc, be32_to_cpu(vtbl[i].crc));
ubi_dbg_dump_vtbl_record(&vtbl[i], i);
return 1;
}
@@ -225,8 +222,8 @@ static int vtbl_check(const struct ubi_device *ubi,
/* Checks that all names are unique */
for (i = 0; i < ubi->vtbl_slots - 1; i++) {
for (n = i + 1; n < ubi->vtbl_slots; n++) {
- int len1 = ubi16_to_cpu(vtbl[i].name_len);
- int len2 = ubi16_to_cpu(vtbl[n].name_len);
+ int len1 = be16_to_cpu(vtbl[i].name_len);
+ int len2 = be16_to_cpu(vtbl[n].name_len);
if (len1 > 0 && len1 == len2 &&
!strncmp(vtbl[i].name, vtbl[n].name, len1)) {
@@ -288,13 +285,13 @@ retry:
}
vid_hdr->vol_type = UBI_VID_DYNAMIC;
- vid_hdr->vol_id = cpu_to_ubi32(UBI_LAYOUT_VOL_ID);
+ vid_hdr->vol_id = cpu_to_be32(UBI_LAYOUT_VOL_ID);
vid_hdr->compat = UBI_LAYOUT_VOLUME_COMPAT;
vid_hdr->data_size = vid_hdr->used_ebs =
- vid_hdr->data_pad = cpu_to_ubi32(0);
- vid_hdr->lnum = cpu_to_ubi32(copy);
- vid_hdr->sqnum = cpu_to_ubi64(++si->max_sqnum);
- vid_hdr->leb_ver = cpu_to_ubi32(old_seb ? old_seb->leb_ver + 1: 0);
+ vid_hdr->data_pad = cpu_to_be32(0);
+ vid_hdr->lnum = cpu_to_be32(copy);
+ vid_hdr->sqnum = cpu_to_be64(++si->max_sqnum);
+ vid_hdr->leb_ver = cpu_to_be32(old_seb ? old_seb->leb_ver + 1: 0);
/* The EC header is already there, write the VID header */
err = ubi_io_write_vid_hdr(ubi, new_seb->pnum, vid_hdr);
@@ -317,14 +314,15 @@ retry:
return err;
write_error:
- kfree(new_seb);
- /* May be this physical eraseblock went bad, try to pick another one */
- if (++tries <= 5) {
- err = ubi_scan_add_to_list(si, new_seb->pnum, new_seb->ec,
- &si->corr);
- if (!err)
- goto retry;
+ if (err == -EIO && ++tries <= 5) {
+ /*
+ * Probably this physical eraseblock went bad, try to pick
+ * another one.
+ */
+ list_add_tail(&new_seb->u.list, &si->corr);
+ goto retry;
}
+ kfree(new_seb);
out_free:
ubi_free_vid_hdr(ubi, vid_hdr);
return err;
@@ -380,11 +378,12 @@ static struct ubi_vtbl_record *process_lvol(const struct ubi_device *ubi,
/* Read both LEB 0 and LEB 1 into memory */
ubi_rb_for_each_entry(rb, seb, &sv->root, u.rb) {
- leb[seb->lnum] = kzalloc(ubi->vtbl_size, GFP_KERNEL);
+ leb[seb->lnum] = vmalloc(ubi->vtbl_size);
if (!leb[seb->lnum]) {
err = -ENOMEM;
goto out_free;
}
+ memset(leb[seb->lnum], 0, ubi->vtbl_size);
err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0,
ubi->vtbl_size);
@@ -415,7 +414,7 @@ static struct ubi_vtbl_record *process_lvol(const struct ubi_device *ubi,
}
/* Both LEB 1 and LEB 2 are OK and consistent */
- kfree(leb[1]);
+ vfree(leb[1]);
return leb[0];
} else {
/* LEB 0 is corrupted or does not exist */
@@ -436,13 +435,13 @@ static struct ubi_vtbl_record *process_lvol(const struct ubi_device *ubi,
goto out_free;
ubi_msg("volume table was restored");
- kfree(leb[0]);
+ vfree(leb[0]);
return leb[1];
}
out_free:
- kfree(leb[0]);
- kfree(leb[1]);
+ vfree(leb[0]);
+ vfree(leb[1]);
return ERR_PTR(err);
}
@@ -460,9 +459,10 @@ static struct ubi_vtbl_record *create_empty_lvol(const struct ubi_device *ubi,
int i;
struct ubi_vtbl_record *vtbl;
- vtbl = kzalloc(ubi->vtbl_size, GFP_KERNEL);
+ vtbl = vmalloc(ubi->vtbl_size);
if (!vtbl)
return ERR_PTR(-ENOMEM);
+ memset(vtbl, 0, ubi->vtbl_size);
for (i = 0; i < ubi->vtbl_slots; i++)
memcpy(&vtbl[i], &empty_vtbl_record, UBI_VTBL_RECORD_SIZE);
@@ -472,7 +472,7 @@ static struct ubi_vtbl_record *create_empty_lvol(const struct ubi_device *ubi,
err = create_vtbl(ubi, si, i, vtbl);
if (err) {
- kfree(vtbl);
+ vfree(vtbl);
return ERR_PTR(err);
}
}
@@ -500,19 +500,19 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
for (i = 0; i < ubi->vtbl_slots; i++) {
cond_resched();
- if (ubi32_to_cpu(vtbl[i].reserved_pebs) == 0)
+ if (be32_to_cpu(vtbl[i].reserved_pebs) == 0)
continue; /* Empty record */
vol = kzalloc(sizeof(struct ubi_volume), GFP_KERNEL);
if (!vol)
return -ENOMEM;
- vol->reserved_pebs = ubi32_to_cpu(vtbl[i].reserved_pebs);
- vol->alignment = ubi32_to_cpu(vtbl[i].alignment);
- vol->data_pad = ubi32_to_cpu(vtbl[i].data_pad);
+ vol->reserved_pebs = be32_to_cpu(vtbl[i].reserved_pebs);
+ vol->alignment = be32_to_cpu(vtbl[i].alignment);
+ vol->data_pad = be32_to_cpu(vtbl[i].data_pad);
vol->vol_type = vtbl[i].vol_type == UBI_VID_DYNAMIC ?
UBI_DYNAMIC_VOLUME : UBI_STATIC_VOLUME;
- vol->name_len = ubi16_to_cpu(vtbl[i].name_len);
+ vol->name_len = be16_to_cpu(vtbl[i].name_len);
vol->usable_leb_size = ubi->leb_size - vol->data_pad;
memcpy(vol->name, vtbl[i].name, vol->name_len);
vol->name[vol->name_len] = '\0';
@@ -531,7 +531,8 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
vol->used_ebs = vol->reserved_pebs;
vol->last_eb_bytes = vol->usable_leb_size;
- vol->used_bytes = vol->used_ebs * vol->usable_leb_size;
+ vol->used_bytes =
+ (long long)vol->used_ebs * vol->usable_leb_size;
continue;
}
@@ -561,7 +562,8 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
}
vol->used_ebs = sv->used_ebs;
- vol->used_bytes = (vol->used_ebs - 1) * vol->usable_leb_size;
+ vol->used_bytes =
+ (long long)(vol->used_ebs - 1) * vol->usable_leb_size;
vol->used_bytes += sv->last_data_size;
vol->last_eb_bytes = sv->last_data_size;
}
@@ -578,7 +580,8 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
vol->usable_leb_size = ubi->leb_size;
vol->used_ebs = vol->reserved_pebs;
vol->last_eb_bytes = vol->reserved_pebs;
- vol->used_bytes = vol->used_ebs * (ubi->leb_size - vol->data_pad);
+ vol->used_bytes =
+ (long long)vol->used_ebs * (ubi->leb_size - vol->data_pad);
vol->vol_id = UBI_LAYOUT_VOL_ID;
ubi_assert(!ubi->volumes[i]);
@@ -718,7 +721,7 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
int i, err;
struct ubi_scan_volume *sv;
- empty_vtbl_record.crc = cpu_to_ubi32(0xf116c36b);
+ empty_vtbl_record.crc = cpu_to_be32(0xf116c36b);
/*
* The number of supported volumes is limited by the eraseblock size
@@ -783,7 +786,7 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
return 0;
out_free:
- kfree(ubi->vtbl);
+ vfree(ubi->vtbl);
for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++)
if (ubi->volumes[i]) {
kfree(ubi->volumes[i]);
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 9ecaf77eca9e..a5a9b8d87302 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -667,7 +667,7 @@ static int sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, int tortur
dbg_wl("erased PEB %d, new EC %llu", e->pnum, ec);
- ec_hdr->ec = cpu_to_ubi64(ec);
+ ec_hdr->ec = cpu_to_be64(ec);
err = ubi_io_write_ec_hdr(ubi, e->pnum, ec_hdr);
if (err)
@@ -1060,9 +1060,8 @@ out_unlock:
static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
int cancel)
{
- int err;
struct ubi_wl_entry *e = wl_wrk->e;
- int pnum = e->pnum;
+ int pnum = e->pnum, err, need;
if (cancel) {
dbg_wl("cancel erasure of PEB %d EC %d", pnum, e->ec);
@@ -1097,62 +1096,70 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
kfree(wl_wrk);
kmem_cache_free(wl_entries_slab, e);
- if (err != -EIO) {
+ if (err == -EINTR || err == -ENOMEM || err == -EAGAIN ||
+ err == -EBUSY) {
+ int err1;
+
+ /* Re-schedule the LEB for erasure */
+ err1 = schedule_erase(ubi, e, 0);
+ if (err1) {
+ err = err1;
+ goto out_ro;
+ }
+ return err;
+ } else if (err != -EIO) {
/*
* If this is not %-EIO, we have no idea what to do. Scheduling
* this physical eraseblock for erasure again would cause
* errors again and again. Well, lets switch to RO mode.
*/
- ubi_ro_mode(ubi);
- return err;
+ goto out_ro;
}
/* It is %-EIO, the PEB went bad */
if (!ubi->bad_allowed) {
ubi_err("bad physical eraseblock %d detected", pnum);
- ubi_ro_mode(ubi);
- err = -EIO;
- } else {
- int need;
-
- spin_lock(&ubi->volumes_lock);
- need = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs + 1;
- if (need > 0) {
- need = ubi->avail_pebs >= need ? need : ubi->avail_pebs;
- ubi->avail_pebs -= need;
- ubi->rsvd_pebs += need;
- ubi->beb_rsvd_pebs += need;
- if (need > 0)
- ubi_msg("reserve more %d PEBs", need);
- }
+ goto out_ro;
+ }
- if (ubi->beb_rsvd_pebs == 0) {
- spin_unlock(&ubi->volumes_lock);
- ubi_err("no reserved physical eraseblocks");
- ubi_ro_mode(ubi);
- return -EIO;
- }
+ spin_lock(&ubi->volumes_lock);
+ need = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs + 1;
+ if (need > 0) {
+ need = ubi->avail_pebs >= need ? need : ubi->avail_pebs;
+ ubi->avail_pebs -= need;
+ ubi->rsvd_pebs += need;
+ ubi->beb_rsvd_pebs += need;
+ if (need > 0)
+ ubi_msg("reserve more %d PEBs", need);
+ }
+ if (ubi->beb_rsvd_pebs == 0) {
spin_unlock(&ubi->volumes_lock);
- ubi_msg("mark PEB %d as bad", pnum);
+ ubi_err("no reserved physical eraseblocks");
+ goto out_ro;
+ }
- err = ubi_io_mark_bad(ubi, pnum);
- if (err) {
- ubi_ro_mode(ubi);
- return err;
- }
+ spin_unlock(&ubi->volumes_lock);
+ ubi_msg("mark PEB %d as bad", pnum);
- spin_lock(&ubi->volumes_lock);
- ubi->beb_rsvd_pebs -= 1;
- ubi->bad_peb_count += 1;
- ubi->good_peb_count -= 1;
- ubi_calculate_reserved(ubi);
- if (ubi->beb_rsvd_pebs == 0)
- ubi_warn("last PEB from the reserved pool was used");
- spin_unlock(&ubi->volumes_lock);
- }
+ err = ubi_io_mark_bad(ubi, pnum);
+ if (err)
+ goto out_ro;
+
+ spin_lock(&ubi->volumes_lock);
+ ubi->beb_rsvd_pebs -= 1;
+ ubi->bad_peb_count += 1;
+ ubi->good_peb_count -= 1;
+ ubi_calculate_reserved(ubi);
+ if (ubi->beb_rsvd_pebs == 0)
+ ubi_warn("last PEB from the reserved pool was used");
+ spin_unlock(&ubi->volumes_lock);
+
+ return err;
+out_ro:
+ ubi_ro_mode(ubi);
return err;
}
@@ -1346,6 +1353,7 @@ static int ubi_thread(void *u)
ubi_msg("background thread \"%s\" started, PID %d",
ubi->bgt_name, current->pid);
+ set_freezable();
for (;;) {
int err;
@@ -1444,7 +1452,7 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
if (ubi_devices_cnt == 0) {
wl_entries_slab = kmem_cache_create("ubi_wl_entry_slab",
sizeof(struct ubi_wl_entry),
- 0, 0, NULL, NULL);
+ 0, 0, NULL);
if (!wl_entries_slab)
return -ENOMEM;
}
@@ -1633,7 +1641,7 @@ static int paranoid_check_ec(const struct ubi_device *ubi, int pnum, int ec)
goto out_free;
}
- read_ec = ubi64_to_cpu(ec_hdr->ec);
+ read_ec = be64_to_cpu(ec_hdr->ec);
if (ec != read_ec) {
ubi_err("paranoid check failed for PEB %d", pnum);
ubi_err("read EC is %lld, should be %d", read_ec, ec);