Commit 90f4ad03 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull mtd fixes from Miquel Raynal:

 - Rockchip NAND controller driver was not checking the timings properly
   and the introduction of NV-DDR support broke it.

 - The core was also misbehaving in some very specific cases: in case of
   (unlikely) bitflips in the parameter page, the fallback might have
   failed as well but for software reasons.

 - Finally, the chosen ECC configuration was no longer properly
   propagated to upper layers, mostly failing an info message at probe
   time.

* tag 'mtd/fixes-for-6.10-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux:
  mtd: rawnand: rockchip: ensure NVDDR timings are rejected
  mtd: rawnand: Bypass a couple of sanity checks during NAND identification
  mtd: rawnand: Fix the nand_read_data_op() early check
  mtd: rawnand: Ensure ECC configuration is propagated to upper layers
parents 9b458a26 b27d8946
Loading
Loading
Loading
Loading
+40 −26
Original line number Diff line number Diff line
@@ -1093,7 +1093,10 @@ static int nand_fill_column_cycles(struct nand_chip *chip, u8 *addrs,
				   unsigned int offset_in_page)
{
	struct mtd_info *mtd = nand_to_mtd(chip);
	bool ident_stage = !mtd->writesize;

	/* Bypass all checks during NAND identification */
	if (likely(!ident_stage)) {
		/* Make sure the offset is less than the actual page size. */
		if (offset_in_page > mtd->writesize + mtd->oobsize)
			return -EINVAL;
@@ -1116,6 +1119,7 @@ static int nand_fill_column_cycles(struct nand_chip *chip, u8 *addrs,

			offset_in_page /= 2;
		}
	}

	addrs[0] = offset_in_page;

@@ -1123,7 +1127,7 @@ static int nand_fill_column_cycles(struct nand_chip *chip, u8 *addrs,
	 * Small page NANDs use 1 cycle for the columns, while large page NANDs
	 * need 2
	 */
	if (mtd->writesize <= 512)
	if (!ident_stage && mtd->writesize <= 512)
		return 1;

	addrs[1] = offset_in_page >> 8;
@@ -1436,16 +1440,19 @@ int nand_change_read_column_op(struct nand_chip *chip,
			       unsigned int len, bool force_8bit)
{
	struct mtd_info *mtd = nand_to_mtd(chip);
	bool ident_stage = !mtd->writesize;

	if (len && !buf)
		return -EINVAL;

	if (!ident_stage) {
		if (offset_in_page + len > mtd->writesize + mtd->oobsize)
			return -EINVAL;

		/* Small page NANDs do not support column change. */
		if (mtd->writesize <= 512)
			return -ENOTSUPP;
	}

	if (nand_has_exec_op(chip)) {
		const struct nand_interface_config *conf =
@@ -2173,7 +2180,7 @@ EXPORT_SYMBOL_GPL(nand_reset_op);
int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len,
		      bool force_8bit, bool check_only)
{
	if (!len || !buf)
	if (!len || (!check_only && !buf))
		return -EINVAL;

	if (nand_has_exec_op(chip)) {
@@ -6301,6 +6308,7 @@ static const struct nand_ops rawnand_ops = {
static int nand_scan_tail(struct nand_chip *chip)
{
	struct mtd_info *mtd = nand_to_mtd(chip);
	struct nand_device *base = &chip->base;
	struct nand_ecc_ctrl *ecc = &chip->ecc;
	int ret, i;

@@ -6445,9 +6453,13 @@ static int nand_scan_tail(struct nand_chip *chip)
	if (!ecc->write_oob_raw)
		ecc->write_oob_raw = ecc->write_oob;

	/* propagate ecc info to mtd_info */
	/* Propagate ECC info to the generic NAND and MTD layers */
	mtd->ecc_strength = ecc->strength;
	if (!base->ecc.ctx.conf.strength)
		base->ecc.ctx.conf.strength = ecc->strength;
	mtd->ecc_step_size = ecc->size;
	if (!base->ecc.ctx.conf.step_size)
		base->ecc.ctx.conf.step_size = ecc->size;

	/*
	 * Set the number of read / write steps for one page depending on ECC
@@ -6455,6 +6467,8 @@ static int nand_scan_tail(struct nand_chip *chip)
	 */
	if (!ecc->steps)
		ecc->steps = mtd->writesize / ecc->size;
	if (!base->ecc.ctx.nsteps)
		base->ecc.ctx.nsteps = ecc->steps;
	if (ecc->steps * ecc->size != mtd->writesize) {
		WARN(1, "Invalid ECC parameters\n");
		ret = -EINVAL;
+3 −3
Original line number Diff line number Diff line
@@ -420,13 +420,13 @@ static int rk_nfc_setup_interface(struct nand_chip *chip, int target,
	u32 rate, tc2rw, trwpw, trw2c;
	u32 temp;

	if (target < 0)
		return 0;

	timings = nand_get_sdr_timings(conf);
	if (IS_ERR(timings))
		return -EOPNOTSUPP;

	if (target < 0)
		return 0;

	if (IS_ERR(nfc->nfc_clk))
		rate = clk_get_rate(nfc->ahb_clk);
	else