aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2013-03-12 11:19:44 -0400
committerLuciano Coelho <coelho@ti.com>2013-03-25 06:33:12 -0400
commit0e752df6fda25993acc30e1162808fbb2543be03 (patch)
treede0faa9284fada9d779975ab24c511400caf0de8
parent5a99610c99625ae86d76014da25659dff72e8792 (diff)
wlcore: AP-mode - recover security seq num for stations
Save the sequence number of the broadcast AP link in the wlvif. For each connected station, save the sequence number in the drv_priv part of ieee80211_sta. Use the saved numbers on recovery/resume, with the obligatory increment on recovery. Signed-off-by: Arik Nemtsov <arik@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.c8
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c28
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore_i.h9
3 files changed, 44 insertions, 1 deletions
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index 56d248a0acc1..c9e060795d13 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -366,7 +366,9 @@ void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
366 wl1271_tx_reset_link_queues(wl, *hlid); 366 wl1271_tx_reset_link_queues(wl, *hlid);
367 wl->links[*hlid].wlvif = NULL; 367 wl->links[*hlid].wlvif = NULL;
368 368
369 if (wlvif->bss_type != BSS_TYPE_AP_BSS) { 369 if (wlvif->bss_type == BSS_TYPE_STA_BSS ||
370 (wlvif->bss_type == BSS_TYPE_AP_BSS &&
371 *hlid == wlvif->ap.bcast_hlid)) {
370 /* 372 /*
371 * save the total freed packets in the wlvif, in case this is 373 * save the total freed packets in the wlvif, in case this is
372 * recovery or suspend 374 * recovery or suspend
@@ -635,6 +637,10 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)
635 if (ret < 0) 637 if (ret < 0)
636 goto out_free_global; 638 goto out_free_global;
637 639
640 /* use the previous security seq, if this is a recovery/resume */
641 wl->links[wlvif->ap.bcast_hlid].total_freed_pkts =
642 wlvif->total_freed_pkts;
643
638 cmd->role_id = wlvif->role_id; 644 cmd->role_id = wlvif->role_id;
639 cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); 645 cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period);
640 cmd->ap.bss_index = WL1271_AP_BSS_INDEX; 646 cmd->ap.bss_index = WL1271_AP_BSS_INDEX;
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 4da558460449..43865d1348ec 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -4505,6 +4505,9 @@ static int wl1271_allocate_sta(struct wl1271 *wl,
4505 return -EBUSY; 4505 return -EBUSY;
4506 } 4506 }
4507 4507
4508 /* use the previous security seq, if this is a recovery/resume */
4509 wl->links[wl_sta->hlid].total_freed_pkts = wl_sta->total_freed_pkts;
4510
4508 set_bit(wl_sta->hlid, wlvif->ap.sta_hlid_map); 4511 set_bit(wl_sta->hlid, wlvif->ap.sta_hlid_map);
4509 memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN); 4512 memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN);
4510 wl->active_sta_count++; 4513 wl->active_sta_count++;
@@ -4513,12 +4516,37 @@ static int wl1271_allocate_sta(struct wl1271 *wl,
4513 4516
4514void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid) 4517void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid)
4515{ 4518{
4519 struct wl1271_station *wl_sta;
4520 struct ieee80211_sta *sta;
4521 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
4522
4516 if (!test_bit(hlid, wlvif->ap.sta_hlid_map)) 4523 if (!test_bit(hlid, wlvif->ap.sta_hlid_map))
4517 return; 4524 return;
4518 4525
4519 clear_bit(hlid, wlvif->ap.sta_hlid_map); 4526 clear_bit(hlid, wlvif->ap.sta_hlid_map);
4520 __clear_bit(hlid, &wl->ap_ps_map); 4527 __clear_bit(hlid, &wl->ap_ps_map);
4521 __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); 4528 __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
4529
4530 /*
4531 * save the last used PN in the private part of iee80211_sta,
4532 * in case of recovery/suspend
4533 */
4534 rcu_read_lock();
4535 sta = ieee80211_find_sta(vif, wl->links[hlid].addr);
4536 if (sta) {
4537 wl_sta = (void *)sta->drv_priv;
4538 wl_sta->total_freed_pkts = wl->links[hlid].total_freed_pkts;
4539
4540 /*
4541 * increment the initial seq number on recovery to account for
4542 * transmitted packets that we haven't yet got in the FW status
4543 */
4544 if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
4545 wl_sta->total_freed_pkts +=
4546 WL1271_TX_SQN_POST_RECOVERY_PADDING;
4547 }
4548 rcu_read_unlock();
4549
4522 wl12xx_free_link(wl, wlvif, &hlid); 4550 wl12xx_free_link(wl, wlvif, &hlid);
4523 wl->active_sta_count--; 4551 wl->active_sta_count--;
4524 4552
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index 47d2f6000a42..7b55ef9c4288 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -325,6 +325,13 @@ struct wl12xx_rx_filter {
325struct wl1271_station { 325struct wl1271_station {
326 u8 hlid; 326 u8 hlid;
327 bool in_connection; 327 bool in_connection;
328
329 /*
330 * total freed FW packets on the link to the STA - used for tracking the
331 * AES/TKIP PN across recoveries. Re-initialized each time from the
332 * wl1271_station structure.
333 */
334 u64 total_freed_pkts;
328}; 335};
329 336
330struct wl12xx_vif { 337struct wl12xx_vif {
@@ -461,6 +468,8 @@ struct wl12xx_vif {
461 * total freed FW packets on the link - used for 468 * total freed FW packets on the link - used for
462 * storing the AES/TKIP PN during recovery, as this 469 * storing the AES/TKIP PN during recovery, as this
463 * structure is not zeroed out. 470 * structure is not zeroed out.
471 * For STA this holds the PN of the link to the AP.
472 * For AP this holds the PN of the broadcast link.
464 */ 473 */
465 u64 total_freed_pkts; 474 u64 total_freed_pkts;
466 }; 475 };