From: Greg Kroah-Hartman Date: Mon, 13 Jun 2022 09:24:17 +0000 (+0200) Subject: 4.19-stable patches X-Git-Tag: v4.9.318~24 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ef7f0fb363ccf5f9890080db89412b9f0bd7650a;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: mtd-cfi_cmdset_0002-move-and-rename-chip_check-chip_ready-chip_good_for_write.patch mtd-cfi_cmdset_0002-use-chip_ready-for-write-on-s29gl064n.patch --- diff --git a/queue-4.19/mtd-cfi_cmdset_0002-move-and-rename-chip_check-chip_ready-chip_good_for_write.patch b/queue-4.19/mtd-cfi_cmdset_0002-move-and-rename-chip_check-chip_ready-chip_good_for_write.patch new file mode 100644 index 00000000000..856ba1af6ff --- /dev/null +++ b/queue-4.19/mtd-cfi_cmdset_0002-move-and-rename-chip_check-chip_ready-chip_good_for_write.patch @@ -0,0 +1,234 @@ +From 083084df578a8bdb18334f69e7b32d690aaa3247 Mon Sep 17 00:00:00 2001 +From: Tokunori Ikegami +Date: Thu, 24 Mar 2022 02:04:55 +0900 +Subject: mtd: cfi_cmdset_0002: Move and rename chip_check/chip_ready/chip_good_for_write + +From: Tokunori Ikegami + +commit 083084df578a8bdb18334f69e7b32d690aaa3247 upstream. + +This is a preparation patch for the S29GL064N buffer writes fix. There +is no functional change. + +Link: https://lore.kernel.org/r/b687c259-6413-26c9-d4c9-b3afa69ea124@pengutronix.de/ +Fixes: dfeae1073583("mtd: cfi_cmdset_0002: Change write buffer to check correct value") +Signed-off-by: Tokunori Ikegami +Cc: stable@vger.kernel.org +Acked-by: Vignesh Raghavendra +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20220323170458.5608-2-ikegami.t@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mtd/chips/cfi_cmdset_0002.c | 77 ++++++++++++++---------------------- + 1 file changed, 32 insertions(+), 45 deletions(-) + +--- a/drivers/mtd/chips/cfi_cmdset_0002.c ++++ b/drivers/mtd/chips/cfi_cmdset_0002.c +@@ -731,50 +731,34 @@ static struct mtd_info *cfi_amdstd_setup + } + + /* +- * Return true if the chip is ready. ++ * Return true if the chip is ready and has the correct value. + * + * Ready is one of: read mode, query mode, erase-suspend-read mode (in any + * non-suspended sector) and is indicated by no toggle bits toggling. + * ++ * Error are indicated by toggling bits or bits held with the wrong value, ++ * or with bits toggling. ++ * + * Note that anything more complicated than checking if no bits are toggling + * (including checking DQ5 for an error status) is tricky to get working + * correctly and is therefore not done (particularly with interleaved chips + * as each chip must be checked independently of the others). + */ +-static int __xipram chip_ready(struct map_info *map, unsigned long addr) ++static int __xipram chip_ready(struct map_info *map, unsigned long addr, ++ map_word *expected) + { + map_word d, t; ++ int ret; + + d = map_read(map, addr); + t = map_read(map, addr); + +- return map_word_equal(map, d, t); +-} ++ ret = map_word_equal(map, d, t); + +-/* +- * Return true if the chip is ready and has the correct value. +- * +- * Ready is one of: read mode, query mode, erase-suspend-read mode (in any +- * non-suspended sector) and it is indicated by no bits toggling. +- * +- * Error are indicated by toggling bits or bits held with the wrong value, +- * or with bits toggling. +- * +- * Note that anything more complicated than checking if no bits are toggling +- * (including checking DQ5 for an error status) is tricky to get working +- * correctly and is therefore not done (particularly with interleaved chips +- * as each chip must be checked independently of the others). +- * +- */ +-static int __xipram chip_good(struct map_info *map, unsigned long addr, map_word expected) +-{ +- map_word oldd, curd; +- +- oldd = map_read(map, addr); +- curd = map_read(map, addr); ++ if (!ret || !expected) ++ return ret; + +- return map_word_equal(map, oldd, curd) && +- map_word_equal(map, curd, expected); ++ return map_word_equal(map, t, *expected); + } + + static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode) +@@ -791,7 +775,7 @@ static int get_chip(struct map_info *map + + case FL_STATUS: + for (;;) { +- if (chip_ready(map, adr)) ++ if (chip_ready(map, adr, NULL)) + break; + + if (time_after(jiffies, timeo)) { +@@ -829,7 +813,7 @@ static int get_chip(struct map_info *map + chip->state = FL_ERASE_SUSPENDING; + chip->erase_suspended = 1; + for (;;) { +- if (chip_ready(map, adr)) ++ if (chip_ready(map, adr, NULL)) + break; + + if (time_after(jiffies, timeo)) { +@@ -1360,7 +1344,7 @@ static int do_otp_lock(struct map_info * + /* wait for chip to become ready */ + timeo = jiffies + msecs_to_jiffies(2); + for (;;) { +- if (chip_ready(map, adr)) ++ if (chip_ready(map, adr, NULL)) + break; + + if (time_after(jiffies, timeo)) { +@@ -1627,10 +1611,11 @@ static int __xipram do_write_oneword(str + } + + /* +- * We check "time_after" and "!chip_good" before checking +- * "chip_good" to avoid the failure due to scheduling. ++ * We check "time_after" and "!chip_ready" before checking ++ * "chip_ready" to avoid the failure due to scheduling. + */ +- if (time_after(jiffies, timeo) && !chip_good(map, adr, datum)) { ++ if (time_after(jiffies, timeo) && ++ !chip_ready(map, adr, &datum)) { + xip_enable(map, chip, adr); + printk(KERN_WARNING "MTD %s(): software timeout\n", __func__); + xip_disable(map, chip, adr); +@@ -1638,7 +1623,7 @@ static int __xipram do_write_oneword(str + break; + } + +- if (chip_good(map, adr, datum)) ++ if (chip_ready(map, adr, &datum)) + break; + + /* Latency issues. Drop the lock, wait a while and retry */ +@@ -1882,13 +1867,13 @@ static int __xipram do_write_buffer(stru + } + + /* +- * We check "time_after" and "!chip_good" before checking "chip_good" to avoid +- * the failure due to scheduling. ++ * We check "time_after" and "!chip_ready" before checking ++ * "chip_ready" to avoid the failure due to scheduling. + */ +- if (time_after(jiffies, timeo) && !chip_good(map, adr, datum)) ++ if (time_after(jiffies, timeo) && !chip_ready(map, adr, &datum)) + break; + +- if (chip_good(map, adr, datum)) { ++ if (chip_ready(map, adr, &datum)) { + xip_enable(map, chip, adr); + goto op_done; + } +@@ -2022,7 +2007,7 @@ static int cfi_amdstd_panic_wait(struct + * If the driver thinks the chip is idle, and no toggle bits + * are changing, then the chip is actually idle for sure. + */ +- if (chip->state == FL_READY && chip_ready(map, adr)) ++ if (chip->state == FL_READY && chip_ready(map, adr, NULL)) + return 0; + + /* +@@ -2039,7 +2024,7 @@ static int cfi_amdstd_panic_wait(struct + + /* wait for the chip to become ready */ + for (i = 0; i < jiffies_to_usecs(timeo); i++) { +- if (chip_ready(map, adr)) ++ if (chip_ready(map, adr, NULL)) + return 0; + + udelay(1); +@@ -2103,13 +2088,13 @@ retry: + map_write(map, datum, adr); + + for (i = 0; i < jiffies_to_usecs(uWriteTimeout); i++) { +- if (chip_ready(map, adr)) ++ if (chip_ready(map, adr, NULL)) + break; + + udelay(1); + } + +- if (!chip_good(map, adr, datum)) { ++ if (!chip_ready(map, adr, &datum)) { + /* reset on all failures. */ + map_write(map, CMD(0xF0), chip->start); + /* FIXME - should have reset delay before continuing */ +@@ -2250,6 +2235,7 @@ static int __xipram do_erase_chip(struct + DECLARE_WAITQUEUE(wait, current); + int ret = 0; + int retry_cnt = 0; ++ map_word datum = map_word_ff(map); + + adr = cfi->addr_unlock1; + +@@ -2304,7 +2290,7 @@ static int __xipram do_erase_chip(struct + chip->erase_suspended = 0; + } + +- if (chip_good(map, adr, map_word_ff(map))) ++ if (chip_ready(map, adr, &datum)) + break; + + if (time_after(jiffies, timeo)) { +@@ -2346,6 +2332,7 @@ static int __xipram do_erase_oneblock(st + DECLARE_WAITQUEUE(wait, current); + int ret = 0; + int retry_cnt = 0; ++ map_word datum = map_word_ff(map); + + adr += chip->start; + +@@ -2400,7 +2387,7 @@ static int __xipram do_erase_oneblock(st + chip->erase_suspended = 0; + } + +- if (chip_good(map, adr, map_word_ff(map))) ++ if (chip_ready(map, adr, &datum)) + break; + + if (time_after(jiffies, timeo)) { +@@ -2593,7 +2580,7 @@ static int __maybe_unused do_ppb_xxlock( + */ + timeo = jiffies + msecs_to_jiffies(2000); /* 2s max (un)locking */ + for (;;) { +- if (chip_ready(map, adr)) ++ if (chip_ready(map, adr, NULL)) + break; + + if (time_after(jiffies, timeo)) { diff --git a/queue-4.19/mtd-cfi_cmdset_0002-use-chip_ready-for-write-on-s29gl064n.patch b/queue-4.19/mtd-cfi_cmdset_0002-use-chip_ready-for-write-on-s29gl064n.patch new file mode 100644 index 00000000000..e78f9f66fc9 --- /dev/null +++ b/queue-4.19/mtd-cfi_cmdset_0002-use-chip_ready-for-write-on-s29gl064n.patch @@ -0,0 +1,138 @@ +From 0a8e98305f63deaf0a799d5cf5532cc83af035d1 Mon Sep 17 00:00:00 2001 +From: Tokunori Ikegami +Date: Thu, 24 Mar 2022 02:04:56 +0900 +Subject: mtd: cfi_cmdset_0002: Use chip_ready() for write on S29GL064N + +From: Tokunori Ikegami + +commit 0a8e98305f63deaf0a799d5cf5532cc83af035d1 upstream. + +Since commit dfeae1073583("mtd: cfi_cmdset_0002: Change write buffer to +check correct value") buffered writes fail on S29GL064N. This is +because, on S29GL064N, reads return 0xFF at the end of DQ polling for +write completion, where as, chip_good() check expects actual data +written to the last location to be returned post DQ polling completion. +Fix is to revert to using chip_good() for S29GL064N which only checks +for DQ lines to settle down to determine write completion. + +Link: https://lore.kernel.org/r/b687c259-6413-26c9-d4c9-b3afa69ea124@pengutronix.de/ +Fixes: dfeae1073583("mtd: cfi_cmdset_0002: Change write buffer to check correct value") +Cc: stable@vger.kernel.org +Signed-off-by: Tokunori Ikegami +Acked-by: Vignesh Raghavendra +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20220323170458.5608-3-ikegami.t@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mtd/chips/cfi_cmdset_0002.c | 42 +++++++++++++++++++++++++++++------- + include/linux/mtd/cfi.h | 1 + 2 files changed, 35 insertions(+), 8 deletions(-) + +--- a/drivers/mtd/chips/cfi_cmdset_0002.c ++++ b/drivers/mtd/chips/cfi_cmdset_0002.c +@@ -49,6 +49,10 @@ + #define SST49LF008A 0x005a + #define AT49BV6416 0x00d6 + ++enum cfi_quirks { ++ CFI_QUIRK_DQ_TRUE_DATA = BIT(0), ++}; ++ + static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); + static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); + static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); +@@ -365,6 +369,15 @@ static void fixup_s29ns512p_sectors(stru + mtd->name); + } + ++static void fixup_quirks(struct mtd_info *mtd) ++{ ++ struct map_info *map = mtd->priv; ++ struct cfi_private *cfi = map->fldrv_priv; ++ ++ if (cfi->mfr == CFI_MFR_AMD && cfi->id == 0x0c01) ++ cfi->quirks |= CFI_QUIRK_DQ_TRUE_DATA; ++} ++ + /* Used to fix CFI-Tables of chips without Extended Query Tables */ + static struct cfi_fixup cfi_nopri_fixup_table[] = { + { CFI_MFR_SST, 0x234a, fixup_sst39vf }, /* SST39VF1602 */ +@@ -403,6 +416,7 @@ static struct cfi_fixup cfi_fixup_table[ + #if !FORCE_WORD_WRITE + { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers }, + #endif ++ { CFI_MFR_ANY, CFI_ID_ANY, fixup_quirks }, + { 0, 0, NULL } + }; + static struct cfi_fixup jedec_fixup_table[] = { +@@ -761,6 +775,18 @@ static int __xipram chip_ready(struct ma + return map_word_equal(map, t, *expected); + } + ++static int __xipram chip_good(struct map_info *map, unsigned long addr, ++ map_word *expected) ++{ ++ struct cfi_private *cfi = map->fldrv_priv; ++ map_word *datum = expected; ++ ++ if (cfi->quirks & CFI_QUIRK_DQ_TRUE_DATA) ++ datum = NULL; ++ ++ return chip_ready(map, addr, datum); ++} ++ + static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode) + { + DECLARE_WAITQUEUE(wait, current); +@@ -1611,11 +1637,11 @@ static int __xipram do_write_oneword(str + } + + /* +- * We check "time_after" and "!chip_ready" before checking +- * "chip_ready" to avoid the failure due to scheduling. ++ * We check "time_after" and "!chip_good" before checking ++ * "chip_good" to avoid the failure due to scheduling. + */ + if (time_after(jiffies, timeo) && +- !chip_ready(map, adr, &datum)) { ++ !chip_good(map, adr, &datum)) { + xip_enable(map, chip, adr); + printk(KERN_WARNING "MTD %s(): software timeout\n", __func__); + xip_disable(map, chip, adr); +@@ -1623,7 +1649,7 @@ static int __xipram do_write_oneword(str + break; + } + +- if (chip_ready(map, adr, &datum)) ++ if (chip_good(map, adr, &datum)) + break; + + /* Latency issues. Drop the lock, wait a while and retry */ +@@ -1867,13 +1893,13 @@ static int __xipram do_write_buffer(stru + } + + /* +- * We check "time_after" and "!chip_ready" before checking +- * "chip_ready" to avoid the failure due to scheduling. ++ * We check "time_after" and "!chip_good" before checking ++ * "chip_good" to avoid the failure due to scheduling. + */ +- if (time_after(jiffies, timeo) && !chip_ready(map, adr, &datum)) ++ if (time_after(jiffies, timeo) && !chip_good(map, adr, &datum)) + break; + +- if (chip_ready(map, adr, &datum)) { ++ if (chip_good(map, adr, &datum)) { + xip_enable(map, chip, adr); + goto op_done; + } +--- a/include/linux/mtd/cfi.h ++++ b/include/linux/mtd/cfi.h +@@ -293,6 +293,7 @@ struct cfi_private { + map_word sector_erase_cmd; + unsigned long chipshift; /* Because they're of the same type */ + const char *im_name; /* inter_module name for cmdset_setup */ ++ unsigned long quirks; + struct flchip chips[0]; /* per-chip data structure for each chip */ + }; + diff --git a/queue-4.19/series b/queue-4.19/series index 42c884da4b5..49c38eec5b3 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -284,3 +284,5 @@ ixgbe-fix-unexpected-vlan-rx-in-promisc-mode-on-vf.patch input-bcm5974-set-missing-urb_no_transfer_dma_map-urb-flag.patch powerpc-32-fix-overread-overwrite-of-thread_struct-via-ptrace.patch md-raid0-ignore-raid0-layout-if-the-second-zone-has-only-one-device.patch +mtd-cfi_cmdset_0002-move-and-rename-chip_check-chip_ready-chip_good_for_write.patch +mtd-cfi_cmdset_0002-use-chip_ready-for-write-on-s29gl064n.patch