diff options
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/devices/docg3.c | 16 | ||||
-rw-r--r-- | drivers/mtd/maps/lantiq-flash.c | 76 | ||||
-rw-r--r-- | drivers/mtd/nand/autcpu12.c | 10 | ||||
-rw-r--r-- | drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 9 | ||||
-rw-r--r-- | drivers/mtd/nand/h1910.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/mxc_nand.c | 6 | ||||
-rw-r--r-- | drivers/mtd/nand/orion_nand.c | 65 | ||||
-rw-r--r-- | drivers/mtd/ubi/Kconfig | 8 | ||||
-rw-r--r-- | drivers/mtd/ubi/Makefile | 5 | ||||
-rw-r--r-- | drivers/mtd/ubi/attach.c (renamed from drivers/mtd/ubi/scan.c) | 970 | ||||
-rw-r--r-- | drivers/mtd/ubi/build.c | 85 | ||||
-rw-r--r-- | drivers/mtd/ubi/cdev.c | 36 | ||||
-rw-r--r-- | drivers/mtd/ubi/debug.c | 137 | ||||
-rw-r--r-- | drivers/mtd/ubi/debug.h | 98 | ||||
-rw-r--r-- | drivers/mtd/ubi/eba.c | 68 | ||||
-rw-r--r-- | drivers/mtd/ubi/gluebi.c | 2 | ||||
-rw-r--r-- | drivers/mtd/ubi/io.c | 211 | ||||
-rw-r--r-- | drivers/mtd/ubi/kapi.c | 61 | ||||
-rw-r--r-- | drivers/mtd/ubi/scan.h | 174 | ||||
-rw-r--r-- | drivers/mtd/ubi/ubi-media.h | 8 | ||||
-rw-r--r-- | drivers/mtd/ubi/ubi.h | 179 | ||||
-rw-r--r-- | drivers/mtd/ubi/upd.c | 16 | ||||
-rw-r--r-- | drivers/mtd/ubi/vmt.c | 62 | ||||
-rw-r--r-- | drivers/mtd/ubi/vtbl.c | 228 | ||||
-rw-r--r-- | drivers/mtd/ubi/wl.c | 260 |
25 files changed, 1317 insertions, 1475 deletions
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c index 3dbbfa58251d..f70854d728fe 100644 --- a/drivers/mtd/devices/docg3.c +++ b/drivers/mtd/devices/docg3.c @@ -383,7 +383,7 @@ static void doc_set_device_id(struct docg3 *docg3, int id) * leveling counters are stored. To access this last area of 4 bytes, a special * mode must be input to the flash ASIC. * - * Returns 0 if no error occured, -EIO else. + * Returns 0 if no error occurred, -EIO else. */ static int doc_set_extra_page_mode(struct docg3 *docg3) { @@ -681,7 +681,7 @@ out: * - one read of 512 bytes at offset 0 * - one read of 512 bytes at offset 512 + 16 * - * Returns 0 if successful, -EIO if a read error occured. + * Returns 0 if successful, -EIO if a read error occurred. */ static int doc_read_page_prepare(struct docg3 *docg3, int block0, int block1, int page, int offset) @@ -851,7 +851,7 @@ static void calc_block_sector(loff_t from, int *block0, int *block1, int *page, * * Reads flash memory OOB area of pages. * - * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured + * Returns 0 if read successful, of -EIO, -EINVAL if an error occurred */ static int doc_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) @@ -985,7 +985,7 @@ err_in_read: * Reads flash memory pages. This function does not read the OOB chunk, but only * the page data. * - * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured + * Returns 0 if read successful, of -EIO, -EINVAL if an error occurred */ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) @@ -1123,7 +1123,7 @@ static int doc_get_op_status(struct docg3 *docg3) * Wait for the chip to be ready again after erase or write operation, and check * erase/write status. * - * Returns 0 if erase successfull, -EIO if erase/write issue, -ETIMEOUT if + * Returns 0 if erase successful, -EIO if erase/write issue, -ETIMEOUT if * timeout */ static int doc_write_erase_wait_status(struct docg3 *docg3) @@ -1200,7 +1200,7 @@ static int doc_erase_block(struct docg3 *docg3, int block0, int block1) * Erase a bunch of contiguous blocks, by pairs, as a "mtd" page of 1024 is * split into 2 pages of 512 bytes on 2 contiguous blocks. * - * Returns 0 if erase successful, -EINVAL if adressing error, -EIO if erase + * Returns 0 if erase successful, -EINVAL if addressing error, -EIO if erase * issue */ static int doc_erase(struct mtd_info *mtd, struct erase_info *info) @@ -1411,7 +1411,7 @@ static int doc_backup_oob(struct docg3 *docg3, loff_t to, * Or provide data without OOB, and then a all zeroed OOB will be used (ECC will * still be filled in if asked for). * - * Returns 0 is successfull, EINVAL if length is not 14 bytes + * Returns 0 is successful, EINVAL if length is not 14 bytes */ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, struct mtd_oob_ops *ops) @@ -1959,7 +1959,7 @@ static void doc_release_device(struct mtd_info *mtd) * docg3_resume - Awakens docg3 floor * @pdev: platfrom device * - * Returns 0 (always successfull) + * Returns 0 (always successful) */ static int docg3_resume(struct platform_device *pdev) { diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c index b5401e355745..c03456f17004 100644 --- a/drivers/mtd/maps/lantiq-flash.c +++ b/drivers/mtd/maps/lantiq-flash.c @@ -19,9 +19,9 @@ #include <linux/mtd/cfi.h> #include <linux/platform_device.h> #include <linux/mtd/physmap.h> +#include <linux/of.h> #include <lantiq_soc.h> -#include <lantiq_platform.h> /* * The NOR flash is connected to the same external bus unit (EBU) as PCI. @@ -44,8 +44,9 @@ struct ltq_mtd { struct map_info *map; }; -static char ltq_map_name[] = "ltq_nor"; -static const char *ltq_probe_types[] __devinitconst = { "cmdlinepart", NULL }; +static const char ltq_map_name[] = "ltq_nor"; +static const char *ltq_probe_types[] __devinitconst = { + "cmdlinepart", "ofpart", NULL }; static map_word ltq_read16(struct map_info *map, unsigned long adr) @@ -108,42 +109,38 @@ ltq_copy_to(struct map_info *map, unsigned long to, spin_unlock_irqrestore(&ebu_lock, flags); } -static int __init +static int __devinit ltq_mtd_probe(struct platform_device *pdev) { - struct physmap_flash_data *ltq_mtd_data = dev_get_platdata(&pdev->dev); + struct mtd_part_parser_data ppdata; struct ltq_mtd *ltq_mtd; - struct resource *res; struct cfi_private *cfi; int err; + if (of_machine_is_compatible("lantiq,falcon") && + (ltq_boot_select() != BS_FLASH)) { + dev_err(&pdev->dev, "invalid bootstrap options\n"); + return -ENODEV; + } + ltq_mtd = kzalloc(sizeof(struct ltq_mtd), GFP_KERNEL); platform_set_drvdata(pdev, ltq_mtd); ltq_mtd->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!ltq_mtd->res) { - dev_err(&pdev->dev, "failed to get memory resource"); + dev_err(&pdev->dev, "failed to get memory resource\n"); err = -ENOENT; goto err_out; } - res = devm_request_mem_region(&pdev->dev, ltq_mtd->res->start, - resource_size(ltq_mtd->res), dev_name(&pdev->dev)); - if (!ltq_mtd->res) { - dev_err(&pdev->dev, "failed to request mem resource"); - err = -EBUSY; - goto err_out; - } - ltq_mtd->map = kzalloc(sizeof(struct map_info), GFP_KERNEL); - ltq_mtd->map->phys = res->start; - ltq_mtd->map->size = resource_size(res); - ltq_mtd->map->virt = devm_ioremap_nocache(&pdev->dev, - ltq_mtd->map->phys, ltq_mtd->map->size); + ltq_mtd->map->phys = ltq_mtd->res->start; + ltq_mtd->map->size = resource_size(ltq_mtd->res); + ltq_mtd->map->virt = devm_request_and_ioremap(&pdev->dev, ltq_mtd->res); if (!ltq_mtd->map->virt) { - dev_err(&pdev->dev, "failed to ioremap!\n"); - err = -ENOMEM; - goto err_free; + dev_err(&pdev->dev, "failed to remap mem resource\n"); + err = -EBUSY; + goto err_out; } ltq_mtd->map->name = ltq_map_name; @@ -169,9 +166,9 @@ ltq_mtd_probe(struct platform_device *pdev) cfi->addr_unlock1 ^= 1; cfi->addr_unlock2 ^= 1; - err = mtd_device_parse_register(ltq_mtd->mtd, ltq_probe_types, NULL, - ltq_mtd_data->parts, - ltq_mtd_data->nr_parts); + ppdata.of_node = pdev->dev.of_node; + err = mtd_device_parse_register(ltq_mtd->mtd, ltq_probe_types, + &ppdata, NULL, 0); if (err) { dev_err(&pdev->dev, "failed to add partitions\n"); goto err_destroy; @@ -204,32 +201,23 @@ ltq_mtd_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id ltq_mtd_match[] = { + { .compatible = "lantiq,nor" }, + {}, +}; +MODULE_DEVICE_TABLE(of, ltq_mtd_match); + static struct platform_driver ltq_mtd_driver = { + .probe = ltq_mtd_probe, .remove = __devexit_p(ltq_mtd_remove), .driver = { - .name = "ltq_nor", + .name = "ltq-nor", .owner = THIS_MODULE, + .of_match_table = ltq_mtd_match, }, }; -static int __init -init_ltq_mtd(void) -{ - int ret = platform_driver_probe(<q_mtd_driver, ltq_mtd_probe); - - if (ret) - pr_err("ltq_nor: error registering platform driver"); - return ret; -} - -static void __exit -exit_ltq_mtd(void) -{ - platform_driver_unregister(<q_mtd_driver); -} - -module_init(init_ltq_mtd); -module_exit(exit_ltq_mtd); +module_platform_driver(ltq_mtd_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c index 2e42ec2e8ff4..04769a49a7cb 100644 --- a/drivers/mtd/nand/autcpu12.c +++ b/drivers/mtd/nand/autcpu12.c @@ -102,10 +102,10 @@ static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd, void __iomem *addr; unsigned char bits; - addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET; - bits = (ctrl & NAND_CLE) << 4; + bits = clps_readb(AUTCPU12_SMC_PORT_OFFSET) & ~0x30; + bits |= (ctrl & NAND_CLE) << 4; bits |= (ctrl & NAND_ALE) << 2; - writeb((readb(addr) & ~0x30) | bits, addr); + clps_writeb(bits, AUTCPU12_SMC_PORT_OFFSET); addr = autcpu12_fio_base + AUTCPU12_SMC_SELECT_OFFSET; writeb((readb(addr) & ~0x1) | (ctrl & NAND_NCE), addr); @@ -120,9 +120,7 @@ static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd, */ int autcpu12_device_ready(struct mtd_info *mtd) { - void __iomem *addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET; - - return readb(addr) & AUTCPU12_SMC_RDY; + return clps_readb(AUTCPU12_SMC_PORT_OFFSET) & AUTCPU12_SMC_RDY; } /* diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 3eafc68154ed..a05b7b444d4f 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -24,6 +24,7 @@ #include <linux/module.h> #include <linux/mtd/gpmi-nand.h> #include <linux/mtd/partitions.h> +#include <linux/pinctrl/consumer.h> #include <linux/of.h> #include <linux/of_device.h> #include "gpmi-nand.h" @@ -466,6 +467,7 @@ acquire_err: static int __devinit acquire_resources(struct gpmi_nand_data *this) { struct resources *res = &this->resources; + struct pinctrl *pinctrl; int ret; ret = acquire_register_block(this, GPMI_NAND_GPMI_REGS_ADDR_RES_NAME); @@ -484,6 +486,12 @@ static int __devinit acquire_resources(struct gpmi_nand_data *this) if (ret) goto exit_dma_channels; + pinctrl = devm_pinctrl_get_select_default(&this->pdev->dev); + if (IS_ERR(pinctrl)) { + ret = PTR_ERR(pinctrl); + goto exit_pin; + } + res->clock = clk_get(&this->pdev->dev, NULL); if (IS_ERR(res->clock)) { pr_err("can not get the clock\n"); @@ -493,6 +501,7 @@ static int __devinit acquire_resources(struct gpmi_nand_data *this) return 0; exit_clock: +exit_pin: release_dma_channels(this); exit_dma_channels: release_bch_irq(this); diff --git a/drivers/mtd/nand/h1910.c b/drivers/mtd/nand/h1910.c index 85e55a5eb2ff..50166e93ba96 100644 --- a/drivers/mtd/nand/h1910.c +++ b/drivers/mtd/nand/h1910.c @@ -24,7 +24,7 @@ #include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> #include <asm/io.h> -#include <mach/hardware.h> /* for CLPS7111_VIRT_BASE */ +#include <mach/hardware.h> #include <asm/sizes.h> #include <mach/h1900-gpio.h> #include <mach/ipaq.h> diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 3310a48000d1..c58e6a93f445 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -743,7 +743,7 @@ static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip) if (chip == -1) { /* Disable the NFC clock */ if (host->clk_act) { - clk_disable(host->clk); + clk_disable_unprepare(host->clk); host->clk_act = 0; } return; @@ -751,7 +751,7 @@ static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip) if (!host->clk_act) { /* Enable the NFC clock */ - clk_enable(host->clk); + clk_prepare_enable(host->clk); host->clk_act = 1; } } @@ -1357,7 +1357,7 @@ static int __init mxcnd_probe(struct platform_device *pdev) goto eclk; } - clk_enable(host->clk); + clk_prepare_enable(host->clk); host->clk_act = 1; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index 1d3bfb26080c..513dc88a05ca 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c @@ -13,9 +13,12 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/of.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> +#include <linux/clk.h> +#include <linux/err.h> #include <asm/io.h> #include <asm/sizes.h> #include <mach/hardware.h> @@ -74,11 +77,14 @@ static void orion_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) static int __init orion_nand_probe(struct platform_device *pdev) { struct mtd_info *mtd; + struct mtd_part_parser_data ppdata = {}; struct nand_chip *nc; struct orion_nand_data *board; struct resource *res; + struct clk *clk; void __iomem *io_base; int ret = 0; + u32 val = 0; nc = kzalloc(sizeof(struct nand_chip) + sizeof(struct mtd_info), GFP_KERNEL); if (!nc) { @@ -101,7 +107,32 @@ static int __init orion_nand_probe(struct platform_device *pdev) goto no_res; } - board = pdev->dev.platform_data; + if (pdev->dev.of_node) { + board = devm_kzalloc(&pdev->dev, sizeof(struct orion_nand_data), + GFP_KERNEL); + if (!board) { + printk(KERN_ERR "orion_nand: failed to allocate board structure.\n"); + ret = -ENOMEM; + goto no_res; + } + if (!of_property_read_u32(pdev->dev.of_node, "cle", &val)) + board->cle = (u8)val; + else + board->cle = 0; + if (!of_property_read_u32(pdev->dev.of_node, "ale", &val)) + board->ale = (u8)val; + else + board->ale = 1; + if (!of_property_read_u32(pdev->dev.of_node, + "bank-width", &val)) + board->width = (u8)val * 8; + else + board->width = 8; + if (!of_property_read_u32(pdev->dev.of_node, + "chip-delay", &val)) + board->chip_delay = (u8)val; + } else + board = pdev->dev.platform_data; mtd->priv = nc; mtd->owner = THIS_MODULE; @@ -115,6 +146,10 @@ static int __init orion_nand_probe(struct platform_device *pdev) if (board->chip_delay) nc->chip_delay = board->chip_delay; + WARN(board->width > 16, + "%d bit bus width out of range", + board->width); + if (board->width == 16) nc->options |= NAND_BUSWIDTH_16; @@ -123,14 +158,23 @@ static int __init orion_nand_probe(struct platform_device *pdev) platform_set_drvdata(pdev, mtd); + /* Not all platforms can gate the clock, so it is not + an error if the clock does not exists. */ + clk = clk_get(&pdev->dev, NULL); + if (!IS_ERR(clk)) { + clk_prepare_enable(clk); + clk_put(clk); + } + if (nand_scan(mtd, 1)) { ret = -ENXIO; goto no_dev; } mtd->name = "orion_nand"; - ret = mtd_device_parse_register(mtd, NULL, NULL, board->parts, - board->nr_parts); + ppdata.of_node = pdev->dev.of_node; + ret = mtd_device_parse_register(mtd, NULL, &ppdata, + board->parts, board->nr_parts); if (ret) { nand_release(mtd); goto no_dev; @@ -151,6 +195,7 @@ static int __devexit orion_nand_remove(struct platform_device *pdev) { struct mtd_info *mtd = platform_get_drvdata(pdev); struct nand_chip *nc = mtd->priv; + struct clk *clk; nand_release(mtd); @@ -158,14 +203,28 @@ static int __devexit orion_nand_remove(struct platform_device *pdev) kfree(nc); + clk = clk_get(&pdev->dev, NULL); + if (!IS_ERR(clk)) { + clk_disable_unprepare(clk); + clk_put(clk); + } + return 0; } +#ifdef CONFIG_OF +static struct of_device_id orion_nand_of_match_table[] = { + { .compatible = "mrvl,orion-nand", }, + {}, +}; +#endif + static struct platform_driver orion_nand_driver = { .remove = __devexit_p(orion_nand_remove), .driver = { .name = "orion_nand", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(orion_nand_of_match_table), }, }; diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig index 4dcc752a0c0b..738ee8dc16cd 100644 --- a/drivers/mtd/ubi/Kconfig +++ b/drivers/mtd/ubi/Kconfig @@ -52,12 +52,4 @@ config MTD_UBI_GLUEBI work on top of UBI. Do not enable this unless you use legacy software. -config MTD_UBI_DEBUG - bool "UBI debugging" - depends on SYSFS - select DEBUG_FS - select KALLSYMS - help - This option enables UBI debugging. - endif # MTD_UBI diff --git a/drivers/mtd/ubi/Makefile b/drivers/mtd/ubi/Makefile index c9302a5452b0..a0803ac74712 100644 --- a/drivers/mtd/ubi/Makefile +++ b/drivers/mtd/ubi/Makefile @@ -1,7 +1,6 @@ obj-$(CONFIG_MTD_UBI) += ubi.o -ubi-y += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o scan.o -ubi-y += misc.o +ubi-y += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o attach.o +ubi-y += misc.o debug.o -ubi-$(CONFIG_MTD_UBI_DEBUG) += debug.o obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/attach.c index 12c43b44f815..bd27cbbb4066 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/attach.c @@ -19,21 +19,21 @@ */ /* - * UBI scanning sub-system. + * UBI attaching sub-system. * - * This sub-system is responsible for scanning the flash media, checking UBI - * headers and providing complete information about the UBI flash image. + * This sub-system is responsible for attaching MTD devices and it also + * implements flash media scanning. * - * The scanning information is represented by a &struct ubi_scan_info' object. - * Information about found volumes is represented by &struct ubi_scan_volume + * The attaching information is represented by a &struct ubi_attach_info' + * object. Information about volumes is represented by &struct ubi_ainf_volume * objects which are kept in volume RB-tree with root at the @volumes field. * The RB-tree is indexed by the volume ID. * - * Scanned logical eraseblocks are represented by &struct ubi_scan_leb objects. - * These objects are kept in per-volume RB-trees with the root at the - * corresponding &struct ubi_scan_volume object. To put it differently, we keep - * an RB-tree of per-volume objects and each of these objects is the root of - * RB-tree of per-eraseblock objects. + * Logical eraseblocks are represented by &struct ubi_ainf_peb objects. These + * objects are kept in per-volume RB-trees with the root at the corresponding + * &struct ubi_ainf_volume object. To put it differently, we keep an RB-tree of + * per-volume objects and each of these objects is the root of RB-tree of + * per-LEB objects. * * Corrupted physical eraseblocks are put to the @corr list, free physical * eraseblocks are put to the @free list and the physical eraseblock to be @@ -51,28 +51,29 @@ * * 1. Corruptions caused by power cuts. These are expected corruptions and UBI * tries to handle them gracefully, without printing too many warnings and - * error messages. The idea is that we do not lose important data in these case - * - we may lose only the data which was being written to the media just before - * the power cut happened, and the upper layers (e.g., UBIFS) are supposed to - * handle such data losses (e.g., by using the FS journal). + * error messages. The idea is that we do not lose important data in these + * cases - we may lose only the data which were being written to the media just + * before the power cut happened, and the upper layers (e.g., UBIFS) are + * supposed to handle such data losses (e.g., by using the FS journal). * * When UBI detects a corruption (CRC-32 mismatch) in a PEB, and it looks like * the reason is a power cut, UBI puts this PEB to the @erase list, and all * PEBs in the @erase list are scheduled for erasure later. * * 2. Unexpected corruptions which are not caused by power cuts. During - * scanning, such PEBs are put to the @corr list and UBI preserves them. + * attaching, such PEBs are put to the @corr list and UBI preserves them. * Obviously, this lessens the amount of available PEBs, and if at some point * UBI runs out of free PEBs, it switches to R/O mode. UBI also loudly informs * about such PEBs every time the MTD device is attached. * * However, it is difficult to reliably distinguish between these types of - * corruptions and UBI's strategy is as follows. UBI assumes corruption type 2 - * if the VID header is corrupted and the data area does not contain all 0xFFs, - * and there were no bit-flips or integrity errors while reading the data area. - * Otherwise UBI assumes corruption type 1. So the decision criteria are as - * follows. - * o If the data area contains only 0xFFs, there is no data, and it is safe + * corruptions and UBI's strategy is as follows (in case of attaching by + * scanning). UBI assumes corruption type 2 if the VID header is corrupted and + * the data area does not contain all 0xFFs, and there were no bit-flips or + * integrity errors (e.g., ECC errors in case of NAND) while reading the data + * area. Otherwise UBI assumes corruption type 1. So the decision criteria + * are as follows. + * o If the data area contains only 0xFFs, there are no data, and it is safe * to just erase this PEB - this is corruption type 1. * o If the data area has bit-flips or data integrity errors (ECC errors on * NAND), it is probably a PEB which was being erased when power cut @@ -88,11 +89,7 @@ #include <linux/random.h> #include "ubi.h" -#ifdef CONFIG_MTD_UBI_DEBUG -static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si); -#else -#define paranoid_check_si(ubi, si) 0 -#endif +static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai); /* Temporary variables used during scanning */ static struct ubi_ec_hdr *ech; @@ -100,13 +97,18 @@ static struct ubi_vid_hdr *vidh; /** * add_to_list - add physical eraseblock to a list. - * @si: scanning information + * @ai: attaching information * @pnum: physical eraseblock number to add + * @vol_id: the last used volume id for the PEB + * @lnum: the last used LEB number for the PEB * @ec: erase counter of the physical eraseblock * @to_head: if not zero, add to the head of the list * @list: the list to add to * - * This function adds physical eraseblock @pnum to free, erase, or alien lists. + * This function allocates a 'struct ubi_ainf_peb' object for physical + * eraseblock @pnum and adds it to the "free", "erase", or "alien" lists. + * It stores the @lnum and @vol_id alongside, which can both be + * %UBI_UNKNOWN if they are not available, not readable, or not assigned. * If @to_head is not zero, PEB will be added to the head of the list, which * basically means it will be processed first later. E.g., we add corrupted * PEBs (corrupted due to power cuts) to the head of the erase list to make @@ -114,65 +116,68 @@ static struct ubi_vid_hdr *vidh; * 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, int to_head, - struct list_head *list) +static int add_to_list(struct ubi_attach_info *ai, int pnum, int vol_id, + int lnum, int ec, int to_head, struct list_head *list) { - struct ubi_scan_leb *seb; + struct ubi_ainf_peb *aeb; - if (list == &si->free) { + if (list == &ai->free) { dbg_bld("add to free: PEB %d, EC %d", pnum, ec); - } else if (list == &si->erase) { + } else if (list == &ai->erase) { dbg_bld("add to erase: PEB %d, EC %d", pnum, ec); - } else if (list == &si->alien) { + } else if (list == &ai->alien) { dbg_bld("add to alien: PEB %d, EC %d", pnum, ec); - si->alien_peb_count += 1; + ai->alien_peb_count += 1; } else BUG(); - seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL); - if (!seb) + aeb = kmem_cache_alloc(ai->aeb_slab_cache, GFP_KERNEL); + if (!aeb) return -ENOMEM; - seb->pnum = pnum; - seb->ec = ec; + aeb->pnum = pnum; + aeb->vol_id = vol_id; + aeb->lnum = lnum; + aeb->ec = ec; if (to_head) - list_add(&seb->u.list, list); + list_add(&aeb->u.list, list); else - list_add_tail(&seb->u.list, list); + list_add_tail(&aeb->u.list, list); return 0; } /** * add_corrupted - add a corrupted physical eraseblock. - * @si: scanning information + * @ai: attaching information * @pnum: physical eraseblock number to add * @ec: erase counter of the physical eraseblock * - * This function adds corrupted physical eraseblock @pnum to the 'corr' list. - * The corruption was presumably not caused by a power cut. Returns zero in - * case of success and a negative error code in case of failure. + * This function allocates a 'struct ubi_ainf_peb' object for a corrupted + * physical eraseblock @pnum and adds it to the 'corr' list. The corruption + * was presumably not caused by a power cut. Returns zero in case of success + * and a negative error code in case of failure. */ -static int add_corrupted(struct ubi_scan_info *si, int pnum, int ec) +static int add_corrupted(struct ubi_attach_info *ai, int pnum, int ec) { - struct ubi_scan_leb *seb; + struct ubi_ainf_peb *aeb; dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec); - seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL); - if (!seb) + aeb = kmem_cache_alloc(ai->aeb_slab_cache, GFP_KERNEL); + if (!aeb) return -ENOMEM; - si->corr_peb_count += 1; - seb->pnum = pnum; - seb->ec = ec; - list_add(&seb->u.list, &si->corr); + ai->corr_peb_count += 1; + aeb->pnum = pnum; + aeb->ec = ec; + list_add(&aeb->u.list, &ai->corr); return 0; } /** * validate_vid_hdr - check volume identifier header. * @vid_hdr: the volume identifier header to check - * @sv: information about the volume this logical eraseblock belongs to + * @av: information about the volume this logical eraseblock belongs to * @pnum: physical eraseblock number the VID header came from * * This function checks that data stored in @vid_hdr is consistent. Returns @@ -184,15 +189,15 @@ static int add_corrupted(struct ubi_scan_info *si, int pnum, int ec) * headers of the same volume. */ static int validate_vid_hdr(const struct ubi_vid_hdr *vid_hdr, - const struct ubi_scan_volume *sv, int pnum) + const struct ubi_ainf_volume *av, int pnum) { int vol_type = vid_hdr->vol_type; 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; + if (av->leb_count != 0) { + int av_vol_type; /* * This is not the first logical eraseblock belonging to this @@ -200,28 +205,28 @@ static int validate_vid_hdr(const struct ubi_vid_hdr *vid_hdr, * to the data in previous logical eraseblock headers. */ - if (vol_id != sv->vol_id) { - dbg_err("inconsistent vol_id"); + if (vol_id != av->vol_id) { + ubi_err("inconsistent vol_id"); goto bad; } - if (sv->vol_type == UBI_STATIC_VOLUME) - sv_vol_type = UBI_VID_STATIC; + if (av->vol_type == UBI_STATIC_VOLUME) + av_vol_type = UBI_VID_STATIC; else - sv_vol_type = UBI_VID_DYNAMIC; + av_vol_type = UBI_VID_DYNAMIC; - if (vol_type != sv_vol_type) { - dbg_err("inconsistent vol_type"); + if (vol_type != av_vol_type) { + ubi_err("inconsistent vol_type"); goto bad; } - if (used_ebs != sv->used_ebs) { - dbg_err("inconsistent used_ebs"); + if (used_ebs != av->used_ebs) { + ubi_err("inconsistent used_ebs"); goto bad; } - if (data_pad != sv->data_pad) { - dbg_err("inconsistent data_pad"); + if (data_pad != av->data_pad) { + ubi_err("inconsistent data_pad"); goto bad; } } @@ -230,74 +235,74 @@ static int validate_vid_hdr(const struct ubi_vid_hdr *vid_hdr, bad: ubi_err("inconsistent VID header at PEB %d", pnum); - ubi_dbg_dump_vid_hdr(vid_hdr); - ubi_dbg_dump_sv(sv); + ubi_dump_vid_hdr(vid_hdr); + ubi_dump_av(av); return -EINVAL; } /** - * add_volume - add volume to the scanning information. - * @si: scanning information + * add_volume - add volume to the attaching information. + * @ai: attaching information * @vol_id: ID of the volume to add * @pnum: physical eraseblock number * @vid_hdr: volume identifier header * * If the volume corresponding to the @vid_hdr logical eraseblock is already - * present in the scanning information, this function does nothing. Otherwise - * it adds corresponding volume to the scanning information. Returns a pointer - * to the scanning volume object in case of success and a negative error code - * in case of failure. + * present in the attaching information, this function does nothing. Otherwise + * it adds corresponding volume to the attaching information. Returns a pointer + * to the allocated "av" object in case of success and a negative error code in + * case of failure. */ -static struct ubi_scan_volume *add_volume(struct ubi_scan_info *si, int vol_id, - int pnum, +static struct ubi_ainf_volume *add_volume(struct ubi_attach_info *ai, + int vol_id, int pnum, const struct ubi_vid_hdr *vid_hdr) { - struct ubi_scan_volume *sv; - struct rb_node **p = &si->volumes.rb_node, *parent = NULL; + struct ubi_ainf_volume *av; + struct rb_node **p = &ai->volumes.rb_node, *parent = NULL; 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) { parent = *p; - sv = rb_entry(parent, struct ubi_scan_volume, rb); + av = rb_entry(parent, struct ubi_ainf_volume, rb); - if (vol_id == sv->vol_id) - return sv; + if (vol_id == av->vol_id) + return av; |