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

mtd: nand: move nand_check_erased_ecc_chunk() to nand/core

The check function for bitflips in erased blocks will be needed
by the Realtek ECC engine driver (which is currently under
development). Right now it is located in raw/nand_base.c.
While this is sufficient for the current usecases, there is
no real dependency for an ECC engine on the raw nand library.

Move the function over to a more generic place in core library.

Suggested-by: Miquel Raynal <miquel.raynal@bootlin.com>
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

authored by

Markus Stockhausen and committed by
Miquel Raynal
6b88293a 01adc820

+136 -136
+131
drivers/mtd/nand/core.c
··· 13 13 #include <linux/mtd/nand.h> 14 14 15 15 /** 16 + * nand_check_erased_buf - check if a buffer contains (almost) only 0xff data 17 + * @buf: buffer to test 18 + * @len: buffer length 19 + * @bitflips_threshold: maximum number of bitflips 20 + * 21 + * Check if a buffer contains only 0xff, which means the underlying region 22 + * has been erased and is ready to be programmed. 23 + * The bitflips_threshold specify the maximum number of bitflips before 24 + * considering the region is not erased. 25 + * Note: The logic of this function has been extracted from the memweight 26 + * implementation, except that nand_check_erased_buf function exit before 27 + * testing the whole buffer if the number of bitflips exceed the 28 + * bitflips_threshold value. 29 + * 30 + * Returns a positive number of bitflips less than or equal to 31 + * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the 32 + * threshold. 33 + */ 34 + static int nand_check_erased_buf(void *buf, int len, int bitflips_threshold) 35 + { 36 + const unsigned char *bitmap = buf; 37 + int bitflips = 0; 38 + int weight; 39 + 40 + for (; len && ((uintptr_t)bitmap) % sizeof(long); 41 + len--, bitmap++) { 42 + weight = hweight8(*bitmap); 43 + bitflips += BITS_PER_BYTE - weight; 44 + if (unlikely(bitflips > bitflips_threshold)) 45 + return -EBADMSG; 46 + } 47 + 48 + for (; len >= sizeof(long); 49 + len -= sizeof(long), bitmap += sizeof(long)) { 50 + unsigned long d = *((unsigned long *)bitmap); 51 + if (d == ~0UL) 52 + continue; 53 + weight = hweight_long(d); 54 + bitflips += BITS_PER_LONG - weight; 55 + if (unlikely(bitflips > bitflips_threshold)) 56 + return -EBADMSG; 57 + } 58 + 59 + for (; len > 0; len--, bitmap++) { 60 + weight = hweight8(*bitmap); 61 + bitflips += BITS_PER_BYTE - weight; 62 + if (unlikely(bitflips > bitflips_threshold)) 63 + return -EBADMSG; 64 + } 65 + 66 + return bitflips; 67 + } 68 + 69 + /** 70 + * nand_check_erased_ecc_chunk - check if an ECC chunk contains (almost) only 71 + * 0xff data 72 + * @data: data buffer to test 73 + * @datalen: data length 74 + * @ecc: ECC buffer 75 + * @ecclen: ECC length 76 + * @extraoob: extra OOB buffer 77 + * @extraooblen: extra OOB length 78 + * @bitflips_threshold: maximum number of bitflips 79 + * 80 + * Check if a data buffer and its associated ECC and OOB data contains only 81 + * 0xff pattern, which means the underlying region has been erased and is 82 + * ready to be programmed. 83 + * The bitflips_threshold specify the maximum number of bitflips before 84 + * considering the region as not erased. 85 + * 86 + * Note: 87 + * 1/ ECC algorithms are working on pre-defined block sizes which are usually 88 + * different from the NAND page size. When fixing bitflips, ECC engines will 89 + * report the number of errors per chunk, and the NAND core infrastructure 90 + * expect you to return the maximum number of bitflips for the whole page. 91 + * This is why you should always use this function on a single chunk and 92 + * not on the whole page. After checking each chunk you should update your 93 + * max_bitflips value accordingly. 94 + * 2/ When checking for bitflips in erased pages you should not only check 95 + * the payload data but also their associated ECC data, because a user might 96 + * have programmed almost all bits to 1 but a few. In this case, we 97 + * shouldn't consider the chunk as erased, and checking ECC bytes prevent 98 + * this case. 99 + * 3/ The extraoob argument is optional, and should be used if some of your OOB 100 + * data are protected by the ECC engine. 101 + * It could also be used if you support subpages and want to attach some 102 + * extra OOB data to an ECC chunk. 103 + * 104 + * Returns a positive number of bitflips less than or equal to 105 + * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the 106 + * threshold. In case of success, the passed buffers are filled with 0xff. 107 + */ 108 + int nand_check_erased_ecc_chunk(void *data, int datalen, 109 + void *ecc, int ecclen, 110 + void *extraoob, int extraooblen, 111 + int bitflips_threshold) 112 + { 113 + int data_bitflips = 0, ecc_bitflips = 0, extraoob_bitflips = 0; 114 + 115 + data_bitflips = nand_check_erased_buf(data, datalen, 116 + bitflips_threshold); 117 + if (data_bitflips < 0) 118 + return data_bitflips; 119 + 120 + bitflips_threshold -= data_bitflips; 121 + 122 + ecc_bitflips = nand_check_erased_buf(ecc, ecclen, bitflips_threshold); 123 + if (ecc_bitflips < 0) 124 + return ecc_bitflips; 125 + 126 + bitflips_threshold -= ecc_bitflips; 127 + 128 + extraoob_bitflips = nand_check_erased_buf(extraoob, extraooblen, 129 + bitflips_threshold); 130 + if (extraoob_bitflips < 0) 131 + return extraoob_bitflips; 132 + 133 + if (data_bitflips) 134 + memset(data, 0xff, datalen); 135 + 136 + if (ecc_bitflips) 137 + memset(ecc, 0xff, ecclen); 138 + 139 + if (extraoob_bitflips) 140 + memset(extraoob, 0xff, extraooblen); 141 + 142 + return data_bitflips + ecc_bitflips + extraoob_bitflips; 143 + } 144 + EXPORT_SYMBOL(nand_check_erased_ecc_chunk); 145 + 146 + /** 16 147 * nanddev_isbad() - Check if a block is bad 17 148 * @nand: NAND device 18 149 * @pos: position pointing to the block we want to check
-131
drivers/mtd/nand/raw/nand_base.c
··· 2784 2784 } 2785 2785 2786 2786 /** 2787 - * nand_check_erased_buf - check if a buffer contains (almost) only 0xff data 2788 - * @buf: buffer to test 2789 - * @len: buffer length 2790 - * @bitflips_threshold: maximum number of bitflips 2791 - * 2792 - * Check if a buffer contains only 0xff, which means the underlying region 2793 - * has been erased and is ready to be programmed. 2794 - * The bitflips_threshold specify the maximum number of bitflips before 2795 - * considering the region is not erased. 2796 - * Note: The logic of this function has been extracted from the memweight 2797 - * implementation, except that nand_check_erased_buf function exit before 2798 - * testing the whole buffer if the number of bitflips exceed the 2799 - * bitflips_threshold value. 2800 - * 2801 - * Returns a positive number of bitflips less than or equal to 2802 - * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the 2803 - * threshold. 2804 - */ 2805 - static int nand_check_erased_buf(void *buf, int len, int bitflips_threshold) 2806 - { 2807 - const unsigned char *bitmap = buf; 2808 - int bitflips = 0; 2809 - int weight; 2810 - 2811 - for (; len && ((uintptr_t)bitmap) % sizeof(long); 2812 - len--, bitmap++) { 2813 - weight = hweight8(*bitmap); 2814 - bitflips += BITS_PER_BYTE - weight; 2815 - if (unlikely(bitflips > bitflips_threshold)) 2816 - return -EBADMSG; 2817 - } 2818 - 2819 - for (; len >= sizeof(long); 2820 - len -= sizeof(long), bitmap += sizeof(long)) { 2821 - unsigned long d = *((unsigned long *)bitmap); 2822 - if (d == ~0UL) 2823 - continue; 2824 - weight = hweight_long(d); 2825 - bitflips += BITS_PER_LONG - weight; 2826 - if (unlikely(bitflips > bitflips_threshold)) 2827 - return -EBADMSG; 2828 - } 2829 - 2830 - for (; len > 0; len--, bitmap++) { 2831 - weight = hweight8(*bitmap); 2832 - bitflips += BITS_PER_BYTE - weight; 2833 - if (unlikely(bitflips > bitflips_threshold)) 2834 - return -EBADMSG; 2835 - } 2836 - 2837 - return bitflips; 2838 - } 2839 - 2840 - /** 2841 - * nand_check_erased_ecc_chunk - check if an ECC chunk contains (almost) only 2842 - * 0xff data 2843 - * @data: data buffer to test 2844 - * @datalen: data length 2845 - * @ecc: ECC buffer 2846 - * @ecclen: ECC length 2847 - * @extraoob: extra OOB buffer 2848 - * @extraooblen: extra OOB length 2849 - * @bitflips_threshold: maximum number of bitflips 2850 - * 2851 - * Check if a data buffer and its associated ECC and OOB data contains only 2852 - * 0xff pattern, which means the underlying region has been erased and is 2853 - * ready to be programmed. 2854 - * The bitflips_threshold specify the maximum number of bitflips before 2855 - * considering the region as not erased. 2856 - * 2857 - * Note: 2858 - * 1/ ECC algorithms are working on pre-defined block sizes which are usually 2859 - * different from the NAND page size. When fixing bitflips, ECC engines will 2860 - * report the number of errors per chunk, and the NAND core infrastructure 2861 - * expect you to return the maximum number of bitflips for the whole page. 2862 - * This is why you should always use this function on a single chunk and 2863 - * not on the whole page. After checking each chunk you should update your 2864 - * max_bitflips value accordingly. 2865 - * 2/ When checking for bitflips in erased pages you should not only check 2866 - * the payload data but also their associated ECC data, because a user might 2867 - * have programmed almost all bits to 1 but a few. In this case, we 2868 - * shouldn't consider the chunk as erased, and checking ECC bytes prevent 2869 - * this case. 2870 - * 3/ The extraoob argument is optional, and should be used if some of your OOB 2871 - * data are protected by the ECC engine. 2872 - * It could also be used if you support subpages and want to attach some 2873 - * extra OOB data to an ECC chunk. 2874 - * 2875 - * Returns a positive number of bitflips less than or equal to 2876 - * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the 2877 - * threshold. In case of success, the passed buffers are filled with 0xff. 2878 - */ 2879 - int nand_check_erased_ecc_chunk(void *data, int datalen, 2880 - void *ecc, int ecclen, 2881 - void *extraoob, int extraooblen, 2882 - int bitflips_threshold) 2883 - { 2884 - int data_bitflips = 0, ecc_bitflips = 0, extraoob_bitflips = 0; 2885 - 2886 - data_bitflips = nand_check_erased_buf(data, datalen, 2887 - bitflips_threshold); 2888 - if (data_bitflips < 0) 2889 - return data_bitflips; 2890 - 2891 - bitflips_threshold -= data_bitflips; 2892 - 2893 - ecc_bitflips = nand_check_erased_buf(ecc, ecclen, bitflips_threshold); 2894 - if (ecc_bitflips < 0) 2895 - return ecc_bitflips; 2896 - 2897 - bitflips_threshold -= ecc_bitflips; 2898 - 2899 - extraoob_bitflips = nand_check_erased_buf(extraoob, extraooblen, 2900 - bitflips_threshold); 2901 - if (extraoob_bitflips < 0) 2902 - return extraoob_bitflips; 2903 - 2904 - if (data_bitflips) 2905 - memset(data, 0xff, datalen); 2906 - 2907 - if (ecc_bitflips) 2908 - memset(ecc, 0xff, ecclen); 2909 - 2910 - if (extraoob_bitflips) 2911 - memset(extraoob, 0xff, extraooblen); 2912 - 2913 - return data_bitflips + ecc_bitflips + extraoob_bitflips; 2914 - } 2915 - EXPORT_SYMBOL(nand_check_erased_ecc_chunk); 2916 - 2917 - /** 2918 2787 * nand_read_page_raw_notsupp - dummy read raw page function 2919 2788 * @chip: nand chip info structure 2920 2789 * @buf: buffer to store read data
+5
include/linux/mtd/nand.h
··· 1136 1136 int nanddev_mtd_erase(struct mtd_info *mtd, struct erase_info *einfo); 1137 1137 int nanddev_mtd_max_bad_blocks(struct mtd_info *mtd, loff_t offs, size_t len); 1138 1138 1139 + int nand_check_erased_ecc_chunk(void *data, int datalen, 1140 + void *ecc, int ecclen, 1141 + void *extraoob, int extraooblen, 1142 + int threshold); 1143 + 1139 1144 #endif /* __LINUX_MTD_NAND_H */
-5
include/linux/mtd/rawnand.h
··· 1519 1519 unsigned char *read_ecc, unsigned char *calc_ecc); 1520 1520 void rawnand_sw_bch_cleanup(struct nand_chip *chip); 1521 1521 1522 - int nand_check_erased_ecc_chunk(void *data, int datalen, 1523 - void *ecc, int ecclen, 1524 - void *extraoob, int extraooblen, 1525 - int threshold); 1526 - 1527 1522 int nand_ecc_choose_conf(struct nand_chip *chip, 1528 1523 const struct nand_ecc_caps *caps, int oobavail); 1529 1524