]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
cfg80211/mac80211: allow management TX to not wait for ACK
authorJohannes Berg <johannes.berg@intel.com>
Fri, 4 Nov 2011 10:18:21 +0000 (11:18 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 9 Nov 2011 21:13:54 +0000 (16:13 -0500)
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>
drivers/net/wireless/ath/ath6kl/cfg80211.c
include/linux/nl80211.h
include/net/cfg80211.h
net/mac80211/cfg.c
net/wireless/core.h
net/wireless/mlme.c
net/wireless/nl80211.c

index 3aff36bad5d3a64194d08c312701ad26ae9a430d..daf444bf8d480bf4bfff06bb7cce4ae3fa029d92 100644 (file)
@@ -1732,7 +1732,8 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
                          struct ieee80211_channel *chan, bool offchan,
                          enum nl80211_channel_type channel_type,
                          bool channel_type_valid, unsigned int wait,
-                         const u8 *buf, size_t len, bool no_cck, u64 *cookie)
+                         const u8 *buf, size_t len, bool no_cck,
+                         bool dont_wait_for_ack, u64 *cookie)
 {
        struct ath6kl *ar = ath6kl_priv(dev);
        u32 id;
index 09474ab7de8c66ce0a35febf8278f44d1f3c867f..165e16fc7af16645d89d7b3f928fbc5dcde16f0a 100644 (file)
@@ -1151,6 +1151,11 @@ enum nl80211_commands {
  *     with support for the features listed in this attribute, see
  *     &enum nl80211_ap_sme_features.
  *
+ * @NL80211_ATTR_DONT_WAIT_FOR_ACK: Used with %NL80211_CMD_FRAME, this tells
+ *     the driver to not wait for an acknowledgement. Note that due to this,
+ *     it will also not give a status callback nor return a cookie. This is
+ *     mostly useful for probe responses to save airtime.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1381,6 +1386,8 @@ enum nl80211_attrs {
 
        NL80211_ATTR_DEVICE_AP_SME,
 
+       NL80211_ATTR_DONT_WAIT_FOR_ACK,
+
        /* add attributes here, update the policy in nl80211.c */
 
        __NL80211_ATTR_AFTER_LAST,
index be3535f0895e54a7725e697e432e822d48a8489d..00287bdef919848b786b6bd31410fbc20a184196 100644 (file)
@@ -1588,7 +1588,7 @@ struct cfg80211_ops {
                          enum nl80211_channel_type channel_type,
                          bool channel_type_valid, unsigned int wait,
                          const u8 *buf, size_t len, bool no_cck,
-                         u64 *cookie);
+                         bool dont_wait_for_ack, u64 *cookie);
        int     (*mgmt_tx_cancel_wait)(struct wiphy *wiphy,
                                       struct net_device *dev,
                                       u64 cookie);
index e072fea69a302b9d1d8bd1bf87e378b0b6dee7e1..ab3258ac0b2ceb75ce01797c9ac15c8641a11536 100644 (file)
@@ -1936,7 +1936,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
                             enum nl80211_channel_type channel_type,
                             bool channel_type_valid, unsigned int wait,
                             const u8 *buf, size_t len, bool no_cck,
-                            u64 *cookie)
+                            bool dont_wait_for_ack, u64 *cookie)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
@@ -1944,10 +1944,15 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
        struct sta_info *sta;
        struct ieee80211_work *wk;
        const struct ieee80211_mgmt *mgmt = (void *)buf;
-       u32 flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX |
-                   IEEE80211_TX_CTL_REQ_TX_STATUS;
+       u32 flags;
        bool is_offchan = false;
 
+       if (dont_wait_for_ack)
+               flags = IEEE80211_TX_CTL_NO_ACK;
+       else
+               flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX |
+                       IEEE80211_TX_CTL_REQ_TX_STATUS;
+
        /* Check that we are on the requested channel for transmission */
        if (chan != local->tmp_channel &&
            chan != local->oper_channel)
index 4c6ff402435670db9bdf577b320c1f928433ec23..1c7d4df5418cdef9929939a782c0fcf0893a0bd3 100644 (file)
@@ -378,7 +378,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
                          enum nl80211_channel_type channel_type,
                          bool channel_type_valid, unsigned int wait,
                          const u8 *buf, size_t len, bool no_cck,
-                         u64 *cookie);
+                         bool dont_wait_for_ack, u64 *cookie);
 
 /* SME */
 int __cfg80211_connect(struct cfg80211_registered_device *rdev,
index 34891e08c54a13dc2597d0507bcf8a9e79738c41..6c1bafd508c8dabddee9422448084f92c04a2be8 100644 (file)
@@ -904,7 +904,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
                          enum nl80211_channel_type channel_type,
                          bool channel_type_valid, unsigned int wait,
                          const u8 *buf, size_t len, bool no_cck,
-                         u64 *cookie)
+                         bool dont_wait_for_ack, u64 *cookie)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        const struct ieee80211_mgmt *mgmt;
@@ -995,7 +995,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
        /* Transmit the Action frame as requested by user space */
        return rdev->ops->mgmt_tx(&rdev->wiphy, dev, chan, offchan,
                                  channel_type, channel_type_valid,
-                                 wait, buf, len, no_cck, cookie);
+                                 wait, buf, len, no_cck, dont_wait_for_ack,
+                                 cookie);
 }
 
 bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf,
index 5b659068b02092ebf54b17726250c3b91a081917..0ef09415c89afdfd5120dfa7f9c0a80b4dfe7a15 100644 (file)
@@ -196,6 +196,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
        [NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 },
        [NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG },
        [NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG },
+       [NL80211_ATTR_DONT_WAIT_FOR_ACK] = { .type = NLA_FLAG },
 };
 
 /* policy for the key attributes */
@@ -5282,10 +5283,11 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
        int err;
        void *hdr;
        u64 cookie;
-       struct sk_buff *msg;
+       struct sk_buff *msg = NULL;
        unsigned int wait = 0;
-       bool offchan;
-       bool no_cck;
+       bool offchan, no_cck, dont_wait_for_ack;
+
+       dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
 
        if (!info->attrs[NL80211_ATTR_FRAME] ||
            !info->attrs[NL80211_ATTR_WIPHY_FREQ])
@@ -5329,29 +5331,36 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
        if (chan == NULL)
                return -EINVAL;
 
-       msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-       if (!msg)
-               return -ENOMEM;
+       if (!dont_wait_for_ack) {
+               msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+               if (!msg)
+                       return -ENOMEM;
 
-       hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
-                            NL80211_CMD_FRAME);
+               hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
+                                    NL80211_CMD_FRAME);
 
-       if (IS_ERR(hdr)) {
-               err = PTR_ERR(hdr);
-               goto free_msg;
+               if (IS_ERR(hdr)) {
+                       err = PTR_ERR(hdr);
+                       goto free_msg;
+               }
        }
+
        err = cfg80211_mlme_mgmt_tx(rdev, dev, chan, offchan, channel_type,
                                    channel_type_valid, wait,
                                    nla_data(info->attrs[NL80211_ATTR_FRAME]),
                                    nla_len(info->attrs[NL80211_ATTR_FRAME]),
-                                   no_cck, &cookie);
+                                   no_cck, dont_wait_for_ack, &cookie);
        if (err)
                goto free_msg;
 
-       NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
+       if (msg) {
+               NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
 
-       genlmsg_end(msg, hdr);
-       return genlmsg_reply(msg, info);
+               genlmsg_end(msg, hdr);
+               return genlmsg_reply(msg, info);
+       }
+
+       return 0;
 
  nla_put_failure:
        err = -ENOBUFS;