cfg80211/mac80211: add wmm info to assoc event
authorEliad Peller <eliad@wizery.com>
Tue, 9 Sep 2014 14:09:45 +0000 (17:09 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Thu, 11 Sep 2014 10:24:39 +0000 (12:24 +0200)
Userspace might need to know what queues are configured
for uapsd (e.g. for setting proper default values in tspecs).

Add this bitmap to the association event (inside wmm
nested attribute)

Add additional parameter to cfg80211_rx_assoc_resp,
and update its callers.

Signed-off-by: Eliad Peller <eliadx.peller@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/cfg80211.h
net/mac80211/mlme.c
net/wireless/mlme.c
net/wireless/nl80211.c
net/wireless/nl80211.h

index a13beab123dc8528572cd7f86210678001f8eced..2ed1f80f7eb699c1f18a40219e72fd346c7d30df 100644 (file)
@@ -3944,6 +3944,7 @@ void cfg80211_auth_timeout(struct net_device *dev, const u8 *addr);
  *     moves to cfg80211 in this call
  * @buf: authentication frame (header + body)
  * @len: length of the frame data
+ * @uapsd_queues: bitmap of ACs configured to uapsd. -1 if n/a.
  *
  * After being asked to associate via cfg80211_ops::assoc() the driver must
  * call either this function or cfg80211_auth_timeout().
@@ -3952,7 +3953,8 @@ void cfg80211_auth_timeout(struct net_device *dev, const u8 *addr);
  */
 void cfg80211_rx_assoc_resp(struct net_device *dev,
                            struct cfg80211_bss *bss,
-                           const u8 *buf, size_t len);
+                           const u8 *buf, size_t len,
+                           int uapsd_queues);
 
 /**
  * cfg80211_assoc_timeout - notification of timed out association
index a7b92f5f7161748c1f03fb8c73c26adeb5797220..efa41fc66c1ffda31e0c7667067c737ed6c17525 100644 (file)
@@ -2817,6 +2817,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
        u16 capab_info, status_code, aid;
        struct ieee802_11_elems elems;
+       int ac, uapsd_queues = -1;
        u8 *pos;
        bool reassoc;
        struct cfg80211_bss *bss;
@@ -2886,9 +2887,15 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
                 * is set can cause the interface to go idle
                 */
                ieee80211_destroy_assoc_data(sdata, true);
+
+               /* get uapsd queues configuration */
+               uapsd_queues = 0;
+               for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
+                       if (sdata->tx_conf[ac].uapsd)
+                               uapsd_queues |= BIT(ac);
        }
 
-       cfg80211_rx_assoc_resp(sdata->dev, bss, (u8 *)mgmt, len);
+       cfg80211_rx_assoc_resp(sdata->dev, bss, (u8 *)mgmt, len, uapsd_queues);
 }
 
 static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
index 369fc334fdadede142c86f9676dd752761d4f4c4..2c52b59e43f319670e6ce054b0eda1bde995ce1c 100644 (file)
@@ -19,7 +19,7 @@
 
 
 void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss,
-                           const u8 *buf, size_t len)
+                           const u8 *buf, size_t len, int uapsd_queues)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct wiphy *wiphy = wdev->wiphy;
@@ -43,7 +43,7 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss,
                return;
        }
 
-       nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL);
+       nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL, uapsd_queues);
        /* update current_bss etc., consumes the bss reference */
        __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
                                  status_code,
index ab7ee4893e40a3c386834c7ae5a5f371be22005b..e8114c7a37e35ba4314ca0ed8f78552e1b02589f 100644 (file)
@@ -10524,7 +10524,8 @@ nla_put_failure:
 static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
                                    struct net_device *netdev,
                                    const u8 *buf, size_t len,
-                                   enum nl80211_commands cmd, gfp_t gfp)
+                                   enum nl80211_commands cmd, gfp_t gfp,
+                                   int uapsd_queues)
 {
        struct sk_buff *msg;
        void *hdr;
@@ -10544,6 +10545,19 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
            nla_put(msg, NL80211_ATTR_FRAME, len, buf))
                goto nla_put_failure;
 
+       if (uapsd_queues >= 0) {
+               struct nlattr *nla_wmm =
+                       nla_nest_start(msg, NL80211_ATTR_STA_WME);
+               if (!nla_wmm)
+                       goto nla_put_failure;
+
+               if (nla_put_u8(msg, NL80211_STA_WME_UAPSD_QUEUES,
+                              uapsd_queues))
+                       goto nla_put_failure;
+
+               nla_nest_end(msg, nla_wmm);
+       }
+
        genlmsg_end(msg, hdr);
 
        genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
@@ -10560,15 +10574,15 @@ void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
                          size_t len, gfp_t gfp)
 {
        nl80211_send_mlme_event(rdev, netdev, buf, len,
-                               NL80211_CMD_AUTHENTICATE, gfp);
+                               NL80211_CMD_AUTHENTICATE, gfp, -1);
 }
 
 void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
                           struct net_device *netdev, const u8 *buf,
-                          size_t len, gfp_t gfp)
+                          size_t len, gfp_t gfp, int uapsd_queues)
 {
        nl80211_send_mlme_event(rdev, netdev, buf, len,
-                               NL80211_CMD_ASSOCIATE, gfp);
+                               NL80211_CMD_ASSOCIATE, gfp, uapsd_queues);
 }
 
 void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
@@ -10576,7 +10590,7 @@ void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
                         size_t len, gfp_t gfp)
 {
        nl80211_send_mlme_event(rdev, netdev, buf, len,
-                               NL80211_CMD_DEAUTHENTICATE, gfp);
+                               NL80211_CMD_DEAUTHENTICATE, gfp, -1);
 }
 
 void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
@@ -10584,7 +10598,7 @@ void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
                           size_t len, gfp_t gfp)
 {
        nl80211_send_mlme_event(rdev, netdev, buf, len,
-                               NL80211_CMD_DISASSOCIATE, gfp);
+                               NL80211_CMD_DISASSOCIATE, gfp, -1);
 }
 
 void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
@@ -10605,7 +10619,7 @@ void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
                cmd = NL80211_CMD_UNPROT_DISASSOCIATE;
 
        trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len);
-       nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC);
+       nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1);
 }
 EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt);
 
index 49c9a482dd1248565f0b7f333ecacf5f027ff650..7ad70d6f0cc699147e26c679c298d1200e182f1a 100644 (file)
@@ -23,7 +23,8 @@ void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
                          const u8 *buf, size_t len, gfp_t gfp);
 void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
                           struct net_device *netdev,
-                          const u8 *buf, size_t len, gfp_t gfp);
+                          const u8 *buf, size_t len, gfp_t gfp,
+                          int uapsd_queues);
 void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
                         struct net_device *netdev,
                         const u8 *buf, size_t len, gfp_t gfp);