Skip to content

Commit

Permalink
mtd: rawnand: Use nanddev_get/set_ecc_requirements() when relevant
Browse files Browse the repository at this point in the history
Instead of accessing ->strength/step_size directly.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20200827085208.16276-15-miquel.raynal@bootlin.com
  • Loading branch information
Miquel Raynal committed Sep 28, 2020
1 parent 3316c8e commit 53576c7
Show file tree
Hide file tree
Showing 16 changed files with 144 additions and 86 deletions.
10 changes: 6 additions & 4 deletions drivers/mtd/nand/raw/atmel/nand-controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -1043,6 +1043,8 @@ static int atmel_hsmc_nand_pmecc_read_page_raw(struct nand_chip *chip,

static int atmel_nand_pmecc_init(struct nand_chip *chip)
{
const struct nand_ecc_props *requirements =
nanddev_get_ecc_requirements(&chip->base);
struct mtd_info *mtd = nand_to_mtd(chip);
struct atmel_nand *nand = to_atmel_nand(chip);
struct atmel_nand_controller *nc;
Expand Down Expand Up @@ -1072,15 +1074,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;

Expand Down
8 changes: 5 additions & 3 deletions drivers/mtd/nand/raw/brcmnand/brcmnand.c
Original file line number Diff line number Diff line change
Expand Up @@ -2532,6 +2532,8 @@ static int brcmnand_setup_dev(struct brcmnand_host *host)
{
struct mtd_info *mtd = nand_to_mtd(&host->chip);
struct nand_chip *chip = &host->chip;
const struct nand_ecc_props *requirements =
nanddev_get_ecc_requirements(&chip->base);
struct brcmnand_controller *ctrl = host->ctrl;
struct brcmnand_cfg *cfg = &host->hwcfg;
char msg[128];
Expand Down Expand Up @@ -2589,10 +2591,10 @@ 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 (requirements->step_size && requirements->strength) {
/* use detected ECC parameters */
chip->ecc.size = chip->base.eccreq.step_size;
chip->ecc.strength = chip->base.eccreq.strength;
chip->ecc.size = requirements->step_size;
chip->ecc.strength = requirements->strength;
dev_info(ctrl->dev, "Using ECC step-size %d, strength %d\n",
chip->ecc.size, chip->ecc.strength);
}
Expand Down
13 changes: 7 additions & 6 deletions drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
nanddev_get_ecc_requirements(&chip->base)->strength,
nanddev_get_ecc_requirements(&chip->base)->step_size);
return -EINVAL;
}
geo->ecc_chunk_size = ecc_step;
Expand Down Expand Up @@ -510,20 +510,21 @@ static int legacy_set_geometry(struct gpmi_nand_data *this)
static int common_nfc_set_geometry(struct gpmi_nand_data *this)
{
struct nand_chip *chip = &this->nand;
const struct nand_ecc_props *requirements =
nanddev_get_ecc_requirements(&chip->base);

if (chip->ecc.strength > 0 && chip->ecc.size > 0)
return set_geometry_by_ecc_info(this, chip->ecc.strength,
chip->ecc.size);

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 (!(requirements->strength > 0 && requirements->step_size > 0))
return -EINVAL;

return set_geometry_by_ecc_info(this,
chip->base.eccreq.strength,
chip->base.eccreq.step_size);
requirements->strength,
requirements->step_size);
}

return 0;
Expand Down
8 changes: 5 additions & 3 deletions drivers/mtd/nand/raw/marvell_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -2247,14 +2247,16 @@ static int marvell_nand_ecc_init(struct mtd_info *mtd,
struct nand_ecc_ctrl *ecc)
{
struct nand_chip *chip = mtd_to_nand(mtd);
const struct nand_ecc_props *requirements =
nanddev_get_ecc_requirements(&chip->base);
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");
Expand Down
6 changes: 4 additions & 2 deletions drivers/mtd/nand/raw/mtk_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -1253,6 +1253,8 @@ static int mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)
static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd)
{
struct nand_chip *nand = mtd_to_nand(mtd);
const struct nand_ecc_props *requirements =
nanddev_get_ecc_requirements(&nand->base);
struct mtk_nfc *nfc = nand_get_controller_data(nand);
u32 spare;
int free, ret;
Expand All @@ -1266,8 +1268,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 = requirements->strength;
nand->ecc.size = requirements->step_size;

/*
* align eccstrength and eccsize
Expand Down
27 changes: 17 additions & 10 deletions drivers/mtd/nand/raw/nand_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -4750,6 +4750,8 @@ static inline bool is_full_id_nand(struct nand_flash_dev *type)
static bool find_full_id_nand(struct nand_chip *chip,
struct nand_flash_dev *type)
{
struct nand_device *base = &chip->base;
struct nand_ecc_props requirements;
struct mtd_info *mtd = nand_to_mtd(chip);
struct nand_memory_organization *memorg;
u8 *id_data = chip->id.data;
Expand All @@ -4771,8 +4773,9 @@ 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);
requirements.strength = NAND_ECC_STRENGTH(type);
requirements.step_size = NAND_ECC_STEP(type);
nanddev_set_ecc_requirements(base, &requirements);

chip->parameters.model = kstrdup(type->name, GFP_KERNEL);
if (!chip->parameters.model)
Expand Down Expand Up @@ -5472,10 +5475,12 @@ static int
nand_match_ecc_req(struct nand_chip *chip,
const struct nand_ecc_caps *caps, int oobavail)
{
const struct nand_ecc_props *requirements =
nanddev_get_ecc_requirements(&chip->base);
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 = requirements->step_size;
int req_strength = 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;
Expand Down Expand Up @@ -5666,9 +5671,11 @@ 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;
const struct nand_ecc_props *requirements =
nanddev_get_ecc_requirements(&chip->base);
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;

Expand All @@ -5677,10 +5684,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)
Expand Down Expand Up @@ -5967,8 +5974,8 @@ static int nand_scan_tail(struct nand_chip *chip)
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);
nanddev_get_ecc_requirements(&chip->base)->strength,
nanddev_get_ecc_requirements(&chip->base)->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)) {
Expand Down
15 changes: 10 additions & 5 deletions drivers/mtd/nand/raw/nand_esmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,32 @@

static void esmt_nand_decode_id(struct nand_chip *chip)
{
struct nand_device *base = &chip->base;
struct nand_ecc_props 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;
}
}

nanddev_set_ecc_requirements(base, &requirements);
}

static int esmt_nand_init(struct nand_chip *chip)
Expand Down
44 changes: 24 additions & 20 deletions drivers/mtd/nand/raw/nand_hynix.c
Original file line number Diff line number Diff line change
Expand Up @@ -495,34 +495,36 @@ 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_device *base = &chip->base;
struct nand_ecc_props 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:
/*
Expand All @@ -543,14 +545,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
Expand All @@ -563,18 +565,20 @@ 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));
}
}
}

nanddev_set_ecc_requirements(base, &requirements);
}

static void hynix_nand_extract_scrambling_requirements(struct nand_chip *chip,
Expand Down
9 changes: 7 additions & 2 deletions drivers/mtd/nand/raw/nand_jedec.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/
int nand_jedec_detect(struct nand_chip *chip)
{
struct nand_device *base = &chip->base;
struct mtd_info *mtd = nand_to_mtd(chip);
struct nand_memory_organization *memorg;
struct nand_jedec_params *p;
Expand Down Expand Up @@ -120,8 +121,12 @@ 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;
struct nand_ecc_props requirements = {
.strength = ecc->ecc_bits,
.step_size = 1 << ecc->codeword_size,
};

nanddev_set_ecc_requirements(base, &requirements);
} else {
pr_warn("Invalid codeword size\n");
}
Expand Down
Loading

0 comments on commit 53576c7

Please sign in to comment.