Skip to content

Commit 7c079e6

Browse files
committed
[sparx5] Use SKB reference counting for PTP tx path
There is a race condition in the TX path of PTP event packets. When the packet is transmitted, DMA is kicked off and then SKB is freed. However, in case of PTP packet, SKB is queued for timestamping, and is freed in the interrupt handler. If PTP IRQ arrives before the call to sparx5_consume_skb(), it will free the packet, and then sparx5_consume_skb() will cause Oops, when testing whether SKB is PTP or not. This change uses SKB reference counting to ensure SKB is freed regardless of order of events, and no crash occurs.
1 parent e0e964b commit 7c079e6

File tree

4 files changed

+9
-15
lines changed

4 files changed

+9
-15
lines changed

drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ int sparx5_fdma_xmit(struct sparx5 *sparx5, u32 *ifh, struct sk_buff *skb)
299299

300300
sparx5_fdma_reload(sparx5, fdma);
301301

302-
sparx5_consume_skb(skb);
302+
dev_consume_skb_any(skb);
303303

304304
return NETDEV_TX_OK;
305305
}

drivers/net/ethernet/microchip/sparx5/sparx5_main.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1081,7 +1081,6 @@ u32 sparx5_mirror_monitor_get(struct sparx5 *sparx5, u32 idx);
10811081

10821082
/* sparx5_packet.c */
10831083
u32 sparx5_get_packet_pipeline_pt(enum sparx5_packet_pipeline_pt pt);
1084-
void sparx5_consume_skb(struct sk_buff *skb);
10851084
bool sparx5_skb_offloaded(struct sparx5 *sparx5, u32 port, struct sk_buff *skb);
10861085

10871086
/* sparx5_afi.c */

drivers/net/ethernet/microchip/sparx5/sparx5_packet.c

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ static int sparx5_inject(struct sparx5 *sparx5,
276276
HRTIMER_MODE_REL);
277277
}
278278

279-
sparx5_consume_skb(skb);
279+
dev_consume_skb_any(skb);
280280

281281
return NETDEV_TX_OK;
282282
}
@@ -448,18 +448,6 @@ void sparx5_port_inj_timer_setup(struct sparx5_port *port)
448448
port->inj_timer.function = sparx5_injection_timeout;
449449
}
450450

451-
void sparx5_consume_skb(struct sk_buff *skb)
452-
{
453-
bool ptp = false;
454-
455-
if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
456-
SPARX5_SKB_CB(skb)->rew_op == IFH_REW_OP_TWO_STEP_PTP)
457-
ptp = true;
458-
459-
if (!ptp)
460-
dev_consume_skb_any(skb);
461-
}
462-
463451
bool sparx5_skb_offloaded(struct sparx5 *sparx5, u32 port, struct sk_buff *skb)
464452
{
465453
u32 val;

drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,13 @@ int sparx5_ptp_txtstamp_request(struct sparx5_port *port,
568568
}
569569

570570
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
571+
/* Increase reference count, in order to prevent double-free,
572+
in case PTP IRQ happens after DMA is kicked off, but before
573+
dev_consume_skb_any is called.
574+
For PTP packets, skb is freed extra time by the PTP IRQ handler,
575+
so we need to increase the reference count here.
576+
*/
577+
skb_get(skb);
571578

572579
skb_queue_tail(&port->tx_skbs, skb);
573580
SPARX5_SKB_CB(skb)->ts_id = port->ts_id;

0 commit comments

Comments
 (0)