Commit 572e27c0 authored by Jouni Malinen's avatar Jouni Malinen Committed by Kalle Valo

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: default avatarJouni Malinen <jouni@qca.qualcomm.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent d6e51e6a
...@@ -560,6 +560,10 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel, ...@@ -560,6 +560,10 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel,
u16 beacon_int, enum network_type net_type, u16 beacon_int, enum network_type net_type,
u8 beacon_ie_len, u8 assoc_req_len, u8 beacon_ie_len, u8 assoc_req_len,
u8 assoc_resp_len, u8 *assoc_info); 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, void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason,
u8 *bssid, u8 assoc_resp_len, u8 *bssid, u8 assoc_resp_len,
u8 *assoc_info, u16 prot_reason_status); u8 *assoc_info, u16 prot_reason_status);
......
...@@ -519,23 +519,15 @@ static void ath6kl_install_static_wep_keys(struct ath6kl *ar) ...@@ -519,23 +519,15 @@ static void ath6kl_install_static_wep_keys(struct ath6kl *ar)
} }
} }
static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid, void ath6kl_connect_ap_mode_bss(struct ath6kl *ar, u16 channel)
u16 listen_int, u16 beacon_int,
u8 assoc_req_len, u8 *assoc_info)
{ {
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; struct ath6kl_req_key *ik;
int res; int res;
u8 key_rsc[ATH6KL_KEY_SEQ_LEN]; 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", ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "AP mode started on %u MHz\n", channel);
channel);
switch (ar->auth_mode) { switch (ar->auth_mode) {
case NONE_AUTH: case NONE_AUTH:
...@@ -544,7 +536,7 @@ static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid, ...@@ -544,7 +536,7 @@ static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid,
break; break;
case WPA_PSK_AUTH: case WPA_PSK_AUTH:
case WPA2_PSK_AUTH: case WPA2_PSK_AUTH:
case (WPA_PSK_AUTH|WPA2_PSK_AUTH): case (WPA_PSK_AUTH | WPA2_PSK_AUTH):
if (!ik->valid) if (!ik->valid)
break; break;
...@@ -565,11 +557,17 @@ static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid, ...@@ -565,11 +557,17 @@ static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid,
ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0); ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0);
set_bit(CONNECTED, &ar->flag); set_bit(CONNECTED, &ar->flag);
netif_carrier_on(ar->net_dev); netif_carrier_on(ar->net_dev);
return; }
}
ath6kl_dbg(ATH6KL_DBG_TRC, "new station %pM aid=%d\n", void ath6kl_connect_ap_mode_sta(struct ath6kl *ar, u16 aid, u8 *mac_addr,
bssid, channel); 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)) { if (assoc_req_len > sizeof(struct ieee80211_hdr_3addr)) {
struct ieee80211_mgmt *mgmt = struct ieee80211_mgmt *mgmt =
...@@ -606,10 +604,9 @@ static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid, ...@@ -606,10 +604,9 @@ static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid,
pos += 2 + pos[1]; 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, wpa_ie ? 2 + wpa_ie[1] : 0,
listen_int & 0xFF, beacon_int, keymgmt, ucipher, auth);
(listen_int >> 8) & 0xFF);
/* send event to application */ /* send event to application */
memset(&sinfo, 0, sizeof(sinfo)); memset(&sinfo, 0, sizeof(sinfo));
...@@ -620,11 +617,9 @@ static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid, ...@@ -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.assoc_req_ies_len = ies_len;
sinfo.filled |= STATION_INFO_ASSOC_REQ_IES; 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); netif_wake_queue(ar->net_dev);
return;
} }
/* Functions for Tx credit handling */ /* Functions for Tx credit handling */
...@@ -1030,13 +1025,6 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel, u8 *bssid, ...@@ -1030,13 +1025,6 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel, u8 *bssid,
{ {
unsigned long flags; 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, ath6kl_cfg80211_connect_event(ar, channel, bssid,
listen_int, beacon_int, listen_int, beacon_int,
net_type, beacon_ie_len, net_type, beacon_ie_len,
......
...@@ -699,14 +699,47 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len) ...@@ -699,14 +699,47 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len)
{ {
struct wmi_connect_event *ev; struct wmi_connect_event *ev;
u8 *pie, *peie; u8 *pie, *peie;
struct ath6kl *ar = wmi->parent_dev;
if (len < sizeof(struct wmi_connect_event)) if (len < sizeof(struct wmi_connect_event))
return -EINVAL; return -EINVAL;
ev = (struct wmi_connect_event *) datap; 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", 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 */ /* Start of assoc rsp IEs */
pie = ev->assoc_info + ev->beacon_ie_len + 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,10 +768,11 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len)
pie += pie[1] + 2; pie += pie[1] + 2;
} }
ath6kl_connect_event(wmi->parent_dev, le16_to_cpu(ev->ch), ev->bssid, ath6kl_connect_event(wmi->parent_dev, le16_to_cpu(ev->u.sta.ch),
le16_to_cpu(ev->listen_intvl), ev->u.sta.bssid,
le16_to_cpu(ev->beacon_intvl), le16_to_cpu(ev->u.sta.listen_intvl),
le32_to_cpu(ev->nw_type), 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->beacon_ie_len, ev->assoc_req_len,
ev->assoc_resp_len, ev->assoc_info); ev->assoc_resp_len, ev->assoc_info);
......
...@@ -1275,11 +1275,30 @@ struct wmi_ready_event_2 { ...@@ -1275,11 +1275,30 @@ struct wmi_ready_event_2 {
/* Connect Event */ /* Connect Event */
struct wmi_connect_event { struct wmi_connect_event {
union {
struct {
__le16 ch; __le16 ch;
u8 bssid[ETH_ALEN]; u8 bssid[ETH_ALEN];
__le16 listen_intvl; __le16 listen_intvl;
__le16 beacon_intvl; __le16 beacon_intvl;
__le32 nw_type; __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 beacon_ie_len;
u8 assoc_req_len; u8 assoc_req_len;
u8 assoc_resp_len; u8 assoc_resp_len;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment