Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 782a6675 authored by Herbert Xu's avatar Herbert Xu Committed by John W. Linville
Browse files

[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: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent efe78cda
Loading
Loading
Loading
Loading
+23 −1
Original line number Original line Diff line number Diff line
@@ -82,6 +82,7 @@
#include <linux/init.h>			/* for __init */
#include <linux/init.h>			/* for __init */
#include <linux/if_arp.h>		/* ARPHRD_ETHER */
#include <linux/if_arp.h>		/* ARPHRD_ETHER */
#include <linux/etherdevice.h>		/* compare_ether_addr */
#include <linux/etherdevice.h>		/* compare_ether_addr */
#include <linux/interrupt.h>


#include <linux/wireless.h>		/* Pretty obvious */
#include <linux/wireless.h>		/* Pretty obvious */
#include <net/iw_handler.h>		/* New driver API */
#include <net/iw_handler.h>		/* New driver API */
@@ -1842,6 +1843,18 @@ int wireless_rtnetlink_set(struct net_device * dev,
 */
 */


#ifdef WE_EVENT_RTNETLINK
#ifdef WE_EVENT_RTNETLINK
static struct sk_buff_head wireless_nlevent_queue;

static void wireless_nlevent_process(unsigned long data)
{
	struct sk_buff *skb;

	while ((skb = skb_dequeue(&wireless_nlevent_queue)))
		netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC);
}

static DECLARE_TASKLET(wireless_nlevent_tasklet, wireless_nlevent_process, 0);

/* ---------------------------------------------------------------- */
/* ---------------------------------------------------------------- */
/*
/*
 * Fill a rtnetlink message with our event data.
 * Fill a rtnetlink message with our event data.
@@ -1904,8 +1917,17 @@ static inline void rtmsg_iwinfo(struct net_device * dev,
		return;
		return;
	}
	}
	NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
	NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
	netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC);
	skb_queue_tail(&wireless_nlevent_queue, skb);
	tasklet_schedule(&wireless_nlevent_tasklet);
}
}

static int __init wireless_nlevent_init(void)
{
	skb_queue_head_init(&wireless_nlevent_queue);
	return 0;
}

subsys_initcall(wireless_nlevent_init);
#endif	/* WE_EVENT_RTNETLINK */
#endif	/* WE_EVENT_RTNETLINK */


/* ---------------------------------------------------------------- */
/* ---------------------------------------------------------------- */