Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'mtd/for-6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux

Pull MTD updates from Miquel Raynal:
"Core MTD changes:
- mtdchar: add MEMREAD ioctl
- Add ECC error accounting for each read request
- always initialize 'stats' in struct mtd_oob_ops
- Track maximum number of bitflips for each read request
- Fix repeated word in comment
- Move from strlcpy with unused retval to strscpy
- Fix a typo in a comment
- Add binding for U-Boot bootloader partitions

MTD device drivers changes:
- FTL: use container_of() rather than cast
- docg3:
- Use correct function names in comment blocks
- Check the return value of devm_ioremap() in the probe
- physmap-core: Fix NULL pointer dereferencing in
of_select_probe_type()
- parsers: add Broadcom's U-Boot parser

Raw NAND core changes:
- Replace of_gpio_named_count() by gpiod_count()
- Remove misguided comment of nand_get_device()
- bbt: Use the bitmap API to allocate bitmaps

Raw NAND controller drivers changes:
- Meson:
- Stop supporting legacy clocks
- Refine resource getting in probe
- Convert bindings to yaml
- Fix clock handling and update the bindings accordingly
- Fix bit map use in meson_nfc_ecc_correct()
- bcm47xx:
- Fix spelling typo in comment
- STM32 FMC2:
- Switch to using devm_fwnode_gpiod_get()
- Fix dma_map_sg error check
- Cadence:
- Remove an unneeded result variable
- Marvell:
- Fix error handle regarding dma_map_sg
- Orion:
- Use devm_clk_get_optional()
- Cafe:
- Use correct function name in comment block
- Atmel:
- Unmap streaming DMA mappings
- Arasan:
- Stop using 0 as NULL pointer
- GPMI:
- Fix typo 'the the' in comment
- BRCM:
- Add individual glue driver selection
- Move Kconfig to driver folder
- FSL: Fix none ECC mode
- Intel:
- Use devm_platform_ioremap_resource_byname()
- Remove unused clk_rate member from struct ebu_nand
- Remove unused nand_pa member from ebu_nand_cs
- Don't re-define NAND_DATA_IFACE_CHECK_ONLY
- Remove undocumented compatible string
- Fix compatible string in the bindings
- Read the chip-select line from the correct OF node
- Fix maximum chip select value in the bindings"

* tag 'mtd/for-6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux: (43 commits)
mtd: rawnand: meson: stop supporting legacy clocks
dt-bindings: nand: meson: convert txt to yaml
mtd: rawnand: meson: refine resource getting in probe
mtd: rawnand: meson: fix the clock
dt-bindings: nand: meson: fix meson nfc clock
mtd: rawnand: bcm47xx: fix spelling typo in comment
mtd: rawnand: stm32_fmc2: switch to using devm_fwnode_gpiod_get()
mtd: rawnand: cadence: Remove an unneeded result variable
mtd: rawnand: Replace of_gpio_named_count() by gpiod_count()
mtd: rawnand: marvell: Fix error handle regarding dma_map_sg
mtd: rawnand: stm32_fmc2: Fix dma_map_sg error check
mtd: rawnand: remove misguided comment of nand_get_device()
mtd: rawnand: orion: Use devm_clk_get_optional()
mtd: rawnand: cafe: Use correct function name in comment block
mtd: rawnand: atmel: Unmap streaming DMA mappings
mtd: rawnand: meson: fix bit map use in meson_nfc_ecc_correct()
mtd: rawnand: arasan: stop using 0 as NULL pointer
mtd: rawnand: gpmi: Fix typo 'the the' in comment
mtd: rawnand: brcmnand: Add individual glue driver selection
mtd: rawnand: brcmnand: Move Kconfig to driver folder
...

+694 -243
-60
Documentation/devicetree/bindings/mtd/amlogic,meson-nand.txt
··· 1 - Amlogic NAND Flash Controller (NFC) for GXBB/GXL/AXG family SoCs 2 - 3 - This file documents the properties in addition to those available in 4 - the MTD NAND bindings. 5 - 6 - Required properties: 7 - - compatible : contains one of: 8 - - "amlogic,meson-gxl-nfc" 9 - - "amlogic,meson-axg-nfc" 10 - - clocks : 11 - A list of phandle + clock-specifier pairs for the clocks listed 12 - in clock-names. 13 - 14 - - clock-names: Should contain the following: 15 - "core" - NFC module gate clock 16 - "device" - device clock from eMMC sub clock controller 17 - "rx" - rx clock phase 18 - "tx" - tx clock phase 19 - 20 - - amlogic,mmc-syscon : Required for NAND clocks, it's shared with SD/eMMC 21 - controller port C 22 - 23 - Optional children nodes: 24 - Children nodes represent the available nand chips. 25 - 26 - Other properties: 27 - see Documentation/devicetree/bindings/mtd/nand-controller.yaml for generic bindings. 28 - 29 - Example demonstrate on AXG SoC: 30 - 31 - sd_emmc_c_clkc: mmc@7000 { 32 - compatible = "amlogic,meson-axg-mmc-clkc", "syscon"; 33 - reg = <0x0 0x7000 0x0 0x800>; 34 - }; 35 - 36 - nand-controller@7800 { 37 - compatible = "amlogic,meson-axg-nfc"; 38 - reg = <0x0 0x7800 0x0 0x100>; 39 - #address-cells = <1>; 40 - #size-cells = <0>; 41 - interrupts = <GIC_SPI 34 IRQ_TYPE_EDGE_RISING>; 42 - 43 - clocks = <&clkc CLKID_SD_EMMC_C>, 44 - <&sd_emmc_c_clkc CLKID_MMC_DIV>, 45 - <&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>, 46 - <&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>; 47 - clock-names = "core", "device", "rx", "tx"; 48 - amlogic,mmc-syscon = <&sd_emmc_c_clkc>; 49 - 50 - pinctrl-names = "default"; 51 - pinctrl-0 = <&nand_pins>; 52 - 53 - nand@0 { 54 - reg = <0>; 55 - #address-cells = <1>; 56 - #size-cells = <1>; 57 - 58 - nand-on-flash-bbt; 59 - }; 60 - };
+93
Documentation/devicetree/bindings/mtd/amlogic,meson-nand.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/mtd/amlogic,meson-nand.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Amlogic NAND Flash Controller (NFC) for GXBB/GXL/AXG family SoCs 8 + 9 + allOf: 10 + - $ref: nand-controller.yaml 11 + 12 + maintainers: 13 + - liang.yang@amlogic.com 14 + 15 + properties: 16 + compatible: 17 + enum: 18 + - amlogic,meson-gxl-nfc 19 + - amlogic,meson-axg-nfc 20 + 21 + reg: 22 + maxItems: 2 23 + 24 + reg-names: 25 + items: 26 + - const: nfc 27 + - const: emmc 28 + 29 + interrupts: 30 + maxItems: 1 31 + 32 + clocks: 33 + minItems: 2 34 + 35 + clock-names: 36 + items: 37 + - const: core 38 + - const: device 39 + 40 + patternProperties: 41 + "^nand@[0-7]$": 42 + type: object 43 + properties: 44 + reg: 45 + minimum: 0 46 + maximum: 1 47 + 48 + nand-ecc-mode: 49 + const: hw 50 + 51 + nand-ecc-step-size: 52 + const: 1024 53 + 54 + nand-ecc-strength: 55 + enum: [8, 16, 24, 30, 40, 50, 60] 56 + description: | 57 + The ECC configurations that can be supported are as follows. 58 + meson-gxl-nfc 8, 16, 24, 30, 40, 50, 60 59 + meson-axg-nfc 8 60 + 61 + required: 62 + - compatible 63 + - reg 64 + - interrupts 65 + - clocks 66 + - clock-names 67 + 68 + unevaluatedProperties: false 69 + 70 + examples: 71 + - | 72 + #include <dt-bindings/clock/axg-clkc.h> 73 + #include <dt-bindings/interrupt-controller/arm-gic.h> 74 + nand-controller@ffe07800 { 75 + compatible = "amlogic,meson-axg-nfc"; 76 + reg = <0xffe07800 0x100>, <0xffe07000 0x800>; 77 + reg-names = "nfc", "emmc"; 78 + interrupts = <GIC_SPI 34 IRQ_TYPE_EDGE_RISING>; 79 + clocks = <&clkc CLKID_SD_EMMC_C>, <&clkc CLKID_FCLK_DIV2>; 80 + clock-names = "core", "device"; 81 + 82 + pinctrl-0 = <&nand_pins>; 83 + pinctrl-names = "default"; 84 + 85 + #address-cells = <1>; 86 + #size-cells = <0>; 87 + 88 + nand@0 { 89 + reg = <0>; 90 + }; 91 + }; 92 + 93 + ...
+4 -4
Documentation/devicetree/bindings/mtd/intel,lgm-nand.yaml Documentation/devicetree/bindings/mtd/intel,lgm-ebunand.yaml
··· 1 1 # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 2 %YAML 1.2 3 3 --- 4 - $id: http://devicetree.org/schemas/mtd/intel,lgm-nand.yaml# 4 + $id: http://devicetree.org/schemas/mtd/intel,lgm-ebunand.yaml# 5 5 $schema: http://devicetree.org/meta-schemas/core.yaml# 6 6 7 7 title: Intel LGM SoC NAND Controller Device Tree Bindings ··· 14 14 15 15 properties: 16 16 compatible: 17 - const: intel,lgm-nand 17 + const: intel,lgm-ebunand 18 18 19 19 reg: 20 20 maxItems: 6 ··· 51 51 properties: 52 52 reg: 53 53 minimum: 0 54 - maximum: 7 54 + maximum: 1 55 55 56 56 nand-ecc-mode: true 57 57 ··· 75 75 examples: 76 76 - | 77 77 nand-controller@e0f00000 { 78 - compatible = "intel,lgm-nand"; 78 + compatible = "intel,lgm-ebunand"; 79 79 reg = <0xe0f00000 0x100>, 80 80 <0xe1000000 0x300>, 81 81 <0xe1400000 0x8000>,
+49
Documentation/devicetree/bindings/mtd/partitions/u-boot.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/mtd/partitions/u-boot.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: U-Boot bootloader partition 8 + 9 + description: | 10 + U-Boot is a bootlodaer commonly used in embedded devices. It's almost always 11 + located on some kind of flash device. 12 + 13 + Device configuration is stored as a set of environment variables that are 14 + located in a (usually standalone) block of data. 15 + 16 + maintainers: 17 + - Rafał Miłecki <rafal@milecki.pl> 18 + 19 + allOf: 20 + - $ref: partition.yaml# 21 + 22 + properties: 23 + compatible: 24 + oneOf: 25 + - const: brcm,u-boot 26 + description: | 27 + Broadcom stores environment variables inside a U-Boot partition. They 28 + can be identified by a custom header with magic value. 29 + 30 + unevaluatedProperties: false 31 + 32 + examples: 33 + - | 34 + partitions { 35 + compatible = "fixed-partitions"; 36 + #address-cells = <1>; 37 + #size-cells = <1>; 38 + 39 + partition@0 { 40 + compatible = "brcm,u-boot"; 41 + reg = <0x0 0x100000>; 42 + label = "u-boot"; 43 + }; 44 + 45 + partition@100000 { 46 + reg = <0x100000 0x1ff00000>; 47 + label = "firmware"; 48 + }; 49 + };
+1 -1
drivers/mtd/devices/block2mtd.c
··· 461 461 the device (even kmalloc() fails). Deter that work to 462 462 block2mtd_setup2(). */ 463 463 464 - strlcpy(block2mtd_paramline, val, sizeof(block2mtd_paramline)); 464 + strscpy(block2mtd_paramline, val, sizeof(block2mtd_paramline)); 465 465 466 466 return 0; 467 467 #endif
+17 -4
drivers/mtd/devices/docg3.c
··· 300 300 } 301 301 302 302 /** 303 - * doc_set_data_mode - Sets the flash to normal or reliable data mode 303 + * doc_set_reliable_mode - Sets the flash to normal or reliable data mode 304 304 * @docg3: the device 305 305 * 306 306 * The reliable data mode is a bit slower than the fast mode, but less errors ··· 442 442 } 443 443 444 444 /** 445 - * doc_seek - Set both flash planes to the specified block, page for reading 445 + * doc_read_seek - Set both flash planes to the specified block, page for reading 446 446 * @docg3: the device 447 447 * @block0: the first plane block index 448 448 * @block1: the second plane block index ··· 871 871 u8 *buf = ops->datbuf; 872 872 size_t len, ooblen, nbdata, nboob; 873 873 u8 hwecc[DOC_ECC_BCH_SIZE], eccconf1; 874 + struct mtd_ecc_stats old_stats; 874 875 int max_bitflips = 0; 875 876 876 877 if (buf) ··· 896 895 ret = 0; 897 896 skip = from % DOC_LAYOUT_PAGE_SIZE; 898 897 mutex_lock(&docg3->cascade->lock); 898 + old_stats = mtd->ecc_stats; 899 899 while (ret >= 0 && (len > 0 || ooblen > 0)) { 900 900 calc_block_sector(from - skip, &block0, &block1, &page, &ofs, 901 901 docg3->reliable); ··· 968 966 } 969 967 970 968 out: 969 + if (ops->stats) { 970 + ops->stats->uncorrectable_errors += 971 + mtd->ecc_stats.failed - old_stats.failed; 972 + ops->stats->corrected_bitflips += 973 + mtd->ecc_stats.corrected - old_stats.corrected; 974 + } 971 975 mutex_unlock(&docg3->cascade->lock); 972 976 return ret; 973 977 err_in_read: ··· 1959 1951 } 1960 1952 1961 1953 /** 1962 - * doc_probe - Probe the IO space for a DiskOnChip G3 chip 1954 + * docg3_probe - Probe the IO space for a DiskOnChip G3 chip 1963 1955 * @pdev: platform device 1964 1956 * 1965 1957 * Probes for a G3 chip at the specified IO space in the platform data ··· 1982 1974 dev_err(dev, "No I/O memory resource defined\n"); 1983 1975 return ret; 1984 1976 } 1985 - base = devm_ioremap(dev, ress->start, DOC_IOSPACE_SIZE); 1986 1977 1987 1978 ret = -ENOMEM; 1979 + base = devm_ioremap(dev, ress->start, DOC_IOSPACE_SIZE); 1980 + if (!base) { 1981 + dev_err(dev, "devm_ioremap dev failed\n"); 1982 + return ret; 1983 + } 1984 + 1988 1985 cascade = devm_kcalloc(dev, DOC_MAX_NBFLOORS, sizeof(*cascade), 1989 1986 GFP_KERNEL); 1990 1987 if (!cascade)
+2 -2
drivers/mtd/ftl.c
··· 941 941 942 942 static int ftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo) 943 943 { 944 - partition_t *part = (void *)dev; 944 + partition_t *part = container_of(dev, struct partition_t, mbd); 945 945 u_long sect; 946 946 947 947 /* Sort of arbitrary: round size down to 4KiB boundary */ ··· 969 969 static int ftl_discardsect(struct mtd_blktrans_dev *dev, 970 970 unsigned long sector, unsigned nr_sects) 971 971 { 972 - partition_t *part = (void *)dev; 972 + partition_t *part = container_of(dev, struct partition_t, mbd); 973 973 uint32_t bsize = 1 << part->header.EraseUnitSize; 974 974 975 975 pr_debug("FTL erase sector %ld for %d sectors\n",
+3 -3
drivers/mtd/inftlcore.c
··· 136 136 int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len, 137 137 size_t *retlen, uint8_t *buf) 138 138 { 139 - struct mtd_oob_ops ops; 139 + struct mtd_oob_ops ops = { }; 140 140 int res; 141 141 142 142 ops.mode = MTD_OPS_PLACE_OOB; ··· 156 156 int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len, 157 157 size_t *retlen, uint8_t *buf) 158 158 { 159 - struct mtd_oob_ops ops; 159 + struct mtd_oob_ops ops = { }; 160 160 int res; 161 161 162 162 ops.mode = MTD_OPS_PLACE_OOB; ··· 176 176 static int inftl_write(struct mtd_info *mtd, loff_t offs, size_t len, 177 177 size_t *retlen, uint8_t *buf, uint8_t *oob) 178 178 { 179 - struct mtd_oob_ops ops; 179 + struct mtd_oob_ops ops = { }; 180 180 int res; 181 181 182 182 ops.mode = MTD_OPS_PLACE_OOB;
+3
drivers/mtd/maps/physmap-core.c
··· 300 300 const char *probe_type; 301 301 302 302 match = of_match_device(of_flash_match, &dev->dev); 303 + if (!match) 304 + return NULL; 305 + 303 306 probe_type = match->data; 304 307 if (probe_type) 305 308 return probe_type;
+139
drivers/mtd/mtdchar.c
··· 688 688 return ret; 689 689 } 690 690 691 + static int mtdchar_read_ioctl(struct mtd_info *mtd, 692 + struct mtd_read_req __user *argp) 693 + { 694 + struct mtd_info *master = mtd_get_master(mtd); 695 + struct mtd_read_req req; 696 + void __user *usr_data, *usr_oob; 697 + uint8_t *datbuf = NULL, *oobbuf = NULL; 698 + size_t datbuf_len, oobbuf_len; 699 + size_t orig_len, orig_ooblen; 700 + int ret = 0; 701 + 702 + if (copy_from_user(&req, argp, sizeof(req))) 703 + return -EFAULT; 704 + 705 + orig_len = req.len; 706 + orig_ooblen = req.ooblen; 707 + 708 + usr_data = (void __user *)(uintptr_t)req.usr_data; 709 + usr_oob = (void __user *)(uintptr_t)req.usr_oob; 710 + 711 + if (!master->_read_oob) 712 + return -EOPNOTSUPP; 713 + 714 + if (!usr_data) 715 + req.len = 0; 716 + 717 + if (!usr_oob) 718 + req.ooblen = 0; 719 + 720 + req.ecc_stats.uncorrectable_errors = 0; 721 + req.ecc_stats.corrected_bitflips = 0; 722 + req.ecc_stats.max_bitflips = 0; 723 + 724 + req.len &= 0xffffffff; 725 + req.ooblen &= 0xffffffff; 726 + 727 + if (req.start + req.len > mtd->size) { 728 + ret = -EINVAL; 729 + goto out; 730 + } 731 + 732 + datbuf_len = min_t(size_t, req.len, mtd->erasesize); 733 + if (datbuf_len > 0) { 734 + datbuf = kvmalloc(datbuf_len, GFP_KERNEL); 735 + if (!datbuf) { 736 + ret = -ENOMEM; 737 + goto out; 738 + } 739 + } 740 + 741 + oobbuf_len = min_t(size_t, req.ooblen, mtd->erasesize); 742 + if (oobbuf_len > 0) { 743 + oobbuf = kvmalloc(oobbuf_len, GFP_KERNEL); 744 + if (!oobbuf) { 745 + ret = -ENOMEM; 746 + goto out; 747 + } 748 + } 749 + 750 + while (req.len > 0 || (!usr_data && req.ooblen > 0)) { 751 + struct mtd_req_stats stats; 752 + struct mtd_oob_ops ops = { 753 + .mode = req.mode, 754 + .len = min_t(size_t, req.len, datbuf_len), 755 + .ooblen = min_t(size_t, req.ooblen, oobbuf_len), 756 + .datbuf = datbuf, 757 + .oobbuf = oobbuf, 758 + .stats = &stats, 759 + }; 760 + 761 + /* 762 + * Shorten non-page-aligned, eraseblock-sized reads so that the 763 + * read ends on an eraseblock boundary. This is necessary in 764 + * order to prevent OOB data for some pages from being 765 + * duplicated in the output of non-page-aligned reads requiring 766 + * multiple mtd_read_oob() calls to be completed. 767 + */ 768 + if (ops.len == mtd->erasesize) 769 + ops.len -= mtd_mod_by_ws(req.start + ops.len, mtd); 770 + 771 + ret = mtd_read_oob(mtd, (loff_t)req.start, &ops); 772 + 773 + req.ecc_stats.uncorrectable_errors += 774 + stats.uncorrectable_errors; 775 + req.ecc_stats.corrected_bitflips += stats.corrected_bitflips; 776 + req.ecc_stats.max_bitflips = 777 + max(req.ecc_stats.max_bitflips, stats.max_bitflips); 778 + 779 + if (ret && !mtd_is_bitflip_or_eccerr(ret)) 780 + break; 781 + 782 + if (copy_to_user(usr_data, ops.datbuf, ops.retlen) || 783 + copy_to_user(usr_oob, ops.oobbuf, ops.oobretlen)) { 784 + ret = -EFAULT; 785 + break; 786 + } 787 + 788 + req.start += ops.retlen; 789 + req.len -= ops.retlen; 790 + usr_data += ops.retlen; 791 + 792 + req.ooblen -= ops.oobretlen; 793 + usr_oob += ops.oobretlen; 794 + } 795 + 796 + /* 797 + * As multiple iterations of the above loop (and therefore multiple 798 + * mtd_read_oob() calls) may be necessary to complete the read request, 799 + * adjust the final return code to ensure it accounts for all detected 800 + * ECC errors. 801 + */ 802 + if (!ret || mtd_is_bitflip(ret)) { 803 + if (req.ecc_stats.uncorrectable_errors > 0) 804 + ret = -EBADMSG; 805 + else if (req.ecc_stats.corrected_bitflips > 0) 806 + ret = -EUCLEAN; 807 + } 808 + 809 + out: 810 + req.len = orig_len - req.len; 811 + req.ooblen = orig_ooblen - req.ooblen; 812 + 813 + if (copy_to_user(argp, &req, sizeof(req))) 814 + ret = -EFAULT; 815 + 816 + kvfree(datbuf); 817 + kvfree(oobbuf); 818 + 819 + return ret; 820 + } 821 + 691 822 static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg) 692 823 { 693 824 struct mtd_file_info *mfi = file->private_data; ··· 841 710 case MEMGETINFO: 842 711 case MEMREADOOB: 843 712 case MEMREADOOB64: 713 + case MEMREAD: 844 714 case MEMISLOCKED: 845 715 case MEMGETOOBSEL: 846 716 case MEMGETBADBLOCK: ··· 1013 881 { 1014 882 ret = mtdchar_write_ioctl(mtd, 1015 883 (struct mtd_write_req __user *)arg); 884 + break; 885 + } 886 + 887 + case MEMREAD: 888 + { 889 + ret = mtdchar_read_ioctl(mtd, 890 + (struct mtd_read_req __user *)arg); 1016 891 break; 1017 892 } 1018 893
+1 -1
drivers/mtd/mtdconcat.c
··· 836 836 837 837 /* 838 838 * walk the map of the new device once more and fill in 839 - * in erase region info: 839 + * erase region info: 840 840 */ 841 841 curr_erasesize = subdev[0]->erasesize; 842 842 begin = position = 0;
+5
drivers/mtd/mtdcore.c
··· 1624 1624 if (!master->_read_oob && (!master->_read || ops->oobbuf)) 1625 1625 return -EOPNOTSUPP; 1626 1626 1627 + if (ops->stats) 1628 + memset(ops->stats, 0, sizeof(*ops->stats)); 1629 + 1627 1630 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) 1628 1631 ret_code = mtd_io_emulated_slc(mtd, from, true, ops); 1629 1632 else ··· 1644 1641 return ret_code; 1645 1642 if (mtd->ecc_strength == 0) 1646 1643 return 0; /* device lacks ecc */ 1644 + if (ops->stats) 1645 + ops->stats->max_bitflips = ret_code; 1647 1646 return ret_code >= mtd->bitflip_threshold ? -EUCLEAN : 0; 1648 1647 } 1649 1648 EXPORT_SYMBOL_GPL(mtd_read_oob);
+1 -1
drivers/mtd/mtdpstore.c
··· 401 401 /* 402 402 * kmsg_size must be aligned to 4096 Bytes, which is limited by 403 403 * psblk. The default value of kmsg_size is 64KB. If kmsg_size 404 - * is larger than erasesize, some errors will occur since mtdpsotre 404 + * is larger than erasesize, some errors will occur since mtdpstore 405 405 * is designed on it. 406 406 */ 407 407 if (mtd->erasesize < info->kmsg_size) {
+3 -3
drivers/mtd/mtdswap.c
··· 323 323 struct mtdswap_oobdata *data, *data2; 324 324 int ret; 325 325 loff_t offset; 326 - struct mtd_oob_ops ops; 326 + struct mtd_oob_ops ops = { }; 327 327 328 328 offset = mtdswap_eb_offset(d, eb); 329 329 ··· 370 370 struct mtdswap_oobdata n; 371 371 int ret; 372 372 loff_t offset; 373 - struct mtd_oob_ops ops; 373 + struct mtd_oob_ops ops = { }; 374 374 375 375 ops.ooboffs = 0; 376 376 ops.oobbuf = (uint8_t *)&n; ··· 878 878 loff_t base, pos; 879 879 unsigned int *p1 = (unsigned int *)d->page_buf; 880 880 unsigned char *p2 = (unsigned char *)d->oob_buf; 881 - struct mtd_oob_ops ops; 881 + struct mtd_oob_ops ops = { }; 882 882 int ret; 883 883 884 884 ops.mode = MTD_OPS_AUTO_OOB;
+2 -5
drivers/mtd/nand/bbt.c
··· 24 24 { 25 25 unsigned int bits_per_block = fls(NAND_BBT_BLOCK_NUM_STATUS); 26 26 unsigned int nblocks = nanddev_neraseblocks(nand); 27 - unsigned int nwords = DIV_ROUND_UP(nblocks * bits_per_block, 28 - BITS_PER_LONG); 29 27 30 - nand->bbt.cache = kcalloc(nwords, sizeof(*nand->bbt.cache), 31 - GFP_KERNEL); 28 + nand->bbt.cache = bitmap_zalloc(nblocks * bits_per_block, GFP_KERNEL); 32 29 if (!nand->bbt.cache) 33 30 return -ENOMEM; 34 31 ··· 41 44 */ 42 45 void nanddev_bbt_cleanup(struct nand_device *nand) 43 46 { 44 - kfree(nand->bbt.cache); 47 + bitmap_free(nand->bbt.cache); 45 48 } 46 49 EXPORT_SYMBOL_GPL(nanddev_bbt_cleanup); 47 50
+14 -2
drivers/mtd/nand/onenand/onenand_base.c
··· 1440 1440 struct mtd_oob_ops *ops) 1441 1441 { 1442 1442 struct onenand_chip *this = mtd->priv; 1443 + struct mtd_ecc_stats old_stats; 1443 1444 int ret; 1444 1445 1445 1446 switch (ops->mode) { ··· 1454 1453 } 1455 1454 1456 1455 onenand_get_device(mtd, FL_READING); 1456 + 1457 + old_stats = mtd->ecc_stats; 1458 + 1457 1459 if (ops->datbuf) 1458 1460 ret = ONENAND_IS_4KB_PAGE(this) ? 1459 1461 onenand_mlc_read_ops_nolock(mtd, from, ops) : 1460 1462 onenand_read_ops_nolock(mtd, from, ops); 1461 1463 else 1462 1464 ret = onenand_read_oob_nolock(mtd, from, ops); 1465 + 1466 + if (ops->stats) { 1467 + ops->stats->uncorrectable_errors += 1468 + mtd->ecc_stats.failed - old_stats.failed; 1469 + ops->stats->corrected_bitflips += 1470 + mtd->ecc_stats.corrected - old_stats.corrected; 1471 + } 1472 + 1463 1473 onenand_release_device(mtd); 1464 1474 1465 1475 return ret; ··· 2947 2935 struct onenand_chip *this = mtd->priv; 2948 2936 unsigned char *pbuf = buf; 2949 2937 int ret; 2950 - struct mtd_oob_ops ops; 2938 + struct mtd_oob_ops ops = { }; 2951 2939 2952 2940 /* Force buffer page aligned */ 2953 2941 if (len < mtd->writesize) { ··· 2989 2977 size_t *retlen, u_char *buf) 2990 2978 { 2991 2979 struct onenand_chip *this = mtd->priv; 2992 - struct mtd_oob_ops ops; 2980 + struct mtd_oob_ops ops = { }; 2993 2981 int ret; 2994 2982 2995 2983 if (FLEXONENAND(this)) {
+1 -1
drivers/mtd/nand/onenand/onenand_bbt.c
··· 61 61 int startblock; 62 62 loff_t from; 63 63 size_t readlen; 64 - struct mtd_oob_ops ops; 64 + struct mtd_oob_ops ops = { }; 65 65 int rgn; 66 66 67 67 printk(KERN_INFO "Scanning device for bad blocks\n");
+2 -22
drivers/mtd/nand/raw/Kconfig
··· 200 200 Support for NAND flash connected to a Toshiba Mobile IO 201 201 Controller in some PDAs, including the Sharp SL6000x. 202 202 203 - config MTD_NAND_BRCMNAND 204 - tristate "Broadcom STB NAND controller" 205 - depends on ARM || ARM64 || MIPS || COMPILE_TEST 206 - depends on HAS_IOMEM 207 - help 208 - Enables the Broadcom NAND controller driver. The controller was 209 - originally designed for Set-Top Box but is used on various BCM7xxx, 210 - BCM3xxx, BCM63xxx, iProc/Cygnus and more. 211 - 212 - if MTD_NAND_BRCMNAND 213 - 214 - config MTD_NAND_BRCMNAND_BCMA 215 - tristate "Broadcom BCMA NAND controller" 216 - depends on BCMA_NFLASH 217 - depends on BCMA 218 - help 219 - Enables the BRCMNAND controller over BCMA on BCM47186/BCM5358 SoCs. 220 - The glue driver will take care of performing the low-level I/O 221 - operations to interface the BRCMNAND controller over the BCMA bus. 222 - 223 - endif # MTD_NAND_BRCMNAND 203 + source "drivers/mtd/nand/raw/brcmnand/Kconfig" 224 204 225 205 config MTD_NAND_BCM47XXNFLASH 226 206 tristate "BCM4706 BCMA NAND controller" ··· 390 410 391 411 config MTD_NAND_MESON 392 412 tristate "Support for NAND controller on Amlogic's Meson SoCs" 393 - depends on ARCH_MESON || COMPILE_TEST 413 + depends on COMMON_CLK && (ARCH_MESON || COMPILE_TEST) 394 414 select MFD_SYSCON 395 415 help 396 416 Enables support for NAND controller on Amlogic's Meson SoCs.
+1 -1
drivers/mtd/nand/raw/arasan-nand-controller.c
··· 915 915 if (instr->ctx.data.len > ANFC_MAX_CHUNK_SIZE) 916 916 return -ENOTSUPP; 917 917 918 - if (anfc_pkt_len_config(instr->ctx.data.len, 0, 0)) 918 + if (anfc_pkt_len_config(instr->ctx.data.len, NULL, NULL)) 919 919 return -ENOTSUPP; 920 920 921 921 break;
+1
drivers/mtd/nand/raw/atmel/nand-controller.c
··· 405 405 406 406 dma_async_issue_pending(nc->dmac); 407 407 wait_for_completion(&finished); 408 + dma_unmap_single(nc->dev, buf_dma, len, dir); 408 409 409 410 return 0; 410 411
+1 -1
drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c
··· 14 14 #include <linux/bcma/bcma.h> 15 15 16 16 /* Broadcom uses 1'000'000 but it seems to be too many. Tests on WNDR4500 has 17 - * shown ~1000 retries as maxiumum. */ 17 + * shown ~1000 retries as maximum. */ 18 18 #define NFLASH_READY_RETRIES 10000 19 19 20 20 #define NFLASH_SECTOR_SIZE 512
+49
drivers/mtd/nand/raw/brcmnand/Kconfig
··· 1 + config MTD_NAND_BRCMNAND 2 + tristate "Broadcom STB NAND controller" 3 + depends on ARM || ARM64 || MIPS || COMPILE_TEST 4 + depends on HAS_IOMEM 5 + help 6 + Enables the Broadcom NAND controller driver. The controller was 7 + originally designed for Set-Top Box but is used on various BCM7xxx, 8 + BCM3xxx, BCM63xxx, iProc/Cygnus and more. 9 + 10 + if MTD_NAND_BRCMNAND 11 + 12 + config MTD_NAND_BRCMNAND_BCM63XX 13 + tristate "Broadcom BCM63xx NAND controller glue" 14 + default BCM63XX 15 + help 16 + Enables the BRCMNAND glue driver to register the NAND controller 17 + on Broadcom BCM63xx MIPS-based DSL platforms. 18 + 19 + config MTD_NAND_BRCMNAND_BCMA 20 + tristate "Broadcom BCMA NAND controller" 21 + depends on BCMA_NFLASH 22 + depends on BCMA 23 + help 24 + Enables the BRCMNAND controller over BCMA on BCM47186/BCM5358 SoCs. 25 + The glue driver will take care of performing the low-level I/O 26 + operations to interface the BRCMNAND controller over the BCMA bus. 27 + 28 + config MTD_NAND_BRCMNAND_BCMBCA 29 + tristate "Broadcom BCMBCA NAND controller glue" 30 + default ARCH_BCMBCA 31 + help 32 + Enables the BRCMNAND glue driver to register the NAND controller 33 + on Broadcom BCA platforms. 34 + 35 + config MTD_NAND_BRCMNAND_BRCMSTB 36 + tristate "Broadcom STB Nand controller glue" 37 + default ARCH_BRCMSTB 38 + help 39 + Enables the BRCMNAND glue driver to register the NAND controller 40 + on Broadcom STB platforms. 41 + 42 + config MTD_NAND_BRCMNAND_IPROC 43 + tristate "Broadcom iProc NAND controller glue" 44 + default ARCH_BCM_IPROC 45 + help 46 + Enables the BRCMNAND controller glue driver to register the NAND 47 + controller on Broadcom iProc platforms. 48 + 49 + endif # MTD_NAND_BRCMNAND
+4 -4
drivers/mtd/nand/raw/brcmnand/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 # link order matters; don't link the more generic brcmstb_nand.o before the 3 3 # more specific iproc_nand.o, for instance 4 - obj-$(CONFIG_MTD_NAND_BRCMNAND) += iproc_nand.o 5 - obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63138_nand.o 6 - obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm6368_nand.o 7 - obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmstb_nand.o 4 + obj-$(CONFIG_MTD_NAND_BRCMNAND_IPROC) += iproc_nand.o 5 + obj-$(CONFIG_MTD_NAND_BRCMNAND_BCMBCA) += bcm63138_nand.o 6 + obj-$(CONFIG_MTD_NAND_BRCMNAND_BCM63XX) += bcm6368_nand.o 7 + obj-$(CONFIG_MTD_NAND_BRCMNAND_BRCMSTB) += brcmstb_nand.o 8 8 obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand.o 9 9 10 10 obj-$(CONFIG_MTD_NAND_BRCMNAND_BCMA) += bcma_nand.o
+1 -4
drivers/mtd/nand/raw/cadence-nand-controller.c
··· 1979 1979 bool force_8bit) 1980 1980 { 1981 1981 struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller); 1982 - int status; 1983 1982 1984 1983 /* 1985 1984 * Callers of this function do not verify if the NAND is using a 16-bit ··· 1989 1990 if (!(chip->options & NAND_BUSWIDTH_16)) 1990 1991 return 0; 1991 1992 1992 - status = cadence_nand_set_access_width16(cdns_ctrl, !force_8bit); 1993 - 1994 - return status; 1993 + return cadence_nand_set_access_width16(cdns_ctrl, !force_8bit); 1995 1994 } 1996 1995 1997 1996 static int cadence_nand_cmd_opcode(struct nand_chip *chip,
+1 -1
drivers/mtd/nand/raw/cafe_nand.c
··· 358 358 return nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize); 359 359 } 360 360 /** 361 - * cafe_nand_read_page_syndrome - [REPLACEABLE] hardware ecc syndrome based page read 361 + * cafe_nand_read_page - [REPLACEABLE] hardware ecc syndrome based page read 362 362 * @chip: nand chip info structure 363 363 * @buf: buffer to store read data 364 364 * @oob_required: caller expects OOB data read to chip->oob_poi
+16 -12
drivers/mtd/nand/raw/fsl_elbc_nand.c
··· 726 726 struct fsl_lbc_regs __iomem *lbc = ctrl->regs; 727 727 unsigned int al; 728 728 729 - switch (chip->ecc.engine_type) { 730 729 /* 731 730 * if ECC was not chosen in DT, decide whether to use HW or SW ECC from 732 731 * CS Base Register 733 732 */ 734 - case NAND_ECC_ENGINE_TYPE_NONE: 733 + if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_INVALID) { 735 734 /* If CS Base Register selects full hardware ECC then use it */ 736 735 if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) == 737 736 BR_DECC_CHK_GEN) { 738 - chip->ecc.read_page = fsl_elbc_read_page; 739 - chip->ecc.write_page = fsl_elbc_write_page; 740 - chip->ecc.write_subpage = fsl_elbc_write_subpage; 741 - 742 737 chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; 743 - mtd_set_ooblayout(mtd, &fsl_elbc_ooblayout_ops); 744 - chip->ecc.size = 512; 745 - chip->ecc.bytes = 3; 746 - chip->ecc.strength = 1; 747 738 } else { 748 739 /* otherwise fall back to default software ECC */ 749 740 chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; 750 741 chip->ecc.algo = NAND_ECC_ALGO_HAMMING; 751 742 } 743 + } 744 + 745 + switch (chip->ecc.engine_type) { 746 + /* if HW ECC was chosen, setup ecc and oob layout */ 747 + case NAND_ECC_ENGINE_TYPE_ON_HOST: 748 + chip->ecc.read_page = fsl_elbc_read_page; 749 + chip->ecc.write_page = fsl_elbc_write_page; 750 + chip->ecc.write_subpage = fsl_elbc_write_subpage; 751 + mtd_set_ooblayout(mtd, &fsl_elbc_ooblayout_ops); 752 + chip->ecc.size = 512; 753 + chip->ecc.bytes = 3; 754 + chip->ecc.strength = 1; 752 755 break; 753 756 754 - /* if SW ECC was chosen in DT, we do not need to set anything here */ 757 + /* if none or SW ECC was chosen, we do not need to set anything here */ 758 + case NAND_ECC_ENGINE_TYPE_NONE: 755 759 case NAND_ECC_ENGINE_TYPE_SOFT: 760 + case NAND_ECC_ENGINE_TYPE_ON_DIE: 756 761 break; 757 762 758 - /* should we also implement *_ECC_ENGINE_CONTROLLER to do as above? */ 759 763 default: 760 764 return -EINVAL; 761 765 }
+1 -1
drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
··· 1361 1361 /* 1362 1362 * Handles block mark swapping. 1363 1363 * It can be called in swapping the block mark, or swapping it back, 1364 - * because the the operations are the same. 1364 + * because the operations are the same. 1365 1365 */ 1366 1366 static void block_mark_swapping(struct gpmi_nand_data *this, 1367 1367 void *payload, void *auxiliary)
+13 -15
drivers/mtd/nand/raw/intel-nand-controller.c
··· 16 16 #include <linux/mtd/rawnand.h> 17 17 #include <linux/mtd/nand.h> 18 18 19 + #include <linux/of.h> 19 20 #include <linux/platform_device.h> 20 21 #include <linux/sched.h> 21 22 #include <linux/slab.h> ··· 100 99 101 100 #define HSNAND_ECC_OFFSET 0x008 102 101 103 - #define NAND_DATA_IFACE_CHECK_ONLY -1 104 - 105 102 #define MAX_CS 2 106 103 107 104 #define USEC_PER_SEC 1000000L 108 105 109 106 struct ebu_nand_cs { 110 107 void __iomem *chipaddr; 111 - dma_addr_t nand_pa; 112 108 u32 addr_sel; 113 109 }; 114 110 ··· 118 120 struct dma_chan *dma_tx; 119 121 struct dma_chan *dma_rx; 120 122 struct completion dma_access_complete; 121 - unsigned long clk_rate; 122 123 struct clk *clk; 123 124 u32 nd_para0; 124 125 u8 cs_num; ··· 577 580 { 578 581 struct device *dev = &pdev->dev; 579 582 struct ebu_nand_controller *ebu_host; 583 + struct device_node *chip_np; 580 584 struct nand_chip *nand; 581 585 struct mtd_info *mtd; 582 586 struct resource *res; ··· 592 594 ebu_host->dev = dev; 593 595 nand_controller_init(&ebu_host->controller); 594 596 595 - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ebunand"); 596 - ebu_host->ebu = devm_ioremap_resource(&pdev->dev, res); 597 + ebu_host->ebu = devm_platform_ioremap_resource_byname(pdev, "ebunand"); 597 598 if (IS_ERR(ebu_host->ebu)) 598 599 return PTR_ERR(ebu_host->ebu); 599 600 600 - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hsnand"); 601 - ebu_host->hsnand = devm_ioremap_resource(&pdev->dev, res); 601 + ebu_host->hsnand = devm_platform_ioremap_resource_byname(pdev, "hsnand"); 602 602 if (IS_ERR(ebu_host->hsnand)) 603 603 return PTR_ERR(ebu_host->hsnand); 604 604 605 - ret = device_property_read_u32(dev, "reg", &cs); 605 + chip_np = of_get_next_child(dev->of_node, NULL); 606 + if (!chip_np) 607 + return dev_err_probe(dev, -EINVAL, 608 + "Could not find child node for the NAND chip\n"); 609 + 610 + ret = of_property_read_u32(chip_np, "reg", &cs); 606 611 if (ret) { 607 612 dev_err(dev, "failed to get chip select: %d\n", ret); 608 613 return ret; ··· 618 617 ebu_host->cs_num = cs; 619 618 620 619 resname = devm_kasprintf(dev, GFP_KERNEL, "nand_cs%d", cs); 621 - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, resname); 622 - ebu_host->cs[cs].chipaddr = devm_ioremap_resource(dev, res); 620 + ebu_host->cs[cs].chipaddr = devm_platform_ioremap_resource_byname(pdev, 621 + resname); 623 622 if (IS_ERR(ebu_host->cs[cs].chipaddr)) 624 623 return PTR_ERR(ebu_host->cs[cs].chipaddr); 625 - ebu_host->cs[cs].nand_pa = res->start; 626 624 627 625 ebu_host->clk = devm_clk_get(dev, NULL); 628 626 if (IS_ERR(ebu_host->clk)) ··· 633 633 dev_err(dev, "failed to enable clock: %d\n", ret); 634 634 return ret; 635 635 } 636 - ebu_host->clk_rate = clk_get_rate(ebu_host->clk); 637 636 638 637 ebu_host->dma_tx = dma_request_chan(dev, "tx"); 639 638 if (IS_ERR(ebu_host->dma_tx)) { ··· 659 660 writel(ebu_host->cs[cs].addr_sel | EBU_ADDR_MASK(5) | EBU_ADDR_SEL_REGEN, 660 661 ebu_host->ebu + EBU_ADDR_SEL(cs)); 661 662 662 - nand_set_flash_node(&ebu_host->chip, dev->of_node); 663 + nand_set_flash_node(&ebu_host->chip, chip_np); 663 664 664 665 mtd = nand_to_mtd(&ebu_host->chip); 665 666 if (!mtd->name) { ··· 715 716 } 716 717 717 718 static const struct of_device_id ebu_nand_match[] = { 718 - { .compatible = "intel,nand-controller" }, 719 719 { .compatible = "intel,lgm-ebunand" }, 720 720 {} 721 721 };
+7 -1
drivers/mtd/nand/raw/marvell_nand.c
··· 865 865 marvell_nfc_enable_dma(nfc); 866 866 /* Prepare the DMA transfer */ 867 867 sg_init_one(&sg, nfc->dma_buf, dma_len); 868 - dma_map_sg(nfc->dma_chan->device->dev, &sg, 1, direction); 868 + ret = dma_map_sg(nfc->dma_chan->device->dev, &sg, 1, direction); 869 + if (!ret) { 870 + dev_err(nfc->dev, "Could not map DMA S/G list\n"); 871 + return -ENXIO; 872 + } 873 + 869 874 tx = dmaengine_prep_slave_sg(nfc->dma_chan, &sg, 1, 870 875 direction == DMA_FROM_DEVICE ? 871 876 DMA_DEV_TO_MEM : DMA_MEM_TO_DEV, 872 877 DMA_PREP_INTERRUPT); 873 878 if (!tx) { 874 879 dev_err(nfc->dev, "Could not prepare DMA S/G list\n"); 880 + dma_unmap_sg(nfc->dma_chan->device->dev, &sg, 1, direction); 875 881 return -ENXIO; 876 882 } 877 883
+43 -45
drivers/mtd/nand/raw/meson_nand.c
··· 10 10 #include <linux/dma-mapping.h> 11 11 #include <linux/interrupt.h> 12 12 #include <linux/clk.h> 13 + #include <linux/clk-provider.h> 13 14 #include <linux/mtd/rawnand.h> 14 15 #include <linux/mtd/mtd.h> 15 16 #include <linux/mfd/syscon.h> ··· 56 55 #define NFC_REG_VER 0x38 57 56 58 57 #define NFC_RB_IRQ_EN BIT(21) 58 + 59 + #define CLK_DIV_SHIFT 0 60 + #define CLK_DIV_WIDTH 6 59 61 60 62 #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages) \ 61 63 ( \ ··· 155 151 struct nand_controller controller; 156 152 struct clk *core_clk; 157 153 struct clk *device_clk; 158 - struct clk *phase_tx; 159 - struct clk *phase_rx; 154 + struct clk *nand_clk; 155 + struct clk_divider nand_divider; 160 156 161 157 unsigned long clk_rate; 162 158 u32 bus_timing; 163 159 164 160 struct device *dev; 165 161 void __iomem *reg_base; 166 - struct regmap *reg_clk; 162 + void __iomem *reg_clk; 167 163 struct completion completion; 168 164 struct list_head chips; 169 165 const struct meson_nfc_data *data; ··· 239 235 nfc->timing.tbers_max = meson_chip->tbers_max; 240 236 241 237 if (nfc->clk_rate != meson_chip->clk_rate) { 242 - ret = clk_set_rate(nfc->device_clk, meson_chip->clk_rate); 238 + ret = clk_set_rate(nfc->nand_clk, meson_chip->clk_rate); 243 239 if (ret) { 244 240 dev_err(nfc->dev, "failed to set clock rate\n"); 245 241 return; ··· 458 454 if (ECC_ERR_CNT(*info) != ECC_UNCORRECTABLE) { 459 455 mtd->ecc_stats.corrected += ECC_ERR_CNT(*info); 460 456 *bitflips = max_t(u32, *bitflips, ECC_ERR_CNT(*info)); 461 - *correct_bitmap |= 1 >> i; 457 + *correct_bitmap |= BIT_ULL(i); 462 458 continue; 463 459 } 464 460 if ((nand->options & NAND_NEED_SCRAMBLING) && ··· 804 800 u8 *data = buf + i * ecc->size; 805 801 u8 *oob = nand->oob_poi + i * (ecc->bytes + 2); 806 802 807 - if (correct_bitmap & (1 << i)) 803 + if (correct_bitmap & BIT_ULL(i)) 808 804 continue; 809 805 ret = nand_check_erased_ecc_chunk(data, ecc->size, 810 806 oob, ecc->bytes + 2, ··· 991 987 992 988 static int meson_nfc_clk_init(struct meson_nfc *nfc) 993 989 { 990 + struct clk_parent_data nfc_divider_parent_data[1]; 991 + struct clk_init_data init = {0}; 994 992 int ret; 995 993 996 994 /* request core clock */ ··· 1008 1002 return PTR_ERR(nfc->device_clk); 1009 1003 } 1010 1004 1011 - nfc->phase_tx = devm_clk_get(nfc->dev, "tx"); 1012 - if (IS_ERR(nfc->phase_tx)) { 1013 - dev_err(nfc->dev, "failed to get TX clk\n"); 1014 - return PTR_ERR(nfc->phase_tx); 1015 - } 1005 + init.name = devm_kasprintf(nfc->dev, 1006 + GFP_KERNEL, "%s#div", 1007 + dev_name(nfc->dev)); 1008 + init.ops = &clk_divider_ops; 1009 + nfc_divider_parent_data[0].fw_name = "device"; 1010 + init.parent_data = nfc_divider_parent_data; 1011 + init.num_parents = 1; 1012 + nfc->nand_divider.reg = nfc->reg_clk; 1013 + nfc->nand_divider.shift = CLK_DIV_SHIFT; 1014 + nfc->nand_divider.width = CLK_DIV_WIDTH; 1015 + nfc->nand_divider.hw.init = &init; 1016 + nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED | 1017 + CLK_DIVIDER_ROUND_CLOSEST | 1018 + CLK_DIVIDER_ALLOW_ZERO; 1016 1019 1017 - nfc->phase_rx = devm_clk_get(nfc->dev, "rx"); 1018 - if (IS_ERR(nfc->phase_rx)) { 1019 - dev_err(nfc->dev, "failed to get RX clk\n"); 1020 - return PTR_ERR(nfc->phase_rx); 1021 - } 1020 + nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw); 1021 + if (IS_ERR(nfc->nand_clk)) 1022 + return PTR_ERR(nfc->nand_clk); 1022 1023 1023 1024 /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */ 1024 - regmap_update_bits(nfc->reg_clk, 1025 - 0, CLK_SELECT_NAND, CLK_SELECT_NAND); 1025 + writel(CLK_SELECT_NAND | readl(nfc->reg_clk), 1026 + nfc->reg_clk); 1026 1027 1027 1028 ret = clk_prepare_enable(nfc->core_clk); 1028 1029 if (ret) { ··· 1043 1030 goto err_device_clk; 1044 1031 } 1045 1032 1046 - ret = clk_prepare_enable(nfc->phase_tx); 1033 + ret = clk_prepare_enable(nfc->nand_clk); 1047 1034 if (ret) { 1048 - dev_err(nfc->dev, "failed to enable TX clock\n"); 1049 - goto err_phase_tx; 1035 + dev_err(nfc->dev, "pre enable NFC divider fail\n"); 1036 + goto err_nand_clk; 1050 1037 } 1051 1038 1052 - ret = clk_prepare_enable(nfc->phase_rx); 1053 - if (ret) { 1054 - dev_err(nfc->dev, "failed to enable RX clock\n"); 1055 - goto err_phase_rx; 1056 - } 1057 - 1058 - ret = clk_set_rate(nfc->device_clk, 24000000); 1039 + ret = clk_set_rate(nfc->nand_clk, 24000000); 1059 1040 if (ret) 1060 - goto err_disable_rx; 1041 + goto err_disable_clk; 1061 1042 1062 1043 return 0; 1063 1044 1064 - err_disable_rx: 1065 - clk_disable_unprepare(nfc->phase_rx); 1066 - err_phase_rx: 1067 - clk_disable_unprepare(nfc->phase_tx); 1068 - err_phase_tx: 1045 + err_disable_clk: 1046 + clk_disable_unprepare(nfc->nand_clk); 1047 + err_nand_clk: 1069 1048 clk_disable_unprepare(nfc->device_clk); 1070 1049 err_device_clk: 1071 1050 clk_disable_unprepare(nfc->core_clk); ··· 1066 1061 1067 1062 static void meson_nfc_disable_clk(struct meson_nfc *nfc) 1068 1063 { 1069 - clk_disable_unprepare(nfc->phase_rx); 1070 - clk_disable_unprepare(nfc->phase_tx); 1064 + clk_disable_unprepare(nfc->nand_clk); 1071 1065 clk_disable_unprepare(nfc->device_clk); 1072 1066 clk_disable_unprepare(nfc->core_clk); 1073 1067 } ··· 1372 1368 { 1373 1369 struct device *dev = &pdev->dev; 1374 1370 struct meson_nfc *nfc; 1375 - struct resource *res; 1376 1371 int ret, irq; 1377 1372 1378 1373 nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL); ··· 1388 1385 1389 1386 nfc->dev = dev; 1390 1387 1391 - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1392 - nfc->reg_base = devm_ioremap_resource(dev, res); 1388 + nfc->reg_base = devm_platform_ioremap_resource_byname(pdev, "nfc"); 1393 1389 if (IS_ERR(nfc->reg_base)) 1394 1390 return PTR_ERR(nfc->reg_base); 1395 1391 1396 - nfc->reg_clk = 1397 - syscon_regmap_lookup_by_phandle(dev->of_node, 1398 - "amlogic,mmc-syscon"); 1399 - if (IS_ERR(nfc->reg_clk)) { 1400 - dev_err(dev, "Failed to lookup clock base\n"); 1392 + nfc->reg_clk = devm_platform_ioremap_resource_byname(pdev, "emmc"); 1393 + if (IS_ERR(nfc->reg_clk)) 1401 1394 return PTR_ERR(nfc->reg_clk); 1402 - } 1403 1395 1404 1396 irq = platform_get_irq(pdev, 0); 1405 1397 if (irq < 0)
+11 -4
drivers/mtd/nand/raw/nand_base.c
··· 335 335 * @chip: NAND chip structure 336 336 * 337 337 * Lock the device and its controller for exclusive access 338 - * 339 - * Return: -EBUSY if the chip has been suspended, 0 otherwise 340 338 */ 341 339 static void nand_get_device(struct nand_chip *chip) 342 340 { ··· 3816 3818 struct mtd_oob_ops *ops) 3817 3819 { 3818 3820 struct nand_chip *chip = mtd_to_nand(mtd); 3821 + struct mtd_ecc_stats old_stats; 3819 3822 int ret; 3820 3823 3821 3824 ops->retlen = 0; ··· 3828 3829 3829 3830 nand_get_device(chip); 3830 3831 3832 + old_stats = mtd->ecc_stats; 3833 + 3831 3834 if (!ops->datbuf) 3832 3835 ret = nand_do_read_oob(chip, from, ops); 3833 3836 else 3834 3837 ret = nand_do_read_ops(chip, from, ops); 3838 + 3839 + if (ops->stats) { 3840 + ops->stats->uncorrectable_errors += 3841 + mtd->ecc_stats.failed - old_stats.failed; 3842 + ops->stats->corrected_bitflips += 3843 + mtd->ecc_stats.corrected - old_stats.corrected; 3844 + } 3835 3845 3836 3846 nand_release_device(chip); 3837 3847 return ret; ··· 5339 5331 int rawnand_dt_parse_gpio_cs(struct device *dev, struct gpio_desc ***cs_array, 5340 5332 unsigned int *ncs_array) 5341 5333 { 5342 - struct device_node *np = dev->of_node; 5343 5334 struct gpio_desc **descs; 5344 5335 int ndescs, i; 5345 5336 5346 - ndescs = of_gpio_named_count(np, "cs-gpios"); 5337 + ndescs = gpiod_count(dev, "cs"); 5347 5338 if (ndescs < 0) { 5348 5339 dev_dbg(dev, "No valid cs-gpios property\n"); 5349 5340 return 0;
+4 -4
drivers/mtd/nand/raw/nand_bbt.c
··· 313 313 size_t len) 314 314 { 315 315 struct mtd_info *mtd = nand_to_mtd(this); 316 - struct mtd_oob_ops ops; 316 + struct mtd_oob_ops ops = { }; 317 317 int res, ret = 0; 318 318 319 319 ops.mode = MTD_OPS_PLACE_OOB; ··· 354 354 uint8_t *buf, uint8_t *oob) 355 355 { 356 356 struct mtd_info *mtd = nand_to_mtd(this); 357 - struct mtd_oob_ops ops; 357 + struct mtd_oob_ops ops = { }; 358 358 359 359 ops.mode = MTD_OPS_PLACE_OOB; 360 360 ops.ooboffs = 0; ··· 416 416 { 417 417 struct mtd_info *mtd = nand_to_mtd(this); 418 418 419 - struct mtd_oob_ops ops; 419 + struct mtd_oob_ops ops = { }; 420 420 int ret, page_offset; 421 421 422 422 ops.ooblen = mtd->oobsize; ··· 756 756 uint8_t rcode = td->reserved_block_code; 757 757 size_t retlen, len = 0; 758 758 loff_t to; 759 - struct mtd_oob_ops ops; 759 + struct mtd_oob_ops ops = { }; 760 760 761 761 ops.ooblen = mtd->oobsize; 762 762 ops.ooboffs = 0;
+5 -12
drivers/mtd/nand/raw/orion_nand.c
··· 170 170 171 171 platform_set_drvdata(pdev, info); 172 172 173 - /* Not all platforms can gate the clock, so it is not 174 - an error if the clock does not exists. */ 175 - info->clk = devm_clk_get(&pdev->dev, NULL); 176 - if (IS_ERR(info->clk)) { 177 - ret = PTR_ERR(info->clk); 178 - if (ret == -ENOENT) { 179 - info->clk = NULL; 180 - } else { 181 - dev_err(&pdev->dev, "failed to get clock!\n"); 182 - return ret; 183 - } 184 - } 173 + /* Not all platforms can gate the clock, so it is optional. */ 174 + info->clk = devm_clk_get_optional(&pdev->dev, NULL); 175 + if (IS_ERR(info->clk)) 176 + return dev_err_probe(&pdev->dev, PTR_ERR(info->clk), 177 + "failed to get clock!\n"); 185 178 186 179 ret = clk_prepare_enable(info->clk); 187 180 if (ret) {
+1 -1
drivers/mtd/nand/raw/sm_common.c
··· 99 99 static int sm_block_markbad(struct nand_chip *chip, loff_t ofs) 100 100 { 101 101 struct mtd_info *mtd = nand_to_mtd(chip); 102 - struct mtd_oob_ops ops; 102 + struct mtd_oob_ops ops = { }; 103 103 struct sm_oob oob; 104 104 int ret; 105 105
+7 -6
drivers/mtd/nand/raw/stm32_fmc2_nand.c
··· 862 862 863 863 ret = dma_map_sg(nfc->dev, nfc->dma_data_sg.sgl, 864 864 eccsteps, dma_data_dir); 865 - if (ret < 0) 866 - return ret; 865 + if (!ret) 866 + return -EIO; 867 867 868 868 desc_data = dmaengine_prep_slave_sg(dma_ch, nfc->dma_data_sg.sgl, 869 869 eccsteps, dma_transfer_dir, ··· 893 893 894 894 ret = dma_map_sg(nfc->dev, nfc->dma_ecc_sg.sgl, 895 895 eccsteps, dma_data_dir); 896 - if (ret < 0) 896 + if (!ret) { 897 + ret = -EIO; 897 898 goto err_unmap_data; 899 + } 898 900 899 901 desc_ecc = dmaengine_prep_slave_sg(nfc->dma_ecc_ch, 900 902 nfc->dma_ecc_sg.sgl, ··· 1801 1799 nand->cs_used[i] = cs; 1802 1800 } 1803 1801 1804 - nand->wp_gpio = devm_gpiod_get_from_of_node(nfc->dev, dn, 1805 - "wp-gpios", 0, 1806 - GPIOD_OUT_HIGH, "wp"); 1802 + nand->wp_gpio = devm_fwnode_gpiod_get(nfc->dev, of_fwnode_handle(dn), 1803 + "wp", GPIOD_OUT_HIGH, "wp"); 1807 1804 if (IS_ERR(nand->wp_gpio)) { 1808 1805 ret = PTR_ERR(nand->wp_gpio); 1809 1806 if (ret != -ENOENT)
+10
drivers/mtd/nand/spi/core.c
··· 635 635 { 636 636 struct spinand_device *spinand = mtd_to_spinand(mtd); 637 637 struct nand_device *nand = mtd_to_nanddev(mtd); 638 + struct mtd_ecc_stats old_stats; 638 639 unsigned int max_bitflips = 0; 639 640 struct nand_io_iter iter; 640 641 bool disable_ecc = false; ··· 646 645 disable_ecc = true; 647 646 648 647 mutex_lock(&spinand->lock); 648 + 649 + old_stats = mtd->ecc_stats; 649 650 650 651 nanddev_io_for_each_page(nand, NAND_PAGE_READ, from, ops, &iter) { 651 652 if (disable_ecc) ··· 669 666 ret = 0; 670 667 ops->retlen += iter.req.datalen; 671 668 ops->oobretlen += iter.req.ooblen; 669 + } 670 + 671 + if (ops->stats) { 672 + ops->stats->uncorrectable_errors += 673 + mtd->ecc_stats.failed - old_stats.failed; 674 + ops->stats->corrected_bitflips += 675 + mtd->ecc_stats.corrected - old_stats.corrected; 672 676 } 673 677 674 678 mutex_unlock(&spinand->lock);
+3 -3
drivers/mtd/nftlcore.c
··· 124 124 size_t *retlen, uint8_t *buf) 125 125 { 126 126 loff_t mask = mtd->writesize - 1; 127 - struct mtd_oob_ops ops; 127 + struct mtd_oob_ops ops = { }; 128 128 int res; 129 129 130 130 ops.mode = MTD_OPS_PLACE_OOB; ··· 145 145 size_t *retlen, uint8_t *buf) 146 146 { 147 147 loff_t mask = mtd->writesize - 1; 148 - struct mtd_oob_ops ops; 148 + struct mtd_oob_ops ops = { }; 149 149 int res; 150 150 151 151 ops.mode = MTD_OPS_PLACE_OOB; ··· 168 168 size_t *retlen, uint8_t *buf, uint8_t *oob) 169 169 { 170 170 loff_t mask = mtd->writesize - 1; 171 - struct mtd_oob_ops ops; 171 + struct mtd_oob_ops ops = { }; 172 172 int res; 173 173 174 174 ops.mode = MTD_OPS_PLACE_OOB;
+10
drivers/mtd/parsers/Kconfig
··· 20 20 This provides partition parsing for BCM63xx devices with CFE 21 21 bootloaders. 22 22 23 + config MTD_BRCM_U_BOOT 24 + tristate "Broadcom's U-Boot partition parser" 25 + depends on ARCH_BCM4908 || COMPILE_TEST 26 + help 27 + Broadcom uses a custom way of storing U-Boot environment variables. 28 + They are placed inside U-Boot partition itself at unspecified offset. 29 + It's possible to locate them by looking for a custom header with a 30 + magic value. This driver does that and creates subpartitions for 31 + each found environment variables block. 32 + 23 33 config MTD_CMDLINE_PARTS 24 34 tristate "Command line partition table parsing" 25 35 depends on MTD
+1
drivers/mtd/parsers/Makefile
··· 2 2 obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o 3 3 obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o 4 4 obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o 5 + obj-$(CONFIG_MTD_BRCM_U_BOOT) += brcm_u-boot.o 5 6 obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o 6 7 obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o 7 8 ofpart-y += ofpart_core.o
+84
drivers/mtd/parsers/brcm_u-boot.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright © 2022 Rafał Miłecki <rafal@milecki.pl> 4 + */ 5 + 6 + #include <linux/module.h> 7 + #include <linux/kernel.h> 8 + #include <linux/slab.h> 9 + #include <linux/mtd/mtd.h> 10 + #include <linux/mtd/partitions.h> 11 + 12 + #define BRCM_U_BOOT_MAX_OFFSET 0x200000 13 + #define BRCM_U_BOOT_STEP 0x1000 14 + 15 + #define BRCM_U_BOOT_MAX_PARTS 2 16 + 17 + #define BRCM_U_BOOT_MAGIC 0x75456e76 /* uEnv */ 18 + 19 + struct brcm_u_boot_header { 20 + __le32 magic; 21 + __le32 length; 22 + } __packed; 23 + 24 + static const char *names[BRCM_U_BOOT_MAX_PARTS] = { 25 + "u-boot-env", 26 + "u-boot-env-backup", 27 + }; 28 + 29 + static int brcm_u_boot_parse(struct mtd_info *mtd, 30 + const struct mtd_partition **pparts, 31 + struct mtd_part_parser_data *data) 32 + { 33 + struct brcm_u_boot_header header; 34 + struct mtd_partition *parts; 35 + size_t bytes_read; 36 + size_t offset; 37 + int err; 38 + int i = 0; 39 + 40 + parts = kcalloc(BRCM_U_BOOT_MAX_PARTS, sizeof(*parts), GFP_KERNEL); 41 + if (!parts) 42 + return -ENOMEM; 43 + 44 + for (offset = 0; 45 + offset < min_t(size_t, mtd->size, BRCM_U_BOOT_MAX_OFFSET); 46 + offset += BRCM_U_BOOT_STEP) { 47 + err = mtd_read(mtd, offset, sizeof(header), &bytes_read, (uint8_t *)&header); 48 + if (err && !mtd_is_bitflip(err)) { 49 + pr_err("Failed to read from %s at 0x%zx: %d\n", mtd->name, offset, err); 50 + continue; 51 + } 52 + 53 + if (le32_to_cpu(header.magic) != BRCM_U_BOOT_MAGIC) 54 + continue; 55 + 56 + parts[i].name = names[i]; 57 + parts[i].offset = offset; 58 + parts[i].size = sizeof(header) + le32_to_cpu(header.length); 59 + i++; 60 + pr_info("offset:0x%zx magic:0x%08x BINGO\n", offset, header.magic); 61 + 62 + if (i == BRCM_U_BOOT_MAX_PARTS) 63 + break; 64 + } 65 + 66 + *pparts = parts; 67 + 68 + return i; 69 + }; 70 + 71 + static const struct of_device_id brcm_u_boot_of_match_table[] = { 72 + { .compatible = "brcm,u-boot" }, 73 + {}, 74 + }; 75 + MODULE_DEVICE_TABLE(of, brcm_u_boot_of_match_table); 76 + 77 + static struct mtd_part_parser brcm_u_boot_mtd_parser = { 78 + .parse_fn = brcm_u_boot_parse, 79 + .name = "brcm_u-boot", 80 + .of_match_table = brcm_u_boot_of_match_table, 81 + }; 82 + module_mtd_part_parser(brcm_u_boot_mtd_parser); 83 + 84 + MODULE_LICENSE("GPL");
+2 -2
drivers/mtd/parsers/cmdlinepart.c
··· 193 193 parts[this_part].mask_flags = mask_flags; 194 194 parts[this_part].add_flags = add_flags; 195 195 if (name) 196 - strlcpy(extra_mem, name, name_len + 1); 196 + strscpy(extra_mem, name, name_len + 1); 197 197 else 198 198 sprintf(extra_mem, "Partition_%03d", this_part); 199 199 parts[this_part].name = extra_mem; ··· 298 298 this_mtd->parts = parts; 299 299 this_mtd->num_parts = num_parts; 300 300 this_mtd->mtd_id = (char*)(this_mtd + 1); 301 - strlcpy(this_mtd->mtd_id, mtd_id, mtd_id_len + 1); 301 + strscpy(this_mtd->mtd_id, mtd_id, mtd_id_len + 1); 302 302 303 303 /* link into chain */ 304 304 this_mtd->next = partitions;
+2 -2
drivers/mtd/sm_ftl.c
··· 239 239 uint8_t *buffer, struct sm_oob *oob) 240 240 { 241 241 struct mtd_info *mtd = ftl->trans->mtd; 242 - struct mtd_oob_ops ops; 242 + struct mtd_oob_ops ops = { }; 243 243 struct sm_oob tmp_oob; 244 244 int ret = -EIO; 245 245 int try = 0; ··· 323 323 int zone, int block, int boffset, 324 324 uint8_t *buffer, struct sm_oob *oob) 325 325 { 326 - struct mtd_oob_ops ops; 326 + struct mtd_oob_ops ops = { }; 327 327 struct mtd_info *mtd = ftl->trans->mtd; 328 328 int ret; 329 329
+1 -1
drivers/mtd/ssfdc.c
··· 163 163 /* Read redundancy area (wrapper to MTD_READ_OOB */ 164 164 static int read_raw_oob(struct mtd_info *mtd, loff_t offs, uint8_t *buf) 165 165 { 166 - struct mtd_oob_ops ops; 166 + struct mtd_oob_ops ops = { }; 167 167 int ret; 168 168 169 169 ops.mode = MTD_OPS_RAW;
+1 -1
drivers/mtd/tests/nandbiterrs.c
··· 99 99 static int rewrite_page(int log) 100 100 { 101 101 int err = 0; 102 - struct mtd_oob_ops ops; 102 + struct mtd_oob_ops ops = { }; 103 103 104 104 if (log) 105 105 pr_info("rewrite page\n");
+4 -4
drivers/mtd/tests/oobtest.c
··· 56 56 static int write_eraseblock(int ebnum) 57 57 { 58 58 int i; 59 - struct mtd_oob_ops ops; 59 + struct mtd_oob_ops ops = { }; 60 60 int err = 0; 61 61 loff_t addr = (loff_t)ebnum * mtd->erasesize; 62 62 ··· 165 165 static int verify_eraseblock(int ebnum) 166 166 { 167 167 int i; 168 - struct mtd_oob_ops ops; 168 + struct mtd_oob_ops ops = { }; 169 169 int err = 0; 170 170 loff_t addr = (loff_t)ebnum * mtd->erasesize; 171 171 size_t bitflips; ··· 260 260 261 261 static int verify_eraseblock_in_one_go(int ebnum) 262 262 { 263 - struct mtd_oob_ops ops; 263 + struct mtd_oob_ops ops = { }; 264 264 int err = 0; 265 265 loff_t addr = (loff_t)ebnum * mtd->erasesize; 266 266 size_t len = mtd->oobavail * pgcnt; ··· 338 338 int err = 0; 339 339 unsigned int i; 340 340 uint64_t tmp; 341 - struct mtd_oob_ops ops; 341 + struct mtd_oob_ops ops = { }; 342 342 loff_t addr = 0, addr0; 343 343 344 344 printk(KERN_INFO "\n");
+1 -1
drivers/mtd/tests/readtest.c
··· 47 47 err = ret; 48 48 } 49 49 if (mtd->oobsize) { 50 - struct mtd_oob_ops ops; 50 + struct mtd_oob_ops ops = { }; 51 51 52 52 ops.mode = MTD_OPS_PLACE_OOB; 53 53 ops.len = 0;
+3 -3
fs/jffs2/wbuf.c
··· 1035 1035 { 1036 1036 int i, ret; 1037 1037 int cmlen = min_t(int, c->oobavail, OOB_CM_SIZE); 1038 - struct mtd_oob_ops ops; 1038 + struct mtd_oob_ops ops = { }; 1039 1039 1040 1040 ops.mode = MTD_OPS_AUTO_OOB; 1041 1041 ops.ooblen = NR_OOB_SCAN_PAGES * c->oobavail; ··· 1076 1076 int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, 1077 1077 struct jffs2_eraseblock *jeb) 1078 1078 { 1079 - struct mtd_oob_ops ops; 1079 + struct mtd_oob_ops ops = { }; 1080 1080 int ret, cmlen = min_t(int, c->oobavail, OOB_CM_SIZE); 1081 1081 1082 1082 ops.mode = MTD_OPS_AUTO_OOB; ··· 1101 1101 struct jffs2_eraseblock *jeb) 1102 1102 { 1103 1103 int ret; 1104 - struct mtd_oob_ops ops; 1104 + struct mtd_oob_ops ops = { }; 1105 1105 int cmlen = min_t(int, c->oobavail, OOB_CM_SIZE); 1106 1106 1107 1107 ops.mode = MTD_OPS_AUTO_OOB;
+7
include/linux/mtd/mtd.h
··· 40 40 unsigned long *lockmap; /* If keeping bitmap of locks */ 41 41 }; 42 42 43 + struct mtd_req_stats { 44 + unsigned int uncorrectable_errors; 45 + unsigned int corrected_bitflips; 46 + unsigned int max_bitflips; 47 + }; 48 + 43 49 /** 44 50 * struct mtd_oob_ops - oob operation operands 45 51 * @mode: operation mode ··· 76 70 uint32_t ooboffs; 77 71 uint8_t *datbuf; 78 72 uint8_t *oobbuf; 73 + struct mtd_req_stats *stats; 79 74 }; 80 75 81 76 /**
+59 -5
include/uapi/mtd/mtd-abi.h
··· 55 55 * @MTD_OPS_RAW: data are transferred as-is, with no error correction; 56 56 * this mode implies %MTD_OPS_PLACE_OOB 57 57 * 58 - * These modes can be passed to ioctl(MEMWRITE) and are also used internally. 59 - * See notes on "MTD file modes" for discussion on %MTD_OPS_RAW vs. 60 - * %MTD_FILE_MODE_RAW. 58 + * These modes can be passed to ioctl(MEMWRITE) and ioctl(MEMREAD); they are 59 + * also used internally. See notes on "MTD file modes" for discussion on 60 + * %MTD_OPS_RAW vs. %MTD_FILE_MODE_RAW. 61 61 */ 62 62 enum { 63 63 MTD_OPS_PLACE_OOB = 0, ··· 89 89 __u64 usr_oob; 90 90 __u8 mode; 91 91 __u8 padding[7]; 92 + }; 93 + 94 + /** 95 + * struct mtd_read_req_ecc_stats - ECC statistics for a read operation 96 + * 97 + * @uncorrectable_errors: the number of uncorrectable errors that happened 98 + * during the read operation 99 + * @corrected_bitflips: the number of bitflips corrected during the read 100 + * operation 101 + * @max_bitflips: the maximum number of bitflips detected in any single ECC 102 + * step for the data read during the operation; this information 103 + * can be used to decide whether the data stored in a specific 104 + * region of the MTD device should be moved somewhere else to 105 + * avoid data loss. 106 + */ 107 + struct mtd_read_req_ecc_stats { 108 + __u32 uncorrectable_errors; 109 + __u32 corrected_bitflips; 110 + __u32 max_bitflips; 111 + }; 112 + 113 + /** 114 + * struct mtd_read_req - data structure for requesting a read operation 115 + * 116 + * @start: start address 117 + * @len: length of data buffer (only lower 32 bits are used) 118 + * @ooblen: length of OOB buffer (only lower 32 bits are used) 119 + * @usr_data: user-provided data buffer 120 + * @usr_oob: user-provided OOB buffer 121 + * @mode: MTD mode (see "MTD operation modes") 122 + * @padding: reserved, must be set to 0 123 + * @ecc_stats: ECC statistics for the read operation 124 + * 125 + * This structure supports ioctl(MEMREAD) operations, allowing data and/or OOB 126 + * reads in various modes. To read from OOB-only, set @usr_data == NULL, and to 127 + * read data-only, set @usr_oob == NULL. However, setting both @usr_data and 128 + * @usr_oob to NULL is not allowed. 129 + */ 130 + struct mtd_read_req { 131 + __u64 start; 132 + __u64 len; 133 + __u64 ooblen; 134 + __u64 usr_data; 135 + __u64 usr_oob; 136 + __u8 mode; 137 + __u8 padding[7]; 138 + struct mtd_read_req_ecc_stats ecc_stats; 92 139 }; 93 140 94 141 #define MTD_ABSENT 0 ··· 254 207 #define MEMWRITE _IOWR('M', 24, struct mtd_write_req) 255 208 /* Erase a given range of user data (must be in mode %MTD_FILE_MODE_OTP_USER) */ 256 209 #define OTPERASE _IOW('M', 25, struct otp_info) 210 + /* 211 + * Most generic read interface; can read in-band and/or out-of-band in various 212 + * modes (see "struct mtd_read_req"). This ioctl is not supported for flashes 213 + * without OOB, e.g., NOR flash. 214 + */ 215 + #define MEMREAD _IOWR('M', 26, struct mtd_read_req) 257 216 258 217 /* 259 218 * Obsolete legacy interface. Keep it in order not to break userspace ··· 323 270 * Note: %MTD_FILE_MODE_RAW provides the same functionality as %MTD_OPS_RAW - 324 271 * raw access to the flash, without error correction or autoplacement schemes. 325 272 * Wherever possible, the MTD_OPS_* mode will override the MTD_FILE_MODE_* mode 326 - * (e.g., when using ioctl(MEMWRITE)), but in some cases, the MTD_FILE_MODE is 327 - * used out of necessity (e.g., `write()', ioctl(MEMWRITEOOB64)). 273 + * (e.g., when using ioctl(MEMWRITE) or ioctl(MEMREAD)), but in some cases, the 274 + * MTD_FILE_MODE is used out of necessity (e.g., `write()', 275 + * ioctl(MEMWRITEOOB64)). 328 276 */ 329 277 enum mtd_file_modes { 330 278 MTD_FILE_MODE_NORMAL = MTD_OTP_OFF,