From dd5eba1bb5b4f944a8fa4031645cbb2f854fdc92 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Mon, 27 Apr 2020 15:40:18 +0200 Subject: [PATCH] staging: wfx: fix support for AP that do not support PS-Poll MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit When multiple virtual interfaces (on different channels) are in use, the device ask to activate Power Save on station interfaces. The device developers recommends to use legacy PS-Poll in this case since it is the mode that disturb the less the other interface. However, some AP start to not answer anymore to PS-Poll. The device is able to detect this case and return a special warning in this case. So, this commit catch the warning and force usage of FastPS in this case. In order to confuse the less possible the other interface a small FastPS period is used (30ms). Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200427134031.323403-5-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_rx.c | 8 +++++++- drivers/staging/wfx/sta.c | 16 +++++++++++++++- drivers/staging/wfx/wfx.h | 2 ++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wfx/hif_rx.c b/drivers/staging/wfx/hif_rx.c index 6dbe289..a2ac6c0 100644 --- a/drivers/staging/wfx/hif_rx.c +++ b/drivers/staging/wfx/hif_rx.c @@ -176,7 +176,13 @@ static int hif_event_indication(struct wfx_dev *wdev, dev_dbg(wdev->dev, "ignore BSSREGAINED indication\n"); break; case HIF_EVENT_IND_PS_MODE_ERROR: - dev_warn(wdev->dev, "error while processing power save request\n"); + dev_warn(wdev->dev, "error while processing power save request: %d\n", + body->event_data.ps_mode_error); + if (body->event_data.ps_mode_error == + HIF_PS_ERROR_AP_NOT_RESP_TO_POLL) { + wvif->bss_not_support_ps_poll = true; + schedule_work(&wvif->update_pm_work); + } break; default: dev_warn(wdev->dev, "unhandled event indication: %.2x\n", diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 2262e1d..77d5ff1 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -205,7 +205,10 @@ static int wfx_update_pm(struct wfx_vif *wvif) if (chan0 && chan1 && chan0->hw_value != chan1->hw_value && wvif->vif->type != NL80211_IFTYPE_AP) { ps = true; - ps_timeout = 0; + if (wvif->bss_not_support_ps_poll) + ps_timeout = 30; + else + ps_timeout = 0; } if (!wait_for_completion_timeout(&wvif->set_pm_mode_complete, @@ -215,6 +218,14 @@ static int wfx_update_pm(struct wfx_vif *wvif) return hif_set_pm(wvif, ps, ps_timeout); } +static void wfx_update_pm_work(struct work_struct *work) +{ + struct wfx_vif *wvif = container_of(work, struct wfx_vif, + update_pm_work); + + wfx_update_pm(wvif); +} + int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, const struct ieee80211_tx_queue_params *params) { @@ -293,6 +304,7 @@ static void wfx_do_unjoin(struct wfx_vif *wvif) if (wvif_count(wvif->wdev) <= 1) hif_set_block_ack_policy(wvif, 0xFF, 0xFF); wfx_tx_unlock(wvif->wdev); + wvif->bss_not_support_ps_poll = false; cancel_delayed_work_sync(&wvif->beacon_loss_work); } @@ -453,6 +465,7 @@ void wfx_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) wfx_tx_policy_init(wvif); if (wvif_count(wvif->wdev) <= 1) hif_set_block_ack_policy(wvif, 0xFF, 0xFF); + wvif->bss_not_support_ps_poll = false; } static void wfx_join_finalize(struct wfx_vif *wvif, @@ -737,6 +750,7 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) init_completion(&wvif->set_pm_mode_complete); complete(&wvif->set_pm_mode_complete); + INIT_WORK(&wvif->update_pm_work, wfx_update_pm_work); INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work); mutex_init(&wvif->scan_lock); diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index 77bb6c6..c7a58ab 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -89,6 +89,8 @@ struct wfx_vif { bool scan_abort; struct ieee80211_scan_request *scan_req; + bool bss_not_support_ps_poll; + struct work_struct update_pm_work; struct completion set_pm_mode_complete; }; -- 2.7.4