From: Sasha Levin Date: Tue, 18 Apr 2023 01:24:53 +0000 (-0400) Subject: Fixes for 5.4 X-Git-Tag: v4.14.313~18^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b83899f646aab2d07895a7b50d3fdaee9fa1741f;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.4 Signed-off-by: Sasha Levin --- diff --git a/queue-5.4/i2c-ocores-generate-stop-condition-after-timeout-in-.patch b/queue-5.4/i2c-ocores-generate-stop-condition-after-timeout-in-.patch new file mode 100644 index 00000000000..c3b25a1440b --- /dev/null +++ b/queue-5.4/i2c-ocores-generate-stop-condition-after-timeout-in-.patch @@ -0,0 +1,106 @@ +From 16cd8aa76c3ca1874f848f19b91edbac878dd628 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Apr 2023 11:37:37 +0200 +Subject: i2c: ocores: generate stop condition after timeout in polling mode + +From: Gregor Herburger + +[ Upstream commit f8160d3b35fc94491bb0cb974dbda310ef96c0e2 ] + +In polling mode, no stop condition is generated after a timeout. This +causes SCL to remain low and thereby block the bus. If this happens +during a transfer it can cause slaves to misinterpret the subsequent +transfer and return wrong values. + +To solve this, pass the ETIMEDOUT error up from ocores_process_polling() +instead of setting STATE_ERROR directly. The caller is adjusted to call +ocores_process_timeout() on error both in polling and in IRQ mode, which +will set STATE_ERROR and generate a stop condition. + +Fixes: 69c8c0c0efa8 ("i2c: ocores: add polling interface") +Signed-off-by: Gregor Herburger +Signed-off-by: Matthias Schiffer +Acked-by: Peter Korsgaard +Reviewed-by: Andrew Lunn +Reviewed-by: Federico Vaga +Signed-off-by: Wolfram Sang +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-ocores.c | 35 ++++++++++++++++++--------------- + 1 file changed, 19 insertions(+), 16 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c +index ca8b3ecfa93d1..1c3595c8a761a 100644 +--- a/drivers/i2c/busses/i2c-ocores.c ++++ b/drivers/i2c/busses/i2c-ocores.c +@@ -343,18 +343,18 @@ static int ocores_poll_wait(struct ocores_i2c *i2c) + * ocores_isr(), we just add our polling code around it. + * + * It can run in atomic context ++ * ++ * Return: 0 on success, -ETIMEDOUT on timeout + */ +-static void ocores_process_polling(struct ocores_i2c *i2c) ++static int ocores_process_polling(struct ocores_i2c *i2c) + { +- while (1) { +- irqreturn_t ret; +- int err; ++ irqreturn_t ret; ++ int err = 0; + ++ while (1) { + err = ocores_poll_wait(i2c); +- if (err) { +- i2c->state = STATE_ERROR; ++ if (err) + break; /* timeout */ +- } + + ret = ocores_isr(-1, i2c); + if (ret == IRQ_NONE) +@@ -365,13 +365,15 @@ static void ocores_process_polling(struct ocores_i2c *i2c) + break; + } + } ++ ++ return err; + } + + static int ocores_xfer_core(struct ocores_i2c *i2c, + struct i2c_msg *msgs, int num, + bool polling) + { +- int ret; ++ int ret = 0; + u8 ctrl; + + ctrl = oc_getreg(i2c, OCI2C_CONTROL); +@@ -389,15 +391,16 @@ static int ocores_xfer_core(struct ocores_i2c *i2c, + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); + + if (polling) { +- ocores_process_polling(i2c); ++ ret = ocores_process_polling(i2c); + } else { +- ret = wait_event_timeout(i2c->wait, +- (i2c->state == STATE_ERROR) || +- (i2c->state == STATE_DONE), HZ); +- if (ret == 0) { +- ocores_process_timeout(i2c); +- return -ETIMEDOUT; +- } ++ if (wait_event_timeout(i2c->wait, ++ (i2c->state == STATE_ERROR) || ++ (i2c->state == STATE_DONE), HZ) == 0) ++ ret = -ETIMEDOUT; ++ } ++ if (ret) { ++ ocores_process_timeout(i2c); ++ return ret; + } + + return (i2c->state == STATE_DONE) ? num : -EIO; +-- +2.39.2 + diff --git a/queue-5.4/mtd-ubi-wl-fix-a-couple-of-kernel-doc-issues.patch b/queue-5.4/mtd-ubi-wl-fix-a-couple-of-kernel-doc-issues.patch new file mode 100644 index 00000000000..65c0c8172f8 --- /dev/null +++ b/queue-5.4/mtd-ubi-wl-fix-a-couple-of-kernel-doc-issues.patch @@ -0,0 +1,51 @@ +From 0440fd5e35d98780a2fcec0f2858cc05779427d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Nov 2020 18:21:55 +0000 +Subject: mtd: ubi: wl: Fix a couple of kernel-doc issues + +From: Lee Jones + +[ Upstream commit ab4e4de9fd8b469823a645f05f2c142e9270b012 ] + +Fixes the following W=1 kernel build warning(s): + + drivers/mtd/ubi/wl.c:584: warning: Function parameter or member 'nested' not described in 'schedule_erase' + drivers/mtd/ubi/wl.c:1075: warning: Excess function parameter 'shutdown' description in '__erase_worker' + +Cc: Richard Weinberger +Cc: Miquel Raynal +Cc: Vignesh Raghavendra +Cc: linux-mtd@lists.infradead.org +Signed-off-by: Lee Jones +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20201109182206.3037326-13-lee.jones@linaro.org +Stable-dep-of: f773f0a331d6 ("ubi: Fix deadlock caused by recursively holding work_sem") +Signed-off-by: Sasha Levin +--- + drivers/mtd/ubi/wl.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c +index 4f88433d4adc7..28110cd4400b5 100644 +--- a/drivers/mtd/ubi/wl.c ++++ b/drivers/mtd/ubi/wl.c +@@ -576,6 +576,7 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, + * @vol_id: the volume ID that last used this PEB + * @lnum: the last used logical eraseblock number for the PEB + * @torture: if the physical eraseblock has to be tortured ++ * @nested: denotes whether the work_sem is already held in read mode + * + * This function returns zero in case of success and a %-ENOMEM in case of + * failure. +@@ -1060,8 +1061,6 @@ static int ensure_wear_leveling(struct ubi_device *ubi, int nested) + * __erase_worker - physical eraseblock erase worker function. + * @ubi: UBI device description object + * @wl_wrk: the work object +- * @shutdown: non-zero if the worker has to free memory and exit +- * because the WL sub-system is shutting down + * + * This function erases a physical eraseblock and perform torture testing if + * needed. It also takes care about marking the physical eraseblock bad if +-- +2.39.2 + diff --git a/queue-5.4/series b/queue-5.4/series index 6a27e6fbcde..5d203e18044 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -67,3 +67,7 @@ efi-sysfb_efi-add-quirk-for-lenovo-yoga-book-x91f-l.patch drm-panel-orientation-quirks-add-quirk-for-lenovo-yo.patch verify_pefile-relax-wrapper-length-check.patch asymmetric_keys-log-on-fatal-failures-in-pe-pkcs7.patch +mtd-ubi-wl-fix-a-couple-of-kernel-doc-issues.patch +ubi-fix-deadlock-caused-by-recursively-holding-work_.patch +ubi-fix-failure-attaching-when-vid_hdr-offset-equals.patch +i2c-ocores-generate-stop-condition-after-timeout-in-.patch diff --git a/queue-5.4/ubi-fix-deadlock-caused-by-recursively-holding-work_.patch b/queue-5.4/ubi-fix-deadlock-caused-by-recursively-holding-work_.patch new file mode 100644 index 00000000000..5403da82ce0 --- /dev/null +++ b/queue-5.4/ubi-fix-deadlock-caused-by-recursively-holding-work_.patch @@ -0,0 +1,66 @@ +From e825d740a2b8c68aeb5b39ab04b500733c3a4a3c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Mar 2023 09:41:41 +0800 +Subject: ubi: Fix deadlock caused by recursively holding work_sem + +From: ZhaoLong Wang + +[ Upstream commit f773f0a331d6c41733b17bebbc1b6cae12e016f5 ] + +During the processing of the bgt, if the sync_erase() return -EBUSY +or some other error code in __erase_worker(),schedule_erase() called +again lead to the down_read(ubi->work_sem) hold twice and may get +block by down_write(ubi->work_sem) in ubi_update_fastmap(), +which cause deadlock. + + ubi bgt other task + do_work + down_read(&ubi->work_sem) ubi_update_fastmap + erase_worker # Blocked by down_read + __erase_worker down_write(&ubi->work_sem) + schedule_erase + schedule_ubi_work + down_read(&ubi->work_sem) + +Fix this by changing input parameter @nested of the schedule_erase() to +'true' to avoid recursively acquiring the down_read(&ubi->work_sem). + +Also, fix the incorrect comment about @nested parameter of the +schedule_erase() because when down_write(ubi->work_sem) is held, the +@nested is also need be true. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=217093 +Fixes: 2e8f08deabbc ("ubi: Fix races around ubi_refill_pools()") +Signed-off-by: ZhaoLong Wang +Reviewed-by: Zhihao Cheng +Signed-off-by: Richard Weinberger +Signed-off-by: Sasha Levin +--- + drivers/mtd/ubi/wl.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c +index 28110cd4400b5..fd0e8f948c3da 100644 +--- a/drivers/mtd/ubi/wl.c ++++ b/drivers/mtd/ubi/wl.c +@@ -576,7 +576,7 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, + * @vol_id: the volume ID that last used this PEB + * @lnum: the last used logical eraseblock number for the PEB + * @torture: if the physical eraseblock has to be tortured +- * @nested: denotes whether the work_sem is already held in read mode ++ * @nested: denotes whether the work_sem is already held + * + * This function returns zero in case of success and a %-ENOMEM in case of + * failure. +@@ -1110,7 +1110,7 @@ static int __erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk) + int err1; + + /* Re-schedule the LEB for erasure */ +- err1 = schedule_erase(ubi, e, vol_id, lnum, 0, false); ++ err1 = schedule_erase(ubi, e, vol_id, lnum, 0, true); + if (err1) { + spin_lock(&ubi->wl_lock); + wl_entry_destroy(ubi, e); +-- +2.39.2 + diff --git a/queue-5.4/ubi-fix-failure-attaching-when-vid_hdr-offset-equals.patch b/queue-5.4/ubi-fix-failure-attaching-when-vid_hdr-offset-equals.patch new file mode 100644 index 00000000000..88153a1b94a --- /dev/null +++ b/queue-5.4/ubi-fix-failure-attaching-when-vid_hdr-offset-equals.patch @@ -0,0 +1,79 @@ +From 78295f107d5e71840da8aa65da48df40fb5d3bea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Mar 2023 09:33:08 +0800 +Subject: ubi: Fix failure attaching when vid_hdr offset equals to (sub)page + size + +From: Zhihao Cheng + +[ Upstream commit 1e020e1b96afdecd20680b5b5be2a6ffc3d27628 ] + +Following process will make ubi attaching failed since commit +1b42b1a36fc946 ("ubi: ensure that VID header offset ... size"): + +ID="0xec,0xa1,0x00,0x15" # 128M 128KB 2KB +modprobe nandsim id_bytes=$ID +flash_eraseall /dev/mtd0 +modprobe ubi mtd="0,2048" # set vid_hdr offset as 2048 (one page) +(dmesg): + ubi0 error: ubi_attach_mtd_dev [ubi]: VID header offset 2048 too large. + UBI error: cannot attach mtd0 + UBI error: cannot initialize UBI, error -22 + +Rework original solution, the key point is making sure +'vid_hdr_shift + UBI_VID_HDR_SIZE < ubi->vid_hdr_alsize', +so we should check vid_hdr_shift rather not vid_hdr_offset. +Then, ubi still support (sub)page aligined VID header offset. + +Fixes: 1b42b1a36fc946 ("ubi: ensure that VID header offset ... size") +Signed-off-by: Zhihao Cheng +Tested-by: Nicolas Schichan +Tested-by: Miquel Raynal # v5.10, v4.19 +Signed-off-by: Richard Weinberger +Signed-off-by: Sasha Levin +--- + drivers/mtd/ubi/build.c | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c +index 13f8292ceea52..f29ed9102ce91 100644 +--- a/drivers/mtd/ubi/build.c ++++ b/drivers/mtd/ubi/build.c +@@ -644,12 +644,6 @@ static int io_init(struct ubi_device *ubi, int max_beb_per1024) + ubi->ec_hdr_alsize = ALIGN(UBI_EC_HDR_SIZE, ubi->hdrs_min_io_size); + ubi->vid_hdr_alsize = ALIGN(UBI_VID_HDR_SIZE, ubi->hdrs_min_io_size); + +- if (ubi->vid_hdr_offset && ((ubi->vid_hdr_offset + UBI_VID_HDR_SIZE) > +- ubi->vid_hdr_alsize)) { +- ubi_err(ubi, "VID header offset %d too large.", ubi->vid_hdr_offset); +- return -EINVAL; +- } +- + dbg_gen("min_io_size %d", ubi->min_io_size); + dbg_gen("max_write_size %d", ubi->max_write_size); + dbg_gen("hdrs_min_io_size %d", ubi->hdrs_min_io_size); +@@ -667,6 +661,21 @@ static int io_init(struct ubi_device *ubi, int max_beb_per1024) + ubi->vid_hdr_aloffset; + } + ++ /* ++ * Memory allocation for VID header is ubi->vid_hdr_alsize ++ * which is described in comments in io.c. ++ * Make sure VID header shift + UBI_VID_HDR_SIZE not exceeds ++ * ubi->vid_hdr_alsize, so that all vid header operations ++ * won't access memory out of bounds. ++ */ ++ if ((ubi->vid_hdr_shift + UBI_VID_HDR_SIZE) > ubi->vid_hdr_alsize) { ++ ubi_err(ubi, "Invalid VID header offset %d, VID header shift(%d)" ++ " + VID header size(%zu) > VID header aligned size(%d).", ++ ubi->vid_hdr_offset, ubi->vid_hdr_shift, ++ UBI_VID_HDR_SIZE, ubi->vid_hdr_alsize); ++ return -EINVAL; ++ } ++ + /* Similar for the data offset */ + ubi->leb_start = ubi->vid_hdr_offset + UBI_VID_HDR_SIZE; + ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size); +-- +2.39.2 +