Skip to content

Commit f754c9c

Browse files
Michael Changregkh
authored andcommitted
tg3: Fix vunmap() BUG_ON() triggered from tg3_free_consistent().
[ Upstream commit d89a2ad ] 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]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 413d262 commit f754c9c

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
@@ -8723,14 +8723,15 @@ static void tg3_free_consistent(struct tg3 *tp)
87238723
tg3_mem_rx_release(tp);
87248724
tg3_mem_tx_release(tp);
87258725

8726-
/* Protect tg3_get_stats64() from reading freed tp->hw_stats. */
8727-
tg3_full_lock(tp, 0);
8726+
/* tp->hw_stats can be referenced safely:
8727+
* 1. under rtnl_lock
8728+
* 2. or under tp->lock if TG3_FLAG_INIT_COMPLETE is set.
8729+
*/
87288730
if (tp->hw_stats) {
87298731
dma_free_coherent(&tp->pdev->dev, sizeof(struct tg3_hw_stats),
87308732
tp->hw_stats, tp->stats_mapping);
87318733
tp->hw_stats = NULL;
87328734
}
8733-
tg3_full_unlock(tp);
87348735
}
87358736

87368737
/*
@@ -14167,7 +14168,7 @@ static void tg3_get_stats64(struct net_device *dev,
1416714168
struct tg3 *tp = netdev_priv(dev);
1416814169

1416914170
spin_lock_bh(&tp->lock);
14170-
if (!tp->hw_stats) {
14171+
if (!tp->hw_stats || !tg3_flag(tp, INIT_COMPLETE)) {
1417114172
*stats = tp->net_stats_prev;
1417214173
spin_unlock_bh(&tp->lock);
1417314174
return;

0 commit comments

Comments
 (0)