diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2006-08-03 09:54:41 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2006-08-04 14:57:19 -0400 |
commit | 782a6675119c76c071e74e2ddd98268f47770cba (patch) | |
tree | 83815eb8984242ec93a632694d0d243ec8ccd691 /net | |
parent | efe78cda3596f8a6d1c2d4a6b1a221bafa3e1a48 (diff) |
[PATCH] Send wireless netlink events with a clean slate
Drivers expect to be able to call wireless_send_event in arbitrary
contexts. On the other hand, netlink really doesn't like being
invoked in an IRQ context. So we need to postpone the sending of
netlink skb's to a tasklet.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/wireless.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/net/core/wireless.c b/net/core/wireless.c index d2bc72d318f7..de0bde4b51dd 100644 --- a/net/core/wireless.c +++ b/net/core/wireless.c | |||
@@ -82,6 +82,7 @@ | |||
82 | #include <linux/init.h> /* for __init */ | 82 | #include <linux/init.h> /* for __init */ |
83 | #include <linux/if_arp.h> /* ARPHRD_ETHER */ | 83 | #include <linux/if_arp.h> /* ARPHRD_ETHER */ |
84 | #include <linux/etherdevice.h> /* compare_ether_addr */ | 84 | #include <linux/etherdevice.h> /* compare_ether_addr */ |
85 | #include <linux/interrupt.h> | ||
85 | 86 | ||
86 | #include <linux/wireless.h> /* Pretty obvious */ | 87 | #include <linux/wireless.h> /* Pretty obvious */ |
87 | #include <net/iw_handler.h> /* New driver API */ | 88 | #include <net/iw_handler.h> /* New driver API */ |
@@ -1842,6 +1843,18 @@ int wireless_rtnetlink_set(struct net_device * dev, | |||
1842 | */ | 1843 | */ |
1843 | 1844 | ||
1844 | #ifdef WE_EVENT_RTNETLINK | 1845 | #ifdef WE_EVENT_RTNETLINK |
1846 | static struct sk_buff_head wireless_nlevent_queue; | ||
1847 | |||
1848 | static void wireless_nlevent_process(unsigned long data) | ||
1849 | { | ||
1850 | struct sk_buff *skb; | ||
1851 | |||
1852 | while ((skb = skb_dequeue(&wireless_nlevent_queue))) | ||
1853 | netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC); | ||
1854 | } | ||
1855 | |||
1856 | static DECLARE_TASKLET(wireless_nlevent_tasklet, wireless_nlevent_process, 0); | ||
1857 | |||
1845 | /* ---------------------------------------------------------------- */ | 1858 | /* ---------------------------------------------------------------- */ |
1846 | /* | 1859 | /* |
1847 | * Fill a rtnetlink message with our event data. | 1860 | * Fill a rtnetlink message with our event data. |
@@ -1904,8 +1917,17 @@ static inline void rtmsg_iwinfo(struct net_device * dev, | |||
1904 | return; | 1917 | return; |
1905 | } | 1918 | } |
1906 | NETLINK_CB(skb).dst_group = RTNLGRP_LINK; | 1919 | NETLINK_CB(skb).dst_group = RTNLGRP_LINK; |
1907 | netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC); | 1920 | skb_queue_tail(&wireless_nlevent_queue, skb); |
1921 | tasklet_schedule(&wireless_nlevent_tasklet); | ||
1922 | } | ||
1923 | |||
1924 | static int __init wireless_nlevent_init(void) | ||
1925 | { | ||
1926 | skb_queue_head_init(&wireless_nlevent_queue); | ||
1927 | return 0; | ||
1908 | } | 1928 | } |
1929 | |||
1930 | subsys_initcall(wireless_nlevent_init); | ||
1909 | #endif /* WE_EVENT_RTNETLINK */ | 1931 | #endif /* WE_EVENT_RTNETLINK */ |
1910 | 1932 | ||
1911 | /* ---------------------------------------------------------------- */ | 1933 | /* ---------------------------------------------------------------- */ |