From: Sasha Levin Date: Mon, 1 Jul 2024 00:09:14 +0000 (-0400) Subject: Fixes for 4.19 X-Git-Tag: v4.19.317~112 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=58e3c532ebbc410b56a078b289ff771c54452195;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 4.19 Signed-off-by: Sasha Levin --- diff --git a/queue-4.19/i2c-ocores-set-iack-bit-after-core-is-enabled.patch b/queue-4.19/i2c-ocores-set-iack-bit-after-core-is-enabled.patch new file mode 100644 index 00000000000..37288389a84 --- /dev/null +++ b/queue-4.19/i2c-ocores-set-iack-bit-after-core-is-enabled.patch @@ -0,0 +1,44 @@ +From 99bc9c04c215ee00533b69200ee5c59b2a93871b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 May 2024 17:39:32 +0200 +Subject: i2c: ocores: set IACK bit after core is enabled + +From: Grygorii Tertychnyi + +[ Upstream commit 5a72477273066b5b357801ab2d315ef14949d402 ] + +Setting IACK bit when core is disabled does not clear the "Interrupt Flag" +bit in the status register, and the interrupt remains pending. + +Sometimes it causes failure for the very first message transfer, that is +usually a device probe. + +Hence, set IACK bit after core is enabled to clear pending interrupt. + +Fixes: 18f98b1e3147 ("[PATCH] i2c: New bus driver for the OpenCores I2C controller") +Signed-off-by: Grygorii Tertychnyi +Acked-by: Peter Korsgaard +Cc: stable@vger.kernel.org +Signed-off-by: Andi Shyti +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-ocores.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c +index aa852028d8c15..7646d6c99179b 100644 +--- a/drivers/i2c/busses/i2c-ocores.c ++++ b/drivers/i2c/busses/i2c-ocores.c +@@ -290,8 +290,8 @@ static int ocores_init(struct device *dev, struct ocores_i2c *i2c) + oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8); + + /* Init the device */ +- oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK); + oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_IEN | OCI2C_CTRL_EN); ++ oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK); + + return 0; + } +-- +2.43.0 + diff --git a/queue-4.19/i2c-ocores-stop-transfer-on-timeout.patch b/queue-4.19/i2c-ocores-stop-transfer-on-timeout.patch new file mode 100644 index 00000000000..61715ec387b --- /dev/null +++ b/queue-4.19/i2c-ocores-stop-transfer-on-timeout.patch @@ -0,0 +1,192 @@ +From 5cbeaa9e0172a9125dee6bff34248c377fa067b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Feb 2019 09:51:30 +0100 +Subject: i2c: ocores: stop transfer on timeout + +From: Federico Vaga + +[ Upstream commit e7663ef5ae0f02e3b902eb0305dec981333eb3e1 ] + +Detecting a timeout is ok, but we also need to assert a STOP command on +the bus in order to prevent it from generating interrupts when there are +no on going transfers. + +Example: very long transmission. + +1. ocores_xfer: START a transfer +2. ocores_isr : handle byte by byte the transfer +3. ocores_xfer: goes in timeout [[bugfix here]] +4. ocores_xfer: return to I2C subsystem and to the I2C driver +5. I2C driver : it may clean up the i2c_msg memory +6. ocores_isr : receives another interrupt (pending bytes to be + transferred) but the i2c_msg memory is invalid now + +So, since the transfer was too long, we have to detect the timeout and +STOP the transfer. + +Another point is that we have a critical region here. When handling the +timeout condition we may have a running IRQ handler. For this reason I +introduce a spinlock. + +In order to make easier to understan locking I have: +- added a new function to handle timeout +- modified the current ocores_process() function in order to be protected + by the new spinlock +Like this it is obvious at first sight that this locking serializes +the execution of ocores_process() and ocores_process_timeout() + +Signed-off-by: Federico Vaga +Reviewed-by: Andrew Lunn +Signed-off-by: Wolfram Sang +Stable-dep-of: 5a7247727306 ("i2c: ocores: set IACK bit after core is enabled") +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-ocores.c | 54 +++++++++++++++++++++++++++------ + 1 file changed, 45 insertions(+), 9 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c +index 87f9caacba856..aa852028d8c15 100644 +--- a/drivers/i2c/busses/i2c-ocores.c ++++ b/drivers/i2c/busses/i2c-ocores.c +@@ -25,7 +25,12 @@ + #include + #include + #include ++#include + ++/** ++ * @process_lock: protect I2C transfer process. ++ * ocores_process() and ocores_process_timeout() can't run in parallel. ++ */ + struct ocores_i2c { + void __iomem *base; + u32 reg_shift; +@@ -36,6 +41,7 @@ struct ocores_i2c { + int pos; + int nmsgs; + int state; /* see STATE_ */ ++ spinlock_t process_lock; + struct clk *clk; + int ip_clock_khz; + int bus_clock_khz; +@@ -141,19 +147,26 @@ static void ocores_process(struct ocores_i2c *i2c) + { + struct i2c_msg *msg = i2c->msg; + u8 stat = oc_getreg(i2c, OCI2C_STATUS); ++ unsigned long flags; ++ ++ /* ++ * If we spin here is because we are in timeout, so we are going ++ * to be in STATE_ERROR. See ocores_process_timeout() ++ */ ++ spin_lock_irqsave(&i2c->process_lock, flags); + + if ((i2c->state == STATE_DONE) || (i2c->state == STATE_ERROR)) { + /* stop has been sent */ + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK); + wake_up(&i2c->wait); +- return; ++ goto out; + } + + /* error? */ + if (stat & OCI2C_STAT_ARBLOST) { + i2c->state = STATE_ERROR; + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); +- return; ++ goto out; + } + + if ((i2c->state == STATE_START) || (i2c->state == STATE_WRITE)) { +@@ -163,7 +176,7 @@ static void ocores_process(struct ocores_i2c *i2c) + if (stat & OCI2C_STAT_NACK) { + i2c->state = STATE_ERROR; + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); +- return; ++ goto out; + } + } else + msg->buf[i2c->pos++] = oc_getreg(i2c, OCI2C_DATA); +@@ -184,14 +197,14 @@ static void ocores_process(struct ocores_i2c *i2c) + + oc_setreg(i2c, OCI2C_DATA, addr); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); +- return; ++ goto out; + } else + i2c->state = (msg->flags & I2C_M_RD) + ? STATE_READ : STATE_WRITE; + } else { + i2c->state = STATE_DONE; + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); +- return; ++ goto out; + } + } + +@@ -202,6 +215,9 @@ static void ocores_process(struct ocores_i2c *i2c) + oc_setreg(i2c, OCI2C_DATA, msg->buf[i2c->pos++]); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_WRITE); + } ++ ++out: ++ spin_unlock_irqrestore(&i2c->process_lock, flags); + } + + static irqreturn_t ocores_isr(int irq, void *dev_id) +@@ -213,9 +229,24 @@ static irqreturn_t ocores_isr(int irq, void *dev_id) + return IRQ_HANDLED; + } + ++/** ++ * Process timeout event ++ * @i2c: ocores I2C device instance ++ */ ++static void ocores_process_timeout(struct ocores_i2c *i2c) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&i2c->process_lock, flags); ++ i2c->state = STATE_ERROR; ++ oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); ++ spin_unlock_irqrestore(&i2c->process_lock, flags); ++} ++ + static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) + { + struct ocores_i2c *i2c = i2c_get_adapdata(adap); ++ int ret; + + i2c->msg = msgs; + i2c->pos = 0; +@@ -225,11 +256,14 @@ static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) + oc_setreg(i2c, OCI2C_DATA, i2c_8bit_addr_from_msg(i2c->msg)); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); + +- if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) || +- (i2c->state == STATE_DONE), HZ)) +- return (i2c->state == STATE_DONE) ? num : -EIO; +- 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; ++ } ++ ++ return (i2c->state == STATE_DONE) ? num : -EIO; + } + + static int ocores_init(struct device *dev, struct ocores_i2c *i2c) +@@ -422,6 +456,8 @@ static int ocores_i2c_probe(struct platform_device *pdev) + if (!i2c) + return -ENOMEM; + ++ spin_lock_init(&i2c->process_lock); ++ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + i2c->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(i2c->base)) +-- +2.43.0 + diff --git a/queue-4.19/series b/queue-4.19/series index 3a64edf5ea4..6b63162032b 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -123,3 +123,6 @@ nvme-fixup-comment-for-nvme-rdma-provider-type.patch gpio-davinci-use-dev-name-for-label-and-automatic-ba.patch gpio-davinci-allocate-the-correct-amount-of-memory-f.patch gpio-davinci-validate-the-obtained-number-of-irqs.patch +i2c-ocores-stop-transfer-on-timeout.patch +i2c-ocores-set-iack-bit-after-core-is-enabled.patch +x86-stop-playing-stack-games-in-profile_pc.patch diff --git a/queue-4.19/x86-stop-playing-stack-games-in-profile_pc.patch b/queue-4.19/x86-stop-playing-stack-games-in-profile_pc.patch new file mode 100644 index 00000000000..b19f435d2b9 --- /dev/null +++ b/queue-4.19/x86-stop-playing-stack-games-in-profile_pc.patch @@ -0,0 +1,96 @@ +From e474f7465cfb70f14df39c626e12d531a39de276 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Jun 2024 14:27:22 -0700 +Subject: x86: stop playing stack games in profile_pc() + +From: Linus Torvalds + +[ Upstream commit 093d9603b60093a9aaae942db56107f6432a5dca ] + +The 'profile_pc()' function is used for timer-based profiling, which +isn't really all that relevant any more to begin with, but it also ends +up making assumptions based on the stack layout that aren't necessarily +valid. + +Basically, the code tries to account the time spent in spinlocks to the +caller rather than the spinlock, and while I support that as a concept, +it's not worth the code complexity or the KASAN warnings when no serious +profiling is done using timers anyway these days. + +And the code really does depend on stack layout that is only true in the +simplest of cases. We've lost the comment at some point (I think when +the 32-bit and 64-bit code was unified), but it used to say: + + Assume the lock function has either no stack frame or a copy + of eflags from PUSHF. + +which explains why it just blindly loads a word or two straight off the +stack pointer and then takes a minimal look at the values to just check +if they might be eflags or the return pc: + + Eflags always has bits 22 and up cleared unlike kernel addresses + +but that basic stack layout assumption assumes that there isn't any lock +debugging etc going on that would complicate the code and cause a stack +frame. + +It causes KASAN unhappiness reported for years by syzkaller [1] and +others [2]. + +With no real practical reason for this any more, just remove the code. + +Just for historical interest, here's some background commits relating to +this code from 2006: + + 0cb91a229364 ("i386: Account spinlocks to the caller during profiling for !FP kernels") + 31679f38d886 ("Simplify profile_pc on x86-64") + +and a code unification from 2009: + + ef4512882dbe ("x86: time_32/64.c unify profile_pc") + +but the basics of this thing actually goes back to before the git tree. + +Link: https://syzkaller.appspot.com/bug?extid=84fe685c02cd112a2ac3 [1] +Link: https://lore.kernel.org/all/CAK55_s7Xyq=nh97=K=G1sxueOFrJDAvPOJAL4TPTCAYvmxO9_A@mail.gmail.com/ [2] +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/time.c | 21 +-------------------- + 1 file changed, 1 insertion(+), 20 deletions(-) + +diff --git a/arch/x86/kernel/time.c b/arch/x86/kernel/time.c +index 0680a2e9e06bb..b52ba6962325c 100644 +--- a/arch/x86/kernel/time.c ++++ b/arch/x86/kernel/time.c +@@ -26,26 +26,7 @@ + + unsigned long profile_pc(struct pt_regs *regs) + { +- unsigned long pc = instruction_pointer(regs); +- +- if (!user_mode(regs) && in_lock_functions(pc)) { +-#ifdef CONFIG_FRAME_POINTER +- return *(unsigned long *)(regs->bp + sizeof(long)); +-#else +- unsigned long *sp = +- (unsigned long *)kernel_stack_pointer(regs); +- /* +- * Return address is either directly at stack pointer +- * or above a saved flags. Eflags has bits 22-31 zero, +- * kernel addresses don't. +- */ +- if (sp[0] >> 22) +- return sp[0]; +- if (sp[1] >> 22) +- return sp[1]; +-#endif +- } +- return pc; ++ return instruction_pointer(regs); + } + EXPORT_SYMBOL(profile_pc); + +-- +2.43.0 +