Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 158973
b: refs/heads/master
c: b333b3d
h: refs/heads/master
i:
  158971: 61d3616
v: v3
  • Loading branch information
Johannes Berg authored and David S. Miller committed Jul 15, 2009
1 parent 295a514 commit 20d1edb
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 33 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 97fd5bc7f2e442482a7a6cc4bc2a286cbb5f4754
refs/heads/master: b333b3d22822cf9b295990866798e9239c9dee72
3 changes: 3 additions & 0 deletions trunk/include/net/net_namespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ struct net {
#endif
#ifdef CONFIG_XFRM
struct netns_xfrm xfrm;
#endif
#ifdef CONFIG_WIRELESS_EXT
struct sk_buff_head wext_nlevents;
#endif
struct net_generic *gen;
};
Expand Down
61 changes: 29 additions & 32 deletions trunk/net/wireless/wext.c
Original file line number Diff line number Diff line change
Expand Up @@ -1257,48 +1257,48 @@ int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
}
#endif

/************************* EVENT PROCESSING *************************/
/*
* Process events generated by the wireless layer or the driver.
* Most often, the event will be propagated through rtnetlink
*/
static int __net_init wext_pernet_init(struct net *net)
{
skb_queue_head_init(&net->wext_nlevents);
return 0;
}

/* ---------------------------------------------------------------- */
/*
* Locking...
* ----------
*
* Thanks to Herbert Xu <herbert@gondor.apana.org.au> for fixing
* the locking issue in here and implementing this code !
*
* The issue : wireless_send_event() is often called in interrupt context,
* while the Netlink layer can never be called in interrupt context.
* The fully formed RtNetlink events are queued, and then a tasklet is run
* to feed those to Netlink.
* The skb_queue is interrupt safe, and its lock is not held while calling
* Netlink, so there is no possibility of dealock.
* Jean II
*/
static void __net_exit wext_pernet_exit(struct net *net)
{
skb_queue_purge(&net->wext_nlevents);
}

static struct sk_buff_head wireless_nlevent_queue;
static struct pernet_operations wext_pernet_ops = {
.init = wext_pernet_init,
.exit = wext_pernet_exit,
};

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

subsys_initcall(wireless_nlevent_init);

static void wireless_nlevent_process(unsigned long data)
/* Process events generated by the wireless layer or the driver. */
static void wireless_nlevent_process(struct work_struct *work)
{
struct sk_buff *skb;
struct net *net;

rtnl_lock();

while ((skb = skb_dequeue(&wireless_nlevent_queue)))
rtnl_notify(skb, &init_net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
for_each_net(net) {
while ((skb = skb_dequeue(&net->wext_nlevents)))
rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL,
GFP_KERNEL);
}

rtnl_unlock();
}

static DECLARE_TASKLET(wireless_nlevent_tasklet, wireless_nlevent_process, 0);
static DECLARE_WORK(wireless_nlevent_work, wireless_nlevent_process);

/* ---------------------------------------------------------------- */
/*
Expand Down Expand Up @@ -1348,9 +1348,6 @@ static void rtmsg_iwinfo(struct net_device *dev, char *event, int event_len)
struct sk_buff *skb;
int err;

if (!net_eq(dev_net(dev), &init_net))
return;

skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
if (!skb)
return;
Expand All @@ -1363,8 +1360,8 @@ static void rtmsg_iwinfo(struct net_device *dev, char *event, int event_len)
}

NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
skb_queue_tail(&wireless_nlevent_queue, skb);
tasklet_schedule(&wireless_nlevent_tasklet);
skb_queue_tail(&dev_net(dev)->wext_nlevents, skb);
schedule_work(&wireless_nlevent_work);
}

/* ---------------------------------------------------------------- */
Expand Down

0 comments on commit 20d1edb

Please sign in to comment.