Skip to content

Commit 78ba077

Browse files
HoratiuVulturgregkh
authored andcommitted
phy: mscc: Fix timestamping for vsc8584
[ Upstream commit bc1a59c ] 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: 7d272e6 ("net: phy: mscc: timestamping and PHC support") Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com> Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev> Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com> Link: https://patch.msgid.link/20250818081029.1300780-1-horatiu.vultur@microchip.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 4931fe2 commit 78ba077

File tree

3 files changed

+61
-12
lines changed

3 files changed

+61
-12
lines changed

drivers/net/phy/mscc/mscc.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,13 @@ struct vsc85xx_hw_stat {
362362
u16 mask;
363363
};
364364

365+
struct vsc8531_skb_cb {
366+
u32 ns;
367+
};
368+
369+
#define VSC8531_SKB_CB(skb) \
370+
((struct vsc8531_skb_cb *)((skb)->cb))
371+
365372
struct vsc8531_private {
366373
int rate_magic;
367374
u16 supp_led_modes;
@@ -410,6 +417,11 @@ struct vsc8531_private {
410417
*/
411418
struct mutex ts_lock;
412419
struct mutex phc_lock;
420+
421+
/* list of skbs that were received and need timestamp information but it
422+
* didn't received it yet
423+
*/
424+
struct sk_buff_head rx_skbs_list;
413425
};
414426

415427
/* Shared structure between the PHYs of the same package.

drivers/net/phy/mscc/mscc_main.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2335,6 +2335,13 @@ static int vsc85xx_probe(struct phy_device *phydev)
23352335
return vsc85xx_dt_led_modes_get(phydev, default_mode);
23362336
}
23372337

2338+
static void vsc85xx_remove(struct phy_device *phydev)
2339+
{
2340+
struct vsc8531_private *priv = phydev->priv;
2341+
2342+
skb_queue_purge(&priv->rx_skbs_list);
2343+
}
2344+
23382345
/* Microsemi VSC85xx PHYs */
23392346
static struct phy_driver vsc85xx_driver[] = {
23402347
{
@@ -2589,6 +2596,7 @@ static struct phy_driver vsc85xx_driver[] = {
25892596
.config_intr = &vsc85xx_config_intr,
25902597
.suspend = &genphy_suspend,
25912598
.resume = &genphy_resume,
2599+
.remove = &vsc85xx_remove,
25922600
.probe = &vsc8574_probe,
25932601
.set_wol = &vsc85xx_wol_set,
25942602
.get_wol = &vsc85xx_wol_get,
@@ -2614,6 +2622,7 @@ static struct phy_driver vsc85xx_driver[] = {
26142622
.config_intr = &vsc85xx_config_intr,
26152623
.suspend = &genphy_suspend,
26162624
.resume = &genphy_resume,
2625+
.remove = &vsc85xx_remove,
26172626
.probe = &vsc8574_probe,
26182627
.set_wol = &vsc85xx_wol_set,
26192628
.get_wol = &vsc85xx_wol_get,
@@ -2639,6 +2648,7 @@ static struct phy_driver vsc85xx_driver[] = {
26392648
.config_intr = &vsc85xx_config_intr,
26402649
.suspend = &genphy_suspend,
26412650
.resume = &genphy_resume,
2651+
.remove = &vsc85xx_remove,
26422652
.probe = &vsc8584_probe,
26432653
.get_tunable = &vsc85xx_get_tunable,
26442654
.set_tunable = &vsc85xx_set_tunable,
@@ -2662,6 +2672,7 @@ static struct phy_driver vsc85xx_driver[] = {
26622672
.config_intr = &vsc85xx_config_intr,
26632673
.suspend = &genphy_suspend,
26642674
.resume = &genphy_resume,
2675+
.remove = &vsc85xx_remove,
26652676
.probe = &vsc8584_probe,
26662677
.get_tunable = &vsc85xx_get_tunable,
26672678
.set_tunable = &vsc85xx_set_tunable,
@@ -2685,6 +2696,7 @@ static struct phy_driver vsc85xx_driver[] = {
26852696
.config_intr = &vsc85xx_config_intr,
26862697
.suspend = &genphy_suspend,
26872698
.resume = &genphy_resume,
2699+
.remove = &vsc85xx_remove,
26882700
.probe = &vsc8584_probe,
26892701
.get_tunable = &vsc85xx_get_tunable,
26902702
.set_tunable = &vsc85xx_set_tunable,

drivers/net/phy/mscc/mscc_ptp.c

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,9 +1191,7 @@ static bool vsc85xx_rxtstamp(struct mii_timestamper *mii_ts,
11911191
{
11921192
struct vsc8531_private *vsc8531 =
11931193
container_of(mii_ts, struct vsc8531_private, mii_ts);
1194-
struct skb_shared_hwtstamps *shhwtstamps = NULL;
11951194
struct vsc85xx_ptphdr *ptphdr;
1196-
struct timespec64 ts;
11971195
unsigned long ns;
11981196

11991197
if (!vsc8531->ptp->configured)
@@ -1203,27 +1201,52 @@ static bool vsc85xx_rxtstamp(struct mii_timestamper *mii_ts,
12031201
type == PTP_CLASS_NONE)
12041202
return false;
12051203

1206-
vsc85xx_gettime(&vsc8531->ptp->caps, &ts);
1207-
12081204
ptphdr = get_ptp_header_rx(skb, vsc8531->ptp->rx_filter);
12091205
if (!ptphdr)
12101206
return false;
12111207

1212-
shhwtstamps = skb_hwtstamps(skb);
1213-
memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
1214-
12151208
ns = ntohl(ptphdr->rsrvd2);
12161209

1217-
/* nsec is in reserved field */
1218-
if (ts.tv_nsec < ns)
1219-
ts.tv_sec--;
1210+
VSC8531_SKB_CB(skb)->ns = ns;
1211+
skb_queue_tail(&vsc8531->rx_skbs_list, skb);
12201212

1221-
shhwtstamps->hwtstamp = ktime_set(ts.tv_sec, ns);
1222-
netif_rx(skb);
1213+
ptp_schedule_worker(vsc8531->ptp->ptp_clock, 0);
12231214

12241215
return true;
12251216
}
12261217

1218+
static long vsc85xx_do_aux_work(struct ptp_clock_info *info)
1219+
{
1220+
struct vsc85xx_ptp *ptp = container_of(info, struct vsc85xx_ptp, caps);
1221+
struct skb_shared_hwtstamps *shhwtstamps = NULL;
1222+
struct phy_device *phydev = ptp->phydev;
1223+
struct vsc8531_private *priv = phydev->priv;
1224+
struct sk_buff_head received;
1225+
struct sk_buff *rx_skb;
1226+
struct timespec64 ts;
1227+
unsigned long flags;
1228+
1229+
__skb_queue_head_init(&received);
1230+
spin_lock_irqsave(&priv->rx_skbs_list.lock, flags);
1231+
skb_queue_splice_tail_init(&priv->rx_skbs_list, &received);
1232+
spin_unlock_irqrestore(&priv->rx_skbs_list.lock, flags);
1233+
1234+
vsc85xx_gettime(info, &ts);
1235+
while ((rx_skb = __skb_dequeue(&received)) != NULL) {
1236+
shhwtstamps = skb_hwtstamps(rx_skb);
1237+
memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
1238+
1239+
if (ts.tv_nsec < VSC8531_SKB_CB(rx_skb)->ns)
1240+
ts.tv_sec--;
1241+
1242+
shhwtstamps->hwtstamp = ktime_set(ts.tv_sec,
1243+
VSC8531_SKB_CB(rx_skb)->ns);
1244+
netif_rx(rx_skb);
1245+
}
1246+
1247+
return -1;
1248+
}
1249+
12271250
static const struct ptp_clock_info vsc85xx_clk_caps = {
12281251
.owner = THIS_MODULE,
12291252
.name = "VSC85xx timer",
@@ -1237,6 +1260,7 @@ static const struct ptp_clock_info vsc85xx_clk_caps = {
12371260
.adjfine = &vsc85xx_adjfine,
12381261
.gettime64 = &vsc85xx_gettime,
12391262
.settime64 = &vsc85xx_settime,
1263+
.do_aux_work = &vsc85xx_do_aux_work,
12401264
};
12411265

12421266
static struct vsc8531_private *vsc8584_base_priv(struct phy_device *phydev)
@@ -1564,6 +1588,7 @@ int vsc8584_ptp_probe(struct phy_device *phydev)
15641588

15651589
mutex_init(&vsc8531->phc_lock);
15661590
mutex_init(&vsc8531->ts_lock);
1591+
skb_queue_head_init(&vsc8531->rx_skbs_list);
15671592

15681593
/* Retrieve the shared load/save GPIO. Request it as non exclusive as
15691594
* the same GPIO can be requested by all the PHYs of the same package.

0 commit comments

Comments
 (0)