Skip to content

Commit 6b88293

Browse files
plappermaulmiquelraynal
authored andcommitted
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>
1 parent 01adc82 commit 6b88293

4 files changed

Lines changed: 136 additions & 136 deletions

File tree

drivers/mtd/nand/core.c

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,137 @@
1212
#include <linux/module.h>
1313
#include <linux/mtd/nand.h>
1414

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+
15146
/**
16147
* nanddev_isbad() - Check if a block is bad
17148
* @nand: NAND device

drivers/mtd/nand/raw/nand_base.c

Lines changed: 0 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -2783,137 +2783,6 @@ int nand_set_features(struct nand_chip *chip, int addr,
27832783
return nand_set_features_op(chip, addr, subfeature_param);
27842784
}
27852785

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-
29172786
/**
29182787
* nand_read_page_raw_notsupp - dummy read raw page function
29192788
* @chip: nand chip info structure

include/linux/mtd/nand.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,4 +1136,9 @@ static inline bool nanddev_bbt_is_initialized(struct nand_device *nand)
11361136
int nanddev_mtd_erase(struct mtd_info *mtd, struct erase_info *einfo);
11371137
int nanddev_mtd_max_bad_blocks(struct mtd_info *mtd, loff_t offs, size_t len);
11381138

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+
11391144
#endif /* __LINUX_MTD_NAND_H */

include/linux/mtd/rawnand.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,11 +1519,6 @@ int rawnand_sw_bch_correct(struct nand_chip *chip, unsigned char *buf,
15191519
unsigned char *read_ecc, unsigned char *calc_ecc);
15201520
void rawnand_sw_bch_cleanup(struct nand_chip *chip);
15211521

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-
15271522
int nand_ecc_choose_conf(struct nand_chip *chip,
15281523
const struct nand_ecc_caps *caps, int oobavail);
15291524

0 commit comments

Comments
 (0)