Add a netdevice_tracker inside struct net_device, to track the self reference when a device has an active watchdog timer.
Unified · Split
| @@ -1951,6 +1951,7 @@ enum netdev_ml_priv_type { · 1950 unmodified lines | ||
| 1951 | 1951 | * |
| 1952 | 1952 | * @dev_addr_shadow: Copy of @dev_addr to catch direct writes. |
| 1953 | 1953 | * @linkwatch_dev_tracker: refcount tracker used by linkwatch. |
| 1954 | + * @watchdog_dev_tracker: refcount tracker used by watchdog. | |
| 1954 | 1955 | * |
| 1955 | 1956 | * FIXME: cleanup struct net_device such that network protocol info |
| 1956 | 1957 | * moves out. |
| @@ -2282,6 +2283,7 @@ struct net_device { · 325 unmodified lines | ||
| 2282 | 2283 | |
| 2283 | 2284 | u8 dev_addr_shadow[MAX_ADDR_LEN]; |
| 2284 | 2285 | netdevice_tracker linkwatch_dev_tracker; |
| 2286 | + netdevice_tracker watchdog_dev_tracker; | |
| 2285 | 2287 | }; |
| 2286 | 2288 | #define to_net_dev(d) container_of(d, struct net_device, dev) |
| 2287 | 2289 | |
| @@ -499,6 +499,7 @@ EXPORT_SYMBOL(netif_tx_unlock); · 498 unmodified lines | ||
| 499 | 499 | static void dev_watchdog(struct timer_list *t) |
| 500 | 500 | { |
| 501 | 501 | struct net_device *dev = from_timer(dev, t, watchdog_timer); |
| 502 | + bool release = true; | |
| 502 | 503 | |
| 503 | 504 | spin_lock(&dev->tx_global_lock); |
| 504 | 505 | if (!qdisc_tx_is_noop(dev)) { |
| @@ -534,12 +535,13 @@ static void dev_watchdog(struct timer_list *t) · 29 unmodified lines | ||
| 534 | 535 | if (!mod_timer(&dev->watchdog_timer, |
| 535 | 536 | round_jiffies(jiffies + |
| 536 | 537 | dev->watchdog_timeo))) |
| 537 | − dev_hold(dev); | |
| 538 | + release = false; | |
| 538 | 539 | } |
| 539 | 540 | } |
| 540 | 541 | spin_unlock(&dev->tx_global_lock); |
| 541 | 542 | |
| 542 | − dev_put(dev); | |
| 543 | + if (release) | |
| 544 | + dev_put_track(dev, &dev->watchdog_dev_tracker); | |
| 543 | 545 | } |
| 544 | 546 | |
| 545 | 547 | void __netdev_watchdog_up(struct net_device *dev) |
| @@ -549,7 +551,7 @@ void __netdev_watchdog_up(struct net_device *dev) · 3 unmodified lines | ||
| 549 | 551 | dev->watchdog_timeo = 5*HZ; |
| 550 | 552 | if (!mod_timer(&dev->watchdog_timer, |
| 551 | 553 | round_jiffies(jiffies + dev->watchdog_timeo))) |
| 552 | − dev_hold(dev); | |
| 554 | + dev_hold_track(dev, &dev->watchdog_dev_tracker, GFP_ATOMIC); | |
| 553 | 555 | } |
| 554 | 556 | } |
| 555 | 557 | EXPORT_SYMBOL_GPL(__netdev_watchdog_up); |
| @@ -563,7 +565,7 @@ static void dev_watchdog_down(struct net_device *dev) · 7 unmodified lines | ||
| 563 | 565 | { |
| 564 | 566 | netif_tx_lock_bh(dev); |
| 565 | 567 | if (del_timer(&dev->watchdog_timer)) |
| 566 | − dev_put(dev); | |
| 568 | + dev_put_track(dev, &dev->watchdog_dev_tracker); | |
| 567 | 569 | netif_tx_unlock_bh(dev); |
| 568 | 570 | } |
| 569 | 571 | |