Skip to content

Commit d89a2ad

Browse files
Michael Chandavem330
authored andcommitted
tg3: Fix vunmap() BUG_ON() triggered from tg3_free_consistent().
tg3_free_consistent() calls dma_free_coherent() to free tp->hw_stats under spinlock and can trigger BUG_ON() in vunmap() because vunmap() may sleep. Fix it by removing the spinlock and relying on the TG3_FLAG_INIT_COMPLETE flag to prevent race conditions between tg3_get_stats64() and tg3_free_consistent(). TG3_FLAG_INIT_COMPLETE is always cleared under tp->lock before tg3_free_consistent() and therefore tg3_get_stats64() can safely access tp->hw_stats under tp->lock if TG3_FLAG_INIT_COMPLETE is set. Fixes: f5992b7 ("tg3: Fix race condition in tg3_get_stats64().") Reported-by: Zumeng Chen <[email protected]> Signed-off-by: Michael Chan <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent af50e4b commit d89a2ad

File tree

1 file changed

+5
-4
lines changed
  • drivers/net/ethernet/broadcom

1 file changed

+5
-4
lines changed

drivers/net/ethernet/broadcom/tg3.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8733,14 +8733,15 @@ static void tg3_free_consistent(struct tg3 *tp)
87338733
tg3_mem_rx_release(tp);
87348734
tg3_mem_tx_release(tp);
87358735

8736-
/* Protect tg3_get_stats64() from reading freed tp->hw_stats. */
8737-
tg3_full_lock(tp, 0);
8736+
/* tp->hw_stats can be referenced safely:
8737+
* 1. under rtnl_lock
8738+
* 2. or under tp->lock if TG3_FLAG_INIT_COMPLETE is set.
8739+
*/
87388740
if (tp->hw_stats) {
87398741
dma_free_coherent(&tp->pdev->dev, sizeof(struct tg3_hw_stats),
87408742
tp->hw_stats, tp->stats_mapping);
87418743
tp->hw_stats = NULL;
87428744
}
8743-
tg3_full_unlock(tp);
87448745
}
87458746

87468747
/*
@@ -14178,7 +14179,7 @@ static void tg3_get_stats64(struct net_device *dev,
1417814179
struct tg3 *tp = netdev_priv(dev);
1417914180

1418014181
spin_lock_bh(&tp->lock);
14181-
if (!tp->hw_stats) {
14182+
if (!tp->hw_stats || !tg3_flag(tp, INIT_COMPLETE)) {
1418214183
*stats = tp->net_stats_prev;
1418314184
spin_unlock_bh(&tp->lock);
1418414185
return;

0 commit comments

Comments
 (0)