summaryrefslogtreecommitdiffstats
path: root/net/mac80211/cfg.c
diff options
context:
space:
mode:
authorEyal Shapira <eyal@wizery.com>2012-08-06 14:26:16 +0300
committerJohannes Berg <johannes.berg@intel.com>2012-08-20 13:20:56 +0200
commitaa7a00809cf6afe3cd6f5af2889110b47b798667 (patch)
tree4b2d537fdad3058f61ab0bb894b935afc75442b5 /net/mac80211/cfg.c
parentf609a43dca2964a8a604ef554be92fa11c3b4c41 (diff)
downloadlinux-aa7a00809cf6afe3cd6f5af2889110b47b798667.tar.bz2
mac80211: avoid using synchronize_rcu in ieee80211_set_probe_resp
This could take a while (100ms+) and may delay sending assoc resp in AP mode with WPS or P2P GO (as setting the probe resp takes place there). We've encountered situations where the delay was big enough to cause connection problems with devices like Galaxy Nexus. Switch to using call_rcu with a free handler. [Arik - rework to use plain buffer and instead of skb] Signed-off-by: Eyal Shapira <eyal@wizery.com> Signed-off-by: Arik Nemtsov <arik@wizery.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r--net/mac80211/cfg.c16
1 files changed, 7 insertions, 9 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index df64b455821d..8052a7ad03a6 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -725,25 +725,23 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
const u8 *resp, size_t resp_len)
{
- struct sk_buff *new, *old;
+ struct probe_resp *new, *old;
if (!resp || !resp_len)
- return 1;
+ return -EINVAL;
old = rtnl_dereference(sdata->u.ap.probe_resp);
- new = dev_alloc_skb(resp_len);
+ new = kzalloc(sizeof(struct probe_resp) + resp_len, GFP_KERNEL);
if (!new)
return -ENOMEM;
- memcpy(skb_put(new, resp_len), resp, resp_len);
+ new->len = resp_len;
+ memcpy(new->data, resp, resp_len);
rcu_assign_pointer(sdata->u.ap.probe_resp, new);
- if (old) {
- /* TODO: use call_rcu() */
- synchronize_rcu();
- dev_kfree_skb(old);
- }
+ if (old)
+ kfree_rcu(old, rcu_head);
return 0;
}