summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ti/wlcore/main.c
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2013-03-12 15:19:38 (GMT)
committerLuciano Coelho <coelho@ti.com>2013-03-25 10:33:11 (GMT)
commit93d5d10085ad7bf89a9e36c6ba117b9afe2de823 (patch)
tree4ef67a73a231870c71121e0fb8a9316ba54f34b3 /drivers/net/wireless/ti/wlcore/main.c
parent2fec3d27660fe4fe140374cd7d84ec799f3ebb15 (diff)
downloadlinux-93d5d10085ad7bf89a9e36c6ba117b9afe2de823.tar.xz
wlcore: consolidate tx_seq handling on recovery
Accumulate the total number of sent packets per-link to find out how far the encryption sequence number has progressed. Use this number as the initial security sequence number after recovery. This consolidates security sequence handling for both chip families, as we no longer have to rely on 12xx specific Tx completion. A fortunate side effect of this is correct management of seq numbers for AP roles and multi-role scenarios. When a link is removed we save the last seq number on a persistent part of the wlvif. This helps the data survive through recoveries/suspends, which also entail changes in the hlid of the link. This functionality is STA only currently. Signed-off-by: Arik Nemtsov <arik@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net/wireless/ti/wlcore/main.c')
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c55
1 files changed, 28 insertions, 27 deletions
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index c3e2471..c1a60cd 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -418,13 +418,21 @@ static int wlcore_fw_status(struct wl1271 *wl,
for_each_set_bit(i, wl->links_map, WL12XX_MAX_LINKS) {
+ u8 diff;
lnk = &wl->links[i];
+
/* prevent wrap-around in freed-packets counter */
- lnk->allocated_pkts -=
- (status_2->counters.tx_lnk_free_pkts[i] -
- lnk->prev_freed_pkts) & 0xff;
+ diff = (status_2->counters.tx_lnk_free_pkts[i] -
+ lnk->prev_freed_pkts) & 0xff;
+
+ if (diff == 0)
+ continue;
+ lnk->allocated_pkts -= diff;
lnk->prev_freed_pkts = status_2->counters.tx_lnk_free_pkts[i];
+
+ /* accumulate the prev_freed_pkts counter */
+ lnk->total_freed_pkts += diff;
}
/* prevent wrap-around in total blocks counter */
@@ -923,18 +931,6 @@ static void wl1271_recovery_work(struct work_struct *work)
goto out_unlock;
}
- /*
- * Advance security sequence number to overcome potential progress
- * in the firmware during recovery. This doens't hurt if the network is
- * not encrypted.
- */
- wl12xx_for_each_wlvif(wl, wlvif) {
- if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) ||
- test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags))
- wlvif->tx_security_seq +=
- WL1271_TX_SQN_POST_RECOVERY_PADDING;
- }
-
/* Prevent spurious TX during FW restart */
wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_FW_RESTART);
@@ -2864,10 +2860,6 @@ static int wlcore_unset_assoc(struct wl1271 *wl, struct wl12xx_vif *wlvif)
wlvif->sta.klv_template_id,
ACX_KEEP_ALIVE_TPL_INVALID);
- /* reset TX security counters on a clean disconnect */
- wlvif->tx_security_last_seq_lsb = 0;
- wlvif->tx_security_seq = 0;
-
return 0;
}
@@ -3266,6 +3258,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
u32 tx_seq_32 = 0;
u16 tx_seq_16 = 0;
u8 key_type;
+ u8 hlid;
wl1271_debug(DEBUG_MAC80211, "mac80211 set key");
@@ -3275,6 +3268,22 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
key_conf->keylen, key_conf->flags);
wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen);
+ if (wlvif->bss_type == BSS_TYPE_AP_BSS)
+ if (sta) {
+ struct wl1271_station *wl_sta = (void *)sta->drv_priv;
+ hlid = wl_sta->hlid;
+ } else {
+ hlid = wlvif->ap.bcast_hlid;
+ }
+ else
+ hlid = wlvif->sta.hlid;
+
+ if (hlid != WL12XX_INVALID_LINK_ID) {
+ u64 tx_seq = wl->links[hlid].total_freed_pkts;
+ tx_seq_32 = WL1271_TX_SECURITY_HI32(tx_seq);
+ tx_seq_16 = WL1271_TX_SECURITY_LO16(tx_seq);
+ }
+
switch (key_conf->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
@@ -3284,22 +3293,14 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
break;
case WLAN_CIPHER_SUITE_TKIP:
key_type = KEY_TKIP;
-
key_conf->hw_key_idx = key_conf->keyidx;
- tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq);
- tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq);
break;
case WLAN_CIPHER_SUITE_CCMP:
key_type = KEY_AES;
-
key_conf->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
- tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq);
- tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq);
break;
case WL1271_CIPHER_SUITE_GEM:
key_type = KEY_GEM;
- tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq);
- tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq);
break;
default:
wl1271_error("Unknown key algo 0x%x", key_conf->cipher);