diff options
Diffstat (limited to 'net/core/link_watch.c')
| -rw-r--r-- | net/core/link_watch.c | 17 | 
1 files changed, 14 insertions, 3 deletions
| diff --git a/net/core/link_watch.c b/net/core/link_watch.c index 1a455847da54..b0f5344d1185 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c @@ -55,7 +55,7 @@ static void rfc2863_policy(struct net_device *dev)  	if (operstate == dev->operstate)  		return; -	write_lock_bh(&dev_base_lock); +	write_lock(&dev_base_lock);  	switch(dev->link_mode) {  	case IF_LINK_MODE_TESTING: @@ -74,7 +74,7 @@ static void rfc2863_policy(struct net_device *dev)  	dev->operstate = operstate; -	write_unlock_bh(&dev_base_lock); +	write_unlock(&dev_base_lock);  } @@ -109,7 +109,7 @@ static void linkwatch_add_event(struct net_device *dev)  	spin_lock_irqsave(&lweventlist_lock, flags);  	if (list_empty(&dev->link_watch_list)) {  		list_add_tail(&dev->link_watch_list, &lweventlist); -		dev_hold(dev); +		dev_hold_track(dev, &dev->linkwatch_dev_tracker, GFP_ATOMIC);  	}  	spin_unlock_irqrestore(&lweventlist_lock, flags);  } @@ -166,6 +166,9 @@ static void linkwatch_do_dev(struct net_device *dev)  		netdev_state_change(dev);  	} +	/* Note: our callers are responsible for +	 * calling netdev_tracker_free(). +	 */  	dev_put(dev);  } @@ -209,6 +212,10 @@ static void __linkwatch_run_queue(int urgent_only)  			list_add_tail(&dev->link_watch_list, &lweventlist);  			continue;  		} +		/* We must free netdev tracker under +		 * the spinlock protection. +		 */ +		netdev_tracker_free(dev, &dev->linkwatch_dev_tracker);  		spin_unlock_irq(&lweventlist_lock);  		linkwatch_do_dev(dev);  		do_dev--; @@ -232,6 +239,10 @@ void linkwatch_forget_dev(struct net_device *dev)  	if (!list_empty(&dev->link_watch_list)) {  		list_del_init(&dev->link_watch_list);  		clean = 1; +		/* We must release netdev tracker under +		 * the spinlock protection. +		 */ +		netdev_tracker_free(dev, &dev->linkwatch_dev_tracker);  	}  	spin_unlock_irqrestore(&lweventlist_lock, flags);  	if (clean) |