From nobody Sat Oct 4 11:13:53 2025 Received: from esa.microchip.iphmx.com (esa.microchip.iphmx.com [68.232.153.233]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 62FBD2FB98D; Mon, 18 Aug 2025 08:16:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=68.232.153.233 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755504996; cv=none; b=cQfdKHdS7zOZ5q369Lk+dt2jDqVX7aW1ZCpa2nxtuYPIVl3PkUR0jzYAh9F+rj1A2+hshiZGeysbwnZy7BDZEAD0hi8K4eLeKgYl9c+GaihpLm+r+oFTDd9UdwQpSIpVIo5L6Vuc1sq5tJlVDc641rhsi3jUpEIjdsvYg2ktTGk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755504996; c=relaxed/simple; bh=G+aHlvQ+CweaIXV2IXq48IipOx5UUo5t880wy4OPl1k=; h=From:To:CC:Subject:Date:Message-ID:MIME-Version:Content-Type; b=uus9OpI91w0kymSMcjzShacJhPc3POn2zqu/ryt6bSwIqORtxvmMagpE5ZtT9STuEMb5hcPGvqg/Tep/gQw+Fr/V7mQ4ZGxo5WV5ttxMu31s+ctBiCrMemsDLNaTO4Lb1hzZ67eCV+Bp7UO4gileECsNNPIL0i2ak1hkSuvb6Ow= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=microchip.com; spf=pass smtp.mailfrom=microchip.com; dkim=pass (2048-bit key) header.d=microchip.com header.i=@microchip.com header.b=UizifVZ6; arc=none smtp.client-ip=68.232.153.233 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=microchip.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=microchip.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=microchip.com header.i=@microchip.com header.b="UizifVZ6" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1755504995; x=1787040995; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=G+aHlvQ+CweaIXV2IXq48IipOx5UUo5t880wy4OPl1k=; b=UizifVZ6OOTI93X5pS/Vsz7ttD9upmS1b6EpPTq565sE1t5CEo/bcQWT ZgV0C9kV/U2XB+7BiGDJO9xY4KLrrHQ0NfcdZtKthzthw/H9k1x5/QODB pyU1ndRvKEH09kt3gJWrwsISRzfGEAULgZWA17ra+ytNJm9fpqN6XtIJ7 9YOvm+SG76mZcn1MgQ2uCst5tC52muvByYhceGLeaZt56KUvLGNDwIuTh 7obv5wTEAZeSfoJfUfaiI23P0EFrUskjMIe5TaatkaYyT6Bp9m5J4wxd0 MfT4rTdrtKhHOuEsffM40SPJ8sn2T7rzDidD+I5w29ute2MZu1hW6Bzre Q==; X-CSE-ConnectionGUID: DwC6mKDGSdioEGdvpUJHIA== X-CSE-MsgGUID: bN7t/wOcQFGpXpVdOUpFVA== X-IronPort-AV: E=Sophos;i="6.17,293,1747724400"; d="scan'208";a="45303678" X-Amp-Result: SKIPPED(no attachment in message) Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa3.microchip.iphmx.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 18 Aug 2025 01:16:34 -0700 Received: from chn-vm-ex04.mchp-main.com (10.10.85.152) by chn-vm-ex03.mchp-main.com (10.10.85.151) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.44; Mon, 18 Aug 2025 01:16:20 -0700 Received: from DEN-DL-M31836.microchip.com (10.10.85.11) by chn-vm-ex04.mchp-main.com (10.10.85.152) with Microsoft SMTP Server id 15.1.2507.44 via Frontend Transport; Mon, 18 Aug 2025 01:16:17 -0700 From: Horatiu Vultur To: , , , , , , , , , , , , , , CC: , , Horatiu Vultur Subject: [PATCH net v4] phy: mscc: Fix timestamping for vsc8584 Date: Mon, 18 Aug 2025 10:10:29 +0200 Message-ID: <20250818081029.1300780-1-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.34.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" There was a problem when we received frames and the frames were timestamped. The driver is configured to store the nanosecond part of the timestmap in the ptp reserved bits and it would take the second part by reading the LTC. The problem is that when reading the LTC we are in atomic context and to read the second part will go over mdio bus which might sleep, so we get an error. The fix consists in actually put all the frames in a queue and start the aux work and in that work to read the LTC and then calculate the full received time. Fixes: 7d272e63e0979d ("net: phy: mscc: timestamping and PHC support") Signed-off-by: Horatiu Vultur Reviewed-by: Vadim Fedorenko Reviewed-by: Vladimir Oltean --- v3->v4: - remove empty line v2->v3: - make sure to flush the rx_skbs_list when the driver is removed v1->v2: - use sk_buff_head instead of a list_head and spinlock_t - stop allocating vsc8431_skb but put the timestamp in skb->cb --- drivers/net/phy/mscc/mscc.h | 12 ++++++++ drivers/net/phy/mscc/mscc_main.c | 12 ++++++++ drivers/net/phy/mscc/mscc_ptp.c | 49 ++++++++++++++++++++++++-------- 3 files changed, 61 insertions(+), 12 deletions(-) diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h index 138355f1ab0bc..b8c6ba7c7834e 100644 --- a/drivers/net/phy/mscc/mscc.h +++ b/drivers/net/phy/mscc/mscc.h @@ -365,6 +365,13 @@ struct vsc85xx_hw_stat { u16 mask; }; =20 +struct vsc8531_skb_cb { + u32 ns; +}; + +#define VSC8531_SKB_CB(skb) \ + ((struct vsc8531_skb_cb *)((skb)->cb)) + struct vsc8531_private { int rate_magic; u16 supp_led_modes; @@ -413,6 +420,11 @@ struct vsc8531_private { */ struct mutex ts_lock; struct mutex phc_lock; + + /* list of skbs that were received and need timestamp information but it + * didn't received it yet + */ + struct sk_buff_head rx_skbs_list; }; =20 /* Shared structure between the PHYs of the same package. diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_m= ain.c index 37e3e931a8e53..800da302ae632 100644 --- a/drivers/net/phy/mscc/mscc_main.c +++ b/drivers/net/phy/mscc/mscc_main.c @@ -2368,6 +2368,13 @@ static int vsc85xx_probe(struct phy_device *phydev) return vsc85xx_dt_led_modes_get(phydev, default_mode); } =20 +static void vsc85xx_remove(struct phy_device *phydev) +{ + struct vsc8531_private *priv =3D phydev->priv; + + skb_queue_purge(&priv->rx_skbs_list); +} + /* Microsemi VSC85xx PHYs */ static struct phy_driver vsc85xx_driver[] =3D { { @@ -2630,6 +2637,7 @@ static struct phy_driver vsc85xx_driver[] =3D { .config_intr =3D &vsc85xx_config_intr, .suspend =3D &genphy_suspend, .resume =3D &genphy_resume, + .remove =3D &vsc85xx_remove, .probe =3D &vsc8574_probe, .set_wol =3D &vsc85xx_wol_set, .get_wol =3D &vsc85xx_wol_get, @@ -2657,6 +2665,7 @@ static struct phy_driver vsc85xx_driver[] =3D { .config_intr =3D &vsc85xx_config_intr, .suspend =3D &genphy_suspend, .resume =3D &genphy_resume, + .remove =3D &vsc85xx_remove, .probe =3D &vsc8574_probe, .set_wol =3D &vsc85xx_wol_set, .get_wol =3D &vsc85xx_wol_get, @@ -2684,6 +2693,7 @@ static struct phy_driver vsc85xx_driver[] =3D { .config_intr =3D &vsc85xx_config_intr, .suspend =3D &genphy_suspend, .resume =3D &genphy_resume, + .remove =3D &vsc85xx_remove, .probe =3D &vsc8584_probe, .get_tunable =3D &vsc85xx_get_tunable, .set_tunable =3D &vsc85xx_set_tunable, @@ -2709,6 +2719,7 @@ static struct phy_driver vsc85xx_driver[] =3D { .config_intr =3D &vsc85xx_config_intr, .suspend =3D &genphy_suspend, .resume =3D &genphy_resume, + .remove =3D &vsc85xx_remove, .probe =3D &vsc8584_probe, .get_tunable =3D &vsc85xx_get_tunable, .set_tunable =3D &vsc85xx_set_tunable, @@ -2734,6 +2745,7 @@ static struct phy_driver vsc85xx_driver[] =3D { .config_intr =3D &vsc85xx_config_intr, .suspend =3D &genphy_suspend, .resume =3D &genphy_resume, + .remove =3D &vsc85xx_remove, .probe =3D &vsc8584_probe, .get_tunable =3D &vsc85xx_get_tunable, .set_tunable =3D &vsc85xx_set_tunable, diff --git a/drivers/net/phy/mscc/mscc_ptp.c b/drivers/net/phy/mscc/mscc_pt= p.c index 275706de5847c..de6c7312e8f29 100644 --- a/drivers/net/phy/mscc/mscc_ptp.c +++ b/drivers/net/phy/mscc/mscc_ptp.c @@ -1194,9 +1194,7 @@ static bool vsc85xx_rxtstamp(struct mii_timestamper *= mii_ts, { struct vsc8531_private *vsc8531 =3D container_of(mii_ts, struct vsc8531_private, mii_ts); - struct skb_shared_hwtstamps *shhwtstamps =3D NULL; struct vsc85xx_ptphdr *ptphdr; - struct timespec64 ts; unsigned long ns; =20 if (!vsc8531->ptp->configured) @@ -1206,27 +1204,52 @@ static bool vsc85xx_rxtstamp(struct mii_timestamper= *mii_ts, type =3D=3D PTP_CLASS_NONE) return false; =20 - vsc85xx_gettime(&vsc8531->ptp->caps, &ts); - ptphdr =3D get_ptp_header_rx(skb, vsc8531->ptp->rx_filter); if (!ptphdr) return false; =20 - shhwtstamps =3D skb_hwtstamps(skb); - memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps)); - ns =3D ntohl(ptphdr->rsrvd2); =20 - /* nsec is in reserved field */ - if (ts.tv_nsec < ns) - ts.tv_sec--; + VSC8531_SKB_CB(skb)->ns =3D ns; + skb_queue_tail(&vsc8531->rx_skbs_list, skb); =20 - shhwtstamps->hwtstamp =3D ktime_set(ts.tv_sec, ns); - netif_rx(skb); + ptp_schedule_worker(vsc8531->ptp->ptp_clock, 0); =20 return true; } =20 +static long vsc85xx_do_aux_work(struct ptp_clock_info *info) +{ + struct vsc85xx_ptp *ptp =3D container_of(info, struct vsc85xx_ptp, caps); + struct skb_shared_hwtstamps *shhwtstamps =3D NULL; + struct phy_device *phydev =3D ptp->phydev; + struct vsc8531_private *priv =3D phydev->priv; + struct sk_buff_head received; + struct sk_buff *rx_skb; + struct timespec64 ts; + unsigned long flags; + + __skb_queue_head_init(&received); + spin_lock_irqsave(&priv->rx_skbs_list.lock, flags); + skb_queue_splice_tail_init(&priv->rx_skbs_list, &received); + spin_unlock_irqrestore(&priv->rx_skbs_list.lock, flags); + + vsc85xx_gettime(info, &ts); + while ((rx_skb =3D __skb_dequeue(&received)) !=3D NULL) { + shhwtstamps =3D skb_hwtstamps(rx_skb); + memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps)); + + if (ts.tv_nsec < VSC8531_SKB_CB(rx_skb)->ns) + ts.tv_sec--; + + shhwtstamps->hwtstamp =3D ktime_set(ts.tv_sec, + VSC8531_SKB_CB(rx_skb)->ns); + netif_rx(rx_skb); + } + + return -1; +} + static const struct ptp_clock_info vsc85xx_clk_caps =3D { .owner =3D THIS_MODULE, .name =3D "VSC85xx timer", @@ -1240,6 +1263,7 @@ static const struct ptp_clock_info vsc85xx_clk_caps = =3D { .adjfine =3D &vsc85xx_adjfine, .gettime64 =3D &vsc85xx_gettime, .settime64 =3D &vsc85xx_settime, + .do_aux_work =3D &vsc85xx_do_aux_work, }; =20 static struct vsc8531_private *vsc8584_base_priv(struct phy_device *phydev) @@ -1567,6 +1591,7 @@ int vsc8584_ptp_probe(struct phy_device *phydev) =20 mutex_init(&vsc8531->phc_lock); mutex_init(&vsc8531->ts_lock); + skb_queue_head_init(&vsc8531->rx_skbs_list); =20 /* 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. --=20 2.34.1