Commit 50d26aa3 authored by Eliad Peller's avatar Eliad Peller Committed by John W. Linville

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: default avatarEliad Peller <eliad@wizery.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 72fcd3d1
...@@ -372,9 +372,8 @@ void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) ...@@ -372,9 +372,8 @@ void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
wl1271_tx_reset_link_queues(wl, *hlid); wl1271_tx_reset_link_queues(wl, *hlid);
wl->links[*hlid].wlvif = NULL; wl->links[*hlid].wlvif = NULL;
if (wlvif->bss_type == BSS_TYPE_STA_BSS || if (wlvif->bss_type == BSS_TYPE_AP_BSS &&
(wlvif->bss_type == BSS_TYPE_AP_BSS && *hlid == wlvif->ap.bcast_hlid) {
*hlid == wlvif->ap.bcast_hlid)) {
/* /*
* save the total freed packets in the wlvif, in case this is * save the total freed packets in the wlvif, in case this is
* recovery or suspend * recovery or suspend
......
...@@ -898,6 +898,41 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) ...@@ -898,6 +898,41 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
wlcore_set_partition(wl, &old_part); 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) static void wlcore_print_recovery(struct wl1271 *wl)
{ {
u32 pc = 0; u32 pc = 0;
...@@ -961,6 +996,13 @@ static void wl1271_recovery_work(struct work_struct *work) ...@@ -961,6 +996,13 @@ static void wl1271_recovery_work(struct work_struct *work)
wlvif = list_first_entry(&wl->wlvif_list, wlvif = list_first_entry(&wl->wlvif_list,
struct wl12xx_vif, list); struct wl12xx_vif, list);
vif = wl12xx_wlvif_to_vif(wlvif); 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); __wl1271_op_remove_interface(wl, vif, false);
} }
...@@ -4703,10 +4745,6 @@ static int wl1271_allocate_sta(struct wl1271 *wl, ...@@ -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) 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)) if (!test_bit(hlid, wlvif->ap.sta_hlid_map))
return; return;
...@@ -4718,21 +4756,7 @@ void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid) ...@@ -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, * save the last used PN in the private part of iee80211_sta,
* in case of recovery/suspend * in case of recovery/suspend
*/ */
rcu_read_lock(); wlcore_save_freed_pkts_addr(wl, wlvif, hlid, wl->links[hlid].addr);
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();
wl12xx_free_link(wl, wlvif, &hlid); wl12xx_free_link(wl, wlvif, &hlid);
wl->active_sta_count--; wl->active_sta_count--;
...@@ -4915,6 +4939,21 @@ static int wl12xx_update_sta_state(struct wl1271 *wl, ...@@ -4915,6 +4939,21 @@ static int wl12xx_update_sta_state(struct wl1271 *wl,
clear_bit(WLVIF_FLAG_STA_STATE_SENT, &wlvif->flags); 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 */ /* clear ROCs on failure or authorization */
if (is_sta && if (is_sta &&
(new_state == IEEE80211_STA_AUTHORIZED || (new_state == IEEE80211_STA_AUTHORIZED ||
......
...@@ -324,6 +324,7 @@ struct wl1271_station { ...@@ -324,6 +324,7 @@ struct wl1271_station {
* total freed FW packets on the link to the STA - used for tracking the * 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 * AES/TKIP PN across recoveries. Re-initialized each time from the
* wl1271_station structure. * wl1271_station structure.
* Used in both AP and STA mode.
*/ */
u64 total_freed_pkts; u64 total_freed_pkts;
}; };
...@@ -459,6 +460,13 @@ struct wl12xx_vif { ...@@ -459,6 +460,13 @@ struct wl12xx_vif {
/* work for canceling ROC after pending auth reply */ /* work for canceling ROC after pending auth reply */
struct delayed_work pending_auth_complete_work; 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! * This struct must be last!
* data that has to be saved acrossed reconfigs (e.g. recovery) * data that has to be saved acrossed reconfigs (e.g. recovery)
...@@ -466,15 +474,6 @@ struct wl12xx_vif { ...@@ -466,15 +474,6 @@ struct wl12xx_vif {
*/ */
struct { struct {
u8 persistent[0]; 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;
}; };
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment