]> www.infradead.org Git - users/griffoul/linux.git/commitdiff
phy: mscc: Stop taking ts_lock for tx_queue and use its own lock
authorHoratiu Vultur <horatiu.vultur@microchip.com>
Tue, 2 Sep 2025 12:12:59 +0000 (14:12 +0200)
committerJakub Kicinski <kuba@kernel.org>
Thu, 4 Sep 2025 14:48:29 +0000 (07:48 -0700)
When transmitting a PTP frame which is timestamp using 2 step, the
following warning appears if CONFIG_PROVE_LOCKING is enabled:
=============================
[ BUG: Invalid wait context ]
6.17.0-rc1-00326-ge6160462704e #427 Not tainted
-----------------------------
ptp4l/119 is trying to lock:
c2a44ed4 (&vsc8531->ts_lock){+.+.}-{3:3}, at: vsc85xx_txtstamp+0x50/0xac
other info that might help us debug this:
context-{4:4}
4 locks held by ptp4l/119:
 #0: c145f068 (rcu_read_lock_bh){....}-{1:2}, at: __dev_queue_xmit+0x58/0x1440
 #1: c29df974 (dev->qdisc_tx_busylock ?: &qdisc_tx_busylock){+...}-{2:2}, at: __dev_queue_xmit+0x5c4/0x1440
 #2: c2aaaad0 (_xmit_ETHER#2){+.-.}-{2:2}, at: sch_direct_xmit+0x108/0x350
 #3: c2aac170 (&lan966x->tx_lock){+.-.}-{2:2}, at: lan966x_port_xmit+0xd0/0x350
stack backtrace:
CPU: 0 UID: 0 PID: 119 Comm: ptp4l Not tainted 6.17.0-rc1-00326-ge6160462704e #427 NONE
Hardware name: Generic DT based system
Call trace:
 unwind_backtrace from show_stack+0x10/0x14
 show_stack from dump_stack_lvl+0x7c/0xac
 dump_stack_lvl from __lock_acquire+0x8e8/0x29dc
 __lock_acquire from lock_acquire+0x108/0x38c
 lock_acquire from __mutex_lock+0xb0/0xe78
 __mutex_lock from mutex_lock_nested+0x1c/0x24
 mutex_lock_nested from vsc85xx_txtstamp+0x50/0xac
 vsc85xx_txtstamp from lan966x_fdma_xmit+0xd8/0x3a8
 lan966x_fdma_xmit from lan966x_port_xmit+0x1bc/0x350
 lan966x_port_xmit from dev_hard_start_xmit+0xc8/0x2c0
 dev_hard_start_xmit from sch_direct_xmit+0x8c/0x350
 sch_direct_xmit from __dev_queue_xmit+0x680/0x1440
 __dev_queue_xmit from packet_sendmsg+0xfa4/0x1568
 packet_sendmsg from __sys_sendto+0x110/0x19c
 __sys_sendto from sys_send+0x18/0x20
 sys_send from ret_fast_syscall+0x0/0x1c
Exception stack(0xf0b05fa8 to 0xf0b05ff0)
5fa0:                   00000001 0000000e 0000000e 0004b47a 0000003a 00000000
5fc0: 00000001 0000000e 00000000 00000121 0004af58 00044874 00000000 00000000
5fe0: 00000001 bee9d420 00025a10 b6e75c7c

So, instead of using the ts_lock for tx_queue, use the spinlock that
skb_buff_head has.

Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Fixes: 7d272e63e0979d ("net: phy: mscc: timestamping and PHC support")
Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Link: https://patch.msgid.link/20250902121259.3257536-1-horatiu.vultur@microchip.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/phy/mscc/mscc_ptp.c

index 72847320cb652df437861f68580d5fd498b87979..d692df7d975c70034660b6907ffeedcf1da64759 100644 (file)
@@ -456,12 +456,12 @@ static void vsc85xx_dequeue_skb(struct vsc85xx_ptp *ptp)
                *p++ = (reg >> 24) & 0xff;
        }
 
-       len = skb_queue_len(&ptp->tx_queue);
+       len = skb_queue_len_lockless(&ptp->tx_queue);
        if (len < 1)
                return;
 
        while (len--) {
-               skb = __skb_dequeue(&ptp->tx_queue);
+               skb = skb_dequeue(&ptp->tx_queue);
                if (!skb)
                        return;
 
@@ -486,7 +486,7 @@ static void vsc85xx_dequeue_skb(struct vsc85xx_ptp *ptp)
                 * packet in the FIFO right now, reschedule it for later
                 * packets.
                 */
-               __skb_queue_tail(&ptp->tx_queue, skb);
+               skb_queue_tail(&ptp->tx_queue, skb);
        }
 }
 
@@ -1068,6 +1068,7 @@ static int vsc85xx_hwtstamp(struct mii_timestamper *mii_ts,
        case HWTSTAMP_TX_ON:
                break;
        case HWTSTAMP_TX_OFF:
+               skb_queue_purge(&vsc8531->ptp->tx_queue);
                break;
        default:
                return -ERANGE;
@@ -1092,9 +1093,6 @@ static int vsc85xx_hwtstamp(struct mii_timestamper *mii_ts,
 
        mutex_lock(&vsc8531->ts_lock);
 
-       __skb_queue_purge(&vsc8531->ptp->tx_queue);
-       __skb_queue_head_init(&vsc8531->ptp->tx_queue);
-
        /* Disable predictor while configuring the 1588 block */
        val = vsc85xx_ts_read_csr(phydev, PROCESSOR,
                                  MSCC_PHY_PTP_INGR_PREDICTOR);
@@ -1180,9 +1178,7 @@ static void vsc85xx_txtstamp(struct mii_timestamper *mii_ts,
 
        skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
 
-       mutex_lock(&vsc8531->ts_lock);
-       __skb_queue_tail(&vsc8531->ptp->tx_queue, skb);
-       mutex_unlock(&vsc8531->ts_lock);
+       skb_queue_tail(&vsc8531->ptp->tx_queue, skb);
        return;
 
 out:
@@ -1548,6 +1544,7 @@ void vsc8584_ptp_deinit(struct phy_device *phydev)
        if (vsc8531->ptp->ptp_clock) {
                ptp_clock_unregister(vsc8531->ptp->ptp_clock);
                skb_queue_purge(&vsc8531->rx_skbs_list);
+               skb_queue_purge(&vsc8531->ptp->tx_queue);
        }
 }
 
@@ -1571,7 +1568,7 @@ irqreturn_t vsc8584_handle_ts_interrupt(struct phy_device *phydev)
        if (rc & VSC85XX_1588_INT_FIFO_ADD) {
                vsc85xx_get_tx_ts(priv->ptp);
        } else if (rc & VSC85XX_1588_INT_FIFO_OVERFLOW) {
-               __skb_queue_purge(&priv->ptp->tx_queue);
+               skb_queue_purge(&priv->ptp->tx_queue);
                vsc85xx_ts_reset_fifo(phydev);
        }
 
@@ -1591,6 +1588,7 @@ int vsc8584_ptp_probe(struct phy_device *phydev)
        mutex_init(&vsc8531->phc_lock);
        mutex_init(&vsc8531->ts_lock);
        skb_queue_head_init(&vsc8531->rx_skbs_list);
+       skb_queue_head_init(&vsc8531->ptp->tx_queue);
 
        /* Retrieve the shared load/save GPIO. Request it as non exclusive as
         * the same GPIO can be requested by all the PHYs of the same package.