diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/wl12xx/cmd.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/debugfs.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 18 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/tx.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/tx.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl12xx.h | 14 |
6 files changed, 47 insertions, 15 deletions
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index c9a1fa523274..a712a0f7b370 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c | |||
@@ -400,10 +400,6 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) | |||
400 | 400 | ||
401 | join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET; | 401 | join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET; |
402 | 402 | ||
403 | /* reset TX security counters */ | ||
404 | wl->tx_security_last_seq = 0; | ||
405 | wl->tx_security_seq = 0; | ||
406 | |||
407 | wl1271_debug(DEBUG_CMD, "cmd join: basic_rate_set=0x%x, rate_set=0x%x", | 403 | wl1271_debug(DEBUG_CMD, "cmd join: basic_rate_set=0x%x, rate_set=0x%x", |
408 | join->basic_rate_set, join->supported_rate_set); | 404 | join->basic_rate_set, join->supported_rate_set); |
409 | 405 | ||
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index da2127018300..3f6314143ef8 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c | |||
@@ -349,7 +349,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, | |||
349 | DRIVER_STATE_PRINT_INT(tx_blocks_freed[1]); | 349 | DRIVER_STATE_PRINT_INT(tx_blocks_freed[1]); |
350 | DRIVER_STATE_PRINT_INT(tx_blocks_freed[2]); | 350 | DRIVER_STATE_PRINT_INT(tx_blocks_freed[2]); |
351 | DRIVER_STATE_PRINT_INT(tx_blocks_freed[3]); | 351 | DRIVER_STATE_PRINT_INT(tx_blocks_freed[3]); |
352 | DRIVER_STATE_PRINT_INT(tx_security_last_seq); | 352 | DRIVER_STATE_PRINT_INT(tx_security_last_seq_lsb); |
353 | DRIVER_STATE_PRINT_INT(rx_counter); | 353 | DRIVER_STATE_PRINT_INT(rx_counter); |
354 | DRIVER_STATE_PRINT_INT(session_counter); | 354 | DRIVER_STATE_PRINT_INT(session_counter); |
355 | DRIVER_STATE_PRINT_INT(state); | 355 | DRIVER_STATE_PRINT_INT(state); |
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index a3734bdf5119..b896f5956d9e 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -1227,6 +1227,15 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
1227 | wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x", | 1227 | wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x", |
1228 | wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4)); | 1228 | wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4)); |
1229 | 1229 | ||
1230 | /* | ||
1231 | * Advance security sequence number to overcome potential progress | ||
1232 | * in the firmware during recovery. This doens't hurt if the network is | ||
1233 | * not encrypted. | ||
1234 | */ | ||
1235 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || | ||
1236 | test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) | ||
1237 | wl->tx_security_seq += WL1271_TX_SQN_POST_RECOVERY_PADDING; | ||
1238 | |||
1230 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | 1239 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) |
1231 | ieee80211_connection_loss(wl->vif); | 1240 | ieee80211_connection_loss(wl->vif); |
1232 | 1241 | ||
@@ -1980,8 +1989,6 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, | |||
1980 | wl->tx_allocated_blocks = 0; | 1989 | wl->tx_allocated_blocks = 0; |
1981 | wl->tx_results_count = 0; | 1990 | wl->tx_results_count = 0; |
1982 | wl->tx_packets_count = 0; | 1991 | wl->tx_packets_count = 0; |
1983 | wl->tx_security_last_seq = 0; | ||
1984 | wl->tx_security_seq = 0; | ||
1985 | wl->time_offset = 0; | 1992 | wl->time_offset = 0; |
1986 | wl->session_counter = 0; | 1993 | wl->session_counter = 0; |
1987 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 1994 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; |
@@ -2154,6 +2161,10 @@ static int wl1271_unjoin(struct wl1271 *wl) | |||
2154 | clear_bit(WL1271_FLAG_JOINED, &wl->flags); | 2161 | clear_bit(WL1271_FLAG_JOINED, &wl->flags); |
2155 | memset(wl->bssid, 0, ETH_ALEN); | 2162 | memset(wl->bssid, 0, ETH_ALEN); |
2156 | 2163 | ||
2164 | /* reset TX security counters on a clean disconnect */ | ||
2165 | wl->tx_security_last_seq_lsb = 0; | ||
2166 | wl->tx_security_seq = 0; | ||
2167 | |||
2157 | /* stop filtering packets based on bssid */ | 2168 | /* stop filtering packets based on bssid */ |
2158 | wl1271_configure_filters(wl, FIF_OTHER_BSS); | 2169 | wl1271_configure_filters(wl, FIF_OTHER_BSS); |
2159 | 2170 | ||
@@ -4327,6 +4338,9 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
4327 | wl->quirks = 0; | 4338 | wl->quirks = 0; |
4328 | wl->platform_quirks = 0; | 4339 | wl->platform_quirks = 0; |
4329 | wl->sched_scanning = false; | 4340 | wl->sched_scanning = false; |
4341 | wl->tx_security_seq = 0; | ||
4342 | wl->tx_security_last_seq_lsb = 0; | ||
4343 | |||
4330 | setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer, | 4344 | setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer, |
4331 | (unsigned long) wl); | 4345 | (unsigned long) wl); |
4332 | wl->fwlog_size = 0; | 4346 | wl->fwlog_size = 0; |
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 200590c0d9e3..003f9e08691b 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c | |||
@@ -704,10 +704,24 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
704 | 704 | ||
705 | wl->stats.retry_count += result->ack_failures; | 705 | wl->stats.retry_count += result->ack_failures; |
706 | 706 | ||
707 | /* update security sequence number */ | 707 | /* |
708 | wl->tx_security_seq += (result->lsb_security_sequence_number - | 708 | * update sequence number only when relevant, i.e. only in |
709 | wl->tx_security_last_seq); | 709 | * sessions of TKIP, AES and GEM (not in open or WEP sessions) |
710 | wl->tx_security_last_seq = result->lsb_security_sequence_number; | 710 | */ |
711 | if (info->control.hw_key && | ||
712 | (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP || | ||
713 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP || | ||
714 | info->control.hw_key->cipher == WL1271_CIPHER_SUITE_GEM)) { | ||
715 | u8 fw_lsb = result->tx_security_sequence_number_lsb; | ||
716 | u8 cur_lsb = wl->tx_security_last_seq_lsb; | ||
717 | |||
718 | /* | ||
719 | * update security sequence number, taking care of potential | ||
720 | * wrap-around | ||
721 | */ | ||
722 | wl->tx_security_seq += (fw_lsb - cur_lsb + 256) % 256; | ||
723 | wl->tx_security_last_seq_lsb = fw_lsb; | ||
724 | } | ||
711 | 725 | ||
712 | /* remove private header from packet */ | 726 | /* remove private header from packet */ |
713 | skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); | 727 | skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); |
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index 832f9258d675..7ed3c01f3651 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h | |||
@@ -150,7 +150,7 @@ struct wl1271_tx_hw_res_descr { | |||
150 | (from 1st EDCA AIFS counter until TX Complete). */ | 150 | (from 1st EDCA AIFS counter until TX Complete). */ |
151 | __le32 medium_delay; | 151 | __le32 medium_delay; |
152 | /* LS-byte of last TKIP seq-num (saved per AC for recovery). */ | 152 | /* LS-byte of last TKIP seq-num (saved per AC for recovery). */ |
153 | u8 lsb_security_sequence_number; | 153 | u8 tx_security_sequence_number_lsb; |
154 | /* Retry count - number of transmissions without successful ACK.*/ | 154 | /* Retry count - number of transmissions without successful ACK.*/ |
155 | u8 ack_failures; | 155 | u8 ack_failures; |
156 | /* The rate that succeeded getting ACK | 156 | /* The rate that succeeded getting ACK |
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index d7db6e77047a..002d9c53e373 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h | |||
@@ -144,6 +144,7 @@ extern u32 wl12xx_debug_level; | |||
144 | 144 | ||
145 | #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff)) | 145 | #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff)) |
146 | #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff)) | 146 | #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff)) |
147 | #define WL1271_TX_SQN_POST_RECOVERY_PADDING 0xff | ||
147 | 148 | ||
148 | #define WL1271_CIPHER_SUITE_GEM 0x00147201 | 149 | #define WL1271_CIPHER_SUITE_GEM 0x00147201 |
149 | 150 | ||
@@ -454,9 +455,16 @@ struct wl1271 { | |||
454 | struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS]; | 455 | struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS]; |
455 | int tx_frames_cnt; | 456 | int tx_frames_cnt; |
456 | 457 | ||
457 | /* Security sequence number counters */ | 458 | /* |
458 | u8 tx_security_last_seq; | 459 | * Security sequence number |
459 | s64 tx_security_seq; | 460 | * bits 0-15: lower 16 bits part of sequence number |
461 | * bits 16-47: higher 32 bits part of sequence number | ||
462 | * bits 48-63: not in use | ||
463 | */ | ||
464 | u64 tx_security_seq; | ||
465 | |||
466 | /* 8 bits of the last sequence number in use */ | ||
467 | u8 tx_security_last_seq_lsb; | ||
460 | 468 | ||
461 | /* FW Rx counter */ | 469 | /* FW Rx counter */ |
462 | u32 rx_counter; | 470 | u32 rx_counter; |