diff options
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/cfg80211.c | 3 | ||||
-rw-r--r-- | include/linux/nl80211.h | 7 | ||||
-rw-r--r-- | include/net/cfg80211.h | 2 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 11 | ||||
-rw-r--r-- | net/wireless/core.h | 2 | ||||
-rw-r--r-- | net/wireless/mlme.c | 5 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 39 |
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 */ |
384 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, | 384 | int __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 | ||
1001 | bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf, | 1002 | bool 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; |