]> git.karo-electronics.de Git - linux-beck.git/commitdiff
ath6kl: Fix AP mode connect event parsing and TIM updates
authorJouni Malinen <jouni@qca.qualcomm.com>
Mon, 5 Sep 2011 14:38:45 +0000 (17:38 +0300)
committerKalle Valo <kvalo@qca.qualcomm.com>
Tue, 6 Sep 2011 07:44:03 +0000 (10:44 +0300)
This cleans up the connect event parsing by defining a union in
struct wmi_connect_event to match with the three possible sets of
fields that the target uses depending on which type of connect
event is being indicated. In addition, two AP cases are now
separated from ath6kl_connect_event() so that correct field names
can be used to make it actually possible to understand what the
code is doing.

The bug hiding in the previous mess was in parsing the AID incorrectly
when processing the new station connecting event in AP mode. The fix
here for that is also fixing TIM updates for PS buffering to use the
correct AID.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/ath6kl/core.h
drivers/net/wireless/ath/ath6kl/main.c
drivers/net/wireless/ath/ath6kl/wmi.c
drivers/net/wireless/ath/ath6kl/wmi.h

index fdb796fe79b2b098a4275fc020554fbe9faa1815..054da13ce488e3973ba170806247b6c2979ec215 100644 (file)
@@ -560,6 +560,10 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel,
                          u16 beacon_int, enum network_type net_type,
                          u8 beacon_ie_len, u8 assoc_req_len,
                          u8 assoc_resp_len, u8 *assoc_info);
+void ath6kl_connect_ap_mode_bss(struct ath6kl *ar, u16 channel);
+void ath6kl_connect_ap_mode_sta(struct ath6kl *ar, u16 aid, u8 *mac_addr,
+                               u8 keymgmt, u8 ucipher, u8 auth,
+                               u8 assoc_req_len, u8 *assoc_info);
 void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason,
                             u8 *bssid, u8 assoc_resp_len,
                             u8 *assoc_info, u16 prot_reason_status);
index 3cefca65fc0c872adba4a6f6fb6f35a6e47277fb..d510046c99d60f12e5b003bda05bffa21dbc9329 100644 (file)
@@ -519,57 +519,55 @@ static void ath6kl_install_static_wep_keys(struct ath6kl *ar)
        }
 }
 
-static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid,
-                                  u16 listen_int, u16 beacon_int,
-                                  u8 assoc_req_len, u8 *assoc_info)
+void ath6kl_connect_ap_mode_bss(struct ath6kl *ar, u16 channel)
 {
-       struct net_device *dev = ar->net_dev;
-       u8 *ies = NULL, *wpa_ie = NULL, *pos;
-       size_t ies_len = 0;
-       struct station_info sinfo;
        struct ath6kl_req_key *ik;
        int res;
        u8 key_rsc[ATH6KL_KEY_SEQ_LEN];
 
-       if (memcmp(dev->dev_addr, bssid, ETH_ALEN) == 0) {
-               ik = &ar->ap_mode_bkey;
+       ik = &ar->ap_mode_bkey;
 
-               ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "AP mode started on %u MHz\n",
-                          channel);
+       ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "AP mode started on %u MHz\n", channel);
 
-               switch (ar->auth_mode) {
-               case NONE_AUTH:
-                       if (ar->prwise_crypto == WEP_CRYPT)
-                               ath6kl_install_static_wep_keys(ar);
+       switch (ar->auth_mode) {
+       case NONE_AUTH:
+               if (ar->prwise_crypto == WEP_CRYPT)
+                       ath6kl_install_static_wep_keys(ar);
+               break;
+       case WPA_PSK_AUTH:
+       case WPA2_PSK_AUTH:
+       case (WPA_PSK_AUTH | WPA2_PSK_AUTH):
+               if (!ik->valid)
                        break;
-               case WPA_PSK_AUTH:
-               case WPA2_PSK_AUTH:
-               case (WPA_PSK_AUTH|WPA2_PSK_AUTH):
-                       if (!ik->valid)
-                               break;
 
-                       ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed addkey for "
-                                  "the initial group key for AP mode\n");
-                       memset(key_rsc, 0, sizeof(key_rsc));
-                       res = ath6kl_wmi_addkey_cmd(
-                               ar->wmi, ik->key_index, ik->key_type,
-                               GROUP_USAGE, ik->key_len, key_rsc, ik->key,
-                               KEY_OP_INIT_VAL, NULL, SYNC_BOTH_WMIFLAG);
-                       if (res) {
-                               ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed "
-                                          "addkey failed: %d\n", res);
-                       }
-                       break;
+               ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed addkey for "
+                          "the initial group key for AP mode\n");
+               memset(key_rsc, 0, sizeof(key_rsc));
+               res = ath6kl_wmi_addkey_cmd(
+                       ar->wmi, ik->key_index, ik->key_type,
+                       GROUP_USAGE, ik->key_len, key_rsc, ik->key,
+                       KEY_OP_INIT_VAL, NULL, SYNC_BOTH_WMIFLAG);
+               if (res) {
+                       ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed "
+                                  "addkey failed: %d\n", res);
                }
-
-               ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0);
-               set_bit(CONNECTED, &ar->flag);
-               netif_carrier_on(ar->net_dev);
-               return;
+               break;
        }
 
-       ath6kl_dbg(ATH6KL_DBG_TRC, "new station %pM aid=%d\n",
-                  bssid, channel);
+       ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0);
+       set_bit(CONNECTED, &ar->flag);
+       netif_carrier_on(ar->net_dev);
+}
+
+void ath6kl_connect_ap_mode_sta(struct ath6kl *ar, u16 aid, u8 *mac_addr,
+                               u8 keymgmt, u8 ucipher, u8 auth,
+                               u8 assoc_req_len, u8 *assoc_info)
+{
+       u8 *ies = NULL, *wpa_ie = NULL, *pos;
+       size_t ies_len = 0;
+       struct station_info sinfo;
+
+       ath6kl_dbg(ATH6KL_DBG_TRC, "new station %pM aid=%d\n", mac_addr, aid);
 
        if (assoc_req_len > sizeof(struct ieee80211_hdr_3addr)) {
                struct ieee80211_mgmt *mgmt =
@@ -606,10 +604,9 @@ static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid,
                pos += 2 + pos[1];
        }
 
-       ath6kl_add_new_sta(ar, bssid, channel, wpa_ie,
+       ath6kl_add_new_sta(ar, mac_addr, aid, wpa_ie,
                           wpa_ie ? 2 + wpa_ie[1] : 0,
-                          listen_int & 0xFF, beacon_int,
-                          (listen_int >> 8) & 0xFF);
+                          keymgmt, ucipher, auth);
 
        /* send event to application */
        memset(&sinfo, 0, sizeof(sinfo));
@@ -620,11 +617,9 @@ static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid,
        sinfo.assoc_req_ies_len = ies_len;
        sinfo.filled |= STATION_INFO_ASSOC_REQ_IES;
 
-       cfg80211_new_sta(ar->net_dev, bssid, &sinfo, GFP_KERNEL);
+       cfg80211_new_sta(ar->net_dev, mac_addr, &sinfo, GFP_KERNEL);
 
        netif_wake_queue(ar->net_dev);
-
-       return;
 }
 
 /* Functions for Tx credit handling */
@@ -1030,13 +1025,6 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel, u8 *bssid,
 {
        unsigned long flags;
 
-       if (ar->nw_type == AP_NETWORK) {
-               ath6kl_connect_ap_mode(ar, channel, bssid, listen_int,
-                                      beacon_int, assoc_req_len,
-                                      assoc_info + beacon_ie_len);
-               return;
-       }
-
        ath6kl_cfg80211_connect_event(ar, channel, bssid,
                                      listen_int, beacon_int,
                                      net_type, beacon_ie_len,
index b2c5c40727fbeb430a5f637226f61ce4f164c3d2..b56830f6d4748c6d8f07d5763e63d0b72286d395 100644 (file)
@@ -699,14 +699,47 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len)
 {
        struct wmi_connect_event *ev;
        u8 *pie, *peie;
+       struct ath6kl *ar = wmi->parent_dev;
 
        if (len < sizeof(struct wmi_connect_event))
                return -EINVAL;
 
        ev = (struct wmi_connect_event *) datap;
 
+       if (ar->nw_type == AP_NETWORK) {
+               /* AP mode start/STA connected event */
+               struct net_device *dev = ar->net_dev;
+               if (memcmp(dev->dev_addr, ev->u.ap_bss.bssid, ETH_ALEN) == 0) {
+                       ath6kl_dbg(ATH6KL_DBG_WMI, "%s: freq %d bssid %pM "
+                                  "(AP started)\n",
+                                  __func__, le16_to_cpu(ev->u.ap_bss.ch),
+                                  ev->u.ap_bss.bssid);
+                       ath6kl_connect_ap_mode_bss(
+                               ar, le16_to_cpu(ev->u.ap_bss.ch));
+               } else {
+                       ath6kl_dbg(ATH6KL_DBG_WMI, "%s: aid %u mac_addr %pM "
+                                  "auth=%u keymgmt=%u cipher=%u apsd_info=%u "
+                                  "(STA connected)\n",
+                                  __func__, ev->u.ap_sta.aid,
+                                  ev->u.ap_sta.mac_addr,
+                                  ev->u.ap_sta.auth,
+                                  ev->u.ap_sta.keymgmt,
+                                  le16_to_cpu(ev->u.ap_sta.cipher),
+                                  ev->u.ap_sta.apsd_info);
+                       ath6kl_connect_ap_mode_sta(
+                               ar, ev->u.ap_sta.aid, ev->u.ap_sta.mac_addr,
+                               ev->u.ap_sta.keymgmt,
+                               le16_to_cpu(ev->u.ap_sta.cipher),
+                               ev->u.ap_sta.auth, ev->assoc_req_len,
+                               ev->assoc_info + ev->beacon_ie_len);
+               }
+               return 0;
+       }
+
+       /* STA/IBSS mode connection event */
+
        ath6kl_dbg(ATH6KL_DBG_WMI, "%s: freq %d bssid %pM\n",
-                  __func__, ev->ch, ev->bssid);
+                  __func__, le16_to_cpu(ev->u.sta.ch), ev->u.sta.bssid);
 
        /* Start of assoc rsp IEs */
        pie = ev->assoc_info + ev->beacon_ie_len +
@@ -735,10 +768,11 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len)
                pie += pie[1] + 2;
        }
 
-       ath6kl_connect_event(wmi->parent_dev, le16_to_cpu(ev->ch), ev->bssid,
-                            le16_to_cpu(ev->listen_intvl),
-                            le16_to_cpu(ev->beacon_intvl),
-                            le32_to_cpu(ev->nw_type),
+       ath6kl_connect_event(wmi->parent_dev, le16_to_cpu(ev->u.sta.ch),
+                            ev->u.sta.bssid,
+                            le16_to_cpu(ev->u.sta.listen_intvl),
+                            le16_to_cpu(ev->u.sta.beacon_intvl),
+                            le32_to_cpu(ev->u.sta.nw_type),
                             ev->beacon_ie_len, ev->assoc_req_len,
                             ev->assoc_resp_len, ev->assoc_info);
 
index e86b81d326eb352fa09dee6075b1ff2e3fbf652a..5ca8c8e904cf4eecc080e54a2fd69f1e725f0676 100644 (file)
@@ -1275,11 +1275,30 @@ struct wmi_ready_event_2 {
 
 /* Connect Event */
 struct wmi_connect_event {
-       __le16 ch;
-       u8 bssid[ETH_ALEN];
-       __le16 listen_intvl;
-       __le16 beacon_intvl;
-       __le32 nw_type;
+       union {
+               struct {
+                       __le16 ch;
+                       u8 bssid[ETH_ALEN];
+                       __le16 listen_intvl;
+                       __le16 beacon_intvl;
+                       __le32 nw_type;
+               } sta;
+               struct {
+                       u8 phymode;
+                       u8 aid;
+                       u8 mac_addr[ETH_ALEN];
+                       u8 auth;
+                       u8 keymgmt;
+                       __le16 cipher;
+                       u8 apsd_info;
+                       u8 unused[3];
+               } ap_sta;
+               struct {
+                       __le16 ch;
+                       u8 bssid[ETH_ALEN];
+                       u8 unused[8];
+               } ap_bss;
+       } u;
        u8 beacon_ie_len;
        u8 assoc_req_len;
        u8 assoc_resp_len;