summaryrefslogtreecommitdiffstats
path: root/drivers/staging/wfx/sta.c
diff options
context:
space:
mode:
authorJérôme Pouiller <jerome.pouiller@silabs.com>2020-01-15 13:55:25 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-01-16 20:59:52 +0100
commita3c529a835890b0eecd324d9f0c37c67345f84e2 (patch)
tree6fe2feabcbb779233a3c2314d8d73abd781d3145 /drivers/staging/wfx/sta.c
parent22c03264e5a914966c93baa367d63eb77f60ebaf (diff)
staging: wfx: simplify handling of IEEE80211_TX_CTL_SEND_AFTER_DTIM
When mac80211 ask for a frame to be sent after a DTIM, driver should: 1. Update TIM with multicast bit set (using update_ie). This function can be called whenever. 2. Keep buffered all frames marked "after dtim" 3. When it receive a suspend_resume indication (see wfx_suspend_resume_mc()), send all the buffered frames. This indication is sent by the firmware 4ms before the dtim. 4. If one of the frames returns status "REQUEUE", it means that the DTIM period was ended before to be able to send the frame. 5. When all the buffered frames were sent or if DTIM period was ended, driver should update the TIM with multicast bit reset. All the mess with the asynchronous works can be dropped. Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com> Link: https://lore.kernel.org/r/20200115135338.14374-58-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/wfx/sta.c')
-rw-r--r--drivers/staging/wfx/sta.c78
1 files changed, 6 insertions, 72 deletions
diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c
index bdc15554958c..a9b58e4a9fa3 100644
--- a/drivers/staging/wfx/sta.c
+++ b/drivers/staging/wfx/sta.c
@@ -851,16 +851,12 @@ static void wfx_ps_notify_sta(struct wfx_vif *wvif,
switch (notify_cmd) {
case STA_NOTIFY_SLEEP:
if (!prev) {
- if (wvif->mcast_buffered && !wvif->sta_asleep_mask)
- schedule_work(&wvif->mcast_start_work);
wvif->sta_asleep_mask |= bit;
}
break;
case STA_NOTIFY_AWAKE:
if (prev) {
wvif->sta_asleep_mask &= ~bit;
- if (!wvif->sta_asleep_mask)
- schedule_work(&wvif->mcast_stop_work);
wfx_bh_request_tx(wvif->wdev);
}
break;
@@ -898,7 +894,7 @@ static int wfx_update_tim(struct wfx_vif *wvif)
tim_ptr[2] = 0;
/* Set/reset aid0 bit */
- if (wvif->aid0_bit_set)
+ if (wfx_tx_queues_get_after_dtim(wvif))
tim_ptr[4] |= 1;
else
tim_ptr[4] &= ~1;
@@ -927,47 +923,12 @@ int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
return 0;
}
-static void wfx_mcast_start_work(struct work_struct *work)
-{
- struct wfx_vif *wvif =
- container_of(work, struct wfx_vif, mcast_start_work);
- struct ieee80211_bss_conf *conf = &wvif->vif->bss_conf;
- long tmo = conf->dtim_period * TU_TO_JIFFIES(wvif->beacon_int + 20);
-
- cancel_work_sync(&wvif->mcast_stop_work);
- if (!wvif->aid0_bit_set) {
- wfx_tx_lock_flush(wvif->wdev);
- wvif->aid0_bit_set = true;
- wfx_update_tim(wvif);
- mod_timer(&wvif->mcast_timeout, jiffies + tmo);
- wfx_tx_unlock(wvif->wdev);
- }
-}
-
-static void wfx_mcast_stop_work(struct work_struct *work)
-{
- struct wfx_vif *wvif = container_of(work, struct wfx_vif,
- mcast_stop_work);
-
- if (wvif->aid0_bit_set) {
- del_timer_sync(&wvif->mcast_timeout);
- wfx_tx_lock_flush(wvif->wdev);
- wvif->aid0_bit_set = false;
- wfx_update_tim(wvif);
- wfx_tx_unlock(wvif->wdev);
- }
-}
-
-static void wfx_mcast_timeout(struct timer_list *t)
+void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd)
{
- struct wfx_vif *wvif = from_timer(wvif, t, mcast_timeout);
-
- dev_warn(wvif->wdev->dev, "multicast delivery timeout\n");
- spin_lock_bh(&wvif->ps_state_lock);
- wvif->mcast_tx = wvif->aid0_bit_set && wvif->mcast_buffered;
- if (wvif->mcast_tx)
- wfx_bh_request_tx(wvif->wdev);
- spin_unlock_bh(&wvif->ps_state_lock);
+ WARN(!wfx_tx_queues_get_after_dtim(wvif), "incorrect sequence");
+ WARN(wvif->after_dtim_tx_allowed, "incorrect sequence");
+ wvif->after_dtim_tx_allowed = true;
+ wfx_bh_request_tx(wvif->wdev);
}
int wfx_ampdu_action(struct ieee80211_hw *hw,
@@ -985,25 +946,6 @@ int wfx_ampdu_action(struct ieee80211_hw *hw,
return -ENOTSUPP;
}
-void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd)
-{
- bool cancel_tmo = false;
-
- spin_lock_bh(&wvif->ps_state_lock);
- if (notify_cmd == STA_NOTIFY_SLEEP)
- wvif->mcast_tx = false;
- else
- wvif->mcast_tx = wvif->aid0_bit_set &&
- wvif->mcast_buffered;
- if (wvif->mcast_tx) {
- cancel_tmo = true;
- wfx_bh_request_tx(wvif->wdev);
- }
- spin_unlock_bh(&wvif->ps_state_lock);
- if (cancel_tmo)
- del_timer_sync(&wvif->mcast_timeout);
-}
-
int wfx_add_chanctx(struct ieee80211_hw *hw,
struct ieee80211_chanctx_conf *conf)
{
@@ -1090,10 +1032,6 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
spin_lock_init(&wvif->ps_state_lock);
INIT_WORK(&wvif->update_tim_work, wfx_update_tim_work);
- INIT_WORK(&wvif->mcast_start_work, wfx_mcast_start_work);
- INIT_WORK(&wvif->mcast_stop_work, wfx_mcast_stop_work);
- timer_setup(&wvif->mcast_timeout, wfx_mcast_timeout, 0);
-
memset(&wvif->bss_params, 0, sizeof(wvif->bss_params));
mutex_init(&wvif->bss_loss_lock);
@@ -1156,9 +1094,6 @@ void wfx_remove_interface(struct ieee80211_hw *hw,
break;
case WFX_STATE_AP:
wvif->sta_asleep_mask = 0;
- wvif->mcast_tx = false;
- wvif->aid0_bit_set = false;
- wvif->mcast_buffered = false;
/* reset.link_id = 0; */
hif_reset(wvif, false);
break;
@@ -1175,7 +1110,6 @@ void wfx_remove_interface(struct ieee80211_hw *hw,
wfx_cqm_bssloss_sm(wvif, 0, 0, 0);
cancel_work_sync(&wvif->unjoin_work);
- del_timer_sync(&wvif->mcast_timeout);
wfx_free_event_queue(wvif);
wdev->vif[wvif->id] = NULL;