wlcore: save seq num only between recoveries

We want seq num (freed_pkts) to be initialized
on each new connection, but keep persistent
between recoveries/suspends.

Save the freed_pkts in the private block of the
sta struct (we already do a similar thing for
AP's stations).

However, keep the old wlvif->total_freed_pkts
in order to avoid too intrusive change.

Signed-off-by: Eliad Peller <eliad@wizery.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Eliad Peller 2014-07-11 03:01:26 +03:00 committed by John W. Linville
parent 72fcd3d16c
commit 50d26aa338
3 changed files with 68 additions and 31 deletions

View File

@ -372,9 +372,8 @@ void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
wl1271_tx_reset_link_queues(wl, *hlid);
wl->links[*hlid].wlvif = NULL;
if (wlvif->bss_type == BSS_TYPE_STA_BSS ||
(wlvif->bss_type == BSS_TYPE_AP_BSS &&
*hlid == wlvif->ap.bcast_hlid)) {
if (wlvif->bss_type == BSS_TYPE_AP_BSS &&
*hlid == wlvif->ap.bcast_hlid) {
/*
* save the total freed packets in the wlvif, in case this is
* recovery or suspend

View File

@ -898,6 +898,41 @@ out:
wlcore_set_partition(wl, &old_part);
}
static void wlcore_save_freed_pkts(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8 hlid, struct ieee80211_sta *sta)
{
struct wl1271_station *wl_sta;
wl_sta = (void *)sta->drv_priv;
wl_sta->total_freed_pkts = wl->links[hlid].total_freed_pkts;
/*
* increment the initial seq number on recovery to account for
* transmitted packets that we haven't yet got in the FW status
*/
if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
wl_sta->total_freed_pkts +=
WL1271_TX_SQN_POST_RECOVERY_PADDING;
}
static void wlcore_save_freed_pkts_addr(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
u8 hlid, const u8 *addr)
{
struct ieee80211_sta *sta;
struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
if (WARN_ON(hlid == WL12XX_INVALID_LINK_ID ||
is_zero_ether_addr(addr)))
return;
rcu_read_lock();
sta = ieee80211_find_sta(vif, addr);
if (sta)
wlcore_save_freed_pkts(wl, wlvif, hlid, sta);
rcu_read_unlock();
}
static void wlcore_print_recovery(struct wl1271 *wl)
{
u32 pc = 0;
@ -961,6 +996,13 @@ static void wl1271_recovery_work(struct work_struct *work)
wlvif = list_first_entry(&wl->wlvif_list,
struct wl12xx_vif, list);
vif = wl12xx_wlvif_to_vif(wlvif);
if (wlvif->bss_type == BSS_TYPE_STA_BSS &&
test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) {
wlcore_save_freed_pkts_addr(wl, wlvif, wlvif->sta.hlid,
vif->bss_conf.bssid);
}
__wl1271_op_remove_interface(wl, vif, false);
}
@ -4703,10 +4745,6 @@ static int wl1271_allocate_sta(struct wl1271 *wl,
void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid)
{
struct wl1271_station *wl_sta;
struct ieee80211_sta *sta;
struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
if (!test_bit(hlid, wlvif->ap.sta_hlid_map))
return;
@ -4718,21 +4756,7 @@ void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid)
* save the last used PN in the private part of iee80211_sta,
* in case of recovery/suspend
*/
rcu_read_lock();
sta = ieee80211_find_sta(vif, wl->links[hlid].addr);
if (sta) {
wl_sta = (void *)sta->drv_priv;
wl_sta->total_freed_pkts = wl->links[hlid].total_freed_pkts;
/*
* increment the initial seq number on recovery to account for
* transmitted packets that we haven't yet got in the FW status
*/
if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
wl_sta->total_freed_pkts +=
WL1271_TX_SQN_POST_RECOVERY_PADDING;
}
rcu_read_unlock();
wlcore_save_freed_pkts_addr(wl, wlvif, hlid, wl->links[hlid].addr);
wl12xx_free_link(wl, wlvif, &hlid);
wl->active_sta_count--;
@ -4915,6 +4939,21 @@ static int wl12xx_update_sta_state(struct wl1271 *wl,
clear_bit(WLVIF_FLAG_STA_STATE_SENT, &wlvif->flags);
}
/* save seq number on disassoc (suspend) */
if (is_sta &&
old_state == IEEE80211_STA_ASSOC &&
new_state == IEEE80211_STA_AUTH) {
wlcore_save_freed_pkts(wl, wlvif, wlvif->sta.hlid, sta);
wlvif->total_freed_pkts = 0;
}
/* restore seq number on assoc (resume) */
if (is_sta &&
old_state == IEEE80211_STA_AUTH &&
new_state == IEEE80211_STA_ASSOC) {
wlvif->total_freed_pkts = wl_sta->total_freed_pkts;
}
/* clear ROCs on failure or authorization */
if (is_sta &&
(new_state == IEEE80211_STA_AUTHORIZED ||

View File

@ -324,6 +324,7 @@ struct wl1271_station {
* total freed FW packets on the link to the STA - used for tracking the
* AES/TKIP PN across recoveries. Re-initialized each time from the
* wl1271_station structure.
* Used in both AP and STA mode.
*/
u64 total_freed_pkts;
};
@ -459,6 +460,13 @@ struct wl12xx_vif {
/* work for canceling ROC after pending auth reply */
struct delayed_work pending_auth_complete_work;
/*
* total freed FW packets on the link.
* For STA this holds the PN of the link to the AP.
* For AP this holds the PN of the broadcast link.
*/
u64 total_freed_pkts;
/*
* This struct must be last!
* data that has to be saved acrossed reconfigs (e.g. recovery)
@ -466,15 +474,6 @@ struct wl12xx_vif {
*/
struct {
u8 persistent[0];
/*
* total freed FW packets on the link - used for
* storing the AES/TKIP PN during recovery, as this
* structure is not zeroed out.
* For STA this holds the PN of the link to the AP.
* For AP this holds the PN of the broadcast link.
*/
u64 total_freed_pkts;
};
};