Skip to content

Commit bc1a59c

Browse files
HoratiuVulturkuba-moo
authored andcommitted
phy: mscc: Fix timestamping for vsc8584
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 <[email protected]> Reviewed-by: Vadim Fedorenko <[email protected]> Reviewed-by: Vladimir Oltean <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent f179f5b commit bc1a59c

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
@@ -1194,9 +1194,7 @@ static bool vsc85xx_rxtstamp(struct mii_timestamper *mii_ts,
11941194
{
11951195
struct vsc8531_private *vsc8531 =
11961196
container_of(mii_ts, struct vsc8531_private, mii_ts);
1197-
struct skb_shared_hwtstamps *shhwtstamps = NULL;
11981197
struct vsc85xx_ptphdr *ptphdr;
1199-
struct timespec64 ts;
12001198
unsigned long ns;
12011199

12021200
if (!vsc8531->ptp->configured)
@@ -1206,27 +1204,52 @@ static bool vsc85xx_rxtstamp(struct mii_timestamper *mii_ts,
12061204
type == PTP_CLASS_NONE)
12071205
return false;
12081206

1209-
vsc85xx_gettime(&vsc8531->ptp->caps, &ts);
1210-
12111207
ptphdr = get_ptp_header_rx(skb, vsc8531->ptp->rx_filter);
12121208
if (!ptphdr)
12131209
return false;
12141210

1215-
shhwtstamps = skb_hwtstamps(skb);
1216-
memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
1217-
12181211
ns = ntohl(ptphdr->rsrvd2);
12191212

1220-
/* nsec is in reserved field */
1221-
if (ts.tv_nsec < ns)
1222-
ts.tv_sec--;
1213+
VSC8531_SKB_CB(skb)->ns = ns;
1214+
skb_queue_tail(&vsc8531->rx_skbs_list, skb);
12231215

1224-
shhwtstamps->hwtstamp = ktime_set(ts.tv_sec, ns);
1225-
netif_rx(skb);
1216+
ptp_schedule_worker(vsc8531->ptp->ptp_clock, 0);
12261217

12271218
return true;
12281219
}
12291220

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

12451269
static struct vsc8531_private *vsc8584_base_priv(struct phy_device *phydev)
@@ -1567,6 +1591,7 @@ int vsc8584_ptp_probe(struct phy_device *phydev)
15671591

15681592
mutex_init(&vsc8531->phc_lock);
15691593
mutex_init(&vsc8531->ts_lock);
1594+
skb_queue_head_init(&vsc8531->rx_skbs_list);
15701595

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

0 commit comments

Comments
 (0)