Skip to content

Commit 1ebf1b9

Browse files
HoratiuVulturNipaLocal
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]> Signed-off-by: NipaLocal <nipa@local>
1 parent 0872122 commit 1ebf1b9

File tree

2 files changed

+50
-12
lines changed

2 files changed

+50
-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_ptp.c

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,9 +1194,8 @@ 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;
1197+
11981198
struct vsc85xx_ptphdr *ptphdr;
1199-
struct timespec64 ts;
12001199
unsigned long ns;
12011200

12021201
if (!vsc8531->ptp->configured)
@@ -1206,27 +1205,52 @@ static bool vsc85xx_rxtstamp(struct mii_timestamper *mii_ts,
12061205
type == PTP_CLASS_NONE)
12071206
return false;
12081207

1209-
vsc85xx_gettime(&vsc8531->ptp->caps, &ts);
1210-
12111208
ptphdr = get_ptp_header_rx(skb, vsc8531->ptp->rx_filter);
12121209
if (!ptphdr)
12131210
return false;
12141211

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

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

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

12271219
return true;
12281220
}
12291221

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

12451270
static struct vsc8531_private *vsc8584_base_priv(struct phy_device *phydev)
@@ -1567,6 +1592,7 @@ int vsc8584_ptp_probe(struct phy_device *phydev)
15671592

15681593
mutex_init(&vsc8531->phc_lock);
15691594
mutex_init(&vsc8531->ts_lock);
1595+
skb_queue_head_init(&vsc8531->rx_skbs_list);
15701596

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

0 commit comments

Comments
 (0)