In the raw NAND subsystem, the major fix prevents using cached reads

with devices not supporting it. There was two bug reports about
 this. Aside, 3 drivers (pl353, arasan and marvell) could sometimes hide
 page program failures due to their their own program page helper not
 being fully compliant with the specification (many drivers use the
 default helpers shared by the core). Adding a missing check prevents
 these situation. Finally, the Qualcomm driver had a broken error path.
 
 In the SPI-NAND subsystem one Micron device used a wrong bitmak
 reporting possibly corrupted ECC status.
 
 Finally, the physmap-core got stripped from its map_rom fallback by
 mistake, this feature is added back.
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEE9HuaYnbmDhq/XIDIJWrqGEe9VoQFAmUyvxcACgkQJWrqGEe9
 VoStmwf9HjOY3kNB37ip0NpG5viRWeLNC8hMxJOJaGZlyX6x9b/88xsBjVFc7z3s
 hoCBGfOnUSDXk4KfxNiYps5YqfMgb+yLeIGdsDsLhNht6Mh/YOEFzXgcD8+iudKH
 OpjjJnRzQHxNM3zA3Vauh1XD/j+6uvQ3BHlJpQfA+Ukv4+34Irin4/gKhZCoUedo
 IJNVU5hurJexCkjGk2yO+B34qD8ZXGKWeXzwsKKYB/FE55iO69GrHNdLBMnFfxu+
 uU6GcV+YKroPLDs5mKH2oojKhyAhrh3gQyrNJFnCqh/sVnNCAbD75N+YC6enHeBe
 ovlc82AWmLUJVktsih27OsU58RnCxA==
 =7Xq1
 -----END PGP SIGNATURE-----

Merge tag 'mtd/fixes-for-6.6-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux

Pull MTD fixes from Miquel Raynal:
 "In the raw NAND subsystem, the major fix prevents using cached reads
  with devices not supporting it. There was two bug reports about this.

  Apart from that, three drivers (pl353, arasan and marvell) could
  sometimes hide page program failures due to their their own program
  page helper not being fully compliant with the specification (many
  drivers use the default helpers shared by the core). Adding a missing
  check prevents these situation.

  Finally, the Qualcomm driver had a broken error path.

  In the SPI-NAND subsystem one Micron device used a wrong bitmak
  reporting possibly corrupted ECC status.

  Finally, the physmap-core got stripped from its map_rom fallback by
  mistake, this feature is added back"

* tag 'mtd/fixes-for-6.6-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux:
  mtd: rawnand: Ensure the nand chip supports cached reads
  mtd: rawnand: qcom: Unmap the right resource upon probe failure
  mtd: rawnand: pl353: Ensure program page operations are successful
  mtd: rawnand: arasan: Ensure program page operations are successful
  mtd: spinand: micron: correct bitmask for ecc status
  mtd: physmap-core: Restore map_rom fallback
  mtd: rawnand: marvell: Ensure program page operations are successful
This commit is contained in:
Linus Torvalds 2023-10-20 13:12:34 -07:00
commit f617647154
12 changed files with 73 additions and 5 deletions

View File

@ -551,6 +551,17 @@ static int physmap_flash_probe(struct platform_device *dev)
if (info->probe_type) {
info->mtds[i] = do_map_probe(info->probe_type,
&info->maps[i]);
/* Fall back to mapping region as ROM */
if (!info->mtds[i] && IS_ENABLED(CONFIG_MTD_ROM) &&
strcmp(info->probe_type, "map_rom")) {
dev_warn(&dev->dev,
"map_probe() failed for type %s\n",
info->probe_type);
info->mtds[i] = do_map_probe("map_rom",
&info->maps[i]);
}
} else {
int j;

View File

@ -515,6 +515,7 @@ static int anfc_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf,
struct mtd_info *mtd = nand_to_mtd(chip);
unsigned int len = mtd->writesize + (oob_required ? mtd->oobsize : 0);
dma_addr_t dma_addr;
u8 status;
int ret;
struct anfc_op nfc_op = {
.pkt_reg =
@ -561,10 +562,21 @@ static int anfc_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf,
}
/* Spare data is not protected */
if (oob_required)
if (oob_required) {
ret = nand_write_oob_std(chip, page);
if (ret)
return ret;
}
return ret;
/* Check write status on the chip side */
ret = nand_status_op(chip, &status);
if (ret)
return ret;
if (status & NAND_STATUS_FAIL)
return -EIO;
return 0;
}
static int anfc_sel_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf,

View File

@ -1165,6 +1165,7 @@ static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip,
.ndcb[2] = NDCB2_ADDR5_PAGE(page),
};
unsigned int oob_bytes = lt->spare_bytes + (raw ? lt->ecc_bytes : 0);
u8 status;
int ret;
/* NFCv2 needs more information about the operation being executed */
@ -1198,7 +1199,18 @@ static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip,
ret = marvell_nfc_wait_op(chip,
PSEC_TO_MSEC(sdr->tPROG_max));
return ret;
if (ret)
return ret;
/* Check write status on the chip side */
ret = nand_status_op(chip, &status);
if (ret)
return ret;
if (status & NAND_STATUS_FAIL)
return -EIO;
return 0;
}
static int marvell_nfc_hw_ecc_hmg_write_page_raw(struct nand_chip *chip,
@ -1627,6 +1639,7 @@ static int marvell_nfc_hw_ecc_bch_write_page(struct nand_chip *chip,
int data_len = lt->data_bytes;
int spare_len = lt->spare_bytes;
int chunk, ret;
u8 status;
marvell_nfc_select_target(chip, chip->cur_cs);
@ -1663,6 +1676,14 @@ static int marvell_nfc_hw_ecc_bch_write_page(struct nand_chip *chip,
if (ret)
return ret;
/* Check write status on the chip side */
ret = nand_status_op(chip, &status);
if (ret)
return ret;
if (status & NAND_STATUS_FAIL)
return -EIO;
return 0;
}

View File

@ -5110,6 +5110,9 @@ static void rawnand_check_cont_read_support(struct nand_chip *chip)
{
struct mtd_info *mtd = nand_to_mtd(chip);
if (!chip->parameters.supports_read_cache)
return;
if (chip->read_retries)
return;

View File

@ -94,6 +94,9 @@ int nand_jedec_detect(struct nand_chip *chip)
goto free_jedec_param_page;
}
if (p->opt_cmd[0] & JEDEC_OPT_CMD_READ_CACHE)
chip->parameters.supports_read_cache = true;
memorg->pagesize = le32_to_cpu(p->byte_per_page);
mtd->writesize = memorg->pagesize;

View File

@ -303,6 +303,9 @@ int nand_onfi_detect(struct nand_chip *chip)
ONFI_FEATURE_ADDR_TIMING_MODE, 1);
}
if (le16_to_cpu(p->opt_cmd) & ONFI_OPT_CMD_READ_CACHE)
chip->parameters.supports_read_cache = true;
onfi = kzalloc(sizeof(*onfi), GFP_KERNEL);
if (!onfi) {
ret = -ENOMEM;

View File

@ -511,6 +511,7 @@ static int pl35x_nand_write_page_hwecc(struct nand_chip *chip,
u32 addr1 = 0, addr2 = 0, row;
u32 cmd_addr;
int i, ret;
u8 status;
ret = pl35x_smc_set_ecc_mode(nfc, chip, PL35X_SMC_ECC_CFG_MODE_APB);
if (ret)
@ -563,6 +564,14 @@ static int pl35x_nand_write_page_hwecc(struct nand_chip *chip,
if (ret)
goto disable_ecc_engine;
/* Check write status on the chip side */
ret = nand_status_op(chip, &status);
if (ret)
goto disable_ecc_engine;
if (status & NAND_STATUS_FAIL)
ret = -EIO;
disable_ecc_engine:
pl35x_smc_set_ecc_mode(nfc, chip, PL35X_SMC_ECC_CFG_MODE_BYPASS);

View File

@ -3444,7 +3444,7 @@ static int qcom_nandc_probe(struct platform_device *pdev)
err_aon_clk:
clk_disable_unprepare(nandc->core_clk);
err_core_clk:
dma_unmap_resource(dev, res->start, resource_size(res),
dma_unmap_resource(dev, nandc->base_dma, resource_size(res),
DMA_BIDIRECTIONAL, 0);
return ret;
}

View File

@ -12,7 +12,7 @@
#define SPINAND_MFR_MICRON 0x2c
#define MICRON_STATUS_ECC_MASK GENMASK(7, 4)
#define MICRON_STATUS_ECC_MASK GENMASK(6, 4)
#define MICRON_STATUS_ECC_NO_BITFLIPS (0 << 4)
#define MICRON_STATUS_ECC_1TO3_BITFLIPS (1 << 4)
#define MICRON_STATUS_ECC_4TO6_BITFLIPS (3 << 4)

View File

@ -21,6 +21,9 @@ struct jedec_ecc_info {
/* JEDEC features */
#define JEDEC_FEATURE_16_BIT_BUS (1 << 0)
/* JEDEC Optional Commands */
#define JEDEC_OPT_CMD_READ_CACHE BIT(1)
struct nand_jedec_params {
/* rev info and features block */
/* 'J' 'E' 'S' 'D' */

View File

@ -55,6 +55,7 @@
#define ONFI_SUBFEATURE_PARAM_LEN 4
/* ONFI optional commands SET/GET FEATURES supported? */
#define ONFI_OPT_CMD_READ_CACHE BIT(1)
#define ONFI_OPT_CMD_SET_GET_FEATURES BIT(2)
struct nand_onfi_params {

View File

@ -225,6 +225,7 @@ struct gpio_desc;
* struct nand_parameters - NAND generic parameters from the parameter page
* @model: Model name
* @supports_set_get_features: The NAND chip supports setting/getting features
* @supports_read_cache: The NAND chip supports read cache operations
* @set_feature_list: Bitmap of features that can be set
* @get_feature_list: Bitmap of features that can be get
* @onfi: ONFI specific parameters
@ -233,6 +234,7 @@ struct nand_parameters {
/* Generic parameters */
const char *model;
bool supports_set_get_features;
bool supports_read_cache;
DECLARE_BITMAP(set_feature_list, ONFI_FEATURE_NUMBER);
DECLARE_BITMAP(get_feature_list, ONFI_FEATURE_NUMBER);