Subject: Re: [PATCH v7 16/20] mtd: nand: Convert generic NAND bits to use the ECC framework

From: Boris Brezillon <[email-masked]>
Date: Fri, 29 May 2020 10:32:22 +0200

On Fri, 29 May 2020 02:25:13 +0200
Miquel Raynal <[email-masked]> 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 <[email-masked]>
> ---
>  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,
>  					  &micron_nand_on_die_4_ooblayout_ops);
>  		else
>  			mtd_set_ooblayout(mtd,
>  					  &micron_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;

_______________________________________________
linux-arm-kernel mailing list
[email-masked]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel