aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-11-04 06:18:21 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-11-09 16:13:54 -0500
commite247bd9068e3e86c3571147c128883596ace9d05 (patch)
tree5639065f2b0bfe4cb7389a75e274bc8a53efd75f /net
parente7f4a940bb5eecd07cf0039e7d9201badc332ae0 (diff)
cfg80211/mac80211: allow management TX to not wait for ACK
For probe responses it can be useful to not wait for ACK to avoid retransmissions if the station that sent the probe is already on the next channel, so allow userspace to request not caring about the ACK with a new nl80211 flag. Since mac80211 needs to be updated for the new function prototype anyway implement it right away -- it's just a few lines of code. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c11
-rw-r--r--net/wireless/core.h2
-rw-r--r--net/wireless/mlme.c5
-rw-r--r--net/wireless/nl80211.c39
4 files changed, 36 insertions, 21 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index e072fea69a30..ab3258ac0b2c 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1936,7 +1936,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
1936 enum nl80211_channel_type channel_type, 1936 enum nl80211_channel_type channel_type,
1937 bool channel_type_valid, unsigned int wait, 1937 bool channel_type_valid, unsigned int wait,
1938 const u8 *buf, size_t len, bool no_cck, 1938 const u8 *buf, size_t len, bool no_cck,
1939 u64 *cookie) 1939 bool dont_wait_for_ack, u64 *cookie)
1940{ 1940{
1941 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1941 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1942 struct ieee80211_local *local = sdata->local; 1942 struct ieee80211_local *local = sdata->local;
@@ -1944,10 +1944,15 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
1944 struct sta_info *sta; 1944 struct sta_info *sta;
1945 struct ieee80211_work *wk; 1945 struct ieee80211_work *wk;
1946 const struct ieee80211_mgmt *mgmt = (void *)buf; 1946 const struct ieee80211_mgmt *mgmt = (void *)buf;
1947 u32 flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | 1947 u32 flags;
1948 IEEE80211_TX_CTL_REQ_TX_STATUS;
1949 bool is_offchan = false; 1948 bool is_offchan = false;
1950 1949
1950 if (dont_wait_for_ack)
1951 flags = IEEE80211_TX_CTL_NO_ACK;
1952 else
1953 flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX |
1954 IEEE80211_TX_CTL_REQ_TX_STATUS;
1955
1951 /* Check that we are on the requested channel for transmission */ 1956 /* Check that we are on the requested channel for transmission */
1952 if (chan != local->tmp_channel && 1957 if (chan != local->tmp_channel &&
1953 chan != local->oper_channel) 1958 chan != local->oper_channel)
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 4c6ff4024356..1c7d4df5418c 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -378,7 +378,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
378 enum nl80211_channel_type channel_type, 378 enum nl80211_channel_type channel_type,
379 bool channel_type_valid, unsigned int wait, 379 bool channel_type_valid, unsigned int wait,
380 const u8 *buf, size_t len, bool no_cck, 380 const u8 *buf, size_t len, bool no_cck,
381 u64 *cookie); 381 bool dont_wait_for_ack, u64 *cookie);
382 382
383/* SME */ 383/* SME */
384int __cfg80211_connect(struct cfg80211_registered_device *rdev, 384int __cfg80211_connect(struct cfg80211_registered_device *rdev,
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 34891e08c54a..6c1bafd508c8 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -904,7 +904,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
904 enum nl80211_channel_type channel_type, 904 enum nl80211_channel_type channel_type,
905 bool channel_type_valid, unsigned int wait, 905 bool channel_type_valid, unsigned int wait,
906 const u8 *buf, size_t len, bool no_cck, 906 const u8 *buf, size_t len, bool no_cck,
907 u64 *cookie) 907 bool dont_wait_for_ack, u64 *cookie)
908{ 908{
909 struct wireless_dev *wdev = dev->ieee80211_ptr; 909 struct wireless_dev *wdev = dev->ieee80211_ptr;
910 const struct ieee80211_mgmt *mgmt; 910 const struct ieee80211_mgmt *mgmt;
@@ -995,7 +995,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
995 /* Transmit the Action frame as requested by user space */ 995 /* Transmit the Action frame as requested by user space */
996 return rdev->ops->mgmt_tx(&rdev->wiphy, dev, chan, offchan, 996 return rdev->ops->mgmt_tx(&rdev->wiphy, dev, chan, offchan,
997 channel_type, channel_type_valid, 997 channel_type, channel_type_valid,
998 wait, buf, len, no_cck, cookie); 998 wait, buf, len, no_cck, dont_wait_for_ack,
999 cookie);
999} 1000}
1000 1001
1001bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf, 1002bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 5b659068b020..0ef09415c89a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -196,6 +196,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
196 [NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 }, 196 [NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 },
197 [NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG }, 197 [NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG },
198 [NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG }, 198 [NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG },
199 [NL80211_ATTR_DONT_WAIT_FOR_ACK] = { .type = NLA_FLAG },
199}; 200};
200 201
201/* policy for the key attributes */ 202/* policy for the key attributes */
@@ -5282,10 +5283,11 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
5282 int err; 5283 int err;
5283 void *hdr; 5284 void *hdr;
5284 u64 cookie; 5285 u64 cookie;
5285 struct sk_buff *msg; 5286 struct sk_buff *msg = NULL;
5286 unsigned int wait = 0; 5287 unsigned int wait = 0;
5287 bool offchan; 5288 bool offchan, no_cck, dont_wait_for_ack;
5288 bool no_cck; 5289
5290 dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
5289 5291
5290 if (!info->attrs[NL80211_ATTR_FRAME] || 5292 if (!info->attrs[NL80211_ATTR_FRAME] ||
5291 !info->attrs[NL80211_ATTR_WIPHY_FREQ]) 5293 !info->attrs[NL80211_ATTR_WIPHY_FREQ])
@@ -5329,29 +5331,36 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
5329 if (chan == NULL) 5331 if (chan == NULL)
5330 return -EINVAL; 5332 return -EINVAL;
5331 5333
5332 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 5334 if (!dont_wait_for_ack) {
5333 if (!msg) 5335 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5334 return -ENOMEM; 5336 if (!msg)
5337 return -ENOMEM;
5335 5338
5336 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, 5339 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
5337 NL80211_CMD_FRAME); 5340 NL80211_CMD_FRAME);
5338 5341
5339 if (IS_ERR(hdr)) { 5342 if (IS_ERR(hdr)) {
5340 err = PTR_ERR(hdr); 5343 err = PTR_ERR(hdr);
5341 goto free_msg; 5344 goto free_msg;
5345 }
5342 } 5346 }
5347
5343 err = cfg80211_mlme_mgmt_tx(rdev, dev, chan, offchan, channel_type, 5348 err = cfg80211_mlme_mgmt_tx(rdev, dev, chan, offchan, channel_type,
5344 channel_type_valid, wait, 5349 channel_type_valid, wait,
5345 nla_data(info->attrs[NL80211_ATTR_FRAME]), 5350 nla_data(info->attrs[NL80211_ATTR_FRAME]),
5346 nla_len(info->attrs[NL80211_ATTR_FRAME]), 5351 nla_len(info->attrs[NL80211_ATTR_FRAME]),
5347 no_cck, &cookie); 5352 no_cck, dont_wait_for_ack, &cookie);
5348 if (err) 5353 if (err)
5349 goto free_msg; 5354 goto free_msg;
5350 5355
5351 NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); 5356 if (msg) {
5357 NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
5352 5358
5353 genlmsg_end(msg, hdr); 5359 genlmsg_end(msg, hdr);
5354 return genlmsg_reply(msg, info); 5360 return genlmsg_reply(msg, info);
5361 }
5362
5363 return 0;
5355 5364
5356 nla_put_failure: 5365 nla_put_failure:
5357 err = -ENOBUFS; 5366 err = -ENOBUFS;