summaryrefslogtreecommitdiffstats
path: root/net/core/link_watch.c
diff options
context:
space:
mode:
authorJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-03-21 13:05:45 -0600
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-03-21 13:05:45 -0600
commitd04cdb64212eb5ae6a98026a97dda626e40e8e9a (patch)
treeb6a7dbb21ccfceb915844e9a330b3d3dfcaf3c5b /net/core/link_watch.c
parent2f8600dff2b140096a7df781884e918a16aa90e0 (diff)
parentec1248e70edc5cf7b485efcc7b41e44e10f422e5 (diff)
downloadlinux-d04cdb64212eb5ae6a98026a97dda626e40e8e9a.tar.bz2
Merge ../linux-2.6
Diffstat (limited to 'net/core/link_watch.c')
-rw-r--r--net/core/link_watch.c44
1 files changed, 42 insertions, 2 deletions
diff --git a/net/core/link_watch.c b/net/core/link_watch.c
index d43d1201275c..341de44c7ed1 100644
--- a/net/core/link_watch.c
+++ b/net/core/link_watch.c
@@ -49,6 +49,45 @@ struct lw_event {
/* 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)
{
@@ -74,6 +113,7 @@ void linkwatch_run_queue(void)
*/
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);
@@ -99,9 +139,9 @@ static void linkwatch_event(void *dummy)
linkwatch_nextevent = jiffies + HZ;
clear_bit(LW_RUNNING, &linkwatch_flags);
- rtnl_shlock();
+ rtnl_lock();
linkwatch_run_queue();
- rtnl_shunlock();
+ rtnl_unlock();
}