Commit 03498b71 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull MTD fixes from Miquel Raynal:
 "Core fix:

   - Fix a possible data corruption of the 'part' field in mtd_info

  Rawnand fixes:

   - Fix the check on the return value of wait_for_completion_timeout

   - Fix wrong ECC parameters for mt7622

   - Fix a possible memory corruption that might panic in the Qcom
     driver"

* tag 'mtd/fixes-for-5.18-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux:
  mtd: rawnand: qcom: fix memory corruption that causes panic
  mtd: fix 'part' field data corruption in mtd_info
  mtd: rawnand: Fix return value check of wait_for_completion_timeout
  mtd: rawnand: fix ecc parameters for mt7622
parents 233087ca ba7542eb
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@

struct mtk_ecc_caps {
	u32 err_mask;
	u32 err_shift;
	const u8 *ecc_strength;
	const u32 *ecc_regs;
	u8 num_ecc_strength;
@@ -76,7 +77,7 @@ static const u8 ecc_strength_mt2712[] = {
};

static const u8 ecc_strength_mt7622[] = {
	4, 6, 8, 10, 12, 14, 16
	4, 6, 8, 10, 12
};

enum mtk_ecc_regs {
@@ -221,7 +222,7 @@ void mtk_ecc_get_stats(struct mtk_ecc *ecc, struct mtk_ecc_stats *stats,
	for (i = 0; i < sectors; i++) {
		offset = (i >> 2) << 2;
		err = readl(ecc->regs + ECC_DECENUM0 + offset);
		err = err >> ((i % 4) * 8);
		err = err >> ((i % 4) * ecc->caps->err_shift);
		err &= ecc->caps->err_mask;
		if (err == ecc->caps->err_mask) {
			/* uncorrectable errors */
@@ -449,6 +450,7 @@ EXPORT_SYMBOL(mtk_ecc_get_parity_bits);

static const struct mtk_ecc_caps mtk_ecc_caps_mt2701 = {
	.err_mask = 0x3f,
	.err_shift = 8,
	.ecc_strength = ecc_strength_mt2701,
	.ecc_regs = mt2701_ecc_regs,
	.num_ecc_strength = 20,
@@ -459,6 +461,7 @@ static const struct mtk_ecc_caps mtk_ecc_caps_mt2701 = {

static const struct mtk_ecc_caps mtk_ecc_caps_mt2712 = {
	.err_mask = 0x7f,
	.err_shift = 8,
	.ecc_strength = ecc_strength_mt2712,
	.ecc_regs = mt2712_ecc_regs,
	.num_ecc_strength = 23,
@@ -468,10 +471,11 @@ static const struct mtk_ecc_caps mtk_ecc_caps_mt2712 = {
};

static const struct mtk_ecc_caps mtk_ecc_caps_mt7622 = {
	.err_mask = 0x3f,
	.err_mask = 0x1f,
	.err_shift = 5,
	.ecc_strength = ecc_strength_mt7622,
	.ecc_regs = mt7622_ecc_regs,
	.num_ecc_strength = 7,
	.num_ecc_strength = 5,
	.ecc_mode_shift = 4,
	.parity_bits = 13,
	.pg_irq_sel = 0,
+13 −11
Original line number Diff line number Diff line
@@ -2651,10 +2651,23 @@ static int qcom_nand_attach_chip(struct nand_chip *chip)
	ecc->engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;

	mtd_set_ooblayout(mtd, &qcom_nand_ooblayout_ops);
	/* Free the initially allocated BAM transaction for reading the ONFI params */
	if (nandc->props->is_bam)
		free_bam_transaction(nandc);

	nandc->max_cwperpage = max_t(unsigned int, nandc->max_cwperpage,
				     cwperpage);

	/* Now allocate the BAM transaction based on updated max_cwperpage */
	if (nandc->props->is_bam) {
		nandc->bam_txn = alloc_bam_transaction(nandc);
		if (!nandc->bam_txn) {
			dev_err(nandc->dev,
				"failed to allocate bam transaction\n");
			return -ENOMEM;
		}
	}

	/*
	 * DATA_UD_BYTES varies based on whether the read/write command protects
	 * spare data with ECC too. We protect spare data by default, so we set
@@ -2955,17 +2968,6 @@ static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc,
	if (ret)
		return ret;

	if (nandc->props->is_bam) {
		free_bam_transaction(nandc);
		nandc->bam_txn = alloc_bam_transaction(nandc);
		if (!nandc->bam_txn) {
			dev_err(nandc->dev,
				"failed to allocate bam transaction\n");
			nand_cleanup(chip);
			return -ENOMEM;
		}
	}

	ret = mtd_device_parse_register(mtd, probes, NULL, NULL, 0);
	if (ret)
		nand_cleanup(chip);
+8 −6
Original line number Diff line number Diff line
@@ -384,7 +384,8 @@ static int flctl_dma_fifo0_transfer(struct sh_flctl *flctl, unsigned long *buf,
	dma_addr_t dma_addr;
	dma_cookie_t cookie;
	uint32_t reg;
	int ret;
	int ret = 0;
	unsigned long time_left;

	if (dir == DMA_FROM_DEVICE) {
		chan = flctl->chan_fifo0_rx;
@@ -425,13 +426,14 @@ static int flctl_dma_fifo0_transfer(struct sh_flctl *flctl, unsigned long *buf,
		goto out;
	}

	ret =
	time_left =
	wait_for_completion_timeout(&flctl->dma_complete,
				msecs_to_jiffies(3000));

	if (ret <= 0) {
	if (time_left == 0) {
		dmaengine_terminate_all(chan);
		dev_err(&flctl->pdev->dev, "wait_for_completion_timeout\n");
		ret = -ETIMEDOUT;
	}

out:
@@ -441,7 +443,7 @@ static int flctl_dma_fifo0_transfer(struct sh_flctl *flctl, unsigned long *buf,

	dma_unmap_single(chan->device->dev, dma_addr, len, dir);

	/* ret > 0 is success */
	/* ret == 0 is success */
	return ret;
}

@@ -465,7 +467,7 @@ static void read_fiforeg(struct sh_flctl *flctl, int rlen, int offset)

	/* initiate DMA transfer */
	if (flctl->chan_fifo0_rx && rlen >= 32 &&
		flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_FROM_DEVICE) > 0)
		!flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_FROM_DEVICE))
			goto convert;	/* DMA success */

	/* do polling transfer */
@@ -524,7 +526,7 @@ static void write_ec_fiforeg(struct sh_flctl *flctl, int rlen,

	/* initiate DMA transfer */
	if (flctl->chan_fifo0_tx && rlen >= 32 &&
		flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_TO_DEVICE) > 0)
		!flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_TO_DEVICE))
			return;	/* DMA success */

	/* do polling transfer */
+2 −4
Original line number Diff line number Diff line
@@ -389,11 +389,9 @@ struct mtd_info {
	/* List of partitions attached to this MTD device */
	struct list_head partitions;

	union {
	struct mtd_part part;
	struct mtd_master master;
};
};

static inline struct mtd_info *mtd_get_master(struct mtd_info *mtd)
{