diff options
author | Eliad Peller <eliad@wizery.com> | 2011-10-10 04:12:58 -0400 |
---|---|---|
committer | Luciano Coelho <coelho@ti.com> | 2011-10-11 08:04:23 -0400 |
commit | 48e93e402ad19f570bae323b07911bdf6562af8e (patch) | |
tree | e472d28864aede3c878886941b338bdb64947a54 /drivers | |
parent | 4b730b6a814fe52425d90ff3db3d8deefb22fb24 (diff) |
wl12xx: move tx_security_seq into wlvif
The last security seq num has to be saved across reconfigs.
Add a new "persistent" struct into wlvif, which won't get
deleted on wl12xx_init_vif_data()
Signed-off-by: Eliad Peller <eliad@wizery.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/wl12xx/debugfs.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 32 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/tx.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl12xx.h | 30 |
4 files changed, 45 insertions, 30 deletions
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index bbc8004edf40..669b081848e8 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c | |||
@@ -346,7 +346,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, | |||
346 | DRIVER_STATE_PRINT_INT(tx_results_count); | 346 | DRIVER_STATE_PRINT_INT(tx_results_count); |
347 | DRIVER_STATE_PRINT_LHEX(flags); | 347 | DRIVER_STATE_PRINT_LHEX(flags); |
348 | DRIVER_STATE_PRINT_INT(tx_blocks_freed); | 348 | DRIVER_STATE_PRINT_INT(tx_blocks_freed); |
349 | DRIVER_STATE_PRINT_INT(tx_security_last_seq_lsb); | ||
350 | DRIVER_STATE_PRINT_INT(rx_counter); | 349 | DRIVER_STATE_PRINT_INT(rx_counter); |
351 | DRIVER_STATE_PRINT_INT(state); | 350 | DRIVER_STATE_PRINT_INT(state); |
352 | DRIVER_STATE_PRINT_INT(channel); | 351 | DRIVER_STATE_PRINT_INT(channel); |
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index b52deac368f4..8d87df53bbec 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -1206,6 +1206,7 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
1206 | { | 1206 | { |
1207 | struct wl1271 *wl = | 1207 | struct wl1271 *wl = |
1208 | container_of(work, struct wl1271, recovery_work); | 1208 | container_of(work, struct wl1271, recovery_work); |
1209 | struct wl12xx_vif *wlvif; | ||
1209 | 1210 | ||
1210 | mutex_lock(&wl->mutex); | 1211 | mutex_lock(&wl->mutex); |
1211 | 1212 | ||
@@ -1227,9 +1228,12 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
1227 | * in the firmware during recovery. This doens't hurt if the network is | 1228 | * in the firmware during recovery. This doens't hurt if the network is |
1228 | * not encrypted. | 1229 | * not encrypted. |
1229 | */ | 1230 | */ |
1230 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || | 1231 | wl12xx_for_each_wlvif(wl, wlvif) { |
1231 | test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) | 1232 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || |
1232 | wl->tx_security_seq += WL1271_TX_SQN_POST_RECOVERY_PADDING; | 1233 | test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) |
1234 | wlvif->tx_security_seq += | ||
1235 | WL1271_TX_SQN_POST_RECOVERY_PADDING; | ||
1236 | } | ||
1233 | 1237 | ||
1234 | /* Prevent spurious TX during FW restart */ | 1238 | /* Prevent spurious TX during FW restart */ |
1235 | ieee80211_stop_queues(wl->hw); | 1239 | ieee80211_stop_queues(wl->hw); |
@@ -1910,8 +1914,8 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) | |||
1910 | { | 1914 | { |
1911 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | 1915 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); |
1912 | 1916 | ||
1913 | /* make sure wlvif is zeroed */ | 1917 | /* clear everything but the persistent data */ |
1914 | memset(wlvif, 0, sizeof(*wlvif)); | 1918 | memset(wlvif, 0, offsetof(struct wl12xx_vif, persistent)); |
1915 | 1919 | ||
1916 | switch (ieee80211_vif_type_p2p(vif)) { | 1920 | switch (ieee80211_vif_type_p2p(vif)) { |
1917 | case NL80211_IFTYPE_P2P_CLIENT: | 1921 | case NL80211_IFTYPE_P2P_CLIENT: |
@@ -2297,8 +2301,8 @@ static int wl1271_unjoin(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
2297 | goto out; | 2301 | goto out; |
2298 | 2302 | ||
2299 | /* reset TX security counters on a clean disconnect */ | 2303 | /* reset TX security counters on a clean disconnect */ |
2300 | wl->tx_security_last_seq_lsb = 0; | 2304 | wlvif->tx_security_last_seq_lsb = 0; |
2301 | wl->tx_security_seq = 0; | 2305 | wlvif->tx_security_seq = 0; |
2302 | 2306 | ||
2303 | out: | 2307 | out: |
2304 | return ret; | 2308 | return ret; |
@@ -2870,20 +2874,20 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2870 | key_type = KEY_TKIP; | 2874 | key_type = KEY_TKIP; |
2871 | 2875 | ||
2872 | key_conf->hw_key_idx = key_conf->keyidx; | 2876 | key_conf->hw_key_idx = key_conf->keyidx; |
2873 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); | 2877 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq); |
2874 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); | 2878 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq); |
2875 | break; | 2879 | break; |
2876 | case WLAN_CIPHER_SUITE_CCMP: | 2880 | case WLAN_CIPHER_SUITE_CCMP: |
2877 | key_type = KEY_AES; | 2881 | key_type = KEY_AES; |
2878 | 2882 | ||
2879 | key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 2883 | key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
2880 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); | 2884 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq); |
2881 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); | 2885 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq); |
2882 | break; | 2886 | break; |
2883 | case WL1271_CIPHER_SUITE_GEM: | 2887 | case WL1271_CIPHER_SUITE_GEM: |
2884 | key_type = KEY_GEM; | 2888 | key_type = KEY_GEM; |
2885 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); | 2889 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq); |
2886 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); | 2890 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq); |
2887 | break; | 2891 | break; |
2888 | default: | 2892 | default: |
2889 | wl1271_error("Unknown key algo 0x%x", key_conf->cipher); | 2893 | wl1271_error("Unknown key algo 0x%x", key_conf->cipher); |
@@ -4923,8 +4927,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
4923 | wl->quirks = 0; | 4927 | wl->quirks = 0; |
4924 | wl->platform_quirks = 0; | 4928 | wl->platform_quirks = 0; |
4925 | wl->sched_scanning = false; | 4929 | wl->sched_scanning = false; |
4926 | wl->tx_security_seq = 0; | ||
4927 | wl->tx_security_last_seq_lsb = 0; | ||
4928 | wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; | 4930 | wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; |
4929 | wl->system_hlid = WL12XX_SYSTEM_HLID; | 4931 | wl->system_hlid = WL12XX_SYSTEM_HLID; |
4930 | wl->active_sta_count = 0; | 4932 | wl->active_sta_count = 0; |
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index c7be15186c4a..8c35d37ba600 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c | |||
@@ -755,6 +755,8 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
755 | struct wl1271_tx_hw_res_descr *result) | 755 | struct wl1271_tx_hw_res_descr *result) |
756 | { | 756 | { |
757 | struct ieee80211_tx_info *info; | 757 | struct ieee80211_tx_info *info; |
758 | struct ieee80211_vif *vif; | ||
759 | struct wl12xx_vif *wlvif; | ||
758 | struct sk_buff *skb; | 760 | struct sk_buff *skb; |
759 | int id = result->id; | 761 | int id = result->id; |
760 | int rate = -1; | 762 | int rate = -1; |
@@ -774,6 +776,10 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
774 | return; | 776 | return; |
775 | } | 777 | } |
776 | 778 | ||
779 | /* info->control is valid as long as we don't update info->status */ | ||
780 | vif = info->control.vif; | ||
781 | wlvif = wl12xx_vif_to_data(vif); | ||
782 | |||
777 | /* update the TX status info */ | 783 | /* update the TX status info */ |
778 | if (result->status == TX_SUCCESS) { | 784 | if (result->status == TX_SUCCESS) { |
779 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) | 785 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) |
@@ -801,14 +807,14 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
801 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP || | 807 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP || |
802 | info->control.hw_key->cipher == WL1271_CIPHER_SUITE_GEM)) { | 808 | info->control.hw_key->cipher == WL1271_CIPHER_SUITE_GEM)) { |
803 | u8 fw_lsb = result->tx_security_sequence_number_lsb; | 809 | u8 fw_lsb = result->tx_security_sequence_number_lsb; |
804 | u8 cur_lsb = wl->tx_security_last_seq_lsb; | 810 | u8 cur_lsb = wlvif->tx_security_last_seq_lsb; |
805 | 811 | ||
806 | /* | 812 | /* |
807 | * update security sequence number, taking care of potential | 813 | * update security sequence number, taking care of potential |
808 | * wrap-around | 814 | * wrap-around |
809 | */ | 815 | */ |
810 | wl->tx_security_seq += (fw_lsb - cur_lsb + 256) % 256; | 816 | wlvif->tx_security_seq += (fw_lsb - cur_lsb) & 0xff; |
811 | wl->tx_security_last_seq_lsb = fw_lsb; | 817 | wlvif->tx_security_last_seq_lsb = fw_lsb; |
812 | } | 818 | } |
813 | 819 | ||
814 | /* remove private header from packet */ | 820 | /* remove private header from packet */ |
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index de9a2b639403..d58488598d11 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h | |||
@@ -437,17 +437,6 @@ struct wl1271 { | |||
437 | struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS]; | 437 | struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS]; |
438 | int tx_frames_cnt; | 438 | int tx_frames_cnt; |
439 | 439 | ||
440 | /* | ||
441 | * Security sequence number | ||
442 | * bits 0-15: lower 16 bits part of sequence number | ||
443 | * bits 16-47: higher 32 bits part of sequence number | ||
444 | * bits 48-63: not in use | ||
445 | */ | ||
446 | u64 tx_security_seq; | ||
447 | |||
448 | /* 8 bits of the last sequence number in use */ | ||
449 | u8 tx_security_last_seq_lsb; | ||
450 | |||
451 | /* FW Rx counter */ | 440 | /* FW Rx counter */ |
452 | u32 rx_counter; | 441 | u32 rx_counter; |
453 | 442 | ||
@@ -645,6 +634,25 @@ struct wl12xx_vif { | |||
645 | /* RX BA constraint value */ | 634 | /* RX BA constraint value */ |
646 | bool ba_support; | 635 | bool ba_support; |
647 | bool ba_allowed; | 636 | bool ba_allowed; |
637 | |||
638 | /* | ||
639 | * This struct must be last! | ||
640 | * data that has to be saved acrossed reconfigs (e.g. recovery) | ||
641 | * should be declared in this struct. | ||
642 | */ | ||
643 | struct { | ||
644 | u8 persistent[0]; | ||
645 | /* | ||
646 | * Security sequence number | ||
647 | * bits 0-15: lower 16 bits part of sequence number | ||
648 | * bits 16-47: higher 32 bits part of sequence number | ||
649 | * bits 48-63: not in use | ||
650 | */ | ||
651 | u64 tx_security_seq; | ||
652 | |||
653 | /* 8 bits of the last sequence number in use */ | ||
654 | u8 tx_security_last_seq_lsb; | ||
655 | }; | ||
648 | }; | 656 | }; |
649 | 657 | ||
650 | static inline struct wl12xx_vif *wl12xx_vif_to_data(struct ieee80211_vif *vif) | 658 | static inline struct wl12xx_vif *wl12xx_vif_to_data(struct ieee80211_vif *vif) |