aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c3
-rw-r--r--include/linux/nl80211.h7
-rw-r--r--include/net/cfg80211.h2
-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
7 files changed, 46 insertions, 23 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 3aff36bad5d3..daf444bf8d48 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -1732,7 +1732,8 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
1732 struct ieee80211_channel *chan, bool offchan, 1732 struct ieee80211_channel *chan, bool offchan,
1733 enum nl80211_channel_type channel_type, 1733 enum nl80211_channel_type channel_type,
1734 bool channel_type_valid, unsigned int wait, 1734 bool channel_type_valid, unsigned int wait,
1735 const u8 *buf, size_t len, bool no_cck, u64 *cookie) 1735 const u8 *buf, size_t len, bool no_cck,
1736 bool dont_wait_for_ack, u64 *cookie)
1736{ 1737{
1737 struct ath6kl *ar = ath6kl_priv(dev); 1738 struct ath6kl *ar = ath6kl_priv(dev);
1738 u32 id; 1739 u32 id;
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 09474ab7de8c..165e16fc7af1 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1151,6 +1151,11 @@ enum nl80211_commands {
1151 * with support for the features listed in this attribute, see 1151 * with support for the features listed in this attribute, see
1152 * &enum nl80211_ap_sme_features. 1152 * &enum nl80211_ap_sme_features.
1153 * 1153 *
1154 * @NL80211_ATTR_DONT_WAIT_FOR_ACK: Used with %NL80211_CMD_FRAME, this tells
1155 * the driver to not wait for an acknowledgement. Note that due to this,
1156 * it will also not give a status callback nor return a cookie. This is
1157 * mostly useful for probe responses to save airtime.
1158 *
1154 * @NL80211_ATTR_MAX: highest attribute number currently defined 1159 * @NL80211_ATTR_MAX: highest attribute number currently defined
1155 * @__NL80211_ATTR_AFTER_LAST: internal use 1160 * @__NL80211_ATTR_AFTER_LAST: internal use
1156 */ 1161 */
@@ -1381,6 +1386,8 @@ enum nl80211_attrs {
1381 1386
1382 NL80211_ATTR_DEVICE_AP_SME, 1387 NL80211_ATTR_DEVICE_AP_SME,
1383 1388
1389 NL80211_ATTR_DONT_WAIT_FOR_ACK,
1390
1384 /* add attributes here, update the policy in nl80211.c */ 1391 /* add attributes here, update the policy in nl80211.c */
1385 1392
1386 __NL80211_ATTR_AFTER_LAST, 1393 __NL80211_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index be3535f0895e..00287bdef919 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1588,7 +1588,7 @@ struct cfg80211_ops {
1588 enum nl80211_channel_type channel_type, 1588 enum nl80211_channel_type channel_type,
1589 bool channel_type_valid, unsigned int wait, 1589 bool channel_type_valid, unsigned int wait,
1590 const u8 *buf, size_t len, bool no_cck, 1590 const u8 *buf, size_t len, bool no_cck,
1591 u64 *cookie); 1591 bool dont_wait_for_ack, u64 *cookie);
1592 int (*mgmt_tx_cancel_wait)(struct wiphy *wiphy, 1592 int (*mgmt_tx_cancel_wait)(struct wiphy *wiphy,
1593 struct net_device *dev, 1593 struct net_device *dev,
1594 u64 cookie); 1594 u64 cookie);
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;