aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/wext-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/wext-core.c')
-rw-r--r--net/wireless/wext-core.c52
1 files changed, 41 insertions, 11 deletions
diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c
index c8717c1d082e..b50ee5d622e1 100644
--- a/net/wireless/wext-core.c
+++ b/net/wireless/wext-core.c
@@ -342,6 +342,40 @@ static const int compat_event_type_size[] = {
342 342
343/* IW event code */ 343/* IW event code */
344 344
345void wireless_nlevent_flush(void)
346{
347 struct sk_buff *skb;
348 struct net *net;
349
350 ASSERT_RTNL();
351
352 for_each_net(net) {
353 while ((skb = skb_dequeue(&net->wext_nlevents)))
354 rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL,
355 GFP_KERNEL);
356 }
357}
358EXPORT_SYMBOL_GPL(wireless_nlevent_flush);
359
360static int wext_netdev_notifier_call(struct notifier_block *nb,
361 unsigned long state, void *ptr)
362{
363 /*
364 * When a netdev changes state in any way, flush all pending messages
365 * to avoid them going out in a strange order, e.g. RTM_NEWLINK after
366 * RTM_DELLINK, or with IFF_UP after without IFF_UP during dev_close()
367 * or similar - all of which could otherwise happen due to delays from
368 * schedule_work().
369 */
370 wireless_nlevent_flush();
371
372 return NOTIFY_OK;
373}
374
375static struct notifier_block wext_netdev_notifier = {
376 .notifier_call = wext_netdev_notifier_call,
377};
378
345static int __net_init wext_pernet_init(struct net *net) 379static int __net_init wext_pernet_init(struct net *net)
346{ 380{
347 skb_queue_head_init(&net->wext_nlevents); 381 skb_queue_head_init(&net->wext_nlevents);
@@ -360,7 +394,12 @@ static struct pernet_operations wext_pernet_ops = {
360 394
361static int __init wireless_nlevent_init(void) 395static int __init wireless_nlevent_init(void)
362{ 396{
363 return register_pernet_subsys(&wext_pernet_ops); 397 int err = register_pernet_subsys(&wext_pernet_ops);
398
399 if (err)
400 return err;
401
402 return register_netdevice_notifier(&wext_netdev_notifier);
364} 403}
365 404
366subsys_initcall(wireless_nlevent_init); 405subsys_initcall(wireless_nlevent_init);
@@ -368,17 +407,8 @@ subsys_initcall(wireless_nlevent_init);
368/* Process events generated by the wireless layer or the driver. */ 407/* Process events generated by the wireless layer or the driver. */
369static void wireless_nlevent_process(struct work_struct *work) 408static void wireless_nlevent_process(struct work_struct *work)
370{ 409{
371 struct sk_buff *skb;
372 struct net *net;
373
374 rtnl_lock(); 410 rtnl_lock();
375 411 wireless_nlevent_flush();
376 for_each_net(net) {
377 while ((skb = skb_dequeue(&net->wext_nlevents)))
378 rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL,
379 GFP_KERNEL);
380 }
381
382 rtnl_unlock(); 412 rtnl_unlock();
383} 413}
384 414