aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/cfg.c
diff options
context:
space:
mode:
authorEyal Shapira <eyal@wizery.com>2012-08-06 07:26:16 -0400
committerJohannes Berg <johannes.berg@intel.com>2012-08-20 07:20:56 -0400
commitaa7a00809cf6afe3cd6f5af2889110b47b798667 (patch)
tree4b2d537fdad3058f61ab0bb894b935afc75442b5 /net/mac80211/cfg.c
parentf609a43dca2964a8a604ef554be92fa11c3b4c41 (diff)
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,
725static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, 725static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
726 const u8 *resp, size_t resp_len) 726 const u8 *resp, size_t resp_len)
727{ 727{
728 struct sk_buff *new, *old; 728 struct probe_resp *new, *old;
729 729
730 if (!resp || !resp_len) 730 if (!resp || !resp_len)
731 return 1; 731 return -EINVAL;
732 732
733 old = rtnl_dereference(sdata->u.ap.probe_resp); 733 old = rtnl_dereference(sdata->u.ap.probe_resp);
734 734
735 new = dev_alloc_skb(resp_len); 735 new = kzalloc(sizeof(struct probe_resp) + resp_len, GFP_KERNEL);
736 if (!new) 736 if (!new)
737 return -ENOMEM; 737 return -ENOMEM;
738 738
739 memcpy(skb_put(new, resp_len), resp, resp_len); 739 new->len = resp_len;
740 memcpy(new->data, resp, resp_len);
740 741
741 rcu_assign_pointer(sdata->u.ap.probe_resp, new); 742 rcu_assign_pointer(sdata->u.ap.probe_resp, new);
742 if (old) { 743 if (old)
743 /* TODO: use call_rcu() */ 744 kfree_rcu(old, rcu_head);
744 synchronize_rcu();
745 dev_kfree_skb(old);
746 }
747 745
748 return 0; 746 return 0;
749} 747}