Skip to content

Commit

Permalink
net: dsa: mv88e6xxx: Fix receive time stamp race condition.
Browse files Browse the repository at this point in the history
The DSA stack passes received PTP frames to this driver via
mv88e6xxx_port_rxtstamp() for deferred delivery.  The driver then
queues the frame and kicks the worker thread.  The work callback reads
out the latched receive time stamp and then works through the queue,
delivering any non-matching frames without a time stamp.

If a new frame arrives after the worker thread has read out the time
stamp register but enters the queue before the worker finishes
processing the queue, that frame will be delivered without a time
stamp.

This patch fixes the race by moving the queue onto a list on the stack
before reading out the latched time stamp value.

Fixes: c6fe0ad ("net: dsa: mv88e6xxx: add rx/tx timestamping support")
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Richard Cochran authored and David S. Miller committed Apr 13, 2018
1 parent 53b76cd commit 2290482
Showing 1 changed file with 10 additions and 2 deletions.
12 changes: 10 additions & 2 deletions drivers/net/dsa/mv88e6xxx/hwtstamp.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,10 +285,18 @@ static void mv88e6xxx_get_rxts(struct mv88e6xxx_chip *chip,
struct sk_buff_head *rxq)
{
u16 buf[4] = { 0 }, status, seq_id;
u64 ns, timelo, timehi;
struct skb_shared_hwtstamps *shwt;
struct sk_buff_head received;
u64 ns, timelo, timehi;
unsigned long flags;
int err;

/* The latched timestamp belongs to one of the received frames. */
__skb_queue_head_init(&received);
spin_lock_irqsave(&rxq->lock, flags);
skb_queue_splice_tail_init(rxq, &received);
spin_unlock_irqrestore(&rxq->lock, flags);

mutex_lock(&chip->reg_lock);
err = mv88e6xxx_port_ptp_read(chip, ps->port_id,
reg, buf, ARRAY_SIZE(buf));
Expand All @@ -311,7 +319,7 @@ static void mv88e6xxx_get_rxts(struct mv88e6xxx_chip *chip,
/* Since the device can only handle one time stamp at a time,
* we purge any extra frames from the queue.
*/
for ( ; skb; skb = skb_dequeue(rxq)) {
for ( ; skb; skb = __skb_dequeue(&received)) {
if (mv88e6xxx_ts_valid(status) && seq_match(skb, seq_id)) {
ns = timehi << 16 | timelo;

Expand Down

0 comments on commit 2290482

Please sign in to comment.