From 8afd2cd9b130fe69d29342f5986bb0e5defe512b Mon Sep 17 00:00:00 2001 From: Lior David Date: Wed, 20 Nov 2019 18:53:47 +0200 Subject: [PATCH 1/3] wil6210: fix update SSID when changing beacon The change_beacon cfg80211 operation can be used to change the SSID by specifying a different SSID in the probe response and association response IEs. However the current driver implementation does not update the firmware properly, as a result it causes association requests to fail. Fix this by extracting the SSID from the probe response IE and if it was changed, update the firmware properly. Change-Id: I8513c315b02b79bd2e29826672fd53b3a56ded91 Signed-off-by: Lior David --- drivers/net/wireless/ath/wil6210/cfg80211.c | 37 +++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index dd0bdae7b3e2..5cef9206daaa 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -2336,6 +2336,11 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy, struct wil6210_vif *vif = ndev_to_vif(ndev); int rc; u32 privacy = 0; + u16 len = 0, proberesp_len = 0; + u8 *ies = NULL, *proberesp; + bool ssid_changed = false; + const u8 *ie; + wil_dbg_misc(wil, "change_beacon, mid=%d\n", vif->mid); wil_print_bcon_data(bcon); @@ -2348,6 +2353,27 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy, memcpy(vif->ssid, wdev->ssid, wdev->ssid_len); vif->ssid_len = wdev->ssid_len; + /* extract updated SSID from the probe response IE */ + proberesp = _wil_cfg80211_get_proberesp_ies(bcon->probe_resp, + bcon->probe_resp_len, + &proberesp_len); + rc = _wil_cfg80211_merge_extra_ies(proberesp, + proberesp_len, + bcon->proberesp_ies, + bcon->proberesp_ies_len, + &ies, &len); + + if (!rc) { + ie = cfg80211_find_ie(WLAN_EID_SSID, ies, len); + if (ie && ie[1] <= IEEE80211_MAX_SSID_LEN) + if (ie[1] != vif->ssid_len || + memcmp(&ie[2], vif->ssid, ie[1])) { + memcpy(vif->ssid, &ie[2], ie[1]); + vif->ssid_len = ie[1]; + ssid_changed = true; + } + } + /* in case privacy has changed, need to restart the AP */ if (vif->privacy != privacy) { wil_dbg_misc(wil, "privacy changed %d=>%d. Restarting AP\n", @@ -2361,9 +2387,20 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy, vif->hidden_ssid, vif->pbss); } else { + if (ssid_changed) { + rc = wmi_set_ssid(vif, vif->ssid_len, vif->ssid); + if (rc) + goto out; + } rc = _wil_cfg80211_set_ies(vif, bcon); } + if (ssid_changed) { + wdev->ssid_len = vif->ssid_len; + memcpy(wdev->ssid, vif->ssid, vif->ssid_len); + } + +out: return rc; } From 9c6eb35345cbde31e375986f2bf3251ca922f310 Mon Sep 17 00:00:00 2001 From: Alexei Avshalom Lazar Date: Sun, 1 Dec 2019 10:10:01 +0200 Subject: [PATCH 2/3] wil6210: allow disabling EDMG through force_edmg_channel debugfs EDMG feature can be controlled through force_edmg_channel debugfs but cannot be disabled. Add support for disabling EDMG feature by setting force_edmg_channel = 255. Change-Id: I2cfc242e82ad8eb28f895cf537352de1265c65ec Signed-off-by: Alexei Avshalom Lazar --- drivers/net/wireless/ath/wil6210/cfg80211.c | 5 +++++ drivers/net/wireless/ath/wil6210/wil6210.h | 1 + 2 files changed, 6 insertions(+) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 5cef9206daaa..92d1fcdad680 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -34,6 +34,8 @@ */ #define WIL_EDMG_CHANNELS (BIT(0) | BIT(1) | BIT(2) | BIT(3)) +#define WIL_DISABLE_EDMG 255 + bool disable_ap_sme; module_param(disable_ap_sme, bool, 0444); MODULE_PARM_DESC(disable_ap_sme, " let user space handle AP mode SME"); @@ -594,6 +596,9 @@ int wil_spec2wmi_ch(u8 spec_ch, u8 *wmi_ch) case 12: *wmi_ch = WMI_CHANNEL_12; break; + case WIL_DISABLE_EDMG: + *wmi_ch = 0; + break; default: return -EINVAL; } diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 8454c662f861..9deeb3dec992 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -1049,6 +1049,7 @@ struct wil6210_priv { u8 wakeup_trigger; struct wil_suspend_stats suspend_stats; struct wil_debugfs_data dbg_data; + /* set to WIL_EDMG_DISABLE to force disable EDMG */ u8 force_edmg_channel; bool tx_latency; /* collect TX latency measurements */ size_t tx_latency_res; /* bin resolution in usec */ From b5eee425b4b8dca8240b1fd4a423d26c9afaa8b0 Mon Sep 17 00:00:00 2001 From: Alexei Avshalom Lazar Date: Sun, 22 Dec 2019 11:41:56 +0200 Subject: [PATCH 3/3] wil6210: notify cfg80211_new_sta upon connection before init tx ring In AP mode upon client connection, sometimes Rx data packet (e.g EAPOL) arrives before driver notify cfg80211_new_sta to kernel. This causes the Rx packet to get lost. To fix this, as part of connect event handling, call cfg80211_new_sta() earlier, before initializing Tx ring. Change-Id: Ife5fd7a5c79da4c0dd094c2b9cbc3785a165331d Signed-off-by: Alexei Avshalom Lazar --- drivers/net/wireless/ath/wil6210/wmi.c | 40 +++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 1aed102c2734..6040b5c1a1e8 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -1069,6 +1069,24 @@ static void wmi_evt_connect(struct wil6210_vif *vif, int id, void *d, int len) mutex_unlock(&wil->mutex); return; } + + sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL); + if (!sinfo) { + wmi_disconnect_sta(vif, wil->sta[evt->cid].addr, + WLAN_REASON_UNSPECIFIED, false); + rc = -ENOMEM; + goto out; + } + + sinfo->generation = wil->sinfo_gen++; + + if (assoc_req_ie) { + sinfo->assoc_req_ies = assoc_req_ie; + sinfo->assoc_req_ies_len = assoc_req_ielen; + } + + cfg80211_new_sta(ndev, evt->bssid, sinfo, GFP_KERNEL); + kfree(sinfo); } ether_addr_copy(wil->sta[evt->cid].addr, evt->bssid); @@ -1111,28 +1129,10 @@ static void wmi_evt_connect(struct wil6210_vif *vif, int id, void *d, int len) (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { if (rc) { - if (disable_ap_sme) - /* notify new_sta has failed */ - cfg80211_del_sta(ndev, evt->bssid, GFP_KERNEL); + /* notify new_sta has failed */ + cfg80211_del_sta(ndev, evt->bssid, GFP_KERNEL); goto out; } - - sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL); - if (!sinfo) { - rc = -ENOMEM; - goto out; - } - - sinfo->generation = wil->sinfo_gen++; - - if (assoc_req_ie) { - sinfo->assoc_req_ies = assoc_req_ie; - sinfo->assoc_req_ies_len = assoc_req_ielen; - } - - cfg80211_new_sta(ndev, evt->bssid, sinfo, GFP_KERNEL); - - kfree(sinfo); } else { wil_err(wil, "unhandled iftype %d for CID %d\n", wdev->iftype, evt->cid);