diff options
author | John W. Linville <linville@tuxdriver.com> | 2011-07-08 11:05:20 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-07-08 11:05:20 -0400 |
commit | e441a5eab928ddee8a946b4d48489341b41f88f2 (patch) | |
tree | 86156e4e6f3cc1b8668f426f635a93d108eadf5c /drivers/net/wireless | |
parent | 5f0dd296a01c8173fcc05a8b262a1168ae90bc74 (diff) | |
parent | f1a46384ad568f72c11edbe2a3ec284bf32f2dbd (diff) |
Merge branch 'for-linville' of git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/wl12xx/acx.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/acx.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/boot.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/cmd.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/conf.h | 10 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/debugfs.c | 15 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/event.c | 42 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/event.h | 12 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/init.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 202 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/ps.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/scan.c | 27 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/scan.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/sdio.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/tx.c | 143 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/tx.h | 28 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl12xx.h | 24 |
17 files changed, 414 insertions, 144 deletions
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 87caa94fd815..7e33f1f4f3d4 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c | |||
@@ -90,7 +90,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power) | |||
90 | struct acx_current_tx_power *acx; | 90 | struct acx_current_tx_power *acx; |
91 | int ret; | 91 | int ret; |
92 | 92 | ||
93 | wl1271_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr"); | 93 | wl1271_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr %d", power); |
94 | 94 | ||
95 | if (power < 0 || power > 25) | 95 | if (power < 0 || power > 25) |
96 | return -EINVAL; | 96 | return -EINVAL; |
@@ -1624,22 +1624,22 @@ out: | |||
1624 | return ret; | 1624 | return ret; |
1625 | } | 1625 | } |
1626 | 1626 | ||
1627 | int wl1271_acx_max_tx_retry(struct wl1271 *wl) | 1627 | int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl) |
1628 | { | 1628 | { |
1629 | struct wl1271_acx_max_tx_retry *acx = NULL; | 1629 | struct wl1271_acx_ap_max_tx_retry *acx = NULL; |
1630 | int ret; | 1630 | int ret; |
1631 | 1631 | ||
1632 | wl1271_debug(DEBUG_ACX, "acx max tx retry"); | 1632 | wl1271_debug(DEBUG_ACX, "acx ap max tx retry"); |
1633 | 1633 | ||
1634 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 1634 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
1635 | if (!acx) | 1635 | if (!acx) |
1636 | return -ENOMEM; | 1636 | return -ENOMEM; |
1637 | 1637 | ||
1638 | acx->max_tx_retry = cpu_to_le16(wl->conf.tx.ap_max_tx_retries); | 1638 | acx->max_tx_retry = cpu_to_le16(wl->conf.tx.max_tx_retries); |
1639 | 1639 | ||
1640 | ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx)); | 1640 | ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx)); |
1641 | if (ret < 0) { | 1641 | if (ret < 0) { |
1642 | wl1271_warning("acx max tx retry failed: %d", ret); | 1642 | wl1271_warning("acx ap max tx retry failed: %d", ret); |
1643 | goto out; | 1643 | goto out; |
1644 | } | 1644 | } |
1645 | 1645 | ||
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index d303265f163a..d2eb86eccc04 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h | |||
@@ -1168,7 +1168,7 @@ struct wl1271_acx_ps_rx_streaming { | |||
1168 | u8 timeout; | 1168 | u8 timeout; |
1169 | } __packed; | 1169 | } __packed; |
1170 | 1170 | ||
1171 | struct wl1271_acx_max_tx_retry { | 1171 | struct wl1271_acx_ap_max_tx_retry { |
1172 | struct acx_header header; | 1172 | struct acx_header header; |
1173 | 1173 | ||
1174 | /* | 1174 | /* |
@@ -1400,7 +1400,7 @@ int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn, | |||
1400 | bool enable); | 1400 | bool enable); |
1401 | int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); | 1401 | int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); |
1402 | int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable); | 1402 | int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable); |
1403 | int wl1271_acx_max_tx_retry(struct wl1271 *wl); | 1403 | int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl); |
1404 | int wl1271_acx_config_ps(struct wl1271 *wl); | 1404 | int wl1271_acx_config_ps(struct wl1271 *wl); |
1405 | int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); | 1405 | int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); |
1406 | int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable); | 1406 | int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable); |
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index 101f7e0f6329..5ebc64d89407 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c | |||
@@ -513,7 +513,9 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
513 | PERIODIC_SCAN_COMPLETE_EVENT_ID; | 513 | PERIODIC_SCAN_COMPLETE_EVENT_ID; |
514 | 514 | ||
515 | if (wl->bss_type == BSS_TYPE_AP_BSS) | 515 | if (wl->bss_type == BSS_TYPE_AP_BSS) |
516 | wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID; | 516 | wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID | |
517 | INACTIVE_STA_EVENT_ID | | ||
518 | MAX_TX_RETRY_EVENT_ID; | ||
517 | else | 519 | else |
518 | wl->event_mask |= DUMMY_PACKET_EVENT_ID | | 520 | wl->event_mask |= DUMMY_PACKET_EVENT_ID | |
519 | BA_SESSION_RX_CONSTRAINT_EVENT_ID; | 521 | BA_SESSION_RX_CONSTRAINT_EVENT_ID; |
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 68972cbc68b4..97dd237a9580 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 | ||
@@ -1084,7 +1080,7 @@ int wl1271_cmd_start_bss(struct wl1271 *wl) | |||
1084 | 1080 | ||
1085 | memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN); | 1081 | memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN); |
1086 | 1082 | ||
1087 | cmd->aging_period = cpu_to_le16(WL1271_AP_DEF_INACTIV_SEC); | 1083 | cmd->aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); |
1088 | cmd->bss_index = WL1271_AP_BSS_INDEX; | 1084 | cmd->bss_index = WL1271_AP_BSS_INDEX; |
1089 | cmd->global_hlid = WL1271_AP_GLOBAL_HLID; | 1085 | cmd->global_hlid = WL1271_AP_GLOBAL_HLID; |
1090 | cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID; | 1086 | cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID; |
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index b5a7b30afda3..6080e01d92c6 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h | |||
@@ -713,8 +713,16 @@ struct conf_tx_settings { | |||
713 | /* | 713 | /* |
714 | * AP-mode - allow this number of TX retries to a station before an | 714 | * AP-mode - allow this number of TX retries to a station before an |
715 | * event is triggered from FW. | 715 | * event is triggered from FW. |
716 | * In AP-mode the hlids of unreachable stations are given in the | ||
717 | * "sta_tx_retry_exceeded" member in the event mailbox. | ||
716 | */ | 718 | */ |
717 | u16 ap_max_tx_retries; | 719 | u8 max_tx_retries; |
720 | |||
721 | /* | ||
722 | * AP-mode - after this number of seconds a connected station is | ||
723 | * considered inactive. | ||
724 | */ | ||
725 | u16 ap_aging_period; | ||
718 | 726 | ||
719 | /* | 727 | /* |
720 | * Configuration for TID parameters. | 728 | * Configuration for TID parameters. |
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index da2127018300..37934b5601cd 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "acx.h" | 30 | #include "acx.h" |
31 | #include "ps.h" | 31 | #include "ps.h" |
32 | #include "io.h" | 32 | #include "io.h" |
33 | #include "tx.h" | ||
33 | 34 | ||
34 | /* ms */ | 35 | /* ms */ |
35 | #define WL1271_DEBUGFS_STATS_LIFETIME 1000 | 36 | #define WL1271_DEBUGFS_STATS_LIFETIME 1000 |
@@ -233,7 +234,7 @@ static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf, | |||
233 | char buf[20]; | 234 | char buf[20]; |
234 | int res; | 235 | int res; |
235 | 236 | ||
236 | queue_len = wl->tx_queue_count; | 237 | queue_len = wl1271_tx_total_queue_count(wl); |
237 | 238 | ||
238 | res = scnprintf(buf, sizeof(buf), "%u\n", queue_len); | 239 | res = scnprintf(buf, sizeof(buf), "%u\n", queue_len); |
239 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); | 240 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); |
@@ -338,10 +339,16 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, | |||
338 | #define DRIVER_STATE_PRINT_HEX(x) DRIVER_STATE_PRINT(x, "0x%x") | 339 | #define DRIVER_STATE_PRINT_HEX(x) DRIVER_STATE_PRINT(x, "0x%x") |
339 | 340 | ||
340 | DRIVER_STATE_PRINT_INT(tx_blocks_available); | 341 | DRIVER_STATE_PRINT_INT(tx_blocks_available); |
341 | DRIVER_STATE_PRINT_INT(tx_allocated_blocks); | 342 | DRIVER_STATE_PRINT_INT(tx_allocated_blocks[0]); |
343 | DRIVER_STATE_PRINT_INT(tx_allocated_blocks[1]); | ||
344 | DRIVER_STATE_PRINT_INT(tx_allocated_blocks[2]); | ||
345 | DRIVER_STATE_PRINT_INT(tx_allocated_blocks[3]); | ||
342 | DRIVER_STATE_PRINT_INT(tx_frames_cnt); | 346 | DRIVER_STATE_PRINT_INT(tx_frames_cnt); |
343 | DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]); | 347 | DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]); |
344 | DRIVER_STATE_PRINT_INT(tx_queue_count); | 348 | DRIVER_STATE_PRINT_INT(tx_queue_count[0]); |
349 | DRIVER_STATE_PRINT_INT(tx_queue_count[1]); | ||
350 | DRIVER_STATE_PRINT_INT(tx_queue_count[2]); | ||
351 | DRIVER_STATE_PRINT_INT(tx_queue_count[3]); | ||
345 | DRIVER_STATE_PRINT_INT(tx_packets_count); | 352 | DRIVER_STATE_PRINT_INT(tx_packets_count); |
346 | DRIVER_STATE_PRINT_INT(tx_results_count); | 353 | DRIVER_STATE_PRINT_INT(tx_results_count); |
347 | DRIVER_STATE_PRINT_LHEX(flags); | 354 | DRIVER_STATE_PRINT_LHEX(flags); |
@@ -349,7 +356,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, | |||
349 | DRIVER_STATE_PRINT_INT(tx_blocks_freed[1]); | 356 | DRIVER_STATE_PRINT_INT(tx_blocks_freed[1]); |
350 | DRIVER_STATE_PRINT_INT(tx_blocks_freed[2]); | 357 | DRIVER_STATE_PRINT_INT(tx_blocks_freed[2]); |
351 | DRIVER_STATE_PRINT_INT(tx_blocks_freed[3]); | 358 | DRIVER_STATE_PRINT_INT(tx_blocks_freed[3]); |
352 | DRIVER_STATE_PRINT_INT(tx_security_last_seq); | 359 | DRIVER_STATE_PRINT_INT(tx_security_last_seq_lsb); |
353 | DRIVER_STATE_PRINT_INT(rx_counter); | 360 | DRIVER_STATE_PRINT_INT(rx_counter); |
354 | DRIVER_STATE_PRINT_INT(session_counter); | 361 | DRIVER_STATE_PRINT_INT(session_counter); |
355 | DRIVER_STATE_PRINT_INT(state); | 362 | DRIVER_STATE_PRINT_INT(state); |
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index a16dee58a664..304aaa2ee011 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c | |||
@@ -214,6 +214,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
214 | u32 vector; | 214 | u32 vector; |
215 | bool beacon_loss = false; | 215 | bool beacon_loss = false; |
216 | bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); | 216 | bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); |
217 | bool disconnect_sta = false; | ||
218 | unsigned long sta_bitmap = 0; | ||
217 | 219 | ||
218 | wl1271_event_mbox_dump(mbox); | 220 | wl1271_event_mbox_dump(mbox); |
219 | 221 | ||
@@ -295,6 +297,46 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
295 | wl1271_tx_dummy_packet(wl); | 297 | wl1271_tx_dummy_packet(wl); |
296 | } | 298 | } |
297 | 299 | ||
300 | /* | ||
301 | * "TX retries exceeded" has a different meaning according to mode. | ||
302 | * In AP mode the offending station is disconnected. | ||
303 | */ | ||
304 | if ((vector & MAX_TX_RETRY_EVENT_ID) && is_ap) { | ||
305 | wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID"); | ||
306 | sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded); | ||
307 | disconnect_sta = true; | ||
308 | } | ||
309 | |||
310 | if ((vector & INACTIVE_STA_EVENT_ID) && is_ap) { | ||
311 | wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID"); | ||
312 | sta_bitmap |= le16_to_cpu(mbox->sta_aging_status); | ||
313 | disconnect_sta = true; | ||
314 | } | ||
315 | |||
316 | if (is_ap && disconnect_sta) { | ||
317 | u32 num_packets = wl->conf.tx.max_tx_retries; | ||
318 | struct ieee80211_sta *sta; | ||
319 | const u8 *addr; | ||
320 | int h; | ||
321 | |||
322 | for (h = find_first_bit(&sta_bitmap, AP_MAX_LINKS); | ||
323 | h < AP_MAX_LINKS; | ||
324 | h = find_next_bit(&sta_bitmap, AP_MAX_LINKS, h+1)) { | ||
325 | if (!wl1271_is_active_sta(wl, h)) | ||
326 | continue; | ||
327 | |||
328 | addr = wl->links[h].addr; | ||
329 | |||
330 | rcu_read_lock(); | ||
331 | sta = ieee80211_find_sta(wl->vif, addr); | ||
332 | if (sta) { | ||
333 | wl1271_debug(DEBUG_EVENT, "remove sta %d", h); | ||
334 | ieee80211_report_low_ack(sta, num_packets); | ||
335 | } | ||
336 | rcu_read_unlock(); | ||
337 | } | ||
338 | } | ||
339 | |||
298 | if (wl->vif && beacon_loss) | 340 | if (wl->vif && beacon_loss) |
299 | ieee80211_connection_loss(wl->vif); | 341 | ieee80211_connection_loss(wl->vif); |
300 | 342 | ||
diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h index ce99adf4256e..e524ad6fe4e3 100644 --- a/drivers/net/wireless/wl12xx/event.h +++ b/drivers/net/wireless/wl12xx/event.h | |||
@@ -58,13 +58,16 @@ enum { | |||
58 | CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17), | 58 | CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17), |
59 | BSS_LOSE_EVENT_ID = BIT(18), | 59 | BSS_LOSE_EVENT_ID = BIT(18), |
60 | REGAINED_BSS_EVENT_ID = BIT(19), | 60 | REGAINED_BSS_EVENT_ID = BIT(19), |
61 | ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20), | 61 | MAX_TX_RETRY_EVENT_ID = BIT(20), |
62 | /* STA: dummy paket for dynamic mem blocks */ | 62 | /* STA: dummy paket for dynamic mem blocks */ |
63 | DUMMY_PACKET_EVENT_ID = BIT(21), | 63 | DUMMY_PACKET_EVENT_ID = BIT(21), |
64 | /* AP: STA remove complete */ | 64 | /* AP: STA remove complete */ |
65 | STA_REMOVE_COMPLETE_EVENT_ID = BIT(21), | 65 | STA_REMOVE_COMPLETE_EVENT_ID = BIT(21), |
66 | SOFT_GEMINI_SENSE_EVENT_ID = BIT(22), | 66 | SOFT_GEMINI_SENSE_EVENT_ID = BIT(22), |
67 | /* STA: SG prediction */ | ||
67 | SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23), | 68 | SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23), |
69 | /* AP: Inactive STA */ | ||
70 | INACTIVE_STA_EVENT_ID = BIT(23), | ||
68 | SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24), | 71 | SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24), |
69 | PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25), | 72 | PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25), |
70 | DBG_EVENT_ID = BIT(26), | 73 | DBG_EVENT_ID = BIT(26), |
@@ -119,7 +122,11 @@ struct event_mailbox { | |||
119 | 122 | ||
120 | /* AP FW only */ | 123 | /* AP FW only */ |
121 | u8 hlid_removed; | 124 | u8 hlid_removed; |
125 | |||
126 | /* a bitmap of hlids for stations that have been inactive too long */ | ||
122 | __le16 sta_aging_status; | 127 | __le16 sta_aging_status; |
128 | |||
129 | /* a bitmap of hlids for stations which didn't respond to TX */ | ||
123 | __le16 sta_tx_retry_exceeded; | 130 | __le16 sta_tx_retry_exceeded; |
124 | 131 | ||
125 | /* | 132 | /* |
@@ -143,4 +150,7 @@ void wl1271_event_mbox_config(struct wl1271 *wl); | |||
143 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox); | 150 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox); |
144 | void wl1271_pspoll_work(struct work_struct *work); | 151 | void wl1271_pspoll_work(struct work_struct *work); |
145 | 152 | ||
153 | /* Functions from main.c */ | ||
154 | bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid); | ||
155 | |||
146 | #endif | 156 | #endif |
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index cf40ac93cead..c3e9a2e4410e 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c | |||
@@ -447,7 +447,7 @@ static int wl1271_ap_hw_init(struct wl1271 *wl) | |||
447 | if (ret < 0) | 447 | if (ret < 0) |
448 | return ret; | 448 | return ret; |
449 | 449 | ||
450 | ret = wl1271_acx_max_tx_retry(wl); | 450 | ret = wl1271_acx_ap_max_tx_retry(wl); |
451 | if (ret < 0) | 451 | if (ret < 0) |
452 | return ret; | 452 | return ret; |
453 | 453 | ||
@@ -455,6 +455,11 @@ static int wl1271_ap_hw_init(struct wl1271 *wl) | |||
455 | if (ret < 0) | 455 | if (ret < 0) |
456 | return ret; | 456 | return ret; |
457 | 457 | ||
458 | /* initialize Tx power */ | ||
459 | ret = wl1271_acx_tx_power(wl, wl->power_level); | ||
460 | if (ret < 0) | ||
461 | return ret; | ||
462 | |||
458 | return 0; | 463 | return 0; |
459 | } | 464 | } |
460 | 465 | ||
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index a3734bdf5119..e58c22d21e39 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -210,7 +210,8 @@ static struct conf_drv_settings default_conf = { | |||
210 | .tx_op_limit = 1504, | 210 | .tx_op_limit = 1504, |
211 | }, | 211 | }, |
212 | }, | 212 | }, |
213 | .ap_max_tx_retries = 100, | 213 | .max_tx_retries = 100, |
214 | .ap_aging_period = 300, | ||
214 | .tid_conf_count = 4, | 215 | .tid_conf_count = 4, |
215 | .tid_conf = { | 216 | .tid_conf = { |
216 | [CONF_TX_AC_BE] = { | 217 | [CONF_TX_AC_BE] = { |
@@ -823,13 +824,24 @@ static void wl1271_irq_update_links_status(struct wl1271 *wl, | |||
823 | } | 824 | } |
824 | } | 825 | } |
825 | 826 | ||
827 | static u32 wl1271_tx_allocated_blocks(struct wl1271 *wl) | ||
828 | { | ||
829 | int i; | ||
830 | u32 total_alloc_blocks = 0; | ||
831 | |||
832 | for (i = 0; i < NUM_TX_QUEUES; i++) | ||
833 | total_alloc_blocks += wl->tx_allocated_blocks[i]; | ||
834 | |||
835 | return total_alloc_blocks; | ||
836 | } | ||
837 | |||
826 | static void wl1271_fw_status(struct wl1271 *wl, | 838 | static void wl1271_fw_status(struct wl1271 *wl, |
827 | struct wl1271_fw_full_status *full_status) | 839 | struct wl1271_fw_full_status *full_status) |
828 | { | 840 | { |
829 | struct wl1271_fw_common_status *status = &full_status->common; | 841 | struct wl1271_fw_common_status *status = &full_status->common; |
830 | struct timespec ts; | 842 | struct timespec ts; |
831 | u32 old_tx_blk_count = wl->tx_blocks_available; | 843 | u32 old_tx_blk_count = wl->tx_blocks_available; |
832 | u32 freed_blocks = 0; | 844 | u32 freed_blocks = 0, ac_freed_blocks; |
833 | int i; | 845 | int i; |
834 | 846 | ||
835 | if (wl->bss_type == BSS_TYPE_AP_BSS) { | 847 | if (wl->bss_type == BSS_TYPE_AP_BSS) { |
@@ -849,21 +861,23 @@ static void wl1271_fw_status(struct wl1271 *wl, | |||
849 | 861 | ||
850 | /* update number of available TX blocks */ | 862 | /* update number of available TX blocks */ |
851 | for (i = 0; i < NUM_TX_QUEUES; i++) { | 863 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
852 | freed_blocks += le32_to_cpu(status->tx_released_blks[i]) - | 864 | ac_freed_blocks = le32_to_cpu(status->tx_released_blks[i]) - |
853 | wl->tx_blocks_freed[i]; | 865 | wl->tx_blocks_freed[i]; |
866 | freed_blocks += ac_freed_blocks; | ||
867 | |||
868 | wl->tx_allocated_blocks[i] -= ac_freed_blocks; | ||
854 | 869 | ||
855 | wl->tx_blocks_freed[i] = | 870 | wl->tx_blocks_freed[i] = |
856 | le32_to_cpu(status->tx_released_blks[i]); | 871 | le32_to_cpu(status->tx_released_blks[i]); |
857 | } | 872 | } |
858 | 873 | ||
859 | wl->tx_allocated_blocks -= freed_blocks; | ||
860 | |||
861 | if (wl->bss_type == BSS_TYPE_AP_BSS) { | 874 | if (wl->bss_type == BSS_TYPE_AP_BSS) { |
862 | /* Update num of allocated TX blocks per link and ps status */ | 875 | /* Update num of allocated TX blocks per link and ps status */ |
863 | wl1271_irq_update_links_status(wl, &full_status->ap); | 876 | wl1271_irq_update_links_status(wl, &full_status->ap); |
864 | wl->tx_blocks_available += freed_blocks; | 877 | wl->tx_blocks_available += freed_blocks; |
865 | } else { | 878 | } else { |
866 | int avail = full_status->sta.tx_total - wl->tx_allocated_blocks; | 879 | int avail = full_status->sta.tx_total - |
880 | wl1271_tx_allocated_blocks(wl); | ||
867 | 881 | ||
868 | /* | 882 | /* |
869 | * The FW might change the total number of TX memblocks before | 883 | * The FW might change the total number of TX memblocks before |
@@ -978,7 +992,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie) | |||
978 | /* Check if any tx blocks were freed */ | 992 | /* Check if any tx blocks were freed */ |
979 | spin_lock_irqsave(&wl->wl_lock, flags); | 993 | spin_lock_irqsave(&wl->wl_lock, flags); |
980 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) && | 994 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) && |
981 | wl->tx_queue_count) { | 995 | wl1271_tx_total_queue_count(wl) > 0) { |
982 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 996 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
983 | /* | 997 | /* |
984 | * In order to avoid starvation of the TX path, | 998 | * In order to avoid starvation of the TX path, |
@@ -1026,7 +1040,7 @@ out: | |||
1026 | /* In case TX was not handled here, queue TX work */ | 1040 | /* In case TX was not handled here, queue TX work */ |
1027 | clear_bit(WL1271_FLAG_TX_PENDING, &wl->flags); | 1041 | clear_bit(WL1271_FLAG_TX_PENDING, &wl->flags); |
1028 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) && | 1042 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) && |
1029 | wl->tx_queue_count) | 1043 | wl1271_tx_total_queue_count(wl) > 0) |
1030 | ieee80211_queue_work(wl->hw, &wl->tx_work); | 1044 | ieee80211_queue_work(wl->hw, &wl->tx_work); |
1031 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 1045 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
1032 | 1046 | ||
@@ -1227,6 +1241,15 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
1227 | wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x", | 1241 | wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x", |
1228 | wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4)); | 1242 | wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4)); |
1229 | 1243 | ||
1244 | /* | ||
1245 | * Advance security sequence number to overcome potential progress | ||
1246 | * in the firmware during recovery. This doens't hurt if the network is | ||
1247 | * not encrypted. | ||
1248 | */ | ||
1249 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || | ||
1250 | test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) | ||
1251 | wl->tx_security_seq += WL1271_TX_SQN_POST_RECOVERY_PADDING; | ||
1252 | |||
1230 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | 1253 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) |
1231 | ieee80211_connection_loss(wl->vif); | 1254 | ieee80211_connection_loss(wl->vif); |
1232 | 1255 | ||
@@ -1474,26 +1497,27 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1474 | { | 1497 | { |
1475 | struct wl1271 *wl = hw->priv; | 1498 | struct wl1271 *wl = hw->priv; |
1476 | unsigned long flags; | 1499 | unsigned long flags; |
1477 | int q; | 1500 | int q, mapping; |
1478 | u8 hlid = 0; | 1501 | u8 hlid = 0; |
1479 | 1502 | ||
1480 | q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); | 1503 | mapping = skb_get_queue_mapping(skb); |
1504 | q = wl1271_tx_get_queue(mapping); | ||
1481 | 1505 | ||
1482 | if (wl->bss_type == BSS_TYPE_AP_BSS) | 1506 | if (wl->bss_type == BSS_TYPE_AP_BSS) |
1483 | hlid = wl1271_tx_get_hlid(skb); | 1507 | hlid = wl1271_tx_get_hlid(skb); |
1484 | 1508 | ||
1485 | spin_lock_irqsave(&wl->wl_lock, flags); | 1509 | spin_lock_irqsave(&wl->wl_lock, flags); |
1486 | 1510 | ||
1487 | wl->tx_queue_count++; | 1511 | wl->tx_queue_count[q]++; |
1488 | 1512 | ||
1489 | /* | 1513 | /* |
1490 | * The workqueue is slow to process the tx_queue and we need stop | 1514 | * The workqueue is slow to process the tx_queue and we need stop |
1491 | * the queue here, otherwise the queue will get too long. | 1515 | * the queue here, otherwise the queue will get too long. |
1492 | */ | 1516 | */ |
1493 | if (wl->tx_queue_count >= WL1271_TX_QUEUE_HIGH_WATERMARK) { | 1517 | if (wl->tx_queue_count[q] >= WL1271_TX_QUEUE_HIGH_WATERMARK) { |
1494 | wl1271_debug(DEBUG_TX, "op_tx: stopping queues"); | 1518 | wl1271_debug(DEBUG_TX, "op_tx: stopping queues for q %d", q); |
1495 | ieee80211_stop_queues(wl->hw); | 1519 | ieee80211_stop_queue(wl->hw, mapping); |
1496 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); | 1520 | set_bit(q, &wl->stopped_queues_map); |
1497 | } | 1521 | } |
1498 | 1522 | ||
1499 | /* queue the packet */ | 1523 | /* queue the packet */ |
@@ -1519,10 +1543,11 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1519 | int wl1271_tx_dummy_packet(struct wl1271 *wl) | 1543 | int wl1271_tx_dummy_packet(struct wl1271 *wl) |
1520 | { | 1544 | { |
1521 | unsigned long flags; | 1545 | unsigned long flags; |
1546 | int q = wl1271_tx_get_queue(skb_get_queue_mapping(wl->dummy_packet)); | ||
1522 | 1547 | ||
1523 | spin_lock_irqsave(&wl->wl_lock, flags); | 1548 | spin_lock_irqsave(&wl->wl_lock, flags); |
1524 | set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags); | 1549 | set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags); |
1525 | wl->tx_queue_count++; | 1550 | wl->tx_queue_count[q]++; |
1526 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 1551 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
1527 | 1552 | ||
1528 | /* The FW is low on RX memory blocks, so send the dummy packet asap */ | 1553 | /* The FW is low on RX memory blocks, so send the dummy packet asap */ |
@@ -1586,10 +1611,13 @@ static struct notifier_block wl1271_dev_notifier = { | |||
1586 | #ifdef CONFIG_PM | 1611 | #ifdef CONFIG_PM |
1587 | static int wl1271_configure_suspend_sta(struct wl1271 *wl) | 1612 | static int wl1271_configure_suspend_sta(struct wl1271 *wl) |
1588 | { | 1613 | { |
1589 | int ret; | 1614 | int ret = 0; |
1590 | 1615 | ||
1591 | mutex_lock(&wl->mutex); | 1616 | mutex_lock(&wl->mutex); |
1592 | 1617 | ||
1618 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | ||
1619 | goto out_unlock; | ||
1620 | |||
1593 | ret = wl1271_ps_elp_wakeup(wl); | 1621 | ret = wl1271_ps_elp_wakeup(wl); |
1594 | if (ret < 0) | 1622 | if (ret < 0) |
1595 | goto out_unlock; | 1623 | goto out_unlock; |
@@ -1634,10 +1662,13 @@ out: | |||
1634 | 1662 | ||
1635 | static int wl1271_configure_suspend_ap(struct wl1271 *wl) | 1663 | static int wl1271_configure_suspend_ap(struct wl1271 *wl) |
1636 | { | 1664 | { |
1637 | int ret; | 1665 | int ret = 0; |
1638 | 1666 | ||
1639 | mutex_lock(&wl->mutex); | 1667 | mutex_lock(&wl->mutex); |
1640 | 1668 | ||
1669 | if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) | ||
1670 | goto out_unlock; | ||
1671 | |||
1641 | ret = wl1271_ps_elp_wakeup(wl); | 1672 | ret = wl1271_ps_elp_wakeup(wl); |
1642 | if (ret < 0) | 1673 | if (ret < 0) |
1643 | goto out_unlock; | 1674 | goto out_unlock; |
@@ -1705,7 +1736,6 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, | |||
1705 | } | 1736 | } |
1706 | /* flush any remaining work */ | 1737 | /* flush any remaining work */ |
1707 | wl1271_debug(DEBUG_MAC80211, "flushing remaining works"); | 1738 | wl1271_debug(DEBUG_MAC80211, "flushing remaining works"); |
1708 | flush_delayed_work(&wl->scan_complete_work); | ||
1709 | 1739 | ||
1710 | /* | 1740 | /* |
1711 | * disable and re-enable interrupts in order to flush | 1741 | * disable and re-enable interrupts in order to flush |
@@ -1977,11 +2007,8 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, | |||
1977 | wl->psm_entry_retry = 0; | 2007 | wl->psm_entry_retry = 0; |
1978 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 2008 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
1979 | wl->tx_blocks_available = 0; | 2009 | wl->tx_blocks_available = 0; |
1980 | wl->tx_allocated_blocks = 0; | ||
1981 | wl->tx_results_count = 0; | 2010 | wl->tx_results_count = 0; |
1982 | wl->tx_packets_count = 0; | 2011 | wl->tx_packets_count = 0; |
1983 | wl->tx_security_last_seq = 0; | ||
1984 | wl->tx_security_seq = 0; | ||
1985 | wl->time_offset = 0; | 2012 | wl->time_offset = 0; |
1986 | wl->session_counter = 0; | 2013 | wl->session_counter = 0; |
1987 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 2014 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; |
@@ -2000,8 +2027,10 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, | |||
2000 | */ | 2027 | */ |
2001 | wl->flags = 0; | 2028 | wl->flags = 0; |
2002 | 2029 | ||
2003 | for (i = 0; i < NUM_TX_QUEUES; i++) | 2030 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
2004 | wl->tx_blocks_freed[i] = 0; | 2031 | wl->tx_blocks_freed[i] = 0; |
2032 | wl->tx_allocated_blocks[i] = 0; | ||
2033 | } | ||
2005 | 2034 | ||
2006 | wl1271_debugfs_reset(wl); | 2035 | wl1271_debugfs_reset(wl); |
2007 | 2036 | ||
@@ -2154,6 +2183,10 @@ static int wl1271_unjoin(struct wl1271 *wl) | |||
2154 | clear_bit(WL1271_FLAG_JOINED, &wl->flags); | 2183 | clear_bit(WL1271_FLAG_JOINED, &wl->flags); |
2155 | memset(wl->bssid, 0, ETH_ALEN); | 2184 | memset(wl->bssid, 0, ETH_ALEN); |
2156 | 2185 | ||
2186 | /* reset TX security counters on a clean disconnect */ | ||
2187 | wl->tx_security_last_seq_lsb = 0; | ||
2188 | wl->tx_security_seq = 0; | ||
2189 | |||
2157 | /* stop filtering packets based on bssid */ | 2190 | /* stop filtering packets based on bssid */ |
2158 | wl1271_configure_filters(wl, FIF_OTHER_BSS); | 2191 | wl1271_configure_filters(wl, FIF_OTHER_BSS); |
2159 | 2192 | ||
@@ -2246,6 +2279,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
2246 | wl->channel = channel; | 2279 | wl->channel = channel; |
2247 | } | 2280 | } |
2248 | 2281 | ||
2282 | if ((changed & IEEE80211_CONF_CHANGE_POWER)) | ||
2283 | wl->power_level = conf->power_level; | ||
2284 | |||
2249 | goto out; | 2285 | goto out; |
2250 | } | 2286 | } |
2251 | 2287 | ||
@@ -2753,6 +2789,44 @@ out: | |||
2753 | return ret; | 2789 | return ret; |
2754 | } | 2790 | } |
2755 | 2791 | ||
2792 | static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw, | ||
2793 | struct ieee80211_vif *vif) | ||
2794 | { | ||
2795 | struct wl1271 *wl = hw->priv; | ||
2796 | int ret; | ||
2797 | |||
2798 | wl1271_debug(DEBUG_MAC80211, "mac80211 cancel hw scan"); | ||
2799 | |||
2800 | mutex_lock(&wl->mutex); | ||
2801 | |||
2802 | if (wl->state == WL1271_STATE_OFF) | ||
2803 | goto out; | ||
2804 | |||
2805 | if (wl->scan.state == WL1271_SCAN_STATE_IDLE) | ||
2806 | goto out; | ||
2807 | |||
2808 | ret = wl1271_ps_elp_wakeup(wl); | ||
2809 | if (ret < 0) | ||
2810 | goto out; | ||
2811 | |||
2812 | if (wl->scan.state != WL1271_SCAN_STATE_DONE) { | ||
2813 | ret = wl1271_scan_stop(wl); | ||
2814 | if (ret < 0) | ||
2815 | goto out_sleep; | ||
2816 | } | ||
2817 | wl->scan.state = WL1271_SCAN_STATE_IDLE; | ||
2818 | memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); | ||
2819 | wl->scan.req = NULL; | ||
2820 | ieee80211_scan_completed(wl->hw, true); | ||
2821 | |||
2822 | out_sleep: | ||
2823 | wl1271_ps_elp_sleep(wl); | ||
2824 | out: | ||
2825 | mutex_unlock(&wl->mutex); | ||
2826 | |||
2827 | cancel_delayed_work_sync(&wl->scan_complete_work); | ||
2828 | } | ||
2829 | |||
2756 | static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw, | 2830 | static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw, |
2757 | struct ieee80211_vif *vif, | 2831 | struct ieee80211_vif *vif, |
2758 | struct cfg80211_sched_scan_request *req, | 2832 | struct cfg80211_sched_scan_request *req, |
@@ -3515,6 +3589,12 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid) | |||
3515 | __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | 3589 | __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); |
3516 | } | 3590 | } |
3517 | 3591 | ||
3592 | bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid) | ||
3593 | { | ||
3594 | int id = hlid - WL1271_AP_STA_HLID_START; | ||
3595 | return test_bit(id, wl->ap_hlid_map); | ||
3596 | } | ||
3597 | |||
3518 | static int wl1271_op_sta_add(struct ieee80211_hw *hw, | 3598 | static int wl1271_op_sta_add(struct ieee80211_hw *hw, |
3519 | struct ieee80211_vif *vif, | 3599 | struct ieee80211_vif *vif, |
3520 | struct ieee80211_sta *sta) | 3600 | struct ieee80211_sta *sta) |
@@ -3673,7 +3753,7 @@ static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) | |||
3673 | goto out; | 3753 | goto out; |
3674 | 3754 | ||
3675 | /* packets are considered pending if in the TX queue or the FW */ | 3755 | /* packets are considered pending if in the TX queue or the FW */ |
3676 | ret = (wl->tx_queue_count > 0) || (wl->tx_frames_cnt > 0); | 3756 | ret = (wl1271_tx_total_queue_count(wl) > 0) || (wl->tx_frames_cnt > 0); |
3677 | 3757 | ||
3678 | /* the above is appropriate for STA mode for PS purposes */ | 3758 | /* the above is appropriate for STA mode for PS purposes */ |
3679 | WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); | 3759 | WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); |
@@ -3836,40 +3916,40 @@ static struct ieee80211_rate wl1271_rates_5ghz[] = { | |||
3836 | 3916 | ||
3837 | /* 5 GHz band channels for WL1273 */ | 3917 | /* 5 GHz band channels for WL1273 */ |
3838 | static struct ieee80211_channel wl1271_channels_5ghz[] = { | 3918 | static struct ieee80211_channel wl1271_channels_5ghz[] = { |
3839 | { .hw_value = 7, .center_freq = 5035}, | 3919 | { .hw_value = 7, .center_freq = 5035, .max_power = 25 }, |
3840 | { .hw_value = 8, .center_freq = 5040}, | 3920 | { .hw_value = 8, .center_freq = 5040, .max_power = 25 }, |
3841 | { .hw_value = 9, .center_freq = 5045}, | 3921 | { .hw_value = 9, .center_freq = 5045, .max_power = 25 }, |
3842 | { .hw_value = 11, .center_freq = 5055}, | 3922 | { .hw_value = 11, .center_freq = 5055, .max_power = 25 }, |
3843 | { .hw_value = 12, .center_freq = 5060}, | 3923 | { .hw_value = 12, .center_freq = 5060, .max_power = 25 }, |
3844 | { .hw_value = 16, .center_freq = 5080}, | 3924 | { .hw_value = 16, .center_freq = 5080, .max_power = 25 }, |
3845 | { .hw_value = 34, .center_freq = 5170}, | 3925 | { .hw_value = 34, .center_freq = 5170, .max_power = 25 }, |
3846 | { .hw_value = 36, .center_freq = 5180}, | 3926 | { .hw_value = 36, .center_freq = 5180, .max_power = 25 }, |
3847 | { .hw_value = 38, .center_freq = 5190}, | 3927 | { .hw_value = 38, .center_freq = 5190, .max_power = 25 }, |
3848 | { .hw_value = 40, .center_freq = 5200}, | 3928 | { .hw_value = 40, .center_freq = 5200, .max_power = 25 }, |
3849 | { .hw_value = 42, .center_freq = 5210}, | 3929 | { .hw_value = 42, .center_freq = 5210, .max_power = 25 }, |
3850 | { .hw_value = 44, .center_freq = 5220}, | 3930 | { .hw_value = 44, .center_freq = 5220, .max_power = 25 }, |
3851 | { .hw_value = 46, .center_freq = 5230}, | 3931 | { .hw_value = 46, .center_freq = 5230, .max_power = 25 }, |
3852 | { .hw_value = 48, .center_freq = 5240}, | 3932 | { .hw_value = 48, .center_freq = 5240, .max_power = 25 }, |
3853 | { .hw_value = 52, .center_freq = 5260}, | 3933 | { .hw_value = 52, .center_freq = 5260, .max_power = 25 }, |
3854 | { .hw_value = 56, .center_freq = 5280}, | 3934 | { .hw_value = 56, .center_freq = 5280, .max_power = 25 }, |
3855 | { .hw_value = 60, .center_freq = 5300}, | 3935 | { .hw_value = 60, .center_freq = 5300, .max_power = 25 }, |
3856 | { .hw_value = 64, .center_freq = 5320}, | 3936 | { .hw_value = 64, .center_freq = 5320, .max_power = 25 }, |
3857 | { .hw_value = 100, .center_freq = 5500}, | 3937 | { .hw_value = 100, .center_freq = 5500, .max_power = 25 }, |
3858 | { .hw_value = 104, .center_freq = 5520}, | 3938 | { .hw_value = 104, .center_freq = 5520, .max_power = 25 }, |
3859 | { .hw_value = 108, .center_freq = 5540}, | 3939 | { .hw_value = 108, .center_freq = 5540, .max_power = 25 }, |
3860 | { .hw_value = 112, .center_freq = 5560}, | 3940 | { .hw_value = 112, .center_freq = 5560, .max_power = 25 }, |
3861 | { .hw_value = 116, .center_freq = 5580}, | 3941 | { .hw_value = 116, .center_freq = 5580, .max_power = 25 }, |
3862 | { .hw_value = 120, .center_freq = 5600}, | 3942 | { .hw_value = 120, .center_freq = 5600, .max_power = 25 }, |
3863 | { .hw_value = 124, .center_freq = 5620}, | 3943 | { .hw_value = 124, .center_freq = 5620, .max_power = 25 }, |
3864 | { .hw_value = 128, .center_freq = 5640}, | 3944 | { .hw_value = 128, .center_freq = 5640, .max_power = 25 }, |
3865 | { .hw_value = 132, .center_freq = 5660}, | 3945 | { .hw_value = 132, .center_freq = 5660, .max_power = 25 }, |
3866 | { .hw_value = 136, .center_freq = 5680}, | 3946 | { .hw_value = 136, .center_freq = 5680, .max_power = 25 }, |
3867 | { .hw_value = 140, .center_freq = 5700}, | 3947 | { .hw_value = 140, .center_freq = 5700, .max_power = 25 }, |
3868 | { .hw_value = 149, .center_freq = 5745}, | 3948 | { .hw_value = 149, .center_freq = 5745, .max_power = 25 }, |
3869 | { .hw_value = 153, .center_freq = 5765}, | 3949 | { .hw_value = 153, .center_freq = 5765, .max_power = 25 }, |
3870 | { .hw_value = 157, .center_freq = 5785}, | 3950 | { .hw_value = 157, .center_freq = 5785, .max_power = 25 }, |
3871 | { .hw_value = 161, .center_freq = 5805}, | 3951 | { .hw_value = 161, .center_freq = 5805, .max_power = 25 }, |
3872 | { .hw_value = 165, .center_freq = 5825}, | 3952 | { .hw_value = 165, .center_freq = 5825, .max_power = 25 }, |
3873 | }; | 3953 | }; |
3874 | 3954 | ||
3875 | /* mapping to indexes for wl1271_rates_5ghz */ | 3955 | /* mapping to indexes for wl1271_rates_5ghz */ |
@@ -3930,6 +4010,7 @@ static const struct ieee80211_ops wl1271_ops = { | |||
3930 | .tx = wl1271_op_tx, | 4010 | .tx = wl1271_op_tx, |
3931 | .set_key = wl1271_op_set_key, | 4011 | .set_key = wl1271_op_set_key, |
3932 | .hw_scan = wl1271_op_hw_scan, | 4012 | .hw_scan = wl1271_op_hw_scan, |
4013 | .cancel_hw_scan = wl1271_op_cancel_hw_scan, | ||
3933 | .sched_scan_start = wl1271_op_sched_scan_start, | 4014 | .sched_scan_start = wl1271_op_sched_scan_start, |
3934 | .sched_scan_stop = wl1271_op_sched_scan_stop, | 4015 | .sched_scan_stop = wl1271_op_sched_scan_stop, |
3935 | .bss_info_changed = wl1271_op_bss_info_changed, | 4016 | .bss_info_changed = wl1271_op_bss_info_changed, |
@@ -4327,6 +4408,9 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
4327 | wl->quirks = 0; | 4408 | wl->quirks = 0; |
4328 | wl->platform_quirks = 0; | 4409 | wl->platform_quirks = 0; |
4329 | wl->sched_scanning = false; | 4410 | wl->sched_scanning = false; |
4411 | wl->tx_security_seq = 0; | ||
4412 | wl->tx_security_last_seq_lsb = 0; | ||
4413 | |||
4330 | setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer, | 4414 | setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer, |
4331 | (unsigned long) wl); | 4415 | (unsigned long) wl); |
4332 | wl->fwlog_size = 0; | 4416 | wl->fwlog_size = 0; |
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c index 3e68a664c9de..3548377ab9c2 100644 --- a/drivers/net/wireless/wl12xx/ps.c +++ b/drivers/net/wireless/wl12xx/ps.c | |||
@@ -193,24 +193,27 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, | |||
193 | 193 | ||
194 | static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid) | 194 | static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid) |
195 | { | 195 | { |
196 | int i, filtered = 0; | 196 | int i; |
197 | struct sk_buff *skb; | 197 | struct sk_buff *skb; |
198 | struct ieee80211_tx_info *info; | 198 | struct ieee80211_tx_info *info; |
199 | unsigned long flags; | 199 | unsigned long flags; |
200 | int filtered[NUM_TX_QUEUES]; | ||
200 | 201 | ||
201 | /* filter all frames currently the low level queus for this hlid */ | 202 | /* filter all frames currently the low level queus for this hlid */ |
202 | for (i = 0; i < NUM_TX_QUEUES; i++) { | 203 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
204 | filtered[i] = 0; | ||
203 | while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) { | 205 | while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) { |
204 | info = IEEE80211_SKB_CB(skb); | 206 | info = IEEE80211_SKB_CB(skb); |
205 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | 207 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; |
206 | info->status.rates[0].idx = -1; | 208 | info->status.rates[0].idx = -1; |
207 | ieee80211_tx_status_ni(wl->hw, skb); | 209 | ieee80211_tx_status_ni(wl->hw, skb); |
208 | filtered++; | 210 | filtered[i]++; |
209 | } | 211 | } |
210 | } | 212 | } |
211 | 213 | ||
212 | spin_lock_irqsave(&wl->wl_lock, flags); | 214 | spin_lock_irqsave(&wl->wl_lock, flags); |
213 | wl->tx_queue_count -= filtered; | 215 | for (i = 0; i < NUM_TX_QUEUES; i++) |
216 | wl->tx_queue_count[i] -= filtered[i]; | ||
214 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 217 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
215 | 218 | ||
216 | wl1271_handle_tx_low_watermark(wl); | 219 | wl1271_handle_tx_low_watermark(wl); |
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index 5e5c66dd06d5..edfe01c321ca 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c | |||
@@ -321,6 +321,33 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | |||
321 | return 0; | 321 | return 0; |
322 | } | 322 | } |
323 | 323 | ||
324 | int wl1271_scan_stop(struct wl1271 *wl) | ||
325 | { | ||
326 | struct wl1271_cmd_header *cmd = NULL; | ||
327 | int ret = 0; | ||
328 | |||
329 | if (WARN_ON(wl->scan.state == WL1271_SCAN_STATE_IDLE)) | ||
330 | return -EINVAL; | ||
331 | |||
332 | wl1271_debug(DEBUG_CMD, "cmd scan stop"); | ||
333 | |||
334 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
335 | if (!cmd) { | ||
336 | ret = -ENOMEM; | ||
337 | goto out; | ||
338 | } | ||
339 | |||
340 | ret = wl1271_cmd_send(wl, CMD_STOP_SCAN, cmd, | ||
341 | sizeof(*cmd), 0); | ||
342 | if (ret < 0) { | ||
343 | wl1271_error("cmd stop_scan failed"); | ||
344 | goto out; | ||
345 | } | ||
346 | out: | ||
347 | kfree(cmd); | ||
348 | return ret; | ||
349 | } | ||
350 | |||
324 | static int | 351 | static int |
325 | wl1271_scan_get_sched_scan_channels(struct wl1271 *wl, | 352 | wl1271_scan_get_sched_scan_channels(struct wl1271 *wl, |
326 | struct cfg80211_sched_scan_request *req, | 353 | struct cfg80211_sched_scan_request *req, |
diff --git a/drivers/net/wireless/wl12xx/scan.h b/drivers/net/wireless/wl12xx/scan.h index ca81de20ebef..d882e4da71b7 100644 --- a/drivers/net/wireless/wl12xx/scan.h +++ b/drivers/net/wireless/wl12xx/scan.h | |||
@@ -28,6 +28,7 @@ | |||
28 | 28 | ||
29 | int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | 29 | int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, |
30 | struct cfg80211_scan_request *req); | 30 | struct cfg80211_scan_request *req); |
31 | int wl1271_scan_stop(struct wl1271 *wl); | ||
31 | int wl1271_scan_build_probe_req(struct wl1271 *wl, | 32 | int wl1271_scan_build_probe_req(struct wl1271 *wl, |
32 | const u8 *ssid, size_t ssid_len, | 33 | const u8 *ssid, size_t ssid_len, |
33 | const u8 *ie, size_t ie_len, u8 band); | 34 | const u8 *ie, size_t ie_len, u8 band); |
diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 4dc4573b6861..5cf18c2c23f0 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c | |||
@@ -166,13 +166,13 @@ static int wl1271_sdio_power_on(struct wl1271 *wl) | |||
166 | ret = pm_runtime_get_sync(&func->dev); | 166 | ret = pm_runtime_get_sync(&func->dev); |
167 | if (ret) | 167 | if (ret) |
168 | goto out; | 168 | goto out; |
169 | } else { | ||
170 | /* Runtime PM is disabled: power up the card manually */ | ||
171 | ret = mmc_power_restore_host(func->card->host); | ||
172 | if (ret < 0) | ||
173 | goto out; | ||
169 | } | 174 | } |
170 | 175 | ||
171 | /* Runtime PM might be disabled, so power up the card manually */ | ||
172 | ret = mmc_power_restore_host(func->card->host); | ||
173 | if (ret < 0) | ||
174 | goto out; | ||
175 | |||
176 | sdio_claim_host(func); | 176 | sdio_claim_host(func); |
177 | sdio_enable_func(func); | 177 | sdio_enable_func(func); |
178 | 178 | ||
@@ -188,7 +188,7 @@ static int wl1271_sdio_power_off(struct wl1271 *wl) | |||
188 | sdio_disable_func(func); | 188 | sdio_disable_func(func); |
189 | sdio_release_host(func); | 189 | sdio_release_host(func); |
190 | 190 | ||
191 | /* Runtime PM might be disabled, so power off the card manually */ | 191 | /* Power off the card manually, even if runtime PM is enabled. */ |
192 | ret = mmc_power_save_host(func->card->host); | 192 | ret = mmc_power_save_host(func->card->host); |
193 | if (ret < 0) | 193 | if (ret < 0) |
194 | return ret; | 194 | return ret; |
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 200590c0d9e3..48fde96ce0d4 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c | |||
@@ -168,7 +168,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, | |||
168 | u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; | 168 | u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; |
169 | u32 len; | 169 | u32 len; |
170 | u32 total_blocks; | 170 | u32 total_blocks; |
171 | int id, ret = -EBUSY; | 171 | int id, ret = -EBUSY, ac; |
172 | u32 spare_blocks; | 172 | u32 spare_blocks; |
173 | 173 | ||
174 | if (unlikely(wl->quirks & WL12XX_QUIRK_USE_2_SPARE_BLOCKS)) | 174 | if (unlikely(wl->quirks & WL12XX_QUIRK_USE_2_SPARE_BLOCKS)) |
@@ -206,7 +206,9 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, | |||
206 | desc->id = id; | 206 | desc->id = id; |
207 | 207 | ||
208 | wl->tx_blocks_available -= total_blocks; | 208 | wl->tx_blocks_available -= total_blocks; |
209 | wl->tx_allocated_blocks += total_blocks; | 209 | |
210 | ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); | ||
211 | wl->tx_allocated_blocks[ac] += total_blocks; | ||
210 | 212 | ||
211 | if (wl->bss_type == BSS_TYPE_AP_BSS) | 213 | if (wl->bss_type == BSS_TYPE_AP_BSS) |
212 | wl->links[hlid].allocated_blks += total_blocks; | 214 | wl->links[hlid].allocated_blks += total_blocks; |
@@ -383,6 +385,8 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, | |||
383 | if (ret < 0) | 385 | if (ret < 0) |
384 | return ret; | 386 | return ret; |
385 | 387 | ||
388 | wl1271_tx_fill_hdr(wl, skb, extra, info, hlid); | ||
389 | |||
386 | if (wl->bss_type == BSS_TYPE_AP_BSS) { | 390 | if (wl->bss_type == BSS_TYPE_AP_BSS) { |
387 | wl1271_tx_ap_update_inconnection_sta(wl, skb); | 391 | wl1271_tx_ap_update_inconnection_sta(wl, skb); |
388 | wl1271_tx_regulate_link(wl, hlid); | 392 | wl1271_tx_regulate_link(wl, hlid); |
@@ -390,8 +394,6 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, | |||
390 | wl1271_tx_update_filters(wl, skb); | 394 | wl1271_tx_update_filters(wl, skb); |
391 | } | 395 | } |
392 | 396 | ||
393 | wl1271_tx_fill_hdr(wl, skb, extra, info, hlid); | ||
394 | |||
395 | /* | 397 | /* |
396 | * The length of each packet is stored in terms of | 398 | * The length of each packet is stored in terms of |
397 | * words. Thus, we must pad the skb data to make sure its | 399 | * words. Thus, we must pad the skb data to make sure its |
@@ -442,37 +444,62 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) | |||
442 | void wl1271_handle_tx_low_watermark(struct wl1271 *wl) | 444 | void wl1271_handle_tx_low_watermark(struct wl1271 *wl) |
443 | { | 445 | { |
444 | unsigned long flags; | 446 | unsigned long flags; |
447 | int i; | ||
445 | 448 | ||
446 | if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) && | 449 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
447 | wl->tx_queue_count <= WL1271_TX_QUEUE_LOW_WATERMARK) { | 450 | if (test_bit(i, &wl->stopped_queues_map) && |
448 | /* firmware buffer has space, restart queues */ | 451 | wl->tx_queue_count[i] <= WL1271_TX_QUEUE_LOW_WATERMARK) { |
449 | spin_lock_irqsave(&wl->wl_lock, flags); | 452 | /* firmware buffer has space, restart queues */ |
450 | ieee80211_wake_queues(wl->hw); | 453 | spin_lock_irqsave(&wl->wl_lock, flags); |
451 | clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); | 454 | ieee80211_wake_queue(wl->hw, |
452 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 455 | wl1271_tx_get_mac80211_queue(i)); |
456 | clear_bit(i, &wl->stopped_queues_map); | ||
457 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
458 | } | ||
453 | } | 459 | } |
454 | } | 460 | } |
455 | 461 | ||
462 | static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl, | ||
463 | struct sk_buff_head *queues) | ||
464 | { | ||
465 | int i, q = -1; | ||
466 | u32 min_blks = 0xffffffff; | ||
467 | |||
468 | /* | ||
469 | * Find a non-empty ac where: | ||
470 | * 1. There are packets to transmit | ||
471 | * 2. The FW has the least allocated blocks | ||
472 | */ | ||
473 | for (i = 0; i < NUM_TX_QUEUES; i++) | ||
474 | if (!skb_queue_empty(&queues[i]) && | ||
475 | (wl->tx_allocated_blocks[i] < min_blks)) { | ||
476 | q = i; | ||
477 | min_blks = wl->tx_allocated_blocks[q]; | ||
478 | } | ||
479 | |||
480 | if (q == -1) | ||
481 | return NULL; | ||
482 | |||
483 | return &queues[q]; | ||
484 | } | ||
485 | |||
456 | static struct sk_buff *wl1271_sta_skb_dequeue(struct wl1271 *wl) | 486 | static struct sk_buff *wl1271_sta_skb_dequeue(struct wl1271 *wl) |
457 | { | 487 | { |
458 | struct sk_buff *skb = NULL; | 488 | struct sk_buff *skb = NULL; |
459 | unsigned long flags; | 489 | unsigned long flags; |
490 | struct sk_buff_head *queue; | ||
460 | 491 | ||
461 | skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VO]); | 492 | queue = wl1271_select_queue(wl, wl->tx_queue); |
462 | if (skb) | 493 | if (!queue) |
463 | goto out; | ||
464 | skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VI]); | ||
465 | if (skb) | ||
466 | goto out; | 494 | goto out; |
467 | skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BE]); | 495 | |
468 | if (skb) | 496 | skb = skb_dequeue(queue); |
469 | goto out; | ||
470 | skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BK]); | ||
471 | 497 | ||
472 | out: | 498 | out: |
473 | if (skb) { | 499 | if (skb) { |
500 | int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); | ||
474 | spin_lock_irqsave(&wl->wl_lock, flags); | 501 | spin_lock_irqsave(&wl->wl_lock, flags); |
475 | wl->tx_queue_count--; | 502 | wl->tx_queue_count[q]--; |
476 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 503 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
477 | } | 504 | } |
478 | 505 | ||
@@ -484,6 +511,7 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl) | |||
484 | struct sk_buff *skb = NULL; | 511 | struct sk_buff *skb = NULL; |
485 | unsigned long flags; | 512 | unsigned long flags; |
486 | int i, h, start_hlid; | 513 | int i, h, start_hlid; |
514 | struct sk_buff_head *queue; | ||
487 | 515 | ||
488 | /* start from the link after the last one */ | 516 | /* start from the link after the last one */ |
489 | start_hlid = (wl->last_tx_hlid + 1) % AP_MAX_LINKS; | 517 | start_hlid = (wl->last_tx_hlid + 1) % AP_MAX_LINKS; |
@@ -492,25 +520,25 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl) | |||
492 | for (i = 0; i < AP_MAX_LINKS; i++) { | 520 | for (i = 0; i < AP_MAX_LINKS; i++) { |
493 | h = (start_hlid + i) % AP_MAX_LINKS; | 521 | h = (start_hlid + i) % AP_MAX_LINKS; |
494 | 522 | ||
495 | skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VO]); | 523 | /* only consider connected stations */ |
496 | if (skb) | 524 | if (h >= WL1271_AP_STA_HLID_START && |
497 | goto out; | 525 | !test_bit(h - WL1271_AP_STA_HLID_START, wl->ap_hlid_map)) |
498 | skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VI]); | 526 | continue; |
499 | if (skb) | 527 | |
500 | goto out; | 528 | queue = wl1271_select_queue(wl, wl->links[h].tx_queue); |
501 | skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BE]); | 529 | if (!queue) |
502 | if (skb) | 530 | continue; |
503 | goto out; | 531 | |
504 | skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BK]); | 532 | skb = skb_dequeue(queue); |
505 | if (skb) | 533 | if (skb) |
506 | goto out; | 534 | break; |
507 | } | 535 | } |
508 | 536 | ||
509 | out: | ||
510 | if (skb) { | 537 | if (skb) { |
538 | int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); | ||
511 | wl->last_tx_hlid = h; | 539 | wl->last_tx_hlid = h; |
512 | spin_lock_irqsave(&wl->wl_lock, flags); | 540 | spin_lock_irqsave(&wl->wl_lock, flags); |
513 | wl->tx_queue_count--; | 541 | wl->tx_queue_count[q]--; |
514 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 542 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
515 | } else { | 543 | } else { |
516 | wl->last_tx_hlid = 0; | 544 | wl->last_tx_hlid = 0; |
@@ -531,9 +559,12 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl) | |||
531 | 559 | ||
532 | if (!skb && | 560 | if (!skb && |
533 | test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) { | 561 | test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) { |
562 | int q; | ||
563 | |||
534 | skb = wl->dummy_packet; | 564 | skb = wl->dummy_packet; |
565 | q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); | ||
535 | spin_lock_irqsave(&wl->wl_lock, flags); | 566 | spin_lock_irqsave(&wl->wl_lock, flags); |
536 | wl->tx_queue_count--; | 567 | wl->tx_queue_count[q]--; |
537 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 568 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
538 | } | 569 | } |
539 | 570 | ||
@@ -558,7 +589,7 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb) | |||
558 | } | 589 | } |
559 | 590 | ||
560 | spin_lock_irqsave(&wl->wl_lock, flags); | 591 | spin_lock_irqsave(&wl->wl_lock, flags); |
561 | wl->tx_queue_count++; | 592 | wl->tx_queue_count[q]++; |
562 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 593 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
563 | } | 594 | } |
564 | 595 | ||
@@ -704,10 +735,24 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
704 | 735 | ||
705 | wl->stats.retry_count += result->ack_failures; | 736 | wl->stats.retry_count += result->ack_failures; |
706 | 737 | ||
707 | /* update security sequence number */ | 738 | /* |
708 | wl->tx_security_seq += (result->lsb_security_sequence_number - | 739 | * update sequence number only when relevant, i.e. only in |
709 | wl->tx_security_last_seq); | 740 | * sessions of TKIP, AES and GEM (not in open or WEP sessions) |
710 | wl->tx_security_last_seq = result->lsb_security_sequence_number; | 741 | */ |
742 | if (info->control.hw_key && | ||
743 | (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP || | ||
744 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP || | ||
745 | info->control.hw_key->cipher == WL1271_CIPHER_SUITE_GEM)) { | ||
746 | u8 fw_lsb = result->tx_security_sequence_number_lsb; | ||
747 | u8 cur_lsb = wl->tx_security_last_seq_lsb; | ||
748 | |||
749 | /* | ||
750 | * update security sequence number, taking care of potential | ||
751 | * wrap-around | ||
752 | */ | ||
753 | wl->tx_security_seq += (fw_lsb - cur_lsb + 256) % 256; | ||
754 | wl->tx_security_last_seq_lsb = fw_lsb; | ||
755 | } | ||
711 | 756 | ||
712 | /* remove private header from packet */ | 757 | /* remove private header from packet */ |
713 | skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); | 758 | skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); |
@@ -772,23 +817,26 @@ void wl1271_tx_complete(struct wl1271 *wl) | |||
772 | void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid) | 817 | void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid) |
773 | { | 818 | { |
774 | struct sk_buff *skb; | 819 | struct sk_buff *skb; |
775 | int i, total = 0; | 820 | int i; |
776 | unsigned long flags; | 821 | unsigned long flags; |
777 | struct ieee80211_tx_info *info; | 822 | struct ieee80211_tx_info *info; |
823 | int total[NUM_TX_QUEUES]; | ||
778 | 824 | ||
779 | for (i = 0; i < NUM_TX_QUEUES; i++) { | 825 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
826 | total[i] = 0; | ||
780 | while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) { | 827 | while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) { |
781 | wl1271_debug(DEBUG_TX, "link freeing skb 0x%p", skb); | 828 | wl1271_debug(DEBUG_TX, "link freeing skb 0x%p", skb); |
782 | info = IEEE80211_SKB_CB(skb); | 829 | info = IEEE80211_SKB_CB(skb); |
783 | info->status.rates[0].idx = -1; | 830 | info->status.rates[0].idx = -1; |
784 | info->status.rates[0].count = 0; | 831 | info->status.rates[0].count = 0; |
785 | ieee80211_tx_status_ni(wl->hw, skb); | 832 | ieee80211_tx_status_ni(wl->hw, skb); |
786 | total++; | 833 | total[i]++; |
787 | } | 834 | } |
788 | } | 835 | } |
789 | 836 | ||
790 | spin_lock_irqsave(&wl->wl_lock, flags); | 837 | spin_lock_irqsave(&wl->wl_lock, flags); |
791 | wl->tx_queue_count -= total; | 838 | for (i = 0; i < NUM_TX_QUEUES; i++) |
839 | wl->tx_queue_count[i] -= total[i]; | ||
792 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 840 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
793 | 841 | ||
794 | wl1271_handle_tx_low_watermark(wl); | 842 | wl1271_handle_tx_low_watermark(wl); |
@@ -823,10 +871,11 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues) | |||
823 | ieee80211_tx_status_ni(wl->hw, skb); | 871 | ieee80211_tx_status_ni(wl->hw, skb); |
824 | } | 872 | } |
825 | } | 873 | } |
874 | wl->tx_queue_count[i] = 0; | ||
826 | } | 875 | } |
827 | } | 876 | } |
828 | 877 | ||
829 | wl->tx_queue_count = 0; | 878 | wl->stopped_queues_map = 0; |
830 | 879 | ||
831 | /* | 880 | /* |
832 | * Make sure the driver is at a consistent state, in case this | 881 | * Make sure the driver is at a consistent state, in case this |
@@ -879,8 +928,10 @@ void wl1271_tx_flush(struct wl1271 *wl) | |||
879 | while (!time_after(jiffies, timeout)) { | 928 | while (!time_after(jiffies, timeout)) { |
880 | mutex_lock(&wl->mutex); | 929 | mutex_lock(&wl->mutex); |
881 | wl1271_debug(DEBUG_TX, "flushing tx buffer: %d %d", | 930 | wl1271_debug(DEBUG_TX, "flushing tx buffer: %d %d", |
882 | wl->tx_frames_cnt, wl->tx_queue_count); | 931 | wl->tx_frames_cnt, |
883 | if ((wl->tx_frames_cnt == 0) && (wl->tx_queue_count == 0)) { | 932 | wl1271_tx_total_queue_count(wl)); |
933 | if ((wl->tx_frames_cnt == 0) && | ||
934 | (wl1271_tx_total_queue_count(wl) == 0)) { | ||
884 | mutex_unlock(&wl->mutex); | 935 | mutex_unlock(&wl->mutex); |
885 | return; | 936 | return; |
886 | } | 937 | } |
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index 832f9258d675..5d719b5a3d1d 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 |
@@ -182,6 +182,32 @@ static inline int wl1271_tx_get_queue(int queue) | |||
182 | } | 182 | } |
183 | } | 183 | } |
184 | 184 | ||
185 | static inline int wl1271_tx_get_mac80211_queue(int queue) | ||
186 | { | ||
187 | switch (queue) { | ||
188 | case CONF_TX_AC_VO: | ||
189 | return 0; | ||
190 | case CONF_TX_AC_VI: | ||
191 | return 1; | ||
192 | case CONF_TX_AC_BE: | ||
193 | return 2; | ||
194 | case CONF_TX_AC_BK: | ||
195 | return 3; | ||
196 | default: | ||
197 | return 2; | ||
198 | } | ||
199 | } | ||
200 | |||
201 | static inline int wl1271_tx_total_queue_count(struct wl1271 *wl) | ||
202 | { | ||
203 | int i, count = 0; | ||
204 | |||
205 | for (i = 0; i < NUM_TX_QUEUES; i++) | ||
206 | count += wl->tx_queue_count[i]; | ||
207 | |||
208 | return count; | ||
209 | } | ||
210 | |||
185 | void wl1271_tx_work(struct work_struct *work); | 211 | void wl1271_tx_work(struct work_struct *work); |
186 | void wl1271_tx_work_locked(struct wl1271 *wl); | 212 | void wl1271_tx_work_locked(struct wl1271 *wl); |
187 | void wl1271_tx_complete(struct wl1271 *wl); | 213 | void wl1271_tx_complete(struct wl1271 *wl); |
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index d7db6e77047a..1a8751eb8140 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 | ||
@@ -172,7 +173,6 @@ extern u32 wl12xx_debug_level; | |||
172 | #define WL1271_PS_STA_MAX_BLOCKS (2 * 9) | 173 | #define WL1271_PS_STA_MAX_BLOCKS (2 * 9) |
173 | 174 | ||
174 | #define WL1271_AP_BSS_INDEX 0 | 175 | #define WL1271_AP_BSS_INDEX 0 |
175 | #define WL1271_AP_DEF_INACTIV_SEC 300 | ||
176 | #define WL1271_AP_DEF_BEACON_EXP 20 | 176 | #define WL1271_AP_DEF_BEACON_EXP 20 |
177 | 177 | ||
178 | #define ACX_TX_DESCRIPTORS 32 | 178 | #define ACX_TX_DESCRIPTORS 32 |
@@ -424,7 +424,7 @@ struct wl1271 { | |||
424 | /* Accounting for allocated / available TX blocks on HW */ | 424 | /* Accounting for allocated / available TX blocks on HW */ |
425 | u32 tx_blocks_freed[NUM_TX_QUEUES]; | 425 | u32 tx_blocks_freed[NUM_TX_QUEUES]; |
426 | u32 tx_blocks_available; | 426 | u32 tx_blocks_available; |
427 | u32 tx_allocated_blocks; | 427 | u32 tx_allocated_blocks[NUM_TX_QUEUES]; |
428 | u32 tx_results_count; | 428 | u32 tx_results_count; |
429 | 429 | ||
430 | /* Transmitted TX packets counter for chipset interface */ | 430 | /* Transmitted TX packets counter for chipset interface */ |
@@ -438,7 +438,8 @@ struct wl1271 { | |||
438 | 438 | ||
439 | /* Frames scheduled for transmission, not handled yet */ | 439 | /* Frames scheduled for transmission, not handled yet */ |
440 | struct sk_buff_head tx_queue[NUM_TX_QUEUES]; | 440 | struct sk_buff_head tx_queue[NUM_TX_QUEUES]; |
441 | int tx_queue_count; | 441 | int tx_queue_count[NUM_TX_QUEUES]; |
442 | long stopped_queues_map; | ||
442 | 443 | ||
443 | /* Frames received, not handled yet by mac80211 */ | 444 | /* Frames received, not handled yet by mac80211 */ |
444 | struct sk_buff_head deferred_rx_queue; | 445 | struct sk_buff_head deferred_rx_queue; |
@@ -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; |
@@ -632,8 +640,8 @@ size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen); | |||
632 | 640 | ||
633 | #define WL1271_DEFAULT_POWER_LEVEL 0 | 641 | #define WL1271_DEFAULT_POWER_LEVEL 0 |
634 | 642 | ||
635 | #define WL1271_TX_QUEUE_LOW_WATERMARK 10 | 643 | #define WL1271_TX_QUEUE_LOW_WATERMARK 32 |
636 | #define WL1271_TX_QUEUE_HIGH_WATERMARK 25 | 644 | #define WL1271_TX_QUEUE_HIGH_WATERMARK 256 |
637 | 645 | ||
638 | #define WL1271_DEFERRED_QUEUE_LIMIT 64 | 646 | #define WL1271_DEFERRED_QUEUE_LIMIT 64 |
639 | 647 | ||