diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx/main.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 827 |
1 files changed, 682 insertions, 145 deletions
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 8b3c8d196b03..bc00e52f6445 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/vmalloc.h> | 30 | #include <linux/vmalloc.h> |
31 | #include <linux/platform_device.h> | 31 | #include <linux/platform_device.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/wl12xx.h> | ||
33 | 34 | ||
34 | #include "wl12xx.h" | 35 | #include "wl12xx.h" |
35 | #include "wl12xx_80211.h" | 36 | #include "wl12xx_80211.h" |
@@ -50,11 +51,11 @@ | |||
50 | 51 | ||
51 | static struct conf_drv_settings default_conf = { | 52 | static struct conf_drv_settings default_conf = { |
52 | .sg = { | 53 | .sg = { |
53 | .params = { | 54 | .sta_params = { |
54 | [CONF_SG_BT_PER_THRESHOLD] = 7500, | 55 | [CONF_SG_BT_PER_THRESHOLD] = 7500, |
55 | [CONF_SG_HV3_MAX_OVERRIDE] = 0, | 56 | [CONF_SG_HV3_MAX_OVERRIDE] = 0, |
56 | [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, | 57 | [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, |
57 | [CONF_SG_BT_LOAD_RATIO] = 50, | 58 | [CONF_SG_BT_LOAD_RATIO] = 200, |
58 | [CONF_SG_AUTO_PS_MODE] = 1, | 59 | [CONF_SG_AUTO_PS_MODE] = 1, |
59 | [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, | 60 | [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, |
60 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, | 61 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, |
@@ -100,6 +101,61 @@ static struct conf_drv_settings default_conf = { | |||
100 | [CONF_SG_DHCP_TIME] = 5000, | 101 | [CONF_SG_DHCP_TIME] = 5000, |
101 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, | 102 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, |
102 | }, | 103 | }, |
104 | .ap_params = { | ||
105 | [CONF_SG_BT_PER_THRESHOLD] = 7500, | ||
106 | [CONF_SG_HV3_MAX_OVERRIDE] = 0, | ||
107 | [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, | ||
108 | [CONF_SG_BT_LOAD_RATIO] = 50, | ||
109 | [CONF_SG_AUTO_PS_MODE] = 1, | ||
110 | [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, | ||
111 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, | ||
112 | [CONF_SG_ANTENNA_CONFIGURATION] = 0, | ||
113 | [CONF_SG_BEACON_MISS_PERCENT] = 60, | ||
114 | [CONF_SG_RATE_ADAPT_THRESH] = 64, | ||
115 | [CONF_SG_RATE_ADAPT_SNR] = 1, | ||
116 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR] = 10, | ||
117 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR] = 25, | ||
118 | [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR] = 25, | ||
119 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR] = 20, | ||
120 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR] = 25, | ||
121 | [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR] = 25, | ||
122 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR] = 7, | ||
123 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR] = 25, | ||
124 | [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR] = 25, | ||
125 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR] = 8, | ||
126 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR] = 25, | ||
127 | [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR] = 25, | ||
128 | [CONF_SG_RXT] = 1200, | ||
129 | [CONF_SG_TXT] = 1000, | ||
130 | [CONF_SG_ADAPTIVE_RXT_TXT] = 1, | ||
131 | [CONF_SG_PS_POLL_TIMEOUT] = 10, | ||
132 | [CONF_SG_UPSD_TIMEOUT] = 10, | ||
133 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR] = 7, | ||
134 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR] = 15, | ||
135 | [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR] = 15, | ||
136 | [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR] = 8, | ||
137 | [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR] = 20, | ||
138 | [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR] = 15, | ||
139 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR] = 20, | ||
140 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR] = 50, | ||
141 | [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR] = 10, | ||
142 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200, | ||
143 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP] = 800, | ||
144 | [CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME] = 75, | ||
145 | [CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME] = 15, | ||
146 | [CONF_SG_HV3_MAX_SERVED] = 6, | ||
147 | [CONF_SG_DHCP_TIME] = 5000, | ||
148 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, | ||
149 | [CONF_SG_TEMP_PARAM_1] = 0, | ||
150 | [CONF_SG_TEMP_PARAM_2] = 0, | ||
151 | [CONF_SG_TEMP_PARAM_3] = 0, | ||
152 | [CONF_SG_TEMP_PARAM_4] = 0, | ||
153 | [CONF_SG_TEMP_PARAM_5] = 0, | ||
154 | [CONF_SG_AP_BEACON_MISS_TX] = 3, | ||
155 | [CONF_SG_RX_WINDOW_LENGTH] = 6, | ||
156 | [CONF_SG_AP_CONNECTION_PROTECTION_TIME] = 50, | ||
157 | [CONF_SG_TEMP_PARAM_6] = 1, | ||
158 | }, | ||
103 | .state = CONF_SG_PROTECTIVE, | 159 | .state = CONF_SG_PROTECTIVE, |
104 | }, | 160 | }, |
105 | .rx = { | 161 | .rx = { |
@@ -107,7 +163,7 @@ static struct conf_drv_settings default_conf = { | |||
107 | .packet_detection_threshold = 0, | 163 | .packet_detection_threshold = 0, |
108 | .ps_poll_timeout = 15, | 164 | .ps_poll_timeout = 15, |
109 | .upsd_timeout = 15, | 165 | .upsd_timeout = 15, |
110 | .rts_threshold = 2347, | 166 | .rts_threshold = IEEE80211_MAX_RTS_THRESHOLD, |
111 | .rx_cca_threshold = 0, | 167 | .rx_cca_threshold = 0, |
112 | .irq_blk_threshold = 0xFFFF, | 168 | .irq_blk_threshold = 0xFFFF, |
113 | .irq_pkt_threshold = 0, | 169 | .irq_pkt_threshold = 0, |
@@ -153,44 +209,6 @@ static struct conf_drv_settings default_conf = { | |||
153 | .tx_op_limit = 1504, | 209 | .tx_op_limit = 1504, |
154 | }, | 210 | }, |
155 | }, | 211 | }, |
156 | .ap_rc_conf = { | ||
157 | [0] = { | ||
158 | .enabled_rates = CONF_TX_AP_ENABLED_RATES, | ||
159 | .short_retry_limit = 10, | ||
160 | .long_retry_limit = 10, | ||
161 | .aflags = 0, | ||
162 | }, | ||
163 | [1] = { | ||
164 | .enabled_rates = CONF_TX_AP_ENABLED_RATES, | ||
165 | .short_retry_limit = 10, | ||
166 | .long_retry_limit = 10, | ||
167 | .aflags = 0, | ||
168 | }, | ||
169 | [2] = { | ||
170 | .enabled_rates = CONF_TX_AP_ENABLED_RATES, | ||
171 | .short_retry_limit = 10, | ||
172 | .long_retry_limit = 10, | ||
173 | .aflags = 0, | ||
174 | }, | ||
175 | [3] = { | ||
176 | .enabled_rates = CONF_TX_AP_ENABLED_RATES, | ||
177 | .short_retry_limit = 10, | ||
178 | .long_retry_limit = 10, | ||
179 | .aflags = 0, | ||
180 | }, | ||
181 | }, | ||
182 | .ap_mgmt_conf = { | ||
183 | .enabled_rates = CONF_TX_AP_DEFAULT_MGMT_RATES, | ||
184 | .short_retry_limit = 10, | ||
185 | .long_retry_limit = 10, | ||
186 | .aflags = 0, | ||
187 | }, | ||
188 | .ap_bcst_conf = { | ||
189 | .enabled_rates = CONF_HW_BIT_RATE_1MBPS, | ||
190 | .short_retry_limit = 10, | ||
191 | .long_retry_limit = 10, | ||
192 | .aflags = 0, | ||
193 | }, | ||
194 | .ap_max_tx_retries = 100, | 212 | .ap_max_tx_retries = 100, |
195 | .tid_conf_count = 4, | 213 | .tid_conf_count = 4, |
196 | .tid_conf = { | 214 | .tid_conf = { |
@@ -239,12 +257,16 @@ static struct conf_drv_settings default_conf = { | |||
239 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | 257 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, |
240 | .listen_interval = 1, | 258 | .listen_interval = 1, |
241 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, | 259 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, |
242 | .bcn_filt_ie_count = 1, | 260 | .bcn_filt_ie_count = 2, |
243 | .bcn_filt_ie = { | 261 | .bcn_filt_ie = { |
244 | [0] = { | 262 | [0] = { |
245 | .ie = WLAN_EID_CHANNEL_SWITCH, | 263 | .ie = WLAN_EID_CHANNEL_SWITCH, |
246 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, | 264 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, |
247 | } | 265 | }, |
266 | [1] = { | ||
267 | .ie = WLAN_EID_HT_INFORMATION, | ||
268 | .rule = CONF_BCN_RULE_PASS_ON_CHANGE, | ||
269 | }, | ||
248 | }, | 270 | }, |
249 | .synch_fail_thold = 10, | 271 | .synch_fail_thold = 10, |
250 | .bss_lose_timeout = 100, | 272 | .bss_lose_timeout = 100, |
@@ -254,9 +276,9 @@ static struct conf_drv_settings default_conf = { | |||
254 | .ps_poll_threshold = 10, | 276 | .ps_poll_threshold = 10, |
255 | .ps_poll_recovery_period = 700, | 277 | .ps_poll_recovery_period = 700, |
256 | .bet_enable = CONF_BET_MODE_ENABLE, | 278 | .bet_enable = CONF_BET_MODE_ENABLE, |
257 | .bet_max_consecutive = 10, | 279 | .bet_max_consecutive = 50, |
258 | .psm_entry_retries = 5, | 280 | .psm_entry_retries = 5, |
259 | .psm_exit_retries = 255, | 281 | .psm_exit_retries = 16, |
260 | .psm_entry_nullfunc_retries = 3, | 282 | .psm_entry_nullfunc_retries = 3, |
261 | .psm_entry_hangover_period = 1, | 283 | .psm_entry_hangover_period = 1, |
262 | .keep_alive_interval = 55000, | 284 | .keep_alive_interval = 55000, |
@@ -284,6 +306,15 @@ static struct conf_drv_settings default_conf = { | |||
284 | .max_dwell_time_passive = 100000, | 306 | .max_dwell_time_passive = 100000, |
285 | .num_probe_reqs = 2, | 307 | .num_probe_reqs = 2, |
286 | }, | 308 | }, |
309 | .sched_scan = { | ||
310 | /* sched_scan requires dwell times in TU instead of TU/1000 */ | ||
311 | .min_dwell_time_active = 8, | ||
312 | .max_dwell_time_active = 30, | ||
313 | .dwell_time_passive = 100, | ||
314 | .num_probe_reqs = 2, | ||
315 | .rssi_threshold = -90, | ||
316 | .snr_threshold = 0, | ||
317 | }, | ||
287 | .rf = { | 318 | .rf = { |
288 | .tx_per_channel_power_compensation_2 = { | 319 | .tx_per_channel_power_compensation_2 = { |
289 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 320 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -298,19 +329,43 @@ static struct conf_drv_settings default_conf = { | |||
298 | .tx_ba_win_size = 64, | 329 | .tx_ba_win_size = 64, |
299 | .inactivity_timeout = 10000, | 330 | .inactivity_timeout = 10000, |
300 | }, | 331 | }, |
301 | .mem = { | 332 | .mem_wl127x = { |
302 | .num_stations = 1, | 333 | .num_stations = 1, |
303 | .ssid_profiles = 1, | 334 | .ssid_profiles = 1, |
304 | .rx_block_num = 70, | 335 | .rx_block_num = 70, |
305 | .tx_min_block_num = 40, | 336 | .tx_min_block_num = 40, |
306 | .dynamic_memory = 0, | 337 | .dynamic_memory = 1, |
307 | .min_req_tx_blocks = 100, | 338 | .min_req_tx_blocks = 100, |
308 | .min_req_rx_blocks = 22, | 339 | .min_req_rx_blocks = 22, |
309 | .tx_min = 27, | 340 | .tx_min = 27, |
310 | } | 341 | }, |
342 | .mem_wl128x = { | ||
343 | .num_stations = 1, | ||
344 | .ssid_profiles = 1, | ||
345 | .rx_block_num = 40, | ||
346 | .tx_min_block_num = 40, | ||
347 | .dynamic_memory = 1, | ||
348 | .min_req_tx_blocks = 45, | ||
349 | .min_req_rx_blocks = 22, | ||
350 | .tx_min = 27, | ||
351 | }, | ||
352 | .fm_coex = { | ||
353 | .enable = true, | ||
354 | .swallow_period = 5, | ||
355 | .n_divider_fref_set_1 = 0xff, /* default */ | ||
356 | .n_divider_fref_set_2 = 12, | ||
357 | .m_divider_fref_set_1 = 148, | ||
358 | .m_divider_fref_set_2 = 0xffff, /* default */ | ||
359 | .coex_pll_stabilization_time = 0xffffffff, /* default */ | ||
360 | .ldo_stabilization_time = 0xffff, /* default */ | ||
361 | .fm_disturbed_band_margin = 0xff, /* default */ | ||
362 | .swallow_clk_diff = 0xff, /* default */ | ||
363 | }, | ||
364 | .hci_io_ds = HCI_IO_DS_6MA, | ||
311 | }; | 365 | }; |
312 | 366 | ||
313 | static void __wl1271_op_remove_interface(struct wl1271 *wl); | 367 | static void __wl1271_op_remove_interface(struct wl1271 *wl, |
368 | bool reset_tx_queues); | ||
314 | static void wl1271_free_ap_keys(struct wl1271 *wl); | 369 | static void wl1271_free_ap_keys(struct wl1271 *wl); |
315 | 370 | ||
316 | 371 | ||
@@ -329,6 +384,7 @@ static struct platform_device wl1271_device = { | |||
329 | }, | 384 | }, |
330 | }; | 385 | }; |
331 | 386 | ||
387 | static DEFINE_MUTEX(wl_list_mutex); | ||
332 | static LIST_HEAD(wl_list); | 388 | static LIST_HEAD(wl_list); |
333 | 389 | ||
334 | static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, | 390 | static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, |
@@ -359,10 +415,12 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, | |||
359 | return NOTIFY_DONE; | 415 | return NOTIFY_DONE; |
360 | 416 | ||
361 | wl_temp = hw->priv; | 417 | wl_temp = hw->priv; |
418 | mutex_lock(&wl_list_mutex); | ||
362 | list_for_each_entry(wl, &wl_list, list) { | 419 | list_for_each_entry(wl, &wl_list, list) { |
363 | if (wl == wl_temp) | 420 | if (wl == wl_temp) |
364 | break; | 421 | break; |
365 | } | 422 | } |
423 | mutex_unlock(&wl_list_mutex); | ||
366 | if (wl != wl_temp) | 424 | if (wl != wl_temp) |
367 | return NOTIFY_DONE; | 425 | return NOTIFY_DONE; |
368 | 426 | ||
@@ -438,15 +496,30 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
438 | struct conf_tx_tid *conf_tid; | 496 | struct conf_tx_tid *conf_tid; |
439 | int ret, i; | 497 | int ret, i; |
440 | 498 | ||
441 | ret = wl1271_cmd_general_parms(wl); | 499 | if (wl->chip.id == CHIP_ID_1283_PG20) |
500 | ret = wl128x_cmd_general_parms(wl); | ||
501 | else | ||
502 | ret = wl1271_cmd_general_parms(wl); | ||
503 | if (ret < 0) | ||
504 | return ret; | ||
505 | |||
506 | if (wl->chip.id == CHIP_ID_1283_PG20) | ||
507 | ret = wl128x_cmd_radio_parms(wl); | ||
508 | else | ||
509 | ret = wl1271_cmd_radio_parms(wl); | ||
442 | if (ret < 0) | 510 | if (ret < 0) |
443 | return ret; | 511 | return ret; |
444 | 512 | ||
445 | ret = wl1271_cmd_radio_parms(wl); | 513 | if (wl->chip.id != CHIP_ID_1283_PG20) { |
514 | ret = wl1271_cmd_ext_radio_parms(wl); | ||
515 | if (ret < 0) | ||
516 | return ret; | ||
517 | } | ||
446 | if (ret < 0) | 518 | if (ret < 0) |
447 | return ret; | 519 | return ret; |
448 | 520 | ||
449 | ret = wl1271_cmd_ext_radio_parms(wl); | 521 | /* Chip-specific initializations */ |
522 | ret = wl1271_chip_specific_init(wl); | ||
450 | if (ret < 0) | 523 | if (ret < 0) |
451 | return ret; | 524 | return ret; |
452 | 525 | ||
@@ -477,6 +550,11 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
477 | if (ret < 0) | 550 | if (ret < 0) |
478 | goto out_free_memmap; | 551 | goto out_free_memmap; |
479 | 552 | ||
553 | /* FM WLAN coexistence */ | ||
554 | ret = wl1271_acx_fm_coex(wl); | ||
555 | if (ret < 0) | ||
556 | goto out_free_memmap; | ||
557 | |||
480 | /* Energy detection */ | 558 | /* Energy detection */ |
481 | ret = wl1271_init_energy_detection(wl); | 559 | ret = wl1271_init_energy_detection(wl); |
482 | if (ret < 0) | 560 | if (ret < 0) |
@@ -593,15 +671,17 @@ static void wl1271_fw_status(struct wl1271 *wl, | |||
593 | { | 671 | { |
594 | struct wl1271_fw_common_status *status = &full_status->common; | 672 | struct wl1271_fw_common_status *status = &full_status->common; |
595 | struct timespec ts; | 673 | struct timespec ts; |
596 | u32 total = 0; | 674 | u32 old_tx_blk_count = wl->tx_blocks_available; |
675 | u32 freed_blocks = 0; | ||
597 | int i; | 676 | int i; |
598 | 677 | ||
599 | if (wl->bss_type == BSS_TYPE_AP_BSS) | 678 | if (wl->bss_type == BSS_TYPE_AP_BSS) { |
600 | wl1271_raw_read(wl, FW_STATUS_ADDR, status, | 679 | wl1271_raw_read(wl, FW_STATUS_ADDR, status, |
601 | sizeof(struct wl1271_fw_ap_status), false); | 680 | sizeof(struct wl1271_fw_ap_status), false); |
602 | else | 681 | } else { |
603 | wl1271_raw_read(wl, FW_STATUS_ADDR, status, | 682 | wl1271_raw_read(wl, FW_STATUS_ADDR, status, |
604 | sizeof(struct wl1271_fw_sta_status), false); | 683 | sizeof(struct wl1271_fw_sta_status), false); |
684 | } | ||
605 | 685 | ||
606 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " | 686 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " |
607 | "drv_rx_counter = %d, tx_results_counter = %d)", | 687 | "drv_rx_counter = %d, tx_results_counter = %d)", |
@@ -612,22 +692,37 @@ static void wl1271_fw_status(struct wl1271 *wl, | |||
612 | 692 | ||
613 | /* update number of available TX blocks */ | 693 | /* update number of available TX blocks */ |
614 | for (i = 0; i < NUM_TX_QUEUES; i++) { | 694 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
615 | u32 cnt = le32_to_cpu(status->tx_released_blks[i]) - | 695 | freed_blocks += le32_to_cpu(status->tx_released_blks[i]) - |
616 | wl->tx_blocks_freed[i]; | 696 | wl->tx_blocks_freed[i]; |
617 | 697 | ||
618 | wl->tx_blocks_freed[i] = | 698 | wl->tx_blocks_freed[i] = |
619 | le32_to_cpu(status->tx_released_blks[i]); | 699 | le32_to_cpu(status->tx_released_blks[i]); |
620 | wl->tx_blocks_available += cnt; | ||
621 | total += cnt; | ||
622 | } | 700 | } |
623 | 701 | ||
624 | /* if more blocks are available now, tx work can be scheduled */ | 702 | wl->tx_allocated_blocks -= freed_blocks; |
625 | if (total) | ||
626 | clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); | ||
627 | 703 | ||
628 | /* for AP update num of allocated TX blocks per link and ps status */ | 704 | if (wl->bss_type == BSS_TYPE_AP_BSS) { |
629 | if (wl->bss_type == BSS_TYPE_AP_BSS) | 705 | /* Update num of allocated TX blocks per link and ps status */ |
630 | wl1271_irq_update_links_status(wl, &full_status->ap); | 706 | wl1271_irq_update_links_status(wl, &full_status->ap); |
707 | wl->tx_blocks_available += freed_blocks; | ||
708 | } else { | ||
709 | int avail = full_status->sta.tx_total - wl->tx_allocated_blocks; | ||
710 | |||
711 | /* | ||
712 | * The FW might change the total number of TX memblocks before | ||
713 | * we get a notification about blocks being released. Thus, the | ||
714 | * available blocks calculation might yield a temporary result | ||
715 | * which is lower than the actual available blocks. Keeping in | ||
716 | * mind that only blocks that were allocated can be moved from | ||
717 | * TX to RX, tx_blocks_available should never decrease here. | ||
718 | */ | ||
719 | wl->tx_blocks_available = max((int)wl->tx_blocks_available, | ||
720 | avail); | ||
721 | } | ||
722 | |||
723 | /* if more blocks are available now, tx work can be scheduled */ | ||
724 | if (wl->tx_blocks_available > old_tx_blk_count) | ||
725 | clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); | ||
631 | 726 | ||
632 | /* update the host-chipset time offset */ | 727 | /* update the host-chipset time offset */ |
633 | getnstimeofday(&ts); | 728 | getnstimeofday(&ts); |
@@ -674,6 +769,13 @@ irqreturn_t wl1271_irq(int irq, void *cookie) | |||
674 | set_bit(WL1271_FLAG_TX_PENDING, &wl->flags); | 769 | set_bit(WL1271_FLAG_TX_PENDING, &wl->flags); |
675 | cancel_work_sync(&wl->tx_work); | 770 | cancel_work_sync(&wl->tx_work); |
676 | 771 | ||
772 | /* | ||
773 | * In case edge triggered interrupt must be used, we cannot iterate | ||
774 | * more than once without introducing race conditions with the hardirq. | ||
775 | */ | ||
776 | if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) | ||
777 | loopcount = 1; | ||
778 | |||
677 | mutex_lock(&wl->mutex); | 779 | mutex_lock(&wl->mutex); |
678 | 780 | ||
679 | wl1271_debug(DEBUG_IRQ, "IRQ work"); | 781 | wl1271_debug(DEBUG_IRQ, "IRQ work"); |
@@ -785,11 +887,17 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) | |||
785 | 887 | ||
786 | switch (wl->bss_type) { | 888 | switch (wl->bss_type) { |
787 | case BSS_TYPE_AP_BSS: | 889 | case BSS_TYPE_AP_BSS: |
788 | fw_name = WL1271_AP_FW_NAME; | 890 | if (wl->chip.id == CHIP_ID_1283_PG20) |
891 | fw_name = WL128X_AP_FW_NAME; | ||
892 | else | ||
893 | fw_name = WL127X_AP_FW_NAME; | ||
789 | break; | 894 | break; |
790 | case BSS_TYPE_IBSS: | 895 | case BSS_TYPE_IBSS: |
791 | case BSS_TYPE_STA_BSS: | 896 | case BSS_TYPE_STA_BSS: |
792 | fw_name = WL1271_FW_NAME; | 897 | if (wl->chip.id == CHIP_ID_1283_PG20) |
898 | fw_name = WL128X_FW_NAME; | ||
899 | else | ||
900 | fw_name = WL1271_FW_NAME; | ||
793 | break; | 901 | break; |
794 | default: | 902 | default: |
795 | wl1271_error("no compatible firmware for bss_type %d", | 903 | wl1271_error("no compatible firmware for bss_type %d", |
@@ -838,14 +946,14 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) | |||
838 | const struct firmware *fw; | 946 | const struct firmware *fw; |
839 | int ret; | 947 | int ret; |
840 | 948 | ||
841 | ret = request_firmware(&fw, WL1271_NVS_NAME, wl1271_wl_to_dev(wl)); | 949 | ret = request_firmware(&fw, WL12XX_NVS_NAME, wl1271_wl_to_dev(wl)); |
842 | 950 | ||
843 | if (ret < 0) { | 951 | if (ret < 0) { |
844 | wl1271_error("could not get nvs file: %d", ret); | 952 | wl1271_error("could not get nvs file: %d", ret); |
845 | return ret; | 953 | return ret; |
846 | } | 954 | } |
847 | 955 | ||
848 | wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL); | 956 | wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL); |
849 | 957 | ||
850 | if (!wl->nvs) { | 958 | if (!wl->nvs) { |
851 | wl1271_error("could not allocate memory for the nvs file"); | 959 | wl1271_error("could not allocate memory for the nvs file"); |
@@ -871,15 +979,30 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
871 | if (wl->state != WL1271_STATE_ON) | 979 | if (wl->state != WL1271_STATE_ON) |
872 | goto out; | 980 | goto out; |
873 | 981 | ||
874 | wl1271_info("Hardware recovery in progress."); | 982 | wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x", |
983 | wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4)); | ||
875 | 984 | ||
876 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | 985 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) |
877 | ieee80211_connection_loss(wl->vif); | 986 | ieee80211_connection_loss(wl->vif); |
878 | 987 | ||
988 | /* Prevent spurious TX during FW restart */ | ||
989 | ieee80211_stop_queues(wl->hw); | ||
990 | |||
991 | if (wl->sched_scanning) { | ||
992 | ieee80211_sched_scan_stopped(wl->hw); | ||
993 | wl->sched_scanning = false; | ||
994 | } | ||
995 | |||
879 | /* reboot the chipset */ | 996 | /* reboot the chipset */ |
880 | __wl1271_op_remove_interface(wl); | 997 | __wl1271_op_remove_interface(wl, false); |
881 | ieee80211_restart_hw(wl->hw); | 998 | ieee80211_restart_hw(wl->hw); |
882 | 999 | ||
1000 | /* | ||
1001 | * Its safe to enable TX now - the queues are stopped after a request | ||
1002 | * to restart the HW. | ||
1003 | */ | ||
1004 | ieee80211_wake_queues(wl->hw); | ||
1005 | |||
883 | out: | 1006 | out: |
884 | mutex_unlock(&wl->mutex); | 1007 | mutex_unlock(&wl->mutex); |
885 | } | 1008 | } |
@@ -950,10 +1073,25 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
950 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", | 1073 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", |
951 | wl->chip.id); | 1074 | wl->chip.id); |
952 | 1075 | ||
1076 | /* end-of-transaction flag should be set in wl127x AP mode */ | ||
1077 | if (wl->bss_type == BSS_TYPE_AP_BSS) | ||
1078 | wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION; | ||
1079 | |||
953 | ret = wl1271_setup(wl); | 1080 | ret = wl1271_setup(wl); |
954 | if (ret < 0) | 1081 | if (ret < 0) |
955 | goto out; | 1082 | goto out; |
956 | break; | 1083 | break; |
1084 | case CHIP_ID_1283_PG20: | ||
1085 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)", | ||
1086 | wl->chip.id); | ||
1087 | |||
1088 | ret = wl1271_setup(wl); | ||
1089 | if (ret < 0) | ||
1090 | goto out; | ||
1091 | if (wl1271_set_block_size(wl)) | ||
1092 | wl->quirks |= WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT; | ||
1093 | break; | ||
1094 | case CHIP_ID_1283_PG10: | ||
957 | default: | 1095 | default: |
958 | wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); | 1096 | wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); |
959 | ret = -ENODEV; | 1097 | ret = -ENODEV; |
@@ -978,6 +1116,24 @@ out: | |||
978 | return ret; | 1116 | return ret; |
979 | } | 1117 | } |
980 | 1118 | ||
1119 | static unsigned int wl1271_get_fw_ver_quirks(struct wl1271 *wl) | ||
1120 | { | ||
1121 | unsigned int quirks = 0; | ||
1122 | unsigned int *fw_ver = wl->chip.fw_ver; | ||
1123 | |||
1124 | /* Only for wl127x */ | ||
1125 | if ((fw_ver[FW_VER_CHIP] == FW_VER_CHIP_WL127X) && | ||
1126 | /* Check STA version */ | ||
1127 | (((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) && | ||
1128 | (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_STA_MIN)) || | ||
1129 | /* Check AP version */ | ||
1130 | ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) && | ||
1131 | (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_AP_MIN)))) | ||
1132 | quirks |= WL12XX_QUIRK_USE_2_SPARE_BLOCKS; | ||
1133 | |||
1134 | return quirks; | ||
1135 | } | ||
1136 | |||
981 | int wl1271_plt_start(struct wl1271 *wl) | 1137 | int wl1271_plt_start(struct wl1271 *wl) |
982 | { | 1138 | { |
983 | int retries = WL1271_BOOT_RETRIES; | 1139 | int retries = WL1271_BOOT_RETRIES; |
@@ -1013,6 +1169,9 @@ int wl1271_plt_start(struct wl1271 *wl) | |||
1013 | wl->state = WL1271_STATE_PLT; | 1169 | wl->state = WL1271_STATE_PLT; |
1014 | wl1271_notice("firmware booted in PLT mode (%s)", | 1170 | wl1271_notice("firmware booted in PLT mode (%s)", |
1015 | wl->chip.fw_ver_str); | 1171 | wl->chip.fw_ver_str); |
1172 | |||
1173 | /* Check if any quirks are needed with older fw versions */ | ||
1174 | wl->quirks |= wl1271_get_fw_ver_quirks(wl); | ||
1016 | goto out; | 1175 | goto out; |
1017 | 1176 | ||
1018 | irq_disable: | 1177 | irq_disable: |
@@ -1040,7 +1199,7 @@ out: | |||
1040 | return ret; | 1199 | return ret; |
1041 | } | 1200 | } |
1042 | 1201 | ||
1043 | int __wl1271_plt_stop(struct wl1271 *wl) | 1202 | static int __wl1271_plt_stop(struct wl1271 *wl) |
1044 | { | 1203 | { |
1045 | int ret = 0; | 1204 | int ret = 0; |
1046 | 1205 | ||
@@ -1124,10 +1283,219 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1124 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 1283 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
1125 | } | 1284 | } |
1126 | 1285 | ||
1286 | int wl1271_tx_dummy_packet(struct wl1271 *wl) | ||
1287 | { | ||
1288 | unsigned long flags; | ||
1289 | |||
1290 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
1291 | set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags); | ||
1292 | wl->tx_queue_count++; | ||
1293 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
1294 | |||
1295 | /* The FW is low on RX memory blocks, so send the dummy packet asap */ | ||
1296 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags)) | ||
1297 | wl1271_tx_work_locked(wl); | ||
1298 | |||
1299 | /* | ||
1300 | * If the FW TX is busy, TX work will be scheduled by the threaded | ||
1301 | * interrupt handler function | ||
1302 | */ | ||
1303 | return 0; | ||
1304 | } | ||
1305 | |||
1306 | /* | ||
1307 | * The size of the dummy packet should be at least 1400 bytes. However, in | ||
1308 | * order to minimize the number of bus transactions, aligning it to 512 bytes | ||
1309 | * boundaries could be beneficial, performance wise | ||
1310 | */ | ||
1311 | #define TOTAL_TX_DUMMY_PACKET_SIZE (ALIGN(1400, 512)) | ||
1312 | |||
1313 | static struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl) | ||
1314 | { | ||
1315 | struct sk_buff *skb; | ||
1316 | struct ieee80211_hdr_3addr *hdr; | ||
1317 | unsigned int dummy_packet_size; | ||
1318 | |||
1319 | dummy_packet_size = TOTAL_TX_DUMMY_PACKET_SIZE - | ||
1320 | sizeof(struct wl1271_tx_hw_descr) - sizeof(*hdr); | ||
1321 | |||
1322 | skb = dev_alloc_skb(TOTAL_TX_DUMMY_PACKET_SIZE); | ||
1323 | if (!skb) { | ||
1324 | wl1271_warning("Failed to allocate a dummy packet skb"); | ||
1325 | return NULL; | ||
1326 | } | ||
1327 | |||
1328 | skb_reserve(skb, sizeof(struct wl1271_tx_hw_descr)); | ||
1329 | |||
1330 | hdr = (struct ieee80211_hdr_3addr *) skb_put(skb, sizeof(*hdr)); | ||
1331 | memset(hdr, 0, sizeof(*hdr)); | ||
1332 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | | ||
1333 | IEEE80211_STYPE_NULLFUNC | | ||
1334 | IEEE80211_FCTL_TODS); | ||
1335 | |||
1336 | memset(skb_put(skb, dummy_packet_size), 0, dummy_packet_size); | ||
1337 | |||
1338 | /* Dummy packets require the TID to be management */ | ||
1339 | skb->priority = WL1271_TID_MGMT; | ||
1340 | |||
1341 | /* Initialize all fields that might be used */ | ||
1342 | skb_set_queue_mapping(skb, 0); | ||
1343 | memset(IEEE80211_SKB_CB(skb), 0, sizeof(struct ieee80211_tx_info)); | ||
1344 | |||
1345 | return skb; | ||
1346 | } | ||
1347 | |||
1348 | |||
1127 | static struct notifier_block wl1271_dev_notifier = { | 1349 | static struct notifier_block wl1271_dev_notifier = { |
1128 | .notifier_call = wl1271_dev_notify, | 1350 | .notifier_call = wl1271_dev_notify, |
1129 | }; | 1351 | }; |
1130 | 1352 | ||
1353 | #ifdef CONFIG_PM | ||
1354 | static int wl1271_configure_suspend(struct wl1271 *wl) | ||
1355 | { | ||
1356 | int ret; | ||
1357 | |||
1358 | if (wl->bss_type != BSS_TYPE_STA_BSS) | ||
1359 | return 0; | ||
1360 | |||
1361 | mutex_lock(&wl->mutex); | ||
1362 | |||
1363 | ret = wl1271_ps_elp_wakeup(wl); | ||
1364 | if (ret < 0) | ||
1365 | goto out_unlock; | ||
1366 | |||
1367 | /* enter psm if needed*/ | ||
1368 | if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) { | ||
1369 | DECLARE_COMPLETION_ONSTACK(compl); | ||
1370 | |||
1371 | wl->ps_compl = &compl; | ||
1372 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, | ||
1373 | wl->basic_rate, true); | ||
1374 | if (ret < 0) | ||
1375 | goto out_sleep; | ||
1376 | |||
1377 | /* we must unlock here so we will be able to get events */ | ||
1378 | wl1271_ps_elp_sleep(wl); | ||
1379 | mutex_unlock(&wl->mutex); | ||
1380 | |||
1381 | ret = wait_for_completion_timeout( | ||
1382 | &compl, msecs_to_jiffies(WL1271_PS_COMPLETE_TIMEOUT)); | ||
1383 | if (ret <= 0) { | ||
1384 | wl1271_warning("couldn't enter ps mode!"); | ||
1385 | ret = -EBUSY; | ||
1386 | goto out; | ||
1387 | } | ||
1388 | |||
1389 | /* take mutex again, and wakeup */ | ||
1390 | mutex_lock(&wl->mutex); | ||
1391 | |||
1392 | ret = wl1271_ps_elp_wakeup(wl); | ||
1393 | if (ret < 0) | ||
1394 | goto out_unlock; | ||
1395 | } | ||
1396 | out_sleep: | ||
1397 | wl1271_ps_elp_sleep(wl); | ||
1398 | out_unlock: | ||
1399 | mutex_unlock(&wl->mutex); | ||
1400 | out: | ||
1401 | return ret; | ||
1402 | |||
1403 | } | ||
1404 | |||
1405 | static void wl1271_configure_resume(struct wl1271 *wl) | ||
1406 | { | ||
1407 | int ret; | ||
1408 | |||
1409 | if (wl->bss_type != BSS_TYPE_STA_BSS) | ||
1410 | return; | ||
1411 | |||
1412 | mutex_lock(&wl->mutex); | ||
1413 | ret = wl1271_ps_elp_wakeup(wl); | ||
1414 | if (ret < 0) | ||
1415 | goto out; | ||
1416 | |||
1417 | /* exit psm if it wasn't configured */ | ||
1418 | if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) | ||
1419 | wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, | ||
1420 | wl->basic_rate, true); | ||
1421 | |||
1422 | wl1271_ps_elp_sleep(wl); | ||
1423 | out: | ||
1424 | mutex_unlock(&wl->mutex); | ||
1425 | } | ||
1426 | |||
1427 | static int wl1271_op_suspend(struct ieee80211_hw *hw, | ||
1428 | struct cfg80211_wowlan *wow) | ||
1429 | { | ||
1430 | struct wl1271 *wl = hw->priv; | ||
1431 | wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); | ||
1432 | wl->wow_enabled = !!wow; | ||
1433 | if (wl->wow_enabled) { | ||
1434 | int ret; | ||
1435 | ret = wl1271_configure_suspend(wl); | ||
1436 | if (ret < 0) { | ||
1437 | wl1271_warning("couldn't prepare device to suspend"); | ||
1438 | return ret; | ||
1439 | } | ||
1440 | /* flush any remaining work */ | ||
1441 | wl1271_debug(DEBUG_MAC80211, "flushing remaining works"); | ||
1442 | flush_delayed_work(&wl->scan_complete_work); | ||
1443 | |||
1444 | /* | ||
1445 | * disable and re-enable interrupts in order to flush | ||
1446 | * the threaded_irq | ||
1447 | */ | ||
1448 | wl1271_disable_interrupts(wl); | ||
1449 | |||
1450 | /* | ||
1451 | * set suspended flag to avoid triggering a new threaded_irq | ||
1452 | * work. no need for spinlock as interrupts are disabled. | ||
1453 | */ | ||
1454 | set_bit(WL1271_FLAG_SUSPENDED, &wl->flags); | ||
1455 | |||
1456 | wl1271_enable_interrupts(wl); | ||
1457 | flush_work(&wl->tx_work); | ||
1458 | flush_delayed_work(&wl->pspoll_work); | ||
1459 | flush_delayed_work(&wl->elp_work); | ||
1460 | } | ||
1461 | return 0; | ||
1462 | } | ||
1463 | |||
1464 | static int wl1271_op_resume(struct ieee80211_hw *hw) | ||
1465 | { | ||
1466 | struct wl1271 *wl = hw->priv; | ||
1467 | wl1271_debug(DEBUG_MAC80211, "mac80211 resume wow=%d", | ||
1468 | wl->wow_enabled); | ||
1469 | |||
1470 | /* | ||
1471 | * re-enable irq_work enqueuing, and call irq_work directly if | ||
1472 | * there is a pending work. | ||
1473 | */ | ||
1474 | if (wl->wow_enabled) { | ||
1475 | struct wl1271 *wl = hw->priv; | ||
1476 | unsigned long flags; | ||
1477 | bool run_irq_work = false; | ||
1478 | |||
1479 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
1480 | clear_bit(WL1271_FLAG_SUSPENDED, &wl->flags); | ||
1481 | if (test_and_clear_bit(WL1271_FLAG_PENDING_WORK, &wl->flags)) | ||
1482 | run_irq_work = true; | ||
1483 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
1484 | |||
1485 | if (run_irq_work) { | ||
1486 | wl1271_debug(DEBUG_MAC80211, | ||
1487 | "run postponed irq_work directly"); | ||
1488 | wl1271_irq(0, wl); | ||
1489 | wl1271_enable_interrupts(wl); | ||
1490 | } | ||
1491 | |||
1492 | wl1271_configure_resume(wl); | ||
1493 | } | ||
1494 | |||
1495 | return 0; | ||
1496 | } | ||
1497 | #endif | ||
1498 | |||
1131 | static int wl1271_op_start(struct ieee80211_hw *hw) | 1499 | static int wl1271_op_start(struct ieee80211_hw *hw) |
1132 | { | 1500 | { |
1133 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); | 1501 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); |
@@ -1174,6 +1542,16 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
1174 | goto out; | 1542 | goto out; |
1175 | } | 1543 | } |
1176 | 1544 | ||
1545 | /* | ||
1546 | * in some very corner case HW recovery scenarios its possible to | ||
1547 | * get here before __wl1271_op_remove_interface is complete, so | ||
1548 | * opt out if that is the case. | ||
1549 | */ | ||
1550 | if (test_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags)) { | ||
1551 | ret = -EBUSY; | ||
1552 | goto out; | ||
1553 | } | ||
1554 | |||
1177 | switch (vif->type) { | 1555 | switch (vif->type) { |
1178 | case NL80211_IFTYPE_STATION: | 1556 | case NL80211_IFTYPE_STATION: |
1179 | wl->bss_type = BSS_TYPE_STA_BSS; | 1557 | wl->bss_type = BSS_TYPE_STA_BSS; |
@@ -1242,6 +1620,7 @@ power_off: | |||
1242 | 1620 | ||
1243 | wl->vif = vif; | 1621 | wl->vif = vif; |
1244 | wl->state = WL1271_STATE_ON; | 1622 | wl->state = WL1271_STATE_ON; |
1623 | set_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags); | ||
1245 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver_str); | 1624 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver_str); |
1246 | 1625 | ||
1247 | /* update hw/fw version info in wiphy struct */ | 1626 | /* update hw/fw version info in wiphy struct */ |
@@ -1249,6 +1628,9 @@ power_off: | |||
1249 | strncpy(wiphy->fw_version, wl->chip.fw_ver_str, | 1628 | strncpy(wiphy->fw_version, wl->chip.fw_ver_str, |
1250 | sizeof(wiphy->fw_version)); | 1629 | sizeof(wiphy->fw_version)); |
1251 | 1630 | ||
1631 | /* Check if any quirks are needed with older fw versions */ | ||
1632 | wl->quirks |= wl1271_get_fw_ver_quirks(wl); | ||
1633 | |||
1252 | /* | 1634 | /* |
1253 | * Now we know if 11a is supported (info from the NVS), so disable | 1635 | * Now we know if 11a is supported (info from the NVS), so disable |
1254 | * 11a channels if not supported | 1636 | * 11a channels if not supported |
@@ -1262,23 +1644,30 @@ power_off: | |||
1262 | out: | 1644 | out: |
1263 | mutex_unlock(&wl->mutex); | 1645 | mutex_unlock(&wl->mutex); |
1264 | 1646 | ||
1647 | mutex_lock(&wl_list_mutex); | ||
1265 | if (!ret) | 1648 | if (!ret) |
1266 | list_add(&wl->list, &wl_list); | 1649 | list_add(&wl->list, &wl_list); |
1650 | mutex_unlock(&wl_list_mutex); | ||
1267 | 1651 | ||
1268 | return ret; | 1652 | return ret; |
1269 | } | 1653 | } |
1270 | 1654 | ||
1271 | static void __wl1271_op_remove_interface(struct wl1271 *wl) | 1655 | static void __wl1271_op_remove_interface(struct wl1271 *wl, |
1656 | bool reset_tx_queues) | ||
1272 | { | 1657 | { |
1273 | int i; | 1658 | int i; |
1274 | 1659 | ||
1275 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); | 1660 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); |
1276 | 1661 | ||
1662 | /* because of hardware recovery, we may get here twice */ | ||
1663 | if (wl->state != WL1271_STATE_ON) | ||
1664 | return; | ||
1665 | |||
1277 | wl1271_info("down"); | 1666 | wl1271_info("down"); |
1278 | 1667 | ||
1668 | mutex_lock(&wl_list_mutex); | ||
1279 | list_del(&wl->list); | 1669 | list_del(&wl->list); |
1280 | 1670 | mutex_unlock(&wl_list_mutex); | |
1281 | WARN_ON(wl->state != WL1271_STATE_ON); | ||
1282 | 1671 | ||
1283 | /* enable dyn ps just in case (if left on due to fw crash etc) */ | 1672 | /* enable dyn ps just in case (if left on due to fw crash etc) */ |
1284 | if (wl->bss_type == BSS_TYPE_STA_BSS) | 1673 | if (wl->bss_type == BSS_TYPE_STA_BSS) |
@@ -1286,12 +1675,15 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) | |||
1286 | 1675 | ||
1287 | if (wl->scan.state != WL1271_SCAN_STATE_IDLE) { | 1676 | if (wl->scan.state != WL1271_SCAN_STATE_IDLE) { |
1288 | wl->scan.state = WL1271_SCAN_STATE_IDLE; | 1677 | wl->scan.state = WL1271_SCAN_STATE_IDLE; |
1289 | kfree(wl->scan.scanned_ch); | 1678 | memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); |
1290 | wl->scan.scanned_ch = NULL; | ||
1291 | wl->scan.req = NULL; | 1679 | wl->scan.req = NULL; |
1292 | ieee80211_scan_completed(wl->hw, true); | 1680 | ieee80211_scan_completed(wl->hw, true); |
1293 | } | 1681 | } |
1294 | 1682 | ||
1683 | /* | ||
1684 | * this must be before the cancel_work calls below, so that the work | ||
1685 | * functions don't perform further work. | ||
1686 | */ | ||
1295 | wl->state = WL1271_STATE_OFF; | 1687 | wl->state = WL1271_STATE_OFF; |
1296 | 1688 | ||
1297 | mutex_unlock(&wl->mutex); | 1689 | mutex_unlock(&wl->mutex); |
@@ -1307,7 +1699,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) | |||
1307 | mutex_lock(&wl->mutex); | 1699 | mutex_lock(&wl->mutex); |
1308 | 1700 | ||
1309 | /* let's notify MAC80211 about the remaining pending TX frames */ | 1701 | /* let's notify MAC80211 about the remaining pending TX frames */ |
1310 | wl1271_tx_reset(wl); | 1702 | wl1271_tx_reset(wl, reset_tx_queues); |
1311 | wl1271_power_off(wl); | 1703 | wl1271_power_off(wl); |
1312 | 1704 | ||
1313 | memset(wl->bssid, 0, ETH_ALEN); | 1705 | memset(wl->bssid, 0, ETH_ALEN); |
@@ -1321,6 +1713,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) | |||
1321 | wl->psm_entry_retry = 0; | 1713 | wl->psm_entry_retry = 0; |
1322 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 1714 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
1323 | wl->tx_blocks_available = 0; | 1715 | wl->tx_blocks_available = 0; |
1716 | wl->tx_allocated_blocks = 0; | ||
1324 | wl->tx_results_count = 0; | 1717 | wl->tx_results_count = 0; |
1325 | wl->tx_packets_count = 0; | 1718 | wl->tx_packets_count = 0; |
1326 | wl->tx_security_last_seq = 0; | 1719 | wl->tx_security_last_seq = 0; |
@@ -1328,13 +1721,20 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) | |||
1328 | wl->time_offset = 0; | 1721 | wl->time_offset = 0; |
1329 | wl->session_counter = 0; | 1722 | wl->session_counter = 0; |
1330 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 1723 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; |
1331 | wl->flags = 0; | ||
1332 | wl->vif = NULL; | 1724 | wl->vif = NULL; |
1333 | wl->filters = 0; | 1725 | wl->filters = 0; |
1334 | wl1271_free_ap_keys(wl); | 1726 | wl1271_free_ap_keys(wl); |
1335 | memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); | 1727 | memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); |
1336 | wl->ap_fw_ps_map = 0; | 1728 | wl->ap_fw_ps_map = 0; |
1337 | wl->ap_ps_map = 0; | 1729 | wl->ap_ps_map = 0; |
1730 | wl->sched_scanning = false; | ||
1731 | |||
1732 | /* | ||
1733 | * this is performed after the cancel_work calls and the associated | ||
1734 | * mutex_lock, so that wl1271_op_add_interface does not accidentally | ||
1735 | * get executed before all these vars have been reset. | ||
1736 | */ | ||
1737 | wl->flags = 0; | ||
1338 | 1738 | ||
1339 | for (i = 0; i < NUM_TX_QUEUES; i++) | 1739 | for (i = 0; i < NUM_TX_QUEUES; i++) |
1340 | wl->tx_blocks_freed[i] = 0; | 1740 | wl->tx_blocks_freed[i] = 0; |
@@ -1361,14 +1761,14 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
1361 | */ | 1761 | */ |
1362 | if (wl->vif) { | 1762 | if (wl->vif) { |
1363 | WARN_ON(wl->vif != vif); | 1763 | WARN_ON(wl->vif != vif); |
1364 | __wl1271_op_remove_interface(wl); | 1764 | __wl1271_op_remove_interface(wl, true); |
1365 | } | 1765 | } |
1366 | 1766 | ||
1367 | mutex_unlock(&wl->mutex); | 1767 | mutex_unlock(&wl->mutex); |
1368 | cancel_work_sync(&wl->recovery_work); | 1768 | cancel_work_sync(&wl->recovery_work); |
1369 | } | 1769 | } |
1370 | 1770 | ||
1371 | static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) | 1771 | void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) |
1372 | { | 1772 | { |
1373 | wl1271_set_default_filters(wl); | 1773 | wl1271_set_default_filters(wl); |
1374 | 1774 | ||
@@ -1431,10 +1831,10 @@ static int wl1271_join(struct wl1271 *wl, bool set_assoc) | |||
1431 | * One of the side effects of the JOIN command is that is clears | 1831 | * One of the side effects of the JOIN command is that is clears |
1432 | * WPA/WPA2 keys from the chipset. Performing a JOIN while associated | 1832 | * WPA/WPA2 keys from the chipset. Performing a JOIN while associated |
1433 | * to a WPA/WPA2 access point will therefore kill the data-path. | 1833 | * to a WPA/WPA2 access point will therefore kill the data-path. |
1434 | * Currently there is no supported scenario for JOIN during | 1834 | * Currently the only valid scenario for JOIN during association |
1435 | * association - if it becomes a supported scenario, the WPA/WPA2 keys | 1835 | * is on roaming, in which case we will also be given new keys. |
1436 | * must be handled somehow. | 1836 | * Keep the below message for now, unless it starts bothering |
1437 | * | 1837 | * users who really like to roam a lot :) |
1438 | */ | 1838 | */ |
1439 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | 1839 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) |
1440 | wl1271_info("JOIN while associated."); | 1840 | wl1271_info("JOIN while associated."); |
@@ -1490,7 +1890,7 @@ static int wl1271_unjoin(struct wl1271 *wl) | |||
1490 | clear_bit(WL1271_FLAG_JOINED, &wl->flags); | 1890 | clear_bit(WL1271_FLAG_JOINED, &wl->flags); |
1491 | memset(wl->bssid, 0, ETH_ALEN); | 1891 | memset(wl->bssid, 0, ETH_ALEN); |
1492 | 1892 | ||
1493 | /* stop filterting packets based on bssid */ | 1893 | /* stop filtering packets based on bssid */ |
1494 | wl1271_configure_filters(wl, FIF_OTHER_BSS); | 1894 | wl1271_configure_filters(wl, FIF_OTHER_BSS); |
1495 | 1895 | ||
1496 | out: | 1896 | out: |
@@ -1530,6 +1930,13 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle) | |||
1530 | wl->session_counter++; | 1930 | wl->session_counter++; |
1531 | if (wl->session_counter >= SESSION_COUNTER_MAX) | 1931 | if (wl->session_counter >= SESSION_COUNTER_MAX) |
1532 | wl->session_counter = 0; | 1932 | wl->session_counter = 0; |
1933 | |||
1934 | /* The current firmware only supports sched_scan in idle */ | ||
1935 | if (wl->sched_scanning) { | ||
1936 | wl1271_scan_sched_scan_stop(wl); | ||
1937 | ieee80211_sched_scan_stopped(wl->hw); | ||
1938 | } | ||
1939 | |||
1533 | ret = wl1271_dummy_join(wl); | 1940 | ret = wl1271_dummy_join(wl); |
1534 | if (ret < 0) | 1941 | if (ret < 0) |
1535 | goto out; | 1942 | goto out; |
@@ -1569,7 +1976,12 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1569 | mutex_lock(&wl->mutex); | 1976 | mutex_lock(&wl->mutex); |
1570 | 1977 | ||
1571 | if (unlikely(wl->state == WL1271_STATE_OFF)) { | 1978 | if (unlikely(wl->state == WL1271_STATE_OFF)) { |
1572 | ret = -EAGAIN; | 1979 | /* we support configuring the channel and band while off */ |
1980 | if ((changed & IEEE80211_CONF_CHANGE_CHANNEL)) { | ||
1981 | wl->band = conf->channel->band; | ||
1982 | wl->channel = channel; | ||
1983 | } | ||
1984 | |||
1573 | goto out; | 1985 | goto out; |
1574 | } | 1986 | } |
1575 | 1987 | ||
@@ -2077,6 +2489,60 @@ out: | |||
2077 | return ret; | 2489 | return ret; |
2078 | } | 2490 | } |
2079 | 2491 | ||
2492 | static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw, | ||
2493 | struct ieee80211_vif *vif, | ||
2494 | struct cfg80211_sched_scan_request *req, | ||
2495 | struct ieee80211_sched_scan_ies *ies) | ||
2496 | { | ||
2497 | struct wl1271 *wl = hw->priv; | ||
2498 | int ret; | ||
2499 | |||
2500 | wl1271_debug(DEBUG_MAC80211, "wl1271_op_sched_scan_start"); | ||
2501 | |||
2502 | mutex_lock(&wl->mutex); | ||
2503 | |||
2504 | ret = wl1271_ps_elp_wakeup(wl); | ||
2505 | if (ret < 0) | ||
2506 | goto out; | ||
2507 | |||
2508 | ret = wl1271_scan_sched_scan_config(wl, req, ies); | ||
2509 | if (ret < 0) | ||
2510 | goto out_sleep; | ||
2511 | |||
2512 | ret = wl1271_scan_sched_scan_start(wl); | ||
2513 | if (ret < 0) | ||
2514 | goto out_sleep; | ||
2515 | |||
2516 | wl->sched_scanning = true; | ||
2517 | |||
2518 | out_sleep: | ||
2519 | wl1271_ps_elp_sleep(wl); | ||
2520 | out: | ||
2521 | mutex_unlock(&wl->mutex); | ||
2522 | return ret; | ||
2523 | } | ||
2524 | |||
2525 | static void wl1271_op_sched_scan_stop(struct ieee80211_hw *hw, | ||
2526 | struct ieee80211_vif *vif) | ||
2527 | { | ||
2528 | struct wl1271 *wl = hw->priv; | ||
2529 | int ret; | ||
2530 | |||
2531 | wl1271_debug(DEBUG_MAC80211, "wl1271_op_sched_scan_stop"); | ||
2532 | |||
2533 | mutex_lock(&wl->mutex); | ||
2534 | |||
2535 | ret = wl1271_ps_elp_wakeup(wl); | ||
2536 | if (ret < 0) | ||
2537 | goto out; | ||
2538 | |||
2539 | wl1271_scan_sched_scan_stop(wl); | ||
2540 | |||
2541 | wl1271_ps_elp_sleep(wl); | ||
2542 | out: | ||
2543 | mutex_unlock(&wl->mutex); | ||
2544 | } | ||
2545 | |||
2080 | static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value) | 2546 | static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value) |
2081 | { | 2547 | { |
2082 | struct wl1271 *wl = hw->priv; | 2548 | struct wl1271 *wl = hw->priv; |
@@ -2093,7 +2559,7 @@ static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value) | |||
2093 | if (ret < 0) | 2559 | if (ret < 0) |
2094 | goto out; | 2560 | goto out; |
2095 | 2561 | ||
2096 | ret = wl1271_acx_frag_threshold(wl, (u16)value); | 2562 | ret = wl1271_acx_frag_threshold(wl, value); |
2097 | if (ret < 0) | 2563 | if (ret < 0) |
2098 | wl1271_warning("wl1271_op_set_frag_threshold failed: %d", ret); | 2564 | wl1271_warning("wl1271_op_set_frag_threshold failed: %d", ret); |
2099 | 2565 | ||
@@ -2121,7 +2587,7 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | |||
2121 | if (ret < 0) | 2587 | if (ret < 0) |
2122 | goto out; | 2588 | goto out; |
2123 | 2589 | ||
2124 | ret = wl1271_acx_rts_threshold(wl, (u16) value); | 2590 | ret = wl1271_acx_rts_threshold(wl, value); |
2125 | if (ret < 0) | 2591 | if (ret < 0) |
2126 | wl1271_warning("wl1271_op_set_rts_threshold failed: %d", ret); | 2592 | wl1271_warning("wl1271_op_set_rts_threshold failed: %d", ret); |
2127 | 2593 | ||
@@ -2136,20 +2602,24 @@ out: | |||
2136 | static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, | 2602 | static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, |
2137 | int offset) | 2603 | int offset) |
2138 | { | 2604 | { |
2139 | u8 *ptr = skb->data + offset; | 2605 | u8 ssid_len; |
2606 | const u8 *ptr = cfg80211_find_ie(WLAN_EID_SSID, skb->data + offset, | ||
2607 | skb->len - offset); | ||
2140 | 2608 | ||
2141 | /* find the location of the ssid in the beacon */ | 2609 | if (!ptr) { |
2142 | while (ptr < skb->data + skb->len) { | 2610 | wl1271_error("No SSID in IEs!"); |
2143 | if (ptr[0] == WLAN_EID_SSID) { | 2611 | return -ENOENT; |
2144 | wl->ssid_len = ptr[1]; | ||
2145 | memcpy(wl->ssid, ptr+2, wl->ssid_len); | ||
2146 | return 0; | ||
2147 | } | ||
2148 | ptr += (ptr[1] + 2); | ||
2149 | } | 2612 | } |
2150 | 2613 | ||
2151 | wl1271_error("No SSID in IEs!\n"); | 2614 | ssid_len = ptr[1]; |
2152 | return -ENOENT; | 2615 | if (ssid_len > IEEE80211_MAX_SSID_LEN) { |
2616 | wl1271_error("SSID is too long!"); | ||
2617 | return -EINVAL; | ||
2618 | } | ||
2619 | |||
2620 | wl->ssid_len = ssid_len; | ||
2621 | memcpy(wl->ssid, ptr+2, ssid_len); | ||
2622 | return 0; | ||
2153 | } | 2623 | } |
2154 | 2624 | ||
2155 | static int wl1271_bss_erp_info_changed(struct wl1271 *wl, | 2625 | static int wl1271_bss_erp_info_changed(struct wl1271 *wl, |
@@ -2264,24 +2734,19 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, | |||
2264 | 2734 | ||
2265 | if ((changed & BSS_CHANGED_BASIC_RATES)) { | 2735 | if ((changed & BSS_CHANGED_BASIC_RATES)) { |
2266 | u32 rates = bss_conf->basic_rates; | 2736 | u32 rates = bss_conf->basic_rates; |
2267 | struct conf_tx_rate_class mgmt_rc; | ||
2268 | 2737 | ||
2269 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates); | 2738 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates); |
2270 | wl->basic_rate = wl1271_tx_min_rate_get(wl); | 2739 | wl->basic_rate = wl1271_tx_min_rate_get(wl); |
2271 | wl1271_debug(DEBUG_AP, "basic rates: 0x%x", | 2740 | |
2272 | wl->basic_rate_set); | 2741 | ret = wl1271_init_ap_rates(wl); |
2273 | |||
2274 | /* update the AP management rate policy with the new rates */ | ||
2275 | mgmt_rc.enabled_rates = wl->basic_rate_set; | ||
2276 | mgmt_rc.long_retry_limit = 10; | ||
2277 | mgmt_rc.short_retry_limit = 10; | ||
2278 | mgmt_rc.aflags = 0; | ||
2279 | ret = wl1271_acx_ap_rate_policy(wl, &mgmt_rc, | ||
2280 | ACX_TX_AP_MODE_MGMT_RATE); | ||
2281 | if (ret < 0) { | 2742 | if (ret < 0) { |
2282 | wl1271_error("AP mgmt policy change failed %d", ret); | 2743 | wl1271_error("AP rate policy change failed %d", ret); |
2283 | goto out; | 2744 | goto out; |
2284 | } | 2745 | } |
2746 | |||
2747 | ret = wl1271_ap_init_templates(wl); | ||
2748 | if (ret < 0) | ||
2749 | goto out; | ||
2285 | } | 2750 | } |
2286 | 2751 | ||
2287 | ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, changed); | 2752 | ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, changed); |
@@ -2314,6 +2779,24 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, | |||
2314 | } | 2779 | } |
2315 | } | 2780 | } |
2316 | 2781 | ||
2782 | if (changed & BSS_CHANGED_IBSS) { | ||
2783 | wl1271_debug(DEBUG_ADHOC, "ibss_joined: %d", | ||
2784 | bss_conf->ibss_joined); | ||
2785 | |||
2786 | if (bss_conf->ibss_joined) { | ||
2787 | u32 rates = bss_conf->basic_rates; | ||
2788 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, | ||
2789 | rates); | ||
2790 | wl->basic_rate = wl1271_tx_min_rate_get(wl); | ||
2791 | |||
2792 | /* by default, use 11b rates */ | ||
2793 | wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES; | ||
2794 | ret = wl1271_acx_sta_rate_policies(wl); | ||
2795 | if (ret < 0) | ||
2796 | goto out; | ||
2797 | } | ||
2798 | } | ||
2799 | |||
2317 | ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed); | 2800 | ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed); |
2318 | if (ret < 0) | 2801 | if (ret < 0) |
2319 | goto out; | 2802 | goto out; |
@@ -2503,8 +2986,10 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
2503 | } | 2986 | } |
2504 | } else { | 2987 | } else { |
2505 | /* use defaults when not associated */ | 2988 | /* use defaults when not associated */ |
2989 | bool was_assoc = | ||
2990 | !!test_and_clear_bit(WL1271_FLAG_STA_ASSOCIATED, | ||
2991 | &wl->flags); | ||
2506 | clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags); | 2992 | clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags); |
2507 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | ||
2508 | wl->aid = 0; | 2993 | wl->aid = 0; |
2509 | 2994 | ||
2510 | /* free probe-request template */ | 2995 | /* free probe-request template */ |
@@ -2530,8 +3015,10 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
2530 | goto out; | 3015 | goto out; |
2531 | 3016 | ||
2532 | /* restore the bssid filter and go to dummy bssid */ | 3017 | /* restore the bssid filter and go to dummy bssid */ |
2533 | wl1271_unjoin(wl); | 3018 | if (was_assoc) { |
2534 | wl1271_dummy_join(wl); | 3019 | wl1271_unjoin(wl); |
3020 | wl1271_dummy_join(wl); | ||
3021 | } | ||
2535 | } | 3022 | } |
2536 | } | 3023 | } |
2537 | 3024 | ||
@@ -2650,32 +3137,31 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
2650 | conf_tid->ack_policy = CONF_ACK_POLICY_LEGACY; | 3137 | conf_tid->ack_policy = CONF_ACK_POLICY_LEGACY; |
2651 | conf_tid->apsd_conf[0] = 0; | 3138 | conf_tid->apsd_conf[0] = 0; |
2652 | conf_tid->apsd_conf[1] = 0; | 3139 | conf_tid->apsd_conf[1] = 0; |
2653 | } else { | 3140 | goto out; |
2654 | ret = wl1271_ps_elp_wakeup(wl); | 3141 | } |
2655 | if (ret < 0) | ||
2656 | goto out; | ||
2657 | 3142 | ||
2658 | /* | 3143 | ret = wl1271_ps_elp_wakeup(wl); |
2659 | * the txop is confed in units of 32us by the mac80211, | 3144 | if (ret < 0) |
2660 | * we need us | 3145 | goto out; |
2661 | */ | ||
2662 | ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), | ||
2663 | params->cw_min, params->cw_max, | ||
2664 | params->aifs, params->txop << 5); | ||
2665 | if (ret < 0) | ||
2666 | goto out_sleep; | ||
2667 | 3146 | ||
2668 | ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), | 3147 | /* |
2669 | CONF_CHANNEL_TYPE_EDCF, | 3148 | * the txop is confed in units of 32us by the mac80211, |
2670 | wl1271_tx_get_queue(queue), | 3149 | * we need us |
2671 | ps_scheme, CONF_ACK_POLICY_LEGACY, | 3150 | */ |
2672 | 0, 0); | 3151 | ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), |
2673 | if (ret < 0) | 3152 | params->cw_min, params->cw_max, |
2674 | goto out_sleep; | 3153 | params->aifs, params->txop << 5); |
3154 | if (ret < 0) | ||
3155 | goto out_sleep; | ||
3156 | |||
3157 | ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), | ||
3158 | CONF_CHANNEL_TYPE_EDCF, | ||
3159 | wl1271_tx_get_queue(queue), | ||
3160 | ps_scheme, CONF_ACK_POLICY_LEGACY, | ||
3161 | 0, 0); | ||
2675 | 3162 | ||
2676 | out_sleep: | 3163 | out_sleep: |
2677 | wl1271_ps_elp_sleep(wl); | 3164 | wl1271_ps_elp_sleep(wl); |
2678 | } | ||
2679 | 3165 | ||
2680 | out: | 3166 | out: |
2681 | mutex_unlock(&wl->mutex); | 3167 | mutex_unlock(&wl->mutex); |
@@ -2847,10 +3333,11 @@ out: | |||
2847 | return ret; | 3333 | return ret; |
2848 | } | 3334 | } |
2849 | 3335 | ||
2850 | int wl1271_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 3336 | static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, |
2851 | enum ieee80211_ampdu_mlme_action action, | 3337 | struct ieee80211_vif *vif, |
2852 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, | 3338 | enum ieee80211_ampdu_mlme_action action, |
2853 | u8 buf_size) | 3339 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, |
3340 | u8 buf_size) | ||
2854 | { | 3341 | { |
2855 | struct wl1271 *wl = hw->priv; | 3342 | struct wl1271 *wl = hw->priv; |
2856 | int ret; | 3343 | int ret; |
@@ -2907,6 +3394,28 @@ out: | |||
2907 | return ret; | 3394 | return ret; |
2908 | } | 3395 | } |
2909 | 3396 | ||
3397 | static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) | ||
3398 | { | ||
3399 | struct wl1271 *wl = hw->priv; | ||
3400 | bool ret = false; | ||
3401 | |||
3402 | mutex_lock(&wl->mutex); | ||
3403 | |||
3404 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
3405 | goto out; | ||
3406 | |||
3407 | /* packets are considered pending if in the TX queue or the FW */ | ||
3408 | ret = (wl->tx_queue_count > 0) || (wl->tx_frames_cnt > 0); | ||
3409 | |||
3410 | /* the above is appropriate for STA mode for PS purposes */ | ||
3411 | WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); | ||
3412 | |||
3413 | out: | ||
3414 | mutex_unlock(&wl->mutex); | ||
3415 | |||
3416 | return ret; | ||
3417 | } | ||
3418 | |||
2910 | /* can't be const, mac80211 writes to this */ | 3419 | /* can't be const, mac80211 writes to this */ |
2911 | static struct ieee80211_rate wl1271_rates[] = { | 3420 | static struct ieee80211_rate wl1271_rates[] = { |
2912 | { .bitrate = 10, | 3421 | { .bitrate = 10, |
@@ -3003,7 +3512,8 @@ static const u8 wl1271_rate_to_idx_2ghz[] = { | |||
3003 | 3512 | ||
3004 | #ifdef CONFIG_WL12XX_HT | 3513 | #ifdef CONFIG_WL12XX_HT |
3005 | #define WL12XX_HT_CAP { \ | 3514 | #define WL12XX_HT_CAP { \ |
3006 | .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20, \ | 3515 | .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | \ |
3516 | (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT), \ | ||
3007 | .ht_supported = true, \ | 3517 | .ht_supported = true, \ |
3008 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K, \ | 3518 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K, \ |
3009 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, \ | 3519 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, \ |
@@ -3142,12 +3652,18 @@ static const struct ieee80211_ops wl1271_ops = { | |||
3142 | .stop = wl1271_op_stop, | 3652 | .stop = wl1271_op_stop, |
3143 | .add_interface = wl1271_op_add_interface, | 3653 | .add_interface = wl1271_op_add_interface, |
3144 | .remove_interface = wl1271_op_remove_interface, | 3654 | .remove_interface = wl1271_op_remove_interface, |
3655 | #ifdef CONFIG_PM | ||
3656 | .suspend = wl1271_op_suspend, | ||
3657 | .resume = wl1271_op_resume, | ||
3658 | #endif | ||
3145 | .config = wl1271_op_config, | 3659 | .config = wl1271_op_config, |
3146 | .prepare_multicast = wl1271_op_prepare_multicast, | 3660 | .prepare_multicast = wl1271_op_prepare_multicast, |
3147 | .configure_filter = wl1271_op_configure_filter, | 3661 | .configure_filter = wl1271_op_configure_filter, |
3148 | .tx = wl1271_op_tx, | 3662 | .tx = wl1271_op_tx, |
3149 | .set_key = wl1271_op_set_key, | 3663 | .set_key = wl1271_op_set_key, |
3150 | .hw_scan = wl1271_op_hw_scan, | 3664 | .hw_scan = wl1271_op_hw_scan, |
3665 | .sched_scan_start = wl1271_op_sched_scan_start, | ||
3666 | .sched_scan_stop = wl1271_op_sched_scan_stop, | ||
3151 | .bss_info_changed = wl1271_op_bss_info_changed, | 3667 | .bss_info_changed = wl1271_op_bss_info_changed, |
3152 | .set_frag_threshold = wl1271_op_set_frag_threshold, | 3668 | .set_frag_threshold = wl1271_op_set_frag_threshold, |
3153 | .set_rts_threshold = wl1271_op_set_rts_threshold, | 3669 | .set_rts_threshold = wl1271_op_set_rts_threshold, |
@@ -3157,6 +3673,7 @@ static const struct ieee80211_ops wl1271_ops = { | |||
3157 | .sta_add = wl1271_op_sta_add, | 3673 | .sta_add = wl1271_op_sta_add, |
3158 | .sta_remove = wl1271_op_sta_remove, | 3674 | .sta_remove = wl1271_op_sta_remove, |
3159 | .ampdu_action = wl1271_op_ampdu_action, | 3675 | .ampdu_action = wl1271_op_ampdu_action, |
3676 | .tx_frames_pending = wl1271_tx_frames_pending, | ||
3160 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | 3677 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) |
3161 | }; | 3678 | }; |
3162 | 3679 | ||
@@ -3207,8 +3724,7 @@ static ssize_t wl1271_sysfs_store_bt_coex_state(struct device *dev, | |||
3207 | unsigned long res; | 3724 | unsigned long res; |
3208 | int ret; | 3725 | int ret; |
3209 | 3726 | ||
3210 | ret = strict_strtoul(buf, 10, &res); | 3727 | ret = kstrtoul(buf, 10, &res); |
3211 | |||
3212 | if (ret < 0) { | 3728 | if (ret < 0) { |
3213 | wl1271_warning("incorrect value written to bt_coex_mode"); | 3729 | wl1271_warning("incorrect value written to bt_coex_mode"); |
3214 | return count; | 3730 | return count; |
@@ -3273,7 +3789,11 @@ int wl1271_register_hw(struct wl1271 *wl) | |||
3273 | 3789 | ||
3274 | ret = wl1271_fetch_nvs(wl); | 3790 | ret = wl1271_fetch_nvs(wl); |
3275 | if (ret == 0) { | 3791 | if (ret == 0) { |
3276 | u8 *nvs_ptr = (u8 *)wl->nvs->nvs; | 3792 | /* NOTE: The wl->nvs->nvs element must be first, in |
3793 | * order to simplify the casting, we assume it is at | ||
3794 | * the beginning of the wl->nvs structure. | ||
3795 | */ | ||
3796 | u8 *nvs_ptr = (u8 *)wl->nvs; | ||
3277 | 3797 | ||
3278 | wl->mac_addr[0] = nvs_ptr[11]; | 3798 | wl->mac_addr[0] = nvs_ptr[11]; |
3279 | wl->mac_addr[1] = nvs_ptr[10]; | 3799 | wl->mac_addr[1] = nvs_ptr[10]; |
@@ -3342,6 +3862,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
3342 | IEEE80211_HW_CONNECTION_MONITOR | | 3862 | IEEE80211_HW_CONNECTION_MONITOR | |
3343 | IEEE80211_HW_SUPPORTS_CQM_RSSI | | 3863 | IEEE80211_HW_SUPPORTS_CQM_RSSI | |
3344 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | | 3864 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | |
3865 | IEEE80211_HW_SPECTRUM_MGMT | | ||
3345 | IEEE80211_HW_AP_LINK_PS; | 3866 | IEEE80211_HW_AP_LINK_PS; |
3346 | 3867 | ||
3347 | wl->hw->wiphy->cipher_suites = cipher_suites; | 3868 | wl->hw->wiphy->cipher_suites = cipher_suites; |
@@ -3358,6 +3879,10 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
3358 | wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - | 3879 | wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - |
3359 | sizeof(struct ieee80211_header); | 3880 | sizeof(struct ieee80211_header); |
3360 | 3881 | ||
3882 | /* make sure all our channels fit in the scanned_ch bitmask */ | ||
3883 | BUILD_BUG_ON(ARRAY_SIZE(wl1271_channels) + | ||
3884 | ARRAY_SIZE(wl1271_channels_5ghz) > | ||
3885 | WL1271_MAX_CHANNELS); | ||
3361 | /* | 3886 | /* |
3362 | * We keep local copies of the band structs because we need to | 3887 | * We keep local copies of the band structs because we need to |
3363 | * modify them on a per-device basis. | 3888 | * modify them on a per-device basis. |
@@ -3458,6 +3983,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
3458 | wl->ap_ps_map = 0; | 3983 | wl->ap_ps_map = 0; |
3459 | wl->ap_fw_ps_map = 0; | 3984 | wl->ap_fw_ps_map = 0; |
3460 | wl->quirks = 0; | 3985 | wl->quirks = 0; |
3986 | wl->platform_quirks = 0; | ||
3987 | wl->sched_scanning = false; | ||
3461 | 3988 | ||
3462 | memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); | 3989 | memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); |
3463 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 3990 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
@@ -3478,11 +4005,17 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
3478 | goto err_hw; | 4005 | goto err_hw; |
3479 | } | 4006 | } |
3480 | 4007 | ||
4008 | wl->dummy_packet = wl12xx_alloc_dummy_packet(wl); | ||
4009 | if (!wl->dummy_packet) { | ||
4010 | ret = -ENOMEM; | ||
4011 | goto err_aggr; | ||
4012 | } | ||
4013 | |||
3481 | /* Register platform device */ | 4014 | /* Register platform device */ |
3482 | ret = platform_device_register(wl->plat_dev); | 4015 | ret = platform_device_register(wl->plat_dev); |
3483 | if (ret) { | 4016 | if (ret) { |
3484 | wl1271_error("couldn't register platform device"); | 4017 | wl1271_error("couldn't register platform device"); |
3485 | goto err_aggr; | 4018 | goto err_dummy_packet; |
3486 | } | 4019 | } |
3487 | dev_set_drvdata(&wl->plat_dev->dev, wl); | 4020 | dev_set_drvdata(&wl->plat_dev->dev, wl); |
3488 | 4021 | ||
@@ -3508,6 +4041,9 @@ err_bt_coex_state: | |||
3508 | err_platform: | 4041 | err_platform: |
3509 | platform_device_unregister(wl->plat_dev); | 4042 | platform_device_unregister(wl->plat_dev); |
3510 | 4043 | ||
4044 | err_dummy_packet: | ||
4045 | dev_kfree_skb(wl->dummy_packet); | ||
4046 | |||
3511 | err_aggr: | 4047 | err_aggr: |
3512 | free_pages((unsigned long)wl->aggr_buf, order); | 4048 | free_pages((unsigned long)wl->aggr_buf, order); |
3513 | 4049 | ||
@@ -3527,6 +4063,7 @@ EXPORT_SYMBOL_GPL(wl1271_alloc_hw); | |||
3527 | int wl1271_free_hw(struct wl1271 *wl) | 4063 | int wl1271_free_hw(struct wl1271 *wl) |
3528 | { | 4064 | { |
3529 | platform_device_unregister(wl->plat_dev); | 4065 | platform_device_unregister(wl->plat_dev); |
4066 | dev_kfree_skb(wl->dummy_packet); | ||
3530 | free_pages((unsigned long)wl->aggr_buf, | 4067 | free_pages((unsigned long)wl->aggr_buf, |
3531 | get_order(WL1271_AGGR_BUFFER_SIZE)); | 4068 | get_order(WL1271_AGGR_BUFFER_SIZE)); |
3532 | kfree(wl->plat_dev); | 4069 | kfree(wl->plat_dev); |