*
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/if.h>
/* Avoid kmalloc() for most systems */
static struct lw_event singleevent;
-static unsigned char default_operstate(const struct net_device *dev)
-{
- if (!netif_carrier_ok(dev))
- return (dev->ifindex != dev->iflink ?
- IF_OPER_LOWERLAYERDOWN : IF_OPER_DOWN);
-
- if (netif_dormant(dev))
- return IF_OPER_DORMANT;
-
- return IF_OPER_UP;
-}
-
-
-static void rfc2863_policy(struct net_device *dev)
-{
- unsigned char operstate = default_operstate(dev);
-
- if (operstate == dev->operstate)
- return;
-
- write_lock_bh(&dev_base_lock);
-
- switch(dev->link_mode) {
- case IF_LINK_MODE_DORMANT:
- if (operstate == IF_OPER_UP)
- operstate = IF_OPER_DORMANT;
- break;
-
- case IF_LINK_MODE_DEFAULT:
- default:
- break;
- };
-
- dev->operstate = operstate;
-
- write_unlock_bh(&dev_base_lock);
-}
-
-
/* Must be called with the rtnl semaphore held */
void linkwatch_run_queue(void)
{
- struct list_head head, *n, *next;
+ LIST_HEAD(head);
+ struct list_head *n, *next;
spin_lock_irq(&lweventlist_lock);
- list_replace_init(&lweventlist, &head);
+ list_splice_init(&lweventlist, &head);
spin_unlock_irq(&lweventlist_lock);
list_for_each_safe(n, next, &head) {
*/
clear_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state);
- rfc2863_policy(dev);
if (dev->flags & IFF_UP) {
if (netif_carrier_ok(dev)) {
WARN_ON(dev->qdisc_sleeping == &noop_qdisc);
linkwatch_nextevent = jiffies + HZ;
clear_bit(LW_RUNNING, &linkwatch_flags);
- rtnl_lock();
+ rtnl_shlock();
linkwatch_run_queue();
- rtnl_unlock();
+ rtnl_shunlock();
}
spin_unlock_irqrestore(&lweventlist_lock, flags);
if (!test_and_set_bit(LW_RUNNING, &linkwatch_flags)) {
- unsigned long delay = linkwatch_nextevent - jiffies;
+ unsigned long thisevent = jiffies;
- /* If we wrap around we'll delay it by at most HZ. */
- if (!delay || delay > HZ)
+ if (thisevent >= linkwatch_nextevent) {
schedule_work(&linkwatch_work);
- else
- schedule_delayed_work(&linkwatch_work, delay);
+ } else {
+ schedule_delayed_work(&linkwatch_work, linkwatch_nextevent - thisevent);
+ }
}
}
}