From: Greg Kroah-Hartman Date: Mon, 9 Aug 2021 10:39:24 +0000 (+0200) Subject: 5.4-stable patches X-Git-Tag: v4.4.280~32 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5b1489627c0a05e58211434882f86fcd3b4a435b;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: mips-malta-do-not-byte-swap-accesses-to-the-cbus-uart.patch serial-8250-mask-out-floating-16-32-bit-bus-bits.patch serial-8250_mtk-fix-uart-corruption-issue-when-rx-power-off.patch serial-8250_pci-avoid-irq-sharing-for-msi-x-interrupts.patch serial-8250_pci-enumerate-elkhart-lake-uarts-via-dedicated-driver.patch serial-tegra-only-print-fifo-error-message-when-an-error-occurs.patch timers-move-clearing-of-base-timer_running-under-base-lock.patch --- diff --git a/queue-5.4/mips-malta-do-not-byte-swap-accesses-to-the-cbus-uart.patch b/queue-5.4/mips-malta-do-not-byte-swap-accesses-to-the-cbus-uart.patch new file mode 100644 index 00000000000..aea6b7e800e --- /dev/null +++ b/queue-5.4/mips-malta-do-not-byte-swap-accesses-to-the-cbus-uart.patch @@ -0,0 +1,68 @@ +From 9a936d6c3d3d6c33ecbadf72dccdb567b5cd3c72 Mon Sep 17 00:00:00 2001 +From: "Maciej W. Rozycki" +Date: Sat, 26 Jun 2021 06:11:13 +0200 +Subject: MIPS: Malta: Do not byte-swap accesses to the CBUS UART +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Maciej W. Rozycki + +commit 9a936d6c3d3d6c33ecbadf72dccdb567b5cd3c72 upstream. + +Correct big-endian accesses to the CBUS UART, a Malta on-board discrete +TI16C550C part wired directly to the system controller's device bus, and +do not use byte swapping with the 32-bit accesses to the device. + +The CBUS is used for devices such as the boot flash memory needed early +on in system bootstrap even before PCI has been initialised. Therefore +it uses the system controller's device bus, which follows the endianness +set with the CPU, which means no byte-swapping is ever required for data +accesses to CBUS, unlike with PCI. + +The CBUS UART uses the UPIO_MEM32 access method, that is the `readl' and +`writel' MMIO accessors, which on the MIPS platform imply byte-swapping +with PCI systems. Consequently the wrong byte lane is accessed with the +big-endian configuration and the UART is not correctly accessed. + +As it happens the UPIO_MEM32BE access method makes use of the `ioread32' +and `iowrite32' MMIO accessors, which still use `readl' and `writel' +respectively, however they byte-swap data passed, effectively cancelling +swapping done with the accessors themselves and making it suitable for +the CBUS UART. + +Make the CBUS UART switch between UPIO_MEM32 and UPIO_MEM32BE then, +based on the endianness selected. With this change in place the device +is correctly recognised with big-endian Malta at boot, along with the +Super I/O devices behind PCI: + +Serial: 8250/16550 driver, 5 ports, IRQ sharing enabled +printk: console [ttyS0] disabled +serial8250.0: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A +printk: console [ttyS0] enabled +printk: bootconsole [uart8250] disabled +serial8250.0: ttyS1 at I/O 0x2f8 (irq = 3, base_baud = 115200) is a 16550A +serial8250.0: ttyS2 at MMIO 0x1f000900 (irq = 20, base_baud = 230400) is a 16550A + +Fixes: e7c4782f92fc ("[MIPS] Put an end to 's long and annyoing existence") +Cc: stable@vger.kernel.org # v2.6.23+ +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Maciej W. Rozycki +Link: https://lore.kernel.org/r/alpine.DEB.2.21.2106260524430.37803@angie.orcam.me.uk +Signed-off-by: Greg Kroah-Hartman +--- + arch/mips/mti-malta/malta-platform.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/mips/mti-malta/malta-platform.c ++++ b/arch/mips/mti-malta/malta-platform.c +@@ -47,7 +47,8 @@ static struct plat_serial8250_port uart8 + .mapbase = 0x1f000900, /* The CBUS UART */ + .irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB2, + .uartclk = 3686400, /* Twice the usual clk! */ +- .iotype = UPIO_MEM32, ++ .iotype = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) ? ++ UPIO_MEM32BE : UPIO_MEM32, + .flags = CBUS_UART_FLAGS, + .regshift = 3, + }, diff --git a/queue-5.4/serial-8250-mask-out-floating-16-32-bit-bus-bits.patch b/queue-5.4/serial-8250-mask-out-floating-16-32-bit-bus-bits.patch new file mode 100644 index 00000000000..ac041f646c5 --- /dev/null +++ b/queue-5.4/serial-8250-mask-out-floating-16-32-bit-bus-bits.patch @@ -0,0 +1,104 @@ +From e5227c51090e165db4b48dcaa300605bfced7014 Mon Sep 17 00:00:00 2001 +From: "Maciej W. Rozycki" +Date: Sat, 26 Jun 2021 06:11:05 +0200 +Subject: serial: 8250: Mask out floating 16/32-bit bus bits +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Maciej W. Rozycki + +commit e5227c51090e165db4b48dcaa300605bfced7014 upstream. + +Make sure only actual 8 bits of the IIR register are used in determining +the port type in `autoconfig'. + +The `serial_in' port accessor returns the `unsigned int' type, meaning +that with UPIO_AU, UPIO_MEM16, UPIO_MEM32, and UPIO_MEM32BE access types +more than 8 bits of data are returned, of which the high order bits will +often come from bus lines that are left floating in the data phase. For +example with the MIPS Malta board's CBUS UART, where the registers are +aligned on 8-byte boundaries and which uses 32-bit accesses, data as +follows is returned: + +YAMON> dump -32 0xbf000900 0x40 + +BF000900: 1F000942 1F000942 1F000900 1F000900 ...B...B........ +BF000910: 1F000901 1F000901 1F000900 1F000900 ................ +BF000920: 1F000900 1F000900 1F000960 1F000960 ...........`...` +BF000930: 1F000900 1F000900 1F0009FF 1F0009FF ................ + +YAMON> + +Evidently high-order 24 bits return values previously driven in the +address phase (the 3 highest order address bits used with the command +above are masked out in the simple virtual address mapping used here and +come out at zeros on the external bus), a common scenario with bus lines +left floating, due to bus capacitance. + +Consequently when the value of IIR, mapped at 0x1f000910, is retrieved +in `autoconfig', it comes out at 0x1f0009c1 and when it is right-shifted +by 6 and then assigned to 8-bit `scratch' variable, the value calculated +is 0x27, not one of 0, 1, 2, 3 expected in port type determination. + +Fix the issue then, by assigning the value returned from `serial_in' to +`scratch' first, which masks out 24 high-order bits retrieved, and only +then right-shift the resulting 8-bit data quantity, producing the value +of 3 in this case, as expected. Fix the same issue in `serial_dl_read'. + +The problem first appeared with Linux 2.6.9-rc3 which predates our repo +history, but the origin could be identified with the old MIPS/Linux repo +also at: +as commit e0d2356c0777 ("Merge with Linux 2.6.9-rc3."), where code in +`serial_in' was updated with this case: + ++ case UPIO_MEM32: ++ return readl(up->port.membase + offset); ++ + +which made it produce results outside the unsigned 8-bit range for the +first time, though obviously it is system dependent what actual values +appear in the high order bits retrieved and it may well have been zeros +in the relevant positions with the system the change originally was +intended for. It is at that point that code in `autoconf' should have +been updated accordingly, but clearly it was overlooked. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable@vger.kernel.org # v2.6.12+ +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Maciej W. Rozycki +Link: https://lore.kernel.org/r/alpine.DEB.2.21.2106260516220.37803@angie.orcam.me.uk +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serial/8250/8250_port.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +--- a/drivers/tty/serial/8250/8250_port.c ++++ b/drivers/tty/serial/8250/8250_port.c +@@ -314,7 +314,11 @@ static const struct serial8250_config ua + /* Uart divisor latch read */ + static int default_serial_dl_read(struct uart_8250_port *up) + { +- return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8; ++ /* Assign these in pieces to truncate any bits above 7. */ ++ unsigned char dll = serial_in(up, UART_DLL); ++ unsigned char dlm = serial_in(up, UART_DLM); ++ ++ return dll | dlm << 8; + } + + /* Uart divisor latch write */ +@@ -1258,9 +1262,11 @@ static void autoconfig(struct uart_8250_ + serial_out(up, UART_LCR, 0); + + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); +- scratch = serial_in(up, UART_IIR) >> 6; + +- switch (scratch) { ++ /* Assign this as it is to truncate any bits above 7. */ ++ scratch = serial_in(up, UART_IIR); ++ ++ switch (scratch >> 6) { + case 0: + autoconfig_8250(up); + break; diff --git a/queue-5.4/serial-8250_mtk-fix-uart-corruption-issue-when-rx-power-off.patch b/queue-5.4/serial-8250_mtk-fix-uart-corruption-issue-when-rx-power-off.patch new file mode 100644 index 00000000000..a7bf6a68b8d --- /dev/null +++ b/queue-5.4/serial-8250_mtk-fix-uart-corruption-issue-when-rx-power-off.patch @@ -0,0 +1,63 @@ +From 7c4a509d3815a260c423c0633bd73695250ac26d Mon Sep 17 00:00:00 2001 +From: Zhiyong Tao +Date: Thu, 29 Jul 2021 16:46:40 +0800 +Subject: serial: 8250_mtk: fix uart corruption issue when rx power off + +From: Zhiyong Tao + +commit 7c4a509d3815a260c423c0633bd73695250ac26d upstream. + +Fix uart corruption issue when rx power off. +Add spin lock in mtk8250_dma_rx_complete function in APDMA mode. + +when uart is used as a communication port with external device(GPS). +when external device(GPS) power off, the power of rx pin is also from +1.8v to 0v. Even if there is not any data in rx. But uart rx pin can +capture the data "0". +If uart don't receive any data in specified cycle, uart will generates +BI(Break interrupt) interrupt. +If external device(GPS) power off, we found that BI interrupt appeared +continuously and very frequently. +When uart interrupt type is BI, uart IRQ handler(8250 framwork +API:serial8250_handle_irq) will push data to tty buffer. +mtk8250_dma_rx_complete is a task of mtk_uart_apdma_rx_handler. +mtk8250_dma_rx_complete priority is lower than uart irq +handler(serial8250_handle_irq). +if we are in process of mtk8250_dma_rx_complete, uart appear BI +interrupt:1)serial8250_handle_irq will priority execution.2)it may cause +write tty buffer conflict in mtk8250_dma_rx_complete. +So the spin lock protect the rx receive data process is not break. + +Signed-off-by: Zhiyong Tao +Cc: stable +Link: https://lore.kernel.org/r/20210729084640.17613-2-zhiyong.tao@mediatek.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serial/8250/8250_mtk.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/tty/serial/8250/8250_mtk.c ++++ b/drivers/tty/serial/8250/8250_mtk.c +@@ -92,10 +92,13 @@ static void mtk8250_dma_rx_complete(void + struct dma_tx_state state; + int copied, total, cnt; + unsigned char *ptr; ++ unsigned long flags; + + if (data->rx_status == DMA_RX_SHUTDOWN) + return; + ++ spin_lock_irqsave(&up->port.lock, flags); ++ + dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state); + total = dma->rx_size - state.residue; + cnt = total; +@@ -119,6 +122,8 @@ static void mtk8250_dma_rx_complete(void + tty_flip_buffer_push(tty_port); + + mtk8250_rx_dma(up); ++ ++ spin_unlock_irqrestore(&up->port.lock, flags); + } + + static void mtk8250_rx_dma(struct uart_8250_port *up) diff --git a/queue-5.4/serial-8250_pci-avoid-irq-sharing-for-msi-x-interrupts.patch b/queue-5.4/serial-8250_pci-avoid-irq-sharing-for-msi-x-interrupts.patch new file mode 100644 index 00000000000..039068c0d7f --- /dev/null +++ b/queue-5.4/serial-8250_pci-avoid-irq-sharing-for-msi-x-interrupts.patch @@ -0,0 +1,96 @@ +From 341abd693d10e5f337a51f140ae3e7a1ae0febf6 Mon Sep 17 00:00:00 2001 +From: Mario Kleiner +Date: Thu, 29 Jul 2021 06:33:06 +0200 +Subject: serial: 8250_pci: Avoid irq sharing for MSI(-X) interrupts. + +From: Mario Kleiner + +commit 341abd693d10e5f337a51f140ae3e7a1ae0febf6 upstream. + +This attempts to fix a bug found with a serial port card which uses +an MCS9922 chip, one of the 4 models for which MSI-X interrupts are +currently supported. I don't possess such a card, and i'm not +experienced with the serial subsystem, so this patch is based on what +i think i found as a likely reason for failure, based on walking the +user who actually owns the card through some diagnostic. + +The user who reported the problem finds the following in his dmesg +output for the relevant ttyS4 and ttyS5: + +[ 0.580425] serial 0000:02:00.0: enabling device (0000 -> 0003) +[ 0.601448] 0000:02:00.0: ttyS4 at I/O 0x3010 (irq = 125, base_baud = 115200) is a ST16650V2 +[ 0.603089] serial 0000:02:00.1: enabling device (0000 -> 0003) +[ 0.624119] 0000:02:00.1: ttyS5 at I/O 0x3000 (irq = 126, base_baud = 115200) is a ST16650V2 +... +[ 6.323784] genirq: Flags mismatch irq 128. 00000080 (ttyS5) vs. 00000000 (xhci_hcd) +[ 6.324128] genirq: Flags mismatch irq 128. 00000080 (ttyS5) vs. 00000000 (xhci_hcd) +... + +Output of setserial -a: + +/dev/ttyS4, Line 4, UART: 16650V2, Port: 0x3010, IRQ: 127 + Baud_base: 115200, close_delay: 50, divisor: 0 + closing_wait: 3000 + Flags: spd_normal skip_test + +This suggests to me that the serial driver wants to register and share a +MSI/MSI-X irq 128 with the xhci_hcd driver, whereas the xhci driver does +not want to share the irq, as flags 0x00000080 (== IRQF_SHARED) from the +serial port driver means to share the irq, and this mismatch ends in some +failed irq init? + +With this setup, data reception works very unreliable, with dropped data, +already at a transmission rate of only a 16 Bytes chunk every 1/120th of +a second, ie. 1920 Bytes/sec, presumably due to rx fifo overflow due to +mishandled or not used at all rx irq's? + +See full discussion thread with attempted diagnosis at: + +https://psychtoolbox.discourse.group/t/issues-with-iscan-serial-port-recording/3886 + +Disabling the use of MSI interrupts for the serial port pci card did +fix the reliability problems. The user executed the following sequence +of commands to achieve this: + +echo 0000:02:00.0 | sudo tee /sys/bus/pci/drivers/serial/unbind +echo 0000:02:00.1 | sudo tee /sys/bus/pci/drivers/serial/unbind + +echo 0 | sudo tee /sys/bus/pci/devices/0000:02:00.0/msi_bus +echo 0 | sudo tee /sys/bus/pci/devices/0000:02:00.1/msi_bus + +echo 0000:02:00.0 | sudo tee /sys/bus/pci/drivers/serial/bind +echo 0000:02:00.1 | sudo tee /sys/bus/pci/drivers/serial/bind + +This resulted in the following log output: + +[ 82.179021] pci 0000:02:00.0: MSI/MSI-X disallowed for future drivers +[ 87.003031] pci 0000:02:00.1: MSI/MSI-X disallowed for future drivers +[ 98.537010] 0000:02:00.0: ttyS4 at I/O 0x3010 (irq = 17, base_baud = 115200) is a ST16650V2 +[ 103.648124] 0000:02:00.1: ttyS5 at I/O 0x3000 (irq = 18, base_baud = 115200) is a ST16650V2 + +This patch attempts to fix the problem by disabling irq sharing when +using MSI irq's. Note that all i know for sure is that disabling MSI +irq's fixed the problem for the user, so this patch could be wrong and +is untested. Please review with caution, keeping this in mind. + +Fixes: 8428413b1d14 ("serial: 8250_pci: Implement MSI(-X) support") +Cc: Ralf Ramsauer +Cc: stable +Reviewed-by: Andy Shevchenko +Signed-off-by: Mario Kleiner +Link: https://lore.kernel.org/r/20210729043306.18528-1-mario.kleiner.de@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serial/8250/8250_pci.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/tty/serial/8250/8250_pci.c ++++ b/drivers/tty/serial/8250/8250_pci.c +@@ -3929,6 +3929,7 @@ pciserial_init_ports(struct pci_dev *dev + if (pci_match_id(pci_use_msi, dev)) { + dev_dbg(&dev->dev, "Using MSI(-X) interrupts\n"); + pci_set_master(dev); ++ uart.port.flags &= ~UPF_SHARE_IRQ; + rc = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_ALL_TYPES); + } else { + dev_dbg(&dev->dev, "Using legacy interrupts\n"); diff --git a/queue-5.4/serial-8250_pci-enumerate-elkhart-lake-uarts-via-dedicated-driver.patch b/queue-5.4/serial-8250_pci-enumerate-elkhart-lake-uarts-via-dedicated-driver.patch new file mode 100644 index 00000000000..ceae7f574b8 --- /dev/null +++ b/queue-5.4/serial-8250_pci-enumerate-elkhart-lake-uarts-via-dedicated-driver.patch @@ -0,0 +1,39 @@ +From 7f0909db761535aefafa77031062603a71557267 Mon Sep 17 00:00:00 2001 +From: Andy Shevchenko +Date: Tue, 13 Jul 2021 13:17:39 +0300 +Subject: serial: 8250_pci: Enumerate Elkhart Lake UARTs via dedicated driver + +From: Andy Shevchenko + +commit 7f0909db761535aefafa77031062603a71557267 upstream. + +Elkhart Lake UARTs are PCI enumerated Synopsys DesignWare v4.0+ UART +integrated with Intel iDMA 32-bit DMA controller. There is a specific +driver to handle them, i.e. 8250_lpss. Hence, disable 8250_pci +enumeration for these UARTs. + +Fixes: 1b91d97c66ef ("serial: 8250_lpss: Add ->setup() for Elkhart Lake ports") +Fixes: 4f912b898dc2 ("serial: 8250_lpss: Enable HS UART on Elkhart Lake") +Cc: stable +Signed-off-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20210713101739.36962-1-andriy.shevchenko@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serial/8250/8250_pci.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/tty/serial/8250/8250_pci.c ++++ b/drivers/tty/serial/8250/8250_pci.c +@@ -3763,6 +3763,12 @@ static const struct pci_device_id blackl + { PCI_VDEVICE(INTEL, 0x0f0c), }, + { PCI_VDEVICE(INTEL, 0x228a), }, + { PCI_VDEVICE(INTEL, 0x228c), }, ++ { PCI_VDEVICE(INTEL, 0x4b96), }, ++ { PCI_VDEVICE(INTEL, 0x4b97), }, ++ { PCI_VDEVICE(INTEL, 0x4b98), }, ++ { PCI_VDEVICE(INTEL, 0x4b99), }, ++ { PCI_VDEVICE(INTEL, 0x4b9a), }, ++ { PCI_VDEVICE(INTEL, 0x4b9b), }, + { PCI_VDEVICE(INTEL, 0x9ce3), }, + { PCI_VDEVICE(INTEL, 0x9ce4), }, + diff --git a/queue-5.4/serial-tegra-only-print-fifo-error-message-when-an-error-occurs.patch b/queue-5.4/serial-tegra-only-print-fifo-error-message-when-an-error-occurs.patch new file mode 100644 index 00000000000..62158838934 --- /dev/null +++ b/queue-5.4/serial-tegra-only-print-fifo-error-message-when-an-error-occurs.patch @@ -0,0 +1,42 @@ +From cc9ca4d95846cbbece48d9cd385550f8fba6a3c1 Mon Sep 17 00:00:00 2001 +From: Jon Hunter +Date: Wed, 30 Jun 2021 13:56:43 +0100 +Subject: serial: tegra: Only print FIFO error message when an error occurs + +From: Jon Hunter + +commit cc9ca4d95846cbbece48d9cd385550f8fba6a3c1 upstream. + +The Tegra serial driver always prints an error message when enabling the +FIFO for devices that have support for checking the FIFO enable status. +Fix this by displaying the error message, only when an error occurs. + +Finally, update the error message to make it clear that enabling the +FIFO failed and display the error code. + +Fixes: 222dcdff3405 ("serial: tegra: check for FIFO mode enabled status") +Cc: +Acked-by: Thierry Reding +Signed-off-by: Jon Hunter +Link: https://lore.kernel.org/r/20210630125643.264264-1-jonathanh@nvidia.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serial/serial-tegra.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/tty/serial/serial-tegra.c ++++ b/drivers/tty/serial/serial-tegra.c +@@ -1028,9 +1028,11 @@ static int tegra_uart_hw_init(struct teg + + if (tup->cdata->fifo_mode_enable_status) { + ret = tegra_uart_wait_fifo_mode_enabled(tup); +- dev_err(tup->uport.dev, "FIFO mode not enabled\n"); +- if (ret < 0) ++ if (ret < 0) { ++ dev_err(tup->uport.dev, ++ "Failed to enable FIFO mode: %d\n", ret); + return ret; ++ } + } else { + /* + * For all tegra devices (up to t210), there is a hardware diff --git a/queue-5.4/series b/queue-5.4/series index ae3ea1a5178..2d49b993ae6 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -58,3 +58,10 @@ staging-rtl8712-get-rid-of-flush_scheduled_work.patch media-rtl28xxu-fix-zero-length-control-request.patch pipe-increase-minimum-default-pipe-size-to-2-pages.patch ext4-fix-potential-htree-corruption-when-growing-large_dir-directories.patch +serial-tegra-only-print-fifo-error-message-when-an-error-occurs.patch +serial-8250_mtk-fix-uart-corruption-issue-when-rx-power-off.patch +serial-8250-mask-out-floating-16-32-bit-bus-bits.patch +mips-malta-do-not-byte-swap-accesses-to-the-cbus-uart.patch +serial-8250_pci-enumerate-elkhart-lake-uarts-via-dedicated-driver.patch +serial-8250_pci-avoid-irq-sharing-for-msi-x-interrupts.patch +timers-move-clearing-of-base-timer_running-under-base-lock.patch diff --git a/queue-5.4/timers-move-clearing-of-base-timer_running-under-base-lock.patch b/queue-5.4/timers-move-clearing-of-base-timer_running-under-base-lock.patch new file mode 100644 index 00000000000..813fe519123 --- /dev/null +++ b/queue-5.4/timers-move-clearing-of-base-timer_running-under-base-lock.patch @@ -0,0 +1,84 @@ +From bb7262b295472eb6858b5c49893954794027cd84 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner +Date: Sun, 6 Dec 2020 22:40:07 +0100 +Subject: timers: Move clearing of base::timer_running under base:: Lock + +From: Thomas Gleixner + +commit bb7262b295472eb6858b5c49893954794027cd84 upstream. + +syzbot reported KCSAN data races vs. timer_base::timer_running being set to +NULL without holding base::lock in expire_timers(). + +This looks innocent and most reads are clearly not problematic, but +Frederic identified an issue which is: + + int data = 0; + + void timer_func(struct timer_list *t) + { + data = 1; + } + + CPU 0 CPU 1 + ------------------------------ -------------------------- + base = lock_timer_base(timer, &flags); raw_spin_unlock(&base->lock); + if (base->running_timer != timer) call_timer_fn(timer, fn, baseclk); + ret = detach_if_pending(timer, base, true); base->running_timer = NULL; + raw_spin_unlock_irqrestore(&base->lock, flags); raw_spin_lock(&base->lock); + + x = data; + +If the timer has previously executed on CPU 1 and then CPU 0 can observe +base->running_timer == NULL and returns, assuming the timer has completed, +but it's not guaranteed on all architectures. The comment for +del_timer_sync() makes that guarantee. Moving the assignment under +base->lock prevents this. + +For non-RT kernel it's performance wise completely irrelevant whether the +store happens before or after taking the lock. For an RT kernel moving the +store under the lock requires an extra unlock/lock pair in the case that +there is a waiter for the timer, but that's not the end of the world. + +Reported-by: syzbot+aa7c2385d46c5eba0b89@syzkaller.appspotmail.com +Reported-by: syzbot+abea4558531bae1ba9fe@syzkaller.appspotmail.com +Fixes: 030dcdd197d7 ("timers: Prepare support for PREEMPT_RT") +Signed-off-by: Thomas Gleixner +Tested-by: Sebastian Andrzej Siewior +Link: https://lore.kernel.org/r/87lfea7gw8.fsf@nanos.tec.linutronix.de +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + kernel/time/timer.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/kernel/time/timer.c ++++ b/kernel/time/timer.c +@@ -1269,8 +1269,10 @@ static inline void timer_base_unlock_exp + static void timer_sync_wait_running(struct timer_base *base) + { + if (atomic_read(&base->timer_waiters)) { ++ raw_spin_unlock_irq(&base->lock); + spin_unlock(&base->expiry_lock); + spin_lock(&base->expiry_lock); ++ raw_spin_lock_irq(&base->lock); + } + } + +@@ -1454,14 +1456,14 @@ static void expire_timers(struct timer_b + if (timer->flags & TIMER_IRQSAFE) { + raw_spin_unlock(&base->lock); + call_timer_fn(timer, fn, baseclk); +- base->running_timer = NULL; + raw_spin_lock(&base->lock); ++ base->running_timer = NULL; + } else { + raw_spin_unlock_irq(&base->lock); + call_timer_fn(timer, fn, baseclk); ++ raw_spin_lock_irq(&base->lock); + base->running_timer = NULL; + timer_sync_wait_running(base); +- raw_spin_lock_irq(&base->lock); + } + } + }