From 427bf2e94494fe0f95449db13081ccc24d673a05 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Mon, 9 Feb 2026 07:27:50 -0500 Subject: [PATCH] Fixes for all trees Signed-off-by: Sasha Levin --- queue-5.15/series | 6 + ...x-a-memory-leak-in-tegra_slink_probe.patch | 44 +++++++ ...d-move-curr_xfer-read-inside-spinloc.patch | 68 ++++++++++ ...d-protect-curr_xfer-assignment-in-te.patch | 64 ++++++++++ ...d-protect-curr_xfer-clearing-in-tegr.patch | 51 ++++++++ ...d-protect-curr_xfer-in-tegra_qspi_co.patch | 65 ++++++++++ ...d-return-irq_handled-when-timeout-al.patch | 76 +++++++++++ queue-6.1/series | 6 + ...x-a-memory-leak-in-tegra_slink_probe.patch | 44 +++++++ ...d-move-curr_xfer-read-inside-spinloc.patch | 68 ++++++++++ ...d-protect-curr_xfer-assignment-in-te.patch | 64 ++++++++++ ...d-protect-curr_xfer-clearing-in-tegr.patch | 51 ++++++++ ...d-protect-curr_xfer-in-tegra_qspi_co.patch | 66 ++++++++++ ...d-return-irq_handled-when-timeout-al.patch | 76 +++++++++++ queue-6.12/series | 7 ++ ...x-a-memory-leak-in-tegra_slink_probe.patch | 44 +++++++ ...serve-spi-mode-bits-in-def_command1_.patch | 50 ++++++++ ...d-move-curr_xfer-read-inside-spinloc.patch | 68 ++++++++++ ...d-protect-curr_xfer-assignment-in-te.patch | 64 ++++++++++ ...d-protect-curr_xfer-clearing-in-tegr.patch | 51 ++++++++ ...d-protect-curr_xfer-in-tegra_qspi_co.patch | 66 ++++++++++ ...d-return-irq_handled-when-timeout-al.patch | 76 +++++++++++ ...it-p1-fix-n_voltages-for-buck-and-ld.patch | 56 +++++++++ queue-6.18/series | 9 ++ ...x-a-memory-leak-in-tegra_slink_probe.patch | 44 +++++++ ...serve-spi-mode-bits-in-def_command1_.patch | 50 ++++++++ ...d-move-curr_xfer-read-inside-spinloc.patch | 68 ++++++++++ ...d-protect-curr_xfer-assignment-in-te.patch | 64 ++++++++++ ...d-protect-curr_xfer-check-in-irq-han.patch | 114 +++++++++++++++++ ...d-protect-curr_xfer-clearing-in-tegr.patch | 51 ++++++++ ...d-protect-curr_xfer-in-tegra_qspi_co.patch | 66 ++++++++++ ...d-return-irq_handled-when-timeout-al.patch | 76 +++++++++++ ...rrect-ethtool-rx_dropped-calculation.patch | 119 ++++++++++++++++++ queue-6.6/series | 8 ++ ...x-a-memory-leak-in-tegra_slink_probe.patch | 44 +++++++ ...serve-spi-mode-bits-in-def_command1_.patch | 50 ++++++++ ...d-move-curr_xfer-read-inside-spinloc.patch | 68 ++++++++++ ...d-protect-curr_xfer-assignment-in-te.patch | 64 ++++++++++ ...d-protect-curr_xfer-clearing-in-tegr.patch | 51 ++++++++ ...d-protect-curr_xfer-in-tegra_qspi_co.patch | 66 ++++++++++ ...d-return-irq_handled-when-timeout-al.patch | 76 +++++++++++ 41 files changed, 2319 insertions(+) create mode 100644 queue-5.15/spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch create mode 100644 queue-5.15/spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch create mode 100644 queue-5.15/spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch create mode 100644 queue-5.15/spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch create mode 100644 queue-5.15/spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch create mode 100644 queue-5.15/spi-tegra210-quad-return-irq_handled-when-timeout-al.patch create mode 100644 queue-6.1/spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch create mode 100644 queue-6.1/spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch create mode 100644 queue-6.1/spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch create mode 100644 queue-6.1/spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch create mode 100644 queue-6.1/spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch create mode 100644 queue-6.1/spi-tegra210-quad-return-irq_handled-when-timeout-al.patch create mode 100644 queue-6.12/spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch create mode 100644 queue-6.12/spi-tegra114-preserve-spi-mode-bits-in-def_command1_.patch create mode 100644 queue-6.12/spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch create mode 100644 queue-6.12/spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch create mode 100644 queue-6.12/spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch create mode 100644 queue-6.12/spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch create mode 100644 queue-6.12/spi-tegra210-quad-return-irq_handled-when-timeout-al.patch create mode 100644 queue-6.18/regulator-spacemit-p1-fix-n_voltages-for-buck-and-ld.patch create mode 100644 queue-6.18/spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch create mode 100644 queue-6.18/spi-tegra114-preserve-spi-mode-bits-in-def_command1_.patch create mode 100644 queue-6.18/spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch create mode 100644 queue-6.18/spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch create mode 100644 queue-6.18/spi-tegra210-quad-protect-curr_xfer-check-in-irq-han.patch create mode 100644 queue-6.18/spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch create mode 100644 queue-6.18/spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch create mode 100644 queue-6.18/spi-tegra210-quad-return-irq_handled-when-timeout-al.patch create mode 100644 queue-6.6/gve-correct-ethtool-rx_dropped-calculation.patch create mode 100644 queue-6.6/spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch create mode 100644 queue-6.6/spi-tegra114-preserve-spi-mode-bits-in-def_command1_.patch create mode 100644 queue-6.6/spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch create mode 100644 queue-6.6/spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch create mode 100644 queue-6.6/spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch create mode 100644 queue-6.6/spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch create mode 100644 queue-6.6/spi-tegra210-quad-return-irq_handled-when-timeout-al.patch diff --git a/queue-5.15/series b/queue-5.15/series index 968ee7bf35..9e50403873 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -65,3 +65,9 @@ gfs2-fix-null-pointer-dereference-in-gfs2_log_flush.patch tracing-fix-ftrace-event-field-alignments.patch gve-fix-stats-report-corruption-on-queue-count-change.patch gve-correct-ethtool-rx_dropped-calculation.patch +spi-tegra210-quad-return-irq_handled-when-timeout-al.patch +spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch +spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch +spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch +spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch +spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch diff --git a/queue-5.15/spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch b/queue-5.15/spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch new file mode 100644 index 0000000000..6d9d792b8b --- /dev/null +++ b/queue-5.15/spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch @@ -0,0 +1,44 @@ +From 26eb08d6833fcdff70d50d13de56c7451ed43878 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 Feb 2026 23:15:09 +0800 +Subject: spi: tegra: Fix a memory leak in tegra_slink_probe() + +From: Felix Gu + +[ Upstream commit 41d9a6795b95d6ea28439ac1e9ce8c95bbca20fc ] + +In tegra_slink_probe(), when platform_get_irq() fails, it directly +returns from the function with an error code, which causes a memory leak. + +Replace it with a goto label to ensure proper cleanup. + +Fixes: eb9913b511f1 ("spi: tegra: Fix missing IRQ check in tegra_slink_probe()") +Signed-off-by: Felix Gu +Reviewed-by: Jon Hunter +Link: https://patch.msgid.link/20260202-slink-v1-1-eac50433a6f9@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra20-slink.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c +index c611fedda7de9..a51310aa2556c 100644 +--- a/drivers/spi/spi-tegra20-slink.c ++++ b/drivers/spi/spi-tegra20-slink.c +@@ -1087,8 +1087,10 @@ static int tegra_slink_probe(struct platform_device *pdev) + reset_control_deassert(tspi->rst); + + spi_irq = platform_get_irq(pdev, 0); +- if (spi_irq < 0) +- return spi_irq; ++ if (spi_irq < 0) { ++ ret = spi_irq; ++ goto exit_pm_put; ++ } + tspi->irq = spi_irq; + ret = request_threaded_irq(tspi->irq, tegra_slink_isr, + tegra_slink_isr_thread, IRQF_ONESHOT, +-- +2.51.0 + diff --git a/queue-5.15/spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch b/queue-5.15/spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch new file mode 100644 index 0000000000..515bea4dfa --- /dev/null +++ b/queue-5.15/spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch @@ -0,0 +1,68 @@ +From 77fff45102d771d856f9b0c9d62addc12ccbf290 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:27 -0800 +Subject: spi: tegra210-quad: Move curr_xfer read inside spinlock + +From: Breno Leitao + +[ Upstream commit ef13ba357656451d6371940d8414e3e271df97e3 ] + +Move the assignment of the transfer pointer from curr_xfer inside the +spinlock critical section in both handle_cpu_based_xfer() and +handle_dma_based_xfer(). + +Previously, curr_xfer was read before acquiring the lock, creating a +window where the timeout path could clear curr_xfer between reading it +and using it. By moving the read inside the lock, the handlers are +guaranteed to see a consistent value that cannot be modified by the +timeout path. + +Fixes: 921fc1838fb0 ("spi: tegra210-quad: Add support for Tegra210 QSPI controller") +Signed-off-by: Breno Leitao +Acked-by: Thierry Reding +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-2-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index b8fabeb403bad..18bd11150a5c6 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -1310,10 +1310,11 @@ static int tegra_qspi_transfer_one_message(struct spi_master *master, + + static irqreturn_t handle_cpu_based_xfer(struct tegra_qspi *tqspi) + { +- struct spi_transfer *t = tqspi->curr_xfer; ++ struct spi_transfer *t; + unsigned long flags; + + spin_lock_irqsave(&tqspi->lock, flags); ++ t = tqspi->curr_xfer; + + if (tqspi->tx_status || tqspi->rx_status) { + tegra_qspi_handle_error(tqspi); +@@ -1344,7 +1345,7 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_qspi *tqspi) + + static irqreturn_t handle_dma_based_xfer(struct tegra_qspi *tqspi) + { +- struct spi_transfer *t = tqspi->curr_xfer; ++ struct spi_transfer *t; + unsigned int total_fifo_words; + unsigned long flags; + long wait_status; +@@ -1381,6 +1382,7 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_qspi *tqspi) + } + + spin_lock_irqsave(&tqspi->lock, flags); ++ t = tqspi->curr_xfer; + + if (err) { + tegra_qspi_dma_unmap_xfer(tqspi, t); +-- +2.51.0 + diff --git a/queue-5.15/spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch b/queue-5.15/spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch new file mode 100644 index 0000000000..8dc9b73466 --- /dev/null +++ b/queue-5.15/spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch @@ -0,0 +1,64 @@ +From ce19b74e036d27febb0ce7bbf96c1f2e81dbc6a0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:28 -0800 +Subject: spi: tegra210-quad: Protect curr_xfer assignment in + tegra_qspi_setup_transfer_one + +From: Breno Leitao + +[ Upstream commit f5a4d7f5e32ba163cff893493ec1cbb0fd2fb0d5 ] + +When the timeout handler processes a completed transfer and signals +completion, the transfer thread can immediately set up the next transfer +and assign curr_xfer to point to it. + +If a delayed ISR from the previous transfer then runs, it checks if +(!tqspi->curr_xfer) (currently without the lock also -- to be fixed +soon) to detect stale interrupts, but this check passes because +curr_xfer now points to the new transfer. The ISR then incorrectly +processes the new transfer's context. + +Protect the curr_xfer assignment with the spinlock to ensure the ISR +either sees NULL (and bails out) or sees the new value only after the +assignment is complete. + +Fixes: 921fc1838fb0 ("spi: tegra210-quad: Add support for Tegra210 QSPI controller") +Signed-off-by: Breno Leitao +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Acked-by: Thierry Reding +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-3-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index 18bd11150a5c6..9649c1855dd3c 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -794,6 +794,7 @@ static u32 tegra_qspi_setup_transfer_one(struct spi_device *spi, struct spi_tran + u32 command1, command2, speed = t->speed_hz; + u8 bits_per_word = t->bits_per_word; + u32 tx_tap = 0, rx_tap = 0; ++ unsigned long flags; + int req_mode; + + if (speed != tqspi->cur_speed) { +@@ -801,10 +802,12 @@ static u32 tegra_qspi_setup_transfer_one(struct spi_device *spi, struct spi_tran + tqspi->cur_speed = speed; + } + ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->cur_pos = 0; + tqspi->cur_rx_pos = 0; + tqspi->cur_tx_pos = 0; + tqspi->curr_xfer = t; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + + if (is_first_of_msg) { + tegra_qspi_mask_clear_irq(tqspi); +-- +2.51.0 + diff --git a/queue-5.15/spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch b/queue-5.15/spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch new file mode 100644 index 0000000000..0075804511 --- /dev/null +++ b/queue-5.15/spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch @@ -0,0 +1,51 @@ +From 13ac4c2df1612613e07ebd256e8c7e870ac60eac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:30 -0800 +Subject: spi: tegra210-quad: Protect curr_xfer clearing in + tegra_qspi_non_combined_seq_xfer + +From: Breno Leitao + +[ Upstream commit 6d7723e8161f3c3f14125557e19dd080e9d882be ] + +Protect the curr_xfer clearing in tegra_qspi_non_combined_seq_xfer() +with the spinlock to prevent a race with the interrupt handler that +reads this field to check if a transfer is in progress. + +Fixes: b4e002d8a7ce ("spi: tegra210-quad: Fix timeout handling") +Signed-off-by: Breno Leitao +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Acked-by: Thierry Reding +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-5-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index 3a95788b6fd04..cb9679905682f 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -1178,6 +1178,7 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi, + struct spi_transfer *transfer; + bool is_first_msg = true; + int ret = 0, val = 0; ++ unsigned long flags; + + msg->status = 0; + msg->actual_length = 0; +@@ -1247,7 +1248,9 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi, + msg->actual_length += xfer->len + dummy_bytes; + + complete_xfer: ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->curr_xfer = NULL; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + + if (ret < 0) { + tegra_qspi_transfer_end(spi); +-- +2.51.0 + diff --git a/queue-5.15/spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch b/queue-5.15/spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch new file mode 100644 index 0000000000..e88425e678 --- /dev/null +++ b/queue-5.15/spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch @@ -0,0 +1,65 @@ +From feb4ce330e0ec1b01bff6097c1214a7e9ebdfcc6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:29 -0800 +Subject: spi: tegra210-quad: Protect curr_xfer in tegra_qspi_combined_seq_xfer + +From: Breno Leitao + +[ Upstream commit bf4528ab28e2bf112c3a2cdef44fd13f007781cd ] + +The curr_xfer field is read by the IRQ handler without holding the lock +to check if a transfer is in progress. When clearing curr_xfer in the +combined sequence transfer loop, protect it with the spinlock to prevent +a race with the interrupt handler. + +Protect the curr_xfer clearing at the exit path of +tegra_qspi_combined_seq_xfer() with the spinlock to prevent a race +with the interrupt handler that reads this field. + +Without this protection, the IRQ handler could read a partially updated +curr_xfer value, leading to NULL pointer dereference or use-after-free. + +Fixes: b4e002d8a7ce ("spi: tegra210-quad: Fix timeout handling") +Signed-off-by: Breno Leitao +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Acked-by: Thierry Reding +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-4-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index 9649c1855dd3c..3a95788b6fd04 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -1049,6 +1049,7 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, + u32 address_value = 0; + u32 cmd_config = 0, addr_config = 0; + u8 cmd_value = 0, val = 0; ++ unsigned long flags; + + /* Enable Combined sequence mode */ + val = tegra_qspi_readl(tqspi, QSPI_GLOBAL_CONFIG); +@@ -1155,12 +1156,16 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, + tegra_qspi_transfer_end(spi); + spi_transfer_delay_exec(xfer); + } ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->curr_xfer = NULL; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + transfer_phase++; + } + + exit: ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->curr_xfer = NULL; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + msg->status = ret; + + return ret; +-- +2.51.0 + diff --git a/queue-5.15/spi-tegra210-quad-return-irq_handled-when-timeout-al.patch b/queue-5.15/spi-tegra210-quad-return-irq_handled-when-timeout-al.patch new file mode 100644 index 0000000000..0c58b3e01f --- /dev/null +++ b/queue-5.15/spi-tegra210-quad-return-irq_handled-when-timeout-al.patch @@ -0,0 +1,76 @@ +From 5156d50c1f5145bdf98581fa01a9f415e18438f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:26 -0800 +Subject: spi: tegra210-quad: Return IRQ_HANDLED when timeout already processed + transfer + +From: Breno Leitao + +[ Upstream commit aabd8ea0aa253d40cf5f20a609fc3d6f61e38299 ] + +When the ISR thread wakes up late and finds that the timeout handler +has already processed the transfer (curr_xfer is NULL), return +IRQ_HANDLED instead of IRQ_NONE. + +Use a similar approach to tegra_qspi_handle_timeout() by reading +QSPI_TRANS_STATUS and checking the QSPI_RDY bit to determine if the +hardware actually completed the transfer. If QSPI_RDY is set, the +interrupt was legitimate and triggered by real hardware activity. +The fact that the timeout path handled it first doesn't make it +spurious. Returning IRQ_NONE incorrectly suggests the interrupt +wasn't for this device, which can cause issues with shared interrupt +lines and interrupt accounting. + +Fixes: b4e002d8a7ce ("spi: tegra210-quad: Fix timeout handling") +Signed-off-by: Breno Leitao +Signed-off-by: Usama Arif +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Acked-by: Thierry Reding +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-1-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index 7306ad89bc714..b8fabeb403bad 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -1420,15 +1420,30 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_qspi *tqspi) + static irqreturn_t tegra_qspi_isr_thread(int irq, void *context_data) + { + struct tegra_qspi *tqspi = context_data; ++ u32 status; ++ ++ /* ++ * Read transfer status to check if interrupt was triggered by transfer ++ * completion ++ */ ++ status = tegra_qspi_readl(tqspi, QSPI_TRANS_STATUS); + + /* + * Occasionally the IRQ thread takes a long time to wake up (usually + * when the CPU that it's running on is excessively busy) and we have + * already reached the timeout before and cleaned up the timed out + * transfer. Avoid any processing in that case and bail out early. ++ * ++ * If no transfer is in progress, check if this was a real interrupt ++ * that the timeout handler already processed, or a spurious one. + */ +- if (!tqspi->curr_xfer) +- return IRQ_NONE; ++ if (!tqspi->curr_xfer) { ++ /* Spurious interrupt - transfer not ready */ ++ if (!(status & QSPI_RDY)) ++ return IRQ_NONE; ++ /* Real interrupt, already handled by timeout path */ ++ return IRQ_HANDLED; ++ } + + tqspi->status_reg = tegra_qspi_readl(tqspi, QSPI_FIFO_STATUS); + +-- +2.51.0 + diff --git a/queue-6.1/series b/queue-6.1/series index 2f53b80b59..6ba49b1f7a 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -59,3 +59,9 @@ netfilter-nf_tables-fix-inverted-genmask-check-in-nf.patch asoc-amd-fix-memory-leak-in-acp3x-pdm-dma-ops.patch hfsplus-fix-slab-out-of-bounds-read-in-hfsplus_uni2asc.patch riscv-uprobes-add-missing-fence.i-after-building-the-xol-buffer.patch +spi-tegra210-quad-return-irq_handled-when-timeout-al.patch +spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch +spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch +spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch +spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch +spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch diff --git a/queue-6.1/spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch b/queue-6.1/spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch new file mode 100644 index 0000000000..36bbad9166 --- /dev/null +++ b/queue-6.1/spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch @@ -0,0 +1,44 @@ +From c1cbdf8bfb1abe506b526cbb94f5e911a0a9629a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 Feb 2026 23:15:09 +0800 +Subject: spi: tegra: Fix a memory leak in tegra_slink_probe() + +From: Felix Gu + +[ Upstream commit 41d9a6795b95d6ea28439ac1e9ce8c95bbca20fc ] + +In tegra_slink_probe(), when platform_get_irq() fails, it directly +returns from the function with an error code, which causes a memory leak. + +Replace it with a goto label to ensure proper cleanup. + +Fixes: eb9913b511f1 ("spi: tegra: Fix missing IRQ check in tegra_slink_probe()") +Signed-off-by: Felix Gu +Reviewed-by: Jon Hunter +Link: https://patch.msgid.link/20260202-slink-v1-1-eac50433a6f9@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra20-slink.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c +index 24cab56ecb7fd..5002c9f897c79 100644 +--- a/drivers/spi/spi-tegra20-slink.c ++++ b/drivers/spi/spi-tegra20-slink.c +@@ -1093,8 +1093,10 @@ static int tegra_slink_probe(struct platform_device *pdev) + reset_control_deassert(tspi->rst); + + spi_irq = platform_get_irq(pdev, 0); +- if (spi_irq < 0) +- return spi_irq; ++ if (spi_irq < 0) { ++ ret = spi_irq; ++ goto exit_pm_put; ++ } + tspi->irq = spi_irq; + ret = request_threaded_irq(tspi->irq, tegra_slink_isr, + tegra_slink_isr_thread, IRQF_ONESHOT, +-- +2.51.0 + diff --git a/queue-6.1/spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch b/queue-6.1/spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch new file mode 100644 index 0000000000..f8ee71c192 --- /dev/null +++ b/queue-6.1/spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch @@ -0,0 +1,68 @@ +From 661bd5bcc02012227551ff8be0495efdff3fe7f9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:27 -0800 +Subject: spi: tegra210-quad: Move curr_xfer read inside spinlock + +From: Breno Leitao + +[ Upstream commit ef13ba357656451d6371940d8414e3e271df97e3 ] + +Move the assignment of the transfer pointer from curr_xfer inside the +spinlock critical section in both handle_cpu_based_xfer() and +handle_dma_based_xfer(). + +Previously, curr_xfer was read before acquiring the lock, creating a +window where the timeout path could clear curr_xfer between reading it +and using it. By moving the read inside the lock, the handlers are +guaranteed to see a consistent value that cannot be modified by the +timeout path. + +Fixes: 921fc1838fb0 ("spi: tegra210-quad: Add support for Tegra210 QSPI controller") +Signed-off-by: Breno Leitao +Acked-by: Thierry Reding +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-2-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index 024e1468eee8d..c0cc5bd7e6d2f 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -1325,10 +1325,11 @@ static int tegra_qspi_transfer_one_message(struct spi_master *master, + + static irqreturn_t handle_cpu_based_xfer(struct tegra_qspi *tqspi) + { +- struct spi_transfer *t = tqspi->curr_xfer; ++ struct spi_transfer *t; + unsigned long flags; + + spin_lock_irqsave(&tqspi->lock, flags); ++ t = tqspi->curr_xfer; + + if (tqspi->tx_status || tqspi->rx_status) { + tegra_qspi_handle_error(tqspi); +@@ -1359,7 +1360,7 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_qspi *tqspi) + + static irqreturn_t handle_dma_based_xfer(struct tegra_qspi *tqspi) + { +- struct spi_transfer *t = tqspi->curr_xfer; ++ struct spi_transfer *t; + unsigned int total_fifo_words; + unsigned long flags; + long wait_status; +@@ -1396,6 +1397,7 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_qspi *tqspi) + } + + spin_lock_irqsave(&tqspi->lock, flags); ++ t = tqspi->curr_xfer; + + if (err) { + tegra_qspi_dma_unmap_xfer(tqspi, t); +-- +2.51.0 + diff --git a/queue-6.1/spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch b/queue-6.1/spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch new file mode 100644 index 0000000000..e7d9b292fd --- /dev/null +++ b/queue-6.1/spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch @@ -0,0 +1,64 @@ +From 8a6206ecc87e10674fc57866c7bea4038c71a45b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:28 -0800 +Subject: spi: tegra210-quad: Protect curr_xfer assignment in + tegra_qspi_setup_transfer_one + +From: Breno Leitao + +[ Upstream commit f5a4d7f5e32ba163cff893493ec1cbb0fd2fb0d5 ] + +When the timeout handler processes a completed transfer and signals +completion, the transfer thread can immediately set up the next transfer +and assign curr_xfer to point to it. + +If a delayed ISR from the previous transfer then runs, it checks if +(!tqspi->curr_xfer) (currently without the lock also -- to be fixed +soon) to detect stale interrupts, but this check passes because +curr_xfer now points to the new transfer. The ISR then incorrectly +processes the new transfer's context. + +Protect the curr_xfer assignment with the spinlock to ensure the ISR +either sees NULL (and bails out) or sees the new value only after the +assignment is complete. + +Fixes: 921fc1838fb0 ("spi: tegra210-quad: Add support for Tegra210 QSPI controller") +Signed-off-by: Breno Leitao +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Acked-by: Thierry Reding +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-3-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index c0cc5bd7e6d2f..d3d3e698bffa1 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -813,6 +813,7 @@ static u32 tegra_qspi_setup_transfer_one(struct spi_device *spi, struct spi_tran + u32 command1, command2, speed = t->speed_hz; + u8 bits_per_word = t->bits_per_word; + u32 tx_tap = 0, rx_tap = 0; ++ unsigned long flags; + int req_mode; + + if (!has_acpi_companion(tqspi->dev) && speed != tqspi->cur_speed) { +@@ -820,10 +821,12 @@ static u32 tegra_qspi_setup_transfer_one(struct spi_device *spi, struct spi_tran + tqspi->cur_speed = speed; + } + ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->cur_pos = 0; + tqspi->cur_rx_pos = 0; + tqspi->cur_tx_pos = 0; + tqspi->curr_xfer = t; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + + if (is_first_of_msg) { + tegra_qspi_mask_clear_irq(tqspi); +-- +2.51.0 + diff --git a/queue-6.1/spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch b/queue-6.1/spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch new file mode 100644 index 0000000000..7bbcf3f1b1 --- /dev/null +++ b/queue-6.1/spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch @@ -0,0 +1,51 @@ +From c002c630e08dcb4d326599bcb7c9004c16f7adab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:30 -0800 +Subject: spi: tegra210-quad: Protect curr_xfer clearing in + tegra_qspi_non_combined_seq_xfer + +From: Breno Leitao + +[ Upstream commit 6d7723e8161f3c3f14125557e19dd080e9d882be ] + +Protect the curr_xfer clearing in tegra_qspi_non_combined_seq_xfer() +with the spinlock to prevent a race with the interrupt handler that +reads this field to check if a transfer is in progress. + +Fixes: b4e002d8a7ce ("spi: tegra210-quad: Fix timeout handling") +Signed-off-by: Breno Leitao +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Acked-by: Thierry Reding +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-5-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index a06609a43c7f1..022cc0ebee77c 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -1193,6 +1193,7 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi, + struct spi_transfer *transfer; + bool is_first_msg = true; + int ret = 0, val = 0; ++ unsigned long flags; + + msg->status = 0; + msg->actual_length = 0; +@@ -1262,7 +1263,9 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi, + msg->actual_length += xfer->len + dummy_bytes; + + complete_xfer: ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->curr_xfer = NULL; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + + if (ret < 0) { + tegra_qspi_transfer_end(spi); +-- +2.51.0 + diff --git a/queue-6.1/spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch b/queue-6.1/spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch new file mode 100644 index 0000000000..c3d28c52bb --- /dev/null +++ b/queue-6.1/spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch @@ -0,0 +1,66 @@ +From d07bfe908b9d22f5393c2f3590271a21f436e8b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:29 -0800 +Subject: spi: tegra210-quad: Protect curr_xfer in tegra_qspi_combined_seq_xfer + +From: Breno Leitao + +[ Upstream commit bf4528ab28e2bf112c3a2cdef44fd13f007781cd ] + +The curr_xfer field is read by the IRQ handler without holding the lock +to check if a transfer is in progress. When clearing curr_xfer in the +combined sequence transfer loop, protect it with the spinlock to prevent +a race with the interrupt handler. + +Protect the curr_xfer clearing at the exit path of +tegra_qspi_combined_seq_xfer() with the spinlock to prevent a race +with the interrupt handler that reads this field. + +Without this protection, the IRQ handler could read a partially updated +curr_xfer value, leading to NULL pointer dereference or use-after-free. + +Fixes: b4e002d8a7ce ("spi: tegra210-quad: Fix timeout handling") +Signed-off-by: Breno Leitao +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Acked-by: Thierry Reding +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-4-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index d3d3e698bffa1..a06609a43c7f1 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -1063,6 +1063,7 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, + u32 address_value = 0; + u32 cmd_config = 0, addr_config = 0; + u8 cmd_value = 0, val = 0; ++ unsigned long flags; + + /* Enable Combined sequence mode */ + val = tegra_qspi_readl(tqspi, QSPI_GLOBAL_CONFIG); +@@ -1169,13 +1170,17 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, + tegra_qspi_transfer_end(spi); + spi_transfer_delay_exec(xfer); + } ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->curr_xfer = NULL; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + transfer_phase++; + } + ret = 0; + + exit: ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->curr_xfer = NULL; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + msg->status = ret; + + return ret; +-- +2.51.0 + diff --git a/queue-6.1/spi-tegra210-quad-return-irq_handled-when-timeout-al.patch b/queue-6.1/spi-tegra210-quad-return-irq_handled-when-timeout-al.patch new file mode 100644 index 0000000000..4a82767a64 --- /dev/null +++ b/queue-6.1/spi-tegra210-quad-return-irq_handled-when-timeout-al.patch @@ -0,0 +1,76 @@ +From 4ab9623d54fb1b92461c54a471e2d71bf014e82a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:26 -0800 +Subject: spi: tegra210-quad: Return IRQ_HANDLED when timeout already processed + transfer + +From: Breno Leitao + +[ Upstream commit aabd8ea0aa253d40cf5f20a609fc3d6f61e38299 ] + +When the ISR thread wakes up late and finds that the timeout handler +has already processed the transfer (curr_xfer is NULL), return +IRQ_HANDLED instead of IRQ_NONE. + +Use a similar approach to tegra_qspi_handle_timeout() by reading +QSPI_TRANS_STATUS and checking the QSPI_RDY bit to determine if the +hardware actually completed the transfer. If QSPI_RDY is set, the +interrupt was legitimate and triggered by real hardware activity. +The fact that the timeout path handled it first doesn't make it +spurious. Returning IRQ_NONE incorrectly suggests the interrupt +wasn't for this device, which can cause issues with shared interrupt +lines and interrupt accounting. + +Fixes: b4e002d8a7ce ("spi: tegra210-quad: Fix timeout handling") +Signed-off-by: Breno Leitao +Signed-off-by: Usama Arif +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Acked-by: Thierry Reding +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-1-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index 2e4d1b2f2a273..024e1468eee8d 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -1435,15 +1435,30 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_qspi *tqspi) + static irqreturn_t tegra_qspi_isr_thread(int irq, void *context_data) + { + struct tegra_qspi *tqspi = context_data; ++ u32 status; ++ ++ /* ++ * Read transfer status to check if interrupt was triggered by transfer ++ * completion ++ */ ++ status = tegra_qspi_readl(tqspi, QSPI_TRANS_STATUS); + + /* + * Occasionally the IRQ thread takes a long time to wake up (usually + * when the CPU that it's running on is excessively busy) and we have + * already reached the timeout before and cleaned up the timed out + * transfer. Avoid any processing in that case and bail out early. ++ * ++ * If no transfer is in progress, check if this was a real interrupt ++ * that the timeout handler already processed, or a spurious one. + */ +- if (!tqspi->curr_xfer) +- return IRQ_NONE; ++ if (!tqspi->curr_xfer) { ++ /* Spurious interrupt - transfer not ready */ ++ if (!(status & QSPI_RDY)) ++ return IRQ_NONE; ++ /* Real interrupt, already handled by timeout path */ ++ return IRQ_HANDLED; ++ } + + tqspi->status_reg = tegra_qspi_readl(tqspi, QSPI_FIFO_STATUS); + +-- +2.51.0 + diff --git a/queue-6.12/series b/queue-6.12/series index db789e72f9..0c296798f0 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -103,3 +103,10 @@ netfilter-nf_tables-fix-inverted-genmask-check-in-nf.patch ipv6-fix-ecmp-sibling-count-mismatch-when-clearing-r.patch alsa-usb-audio-fix-broken-logic-in-snd_audigy2nx_led.patch asoc-amd-fix-memory-leak-in-acp3x-pdm-dma-ops.patch +spi-tegra210-quad-return-irq_handled-when-timeout-al.patch +spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch +spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch +spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch +spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch +spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch +spi-tegra114-preserve-spi-mode-bits-in-def_command1_.patch diff --git a/queue-6.12/spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch b/queue-6.12/spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch new file mode 100644 index 0000000000..6db4b4c3f8 --- /dev/null +++ b/queue-6.12/spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch @@ -0,0 +1,44 @@ +From 43607075706930c86b8c09a34c83303e75cfb0b0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 Feb 2026 23:15:09 +0800 +Subject: spi: tegra: Fix a memory leak in tegra_slink_probe() + +From: Felix Gu + +[ Upstream commit 41d9a6795b95d6ea28439ac1e9ce8c95bbca20fc ] + +In tegra_slink_probe(), when platform_get_irq() fails, it directly +returns from the function with an error code, which causes a memory leak. + +Replace it with a goto label to ensure proper cleanup. + +Fixes: eb9913b511f1 ("spi: tegra: Fix missing IRQ check in tegra_slink_probe()") +Signed-off-by: Felix Gu +Reviewed-by: Jon Hunter +Link: https://patch.msgid.link/20260202-slink-v1-1-eac50433a6f9@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra20-slink.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c +index ed1393d159aee..6ea5135915884 100644 +--- a/drivers/spi/spi-tegra20-slink.c ++++ b/drivers/spi/spi-tegra20-slink.c +@@ -1086,8 +1086,10 @@ static int tegra_slink_probe(struct platform_device *pdev) + reset_control_deassert(tspi->rst); + + spi_irq = platform_get_irq(pdev, 0); +- if (spi_irq < 0) +- return spi_irq; ++ if (spi_irq < 0) { ++ ret = spi_irq; ++ goto exit_pm_put; ++ } + tspi->irq = spi_irq; + ret = request_threaded_irq(tspi->irq, tegra_slink_isr, + tegra_slink_isr_thread, IRQF_ONESHOT, +-- +2.51.0 + diff --git a/queue-6.12/spi-tegra114-preserve-spi-mode-bits-in-def_command1_.patch b/queue-6.12/spi-tegra114-preserve-spi-mode-bits-in-def_command1_.patch new file mode 100644 index 0000000000..17da4b0efe --- /dev/null +++ b/queue-6.12/spi-tegra114-preserve-spi-mode-bits-in-def_command1_.patch @@ -0,0 +1,50 @@ +From a364da31deda7b7c6047a0fdee05df750fea53d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 4 Feb 2026 14:12:12 +0000 +Subject: spi: tegra114: Preserve SPI mode bits in def_command1_reg + +From: Vishwaroop A + +[ Upstream commit a0a75b40c919b9f6d3a0b6c978e6ccf344c1be5a ] + +The COMMAND1 register bits [29:28] set the SPI mode, which controls +the clock idle level. When a transfer ends, tegra_spi_transfer_end() +writes def_command1_reg back to restore the default state, but this +register value currently lacks the mode bits. This results in the +clock always being configured as idle low, breaking devices that +need it high. + +Fix this by storing the mode bits in def_command1_reg during setup, +to prevent this field from always being cleared. + +Fixes: f333a331adfa ("spi/tegra114: add spi driver") +Signed-off-by: Vishwaroop A +Link: https://patch.msgid.link/20260204141212.1540382-1-va@nvidia.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra114.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c +index 11db703a0dde3..6aed6429358a2 100644 +--- a/drivers/spi/spi-tegra114.c ++++ b/drivers/spi/spi-tegra114.c +@@ -978,11 +978,14 @@ static int tegra_spi_setup(struct spi_device *spi) + if (spi_get_csgpiod(spi, 0)) + gpiod_set_value(spi_get_csgpiod(spi, 0), 0); + ++ /* Update default register to include CS polarity and SPI mode */ + val = tspi->def_command1_reg; + if (spi->mode & SPI_CS_HIGH) + val &= ~SPI_CS_POL_INACTIVE(spi_get_chipselect(spi, 0)); + else + val |= SPI_CS_POL_INACTIVE(spi_get_chipselect(spi, 0)); ++ val &= ~SPI_CONTROL_MODE_MASK; ++ val |= SPI_MODE_SEL(spi->mode & 0x3); + tspi->def_command1_reg = val; + tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); + spin_unlock_irqrestore(&tspi->lock, flags); +-- +2.51.0 + diff --git a/queue-6.12/spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch b/queue-6.12/spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch new file mode 100644 index 0000000000..5eddfcae8b --- /dev/null +++ b/queue-6.12/spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch @@ -0,0 +1,68 @@ +From a7734c0b86893f4233cc464efb2511f1b25bc051 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:27 -0800 +Subject: spi: tegra210-quad: Move curr_xfer read inside spinlock + +From: Breno Leitao + +[ Upstream commit ef13ba357656451d6371940d8414e3e271df97e3 ] + +Move the assignment of the transfer pointer from curr_xfer inside the +spinlock critical section in both handle_cpu_based_xfer() and +handle_dma_based_xfer(). + +Previously, curr_xfer was read before acquiring the lock, creating a +window where the timeout path could clear curr_xfer between reading it +and using it. By moving the read inside the lock, the handlers are +guaranteed to see a consistent value that cannot be modified by the +timeout path. + +Fixes: 921fc1838fb0 ("spi: tegra210-quad: Add support for Tegra210 QSPI controller") +Signed-off-by: Breno Leitao +Acked-by: Thierry Reding +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-2-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index 24f92af780188..226993cf32669 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -1334,10 +1334,11 @@ static int tegra_qspi_transfer_one_message(struct spi_controller *host, + + static irqreturn_t handle_cpu_based_xfer(struct tegra_qspi *tqspi) + { +- struct spi_transfer *t = tqspi->curr_xfer; ++ struct spi_transfer *t; + unsigned long flags; + + spin_lock_irqsave(&tqspi->lock, flags); ++ t = tqspi->curr_xfer; + + if (tqspi->tx_status || tqspi->rx_status) { + tegra_qspi_handle_error(tqspi); +@@ -1368,7 +1369,7 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_qspi *tqspi) + + static irqreturn_t handle_dma_based_xfer(struct tegra_qspi *tqspi) + { +- struct spi_transfer *t = tqspi->curr_xfer; ++ struct spi_transfer *t; + unsigned int total_fifo_words; + unsigned long flags; + long wait_status; +@@ -1405,6 +1406,7 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_qspi *tqspi) + } + + spin_lock_irqsave(&tqspi->lock, flags); ++ t = tqspi->curr_xfer; + + if (err) { + tegra_qspi_dma_unmap_xfer(tqspi, t); +-- +2.51.0 + diff --git a/queue-6.12/spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch b/queue-6.12/spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch new file mode 100644 index 0000000000..06acf4912d --- /dev/null +++ b/queue-6.12/spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch @@ -0,0 +1,64 @@ +From 8ec111bc07880a8a93c1d4011853d2d32f24b2b0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:28 -0800 +Subject: spi: tegra210-quad: Protect curr_xfer assignment in + tegra_qspi_setup_transfer_one + +From: Breno Leitao + +[ Upstream commit f5a4d7f5e32ba163cff893493ec1cbb0fd2fb0d5 ] + +When the timeout handler processes a completed transfer and signals +completion, the transfer thread can immediately set up the next transfer +and assign curr_xfer to point to it. + +If a delayed ISR from the previous transfer then runs, it checks if +(!tqspi->curr_xfer) (currently without the lock also -- to be fixed +soon) to detect stale interrupts, but this check passes because +curr_xfer now points to the new transfer. The ISR then incorrectly +processes the new transfer's context. + +Protect the curr_xfer assignment with the spinlock to ensure the ISR +either sees NULL (and bails out) or sees the new value only after the +assignment is complete. + +Fixes: 921fc1838fb0 ("spi: tegra210-quad: Add support for Tegra210 QSPI controller") +Signed-off-by: Breno Leitao +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Acked-by: Thierry Reding +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-3-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index 226993cf32669..0c25d9c303bba 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -814,6 +814,7 @@ static u32 tegra_qspi_setup_transfer_one(struct spi_device *spi, struct spi_tran + u32 command1, command2, speed = t->speed_hz; + u8 bits_per_word = t->bits_per_word; + u32 tx_tap = 0, rx_tap = 0; ++ unsigned long flags; + int req_mode; + + if (!has_acpi_companion(tqspi->dev) && speed != tqspi->cur_speed) { +@@ -821,10 +822,12 @@ static u32 tegra_qspi_setup_transfer_one(struct spi_device *spi, struct spi_tran + tqspi->cur_speed = speed; + } + ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->cur_pos = 0; + tqspi->cur_rx_pos = 0; + tqspi->cur_tx_pos = 0; + tqspi->curr_xfer = t; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + + if (is_first_of_msg) { + tegra_qspi_mask_clear_irq(tqspi); +-- +2.51.0 + diff --git a/queue-6.12/spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch b/queue-6.12/spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch new file mode 100644 index 0000000000..50396ac254 --- /dev/null +++ b/queue-6.12/spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch @@ -0,0 +1,51 @@ +From 5c53d55b760f1f3fa9808cade90a1b04d97ac6f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:30 -0800 +Subject: spi: tegra210-quad: Protect curr_xfer clearing in + tegra_qspi_non_combined_seq_xfer + +From: Breno Leitao + +[ Upstream commit 6d7723e8161f3c3f14125557e19dd080e9d882be ] + +Protect the curr_xfer clearing in tegra_qspi_non_combined_seq_xfer() +with the spinlock to prevent a race with the interrupt handler that +reads this field to check if a transfer is in progress. + +Fixes: b4e002d8a7ce ("spi: tegra210-quad: Fix timeout handling") +Signed-off-by: Breno Leitao +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Acked-by: Thierry Reding +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-5-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index 28552a8f27c14..edc9d400728a1 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -1200,6 +1200,7 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi, + struct spi_transfer *transfer; + bool is_first_msg = true; + int ret = 0, val = 0; ++ unsigned long flags; + + msg->status = 0; + msg->actual_length = 0; +@@ -1271,7 +1272,9 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi, + msg->actual_length += xfer->len + dummy_bytes; + + complete_xfer: ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->curr_xfer = NULL; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + + if (ret < 0) { + tegra_qspi_transfer_end(spi); +-- +2.51.0 + diff --git a/queue-6.12/spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch b/queue-6.12/spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch new file mode 100644 index 0000000000..729025c21d --- /dev/null +++ b/queue-6.12/spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch @@ -0,0 +1,66 @@ +From 7a8f63aa3d997430c1d927853e8f313e85d50c7b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:29 -0800 +Subject: spi: tegra210-quad: Protect curr_xfer in tegra_qspi_combined_seq_xfer + +From: Breno Leitao + +[ Upstream commit bf4528ab28e2bf112c3a2cdef44fd13f007781cd ] + +The curr_xfer field is read by the IRQ handler without holding the lock +to check if a transfer is in progress. When clearing curr_xfer in the +combined sequence transfer loop, protect it with the spinlock to prevent +a race with the interrupt handler. + +Protect the curr_xfer clearing at the exit path of +tegra_qspi_combined_seq_xfer() with the spinlock to prevent a race +with the interrupt handler that reads this field. + +Without this protection, the IRQ handler could read a partially updated +curr_xfer value, leading to NULL pointer dereference or use-after-free. + +Fixes: b4e002d8a7ce ("spi: tegra210-quad: Fix timeout handling") +Signed-off-by: Breno Leitao +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Acked-by: Thierry Reding +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-4-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index 0c25d9c303bba..28552a8f27c14 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -1064,6 +1064,7 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, + u32 address_value = 0; + u32 cmd_config = 0, addr_config = 0; + u8 cmd_value = 0, val = 0; ++ unsigned long flags; + + /* Enable Combined sequence mode */ + val = tegra_qspi_readl(tqspi, QSPI_GLOBAL_CONFIG); +@@ -1176,13 +1177,17 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, + tegra_qspi_transfer_end(spi); + spi_transfer_delay_exec(xfer); + } ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->curr_xfer = NULL; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + transfer_phase++; + } + ret = 0; + + exit: ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->curr_xfer = NULL; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + msg->status = ret; + + return ret; +-- +2.51.0 + diff --git a/queue-6.12/spi-tegra210-quad-return-irq_handled-when-timeout-al.patch b/queue-6.12/spi-tegra210-quad-return-irq_handled-when-timeout-al.patch new file mode 100644 index 0000000000..a22a5820d7 --- /dev/null +++ b/queue-6.12/spi-tegra210-quad-return-irq_handled-when-timeout-al.patch @@ -0,0 +1,76 @@ +From 63c1d3984151efd1ce8a3dd401a65cfcdd5b89ff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:26 -0800 +Subject: spi: tegra210-quad: Return IRQ_HANDLED when timeout already processed + transfer + +From: Breno Leitao + +[ Upstream commit aabd8ea0aa253d40cf5f20a609fc3d6f61e38299 ] + +When the ISR thread wakes up late and finds that the timeout handler +has already processed the transfer (curr_xfer is NULL), return +IRQ_HANDLED instead of IRQ_NONE. + +Use a similar approach to tegra_qspi_handle_timeout() by reading +QSPI_TRANS_STATUS and checking the QSPI_RDY bit to determine if the +hardware actually completed the transfer. If QSPI_RDY is set, the +interrupt was legitimate and triggered by real hardware activity. +The fact that the timeout path handled it first doesn't make it +spurious. Returning IRQ_NONE incorrectly suggests the interrupt +wasn't for this device, which can cause issues with shared interrupt +lines and interrupt accounting. + +Fixes: b4e002d8a7ce ("spi: tegra210-quad: Fix timeout handling") +Signed-off-by: Breno Leitao +Signed-off-by: Usama Arif +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Acked-by: Thierry Reding +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-1-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index 39aa0f1485686..24f92af780188 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -1444,15 +1444,30 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_qspi *tqspi) + static irqreturn_t tegra_qspi_isr_thread(int irq, void *context_data) + { + struct tegra_qspi *tqspi = context_data; ++ u32 status; ++ ++ /* ++ * Read transfer status to check if interrupt was triggered by transfer ++ * completion ++ */ ++ status = tegra_qspi_readl(tqspi, QSPI_TRANS_STATUS); + + /* + * Occasionally the IRQ thread takes a long time to wake up (usually + * when the CPU that it's running on is excessively busy) and we have + * already reached the timeout before and cleaned up the timed out + * transfer. Avoid any processing in that case and bail out early. ++ * ++ * If no transfer is in progress, check if this was a real interrupt ++ * that the timeout handler already processed, or a spurious one. + */ +- if (!tqspi->curr_xfer) +- return IRQ_NONE; ++ if (!tqspi->curr_xfer) { ++ /* Spurious interrupt - transfer not ready */ ++ if (!(status & QSPI_RDY)) ++ return IRQ_NONE; ++ /* Real interrupt, already handled by timeout path */ ++ return IRQ_HANDLED; ++ } + + tqspi->status_reg = tegra_qspi_readl(tqspi, QSPI_FIFO_STATUS); + +-- +2.51.0 + diff --git a/queue-6.18/regulator-spacemit-p1-fix-n_voltages-for-buck-and-ld.patch b/queue-6.18/regulator-spacemit-p1-fix-n_voltages-for-buck-and-ld.patch new file mode 100644 index 0000000000..f6dd417eea --- /dev/null +++ b/queue-6.18/regulator-spacemit-p1-fix-n_voltages-for-buck-and-ld.patch @@ -0,0 +1,56 @@ +From 85f0568275182d2076f318e261d94cfb9015c042 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Jan 2026 17:43:42 +0800 +Subject: regulator: spacemit-p1: Fix n_voltages for BUCK and LDO regulators + +From: Guodong Xu + +[ Upstream commit 41399c5d476156635c9a58de870d39318e22fa09 ] + +Higher voltage settings were unusable due to incorrect n_voltages values +causing registration failures. For example, setting aldo4 to 3.3V failed +with -EINVAL because the required selector (123) exceeded the allowed +range (n_voltages=117). + +Fix by aligning n_voltages with the hardware register widths per the P1 +datasheet [1]: +- BUCK: 255 (was 254), allows selectors 0-254, selector 255 is reserved +- LDO: 128 (was 117), allows selectors 0-127, selectors 0-10 are for + suspend mode, valid operational range is 11-127 + +This enables the full voltage range supported by the hardware. + +Fixes: 8b84d712ad84 ("regulator: spacemit: support SpacemiT P1 regulators") +Link: https://developer.spacemit.com/documentation [1] +Signed-off-by: Guodong Xu +Link: https://patch.msgid.link/20260122-spacemit-p1-v1-1-309be27fbff9@riscstar.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/regulator/spacemit-p1.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/regulator/spacemit-p1.c b/drivers/regulator/spacemit-p1.c +index 2bf9137e12b1d..2b585ba01a93d 100644 +--- a/drivers/regulator/spacemit-p1.c ++++ b/drivers/regulator/spacemit-p1.c +@@ -87,13 +87,13 @@ static const struct linear_range p1_ldo_ranges[] = { + } + + #define P1_BUCK_DESC(_n) \ +- P1_REG_DESC(BUCK, buck, _n, "vin", 0x47, BUCK_MASK, 254, p1_buck_ranges) ++ P1_REG_DESC(BUCK, buck, _n, "vin", 0x47, BUCK_MASK, 255, p1_buck_ranges) + + #define P1_ALDO_DESC(_n) \ +- P1_REG_DESC(ALDO, aldo, _n, "vin", 0x5b, LDO_MASK, 117, p1_ldo_ranges) ++ P1_REG_DESC(ALDO, aldo, _n, "vin", 0x5b, LDO_MASK, 128, p1_ldo_ranges) + + #define P1_DLDO_DESC(_n) \ +- P1_REG_DESC(DLDO, dldo, _n, "buck5", 0x67, LDO_MASK, 117, p1_ldo_ranges) ++ P1_REG_DESC(DLDO, dldo, _n, "buck5", 0x67, LDO_MASK, 128, p1_ldo_ranges) + + static const struct regulator_desc p1_regulator_desc[] = { + P1_BUCK_DESC(1), +-- +2.51.0 + diff --git a/queue-6.18/series b/queue-6.18/series index 2f973d848f..836c5ae9cf 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -160,3 +160,12 @@ firmware-cs_dsp-rate-limit-log-messages-in-kunit-bui.patch alsa-usb-audio-fix-broken-logic-in-snd_audigy2nx_led.patch asoc-amd-fix-memory-leak-in-acp3x-pdm-dma-ops.patch gpio-loongson-64bit-fix-incorrect-null-check-after-d.patch +regulator-spacemit-p1-fix-n_voltages-for-buck-and-ld.patch +spi-tegra210-quad-return-irq_handled-when-timeout-al.patch +spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch +spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch +spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch +spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch +spi-tegra210-quad-protect-curr_xfer-check-in-irq-han.patch +spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch +spi-tegra114-preserve-spi-mode-bits-in-def_command1_.patch diff --git a/queue-6.18/spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch b/queue-6.18/spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch new file mode 100644 index 0000000000..2dc6686337 --- /dev/null +++ b/queue-6.18/spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch @@ -0,0 +1,44 @@ +From ded8c88452bcf5d07d4e85f8b9910d27016a4290 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 Feb 2026 23:15:09 +0800 +Subject: spi: tegra: Fix a memory leak in tegra_slink_probe() + +From: Felix Gu + +[ Upstream commit 41d9a6795b95d6ea28439ac1e9ce8c95bbca20fc ] + +In tegra_slink_probe(), when platform_get_irq() fails, it directly +returns from the function with an error code, which causes a memory leak. + +Replace it with a goto label to ensure proper cleanup. + +Fixes: eb9913b511f1 ("spi: tegra: Fix missing IRQ check in tegra_slink_probe()") +Signed-off-by: Felix Gu +Reviewed-by: Jon Hunter +Link: https://patch.msgid.link/20260202-slink-v1-1-eac50433a6f9@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra20-slink.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c +index fe452d03c1ee4..709669610840b 100644 +--- a/drivers/spi/spi-tegra20-slink.c ++++ b/drivers/spi/spi-tegra20-slink.c +@@ -1086,8 +1086,10 @@ static int tegra_slink_probe(struct platform_device *pdev) + reset_control_deassert(tspi->rst); + + spi_irq = platform_get_irq(pdev, 0); +- if (spi_irq < 0) +- return spi_irq; ++ if (spi_irq < 0) { ++ ret = spi_irq; ++ goto exit_pm_put; ++ } + tspi->irq = spi_irq; + ret = request_threaded_irq(tspi->irq, tegra_slink_isr, + tegra_slink_isr_thread, IRQF_ONESHOT, +-- +2.51.0 + diff --git a/queue-6.18/spi-tegra114-preserve-spi-mode-bits-in-def_command1_.patch b/queue-6.18/spi-tegra114-preserve-spi-mode-bits-in-def_command1_.patch new file mode 100644 index 0000000000..be4f5e5b35 --- /dev/null +++ b/queue-6.18/spi-tegra114-preserve-spi-mode-bits-in-def_command1_.patch @@ -0,0 +1,50 @@ +From 5db47fa91b1693316fd02f63fe5458639ec87216 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 4 Feb 2026 14:12:12 +0000 +Subject: spi: tegra114: Preserve SPI mode bits in def_command1_reg + +From: Vishwaroop A + +[ Upstream commit a0a75b40c919b9f6d3a0b6c978e6ccf344c1be5a ] + +The COMMAND1 register bits [29:28] set the SPI mode, which controls +the clock idle level. When a transfer ends, tegra_spi_transfer_end() +writes def_command1_reg back to restore the default state, but this +register value currently lacks the mode bits. This results in the +clock always being configured as idle low, breaking devices that +need it high. + +Fix this by storing the mode bits in def_command1_reg during setup, +to prevent this field from always being cleared. + +Fixes: f333a331adfa ("spi/tegra114: add spi driver") +Signed-off-by: Vishwaroop A +Link: https://patch.msgid.link/20260204141212.1540382-1-va@nvidia.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra114.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c +index 795a8482c2c70..48fb11fea55f2 100644 +--- a/drivers/spi/spi-tegra114.c ++++ b/drivers/spi/spi-tegra114.c +@@ -978,11 +978,14 @@ static int tegra_spi_setup(struct spi_device *spi) + if (spi_get_csgpiod(spi, 0)) + gpiod_set_value(spi_get_csgpiod(spi, 0), 0); + ++ /* Update default register to include CS polarity and SPI mode */ + val = tspi->def_command1_reg; + if (spi->mode & SPI_CS_HIGH) + val &= ~SPI_CS_POL_INACTIVE(spi_get_chipselect(spi, 0)); + else + val |= SPI_CS_POL_INACTIVE(spi_get_chipselect(spi, 0)); ++ val &= ~SPI_CONTROL_MODE_MASK; ++ val |= SPI_MODE_SEL(spi->mode & 0x3); + tspi->def_command1_reg = val; + tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); + spin_unlock_irqrestore(&tspi->lock, flags); +-- +2.51.0 + diff --git a/queue-6.18/spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch b/queue-6.18/spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch new file mode 100644 index 0000000000..b4004b86de --- /dev/null +++ b/queue-6.18/spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch @@ -0,0 +1,68 @@ +From 3d1e853394e569e652830ed9edfe22291eb24abc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:27 -0800 +Subject: spi: tegra210-quad: Move curr_xfer read inside spinlock + +From: Breno Leitao + +[ Upstream commit ef13ba357656451d6371940d8414e3e271df97e3 ] + +Move the assignment of the transfer pointer from curr_xfer inside the +spinlock critical section in both handle_cpu_based_xfer() and +handle_dma_based_xfer(). + +Previously, curr_xfer was read before acquiring the lock, creating a +window where the timeout path could clear curr_xfer between reading it +and using it. By moving the read inside the lock, the handlers are +guaranteed to see a consistent value that cannot be modified by the +timeout path. + +Fixes: 921fc1838fb0 ("spi: tegra210-quad: Add support for Tegra210 QSPI controller") +Signed-off-by: Breno Leitao +Acked-by: Thierry Reding +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-2-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index c6c05e6f48994..a599bad02b4d3 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -1376,10 +1376,11 @@ static int tegra_qspi_transfer_one_message(struct spi_controller *host, + + static irqreturn_t handle_cpu_based_xfer(struct tegra_qspi *tqspi) + { +- struct spi_transfer *t = tqspi->curr_xfer; ++ struct spi_transfer *t; + unsigned long flags; + + spin_lock_irqsave(&tqspi->lock, flags); ++ t = tqspi->curr_xfer; + + if (tqspi->tx_status || tqspi->rx_status) { + tegra_qspi_handle_error(tqspi); +@@ -1410,7 +1411,7 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_qspi *tqspi) + + static irqreturn_t handle_dma_based_xfer(struct tegra_qspi *tqspi) + { +- struct spi_transfer *t = tqspi->curr_xfer; ++ struct spi_transfer *t; + unsigned int total_fifo_words; + unsigned long flags; + long wait_status; +@@ -1449,6 +1450,7 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_qspi *tqspi) + } + + spin_lock_irqsave(&tqspi->lock, flags); ++ t = tqspi->curr_xfer; + + if (num_errors) { + tegra_qspi_dma_unmap_xfer(tqspi, t); +-- +2.51.0 + diff --git a/queue-6.18/spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch b/queue-6.18/spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch new file mode 100644 index 0000000000..fa643b9306 --- /dev/null +++ b/queue-6.18/spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch @@ -0,0 +1,64 @@ +From 4f9e1f7f4cbc7513b3cdd0689c830b35521db68f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:28 -0800 +Subject: spi: tegra210-quad: Protect curr_xfer assignment in + tegra_qspi_setup_transfer_one + +From: Breno Leitao + +[ Upstream commit f5a4d7f5e32ba163cff893493ec1cbb0fd2fb0d5 ] + +When the timeout handler processes a completed transfer and signals +completion, the transfer thread can immediately set up the next transfer +and assign curr_xfer to point to it. + +If a delayed ISR from the previous transfer then runs, it checks if +(!tqspi->curr_xfer) (currently without the lock also -- to be fixed +soon) to detect stale interrupts, but this check passes because +curr_xfer now points to the new transfer. The ISR then incorrectly +processes the new transfer's context. + +Protect the curr_xfer assignment with the spinlock to ensure the ISR +either sees NULL (and bails out) or sees the new value only after the +assignment is complete. + +Fixes: 921fc1838fb0 ("spi: tegra210-quad: Add support for Tegra210 QSPI controller") +Signed-off-by: Breno Leitao +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Acked-by: Thierry Reding +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-3-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index a599bad02b4d3..6d89a9309d85e 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -839,6 +839,7 @@ static u32 tegra_qspi_setup_transfer_one(struct spi_device *spi, struct spi_tran + u32 command1, command2, speed = t->speed_hz; + u8 bits_per_word = t->bits_per_word; + u32 tx_tap = 0, rx_tap = 0; ++ unsigned long flags; + int req_mode; + + if (!has_acpi_companion(tqspi->dev) && speed != tqspi->cur_speed) { +@@ -846,10 +847,12 @@ static u32 tegra_qspi_setup_transfer_one(struct spi_device *spi, struct spi_tran + tqspi->cur_speed = speed; + } + ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->cur_pos = 0; + tqspi->cur_rx_pos = 0; + tqspi->cur_tx_pos = 0; + tqspi->curr_xfer = t; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + + if (is_first_of_msg) { + tegra_qspi_mask_clear_irq(tqspi); +-- +2.51.0 + diff --git a/queue-6.18/spi-tegra210-quad-protect-curr_xfer-check-in-irq-han.patch b/queue-6.18/spi-tegra210-quad-protect-curr_xfer-check-in-irq-han.patch new file mode 100644 index 0000000000..2634280825 --- /dev/null +++ b/queue-6.18/spi-tegra210-quad-protect-curr_xfer-check-in-irq-han.patch @@ -0,0 +1,114 @@ +From b300493fcd8070f30162d75d118c23b4701140e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:31 -0800 +Subject: spi: tegra210-quad: Protect curr_xfer check in IRQ handler + +From: Breno Leitao + +[ Upstream commit edf9088b6e1d6d88982db7eb5e736a0e4fbcc09e ] + +Now that all other accesses to curr_xfer are done under the lock, +protect the curr_xfer NULL check in tegra_qspi_isr_thread() with the +spinlock. Without this protection, the following race can occur: + + CPU0 (ISR thread) CPU1 (timeout path) + ---------------- ------------------- + if (!tqspi->curr_xfer) + // sees non-NULL + spin_lock() + tqspi->curr_xfer = NULL + spin_unlock() + handle_*_xfer() + spin_lock() + t = tqspi->curr_xfer // NULL! + ... t->len ... // NULL dereference! + +With this patch, all curr_xfer accesses are now properly synchronized. + +Although all accesses to curr_xfer are done under the lock, in +tegra_qspi_isr_thread() it checks for NULL, releases the lock and +reacquires it later in handle_cpu_based_xfer()/handle_dma_based_xfer(). +There is a potential for an update in between, which could cause a NULL +pointer dereference. + +To handle this, add a NULL check inside the handlers after acquiring +the lock. This ensures that if the timeout path has already cleared +curr_xfer, the handler will safely return without dereferencing the +NULL pointer. + +Fixes: b4e002d8a7ce ("spi: tegra210-quad: Fix timeout handling") +Signed-off-by: Breno Leitao +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Acked-by: Thierry Reding +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-6-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index 7fe16ed7e84bd..83def82fe48c1 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -1393,6 +1393,11 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_qspi *tqspi) + spin_lock_irqsave(&tqspi->lock, flags); + t = tqspi->curr_xfer; + ++ if (!t) { ++ spin_unlock_irqrestore(&tqspi->lock, flags); ++ return IRQ_HANDLED; ++ } ++ + if (tqspi->tx_status || tqspi->rx_status) { + tegra_qspi_handle_error(tqspi); + complete(&tqspi->xfer_completion); +@@ -1463,6 +1468,11 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_qspi *tqspi) + spin_lock_irqsave(&tqspi->lock, flags); + t = tqspi->curr_xfer; + ++ if (!t) { ++ spin_unlock_irqrestore(&tqspi->lock, flags); ++ return IRQ_HANDLED; ++ } ++ + if (num_errors) { + tegra_qspi_dma_unmap_xfer(tqspi, t); + tegra_qspi_handle_error(tqspi); +@@ -1501,6 +1511,7 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_qspi *tqspi) + static irqreturn_t tegra_qspi_isr_thread(int irq, void *context_data) + { + struct tegra_qspi *tqspi = context_data; ++ unsigned long flags; + u32 status; + + /* +@@ -1518,7 +1529,9 @@ static irqreturn_t tegra_qspi_isr_thread(int irq, void *context_data) + * If no transfer is in progress, check if this was a real interrupt + * that the timeout handler already processed, or a spurious one. + */ ++ spin_lock_irqsave(&tqspi->lock, flags); + if (!tqspi->curr_xfer) { ++ spin_unlock_irqrestore(&tqspi->lock, flags); + /* Spurious interrupt - transfer not ready */ + if (!(status & QSPI_RDY)) + return IRQ_NONE; +@@ -1535,7 +1548,14 @@ static irqreturn_t tegra_qspi_isr_thread(int irq, void *context_data) + tqspi->rx_status = tqspi->status_reg & (QSPI_RX_FIFO_OVF | QSPI_RX_FIFO_UNF); + + tegra_qspi_mask_clear_irq(tqspi); ++ spin_unlock_irqrestore(&tqspi->lock, flags); + ++ /* ++ * Lock is released here but handlers safely re-check curr_xfer under ++ * lock before dereferencing. ++ * DMA handler also needs to sleep in wait_for_completion_*(), which ++ * cannot be done while holding spinlock. ++ */ + if (!tqspi->is_curr_dma_xfer) + return handle_cpu_based_xfer(tqspi); + +-- +2.51.0 + diff --git a/queue-6.18/spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch b/queue-6.18/spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch new file mode 100644 index 0000000000..665ec2b23b --- /dev/null +++ b/queue-6.18/spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch @@ -0,0 +1,51 @@ +From 7a6f2a8dee397deb79875b7a6da5704c4a8a1bd1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:30 -0800 +Subject: spi: tegra210-quad: Protect curr_xfer clearing in + tegra_qspi_non_combined_seq_xfer + +From: Breno Leitao + +[ Upstream commit 6d7723e8161f3c3f14125557e19dd080e9d882be ] + +Protect the curr_xfer clearing in tegra_qspi_non_combined_seq_xfer() +with the spinlock to prevent a race with the interrupt handler that +reads this field to check if a transfer is in progress. + +Fixes: b4e002d8a7ce ("spi: tegra210-quad: Fix timeout handling") +Signed-off-by: Breno Leitao +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Acked-by: Thierry Reding +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-5-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index 78e26c25a7b35..7fe16ed7e84bd 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -1231,6 +1231,7 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi, + struct spi_transfer *transfer; + bool is_first_msg = true; + int ret = 0, val = 0; ++ unsigned long flags; + + msg->status = 0; + msg->actual_length = 0; +@@ -1304,7 +1305,9 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi, + msg->actual_length += xfer->len + dummy_bytes; + + complete_xfer: ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->curr_xfer = NULL; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + + if (ret < 0) { + tegra_qspi_transfer_end(spi); +-- +2.51.0 + diff --git a/queue-6.18/spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch b/queue-6.18/spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch new file mode 100644 index 0000000000..a8636e310f --- /dev/null +++ b/queue-6.18/spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch @@ -0,0 +1,66 @@ +From e536a20f808756cb0d200e785976b188525b919e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:29 -0800 +Subject: spi: tegra210-quad: Protect curr_xfer in tegra_qspi_combined_seq_xfer + +From: Breno Leitao + +[ Upstream commit bf4528ab28e2bf112c3a2cdef44fd13f007781cd ] + +The curr_xfer field is read by the IRQ handler without holding the lock +to check if a transfer is in progress. When clearing curr_xfer in the +combined sequence transfer loop, protect it with the spinlock to prevent +a race with the interrupt handler. + +Protect the curr_xfer clearing at the exit path of +tegra_qspi_combined_seq_xfer() with the spinlock to prevent a race +with the interrupt handler that reads this field. + +Without this protection, the IRQ handler could read a partially updated +curr_xfer value, leading to NULL pointer dereference or use-after-free. + +Fixes: b4e002d8a7ce ("spi: tegra210-quad: Fix timeout handling") +Signed-off-by: Breno Leitao +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Acked-by: Thierry Reding +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-4-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index 6d89a9309d85e..78e26c25a7b35 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -1089,6 +1089,7 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, + u32 address_value = 0; + u32 cmd_config = 0, addr_config = 0; + u8 cmd_value = 0, val = 0; ++ unsigned long flags; + + /* Enable Combined sequence mode */ + val = tegra_qspi_readl(tqspi, QSPI_GLOBAL_CONFIG); +@@ -1207,13 +1208,17 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, + tegra_qspi_transfer_end(spi); + spi_transfer_delay_exec(xfer); + } ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->curr_xfer = NULL; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + transfer_phase++; + } + ret = 0; + + exit: ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->curr_xfer = NULL; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + msg->status = ret; + + return ret; +-- +2.51.0 + diff --git a/queue-6.18/spi-tegra210-quad-return-irq_handled-when-timeout-al.patch b/queue-6.18/spi-tegra210-quad-return-irq_handled-when-timeout-al.patch new file mode 100644 index 0000000000..9908e082e7 --- /dev/null +++ b/queue-6.18/spi-tegra210-quad-return-irq_handled-when-timeout-al.patch @@ -0,0 +1,76 @@ +From 84fc81a14d3c846e8a3e2d692a4e08c4c10666b7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:26 -0800 +Subject: spi: tegra210-quad: Return IRQ_HANDLED when timeout already processed + transfer + +From: Breno Leitao + +[ Upstream commit aabd8ea0aa253d40cf5f20a609fc3d6f61e38299 ] + +When the ISR thread wakes up late and finds that the timeout handler +has already processed the transfer (curr_xfer is NULL), return +IRQ_HANDLED instead of IRQ_NONE. + +Use a similar approach to tegra_qspi_handle_timeout() by reading +QSPI_TRANS_STATUS and checking the QSPI_RDY bit to determine if the +hardware actually completed the transfer. If QSPI_RDY is set, the +interrupt was legitimate and triggered by real hardware activity. +The fact that the timeout path handled it first doesn't make it +spurious. Returning IRQ_NONE incorrectly suggests the interrupt +wasn't for this device, which can cause issues with shared interrupt +lines and interrupt accounting. + +Fixes: b4e002d8a7ce ("spi: tegra210-quad: Fix timeout handling") +Signed-off-by: Breno Leitao +Signed-off-by: Usama Arif +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Acked-by: Thierry Reding +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-1-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index d9ca3d7b082f2..c6c05e6f48994 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -1488,15 +1488,30 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_qspi *tqspi) + static irqreturn_t tegra_qspi_isr_thread(int irq, void *context_data) + { + struct tegra_qspi *tqspi = context_data; ++ u32 status; ++ ++ /* ++ * Read transfer status to check if interrupt was triggered by transfer ++ * completion ++ */ ++ status = tegra_qspi_readl(tqspi, QSPI_TRANS_STATUS); + + /* + * Occasionally the IRQ thread takes a long time to wake up (usually + * when the CPU that it's running on is excessively busy) and we have + * already reached the timeout before and cleaned up the timed out + * transfer. Avoid any processing in that case and bail out early. ++ * ++ * If no transfer is in progress, check if this was a real interrupt ++ * that the timeout handler already processed, or a spurious one. + */ +- if (!tqspi->curr_xfer) +- return IRQ_NONE; ++ if (!tqspi->curr_xfer) { ++ /* Spurious interrupt - transfer not ready */ ++ if (!(status & QSPI_RDY)) ++ return IRQ_NONE; ++ /* Real interrupt, already handled by timeout path */ ++ return IRQ_HANDLED; ++ } + + tqspi->status_reg = tegra_qspi_readl(tqspi, QSPI_FIFO_STATUS); + +-- +2.51.0 + diff --git a/queue-6.6/gve-correct-ethtool-rx_dropped-calculation.patch b/queue-6.6/gve-correct-ethtool-rx_dropped-calculation.patch new file mode 100644 index 0000000000..7cc67c7a20 --- /dev/null +++ b/queue-6.6/gve-correct-ethtool-rx_dropped-calculation.patch @@ -0,0 +1,119 @@ +From 3618bfeccb91eca30e072711bb78a6c94512b562 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 Feb 2026 19:39:25 +0000 +Subject: gve: Correct ethtool rx_dropped calculation + +From: Max Yuan + +[ Upstream commit c7db85d579a1dccb624235534508c75fbf2dfe46 ] + +The gve driver's "rx_dropped" statistic, exposed via `ethtool -S`, +incorrectly includes `rx_buf_alloc_fail` counts. These failures +represent an inability to allocate receive buffers, not true packet +drops where a received packet is discarded. This misrepresentation can +lead to inaccurate diagnostics. + +This patch rectifies the ethtool "rx_dropped" calculation. It removes +`rx_buf_alloc_fail` from the total and adds `xdp_tx_errors` and +`xdp_redirect_errors`, which represent legitimate packet drops within +the XDP path. + +Cc: stable@vger.kernel.org +Fixes: 433e274b8f7b ("gve: Add stats for gve.") +Signed-off-by: Max Yuan +Reviewed-by: Jordan Rhee +Reviewed-by: Joshua Washington +Reviewed-by: Matt Olson +Signed-off-by: Harshitha Ramamurthy +Reviewed-by: Jacob Keller +Link: https://patch.msgid.link/20260202193925.3106272-3-hramamurthy@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/google/gve/gve_ethtool.c | 27 ++++++++++++++----- + 1 file changed, 20 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c +index 59c509ade2625..b1c4df3bab292 100644 +--- a/drivers/net/ethernet/google/gve/gve_ethtool.c ++++ b/drivers/net/ethernet/google/gve/gve_ethtool.c +@@ -156,9 +156,11 @@ gve_get_ethtool_stats(struct net_device *netdev, + { + u64 tmp_rx_pkts, tmp_rx_bytes, tmp_rx_skb_alloc_fail, + tmp_rx_buf_alloc_fail, tmp_rx_desc_err_dropped_pkt, +- tmp_tx_pkts, tmp_tx_bytes; ++ tmp_tx_pkts, tmp_tx_bytes, ++ tmp_xdp_tx_errors, tmp_xdp_redirect_errors; + u64 rx_buf_alloc_fail, rx_desc_err_dropped_pkt, rx_pkts, +- rx_skb_alloc_fail, rx_bytes, tx_pkts, tx_bytes, tx_dropped; ++ rx_skb_alloc_fail, rx_bytes, tx_pkts, tx_bytes, tx_dropped, ++ xdp_tx_errors, xdp_redirect_errors; + int rx_base_stats_idx, max_rx_stats_idx, max_tx_stats_idx; + int stats_idx, stats_region_len, nic_stats_len; + struct stats *report_stats; +@@ -187,7 +189,9 @@ gve_get_ethtool_stats(struct net_device *netdev, + return; + } + for (rx_pkts = 0, rx_bytes = 0, rx_skb_alloc_fail = 0, +- rx_buf_alloc_fail = 0, rx_desc_err_dropped_pkt = 0, ring = 0; ++ rx_buf_alloc_fail = 0, rx_desc_err_dropped_pkt = 0, ++ xdp_tx_errors = 0, xdp_redirect_errors = 0, ++ ring = 0; + ring < priv->rx_cfg.num_queues; ring++) { + if (priv->rx) { + do { +@@ -201,6 +205,9 @@ gve_get_ethtool_stats(struct net_device *netdev, + tmp_rx_buf_alloc_fail = rx->rx_buf_alloc_fail; + tmp_rx_desc_err_dropped_pkt = + rx->rx_desc_err_dropped_pkt; ++ tmp_xdp_tx_errors = rx->xdp_tx_errors; ++ tmp_xdp_redirect_errors = ++ rx->xdp_redirect_errors; + } while (u64_stats_fetch_retry(&priv->rx[ring].statss, + start)); + rx_pkts += tmp_rx_pkts; +@@ -208,6 +215,8 @@ gve_get_ethtool_stats(struct net_device *netdev, + rx_skb_alloc_fail += tmp_rx_skb_alloc_fail; + rx_buf_alloc_fail += tmp_rx_buf_alloc_fail; + rx_desc_err_dropped_pkt += tmp_rx_desc_err_dropped_pkt; ++ xdp_tx_errors += tmp_xdp_tx_errors; ++ xdp_redirect_errors += tmp_xdp_redirect_errors; + } + } + for (tx_pkts = 0, tx_bytes = 0, tx_dropped = 0, ring = 0; +@@ -232,8 +241,8 @@ gve_get_ethtool_stats(struct net_device *netdev, + data[i++] = rx_bytes; + data[i++] = tx_bytes; + /* total rx dropped packets */ +- data[i++] = rx_skb_alloc_fail + rx_buf_alloc_fail + +- rx_desc_err_dropped_pkt; ++ data[i++] = rx_skb_alloc_fail + rx_desc_err_dropped_pkt + ++ xdp_tx_errors + xdp_redirect_errors; + data[i++] = tx_dropped; + data[i++] = priv->tx_timeo_cnt; + data[i++] = rx_skb_alloc_fail; +@@ -300,6 +309,9 @@ gve_get_ethtool_stats(struct net_device *netdev, + tmp_rx_buf_alloc_fail = rx->rx_buf_alloc_fail; + tmp_rx_desc_err_dropped_pkt = + rx->rx_desc_err_dropped_pkt; ++ tmp_xdp_tx_errors = rx->xdp_tx_errors; ++ tmp_xdp_redirect_errors = ++ rx->xdp_redirect_errors; + } while (u64_stats_fetch_retry(&priv->rx[ring].statss, + start)); + data[i++] = tmp_rx_bytes; +@@ -309,8 +321,9 @@ gve_get_ethtool_stats(struct net_device *netdev, + data[i++] = rx->rx_frag_alloc_cnt; + /* rx dropped packets */ + data[i++] = tmp_rx_skb_alloc_fail + +- tmp_rx_buf_alloc_fail + +- tmp_rx_desc_err_dropped_pkt; ++ tmp_rx_desc_err_dropped_pkt + ++ tmp_xdp_tx_errors + ++ tmp_xdp_redirect_errors; + data[i++] = rx->rx_copybreak_pkt; + data[i++] = rx->rx_copied_pkt; + /* stats from NIC */ +-- +2.51.0 + diff --git a/queue-6.6/series b/queue-6.6/series index d82dd5502f..3a8f843979 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -74,3 +74,11 @@ hwmon-occ-mark-occ_init_attribute-as-__printf.patch netfilter-nf_tables-fix-inverted-genmask-check-in-nf.patch ipv6-fix-ecmp-sibling-count-mismatch-when-clearing-r.patch asoc-amd-fix-memory-leak-in-acp3x-pdm-dma-ops.patch +gve-correct-ethtool-rx_dropped-calculation.patch +spi-tegra210-quad-return-irq_handled-when-timeout-al.patch +spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch +spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch +spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch +spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch +spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch +spi-tegra114-preserve-spi-mode-bits-in-def_command1_.patch diff --git a/queue-6.6/spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch b/queue-6.6/spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch new file mode 100644 index 0000000000..87f1f35070 --- /dev/null +++ b/queue-6.6/spi-tegra-fix-a-memory-leak-in-tegra_slink_probe.patch @@ -0,0 +1,44 @@ +From af6b993e4d3dff08ab1014bfa12826645e1d13bd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 Feb 2026 23:15:09 +0800 +Subject: spi: tegra: Fix a memory leak in tegra_slink_probe() + +From: Felix Gu + +[ Upstream commit 41d9a6795b95d6ea28439ac1e9ce8c95bbca20fc ] + +In tegra_slink_probe(), when platform_get_irq() fails, it directly +returns from the function with an error code, which causes a memory leak. + +Replace it with a goto label to ensure proper cleanup. + +Fixes: eb9913b511f1 ("spi: tegra: Fix missing IRQ check in tegra_slink_probe()") +Signed-off-by: Felix Gu +Reviewed-by: Jon Hunter +Link: https://patch.msgid.link/20260202-slink-v1-1-eac50433a6f9@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra20-slink.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c +index f5cd365c913a8..f450409156c64 100644 +--- a/drivers/spi/spi-tegra20-slink.c ++++ b/drivers/spi/spi-tegra20-slink.c +@@ -1086,8 +1086,10 @@ static int tegra_slink_probe(struct platform_device *pdev) + reset_control_deassert(tspi->rst); + + spi_irq = platform_get_irq(pdev, 0); +- if (spi_irq < 0) +- return spi_irq; ++ if (spi_irq < 0) { ++ ret = spi_irq; ++ goto exit_pm_put; ++ } + tspi->irq = spi_irq; + ret = request_threaded_irq(tspi->irq, tegra_slink_isr, + tegra_slink_isr_thread, IRQF_ONESHOT, +-- +2.51.0 + diff --git a/queue-6.6/spi-tegra114-preserve-spi-mode-bits-in-def_command1_.patch b/queue-6.6/spi-tegra114-preserve-spi-mode-bits-in-def_command1_.patch new file mode 100644 index 0000000000..61bf159aaf --- /dev/null +++ b/queue-6.6/spi-tegra114-preserve-spi-mode-bits-in-def_command1_.patch @@ -0,0 +1,50 @@ +From 260eb8cf860bcf3ca25b9898194d0ff48196cff4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 4 Feb 2026 14:12:12 +0000 +Subject: spi: tegra114: Preserve SPI mode bits in def_command1_reg + +From: Vishwaroop A + +[ Upstream commit a0a75b40c919b9f6d3a0b6c978e6ccf344c1be5a ] + +The COMMAND1 register bits [29:28] set the SPI mode, which controls +the clock idle level. When a transfer ends, tegra_spi_transfer_end() +writes def_command1_reg back to restore the default state, but this +register value currently lacks the mode bits. This results in the +clock always being configured as idle low, breaking devices that +need it high. + +Fix this by storing the mode bits in def_command1_reg during setup, +to prevent this field from always being cleared. + +Fixes: f333a331adfa ("spi/tegra114: add spi driver") +Signed-off-by: Vishwaroop A +Link: https://patch.msgid.link/20260204141212.1540382-1-va@nvidia.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra114.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c +index 8d7ce4c556aa1..c99f72c9ab176 100644 +--- a/drivers/spi/spi-tegra114.c ++++ b/drivers/spi/spi-tegra114.c +@@ -978,11 +978,14 @@ static int tegra_spi_setup(struct spi_device *spi) + if (spi_get_csgpiod(spi, 0)) + gpiod_set_value(spi_get_csgpiod(spi, 0), 0); + ++ /* Update default register to include CS polarity and SPI mode */ + val = tspi->def_command1_reg; + if (spi->mode & SPI_CS_HIGH) + val &= ~SPI_CS_POL_INACTIVE(spi_get_chipselect(spi, 0)); + else + val |= SPI_CS_POL_INACTIVE(spi_get_chipselect(spi, 0)); ++ val &= ~SPI_CONTROL_MODE_MASK; ++ val |= SPI_MODE_SEL(spi->mode & 0x3); + tspi->def_command1_reg = val; + tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); + spin_unlock_irqrestore(&tspi->lock, flags); +-- +2.51.0 + diff --git a/queue-6.6/spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch b/queue-6.6/spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch new file mode 100644 index 0000000000..322fd1c60c --- /dev/null +++ b/queue-6.6/spi-tegra210-quad-move-curr_xfer-read-inside-spinloc.patch @@ -0,0 +1,68 @@ +From 09987ae47cf11be39ae958c49f52aa41797d8134 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:27 -0800 +Subject: spi: tegra210-quad: Move curr_xfer read inside spinlock + +From: Breno Leitao + +[ Upstream commit ef13ba357656451d6371940d8414e3e271df97e3 ] + +Move the assignment of the transfer pointer from curr_xfer inside the +spinlock critical section in both handle_cpu_based_xfer() and +handle_dma_based_xfer(). + +Previously, curr_xfer was read before acquiring the lock, creating a +window where the timeout path could clear curr_xfer between reading it +and using it. By moving the read inside the lock, the handlers are +guaranteed to see a consistent value that cannot be modified by the +timeout path. + +Fixes: 921fc1838fb0 ("spi: tegra210-quad: Add support for Tegra210 QSPI controller") +Signed-off-by: Breno Leitao +Acked-by: Thierry Reding +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-2-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index 1fffb1ab30af6..a190abc8d03d1 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -1334,10 +1334,11 @@ static int tegra_qspi_transfer_one_message(struct spi_master *master, + + static irqreturn_t handle_cpu_based_xfer(struct tegra_qspi *tqspi) + { +- struct spi_transfer *t = tqspi->curr_xfer; ++ struct spi_transfer *t; + unsigned long flags; + + spin_lock_irqsave(&tqspi->lock, flags); ++ t = tqspi->curr_xfer; + + if (tqspi->tx_status || tqspi->rx_status) { + tegra_qspi_handle_error(tqspi); +@@ -1368,7 +1369,7 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_qspi *tqspi) + + static irqreturn_t handle_dma_based_xfer(struct tegra_qspi *tqspi) + { +- struct spi_transfer *t = tqspi->curr_xfer; ++ struct spi_transfer *t; + unsigned int total_fifo_words; + unsigned long flags; + long wait_status; +@@ -1405,6 +1406,7 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_qspi *tqspi) + } + + spin_lock_irqsave(&tqspi->lock, flags); ++ t = tqspi->curr_xfer; + + if (err) { + tegra_qspi_dma_unmap_xfer(tqspi, t); +-- +2.51.0 + diff --git a/queue-6.6/spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch b/queue-6.6/spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch new file mode 100644 index 0000000000..8698f2e90a --- /dev/null +++ b/queue-6.6/spi-tegra210-quad-protect-curr_xfer-assignment-in-te.patch @@ -0,0 +1,64 @@ +From 32bd2614c883fab9192ec058f6693abfe7c84463 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:28 -0800 +Subject: spi: tegra210-quad: Protect curr_xfer assignment in + tegra_qspi_setup_transfer_one + +From: Breno Leitao + +[ Upstream commit f5a4d7f5e32ba163cff893493ec1cbb0fd2fb0d5 ] + +When the timeout handler processes a completed transfer and signals +completion, the transfer thread can immediately set up the next transfer +and assign curr_xfer to point to it. + +If a delayed ISR from the previous transfer then runs, it checks if +(!tqspi->curr_xfer) (currently without the lock also -- to be fixed +soon) to detect stale interrupts, but this check passes because +curr_xfer now points to the new transfer. The ISR then incorrectly +processes the new transfer's context. + +Protect the curr_xfer assignment with the spinlock to ensure the ISR +either sees NULL (and bails out) or sees the new value only after the +assignment is complete. + +Fixes: 921fc1838fb0 ("spi: tegra210-quad: Add support for Tegra210 QSPI controller") +Signed-off-by: Breno Leitao +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Acked-by: Thierry Reding +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-3-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index a190abc8d03d1..a4945ff4fdcb2 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -814,6 +814,7 @@ static u32 tegra_qspi_setup_transfer_one(struct spi_device *spi, struct spi_tran + u32 command1, command2, speed = t->speed_hz; + u8 bits_per_word = t->bits_per_word; + u32 tx_tap = 0, rx_tap = 0; ++ unsigned long flags; + int req_mode; + + if (!has_acpi_companion(tqspi->dev) && speed != tqspi->cur_speed) { +@@ -821,10 +822,12 @@ static u32 tegra_qspi_setup_transfer_one(struct spi_device *spi, struct spi_tran + tqspi->cur_speed = speed; + } + ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->cur_pos = 0; + tqspi->cur_rx_pos = 0; + tqspi->cur_tx_pos = 0; + tqspi->curr_xfer = t; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + + if (is_first_of_msg) { + tegra_qspi_mask_clear_irq(tqspi); +-- +2.51.0 + diff --git a/queue-6.6/spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch b/queue-6.6/spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch new file mode 100644 index 0000000000..029b3b796a --- /dev/null +++ b/queue-6.6/spi-tegra210-quad-protect-curr_xfer-clearing-in-tegr.patch @@ -0,0 +1,51 @@ +From 14b188c7739b371a076503659fcf251e0c67fcfe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:30 -0800 +Subject: spi: tegra210-quad: Protect curr_xfer clearing in + tegra_qspi_non_combined_seq_xfer + +From: Breno Leitao + +[ Upstream commit 6d7723e8161f3c3f14125557e19dd080e9d882be ] + +Protect the curr_xfer clearing in tegra_qspi_non_combined_seq_xfer() +with the spinlock to prevent a race with the interrupt handler that +reads this field to check if a transfer is in progress. + +Fixes: b4e002d8a7ce ("spi: tegra210-quad: Fix timeout handling") +Signed-off-by: Breno Leitao +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Acked-by: Thierry Reding +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-5-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index 4ea46fc038a39..f7677b960c342 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -1200,6 +1200,7 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi, + struct spi_transfer *transfer; + bool is_first_msg = true; + int ret = 0, val = 0; ++ unsigned long flags; + + msg->status = 0; + msg->actual_length = 0; +@@ -1271,7 +1272,9 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi, + msg->actual_length += xfer->len + dummy_bytes; + + complete_xfer: ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->curr_xfer = NULL; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + + if (ret < 0) { + tegra_qspi_transfer_end(spi); +-- +2.51.0 + diff --git a/queue-6.6/spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch b/queue-6.6/spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch new file mode 100644 index 0000000000..b5b4bfbff7 --- /dev/null +++ b/queue-6.6/spi-tegra210-quad-protect-curr_xfer-in-tegra_qspi_co.patch @@ -0,0 +1,66 @@ +From 09cafaa5f48f4dce6329ff9884c7e792809f0c73 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:29 -0800 +Subject: spi: tegra210-quad: Protect curr_xfer in tegra_qspi_combined_seq_xfer + +From: Breno Leitao + +[ Upstream commit bf4528ab28e2bf112c3a2cdef44fd13f007781cd ] + +The curr_xfer field is read by the IRQ handler without holding the lock +to check if a transfer is in progress. When clearing curr_xfer in the +combined sequence transfer loop, protect it with the spinlock to prevent +a race with the interrupt handler. + +Protect the curr_xfer clearing at the exit path of +tegra_qspi_combined_seq_xfer() with the spinlock to prevent a race +with the interrupt handler that reads this field. + +Without this protection, the IRQ handler could read a partially updated +curr_xfer value, leading to NULL pointer dereference or use-after-free. + +Fixes: b4e002d8a7ce ("spi: tegra210-quad: Fix timeout handling") +Signed-off-by: Breno Leitao +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Acked-by: Thierry Reding +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-4-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index a4945ff4fdcb2..4ea46fc038a39 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -1064,6 +1064,7 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, + u32 address_value = 0; + u32 cmd_config = 0, addr_config = 0; + u8 cmd_value = 0, val = 0; ++ unsigned long flags; + + /* Enable Combined sequence mode */ + val = tegra_qspi_readl(tqspi, QSPI_GLOBAL_CONFIG); +@@ -1176,13 +1177,17 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, + tegra_qspi_transfer_end(spi); + spi_transfer_delay_exec(xfer); + } ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->curr_xfer = NULL; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + transfer_phase++; + } + ret = 0; + + exit: ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->curr_xfer = NULL; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + msg->status = ret; + + return ret; +-- +2.51.0 + diff --git a/queue-6.6/spi-tegra210-quad-return-irq_handled-when-timeout-al.patch b/queue-6.6/spi-tegra210-quad-return-irq_handled-when-timeout-al.patch new file mode 100644 index 0000000000..2f5eab255a --- /dev/null +++ b/queue-6.6/spi-tegra210-quad-return-irq_handled-when-timeout-al.patch @@ -0,0 +1,76 @@ +From b52d94826b34aeed58a56ac4e7e92a40f130554d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jan 2026 09:50:26 -0800 +Subject: spi: tegra210-quad: Return IRQ_HANDLED when timeout already processed + transfer + +From: Breno Leitao + +[ Upstream commit aabd8ea0aa253d40cf5f20a609fc3d6f61e38299 ] + +When the ISR thread wakes up late and finds that the timeout handler +has already processed the transfer (curr_xfer is NULL), return +IRQ_HANDLED instead of IRQ_NONE. + +Use a similar approach to tegra_qspi_handle_timeout() by reading +QSPI_TRANS_STATUS and checking the QSPI_RDY bit to determine if the +hardware actually completed the transfer. If QSPI_RDY is set, the +interrupt was legitimate and triggered by real hardware activity. +The fact that the timeout path handled it first doesn't make it +spurious. Returning IRQ_NONE incorrectly suggests the interrupt +wasn't for this device, which can cause issues with shared interrupt +lines and interrupt accounting. + +Fixes: b4e002d8a7ce ("spi: tegra210-quad: Fix timeout handling") +Signed-off-by: Breno Leitao +Signed-off-by: Usama Arif +Tested-by: Jon Hunter +Acked-by: Jon Hunter +Acked-by: Thierry Reding +Link: https://patch.msgid.link/20260126-tegra_xfer-v2-1-6d2115e4f387@debian.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-tegra210-quad.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index d9a487274b530..1fffb1ab30af6 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -1444,15 +1444,30 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_qspi *tqspi) + static irqreturn_t tegra_qspi_isr_thread(int irq, void *context_data) + { + struct tegra_qspi *tqspi = context_data; ++ u32 status; ++ ++ /* ++ * Read transfer status to check if interrupt was triggered by transfer ++ * completion ++ */ ++ status = tegra_qspi_readl(tqspi, QSPI_TRANS_STATUS); + + /* + * Occasionally the IRQ thread takes a long time to wake up (usually + * when the CPU that it's running on is excessively busy) and we have + * already reached the timeout before and cleaned up the timed out + * transfer. Avoid any processing in that case and bail out early. ++ * ++ * If no transfer is in progress, check if this was a real interrupt ++ * that the timeout handler already processed, or a spurious one. + */ +- if (!tqspi->curr_xfer) +- return IRQ_NONE; ++ if (!tqspi->curr_xfer) { ++ /* Spurious interrupt - transfer not ready */ ++ if (!(status & QSPI_RDY)) ++ return IRQ_NONE; ++ /* Real interrupt, already handled by timeout path */ ++ return IRQ_HANDLED; ++ } + + tqspi->status_reg = tegra_qspi_readl(tqspi, QSPI_FIFO_STATUS); + +-- +2.51.0 + -- 2.47.3