staging: wfx: use ieee80211_beacon_loss() provided by mac80211
The firmware is able to filter beacons and send a notification if one or multiple beacons are not received. Note that it send this notification only once. Only if it receive beacons gain, it send a new notification. Currently, the driver handle the connection loss itself (see wfx_cqm_bssloss_sm()). It send null frames and watch the answers. This patch fixes all this mess: - settle firmware to send a notification on the first beacon loss - call ieee80211_beacon_loss() and let mac80211 handle all the process - since we do have notification for each beacon loss, add a period task that call ieee80211_beacon_loss() until we receive "REGAIN" notification. Thus, we can drop the ugly wfx_cqm_bssloss_sm() and wfx_bss_params_work(). Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com> Link: https://lore.kernel.org/r/20200420160311.57323-3-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
13fe5a59b3
commit
5a0af69888
@ -547,9 +547,6 @@ void wfx_tx_confirm_cb(struct wfx_vif *wvif, const struct hif_cnf_tx *arg)
|
||||
memset(tx_info->pad, 0, sizeof(tx_info->pad));
|
||||
|
||||
if (!arg->status) {
|
||||
if (wvif->bss_loss_state &&
|
||||
arg->packet_id == wvif->bss_loss_confirm_id)
|
||||
wfx_cqm_bssloss_sm(wvif, 0, 1, 0);
|
||||
tx_info->status.tx_time =
|
||||
arg->media_delay - arg->tx_queue_delay;
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
|
||||
@ -563,10 +560,6 @@ void wfx_tx_confirm_cb(struct wfx_vif *wvif, const struct hif_cnf_tx *arg)
|
||||
schedule_work(&wvif->update_tim_work);
|
||||
}
|
||||
tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
|
||||
} else {
|
||||
if (wvif->bss_loss_state &&
|
||||
arg->packet_id == wvif->bss_loss_confirm_id)
|
||||
wfx_cqm_bssloss_sm(wvif, 0, 0, 1);
|
||||
}
|
||||
wfx_skb_dtor(wvif->wdev, skb);
|
||||
}
|
||||
|
@ -266,17 +266,6 @@ static bool wfx_handle_tx_data(struct wfx_dev *wdev, struct sk_buff *skb)
|
||||
if (!wvif)
|
||||
return false;
|
||||
|
||||
// FIXME: mac80211 is smart enough to handle BSS loss. Driver should not
|
||||
// try to do anything about that.
|
||||
if (ieee80211_is_nullfunc(frame->frame_control)) {
|
||||
mutex_lock(&wvif->bss_loss_lock);
|
||||
if (wvif->bss_loss_state) {
|
||||
wvif->bss_loss_confirm_id = req->packet_id;
|
||||
req->queue_id.queue_id = HIF_QUEUE_ID_VOICE;
|
||||
}
|
||||
mutex_unlock(&wvif->bss_loss_lock);
|
||||
}
|
||||
|
||||
// FIXME: identify the exact scenario matched by this condition. Does it
|
||||
// happen yet?
|
||||
if (ieee80211_has_protected(frame->frame_control) &&
|
||||
|
@ -59,60 +59,6 @@ static void wfx_free_event_queue(struct wfx_vif *wvif)
|
||||
__wfx_free_event_queue(&list);
|
||||
}
|
||||
|
||||
void wfx_cqm_bssloss_sm(struct wfx_vif *wvif, int init, int good, int bad)
|
||||
{
|
||||
int tx = 0;
|
||||
|
||||
mutex_lock(&wvif->bss_loss_lock);
|
||||
cancel_work_sync(&wvif->bss_params_work);
|
||||
|
||||
if (init) {
|
||||
schedule_delayed_work(&wvif->bss_loss_work, HZ);
|
||||
wvif->bss_loss_state = 0;
|
||||
|
||||
if (!atomic_read(&wvif->wdev->tx_lock))
|
||||
tx = 1;
|
||||
} else if (good) {
|
||||
cancel_delayed_work_sync(&wvif->bss_loss_work);
|
||||
wvif->bss_loss_state = 0;
|
||||
schedule_work(&wvif->bss_params_work);
|
||||
} else if (bad) {
|
||||
/* FIXME Should we just keep going until we time out? */
|
||||
if (wvif->bss_loss_state < 3)
|
||||
tx = 1;
|
||||
} else {
|
||||
cancel_delayed_work_sync(&wvif->bss_loss_work);
|
||||
wvif->bss_loss_state = 0;
|
||||
}
|
||||
|
||||
/* Spit out a NULL packet to our AP if necessary */
|
||||
// FIXME: call ieee80211_beacon_loss/ieee80211_connection_loss instead
|
||||
if (tx) {
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_tx_control control = { };
|
||||
|
||||
wvif->bss_loss_state++;
|
||||
|
||||
skb = ieee80211_nullfunc_get(wvif->wdev->hw, wvif->vif, false);
|
||||
if (!skb)
|
||||
goto end;
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
memset(IEEE80211_SKB_CB(skb), 0,
|
||||
sizeof(*IEEE80211_SKB_CB(skb)));
|
||||
IEEE80211_SKB_CB(skb)->control.vif = wvif->vif;
|
||||
IEEE80211_SKB_CB(skb)->driver_rates[0].idx = 0;
|
||||
IEEE80211_SKB_CB(skb)->driver_rates[0].count = 1;
|
||||
IEEE80211_SKB_CB(skb)->driver_rates[1].idx = -1;
|
||||
rcu_read_lock(); // protect control.sta
|
||||
control.sta = ieee80211_find_sta(wvif->vif, hdr->addr1);
|
||||
wfx_tx(wvif->wdev->hw, &control, skb);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
end:
|
||||
mutex_unlock(&wvif->bss_loss_lock);
|
||||
}
|
||||
|
||||
static void wfx_filter_beacon(struct wfx_vif *wvif, bool filter_beacon)
|
||||
{
|
||||
const struct hif_ie_table_entry filter_ies[] = {
|
||||
@ -339,6 +285,17 @@ static void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi)
|
||||
ieee80211_cqm_rssi_notify(wvif->vif, cqm_evt, rcpi_rssi, GFP_KERNEL);
|
||||
}
|
||||
|
||||
static void wfx_beacon_loss_work(struct work_struct *work)
|
||||
{
|
||||
struct wfx_vif *wvif = container_of(to_delayed_work(work),
|
||||
struct wfx_vif, beacon_loss_work);
|
||||
struct ieee80211_bss_conf *bss_conf = &wvif->vif->bss_conf;
|
||||
|
||||
ieee80211_beacon_loss(wvif->vif);
|
||||
schedule_delayed_work(to_delayed_work(work),
|
||||
msecs_to_jiffies(bss_conf->beacon_int));
|
||||
}
|
||||
|
||||
static void wfx_event_handler_work(struct work_struct *work)
|
||||
{
|
||||
struct wfx_vif *wvif =
|
||||
@ -354,12 +311,10 @@ static void wfx_event_handler_work(struct work_struct *work)
|
||||
list_for_each_entry(event, &list, link) {
|
||||
switch (event->evt.event_id) {
|
||||
case HIF_EVENT_IND_BSSLOST:
|
||||
mutex_lock(&wvif->scan_lock);
|
||||
wfx_cqm_bssloss_sm(wvif, 1, 0, 0);
|
||||
mutex_unlock(&wvif->scan_lock);
|
||||
schedule_delayed_work(&wvif->beacon_loss_work, 0);
|
||||
break;
|
||||
case HIF_EVENT_IND_BSSREGAINED:
|
||||
wfx_cqm_bssloss_sm(wvif, 0, 0, 0);
|
||||
cancel_delayed_work(&wvif->beacon_loss_work);
|
||||
break;
|
||||
case HIF_EVENT_IND_RCPI_RSSI:
|
||||
wfx_event_report_rssi(wvif,
|
||||
@ -379,26 +334,6 @@ static void wfx_event_handler_work(struct work_struct *work)
|
||||
__wfx_free_event_queue(&list);
|
||||
}
|
||||
|
||||
static void wfx_bss_loss_work(struct work_struct *work)
|
||||
{
|
||||
struct wfx_vif *wvif = container_of(work, struct wfx_vif,
|
||||
bss_loss_work.work);
|
||||
|
||||
ieee80211_connection_loss(wvif->vif);
|
||||
}
|
||||
|
||||
static void wfx_bss_params_work(struct work_struct *work)
|
||||
{
|
||||
struct wfx_vif *wvif = container_of(work, struct wfx_vif,
|
||||
bss_params_work);
|
||||
|
||||
mutex_lock(&wvif->wdev->conf_mutex);
|
||||
wvif->bss_params.bss_flags.lost_count_only = 1;
|
||||
hif_set_bss_params(wvif, &wvif->bss_params);
|
||||
wvif->bss_params.bss_flags.lost_count_only = 0;
|
||||
mutex_unlock(&wvif->wdev->conf_mutex);
|
||||
}
|
||||
|
||||
// Call it with wdev->conf_mutex locked
|
||||
static void wfx_do_unjoin(struct wfx_vif *wvif)
|
||||
{
|
||||
@ -418,10 +353,10 @@ static void wfx_do_unjoin(struct wfx_vif *wvif)
|
||||
hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
|
||||
wfx_free_event_queue(wvif);
|
||||
cancel_work_sync(&wvif->event_handler_work);
|
||||
wfx_cqm_bssloss_sm(wvif, 0, 0, 0);
|
||||
|
||||
memset(&wvif->bss_params, 0, sizeof(wvif->bss_params));
|
||||
wfx_tx_unlock(wvif->wdev);
|
||||
cancel_delayed_work_sync(&wvif->beacon_loss_work);
|
||||
}
|
||||
|
||||
static void wfx_set_mfp(struct wfx_vif *wvif,
|
||||
@ -615,9 +550,9 @@ static void wfx_join_finalize(struct wfx_vif *wvif,
|
||||
else
|
||||
hif_dual_cts_protection(wvif, false);
|
||||
|
||||
wfx_cqm_bssloss_sm(wvif, 0, 0, 0);
|
||||
|
||||
wvif->bss_params.beacon_lost_count = 20;
|
||||
// beacon_loss_count is defined to 7 in net/mac80211/mlme.c. Let's use
|
||||
// the same value.
|
||||
wvif->bss_params.beacon_lost_count = 7;
|
||||
wvif->bss_params.aid = info->aid;
|
||||
|
||||
hif_set_association_mode(wvif, info);
|
||||
@ -904,12 +839,10 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
|
||||
wvif->link_id_map = 1; // link-id 0 is reserved for multicast
|
||||
INIT_WORK(&wvif->update_tim_work, wfx_update_tim_work);
|
||||
INIT_DELAYED_WORK(&wvif->beacon_loss_work, wfx_beacon_loss_work);
|
||||
|
||||
memset(&wvif->bss_params, 0, sizeof(wvif->bss_params));
|
||||
|
||||
mutex_init(&wvif->bss_loss_lock);
|
||||
INIT_DELAYED_WORK(&wvif->bss_loss_work, wfx_bss_loss_work);
|
||||
|
||||
wvif->wep_default_key_id = -1;
|
||||
INIT_WORK(&wvif->wep_key_work, wfx_wep_key_work);
|
||||
|
||||
@ -919,7 +852,6 @@ 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->bss_params_work, wfx_bss_params_work);
|
||||
INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work);
|
||||
|
||||
mutex_init(&wvif->scan_lock);
|
||||
@ -974,8 +906,8 @@ void wfx_remove_interface(struct ieee80211_hw *hw,
|
||||
/* FIXME: In add to reset MAC address, try to reset interface */
|
||||
hif_set_macaddr(wvif, NULL);
|
||||
|
||||
wfx_cqm_bssloss_sm(wvif, 0, 0, 0);
|
||||
wfx_free_event_queue(wvif);
|
||||
cancel_delayed_work_sync(&wvif->beacon_loss_work);
|
||||
|
||||
wdev->vif[wvif->id] = NULL;
|
||||
wvif->vif = NULL;
|
||||
|
@ -81,7 +81,6 @@ void wfx_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd cmd);
|
||||
|
||||
// Other Helpers
|
||||
void wfx_cqm_bssloss_sm(struct wfx_vif *wvif, int init, int good, int bad);
|
||||
u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates);
|
||||
|
||||
#endif /* WFX_STA_H */
|
||||
|
@ -69,14 +69,10 @@ struct wfx_vif {
|
||||
int id;
|
||||
enum wfx_state state;
|
||||
|
||||
int bss_loss_state;
|
||||
u32 bss_loss_confirm_id;
|
||||
struct mutex bss_loss_lock;
|
||||
struct delayed_work bss_loss_work;
|
||||
|
||||
u32 link_id_map;
|
||||
|
||||
bool after_dtim_tx_allowed;
|
||||
struct delayed_work beacon_loss_work;
|
||||
|
||||
s8 wep_default_key_id;
|
||||
struct sk_buff *wep_pending_skb;
|
||||
@ -92,7 +88,6 @@ struct wfx_vif {
|
||||
|
||||
unsigned long uapsd_mask;
|
||||
struct hif_req_set_bss_params bss_params;
|
||||
struct work_struct bss_params_work;
|
||||
|
||||
int join_complete_status;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user