| From 83e37e0bdd1470bbe6612250b745ad39b1a7b130 Mon Sep 17 00:00:00 2001 |
| From: Rakesh Pillai <pillair@codeaurora.org> |
| Date: Fri, 15 Feb 2019 14:16:02 +0530 |
| Subject: mac80211: Restore vif beacon interval if start ap fails |
| |
| From: Rakesh Pillai <pillair@codeaurora.org> |
| |
| commit 83e37e0bdd1470bbe6612250b745ad39b1a7b130 upstream. |
| |
| The starting of AP interface can fail due to invalid |
| beacon interval, which does not match the minimum gcd |
| requirement set by the wifi driver. In such case, the |
| beacon interval of that interface gets updated with |
| that invalid beacon interval. |
| |
| The next time that interface is brought up in AP mode, |
| an interface combination check is performed and the |
| beacon interval is taken from the previously set value. |
| |
| In a case where an invalid beacon interval, i.e. a beacon |
| interval value which does not satisfy the minimum gcd criteria |
| set by the driver, is set, all the subsequent trials to |
| bring that interface in AP mode will fail, even if the |
| subsequent trials have a valid beacon interval. |
| |
| To avoid this, in case of a failure in bringing up an |
| interface in AP mode due to interface combination error, |
| the interface beacon interval which is stored in bss |
| conf, needs to be restored with the last working value |
| of beacon interval. |
| |
| Tested on ath10k using WCN3990. |
| |
| Cc: stable@vger.kernel.org |
| Fixes: 0c317a02ca98 ("cfg80211: support virtual interfaces with different beacon intervals") |
| Signed-off-by: Rakesh Pillai <pillair@codeaurora.org> |
| Signed-off-by: Johannes Berg <johannes.berg@intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| net/mac80211/cfg.c | 6 +++++- |
| 1 file changed, 5 insertions(+), 1 deletion(-) |
| |
| --- a/net/mac80211/cfg.c |
| +++ b/net/mac80211/cfg.c |
| @@ -941,6 +941,7 @@ static int ieee80211_start_ap(struct wip |
| BSS_CHANGED_P2P_PS | |
| BSS_CHANGED_TXPOWER; |
| int err; |
| + int prev_beacon_int; |
| |
| old = sdata_dereference(sdata->u.ap.beacon, sdata); |
| if (old) |
| @@ -963,6 +964,7 @@ static int ieee80211_start_ap(struct wip |
| |
| sdata->needed_rx_chains = sdata->local->rx_chains; |
| |
| + prev_beacon_int = sdata->vif.bss_conf.beacon_int; |
| sdata->vif.bss_conf.beacon_int = params->beacon_interval; |
| |
| if (params->he_cap) |
| @@ -974,8 +976,10 @@ static int ieee80211_start_ap(struct wip |
| if (!err) |
| ieee80211_vif_copy_chanctx_to_vlans(sdata, false); |
| mutex_unlock(&local->mtx); |
| - if (err) |
| + if (err) { |
| + sdata->vif.bss_conf.beacon_int = prev_beacon_int; |
| return err; |
| + } |
| |
| /* |
| * Apply control port protocol, this allows us to |