* RE: Patch "net: ethernet: oa_tc6: Interrupt is active low, level triggered." has been added to the 7.1-stable tree
[not found] <20260720111749.364311-1-sashal@kernel.org>
@ 2026-07-20 18:31 ` Selvamani Rajagopal
2026-07-21 12:08 ` Sasha Levin
0 siblings, 1 reply; 2+ messages in thread
From: Selvamani Rajagopal @ 2026-07-20 18:31 UTC (permalink / raw)
To: stable@vger.kernel.org, stable-commits@vger.kernel.org
Cc: Parthiban Veerasooran, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Sasha,
There is a follow up patch that is in review. In my view, it is better to wait for this to be merged
before taking the patch to stable repo.
https://patchwork.kernel.org/project/netdevbpf/cover/20260621-fix-race-condition-and-crash-v1-0-87e290d9357f@onsemi.com/
Sincerely
Selva
> -----Original Message-----
> From: Sasha Levin <sashal@kernel.org>
> Sent: Monday, July 20, 2026 4:18 AM
> To: stable-commits@vger.kernel.org; Selvamani Rajagopal
> <Selvamani.Rajagopal@onsemi.com>
> Cc: Parthiban Veerasooran <parthiban.veerasooran@microchip.com>; Andrew Lunn
> <andrew+netdev@lunn.ch>; David S. Miller <davem@davemloft.net>; Eric Dumazet
> <edumazet@google.com>; Jakub Kicinski <kuba@kernel.org>; Paolo Abeni
> <pabeni@redhat.com>
> Subject: Patch "net: ethernet: oa_tc6: Interrupt is active low, level triggered." has been
> added to the 7.1-stable tree
>
>
> This Message Is From an External Sender
> This message came from outside your organization.
>
> This is a note to let you know that I've just added the patch titled
>
> net: ethernet: oa_tc6: Interrupt is active low, level triggered.
>
> to the 7.1-stable tree which can be found at:
> http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
> <http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
> kernel.org>
>
> The filename of the patch is:
> net-ethernet-oa_tc6-interrupt-is-active-low-level-tr.patch
> and it can be found in the queue-7.1 subdirectory.
>
> If you, or anyone else, feels it should not be added to the stable tree,
> please let <stable@vger.kernel.org> know about it.
>
>
>
> commit 67373094ff13ea1e12c8d99590204fef10506165
> Author: Selvamani Rajagopal <Selvamani.Rajagopal@onsemi.com>
> Date: Thu Jun 11 14:55:38 2026 -0700
>
> net: ethernet: oa_tc6: Interrupt is active low, level triggered.
>
> [ Upstream commit b542d13fab0f556660ce5f10179fb3ae66bdb9a4 ]
>
> According OPEN Alliance 10BASET1x MAC-PHY Serial Interface
> specification, interrupt is active low, level triggered.
>
> Code used edge triggered interrupt which has the risk of losing an
> interrupt on instances like when interrupt is disabled. Level
> triggered interrupt won't be deasserted unless handler runs and
> clear the interrupting conditions.
>
> Interrupt handler mechanism is changed to threaded irq from
> interrupt handler and kernel thread waiting on work queue.
> Threaded irq mechanism is best suited for level triggered interrupt
> as it disables the interrupt until handler is run in thread level,
> while giving us an ability to have interrupt context handler to
> signal the threaded irq handler.
>
> Introduced a logic to disable the device interrupt on error. Error
> could be due in data chunk's header and footer or SPI interface itself.
> This will avoid having repeated interrupts, in case the driver couldn't
> recover from the error condition with the available recovery mechanism.
>
> Fixes: 2c6ce5354453 ("net: ethernet: oa_tc6: implement mac-phy interrupt")
> Signed-off-by: Selvamani Rajagopal <Selvamani.Rajagopal@onsemi.com>
> Link: https://patch.msgid.link/20260611-level-trigger-v5-1-4533a9e85ce2@onsemi.com
> <https://patch.msgid.link/20260611-level-trigger-v5-1-4533a9e85ce2@onsemi.com
> patch.msgid.link>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
> Signed-off-by: Sasha Levin <sashal@kernel.org>
>
> diff --git a/drivers/net/ethernet/oa_tc6.c b/drivers/net/ethernet/oa_tc6.c
> index 91a906a7918a25..f3ac2875adfb7b 100644
> --- a/drivers/net/ethernet/oa_tc6.c
> +++ b/drivers/net/ethernet/oa_tc6.c
> @@ -7,6 +7,7 @@
>
> #include <linux/bitfield.h>
> #include <linux/iopoll.h>
> +#include <linux/interrupt.h>
> #include <linux/mdio.h>
> #include <linux/phy.h>
> #include <linux/oa_tc6.h>
> @@ -44,6 +45,8 @@
> #define INT_MASK0_LOSS_OF_FRAME_ERR_MASK BIT(4)
> #define INT_MASK0_RX_BUFFER_OVERFLOW_ERR_MASK BIT(3)
> #define INT_MASK0_TX_PROTOCOL_ERR_MASK BIT(0)
> +#define INT_MASK0_ALL_INTERRUPTS (GENMASK(5, 0) | \
> + GENMASK(12, 7))
>
> /* PHY Clause 22 registers base address and mask */
> #define OA_TC6_PHY_STD_REG_ADDR_BASE 0xFF00
> @@ -121,14 +124,13 @@ struct oa_tc6 {
> struct sk_buff *ongoing_tx_skb;
> struct sk_buff *waiting_tx_skb;
> struct sk_buff *rx_skb;
> - struct task_struct *spi_thread;
> - wait_queue_head_t spi_wq;
> u16 tx_skb_offset;
> u16 spi_data_tx_buf_offset;
> u16 tx_credits;
> u8 rx_chunks_available;
> bool rx_buf_overflow;
> bool int_flag;
> + bool disable_traffic;
> };
>
> enum oa_tc6_header_type {
> @@ -669,6 +671,38 @@ static void oa_tc6_cleanup_ongoing_tx_skb(struct oa_tc6 *tc6)
> }
> }
>
> +static void oa_tc6_cleanup_waiting_tx_skb(struct oa_tc6 *tc6)
> +{
> + if (tc6->waiting_tx_skb) {
> + tc6->netdev->stats.tx_dropped++;
> + kfree_skb(tc6->waiting_tx_skb);
> + tc6->waiting_tx_skb = NULL;
> + }
> +}
> +
> +static void oa_tc6_free_pending_skbs(struct oa_tc6 *tc6)
> +{
> + oa_tc6_cleanup_ongoing_tx_skb(tc6);
> + oa_tc6_cleanup_ongoing_rx_skb(tc6);
> + oa_tc6_cleanup_waiting_tx_skb(tc6);
> +}
> +
> +/* If the failure is at SPI interface level, masking and clearing
> + * the interrupt of the device won't work. Since SPI interrupt is
> + * disabled, it should stop the repeated interrupts.
> + */
> +static void oa_tc6_disable_traffic(struct oa_tc6 *tc6)
> +{
> + u32 regval = INT_MASK0_ALL_INTERRUPTS;
> +
> + tc6->disable_traffic = true;
> + oa_tc6_free_pending_skbs(tc6);
> + oa_tc6_write_register(tc6, OA_TC6_REG_INT_MASK0, regval);
> + oa_tc6_read_register(tc6, OA_TC6_REG_STATUS0, ®val);
> + oa_tc6_write_register(tc6, OA_TC6_REG_STATUS0, regval);
> + dev_err(&tc6->spi->dev, "Device interrupt disabled to avoid interrupt storm");
> +}
> +
> static int oa_tc6_process_extended_status(struct oa_tc6 *tc6)
> {
> u32 value;
> @@ -1105,29 +1139,29 @@ static int oa_tc6_try_spi_transfer(struct oa_tc6 *tc6)
> return 0;
> }
>
> -static int oa_tc6_spi_thread_handler(void *data)
> +static irqreturn_t oa_tc6_macphy_threaded_irq(int irq, void *data)
> {
> struct oa_tc6 *tc6 = data;
> - int ret;
> -
> - while (likely(!kthread_should_stop())) {
> - /* This kthread will be waken up if there is a tx skb or mac-phy
> - * interrupt to perform spi transfer with tx chunks.
> - */
> - wait_event_interruptible(tc6->spi_wq, tc6->int_flag ||
> - (tc6->waiting_tx_skb &&
> - tc6->tx_credits) ||
> - kthread_should_stop());
> -
> - if (kthread_should_stop())
> - break;
> + int ret = 0;
>
> - ret = oa_tc6_try_spi_transfer(tc6);
> - if (ret)
> - return ret;
> + /* It is possible that interrupt woke the thread before it is
> + * disabled. Until we come up with good recovery mechanism,
> + * no need to attempt spi transfer, once it fails. Pending skbs
> + * are already freed.
> + */
> + if (!tc6->disable_traffic) {
> + while (tc6->int_flag ||
> + (tc6->waiting_tx_skb && tc6->tx_credits)) {
> + ret = oa_tc6_try_spi_transfer(tc6);
> + if (ret) {
> + disable_irq_nosync(tc6->spi->irq);
> + oa_tc6_disable_traffic(tc6);
> + break;
> + }
> + }
> }
>
> - return 0;
> + return IRQ_HANDLED;
> }
>
> static int oa_tc6_update_buffer_status_from_register(struct oa_tc6 *tc6)
> @@ -1161,11 +1195,15 @@ static irqreturn_t oa_tc6_macphy_isr(int irq, void *data)
> * the previous rx footer.
> * - extended status event not reported in the previous rx footer.
> */
> - tc6->int_flag = true;
> - /* Wake spi kthread to perform spi transfer */
> - wake_up_interruptible(&tc6->spi_wq);
> -
> - return IRQ_HANDLED;
> + if (tc6->disable_traffic)
> + disable_irq_nosync(tc6->spi->irq);
> + else
> + tc6->int_flag = true;
> + /* Wake IRQ thread to perform spi transfer . In case
> + * disable_traffic is set, threaded irq may run again
> + * one more time.
> + */
> + return IRQ_WAKE_THREAD;
> }
>
> /**
> @@ -1202,7 +1240,7 @@
> EXPORT_SYMBOL_GPL(oa_tc6_zero_align_receive_frame_enable);
> */
> netdev_tx_t oa_tc6_start_xmit(struct oa_tc6 *tc6, struct sk_buff *skb)
> {
> - if (tc6->waiting_tx_skb) {
> + if (tc6->disable_traffic || tc6->waiting_tx_skb) {
> netif_stop_queue(tc6->netdev);
> return NETDEV_TX_BUSY;
> }
> @@ -1217,8 +1255,8 @@ netdev_tx_t oa_tc6_start_xmit(struct oa_tc6 *tc6, struct
> sk_buff *skb)
> tc6->waiting_tx_skb = skb;
> spin_unlock_bh(&tc6->tx_skb_lock);
>
> - /* Wake spi kthread to perform spi transfer */
> - wake_up_interruptible(&tc6->spi_wq);
> + /* Wake the threaded IRQ to perform spi transfer. */
> + irq_wake_thread(tc6->spi->irq, tc6);
>
> return NETDEV_TX_OK;
> }
> @@ -1311,24 +1349,15 @@ struct oa_tc6 *oa_tc6_init(struct spi_device *spi, struct
> net_device *netdev)
> goto phy_exit;
> }
>
> - init_waitqueue_head(&tc6->spi_wq);
> -
> - tc6->spi_thread = kthread_run(oa_tc6_spi_thread_handler, tc6,
> - "oa-tc6-spi-thread");
> - if (IS_ERR(tc6->spi_thread)) {
> - dev_err(&tc6->spi->dev, "Failed to create SPI thread\n");
> - goto phy_exit;
> - }
> -
> - sched_set_fifo(tc6->spi_thread);
> -
> - ret = devm_request_irq(&tc6->spi->dev, tc6->spi->irq, oa_tc6_macphy_isr,
> - IRQF_TRIGGER_FALLING, dev_name(&tc6->spi->dev),
> - tc6);
> + ret = devm_request_threaded_irq(&tc6->spi->dev, tc6->spi->irq,
> + oa_tc6_macphy_isr,
> + oa_tc6_macphy_threaded_irq,
> + IRQF_TRIGGER_LOW | IRQF_ONESHOT,
> + dev_name(&tc6->spi->dev), tc6);
> if (ret) {
> dev_err(&tc6->spi->dev, "Failed to request macphy isr %d\n",
> ret);
> - goto kthread_stop;
> + goto phy_exit;
> }
>
> /* oa_tc6_sw_reset_macphy() function resets and clears the MAC-PHY reset
> @@ -1338,12 +1367,10 @@ struct oa_tc6 *oa_tc6_init(struct spi_device *spi, struct
> net_device *netdev)
> * 7.7 and 9.2.8.8
> <http://9.2.8.8
> .8.8> in the OPEN Alliance specification for more details.
> */
> tc6->int_flag = true;
> - wake_up_interruptible(&tc6->spi_wq);
> + irq_wake_thread(tc6->spi->irq, tc6);
>
> return tc6;
>
> -kthread_stop:
> - kthread_stop(tc6->spi_thread);
> phy_exit:
> oa_tc6_phy_exit(tc6);
> return NULL;
> @@ -1356,11 +1383,10 @@ EXPORT_SYMBOL_GPL(oa_tc6_init);
> */
> void oa_tc6_exit(struct oa_tc6 *tc6)
> {
> + tc6->disable_traffic = true;
> + disable_irq(tc6->spi->irq);
> oa_tc6_phy_exit(tc6);
> - kthread_stop(tc6->spi_thread);
> - dev_kfree_skb_any(tc6->ongoing_tx_skb);
> - dev_kfree_skb_any(tc6->waiting_tx_skb);
> - dev_kfree_skb_any(tc6->rx_skb);
> + oa_tc6_free_pending_skbs(tc6);
> }
> EXPORT_SYMBOL_GPL(oa_tc6_exit);
>
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: Patch "net: ethernet: oa_tc6: Interrupt is active low, level triggered." has been added to the 7.1-stable tree
2026-07-20 18:31 ` Patch "net: ethernet: oa_tc6: Interrupt is active low, level triggered." has been added to the 7.1-stable tree Selvamani Rajagopal
@ 2026-07-21 12:08 ` Sasha Levin
0 siblings, 0 replies; 2+ messages in thread
From: Sasha Levin @ 2026-07-21 12:08 UTC (permalink / raw)
To: stable@vger.kernel.org, stable-commits@vger.kernel.org
Cc: Sasha Levin, Parthiban Veerasooran, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Selvamani Rajagopal
On Mon, Jul 20, 2026 at 06:31:26PM +0000, Selvamani Rajagopal wrote:
>There is a follow up patch that is in review. In my view, it is better to wait for this to be merged
>before taking the patch to stable repo.
Dropped from the 7.1, 6.18, and 6.12 queues. We'll requeue it together
with the fix series once it lands upstream, thanks.
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-07-21 12:08 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20260720111749.364311-1-sashal@kernel.org>
2026-07-20 18:31 ` Patch "net: ethernet: oa_tc6: Interrupt is active low, level triggered." has been added to the 7.1-stable tree Selvamani Rajagopal
2026-07-21 12:08 ` Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox