Message ID | 20200529002517.3546-17-miquel.raynal@bootlin.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Introduce the generic ECC engine abstraction | expand |
On Fri, 29 May 2020 02:25:13 +0200 Miquel Raynal <miquel.raynal@bootlin.com> wrote: > Embed a generic NAND ECC high-level object in the nand_device > structure to carry all the ECC engine configuration/data. Adapt the > raw NAND and SPI-NAND cores to fit the change. In order to split that one, and make future re-organizations less painful (hope we won't have to do that again, but who knows), I would recommend doing things in this order: 1/ create a nanddev_get_ecc_requirements() helper that returns a const struct nand_ecc_props * 2/ patch spinand to use this helper 3/ introduce nand_ecc 4/ patch rawnand to use the new ecc layer > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> > --- > drivers/mtd/nand/raw/atmel/nand-controller.c | 9 +++-- > drivers/mtd/nand/raw/brcmnand/brcmnand.c | 7 ++-- > drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 12 +++--- > drivers/mtd/nand/raw/marvell_nand.c | 7 ++-- > drivers/mtd/nand/raw/mtk_nand.c | 4 +- > drivers/mtd/nand/raw/nand_base.c | 25 ++++++------ > drivers/mtd/nand/raw/nand_esmt.c | 11 +++--- > drivers/mtd/nand/raw/nand_hynix.c | 41 ++++++++++---------- > drivers/mtd/nand/raw/nand_jedec.c | 4 +- > drivers/mtd/nand/raw/nand_micron.c | 14 ++++--- > drivers/mtd/nand/raw/nand_onfi.c | 8 ++-- > drivers/mtd/nand/raw/nand_samsung.c | 19 ++++----- > drivers/mtd/nand/raw/nand_toshiba.c | 11 +++--- > drivers/mtd/nand/raw/sunxi_nand.c | 5 ++- > drivers/mtd/nand/raw/tegra_nand.c | 9 +++-- > drivers/mtd/nand/spi/core.c | 8 ++-- > drivers/mtd/nand/spi/macronix.c | 6 +-- > drivers/mtd/nand/spi/toshiba.c | 6 +-- > include/linux/mtd/nand.h | 8 ++-- > 19 files changed, 114 insertions(+), 100 deletions(-) > > diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c > index 85cf396731ce..2ebcf3087d8d 100644 > --- a/drivers/mtd/nand/raw/atmel/nand-controller.c > +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c > @@ -1043,6 +1043,7 @@ static int atmel_hsmc_nand_pmecc_read_page_raw(struct nand_chip *chip, > > static int atmel_nand_pmecc_init(struct nand_chip *chip) > { > + struct nand_ecc_props *requirements = &chip->base.ecc.requirements; > struct mtd_info *mtd = nand_to_mtd(chip); > struct atmel_nand *nand = to_atmel_nand(chip); > struct atmel_nand_controller *nc; > @@ -1072,15 +1073,15 @@ static int atmel_nand_pmecc_init(struct nand_chip *chip) > req.ecc.strength = ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH; > else if (chip->ecc.strength) > req.ecc.strength = chip->ecc.strength; > - else if (chip->base.eccreq.strength) > - req.ecc.strength = chip->base.eccreq.strength; > + else if (requirements->strength) > + req.ecc.strength = requirements->strength; > else > req.ecc.strength = ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH; > > if (chip->ecc.size) > req.ecc.sectorsize = chip->ecc.size; > - else if (chip->base.eccreq.step_size) > - req.ecc.sectorsize = chip->base.eccreq.step_size; > + else if (requirements->step_size) > + req.ecc.sectorsize = requirements->step_size; > else > req.ecc.sectorsize = ATMEL_PMECC_SECTOR_SIZE_AUTO; > > diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c > index 164617b33942..40f6d107ffa2 100644 > --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c > +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c > @@ -2563,10 +2563,11 @@ static int brcmnand_setup_dev(struct brcmnand_host *host) > > if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_NONE && > (!chip->ecc.size || !chip->ecc.strength)) { > - if (chip->base.eccreq.step_size && chip->base.eccreq.strength) { > + if (chip->base.ecc.requirements.step_size && > + chip->base.ecc.requirements.strength) { > /* use detected ECC parameters */ > - chip->ecc.size = chip->base.eccreq.step_size; > - chip->ecc.strength = chip->base.eccreq.strength; > + chip->ecc.size = chip->base.ecc.requirements.step_size; > + chip->ecc.strength = chip->base.ecc.requirements.strength; > dev_info(ctrl->dev, "Using ECC step-size %d, strength %d\n", > chip->ecc.size, chip->ecc.strength); > } > diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c > index d1ea6df9fd64..5f56570ce04d 100644 > --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c > +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c > @@ -272,8 +272,8 @@ static int set_geometry_by_ecc_info(struct gpmi_nand_data *this, > default: > dev_err(this->dev, > "unsupported nand chip. ecc bits : %d, ecc size : %d\n", > - chip->base.eccreq.strength, > - chip->base.eccreq.step_size); > + chip->base.ecc.requirements.strength, > + chip->base.ecc.requirements.step_size); > return -EINVAL; > } > geo->ecc_chunk_size = ecc_step; > @@ -517,13 +517,13 @@ static int common_nfc_set_geometry(struct gpmi_nand_data *this) > > if ((of_property_read_bool(this->dev->of_node, "fsl,use-minimum-ecc")) > || legacy_set_geometry(this)) { > - if (!(chip->base.eccreq.strength > 0 && > - chip->base.eccreq.step_size > 0)) > + if (!(chip->base.ecc.requirements.strength > 0 && > + chip->base.ecc.requirements.step_size > 0)) > return -EINVAL; > > return set_geometry_by_ecc_info(this, > - chip->base.eccreq.strength, > - chip->base.eccreq.step_size); > + chip->base.ecc.requirements.strength, > + chip->base.ecc.requirements.step_size); > } > > return 0; > diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c > index f9cc03c11deb..e7a269461a6d 100644 > --- a/drivers/mtd/nand/raw/marvell_nand.c > +++ b/drivers/mtd/nand/raw/marvell_nand.c > @@ -2244,14 +2244,15 @@ static int marvell_nand_ecc_init(struct mtd_info *mtd, > struct nand_ecc_ctrl *ecc) > { > struct nand_chip *chip = mtd_to_nand(mtd); > + struct nand_ecc_props *requirements = &chip->base.ecc.requirements; > struct marvell_nfc *nfc = to_marvell_nfc(chip->controller); > int ret; > > if (ecc->engine_type != NAND_ECC_ENGINE_TYPE_NONE && > (!ecc->size || !ecc->strength)) { > - if (chip->base.eccreq.step_size && chip->base.eccreq.strength) { > - ecc->size = chip->base.eccreq.step_size; > - ecc->strength = chip->base.eccreq.strength; > + if (requirements->step_size && requirements->strength) { > + ecc->size = requirements->step_size; > + ecc->strength = requirements->strength; > } else { > dev_info(nfc->dev, > "No minimum ECC strength, using 1b/512B\n"); > diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c > index a0294c9161dd..1f8dbae38286 100644 > --- a/drivers/mtd/nand/raw/mtk_nand.c > +++ b/drivers/mtd/nand/raw/mtk_nand.c > @@ -1234,8 +1234,8 @@ static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd) > /* if optional dt settings not present */ > if (!nand->ecc.size || !nand->ecc.strength) { > /* use datasheet requirements */ > - nand->ecc.strength = nand->base.eccreq.strength; > - nand->ecc.size = nand->base.eccreq.step_size; > + nand->ecc.strength = nand->base.ecc.requirements.strength; > + nand->ecc.size = nand->base.ecc.requirements.step_size; > > /* > * align eccstrength and eccsize > diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c > index 1ce2cbe72e4c..bc2d5d2e8f4c 100644 > --- a/drivers/mtd/nand/raw/nand_base.c > +++ b/drivers/mtd/nand/raw/nand_base.c > @@ -4746,8 +4746,8 @@ static bool find_full_id_nand(struct nand_chip *chip, > memorg->pagesize * > memorg->pages_per_eraseblock); > chip->options |= type->options; > - chip->base.eccreq.strength = NAND_ECC_STRENGTH(type); > - chip->base.eccreq.step_size = NAND_ECC_STEP(type); > + chip->base.ecc.requirements.strength = NAND_ECC_STRENGTH(type); > + chip->base.ecc.requirements.step_size = NAND_ECC_STEP(type); > chip->onfi_timing_mode_default = > type->onfi_timing_mode_default; > > @@ -5485,8 +5485,8 @@ nand_match_ecc_req(struct nand_chip *chip, > { > struct mtd_info *mtd = nand_to_mtd(chip); > const struct nand_ecc_step_info *stepinfo; > - int req_step = chip->base.eccreq.step_size; > - int req_strength = chip->base.eccreq.strength; > + int req_step = chip->base.ecc.requirements.step_size; > + int req_strength = chip->base.ecc.requirements.strength; > int req_corr, step_size, strength, nsteps, ecc_bytes, ecc_bytes_total; > int best_step, best_strength, best_ecc_bytes; > int best_ecc_bytes_total = INT_MAX; > @@ -5677,9 +5677,10 @@ static bool nand_ecc_strength_good(struct nand_chip *chip) > { > struct mtd_info *mtd = nand_to_mtd(chip); > struct nand_ecc_ctrl *ecc = &chip->ecc; > + struct nand_ecc_props *requirements = &chip->base.ecc.requirements; > int corr, ds_corr; > > - if (ecc->size == 0 || chip->base.eccreq.step_size == 0) > + if (ecc->size == 0 || requirements->step_size == 0) > /* Not enough information */ > return true; > > @@ -5688,10 +5689,10 @@ static bool nand_ecc_strength_good(struct nand_chip *chip) > * the correction density. > */ > corr = (mtd->writesize * ecc->strength) / ecc->size; > - ds_corr = (mtd->writesize * chip->base.eccreq.strength) / > - chip->base.eccreq.step_size; > + ds_corr = (mtd->writesize * requirements->strength) / > + requirements->step_size; > > - return corr >= ds_corr && ecc->strength >= chip->base.eccreq.strength; > + return corr >= ds_corr && ecc->strength >= requirements->strength; > } > > static int rawnand_erase(struct nand_device *nand, const struct nand_pos *pos) > @@ -5977,9 +5978,11 @@ static int nand_scan_tail(struct nand_chip *chip) > /* ECC sanity check: warn if it's too weak */ > if (!nand_ecc_strength_good(chip)) > pr_warn("WARNING: %s: the ECC used on your system (%db/%dB) is too weak compared to the one required by the NAND chip (%db/%dB)\n", > - mtd->name, chip->ecc.strength, chip->ecc.size, > - chip->base.eccreq.strength, > - chip->base.eccreq.step_size); > + mtd->name, > + chip->base.ecc.ctx.conf.strength, > + chip->base.ecc.ctx.conf.step_size, > + chip->base.ecc.requirements.strength, > + chip->base.ecc.requirements.step_size); > > /* Allow subpage writes up to ecc.steps. Not possible for MLC flash */ > if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) { > diff --git a/drivers/mtd/nand/raw/nand_esmt.c b/drivers/mtd/nand/raw/nand_esmt.c > index 3338c68aaaf1..11f25ec3e4fc 100644 > --- a/drivers/mtd/nand/raw/nand_esmt.c > +++ b/drivers/mtd/nand/raw/nand_esmt.c > @@ -10,24 +10,25 @@ > > static void esmt_nand_decode_id(struct nand_chip *chip) > { > + struct nand_ecc_props *requirements = &chip->base.ecc.requirements; > nand_decode_ext_id(chip); > > /* Extract ECC requirements from 5th id byte. */ > if (chip->id.len >= 5 && nand_is_slc(chip)) { > - chip->base.eccreq.step_size = 512; > + requirements->step_size = 512; > switch (chip->id.data[4] & 0x3) { > case 0x0: > - chip->base.eccreq.strength = 4; > + requirements->strength = 4; > break; > case 0x1: > - chip->base.eccreq.strength = 2; > + requirements->strength = 2; > break; > case 0x2: > - chip->base.eccreq.strength = 1; > + requirements->strength = 1; > break; > default: > WARN(1, "Could not get ECC info"); > - chip->base.eccreq.step_size = 0; > + requirements->step_size = 0; > break; > } > } > diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c > index 7caedaa5b9e5..bac7732a86e9 100644 > --- a/drivers/mtd/nand/raw/nand_hynix.c > +++ b/drivers/mtd/nand/raw/nand_hynix.c > @@ -495,34 +495,35 @@ static void hynix_nand_extract_oobsize(struct nand_chip *chip, > static void hynix_nand_extract_ecc_requirements(struct nand_chip *chip, > bool valid_jedecid) > { > + struct nand_ecc_props *requirements = &chip->base.ecc.requirements; > u8 ecc_level = (chip->id.data[4] >> 4) & 0x7; > > if (valid_jedecid) { > /* Reference: H27UCG8T2E datasheet */ > - chip->base.eccreq.step_size = 1024; > + requirements->step_size = 1024; > > switch (ecc_level) { > case 0: > - chip->base.eccreq.step_size = 0; > - chip->base.eccreq.strength = 0; > + requirements->step_size = 0; > + requirements->strength = 0; > break; > case 1: > - chip->base.eccreq.strength = 4; > + requirements->strength = 4; > break; > case 2: > - chip->base.eccreq.strength = 24; > + requirements->strength = 24; > break; > case 3: > - chip->base.eccreq.strength = 32; > + requirements->strength = 32; > break; > case 4: > - chip->base.eccreq.strength = 40; > + requirements->strength = 40; > break; > case 5: > - chip->base.eccreq.strength = 50; > + requirements->strength = 50; > break; > case 6: > - chip->base.eccreq.strength = 60; > + requirements->strength = 60; > break; > default: > /* > @@ -543,14 +544,14 @@ static void hynix_nand_extract_ecc_requirements(struct nand_chip *chip, > if (nand_tech < 3) { > /* > 26nm, reference: H27UBG8T2A datasheet */ > if (ecc_level < 5) { > - chip->base.eccreq.step_size = 512; > - chip->base.eccreq.strength = 1 << ecc_level; > + requirements->step_size = 512; > + requirements->strength = 1 << ecc_level; > } else if (ecc_level < 7) { > if (ecc_level == 5) > - chip->base.eccreq.step_size = 2048; > + requirements->step_size = 2048; > else > - chip->base.eccreq.step_size = 1024; > - chip->base.eccreq.strength = 24; > + requirements->step_size = 1024; > + requirements->strength = 24; > } else { > /* > * We should never reach this case, but if that > @@ -563,14 +564,14 @@ static void hynix_nand_extract_ecc_requirements(struct nand_chip *chip, > } else { > /* <= 26nm, reference: H27UBG8T2B datasheet */ > if (!ecc_level) { > - chip->base.eccreq.step_size = 0; > - chip->base.eccreq.strength = 0; > + requirements->step_size = 0; > + requirements->strength = 0; > } else if (ecc_level < 5) { > - chip->base.eccreq.step_size = 512; > - chip->base.eccreq.strength = 1 << (ecc_level - 1); > + requirements->step_size = 512; > + requirements->strength = 1 << (ecc_level - 1); > } else { > - chip->base.eccreq.step_size = 1024; > - chip->base.eccreq.strength = 24 + > + requirements->step_size = 1024; > + requirements->strength = 24 + > (8 * (ecc_level - 5)); > } > } > diff --git a/drivers/mtd/nand/raw/nand_jedec.c b/drivers/mtd/nand/raw/nand_jedec.c > index b15c42f48755..5ed3656d88dd 100644 > --- a/drivers/mtd/nand/raw/nand_jedec.c > +++ b/drivers/mtd/nand/raw/nand_jedec.c > @@ -120,8 +120,8 @@ int nand_jedec_detect(struct nand_chip *chip) > ecc = &p->ecc_info[0]; > > if (ecc->codeword_size >= 9) { > - chip->base.eccreq.strength = ecc->ecc_bits; > - chip->base.eccreq.step_size = 1 << ecc->codeword_size; > + chip->base.ecc.requirements.strength = ecc->ecc_bits; > + chip->base.ecc.requirements.step_size = 1 << ecc->codeword_size; > } else { > pr_warn("Invalid codeword size\n"); > } > diff --git a/drivers/mtd/nand/raw/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c > index c8ebfd8c77a1..d1dc684ecd6c 100644 > --- a/drivers/mtd/nand/raw/nand_micron.c > +++ b/drivers/mtd/nand/raw/nand_micron.c > @@ -413,6 +413,7 @@ enum { > */ > static int micron_supports_on_die_ecc(struct nand_chip *chip) > { > + struct nand_ecc_props *requirements = &chip->base.ecc.requirements; > u8 id[5]; > int ret; > > @@ -425,7 +426,7 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip) > /* > * We only support on-die ECC of 4/512 or 8/512 > */ > - if (chip->base.eccreq.strength != 4 && chip->base.eccreq.strength != 8) > + if (requirements->strength != 4 && requirements->strength != 8) > return MICRON_ON_DIE_UNSUPPORTED; > > /* 0x2 means on-die ECC is available. */ > @@ -466,7 +467,7 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip) > /* > * We only support on-die ECC of 4/512 or 8/512 > */ > - if (chip->base.eccreq.strength != 4 && chip->base.eccreq.strength != 8) > + if (requirements->strength != 4 && requirements->strength != 8) > return MICRON_ON_DIE_UNSUPPORTED; > > return MICRON_ON_DIE_SUPPORTED; > @@ -474,6 +475,7 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip) > > static int micron_nand_init(struct nand_chip *chip) > { > + struct nand_ecc_props *requirements = &chip->base.ecc.requirements; > struct mtd_info *mtd = nand_to_mtd(chip); > struct micron_nand *micron; > int ondie; > @@ -523,7 +525,7 @@ static int micron_nand_init(struct nand_chip *chip) > * That's not needed for 8-bit ECC, because the status expose > * a better approximation of the number of bitflips in a page. > */ > - if (chip->base.eccreq.strength == 4) { > + if (requirements->strength == 4) { > micron->ecc.rawbuf = kmalloc(mtd->writesize + > mtd->oobsize, > GFP_KERNEL); > @@ -533,16 +535,16 @@ static int micron_nand_init(struct nand_chip *chip) > } > } > > - if (chip->base.eccreq.strength == 4) > + if (requirements->strength == 4) > mtd_set_ooblayout(mtd, > µn_nand_on_die_4_ooblayout_ops); > else > mtd_set_ooblayout(mtd, > µn_nand_on_die_8_ooblayout_ops); > > - chip->ecc.bytes = chip->base.eccreq.strength * 2; > + chip->ecc.bytes = requirements->strength * 2; > chip->ecc.size = 512; > - chip->ecc.strength = chip->base.eccreq.strength; > + chip->ecc.strength = requirements->strength; > chip->ecc.algo = NAND_ECC_ALGO_BCH; > chip->ecc.read_page = micron_nand_read_page_on_die_ecc; > chip->ecc.write_page = micron_nand_write_page_on_die_ecc; > diff --git a/drivers/mtd/nand/raw/nand_onfi.c b/drivers/mtd/nand/raw/nand_onfi.c > index be3456627288..c9ae29774c1f 100644 > --- a/drivers/mtd/nand/raw/nand_onfi.c > +++ b/drivers/mtd/nand/raw/nand_onfi.c > @@ -94,8 +94,8 @@ static int nand_flash_detect_ext_param_page(struct nand_chip *chip, > goto ext_out; > } > > - chip->base.eccreq.strength = ecc->ecc_bits; > - chip->base.eccreq.step_size = 1 << ecc->codeword_size; > + chip->base.ecc.requirements.strength = ecc->ecc_bits; > + chip->base.ecc.requirements.step_size = 1 << ecc->codeword_size; > ret = 0; > > ext_out: > @@ -265,8 +265,8 @@ int nand_onfi_detect(struct nand_chip *chip) > chip->options |= NAND_BUSWIDTH_16; > > if (p->ecc_bits != 0xff) { > - chip->base.eccreq.strength = p->ecc_bits; > - chip->base.eccreq.step_size = 512; > + chip->base.ecc.requirements.strength = p->ecc_bits; > + chip->base.ecc.requirements.step_size = 512; > } else if (onfi_version >= 21 && > (le16_to_cpu(p->features) & ONFI_FEATURE_EXT_PARAM_PAGE)) { > > diff --git a/drivers/mtd/nand/raw/nand_samsung.c b/drivers/mtd/nand/raw/nand_samsung.c > index 3a4a19e808f6..0ee85e88aeb5 100644 > --- a/drivers/mtd/nand/raw/nand_samsung.c > +++ b/drivers/mtd/nand/raw/nand_samsung.c > @@ -10,6 +10,7 @@ > > static void samsung_nand_decode_id(struct nand_chip *chip) > { > + struct nand_ecc_props *requirements = &chip->base.ecc.requirements; > struct mtd_info *mtd = nand_to_mtd(chip); > struct nand_memory_organization *memorg; > > @@ -71,23 +72,23 @@ static void samsung_nand_decode_id(struct nand_chip *chip) > /* Extract ECC requirements from 5th id byte*/ > extid = (chip->id.data[4] >> 4) & 0x07; > if (extid < 5) { > - chip->base.eccreq.step_size = 512; > - chip->base.eccreq.strength = 1 << extid; > + requirements->step_size = 512; > + requirements->strength = 1 << extid; > } else { > - chip->base.eccreq.step_size = 1024; > + requirements->step_size = 1024; > switch (extid) { > case 5: > - chip->base.eccreq.strength = 24; > + requirements->strength = 24; > break; > case 6: > - chip->base.eccreq.strength = 40; > + requirements->strength = 40; > break; > case 7: > - chip->base.eccreq.strength = 60; > + requirements->strength = 60; > break; > default: > WARN(1, "Could not decode ECC info"); > - chip->base.eccreq.step_size = 0; > + requirements->step_size = 0; > } > } > } else { > @@ -97,8 +98,8 @@ static void samsung_nand_decode_id(struct nand_chip *chip) > switch (chip->id.data[1]) { > /* K9F4G08U0D-S[I|C]B0(T00) */ > case 0xDC: > - chip->base.eccreq.step_size = 512; > - chip->base.eccreq.strength = 1; > + requirements->step_size = 512; > + requirements->strength = 1; > break; > > /* K9F1G08U0E 21nm chips do not support subpage write */ > diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c > index 436ed90a90ad..1180068007a9 100644 > --- a/drivers/mtd/nand/raw/nand_toshiba.c > +++ b/drivers/mtd/nand/raw/nand_toshiba.c > @@ -145,6 +145,7 @@ static void toshiba_nand_benand_init(struct nand_chip *chip) > > static void toshiba_nand_decode_id(struct nand_chip *chip) > { > + struct nand_ecc_props *requirements = &chip->base.ecc.requirements; > struct mtd_info *mtd = nand_to_mtd(chip); > struct nand_memory_organization *memorg; > > @@ -175,20 +176,20 @@ static void toshiba_nand_decode_id(struct nand_chip *chip) > * - 24nm: 8 bit ECC for each 512Byte is required. > */ > if (chip->id.len >= 6 && nand_is_slc(chip)) { > - chip->base.eccreq.step_size = 512; > + requirements->step_size = 512; > switch (chip->id.data[5] & 0x7) { > case 0x4: > - chip->base.eccreq.strength = 1; > + requirements->strength = 1; > break; > case 0x5: > - chip->base.eccreq.strength = 4; > + requirements->strength = 4; > break; > case 0x6: > - chip->base.eccreq.strength = 8; > + requirements->strength = 8; > break; > default: > WARN(1, "Could not get ECC info"); > - chip->base.eccreq.step_size = 0; > + requirements->step_size = 0; > break; > } > } > diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c > index c6dd2e6d9ef8..a5eefdf89660 100644 > --- a/drivers/mtd/nand/raw/sunxi_nand.c > +++ b/drivers/mtd/nand/raw/sunxi_nand.c > @@ -1732,6 +1732,7 @@ static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc) > > static int sunxi_nand_attach_chip(struct nand_chip *nand) > { > + struct nand_ecc_props *requirements = &nand->base.ecc.requirements; > struct nand_ecc_ctrl *ecc = &nand->ecc; > struct device_node *np = nand_get_flash_node(nand); > int ret; > @@ -1745,8 +1746,8 @@ static int sunxi_nand_attach_chip(struct nand_chip *nand) > nand->options |= NAND_SUBPAGE_READ; > > if (!ecc->size) { > - ecc->size = nand->base.eccreq.step_size; > - ecc->strength = nand->base.eccreq.strength; > + ecc->size = requirements->step_size; > + ecc->strength = requirements->strength; > } > > if (!ecc->size || !ecc->strength) > diff --git a/drivers/mtd/nand/raw/tegra_nand.c b/drivers/mtd/nand/raw/tegra_nand.c > index 2325b06ccc9a..8264bb991d03 100644 > --- a/drivers/mtd/nand/raw/tegra_nand.c > +++ b/drivers/mtd/nand/raw/tegra_nand.c > @@ -855,7 +855,7 @@ static int tegra_nand_get_strength(struct nand_chip *chip, const int *strength, > } else { > strength_sel = strength[i]; > > - if (strength_sel < chip->base.eccreq.strength) > + if (strength_sel < chip->base.ecc.requirements.strength) > continue; > } > > @@ -908,6 +908,7 @@ static int tegra_nand_select_strength(struct nand_chip *chip, int oobsize) > static int tegra_nand_attach_chip(struct nand_chip *chip) > { > struct tegra_nand_controller *ctrl = to_tegra_ctrl(chip->controller); > + struct nand_ecc_props *requirements = &chip->base.ecc.requirements; > struct tegra_nand_chip *nand = to_tegra_chip(chip); > struct mtd_info *mtd = nand_to_mtd(chip); > int bits_per_step; > @@ -919,9 +920,9 @@ static int tegra_nand_attach_chip(struct nand_chip *chip) > chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; > chip->ecc.size = 512; > chip->ecc.steps = mtd->writesize / chip->ecc.size; > - if (chip->base.eccreq.step_size != 512) { > + if (requirements->step_size != 512) { > dev_err(ctrl->dev, "Unsupported step size %d\n", > - chip->base.eccreq.step_size); > + requirements->step_size); > return -EINVAL; > } > > @@ -952,7 +953,7 @@ static int tegra_nand_attach_chip(struct nand_chip *chip) > if (ret < 0) { > dev_err(ctrl->dev, > "No valid strength found, minimum %d\n", > - chip->base.eccreq.strength); > + requirements->strength); > return ret; > } > > diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c > index 6f6ec8aa143d..edc8ec2923d5 100644 > --- a/drivers/mtd/nand/spi/core.c > +++ b/drivers/mtd/nand/spi/core.c > @@ -419,7 +419,7 @@ static int spinand_check_ecc_status(struct spinand_device *spinand, u8 status) > * fixed, so let's return the maximum possible value so that > * wear-leveling layers move the data immediately. > */ > - return nand->eccreq.strength; > + return nand->ecc.ctx.conf.strength; > > case STATUS_ECC_UNCOR_ERROR: > return -EBADMSG; > @@ -903,7 +903,7 @@ int spinand_match_and_init(struct spinand_device *spinand, > continue; > > nand->memorg = table[i].memorg; > - nand->eccreq = table[i].eccreq; > + nand->ecc.requirements = table[i].eccreq; > spinand->eccinfo = table[i].eccinfo; > spinand->flags = table[i].flags; > spinand->id.len = 1 + table[i].devid.len; > @@ -1091,8 +1091,8 @@ static int spinand_init(struct spinand_device *spinand) > mtd->oobavail = ret; > > /* Propagate ECC information to mtd_info */ > - mtd->ecc_strength = nand->eccreq.strength; > - mtd->ecc_step_size = nand->eccreq.step_size; > + mtd->ecc_strength = nand->ecc.ctx.conf.strength; > + mtd->ecc_step_size = nand->ecc.ctx.conf.step_size; > > return 0; > > diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c > index 0f900f3aa21a..9db55828a995 100644 > --- a/drivers/mtd/nand/spi/macronix.c > +++ b/drivers/mtd/nand/spi/macronix.c > @@ -84,10 +84,10 @@ static int mx35lf1ge4ab_ecc_get_status(struct spinand_device *spinand, > * data around if it's not necessary. > */ > if (mx35lf1ge4ab_get_eccsr(spinand, &eccsr)) > - return nand->eccreq.strength; > + return nand->ecc.ctx.conf.strength; > > - if (WARN_ON(eccsr > nand->eccreq.strength || !eccsr)) > - return nand->eccreq.strength; > + if (WARN_ON(eccsr > nand->ecc.ctx.conf.strength || !eccsr)) > + return nand->ecc.ctx.conf.strength; > > return eccsr; > > diff --git a/drivers/mtd/nand/spi/toshiba.c b/drivers/mtd/nand/spi/toshiba.c > index bc801d83343e..c3e5b1a85e3e 100644 > --- a/drivers/mtd/nand/spi/toshiba.c > +++ b/drivers/mtd/nand/spi/toshiba.c > @@ -90,12 +90,12 @@ static int tx58cxgxsxraix_ecc_get_status(struct spinand_device *spinand, > * data around if it's not necessary. > */ > if (spi_mem_exec_op(spinand->spimem, &op)) > - return nand->eccreq.strength; > + return nand->ecc.ctx.conf.strength; > > mbf >>= 4; > > - if (WARN_ON(mbf > nand->eccreq.strength || !mbf)) > - return nand->eccreq.strength; > + if (WARN_ON(mbf > nand->ecc.ctx.conf.strength || !mbf)) > + return nand->ecc.ctx.conf.strength; > > return mbf; > > diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h > index 2f838394b5f7..975ddf26ac8c 100644 > --- a/include/linux/mtd/nand.h > +++ b/include/linux/mtd/nand.h > @@ -290,7 +290,7 @@ struct nand_ecc { > * struct nand_device - NAND device > * @mtd: MTD instance attached to the NAND device > * @memorg: memory layout > - * @eccreq: ECC requirements > + * @ecc: NAND ECC object attached to the NAND device > * @rowconv: position to row address converter > * @bbt: bad block table info > * @ops: NAND operations attached to the NAND device > @@ -298,8 +298,8 @@ struct nand_ecc { > * Generic NAND object. Specialized NAND layers (raw NAND, SPI NAND, OneNAND) > * should declare their own NAND object embedding a nand_device struct (that's > * how inheritance is done). > - * struct_nand_device->memorg and struct_nand_device->eccreq should be filled > - * at device detection time to reflect the NAND device > + * struct_nand_device->memorg and struct_nand_device->ecc.ctx.conf should > + * be filled at device detection time to reflect the NAND device > * capabilities/requirements. Once this is done nanddev_init() can be called. > * It will take care of converting NAND information into MTD ones, which means > * the specialized NAND layers should never manually tweak > @@ -308,7 +308,7 @@ struct nand_ecc { > struct nand_device { > struct mtd_info mtd; > struct nand_memory_organization memorg; > - struct nand_ecc_props eccreq; > + struct nand_ecc ecc; > struct nand_row_converter rowconv; > struct nand_bbt bbt; > const struct nand_ops *ops;
On Fri, 29 May 2020 02:25:13 +0200 Miquel Raynal <miquel.raynal@bootlin.com> wrote: > - * struct_nand_device->memorg and struct_nand_device->eccreq should be filled > - * at device detection time to reflect the NAND device > + * struct_nand_device->memorg and struct_nand_device->ecc.ctx.conf should > + * be filled at device detection time to reflect the NAND device Is it not struct_nand_device->ecc.requirements?
Boris Brezillon <boris.brezillon@collabora.com> wrote on Fri, 29 May 2020 10:32:22 +0200: > On Fri, 29 May 2020 02:25:13 +0200 > Miquel Raynal <miquel.raynal@bootlin.com> wrote: > > > Embed a generic NAND ECC high-level object in the nand_device > > structure to carry all the ECC engine configuration/data. Adapt the > > raw NAND and SPI-NAND cores to fit the change. > > In order to split that one, and make future re-organizations less > painful (hope we won't have to do that again, but who knows), I would > recommend doing things in this order: > > 1/ create a nanddev_get_ecc_requirements() helper that returns a > const struct nand_ecc_props * > 2/ patch spinand to use this helper > 3/ introduce nand_ecc > 4/ patch rawnand to use the new ecc layer Sounds like a lot of efforts for a mechanical change to me. Not mentioning that the diff is pretty small now. But ok, I'll try. > > > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> > > --- > > drivers/mtd/nand/raw/atmel/nand-controller.c | 9 +++-- > > drivers/mtd/nand/raw/brcmnand/brcmnand.c | 7 ++-- > > drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 12 +++--- > > drivers/mtd/nand/raw/marvell_nand.c | 7 ++-- > > drivers/mtd/nand/raw/mtk_nand.c | 4 +- > > drivers/mtd/nand/raw/nand_base.c | 25 ++++++------ > > drivers/mtd/nand/raw/nand_esmt.c | 11 +++--- > > drivers/mtd/nand/raw/nand_hynix.c | 41 ++++++++++---------- > > drivers/mtd/nand/raw/nand_jedec.c | 4 +- > > drivers/mtd/nand/raw/nand_micron.c | 14 ++++--- > > drivers/mtd/nand/raw/nand_onfi.c | 8 ++-- > > drivers/mtd/nand/raw/nand_samsung.c | 19 ++++----- > > drivers/mtd/nand/raw/nand_toshiba.c | 11 +++--- > > drivers/mtd/nand/raw/sunxi_nand.c | 5 ++- > > drivers/mtd/nand/raw/tegra_nand.c | 9 +++-- > > drivers/mtd/nand/spi/core.c | 8 ++-- > > drivers/mtd/nand/spi/macronix.c | 6 +-- > > drivers/mtd/nand/spi/toshiba.c | 6 +-- > > include/linux/mtd/nand.h | 8 ++-- > > 19 files changed, 114 insertions(+), 100 deletions(-) > >
diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index 85cf396731ce..2ebcf3087d8d 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -1043,6 +1043,7 @@ static int atmel_hsmc_nand_pmecc_read_page_raw(struct nand_chip *chip, static int atmel_nand_pmecc_init(struct nand_chip *chip) { + struct nand_ecc_props *requirements = &chip->base.ecc.requirements; struct mtd_info *mtd = nand_to_mtd(chip); struct atmel_nand *nand = to_atmel_nand(chip); struct atmel_nand_controller *nc; @@ -1072,15 +1073,15 @@ static int atmel_nand_pmecc_init(struct nand_chip *chip) req.ecc.strength = ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH; else if (chip->ecc.strength) req.ecc.strength = chip->ecc.strength; - else if (chip->base.eccreq.strength) - req.ecc.strength = chip->base.eccreq.strength; + else if (requirements->strength) + req.ecc.strength = requirements->strength; else req.ecc.strength = ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH; if (chip->ecc.size) req.ecc.sectorsize = chip->ecc.size; - else if (chip->base.eccreq.step_size) - req.ecc.sectorsize = chip->base.eccreq.step_size; + else if (requirements->step_size) + req.ecc.sectorsize = requirements->step_size; else req.ecc.sectorsize = ATMEL_PMECC_SECTOR_SIZE_AUTO; diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 164617b33942..40f6d107ffa2 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -2563,10 +2563,11 @@ static int brcmnand_setup_dev(struct brcmnand_host *host) if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_NONE && (!chip->ecc.size || !chip->ecc.strength)) { - if (chip->base.eccreq.step_size && chip->base.eccreq.strength) { + if (chip->base.ecc.requirements.step_size && + chip->base.ecc.requirements.strength) { /* use detected ECC parameters */ - chip->ecc.size = chip->base.eccreq.step_size; - chip->ecc.strength = chip->base.eccreq.strength; + chip->ecc.size = chip->base.ecc.requirements.step_size; + chip->ecc.strength = chip->base.ecc.requirements.strength; dev_info(ctrl->dev, "Using ECC step-size %d, strength %d\n", chip->ecc.size, chip->ecc.strength); } diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c index d1ea6df9fd64..5f56570ce04d 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c @@ -272,8 +272,8 @@ static int set_geometry_by_ecc_info(struct gpmi_nand_data *this, default: dev_err(this->dev, "unsupported nand chip. ecc bits : %d, ecc size : %d\n", - chip->base.eccreq.strength, - chip->base.eccreq.step_size); + chip->base.ecc.requirements.strength, + chip->base.ecc.requirements.step_size); return -EINVAL; } geo->ecc_chunk_size = ecc_step; @@ -517,13 +517,13 @@ static int common_nfc_set_geometry(struct gpmi_nand_data *this) if ((of_property_read_bool(this->dev->of_node, "fsl,use-minimum-ecc")) || legacy_set_geometry(this)) { - if (!(chip->base.eccreq.strength > 0 && - chip->base.eccreq.step_size > 0)) + if (!(chip->base.ecc.requirements.strength > 0 && + chip->base.ecc.requirements.step_size > 0)) return -EINVAL; return set_geometry_by_ecc_info(this, - chip->base.eccreq.strength, - chip->base.eccreq.step_size); + chip->base.ecc.requirements.strength, + chip->base.ecc.requirements.step_size); } return 0; diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index f9cc03c11deb..e7a269461a6d 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -2244,14 +2244,15 @@ static int marvell_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc) { struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_ecc_props *requirements = &chip->base.ecc.requirements; struct marvell_nfc *nfc = to_marvell_nfc(chip->controller); int ret; if (ecc->engine_type != NAND_ECC_ENGINE_TYPE_NONE && (!ecc->size || !ecc->strength)) { - if (chip->base.eccreq.step_size && chip->base.eccreq.strength) { - ecc->size = chip->base.eccreq.step_size; - ecc->strength = chip->base.eccreq.strength; + if (requirements->step_size && requirements->strength) { + ecc->size = requirements->step_size; + ecc->strength = requirements->strength; } else { dev_info(nfc->dev, "No minimum ECC strength, using 1b/512B\n"); diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c index a0294c9161dd..1f8dbae38286 100644 --- a/drivers/mtd/nand/raw/mtk_nand.c +++ b/drivers/mtd/nand/raw/mtk_nand.c @@ -1234,8 +1234,8 @@ static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd) /* if optional dt settings not present */ if (!nand->ecc.size || !nand->ecc.strength) { /* use datasheet requirements */ - nand->ecc.strength = nand->base.eccreq.strength; - nand->ecc.size = nand->base.eccreq.step_size; + nand->ecc.strength = nand->base.ecc.requirements.strength; + nand->ecc.size = nand->base.ecc.requirements.step_size; /* * align eccstrength and eccsize diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 1ce2cbe72e4c..bc2d5d2e8f4c 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -4746,8 +4746,8 @@ static bool find_full_id_nand(struct nand_chip *chip, memorg->pagesize * memorg->pages_per_eraseblock); chip->options |= type->options; - chip->base.eccreq.strength = NAND_ECC_STRENGTH(type); - chip->base.eccreq.step_size = NAND_ECC_STEP(type); + chip->base.ecc.requirements.strength = NAND_ECC_STRENGTH(type); + chip->base.ecc.requirements.step_size = NAND_ECC_STEP(type); chip->onfi_timing_mode_default = type->onfi_timing_mode_default; @@ -5485,8 +5485,8 @@ nand_match_ecc_req(struct nand_chip *chip, { struct mtd_info *mtd = nand_to_mtd(chip); const struct nand_ecc_step_info *stepinfo; - int req_step = chip->base.eccreq.step_size; - int req_strength = chip->base.eccreq.strength; + int req_step = chip->base.ecc.requirements.step_size; + int req_strength = chip->base.ecc.requirements.strength; int req_corr, step_size, strength, nsteps, ecc_bytes, ecc_bytes_total; int best_step, best_strength, best_ecc_bytes; int best_ecc_bytes_total = INT_MAX; @@ -5677,9 +5677,10 @@ static bool nand_ecc_strength_good(struct nand_chip *chip) { struct mtd_info *mtd = nand_to_mtd(chip); struct nand_ecc_ctrl *ecc = &chip->ecc; + struct nand_ecc_props *requirements = &chip->base.ecc.requirements; int corr, ds_corr; - if (ecc->size == 0 || chip->base.eccreq.step_size == 0) + if (ecc->size == 0 || requirements->step_size == 0) /* Not enough information */ return true; @@ -5688,10 +5689,10 @@ static bool nand_ecc_strength_good(struct nand_chip *chip) * the correction density. */ corr = (mtd->writesize * ecc->strength) / ecc->size; - ds_corr = (mtd->writesize * chip->base.eccreq.strength) / - chip->base.eccreq.step_size; + ds_corr = (mtd->writesize * requirements->strength) / + requirements->step_size; - return corr >= ds_corr && ecc->strength >= chip->base.eccreq.strength; + return corr >= ds_corr && ecc->strength >= requirements->strength; } static int rawnand_erase(struct nand_device *nand, const struct nand_pos *pos) @@ -5977,9 +5978,11 @@ static int nand_scan_tail(struct nand_chip *chip) /* ECC sanity check: warn if it's too weak */ if (!nand_ecc_strength_good(chip)) pr_warn("WARNING: %s: the ECC used on your system (%db/%dB) is too weak compared to the one required by the NAND chip (%db/%dB)\n", - mtd->name, chip->ecc.strength, chip->ecc.size, - chip->base.eccreq.strength, - chip->base.eccreq.step_size); + mtd->name, + chip->base.ecc.ctx.conf.strength, + chip->base.ecc.ctx.conf.step_size, + chip->base.ecc.requirements.strength, + chip->base.ecc.requirements.step_size); /* Allow subpage writes up to ecc.steps. Not possible for MLC flash */ if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) { diff --git a/drivers/mtd/nand/raw/nand_esmt.c b/drivers/mtd/nand/raw/nand_esmt.c index 3338c68aaaf1..11f25ec3e4fc 100644 --- a/drivers/mtd/nand/raw/nand_esmt.c +++ b/drivers/mtd/nand/raw/nand_esmt.c @@ -10,24 +10,25 @@ static void esmt_nand_decode_id(struct nand_chip *chip) { + struct nand_ecc_props *requirements = &chip->base.ecc.requirements; nand_decode_ext_id(chip); /* Extract ECC requirements from 5th id byte. */ if (chip->id.len >= 5 && nand_is_slc(chip)) { - chip->base.eccreq.step_size = 512; + requirements->step_size = 512; switch (chip->id.data[4] & 0x3) { case 0x0: - chip->base.eccreq.strength = 4; + requirements->strength = 4; break; case 0x1: - chip->base.eccreq.strength = 2; + requirements->strength = 2; break; case 0x2: - chip->base.eccreq.strength = 1; + requirements->strength = 1; break; default: WARN(1, "Could not get ECC info"); - chip->base.eccreq.step_size = 0; + requirements->step_size = 0; break; } } diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c index 7caedaa5b9e5..bac7732a86e9 100644 --- a/drivers/mtd/nand/raw/nand_hynix.c +++ b/drivers/mtd/nand/raw/nand_hynix.c @@ -495,34 +495,35 @@ static void hynix_nand_extract_oobsize(struct nand_chip *chip, static void hynix_nand_extract_ecc_requirements(struct nand_chip *chip, bool valid_jedecid) { + struct nand_ecc_props *requirements = &chip->base.ecc.requirements; u8 ecc_level = (chip->id.data[4] >> 4) & 0x7; if (valid_jedecid) { /* Reference: H27UCG8T2E datasheet */ - chip->base.eccreq.step_size = 1024; + requirements->step_size = 1024; switch (ecc_level) { case 0: - chip->base.eccreq.step_size = 0; - chip->base.eccreq.strength = 0; + requirements->step_size = 0; + requirements->strength = 0; break; case 1: - chip->base.eccreq.strength = 4; + requirements->strength = 4; break; case 2: - chip->base.eccreq.strength = 24; + requirements->strength = 24; break; case 3: - chip->base.eccreq.strength = 32; + requirements->strength = 32; break; case 4: - chip->base.eccreq.strength = 40; + requirements->strength = 40; break; case 5: - chip->base.eccreq.strength = 50; + requirements->strength = 50; break; case 6: - chip->base.eccreq.strength = 60; + requirements->strength = 60; break; default: /* @@ -543,14 +544,14 @@ static void hynix_nand_extract_ecc_requirements(struct nand_chip *chip, if (nand_tech < 3) { /* > 26nm, reference: H27UBG8T2A datasheet */ if (ecc_level < 5) { - chip->base.eccreq.step_size = 512; - chip->base.eccreq.strength = 1 << ecc_level; + requirements->step_size = 512; + requirements->strength = 1 << ecc_level; } else if (ecc_level < 7) { if (ecc_level == 5) - chip->base.eccreq.step_size = 2048; + requirements->step_size = 2048; else - chip->base.eccreq.step_size = 1024; - chip->base.eccreq.strength = 24; + requirements->step_size = 1024; + requirements->strength = 24; } else { /* * We should never reach this case, but if that @@ -563,14 +564,14 @@ static void hynix_nand_extract_ecc_requirements(struct nand_chip *chip, } else { /* <= 26nm, reference: H27UBG8T2B datasheet */ if (!ecc_level) { - chip->base.eccreq.step_size = 0; - chip->base.eccreq.strength = 0; + requirements->step_size = 0; + requirements->strength = 0; } else if (ecc_level < 5) { - chip->base.eccreq.step_size = 512; - chip->base.eccreq.strength = 1 << (ecc_level - 1); + requirements->step_size = 512; + requirements->strength = 1 << (ecc_level - 1); } else { - chip->base.eccreq.step_size = 1024; - chip->base.eccreq.strength = 24 + + requirements->step_size = 1024; + requirements->strength = 24 + (8 * (ecc_level - 5)); } } diff --git a/drivers/mtd/nand/raw/nand_jedec.c b/drivers/mtd/nand/raw/nand_jedec.c index b15c42f48755..5ed3656d88dd 100644 --- a/drivers/mtd/nand/raw/nand_jedec.c +++ b/drivers/mtd/nand/raw/nand_jedec.c @@ -120,8 +120,8 @@ int nand_jedec_detect(struct nand_chip *chip) ecc = &p->ecc_info[0]; if (ecc->codeword_size >= 9) { - chip->base.eccreq.strength = ecc->ecc_bits; - chip->base.eccreq.step_size = 1 << ecc->codeword_size; + chip->base.ecc.requirements.strength = ecc->ecc_bits; + chip->base.ecc.requirements.step_size = 1 << ecc->codeword_size; } else { pr_warn("Invalid codeword size\n"); } diff --git a/drivers/mtd/nand/raw/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c index c8ebfd8c77a1..d1dc684ecd6c 100644 --- a/drivers/mtd/nand/raw/nand_micron.c +++ b/drivers/mtd/nand/raw/nand_micron.c @@ -413,6 +413,7 @@ enum { */ static int micron_supports_on_die_ecc(struct nand_chip *chip) { + struct nand_ecc_props *requirements = &chip->base.ecc.requirements; u8 id[5]; int ret; @@ -425,7 +426,7 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip) /* * We only support on-die ECC of 4/512 or 8/512 */ - if (chip->base.eccreq.strength != 4 && chip->base.eccreq.strength != 8) + if (requirements->strength != 4 && requirements->strength != 8) return MICRON_ON_DIE_UNSUPPORTED; /* 0x2 means on-die ECC is available. */ @@ -466,7 +467,7 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip) /* * We only support on-die ECC of 4/512 or 8/512 */ - if (chip->base.eccreq.strength != 4 && chip->base.eccreq.strength != 8) + if (requirements->strength != 4 && requirements->strength != 8) return MICRON_ON_DIE_UNSUPPORTED; return MICRON_ON_DIE_SUPPORTED; @@ -474,6 +475,7 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip) static int micron_nand_init(struct nand_chip *chip) { + struct nand_ecc_props *requirements = &chip->base.ecc.requirements; struct mtd_info *mtd = nand_to_mtd(chip); struct micron_nand *micron; int ondie; @@ -523,7 +525,7 @@ static int micron_nand_init(struct nand_chip *chip) * That's not needed for 8-bit ECC, because the status expose * a better approximation of the number of bitflips in a page. */ - if (chip->base.eccreq.strength == 4) { + if (requirements->strength == 4) { micron->ecc.rawbuf = kmalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL); @@ -533,16 +535,16 @@ static int micron_nand_init(struct nand_chip *chip) } } - if (chip->base.eccreq.strength == 4) + if (requirements->strength == 4) mtd_set_ooblayout(mtd, µn_nand_on_die_4_ooblayout_ops); else mtd_set_ooblayout(mtd, µn_nand_on_die_8_ooblayout_ops); - chip->ecc.bytes = chip->base.eccreq.strength * 2; + chip->ecc.bytes = requirements->strength * 2; chip->ecc.size = 512; - chip->ecc.strength = chip->base.eccreq.strength; + chip->ecc.strength = requirements->strength; chip->ecc.algo = NAND_ECC_ALGO_BCH; chip->ecc.read_page = micron_nand_read_page_on_die_ecc; chip->ecc.write_page = micron_nand_write_page_on_die_ecc; diff --git a/drivers/mtd/nand/raw/nand_onfi.c b/drivers/mtd/nand/raw/nand_onfi.c index be3456627288..c9ae29774c1f 100644 --- a/drivers/mtd/nand/raw/nand_onfi.c +++ b/drivers/mtd/nand/raw/nand_onfi.c @@ -94,8 +94,8 @@ static int nand_flash_detect_ext_param_page(struct nand_chip *chip, goto ext_out; } - chip->base.eccreq.strength = ecc->ecc_bits; - chip->base.eccreq.step_size = 1 << ecc->codeword_size; + chip->base.ecc.requirements.strength = ecc->ecc_bits; + chip->base.ecc.requirements.step_size = 1 << ecc->codeword_size; ret = 0; ext_out: @@ -265,8 +265,8 @@ int nand_onfi_detect(struct nand_chip *chip) chip->options |= NAND_BUSWIDTH_16; if (p->ecc_bits != 0xff) { - chip->base.eccreq.strength = p->ecc_bits; - chip->base.eccreq.step_size = 512; + chip->base.ecc.requirements.strength = p->ecc_bits; + chip->base.ecc.requirements.step_size = 512; } else if (onfi_version >= 21 && (le16_to_cpu(p->features) & ONFI_FEATURE_EXT_PARAM_PAGE)) { diff --git a/drivers/mtd/nand/raw/nand_samsung.c b/drivers/mtd/nand/raw/nand_samsung.c index 3a4a19e808f6..0ee85e88aeb5 100644 --- a/drivers/mtd/nand/raw/nand_samsung.c +++ b/drivers/mtd/nand/raw/nand_samsung.c @@ -10,6 +10,7 @@ static void samsung_nand_decode_id(struct nand_chip *chip) { + struct nand_ecc_props *requirements = &chip->base.ecc.requirements; struct mtd_info *mtd = nand_to_mtd(chip); struct nand_memory_organization *memorg; @@ -71,23 +72,23 @@ static void samsung_nand_decode_id(struct nand_chip *chip) /* Extract ECC requirements from 5th id byte*/ extid = (chip->id.data[4] >> 4) & 0x07; if (extid < 5) { - chip->base.eccreq.step_size = 512; - chip->base.eccreq.strength = 1 << extid; + requirements->step_size = 512; + requirements->strength = 1 << extid; } else { - chip->base.eccreq.step_size = 1024; + requirements->step_size = 1024; switch (extid) { case 5: - chip->base.eccreq.strength = 24; + requirements->strength = 24; break; case 6: - chip->base.eccreq.strength = 40; + requirements->strength = 40; break; case 7: - chip->base.eccreq.strength = 60; + requirements->strength = 60; break; default: WARN(1, "Could not decode ECC info"); - chip->base.eccreq.step_size = 0; + requirements->step_size = 0; } } } else { @@ -97,8 +98,8 @@ static void samsung_nand_decode_id(struct nand_chip *chip) switch (chip->id.data[1]) { /* K9F4G08U0D-S[I|C]B0(T00) */ case 0xDC: - chip->base.eccreq.step_size = 512; - chip->base.eccreq.strength = 1; + requirements->step_size = 512; + requirements->strength = 1; break; /* K9F1G08U0E 21nm chips do not support subpage write */ diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c index 436ed90a90ad..1180068007a9 100644 --- a/drivers/mtd/nand/raw/nand_toshiba.c +++ b/drivers/mtd/nand/raw/nand_toshiba.c @@ -145,6 +145,7 @@ static void toshiba_nand_benand_init(struct nand_chip *chip) static void toshiba_nand_decode_id(struct nand_chip *chip) { + struct nand_ecc_props *requirements = &chip->base.ecc.requirements; struct mtd_info *mtd = nand_to_mtd(chip); struct nand_memory_organization *memorg; @@ -175,20 +176,20 @@ static void toshiba_nand_decode_id(struct nand_chip *chip) * - 24nm: 8 bit ECC for each 512Byte is required. */ if (chip->id.len >= 6 && nand_is_slc(chip)) { - chip->base.eccreq.step_size = 512; + requirements->step_size = 512; switch (chip->id.data[5] & 0x7) { case 0x4: - chip->base.eccreq.strength = 1; + requirements->strength = 1; break; case 0x5: - chip->base.eccreq.strength = 4; + requirements->strength = 4; break; case 0x6: - chip->base.eccreq.strength = 8; + requirements->strength = 8; break; default: WARN(1, "Could not get ECC info"); - chip->base.eccreq.step_size = 0; + requirements->step_size = 0; break; } } diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index c6dd2e6d9ef8..a5eefdf89660 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1732,6 +1732,7 @@ static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc) static int sunxi_nand_attach_chip(struct nand_chip *nand) { + struct nand_ecc_props *requirements = &nand->base.ecc.requirements; struct nand_ecc_ctrl *ecc = &nand->ecc; struct device_node *np = nand_get_flash_node(nand); int ret; @@ -1745,8 +1746,8 @@ static int sunxi_nand_attach_chip(struct nand_chip *nand) nand->options |= NAND_SUBPAGE_READ; if (!ecc->size) { - ecc->size = nand->base.eccreq.step_size; - ecc->strength = nand->base.eccreq.strength; + ecc->size = requirements->step_size; + ecc->strength = requirements->strength; } if (!ecc->size || !ecc->strength) diff --git a/drivers/mtd/nand/raw/tegra_nand.c b/drivers/mtd/nand/raw/tegra_nand.c index 2325b06ccc9a..8264bb991d03 100644 --- a/drivers/mtd/nand/raw/tegra_nand.c +++ b/drivers/mtd/nand/raw/tegra_nand.c @@ -855,7 +855,7 @@ static int tegra_nand_get_strength(struct nand_chip *chip, const int *strength, } else { strength_sel = strength[i]; - if (strength_sel < chip->base.eccreq.strength) + if (strength_sel < chip->base.ecc.requirements.strength) continue; } @@ -908,6 +908,7 @@ static int tegra_nand_select_strength(struct nand_chip *chip, int oobsize) static int tegra_nand_attach_chip(struct nand_chip *chip) { struct tegra_nand_controller *ctrl = to_tegra_ctrl(chip->controller); + struct nand_ecc_props *requirements = &chip->base.ecc.requirements; struct tegra_nand_chip *nand = to_tegra_chip(chip); struct mtd_info *mtd = nand_to_mtd(chip); int bits_per_step; @@ -919,9 +920,9 @@ static int tegra_nand_attach_chip(struct nand_chip *chip) chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; chip->ecc.size = 512; chip->ecc.steps = mtd->writesize / chip->ecc.size; - if (chip->base.eccreq.step_size != 512) { + if (requirements->step_size != 512) { dev_err(ctrl->dev, "Unsupported step size %d\n", - chip->base.eccreq.step_size); + requirements->step_size); return -EINVAL; } @@ -952,7 +953,7 @@ static int tegra_nand_attach_chip(struct nand_chip *chip) if (ret < 0) { dev_err(ctrl->dev, "No valid strength found, minimum %d\n", - chip->base.eccreq.strength); + requirements->strength); return ret; } diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index 6f6ec8aa143d..edc8ec2923d5 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -419,7 +419,7 @@ static int spinand_check_ecc_status(struct spinand_device *spinand, u8 status) * fixed, so let's return the maximum possible value so that * wear-leveling layers move the data immediately. */ - return nand->eccreq.strength; + return nand->ecc.ctx.conf.strength; case STATUS_ECC_UNCOR_ERROR: return -EBADMSG; @@ -903,7 +903,7 @@ int spinand_match_and_init(struct spinand_device *spinand, continue; nand->memorg = table[i].memorg; - nand->eccreq = table[i].eccreq; + nand->ecc.requirements = table[i].eccreq; spinand->eccinfo = table[i].eccinfo; spinand->flags = table[i].flags; spinand->id.len = 1 + table[i].devid.len; @@ -1091,8 +1091,8 @@ static int spinand_init(struct spinand_device *spinand) mtd->oobavail = ret; /* Propagate ECC information to mtd_info */ - mtd->ecc_strength = nand->eccreq.strength; - mtd->ecc_step_size = nand->eccreq.step_size; + mtd->ecc_strength = nand->ecc.ctx.conf.strength; + mtd->ecc_step_size = nand->ecc.ctx.conf.step_size; return 0; diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c index 0f900f3aa21a..9db55828a995 100644 --- a/drivers/mtd/nand/spi/macronix.c +++ b/drivers/mtd/nand/spi/macronix.c @@ -84,10 +84,10 @@ static int mx35lf1ge4ab_ecc_get_status(struct spinand_device *spinand, * data around if it's not necessary. */ if (mx35lf1ge4ab_get_eccsr(spinand, &eccsr)) - return nand->eccreq.strength; + return nand->ecc.ctx.conf.strength; - if (WARN_ON(eccsr > nand->eccreq.strength || !eccsr)) - return nand->eccreq.strength; + if (WARN_ON(eccsr > nand->ecc.ctx.conf.strength || !eccsr)) + return nand->ecc.ctx.conf.strength; return eccsr; diff --git a/drivers/mtd/nand/spi/toshiba.c b/drivers/mtd/nand/spi/toshiba.c index bc801d83343e..c3e5b1a85e3e 100644 --- a/drivers/mtd/nand/spi/toshiba.c +++ b/drivers/mtd/nand/spi/toshiba.c @@ -90,12 +90,12 @@ static int tx58cxgxsxraix_ecc_get_status(struct spinand_device *spinand, * data around if it's not necessary. */ if (spi_mem_exec_op(spinand->spimem, &op)) - return nand->eccreq.strength; + return nand->ecc.ctx.conf.strength; mbf >>= 4; - if (WARN_ON(mbf > nand->eccreq.strength || !mbf)) - return nand->eccreq.strength; + if (WARN_ON(mbf > nand->ecc.ctx.conf.strength || !mbf)) + return nand->ecc.ctx.conf.strength; return mbf; diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 2f838394b5f7..975ddf26ac8c 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -290,7 +290,7 @@ struct nand_ecc { * struct nand_device - NAND device * @mtd: MTD instance attached to the NAND device * @memorg: memory layout - * @eccreq: ECC requirements + * @ecc: NAND ECC object attached to the NAND device * @rowconv: position to row address converter * @bbt: bad block table info * @ops: NAND operations attached to the NAND device @@ -298,8 +298,8 @@ struct nand_ecc { * Generic NAND object. Specialized NAND layers (raw NAND, SPI NAND, OneNAND) * should declare their own NAND object embedding a nand_device struct (that's * how inheritance is done). - * struct_nand_device->memorg and struct_nand_device->eccreq should be filled - * at device detection time to reflect the NAND device + * struct_nand_device->memorg and struct_nand_device->ecc.ctx.conf should + * be filled at device detection time to reflect the NAND device * capabilities/requirements. Once this is done nanddev_init() can be called. * It will take care of converting NAND information into MTD ones, which means * the specialized NAND layers should never manually tweak @@ -308,7 +308,7 @@ struct nand_ecc { struct nand_device { struct mtd_info mtd; struct nand_memory_organization memorg; - struct nand_ecc_props eccreq; + struct nand_ecc ecc; struct nand_row_converter rowconv; struct nand_bbt bbt; const struct nand_ops *ops;
Embed a generic NAND ECC high-level object in the nand_device structure to carry all the ECC engine configuration/data. Adapt the raw NAND and SPI-NAND cores to fit the change. Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> --- drivers/mtd/nand/raw/atmel/nand-controller.c | 9 +++-- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 7 ++-- drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 12 +++--- drivers/mtd/nand/raw/marvell_nand.c | 7 ++-- drivers/mtd/nand/raw/mtk_nand.c | 4 +- drivers/mtd/nand/raw/nand_base.c | 25 ++++++------ drivers/mtd/nand/raw/nand_esmt.c | 11 +++--- drivers/mtd/nand/raw/nand_hynix.c | 41 ++++++++++---------- drivers/mtd/nand/raw/nand_jedec.c | 4 +- drivers/mtd/nand/raw/nand_micron.c | 14 ++++--- drivers/mtd/nand/raw/nand_onfi.c | 8 ++-- drivers/mtd/nand/raw/nand_samsung.c | 19 ++++----- drivers/mtd/nand/raw/nand_toshiba.c | 11 +++--- drivers/mtd/nand/raw/sunxi_nand.c | 5 ++- drivers/mtd/nand/raw/tegra_nand.c | 9 +++-- drivers/mtd/nand/spi/core.c | 8 ++-- drivers/mtd/nand/spi/macronix.c | 6 +-- drivers/mtd/nand/spi/toshiba.c | 6 +-- include/linux/mtd/nand.h | 8 ++-- 19 files changed, 114 insertions(+), 100 deletions(-)