00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <linux/module.h>
00015 #include <linux/netdevice.h>
00016 #include <linux/if.h>
00017 #include <net/sock.h>
00018 #include <net/pkt_sched.h>
00019 #include <linux/rtnetlink.h>
00020 #include <linux/jiffies.h>
00021 #include <linux/spinlock.h>
00022 #include <linux/slab.h>
00023 #include <linux/workqueue.h>
00024 #include <linux/bitops.h>
00025 #include <asm/types.h>
00026
00027
00028 enum lw_bits {
00029 LW_URGENT = 0,
00030 };
00031
00032 static unsigned long linkwatch_flags;
00033 static unsigned long linkwatch_nextevent;
00034
00035 static void linkwatch_event(struct work_struct *dummy);
00036 static DECLARE_DELAYED_WORK(linkwatch_work, linkwatch_event);
00037
00038 static struct net_device *lweventlist;
00039 static DEFINE_SPINLOCK(lweventlist_lock);
00040
00041 static unsigned char default_operstate(const struct net_device *dev)
00042 {
00043 #ifndef DDE_LINUX
00044 if (!netif_carrier_ok(dev))
00045 return (dev->ifindex != dev->iflink ?
00046 IF_OPER_LOWERLAYERDOWN : IF_OPER_DOWN);
00047
00048 if (netif_dormant(dev))
00049 return IF_OPER_DORMANT;
00050 #endif
00051
00052 return IF_OPER_UP;
00053 }
00054
00055
00056 static void rfc2863_policy(struct net_device *dev)
00057 {
00058 #ifndef DDE_LINUX
00059 unsigned char operstate = default_operstate(dev);
00060
00061 if (operstate == dev->operstate)
00062 return;
00063
00064 write_lock_bh(&dev_base_lock);
00065
00066 switch(dev->link_mode) {
00067 case IF_LINK_MODE_DORMANT:
00068 if (operstate == IF_OPER_UP)
00069 operstate = IF_OPER_DORMANT;
00070 break;
00071
00072 case IF_LINK_MODE_DEFAULT:
00073 default:
00074 break;
00075 }
00076
00077 dev->operstate = operstate;
00078
00079 write_unlock_bh(&dev_base_lock);
00080 #endif
00081 }
00082
00083
00084 static bool linkwatch_urgent_event(struct net_device *dev)
00085 {
00086 return netif_running(dev) && netif_carrier_ok(dev) &&
00087 qdisc_tx_changing(dev);
00088 }
00089
00090
00091 static void linkwatch_add_event(struct net_device *dev)
00092 {
00093 unsigned long flags;
00094
00095 spin_lock_irqsave(&lweventlist_lock, flags);
00096 dev->link_watch_next = lweventlist;
00097 lweventlist = dev;
00098 spin_unlock_irqrestore(&lweventlist_lock, flags);
00099 }
00100
00101
00102 static void linkwatch_schedule_work(int urgent)
00103 {
00104 unsigned long delay = linkwatch_nextevent - jiffies;
00105
00106 if (test_bit(LW_URGENT, &linkwatch_flags))
00107 return;
00108
00109
00110 if (urgent) {
00111 if (test_and_set_bit(LW_URGENT, &linkwatch_flags))
00112 return;
00113 delay = 0;
00114 }
00115
00116
00117 if (delay > HZ)
00118 delay = 0;
00119
00120
00121
00122
00123
00124 if (schedule_delayed_work(&linkwatch_work, delay) == !delay)
00125 return;
00126
00127
00128 if (!test_bit(LW_URGENT, &linkwatch_flags))
00129 return;
00130
00131
00132 if (!cancel_delayed_work(&linkwatch_work))
00133 return;
00134
00135
00136 schedule_delayed_work(&linkwatch_work, 0);
00137 }
00138
00139
00140 static void __linkwatch_run_queue(int urgent_only)
00141 {
00142 #ifndef DDE_LINUX
00143 struct net_device *next;
00144
00145
00146
00147
00148
00149
00150
00151
00152 if (!urgent_only)
00153 linkwatch_nextevent = jiffies + HZ;
00154
00155 else if (time_after(linkwatch_nextevent, jiffies + HZ))
00156 linkwatch_nextevent = jiffies;
00157
00158 clear_bit(LW_URGENT, &linkwatch_flags);
00159
00160 spin_lock_irq(&lweventlist_lock);
00161 next = lweventlist;
00162 lweventlist = NULL;
00163 spin_unlock_irq(&lweventlist_lock);
00164
00165 while (next) {
00166 struct net_device *dev = next;
00167
00168 next = dev->link_watch_next;
00169
00170 if (urgent_only && !linkwatch_urgent_event(dev)) {
00171 linkwatch_add_event(dev);
00172 continue;
00173 }
00174
00175
00176
00177
00178
00179 smp_mb__before_clear_bit();
00180
00181
00182
00183
00184 clear_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state);
00185
00186 rfc2863_policy(dev);
00187 if (dev->flags & IFF_UP) {
00188 if (netif_carrier_ok(dev))
00189 dev_activate(dev);
00190 else
00191 dev_deactivate(dev);
00192
00193 netdev_state_change(dev);
00194 }
00195
00196 dev_put(dev);
00197 }
00198
00199 if (lweventlist)
00200 linkwatch_schedule_work(0);
00201 #endif
00202 }
00203
00204
00205
00206 void linkwatch_run_queue(void)
00207 {
00208 __linkwatch_run_queue(0);
00209 }
00210
00211
00212 static void linkwatch_event(struct work_struct *dummy)
00213 {
00214 #ifndef DDE_LINUX
00215 rtnl_lock();
00216 __linkwatch_run_queue(time_after(linkwatch_nextevent, jiffies));
00217 rtnl_unlock();
00218 #endif
00219 }
00220
00221
00222 void linkwatch_fire_event(struct net_device *dev)
00223 {
00224 #ifndef DDE_LINUX
00225 bool urgent = linkwatch_urgent_event(dev);
00226
00227 if (!test_and_set_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state)) {
00228 dev_hold(dev);
00229
00230 linkwatch_add_event(dev);
00231 } else if (!urgent)
00232 return;
00233
00234 linkwatch_schedule_work(urgent);
00235 #endif
00236 }
00237
00238 EXPORT_SYMBOL(linkwatch_fire_event);