diff options
| author | Alexander Couzens <lynxis@fe80.eu> | 2017-05-02 06:19:00 -0400 |
|---|---|---|
| committer | Brian Norris <computersforpeace@gmail.com> | 2017-05-02 21:56:39 -0400 |
| commit | 6a623e07694437ad09f382a13f76cffc32239a7f (patch) | |
| tree | b189b4914fdc96540f99082f04ba9e94c3689e40 | |
| parent | b98e1995e4fa9030474a61ed0dbc033464fe5ea0 (diff) | |
mtd: nand: add ooblayout for old hamming layout
The old 1-bit hamming layout requires ECC data to be placed at a
fixed offset, and not necessarily at the end of the OOB area.
Add this old layout back in order to fix legacy setups.
Fixes: 41b207a70d3a ("mtd: nand: implement the default mtd_ooblayout_ops")
Cc: <stable@vger.kernel.org>
Signed-off-by: Alexander Couzens <lynxis@fe80.eu>
Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
| -rw-r--r-- | drivers/mtd/nand/nand_base.c | 70 |
1 files changed, 69 insertions, 1 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index ed49a1d634b0..d474378ed810 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
| @@ -139,6 +139,74 @@ const struct mtd_ooblayout_ops nand_ooblayout_lp_ops = { | |||
| 139 | }; | 139 | }; |
| 140 | EXPORT_SYMBOL_GPL(nand_ooblayout_lp_ops); | 140 | EXPORT_SYMBOL_GPL(nand_ooblayout_lp_ops); |
| 141 | 141 | ||
| 142 | /* | ||
| 143 | * Support the old "large page" layout used for 1-bit Hamming ECC where ECC | ||
| 144 | * are placed at a fixed offset. | ||
| 145 | */ | ||
| 146 | static int nand_ooblayout_ecc_lp_hamming(struct mtd_info *mtd, int section, | ||
| 147 | struct mtd_oob_region *oobregion) | ||
| 148 | { | ||
| 149 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 150 | struct nand_ecc_ctrl *ecc = &chip->ecc; | ||
| 151 | |||
| 152 | if (section) | ||
| 153 | return -ERANGE; | ||
| 154 | |||
| 155 | switch (mtd->oobsize) { | ||
| 156 | case 64: | ||
| 157 | oobregion->offset = 40; | ||
| 158 | break; | ||
| 159 | case 128: | ||
| 160 | oobregion->offset = 80; | ||
| 161 | break; | ||
| 162 | default: | ||
| 163 | return -EINVAL; | ||
| 164 | } | ||
| 165 | |||
| 166 | oobregion->length = ecc->total; | ||
| 167 | if (oobregion->offset + oobregion->length > mtd->oobsize) | ||
| 168 | return -ERANGE; | ||
| 169 | |||
| 170 | return 0; | ||
| 171 | } | ||
| 172 | |||
| 173 | static int nand_ooblayout_free_lp_hamming(struct mtd_info *mtd, int section, | ||
| 174 | struct mtd_oob_region *oobregion) | ||
| 175 | { | ||
| 176 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 177 | struct nand_ecc_ctrl *ecc = &chip->ecc; | ||
| 178 | int ecc_offset = 0; | ||
| 179 | |||
| 180 | if (section < 0 || section > 1) | ||
| 181 | return -ERANGE; | ||
| 182 | |||
| 183 | switch (mtd->oobsize) { | ||
| 184 | case 64: | ||
| 185 | ecc_offset = 40; | ||
| 186 | break; | ||
| 187 | case 128: | ||
| 188 | ecc_offset = 80; | ||
| 189 | break; | ||
| 190 | default: | ||
| 191 | return -EINVAL; | ||
| 192 | } | ||
| 193 | |||
| 194 | if (section == 0) { | ||
| 195 | oobregion->offset = 2; | ||
| 196 | oobregion->length = ecc_offset - 2; | ||
| 197 | } else { | ||
| 198 | oobregion->offset = ecc_offset + ecc->total; | ||
| 199 | oobregion->length = mtd->oobsize - oobregion->offset; | ||
| 200 | } | ||
| 201 | |||
| 202 | return 0; | ||
| 203 | } | ||
| 204 | |||
| 205 | const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = { | ||
| 206 | .ecc = nand_ooblayout_ecc_lp_hamming, | ||
| 207 | .free = nand_ooblayout_free_lp_hamming, | ||
| 208 | }; | ||
| 209 | |||
| 142 | static int check_offs_len(struct mtd_info *mtd, | 210 | static int check_offs_len(struct mtd_info *mtd, |
| 143 | loff_t ofs, uint64_t len) | 211 | loff_t ofs, uint64_t len) |
| 144 | { | 212 | { |
| @@ -4559,7 +4627,7 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
| 4559 | break; | 4627 | break; |
| 4560 | case 64: | 4628 | case 64: |
| 4561 | case 128: | 4629 | case 128: |
| 4562 | mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops); | 4630 | mtd_set_ooblayout(mtd, &nand_ooblayout_lp_hamming_ops); |
| 4563 | break; | 4631 | break; |
| 4564 | default: | 4632 | default: |
| 4565 | WARN(1, "No oob scheme defined for oobsize %d\n", | 4633 | WARN(1, "No oob scheme defined for oobsize %d\n", |
