aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <jouni@qca.qualcomm.com>2011-09-05 10:38:45 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2011-09-06 03:44:03 -0400
commit572e27c00c9d1250ae2b4951eae7e73992174138 (patch)
tree6ce0dd1956526dc3990c37987983c433e9314371
parentd6e51e6a0cc50b6dd8d9f3a733427cca3f9afdee (diff)
ath6kl: Fix AP mode connect event parsing and TIM updates
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>
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h4
-rw-r--r--drivers/net/wireless/ath/ath6kl/main.c92
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.c44
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.h29
4 files changed, 107 insertions, 62 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index fdb796fe79b2..054da13ce488 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -560,6 +560,10 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel,
560 u16 beacon_int, enum network_type net_type, 560 u16 beacon_int, enum network_type net_type,
561 u8 beacon_ie_len, u8 assoc_req_len, 561 u8 beacon_ie_len, u8 assoc_req_len,
562 u8 assoc_resp_len, u8 *assoc_info); 562 u8 assoc_resp_len, u8 *assoc_info);
563void ath6kl_connect_ap_mode_bss(struct ath6kl *ar, u16 channel);
564void ath6kl_connect_ap_mode_sta(struct ath6kl *ar, u16 aid, u8 *mac_addr,
565 u8 keymgmt, u8 ucipher, u8 auth,
566 u8 assoc_req_len, u8 *assoc_info);
563void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, 567void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason,
564 u8 *bssid, u8 assoc_resp_len, 568 u8 *bssid, u8 assoc_resp_len,
565 u8 *assoc_info, u16 prot_reason_status); 569 u8 *assoc_info, u16 prot_reason_status);
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index 3cefca65fc0c..d510046c99d6 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -519,57 +519,55 @@ static void ath6kl_install_static_wep_keys(struct ath6kl *ar)
519 } 519 }
520} 520}
521 521
522static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid, 522void ath6kl_connect_ap_mode_bss(struct ath6kl *ar, u16 channel)
523 u16 listen_int, u16 beacon_int,
524 u8 assoc_req_len, u8 *assoc_info)
525{ 523{
526 struct net_device *dev = ar->net_dev;
527 u8 *ies = NULL, *wpa_ie = NULL, *pos;
528 size_t ies_len = 0;
529 struct station_info sinfo;
530 struct ath6kl_req_key *ik; 524 struct ath6kl_req_key *ik;
531 int res; 525 int res;
532 u8 key_rsc[ATH6KL_KEY_SEQ_LEN]; 526 u8 key_rsc[ATH6KL_KEY_SEQ_LEN];
533 527
534 if (memcmp(dev->dev_addr, bssid, ETH_ALEN) == 0) { 528 ik = &ar->ap_mode_bkey;
535 ik = &ar->ap_mode_bkey;
536 529
537 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "AP mode started on %u MHz\n", 530 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "AP mode started on %u MHz\n", channel);
538 channel);
539 531
540 switch (ar->auth_mode) { 532 switch (ar->auth_mode) {
541 case NONE_AUTH: 533 case NONE_AUTH:
542 if (ar->prwise_crypto == WEP_CRYPT) 534 if (ar->prwise_crypto == WEP_CRYPT)
543 ath6kl_install_static_wep_keys(ar); 535 ath6kl_install_static_wep_keys(ar);
536 break;
537 case WPA_PSK_AUTH:
538 case WPA2_PSK_AUTH:
539 case (WPA_PSK_AUTH | WPA2_PSK_AUTH):
540 if (!ik->valid)
544 break; 541 break;
545 case WPA_PSK_AUTH:
546 case WPA2_PSK_AUTH:
547 case (WPA_PSK_AUTH|WPA2_PSK_AUTH):
548 if (!ik->valid)
549 break;
550 542
551 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed addkey for " 543 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed addkey for "
552 "the initial group key for AP mode\n"); 544 "the initial group key for AP mode\n");
553 memset(key_rsc, 0, sizeof(key_rsc)); 545 memset(key_rsc, 0, sizeof(key_rsc));
554 res = ath6kl_wmi_addkey_cmd( 546 res = ath6kl_wmi_addkey_cmd(
555 ar->wmi, ik->key_index, ik->key_type, 547 ar->wmi, ik->key_index, ik->key_type,
556 GROUP_USAGE, ik->key_len, key_rsc, ik->key, 548 GROUP_USAGE, ik->key_len, key_rsc, ik->key,
557 KEY_OP_INIT_VAL, NULL, SYNC_BOTH_WMIFLAG); 549 KEY_OP_INIT_VAL, NULL, SYNC_BOTH_WMIFLAG);
558 if (res) { 550 if (res) {
559 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed " 551 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed "
560 "addkey failed: %d\n", res); 552 "addkey failed: %d\n", res);
561 }
562 break;
563 } 553 }
564 554 break;
565 ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0);
566 set_bit(CONNECTED, &ar->flag);
567 netif_carrier_on(ar->net_dev);
568 return;
569 } 555 }
570 556
571 ath6kl_dbg(ATH6KL_DBG_TRC, "new station %pM aid=%d\n", 557 ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0);
572 bssid, channel); 558 set_bit(CONNECTED, &ar->flag);
559 netif_carrier_on(ar->net_dev);
560}
561
562void ath6kl_connect_ap_mode_sta(struct ath6kl *ar, u16 aid, u8 *mac_addr,
563 u8 keymgmt, u8 ucipher, u8 auth,
564 u8 assoc_req_len, u8 *assoc_info)
565{
566 u8 *ies = NULL, *wpa_ie = NULL, *pos;
567 size_t ies_len = 0;
568 struct station_info sinfo;
569
570 ath6kl_dbg(ATH6KL_DBG_TRC, "new station %pM aid=%d\n", mac_addr, aid);
573 571
574 if (assoc_req_len > sizeof(struct ieee80211_hdr_3addr)) { 572 if (assoc_req_len > sizeof(struct ieee80211_hdr_3addr)) {
575 struct ieee80211_mgmt *mgmt = 573 struct ieee80211_mgmt *mgmt =
@@ -606,10 +604,9 @@ static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid,
606 pos += 2 + pos[1]; 604 pos += 2 + pos[1];
607 } 605 }
608 606
609 ath6kl_add_new_sta(ar, bssid, channel, wpa_ie, 607 ath6kl_add_new_sta(ar, mac_addr, aid, wpa_ie,
610 wpa_ie ? 2 + wpa_ie[1] : 0, 608 wpa_ie ? 2 + wpa_ie[1] : 0,
611 listen_int & 0xFF, beacon_int, 609 keymgmt, ucipher, auth);
612 (listen_int >> 8) & 0xFF);
613 610
614 /* send event to application */ 611 /* send event to application */
615 memset(&sinfo, 0, sizeof(sinfo)); 612 memset(&sinfo, 0, sizeof(sinfo));
@@ -620,11 +617,9 @@ static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid,
620 sinfo.assoc_req_ies_len = ies_len; 617 sinfo.assoc_req_ies_len = ies_len;
621 sinfo.filled |= STATION_INFO_ASSOC_REQ_IES; 618 sinfo.filled |= STATION_INFO_ASSOC_REQ_IES;
622 619
623 cfg80211_new_sta(ar->net_dev, bssid, &sinfo, GFP_KERNEL); 620 cfg80211_new_sta(ar->net_dev, mac_addr, &sinfo, GFP_KERNEL);
624 621
625 netif_wake_queue(ar->net_dev); 622 netif_wake_queue(ar->net_dev);
626
627 return;
628} 623}
629 624
630/* Functions for Tx credit handling */ 625/* Functions for Tx credit handling */
@@ -1030,13 +1025,6 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel, u8 *bssid,
1030{ 1025{
1031 unsigned long flags; 1026 unsigned long flags;
1032 1027
1033 if (ar->nw_type == AP_NETWORK) {
1034 ath6kl_connect_ap_mode(ar, channel, bssid, listen_int,
1035 beacon_int, assoc_req_len,
1036 assoc_info + beacon_ie_len);
1037 return;
1038 }
1039
1040 ath6kl_cfg80211_connect_event(ar, channel, bssid, 1028 ath6kl_cfg80211_connect_event(ar, channel, bssid,
1041 listen_int, beacon_int, 1029 listen_int, beacon_int,
1042 net_type, beacon_ie_len, 1030 net_type, beacon_ie_len,
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index b2c5c40727fb..b56830f6d474 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -699,14 +699,47 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len)
699{ 699{
700 struct wmi_connect_event *ev; 700 struct wmi_connect_event *ev;
701 u8 *pie, *peie; 701 u8 *pie, *peie;
702 struct ath6kl *ar = wmi->parent_dev;
702 703
703 if (len < sizeof(struct wmi_connect_event)) 704 if (len < sizeof(struct wmi_connect_event))
704 return -EINVAL; 705 return -EINVAL;
705 706
706 ev = (struct wmi_connect_event *) datap; 707 ev = (struct wmi_connect_event *) datap;
707 708
709 if (ar->nw_type == AP_NETWORK) {
710 /* AP mode start/STA connected event */
711 struct net_device *dev = ar->net_dev;
712 if (memcmp(dev->dev_addr, ev->u.ap_bss.bssid, ETH_ALEN) == 0) {
713 ath6kl_dbg(ATH6KL_DBG_WMI, "%s: freq %d bssid %pM "
714 "(AP started)\n",
715 __func__, le16_to_cpu(ev->u.ap_bss.ch),
716 ev->u.ap_bss.bssid);
717 ath6kl_connect_ap_mode_bss(
718 ar, le16_to_cpu(ev->u.ap_bss.ch));
719 } else {
720 ath6kl_dbg(ATH6KL_DBG_WMI, "%s: aid %u mac_addr %pM "
721 "auth=%u keymgmt=%u cipher=%u apsd_info=%u "
722 "(STA connected)\n",
723 __func__, ev->u.ap_sta.aid,
724 ev->u.ap_sta.mac_addr,
725 ev->u.ap_sta.auth,
726 ev->u.ap_sta.keymgmt,
727 le16_to_cpu(ev->u.ap_sta.cipher),
728 ev->u.ap_sta.apsd_info);
729 ath6kl_connect_ap_mode_sta(
730 ar, ev->u.ap_sta.aid, ev->u.ap_sta.mac_addr,
731 ev->u.ap_sta.keymgmt,
732 le16_to_cpu(ev->u.ap_sta.cipher),
733 ev->u.ap_sta.auth, ev->assoc_req_len,
734 ev->assoc_info + ev->beacon_ie_len);
735 }
736 return 0;
737 }
738
739 /* STA/IBSS mode connection event */
740
708 ath6kl_dbg(ATH6KL_DBG_WMI, "%s: freq %d bssid %pM\n", 741 ath6kl_dbg(ATH6KL_DBG_WMI, "%s: freq %d bssid %pM\n",
709 __func__, ev->ch, ev->bssid); 742 __func__, le16_to_cpu(ev->u.sta.ch), ev->u.sta.bssid);
710 743
711 /* Start of assoc rsp IEs */ 744 /* Start of assoc rsp IEs */
712 pie = ev->assoc_info + ev->beacon_ie_len + 745 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)
735 pie += pie[1] + 2; 768 pie += pie[1] + 2;
736 } 769 }
737 770
738 ath6kl_connect_event(wmi->parent_dev, le16_to_cpu(ev->ch), ev->bssid, 771 ath6kl_connect_event(wmi->parent_dev, le16_to_cpu(ev->u.sta.ch),
739 le16_to_cpu(ev->listen_intvl), 772 ev->u.sta.bssid,
740 le16_to_cpu(ev->beacon_intvl), 773 le16_to_cpu(ev->u.sta.listen_intvl),
741 le32_to_cpu(ev->nw_type), 774 le16_to_cpu(ev->u.sta.beacon_intvl),
775 le32_to_cpu(ev->u.sta.nw_type),
742 ev->beacon_ie_len, ev->assoc_req_len, 776 ev->beacon_ie_len, ev->assoc_req_len,
743 ev->assoc_resp_len, ev->assoc_info); 777 ev->assoc_resp_len, ev->assoc_info);
744 778
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index e86b81d326eb..5ca8c8e904cf 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -1275,11 +1275,30 @@ struct wmi_ready_event_2 {
1275 1275
1276/* Connect Event */ 1276/* Connect Event */
1277struct wmi_connect_event { 1277struct wmi_connect_event {
1278 __le16 ch; 1278 union {
1279 u8 bssid[ETH_ALEN]; 1279 struct {
1280 __le16 listen_intvl; 1280 __le16 ch;
1281 __le16 beacon_intvl; 1281 u8 bssid[ETH_ALEN];
1282 __le32 nw_type; 1282 __le16 listen_intvl;
1283 __le16 beacon_intvl;
1284 __le32 nw_type;
1285 } sta;
1286 struct {
1287 u8 phymode;
1288 u8 aid;
1289 u8 mac_addr[ETH_ALEN];
1290 u8 auth;
1291 u8 keymgmt;
1292 __le16 cipher;
1293 u8 apsd_info;
1294 u8 unused[3];
1295 } ap_sta;
1296 struct {
1297 __le16 ch;
1298 u8 bssid[ETH_ALEN];
1299 u8 unused[8];
1300 } ap_bss;
1301 } u;
1283 u8 beacon_ie_len; 1302 u8 beacon_ie_len;
1284 u8 assoc_req_len; 1303 u8 assoc_req_len;
1285 u8 assoc_resp_len; 1304 u8 assoc_resp_len;