| From 53d3fa613086f07f3091be45344cac70302932e0 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 3 Oct 2018 19:21:39 +0300 |
| Subject: brcmsmac: AP mode: update beacon when TIM changes |
| |
| From: Ali MJ Al-Nasrawy <alimjalnasrawy@gmail.com> |
| |
| [ Upstream commit 2258ee58baa554609a3cc3996276e4276f537b6d ] |
| |
| Beacons are not updated to reflect TIM changes. This is not compliant with |
| power-saving client stations as the beacons do not have valid TIM and can |
| cause the network to stall at random occasions and to have highly variable |
| latencies. |
| Fix it by updating beacon templates on mac80211 set_tim callback. |
| |
| Addresses an issue described in: |
| https://marc.info/?i=20180911163534.21312d08%20()%20manjaro |
| |
| Signed-off-by: Ali MJ Al-Nasrawy <alimjalnasrawy@gmail.com> |
| Signed-off-by: Kalle Valo <kvalo@codeaurora.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| .../broadcom/brcm80211/brcmsmac/mac80211_if.c | 26 +++++++++++++++++++ |
| .../broadcom/brcm80211/brcmsmac/main.h | 1 + |
| 2 files changed, 27 insertions(+) |
| |
| diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c |
| index 6255fb6d97a70..81ff558046a8f 100644 |
| --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c |
| +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c |
| @@ -502,6 +502,7 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
| } |
| |
| spin_lock_bh(&wl->lock); |
| + wl->wlc->vif = vif; |
| wl->mute_tx = false; |
| brcms_c_mute(wl->wlc, false); |
| if (vif->type == NL80211_IFTYPE_STATION) |
| @@ -519,6 +520,11 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
| static void |
| brcms_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
| { |
| + struct brcms_info *wl = hw->priv; |
| + |
| + spin_lock_bh(&wl->lock); |
| + wl->wlc->vif = NULL; |
| + spin_unlock_bh(&wl->lock); |
| } |
| |
| static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed) |
| @@ -937,6 +943,25 @@ static void brcms_ops_set_tsf(struct ieee80211_hw *hw, |
| spin_unlock_bh(&wl->lock); |
| } |
| |
| +static int brcms_ops_beacon_set_tim(struct ieee80211_hw *hw, |
| + struct ieee80211_sta *sta, bool set) |
| +{ |
| + struct brcms_info *wl = hw->priv; |
| + struct sk_buff *beacon = NULL; |
| + u16 tim_offset = 0; |
| + |
| + spin_lock_bh(&wl->lock); |
| + if (wl->wlc->vif) |
| + beacon = ieee80211_beacon_get_tim(hw, wl->wlc->vif, |
| + &tim_offset, NULL); |
| + if (beacon) |
| + brcms_c_set_new_beacon(wl->wlc, beacon, tim_offset, |
| + wl->wlc->vif->bss_conf.dtim_period); |
| + spin_unlock_bh(&wl->lock); |
| + |
| + return 0; |
| +} |
| + |
| static const struct ieee80211_ops brcms_ops = { |
| .tx = brcms_ops_tx, |
| .start = brcms_ops_start, |
| @@ -955,6 +980,7 @@ static const struct ieee80211_ops brcms_ops = { |
| .flush = brcms_ops_flush, |
| .get_tsf = brcms_ops_get_tsf, |
| .set_tsf = brcms_ops_set_tsf, |
| + .set_tim = brcms_ops_beacon_set_tim, |
| }; |
| |
| void brcms_dpc(unsigned long data) |
| diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.h |
| index c4d135cff04ad..9f76b880814e8 100644 |
| --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.h |
| +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.h |
| @@ -563,6 +563,7 @@ struct brcms_c_info { |
| |
| struct wiphy *wiphy; |
| struct scb pri_scb; |
| + struct ieee80211_vif *vif; |
| |
| struct sk_buff *beacon; |
| u16 beacon_tim_offset; |
| -- |
| 2.20.1 |
| |