|
@@ -8733,14 +8733,15 @@ static void tg3_free_consistent(struct tg3 *tp)
|
|
|
tg3_mem_rx_release(tp);
|
|
|
tg3_mem_tx_release(tp);
|
|
|
|
|
|
- /* Protect tg3_get_stats64() from reading freed tp->hw_stats. */
|
|
|
- tg3_full_lock(tp, 0);
|
|
|
+ /* tp->hw_stats can be referenced safely:
|
|
|
+ * 1. under rtnl_lock
|
|
|
+ * 2. or under tp->lock if TG3_FLAG_INIT_COMPLETE is set.
|
|
|
+ */
|
|
|
if (tp->hw_stats) {
|
|
|
dma_free_coherent(&tp->pdev->dev, sizeof(struct tg3_hw_stats),
|
|
|
tp->hw_stats, tp->stats_mapping);
|
|
|
tp->hw_stats = NULL;
|
|
|
}
|
|
|
- tg3_full_unlock(tp);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -14178,7 +14179,7 @@ static void tg3_get_stats64(struct net_device *dev,
|
|
|
struct tg3 *tp = netdev_priv(dev);
|
|
|
|
|
|
spin_lock_bh(&tp->lock);
|
|
|
- if (!tp->hw_stats) {
|
|
|
+ if (!tp->hw_stats || !tg3_flag(tp, INIT_COMPLETE)) {
|
|
|
*stats = tp->net_stats_prev;
|
|
|
spin_unlock_bh(&tp->lock);
|
|
|
return;
|