Skip to content

Commit

Permalink
Merge tag 'mtd/fixes-for-6.6-rc7' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/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
  • Loading branch information
Linus Torvalds committed Oct 20, 2023
2 parents 7da6c04 + f6ca3fb commit f617647
Show file tree
Hide file tree
Showing 12 changed files with 73 additions and 5 deletions.
11 changes: 11 additions & 0 deletions drivers/mtd/maps/physmap-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
16 changes: 14 additions & 2 deletions drivers/mtd/nand/raw/arasan-nand-controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down Expand Up @@ -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,
Expand Down
23 changes: 22 additions & 1 deletion drivers/mtd/nand/raw/marvell_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
}

Expand Down
3 changes: 3 additions & 0 deletions drivers/mtd/nand/raw/nand_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
3 changes: 3 additions & 0 deletions drivers/mtd/nand/raw/nand_jedec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
3 changes: 3 additions & 0 deletions drivers/mtd/nand/raw/nand_onfi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
9 changes: 9 additions & 0 deletions drivers/mtd/nand/raw/pl35x-nand-controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion drivers/mtd/nand/raw/qcom_nandc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/mtd/nand/spi/micron.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions include/linux/mtd/jedec.h
Original file line number Diff line number Diff line change
Expand Up @@ -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' */
Expand Down
1 change: 1 addition & 0 deletions include/linux/mtd/onfi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 2 additions & 0 deletions include/linux/mtd/rawnand.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);

Expand Down

0 comments on commit f617647

Please sign in to comment.