diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 74507c006490f180d2fac6594f6dcf2c86d53919..d0aba8dd46425b242a04b506299c4c66e99d94b4 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -4498,7 +4498,12 @@ static inline void netdev_tracker_free(struct net_device *dev, netdevice_tracker *tracker) { #ifdef CONFIG_NET_DEV_REFCNT_TRACKER - ref_tracker_free(&dev->refcnt_tracker, tracker); + if (!tracker) { + ref_tracker_free(&dev->refcnt_tracker, NULL); + } else if (!IS_ERR(*tracker)) { + ref_tracker_free(&dev->refcnt_tracker, tracker); + *tracker = ERR_PTR(-EEXIST); + } #endif } diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 237ee1cd013673816b651e4686fed7a7b921ca26..9ca9fafe087872cc7f89e83fb0acb2fd0a795cd9 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -568,16 +568,18 @@ static void dev_watchdog(struct timer_list *t) dev->netdev_ops->ndo_tx_timeout(dev, i); netif_unfreeze_queues(dev); } - if (!mod_timer(&dev->watchdog_timer, - round_jiffies(oldest_start + - dev->watchdog_timeo))) - release = false; + mod_timer(&dev->watchdog_timer, + round_jiffies(oldest_start + + dev->watchdog_timeo)); + release = false; } } - spin_unlock(&dev->tx_global_lock); - + if (timer_pending(&dev->watchdog_timer)) + release = false; if (release) netdev_put(dev, &dev->watchdog_dev_tracker); + + spin_unlock(&dev->tx_global_lock); } void netdev_watchdog_up(struct net_device *dev) @@ -586,10 +588,14 @@ void netdev_watchdog_up(struct net_device *dev) return; if (dev->watchdog_timeo <= 0) dev->watchdog_timeo = 5*HZ; + spin_lock_bh(&dev->tx_global_lock); if (!mod_timer(&dev->watchdog_timer, - round_jiffies(jiffies + dev->watchdog_timeo))) - netdev_hold(dev, &dev->watchdog_dev_tracker, - GFP_ATOMIC); + round_jiffies(jiffies + dev->watchdog_timeo))) { + if (!dev->watchdog_dev_tracker) + netdev_hold(dev, &dev->watchdog_dev_tracker, + GFP_ATOMIC); + } + spin_unlock_bh(&dev->tx_global_lock); } EXPORT_SYMBOL_GPL(netdev_watchdog_up); @@ -617,8 +623,6 @@ void netif_carrier_on(struct net_device *dev) return; atomic_inc(&dev->carrier_up_count); linkwatch_fire_event(dev); - if (netif_running(dev)) - netdev_watchdog_up(dev); } } EXPORT_SYMBOL(netif_carrier_on);