diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-02-08 13:16:17 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-02-08 13:16:17 -0500 |
commit | f5237f278f30a92401539a54f87ee0c717b6f818 (patch) | |
tree | 209d4fd6fb00e660c76ca8ac5d4caed59dbb9957 /drivers/net/wireless/ti | |
parent | b285109dde7b873b5dc671ef1b3ae3090f4bc72f (diff) | |
parent | b26f5f09ebdeb85ab152344cc1d6d484a3ce967d (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Diffstat (limited to 'drivers/net/wireless/ti')
47 files changed, 4623 insertions, 2024 deletions
diff --git a/drivers/net/wireless/ti/wl1251/Kconfig b/drivers/net/wireless/ti/wl1251/Kconfig index 1fb65849414f..8fec4ed36ac2 100644 --- a/drivers/net/wireless/ti/wl1251/Kconfig +++ b/drivers/net/wireless/ti/wl1251/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | menuconfig WL1251 | 1 | menuconfig WL1251 |
2 | tristate "TI wl1251 driver support" | 2 | tristate "TI wl1251 driver support" |
3 | depends on MAC80211 && EXPERIMENTAL && GENERIC_HARDIRQS | 3 | depends on MAC80211 && GENERIC_HARDIRQS |
4 | select FW_LOADER | 4 | select FW_LOADER |
5 | select CRC7 | 5 | select CRC7 |
6 | ---help--- | 6 | ---help--- |
diff --git a/drivers/net/wireless/ti/wl12xx/Makefile b/drivers/net/wireless/ti/wl12xx/Makefile index da509aa7d009..e6a24056b3c8 100644 --- a/drivers/net/wireless/ti/wl12xx/Makefile +++ b/drivers/net/wireless/ti/wl12xx/Makefile | |||
@@ -1,3 +1,3 @@ | |||
1 | wl12xx-objs = main.o cmd.o acx.o debugfs.o | 1 | wl12xx-objs = main.o cmd.o acx.o debugfs.o scan.o event.o |
2 | 2 | ||
3 | obj-$(CONFIG_WL12XX) += wl12xx.o | 3 | obj-$(CONFIG_WL12XX) += wl12xx.o |
diff --git a/drivers/net/wireless/ti/wl12xx/cmd.c b/drivers/net/wireless/ti/wl12xx/cmd.c index 622206241e83..7dc9f965037d 100644 --- a/drivers/net/wireless/ti/wl12xx/cmd.c +++ b/drivers/net/wireless/ti/wl12xx/cmd.c | |||
@@ -284,3 +284,40 @@ int wl128x_cmd_radio_parms(struct wl1271 *wl) | |||
284 | kfree(radio_parms); | 284 | kfree(radio_parms); |
285 | return ret; | 285 | return ret; |
286 | } | 286 | } |
287 | |||
288 | int wl12xx_cmd_channel_switch(struct wl1271 *wl, | ||
289 | struct wl12xx_vif *wlvif, | ||
290 | struct ieee80211_channel_switch *ch_switch) | ||
291 | { | ||
292 | struct wl12xx_cmd_channel_switch *cmd; | ||
293 | int ret; | ||
294 | |||
295 | wl1271_debug(DEBUG_ACX, "cmd channel switch"); | ||
296 | |||
297 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
298 | if (!cmd) { | ||
299 | ret = -ENOMEM; | ||
300 | goto out; | ||
301 | } | ||
302 | |||
303 | cmd->role_id = wlvif->role_id; | ||
304 | cmd->channel = ch_switch->channel->hw_value; | ||
305 | cmd->switch_time = ch_switch->count; | ||
306 | cmd->stop_tx = ch_switch->block_tx; | ||
307 | |||
308 | /* FIXME: control from mac80211 in the future */ | ||
309 | /* Enable TX on the target channel */ | ||
310 | cmd->post_switch_tx_disable = 0; | ||
311 | |||
312 | ret = wl1271_cmd_send(wl, CMD_CHANNEL_SWITCH, cmd, sizeof(*cmd), 0); | ||
313 | if (ret < 0) { | ||
314 | wl1271_error("failed to send channel switch command"); | ||
315 | goto out_free; | ||
316 | } | ||
317 | |||
318 | out_free: | ||
319 | kfree(cmd); | ||
320 | |||
321 | out: | ||
322 | return ret; | ||
323 | } | ||
diff --git a/drivers/net/wireless/ti/wl12xx/cmd.h b/drivers/net/wireless/ti/wl12xx/cmd.h index 140a0e8829d5..32cbad54e993 100644 --- a/drivers/net/wireless/ti/wl12xx/cmd.h +++ b/drivers/net/wireless/ti/wl12xx/cmd.h | |||
@@ -103,10 +103,30 @@ struct wl1271_ext_radio_parms_cmd { | |||
103 | u8 padding[3]; | 103 | u8 padding[3]; |
104 | } __packed; | 104 | } __packed; |
105 | 105 | ||
106 | struct wl12xx_cmd_channel_switch { | ||
107 | struct wl1271_cmd_header header; | ||
108 | |||
109 | u8 role_id; | ||
110 | |||
111 | /* The new serving channel */ | ||
112 | u8 channel; | ||
113 | /* Relative time of the serving channel switch in TBTT units */ | ||
114 | u8 switch_time; | ||
115 | /* Stop the role TX, should expect it after radar detection */ | ||
116 | u8 stop_tx; | ||
117 | /* The target channel tx status 1-stopped 0-open*/ | ||
118 | u8 post_switch_tx_disable; | ||
119 | |||
120 | u8 padding[3]; | ||
121 | } __packed; | ||
122 | |||
106 | int wl1271_cmd_general_parms(struct wl1271 *wl); | 123 | int wl1271_cmd_general_parms(struct wl1271 *wl); |
107 | int wl128x_cmd_general_parms(struct wl1271 *wl); | 124 | int wl128x_cmd_general_parms(struct wl1271 *wl); |
108 | int wl1271_cmd_radio_parms(struct wl1271 *wl); | 125 | int wl1271_cmd_radio_parms(struct wl1271 *wl); |
109 | int wl128x_cmd_radio_parms(struct wl1271 *wl); | 126 | int wl128x_cmd_radio_parms(struct wl1271 *wl); |
110 | int wl1271_cmd_ext_radio_parms(struct wl1271 *wl); | 127 | int wl1271_cmd_ext_radio_parms(struct wl1271 *wl); |
128 | int wl12xx_cmd_channel_switch(struct wl1271 *wl, | ||
129 | struct wl12xx_vif *wlvif, | ||
130 | struct ieee80211_channel_switch *ch_switch); | ||
111 | 131 | ||
112 | #endif /* __WL12XX_CMD_H__ */ | 132 | #endif /* __WL12XX_CMD_H__ */ |
diff --git a/drivers/net/wireless/ti/wl12xx/event.c b/drivers/net/wireless/ti/wl12xx/event.c new file mode 100644 index 000000000000..6ac0ed751da8 --- /dev/null +++ b/drivers/net/wireless/ti/wl12xx/event.c | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | * This file is part of wl12xx | ||
3 | * | ||
4 | * Copyright (C) 2012 Texas Instruments. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include "event.h" | ||
23 | #include "scan.h" | ||
24 | #include "../wlcore/cmd.h" | ||
25 | #include "../wlcore/debug.h" | ||
26 | |||
27 | int wl12xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event, | ||
28 | bool *timeout) | ||
29 | { | ||
30 | u32 local_event; | ||
31 | |||
32 | switch (event) { | ||
33 | case WLCORE_EVENT_ROLE_STOP_COMPLETE: | ||
34 | local_event = ROLE_STOP_COMPLETE_EVENT_ID; | ||
35 | break; | ||
36 | |||
37 | case WLCORE_EVENT_PEER_REMOVE_COMPLETE: | ||
38 | local_event = PEER_REMOVE_COMPLETE_EVENT_ID; | ||
39 | break; | ||
40 | |||
41 | default: | ||
42 | /* event not implemented */ | ||
43 | return 0; | ||
44 | } | ||
45 | return wlcore_cmd_wait_for_event_or_timeout(wl, local_event, timeout); | ||
46 | } | ||
47 | |||
48 | int wl12xx_process_mailbox_events(struct wl1271 *wl) | ||
49 | { | ||
50 | struct wl12xx_event_mailbox *mbox = wl->mbox; | ||
51 | u32 vector; | ||
52 | |||
53 | |||
54 | vector = le32_to_cpu(mbox->events_vector); | ||
55 | vector &= ~(le32_to_cpu(mbox->events_mask)); | ||
56 | |||
57 | wl1271_debug(DEBUG_EVENT, "MBOX vector: 0x%x", vector); | ||
58 | |||
59 | if (vector & SCAN_COMPLETE_EVENT_ID) { | ||
60 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", | ||
61 | mbox->scheduled_scan_status); | ||
62 | |||
63 | if (wl->scan_wlvif) | ||
64 | wl12xx_scan_completed(wl, wl->scan_wlvif); | ||
65 | } | ||
66 | |||
67 | if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) { | ||
68 | wl1271_debug(DEBUG_EVENT, | ||
69 | "PERIODIC_SCAN_REPORT_EVENT (status 0x%0x)", | ||
70 | mbox->scheduled_scan_status); | ||
71 | |||
72 | wlcore_scan_sched_scan_results(wl); | ||
73 | } | ||
74 | |||
75 | if (vector & PERIODIC_SCAN_COMPLETE_EVENT_ID) | ||
76 | wlcore_event_sched_scan_completed(wl, | ||
77 | mbox->scheduled_scan_status); | ||
78 | if (vector & SOFT_GEMINI_SENSE_EVENT_ID) | ||
79 | wlcore_event_soft_gemini_sense(wl, | ||
80 | mbox->soft_gemini_sense_info); | ||
81 | |||
82 | if (vector & BSS_LOSE_EVENT_ID) | ||
83 | wlcore_event_beacon_loss(wl, 0xff); | ||
84 | |||
85 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) | ||
86 | wlcore_event_rssi_trigger(wl, mbox->rssi_snr_trigger_metric); | ||
87 | |||
88 | if (vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID) | ||
89 | wlcore_event_ba_rx_constraint(wl, | ||
90 | BIT(mbox->role_id), | ||
91 | mbox->rx_ba_allowed); | ||
92 | |||
93 | if (vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID) | ||
94 | wlcore_event_channel_switch(wl, 0xff, | ||
95 | mbox->channel_switch_status); | ||
96 | |||
97 | if (vector & DUMMY_PACKET_EVENT_ID) | ||
98 | wlcore_event_dummy_packet(wl); | ||
99 | |||
100 | /* | ||
101 | * "TX retries exceeded" has a different meaning according to mode. | ||
102 | * In AP mode the offending station is disconnected. | ||
103 | */ | ||
104 | if (vector & MAX_TX_RETRY_EVENT_ID) | ||
105 | wlcore_event_max_tx_failure(wl, | ||
106 | le16_to_cpu(mbox->sta_tx_retry_exceeded)); | ||
107 | |||
108 | if (vector & INACTIVE_STA_EVENT_ID) | ||
109 | wlcore_event_inactive_sta(wl, | ||
110 | le16_to_cpu(mbox->sta_aging_status)); | ||
111 | |||
112 | if (vector & REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID) | ||
113 | wlcore_event_roc_complete(wl); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
diff --git a/drivers/net/wireless/ti/wl12xx/event.h b/drivers/net/wireless/ti/wl12xx/event.h new file mode 100644 index 000000000000..a5cc3fcd9eea --- /dev/null +++ b/drivers/net/wireless/ti/wl12xx/event.h | |||
@@ -0,0 +1,111 @@ | |||
1 | /* | ||
2 | * This file is part of wl12xx | ||
3 | * | ||
4 | * Copyright (C) 2012 Texas Instruments. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef __WL12XX_EVENT_H__ | ||
23 | #define __WL12XX_EVENT_H__ | ||
24 | |||
25 | #include "../wlcore/wlcore.h" | ||
26 | |||
27 | enum { | ||
28 | MEASUREMENT_START_EVENT_ID = BIT(8), | ||
29 | MEASUREMENT_COMPLETE_EVENT_ID = BIT(9), | ||
30 | SCAN_COMPLETE_EVENT_ID = BIT(10), | ||
31 | WFD_DISCOVERY_COMPLETE_EVENT_ID = BIT(11), | ||
32 | AP_DISCOVERY_COMPLETE_EVENT_ID = BIT(12), | ||
33 | RESERVED1 = BIT(13), | ||
34 | PSPOLL_DELIVERY_FAILURE_EVENT_ID = BIT(14), | ||
35 | ROLE_STOP_COMPLETE_EVENT_ID = BIT(15), | ||
36 | RADAR_DETECTED_EVENT_ID = BIT(16), | ||
37 | CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17), | ||
38 | BSS_LOSE_EVENT_ID = BIT(18), | ||
39 | REGAINED_BSS_EVENT_ID = BIT(19), | ||
40 | MAX_TX_RETRY_EVENT_ID = BIT(20), | ||
41 | DUMMY_PACKET_EVENT_ID = BIT(21), | ||
42 | SOFT_GEMINI_SENSE_EVENT_ID = BIT(22), | ||
43 | CHANGE_AUTO_MODE_TIMEOUT_EVENT_ID = BIT(23), | ||
44 | SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24), | ||
45 | PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25), | ||
46 | INACTIVE_STA_EVENT_ID = BIT(26), | ||
47 | PEER_REMOVE_COMPLETE_EVENT_ID = BIT(27), | ||
48 | PERIODIC_SCAN_COMPLETE_EVENT_ID = BIT(28), | ||
49 | PERIODIC_SCAN_REPORT_EVENT_ID = BIT(29), | ||
50 | BA_SESSION_RX_CONSTRAINT_EVENT_ID = BIT(30), | ||
51 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID = BIT(31), | ||
52 | }; | ||
53 | |||
54 | struct wl12xx_event_mailbox { | ||
55 | __le32 events_vector; | ||
56 | __le32 events_mask; | ||
57 | __le32 reserved_1; | ||
58 | __le32 reserved_2; | ||
59 | |||
60 | u8 number_of_scan_results; | ||
61 | u8 scan_tag; | ||
62 | u8 completed_scan_status; | ||
63 | u8 reserved_3; | ||
64 | |||
65 | u8 soft_gemini_sense_info; | ||
66 | u8 soft_gemini_protective_info; | ||
67 | s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS]; | ||
68 | u8 change_auto_mode_timeout; | ||
69 | u8 scheduled_scan_status; | ||
70 | u8 reserved4; | ||
71 | /* tuned channel (roc) */ | ||
72 | u8 roc_channel; | ||
73 | |||
74 | __le16 hlid_removed_bitmap; | ||
75 | |||
76 | /* bitmap of aged stations (by HLID) */ | ||
77 | __le16 sta_aging_status; | ||
78 | |||
79 | /* bitmap of stations (by HLID) which exceeded max tx retries */ | ||
80 | __le16 sta_tx_retry_exceeded; | ||
81 | |||
82 | /* discovery completed results */ | ||
83 | u8 discovery_tag; | ||
84 | u8 number_of_preq_results; | ||
85 | u8 number_of_prsp_results; | ||
86 | u8 reserved_5; | ||
87 | |||
88 | /* rx ba constraint */ | ||
89 | u8 role_id; /* 0xFF means any role. */ | ||
90 | u8 rx_ba_allowed; | ||
91 | u8 reserved_6[2]; | ||
92 | |||
93 | /* Channel switch results */ | ||
94 | |||
95 | u8 channel_switch_role_id; | ||
96 | u8 channel_switch_status; | ||
97 | u8 reserved_7[2]; | ||
98 | |||
99 | u8 ps_poll_delivery_failure_role_ids; | ||
100 | u8 stopped_role_ids; | ||
101 | u8 started_role_ids; | ||
102 | |||
103 | u8 reserved_8[9]; | ||
104 | } __packed; | ||
105 | |||
106 | int wl12xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event, | ||
107 | bool *timeout); | ||
108 | int wl12xx_process_mailbox_events(struct wl1271 *wl); | ||
109 | |||
110 | #endif | ||
111 | |||
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index e5f5f8f39144..3254bfc81a2a 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c | |||
@@ -38,6 +38,8 @@ | |||
38 | #include "reg.h" | 38 | #include "reg.h" |
39 | #include "cmd.h" | 39 | #include "cmd.h" |
40 | #include "acx.h" | 40 | #include "acx.h" |
41 | #include "scan.h" | ||
42 | #include "event.h" | ||
41 | #include "debugfs.h" | 43 | #include "debugfs.h" |
42 | 44 | ||
43 | static char *fref_param; | 45 | static char *fref_param; |
@@ -208,6 +210,8 @@ static struct wlcore_conf wl12xx_conf = { | |||
208 | .tmpl_short_retry_limit = 10, | 210 | .tmpl_short_retry_limit = 10, |
209 | .tmpl_long_retry_limit = 10, | 211 | .tmpl_long_retry_limit = 10, |
210 | .tx_watchdog_timeout = 5000, | 212 | .tx_watchdog_timeout = 5000, |
213 | .slow_link_thold = 3, | ||
214 | .fast_link_thold = 10, | ||
211 | }, | 215 | }, |
212 | .conn = { | 216 | .conn = { |
213 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | 217 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, |
@@ -265,8 +269,10 @@ static struct wlcore_conf wl12xx_conf = { | |||
265 | .scan = { | 269 | .scan = { |
266 | .min_dwell_time_active = 7500, | 270 | .min_dwell_time_active = 7500, |
267 | .max_dwell_time_active = 30000, | 271 | .max_dwell_time_active = 30000, |
268 | .min_dwell_time_passive = 100000, | 272 | .min_dwell_time_active_long = 25000, |
269 | .max_dwell_time_passive = 100000, | 273 | .max_dwell_time_active_long = 50000, |
274 | .dwell_time_passive = 100000, | ||
275 | .dwell_time_dfs = 150000, | ||
270 | .num_probe_reqs = 2, | 276 | .num_probe_reqs = 2, |
271 | .split_scan_timeout = 50000, | 277 | .split_scan_timeout = 50000, |
272 | }, | 278 | }, |
@@ -368,6 +374,10 @@ static struct wlcore_conf wl12xx_conf = { | |||
368 | .increase_time = 1, | 374 | .increase_time = 1, |
369 | .window_size = 16, | 375 | .window_size = 16, |
370 | }, | 376 | }, |
377 | .recovery = { | ||
378 | .bug_on_recovery = 0, | ||
379 | .no_recovery = 0, | ||
380 | }, | ||
371 | }; | 381 | }; |
372 | 382 | ||
373 | static struct wl12xx_priv_conf wl12xx_default_priv_conf = { | 383 | static struct wl12xx_priv_conf wl12xx_default_priv_conf = { |
@@ -601,9 +611,9 @@ static int wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) | |||
601 | { | 611 | { |
602 | int ret; | 612 | int ret; |
603 | 613 | ||
604 | if (wl->chip.id != CHIP_ID_1283_PG20) { | 614 | if (wl->chip.id != CHIP_ID_128X_PG20) { |
605 | struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; | 615 | struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; |
606 | struct wl127x_rx_mem_pool_addr rx_mem_addr; | 616 | struct wl12xx_priv *priv = wl->priv; |
607 | 617 | ||
608 | /* | 618 | /* |
609 | * Choose the block we want to read | 619 | * Choose the block we want to read |
@@ -612,13 +622,13 @@ static int wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) | |||
612 | */ | 622 | */ |
613 | u32 mem_block = rx_desc & RX_MEM_BLOCK_MASK; | 623 | u32 mem_block = rx_desc & RX_MEM_BLOCK_MASK; |
614 | 624 | ||
615 | rx_mem_addr.addr = (mem_block << 8) + | 625 | priv->rx_mem_addr->addr = (mem_block << 8) + |
616 | le32_to_cpu(wl_mem_map->packet_memory_pool_start); | 626 | le32_to_cpu(wl_mem_map->packet_memory_pool_start); |
617 | 627 | ||
618 | rx_mem_addr.addr_extra = rx_mem_addr.addr + 4; | 628 | priv->rx_mem_addr->addr_extra = priv->rx_mem_addr->addr + 4; |
619 | 629 | ||
620 | ret = wlcore_write(wl, WL1271_SLV_REG_DATA, &rx_mem_addr, | 630 | ret = wlcore_write(wl, WL1271_SLV_REG_DATA, priv->rx_mem_addr, |
621 | sizeof(rx_mem_addr), false); | 631 | sizeof(*priv->rx_mem_addr), false); |
622 | if (ret < 0) | 632 | if (ret < 0) |
623 | return ret; | 633 | return ret; |
624 | } | 634 | } |
@@ -631,13 +641,15 @@ static int wl12xx_identify_chip(struct wl1271 *wl) | |||
631 | int ret = 0; | 641 | int ret = 0; |
632 | 642 | ||
633 | switch (wl->chip.id) { | 643 | switch (wl->chip.id) { |
634 | case CHIP_ID_1271_PG10: | 644 | case CHIP_ID_127X_PG10: |
635 | wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete", | 645 | wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete", |
636 | wl->chip.id); | 646 | wl->chip.id); |
637 | 647 | ||
638 | wl->quirks |= WLCORE_QUIRK_LEGACY_NVS | | 648 | wl->quirks |= WLCORE_QUIRK_LEGACY_NVS | |
639 | WLCORE_QUIRK_DUAL_PROBE_TMPL | | 649 | WLCORE_QUIRK_DUAL_PROBE_TMPL | |
640 | WLCORE_QUIRK_TKIP_HEADER_SPACE; | 650 | WLCORE_QUIRK_TKIP_HEADER_SPACE | |
651 | WLCORE_QUIRK_START_STA_FAILS | | ||
652 | WLCORE_QUIRK_AP_ZERO_SESSION_ID; | ||
641 | wl->sr_fw_name = WL127X_FW_NAME_SINGLE; | 653 | wl->sr_fw_name = WL127X_FW_NAME_SINGLE; |
642 | wl->mr_fw_name = WL127X_FW_NAME_MULTI; | 654 | wl->mr_fw_name = WL127X_FW_NAME_MULTI; |
643 | memcpy(&wl->conf.mem, &wl12xx_default_priv_conf.mem_wl127x, | 655 | memcpy(&wl->conf.mem, &wl12xx_default_priv_conf.mem_wl127x, |
@@ -646,18 +658,22 @@ static int wl12xx_identify_chip(struct wl1271 *wl) | |||
646 | /* read data preparation is only needed by wl127x */ | 658 | /* read data preparation is only needed by wl127x */ |
647 | wl->ops->prepare_read = wl127x_prepare_read; | 659 | wl->ops->prepare_read = wl127x_prepare_read; |
648 | 660 | ||
649 | wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER, WL127X_IFTYPE_VER, | 661 | wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER, |
650 | WL127X_MAJOR_VER, WL127X_SUBTYPE_VER, | 662 | WL127X_IFTYPE_SR_VER, WL127X_MAJOR_SR_VER, |
651 | WL127X_MINOR_VER); | 663 | WL127X_SUBTYPE_SR_VER, WL127X_MINOR_SR_VER, |
664 | WL127X_IFTYPE_MR_VER, WL127X_MAJOR_MR_VER, | ||
665 | WL127X_SUBTYPE_MR_VER, WL127X_MINOR_MR_VER); | ||
652 | break; | 666 | break; |
653 | 667 | ||
654 | case CHIP_ID_1271_PG20: | 668 | case CHIP_ID_127X_PG20: |
655 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", | 669 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", |
656 | wl->chip.id); | 670 | wl->chip.id); |
657 | 671 | ||
658 | wl->quirks |= WLCORE_QUIRK_LEGACY_NVS | | 672 | wl->quirks |= WLCORE_QUIRK_LEGACY_NVS | |
659 | WLCORE_QUIRK_DUAL_PROBE_TMPL | | 673 | WLCORE_QUIRK_DUAL_PROBE_TMPL | |
660 | WLCORE_QUIRK_TKIP_HEADER_SPACE; | 674 | WLCORE_QUIRK_TKIP_HEADER_SPACE | |
675 | WLCORE_QUIRK_START_STA_FAILS | | ||
676 | WLCORE_QUIRK_AP_ZERO_SESSION_ID; | ||
661 | wl->plt_fw_name = WL127X_PLT_FW_NAME; | 677 | wl->plt_fw_name = WL127X_PLT_FW_NAME; |
662 | wl->sr_fw_name = WL127X_FW_NAME_SINGLE; | 678 | wl->sr_fw_name = WL127X_FW_NAME_SINGLE; |
663 | wl->mr_fw_name = WL127X_FW_NAME_MULTI; | 679 | wl->mr_fw_name = WL127X_FW_NAME_MULTI; |
@@ -667,12 +683,14 @@ static int wl12xx_identify_chip(struct wl1271 *wl) | |||
667 | /* read data preparation is only needed by wl127x */ | 683 | /* read data preparation is only needed by wl127x */ |
668 | wl->ops->prepare_read = wl127x_prepare_read; | 684 | wl->ops->prepare_read = wl127x_prepare_read; |
669 | 685 | ||
670 | wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER, WL127X_IFTYPE_VER, | 686 | wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER, |
671 | WL127X_MAJOR_VER, WL127X_SUBTYPE_VER, | 687 | WL127X_IFTYPE_SR_VER, WL127X_MAJOR_SR_VER, |
672 | WL127X_MINOR_VER); | 688 | WL127X_SUBTYPE_SR_VER, WL127X_MINOR_SR_VER, |
689 | WL127X_IFTYPE_MR_VER, WL127X_MAJOR_MR_VER, | ||
690 | WL127X_SUBTYPE_MR_VER, WL127X_MINOR_MR_VER); | ||
673 | break; | 691 | break; |
674 | 692 | ||
675 | case CHIP_ID_1283_PG20: | 693 | case CHIP_ID_128X_PG20: |
676 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)", | 694 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)", |
677 | wl->chip.id); | 695 | wl->chip.id); |
678 | wl->plt_fw_name = WL128X_PLT_FW_NAME; | 696 | wl->plt_fw_name = WL128X_PLT_FW_NAME; |
@@ -682,19 +700,29 @@ static int wl12xx_identify_chip(struct wl1271 *wl) | |||
682 | /* wl128x requires TX blocksize alignment */ | 700 | /* wl128x requires TX blocksize alignment */ |
683 | wl->quirks |= WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN | | 701 | wl->quirks |= WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN | |
684 | WLCORE_QUIRK_DUAL_PROBE_TMPL | | 702 | WLCORE_QUIRK_DUAL_PROBE_TMPL | |
685 | WLCORE_QUIRK_TKIP_HEADER_SPACE; | 703 | WLCORE_QUIRK_TKIP_HEADER_SPACE | |
686 | 704 | WLCORE_QUIRK_START_STA_FAILS | | |
687 | wlcore_set_min_fw_ver(wl, WL128X_CHIP_VER, WL128X_IFTYPE_VER, | 705 | WLCORE_QUIRK_AP_ZERO_SESSION_ID; |
688 | WL128X_MAJOR_VER, WL128X_SUBTYPE_VER, | 706 | |
689 | WL128X_MINOR_VER); | 707 | wlcore_set_min_fw_ver(wl, WL128X_CHIP_VER, |
708 | WL128X_IFTYPE_SR_VER, WL128X_MAJOR_SR_VER, | ||
709 | WL128X_SUBTYPE_SR_VER, WL128X_MINOR_SR_VER, | ||
710 | WL128X_IFTYPE_MR_VER, WL128X_MAJOR_MR_VER, | ||
711 | WL128X_SUBTYPE_MR_VER, WL128X_MINOR_MR_VER); | ||
690 | break; | 712 | break; |
691 | case CHIP_ID_1283_PG10: | 713 | case CHIP_ID_128X_PG10: |
692 | default: | 714 | default: |
693 | wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); | 715 | wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); |
694 | ret = -ENODEV; | 716 | ret = -ENODEV; |
695 | goto out; | 717 | goto out; |
696 | } | 718 | } |
697 | 719 | ||
720 | /* common settings */ | ||
721 | wl->scan_templ_id_2_4 = CMD_TEMPL_APP_PROBE_REQ_2_4_LEGACY; | ||
722 | wl->scan_templ_id_5 = CMD_TEMPL_APP_PROBE_REQ_5_LEGACY; | ||
723 | wl->sched_scan_templ_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4; | ||
724 | wl->sched_scan_templ_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5; | ||
725 | wl->max_channels_5 = WL12XX_MAX_CHANNELS_5GHZ; | ||
698 | out: | 726 | out: |
699 | return ret; | 727 | return ret; |
700 | } | 728 | } |
@@ -1067,7 +1095,7 @@ static int wl12xx_pre_boot(struct wl1271 *wl) | |||
1067 | u32 clk; | 1095 | u32 clk; |
1068 | int selected_clock = -1; | 1096 | int selected_clock = -1; |
1069 | 1097 | ||
1070 | if (wl->chip.id == CHIP_ID_1283_PG20) { | 1098 | if (wl->chip.id == CHIP_ID_128X_PG20) { |
1071 | ret = wl128x_boot_clk(wl, &selected_clock); | 1099 | ret = wl128x_boot_clk(wl, &selected_clock); |
1072 | if (ret < 0) | 1100 | if (ret < 0) |
1073 | goto out; | 1101 | goto out; |
@@ -1098,7 +1126,7 @@ static int wl12xx_pre_boot(struct wl1271 *wl) | |||
1098 | 1126 | ||
1099 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); | 1127 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); |
1100 | 1128 | ||
1101 | if (wl->chip.id == CHIP_ID_1283_PG20) | 1129 | if (wl->chip.id == CHIP_ID_128X_PG20) |
1102 | clk |= ((selected_clock & 0x3) << 1) << 4; | 1130 | clk |= ((selected_clock & 0x3) << 1) << 4; |
1103 | else | 1131 | else |
1104 | clk |= (priv->ref_clock << 1) << 4; | 1132 | clk |= (priv->ref_clock << 1) << 4; |
@@ -1152,7 +1180,7 @@ static int wl12xx_pre_upload(struct wl1271 *wl) | |||
1152 | /* WL1271: The reference driver skips steps 7 to 10 (jumps directly | 1180 | /* WL1271: The reference driver skips steps 7 to 10 (jumps directly |
1153 | * to upload_fw) */ | 1181 | * to upload_fw) */ |
1154 | 1182 | ||
1155 | if (wl->chip.id == CHIP_ID_1283_PG20) { | 1183 | if (wl->chip.id == CHIP_ID_128X_PG20) { |
1156 | ret = wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA); | 1184 | ret = wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA); |
1157 | if (ret < 0) | 1185 | if (ret < 0) |
1158 | goto out; | 1186 | goto out; |
@@ -1219,6 +1247,23 @@ static int wl12xx_boot(struct wl1271 *wl) | |||
1219 | if (ret < 0) | 1247 | if (ret < 0) |
1220 | goto out; | 1248 | goto out; |
1221 | 1249 | ||
1250 | wl->event_mask = BSS_LOSE_EVENT_ID | | ||
1251 | REGAINED_BSS_EVENT_ID | | ||
1252 | SCAN_COMPLETE_EVENT_ID | | ||
1253 | ROLE_STOP_COMPLETE_EVENT_ID | | ||
1254 | RSSI_SNR_TRIGGER_0_EVENT_ID | | ||
1255 | PSPOLL_DELIVERY_FAILURE_EVENT_ID | | ||
1256 | SOFT_GEMINI_SENSE_EVENT_ID | | ||
1257 | PERIODIC_SCAN_REPORT_EVENT_ID | | ||
1258 | PERIODIC_SCAN_COMPLETE_EVENT_ID | | ||
1259 | DUMMY_PACKET_EVENT_ID | | ||
1260 | PEER_REMOVE_COMPLETE_EVENT_ID | | ||
1261 | BA_SESSION_RX_CONSTRAINT_EVENT_ID | | ||
1262 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | | ||
1263 | INACTIVE_STA_EVENT_ID | | ||
1264 | MAX_TX_RETRY_EVENT_ID | | ||
1265 | CHANNEL_SWITCH_COMPLETE_EVENT_ID; | ||
1266 | |||
1222 | ret = wlcore_boot_run_firmware(wl); | 1267 | ret = wlcore_boot_run_firmware(wl); |
1223 | if (ret < 0) | 1268 | if (ret < 0) |
1224 | goto out; | 1269 | goto out; |
@@ -1261,7 +1306,7 @@ static void | |||
1261 | wl12xx_set_tx_desc_blocks(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc, | 1306 | wl12xx_set_tx_desc_blocks(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc, |
1262 | u32 blks, u32 spare_blks) | 1307 | u32 blks, u32 spare_blks) |
1263 | { | 1308 | { |
1264 | if (wl->chip.id == CHIP_ID_1283_PG20) { | 1309 | if (wl->chip.id == CHIP_ID_128X_PG20) { |
1265 | desc->wl128x_mem.total_mem_blocks = blks; | 1310 | desc->wl128x_mem.total_mem_blocks = blks; |
1266 | } else { | 1311 | } else { |
1267 | desc->wl127x_mem.extra_blocks = spare_blks; | 1312 | desc->wl127x_mem.extra_blocks = spare_blks; |
@@ -1275,7 +1320,7 @@ wl12xx_set_tx_desc_data_len(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc, | |||
1275 | { | 1320 | { |
1276 | u32 aligned_len = wlcore_calc_packet_alignment(wl, skb->len); | 1321 | u32 aligned_len = wlcore_calc_packet_alignment(wl, skb->len); |
1277 | 1322 | ||
1278 | if (wl->chip.id == CHIP_ID_1283_PG20) { | 1323 | if (wl->chip.id == CHIP_ID_128X_PG20) { |
1279 | desc->wl128x_mem.extra_bytes = aligned_len - skb->len; | 1324 | desc->wl128x_mem.extra_bytes = aligned_len - skb->len; |
1280 | desc->length = cpu_to_le16(aligned_len >> 2); | 1325 | desc->length = cpu_to_le16(aligned_len >> 2); |
1281 | 1326 | ||
@@ -1339,7 +1384,7 @@ static int wl12xx_hw_init(struct wl1271 *wl) | |||
1339 | { | 1384 | { |
1340 | int ret; | 1385 | int ret; |
1341 | 1386 | ||
1342 | if (wl->chip.id == CHIP_ID_1283_PG20) { | 1387 | if (wl->chip.id == CHIP_ID_128X_PG20) { |
1343 | u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE; | 1388 | u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE; |
1344 | 1389 | ||
1345 | ret = wl128x_cmd_general_parms(wl); | 1390 | ret = wl128x_cmd_general_parms(wl); |
@@ -1394,22 +1439,6 @@ static u32 wl12xx_sta_get_ap_rate_mask(struct wl1271 *wl, | |||
1394 | return wlvif->rate_set; | 1439 | return wlvif->rate_set; |
1395 | } | 1440 | } |
1396 | 1441 | ||
1397 | static int wl12xx_identify_fw(struct wl1271 *wl) | ||
1398 | { | ||
1399 | unsigned int *fw_ver = wl->chip.fw_ver; | ||
1400 | |||
1401 | /* Only new station firmwares support routing fw logs to the host */ | ||
1402 | if ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) && | ||
1403 | (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_FWLOG_STA_MIN)) | ||
1404 | wl->quirks |= WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED; | ||
1405 | |||
1406 | /* This feature is not yet supported for AP mode */ | ||
1407 | if (fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) | ||
1408 | wl->quirks |= WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED; | ||
1409 | |||
1410 | return 0; | ||
1411 | } | ||
1412 | |||
1413 | static void wl12xx_conf_init(struct wl1271 *wl) | 1442 | static void wl12xx_conf_init(struct wl1271 *wl) |
1414 | { | 1443 | { |
1415 | struct wl12xx_priv *priv = wl->priv; | 1444 | struct wl12xx_priv *priv = wl->priv; |
@@ -1426,7 +1455,7 @@ static bool wl12xx_mac_in_fuse(struct wl1271 *wl) | |||
1426 | bool supported = false; | 1455 | bool supported = false; |
1427 | u8 major, minor; | 1456 | u8 major, minor; |
1428 | 1457 | ||
1429 | if (wl->chip.id == CHIP_ID_1283_PG20) { | 1458 | if (wl->chip.id == CHIP_ID_128X_PG20) { |
1430 | major = WL128X_PG_GET_MAJOR(wl->hw_pg_ver); | 1459 | major = WL128X_PG_GET_MAJOR(wl->hw_pg_ver); |
1431 | minor = WL128X_PG_GET_MINOR(wl->hw_pg_ver); | 1460 | minor = WL128X_PG_GET_MINOR(wl->hw_pg_ver); |
1432 | 1461 | ||
@@ -1482,7 +1511,7 @@ static int wl12xx_get_pg_ver(struct wl1271 *wl, s8 *ver) | |||
1482 | u16 die_info; | 1511 | u16 die_info; |
1483 | int ret; | 1512 | int ret; |
1484 | 1513 | ||
1485 | if (wl->chip.id == CHIP_ID_1283_PG20) | 1514 | if (wl->chip.id == CHIP_ID_128X_PG20) |
1486 | ret = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1, | 1515 | ret = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1, |
1487 | &die_info); | 1516 | &die_info); |
1488 | else | 1517 | else |
@@ -1589,16 +1618,46 @@ static int wl12xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd, | |||
1589 | return wlcore_set_key(wl, cmd, vif, sta, key_conf); | 1618 | return wlcore_set_key(wl, cmd, vif, sta, key_conf); |
1590 | } | 1619 | } |
1591 | 1620 | ||
1621 | static int wl12xx_set_peer_cap(struct wl1271 *wl, | ||
1622 | struct ieee80211_sta_ht_cap *ht_cap, | ||
1623 | bool allow_ht_operation, | ||
1624 | u32 rate_set, u8 hlid) | ||
1625 | { | ||
1626 | return wl1271_acx_set_ht_capabilities(wl, ht_cap, allow_ht_operation, | ||
1627 | hlid); | ||
1628 | } | ||
1629 | |||
1630 | static bool wl12xx_lnk_high_prio(struct wl1271 *wl, u8 hlid, | ||
1631 | struct wl1271_link *lnk) | ||
1632 | { | ||
1633 | u8 thold; | ||
1634 | |||
1635 | if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map)) | ||
1636 | thold = wl->conf.tx.fast_link_thold; | ||
1637 | else | ||
1638 | thold = wl->conf.tx.slow_link_thold; | ||
1639 | |||
1640 | return lnk->allocated_pkts < thold; | ||
1641 | } | ||
1642 | |||
1643 | static bool wl12xx_lnk_low_prio(struct wl1271 *wl, u8 hlid, | ||
1644 | struct wl1271_link *lnk) | ||
1645 | { | ||
1646 | /* any link is good for low priority */ | ||
1647 | return true; | ||
1648 | } | ||
1649 | |||
1592 | static int wl12xx_setup(struct wl1271 *wl); | 1650 | static int wl12xx_setup(struct wl1271 *wl); |
1593 | 1651 | ||
1594 | static struct wlcore_ops wl12xx_ops = { | 1652 | static struct wlcore_ops wl12xx_ops = { |
1595 | .setup = wl12xx_setup, | 1653 | .setup = wl12xx_setup, |
1596 | .identify_chip = wl12xx_identify_chip, | 1654 | .identify_chip = wl12xx_identify_chip, |
1597 | .identify_fw = wl12xx_identify_fw, | ||
1598 | .boot = wl12xx_boot, | 1655 | .boot = wl12xx_boot, |
1599 | .plt_init = wl12xx_plt_init, | 1656 | .plt_init = wl12xx_plt_init, |
1600 | .trigger_cmd = wl12xx_trigger_cmd, | 1657 | .trigger_cmd = wl12xx_trigger_cmd, |
1601 | .ack_event = wl12xx_ack_event, | 1658 | .ack_event = wl12xx_ack_event, |
1659 | .wait_for_event = wl12xx_wait_for_event, | ||
1660 | .process_mailbox_events = wl12xx_process_mailbox_events, | ||
1602 | .calc_tx_blocks = wl12xx_calc_tx_blocks, | 1661 | .calc_tx_blocks = wl12xx_calc_tx_blocks, |
1603 | .set_tx_desc_blocks = wl12xx_set_tx_desc_blocks, | 1662 | .set_tx_desc_blocks = wl12xx_set_tx_desc_blocks, |
1604 | .set_tx_desc_data_len = wl12xx_set_tx_desc_data_len, | 1663 | .set_tx_desc_data_len = wl12xx_set_tx_desc_data_len, |
@@ -1615,9 +1674,17 @@ static struct wlcore_ops wl12xx_ops = { | |||
1615 | .set_rx_csum = NULL, | 1674 | .set_rx_csum = NULL, |
1616 | .ap_get_mimo_wide_rate_mask = NULL, | 1675 | .ap_get_mimo_wide_rate_mask = NULL, |
1617 | .debugfs_init = wl12xx_debugfs_add_files, | 1676 | .debugfs_init = wl12xx_debugfs_add_files, |
1677 | .scan_start = wl12xx_scan_start, | ||
1678 | .scan_stop = wl12xx_scan_stop, | ||
1679 | .sched_scan_start = wl12xx_sched_scan_start, | ||
1680 | .sched_scan_stop = wl12xx_scan_sched_scan_stop, | ||
1618 | .get_spare_blocks = wl12xx_get_spare_blocks, | 1681 | .get_spare_blocks = wl12xx_get_spare_blocks, |
1619 | .set_key = wl12xx_set_key, | 1682 | .set_key = wl12xx_set_key, |
1683 | .channel_switch = wl12xx_cmd_channel_switch, | ||
1620 | .pre_pkt_send = NULL, | 1684 | .pre_pkt_send = NULL, |
1685 | .set_peer_cap = wl12xx_set_peer_cap, | ||
1686 | .lnk_high_prio = wl12xx_lnk_high_prio, | ||
1687 | .lnk_low_prio = wl12xx_lnk_low_prio, | ||
1621 | }; | 1688 | }; |
1622 | 1689 | ||
1623 | static struct ieee80211_sta_ht_cap wl12xx_ht_cap = { | 1690 | static struct ieee80211_sta_ht_cap wl12xx_ht_cap = { |
@@ -1641,6 +1708,7 @@ static int wl12xx_setup(struct wl1271 *wl) | |||
1641 | wl->rtable = wl12xx_rtable; | 1708 | wl->rtable = wl12xx_rtable; |
1642 | wl->num_tx_desc = WL12XX_NUM_TX_DESCRIPTORS; | 1709 | wl->num_tx_desc = WL12XX_NUM_TX_DESCRIPTORS; |
1643 | wl->num_rx_desc = WL12XX_NUM_RX_DESCRIPTORS; | 1710 | wl->num_rx_desc = WL12XX_NUM_RX_DESCRIPTORS; |
1711 | wl->num_channels = 1; | ||
1644 | wl->num_mac_addr = WL12XX_NUM_MAC_ADDRESSES; | 1712 | wl->num_mac_addr = WL12XX_NUM_MAC_ADDRESSES; |
1645 | wl->band_rate_to_idx = wl12xx_band_rate_to_idx; | 1713 | wl->band_rate_to_idx = wl12xx_band_rate_to_idx; |
1646 | wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX; | 1714 | wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX; |
@@ -1693,6 +1761,10 @@ static int wl12xx_setup(struct wl1271 *wl) | |||
1693 | wl1271_error("Invalid tcxo parameter %s", tcxo_param); | 1761 | wl1271_error("Invalid tcxo parameter %s", tcxo_param); |
1694 | } | 1762 | } |
1695 | 1763 | ||
1764 | priv->rx_mem_addr = kmalloc(sizeof(*priv->rx_mem_addr), GFP_KERNEL); | ||
1765 | if (!priv->rx_mem_addr) | ||
1766 | return -ENOMEM; | ||
1767 | |||
1696 | return 0; | 1768 | return 0; |
1697 | } | 1769 | } |
1698 | 1770 | ||
@@ -1703,7 +1775,8 @@ static int wl12xx_probe(struct platform_device *pdev) | |||
1703 | int ret; | 1775 | int ret; |
1704 | 1776 | ||
1705 | hw = wlcore_alloc_hw(sizeof(struct wl12xx_priv), | 1777 | hw = wlcore_alloc_hw(sizeof(struct wl12xx_priv), |
1706 | WL12XX_AGGR_BUFFER_SIZE); | 1778 | WL12XX_AGGR_BUFFER_SIZE, |
1779 | sizeof(struct wl12xx_event_mailbox)); | ||
1707 | if (IS_ERR(hw)) { | 1780 | if (IS_ERR(hw)) { |
1708 | wl1271_error("can't allocate hw"); | 1781 | wl1271_error("can't allocate hw"); |
1709 | ret = PTR_ERR(hw); | 1782 | ret = PTR_ERR(hw); |
@@ -1725,6 +1798,21 @@ out: | |||
1725 | return ret; | 1798 | return ret; |
1726 | } | 1799 | } |
1727 | 1800 | ||
1801 | static int wl12xx_remove(struct platform_device *pdev) | ||
1802 | { | ||
1803 | struct wl1271 *wl = platform_get_drvdata(pdev); | ||
1804 | struct wl12xx_priv *priv; | ||
1805 | |||
1806 | if (!wl) | ||
1807 | goto out; | ||
1808 | priv = wl->priv; | ||
1809 | |||
1810 | kfree(priv->rx_mem_addr); | ||
1811 | |||
1812 | out: | ||
1813 | return wlcore_remove(pdev); | ||
1814 | } | ||
1815 | |||
1728 | static const struct platform_device_id wl12xx_id_table[] = { | 1816 | static const struct platform_device_id wl12xx_id_table[] = { |
1729 | { "wl12xx", 0 }, | 1817 | { "wl12xx", 0 }, |
1730 | { } /* Terminating Entry */ | 1818 | { } /* Terminating Entry */ |
@@ -1733,7 +1821,7 @@ MODULE_DEVICE_TABLE(platform, wl12xx_id_table); | |||
1733 | 1821 | ||
1734 | static struct platform_driver wl12xx_driver = { | 1822 | static struct platform_driver wl12xx_driver = { |
1735 | .probe = wl12xx_probe, | 1823 | .probe = wl12xx_probe, |
1736 | .remove = wlcore_remove, | 1824 | .remove = wl12xx_remove, |
1737 | .id_table = wl12xx_id_table, | 1825 | .id_table = wl12xx_id_table, |
1738 | .driver = { | 1826 | .driver = { |
1739 | .name = "wl12xx_driver", | 1827 | .name = "wl12xx_driver", |
diff --git a/drivers/net/wireless/ti/wl12xx/scan.c b/drivers/net/wireless/ti/wl12xx/scan.c new file mode 100644 index 000000000000..affdb3ec6225 --- /dev/null +++ b/drivers/net/wireless/ti/wl12xx/scan.c | |||
@@ -0,0 +1,501 @@ | |||
1 | /* | ||
2 | * This file is part of wl12xx | ||
3 | * | ||
4 | * Copyright (C) 2012 Texas Instruments. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <linux/ieee80211.h> | ||
23 | #include "scan.h" | ||
24 | #include "../wlcore/debug.h" | ||
25 | #include "../wlcore/tx.h" | ||
26 | |||
27 | static int wl1271_get_scan_channels(struct wl1271 *wl, | ||
28 | struct cfg80211_scan_request *req, | ||
29 | struct basic_scan_channel_params *channels, | ||
30 | enum ieee80211_band band, bool passive) | ||
31 | { | ||
32 | struct conf_scan_settings *c = &wl->conf.scan; | ||
33 | int i, j; | ||
34 | u32 flags; | ||
35 | |||
36 | for (i = 0, j = 0; | ||
37 | i < req->n_channels && j < WL1271_SCAN_MAX_CHANNELS; | ||
38 | i++) { | ||
39 | flags = req->channels[i]->flags; | ||
40 | |||
41 | if (!test_bit(i, wl->scan.scanned_ch) && | ||
42 | !(flags & IEEE80211_CHAN_DISABLED) && | ||
43 | (req->channels[i]->band == band) && | ||
44 | /* | ||
45 | * In passive scans, we scan all remaining | ||
46 | * channels, even if not marked as such. | ||
47 | * In active scans, we only scan channels not | ||
48 | * marked as passive. | ||
49 | */ | ||
50 | (passive || !(flags & IEEE80211_CHAN_PASSIVE_SCAN))) { | ||
51 | wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ", | ||
52 | req->channels[i]->band, | ||
53 | req->channels[i]->center_freq); | ||
54 | wl1271_debug(DEBUG_SCAN, "hw_value %d, flags %X", | ||
55 | req->channels[i]->hw_value, | ||
56 | req->channels[i]->flags); | ||
57 | wl1271_debug(DEBUG_SCAN, | ||
58 | "max_antenna_gain %d, max_power %d", | ||
59 | req->channels[i]->max_antenna_gain, | ||
60 | req->channels[i]->max_power); | ||
61 | wl1271_debug(DEBUG_SCAN, "beacon_found %d", | ||
62 | req->channels[i]->beacon_found); | ||
63 | |||
64 | if (!passive) { | ||
65 | channels[j].min_duration = | ||
66 | cpu_to_le32(c->min_dwell_time_active); | ||
67 | channels[j].max_duration = | ||
68 | cpu_to_le32(c->max_dwell_time_active); | ||
69 | } else { | ||
70 | channels[j].min_duration = | ||
71 | cpu_to_le32(c->dwell_time_passive); | ||
72 | channels[j].max_duration = | ||
73 | cpu_to_le32(c->dwell_time_passive); | ||
74 | } | ||
75 | channels[j].early_termination = 0; | ||
76 | channels[j].tx_power_att = req->channels[i]->max_power; | ||
77 | channels[j].channel = req->channels[i]->hw_value; | ||
78 | |||
79 | memset(&channels[j].bssid_lsb, 0xff, 4); | ||
80 | memset(&channels[j].bssid_msb, 0xff, 2); | ||
81 | |||
82 | /* Mark the channels we already used */ | ||
83 | set_bit(i, wl->scan.scanned_ch); | ||
84 | |||
85 | j++; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | return j; | ||
90 | } | ||
91 | |||
92 | #define WL1271_NOTHING_TO_SCAN 1 | ||
93 | |||
94 | static int wl1271_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
95 | enum ieee80211_band band, | ||
96 | bool passive, u32 basic_rate) | ||
97 | { | ||
98 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); | ||
99 | struct wl1271_cmd_scan *cmd; | ||
100 | struct wl1271_cmd_trigger_scan_to *trigger; | ||
101 | int ret; | ||
102 | u16 scan_options = 0; | ||
103 | |||
104 | /* skip active scans if we don't have SSIDs */ | ||
105 | if (!passive && wl->scan.req->n_ssids == 0) | ||
106 | return WL1271_NOTHING_TO_SCAN; | ||
107 | |||
108 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
109 | trigger = kzalloc(sizeof(*trigger), GFP_KERNEL); | ||
110 | if (!cmd || !trigger) { | ||
111 | ret = -ENOMEM; | ||
112 | goto out; | ||
113 | } | ||
114 | |||
115 | if (wl->conf.scan.split_scan_timeout) | ||
116 | scan_options |= WL1271_SCAN_OPT_SPLIT_SCAN; | ||
117 | |||
118 | if (passive) | ||
119 | scan_options |= WL1271_SCAN_OPT_PASSIVE; | ||
120 | |||
121 | cmd->params.role_id = wlvif->role_id; | ||
122 | |||
123 | if (WARN_ON(cmd->params.role_id == WL12XX_INVALID_ROLE_ID)) { | ||
124 | ret = -EINVAL; | ||
125 | goto out; | ||
126 | } | ||
127 | |||
128 | cmd->params.scan_options = cpu_to_le16(scan_options); | ||
129 | |||
130 | cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req, | ||
131 | cmd->channels, | ||
132 | band, passive); | ||
133 | if (cmd->params.n_ch == 0) { | ||
134 | ret = WL1271_NOTHING_TO_SCAN; | ||
135 | goto out; | ||
136 | } | ||
137 | |||
138 | cmd->params.tx_rate = cpu_to_le32(basic_rate); | ||
139 | cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs; | ||
140 | cmd->params.tid_trigger = CONF_TX_AC_ANY_TID; | ||
141 | cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; | ||
142 | |||
143 | if (band == IEEE80211_BAND_2GHZ) | ||
144 | cmd->params.band = WL1271_SCAN_BAND_2_4_GHZ; | ||
145 | else | ||
146 | cmd->params.band = WL1271_SCAN_BAND_5_GHZ; | ||
147 | |||
148 | if (wl->scan.ssid_len && wl->scan.ssid) { | ||
149 | cmd->params.ssid_len = wl->scan.ssid_len; | ||
150 | memcpy(cmd->params.ssid, wl->scan.ssid, wl->scan.ssid_len); | ||
151 | } | ||
152 | |||
153 | memcpy(cmd->addr, vif->addr, ETH_ALEN); | ||
154 | |||
155 | ret = wl12xx_cmd_build_probe_req(wl, wlvif, | ||
156 | cmd->params.role_id, band, | ||
157 | wl->scan.ssid, wl->scan.ssid_len, | ||
158 | wl->scan.req->ie, | ||
159 | wl->scan.req->ie_len, false); | ||
160 | if (ret < 0) { | ||
161 | wl1271_error("PROBE request template failed"); | ||
162 | goto out; | ||
163 | } | ||
164 | |||
165 | trigger->timeout = cpu_to_le32(wl->conf.scan.split_scan_timeout); | ||
166 | ret = wl1271_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger, | ||
167 | sizeof(*trigger), 0); | ||
168 | if (ret < 0) { | ||
169 | wl1271_error("trigger scan to failed for hw scan"); | ||
170 | goto out; | ||
171 | } | ||
172 | |||
173 | wl1271_dump(DEBUG_SCAN, "SCAN: ", cmd, sizeof(*cmd)); | ||
174 | |||
175 | ret = wl1271_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd), 0); | ||
176 | if (ret < 0) { | ||
177 | wl1271_error("SCAN failed"); | ||
178 | goto out; | ||
179 | } | ||
180 | |||
181 | out: | ||
182 | kfree(cmd); | ||
183 | kfree(trigger); | ||
184 | return ret; | ||
185 | } | ||
186 | |||
187 | int wl12xx_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif) | ||
188 | { | ||
189 | struct wl1271_cmd_header *cmd = NULL; | ||
190 | int ret = 0; | ||
191 | |||
192 | if (WARN_ON(wl->scan.state == WL1271_SCAN_STATE_IDLE)) | ||
193 | return -EINVAL; | ||
194 | |||
195 | wl1271_debug(DEBUG_CMD, "cmd scan stop"); | ||
196 | |||
197 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
198 | if (!cmd) { | ||
199 | ret = -ENOMEM; | ||
200 | goto out; | ||
201 | } | ||
202 | |||
203 | ret = wl1271_cmd_send(wl, CMD_STOP_SCAN, cmd, | ||
204 | sizeof(*cmd), 0); | ||
205 | if (ret < 0) { | ||
206 | wl1271_error("cmd stop_scan failed"); | ||
207 | goto out; | ||
208 | } | ||
209 | out: | ||
210 | kfree(cmd); | ||
211 | return ret; | ||
212 | } | ||
213 | |||
214 | void wl1271_scan_stm(struct wl1271 *wl, struct wl12xx_vif *wlvif) | ||
215 | { | ||
216 | int ret = 0; | ||
217 | enum ieee80211_band band; | ||
218 | u32 rate, mask; | ||
219 | |||
220 | switch (wl->scan.state) { | ||
221 | case WL1271_SCAN_STATE_IDLE: | ||
222 | break; | ||
223 | |||
224 | case WL1271_SCAN_STATE_2GHZ_ACTIVE: | ||
225 | band = IEEE80211_BAND_2GHZ; | ||
226 | mask = wlvif->bitrate_masks[band]; | ||
227 | if (wl->scan.req->no_cck) { | ||
228 | mask &= ~CONF_TX_CCK_RATES; | ||
229 | if (!mask) | ||
230 | mask = CONF_TX_RATE_MASK_BASIC_P2P; | ||
231 | } | ||
232 | rate = wl1271_tx_min_rate_get(wl, mask); | ||
233 | ret = wl1271_scan_send(wl, wlvif, band, false, rate); | ||
234 | if (ret == WL1271_NOTHING_TO_SCAN) { | ||
235 | wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE; | ||
236 | wl1271_scan_stm(wl, wlvif); | ||
237 | } | ||
238 | |||
239 | break; | ||
240 | |||
241 | case WL1271_SCAN_STATE_2GHZ_PASSIVE: | ||
242 | band = IEEE80211_BAND_2GHZ; | ||
243 | mask = wlvif->bitrate_masks[band]; | ||
244 | if (wl->scan.req->no_cck) { | ||
245 | mask &= ~CONF_TX_CCK_RATES; | ||
246 | if (!mask) | ||
247 | mask = CONF_TX_RATE_MASK_BASIC_P2P; | ||
248 | } | ||
249 | rate = wl1271_tx_min_rate_get(wl, mask); | ||
250 | ret = wl1271_scan_send(wl, wlvif, band, true, rate); | ||
251 | if (ret == WL1271_NOTHING_TO_SCAN) { | ||
252 | if (wl->enable_11a) | ||
253 | wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE; | ||
254 | else | ||
255 | wl->scan.state = WL1271_SCAN_STATE_DONE; | ||
256 | wl1271_scan_stm(wl, wlvif); | ||
257 | } | ||
258 | |||
259 | break; | ||
260 | |||
261 | case WL1271_SCAN_STATE_5GHZ_ACTIVE: | ||
262 | band = IEEE80211_BAND_5GHZ; | ||
263 | rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); | ||
264 | ret = wl1271_scan_send(wl, wlvif, band, false, rate); | ||
265 | if (ret == WL1271_NOTHING_TO_SCAN) { | ||
266 | wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE; | ||
267 | wl1271_scan_stm(wl, wlvif); | ||
268 | } | ||
269 | |||
270 | break; | ||
271 | |||
272 | case WL1271_SCAN_STATE_5GHZ_PASSIVE: | ||
273 | band = IEEE80211_BAND_5GHZ; | ||
274 | rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); | ||
275 | ret = wl1271_scan_send(wl, wlvif, band, true, rate); | ||
276 | if (ret == WL1271_NOTHING_TO_SCAN) { | ||
277 | wl->scan.state = WL1271_SCAN_STATE_DONE; | ||
278 | wl1271_scan_stm(wl, wlvif); | ||
279 | } | ||
280 | |||
281 | break; | ||
282 | |||
283 | case WL1271_SCAN_STATE_DONE: | ||
284 | wl->scan.failed = false; | ||
285 | cancel_delayed_work(&wl->scan_complete_work); | ||
286 | ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, | ||
287 | msecs_to_jiffies(0)); | ||
288 | break; | ||
289 | |||
290 | default: | ||
291 | wl1271_error("invalid scan state"); | ||
292 | break; | ||
293 | } | ||
294 | |||
295 | if (ret < 0) { | ||
296 | cancel_delayed_work(&wl->scan_complete_work); | ||
297 | ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, | ||
298 | msecs_to_jiffies(0)); | ||
299 | } | ||
300 | } | ||
301 | |||
302 | static void wl12xx_adjust_channels(struct wl1271_cmd_sched_scan_config *cmd, | ||
303 | struct wlcore_scan_channels *cmd_channels) | ||
304 | { | ||
305 | memcpy(cmd->passive, cmd_channels->passive, sizeof(cmd->passive)); | ||
306 | memcpy(cmd->active, cmd_channels->active, sizeof(cmd->active)); | ||
307 | cmd->dfs = cmd_channels->dfs; | ||
308 | cmd->n_pactive_ch = cmd_channels->passive_active; | ||
309 | |||
310 | memcpy(cmd->channels_2, cmd_channels->channels_2, | ||
311 | sizeof(cmd->channels_2)); | ||
312 | memcpy(cmd->channels_5, cmd_channels->channels_5, | ||
313 | sizeof(cmd->channels_2)); | ||
314 | /* channels_4 are not supported, so no need to copy them */ | ||
315 | } | ||
316 | |||
317 | int wl1271_scan_sched_scan_config(struct wl1271 *wl, | ||
318 | struct wl12xx_vif *wlvif, | ||
319 | struct cfg80211_sched_scan_request *req, | ||
320 | struct ieee80211_sched_scan_ies *ies) | ||
321 | { | ||
322 | struct wl1271_cmd_sched_scan_config *cfg = NULL; | ||
323 | struct wlcore_scan_channels *cfg_channels = NULL; | ||
324 | struct conf_sched_scan_settings *c = &wl->conf.sched_scan; | ||
325 | int i, ret; | ||
326 | bool force_passive = !req->n_ssids; | ||
327 | |||
328 | wl1271_debug(DEBUG_CMD, "cmd sched_scan scan config"); | ||
329 | |||
330 | cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); | ||
331 | if (!cfg) | ||
332 | return -ENOMEM; | ||
333 | |||
334 | cfg->role_id = wlvif->role_id; | ||
335 | cfg->rssi_threshold = c->rssi_threshold; | ||
336 | cfg->snr_threshold = c->snr_threshold; | ||
337 | cfg->n_probe_reqs = c->num_probe_reqs; | ||
338 | /* cycles set to 0 it means infinite (until manually stopped) */ | ||
339 | cfg->cycles = 0; | ||
340 | /* report APs when at least 1 is found */ | ||
341 | cfg->report_after = 1; | ||
342 | /* don't stop scanning automatically when something is found */ | ||
343 | cfg->terminate = 0; | ||
344 | cfg->tag = WL1271_SCAN_DEFAULT_TAG; | ||
345 | /* don't filter on BSS type */ | ||
346 | cfg->bss_type = SCAN_BSS_TYPE_ANY; | ||
347 | /* currently NL80211 supports only a single interval */ | ||
348 | for (i = 0; i < SCAN_MAX_CYCLE_INTERVALS; i++) | ||
349 | cfg->intervals[i] = cpu_to_le32(req->interval); | ||
350 | |||
351 | cfg->ssid_len = 0; | ||
352 | ret = wlcore_scan_sched_scan_ssid_list(wl, wlvif, req); | ||
353 | if (ret < 0) | ||
354 | goto out; | ||
355 | |||
356 | cfg->filter_type = ret; | ||
357 | |||
358 | wl1271_debug(DEBUG_SCAN, "filter_type = %d", cfg->filter_type); | ||
359 | |||
360 | cfg_channels = kzalloc(sizeof(*cfg_channels), GFP_KERNEL); | ||
361 | if (!cfg_channels) { | ||
362 | ret = -ENOMEM; | ||
363 | goto out; | ||
364 | } | ||
365 | |||
366 | if (!wlcore_set_scan_chan_params(wl, cfg_channels, req->channels, | ||
367 | req->n_channels, req->n_ssids, | ||
368 | SCAN_TYPE_PERIODIC)) { | ||
369 | wl1271_error("scan channel list is empty"); | ||
370 | ret = -EINVAL; | ||
371 | goto out; | ||
372 | } | ||
373 | wl12xx_adjust_channels(cfg, cfg_channels); | ||
374 | |||
375 | if (!force_passive && cfg->active[0]) { | ||
376 | u8 band = IEEE80211_BAND_2GHZ; | ||
377 | ret = wl12xx_cmd_build_probe_req(wl, wlvif, | ||
378 | wlvif->role_id, band, | ||
379 | req->ssids[0].ssid, | ||
380 | req->ssids[0].ssid_len, | ||
381 | ies->ie[band], | ||
382 | ies->len[band], true); | ||
383 | if (ret < 0) { | ||
384 | wl1271_error("2.4GHz PROBE request template failed"); | ||
385 | goto out; | ||
386 | } | ||
387 | } | ||
388 | |||
389 | if (!force_passive && cfg->active[1]) { | ||
390 | u8 band = IEEE80211_BAND_5GHZ; | ||
391 | ret = wl12xx_cmd_build_probe_req(wl, wlvif, | ||
392 | wlvif->role_id, band, | ||
393 | req->ssids[0].ssid, | ||
394 | req->ssids[0].ssid_len, | ||
395 | ies->ie[band], | ||
396 | ies->len[band], true); | ||
397 | if (ret < 0) { | ||
398 | wl1271_error("5GHz PROBE request template failed"); | ||
399 | goto out; | ||
400 | } | ||
401 | } | ||
402 | |||
403 | wl1271_dump(DEBUG_SCAN, "SCAN_CFG: ", cfg, sizeof(*cfg)); | ||
404 | |||
405 | ret = wl1271_cmd_send(wl, CMD_CONNECTION_SCAN_CFG, cfg, | ||
406 | sizeof(*cfg), 0); | ||
407 | if (ret < 0) { | ||
408 | wl1271_error("SCAN configuration failed"); | ||
409 | goto out; | ||
410 | } | ||
411 | out: | ||
412 | kfree(cfg_channels); | ||
413 | kfree(cfg); | ||
414 | return ret; | ||
415 | } | ||
416 | |||
417 | int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif) | ||
418 | { | ||
419 | struct wl1271_cmd_sched_scan_start *start; | ||
420 | int ret = 0; | ||
421 | |||
422 | wl1271_debug(DEBUG_CMD, "cmd periodic scan start"); | ||
423 | |||
424 | if (wlvif->bss_type != BSS_TYPE_STA_BSS) | ||
425 | return -EOPNOTSUPP; | ||
426 | |||
427 | if ((wl->quirks & WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN) && | ||
428 | test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags)) | ||
429 | return -EBUSY; | ||
430 | |||
431 | start = kzalloc(sizeof(*start), GFP_KERNEL); | ||
432 | if (!start) | ||
433 | return -ENOMEM; | ||
434 | |||
435 | start->role_id = wlvif->role_id; | ||
436 | start->tag = WL1271_SCAN_DEFAULT_TAG; | ||
437 | |||
438 | ret = wl1271_cmd_send(wl, CMD_START_PERIODIC_SCAN, start, | ||
439 | sizeof(*start), 0); | ||
440 | if (ret < 0) { | ||
441 | wl1271_error("failed to send scan start command"); | ||
442 | goto out_free; | ||
443 | } | ||
444 | |||
445 | out_free: | ||
446 | kfree(start); | ||
447 | return ret; | ||
448 | } | ||
449 | |||
450 | int wl12xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
451 | struct cfg80211_sched_scan_request *req, | ||
452 | struct ieee80211_sched_scan_ies *ies) | ||
453 | { | ||
454 | int ret; | ||
455 | |||
456 | ret = wl1271_scan_sched_scan_config(wl, wlvif, req, ies); | ||
457 | if (ret < 0) | ||
458 | return ret; | ||
459 | |||
460 | return wl1271_scan_sched_scan_start(wl, wlvif); | ||
461 | } | ||
462 | |||
463 | void wl12xx_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif) | ||
464 | { | ||
465 | struct wl1271_cmd_sched_scan_stop *stop; | ||
466 | int ret = 0; | ||
467 | |||
468 | wl1271_debug(DEBUG_CMD, "cmd periodic scan stop"); | ||
469 | |||
470 | /* FIXME: what to do if alloc'ing to stop fails? */ | ||
471 | stop = kzalloc(sizeof(*stop), GFP_KERNEL); | ||
472 | if (!stop) { | ||
473 | wl1271_error("failed to alloc memory to send sched scan stop"); | ||
474 | return; | ||
475 | } | ||
476 | |||
477 | stop->role_id = wlvif->role_id; | ||
478 | stop->tag = WL1271_SCAN_DEFAULT_TAG; | ||
479 | |||
480 | ret = wl1271_cmd_send(wl, CMD_STOP_PERIODIC_SCAN, stop, | ||
481 | sizeof(*stop), 0); | ||
482 | if (ret < 0) { | ||
483 | wl1271_error("failed to send sched scan stop command"); | ||
484 | goto out_free; | ||
485 | } | ||
486 | |||
487 | out_free: | ||
488 | kfree(stop); | ||
489 | } | ||
490 | |||
491 | int wl12xx_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
492 | struct cfg80211_scan_request *req) | ||
493 | { | ||
494 | wl1271_scan_stm(wl, wlvif); | ||
495 | return 0; | ||
496 | } | ||
497 | |||
498 | void wl12xx_scan_completed(struct wl1271 *wl, struct wl12xx_vif *wlvif) | ||
499 | { | ||
500 | wl1271_scan_stm(wl, wlvif); | ||
501 | } | ||
diff --git a/drivers/net/wireless/ti/wl12xx/scan.h b/drivers/net/wireless/ti/wl12xx/scan.h new file mode 100644 index 000000000000..264af7ac2785 --- /dev/null +++ b/drivers/net/wireless/ti/wl12xx/scan.h | |||
@@ -0,0 +1,140 @@ | |||
1 | /* | ||
2 | * This file is part of wl12xx | ||
3 | * | ||
4 | * Copyright (C) 2012 Texas Instruments. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef __WL12XX_SCAN_H__ | ||
23 | #define __WL12XX_SCAN_H__ | ||
24 | |||
25 | #include "../wlcore/wlcore.h" | ||
26 | #include "../wlcore/cmd.h" | ||
27 | #include "../wlcore/scan.h" | ||
28 | |||
29 | #define WL12XX_MAX_CHANNELS_5GHZ 23 | ||
30 | |||
31 | struct basic_scan_params { | ||
32 | /* Scan option flags (WL1271_SCAN_OPT_*) */ | ||
33 | __le16 scan_options; | ||
34 | u8 role_id; | ||
35 | /* Number of scan channels in the list (maximum 30) */ | ||
36 | u8 n_ch; | ||
37 | /* This field indicates the number of probe requests to send | ||
38 | per channel for an active scan */ | ||
39 | u8 n_probe_reqs; | ||
40 | u8 tid_trigger; | ||
41 | u8 ssid_len; | ||
42 | u8 use_ssid_list; | ||
43 | |||
44 | /* Rate bit field for sending the probes */ | ||
45 | __le32 tx_rate; | ||
46 | |||
47 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | ||
48 | /* Band to scan */ | ||
49 | u8 band; | ||
50 | |||
51 | u8 scan_tag; | ||
52 | u8 padding2[2]; | ||
53 | } __packed; | ||
54 | |||
55 | struct basic_scan_channel_params { | ||
56 | /* Duration in TU to wait for frames on a channel for active scan */ | ||
57 | __le32 min_duration; | ||
58 | __le32 max_duration; | ||
59 | __le32 bssid_lsb; | ||
60 | __le16 bssid_msb; | ||
61 | u8 early_termination; | ||
62 | u8 tx_power_att; | ||
63 | u8 channel; | ||
64 | /* FW internal use only! */ | ||
65 | u8 dfs_candidate; | ||
66 | u8 activity_detected; | ||
67 | u8 pad; | ||
68 | } __packed; | ||
69 | |||
70 | struct wl1271_cmd_scan { | ||
71 | struct wl1271_cmd_header header; | ||
72 | |||
73 | struct basic_scan_params params; | ||
74 | struct basic_scan_channel_params channels[WL1271_SCAN_MAX_CHANNELS]; | ||
75 | |||
76 | /* src mac address */ | ||
77 | u8 addr[ETH_ALEN]; | ||
78 | u8 padding[2]; | ||
79 | } __packed; | ||
80 | |||
81 | struct wl1271_cmd_sched_scan_config { | ||
82 | struct wl1271_cmd_header header; | ||
83 | |||
84 | __le32 intervals[SCAN_MAX_CYCLE_INTERVALS]; | ||
85 | |||
86 | s8 rssi_threshold; /* for filtering (in dBm) */ | ||
87 | s8 snr_threshold; /* for filtering (in dB) */ | ||
88 | |||
89 | u8 cycles; /* maximum number of scan cycles */ | ||
90 | u8 report_after; /* report when this number of results are received */ | ||
91 | u8 terminate; /* stop scanning after reporting */ | ||
92 | |||
93 | u8 tag; | ||
94 | u8 bss_type; /* for filtering */ | ||
95 | u8 filter_type; | ||
96 | |||
97 | u8 ssid_len; /* For SCAN_SSID_FILTER_SPECIFIC */ | ||
98 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | ||
99 | |||
100 | u8 n_probe_reqs; /* Number of probes requests per channel */ | ||
101 | |||
102 | u8 passive[SCAN_MAX_BANDS]; | ||
103 | u8 active[SCAN_MAX_BANDS]; | ||
104 | |||
105 | u8 dfs; | ||
106 | |||
107 | u8 n_pactive_ch; /* number of pactive (passive until fw detects energy) | ||
108 | channels in BG band */ | ||
109 | u8 role_id; | ||
110 | u8 padding[1]; | ||
111 | struct conn_scan_ch_params channels_2[MAX_CHANNELS_2GHZ]; | ||
112 | struct conn_scan_ch_params channels_5[WL12XX_MAX_CHANNELS_5GHZ]; | ||
113 | struct conn_scan_ch_params channels_4[MAX_CHANNELS_4GHZ]; | ||
114 | } __packed; | ||
115 | |||
116 | struct wl1271_cmd_sched_scan_start { | ||
117 | struct wl1271_cmd_header header; | ||
118 | |||
119 | u8 tag; | ||
120 | u8 role_id; | ||
121 | u8 padding[2]; | ||
122 | } __packed; | ||
123 | |||
124 | struct wl1271_cmd_sched_scan_stop { | ||
125 | struct wl1271_cmd_header header; | ||
126 | |||
127 | u8 tag; | ||
128 | u8 role_id; | ||
129 | u8 padding[2]; | ||
130 | } __packed; | ||
131 | |||
132 | int wl12xx_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
133 | struct cfg80211_scan_request *req); | ||
134 | int wl12xx_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif); | ||
135 | void wl12xx_scan_completed(struct wl1271 *wl, struct wl12xx_vif *wlvif); | ||
136 | int wl12xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
137 | struct cfg80211_sched_scan_request *req, | ||
138 | struct ieee80211_sched_scan_ies *ies); | ||
139 | void wl12xx_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif); | ||
140 | #endif | ||
diff --git a/drivers/net/wireless/ti/wl12xx/wl12xx.h b/drivers/net/wireless/ti/wl12xx/wl12xx.h index 7182bbf6625d..d4552857480c 100644 --- a/drivers/net/wireless/ti/wl12xx/wl12xx.h +++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h | |||
@@ -24,19 +24,37 @@ | |||
24 | 24 | ||
25 | #include "conf.h" | 25 | #include "conf.h" |
26 | 26 | ||
27 | /* minimum FW required for driver for wl127x */ | 27 | /* WiLink 6/7 chip IDs */ |
28 | #define CHIP_ID_127X_PG10 (0x04030101) | ||
29 | #define CHIP_ID_127X_PG20 (0x04030111) | ||
30 | #define CHIP_ID_128X_PG10 (0x05030101) | ||
31 | #define CHIP_ID_128X_PG20 (0x05030111) | ||
32 | |||
33 | /* FW chip version for wl127x */ | ||
28 | #define WL127X_CHIP_VER 6 | 34 | #define WL127X_CHIP_VER 6 |
29 | #define WL127X_IFTYPE_VER 3 | 35 | /* minimum single-role FW version for wl127x */ |
30 | #define WL127X_MAJOR_VER 10 | 36 | #define WL127X_IFTYPE_SR_VER 3 |
31 | #define WL127X_SUBTYPE_VER 2 | 37 | #define WL127X_MAJOR_SR_VER 10 |
32 | #define WL127X_MINOR_VER 115 | 38 | #define WL127X_SUBTYPE_SR_VER WLCORE_FW_VER_IGNORE |
39 | #define WL127X_MINOR_SR_VER 115 | ||
40 | /* minimum multi-role FW version for wl127x */ | ||
41 | #define WL127X_IFTYPE_MR_VER 5 | ||
42 | #define WL127X_MAJOR_MR_VER 7 | ||
43 | #define WL127X_SUBTYPE_MR_VER WLCORE_FW_VER_IGNORE | ||
44 | #define WL127X_MINOR_MR_VER 115 | ||
33 | 45 | ||
34 | /* minimum FW required for driver for wl128x */ | 46 | /* FW chip version for wl128x */ |
35 | #define WL128X_CHIP_VER 7 | 47 | #define WL128X_CHIP_VER 7 |
36 | #define WL128X_IFTYPE_VER 3 | 48 | /* minimum single-role FW version for wl128x */ |
37 | #define WL128X_MAJOR_VER 10 | 49 | #define WL128X_IFTYPE_SR_VER 3 |
38 | #define WL128X_SUBTYPE_VER 2 | 50 | #define WL128X_MAJOR_SR_VER 10 |
39 | #define WL128X_MINOR_VER 115 | 51 | #define WL128X_SUBTYPE_SR_VER WLCORE_FW_VER_IGNORE |
52 | #define WL128X_MINOR_SR_VER 115 | ||
53 | /* minimum multi-role FW version for wl128x */ | ||
54 | #define WL128X_IFTYPE_MR_VER 5 | ||
55 | #define WL128X_MAJOR_MR_VER 7 | ||
56 | #define WL128X_SUBTYPE_MR_VER WLCORE_FW_VER_IGNORE | ||
57 | #define WL128X_MINOR_MR_VER 42 | ||
40 | 58 | ||
41 | #define WL12XX_AGGR_BUFFER_SIZE (4 * PAGE_SIZE) | 59 | #define WL12XX_AGGR_BUFFER_SIZE (4 * PAGE_SIZE) |
42 | 60 | ||
@@ -55,6 +73,8 @@ struct wl12xx_priv { | |||
55 | 73 | ||
56 | int ref_clock; | 74 | int ref_clock; |
57 | int tcxo_clock; | 75 | int tcxo_clock; |
76 | |||
77 | struct wl127x_rx_mem_pool_addr *rx_mem_addr; | ||
58 | }; | 78 | }; |
59 | 79 | ||
60 | #endif /* __WL12XX_PRIV_H__ */ | 80 | #endif /* __WL12XX_PRIV_H__ */ |
diff --git a/drivers/net/wireless/ti/wl18xx/Makefile b/drivers/net/wireless/ti/wl18xx/Makefile index 67c098734c7f..ae2b81735785 100644 --- a/drivers/net/wireless/ti/wl18xx/Makefile +++ b/drivers/net/wireless/ti/wl18xx/Makefile | |||
@@ -1,3 +1,3 @@ | |||
1 | wl18xx-objs = main.o acx.o tx.o io.o debugfs.o | 1 | wl18xx-objs = main.o acx.o tx.o io.o debugfs.o scan.o cmd.o event.o |
2 | 2 | ||
3 | obj-$(CONFIG_WL18XX) += wl18xx.o | 3 | obj-$(CONFIG_WL18XX) += wl18xx.o |
diff --git a/drivers/net/wireless/ti/wl18xx/acx.c b/drivers/net/wireless/ti/wl18xx/acx.c index 72840e23bf59..a169bb5a5dbf 100644 --- a/drivers/net/wireless/ti/wl18xx/acx.c +++ b/drivers/net/wireless/ti/wl18xx/acx.c | |||
@@ -75,7 +75,7 @@ int wl18xx_acx_set_checksum_state(struct wl1271 *wl) | |||
75 | 75 | ||
76 | acx->checksum_state = CHECKSUM_OFFLOAD_ENABLED; | 76 | acx->checksum_state = CHECKSUM_OFFLOAD_ENABLED; |
77 | 77 | ||
78 | ret = wl1271_cmd_configure(wl, ACX_CHECKSUM_CONFIG, acx, sizeof(*acx)); | 78 | ret = wl1271_cmd_configure(wl, ACX_CSUM_CONFIG, acx, sizeof(*acx)); |
79 | if (ret < 0) { | 79 | if (ret < 0) { |
80 | wl1271_warning("failed to set Tx checksum state: %d", ret); | 80 | wl1271_warning("failed to set Tx checksum state: %d", ret); |
81 | goto out; | 81 | goto out; |
@@ -109,3 +109,88 @@ out: | |||
109 | kfree(acx); | 109 | kfree(acx); |
110 | return ret; | 110 | return ret; |
111 | } | 111 | } |
112 | |||
113 | int wl18xx_acx_peer_ht_operation_mode(struct wl1271 *wl, u8 hlid, bool wide) | ||
114 | { | ||
115 | struct wlcore_peer_ht_operation_mode *acx; | ||
116 | int ret; | ||
117 | |||
118 | wl1271_debug(DEBUG_ACX, "acx peer ht operation mode hlid %d bw %d", | ||
119 | hlid, wide); | ||
120 | |||
121 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
122 | if (!acx) { | ||
123 | ret = -ENOMEM; | ||
124 | goto out; | ||
125 | } | ||
126 | |||
127 | acx->hlid = hlid; | ||
128 | acx->bandwidth = wide ? WLCORE_BANDWIDTH_40MHZ : WLCORE_BANDWIDTH_20MHZ; | ||
129 | |||
130 | ret = wl1271_cmd_configure(wl, ACX_PEER_HT_OPERATION_MODE_CFG, acx, | ||
131 | sizeof(*acx)); | ||
132 | |||
133 | if (ret < 0) { | ||
134 | wl1271_warning("acx peer ht operation mode failed: %d", ret); | ||
135 | goto out; | ||
136 | } | ||
137 | |||
138 | out: | ||
139 | kfree(acx); | ||
140 | return ret; | ||
141 | |||
142 | } | ||
143 | |||
144 | /* | ||
145 | * this command is basically the same as wl1271_acx_ht_capabilities, | ||
146 | * with the addition of supported rates. they should be unified in | ||
147 | * the next fw api change | ||
148 | */ | ||
149 | int wl18xx_acx_set_peer_cap(struct wl1271 *wl, | ||
150 | struct ieee80211_sta_ht_cap *ht_cap, | ||
151 | bool allow_ht_operation, | ||
152 | u32 rate_set, u8 hlid) | ||
153 | { | ||
154 | struct wlcore_acx_peer_cap *acx; | ||
155 | int ret = 0; | ||
156 | u32 ht_capabilites = 0; | ||
157 | |||
158 | wl1271_debug(DEBUG_ACX, | ||
159 | "acx set cap ht_supp: %d ht_cap: %d rates: 0x%x", | ||
160 | ht_cap->ht_supported, ht_cap->cap, rate_set); | ||
161 | |||
162 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
163 | if (!acx) { | ||
164 | ret = -ENOMEM; | ||
165 | goto out; | ||
166 | } | ||
167 | |||
168 | if (allow_ht_operation && ht_cap->ht_supported) { | ||
169 | /* no need to translate capabilities - use the spec values */ | ||
170 | ht_capabilites = ht_cap->cap; | ||
171 | |||
172 | /* | ||
173 | * this bit is not employed by the spec but only by FW to | ||
174 | * indicate peer HT support | ||
175 | */ | ||
176 | ht_capabilites |= WL12XX_HT_CAP_HT_OPERATION; | ||
177 | |||
178 | /* get data from A-MPDU parameters field */ | ||
179 | acx->ampdu_max_length = ht_cap->ampdu_factor; | ||
180 | acx->ampdu_min_spacing = ht_cap->ampdu_density; | ||
181 | } | ||
182 | |||
183 | acx->hlid = hlid; | ||
184 | acx->ht_capabilites = cpu_to_le32(ht_capabilites); | ||
185 | acx->supported_rates = cpu_to_le32(rate_set); | ||
186 | |||
187 | ret = wl1271_cmd_configure(wl, ACX_PEER_CAP, acx, sizeof(*acx)); | ||
188 | if (ret < 0) { | ||
189 | wl1271_warning("acx ht capabilities setting failed: %d", ret); | ||
190 | goto out; | ||
191 | } | ||
192 | |||
193 | out: | ||
194 | kfree(acx); | ||
195 | return ret; | ||
196 | } | ||
diff --git a/drivers/net/wireless/ti/wl18xx/acx.h b/drivers/net/wireless/ti/wl18xx/acx.h index e2609a6b7341..0e636def1217 100644 --- a/drivers/net/wireless/ti/wl18xx/acx.h +++ b/drivers/net/wireless/ti/wl18xx/acx.h | |||
@@ -26,7 +26,13 @@ | |||
26 | #include "../wlcore/acx.h" | 26 | #include "../wlcore/acx.h" |
27 | 27 | ||
28 | enum { | 28 | enum { |
29 | ACX_CLEAR_STATISTICS = 0x0047, | 29 | ACX_NS_IPV6_FILTER = 0x0050, |
30 | ACX_PEER_HT_OPERATION_MODE_CFG = 0x0051, | ||
31 | ACX_CSUM_CONFIG = 0x0052, | ||
32 | ACX_SIM_CONFIG = 0x0053, | ||
33 | ACX_CLEAR_STATISTICS = 0x0054, | ||
34 | ACX_AUTO_RX_STREAMING = 0x0055, | ||
35 | ACX_PEER_CAP = 0x0056 | ||
30 | }; | 36 | }; |
31 | 37 | ||
32 | /* numbers of bits the length field takes (add 1 for the actual number) */ | 38 | /* numbers of bits the length field takes (add 1 for the actual number) */ |
@@ -278,10 +284,57 @@ struct wl18xx_acx_clear_statistics { | |||
278 | struct acx_header header; | 284 | struct acx_header header; |
279 | }; | 285 | }; |
280 | 286 | ||
287 | enum wlcore_bandwidth { | ||
288 | WLCORE_BANDWIDTH_20MHZ, | ||
289 | WLCORE_BANDWIDTH_40MHZ, | ||
290 | }; | ||
291 | |||
292 | struct wlcore_peer_ht_operation_mode { | ||
293 | struct acx_header header; | ||
294 | |||
295 | u8 hlid; | ||
296 | u8 bandwidth; /* enum wlcore_bandwidth */ | ||
297 | u8 padding[2]; | ||
298 | }; | ||
299 | |||
300 | /* | ||
301 | * ACX_PEER_CAP | ||
302 | * this struct is very similar to wl1271_acx_ht_capabilities, with the | ||
303 | * addition of supported rates | ||
304 | */ | ||
305 | struct wlcore_acx_peer_cap { | ||
306 | struct acx_header header; | ||
307 | |||
308 | /* bitmask of capability bits supported by the peer */ | ||
309 | __le32 ht_capabilites; | ||
310 | |||
311 | /* rates supported by the remote peer */ | ||
312 | __le32 supported_rates; | ||
313 | |||
314 | /* Indicates to which link these capabilities apply. */ | ||
315 | u8 hlid; | ||
316 | |||
317 | /* | ||
318 | * This the maximum A-MPDU length supported by the AP. The FW may not | ||
319 | * exceed this length when sending A-MPDUs | ||
320 | */ | ||
321 | u8 ampdu_max_length; | ||
322 | |||
323 | /* This is the minimal spacing required when sending A-MPDUs to the AP*/ | ||
324 | u8 ampdu_min_spacing; | ||
325 | |||
326 | u8 padding; | ||
327 | } __packed; | ||
328 | |||
281 | int wl18xx_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap, | 329 | int wl18xx_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap, |
282 | u32 sdio_blk_size, u32 extra_mem_blks, | 330 | u32 sdio_blk_size, u32 extra_mem_blks, |
283 | u32 len_field_size); | 331 | u32 len_field_size); |
284 | int wl18xx_acx_set_checksum_state(struct wl1271 *wl); | 332 | int wl18xx_acx_set_checksum_state(struct wl1271 *wl); |
285 | int wl18xx_acx_clear_statistics(struct wl1271 *wl); | 333 | int wl18xx_acx_clear_statistics(struct wl1271 *wl); |
334 | int wl18xx_acx_peer_ht_operation_mode(struct wl1271 *wl, u8 hlid, bool wide); | ||
335 | int wl18xx_acx_set_peer_cap(struct wl1271 *wl, | ||
336 | struct ieee80211_sta_ht_cap *ht_cap, | ||
337 | bool allow_ht_operation, | ||
338 | u32 rate_set, u8 hlid); | ||
286 | 339 | ||
287 | #endif /* __WL18XX_ACX_H__ */ | 340 | #endif /* __WL18XX_ACX_H__ */ |
diff --git a/drivers/net/wireless/ti/wl18xx/cmd.c b/drivers/net/wireless/ti/wl18xx/cmd.c new file mode 100644 index 000000000000..1d1f6cc7a50a --- /dev/null +++ b/drivers/net/wireless/ti/wl18xx/cmd.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * This file is part of wl18xx | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include "../wlcore/cmd.h" | ||
23 | #include "../wlcore/debug.h" | ||
24 | #include "../wlcore/hw_ops.h" | ||
25 | |||
26 | #include "cmd.h" | ||
27 | |||
28 | int wl18xx_cmd_channel_switch(struct wl1271 *wl, | ||
29 | struct wl12xx_vif *wlvif, | ||
30 | struct ieee80211_channel_switch *ch_switch) | ||
31 | { | ||
32 | struct wl18xx_cmd_channel_switch *cmd; | ||
33 | u32 supported_rates; | ||
34 | int ret; | ||
35 | |||
36 | wl1271_debug(DEBUG_ACX, "cmd channel switch"); | ||
37 | |||
38 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
39 | if (!cmd) { | ||
40 | ret = -ENOMEM; | ||
41 | goto out; | ||
42 | } | ||
43 | |||
44 | cmd->role_id = wlvif->role_id; | ||
45 | cmd->channel = ch_switch->channel->hw_value; | ||
46 | cmd->switch_time = ch_switch->count; | ||
47 | cmd->stop_tx = ch_switch->block_tx; | ||
48 | |||
49 | switch (ch_switch->channel->band) { | ||
50 | case IEEE80211_BAND_2GHZ: | ||
51 | cmd->band = WLCORE_BAND_2_4GHZ; | ||
52 | break; | ||
53 | case IEEE80211_BAND_5GHZ: | ||
54 | cmd->band = WLCORE_BAND_5GHZ; | ||
55 | break; | ||
56 | default: | ||
57 | wl1271_error("invalid channel switch band: %d", | ||
58 | ch_switch->channel->band); | ||
59 | ret = -EINVAL; | ||
60 | goto out_free; | ||
61 | } | ||
62 | |||
63 | supported_rates = CONF_TX_ENABLED_RATES | CONF_TX_MCS_RATES | | ||
64 | wlcore_hw_sta_get_ap_rate_mask(wl, wlvif); | ||
65 | if (wlvif->p2p) | ||
66 | supported_rates &= ~CONF_TX_CCK_RATES; | ||
67 | cmd->local_supported_rates = cpu_to_le32(supported_rates); | ||
68 | cmd->channel_type = wlvif->channel_type; | ||
69 | |||
70 | ret = wl1271_cmd_send(wl, CMD_CHANNEL_SWITCH, cmd, sizeof(*cmd), 0); | ||
71 | if (ret < 0) { | ||
72 | wl1271_error("failed to send channel switch command"); | ||
73 | goto out_free; | ||
74 | } | ||
75 | |||
76 | out_free: | ||
77 | kfree(cmd); | ||
78 | out: | ||
79 | return ret; | ||
80 | } | ||
diff --git a/drivers/net/wireless/ti/wl18xx/cmd.h b/drivers/net/wireless/ti/wl18xx/cmd.h new file mode 100644 index 000000000000..6687d10899ac --- /dev/null +++ b/drivers/net/wireless/ti/wl18xx/cmd.h | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | * This file is part of wl18xx | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef __WL18XX_CMD_H__ | ||
23 | #define __WL18XX_CMD_H__ | ||
24 | |||
25 | #include "../wlcore/wlcore.h" | ||
26 | #include "../wlcore/acx.h" | ||
27 | |||
28 | struct wl18xx_cmd_channel_switch { | ||
29 | struct wl1271_cmd_header header; | ||
30 | |||
31 | u8 role_id; | ||
32 | |||
33 | /* The new serving channel */ | ||
34 | u8 channel; | ||
35 | /* Relative time of the serving channel switch in TBTT units */ | ||
36 | u8 switch_time; | ||
37 | /* Stop the role TX, should expect it after radar detection */ | ||
38 | u8 stop_tx; | ||
39 | |||
40 | __le32 local_supported_rates; | ||
41 | |||
42 | u8 channel_type; | ||
43 | u8 band; | ||
44 | |||
45 | u8 padding[2]; | ||
46 | } __packed; | ||
47 | |||
48 | int wl18xx_cmd_channel_switch(struct wl1271 *wl, | ||
49 | struct wl12xx_vif *wlvif, | ||
50 | struct ieee80211_channel_switch *ch_switch); | ||
51 | |||
52 | #endif | ||
diff --git a/drivers/net/wireless/ti/wl18xx/conf.h b/drivers/net/wireless/ti/wl18xx/conf.h index 4d426cc20274..b5f114857191 100644 --- a/drivers/net/wireless/ti/wl18xx/conf.h +++ b/drivers/net/wireless/ti/wl18xx/conf.h | |||
@@ -23,20 +23,21 @@ | |||
23 | #define __WL18XX_CONF_H__ | 23 | #define __WL18XX_CONF_H__ |
24 | 24 | ||
25 | #define WL18XX_CONF_MAGIC 0x10e100ca | 25 | #define WL18XX_CONF_MAGIC 0x10e100ca |
26 | #define WL18XX_CONF_VERSION (WLCORE_CONF_VERSION | 0x0003) | 26 | #define WL18XX_CONF_VERSION (WLCORE_CONF_VERSION | 0x0005) |
27 | #define WL18XX_CONF_MASK 0x0000ffff | 27 | #define WL18XX_CONF_MASK 0x0000ffff |
28 | #define WL18XX_CONF_SIZE (WLCORE_CONF_SIZE + \ | 28 | #define WL18XX_CONF_SIZE (WLCORE_CONF_SIZE + \ |
29 | sizeof(struct wl18xx_priv_conf)) | 29 | sizeof(struct wl18xx_priv_conf)) |
30 | 30 | ||
31 | #define NUM_OF_CHANNELS_11_ABG 150 | 31 | #define NUM_OF_CHANNELS_11_ABG 150 |
32 | #define NUM_OF_CHANNELS_11_P 7 | 32 | #define NUM_OF_CHANNELS_11_P 7 |
33 | #define WL18XX_NUM_OF_SUB_BANDS 9 | ||
34 | #define SRF_TABLE_LEN 16 | 33 | #define SRF_TABLE_LEN 16 |
35 | #define PIN_MUXING_SIZE 2 | 34 | #define PIN_MUXING_SIZE 2 |
35 | #define WL18XX_TRACE_LOSS_GAPS_TX 10 | ||
36 | #define WL18XX_TRACE_LOSS_GAPS_RX 18 | ||
36 | 37 | ||
37 | struct wl18xx_mac_and_phy_params { | 38 | struct wl18xx_mac_and_phy_params { |
38 | u8 phy_standalone; | 39 | u8 phy_standalone; |
39 | u8 rdl; | 40 | u8 spare0; |
40 | u8 enable_clpc; | 41 | u8 enable_clpc; |
41 | u8 enable_tx_low_pwr_on_siso_rdl; | 42 | u8 enable_tx_low_pwr_on_siso_rdl; |
42 | u8 auto_detect; | 43 | u8 auto_detect; |
@@ -69,18 +70,26 @@ struct wl18xx_mac_and_phy_params { | |||
69 | u8 pwr_limit_reference_11_abg; | 70 | u8 pwr_limit_reference_11_abg; |
70 | u8 per_chan_pwr_limit_arr_11p[NUM_OF_CHANNELS_11_P]; | 71 | u8 per_chan_pwr_limit_arr_11p[NUM_OF_CHANNELS_11_P]; |
71 | u8 pwr_limit_reference_11p; | 72 | u8 pwr_limit_reference_11p; |
72 | u8 per_sub_band_tx_trace_loss[WL18XX_NUM_OF_SUB_BANDS]; | 73 | u8 spare1[9]; |
73 | u8 per_sub_band_rx_trace_loss[WL18XX_NUM_OF_SUB_BANDS]; | 74 | u8 spare2[9]; |
74 | u8 primary_clock_setting_time; | 75 | u8 primary_clock_setting_time; |
75 | u8 clock_valid_on_wake_up; | 76 | u8 clock_valid_on_wake_up; |
76 | u8 secondary_clock_setting_time; | 77 | u8 secondary_clock_setting_time; |
77 | u8 board_type; | 78 | u8 board_type; |
78 | /* enable point saturation */ | 79 | /* enable point saturation */ |
79 | u8 psat; | 80 | u8 psat; |
80 | /* low/medium/high Tx power in dBm */ | 81 | /* low/medium/high Tx power in dBm for STA-HP BG */ |
81 | s8 low_power_val; | 82 | s8 low_power_val; |
82 | s8 med_power_val; | 83 | s8 med_power_val; |
83 | s8 high_power_val; | 84 | s8 high_power_val; |
85 | s8 per_sub_band_tx_trace_loss[WL18XX_TRACE_LOSS_GAPS_TX]; | ||
86 | s8 per_sub_band_rx_trace_loss[WL18XX_TRACE_LOSS_GAPS_RX]; | ||
87 | u8 tx_rf_margin; | ||
88 | /* low/medium/high Tx power in dBm for other role */ | ||
89 | s8 low_power_val_2nd; | ||
90 | s8 med_power_val_2nd; | ||
91 | s8 high_power_val_2nd; | ||
92 | |||
84 | u8 padding[1]; | 93 | u8 padding[1]; |
85 | } __packed; | 94 | } __packed; |
86 | 95 | ||
diff --git a/drivers/net/wireless/ti/wl18xx/event.c b/drivers/net/wireless/ti/wl18xx/event.c new file mode 100644 index 000000000000..c9199d7804c6 --- /dev/null +++ b/drivers/net/wireless/ti/wl18xx/event.c | |||
@@ -0,0 +1,111 @@ | |||
1 | /* | ||
2 | * This file is part of wl12xx | ||
3 | * | ||
4 | * Copyright (C) 2012 Texas Instruments. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include "event.h" | ||
23 | #include "scan.h" | ||
24 | #include "../wlcore/cmd.h" | ||
25 | #include "../wlcore/debug.h" | ||
26 | |||
27 | int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event, | ||
28 | bool *timeout) | ||
29 | { | ||
30 | u32 local_event; | ||
31 | |||
32 | switch (event) { | ||
33 | case WLCORE_EVENT_PEER_REMOVE_COMPLETE: | ||
34 | local_event = PEER_REMOVE_COMPLETE_EVENT_ID; | ||
35 | break; | ||
36 | |||
37 | case WLCORE_EVENT_DFS_CONFIG_COMPLETE: | ||
38 | local_event = DFS_CHANNELS_CONFIG_COMPLETE_EVENT; | ||
39 | break; | ||
40 | |||
41 | default: | ||
42 | /* event not implemented */ | ||
43 | return 0; | ||
44 | } | ||
45 | return wlcore_cmd_wait_for_event_or_timeout(wl, local_event, timeout); | ||
46 | } | ||
47 | |||
48 | int wl18xx_process_mailbox_events(struct wl1271 *wl) | ||
49 | { | ||
50 | struct wl18xx_event_mailbox *mbox = wl->mbox; | ||
51 | u32 vector; | ||
52 | |||
53 | vector = le32_to_cpu(mbox->events_vector); | ||
54 | wl1271_debug(DEBUG_EVENT, "MBOX vector: 0x%x", vector); | ||
55 | |||
56 | if (vector & SCAN_COMPLETE_EVENT_ID) { | ||
57 | wl1271_debug(DEBUG_EVENT, "scan results: %d", | ||
58 | mbox->number_of_scan_results); | ||
59 | |||
60 | if (wl->scan_wlvif) | ||
61 | wl18xx_scan_completed(wl, wl->scan_wlvif); | ||
62 | } | ||
63 | |||
64 | if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) { | ||
65 | wl1271_debug(DEBUG_EVENT, | ||
66 | "PERIODIC_SCAN_REPORT_EVENT (results %d)", | ||
67 | mbox->number_of_sched_scan_results); | ||
68 | |||
69 | wlcore_scan_sched_scan_results(wl); | ||
70 | } | ||
71 | |||
72 | if (vector & PERIODIC_SCAN_COMPLETE_EVENT_ID) | ||
73 | wlcore_event_sched_scan_completed(wl, 1); | ||
74 | |||
75 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) | ||
76 | wlcore_event_rssi_trigger(wl, mbox->rssi_snr_trigger_metric); | ||
77 | |||
78 | if (vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID) | ||
79 | wlcore_event_ba_rx_constraint(wl, | ||
80 | le16_to_cpu(mbox->rx_ba_role_id_bitmap), | ||
81 | le16_to_cpu(mbox->rx_ba_allowed_bitmap)); | ||
82 | |||
83 | if (vector & BSS_LOSS_EVENT_ID) | ||
84 | wlcore_event_beacon_loss(wl, | ||
85 | le16_to_cpu(mbox->bss_loss_bitmap)); | ||
86 | |||
87 | if (vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID) | ||
88 | wlcore_event_channel_switch(wl, | ||
89 | le16_to_cpu(mbox->channel_switch_role_id_bitmap), | ||
90 | true); | ||
91 | |||
92 | if (vector & DUMMY_PACKET_EVENT_ID) | ||
93 | wlcore_event_dummy_packet(wl); | ||
94 | |||
95 | /* | ||
96 | * "TX retries exceeded" has a different meaning according to mode. | ||
97 | * In AP mode the offending station is disconnected. | ||
98 | */ | ||
99 | if (vector & MAX_TX_FAILURE_EVENT_ID) | ||
100 | wlcore_event_max_tx_failure(wl, | ||
101 | le32_to_cpu(mbox->tx_retry_exceeded_bitmap)); | ||
102 | |||
103 | if (vector & INACTIVE_STA_EVENT_ID) | ||
104 | wlcore_event_inactive_sta(wl, | ||
105 | le32_to_cpu(mbox->inactive_sta_bitmap)); | ||
106 | |||
107 | if (vector & REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID) | ||
108 | wlcore_event_roc_complete(wl); | ||
109 | |||
110 | return 0; | ||
111 | } | ||
diff --git a/drivers/net/wireless/ti/wl18xx/event.h b/drivers/net/wireless/ti/wl18xx/event.h new file mode 100644 index 000000000000..398f3d2c0a6c --- /dev/null +++ b/drivers/net/wireless/ti/wl18xx/event.h | |||
@@ -0,0 +1,77 @@ | |||
1 | /* | ||
2 | * This file is part of wl18xx | ||
3 | * | ||
4 | * Copyright (C) 2012 Texas Instruments. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef __WL18XX_EVENT_H__ | ||
23 | #define __WL18XX_EVENT_H__ | ||
24 | |||
25 | #include "../wlcore/wlcore.h" | ||
26 | |||
27 | enum { | ||
28 | SCAN_COMPLETE_EVENT_ID = BIT(8), | ||
29 | RADAR_DETECTED_EVENT_ID = BIT(9), | ||
30 | CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(10), | ||
31 | BSS_LOSS_EVENT_ID = BIT(11), | ||
32 | MAX_TX_FAILURE_EVENT_ID = BIT(12), | ||
33 | DUMMY_PACKET_EVENT_ID = BIT(13), | ||
34 | INACTIVE_STA_EVENT_ID = BIT(14), | ||
35 | PEER_REMOVE_COMPLETE_EVENT_ID = BIT(15), | ||
36 | PERIODIC_SCAN_COMPLETE_EVENT_ID = BIT(16), | ||
37 | BA_SESSION_RX_CONSTRAINT_EVENT_ID = BIT(17), | ||
38 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID = BIT(18), | ||
39 | DFS_CHANNELS_CONFIG_COMPLETE_EVENT = BIT(19), | ||
40 | PERIODIC_SCAN_REPORT_EVENT_ID = BIT(20), | ||
41 | }; | ||
42 | |||
43 | struct wl18xx_event_mailbox { | ||
44 | __le32 events_vector; | ||
45 | |||
46 | u8 number_of_scan_results; | ||
47 | u8 number_of_sched_scan_results; | ||
48 | |||
49 | __le16 channel_switch_role_id_bitmap; | ||
50 | |||
51 | s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS]; | ||
52 | |||
53 | /* bitmap of removed links */ | ||
54 | __le32 hlid_removed_bitmap; | ||
55 | |||
56 | /* rx ba constraint */ | ||
57 | __le16 rx_ba_role_id_bitmap; /* 0xfff means any role. */ | ||
58 | __le16 rx_ba_allowed_bitmap; | ||
59 | |||
60 | /* bitmap of roc completed (by role id) */ | ||
61 | __le16 roc_completed_bitmap; | ||
62 | |||
63 | /* bitmap of stations (by role id) with bss loss */ | ||
64 | __le16 bss_loss_bitmap; | ||
65 | |||
66 | /* bitmap of stations (by HLID) which exceeded max tx retries */ | ||
67 | __le32 tx_retry_exceeded_bitmap; | ||
68 | |||
69 | /* bitmap of inactive stations (by HLID) */ | ||
70 | __le32 inactive_sta_bitmap; | ||
71 | } __packed; | ||
72 | |||
73 | int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event, | ||
74 | bool *timeout); | ||
75 | int wl18xx_process_mailbox_events(struct wl1271 *wl); | ||
76 | |||
77 | #endif | ||
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index 8d8c1f8c63b7..0be1cfc17a86 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c | |||
@@ -34,10 +34,13 @@ | |||
34 | 34 | ||
35 | #include "reg.h" | 35 | #include "reg.h" |
36 | #include "conf.h" | 36 | #include "conf.h" |
37 | #include "cmd.h" | ||
37 | #include "acx.h" | 38 | #include "acx.h" |
38 | #include "tx.h" | 39 | #include "tx.h" |
39 | #include "wl18xx.h" | 40 | #include "wl18xx.h" |
40 | #include "io.h" | 41 | #include "io.h" |
42 | #include "scan.h" | ||
43 | #include "event.h" | ||
41 | #include "debugfs.h" | 44 | #include "debugfs.h" |
42 | 45 | ||
43 | #define WL18XX_RX_CHECKSUM_MASK 0x40 | 46 | #define WL18XX_RX_CHECKSUM_MASK 0x40 |
@@ -334,6 +337,8 @@ static struct wlcore_conf wl18xx_conf = { | |||
334 | .tmpl_short_retry_limit = 10, | 337 | .tmpl_short_retry_limit = 10, |
335 | .tmpl_long_retry_limit = 10, | 338 | .tmpl_long_retry_limit = 10, |
336 | .tx_watchdog_timeout = 5000, | 339 | .tx_watchdog_timeout = 5000, |
340 | .slow_link_thold = 3, | ||
341 | .fast_link_thold = 30, | ||
337 | }, | 342 | }, |
338 | .conn = { | 343 | .conn = { |
339 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | 344 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, |
@@ -391,8 +396,10 @@ static struct wlcore_conf wl18xx_conf = { | |||
391 | .scan = { | 396 | .scan = { |
392 | .min_dwell_time_active = 7500, | 397 | .min_dwell_time_active = 7500, |
393 | .max_dwell_time_active = 30000, | 398 | .max_dwell_time_active = 30000, |
394 | .min_dwell_time_passive = 100000, | 399 | .min_dwell_time_active_long = 25000, |
395 | .max_dwell_time_passive = 100000, | 400 | .max_dwell_time_active_long = 50000, |
401 | .dwell_time_passive = 100000, | ||
402 | .dwell_time_dfs = 150000, | ||
396 | .num_probe_reqs = 2, | 403 | .num_probe_reqs = 2, |
397 | .split_scan_timeout = 50000, | 404 | .split_scan_timeout = 50000, |
398 | }, | 405 | }, |
@@ -489,6 +496,10 @@ static struct wlcore_conf wl18xx_conf = { | |||
489 | .increase_time = 1, | 496 | .increase_time = 1, |
490 | .window_size = 16, | 497 | .window_size = 16, |
491 | }, | 498 | }, |
499 | .recovery = { | ||
500 | .bug_on_recovery = 0, | ||
501 | .no_recovery = 0, | ||
502 | }, | ||
492 | }; | 503 | }; |
493 | 504 | ||
494 | static struct wl18xx_priv_conf wl18xx_default_priv_conf = { | 505 | static struct wl18xx_priv_conf wl18xx_default_priv_conf = { |
@@ -501,7 +512,6 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = { | |||
501 | .clock_valid_on_wake_up = 0x00, | 512 | .clock_valid_on_wake_up = 0x00, |
502 | .secondary_clock_setting_time = 0x05, | 513 | .secondary_clock_setting_time = 0x05, |
503 | .board_type = BOARD_TYPE_HDK_18XX, | 514 | .board_type = BOARD_TYPE_HDK_18XX, |
504 | .rdl = 0x01, | ||
505 | .auto_detect = 0x00, | 515 | .auto_detect = 0x00, |
506 | .dedicated_fem = FEM_NONE, | 516 | .dedicated_fem = FEM_NONE, |
507 | .low_band_component = COMPONENT_3_WAY_SWITCH, | 517 | .low_band_component = COMPONENT_3_WAY_SWITCH, |
@@ -517,14 +527,39 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = { | |||
517 | .enable_clpc = 0x00, | 527 | .enable_clpc = 0x00, |
518 | .enable_tx_low_pwr_on_siso_rdl = 0x00, | 528 | .enable_tx_low_pwr_on_siso_rdl = 0x00, |
519 | .rx_profile = 0x00, | 529 | .rx_profile = 0x00, |
520 | .pwr_limit_reference_11_abg = 0xc8, | 530 | .pwr_limit_reference_11_abg = 0x64, |
531 | .per_chan_pwr_limit_arr_11abg = { | ||
532 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
533 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
534 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
535 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
536 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
537 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
538 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
539 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
540 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
541 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
542 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
543 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
544 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
545 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
546 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
547 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
548 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, | ||
549 | .pwr_limit_reference_11p = 0x64, | ||
550 | .per_chan_pwr_limit_arr_11p = { 0xff, 0xff, 0xff, 0xff, | ||
551 | 0xff, 0xff, 0xff }, | ||
521 | .psat = 0, | 552 | .psat = 0, |
522 | .low_power_val = 0x00, | 553 | .low_power_val = 0x08, |
523 | .med_power_val = 0x0a, | 554 | .med_power_val = 0x12, |
524 | .high_power_val = 0x1e, | 555 | .high_power_val = 0x18, |
556 | .low_power_val_2nd = 0x05, | ||
557 | .med_power_val_2nd = 0x0a, | ||
558 | .high_power_val_2nd = 0x14, | ||
525 | .external_pa_dc2dc = 0, | 559 | .external_pa_dc2dc = 0, |
526 | .number_of_assembled_ant2_4 = 1, | 560 | .number_of_assembled_ant2_4 = 2, |
527 | .number_of_assembled_ant5 = 1, | 561 | .number_of_assembled_ant5 = 1, |
562 | .tx_rf_margin = 1, | ||
528 | }, | 563 | }, |
529 | }; | 564 | }; |
530 | 565 | ||
@@ -595,7 +630,7 @@ static const struct wl18xx_clk_cfg wl18xx_clk_table[NUM_CLOCK_CONFIGS] = { | |||
595 | }; | 630 | }; |
596 | 631 | ||
597 | /* TODO: maybe move to a new header file? */ | 632 | /* TODO: maybe move to a new header file? */ |
598 | #define WL18XX_FW_NAME "ti-connectivity/wl18xx-fw.bin" | 633 | #define WL18XX_FW_NAME "ti-connectivity/wl18xx-fw-2.bin" |
599 | 634 | ||
600 | static int wl18xx_identify_chip(struct wl1271 *wl) | 635 | static int wl18xx_identify_chip(struct wl1271 *wl) |
601 | { | 636 | { |
@@ -608,15 +643,18 @@ static int wl18xx_identify_chip(struct wl1271 *wl) | |||
608 | wl->sr_fw_name = WL18XX_FW_NAME; | 643 | wl->sr_fw_name = WL18XX_FW_NAME; |
609 | /* wl18xx uses the same firmware for PLT */ | 644 | /* wl18xx uses the same firmware for PLT */ |
610 | wl->plt_fw_name = WL18XX_FW_NAME; | 645 | wl->plt_fw_name = WL18XX_FW_NAME; |
611 | wl->quirks |= WLCORE_QUIRK_NO_ELP | | 646 | wl->quirks |= WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN | |
612 | WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN | | ||
613 | WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN | | 647 | WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN | |
614 | WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN | | 648 | WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN | |
615 | WLCORE_QUIRK_TX_PAD_LAST_FRAME; | 649 | WLCORE_QUIRK_TX_PAD_LAST_FRAME | |
616 | 650 | WLCORE_QUIRK_REGDOMAIN_CONF | | |
617 | wlcore_set_min_fw_ver(wl, WL18XX_CHIP_VER, WL18XX_IFTYPE_VER, | 651 | WLCORE_QUIRK_DUAL_PROBE_TMPL; |
618 | WL18XX_MAJOR_VER, WL18XX_SUBTYPE_VER, | 652 | |
619 | WL18XX_MINOR_VER); | 653 | wlcore_set_min_fw_ver(wl, WL18XX_CHIP_VER, |
654 | WL18XX_IFTYPE_VER, WL18XX_MAJOR_VER, | ||
655 | WL18XX_SUBTYPE_VER, WL18XX_MINOR_VER, | ||
656 | /* there's no separate multi-role FW */ | ||
657 | 0, 0, 0, 0); | ||
620 | break; | 658 | break; |
621 | case CHIP_ID_185x_PG10: | 659 | case CHIP_ID_185x_PG10: |
622 | wl1271_warning("chip id 0x%x (185x PG10) is deprecated", | 660 | wl1271_warning("chip id 0x%x (185x PG10) is deprecated", |
@@ -630,6 +668,11 @@ static int wl18xx_identify_chip(struct wl1271 *wl) | |||
630 | goto out; | 668 | goto out; |
631 | } | 669 | } |
632 | 670 | ||
671 | wl->scan_templ_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4; | ||
672 | wl->scan_templ_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5; | ||
673 | wl->sched_scan_templ_id_2_4 = CMD_TEMPL_PROBE_REQ_2_4_PERIODIC; | ||
674 | wl->sched_scan_templ_id_5 = CMD_TEMPL_PROBE_REQ_5_PERIODIC; | ||
675 | wl->max_channels_5 = WL18XX_MAX_CHANNELS_5GHZ; | ||
633 | out: | 676 | out: |
634 | return ret; | 677 | return ret; |
635 | } | 678 | } |
@@ -843,6 +886,20 @@ static int wl18xx_boot(struct wl1271 *wl) | |||
843 | if (ret < 0) | 886 | if (ret < 0) |
844 | goto out; | 887 | goto out; |
845 | 888 | ||
889 | wl->event_mask = BSS_LOSS_EVENT_ID | | ||
890 | SCAN_COMPLETE_EVENT_ID | | ||
891 | RSSI_SNR_TRIGGER_0_EVENT_ID | | ||
892 | PERIODIC_SCAN_COMPLETE_EVENT_ID | | ||
893 | PERIODIC_SCAN_REPORT_EVENT_ID | | ||
894 | DUMMY_PACKET_EVENT_ID | | ||
895 | PEER_REMOVE_COMPLETE_EVENT_ID | | ||
896 | BA_SESSION_RX_CONSTRAINT_EVENT_ID | | ||
897 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | | ||
898 | INACTIVE_STA_EVENT_ID | | ||
899 | MAX_TX_FAILURE_EVENT_ID | | ||
900 | CHANNEL_SWITCH_COMPLETE_EVENT_ID | | ||
901 | DFS_CHANNELS_CONFIG_COMPLETE_EVENT; | ||
902 | |||
846 | ret = wlcore_boot_run_firmware(wl); | 903 | ret = wlcore_boot_run_firmware(wl); |
847 | if (ret < 0) | 904 | if (ret < 0) |
848 | goto out; | 905 | goto out; |
@@ -964,7 +1021,7 @@ static int wl18xx_hw_init(struct wl1271 *wl) | |||
964 | 1021 | ||
965 | /* (re)init private structures. Relevant on recovery as well. */ | 1022 | /* (re)init private structures. Relevant on recovery as well. */ |
966 | priv->last_fw_rls_idx = 0; | 1023 | priv->last_fw_rls_idx = 0; |
967 | priv->extra_spare_vif_count = 0; | 1024 | priv->extra_spare_key_count = 0; |
968 | 1025 | ||
969 | /* set the default amount of spare blocks in the bitmap */ | 1026 | /* set the default amount of spare blocks in the bitmap */ |
970 | ret = wl18xx_set_host_cfg_bitmap(wl, WL18XX_TX_HW_BLOCK_SPARE); | 1027 | ret = wl18xx_set_host_cfg_bitmap(wl, WL18XX_TX_HW_BLOCK_SPARE); |
@@ -1022,7 +1079,12 @@ static bool wl18xx_is_mimo_supported(struct wl1271 *wl) | |||
1022 | { | 1079 | { |
1023 | struct wl18xx_priv *priv = wl->priv; | 1080 | struct wl18xx_priv *priv = wl->priv; |
1024 | 1081 | ||
1025 | return priv->conf.phy.number_of_assembled_ant2_4 >= 2; | 1082 | /* only support MIMO with multiple antennas, and when SISO |
1083 | * is not forced through config | ||
1084 | */ | ||
1085 | return (priv->conf.phy.number_of_assembled_ant2_4 >= 2) && | ||
1086 | (priv->conf.ht.mode != HT_MODE_WIDE) && | ||
1087 | (priv->conf.ht.mode != HT_MODE_SISO20); | ||
1026 | } | 1088 | } |
1027 | 1089 | ||
1028 | /* | 1090 | /* |
@@ -1223,8 +1285,8 @@ static int wl18xx_get_spare_blocks(struct wl1271 *wl, bool is_gem) | |||
1223 | { | 1285 | { |
1224 | struct wl18xx_priv *priv = wl->priv; | 1286 | struct wl18xx_priv *priv = wl->priv; |
1225 | 1287 | ||
1226 | /* If we have VIFs requiring extra spare, indulge them */ | 1288 | /* If we have keys requiring extra spare, indulge them */ |
1227 | if (priv->extra_spare_vif_count) | 1289 | if (priv->extra_spare_key_count) |
1228 | return WL18XX_TX_HW_EXTRA_BLOCK_SPARE; | 1290 | return WL18XX_TX_HW_EXTRA_BLOCK_SPARE; |
1229 | 1291 | ||
1230 | return WL18XX_TX_HW_BLOCK_SPARE; | 1292 | return WL18XX_TX_HW_BLOCK_SPARE; |
@@ -1236,42 +1298,48 @@ static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd, | |||
1236 | struct ieee80211_key_conf *key_conf) | 1298 | struct ieee80211_key_conf *key_conf) |
1237 | { | 1299 | { |
1238 | struct wl18xx_priv *priv = wl->priv; | 1300 | struct wl18xx_priv *priv = wl->priv; |
1239 | bool change_spare = false; | 1301 | bool change_spare = false, special_enc; |
1240 | int ret; | 1302 | int ret; |
1241 | 1303 | ||
1304 | wl1271_debug(DEBUG_CRYPT, "extra spare keys before: %d", | ||
1305 | priv->extra_spare_key_count); | ||
1306 | |||
1307 | special_enc = key_conf->cipher == WL1271_CIPHER_SUITE_GEM || | ||
1308 | key_conf->cipher == WLAN_CIPHER_SUITE_TKIP; | ||
1309 | |||
1310 | ret = wlcore_set_key(wl, cmd, vif, sta, key_conf); | ||
1311 | if (ret < 0) | ||
1312 | goto out; | ||
1313 | |||
1242 | /* | 1314 | /* |
1243 | * when adding the first or removing the last GEM/TKIP interface, | 1315 | * when adding the first or removing the last GEM/TKIP key, |
1244 | * we have to adjust the number of spare blocks. | 1316 | * we have to adjust the number of spare blocks. |
1245 | */ | 1317 | */ |
1246 | change_spare = (key_conf->cipher == WL1271_CIPHER_SUITE_GEM || | 1318 | if (special_enc) { |
1247 | key_conf->cipher == WLAN_CIPHER_SUITE_TKIP) && | 1319 | if (cmd == SET_KEY) { |
1248 | ((priv->extra_spare_vif_count == 0 && cmd == SET_KEY) || | 1320 | /* first key */ |
1249 | (priv->extra_spare_vif_count == 1 && cmd == DISABLE_KEY)); | 1321 | change_spare = (priv->extra_spare_key_count == 0); |
1322 | priv->extra_spare_key_count++; | ||
1323 | } else if (cmd == DISABLE_KEY) { | ||
1324 | /* last key */ | ||
1325 | change_spare = (priv->extra_spare_key_count == 1); | ||
1326 | priv->extra_spare_key_count--; | ||
1327 | } | ||
1328 | } | ||
1250 | 1329 | ||
1251 | /* no need to change spare - just regular set_key */ | 1330 | wl1271_debug(DEBUG_CRYPT, "extra spare keys after: %d", |
1252 | if (!change_spare) | 1331 | priv->extra_spare_key_count); |
1253 | return wlcore_set_key(wl, cmd, vif, sta, key_conf); | ||
1254 | 1332 | ||
1255 | ret = wlcore_set_key(wl, cmd, vif, sta, key_conf); | 1333 | if (!change_spare) |
1256 | if (ret < 0) | ||
1257 | goto out; | 1334 | goto out; |
1258 | 1335 | ||
1259 | /* key is now set, change the spare blocks */ | 1336 | /* key is now set, change the spare blocks */ |
1260 | if (cmd == SET_KEY) { | 1337 | if (priv->extra_spare_key_count) |
1261 | ret = wl18xx_set_host_cfg_bitmap(wl, | 1338 | ret = wl18xx_set_host_cfg_bitmap(wl, |
1262 | WL18XX_TX_HW_EXTRA_BLOCK_SPARE); | 1339 | WL18XX_TX_HW_EXTRA_BLOCK_SPARE); |
1263 | if (ret < 0) | 1340 | else |
1264 | goto out; | ||
1265 | |||
1266 | priv->extra_spare_vif_count++; | ||
1267 | } else { | ||
1268 | ret = wl18xx_set_host_cfg_bitmap(wl, | 1341 | ret = wl18xx_set_host_cfg_bitmap(wl, |
1269 | WL18XX_TX_HW_BLOCK_SPARE); | 1342 | WL18XX_TX_HW_BLOCK_SPARE); |
1270 | if (ret < 0) | ||
1271 | goto out; | ||
1272 | |||
1273 | priv->extra_spare_vif_count--; | ||
1274 | } | ||
1275 | 1343 | ||
1276 | out: | 1344 | out: |
1277 | return ret; | 1345 | return ret; |
@@ -1296,6 +1364,92 @@ static u32 wl18xx_pre_pkt_send(struct wl1271 *wl, | |||
1296 | return buf_offset; | 1364 | return buf_offset; |
1297 | } | 1365 | } |
1298 | 1366 | ||
1367 | static void wl18xx_sta_rc_update(struct wl1271 *wl, | ||
1368 | struct wl12xx_vif *wlvif, | ||
1369 | struct ieee80211_sta *sta, | ||
1370 | u32 changed) | ||
1371 | { | ||
1372 | bool wide = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
1373 | |||
1374 | wl1271_debug(DEBUG_MAC80211, "mac80211 sta_rc_update wide %d", wide); | ||
1375 | |||
1376 | if (!(changed & IEEE80211_RC_BW_CHANGED)) | ||
1377 | return; | ||
1378 | |||
1379 | mutex_lock(&wl->mutex); | ||
1380 | |||
1381 | /* sanity */ | ||
1382 | if (WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS)) | ||
1383 | goto out; | ||
1384 | |||
1385 | /* ignore the change before association */ | ||
1386 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | ||
1387 | goto out; | ||
1388 | |||
1389 | /* | ||
1390 | * If we started out as wide, we can change the operation mode. If we | ||
1391 | * thought this was a 20mhz AP, we have to reconnect | ||
1392 | */ | ||
1393 | if (wlvif->sta.role_chan_type == NL80211_CHAN_HT40MINUS || | ||
1394 | wlvif->sta.role_chan_type == NL80211_CHAN_HT40PLUS) | ||
1395 | wl18xx_acx_peer_ht_operation_mode(wl, wlvif->sta.hlid, wide); | ||
1396 | else | ||
1397 | ieee80211_connection_loss(wl12xx_wlvif_to_vif(wlvif)); | ||
1398 | |||
1399 | out: | ||
1400 | mutex_unlock(&wl->mutex); | ||
1401 | } | ||
1402 | |||
1403 | static int wl18xx_set_peer_cap(struct wl1271 *wl, | ||
1404 | struct ieee80211_sta_ht_cap *ht_cap, | ||
1405 | bool allow_ht_operation, | ||
1406 | u32 rate_set, u8 hlid) | ||
1407 | { | ||
1408 | return wl18xx_acx_set_peer_cap(wl, ht_cap, allow_ht_operation, | ||
1409 | rate_set, hlid); | ||
1410 | } | ||
1411 | |||
1412 | static bool wl18xx_lnk_high_prio(struct wl1271 *wl, u8 hlid, | ||
1413 | struct wl1271_link *lnk) | ||
1414 | { | ||
1415 | u8 thold; | ||
1416 | struct wl18xx_fw_status_priv *status_priv = | ||
1417 | (struct wl18xx_fw_status_priv *)wl->fw_status_2->priv; | ||
1418 | u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap); | ||
1419 | |||
1420 | /* suspended links are never high priority */ | ||
1421 | if (test_bit(hlid, (unsigned long *)&suspend_bitmap)) | ||
1422 | return false; | ||
1423 | |||
1424 | /* the priority thresholds are taken from FW */ | ||
1425 | if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map) && | ||
1426 | !test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map)) | ||
1427 | thold = status_priv->tx_fast_link_prio_threshold; | ||
1428 | else | ||
1429 | thold = status_priv->tx_slow_link_prio_threshold; | ||
1430 | |||
1431 | return lnk->allocated_pkts < thold; | ||
1432 | } | ||
1433 | |||
1434 | static bool wl18xx_lnk_low_prio(struct wl1271 *wl, u8 hlid, | ||
1435 | struct wl1271_link *lnk) | ||
1436 | { | ||
1437 | u8 thold; | ||
1438 | struct wl18xx_fw_status_priv *status_priv = | ||
1439 | (struct wl18xx_fw_status_priv *)wl->fw_status_2->priv; | ||
1440 | u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap); | ||
1441 | |||
1442 | if (test_bit(hlid, (unsigned long *)&suspend_bitmap)) | ||
1443 | thold = status_priv->tx_suspend_threshold; | ||
1444 | else if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map) && | ||
1445 | !test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map)) | ||
1446 | thold = status_priv->tx_fast_stop_threshold; | ||
1447 | else | ||
1448 | thold = status_priv->tx_slow_stop_threshold; | ||
1449 | |||
1450 | return lnk->allocated_pkts < thold; | ||
1451 | } | ||
1452 | |||
1299 | static int wl18xx_setup(struct wl1271 *wl); | 1453 | static int wl18xx_setup(struct wl1271 *wl); |
1300 | 1454 | ||
1301 | static struct wlcore_ops wl18xx_ops = { | 1455 | static struct wlcore_ops wl18xx_ops = { |
@@ -1305,6 +1459,8 @@ static struct wlcore_ops wl18xx_ops = { | |||
1305 | .plt_init = wl18xx_plt_init, | 1459 | .plt_init = wl18xx_plt_init, |
1306 | .trigger_cmd = wl18xx_trigger_cmd, | 1460 | .trigger_cmd = wl18xx_trigger_cmd, |
1307 | .ack_event = wl18xx_ack_event, | 1461 | .ack_event = wl18xx_ack_event, |
1462 | .wait_for_event = wl18xx_wait_for_event, | ||
1463 | .process_mailbox_events = wl18xx_process_mailbox_events, | ||
1308 | .calc_tx_blocks = wl18xx_calc_tx_blocks, | 1464 | .calc_tx_blocks = wl18xx_calc_tx_blocks, |
1309 | .set_tx_desc_blocks = wl18xx_set_tx_desc_blocks, | 1465 | .set_tx_desc_blocks = wl18xx_set_tx_desc_blocks, |
1310 | .set_tx_desc_data_len = wl18xx_set_tx_desc_data_len, | 1466 | .set_tx_desc_data_len = wl18xx_set_tx_desc_data_len, |
@@ -1320,16 +1476,26 @@ static struct wlcore_ops wl18xx_ops = { | |||
1320 | .ap_get_mimo_wide_rate_mask = wl18xx_ap_get_mimo_wide_rate_mask, | 1476 | .ap_get_mimo_wide_rate_mask = wl18xx_ap_get_mimo_wide_rate_mask, |
1321 | .get_mac = wl18xx_get_mac, | 1477 | .get_mac = wl18xx_get_mac, |
1322 | .debugfs_init = wl18xx_debugfs_add_files, | 1478 | .debugfs_init = wl18xx_debugfs_add_files, |
1479 | .scan_start = wl18xx_scan_start, | ||
1480 | .scan_stop = wl18xx_scan_stop, | ||
1481 | .sched_scan_start = wl18xx_sched_scan_start, | ||
1482 | .sched_scan_stop = wl18xx_scan_sched_scan_stop, | ||
1323 | .handle_static_data = wl18xx_handle_static_data, | 1483 | .handle_static_data = wl18xx_handle_static_data, |
1324 | .get_spare_blocks = wl18xx_get_spare_blocks, | 1484 | .get_spare_blocks = wl18xx_get_spare_blocks, |
1325 | .set_key = wl18xx_set_key, | 1485 | .set_key = wl18xx_set_key, |
1486 | .channel_switch = wl18xx_cmd_channel_switch, | ||
1326 | .pre_pkt_send = wl18xx_pre_pkt_send, | 1487 | .pre_pkt_send = wl18xx_pre_pkt_send, |
1488 | .sta_rc_update = wl18xx_sta_rc_update, | ||
1489 | .set_peer_cap = wl18xx_set_peer_cap, | ||
1490 | .lnk_high_prio = wl18xx_lnk_high_prio, | ||
1491 | .lnk_low_prio = wl18xx_lnk_low_prio, | ||
1327 | }; | 1492 | }; |
1328 | 1493 | ||
1329 | /* HT cap appropriate for wide channels in 2Ghz */ | 1494 | /* HT cap appropriate for wide channels in 2Ghz */ |
1330 | static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_2ghz = { | 1495 | static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_2ghz = { |
1331 | .cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | | 1496 | .cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | |
1332 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_DSSSCCK40, | 1497 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_DSSSCCK40 | |
1498 | IEEE80211_HT_CAP_GRN_FLD, | ||
1333 | .ht_supported = true, | 1499 | .ht_supported = true, |
1334 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, | 1500 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, |
1335 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | 1501 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, |
@@ -1343,7 +1509,8 @@ static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_2ghz = { | |||
1343 | /* HT cap appropriate for wide channels in 5Ghz */ | 1509 | /* HT cap appropriate for wide channels in 5Ghz */ |
1344 | static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_5ghz = { | 1510 | static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_5ghz = { |
1345 | .cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | | 1511 | .cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | |
1346 | IEEE80211_HT_CAP_SUP_WIDTH_20_40, | 1512 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | |
1513 | IEEE80211_HT_CAP_GRN_FLD, | ||
1347 | .ht_supported = true, | 1514 | .ht_supported = true, |
1348 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, | 1515 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, |
1349 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | 1516 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, |
@@ -1356,7 +1523,8 @@ static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_5ghz = { | |||
1356 | 1523 | ||
1357 | /* HT cap appropriate for SISO 20 */ | 1524 | /* HT cap appropriate for SISO 20 */ |
1358 | static struct ieee80211_sta_ht_cap wl18xx_siso20_ht_cap = { | 1525 | static struct ieee80211_sta_ht_cap wl18xx_siso20_ht_cap = { |
1359 | .cap = IEEE80211_HT_CAP_SGI_20, | 1526 | .cap = IEEE80211_HT_CAP_SGI_20 | |
1527 | IEEE80211_HT_CAP_GRN_FLD, | ||
1360 | .ht_supported = true, | 1528 | .ht_supported = true, |
1361 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, | 1529 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, |
1362 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | 1530 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, |
@@ -1369,7 +1537,8 @@ static struct ieee80211_sta_ht_cap wl18xx_siso20_ht_cap = { | |||
1369 | 1537 | ||
1370 | /* HT cap appropriate for MIMO rates in 20mhz channel */ | 1538 | /* HT cap appropriate for MIMO rates in 20mhz channel */ |
1371 | static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_2ghz = { | 1539 | static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_2ghz = { |
1372 | .cap = IEEE80211_HT_CAP_SGI_20, | 1540 | .cap = IEEE80211_HT_CAP_SGI_20 | |
1541 | IEEE80211_HT_CAP_GRN_FLD, | ||
1373 | .ht_supported = true, | 1542 | .ht_supported = true, |
1374 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, | 1543 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, |
1375 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | 1544 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, |
@@ -1387,7 +1556,8 @@ static int wl18xx_setup(struct wl1271 *wl) | |||
1387 | 1556 | ||
1388 | wl->rtable = wl18xx_rtable; | 1557 | wl->rtable = wl18xx_rtable; |
1389 | wl->num_tx_desc = WL18XX_NUM_TX_DESCRIPTORS; | 1558 | wl->num_tx_desc = WL18XX_NUM_TX_DESCRIPTORS; |
1390 | wl->num_rx_desc = WL18XX_NUM_TX_DESCRIPTORS; | 1559 | wl->num_rx_desc = WL18XX_NUM_RX_DESCRIPTORS; |
1560 | wl->num_channels = 2; | ||
1391 | wl->num_mac_addr = WL18XX_NUM_MAC_ADDRESSES; | 1561 | wl->num_mac_addr = WL18XX_NUM_MAC_ADDRESSES; |
1392 | wl->band_rate_to_idx = wl18xx_band_rate_to_idx; | 1562 | wl->band_rate_to_idx = wl18xx_band_rate_to_idx; |
1393 | wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX; | 1563 | wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX; |
@@ -1506,7 +1676,8 @@ static int wl18xx_probe(struct platform_device *pdev) | |||
1506 | int ret; | 1676 | int ret; |
1507 | 1677 | ||
1508 | hw = wlcore_alloc_hw(sizeof(struct wl18xx_priv), | 1678 | hw = wlcore_alloc_hw(sizeof(struct wl18xx_priv), |
1509 | WL18XX_AGGR_BUFFER_SIZE); | 1679 | WL18XX_AGGR_BUFFER_SIZE, |
1680 | sizeof(struct wl18xx_event_mailbox)); | ||
1510 | if (IS_ERR(hw)) { | 1681 | if (IS_ERR(hw)) { |
1511 | wl1271_error("can't allocate hw"); | 1682 | wl1271_error("can't allocate hw"); |
1512 | ret = PTR_ERR(hw); | 1683 | ret = PTR_ERR(hw); |
diff --git a/drivers/net/wireless/ti/wl18xx/scan.c b/drivers/net/wireless/ti/wl18xx/scan.c new file mode 100644 index 000000000000..09d944505ac0 --- /dev/null +++ b/drivers/net/wireless/ti/wl18xx/scan.c | |||
@@ -0,0 +1,326 @@ | |||
1 | /* | ||
2 | * This file is part of wl18xx | ||
3 | * | ||
4 | * Copyright (C) 2012 Texas Instruments. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <linux/ieee80211.h> | ||
23 | #include "scan.h" | ||
24 | #include "../wlcore/debug.h" | ||
25 | |||
26 | static void wl18xx_adjust_channels(struct wl18xx_cmd_scan_params *cmd, | ||
27 | struct wlcore_scan_channels *cmd_channels) | ||
28 | { | ||
29 | memcpy(cmd->passive, cmd_channels->passive, sizeof(cmd->passive)); | ||
30 | memcpy(cmd->active, cmd_channels->active, sizeof(cmd->active)); | ||
31 | cmd->dfs = cmd_channels->dfs; | ||
32 | cmd->passive_active = cmd_channels->passive_active; | ||
33 | |||
34 | memcpy(cmd->channels_2, cmd_channels->channels_2, | ||
35 | sizeof(cmd->channels_2)); | ||
36 | memcpy(cmd->channels_5, cmd_channels->channels_5, | ||
37 | sizeof(cmd->channels_2)); | ||
38 | /* channels_4 are not supported, so no need to copy them */ | ||
39 | } | ||
40 | |||
41 | static int wl18xx_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
42 | struct cfg80211_scan_request *req) | ||
43 | { | ||
44 | struct wl18xx_cmd_scan_params *cmd; | ||
45 | struct wlcore_scan_channels *cmd_channels = NULL; | ||
46 | int ret; | ||
47 | |||
48 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
49 | if (!cmd) { | ||
50 | ret = -ENOMEM; | ||
51 | goto out; | ||
52 | } | ||
53 | |||
54 | cmd->role_id = wlvif->role_id; | ||
55 | |||
56 | if (WARN_ON(cmd->role_id == WL12XX_INVALID_ROLE_ID)) { | ||
57 | ret = -EINVAL; | ||
58 | goto out; | ||
59 | } | ||
60 | |||
61 | cmd->scan_type = SCAN_TYPE_SEARCH; | ||
62 | cmd->rssi_threshold = -127; | ||
63 | cmd->snr_threshold = 0; | ||
64 | |||
65 | cmd->bss_type = SCAN_BSS_TYPE_ANY; | ||
66 | |||
67 | cmd->ssid_from_list = 0; | ||
68 | cmd->filter = 0; | ||
69 | cmd->add_broadcast = 0; | ||
70 | |||
71 | cmd->urgency = 0; | ||
72 | cmd->protect = 0; | ||
73 | |||
74 | cmd->n_probe_reqs = wl->conf.scan.num_probe_reqs; | ||
75 | cmd->terminate_after = 0; | ||
76 | |||
77 | /* configure channels */ | ||
78 | WARN_ON(req->n_ssids > 1); | ||
79 | |||
80 | cmd_channels = kzalloc(sizeof(*cmd_channels), GFP_KERNEL); | ||
81 | if (!cmd_channels) { | ||
82 | ret = -ENOMEM; | ||
83 | goto out; | ||
84 | } | ||
85 | |||
86 | wlcore_set_scan_chan_params(wl, cmd_channels, req->channels, | ||
87 | req->n_channels, req->n_ssids, | ||
88 | SCAN_TYPE_SEARCH); | ||
89 | wl18xx_adjust_channels(cmd, cmd_channels); | ||
90 | |||
91 | /* | ||
92 | * all the cycles params (except total cycles) should | ||
93 | * remain 0 for normal scan | ||
94 | */ | ||
95 | cmd->total_cycles = 1; | ||
96 | |||
97 | if (req->no_cck) | ||
98 | cmd->rate = WL18XX_SCAN_RATE_6; | ||
99 | |||
100 | cmd->tag = WL1271_SCAN_DEFAULT_TAG; | ||
101 | |||
102 | if (req->n_ssids) { | ||
103 | cmd->ssid_len = req->ssids[0].ssid_len; | ||
104 | memcpy(cmd->ssid, req->ssids[0].ssid, cmd->ssid_len); | ||
105 | } | ||
106 | |||
107 | /* TODO: per-band ies? */ | ||
108 | if (cmd->active[0]) { | ||
109 | u8 band = IEEE80211_BAND_2GHZ; | ||
110 | ret = wl12xx_cmd_build_probe_req(wl, wlvif, | ||
111 | cmd->role_id, band, | ||
112 | req->ssids ? req->ssids[0].ssid : NULL, | ||
113 | req->ssids ? req->ssids[0].ssid_len : 0, | ||
114 | req->ie, | ||
115 | req->ie_len, | ||
116 | false); | ||
117 | if (ret < 0) { | ||
118 | wl1271_error("2.4GHz PROBE request template failed"); | ||
119 | goto out; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | if (cmd->active[1] || cmd->dfs) { | ||
124 | u8 band = IEEE80211_BAND_5GHZ; | ||
125 | ret = wl12xx_cmd_build_probe_req(wl, wlvif, | ||
126 | cmd->role_id, band, | ||
127 | req->ssids ? req->ssids[0].ssid : NULL, | ||
128 | req->ssids ? req->ssids[0].ssid_len : 0, | ||
129 | req->ie, | ||
130 | req->ie_len, | ||
131 | false); | ||
132 | if (ret < 0) { | ||
133 | wl1271_error("5GHz PROBE request template failed"); | ||
134 | goto out; | ||
135 | } | ||
136 | } | ||
137 | |||
138 | wl1271_dump(DEBUG_SCAN, "SCAN: ", cmd, sizeof(*cmd)); | ||
139 | |||
140 | ret = wl1271_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd), 0); | ||
141 | if (ret < 0) { | ||
142 | wl1271_error("SCAN failed"); | ||
143 | goto out; | ||
144 | } | ||
145 | |||
146 | out: | ||
147 | kfree(cmd_channels); | ||
148 | kfree(cmd); | ||
149 | return ret; | ||
150 | } | ||
151 | |||
152 | void wl18xx_scan_completed(struct wl1271 *wl, struct wl12xx_vif *wlvif) | ||
153 | { | ||
154 | wl->scan.failed = false; | ||
155 | cancel_delayed_work(&wl->scan_complete_work); | ||
156 | ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, | ||
157 | msecs_to_jiffies(0)); | ||
158 | } | ||
159 | |||
160 | static | ||
161 | int wl18xx_scan_sched_scan_config(struct wl1271 *wl, | ||
162 | struct wl12xx_vif *wlvif, | ||
163 | struct cfg80211_sched_scan_request *req, | ||
164 | struct ieee80211_sched_scan_ies *ies) | ||
165 | { | ||
166 | struct wl18xx_cmd_scan_params *cmd; | ||
167 | struct wlcore_scan_channels *cmd_channels = NULL; | ||
168 | struct conf_sched_scan_settings *c = &wl->conf.sched_scan; | ||
169 | int ret; | ||
170 | int filter_type; | ||
171 | |||
172 | wl1271_debug(DEBUG_CMD, "cmd sched_scan scan config"); | ||
173 | |||
174 | filter_type = wlcore_scan_sched_scan_ssid_list(wl, wlvif, req); | ||
175 | if (filter_type < 0) | ||
176 | return filter_type; | ||
177 | |||
178 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
179 | if (!cmd) { | ||
180 | ret = -ENOMEM; | ||
181 | goto out; | ||
182 | } | ||
183 | |||
184 | cmd->role_id = wlvif->role_id; | ||
185 | |||
186 | if (WARN_ON(cmd->role_id == WL12XX_INVALID_ROLE_ID)) { | ||
187 | ret = -EINVAL; | ||
188 | goto out; | ||
189 | } | ||
190 | |||
191 | cmd->scan_type = SCAN_TYPE_PERIODIC; | ||
192 | cmd->rssi_threshold = c->rssi_threshold; | ||
193 | cmd->snr_threshold = c->snr_threshold; | ||
194 | |||
195 | /* don't filter on BSS type */ | ||
196 | cmd->bss_type = SCAN_BSS_TYPE_ANY; | ||
197 | |||
198 | cmd->ssid_from_list = 1; | ||
199 | if (filter_type == SCAN_SSID_FILTER_LIST) | ||
200 | cmd->filter = 1; | ||
201 | cmd->add_broadcast = 0; | ||
202 | |||
203 | cmd->urgency = 0; | ||
204 | cmd->protect = 0; | ||
205 | |||
206 | cmd->n_probe_reqs = c->num_probe_reqs; | ||
207 | /* don't stop scanning automatically when something is found */ | ||
208 | cmd->terminate_after = 0; | ||
209 | |||
210 | cmd_channels = kzalloc(sizeof(*cmd_channels), GFP_KERNEL); | ||
211 | if (!cmd_channels) { | ||
212 | ret = -ENOMEM; | ||
213 | goto out; | ||
214 | } | ||
215 | |||
216 | /* configure channels */ | ||
217 | wlcore_set_scan_chan_params(wl, cmd_channels, req->channels, | ||
218 | req->n_channels, req->n_ssids, | ||
219 | SCAN_TYPE_PERIODIC); | ||
220 | wl18xx_adjust_channels(cmd, cmd_channels); | ||
221 | |||
222 | cmd->short_cycles_sec = 0; | ||
223 | cmd->long_cycles_sec = cpu_to_le16(req->interval); | ||
224 | cmd->short_cycles_count = 0; | ||
225 | |||
226 | cmd->total_cycles = 0; | ||
227 | |||
228 | cmd->tag = WL1271_SCAN_DEFAULT_TAG; | ||
229 | |||
230 | /* create a PERIODIC_SCAN_REPORT_EVENT whenever we've got a match */ | ||
231 | cmd->report_threshold = 1; | ||
232 | cmd->terminate_on_report = 0; | ||
233 | |||
234 | if (cmd->active[0]) { | ||
235 | u8 band = IEEE80211_BAND_2GHZ; | ||
236 | ret = wl12xx_cmd_build_probe_req(wl, wlvif, | ||
237 | cmd->role_id, band, | ||
238 | req->ssids ? req->ssids[0].ssid : NULL, | ||
239 | req->ssids ? req->ssids[0].ssid_len : 0, | ||
240 | ies->ie[band], | ||
241 | ies->len[band], | ||
242 | true); | ||
243 | if (ret < 0) { | ||
244 | wl1271_error("2.4GHz PROBE request template failed"); | ||
245 | goto out; | ||
246 | } | ||
247 | } | ||
248 | |||
249 | if (cmd->active[1] || cmd->dfs) { | ||
250 | u8 band = IEEE80211_BAND_5GHZ; | ||
251 | ret = wl12xx_cmd_build_probe_req(wl, wlvif, | ||
252 | cmd->role_id, band, | ||
253 | req->ssids ? req->ssids[0].ssid : NULL, | ||
254 | req->ssids ? req->ssids[0].ssid_len : 0, | ||
255 | ies->ie[band], | ||
256 | ies->len[band], | ||
257 | true); | ||
258 | if (ret < 0) { | ||
259 | wl1271_error("5GHz PROBE request template failed"); | ||
260 | goto out; | ||
261 | } | ||
262 | } | ||
263 | |||
264 | wl1271_dump(DEBUG_SCAN, "SCAN: ", cmd, sizeof(*cmd)); | ||
265 | |||
266 | ret = wl1271_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd), 0); | ||
267 | if (ret < 0) { | ||
268 | wl1271_error("SCAN failed"); | ||
269 | goto out; | ||
270 | } | ||
271 | |||
272 | out: | ||
273 | kfree(cmd_channels); | ||
274 | kfree(cmd); | ||
275 | return ret; | ||
276 | } | ||
277 | |||
278 | int wl18xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
279 | struct cfg80211_sched_scan_request *req, | ||
280 | struct ieee80211_sched_scan_ies *ies) | ||
281 | { | ||
282 | return wl18xx_scan_sched_scan_config(wl, wlvif, req, ies); | ||
283 | } | ||
284 | |||
285 | static int __wl18xx_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
286 | u8 scan_type) | ||
287 | { | ||
288 | struct wl18xx_cmd_scan_stop *stop; | ||
289 | int ret; | ||
290 | |||
291 | wl1271_debug(DEBUG_CMD, "cmd periodic scan stop"); | ||
292 | |||
293 | stop = kzalloc(sizeof(*stop), GFP_KERNEL); | ||
294 | if (!stop) { | ||
295 | wl1271_error("failed to alloc memory to send sched scan stop"); | ||
296 | return -ENOMEM; | ||
297 | } | ||
298 | |||
299 | stop->role_id = wlvif->role_id; | ||
300 | stop->scan_type = scan_type; | ||
301 | |||
302 | ret = wl1271_cmd_send(wl, CMD_STOP_SCAN, stop, sizeof(*stop), 0); | ||
303 | if (ret < 0) { | ||
304 | wl1271_error("failed to send sched scan stop command"); | ||
305 | goto out_free; | ||
306 | } | ||
307 | |||
308 | out_free: | ||
309 | kfree(stop); | ||
310 | return ret; | ||
311 | } | ||
312 | |||
313 | void wl18xx_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif) | ||
314 | { | ||
315 | __wl18xx_scan_stop(wl, wlvif, SCAN_TYPE_PERIODIC); | ||
316 | } | ||
317 | int wl18xx_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
318 | struct cfg80211_scan_request *req) | ||
319 | { | ||
320 | return wl18xx_scan_send(wl, wlvif, req); | ||
321 | } | ||
322 | |||
323 | int wl18xx_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif) | ||
324 | { | ||
325 | return __wl18xx_scan_stop(wl, wlvif, SCAN_TYPE_SEARCH); | ||
326 | } | ||
diff --git a/drivers/net/wireless/ti/wl18xx/scan.h b/drivers/net/wireless/ti/wl18xx/scan.h new file mode 100644 index 000000000000..eadee42689d1 --- /dev/null +++ b/drivers/net/wireless/ti/wl18xx/scan.h | |||
@@ -0,0 +1,127 @@ | |||
1 | /* | ||
2 | * This file is part of wl18xx | ||
3 | * | ||
4 | * Copyright (C) 2012 Texas Instruments. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef __WL18XX_SCAN_H__ | ||
23 | #define __WL18XX_SCAN_H__ | ||
24 | |||
25 | #include "../wlcore/wlcore.h" | ||
26 | #include "../wlcore/cmd.h" | ||
27 | #include "../wlcore/scan.h" | ||
28 | |||
29 | struct tracking_ch_params { | ||
30 | struct conn_scan_ch_params channel; | ||
31 | |||
32 | __le32 bssid_lsb; | ||
33 | __le16 bssid_msb; | ||
34 | |||
35 | u8 padding[2]; | ||
36 | } __packed; | ||
37 | |||
38 | /* probe request rate */ | ||
39 | enum | ||
40 | { | ||
41 | WL18XX_SCAN_RATE_1 = 0, | ||
42 | WL18XX_SCAN_RATE_5_5 = 1, | ||
43 | WL18XX_SCAN_RATE_6 = 2, | ||
44 | }; | ||
45 | |||
46 | #define WL18XX_MAX_CHANNELS_5GHZ 32 | ||
47 | |||
48 | struct wl18xx_cmd_scan_params { | ||
49 | struct wl1271_cmd_header header; | ||
50 | |||
51 | u8 role_id; | ||
52 | u8 scan_type; | ||
53 | |||
54 | s8 rssi_threshold; /* for filtering (in dBm) */ | ||
55 | s8 snr_threshold; /* for filtering (in dB) */ | ||
56 | |||
57 | u8 bss_type; /* for filtering */ | ||
58 | u8 ssid_from_list; /* use ssid from configured ssid list */ | ||
59 | u8 filter; /* forward only results with matching ssids */ | ||
60 | |||
61 | /* | ||
62 | * add broadcast ssid in addition to the configured ssids. | ||
63 | * the driver should add dummy entry for it (?). | ||
64 | */ | ||
65 | u8 add_broadcast; | ||
66 | |||
67 | u8 urgency; | ||
68 | u8 protect; /* ??? */ | ||
69 | u8 n_probe_reqs; /* Number of probes requests per channel */ | ||
70 | u8 terminate_after; /* early terminate scan operation */ | ||
71 | |||
72 | u8 passive[SCAN_MAX_BANDS]; /* number of passive scan channels */ | ||
73 | u8 active[SCAN_MAX_BANDS]; /* number of active scan channels */ | ||
74 | u8 dfs; /* number of dfs channels in 5ghz */ | ||
75 | u8 passive_active; /* number of passive before active channels 2.4ghz */ | ||
76 | |||
77 | __le16 short_cycles_sec; | ||
78 | __le16 long_cycles_sec; | ||
79 | u8 short_cycles_count; | ||
80 | u8 total_cycles; /* 0 - infinite */ | ||
81 | u8 padding[2]; | ||
82 | |||
83 | union { | ||
84 | struct { | ||
85 | struct conn_scan_ch_params channels_2[MAX_CHANNELS_2GHZ]; | ||
86 | struct conn_scan_ch_params channels_5[WL18XX_MAX_CHANNELS_5GHZ]; | ||
87 | struct conn_scan_ch_params channels_4[MAX_CHANNELS_4GHZ]; | ||
88 | }; | ||
89 | struct tracking_ch_params channels_tracking[WL1271_SCAN_MAX_CHANNELS]; | ||
90 | } ; | ||
91 | |||
92 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | ||
93 | u8 ssid_len; /* For SCAN_SSID_FILTER_SPECIFIC */ | ||
94 | u8 tag; | ||
95 | u8 rate; | ||
96 | |||
97 | /* send SCAN_REPORT_EVENT in periodic scans after each cycle | ||
98 | * if number of results >= report_threshold. Must be 0 for | ||
99 | * non periodic scans | ||
100 | */ | ||
101 | u8 report_threshold; | ||
102 | |||
103 | /* Should periodic scan stop after a report event was created. | ||
104 | * Must be 0 for non periodic scans. | ||
105 | */ | ||
106 | u8 terminate_on_report; | ||
107 | |||
108 | u8 padding1[3]; | ||
109 | } __packed; | ||
110 | |||
111 | struct wl18xx_cmd_scan_stop { | ||
112 | struct wl1271_cmd_header header; | ||
113 | |||
114 | u8 role_id; | ||
115 | u8 scan_type; | ||
116 | u8 padding[2]; | ||
117 | } __packed; | ||
118 | |||
119 | int wl18xx_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
120 | struct cfg80211_scan_request *req); | ||
121 | int wl18xx_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif); | ||
122 | void wl18xx_scan_completed(struct wl1271 *wl, struct wl12xx_vif *wlvif); | ||
123 | int wl18xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
124 | struct cfg80211_sched_scan_request *req, | ||
125 | struct ieee80211_sched_scan_ies *ies); | ||
126 | void wl18xx_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif); | ||
127 | #endif | ||
diff --git a/drivers/net/wireless/ti/wl18xx/tx.c b/drivers/net/wireless/ti/wl18xx/tx.c index 5b1fb10d9fd7..57c694396647 100644 --- a/drivers/net/wireless/ti/wl18xx/tx.c +++ b/drivers/net/wireless/ti/wl18xx/tx.c | |||
@@ -28,6 +28,49 @@ | |||
28 | #include "wl18xx.h" | 28 | #include "wl18xx.h" |
29 | #include "tx.h" | 29 | #include "tx.h" |
30 | 30 | ||
31 | static | ||
32 | void wl18xx_get_last_tx_rate(struct wl1271 *wl, struct ieee80211_vif *vif, | ||
33 | struct ieee80211_tx_rate *rate) | ||
34 | { | ||
35 | u8 fw_rate = wl->fw_status_2->counters.tx_last_rate; | ||
36 | |||
37 | if (fw_rate > CONF_HW_RATE_INDEX_MAX) { | ||
38 | wl1271_error("last Tx rate invalid: %d", fw_rate); | ||
39 | rate->idx = 0; | ||
40 | rate->flags = 0; | ||
41 | return; | ||
42 | } | ||
43 | |||
44 | if (fw_rate <= CONF_HW_RATE_INDEX_54MBPS) { | ||
45 | rate->idx = fw_rate; | ||
46 | rate->flags = 0; | ||
47 | } else { | ||
48 | rate->flags = IEEE80211_TX_RC_MCS; | ||
49 | rate->idx = fw_rate - CONF_HW_RATE_INDEX_MCS0; | ||
50 | |||
51 | /* SGI modifier is counted as a separate rate */ | ||
52 | if (fw_rate >= CONF_HW_RATE_INDEX_MCS7_SGI) | ||
53 | (rate->idx)--; | ||
54 | if (fw_rate == CONF_HW_RATE_INDEX_MCS15_SGI) | ||
55 | (rate->idx)--; | ||
56 | |||
57 | /* this also covers the 40Mhz SGI case (= MCS15) */ | ||
58 | if (fw_rate == CONF_HW_RATE_INDEX_MCS7_SGI || | ||
59 | fw_rate == CONF_HW_RATE_INDEX_MCS15_SGI) | ||
60 | rate->flags |= IEEE80211_TX_RC_SHORT_GI; | ||
61 | |||
62 | if (fw_rate > CONF_HW_RATE_INDEX_MCS7_SGI && vif) { | ||
63 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
64 | if (wlvif->channel_type == NL80211_CHAN_HT40MINUS || | ||
65 | wlvif->channel_type == NL80211_CHAN_HT40PLUS) { | ||
66 | /* adjustment needed for range 0-7 */ | ||
67 | rate->idx -= 8; | ||
68 | rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; | ||
69 | } | ||
70 | } | ||
71 | } | ||
72 | } | ||
73 | |||
31 | static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte) | 74 | static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte) |
32 | { | 75 | { |
33 | struct ieee80211_tx_info *info; | 76 | struct ieee80211_tx_info *info; |
@@ -44,7 +87,6 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte) | |||
44 | /* a zero bit indicates Tx success */ | 87 | /* a zero bit indicates Tx success */ |
45 | tx_success = !(tx_stat_byte & BIT(WL18XX_TX_STATUS_STAT_BIT_IDX)); | 88 | tx_success = !(tx_stat_byte & BIT(WL18XX_TX_STATUS_STAT_BIT_IDX)); |
46 | 89 | ||
47 | |||
48 | skb = wl->tx_frames[id]; | 90 | skb = wl->tx_frames[id]; |
49 | info = IEEE80211_SKB_CB(skb); | 91 | info = IEEE80211_SKB_CB(skb); |
50 | 92 | ||
@@ -56,11 +98,13 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte) | |||
56 | /* update the TX status info */ | 98 | /* update the TX status info */ |
57 | if (tx_success && !(info->flags & IEEE80211_TX_CTL_NO_ACK)) | 99 | if (tx_success && !(info->flags & IEEE80211_TX_CTL_NO_ACK)) |
58 | info->flags |= IEEE80211_TX_STAT_ACK; | 100 | info->flags |= IEEE80211_TX_STAT_ACK; |
101 | /* | ||
102 | * first pass info->control.vif while it's valid, and then fill out | ||
103 | * the info->status structures | ||
104 | */ | ||
105 | wl18xx_get_last_tx_rate(wl, info->control.vif, &info->status.rates[0]); | ||
59 | 106 | ||
60 | /* no real data about Tx completion */ | 107 | info->status.rates[0].count = 1; /* no data about retries */ |
61 | info->status.rates[0].idx = -1; | ||
62 | info->status.rates[0].count = 0; | ||
63 | info->status.rates[0].flags = 0; | ||
64 | info->status.ack_signal = -1; | 108 | info->status.ack_signal = -1; |
65 | 109 | ||
66 | if (!tx_success) | 110 | if (!tx_success) |
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h index 96a1e438d677..b6739e79efcf 100644 --- a/drivers/net/wireless/ti/wl18xx/wl18xx.h +++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h | |||
@@ -26,10 +26,10 @@ | |||
26 | 26 | ||
27 | /* minimum FW required for driver */ | 27 | /* minimum FW required for driver */ |
28 | #define WL18XX_CHIP_VER 8 | 28 | #define WL18XX_CHIP_VER 8 |
29 | #define WL18XX_IFTYPE_VER 2 | 29 | #define WL18XX_IFTYPE_VER 5 |
30 | #define WL18XX_MAJOR_VER 0 | 30 | #define WL18XX_MAJOR_VER WLCORE_FW_VER_IGNORE |
31 | #define WL18XX_SUBTYPE_VER 0 | 31 | #define WL18XX_SUBTYPE_VER WLCORE_FW_VER_IGNORE |
32 | #define WL18XX_MINOR_VER 100 | 32 | #define WL18XX_MINOR_VER 28 |
33 | 33 | ||
34 | #define WL18XX_CMD_MAX_SIZE 740 | 34 | #define WL18XX_CMD_MAX_SIZE 740 |
35 | 35 | ||
@@ -49,8 +49,8 @@ struct wl18xx_priv { | |||
49 | /* Index of last released Tx desc in FW */ | 49 | /* Index of last released Tx desc in FW */ |
50 | u8 last_fw_rls_idx; | 50 | u8 last_fw_rls_idx; |
51 | 51 | ||
52 | /* number of VIFs requiring extra spare mem-blocks */ | 52 | /* number of keys requiring extra spare mem-blocks */ |
53 | int extra_spare_vif_count; | 53 | int extra_spare_key_count; |
54 | }; | 54 | }; |
55 | 55 | ||
56 | #define WL18XX_FW_MAX_TX_STATUS_DESC 33 | 56 | #define WL18XX_FW_MAX_TX_STATUS_DESC 33 |
@@ -68,7 +68,43 @@ struct wl18xx_fw_status_priv { | |||
68 | */ | 68 | */ |
69 | u8 released_tx_desc[WL18XX_FW_MAX_TX_STATUS_DESC]; | 69 | u8 released_tx_desc[WL18XX_FW_MAX_TX_STATUS_DESC]; |
70 | 70 | ||
71 | u8 padding[2]; | 71 | /* A bitmap representing the currently suspended links. The suspend |
72 | * is short lived, for multi-channel Tx requirements. | ||
73 | */ | ||
74 | __le32 link_suspend_bitmap; | ||
75 | |||
76 | /* packet threshold for an "almost empty" AC, | ||
77 | * for Tx schedulng purposes | ||
78 | */ | ||
79 | u8 tx_ac_threshold; | ||
80 | |||
81 | /* number of packets to queue up for a link in PS */ | ||
82 | u8 tx_ps_threshold; | ||
83 | |||
84 | /* number of packet to queue up for a suspended link */ | ||
85 | u8 tx_suspend_threshold; | ||
86 | |||
87 | /* Should have less than this number of packets in queue of a slow | ||
88 | * link to qualify as high priority link | ||
89 | */ | ||
90 | u8 tx_slow_link_prio_threshold; | ||
91 | |||
92 | /* Should have less than this number of packets in queue of a fast | ||
93 | * link to qualify as high priority link | ||
94 | */ | ||
95 | u8 tx_fast_link_prio_threshold; | ||
96 | |||
97 | /* Should have less than this number of packets in queue of a slow | ||
98 | * link before we stop queuing up packets for it. | ||
99 | */ | ||
100 | u8 tx_slow_stop_threshold; | ||
101 | |||
102 | /* Should have less than this number of packets in queue of a fast | ||
103 | * link before we stop queuing up packets for it. | ||
104 | */ | ||
105 | u8 tx_fast_stop_threshold; | ||
106 | |||
107 | u8 padding[3]; | ||
72 | }; | 108 | }; |
73 | 109 | ||
74 | #define WL18XX_PHY_VERSION_MAX_LEN 20 | 110 | #define WL18XX_PHY_VERSION_MAX_LEN 20 |
diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c index ce108a736bd0..c79654323396 100644 --- a/drivers/net/wireless/ti/wlcore/acx.c +++ b/drivers/net/wireless/ti/wlcore/acx.c | |||
@@ -1340,6 +1340,8 @@ out: | |||
1340 | kfree(acx); | 1340 | kfree(acx); |
1341 | return ret; | 1341 | return ret; |
1342 | } | 1342 | } |
1343 | EXPORT_SYMBOL_GPL(wl1271_acx_set_ht_capabilities); | ||
1344 | |||
1343 | 1345 | ||
1344 | int wl1271_acx_set_ht_information(struct wl1271 *wl, | 1346 | int wl1271_acx_set_ht_information(struct wl1271 *wl, |
1345 | struct wl12xx_vif *wlvif, | 1347 | struct wl12xx_vif *wlvif, |
@@ -1433,13 +1435,22 @@ int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, | |||
1433 | acx->win_size = wl->conf.ht.rx_ba_win_size; | 1435 | acx->win_size = wl->conf.ht.rx_ba_win_size; |
1434 | acx->ssn = ssn; | 1436 | acx->ssn = ssn; |
1435 | 1437 | ||
1436 | ret = wl1271_cmd_configure(wl, ACX_BA_SESSION_RX_SETUP, acx, | 1438 | ret = wlcore_cmd_configure_failsafe(wl, ACX_BA_SESSION_RX_SETUP, acx, |
1437 | sizeof(*acx)); | 1439 | sizeof(*acx), |
1440 | BIT(CMD_STATUS_NO_RX_BA_SESSION)); | ||
1438 | if (ret < 0) { | 1441 | if (ret < 0) { |
1439 | wl1271_warning("acx ba receiver session failed: %d", ret); | 1442 | wl1271_warning("acx ba receiver session failed: %d", ret); |
1440 | goto out; | 1443 | goto out; |
1441 | } | 1444 | } |
1442 | 1445 | ||
1446 | /* sometimes we can't start the session */ | ||
1447 | if (ret == CMD_STATUS_NO_RX_BA_SESSION) { | ||
1448 | wl1271_warning("no fw rx ba on tid %d", tid_index); | ||
1449 | ret = -EBUSY; | ||
1450 | goto out; | ||
1451 | } | ||
1452 | |||
1453 | ret = 0; | ||
1443 | out: | 1454 | out: |
1444 | kfree(acx); | 1455 | kfree(acx); |
1445 | return ret; | 1456 | return ret; |
diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h index d03215d6b3bd..126536c6a393 100644 --- a/drivers/net/wireless/ti/wlcore/acx.h +++ b/drivers/net/wireless/ti/wlcore/acx.h | |||
@@ -1025,7 +1025,6 @@ enum { | |||
1025 | ACX_CONFIG_HANGOVER = 0x0042, | 1025 | ACX_CONFIG_HANGOVER = 0x0042, |
1026 | ACX_FEATURE_CFG = 0x0043, | 1026 | ACX_FEATURE_CFG = 0x0043, |
1027 | ACX_PROTECTION_CFG = 0x0044, | 1027 | ACX_PROTECTION_CFG = 0x0044, |
1028 | ACX_CHECKSUM_CONFIG = 0x0045, | ||
1029 | }; | 1028 | }; |
1030 | 1029 | ||
1031 | 1030 | ||
diff --git a/drivers/net/wireless/ti/wlcore/boot.c b/drivers/net/wireless/ti/wlcore/boot.c index 375ea574eafb..b58ae5fc1487 100644 --- a/drivers/net/wireless/ti/wlcore/boot.c +++ b/drivers/net/wireless/ti/wlcore/boot.c | |||
@@ -84,47 +84,57 @@ out: | |||
84 | static int wlcore_validate_fw_ver(struct wl1271 *wl) | 84 | static int wlcore_validate_fw_ver(struct wl1271 *wl) |
85 | { | 85 | { |
86 | unsigned int *fw_ver = wl->chip.fw_ver; | 86 | unsigned int *fw_ver = wl->chip.fw_ver; |
87 | unsigned int *min_ver = wl->min_fw_ver; | 87 | unsigned int *min_ver = (wl->fw_type == WL12XX_FW_TYPE_NORMAL) ? |
88 | wl->min_sr_fw_ver : wl->min_mr_fw_ver; | ||
89 | char min_fw_str[32] = ""; | ||
90 | int i; | ||
88 | 91 | ||
89 | /* the chip must be exactly equal */ | 92 | /* the chip must be exactly equal */ |
90 | if (min_ver[FW_VER_CHIP] != fw_ver[FW_VER_CHIP]) | 93 | if ((min_ver[FW_VER_CHIP] != WLCORE_FW_VER_IGNORE) && |
94 | (min_ver[FW_VER_CHIP] != fw_ver[FW_VER_CHIP])) | ||
91 | goto fail; | 95 | goto fail; |
92 | 96 | ||
93 | /* always check the next digit if all previous ones are equal */ | 97 | /* the firmware type must be equal */ |
94 | 98 | if ((min_ver[FW_VER_IF_TYPE] != WLCORE_FW_VER_IGNORE) && | |
95 | if (min_ver[FW_VER_IF_TYPE] < fw_ver[FW_VER_IF_TYPE]) | 99 | (min_ver[FW_VER_IF_TYPE] != fw_ver[FW_VER_IF_TYPE])) |
96 | goto out; | ||
97 | else if (min_ver[FW_VER_IF_TYPE] > fw_ver[FW_VER_IF_TYPE]) | ||
98 | goto fail; | 100 | goto fail; |
99 | 101 | ||
100 | if (min_ver[FW_VER_MAJOR] < fw_ver[FW_VER_MAJOR]) | 102 | /* the project number must be equal */ |
101 | goto out; | 103 | if ((min_ver[FW_VER_SUBTYPE] != WLCORE_FW_VER_IGNORE) && |
102 | else if (min_ver[FW_VER_MAJOR] > fw_ver[FW_VER_MAJOR]) | 104 | (min_ver[FW_VER_SUBTYPE] != fw_ver[FW_VER_SUBTYPE])) |
103 | goto fail; | 105 | goto fail; |
104 | 106 | ||
105 | if (min_ver[FW_VER_SUBTYPE] < fw_ver[FW_VER_SUBTYPE]) | 107 | /* the API version must be greater or equal */ |
106 | goto out; | 108 | if ((min_ver[FW_VER_MAJOR] != WLCORE_FW_VER_IGNORE) && |
107 | else if (min_ver[FW_VER_SUBTYPE] > fw_ver[FW_VER_SUBTYPE]) | 109 | (min_ver[FW_VER_MAJOR] > fw_ver[FW_VER_MAJOR])) |
108 | goto fail; | 110 | goto fail; |
109 | 111 | ||
110 | if (min_ver[FW_VER_MINOR] < fw_ver[FW_VER_MINOR]) | 112 | /* if the API version is equal... */ |
111 | goto out; | 113 | if (((min_ver[FW_VER_MAJOR] == WLCORE_FW_VER_IGNORE) || |
112 | else if (min_ver[FW_VER_MINOR] > fw_ver[FW_VER_MINOR]) | 114 | (min_ver[FW_VER_MAJOR] == fw_ver[FW_VER_MAJOR])) && |
115 | /* ...the minor must be greater or equal */ | ||
116 | ((min_ver[FW_VER_MINOR] != WLCORE_FW_VER_IGNORE) && | ||
117 | (min_ver[FW_VER_MINOR] > fw_ver[FW_VER_MINOR]))) | ||
113 | goto fail; | 118 | goto fail; |
114 | 119 | ||
115 | out: | ||
116 | return 0; | 120 | return 0; |
117 | 121 | ||
118 | fail: | 122 | fail: |
119 | wl1271_error("Your WiFi FW version (%u.%u.%u.%u.%u) is outdated.\n" | 123 | for (i = 0; i < NUM_FW_VER; i++) |
120 | "Please use at least FW %u.%u.%u.%u.%u.\n" | 124 | if (min_ver[i] == WLCORE_FW_VER_IGNORE) |
121 | "You can get more information at:\n" | 125 | snprintf(min_fw_str, sizeof(min_fw_str), |
122 | "http://wireless.kernel.org/en/users/Drivers/wl12xx", | 126 | "%s*.", min_fw_str); |
127 | else | ||
128 | snprintf(min_fw_str, sizeof(min_fw_str), | ||
129 | "%s%u.", min_fw_str, min_ver[i]); | ||
130 | |||
131 | wl1271_error("Your WiFi FW version (%u.%u.%u.%u.%u) is invalid.\n" | ||
132 | "Please use at least FW %s\n" | ||
133 | "You can get the latest firmwares at:\n" | ||
134 | "git://github.com/TI-OpenLink/firmwares.git", | ||
123 | fw_ver[FW_VER_CHIP], fw_ver[FW_VER_IF_TYPE], | 135 | fw_ver[FW_VER_CHIP], fw_ver[FW_VER_IF_TYPE], |
124 | fw_ver[FW_VER_MAJOR], fw_ver[FW_VER_SUBTYPE], | 136 | fw_ver[FW_VER_MAJOR], fw_ver[FW_VER_SUBTYPE], |
125 | fw_ver[FW_VER_MINOR], min_ver[FW_VER_CHIP], | 137 | fw_ver[FW_VER_MINOR], min_fw_str); |
126 | min_ver[FW_VER_IF_TYPE], min_ver[FW_VER_MAJOR], | ||
127 | min_ver[FW_VER_SUBTYPE], min_ver[FW_VER_MINOR]); | ||
128 | return -EINVAL; | 138 | return -EINVAL; |
129 | } | 139 | } |
130 | 140 | ||
@@ -491,7 +501,7 @@ int wlcore_boot_run_firmware(struct wl1271 *wl) | |||
491 | if (ret < 0) | 501 | if (ret < 0) |
492 | return ret; | 502 | return ret; |
493 | 503 | ||
494 | wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); | 504 | wl->mbox_ptr[1] = wl->mbox_ptr[0] + wl->mbox_size; |
495 | 505 | ||
496 | wl1271_debug(DEBUG_MAILBOX, "MBOX ptrs: 0x%x 0x%x", | 506 | wl1271_debug(DEBUG_MAILBOX, "MBOX ptrs: 0x%x 0x%x", |
497 | wl->mbox_ptr[0], wl->mbox_ptr[1]); | 507 | wl->mbox_ptr[0], wl->mbox_ptr[1]); |
@@ -508,23 +518,6 @@ int wlcore_boot_run_firmware(struct wl1271 *wl) | |||
508 | */ | 518 | */ |
509 | 519 | ||
510 | /* unmask required mbox events */ | 520 | /* unmask required mbox events */ |
511 | wl->event_mask = BSS_LOSE_EVENT_ID | | ||
512 | REGAINED_BSS_EVENT_ID | | ||
513 | SCAN_COMPLETE_EVENT_ID | | ||
514 | ROLE_STOP_COMPLETE_EVENT_ID | | ||
515 | RSSI_SNR_TRIGGER_0_EVENT_ID | | ||
516 | PSPOLL_DELIVERY_FAILURE_EVENT_ID | | ||
517 | SOFT_GEMINI_SENSE_EVENT_ID | | ||
518 | PERIODIC_SCAN_REPORT_EVENT_ID | | ||
519 | PERIODIC_SCAN_COMPLETE_EVENT_ID | | ||
520 | DUMMY_PACKET_EVENT_ID | | ||
521 | PEER_REMOVE_COMPLETE_EVENT_ID | | ||
522 | BA_SESSION_RX_CONSTRAINT_EVENT_ID | | ||
523 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | | ||
524 | INACTIVE_STA_EVENT_ID | | ||
525 | MAX_TX_RETRY_EVENT_ID | | ||
526 | CHANNEL_SWITCH_COMPLETE_EVENT_ID; | ||
527 | |||
528 | ret = wl1271_event_unmask(wl); | 521 | ret = wl1271_event_unmask(wl); |
529 | if (ret < 0) { | 522 | if (ret < 0) { |
530 | wl1271_error("EVENT mask setting failed"); | 523 | wl1271_error("EVENT mask setting failed"); |
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 27f83f72a93b..1201aca9c89a 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c | |||
@@ -48,14 +48,15 @@ | |||
48 | * @id: command id | 48 | * @id: command id |
49 | * @buf: buffer containing the command, must work with dma | 49 | * @buf: buffer containing the command, must work with dma |
50 | * @len: length of the buffer | 50 | * @len: length of the buffer |
51 | * return the cmd status code on success. | ||
51 | */ | 52 | */ |
52 | int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | 53 | static int __wlcore_cmd_send(struct wl1271 *wl, u16 id, void *buf, |
53 | size_t res_len) | 54 | size_t len, size_t res_len) |
54 | { | 55 | { |
55 | struct wl1271_cmd_header *cmd; | 56 | struct wl1271_cmd_header *cmd; |
56 | unsigned long timeout; | 57 | unsigned long timeout; |
57 | u32 intr; | 58 | u32 intr; |
58 | int ret = 0; | 59 | int ret; |
59 | u16 status; | 60 | u16 status; |
60 | u16 poll_count = 0; | 61 | u16 poll_count = 0; |
61 | 62 | ||
@@ -71,7 +72,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
71 | 72 | ||
72 | ret = wlcore_write(wl, wl->cmd_box_addr, buf, len, false); | 73 | ret = wlcore_write(wl, wl->cmd_box_addr, buf, len, false); |
73 | if (ret < 0) | 74 | if (ret < 0) |
74 | goto fail; | 75 | return ret; |
75 | 76 | ||
76 | /* | 77 | /* |
77 | * TODO: we just need this because one bit is in a different | 78 | * TODO: we just need this because one bit is in a different |
@@ -79,19 +80,18 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
79 | */ | 80 | */ |
80 | ret = wl->ops->trigger_cmd(wl, wl->cmd_box_addr, buf, len); | 81 | ret = wl->ops->trigger_cmd(wl, wl->cmd_box_addr, buf, len); |
81 | if (ret < 0) | 82 | if (ret < 0) |
82 | goto fail; | 83 | return ret; |
83 | 84 | ||
84 | timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); | 85 | timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); |
85 | 86 | ||
86 | ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr); | 87 | ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr); |
87 | if (ret < 0) | 88 | if (ret < 0) |
88 | goto fail; | 89 | return ret; |
89 | 90 | ||
90 | while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { | 91 | while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { |
91 | if (time_after(jiffies, timeout)) { | 92 | if (time_after(jiffies, timeout)) { |
92 | wl1271_error("command complete timeout"); | 93 | wl1271_error("command complete timeout"); |
93 | ret = -ETIMEDOUT; | 94 | return -ETIMEDOUT; |
94 | goto fail; | ||
95 | } | 95 | } |
96 | 96 | ||
97 | poll_count++; | 97 | poll_count++; |
@@ -102,7 +102,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
102 | 102 | ||
103 | ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr); | 103 | ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr); |
104 | if (ret < 0) | 104 | if (ret < 0) |
105 | goto fail; | 105 | return ret; |
106 | } | 106 | } |
107 | 107 | ||
108 | /* read back the status code of the command */ | 108 | /* read back the status code of the command */ |
@@ -111,33 +111,66 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
111 | 111 | ||
112 | ret = wlcore_read(wl, wl->cmd_box_addr, cmd, res_len, false); | 112 | ret = wlcore_read(wl, wl->cmd_box_addr, cmd, res_len, false); |
113 | if (ret < 0) | 113 | if (ret < 0) |
114 | goto fail; | 114 | return ret; |
115 | 115 | ||
116 | status = le16_to_cpu(cmd->status); | 116 | status = le16_to_cpu(cmd->status); |
117 | if (status != CMD_STATUS_SUCCESS) { | ||
118 | wl1271_error("command execute failure %d", status); | ||
119 | ret = -EIO; | ||
120 | goto fail; | ||
121 | } | ||
122 | 117 | ||
123 | ret = wlcore_write_reg(wl, REG_INTERRUPT_ACK, | 118 | ret = wlcore_write_reg(wl, REG_INTERRUPT_ACK, |
124 | WL1271_ACX_INTR_CMD_COMPLETE); | 119 | WL1271_ACX_INTR_CMD_COMPLETE); |
125 | if (ret < 0) | 120 | if (ret < 0) |
121 | return ret; | ||
122 | |||
123 | return status; | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * send command to fw and return cmd status on success | ||
128 | * valid_rets contains a bitmap of allowed error codes | ||
129 | */ | ||
130 | int wlcore_cmd_send_failsafe(struct wl1271 *wl, u16 id, void *buf, size_t len, | ||
131 | size_t res_len, unsigned long valid_rets) | ||
132 | { | ||
133 | int ret = __wlcore_cmd_send(wl, id, buf, len, res_len); | ||
134 | |||
135 | if (ret < 0) | ||
126 | goto fail; | 136 | goto fail; |
127 | 137 | ||
128 | return 0; | 138 | /* success is always a valid status */ |
139 | valid_rets |= BIT(CMD_STATUS_SUCCESS); | ||
129 | 140 | ||
141 | if (ret >= MAX_COMMAND_STATUS || | ||
142 | !test_bit(ret, &valid_rets)) { | ||
143 | wl1271_error("command execute failure %d", ret); | ||
144 | ret = -EIO; | ||
145 | goto fail; | ||
146 | } | ||
147 | return ret; | ||
130 | fail: | 148 | fail: |
131 | wl12xx_queue_recovery_work(wl); | 149 | wl12xx_queue_recovery_work(wl); |
132 | return ret; | 150 | return ret; |
133 | } | 151 | } |
152 | EXPORT_SYMBOL_GPL(wl1271_cmd_send); | ||
153 | |||
154 | /* | ||
155 | * wrapper for wlcore_cmd_send that accept only CMD_STATUS_SUCCESS | ||
156 | * return 0 on success. | ||
157 | */ | ||
158 | int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | ||
159 | size_t res_len) | ||
160 | { | ||
161 | int ret = wlcore_cmd_send_failsafe(wl, id, buf, len, res_len, 0); | ||
162 | |||
163 | if (ret < 0) | ||
164 | return ret; | ||
165 | return 0; | ||
166 | } | ||
134 | 167 | ||
135 | /* | 168 | /* |
136 | * Poll the mailbox event field until any of the bits in the mask is set or a | 169 | * Poll the mailbox event field until any of the bits in the mask is set or a |
137 | * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) | 170 | * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) |
138 | */ | 171 | */ |
139 | static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, | 172 | int wlcore_cmd_wait_for_event_or_timeout(struct wl1271 *wl, |
140 | u32 mask, bool *timeout) | 173 | u32 mask, bool *timeout) |
141 | { | 174 | { |
142 | u32 *events_vector; | 175 | u32 *events_vector; |
143 | u32 event; | 176 | u32 event; |
@@ -187,20 +220,7 @@ out: | |||
187 | kfree(events_vector); | 220 | kfree(events_vector); |
188 | return ret; | 221 | return ret; |
189 | } | 222 | } |
190 | 223 | EXPORT_SYMBOL_GPL(wlcore_cmd_wait_for_event_or_timeout); | |
191 | static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) | ||
192 | { | ||
193 | int ret; | ||
194 | bool timeout = false; | ||
195 | |||
196 | ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask, &timeout); | ||
197 | if (ret != 0 || timeout) { | ||
198 | wl12xx_queue_recovery_work(wl); | ||
199 | return ret; | ||
200 | } | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | 224 | ||
205 | int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type, | 225 | int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type, |
206 | u8 *role_id) | 226 | u8 *role_id) |
@@ -278,6 +298,16 @@ out: | |||
278 | return ret; | 298 | return ret; |
279 | } | 299 | } |
280 | 300 | ||
301 | static int wlcore_get_new_session_id(struct wl1271 *wl, u8 hlid) | ||
302 | { | ||
303 | if (wl->session_ids[hlid] >= SESSION_COUNTER_MAX) | ||
304 | wl->session_ids[hlid] = 0; | ||
305 | |||
306 | wl->session_ids[hlid]++; | ||
307 | |||
308 | return wl->session_ids[hlid]; | ||
309 | } | ||
310 | |||
281 | int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) | 311 | int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) |
282 | { | 312 | { |
283 | unsigned long flags; | 313 | unsigned long flags; |
@@ -285,12 +315,21 @@ int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) | |||
285 | if (link >= WL12XX_MAX_LINKS) | 315 | if (link >= WL12XX_MAX_LINKS) |
286 | return -EBUSY; | 316 | return -EBUSY; |
287 | 317 | ||
318 | wl->session_ids[link] = wlcore_get_new_session_id(wl, link); | ||
319 | |||
288 | /* these bits are used by op_tx */ | 320 | /* these bits are used by op_tx */ |
289 | spin_lock_irqsave(&wl->wl_lock, flags); | 321 | spin_lock_irqsave(&wl->wl_lock, flags); |
290 | __set_bit(link, wl->links_map); | 322 | __set_bit(link, wl->links_map); |
291 | __set_bit(link, wlvif->links_map); | 323 | __set_bit(link, wlvif->links_map); |
292 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 324 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
325 | |||
326 | /* take the last "freed packets" value from the current FW status */ | ||
327 | wl->links[link].prev_freed_pkts = | ||
328 | wl->fw_status_2->counters.tx_lnk_free_pkts[link]; | ||
329 | wl->links[link].wlvif = wlvif; | ||
293 | *hlid = link; | 330 | *hlid = link; |
331 | |||
332 | wl->active_link_count++; | ||
294 | return 0; | 333 | return 0; |
295 | } | 334 | } |
296 | 335 | ||
@@ -307,24 +346,21 @@ void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) | |||
307 | __clear_bit(*hlid, wlvif->links_map); | 346 | __clear_bit(*hlid, wlvif->links_map); |
308 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 347 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
309 | 348 | ||
349 | wl->links[*hlid].allocated_pkts = 0; | ||
350 | wl->links[*hlid].prev_freed_pkts = 0; | ||
351 | wl->links[*hlid].ba_bitmap = 0; | ||
352 | memset(wl->links[*hlid].addr, 0, ETH_ALEN); | ||
353 | |||
310 | /* | 354 | /* |
311 | * At this point op_tx() will not add more packets to the queues. We | 355 | * At this point op_tx() will not add more packets to the queues. We |
312 | * can purge them. | 356 | * can purge them. |
313 | */ | 357 | */ |
314 | wl1271_tx_reset_link_queues(wl, *hlid); | 358 | wl1271_tx_reset_link_queues(wl, *hlid); |
359 | wl->links[*hlid].wlvif = NULL; | ||
315 | 360 | ||
316 | *hlid = WL12XX_INVALID_LINK_ID; | 361 | *hlid = WL12XX_INVALID_LINK_ID; |
317 | } | 362 | wl->active_link_count--; |
318 | 363 | WARN_ON_ONCE(wl->active_link_count < 0); | |
319 | static int wl12xx_get_new_session_id(struct wl1271 *wl, | ||
320 | struct wl12xx_vif *wlvif) | ||
321 | { | ||
322 | if (wlvif->session_counter >= SESSION_COUNTER_MAX) | ||
323 | wlvif->session_counter = 0; | ||
324 | |||
325 | wlvif->session_counter++; | ||
326 | |||
327 | return wlvif->session_counter; | ||
328 | } | 364 | } |
329 | 365 | ||
330 | static u8 wlcore_get_native_channel_type(u8 nl_channel_type) | 366 | static u8 wlcore_get_native_channel_type(u8 nl_channel_type) |
@@ -345,7 +381,9 @@ static u8 wlcore_get_native_channel_type(u8 nl_channel_type) | |||
345 | } | 381 | } |
346 | 382 | ||
347 | static int wl12xx_cmd_role_start_dev(struct wl1271 *wl, | 383 | static int wl12xx_cmd_role_start_dev(struct wl1271 *wl, |
348 | struct wl12xx_vif *wlvif) | 384 | struct wl12xx_vif *wlvif, |
385 | enum ieee80211_band band, | ||
386 | int channel) | ||
349 | { | 387 | { |
350 | struct wl12xx_cmd_role_start *cmd; | 388 | struct wl12xx_cmd_role_start *cmd; |
351 | int ret; | 389 | int ret; |
@@ -359,9 +397,9 @@ static int wl12xx_cmd_role_start_dev(struct wl1271 *wl, | |||
359 | wl1271_debug(DEBUG_CMD, "cmd role start dev %d", wlvif->dev_role_id); | 397 | wl1271_debug(DEBUG_CMD, "cmd role start dev %d", wlvif->dev_role_id); |
360 | 398 | ||
361 | cmd->role_id = wlvif->dev_role_id; | 399 | cmd->role_id = wlvif->dev_role_id; |
362 | if (wlvif->band == IEEE80211_BAND_5GHZ) | 400 | if (band == IEEE80211_BAND_5GHZ) |
363 | cmd->band = WLCORE_BAND_5GHZ; | 401 | cmd->band = WLCORE_BAND_5GHZ; |
364 | cmd->channel = wlvif->channel; | 402 | cmd->channel = channel; |
365 | 403 | ||
366 | if (wlvif->dev_hlid == WL12XX_INVALID_LINK_ID) { | 404 | if (wlvif->dev_hlid == WL12XX_INVALID_LINK_ID) { |
367 | ret = wl12xx_allocate_link(wl, wlvif, &wlvif->dev_hlid); | 405 | ret = wl12xx_allocate_link(wl, wlvif, &wlvif->dev_hlid); |
@@ -369,7 +407,7 @@ static int wl12xx_cmd_role_start_dev(struct wl1271 *wl, | |||
369 | goto out_free; | 407 | goto out_free; |
370 | } | 408 | } |
371 | cmd->device.hlid = wlvif->dev_hlid; | 409 | cmd->device.hlid = wlvif->dev_hlid; |
372 | cmd->device.session = wl12xx_get_new_session_id(wl, wlvif); | 410 | cmd->device.session = wl->session_ids[wlvif->dev_hlid]; |
373 | 411 | ||
374 | wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d", | 412 | wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d", |
375 | cmd->role_id, cmd->device.hlid, cmd->device.session); | 413 | cmd->role_id, cmd->device.hlid, cmd->device.session); |
@@ -420,12 +458,6 @@ static int wl12xx_cmd_role_stop_dev(struct wl1271 *wl, | |||
420 | goto out_free; | 458 | goto out_free; |
421 | } | 459 | } |
422 | 460 | ||
423 | ret = wl1271_cmd_wait_for_event(wl, ROLE_STOP_COMPLETE_EVENT_ID); | ||
424 | if (ret < 0) { | ||
425 | wl1271_error("cmd role stop dev event completion error"); | ||
426 | goto out_free; | ||
427 | } | ||
428 | |||
429 | wl12xx_free_link(wl, wlvif, &wlvif->dev_hlid); | 461 | wl12xx_free_link(wl, wlvif, &wlvif->dev_hlid); |
430 | 462 | ||
431 | out_free: | 463 | out_free: |
@@ -439,6 +471,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
439 | { | 471 | { |
440 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); | 472 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); |
441 | struct wl12xx_cmd_role_start *cmd; | 473 | struct wl12xx_cmd_role_start *cmd; |
474 | u32 supported_rates; | ||
442 | int ret; | 475 | int ret; |
443 | 476 | ||
444 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 477 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
@@ -459,7 +492,14 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
459 | cmd->sta.ssid_len = wlvif->ssid_len; | 492 | cmd->sta.ssid_len = wlvif->ssid_len; |
460 | memcpy(cmd->sta.ssid, wlvif->ssid, wlvif->ssid_len); | 493 | memcpy(cmd->sta.ssid, wlvif->ssid, wlvif->ssid_len); |
461 | memcpy(cmd->sta.bssid, vif->bss_conf.bssid, ETH_ALEN); | 494 | memcpy(cmd->sta.bssid, vif->bss_conf.bssid, ETH_ALEN); |
462 | cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set); | 495 | |
496 | supported_rates = CONF_TX_ENABLED_RATES | CONF_TX_MCS_RATES | | ||
497 | wlcore_hw_sta_get_ap_rate_mask(wl, wlvif); | ||
498 | if (wlvif->p2p) | ||
499 | supported_rates &= ~CONF_TX_CCK_RATES; | ||
500 | |||
501 | cmd->sta.local_rates = cpu_to_le32(supported_rates); | ||
502 | |||
463 | cmd->channel_type = wlcore_get_native_channel_type(wlvif->channel_type); | 503 | cmd->channel_type = wlcore_get_native_channel_type(wlvif->channel_type); |
464 | 504 | ||
465 | if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) { | 505 | if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) { |
@@ -468,7 +508,11 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
468 | goto out_free; | 508 | goto out_free; |
469 | } | 509 | } |
470 | cmd->sta.hlid = wlvif->sta.hlid; | 510 | cmd->sta.hlid = wlvif->sta.hlid; |
471 | cmd->sta.session = wl12xx_get_new_session_id(wl, wlvif); | 511 | cmd->sta.session = wl->session_ids[wlvif->sta.hlid]; |
512 | /* | ||
513 | * We don't have the correct remote rates in this stage. the rates | ||
514 | * will be reconfigured later, after authorization. | ||
515 | */ | ||
472 | cmd->sta.remote_rates = cpu_to_le32(wlvif->rate_set); | 516 | cmd->sta.remote_rates = cpu_to_le32(wlvif->rate_set); |
473 | 517 | ||
474 | wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " | 518 | wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " |
@@ -482,6 +526,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
482 | goto err_hlid; | 526 | goto err_hlid; |
483 | } | 527 | } |
484 | 528 | ||
529 | wlvif->sta.role_chan_type = wlvif->channel_type; | ||
485 | goto out_free; | 530 | goto out_free; |
486 | 531 | ||
487 | err_hlid: | 532 | err_hlid: |
@@ -500,7 +545,6 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
500 | { | 545 | { |
501 | struct wl12xx_cmd_role_stop *cmd; | 546 | struct wl12xx_cmd_role_stop *cmd; |
502 | int ret; | 547 | int ret; |
503 | bool timeout = false; | ||
504 | 548 | ||
505 | if (WARN_ON(wlvif->sta.hlid == WL12XX_INVALID_LINK_ID)) | 549 | if (WARN_ON(wlvif->sta.hlid == WL12XX_INVALID_LINK_ID)) |
506 | return -EINVAL; | 550 | return -EINVAL; |
@@ -523,17 +567,6 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
523 | goto out_free; | 567 | goto out_free; |
524 | } | 568 | } |
525 | 569 | ||
526 | /* | ||
527 | * Sometimes the firmware doesn't send this event, so we just | ||
528 | * time out without failing. Queue recovery for other | ||
529 | * failures. | ||
530 | */ | ||
531 | ret = wl1271_cmd_wait_for_event_or_timeout(wl, | ||
532 | ROLE_STOP_COMPLETE_EVENT_ID, | ||
533 | &timeout); | ||
534 | if (ret) | ||
535 | wl12xx_queue_recovery_work(wl); | ||
536 | |||
537 | wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid); | 570 | wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid); |
538 | 571 | ||
539 | out_free: | 572 | out_free: |
@@ -579,12 +612,15 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
579 | cmd->ap.bss_index = WL1271_AP_BSS_INDEX; | 612 | cmd->ap.bss_index = WL1271_AP_BSS_INDEX; |
580 | cmd->ap.global_hlid = wlvif->ap.global_hlid; | 613 | cmd->ap.global_hlid = wlvif->ap.global_hlid; |
581 | cmd->ap.broadcast_hlid = wlvif->ap.bcast_hlid; | 614 | cmd->ap.broadcast_hlid = wlvif->ap.bcast_hlid; |
615 | cmd->ap.global_session_id = wl->session_ids[wlvif->ap.global_hlid]; | ||
616 | cmd->ap.bcast_session_id = wl->session_ids[wlvif->ap.bcast_hlid]; | ||
582 | cmd->ap.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); | 617 | cmd->ap.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); |
583 | cmd->ap.beacon_interval = cpu_to_le16(wlvif->beacon_int); | 618 | cmd->ap.beacon_interval = cpu_to_le16(wlvif->beacon_int); |
584 | cmd->ap.dtim_interval = bss_conf->dtim_period; | 619 | cmd->ap.dtim_interval = bss_conf->dtim_period; |
585 | cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP; | 620 | cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP; |
586 | /* FIXME: Change when adding DFS */ | 621 | /* FIXME: Change when adding DFS */ |
587 | cmd->ap.reset_tsf = 1; /* By default reset AP TSF */ | 622 | cmd->ap.reset_tsf = 1; /* By default reset AP TSF */ |
623 | cmd->ap.wmm = wlvif->wmm_enabled; | ||
588 | cmd->channel = wlvif->channel; | 624 | cmd->channel = wlvif->channel; |
589 | cmd->channel_type = wlcore_get_native_channel_type(wlvif->channel_type); | 625 | cmd->channel_type = wlcore_get_native_channel_type(wlvif->channel_type); |
590 | 626 | ||
@@ -599,8 +635,10 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
599 | memcpy(cmd->ap.ssid, bss_conf->ssid, bss_conf->ssid_len); | 635 | memcpy(cmd->ap.ssid, bss_conf->ssid, bss_conf->ssid_len); |
600 | } | 636 | } |
601 | 637 | ||
602 | supported_rates = CONF_TX_AP_ENABLED_RATES | CONF_TX_MCS_RATES | | 638 | supported_rates = CONF_TX_ENABLED_RATES | CONF_TX_MCS_RATES | |
603 | wlcore_hw_ap_get_mimo_wide_rate_mask(wl, wlvif); | 639 | wlcore_hw_ap_get_mimo_wide_rate_mask(wl, wlvif); |
640 | if (wlvif->p2p) | ||
641 | supported_rates &= ~CONF_TX_CCK_RATES; | ||
604 | 642 | ||
605 | wl1271_debug(DEBUG_CMD, "cmd role start ap with supported_rates 0x%08x", | 643 | wl1271_debug(DEBUG_CMD, "cmd role start ap with supported_rates 0x%08x", |
606 | supported_rates); | 644 | supported_rates); |
@@ -799,8 +837,11 @@ int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len) | |||
799 | * @id: acx id | 837 | * @id: acx id |
800 | * @buf: buffer containing acx, including all headers, must work with dma | 838 | * @buf: buffer containing acx, including all headers, must work with dma |
801 | * @len: length of buf | 839 | * @len: length of buf |
840 | * @valid_rets: bitmap of valid cmd status codes (i.e. return values). | ||
841 | * return the cmd status on success. | ||
802 | */ | 842 | */ |
803 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len) | 843 | int wlcore_cmd_configure_failsafe(struct wl1271 *wl, u16 id, void *buf, |
844 | size_t len, unsigned long valid_rets) | ||
804 | { | 845 | { |
805 | struct acx_header *acx = buf; | 846 | struct acx_header *acx = buf; |
806 | int ret; | 847 | int ret; |
@@ -812,12 +853,26 @@ int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len) | |||
812 | /* payload length, does not include any headers */ | 853 | /* payload length, does not include any headers */ |
813 | acx->len = cpu_to_le16(len - sizeof(*acx)); | 854 | acx->len = cpu_to_le16(len - sizeof(*acx)); |
814 | 855 | ||
815 | ret = wl1271_cmd_send(wl, CMD_CONFIGURE, acx, len, 0); | 856 | ret = wlcore_cmd_send_failsafe(wl, CMD_CONFIGURE, acx, len, 0, |
857 | valid_rets); | ||
816 | if (ret < 0) { | 858 | if (ret < 0) { |
817 | wl1271_warning("CONFIGURE command NOK"); | 859 | wl1271_warning("CONFIGURE command NOK"); |
818 | return ret; | 860 | return ret; |
819 | } | 861 | } |
820 | 862 | ||
863 | return ret; | ||
864 | } | ||
865 | |||
866 | /* | ||
867 | * wrapper for wlcore_cmd_configure that accepts only success status. | ||
868 | * return 0 on success | ||
869 | */ | ||
870 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len) | ||
871 | { | ||
872 | int ret = wlcore_cmd_configure_failsafe(wl, id, buf, len, 0); | ||
873 | |||
874 | if (ret < 0) | ||
875 | return ret; | ||
821 | return 0; | 876 | return 0; |
822 | } | 877 | } |
823 | EXPORT_SYMBOL_GPL(wl1271_cmd_configure); | 878 | EXPORT_SYMBOL_GPL(wl1271_cmd_configure); |
@@ -1034,8 +1089,8 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
1034 | struct sk_buff *skb; | 1089 | struct sk_buff *skb; |
1035 | int ret; | 1090 | int ret; |
1036 | u32 rate; | 1091 | u32 rate; |
1037 | u16 template_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4; | 1092 | u16 template_id_2_4 = wl->scan_templ_id_2_4; |
1038 | u16 template_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5; | 1093 | u16 template_id_5 = wl->scan_templ_id_5; |
1039 | 1094 | ||
1040 | skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len, | 1095 | skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len, |
1041 | ie_len); | 1096 | ie_len); |
@@ -1048,10 +1103,10 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
1048 | 1103 | ||
1049 | wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); | 1104 | wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); |
1050 | 1105 | ||
1051 | if (!sched_scan && | 1106 | if (sched_scan && |
1052 | (wl->quirks & WLCORE_QUIRK_DUAL_PROBE_TMPL)) { | 1107 | (wl->quirks & WLCORE_QUIRK_DUAL_PROBE_TMPL)) { |
1053 | template_id_2_4 = CMD_TEMPL_APP_PROBE_REQ_2_4; | 1108 | template_id_2_4 = wl->sched_scan_templ_id_2_4; |
1054 | template_id_5 = CMD_TEMPL_APP_PROBE_REQ_5; | 1109 | template_id_5 = wl->sched_scan_templ_id_5; |
1055 | } | 1110 | } |
1056 | 1111 | ||
1057 | rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); | 1112 | rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); |
@@ -1068,6 +1123,7 @@ out: | |||
1068 | dev_kfree_skb(skb); | 1123 | dev_kfree_skb(skb); |
1069 | return ret; | 1124 | return ret; |
1070 | } | 1125 | } |
1126 | EXPORT_SYMBOL_GPL(wl12xx_cmd_build_probe_req); | ||
1071 | 1127 | ||
1072 | struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, | 1128 | struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, |
1073 | struct wl12xx_vif *wlvif, | 1129 | struct wl12xx_vif *wlvif, |
@@ -1379,7 +1435,8 @@ out: | |||
1379 | return ret; | 1435 | return ret; |
1380 | } | 1436 | } |
1381 | 1437 | ||
1382 | int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid) | 1438 | int wl12xx_cmd_set_peer_state(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
1439 | u8 hlid) | ||
1383 | { | 1440 | { |
1384 | struct wl12xx_cmd_set_peer_state *cmd; | 1441 | struct wl12xx_cmd_set_peer_state *cmd; |
1385 | int ret = 0; | 1442 | int ret = 0; |
@@ -1395,6 +1452,10 @@ int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid) | |||
1395 | cmd->hlid = hlid; | 1452 | cmd->hlid = hlid; |
1396 | cmd->state = WL1271_CMD_STA_STATE_CONNECTED; | 1453 | cmd->state = WL1271_CMD_STA_STATE_CONNECTED; |
1397 | 1454 | ||
1455 | /* wmm param is valid only for station role */ | ||
1456 | if (wlvif->bss_type == BSS_TYPE_STA_BSS) | ||
1457 | cmd->wmm = wlvif->wmm_enabled; | ||
1458 | |||
1398 | ret = wl1271_cmd_send(wl, CMD_SET_PEER_STATE, cmd, sizeof(*cmd), 0); | 1459 | ret = wl1271_cmd_send(wl, CMD_SET_PEER_STATE, cmd, sizeof(*cmd), 0); |
1399 | if (ret < 0) { | 1460 | if (ret < 0) { |
1400 | wl1271_error("failed to send set peer state command"); | 1461 | wl1271_error("failed to send set peer state command"); |
@@ -1429,6 +1490,7 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
1429 | cmd->hlid = hlid; | 1490 | cmd->hlid = hlid; |
1430 | cmd->sp_len = sta->max_sp; | 1491 | cmd->sp_len = sta->max_sp; |
1431 | cmd->wmm = sta->wme ? 1 : 0; | 1492 | cmd->wmm = sta->wme ? 1 : 0; |
1493 | cmd->session_id = wl->session_ids[hlid]; | ||
1432 | 1494 | ||
1433 | for (i = 0; i < NUM_ACCESS_CATEGORIES_COPY; i++) | 1495 | for (i = 0; i < NUM_ACCESS_CATEGORIES_COPY; i++) |
1434 | if (sta->wme && (sta->uapsd_queues & BIT(i))) | 1496 | if (sta->wme && (sta->uapsd_queues & BIT(i))) |
@@ -1490,9 +1552,10 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid) | |||
1490 | goto out_free; | 1552 | goto out_free; |
1491 | } | 1553 | } |
1492 | 1554 | ||
1493 | ret = wl1271_cmd_wait_for_event_or_timeout(wl, | 1555 | ret = wl->ops->wait_for_event(wl, |
1494 | PEER_REMOVE_COMPLETE_EVENT_ID, | 1556 | WLCORE_EVENT_PEER_REMOVE_COMPLETE, |
1495 | &timeout); | 1557 | &timeout); |
1558 | |||
1496 | /* | 1559 | /* |
1497 | * We are ok with a timeout here. The event is sometimes not sent | 1560 | * We are ok with a timeout here. The event is sometimes not sent |
1498 | * due to a firmware bug. In case of another error (like SDIO timeout) | 1561 | * due to a firmware bug. In case of another error (like SDIO timeout) |
@@ -1508,6 +1571,131 @@ out: | |||
1508 | return ret; | 1571 | return ret; |
1509 | } | 1572 | } |
1510 | 1573 | ||
1574 | static int wlcore_get_reg_conf_ch_idx(enum ieee80211_band band, u16 ch) | ||
1575 | { | ||
1576 | int idx = -1; | ||
1577 | |||
1578 | switch (band) { | ||
1579 | case IEEE80211_BAND_5GHZ: | ||
1580 | if (ch >= 8 && ch <= 16) | ||
1581 | idx = ((ch-8)/4 + 18); | ||
1582 | else if (ch >= 34 && ch <= 64) | ||
1583 | idx = ((ch-34)/2 + 3 + 18); | ||
1584 | else if (ch >= 100 && ch <= 140) | ||
1585 | idx = ((ch-100)/4 + 15 + 18); | ||
1586 | else if (ch >= 149 && ch <= 165) | ||
1587 | idx = ((ch-149)/4 + 26 + 18); | ||
1588 | else | ||
1589 | idx = -1; | ||
1590 | break; | ||
1591 | case IEEE80211_BAND_2GHZ: | ||
1592 | if (ch >= 1 && ch <= 14) | ||
1593 | idx = ch - 1; | ||
1594 | else | ||
1595 | idx = -1; | ||
1596 | break; | ||
1597 | default: | ||
1598 | wl1271_error("get reg conf ch idx - unknown band: %d", | ||
1599 | (int)band); | ||
1600 | } | ||
1601 | |||
1602 | return idx; | ||
1603 | } | ||
1604 | |||
1605 | void wlcore_set_pending_regdomain_ch(struct wl1271 *wl, u16 channel, | ||
1606 | enum ieee80211_band band) | ||
1607 | { | ||
1608 | int ch_bit_idx = 0; | ||
1609 | |||
1610 | if (!(wl->quirks & WLCORE_QUIRK_REGDOMAIN_CONF)) | ||
1611 | return; | ||
1612 | |||
1613 | ch_bit_idx = wlcore_get_reg_conf_ch_idx(band, channel); | ||
1614 | |||
1615 | if (ch_bit_idx > 0 && ch_bit_idx <= WL1271_MAX_CHANNELS) | ||
1616 | set_bit(ch_bit_idx, (long *)wl->reg_ch_conf_pending); | ||
1617 | } | ||
1618 | |||
1619 | int wlcore_cmd_regdomain_config_locked(struct wl1271 *wl) | ||
1620 | { | ||
1621 | struct wl12xx_cmd_regdomain_dfs_config *cmd = NULL; | ||
1622 | int ret = 0, i, b, ch_bit_idx; | ||
1623 | struct ieee80211_channel *channel; | ||
1624 | u32 tmp_ch_bitmap[2]; | ||
1625 | u16 ch; | ||
1626 | struct wiphy *wiphy = wl->hw->wiphy; | ||
1627 | struct ieee80211_supported_band *band; | ||
1628 | bool timeout = false; | ||
1629 | |||
1630 | if (!(wl->quirks & WLCORE_QUIRK_REGDOMAIN_CONF)) | ||
1631 | return 0; | ||
1632 | |||
1633 | wl1271_debug(DEBUG_CMD, "cmd reg domain config"); | ||
1634 | |||
1635 | memset(tmp_ch_bitmap, 0, sizeof(tmp_ch_bitmap)); | ||
1636 | |||
1637 | for (b = IEEE80211_BAND_2GHZ; b <= IEEE80211_BAND_5GHZ; b++) { | ||
1638 | band = wiphy->bands[b]; | ||
1639 | for (i = 0; i < band->n_channels; i++) { | ||
1640 | channel = &band->channels[i]; | ||
1641 | ch = channel->hw_value; | ||
1642 | |||
1643 | if (channel->flags & (IEEE80211_CHAN_DISABLED | | ||
1644 | IEEE80211_CHAN_RADAR | | ||
1645 | IEEE80211_CHAN_PASSIVE_SCAN)) | ||
1646 | continue; | ||
1647 | |||
1648 | ch_bit_idx = wlcore_get_reg_conf_ch_idx(b, ch); | ||
1649 | if (ch_bit_idx < 0) | ||
1650 | continue; | ||
1651 | |||
1652 | set_bit(ch_bit_idx, (long *)tmp_ch_bitmap); | ||
1653 | } | ||
1654 | } | ||
1655 | |||
1656 | tmp_ch_bitmap[0] |= wl->reg_ch_conf_pending[0]; | ||
1657 | tmp_ch_bitmap[1] |= wl->reg_ch_conf_pending[1]; | ||
1658 | |||
1659 | if (!memcmp(tmp_ch_bitmap, wl->reg_ch_conf_last, sizeof(tmp_ch_bitmap))) | ||
1660 | goto out; | ||
1661 | |||
1662 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
1663 | if (!cmd) { | ||
1664 | ret = -ENOMEM; | ||
1665 | goto out; | ||
1666 | } | ||
1667 | |||
1668 | cmd->ch_bit_map1 = cpu_to_le32(tmp_ch_bitmap[0]); | ||
1669 | cmd->ch_bit_map2 = cpu_to_le32(tmp_ch_bitmap[1]); | ||
1670 | |||
1671 | wl1271_debug(DEBUG_CMD, | ||
1672 | "cmd reg domain bitmap1: 0x%08x, bitmap2: 0x%08x", | ||
1673 | cmd->ch_bit_map1, cmd->ch_bit_map2); | ||
1674 | |||
1675 | ret = wl1271_cmd_send(wl, CMD_DFS_CHANNEL_CONFIG, cmd, sizeof(*cmd), 0); | ||
1676 | if (ret < 0) { | ||
1677 | wl1271_error("failed to send reg domain dfs config"); | ||
1678 | goto out; | ||
1679 | } | ||
1680 | |||
1681 | ret = wl->ops->wait_for_event(wl, | ||
1682 | WLCORE_EVENT_DFS_CONFIG_COMPLETE, | ||
1683 | &timeout); | ||
1684 | if (ret < 0 || timeout) { | ||
1685 | wl1271_error("reg domain conf %serror", | ||
1686 | timeout ? "completion " : ""); | ||
1687 | ret = timeout ? -ETIMEDOUT : ret; | ||
1688 | goto out; | ||
1689 | } | ||
1690 | |||
1691 | memcpy(wl->reg_ch_conf_last, tmp_ch_bitmap, sizeof(tmp_ch_bitmap)); | ||
1692 | memset(wl->reg_ch_conf_pending, 0, sizeof(wl->reg_ch_conf_pending)); | ||
1693 | |||
1694 | out: | ||
1695 | kfree(cmd); | ||
1696 | return ret; | ||
1697 | } | ||
1698 | |||
1511 | int wl12xx_cmd_config_fwlog(struct wl1271 *wl) | 1699 | int wl12xx_cmd_config_fwlog(struct wl1271 *wl) |
1512 | { | 1700 | { |
1513 | struct wl12xx_cmd_config_fwlog *cmd; | 1701 | struct wl12xx_cmd_config_fwlog *cmd; |
@@ -1593,12 +1781,12 @@ out: | |||
1593 | } | 1781 | } |
1594 | 1782 | ||
1595 | static int wl12xx_cmd_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 1783 | static int wl12xx_cmd_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
1596 | u8 role_id) | 1784 | u8 role_id, enum ieee80211_band band, u8 channel) |
1597 | { | 1785 | { |
1598 | struct wl12xx_cmd_roc *cmd; | 1786 | struct wl12xx_cmd_roc *cmd; |
1599 | int ret = 0; | 1787 | int ret = 0; |
1600 | 1788 | ||
1601 | wl1271_debug(DEBUG_CMD, "cmd roc %d (%d)", wlvif->channel, role_id); | 1789 | wl1271_debug(DEBUG_CMD, "cmd roc %d (%d)", channel, role_id); |
1602 | 1790 | ||
1603 | if (WARN_ON(role_id == WL12XX_INVALID_ROLE_ID)) | 1791 | if (WARN_ON(role_id == WL12XX_INVALID_ROLE_ID)) |
1604 | return -EINVAL; | 1792 | return -EINVAL; |
@@ -1610,8 +1798,8 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
1610 | } | 1798 | } |
1611 | 1799 | ||
1612 | cmd->role_id = role_id; | 1800 | cmd->role_id = role_id; |
1613 | cmd->channel = wlvif->channel; | 1801 | cmd->channel = channel; |
1614 | switch (wlvif->band) { | 1802 | switch (band) { |
1615 | case IEEE80211_BAND_2GHZ: | 1803 | case IEEE80211_BAND_2GHZ: |
1616 | cmd->band = WLCORE_BAND_2_4GHZ; | 1804 | cmd->band = WLCORE_BAND_2_4GHZ; |
1617 | break; | 1805 | break; |
@@ -1666,30 +1854,18 @@ out: | |||
1666 | return ret; | 1854 | return ret; |
1667 | } | 1855 | } |
1668 | 1856 | ||
1669 | int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id) | 1857 | int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id, |
1858 | enum ieee80211_band band, u8 channel) | ||
1670 | { | 1859 | { |
1671 | int ret = 0; | 1860 | int ret = 0; |
1672 | bool is_first_roc; | ||
1673 | 1861 | ||
1674 | if (WARN_ON(test_bit(role_id, wl->roc_map))) | 1862 | if (WARN_ON(test_bit(role_id, wl->roc_map))) |
1675 | return 0; | 1863 | return 0; |
1676 | 1864 | ||
1677 | is_first_roc = (find_first_bit(wl->roc_map, WL12XX_MAX_ROLES) >= | 1865 | ret = wl12xx_cmd_roc(wl, wlvif, role_id, band, channel); |
1678 | WL12XX_MAX_ROLES); | ||
1679 | |||
1680 | ret = wl12xx_cmd_roc(wl, wlvif, role_id); | ||
1681 | if (ret < 0) | 1866 | if (ret < 0) |
1682 | goto out; | 1867 | goto out; |
1683 | 1868 | ||
1684 | if (is_first_roc) { | ||
1685 | ret = wl1271_cmd_wait_for_event(wl, | ||
1686 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID); | ||
1687 | if (ret < 0) { | ||
1688 | wl1271_error("cmd roc event completion error"); | ||
1689 | goto out; | ||
1690 | } | ||
1691 | } | ||
1692 | |||
1693 | __set_bit(role_id, wl->roc_map); | 1869 | __set_bit(role_id, wl->roc_map); |
1694 | out: | 1870 | out: |
1695 | return ret; | 1871 | return ret; |
@@ -1719,43 +1895,7 @@ out: | |||
1719 | return ret; | 1895 | return ret; |
1720 | } | 1896 | } |
1721 | 1897 | ||
1722 | int wl12xx_cmd_channel_switch(struct wl1271 *wl, | 1898 | int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl, struct wl12xx_vif *wlvif) |
1723 | struct wl12xx_vif *wlvif, | ||
1724 | struct ieee80211_channel_switch *ch_switch) | ||
1725 | { | ||
1726 | struct wl12xx_cmd_channel_switch *cmd; | ||
1727 | int ret; | ||
1728 | |||
1729 | wl1271_debug(DEBUG_ACX, "cmd channel switch"); | ||
1730 | |||
1731 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
1732 | if (!cmd) { | ||
1733 | ret = -ENOMEM; | ||
1734 | goto out; | ||
1735 | } | ||
1736 | |||
1737 | cmd->role_id = wlvif->role_id; | ||
1738 | cmd->channel = ch_switch->channel->hw_value; | ||
1739 | cmd->switch_time = ch_switch->count; | ||
1740 | cmd->stop_tx = ch_switch->block_tx; | ||
1741 | |||
1742 | /* FIXME: control from mac80211 in the future */ | ||
1743 | cmd->post_switch_tx_disable = 0; /* Enable TX on the target channel */ | ||
1744 | |||
1745 | ret = wl1271_cmd_send(wl, CMD_CHANNEL_SWITCH, cmd, sizeof(*cmd), 0); | ||
1746 | if (ret < 0) { | ||
1747 | wl1271_error("failed to send channel switch command"); | ||
1748 | goto out_free; | ||
1749 | } | ||
1750 | |||
1751 | out_free: | ||
1752 | kfree(cmd); | ||
1753 | |||
1754 | out: | ||
1755 | return ret; | ||
1756 | } | ||
1757 | |||
1758 | int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl) | ||
1759 | { | 1899 | { |
1760 | struct wl12xx_cmd_stop_channel_switch *cmd; | 1900 | struct wl12xx_cmd_stop_channel_switch *cmd; |
1761 | int ret; | 1901 | int ret; |
@@ -1768,6 +1908,8 @@ int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl) | |||
1768 | goto out; | 1908 | goto out; |
1769 | } | 1909 | } |
1770 | 1910 | ||
1911 | cmd->role_id = wlvif->role_id; | ||
1912 | |||
1771 | ret = wl1271_cmd_send(wl, CMD_STOP_CHANNEL_SWICTH, cmd, sizeof(*cmd), 0); | 1913 | ret = wl1271_cmd_send(wl, CMD_STOP_CHANNEL_SWICTH, cmd, sizeof(*cmd), 0); |
1772 | if (ret < 0) { | 1914 | if (ret < 0) { |
1773 | wl1271_error("failed to stop channel switch command"); | 1915 | wl1271_error("failed to stop channel switch command"); |
@@ -1782,7 +1924,8 @@ out: | |||
1782 | } | 1924 | } |
1783 | 1925 | ||
1784 | /* start dev role and roc on its channel */ | 1926 | /* start dev role and roc on its channel */ |
1785 | int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) | 1927 | int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
1928 | enum ieee80211_band band, int channel) | ||
1786 | { | 1929 | { |
1787 | int ret; | 1930 | int ret; |
1788 | 1931 | ||
@@ -1797,11 +1940,11 @@ int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
1797 | if (ret < 0) | 1940 | if (ret < 0) |
1798 | goto out; | 1941 | goto out; |
1799 | 1942 | ||
1800 | ret = wl12xx_cmd_role_start_dev(wl, wlvif); | 1943 | ret = wl12xx_cmd_role_start_dev(wl, wlvif, band, channel); |
1801 | if (ret < 0) | 1944 | if (ret < 0) |
1802 | goto out_disable; | 1945 | goto out_disable; |
1803 | 1946 | ||
1804 | ret = wl12xx_roc(wl, wlvif, wlvif->dev_role_id); | 1947 | ret = wl12xx_roc(wl, wlvif, wlvif->dev_role_id, band, channel); |
1805 | if (ret < 0) | 1948 | if (ret < 0) |
1806 | goto out_stop; | 1949 | goto out_stop; |
1807 | 1950 | ||
diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h index 2409f3d71f63..fd34123047cd 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.h +++ b/drivers/net/wireless/ti/wlcore/cmd.h | |||
@@ -31,6 +31,8 @@ struct acx_header; | |||
31 | 31 | ||
32 | int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | 32 | int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, |
33 | size_t res_len); | 33 | size_t res_len); |
34 | int wlcore_cmd_send_failsafe(struct wl1271 *wl, u16 id, void *buf, size_t len, | ||
35 | size_t res_len, unsigned long valid_rets); | ||
34 | int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type, | 36 | int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type, |
35 | u8 *role_id); | 37 | u8 *role_id); |
36 | int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id); | 38 | int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id); |
@@ -39,11 +41,14 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif); | |||
39 | int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 41 | int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
40 | int wl12xx_cmd_role_stop_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 42 | int wl12xx_cmd_role_stop_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
41 | int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 43 | int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
42 | int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 44 | int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
45 | enum ieee80211_band band, int channel); | ||
43 | int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 46 | int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
44 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); | 47 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); |
45 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); | 48 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); |
46 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); | 49 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); |
50 | int wlcore_cmd_configure_failsafe(struct wl1271 *wl, u16 id, void *buf, | ||
51 | size_t len, unsigned long valid_rets); | ||
47 | int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); | 52 | int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); |
48 | int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 53 | int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
49 | u8 ps_mode, u16 auto_ps_timeout); | 54 | u8 ps_mode, u16 auto_ps_timeout); |
@@ -75,22 +80,30 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
75 | u16 action, u8 id, u8 key_type, | 80 | u16 action, u8 id, u8 key_type, |
76 | u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, | 81 | u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, |
77 | u16 tx_seq_16); | 82 | u16 tx_seq_16); |
78 | int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid); | 83 | int wl12xx_cmd_set_peer_state(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
79 | int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id); | 84 | u8 hlid); |
85 | int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id, | ||
86 | enum ieee80211_band band, u8 channel); | ||
80 | int wl12xx_croc(struct wl1271 *wl, u8 role_id); | 87 | int wl12xx_croc(struct wl1271 *wl, u8 role_id); |
81 | int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 88 | int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
82 | struct ieee80211_sta *sta, u8 hlid); | 89 | struct ieee80211_sta *sta, u8 hlid); |
83 | int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid); | 90 | int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid); |
91 | void wlcore_set_pending_regdomain_ch(struct wl1271 *wl, u16 channel, | ||
92 | enum ieee80211_band band); | ||
93 | int wlcore_cmd_regdomain_config_locked(struct wl1271 *wl); | ||
84 | int wl12xx_cmd_config_fwlog(struct wl1271 *wl); | 94 | int wl12xx_cmd_config_fwlog(struct wl1271 *wl); |
85 | int wl12xx_cmd_start_fwlog(struct wl1271 *wl); | 95 | int wl12xx_cmd_start_fwlog(struct wl1271 *wl); |
86 | int wl12xx_cmd_stop_fwlog(struct wl1271 *wl); | 96 | int wl12xx_cmd_stop_fwlog(struct wl1271 *wl); |
87 | int wl12xx_cmd_channel_switch(struct wl1271 *wl, | 97 | int wl12xx_cmd_channel_switch(struct wl1271 *wl, |
88 | struct wl12xx_vif *wlvif, | 98 | struct wl12xx_vif *wlvif, |
89 | struct ieee80211_channel_switch *ch_switch); | 99 | struct ieee80211_channel_switch *ch_switch); |
90 | int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl); | 100 | int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl, |
101 | struct wl12xx_vif *wlvif); | ||
91 | int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 102 | int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
92 | u8 *hlid); | 103 | u8 *hlid); |
93 | void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid); | 104 | void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid); |
105 | int wlcore_cmd_wait_for_event_or_timeout(struct wl1271 *wl, | ||
106 | u32 mask, bool *timeout); | ||
94 | 107 | ||
95 | enum wl1271_commands { | 108 | enum wl1271_commands { |
96 | CMD_INTERROGATE = 1, /* use this to read information elements */ | 109 | CMD_INTERROGATE = 1, /* use this to read information elements */ |
@@ -149,8 +162,11 @@ enum wl1271_commands { | |||
149 | CMD_WFD_START_DISCOVERY = 45, | 162 | CMD_WFD_START_DISCOVERY = 45, |
150 | CMD_WFD_STOP_DISCOVERY = 46, | 163 | CMD_WFD_STOP_DISCOVERY = 46, |
151 | CMD_WFD_ATTRIBUTE_CONFIG = 47, | 164 | CMD_WFD_ATTRIBUTE_CONFIG = 47, |
152 | CMD_NOP = 48, | 165 | CMD_GENERIC_CFG = 48, |
153 | CMD_LAST_COMMAND, | 166 | CMD_NOP = 49, |
167 | |||
168 | /* start of 18xx specific commands */ | ||
169 | CMD_DFS_CHANNEL_CONFIG = 60, | ||
154 | 170 | ||
155 | MAX_COMMAND_ID = 0xFFFF, | 171 | MAX_COMMAND_ID = 0xFFFF, |
156 | }; | 172 | }; |
@@ -167,8 +183,8 @@ enum cmd_templ { | |||
167 | CMD_TEMPL_PS_POLL, | 183 | CMD_TEMPL_PS_POLL, |
168 | CMD_TEMPL_KLV, | 184 | CMD_TEMPL_KLV, |
169 | CMD_TEMPL_DISCONNECT, | 185 | CMD_TEMPL_DISCONNECT, |
170 | CMD_TEMPL_APP_PROBE_REQ_2_4, | 186 | CMD_TEMPL_APP_PROBE_REQ_2_4_LEGACY, |
171 | CMD_TEMPL_APP_PROBE_REQ_5, | 187 | CMD_TEMPL_APP_PROBE_REQ_5_LEGACY, |
172 | CMD_TEMPL_BAR, /* for firmware internal use only */ | 188 | CMD_TEMPL_BAR, /* for firmware internal use only */ |
173 | CMD_TEMPL_CTS, /* | 189 | CMD_TEMPL_CTS, /* |
174 | * For CTS-to-self (FastCTS) mechanism | 190 | * For CTS-to-self (FastCTS) mechanism |
@@ -179,6 +195,8 @@ enum cmd_templ { | |||
179 | CMD_TEMPL_DEAUTH_AP, | 195 | CMD_TEMPL_DEAUTH_AP, |
180 | CMD_TEMPL_TEMPORARY, | 196 | CMD_TEMPL_TEMPORARY, |
181 | CMD_TEMPL_LINK_MEASUREMENT_REPORT, | 197 | CMD_TEMPL_LINK_MEASUREMENT_REPORT, |
198 | CMD_TEMPL_PROBE_REQ_2_4_PERIODIC, | ||
199 | CMD_TEMPL_PROBE_REQ_5_PERIODIC, | ||
182 | 200 | ||
183 | CMD_TEMPL_MAX = 0xff | 201 | CMD_TEMPL_MAX = 0xff |
184 | }; | 202 | }; |
@@ -220,7 +238,8 @@ enum { | |||
220 | CMD_STATUS_FW_RESET = 22, /* Driver internal use.*/ | 238 | CMD_STATUS_FW_RESET = 22, /* Driver internal use.*/ |
221 | CMD_STATUS_TEMPLATE_OOM = 23, | 239 | CMD_STATUS_TEMPLATE_OOM = 23, |
222 | CMD_STATUS_NO_RX_BA_SESSION = 24, | 240 | CMD_STATUS_NO_RX_BA_SESSION = 24, |
223 | MAX_COMMAND_STATUS = 0xff | 241 | |
242 | MAX_COMMAND_STATUS | ||
224 | }; | 243 | }; |
225 | 244 | ||
226 | #define CMDMBOX_HEADER_LEN 4 | 245 | #define CMDMBOX_HEADER_LEN 4 |
@@ -345,7 +364,15 @@ struct wl12xx_cmd_role_start { | |||
345 | 364 | ||
346 | u8 reset_tsf; | 365 | u8 reset_tsf; |
347 | 366 | ||
348 | u8 padding_1[4]; | 367 | /* |
368 | * ap supports wmm (note that there is additional | ||
369 | * per-sta wmm configuration) | ||
370 | */ | ||
371 | u8 wmm; | ||
372 | |||
373 | u8 bcast_session_id; | ||
374 | u8 global_session_id; | ||
375 | u8 padding_1[1]; | ||
349 | } __packed ap; | 376 | } __packed ap; |
350 | }; | 377 | }; |
351 | } __packed; | 378 | } __packed; |
@@ -515,7 +542,14 @@ struct wl12xx_cmd_set_peer_state { | |||
515 | 542 | ||
516 | u8 hlid; | 543 | u8 hlid; |
517 | u8 state; | 544 | u8 state; |
518 | u8 padding[2]; | 545 | |
546 | /* | ||
547 | * wmm is relevant for sta role only. | ||
548 | * ap role configures the per-sta wmm params in | ||
549 | * the add_peer command. | ||
550 | */ | ||
551 | u8 wmm; | ||
552 | u8 padding[1]; | ||
519 | } __packed; | 553 | } __packed; |
520 | 554 | ||
521 | struct wl12xx_cmd_roc { | 555 | struct wl12xx_cmd_roc { |
@@ -558,7 +592,7 @@ struct wl12xx_cmd_add_peer { | |||
558 | u8 bss_index; | 592 | u8 bss_index; |
559 | u8 sp_len; | 593 | u8 sp_len; |
560 | u8 wmm; | 594 | u8 wmm; |
561 | u8 padding1; | 595 | u8 session_id; |
562 | } __packed; | 596 | } __packed; |
563 | 597 | ||
564 | struct wl12xx_cmd_remove_peer { | 598 | struct wl12xx_cmd_remove_peer { |
@@ -597,6 +631,13 @@ enum wl12xx_fwlogger_output { | |||
597 | WL12XX_FWLOG_OUTPUT_HOST, | 631 | WL12XX_FWLOG_OUTPUT_HOST, |
598 | }; | 632 | }; |
599 | 633 | ||
634 | struct wl12xx_cmd_regdomain_dfs_config { | ||
635 | struct wl1271_cmd_header header; | ||
636 | |||
637 | __le32 ch_bit_map1; | ||
638 | __le32 ch_bit_map2; | ||
639 | } __packed; | ||
640 | |||
600 | struct wl12xx_cmd_config_fwlog { | 641 | struct wl12xx_cmd_config_fwlog { |
601 | struct wl1271_cmd_header header; | 642 | struct wl1271_cmd_header header; |
602 | 643 | ||
@@ -626,27 +667,13 @@ struct wl12xx_cmd_stop_fwlog { | |||
626 | struct wl1271_cmd_header header; | 667 | struct wl1271_cmd_header header; |
627 | } __packed; | 668 | } __packed; |
628 | 669 | ||
629 | struct wl12xx_cmd_channel_switch { | 670 | struct wl12xx_cmd_stop_channel_switch { |
630 | struct wl1271_cmd_header header; | 671 | struct wl1271_cmd_header header; |
631 | 672 | ||
632 | u8 role_id; | 673 | u8 role_id; |
633 | |||
634 | /* The new serving channel */ | ||
635 | u8 channel; | ||
636 | /* Relative time of the serving channel switch in TBTT units */ | ||
637 | u8 switch_time; | ||
638 | /* Stop the role TX, should expect it after radar detection */ | ||
639 | u8 stop_tx; | ||
640 | /* The target channel tx status 1-stopped 0-open*/ | ||
641 | u8 post_switch_tx_disable; | ||
642 | |||
643 | u8 padding[3]; | 674 | u8 padding[3]; |
644 | } __packed; | 675 | } __packed; |
645 | 676 | ||
646 | struct wl12xx_cmd_stop_channel_switch { | ||
647 | struct wl1271_cmd_header header; | ||
648 | } __packed; | ||
649 | |||
650 | /* Used to check radio status after calibration */ | 677 | /* Used to check radio status after calibration */ |
651 | #define MAX_TLV_LENGTH 500 | 678 | #define MAX_TLV_LENGTH 500 |
652 | #define TEST_CMD_P2G_CAL 2 /* TX BiP */ | 679 | #define TEST_CMD_P2G_CAL 2 /* TX BiP */ |
diff --git a/drivers/net/wireless/ti/wlcore/conf.h b/drivers/net/wireless/ti/wlcore/conf.h index 9e40760bafe1..2b96ff821341 100644 --- a/drivers/net/wireless/ti/wlcore/conf.h +++ b/drivers/net/wireless/ti/wlcore/conf.h | |||
@@ -57,20 +57,49 @@ enum { | |||
57 | }; | 57 | }; |
58 | 58 | ||
59 | enum { | 59 | enum { |
60 | CONF_HW_RATE_INDEX_1MBPS = 0, | 60 | CONF_HW_RATE_INDEX_1MBPS = 0, |
61 | CONF_HW_RATE_INDEX_2MBPS = 1, | 61 | CONF_HW_RATE_INDEX_2MBPS = 1, |
62 | CONF_HW_RATE_INDEX_5_5MBPS = 2, | 62 | CONF_HW_RATE_INDEX_5_5MBPS = 2, |
63 | CONF_HW_RATE_INDEX_6MBPS = 3, | 63 | CONF_HW_RATE_INDEX_11MBPS = 3, |
64 | CONF_HW_RATE_INDEX_9MBPS = 4, | 64 | CONF_HW_RATE_INDEX_6MBPS = 4, |
65 | CONF_HW_RATE_INDEX_11MBPS = 5, | 65 | CONF_HW_RATE_INDEX_9MBPS = 5, |
66 | CONF_HW_RATE_INDEX_12MBPS = 6, | 66 | CONF_HW_RATE_INDEX_12MBPS = 6, |
67 | CONF_HW_RATE_INDEX_18MBPS = 7, | 67 | CONF_HW_RATE_INDEX_18MBPS = 7, |
68 | CONF_HW_RATE_INDEX_22MBPS = 8, | 68 | CONF_HW_RATE_INDEX_24MBPS = 8, |
69 | CONF_HW_RATE_INDEX_24MBPS = 9, | 69 | CONF_HW_RATE_INDEX_36MBPS = 9, |
70 | CONF_HW_RATE_INDEX_36MBPS = 10, | 70 | CONF_HW_RATE_INDEX_48MBPS = 10, |
71 | CONF_HW_RATE_INDEX_48MBPS = 11, | 71 | CONF_HW_RATE_INDEX_54MBPS = 11, |
72 | CONF_HW_RATE_INDEX_54MBPS = 12, | 72 | CONF_HW_RATE_INDEX_MCS0 = 12, |
73 | CONF_HW_RATE_INDEX_MAX = CONF_HW_RATE_INDEX_54MBPS, | 73 | CONF_HW_RATE_INDEX_MCS1 = 13, |
74 | CONF_HW_RATE_INDEX_MCS2 = 14, | ||
75 | CONF_HW_RATE_INDEX_MCS3 = 15, | ||
76 | CONF_HW_RATE_INDEX_MCS4 = 16, | ||
77 | CONF_HW_RATE_INDEX_MCS5 = 17, | ||
78 | CONF_HW_RATE_INDEX_MCS6 = 18, | ||
79 | CONF_HW_RATE_INDEX_MCS7 = 19, | ||
80 | CONF_HW_RATE_INDEX_MCS7_SGI = 20, | ||
81 | CONF_HW_RATE_INDEX_MCS0_40MHZ = 21, | ||
82 | CONF_HW_RATE_INDEX_MCS1_40MHZ = 22, | ||
83 | CONF_HW_RATE_INDEX_MCS2_40MHZ = 23, | ||
84 | CONF_HW_RATE_INDEX_MCS3_40MHZ = 24, | ||
85 | CONF_HW_RATE_INDEX_MCS4_40MHZ = 25, | ||
86 | CONF_HW_RATE_INDEX_MCS5_40MHZ = 26, | ||
87 | CONF_HW_RATE_INDEX_MCS6_40MHZ = 27, | ||
88 | CONF_HW_RATE_INDEX_MCS7_40MHZ = 28, | ||
89 | CONF_HW_RATE_INDEX_MCS7_40MHZ_SGI = 29, | ||
90 | |||
91 | /* MCS8+ rates overlap with 40Mhz rates */ | ||
92 | CONF_HW_RATE_INDEX_MCS8 = 21, | ||
93 | CONF_HW_RATE_INDEX_MCS9 = 22, | ||
94 | CONF_HW_RATE_INDEX_MCS10 = 23, | ||
95 | CONF_HW_RATE_INDEX_MCS11 = 24, | ||
96 | CONF_HW_RATE_INDEX_MCS12 = 25, | ||
97 | CONF_HW_RATE_INDEX_MCS13 = 26, | ||
98 | CONF_HW_RATE_INDEX_MCS14 = 27, | ||
99 | CONF_HW_RATE_INDEX_MCS15 = 28, | ||
100 | CONF_HW_RATE_INDEX_MCS15_SGI = 29, | ||
101 | |||
102 | CONF_HW_RATE_INDEX_MAX = CONF_HW_RATE_INDEX_MCS7_40MHZ_SGI, | ||
74 | }; | 103 | }; |
75 | 104 | ||
76 | #define CONF_HW_RXTX_RATE_UNSUPPORTED 0xff | 105 | #define CONF_HW_RXTX_RATE_UNSUPPORTED 0xff |
@@ -415,11 +444,11 @@ struct conf_rx_settings { | |||
415 | #define CONF_TX_RATE_MASK_BASIC_P2P CONF_HW_BIT_RATE_6MBPS | 444 | #define CONF_TX_RATE_MASK_BASIC_P2P CONF_HW_BIT_RATE_6MBPS |
416 | 445 | ||
417 | /* | 446 | /* |
418 | * Rates supported for data packets when operating as AP. Note the absence | 447 | * Rates supported for data packets when operating as STA/AP. Note the absence |
419 | * of the 22Mbps rate. There is a FW limitation on 12 rates so we must drop | 448 | * of the 22Mbps rate. There is a FW limitation on 12 rates so we must drop |
420 | * one. The rate dropped is not mandatory under any operating mode. | 449 | * one. The rate dropped is not mandatory under any operating mode. |
421 | */ | 450 | */ |
422 | #define CONF_TX_AP_ENABLED_RATES (CONF_HW_BIT_RATE_1MBPS | \ | 451 | #define CONF_TX_ENABLED_RATES (CONF_HW_BIT_RATE_1MBPS | \ |
423 | CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | \ | 452 | CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | \ |
424 | CONF_HW_BIT_RATE_6MBPS | CONF_HW_BIT_RATE_9MBPS | \ | 453 | CONF_HW_BIT_RATE_6MBPS | CONF_HW_BIT_RATE_9MBPS | \ |
425 | CONF_HW_BIT_RATE_11MBPS | CONF_HW_BIT_RATE_12MBPS | \ | 454 | CONF_HW_BIT_RATE_11MBPS | CONF_HW_BIT_RATE_12MBPS | \ |
@@ -677,6 +706,18 @@ struct conf_tx_settings { | |||
677 | 706 | ||
678 | /* Time in ms for Tx watchdog timer to expire */ | 707 | /* Time in ms for Tx watchdog timer to expire */ |
679 | u32 tx_watchdog_timeout; | 708 | u32 tx_watchdog_timeout; |
709 | |||
710 | /* | ||
711 | * when a slow link has this much packets pending, it becomes a low | ||
712 | * priority link, scheduling-wise | ||
713 | */ | ||
714 | u8 slow_link_thold; | ||
715 | |||
716 | /* | ||
717 | * when a fast link has this much packets pending, it becomes a low | ||
718 | * priority link, scheduling-wise | ||
719 | */ | ||
720 | u8 fast_link_thold; | ||
680 | } __packed; | 721 | } __packed; |
681 | 722 | ||
682 | enum { | 723 | enum { |
@@ -1047,6 +1088,7 @@ struct conf_roam_trigger_settings { | |||
1047 | struct conf_scan_settings { | 1088 | struct conf_scan_settings { |
1048 | /* | 1089 | /* |
1049 | * The minimum time to wait on each channel for active scans | 1090 | * The minimum time to wait on each channel for active scans |
1091 | * This value will be used whenever there's a connected interface. | ||
1050 | * | 1092 | * |
1051 | * Range: u32 tu/1000 | 1093 | * Range: u32 tu/1000 |
1052 | */ | 1094 | */ |
@@ -1054,24 +1096,37 @@ struct conf_scan_settings { | |||
1054 | 1096 | ||
1055 | /* | 1097 | /* |
1056 | * The maximum time to wait on each channel for active scans | 1098 | * The maximum time to wait on each channel for active scans |
1099 | * This value will be currently used whenever there's a | ||
1100 | * connected interface. It shouldn't exceed 30000 (~30ms) to avoid | ||
1101 | * possible interference of voip traffic going on while scanning. | ||
1057 | * | 1102 | * |
1058 | * Range: u32 tu/1000 | 1103 | * Range: u32 tu/1000 |
1059 | */ | 1104 | */ |
1060 | u32 max_dwell_time_active; | 1105 | u32 max_dwell_time_active; |
1061 | 1106 | ||
1062 | /* | 1107 | /* The minimum time to wait on each channel for active scans |
1063 | * The minimum time to wait on each channel for passive scans | 1108 | * when it's possible to have longer scan dwell times. |
1109 | * Currently this is used whenever we're idle on all interfaces. | ||
1110 | * Longer dwell times improve detection of networks within a | ||
1111 | * single scan. | ||
1064 | * | 1112 | * |
1065 | * Range: u32 tu/1000 | 1113 | * Range: u32 tu/1000 |
1066 | */ | 1114 | */ |
1067 | u32 min_dwell_time_passive; | 1115 | u32 min_dwell_time_active_long; |
1068 | 1116 | ||
1069 | /* | 1117 | /* The maximum time to wait on each channel for active scans |
1070 | * The maximum time to wait on each channel for passive scans | 1118 | * when it's possible to have longer scan dwell times. |
1119 | * See min_dwell_time_active_long | ||
1071 | * | 1120 | * |
1072 | * Range: u32 tu/1000 | 1121 | * Range: u32 tu/1000 |
1073 | */ | 1122 | */ |
1074 | u32 max_dwell_time_passive; | 1123 | u32 max_dwell_time_active_long; |
1124 | |||
1125 | /* time to wait on the channel for passive scans (in TU/1000) */ | ||
1126 | u32 dwell_time_passive; | ||
1127 | |||
1128 | /* time to wait on the channel for DFS scans (in TU/1000) */ | ||
1129 | u32 dwell_time_dfs; | ||
1075 | 1130 | ||
1076 | /* | 1131 | /* |
1077 | * Number of probe requests to transmit on each active scan channel | 1132 | * Number of probe requests to transmit on each active scan channel |
@@ -1276,12 +1331,20 @@ struct conf_hangover_settings { | |||
1276 | u8 window_size; | 1331 | u8 window_size; |
1277 | } __packed; | 1332 | } __packed; |
1278 | 1333 | ||
1334 | struct conf_recovery_settings { | ||
1335 | /* BUG() on fw recovery */ | ||
1336 | u8 bug_on_recovery; | ||
1337 | |||
1338 | /* Prevent HW recovery. FW will remain stuck. */ | ||
1339 | u8 no_recovery; | ||
1340 | } __packed; | ||
1341 | |||
1279 | /* | 1342 | /* |
1280 | * The conf version consists of 4 bytes. The two MSB are the wlcore | 1343 | * The conf version consists of 4 bytes. The two MSB are the wlcore |
1281 | * version, the two LSB are the lower driver's private conf | 1344 | * version, the two LSB are the lower driver's private conf |
1282 | * version. | 1345 | * version. |
1283 | */ | 1346 | */ |
1284 | #define WLCORE_CONF_VERSION (0x0002 << 16) | 1347 | #define WLCORE_CONF_VERSION (0x0005 << 16) |
1285 | #define WLCORE_CONF_MASK 0xffff0000 | 1348 | #define WLCORE_CONF_MASK 0xffff0000 |
1286 | #define WLCORE_CONF_SIZE (sizeof(struct wlcore_conf_header) + \ | 1349 | #define WLCORE_CONF_SIZE (sizeof(struct wlcore_conf_header) + \ |
1287 | sizeof(struct wlcore_conf)) | 1350 | sizeof(struct wlcore_conf)) |
@@ -1309,6 +1372,7 @@ struct wlcore_conf { | |||
1309 | struct conf_fwlog fwlog; | 1372 | struct conf_fwlog fwlog; |
1310 | struct conf_rate_policy_settings rate; | 1373 | struct conf_rate_policy_settings rate; |
1311 | struct conf_hangover_settings hangover; | 1374 | struct conf_hangover_settings hangover; |
1375 | struct conf_recovery_settings recovery; | ||
1312 | } __packed; | 1376 | } __packed; |
1313 | 1377 | ||
1314 | struct wlcore_conf_file { | 1378 | struct wlcore_conf_file { |
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c index c86bb00c2488..e70a7c864865 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.c +++ b/drivers/net/wireless/ti/wlcore/debugfs.c | |||
@@ -490,7 +490,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, | |||
490 | DRIVER_STATE_PRINT_HEX(chip.id); | 490 | DRIVER_STATE_PRINT_HEX(chip.id); |
491 | DRIVER_STATE_PRINT_STR(chip.fw_ver_str); | 491 | DRIVER_STATE_PRINT_STR(chip.fw_ver_str); |
492 | DRIVER_STATE_PRINT_STR(chip.phy_fw_ver_str); | 492 | DRIVER_STATE_PRINT_STR(chip.phy_fw_ver_str); |
493 | DRIVER_STATE_PRINT_INT(sched_scanning); | 493 | DRIVER_STATE_PRINT_INT(recovery_count); |
494 | 494 | ||
495 | #undef DRIVER_STATE_PRINT_INT | 495 | #undef DRIVER_STATE_PRINT_INT |
496 | #undef DRIVER_STATE_PRINT_LONG | 496 | #undef DRIVER_STATE_PRINT_LONG |
@@ -560,7 +560,6 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf, | |||
560 | if (wlvif->bss_type == BSS_TYPE_STA_BSS || | 560 | if (wlvif->bss_type == BSS_TYPE_STA_BSS || |
561 | wlvif->bss_type == BSS_TYPE_IBSS) { | 561 | wlvif->bss_type == BSS_TYPE_IBSS) { |
562 | VIF_STATE_PRINT_INT(sta.hlid); | 562 | VIF_STATE_PRINT_INT(sta.hlid); |
563 | VIF_STATE_PRINT_INT(sta.ba_rx_bitmap); | ||
564 | VIF_STATE_PRINT_INT(sta.basic_rate_idx); | 563 | VIF_STATE_PRINT_INT(sta.basic_rate_idx); |
565 | VIF_STATE_PRINT_INT(sta.ap_rate_idx); | 564 | VIF_STATE_PRINT_INT(sta.ap_rate_idx); |
566 | VIF_STATE_PRINT_INT(sta.p2p_rate_idx); | 565 | VIF_STATE_PRINT_INT(sta.p2p_rate_idx); |
@@ -577,6 +576,10 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf, | |||
577 | VIF_STATE_PRINT_INT(ap.ucast_rate_idx[3]); | 576 | VIF_STATE_PRINT_INT(ap.ucast_rate_idx[3]); |
578 | } | 577 | } |
579 | VIF_STATE_PRINT_INT(last_tx_hlid); | 578 | VIF_STATE_PRINT_INT(last_tx_hlid); |
579 | VIF_STATE_PRINT_INT(tx_queue_count[0]); | ||
580 | VIF_STATE_PRINT_INT(tx_queue_count[1]); | ||
581 | VIF_STATE_PRINT_INT(tx_queue_count[2]); | ||
582 | VIF_STATE_PRINT_INT(tx_queue_count[3]); | ||
580 | VIF_STATE_PRINT_LHEX(links_map[0]); | 583 | VIF_STATE_PRINT_LHEX(links_map[0]); |
581 | VIF_STATE_PRINT_NSTR(ssid, wlvif->ssid_len); | 584 | VIF_STATE_PRINT_NSTR(ssid, wlvif->ssid_len); |
582 | VIF_STATE_PRINT_INT(band); | 585 | VIF_STATE_PRINT_INT(band); |
@@ -589,7 +592,6 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf, | |||
589 | VIF_STATE_PRINT_INT(beacon_int); | 592 | VIF_STATE_PRINT_INT(beacon_int); |
590 | VIF_STATE_PRINT_INT(default_key); | 593 | VIF_STATE_PRINT_INT(default_key); |
591 | VIF_STATE_PRINT_INT(aid); | 594 | VIF_STATE_PRINT_INT(aid); |
592 | VIF_STATE_PRINT_INT(session_counter); | ||
593 | VIF_STATE_PRINT_INT(psm_entry_retry); | 595 | VIF_STATE_PRINT_INT(psm_entry_retry); |
594 | VIF_STATE_PRINT_INT(power_level); | 596 | VIF_STATE_PRINT_INT(power_level); |
595 | VIF_STATE_PRINT_INT(rssi_thold); | 597 | VIF_STATE_PRINT_INT(rssi_thold); |
@@ -993,7 +995,7 @@ static ssize_t sleep_auth_write(struct file *file, | |||
993 | return -EINVAL; | 995 | return -EINVAL; |
994 | } | 996 | } |
995 | 997 | ||
996 | if (value < 0 || value > WL1271_PSM_MAX) { | 998 | if (value > WL1271_PSM_MAX) { |
997 | wl1271_warning("sleep_auth must be between 0 and %d", | 999 | wl1271_warning("sleep_auth must be between 0 and %d", |
998 | WL1271_PSM_MAX); | 1000 | WL1271_PSM_MAX); |
999 | return -ERANGE; | 1001 | return -ERANGE; |
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index 48907054d493..70f289aa1bc6 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c | |||
@@ -29,34 +29,39 @@ | |||
29 | #include "scan.h" | 29 | #include "scan.h" |
30 | #include "wl12xx_80211.h" | 30 | #include "wl12xx_80211.h" |
31 | 31 | ||
32 | static void wl1271_event_rssi_trigger(struct wl1271 *wl, | 32 | void wlcore_event_rssi_trigger(struct wl1271 *wl, s8 *metric_arr) |
33 | struct wl12xx_vif *wlvif, | ||
34 | struct event_mailbox *mbox) | ||
35 | { | 33 | { |
36 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); | 34 | struct wl12xx_vif *wlvif; |
35 | struct ieee80211_vif *vif; | ||
37 | enum nl80211_cqm_rssi_threshold_event event; | 36 | enum nl80211_cqm_rssi_threshold_event event; |
38 | s8 metric = mbox->rssi_snr_trigger_metric[0]; | 37 | s8 metric = metric_arr[0]; |
39 | 38 | ||
40 | wl1271_debug(DEBUG_EVENT, "RSSI trigger metric: %d", metric); | 39 | wl1271_debug(DEBUG_EVENT, "RSSI trigger metric: %d", metric); |
41 | 40 | ||
42 | if (metric <= wlvif->rssi_thold) | 41 | /* TODO: check actual multi-role support */ |
43 | event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW; | 42 | wl12xx_for_each_wlvif_sta(wl, wlvif) { |
44 | else | 43 | if (metric <= wlvif->rssi_thold) |
45 | event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; | 44 | event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW; |
46 | 45 | else | |
47 | if (event != wlvif->last_rssi_event) | 46 | event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; |
48 | ieee80211_cqm_rssi_notify(vif, event, GFP_KERNEL); | 47 | |
49 | wlvif->last_rssi_event = event; | 48 | vif = wl12xx_wlvif_to_vif(wlvif); |
49 | if (event != wlvif->last_rssi_event) | ||
50 | ieee80211_cqm_rssi_notify(vif, event, GFP_KERNEL); | ||
51 | wlvif->last_rssi_event = event; | ||
52 | } | ||
50 | } | 53 | } |
54 | EXPORT_SYMBOL_GPL(wlcore_event_rssi_trigger); | ||
51 | 55 | ||
52 | static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif) | 56 | static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif) |
53 | { | 57 | { |
54 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); | 58 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); |
55 | 59 | ||
56 | if (wlvif->bss_type != BSS_TYPE_AP_BSS) { | 60 | if (wlvif->bss_type != BSS_TYPE_AP_BSS) { |
57 | if (!wlvif->sta.ba_rx_bitmap) | 61 | u8 hlid = wlvif->sta.hlid; |
62 | if (!wl->links[hlid].ba_bitmap) | ||
58 | return; | 63 | return; |
59 | ieee80211_stop_rx_ba_session(vif, wlvif->sta.ba_rx_bitmap, | 64 | ieee80211_stop_rx_ba_session(vif, wl->links[hlid].ba_bitmap, |
60 | vif->bss_conf.bssid); | 65 | vif->bss_conf.bssid); |
61 | } else { | 66 | } else { |
62 | u8 hlid; | 67 | u8 hlid; |
@@ -74,8 +79,7 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
74 | } | 79 | } |
75 | } | 80 | } |
76 | 81 | ||
77 | static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl, | 82 | void wlcore_event_soft_gemini_sense(struct wl1271 *wl, u8 enable) |
78 | u8 enable) | ||
79 | { | 83 | { |
80 | struct wl12xx_vif *wlvif; | 84 | struct wl12xx_vif *wlvif; |
81 | 85 | ||
@@ -87,201 +91,169 @@ static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl, | |||
87 | wl1271_recalc_rx_streaming(wl, wlvif); | 91 | wl1271_recalc_rx_streaming(wl, wlvif); |
88 | } | 92 | } |
89 | } | 93 | } |
90 | |||
91 | } | 94 | } |
95 | EXPORT_SYMBOL_GPL(wlcore_event_soft_gemini_sense); | ||
92 | 96 | ||
93 | static void wl1271_event_mbox_dump(struct event_mailbox *mbox) | 97 | void wlcore_event_sched_scan_completed(struct wl1271 *wl, |
98 | u8 status) | ||
94 | { | 99 | { |
95 | wl1271_debug(DEBUG_EVENT, "MBOX DUMP:"); | 100 | wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_COMPLETE_EVENT (status 0x%0x)", |
96 | wl1271_debug(DEBUG_EVENT, "\tvector: 0x%x", mbox->events_vector); | 101 | status); |
97 | wl1271_debug(DEBUG_EVENT, "\tmask: 0x%x", mbox->events_mask); | 102 | |
103 | if (wl->sched_vif) { | ||
104 | ieee80211_sched_scan_stopped(wl->hw); | ||
105 | wl->sched_vif = NULL; | ||
106 | } | ||
98 | } | 107 | } |
108 | EXPORT_SYMBOL_GPL(wlcore_event_sched_scan_completed); | ||
99 | 109 | ||
100 | static int wl1271_event_process(struct wl1271 *wl) | 110 | void wlcore_event_ba_rx_constraint(struct wl1271 *wl, |
111 | unsigned long roles_bitmap, | ||
112 | unsigned long allowed_bitmap) | ||
101 | { | 113 | { |
102 | struct event_mailbox *mbox = wl->mbox; | ||
103 | struct ieee80211_vif *vif; | ||
104 | struct wl12xx_vif *wlvif; | 114 | struct wl12xx_vif *wlvif; |
105 | u32 vector; | ||
106 | bool disconnect_sta = false; | ||
107 | unsigned long sta_bitmap = 0; | ||
108 | int ret; | ||
109 | |||
110 | wl1271_event_mbox_dump(mbox); | ||
111 | |||
112 | vector = le32_to_cpu(mbox->events_vector); | ||
113 | vector &= ~(le32_to_cpu(mbox->events_mask)); | ||
114 | wl1271_debug(DEBUG_EVENT, "vector: 0x%x", vector); | ||
115 | 115 | ||
116 | if (vector & SCAN_COMPLETE_EVENT_ID) { | 116 | wl1271_debug(DEBUG_EVENT, "%s: roles=0x%lx allowed=0x%lx", |
117 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", | 117 | __func__, roles_bitmap, allowed_bitmap); |
118 | mbox->scheduled_scan_status); | ||
119 | |||
120 | wl1271_scan_stm(wl, wl->scan_vif); | ||
121 | } | ||
122 | 118 | ||
123 | if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) { | 119 | wl12xx_for_each_wlvif(wl, wlvif) { |
124 | wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_REPORT_EVENT " | 120 | if (wlvif->role_id == WL12XX_INVALID_ROLE_ID || |
125 | "(status 0x%0x)", mbox->scheduled_scan_status); | 121 | !test_bit(wlvif->role_id , &roles_bitmap)) |
122 | continue; | ||
126 | 123 | ||
127 | wl1271_scan_sched_scan_results(wl); | 124 | wlvif->ba_allowed = !!test_bit(wlvif->role_id, |
125 | &allowed_bitmap); | ||
126 | if (!wlvif->ba_allowed) | ||
127 | wl1271_stop_ba_event(wl, wlvif); | ||
128 | } | 128 | } |
129 | } | ||
130 | EXPORT_SYMBOL_GPL(wlcore_event_ba_rx_constraint); | ||
129 | 131 | ||
130 | if (vector & PERIODIC_SCAN_COMPLETE_EVENT_ID) { | 132 | void wlcore_event_channel_switch(struct wl1271 *wl, |
131 | wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_COMPLETE_EVENT " | 133 | unsigned long roles_bitmap, |
132 | "(status 0x%0x)", mbox->scheduled_scan_status); | 134 | bool success) |
133 | if (wl->sched_scanning) { | 135 | { |
134 | ieee80211_sched_scan_stopped(wl->hw); | 136 | struct wl12xx_vif *wlvif; |
135 | wl->sched_scanning = false; | 137 | struct ieee80211_vif *vif; |
136 | } | ||
137 | } | ||
138 | 138 | ||
139 | if (vector & SOFT_GEMINI_SENSE_EVENT_ID) | 139 | wl1271_debug(DEBUG_EVENT, "%s: roles=0x%lx success=%d", |
140 | wl12xx_event_soft_gemini_sense(wl, | 140 | __func__, roles_bitmap, success); |
141 | mbox->soft_gemini_sense_info); | ||
142 | 141 | ||
143 | /* | 142 | wl12xx_for_each_wlvif_sta(wl, wlvif) { |
144 | * We are HW_MONITOR device. On beacon loss - queue | 143 | if (wlvif->role_id == WL12XX_INVALID_ROLE_ID || |
145 | * connection loss work. Cancel it on REGAINED event. | 144 | !test_bit(wlvif->role_id , &roles_bitmap)) |
146 | */ | 145 | continue; |
147 | if (vector & BSS_LOSE_EVENT_ID) { | ||
148 | /* TODO: check for multi-role */ | ||
149 | int delay = wl->conf.conn.synch_fail_thold * | ||
150 | wl->conf.conn.bss_lose_timeout; | ||
151 | wl1271_info("Beacon loss detected."); | ||
152 | 146 | ||
153 | /* | 147 | if (!test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, |
154 | * if the work is already queued, it should take place. We | 148 | &wlvif->flags)) |
155 | * don't want to delay the connection loss indication | 149 | continue; |
156 | * any more. | ||
157 | */ | ||
158 | ieee80211_queue_delayed_work(wl->hw, &wl->connection_loss_work, | ||
159 | msecs_to_jiffies(delay)); | ||
160 | 150 | ||
161 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | 151 | vif = wl12xx_wlvif_to_vif(wlvif); |
162 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
163 | 152 | ||
164 | ieee80211_cqm_rssi_notify( | 153 | ieee80211_chswitch_done(vif, success); |
165 | vif, | 154 | cancel_delayed_work(&wlvif->channel_switch_work); |
166 | NL80211_CQM_RSSI_BEACON_LOSS_EVENT, | ||
167 | GFP_KERNEL); | ||
168 | } | ||
169 | } | 155 | } |
156 | } | ||
157 | EXPORT_SYMBOL_GPL(wlcore_event_channel_switch); | ||
170 | 158 | ||
171 | if (vector & REGAINED_BSS_EVENT_ID) { | 159 | void wlcore_event_dummy_packet(struct wl1271 *wl) |
172 | /* TODO: check for multi-role */ | 160 | { |
173 | wl1271_info("Beacon regained."); | 161 | wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); |
174 | cancel_delayed_work(&wl->connection_loss_work); | 162 | wl1271_tx_dummy_packet(wl); |
175 | 163 | } | |
176 | /* sanity check - we can't lose and gain the beacon together */ | 164 | EXPORT_SYMBOL_GPL(wlcore_event_dummy_packet); |
177 | WARN(vector & BSS_LOSE_EVENT_ID, | ||
178 | "Concurrent beacon loss and gain from FW"); | ||
179 | } | ||
180 | 165 | ||
181 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { | 166 | static void wlcore_disconnect_sta(struct wl1271 *wl, unsigned long sta_bitmap) |
182 | /* TODO: check actual multi-role support */ | 167 | { |
183 | wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); | 168 | u32 num_packets = wl->conf.tx.max_tx_retries; |
184 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | 169 | struct wl12xx_vif *wlvif; |
185 | wl1271_event_rssi_trigger(wl, wlvif, mbox); | 170 | struct ieee80211_vif *vif; |
171 | struct ieee80211_sta *sta; | ||
172 | const u8 *addr; | ||
173 | int h; | ||
174 | |||
175 | for_each_set_bit(h, &sta_bitmap, WL12XX_MAX_LINKS) { | ||
176 | bool found = false; | ||
177 | /* find the ap vif connected to this sta */ | ||
178 | wl12xx_for_each_wlvif_ap(wl, wlvif) { | ||
179 | if (!test_bit(h, wlvif->ap.sta_hlid_map)) | ||
180 | continue; | ||
181 | found = true; | ||
182 | break; | ||
186 | } | 183 | } |
187 | } | 184 | if (!found) |
185 | continue; | ||
188 | 186 | ||
189 | if (vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID) { | 187 | vif = wl12xx_wlvif_to_vif(wlvif); |
190 | u8 role_id = mbox->role_id; | 188 | addr = wl->links[h].addr; |
191 | wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. " | ||
192 | "ba_allowed = 0x%x, role_id=%d", | ||
193 | mbox->rx_ba_allowed, role_id); | ||
194 | 189 | ||
195 | wl12xx_for_each_wlvif(wl, wlvif) { | 190 | rcu_read_lock(); |
196 | if (role_id != 0xff && role_id != wlvif->role_id) | 191 | sta = ieee80211_find_sta(vif, addr); |
197 | continue; | 192 | if (sta) { |
198 | 193 | wl1271_debug(DEBUG_EVENT, "remove sta %d", h); | |
199 | wlvif->ba_allowed = !!mbox->rx_ba_allowed; | 194 | ieee80211_report_low_ack(sta, num_packets); |
200 | if (!wlvif->ba_allowed) | ||
201 | wl1271_stop_ba_event(wl, wlvif); | ||
202 | } | 195 | } |
196 | rcu_read_unlock(); | ||
203 | } | 197 | } |
198 | } | ||
204 | 199 | ||
205 | if (vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID) { | 200 | void wlcore_event_max_tx_failure(struct wl1271 *wl, unsigned long sta_bitmap) |
206 | wl1271_debug(DEBUG_EVENT, "CHANNEL_SWITCH_COMPLETE_EVENT_ID. " | 201 | { |
207 | "status = 0x%x", | 202 | wl1271_debug(DEBUG_EVENT, "MAX_TX_FAILURE_EVENT_ID"); |
208 | mbox->channel_switch_status); | 203 | wlcore_disconnect_sta(wl, sta_bitmap); |
209 | /* | 204 | } |
210 | * That event uses for two cases: | 205 | EXPORT_SYMBOL_GPL(wlcore_event_max_tx_failure); |
211 | * 1) channel switch complete with status=0 | ||
212 | * 2) channel switch failed status=1 | ||
213 | */ | ||
214 | |||
215 | /* TODO: configure only the relevant vif */ | ||
216 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
217 | bool success; | ||
218 | |||
219 | if (!test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, | ||
220 | &wlvif->flags)) | ||
221 | continue; | ||
222 | |||
223 | success = mbox->channel_switch_status ? false : true; | ||
224 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
225 | 206 | ||
226 | ieee80211_chswitch_done(vif, success); | 207 | void wlcore_event_inactive_sta(struct wl1271 *wl, unsigned long sta_bitmap) |
227 | } | 208 | { |
228 | } | 209 | wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID"); |
210 | wlcore_disconnect_sta(wl, sta_bitmap); | ||
211 | } | ||
212 | EXPORT_SYMBOL_GPL(wlcore_event_inactive_sta); | ||
229 | 213 | ||
230 | if ((vector & DUMMY_PACKET_EVENT_ID)) { | 214 | void wlcore_event_roc_complete(struct wl1271 *wl) |
231 | wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); | 215 | { |
232 | ret = wl1271_tx_dummy_packet(wl); | 216 | wl1271_debug(DEBUG_EVENT, "REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID"); |
233 | if (ret < 0) | 217 | if (wl->roc_vif) |
234 | return ret; | 218 | ieee80211_ready_on_channel(wl->hw); |
235 | } | 219 | } |
220 | EXPORT_SYMBOL_GPL(wlcore_event_roc_complete); | ||
236 | 221 | ||
222 | void wlcore_event_beacon_loss(struct wl1271 *wl, unsigned long roles_bitmap) | ||
223 | { | ||
237 | /* | 224 | /* |
238 | * "TX retries exceeded" has a different meaning according to mode. | 225 | * We are HW_MONITOR device. On beacon loss - queue |
239 | * In AP mode the offending station is disconnected. | 226 | * connection loss work. Cancel it on REGAINED event. |
240 | */ | 227 | */ |
241 | if (vector & MAX_TX_RETRY_EVENT_ID) { | 228 | struct wl12xx_vif *wlvif; |
242 | wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID"); | 229 | struct ieee80211_vif *vif; |
243 | sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded); | 230 | int delay = wl->conf.conn.synch_fail_thold * |
244 | disconnect_sta = true; | 231 | wl->conf.conn.bss_lose_timeout; |
245 | } | ||
246 | 232 | ||
247 | if (vector & INACTIVE_STA_EVENT_ID) { | 233 | wl1271_info("Beacon loss detected. roles:0x%lx", roles_bitmap); |
248 | wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID"); | ||
249 | sta_bitmap |= le16_to_cpu(mbox->sta_aging_status); | ||
250 | disconnect_sta = true; | ||
251 | } | ||
252 | 234 | ||
253 | if (disconnect_sta) { | 235 | wl12xx_for_each_wlvif_sta(wl, wlvif) { |
254 | u32 num_packets = wl->conf.tx.max_tx_retries; | 236 | if (wlvif->role_id == WL12XX_INVALID_ROLE_ID || |
255 | struct ieee80211_sta *sta; | 237 | !test_bit(wlvif->role_id , &roles_bitmap)) |
256 | const u8 *addr; | 238 | continue; |
257 | int h; | ||
258 | |||
259 | for_each_set_bit(h, &sta_bitmap, WL12XX_MAX_LINKS) { | ||
260 | bool found = false; | ||
261 | /* find the ap vif connected to this sta */ | ||
262 | wl12xx_for_each_wlvif_ap(wl, wlvif) { | ||
263 | if (!test_bit(h, wlvif->ap.sta_hlid_map)) | ||
264 | continue; | ||
265 | found = true; | ||
266 | break; | ||
267 | } | ||
268 | if (!found) | ||
269 | continue; | ||
270 | 239 | ||
271 | vif = wl12xx_wlvif_to_vif(wlvif); | 240 | /* |
272 | addr = wl->links[h].addr; | 241 | * if the work is already queued, it should take place. |
242 | * We don't want to delay the connection loss | ||
243 | * indication any more. | ||
244 | */ | ||
245 | ieee80211_queue_delayed_work(wl->hw, | ||
246 | &wlvif->connection_loss_work, | ||
247 | msecs_to_jiffies(delay)); | ||
273 | 248 | ||
274 | rcu_read_lock(); | 249 | vif = wl12xx_wlvif_to_vif(wlvif); |
275 | sta = ieee80211_find_sta(vif, addr); | 250 | ieee80211_cqm_rssi_notify( |
276 | if (sta) { | 251 | vif, |
277 | wl1271_debug(DEBUG_EVENT, "remove sta %d", h); | 252 | NL80211_CQM_RSSI_BEACON_LOSS_EVENT, |
278 | ieee80211_report_low_ack(sta, num_packets); | 253 | GFP_KERNEL); |
279 | } | ||
280 | rcu_read_unlock(); | ||
281 | } | ||
282 | } | 254 | } |
283 | return 0; | ||
284 | } | 255 | } |
256 | EXPORT_SYMBOL_GPL(wlcore_event_beacon_loss); | ||
285 | 257 | ||
286 | int wl1271_event_unmask(struct wl1271 *wl) | 258 | int wl1271_event_unmask(struct wl1271 *wl) |
287 | { | 259 | { |
@@ -305,12 +277,12 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) | |||
305 | 277 | ||
306 | /* first we read the mbox descriptor */ | 278 | /* first we read the mbox descriptor */ |
307 | ret = wlcore_read(wl, wl->mbox_ptr[mbox_num], wl->mbox, | 279 | ret = wlcore_read(wl, wl->mbox_ptr[mbox_num], wl->mbox, |
308 | sizeof(*wl->mbox), false); | 280 | wl->mbox_size, false); |
309 | if (ret < 0) | 281 | if (ret < 0) |
310 | return ret; | 282 | return ret; |
311 | 283 | ||
312 | /* process the descriptor */ | 284 | /* process the descriptor */ |
313 | ret = wl1271_event_process(wl); | 285 | ret = wl->ops->process_mailbox_events(wl); |
314 | if (ret < 0) | 286 | if (ret < 0) |
315 | return ret; | 287 | return ret; |
316 | 288 | ||
diff --git a/drivers/net/wireless/ti/wlcore/event.h b/drivers/net/wireless/ti/wlcore/event.h index 8adf18d6c58f..acc7a59d3828 100644 --- a/drivers/net/wireless/ti/wlcore/event.h +++ b/drivers/net/wireless/ti/wlcore/event.h | |||
@@ -46,33 +46,17 @@ enum { | |||
46 | RSSI_SNR_TRIGGER_5_EVENT_ID = BIT(5), | 46 | RSSI_SNR_TRIGGER_5_EVENT_ID = BIT(5), |
47 | RSSI_SNR_TRIGGER_6_EVENT_ID = BIT(6), | 47 | RSSI_SNR_TRIGGER_6_EVENT_ID = BIT(6), |
48 | RSSI_SNR_TRIGGER_7_EVENT_ID = BIT(7), | 48 | RSSI_SNR_TRIGGER_7_EVENT_ID = BIT(7), |
49 | MEASUREMENT_START_EVENT_ID = BIT(8), | 49 | |
50 | MEASUREMENT_COMPLETE_EVENT_ID = BIT(9), | ||
51 | SCAN_COMPLETE_EVENT_ID = BIT(10), | ||
52 | WFD_DISCOVERY_COMPLETE_EVENT_ID = BIT(11), | ||
53 | AP_DISCOVERY_COMPLETE_EVENT_ID = BIT(12), | ||
54 | RESERVED1 = BIT(13), | ||
55 | PSPOLL_DELIVERY_FAILURE_EVENT_ID = BIT(14), | ||
56 | ROLE_STOP_COMPLETE_EVENT_ID = BIT(15), | ||
57 | RADAR_DETECTED_EVENT_ID = BIT(16), | ||
58 | CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17), | ||
59 | BSS_LOSE_EVENT_ID = BIT(18), | ||
60 | REGAINED_BSS_EVENT_ID = BIT(19), | ||
61 | MAX_TX_RETRY_EVENT_ID = BIT(20), | ||
62 | DUMMY_PACKET_EVENT_ID = BIT(21), | ||
63 | SOFT_GEMINI_SENSE_EVENT_ID = BIT(22), | ||
64 | CHANGE_AUTO_MODE_TIMEOUT_EVENT_ID = BIT(23), | ||
65 | SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24), | ||
66 | PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25), | ||
67 | INACTIVE_STA_EVENT_ID = BIT(26), | ||
68 | PEER_REMOVE_COMPLETE_EVENT_ID = BIT(27), | ||
69 | PERIODIC_SCAN_COMPLETE_EVENT_ID = BIT(28), | ||
70 | PERIODIC_SCAN_REPORT_EVENT_ID = BIT(29), | ||
71 | BA_SESSION_RX_CONSTRAINT_EVENT_ID = BIT(30), | ||
72 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID = BIT(31), | ||
73 | EVENT_MBOX_ALL_EVENT_ID = 0x7fffffff, | 50 | EVENT_MBOX_ALL_EVENT_ID = 0x7fffffff, |
74 | }; | 51 | }; |
75 | 52 | ||
53 | /* events the driver might want to wait for */ | ||
54 | enum wlcore_wait_event { | ||
55 | WLCORE_EVENT_ROLE_STOP_COMPLETE, | ||
56 | WLCORE_EVENT_PEER_REMOVE_COMPLETE, | ||
57 | WLCORE_EVENT_DFS_CONFIG_COMPLETE | ||
58 | }; | ||
59 | |||
76 | enum { | 60 | enum { |
77 | EVENT_ENTER_POWER_SAVE_FAIL = 0, | 61 | EVENT_ENTER_POWER_SAVE_FAIL = 0, |
78 | EVENT_ENTER_POWER_SAVE_SUCCESS, | 62 | EVENT_ENTER_POWER_SAVE_SUCCESS, |
@@ -80,61 +64,24 @@ enum { | |||
80 | 64 | ||
81 | #define NUM_OF_RSSI_SNR_TRIGGERS 8 | 65 | #define NUM_OF_RSSI_SNR_TRIGGERS 8 |
82 | 66 | ||
83 | struct event_mailbox { | ||
84 | __le32 events_vector; | ||
85 | __le32 events_mask; | ||
86 | __le32 reserved_1; | ||
87 | __le32 reserved_2; | ||
88 | |||
89 | u8 number_of_scan_results; | ||
90 | u8 scan_tag; | ||
91 | u8 completed_scan_status; | ||
92 | u8 reserved_3; | ||
93 | |||
94 | u8 soft_gemini_sense_info; | ||
95 | u8 soft_gemini_protective_info; | ||
96 | s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS]; | ||
97 | u8 change_auto_mode_timeout; | ||
98 | u8 scheduled_scan_status; | ||
99 | u8 reserved4; | ||
100 | /* tuned channel (roc) */ | ||
101 | u8 roc_channel; | ||
102 | |||
103 | __le16 hlid_removed_bitmap; | ||
104 | |||
105 | /* bitmap of aged stations (by HLID) */ | ||
106 | __le16 sta_aging_status; | ||
107 | |||
108 | /* bitmap of stations (by HLID) which exceeded max tx retries */ | ||
109 | __le16 sta_tx_retry_exceeded; | ||
110 | |||
111 | /* discovery completed results */ | ||
112 | u8 discovery_tag; | ||
113 | u8 number_of_preq_results; | ||
114 | u8 number_of_prsp_results; | ||
115 | u8 reserved_5; | ||
116 | |||
117 | /* rx ba constraint */ | ||
118 | u8 role_id; /* 0xFF means any role. */ | ||
119 | u8 rx_ba_allowed; | ||
120 | u8 reserved_6[2]; | ||
121 | |||
122 | /* Channel switch results */ | ||
123 | |||
124 | u8 channel_switch_role_id; | ||
125 | u8 channel_switch_status; | ||
126 | u8 reserved_7[2]; | ||
127 | |||
128 | u8 ps_poll_delivery_failure_role_ids; | ||
129 | u8 stopped_role_ids; | ||
130 | u8 started_role_ids; | ||
131 | |||
132 | u8 reserved_8[9]; | ||
133 | } __packed; | ||
134 | |||
135 | struct wl1271; | 67 | struct wl1271; |
136 | 68 | ||
137 | int wl1271_event_unmask(struct wl1271 *wl); | 69 | int wl1271_event_unmask(struct wl1271 *wl); |
138 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox); | 70 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox); |
139 | 71 | ||
72 | void wlcore_event_soft_gemini_sense(struct wl1271 *wl, u8 enable); | ||
73 | void wlcore_event_sched_scan_completed(struct wl1271 *wl, | ||
74 | u8 status); | ||
75 | void wlcore_event_ba_rx_constraint(struct wl1271 *wl, | ||
76 | unsigned long roles_bitmap, | ||
77 | unsigned long allowed_bitmap); | ||
78 | void wlcore_event_channel_switch(struct wl1271 *wl, | ||
79 | unsigned long roles_bitmap, | ||
80 | bool success); | ||
81 | void wlcore_event_beacon_loss(struct wl1271 *wl, unsigned long roles_bitmap); | ||
82 | void wlcore_event_dummy_packet(struct wl1271 *wl); | ||
83 | void wlcore_event_max_tx_failure(struct wl1271 *wl, unsigned long sta_bitmap); | ||
84 | void wlcore_event_inactive_sta(struct wl1271 *wl, unsigned long sta_bitmap); | ||
85 | void wlcore_event_roc_complete(struct wl1271 *wl); | ||
86 | void wlcore_event_rssi_trigger(struct wl1271 *wl, s8 *metric_arr); | ||
140 | #endif | 87 | #endif |
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h index 2673d783ec1e..7fd260c02a0a 100644 --- a/drivers/net/wireless/ti/wlcore/hw_ops.h +++ b/drivers/net/wireless/ti/wlcore/hw_ops.h | |||
@@ -201,4 +201,45 @@ wlcore_hw_pre_pkt_send(struct wl1271 *wl, u32 buf_offset, u32 last_len) | |||
201 | return buf_offset; | 201 | return buf_offset; |
202 | } | 202 | } |
203 | 203 | ||
204 | static inline void | ||
205 | wlcore_hw_sta_rc_update(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
206 | struct ieee80211_sta *sta, u32 changed) | ||
207 | { | ||
208 | if (wl->ops->sta_rc_update) | ||
209 | wl->ops->sta_rc_update(wl, wlvif, sta, changed); | ||
210 | } | ||
211 | |||
212 | static inline int | ||
213 | wlcore_hw_set_peer_cap(struct wl1271 *wl, | ||
214 | struct ieee80211_sta_ht_cap *ht_cap, | ||
215 | bool allow_ht_operation, | ||
216 | u32 rate_set, u8 hlid) | ||
217 | { | ||
218 | if (wl->ops->set_peer_cap) | ||
219 | return wl->ops->set_peer_cap(wl, ht_cap, allow_ht_operation, | ||
220 | rate_set, hlid); | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static inline bool | ||
226 | wlcore_hw_lnk_high_prio(struct wl1271 *wl, u8 hlid, | ||
227 | struct wl1271_link *lnk) | ||
228 | { | ||
229 | if (!wl->ops->lnk_high_prio) | ||
230 | BUG_ON(1); | ||
231 | |||
232 | return wl->ops->lnk_high_prio(wl, hlid, lnk); | ||
233 | } | ||
234 | |||
235 | static inline bool | ||
236 | wlcore_hw_lnk_low_prio(struct wl1271 *wl, u8 hlid, | ||
237 | struct wl1271_link *lnk) | ||
238 | { | ||
239 | if (!wl->ops->lnk_low_prio) | ||
240 | BUG_ON(1); | ||
241 | |||
242 | return wl->ops->lnk_low_prio(wl, hlid, lnk); | ||
243 | } | ||
244 | |||
204 | #endif | 245 | #endif |
diff --git a/drivers/net/wireless/ti/wlcore/init.c b/drivers/net/wireless/ti/wlcore/init.c index 32d157f62f31..5c6f11e157d9 100644 --- a/drivers/net/wireless/ti/wlcore/init.c +++ b/drivers/net/wireless/ti/wlcore/init.c | |||
@@ -41,14 +41,14 @@ int wl1271_init_templates_config(struct wl1271 *wl) | |||
41 | 41 | ||
42 | /* send empty templates for fw memory reservation */ | 42 | /* send empty templates for fw memory reservation */ |
43 | ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, | 43 | ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, |
44 | CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, | 44 | wl->scan_templ_id_2_4, NULL, |
45 | WL1271_CMD_TEMPL_MAX_SIZE, | 45 | WL1271_CMD_TEMPL_MAX_SIZE, |
46 | 0, WL1271_RATE_AUTOMATIC); | 46 | 0, WL1271_RATE_AUTOMATIC); |
47 | if (ret < 0) | 47 | if (ret < 0) |
48 | return ret; | 48 | return ret; |
49 | 49 | ||
50 | ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, | 50 | ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, |
51 | CMD_TEMPL_CFG_PROBE_REQ_5, | 51 | wl->scan_templ_id_5, |
52 | NULL, WL1271_CMD_TEMPL_MAX_SIZE, 0, | 52 | NULL, WL1271_CMD_TEMPL_MAX_SIZE, 0, |
53 | WL1271_RATE_AUTOMATIC); | 53 | WL1271_RATE_AUTOMATIC); |
54 | if (ret < 0) | 54 | if (ret < 0) |
@@ -56,14 +56,16 @@ int wl1271_init_templates_config(struct wl1271 *wl) | |||
56 | 56 | ||
57 | if (wl->quirks & WLCORE_QUIRK_DUAL_PROBE_TMPL) { | 57 | if (wl->quirks & WLCORE_QUIRK_DUAL_PROBE_TMPL) { |
58 | ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, | 58 | ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, |
59 | CMD_TEMPL_APP_PROBE_REQ_2_4, NULL, | 59 | wl->sched_scan_templ_id_2_4, |
60 | NULL, | ||
60 | WL1271_CMD_TEMPL_MAX_SIZE, | 61 | WL1271_CMD_TEMPL_MAX_SIZE, |
61 | 0, WL1271_RATE_AUTOMATIC); | 62 | 0, WL1271_RATE_AUTOMATIC); |
62 | if (ret < 0) | 63 | if (ret < 0) |
63 | return ret; | 64 | return ret; |
64 | 65 | ||
65 | ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, | 66 | ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, |
66 | CMD_TEMPL_APP_PROBE_REQ_5, NULL, | 67 | wl->sched_scan_templ_id_5, |
68 | NULL, | ||
67 | WL1271_CMD_TEMPL_MAX_SIZE, | 69 | WL1271_CMD_TEMPL_MAX_SIZE, |
68 | 0, WL1271_RATE_AUTOMATIC); | 70 | 0, WL1271_RATE_AUTOMATIC); |
69 | if (ret < 0) | 71 | if (ret < 0) |
@@ -463,7 +465,7 @@ int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
463 | if ((wlvif->basic_rate_set & CONF_TX_OFDM_RATES)) | 465 | if ((wlvif->basic_rate_set & CONF_TX_OFDM_RATES)) |
464 | supported_rates = CONF_TX_OFDM_RATES; | 466 | supported_rates = CONF_TX_OFDM_RATES; |
465 | else | 467 | else |
466 | supported_rates = CONF_TX_AP_ENABLED_RATES; | 468 | supported_rates = CONF_TX_ENABLED_RATES; |
467 | 469 | ||
468 | /* unconditionally enable HT rates */ | 470 | /* unconditionally enable HT rates */ |
469 | supported_rates |= CONF_TX_MCS_RATES; | 471 | supported_rates |= CONF_TX_MCS_RATES; |
@@ -575,9 +577,6 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif) | |||
575 | /* Configure for power according to debugfs */ | 577 | /* Configure for power according to debugfs */ |
576 | if (sta_auth != WL1271_PSM_ILLEGAL) | 578 | if (sta_auth != WL1271_PSM_ILLEGAL) |
577 | ret = wl1271_acx_sleep_auth(wl, sta_auth); | 579 | ret = wl1271_acx_sleep_auth(wl, sta_auth); |
578 | /* Configure for power always on */ | ||
579 | else if (wl->quirks & WLCORE_QUIRK_NO_ELP) | ||
580 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | ||
581 | /* Configure for ELP power saving */ | 580 | /* Configure for ELP power saving */ |
582 | else | 581 | else |
583 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP); | 582 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP); |
@@ -679,6 +678,10 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
679 | if (ret < 0) | 678 | if (ret < 0) |
680 | return ret; | 679 | return ret; |
681 | 680 | ||
681 | ret = wlcore_cmd_regdomain_config_locked(wl); | ||
682 | if (ret < 0) | ||
683 | return ret; | ||
684 | |||
682 | /* Bluetooth WLAN coexistence */ | 685 | /* Bluetooth WLAN coexistence */ |
683 | ret = wl1271_init_pta(wl); | 686 | ret = wl1271_init_pta(wl); |
684 | if (ret < 0) | 687 | if (ret < 0) |
diff --git a/drivers/net/wireless/ti/wlcore/io.h b/drivers/net/wireless/ti/wlcore/io.h index f48530fec14f..af7d9f9b3b4d 100644 --- a/drivers/net/wireless/ti/wlcore/io.h +++ b/drivers/net/wireless/ti/wlcore/io.h | |||
@@ -105,13 +105,13 @@ static inline int __must_check wlcore_raw_read32(struct wl1271 *wl, int addr, | |||
105 | { | 105 | { |
106 | int ret; | 106 | int ret; |
107 | 107 | ||
108 | ret = wlcore_raw_read(wl, addr, &wl->buffer_32, | 108 | ret = wlcore_raw_read(wl, addr, wl->buffer_32, |
109 | sizeof(wl->buffer_32), false); | 109 | sizeof(*wl->buffer_32), false); |
110 | if (ret < 0) | 110 | if (ret < 0) |
111 | return ret; | 111 | return ret; |
112 | 112 | ||
113 | if (val) | 113 | if (val) |
114 | *val = le32_to_cpu(wl->buffer_32); | 114 | *val = le32_to_cpu(*wl->buffer_32); |
115 | 115 | ||
116 | return 0; | 116 | return 0; |
117 | } | 117 | } |
@@ -119,9 +119,9 @@ static inline int __must_check wlcore_raw_read32(struct wl1271 *wl, int addr, | |||
119 | static inline int __must_check wlcore_raw_write32(struct wl1271 *wl, int addr, | 119 | static inline int __must_check wlcore_raw_write32(struct wl1271 *wl, int addr, |
120 | u32 val) | 120 | u32 val) |
121 | { | 121 | { |
122 | wl->buffer_32 = cpu_to_le32(val); | 122 | *wl->buffer_32 = cpu_to_le32(val); |
123 | return wlcore_raw_write(wl, addr, &wl->buffer_32, | 123 | return wlcore_raw_write(wl, addr, wl->buffer_32, |
124 | sizeof(wl->buffer_32), false); | 124 | sizeof(*wl->buffer_32), false); |
125 | } | 125 | } |
126 | 126 | ||
127 | static inline int __must_check wlcore_read(struct wl1271 *wl, int addr, | 127 | static inline int __must_check wlcore_read(struct wl1271 *wl, int addr, |
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index ce6e62a37e14..e1dfdf94d0f7 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -56,8 +56,8 @@ | |||
56 | #define WL1271_BOOT_RETRIES 3 | 56 | #define WL1271_BOOT_RETRIES 3 |
57 | 57 | ||
58 | static char *fwlog_param; | 58 | static char *fwlog_param; |
59 | static bool bug_on_recovery; | 59 | static int bug_on_recovery = -1; |
60 | static bool no_recovery; | 60 | static int no_recovery = -1; |
61 | 61 | ||
62 | static void __wl1271_op_remove_interface(struct wl1271 *wl, | 62 | static void __wl1271_op_remove_interface(struct wl1271 *wl, |
63 | struct ieee80211_vif *vif, | 63 | struct ieee80211_vif *vif, |
@@ -79,12 +79,10 @@ static int wl12xx_set_authorized(struct wl1271 *wl, | |||
79 | if (test_and_set_bit(WLVIF_FLAG_STA_STATE_SENT, &wlvif->flags)) | 79 | if (test_and_set_bit(WLVIF_FLAG_STA_STATE_SENT, &wlvif->flags)) |
80 | return 0; | 80 | return 0; |
81 | 81 | ||
82 | ret = wl12xx_cmd_set_peer_state(wl, wlvif->sta.hlid); | 82 | ret = wl12xx_cmd_set_peer_state(wl, wlvif, wlvif->sta.hlid); |
83 | if (ret < 0) | 83 | if (ret < 0) |
84 | return ret; | 84 | return ret; |
85 | 85 | ||
86 | wl12xx_croc(wl, wlvif->role_id); | ||
87 | |||
88 | wl1271_info("Association completed."); | 86 | wl1271_info("Association completed."); |
89 | return 0; | 87 | return 0; |
90 | } | 88 | } |
@@ -95,6 +93,8 @@ static void wl1271_reg_notify(struct wiphy *wiphy, | |||
95 | struct ieee80211_supported_band *band; | 93 | struct ieee80211_supported_band *band; |
96 | struct ieee80211_channel *ch; | 94 | struct ieee80211_channel *ch; |
97 | int i; | 95 | int i; |
96 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | ||
97 | struct wl1271 *wl = hw->priv; | ||
98 | 98 | ||
99 | band = wiphy->bands[IEEE80211_BAND_5GHZ]; | 99 | band = wiphy->bands[IEEE80211_BAND_5GHZ]; |
100 | for (i = 0; i < band->n_channels; i++) { | 100 | for (i = 0; i < band->n_channels; i++) { |
@@ -107,6 +107,9 @@ static void wl1271_reg_notify(struct wiphy *wiphy, | |||
107 | IEEE80211_CHAN_PASSIVE_SCAN; | 107 | IEEE80211_CHAN_PASSIVE_SCAN; |
108 | 108 | ||
109 | } | 109 | } |
110 | |||
111 | if (likely(wl->state == WLCORE_STATE_ON)) | ||
112 | wlcore_regdomain_config(wl); | ||
110 | } | 113 | } |
111 | 114 | ||
112 | static int wl1271_set_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 115 | static int wl1271_set_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
@@ -301,6 +304,7 @@ out: | |||
301 | static void wlcore_adjust_conf(struct wl1271 *wl) | 304 | static void wlcore_adjust_conf(struct wl1271 *wl) |
302 | { | 305 | { |
303 | /* Adjust settings according to optional module parameters */ | 306 | /* Adjust settings according to optional module parameters */ |
307 | |||
304 | if (fwlog_param) { | 308 | if (fwlog_param) { |
305 | if (!strcmp(fwlog_param, "continuous")) { | 309 | if (!strcmp(fwlog_param, "continuous")) { |
306 | wl->conf.fwlog.mode = WL12XX_FWLOG_CONTINUOUS; | 310 | wl->conf.fwlog.mode = WL12XX_FWLOG_CONTINUOUS; |
@@ -316,16 +320,22 @@ static void wlcore_adjust_conf(struct wl1271 *wl) | |||
316 | wl1271_error("Unknown fwlog parameter %s", fwlog_param); | 320 | wl1271_error("Unknown fwlog parameter %s", fwlog_param); |
317 | } | 321 | } |
318 | } | 322 | } |
323 | |||
324 | if (bug_on_recovery != -1) | ||
325 | wl->conf.recovery.bug_on_recovery = (u8) bug_on_recovery; | ||
326 | |||
327 | if (no_recovery != -1) | ||
328 | wl->conf.recovery.no_recovery = (u8) no_recovery; | ||
319 | } | 329 | } |
320 | 330 | ||
321 | static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, | 331 | static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, |
322 | struct wl12xx_vif *wlvif, | 332 | struct wl12xx_vif *wlvif, |
323 | u8 hlid, u8 tx_pkts) | 333 | u8 hlid, u8 tx_pkts) |
324 | { | 334 | { |
325 | bool fw_ps, single_sta; | 335 | bool fw_ps, single_link; |
326 | 336 | ||
327 | fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | 337 | fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); |
328 | single_sta = (wl->active_sta_count == 1); | 338 | single_link = (wl->active_link_count == 1); |
329 | 339 | ||
330 | /* | 340 | /* |
331 | * Wake up from high level PS if the STA is asleep with too little | 341 | * Wake up from high level PS if the STA is asleep with too little |
@@ -336,10 +346,10 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, | |||
336 | 346 | ||
337 | /* | 347 | /* |
338 | * Start high-level PS if the STA is asleep with enough blocks in FW. | 348 | * Start high-level PS if the STA is asleep with enough blocks in FW. |
339 | * Make an exception if this is the only connected station. In this | 349 | * Make an exception if this is the only connected link. In this |
340 | * case FW-memory congestion is not a problem. | 350 | * case FW-memory congestion is less of a problem. |
341 | */ | 351 | */ |
342 | else if (!single_sta && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) | 352 | else if (!single_link && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) |
343 | wl12xx_ps_link_start(wl, wlvif, hlid, true); | 353 | wl12xx_ps_link_start(wl, wlvif, hlid, true); |
344 | } | 354 | } |
345 | 355 | ||
@@ -347,11 +357,8 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl, | |||
347 | struct wl12xx_vif *wlvif, | 357 | struct wl12xx_vif *wlvif, |
348 | struct wl_fw_status_2 *status) | 358 | struct wl_fw_status_2 *status) |
349 | { | 359 | { |
350 | struct wl1271_link *lnk; | ||
351 | u32 cur_fw_ps_map; | 360 | u32 cur_fw_ps_map; |
352 | u8 hlid, cnt; | 361 | u8 hlid; |
353 | |||
354 | /* TODO: also use link_fast_bitmap here */ | ||
355 | 362 | ||
356 | cur_fw_ps_map = le32_to_cpu(status->link_ps_bitmap); | 363 | cur_fw_ps_map = le32_to_cpu(status->link_ps_bitmap); |
357 | if (wl->ap_fw_ps_map != cur_fw_ps_map) { | 364 | if (wl->ap_fw_ps_map != cur_fw_ps_map) { |
@@ -363,17 +370,9 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl, | |||
363 | wl->ap_fw_ps_map = cur_fw_ps_map; | 370 | wl->ap_fw_ps_map = cur_fw_ps_map; |
364 | } | 371 | } |
365 | 372 | ||
366 | for_each_set_bit(hlid, wlvif->ap.sta_hlid_map, WL12XX_MAX_LINKS) { | 373 | for_each_set_bit(hlid, wlvif->ap.sta_hlid_map, WL12XX_MAX_LINKS) |
367 | lnk = &wl->links[hlid]; | ||
368 | cnt = status->counters.tx_lnk_free_pkts[hlid] - | ||
369 | lnk->prev_freed_pkts; | ||
370 | |||
371 | lnk->prev_freed_pkts = status->counters.tx_lnk_free_pkts[hlid]; | ||
372 | lnk->allocated_pkts -= cnt; | ||
373 | |||
374 | wl12xx_irq_ps_regulate_link(wl, wlvif, hlid, | 374 | wl12xx_irq_ps_regulate_link(wl, wlvif, hlid, |
375 | lnk->allocated_pkts); | 375 | wl->links[hlid].allocated_pkts); |
376 | } | ||
377 | } | 376 | } |
378 | 377 | ||
379 | static int wlcore_fw_status(struct wl1271 *wl, | 378 | static int wlcore_fw_status(struct wl1271 *wl, |
@@ -387,6 +386,7 @@ static int wlcore_fw_status(struct wl1271 *wl, | |||
387 | int i; | 386 | int i; |
388 | size_t status_len; | 387 | size_t status_len; |
389 | int ret; | 388 | int ret; |
389 | struct wl1271_link *lnk; | ||
390 | 390 | ||
391 | status_len = WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) + | 391 | status_len = WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) + |
392 | sizeof(*status_2) + wl->fw_status_priv_len; | 392 | sizeof(*status_2) + wl->fw_status_priv_len; |
@@ -412,6 +412,17 @@ static int wlcore_fw_status(struct wl1271 *wl, | |||
412 | wl->tx_pkts_freed[i] = status_2->counters.tx_released_pkts[i]; | 412 | wl->tx_pkts_freed[i] = status_2->counters.tx_released_pkts[i]; |
413 | } | 413 | } |
414 | 414 | ||
415 | |||
416 | for_each_set_bit(i, wl->links_map, WL12XX_MAX_LINKS) { | ||
417 | lnk = &wl->links[i]; | ||
418 | /* prevent wrap-around in freed-packets counter */ | ||
419 | lnk->allocated_pkts -= | ||
420 | (status_2->counters.tx_lnk_free_pkts[i] - | ||
421 | lnk->prev_freed_pkts) & 0xff; | ||
422 | |||
423 | lnk->prev_freed_pkts = status_2->counters.tx_lnk_free_pkts[i]; | ||
424 | } | ||
425 | |||
415 | /* prevent wrap-around in total blocks counter */ | 426 | /* prevent wrap-around in total blocks counter */ |
416 | if (likely(wl->tx_blocks_freed <= | 427 | if (likely(wl->tx_blocks_freed <= |
417 | le32_to_cpu(status_2->total_released_blks))) | 428 | le32_to_cpu(status_2->total_released_blks))) |
@@ -464,6 +475,8 @@ static int wlcore_fw_status(struct wl1271 *wl, | |||
464 | wl->time_offset = (timespec_to_ns(&ts) >> 10) - | 475 | wl->time_offset = (timespec_to_ns(&ts) >> 10) - |
465 | (s64)le32_to_cpu(status_2->fw_localtime); | 476 | (s64)le32_to_cpu(status_2->fw_localtime); |
466 | 477 | ||
478 | wl->fw_fast_lnk_map = le32_to_cpu(status_2->link_fast_bitmap); | ||
479 | |||
467 | return 0; | 480 | return 0; |
468 | } | 481 | } |
469 | 482 | ||
@@ -800,11 +813,13 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) | |||
800 | 813 | ||
801 | /* | 814 | /* |
802 | * Make sure the chip is awake and the logger isn't active. | 815 | * Make sure the chip is awake and the logger isn't active. |
803 | * Do not send a stop fwlog command if the fw is hanged. | 816 | * Do not send a stop fwlog command if the fw is hanged or if |
817 | * dbgpins are used (due to some fw bug). | ||
804 | */ | 818 | */ |
805 | if (wl1271_ps_elp_wakeup(wl)) | 819 | if (wl1271_ps_elp_wakeup(wl)) |
806 | goto out; | 820 | goto out; |
807 | if (!wl->watchdog_recovery) | 821 | if (!wl->watchdog_recovery && |
822 | wl->conf.fwlog.output != WL12XX_FWLOG_OUTPUT_DBG_PINS) | ||
808 | wl12xx_cmd_stop_fwlog(wl); | 823 | wl12xx_cmd_stop_fwlog(wl); |
809 | 824 | ||
810 | /* Read the first memory block address */ | 825 | /* Read the first memory block address */ |
@@ -872,7 +887,8 @@ static void wlcore_print_recovery(struct wl1271 *wl) | |||
872 | if (ret < 0) | 887 | if (ret < 0) |
873 | return; | 888 | return; |
874 | 889 | ||
875 | wl1271_info("pc: 0x%x, hint_sts: 0x%08x", pc, hint_sts); | 890 | wl1271_info("pc: 0x%x, hint_sts: 0x%08x count: %d", |
891 | pc, hint_sts, ++wl->recovery_count); | ||
876 | 892 | ||
877 | wlcore_set_partition(wl, &wl->ptable[PART_WORK]); | 893 | wlcore_set_partition(wl, &wl->ptable[PART_WORK]); |
878 | } | 894 | } |
@@ -895,10 +911,10 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
895 | wlcore_print_recovery(wl); | 911 | wlcore_print_recovery(wl); |
896 | } | 912 | } |
897 | 913 | ||
898 | BUG_ON(bug_on_recovery && | 914 | BUG_ON(wl->conf.recovery.bug_on_recovery && |
899 | !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); | 915 | !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); |
900 | 916 | ||
901 | if (no_recovery) { | 917 | if (wl->conf.recovery.no_recovery) { |
902 | wl1271_info("No recovery (chosen on module load). Fw will remain stuck."); | 918 | wl1271_info("No recovery (chosen on module load). Fw will remain stuck."); |
903 | goto out_unlock; | 919 | goto out_unlock; |
904 | } | 920 | } |
@@ -918,11 +934,6 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
918 | /* Prevent spurious TX during FW restart */ | 934 | /* Prevent spurious TX during FW restart */ |
919 | wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_FW_RESTART); | 935 | wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_FW_RESTART); |
920 | 936 | ||
921 | if (wl->sched_scanning) { | ||
922 | ieee80211_sched_scan_stopped(wl->hw); | ||
923 | wl->sched_scanning = false; | ||
924 | } | ||
925 | |||
926 | /* reboot the chipset */ | 937 | /* reboot the chipset */ |
927 | while (!list_empty(&wl->wlvif_list)) { | 938 | while (!list_empty(&wl->wlvif_list)) { |
928 | wlvif = list_first_entry(&wl->wlvif_list, | 939 | wlvif = list_first_entry(&wl->wlvif_list, |
@@ -1139,7 +1150,6 @@ int wl1271_plt_stop(struct wl1271 *wl) | |||
1139 | cancel_work_sync(&wl->recovery_work); | 1150 | cancel_work_sync(&wl->recovery_work); |
1140 | cancel_delayed_work_sync(&wl->elp_work); | 1151 | cancel_delayed_work_sync(&wl->elp_work); |
1141 | cancel_delayed_work_sync(&wl->tx_watchdog_work); | 1152 | cancel_delayed_work_sync(&wl->tx_watchdog_work); |
1142 | cancel_delayed_work_sync(&wl->connection_loss_work); | ||
1143 | 1153 | ||
1144 | mutex_lock(&wl->mutex); | 1154 | mutex_lock(&wl->mutex); |
1145 | wl1271_power_off(wl); | 1155 | wl1271_power_off(wl); |
@@ -1167,9 +1177,13 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, | |||
1167 | int q, mapping; | 1177 | int q, mapping; |
1168 | u8 hlid; | 1178 | u8 hlid; |
1169 | 1179 | ||
1170 | if (vif) | 1180 | if (!vif) { |
1171 | wlvif = wl12xx_vif_to_data(vif); | 1181 | wl1271_debug(DEBUG_TX, "DROP skb with no vif"); |
1182 | ieee80211_free_txskb(hw, skb); | ||
1183 | return; | ||
1184 | } | ||
1172 | 1185 | ||
1186 | wlvif = wl12xx_vif_to_data(vif); | ||
1173 | mapping = skb_get_queue_mapping(skb); | 1187 | mapping = skb_get_queue_mapping(skb); |
1174 | q = wl1271_tx_get_queue(mapping); | 1188 | q = wl1271_tx_get_queue(mapping); |
1175 | 1189 | ||
@@ -1183,9 +1197,9 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, | |||
1183 | * allow these packets through. | 1197 | * allow these packets through. |
1184 | */ | 1198 | */ |
1185 | if (hlid == WL12XX_INVALID_LINK_ID || | 1199 | if (hlid == WL12XX_INVALID_LINK_ID || |
1186 | (wlvif && !test_bit(hlid, wlvif->links_map)) || | 1200 | (!test_bit(hlid, wlvif->links_map)) || |
1187 | (wlcore_is_queue_stopped(wl, q) && | 1201 | (wlcore_is_queue_stopped_locked(wl, wlvif, q) && |
1188 | !wlcore_is_queue_stopped_by_reason(wl, q, | 1202 | !wlcore_is_queue_stopped_by_reason_locked(wl, wlvif, q, |
1189 | WLCORE_QUEUE_STOP_REASON_WATERMARK))) { | 1203 | WLCORE_QUEUE_STOP_REASON_WATERMARK))) { |
1190 | wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d", hlid, q); | 1204 | wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d", hlid, q); |
1191 | ieee80211_free_txskb(hw, skb); | 1205 | ieee80211_free_txskb(hw, skb); |
@@ -1197,16 +1211,17 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, | |||
1197 | skb_queue_tail(&wl->links[hlid].tx_queue[q], skb); | 1211 | skb_queue_tail(&wl->links[hlid].tx_queue[q], skb); |
1198 | 1212 | ||
1199 | wl->tx_queue_count[q]++; | 1213 | wl->tx_queue_count[q]++; |
1214 | wlvif->tx_queue_count[q]++; | ||
1200 | 1215 | ||
1201 | /* | 1216 | /* |
1202 | * The workqueue is slow to process the tx_queue and we need stop | 1217 | * The workqueue is slow to process the tx_queue and we need stop |
1203 | * the queue here, otherwise the queue will get too long. | 1218 | * the queue here, otherwise the queue will get too long. |
1204 | */ | 1219 | */ |
1205 | if (wl->tx_queue_count[q] >= WL1271_TX_QUEUE_HIGH_WATERMARK && | 1220 | if (wlvif->tx_queue_count[q] >= WL1271_TX_QUEUE_HIGH_WATERMARK && |
1206 | !wlcore_is_queue_stopped_by_reason(wl, q, | 1221 | !wlcore_is_queue_stopped_by_reason_locked(wl, wlvif, q, |
1207 | WLCORE_QUEUE_STOP_REASON_WATERMARK)) { | 1222 | WLCORE_QUEUE_STOP_REASON_WATERMARK)) { |
1208 | wl1271_debug(DEBUG_TX, "op_tx: stopping queues for q %d", q); | 1223 | wl1271_debug(DEBUG_TX, "op_tx: stopping queues for q %d", q); |
1209 | wlcore_stop_queue_locked(wl, q, | 1224 | wlcore_stop_queue_locked(wl, wlvif, q, |
1210 | WLCORE_QUEUE_STOP_REASON_WATERMARK); | 1225 | WLCORE_QUEUE_STOP_REASON_WATERMARK); |
1211 | } | 1226 | } |
1212 | 1227 | ||
@@ -1841,11 +1856,10 @@ static void wlcore_op_stop_locked(struct wl1271 *wl) | |||
1841 | cancel_work_sync(&wl->tx_work); | 1856 | cancel_work_sync(&wl->tx_work); |
1842 | cancel_delayed_work_sync(&wl->elp_work); | 1857 | cancel_delayed_work_sync(&wl->elp_work); |
1843 | cancel_delayed_work_sync(&wl->tx_watchdog_work); | 1858 | cancel_delayed_work_sync(&wl->tx_watchdog_work); |
1844 | cancel_delayed_work_sync(&wl->connection_loss_work); | ||
1845 | 1859 | ||
1846 | /* let's notify MAC80211 about the remaining pending TX frames */ | 1860 | /* let's notify MAC80211 about the remaining pending TX frames */ |
1847 | wl12xx_tx_reset(wl); | ||
1848 | mutex_lock(&wl->mutex); | 1861 | mutex_lock(&wl->mutex); |
1862 | wl12xx_tx_reset(wl); | ||
1849 | 1863 | ||
1850 | wl1271_power_off(wl); | 1864 | wl1271_power_off(wl); |
1851 | /* | 1865 | /* |
@@ -1868,14 +1882,17 @@ static void wlcore_op_stop_locked(struct wl1271 *wl) | |||
1868 | wl->time_offset = 0; | 1882 | wl->time_offset = 0; |
1869 | wl->ap_fw_ps_map = 0; | 1883 | wl->ap_fw_ps_map = 0; |
1870 | wl->ap_ps_map = 0; | 1884 | wl->ap_ps_map = 0; |
1871 | wl->sched_scanning = false; | ||
1872 | wl->sleep_auth = WL1271_PSM_ILLEGAL; | 1885 | wl->sleep_auth = WL1271_PSM_ILLEGAL; |
1873 | memset(wl->roles_map, 0, sizeof(wl->roles_map)); | 1886 | memset(wl->roles_map, 0, sizeof(wl->roles_map)); |
1874 | memset(wl->links_map, 0, sizeof(wl->links_map)); | 1887 | memset(wl->links_map, 0, sizeof(wl->links_map)); |
1875 | memset(wl->roc_map, 0, sizeof(wl->roc_map)); | 1888 | memset(wl->roc_map, 0, sizeof(wl->roc_map)); |
1889 | memset(wl->session_ids, 0, sizeof(wl->session_ids)); | ||
1876 | wl->active_sta_count = 0; | 1890 | wl->active_sta_count = 0; |
1891 | wl->active_link_count = 0; | ||
1877 | 1892 | ||
1878 | /* The system link is always allocated */ | 1893 | /* The system link is always allocated */ |
1894 | wl->links[WL12XX_SYSTEM_HLID].allocated_pkts = 0; | ||
1895 | wl->links[WL12XX_SYSTEM_HLID].prev_freed_pkts = 0; | ||
1879 | __set_bit(WL12XX_SYSTEM_HLID, wl->links_map); | 1896 | __set_bit(WL12XX_SYSTEM_HLID, wl->links_map); |
1880 | 1897 | ||
1881 | /* | 1898 | /* |
@@ -1901,6 +1918,12 @@ static void wlcore_op_stop_locked(struct wl1271 *wl) | |||
1901 | wl->tx_res_if = NULL; | 1918 | wl->tx_res_if = NULL; |
1902 | kfree(wl->target_mem_map); | 1919 | kfree(wl->target_mem_map); |
1903 | wl->target_mem_map = NULL; | 1920 | wl->target_mem_map = NULL; |
1921 | |||
1922 | /* | ||
1923 | * FW channels must be re-calibrated after recovery, | ||
1924 | * clear the last Reg-Domain channel configuration. | ||
1925 | */ | ||
1926 | memset(wl->reg_ch_conf_last, 0, sizeof(wl->reg_ch_conf_last)); | ||
1904 | } | 1927 | } |
1905 | 1928 | ||
1906 | static void wlcore_op_stop(struct ieee80211_hw *hw) | 1929 | static void wlcore_op_stop(struct ieee80211_hw *hw) |
@@ -1916,6 +1939,71 @@ static void wlcore_op_stop(struct ieee80211_hw *hw) | |||
1916 | mutex_unlock(&wl->mutex); | 1939 | mutex_unlock(&wl->mutex); |
1917 | } | 1940 | } |
1918 | 1941 | ||
1942 | static void wlcore_channel_switch_work(struct work_struct *work) | ||
1943 | { | ||
1944 | struct delayed_work *dwork; | ||
1945 | struct wl1271 *wl; | ||
1946 | struct ieee80211_vif *vif; | ||
1947 | struct wl12xx_vif *wlvif; | ||
1948 | int ret; | ||
1949 | |||
1950 | dwork = container_of(work, struct delayed_work, work); | ||
1951 | wlvif = container_of(dwork, struct wl12xx_vif, channel_switch_work); | ||
1952 | wl = wlvif->wl; | ||
1953 | |||
1954 | wl1271_info("channel switch failed (role_id: %d).", wlvif->role_id); | ||
1955 | |||
1956 | mutex_lock(&wl->mutex); | ||
1957 | |||
1958 | if (unlikely(wl->state != WLCORE_STATE_ON)) | ||
1959 | goto out; | ||
1960 | |||
1961 | /* check the channel switch is still ongoing */ | ||
1962 | if (!test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags)) | ||
1963 | goto out; | ||
1964 | |||
1965 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
1966 | ieee80211_chswitch_done(vif, false); | ||
1967 | |||
1968 | ret = wl1271_ps_elp_wakeup(wl); | ||
1969 | if (ret < 0) | ||
1970 | goto out; | ||
1971 | |||
1972 | wl12xx_cmd_stop_channel_switch(wl, wlvif); | ||
1973 | |||
1974 | wl1271_ps_elp_sleep(wl); | ||
1975 | out: | ||
1976 | mutex_unlock(&wl->mutex); | ||
1977 | } | ||
1978 | |||
1979 | static void wlcore_connection_loss_work(struct work_struct *work) | ||
1980 | { | ||
1981 | struct delayed_work *dwork; | ||
1982 | struct wl1271 *wl; | ||
1983 | struct ieee80211_vif *vif; | ||
1984 | struct wl12xx_vif *wlvif; | ||
1985 | |||
1986 | dwork = container_of(work, struct delayed_work, work); | ||
1987 | wlvif = container_of(dwork, struct wl12xx_vif, connection_loss_work); | ||
1988 | wl = wlvif->wl; | ||
1989 | |||
1990 | wl1271_info("Connection loss work (role_id: %d).", wlvif->role_id); | ||
1991 | |||
1992 | mutex_lock(&wl->mutex); | ||
1993 | |||
1994 | if (unlikely(wl->state != WLCORE_STATE_ON)) | ||
1995 | goto out; | ||
1996 | |||
1997 | /* Call mac80211 connection loss */ | ||
1998 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | ||
1999 | goto out; | ||
2000 | |||
2001 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
2002 | ieee80211_connection_loss(vif); | ||
2003 | out: | ||
2004 | mutex_unlock(&wl->mutex); | ||
2005 | } | ||
2006 | |||
1919 | static int wl12xx_allocate_rate_policy(struct wl1271 *wl, u8 *idx) | 2007 | static int wl12xx_allocate_rate_policy(struct wl1271 *wl, u8 *idx) |
1920 | { | 2008 | { |
1921 | u8 policy = find_first_zero_bit(wl->rate_policies_map, | 2009 | u8 policy = find_first_zero_bit(wl->rate_policies_map, |
@@ -2035,15 +2123,15 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) | |||
2035 | for (i = 0; i < CONF_TX_MAX_AC_COUNT; i++) | 2123 | for (i = 0; i < CONF_TX_MAX_AC_COUNT; i++) |
2036 | wl12xx_allocate_rate_policy(wl, | 2124 | wl12xx_allocate_rate_policy(wl, |
2037 | &wlvif->ap.ucast_rate_idx[i]); | 2125 | &wlvif->ap.ucast_rate_idx[i]); |
2038 | wlvif->basic_rate_set = CONF_TX_AP_ENABLED_RATES; | 2126 | wlvif->basic_rate_set = CONF_TX_ENABLED_RATES; |
2039 | /* | 2127 | /* |
2040 | * TODO: check if basic_rate shouldn't be | 2128 | * TODO: check if basic_rate shouldn't be |
2041 | * wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); | 2129 | * wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); |
2042 | * instead (the same thing for STA above). | 2130 | * instead (the same thing for STA above). |
2043 | */ | 2131 | */ |
2044 | wlvif->basic_rate = CONF_TX_AP_ENABLED_RATES; | 2132 | wlvif->basic_rate = CONF_TX_ENABLED_RATES; |
2045 | /* TODO: this seems to be used only for STA, check it */ | 2133 | /* TODO: this seems to be used only for STA, check it */ |
2046 | wlvif->rate_set = CONF_TX_AP_ENABLED_RATES; | 2134 | wlvif->rate_set = CONF_TX_ENABLED_RATES; |
2047 | } | 2135 | } |
2048 | 2136 | ||
2049 | wlvif->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; | 2137 | wlvif->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; |
@@ -2063,6 +2151,10 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) | |||
2063 | wl1271_rx_streaming_enable_work); | 2151 | wl1271_rx_streaming_enable_work); |
2064 | INIT_WORK(&wlvif->rx_streaming_disable_work, | 2152 | INIT_WORK(&wlvif->rx_streaming_disable_work, |
2065 | wl1271_rx_streaming_disable_work); | 2153 | wl1271_rx_streaming_disable_work); |
2154 | INIT_DELAYED_WORK(&wlvif->channel_switch_work, | ||
2155 | wlcore_channel_switch_work); | ||
2156 | INIT_DELAYED_WORK(&wlvif->connection_loss_work, | ||
2157 | wlcore_connection_loss_work); | ||
2066 | INIT_LIST_HEAD(&wlvif->list); | 2158 | INIT_LIST_HEAD(&wlvif->list); |
2067 | 2159 | ||
2068 | setup_timer(&wlvif->rx_streaming_timer, wl1271_rx_streaming_timer, | 2160 | setup_timer(&wlvif->rx_streaming_timer, wl1271_rx_streaming_timer, |
@@ -2196,6 +2288,81 @@ static void wl12xx_force_active_psm(struct wl1271 *wl) | |||
2196 | } | 2288 | } |
2197 | } | 2289 | } |
2198 | 2290 | ||
2291 | struct wlcore_hw_queue_iter_data { | ||
2292 | unsigned long hw_queue_map[BITS_TO_LONGS(WLCORE_NUM_MAC_ADDRESSES)]; | ||
2293 | /* current vif */ | ||
2294 | struct ieee80211_vif *vif; | ||
2295 | /* is the current vif among those iterated */ | ||
2296 | bool cur_running; | ||
2297 | }; | ||
2298 | |||
2299 | static void wlcore_hw_queue_iter(void *data, u8 *mac, | ||
2300 | struct ieee80211_vif *vif) | ||
2301 | { | ||
2302 | struct wlcore_hw_queue_iter_data *iter_data = data; | ||
2303 | |||
2304 | if (WARN_ON_ONCE(vif->hw_queue[0] == IEEE80211_INVAL_HW_QUEUE)) | ||
2305 | return; | ||
2306 | |||
2307 | if (iter_data->cur_running || vif == iter_data->vif) { | ||
2308 | iter_data->cur_running = true; | ||
2309 | return; | ||
2310 | } | ||
2311 | |||
2312 | __set_bit(vif->hw_queue[0] / NUM_TX_QUEUES, iter_data->hw_queue_map); | ||
2313 | } | ||
2314 | |||
2315 | static int wlcore_allocate_hw_queue_base(struct wl1271 *wl, | ||
2316 | struct wl12xx_vif *wlvif) | ||
2317 | { | ||
2318 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); | ||
2319 | struct wlcore_hw_queue_iter_data iter_data = {}; | ||
2320 | int i, q_base; | ||
2321 | |||
2322 | iter_data.vif = vif; | ||
2323 | |||
2324 | /* mark all bits taken by active interfaces */ | ||
2325 | ieee80211_iterate_active_interfaces_atomic(wl->hw, | ||
2326 | IEEE80211_IFACE_ITER_RESUME_ALL, | ||
2327 | wlcore_hw_queue_iter, &iter_data); | ||
2328 | |||
2329 | /* the current vif is already running in mac80211 (resume/recovery) */ | ||
2330 | if (iter_data.cur_running) { | ||
2331 | wlvif->hw_queue_base = vif->hw_queue[0]; | ||
2332 | wl1271_debug(DEBUG_MAC80211, | ||
2333 | "using pre-allocated hw queue base %d", | ||
2334 | wlvif->hw_queue_base); | ||
2335 | |||
2336 | /* interface type might have changed type */ | ||
2337 | goto adjust_cab_queue; | ||
2338 | } | ||
2339 | |||
2340 | q_base = find_first_zero_bit(iter_data.hw_queue_map, | ||
2341 | WLCORE_NUM_MAC_ADDRESSES); | ||
2342 | if (q_base >= WLCORE_NUM_MAC_ADDRESSES) | ||
2343 | return -EBUSY; | ||
2344 | |||
2345 | wlvif->hw_queue_base = q_base * NUM_TX_QUEUES; | ||
2346 | wl1271_debug(DEBUG_MAC80211, "allocating hw queue base: %d", | ||
2347 | wlvif->hw_queue_base); | ||
2348 | |||
2349 | for (i = 0; i < NUM_TX_QUEUES; i++) { | ||
2350 | wl->queue_stop_reasons[wlvif->hw_queue_base + i] = 0; | ||
2351 | /* register hw queues in mac80211 */ | ||
2352 | vif->hw_queue[i] = wlvif->hw_queue_base + i; | ||
2353 | } | ||
2354 | |||
2355 | adjust_cab_queue: | ||
2356 | /* the last places are reserved for cab queues per interface */ | ||
2357 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) | ||
2358 | vif->cab_queue = NUM_TX_QUEUES * WLCORE_NUM_MAC_ADDRESSES + | ||
2359 | wlvif->hw_queue_base / NUM_TX_QUEUES; | ||
2360 | else | ||
2361 | vif->cab_queue = IEEE80211_INVAL_HW_QUEUE; | ||
2362 | |||
2363 | return 0; | ||
2364 | } | ||
2365 | |||
2199 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, | 2366 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, |
2200 | struct ieee80211_vif *vif) | 2367 | struct ieee80211_vif *vif) |
2201 | { | 2368 | { |
@@ -2242,6 +2409,10 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
2242 | goto out; | 2409 | goto out; |
2243 | } | 2410 | } |
2244 | 2411 | ||
2412 | ret = wlcore_allocate_hw_queue_base(wl, wlvif); | ||
2413 | if (ret < 0) | ||
2414 | goto out; | ||
2415 | |||
2245 | if (wl12xx_need_fw_change(wl, vif_count, true)) { | 2416 | if (wl12xx_need_fw_change(wl, vif_count, true)) { |
2246 | wl12xx_force_active_psm(wl); | 2417 | wl12xx_force_active_psm(wl); |
2247 | set_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags); | 2418 | set_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags); |
@@ -2312,7 +2483,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, | |||
2312 | wl1271_info("down"); | 2483 | wl1271_info("down"); |
2313 | 2484 | ||
2314 | if (wl->scan.state != WL1271_SCAN_STATE_IDLE && | 2485 | if (wl->scan.state != WL1271_SCAN_STATE_IDLE && |
2315 | wl->scan_vif == vif) { | 2486 | wl->scan_wlvif == wlvif) { |
2316 | /* | 2487 | /* |
2317 | * Rearm the tx watchdog just before idling scan. This | 2488 | * Rearm the tx watchdog just before idling scan. This |
2318 | * prevents just-finished scans from triggering the watchdog | 2489 | * prevents just-finished scans from triggering the watchdog |
@@ -2321,11 +2492,21 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, | |||
2321 | 2492 | ||
2322 | wl->scan.state = WL1271_SCAN_STATE_IDLE; | 2493 | wl->scan.state = WL1271_SCAN_STATE_IDLE; |
2323 | memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); | 2494 | memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); |
2324 | wl->scan_vif = NULL; | 2495 | wl->scan_wlvif = NULL; |
2325 | wl->scan.req = NULL; | 2496 | wl->scan.req = NULL; |
2326 | ieee80211_scan_completed(wl->hw, true); | 2497 | ieee80211_scan_completed(wl->hw, true); |
2327 | } | 2498 | } |
2328 | 2499 | ||
2500 | if (wl->sched_vif == wlvif) { | ||
2501 | ieee80211_sched_scan_stopped(wl->hw); | ||
2502 | wl->sched_vif = NULL; | ||
2503 | } | ||
2504 | |||
2505 | if (wl->roc_vif == vif) { | ||
2506 | wl->roc_vif = NULL; | ||
2507 | ieee80211_remain_on_channel_expired(wl->hw); | ||
2508 | } | ||
2509 | |||
2329 | if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) { | 2510 | if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) { |
2330 | /* disable active roles */ | 2511 | /* disable active roles */ |
2331 | ret = wl1271_ps_elp_wakeup(wl); | 2512 | ret = wl1271_ps_elp_wakeup(wl); |
@@ -2394,9 +2575,6 @@ deinit: | |||
2394 | /* Configure for power according to debugfs */ | 2575 | /* Configure for power according to debugfs */ |
2395 | if (sta_auth != WL1271_PSM_ILLEGAL) | 2576 | if (sta_auth != WL1271_PSM_ILLEGAL) |
2396 | wl1271_acx_sleep_auth(wl, sta_auth); | 2577 | wl1271_acx_sleep_auth(wl, sta_auth); |
2397 | /* Configure for power always on */ | ||
2398 | else if (wl->quirks & WLCORE_QUIRK_NO_ELP) | ||
2399 | wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | ||
2400 | /* Configure for ELP power saving */ | 2578 | /* Configure for ELP power saving */ |
2401 | else | 2579 | else |
2402 | wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP); | 2580 | wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP); |
@@ -2408,6 +2586,7 @@ unlock: | |||
2408 | del_timer_sync(&wlvif->rx_streaming_timer); | 2586 | del_timer_sync(&wlvif->rx_streaming_timer); |
2409 | cancel_work_sync(&wlvif->rx_streaming_enable_work); | 2587 | cancel_work_sync(&wlvif->rx_streaming_enable_work); |
2410 | cancel_work_sync(&wlvif->rx_streaming_disable_work); | 2588 | cancel_work_sync(&wlvif->rx_streaming_disable_work); |
2589 | cancel_delayed_work_sync(&wlvif->connection_loss_work); | ||
2411 | 2590 | ||
2412 | mutex_lock(&wl->mutex); | 2591 | mutex_lock(&wl->mutex); |
2413 | } | 2592 | } |
@@ -2466,8 +2645,7 @@ static int wl12xx_op_change_interface(struct ieee80211_hw *hw, | |||
2466 | return ret; | 2645 | return ret; |
2467 | } | 2646 | } |
2468 | 2647 | ||
2469 | static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 2648 | static int wlcore_join(struct wl1271 *wl, struct wl12xx_vif *wlvif) |
2470 | bool set_assoc) | ||
2471 | { | 2649 | { |
2472 | int ret; | 2650 | int ret; |
2473 | bool is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS); | 2651 | bool is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS); |
@@ -2487,18 +2665,111 @@ static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
2487 | /* clear encryption type */ | 2665 | /* clear encryption type */ |
2488 | wlvif->encryption_type = KEY_NONE; | 2666 | wlvif->encryption_type = KEY_NONE; |
2489 | 2667 | ||
2490 | if (set_assoc) | ||
2491 | set_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags); | ||
2492 | |||
2493 | if (is_ibss) | 2668 | if (is_ibss) |
2494 | ret = wl12xx_cmd_role_start_ibss(wl, wlvif); | 2669 | ret = wl12xx_cmd_role_start_ibss(wl, wlvif); |
2495 | else | 2670 | else { |
2671 | if (wl->quirks & WLCORE_QUIRK_START_STA_FAILS) { | ||
2672 | /* | ||
2673 | * TODO: this is an ugly workaround for wl12xx fw | ||
2674 | * bug - we are not able to tx/rx after the first | ||
2675 | * start_sta, so make dummy start+stop calls, | ||
2676 | * and then call start_sta again. | ||
2677 | * this should be fixed in the fw. | ||
2678 | */ | ||
2679 | wl12xx_cmd_role_start_sta(wl, wlvif); | ||
2680 | wl12xx_cmd_role_stop_sta(wl, wlvif); | ||
2681 | } | ||
2682 | |||
2496 | ret = wl12xx_cmd_role_start_sta(wl, wlvif); | 2683 | ret = wl12xx_cmd_role_start_sta(wl, wlvif); |
2684 | } | ||
2685 | |||
2686 | return ret; | ||
2687 | } | ||
2688 | |||
2689 | static int wl1271_ssid_set(struct wl12xx_vif *wlvif, struct sk_buff *skb, | ||
2690 | int offset) | ||
2691 | { | ||
2692 | u8 ssid_len; | ||
2693 | const u8 *ptr = cfg80211_find_ie(WLAN_EID_SSID, skb->data + offset, | ||
2694 | skb->len - offset); | ||
2695 | |||
2696 | if (!ptr) { | ||
2697 | wl1271_error("No SSID in IEs!"); | ||
2698 | return -ENOENT; | ||
2699 | } | ||
2700 | |||
2701 | ssid_len = ptr[1]; | ||
2702 | if (ssid_len > IEEE80211_MAX_SSID_LEN) { | ||
2703 | wl1271_error("SSID is too long!"); | ||
2704 | return -EINVAL; | ||
2705 | } | ||
2706 | |||
2707 | wlvif->ssid_len = ssid_len; | ||
2708 | memcpy(wlvif->ssid, ptr+2, ssid_len); | ||
2709 | return 0; | ||
2710 | } | ||
2711 | |||
2712 | static int wlcore_set_ssid(struct wl1271 *wl, struct wl12xx_vif *wlvif) | ||
2713 | { | ||
2714 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); | ||
2715 | struct sk_buff *skb; | ||
2716 | int ieoffset; | ||
2717 | |||
2718 | /* we currently only support setting the ssid from the ap probe req */ | ||
2719 | if (wlvif->bss_type != BSS_TYPE_STA_BSS) | ||
2720 | return -EINVAL; | ||
2721 | |||
2722 | skb = ieee80211_ap_probereq_get(wl->hw, vif); | ||
2723 | if (!skb) | ||
2724 | return -EINVAL; | ||
2725 | |||
2726 | ieoffset = offsetof(struct ieee80211_mgmt, | ||
2727 | u.probe_req.variable); | ||
2728 | wl1271_ssid_set(wlvif, skb, ieoffset); | ||
2729 | dev_kfree_skb(skb); | ||
2730 | |||
2731 | return 0; | ||
2732 | } | ||
2733 | |||
2734 | static int wlcore_set_assoc(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
2735 | struct ieee80211_bss_conf *bss_conf, | ||
2736 | u32 sta_rate_set) | ||
2737 | { | ||
2738 | int ieoffset; | ||
2739 | int ret; | ||
2740 | |||
2741 | wlvif->aid = bss_conf->aid; | ||
2742 | wlvif->channel_type = cfg80211_get_chandef_type(&bss_conf->chandef); | ||
2743 | wlvif->beacon_int = bss_conf->beacon_int; | ||
2744 | wlvif->wmm_enabled = bss_conf->qos; | ||
2745 | |||
2746 | set_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags); | ||
2747 | |||
2748 | /* | ||
2749 | * with wl1271, we don't need to update the | ||
2750 | * beacon_int and dtim_period, because the firmware | ||
2751 | * updates it by itself when the first beacon is | ||
2752 | * received after a join. | ||
2753 | */ | ||
2754 | ret = wl1271_cmd_build_ps_poll(wl, wlvif, wlvif->aid); | ||
2497 | if (ret < 0) | 2755 | if (ret < 0) |
2498 | goto out; | 2756 | return ret; |
2499 | 2757 | ||
2500 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | 2758 | /* |
2501 | goto out; | 2759 | * Get a template for hardware connection maintenance |
2760 | */ | ||
2761 | dev_kfree_skb(wlvif->probereq); | ||
2762 | wlvif->probereq = wl1271_cmd_build_ap_probe_req(wl, | ||
2763 | wlvif, | ||
2764 | NULL); | ||
2765 | ieoffset = offsetof(struct ieee80211_mgmt, | ||
2766 | u.probe_req.variable); | ||
2767 | wl1271_ssid_set(wlvif, wlvif->probereq, ieoffset); | ||
2768 | |||
2769 | /* enable the connection monitoring feature */ | ||
2770 | ret = wl1271_acx_conn_monit_params(wl, wlvif, true); | ||
2771 | if (ret < 0) | ||
2772 | return ret; | ||
2502 | 2773 | ||
2503 | /* | 2774 | /* |
2504 | * The join command disable the keep-alive mode, shut down its process, | 2775 | * The join command disable the keep-alive mode, shut down its process, |
@@ -2508,35 +2779,83 @@ static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
2508 | */ | 2779 | */ |
2509 | ret = wl1271_acx_keep_alive_mode(wl, wlvif, true); | 2780 | ret = wl1271_acx_keep_alive_mode(wl, wlvif, true); |
2510 | if (ret < 0) | 2781 | if (ret < 0) |
2511 | goto out; | 2782 | return ret; |
2512 | 2783 | ||
2513 | ret = wl1271_acx_aid(wl, wlvif, wlvif->aid); | 2784 | ret = wl1271_acx_aid(wl, wlvif, wlvif->aid); |
2514 | if (ret < 0) | 2785 | if (ret < 0) |
2515 | goto out; | 2786 | return ret; |
2516 | 2787 | ||
2517 | ret = wl12xx_cmd_build_klv_null_data(wl, wlvif); | 2788 | ret = wl12xx_cmd_build_klv_null_data(wl, wlvif); |
2518 | if (ret < 0) | 2789 | if (ret < 0) |
2519 | goto out; | 2790 | return ret; |
2520 | 2791 | ||
2521 | ret = wl1271_acx_keep_alive_config(wl, wlvif, | 2792 | ret = wl1271_acx_keep_alive_config(wl, wlvif, |
2522 | wlvif->sta.klv_template_id, | 2793 | wlvif->sta.klv_template_id, |
2523 | ACX_KEEP_ALIVE_TPL_VALID); | 2794 | ACX_KEEP_ALIVE_TPL_VALID); |
2524 | if (ret < 0) | 2795 | if (ret < 0) |
2525 | goto out; | 2796 | return ret; |
2797 | |||
2798 | /* | ||
2799 | * The default fw psm configuration is AUTO, while mac80211 default | ||
2800 | * setting is off (ACTIVE), so sync the fw with the correct value. | ||
2801 | */ | ||
2802 | ret = wl1271_ps_set_mode(wl, wlvif, STATION_ACTIVE_MODE); | ||
2803 | if (ret < 0) | ||
2804 | return ret; | ||
2805 | |||
2806 | if (sta_rate_set) { | ||
2807 | wlvif->rate_set = | ||
2808 | wl1271_tx_enabled_rates_get(wl, | ||
2809 | sta_rate_set, | ||
2810 | wlvif->band); | ||
2811 | ret = wl1271_acx_sta_rate_policies(wl, wlvif); | ||
2812 | if (ret < 0) | ||
2813 | return ret; | ||
2814 | } | ||
2526 | 2815 | ||
2527 | out: | ||
2528 | return ret; | 2816 | return ret; |
2529 | } | 2817 | } |
2530 | 2818 | ||
2531 | static int wl1271_unjoin(struct wl1271 *wl, struct wl12xx_vif *wlvif) | 2819 | static int wlcore_unset_assoc(struct wl1271 *wl, struct wl12xx_vif *wlvif) |
2532 | { | 2820 | { |
2533 | int ret; | 2821 | int ret; |
2822 | bool sta = wlvif->bss_type == BSS_TYPE_STA_BSS; | ||
2823 | |||
2824 | /* make sure we are connected (sta) joined */ | ||
2825 | if (sta && | ||
2826 | !test_and_clear_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | ||
2827 | return false; | ||
2828 | |||
2829 | /* make sure we are joined (ibss) */ | ||
2830 | if (!sta && | ||
2831 | test_and_clear_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags)) | ||
2832 | return false; | ||
2833 | |||
2834 | if (sta) { | ||
2835 | /* use defaults when not associated */ | ||
2836 | wlvif->aid = 0; | ||
2837 | |||
2838 | /* free probe-request template */ | ||
2839 | dev_kfree_skb(wlvif->probereq); | ||
2840 | wlvif->probereq = NULL; | ||
2841 | |||
2842 | /* disable connection monitor features */ | ||
2843 | ret = wl1271_acx_conn_monit_params(wl, wlvif, false); | ||
2844 | if (ret < 0) | ||
2845 | return ret; | ||
2846 | |||
2847 | /* Disable the keep-alive feature */ | ||
2848 | ret = wl1271_acx_keep_alive_mode(wl, wlvif, false); | ||
2849 | if (ret < 0) | ||
2850 | return ret; | ||
2851 | } | ||
2534 | 2852 | ||
2535 | if (test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags)) { | 2853 | if (test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags)) { |
2536 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); | 2854 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); |
2537 | 2855 | ||
2538 | wl12xx_cmd_stop_channel_switch(wl); | 2856 | wl12xx_cmd_stop_channel_switch(wl, wlvif); |
2539 | ieee80211_chswitch_done(vif, false); | 2857 | ieee80211_chswitch_done(vif, false); |
2858 | cancel_delayed_work(&wlvif->channel_switch_work); | ||
2540 | } | 2859 | } |
2541 | 2860 | ||
2542 | /* invalidate keep-alive template */ | 2861 | /* invalidate keep-alive template */ |
@@ -2544,17 +2863,11 @@ static int wl1271_unjoin(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
2544 | wlvif->sta.klv_template_id, | 2863 | wlvif->sta.klv_template_id, |
2545 | ACX_KEEP_ALIVE_TPL_INVALID); | 2864 | ACX_KEEP_ALIVE_TPL_INVALID); |
2546 | 2865 | ||
2547 | /* to stop listening to a channel, we disconnect */ | ||
2548 | ret = wl12xx_cmd_role_stop_sta(wl, wlvif); | ||
2549 | if (ret < 0) | ||
2550 | goto out; | ||
2551 | |||
2552 | /* reset TX security counters on a clean disconnect */ | 2866 | /* reset TX security counters on a clean disconnect */ |
2553 | wlvif->tx_security_last_seq_lsb = 0; | 2867 | wlvif->tx_security_last_seq_lsb = 0; |
2554 | wlvif->tx_security_seq = 0; | 2868 | wlvif->tx_security_seq = 0; |
2555 | 2869 | ||
2556 | out: | 2870 | return 0; |
2557 | return ret; | ||
2558 | } | 2871 | } |
2559 | 2872 | ||
2560 | static void wl1271_set_band_rate(struct wl1271 *wl, struct wl12xx_vif *wlvif) | 2873 | static void wl1271_set_band_rate(struct wl1271 *wl, struct wl12xx_vif *wlvif) |
@@ -2563,147 +2876,10 @@ static void wl1271_set_band_rate(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
2563 | wlvif->rate_set = wlvif->basic_rate_set; | 2876 | wlvif->rate_set = wlvif->basic_rate_set; |
2564 | } | 2877 | } |
2565 | 2878 | ||
2566 | static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
2567 | bool idle) | ||
2568 | { | ||
2569 | int ret; | ||
2570 | bool cur_idle = !test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags); | ||
2571 | |||
2572 | if (idle == cur_idle) | ||
2573 | return 0; | ||
2574 | |||
2575 | if (idle) { | ||
2576 | /* no need to croc if we weren't busy (e.g. during boot) */ | ||
2577 | if (wl12xx_dev_role_started(wlvif)) { | ||
2578 | ret = wl12xx_stop_dev(wl, wlvif); | ||
2579 | if (ret < 0) | ||
2580 | goto out; | ||
2581 | } | ||
2582 | wlvif->rate_set = | ||
2583 | wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); | ||
2584 | ret = wl1271_acx_sta_rate_policies(wl, wlvif); | ||
2585 | if (ret < 0) | ||
2586 | goto out; | ||
2587 | clear_bit(WLVIF_FLAG_IN_USE, &wlvif->flags); | ||
2588 | } else { | ||
2589 | /* The current firmware only supports sched_scan in idle */ | ||
2590 | if (wl->sched_scanning) { | ||
2591 | wl1271_scan_sched_scan_stop(wl, wlvif); | ||
2592 | ieee80211_sched_scan_stopped(wl->hw); | ||
2593 | } | ||
2594 | |||
2595 | ret = wl12xx_start_dev(wl, wlvif); | ||
2596 | if (ret < 0) | ||
2597 | goto out; | ||
2598 | set_bit(WLVIF_FLAG_IN_USE, &wlvif->flags); | ||
2599 | } | ||
2600 | |||
2601 | out: | ||
2602 | return ret; | ||
2603 | } | ||
2604 | |||
2605 | static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 2879 | static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
2606 | struct ieee80211_conf *conf, u32 changed) | 2880 | struct ieee80211_conf *conf, u32 changed) |
2607 | { | 2881 | { |
2608 | bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); | 2882 | int ret; |
2609 | int channel, ret; | ||
2610 | |||
2611 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); | ||
2612 | |||
2613 | /* if the channel changes while joined, join again */ | ||
2614 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL && | ||
2615 | ((wlvif->band != conf->channel->band) || | ||
2616 | (wlvif->channel != channel) || | ||
2617 | (wlvif->channel_type != conf->channel_type))) { | ||
2618 | /* send all pending packets */ | ||
2619 | ret = wlcore_tx_work_locked(wl); | ||
2620 | if (ret < 0) | ||
2621 | return ret; | ||
2622 | |||
2623 | wlvif->band = conf->channel->band; | ||
2624 | wlvif->channel = channel; | ||
2625 | wlvif->channel_type = conf->channel_type; | ||
2626 | |||
2627 | if (is_ap) { | ||
2628 | wl1271_set_band_rate(wl, wlvif); | ||
2629 | ret = wl1271_init_ap_rates(wl, wlvif); | ||
2630 | if (ret < 0) | ||
2631 | wl1271_error("AP rate policy change failed %d", | ||
2632 | ret); | ||
2633 | } else { | ||
2634 | /* | ||
2635 | * FIXME: the mac80211 should really provide a fixed | ||
2636 | * rate to use here. for now, just use the smallest | ||
2637 | * possible rate for the band as a fixed rate for | ||
2638 | * association frames and other control messages. | ||
2639 | */ | ||
2640 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | ||
2641 | wl1271_set_band_rate(wl, wlvif); | ||
2642 | |||
2643 | wlvif->basic_rate = | ||
2644 | wl1271_tx_min_rate_get(wl, | ||
2645 | wlvif->basic_rate_set); | ||
2646 | ret = wl1271_acx_sta_rate_policies(wl, wlvif); | ||
2647 | if (ret < 0) | ||
2648 | wl1271_warning("rate policy for channel " | ||
2649 | "failed %d", ret); | ||
2650 | |||
2651 | /* | ||
2652 | * change the ROC channel. do it only if we are | ||
2653 | * not idle. otherwise, CROC will be called | ||
2654 | * anyway. | ||
2655 | */ | ||
2656 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, | ||
2657 | &wlvif->flags) && | ||
2658 | wl12xx_dev_role_started(wlvif) && | ||
2659 | !(conf->flags & IEEE80211_CONF_IDLE)) { | ||
2660 | ret = wl12xx_stop_dev(wl, wlvif); | ||
2661 | if (ret < 0) | ||
2662 | return ret; | ||
2663 | |||
2664 | ret = wl12xx_start_dev(wl, wlvif); | ||
2665 | if (ret < 0) | ||
2666 | return ret; | ||
2667 | } | ||
2668 | } | ||
2669 | } | ||
2670 | |||
2671 | if ((changed & IEEE80211_CONF_CHANGE_PS) && !is_ap) { | ||
2672 | |||
2673 | if ((conf->flags & IEEE80211_CONF_PS) && | ||
2674 | test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) && | ||
2675 | !test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags)) { | ||
2676 | |||
2677 | int ps_mode; | ||
2678 | char *ps_mode_str; | ||
2679 | |||
2680 | if (wl->conf.conn.forced_ps) { | ||
2681 | ps_mode = STATION_POWER_SAVE_MODE; | ||
2682 | ps_mode_str = "forced"; | ||
2683 | } else { | ||
2684 | ps_mode = STATION_AUTO_PS_MODE; | ||
2685 | ps_mode_str = "auto"; | ||
2686 | } | ||
2687 | |||
2688 | wl1271_debug(DEBUG_PSM, "%s ps enabled", ps_mode_str); | ||
2689 | |||
2690 | ret = wl1271_ps_set_mode(wl, wlvif, ps_mode); | ||
2691 | |||
2692 | if (ret < 0) | ||
2693 | wl1271_warning("enter %s ps failed %d", | ||
2694 | ps_mode_str, ret); | ||
2695 | |||
2696 | } else if (!(conf->flags & IEEE80211_CONF_PS) && | ||
2697 | test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags)) { | ||
2698 | |||
2699 | wl1271_debug(DEBUG_PSM, "auto ps disabled"); | ||
2700 | |||
2701 | ret = wl1271_ps_set_mode(wl, wlvif, | ||
2702 | STATION_ACTIVE_MODE); | ||
2703 | if (ret < 0) | ||
2704 | wl1271_warning("exit auto ps failed %d", ret); | ||
2705 | } | ||
2706 | } | ||
2707 | 2883 | ||
2708 | if (conf->power_level != wlvif->power_level) { | 2884 | if (conf->power_level != wlvif->power_level) { |
2709 | ret = wl1271_acx_tx_power(wl, wlvif, conf->power_level); | 2885 | ret = wl1271_acx_tx_power(wl, wlvif, conf->power_level); |
@@ -2721,37 +2897,17 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
2721 | struct wl1271 *wl = hw->priv; | 2897 | struct wl1271 *wl = hw->priv; |
2722 | struct wl12xx_vif *wlvif; | 2898 | struct wl12xx_vif *wlvif; |
2723 | struct ieee80211_conf *conf = &hw->conf; | 2899 | struct ieee80211_conf *conf = &hw->conf; |
2724 | int channel, ret = 0; | 2900 | int ret = 0; |
2725 | |||
2726 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); | ||
2727 | 2901 | ||
2728 | wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s" | 2902 | wl1271_debug(DEBUG_MAC80211, "mac80211 config psm %s power %d %s" |
2729 | " changed 0x%x", | 2903 | " changed 0x%x", |
2730 | channel, | ||
2731 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", | 2904 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", |
2732 | conf->power_level, | 2905 | conf->power_level, |
2733 | conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use", | 2906 | conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use", |
2734 | changed); | 2907 | changed); |
2735 | 2908 | ||
2736 | /* | ||
2737 | * mac80211 will go to idle nearly immediately after transmitting some | ||
2738 | * frames, such as the deauth. To make sure those frames reach the air, | ||
2739 | * wait here until the TX queue is fully flushed. | ||
2740 | */ | ||
2741 | if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || | ||
2742 | ((changed & IEEE80211_CONF_CHANGE_IDLE) && | ||
2743 | (conf->flags & IEEE80211_CONF_IDLE))) | ||
2744 | wl1271_tx_flush(wl); | ||
2745 | |||
2746 | mutex_lock(&wl->mutex); | 2909 | mutex_lock(&wl->mutex); |
2747 | 2910 | ||
2748 | /* we support configuring the channel and band even while off */ | ||
2749 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | ||
2750 | wl->band = conf->channel->band; | ||
2751 | wl->channel = channel; | ||
2752 | wl->channel_type = conf->channel_type; | ||
2753 | } | ||
2754 | |||
2755 | if (changed & IEEE80211_CONF_CHANGE_POWER) | 2911 | if (changed & IEEE80211_CONF_CHANGE_POWER) |
2756 | wl->power_level = conf->power_level; | 2912 | wl->power_level = conf->power_level; |
2757 | 2913 | ||
@@ -3071,10 +3227,7 @@ static int wlcore_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3071 | * stop the queues and flush to ensure the next packets are | 3227 | * stop the queues and flush to ensure the next packets are |
3072 | * in sync with FW spare block accounting | 3228 | * in sync with FW spare block accounting |
3073 | */ | 3229 | */ |
3074 | mutex_lock(&wl->mutex); | ||
3075 | wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK); | 3230 | wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK); |
3076 | mutex_unlock(&wl->mutex); | ||
3077 | |||
3078 | wl1271_tx_flush(wl); | 3231 | wl1271_tx_flush(wl); |
3079 | } | 3232 | } |
3080 | 3233 | ||
@@ -3200,6 +3353,29 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, | |||
3200 | } | 3353 | } |
3201 | EXPORT_SYMBOL_GPL(wlcore_set_key); | 3354 | EXPORT_SYMBOL_GPL(wlcore_set_key); |
3202 | 3355 | ||
3356 | void wlcore_regdomain_config(struct wl1271 *wl) | ||
3357 | { | ||
3358 | int ret; | ||
3359 | |||
3360 | if (!(wl->quirks & WLCORE_QUIRK_REGDOMAIN_CONF)) | ||
3361 | return; | ||
3362 | |||
3363 | mutex_lock(&wl->mutex); | ||
3364 | ret = wl1271_ps_elp_wakeup(wl); | ||
3365 | if (ret < 0) | ||
3366 | goto out; | ||
3367 | |||
3368 | ret = wlcore_cmd_regdomain_config_locked(wl); | ||
3369 | if (ret < 0) { | ||
3370 | wl12xx_queue_recovery_work(wl); | ||
3371 | goto out; | ||
3372 | } | ||
3373 | |||
3374 | wl1271_ps_elp_sleep(wl); | ||
3375 | out: | ||
3376 | mutex_unlock(&wl->mutex); | ||
3377 | } | ||
3378 | |||
3203 | static int wl1271_op_hw_scan(struct ieee80211_hw *hw, | 3379 | static int wl1271_op_hw_scan(struct ieee80211_hw *hw, |
3204 | struct ieee80211_vif *vif, | 3380 | struct ieee80211_vif *vif, |
3205 | struct cfg80211_scan_request *req) | 3381 | struct cfg80211_scan_request *req) |
@@ -3239,7 +3415,7 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, | |||
3239 | goto out_sleep; | 3415 | goto out_sleep; |
3240 | } | 3416 | } |
3241 | 3417 | ||
3242 | ret = wl1271_scan(hw->priv, vif, ssid, len, req); | 3418 | ret = wlcore_scan(hw->priv, vif, ssid, len, req); |
3243 | out_sleep: | 3419 | out_sleep: |
3244 | wl1271_ps_elp_sleep(wl); | 3420 | wl1271_ps_elp_sleep(wl); |
3245 | out: | 3421 | out: |
@@ -3252,6 +3428,7 @@ static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw, | |||
3252 | struct ieee80211_vif *vif) | 3428 | struct ieee80211_vif *vif) |
3253 | { | 3429 | { |
3254 | struct wl1271 *wl = hw->priv; | 3430 | struct wl1271 *wl = hw->priv; |
3431 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
3255 | int ret; | 3432 | int ret; |
3256 | 3433 | ||
3257 | wl1271_debug(DEBUG_MAC80211, "mac80211 cancel hw scan"); | 3434 | wl1271_debug(DEBUG_MAC80211, "mac80211 cancel hw scan"); |
@@ -3269,7 +3446,7 @@ static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw, | |||
3269 | goto out; | 3446 | goto out; |
3270 | 3447 | ||
3271 | if (wl->scan.state != WL1271_SCAN_STATE_DONE) { | 3448 | if (wl->scan.state != WL1271_SCAN_STATE_DONE) { |
3272 | ret = wl1271_scan_stop(wl); | 3449 | ret = wl->ops->scan_stop(wl, wlvif); |
3273 | if (ret < 0) | 3450 | if (ret < 0) |
3274 | goto out_sleep; | 3451 | goto out_sleep; |
3275 | } | 3452 | } |
@@ -3282,7 +3459,7 @@ static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw, | |||
3282 | 3459 | ||
3283 | wl->scan.state = WL1271_SCAN_STATE_IDLE; | 3460 | wl->scan.state = WL1271_SCAN_STATE_IDLE; |
3284 | memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); | 3461 | memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); |
3285 | wl->scan_vif = NULL; | 3462 | wl->scan_wlvif = NULL; |
3286 | wl->scan.req = NULL; | 3463 | wl->scan.req = NULL; |
3287 | ieee80211_scan_completed(wl->hw, true); | 3464 | ieee80211_scan_completed(wl->hw, true); |
3288 | 3465 | ||
@@ -3316,15 +3493,11 @@ static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw, | |||
3316 | if (ret < 0) | 3493 | if (ret < 0) |
3317 | goto out; | 3494 | goto out; |
3318 | 3495 | ||
3319 | ret = wl1271_scan_sched_scan_config(wl, wlvif, req, ies); | 3496 | ret = wl->ops->sched_scan_start(wl, wlvif, req, ies); |
3320 | if (ret < 0) | 3497 | if (ret < 0) |
3321 | goto out_sleep; | 3498 | goto out_sleep; |
3322 | 3499 | ||
3323 | ret = wl1271_scan_sched_scan_start(wl, wlvif); | 3500 | wl->sched_vif = wlvif; |
3324 | if (ret < 0) | ||
3325 | goto out_sleep; | ||
3326 | |||
3327 | wl->sched_scanning = true; | ||
3328 | 3501 | ||
3329 | out_sleep: | 3502 | out_sleep: |
3330 | wl1271_ps_elp_sleep(wl); | 3503 | wl1271_ps_elp_sleep(wl); |
@@ -3351,7 +3524,7 @@ static void wl1271_op_sched_scan_stop(struct ieee80211_hw *hw, | |||
3351 | if (ret < 0) | 3524 | if (ret < 0) |
3352 | goto out; | 3525 | goto out; |
3353 | 3526 | ||
3354 | wl1271_scan_sched_scan_stop(wl, wlvif); | 3527 | wl->ops->sched_scan_stop(wl, wlvif); |
3355 | 3528 | ||
3356 | wl1271_ps_elp_sleep(wl); | 3529 | wl1271_ps_elp_sleep(wl); |
3357 | out: | 3530 | out: |
@@ -3416,30 +3589,6 @@ out: | |||
3416 | return ret; | 3589 | return ret; |
3417 | } | 3590 | } |
3418 | 3591 | ||
3419 | static int wl1271_ssid_set(struct ieee80211_vif *vif, struct sk_buff *skb, | ||
3420 | int offset) | ||
3421 | { | ||
3422 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
3423 | u8 ssid_len; | ||
3424 | const u8 *ptr = cfg80211_find_ie(WLAN_EID_SSID, skb->data + offset, | ||
3425 | skb->len - offset); | ||
3426 | |||
3427 | if (!ptr) { | ||
3428 | wl1271_error("No SSID in IEs!"); | ||
3429 | return -ENOENT; | ||
3430 | } | ||
3431 | |||
3432 | ssid_len = ptr[1]; | ||
3433 | if (ssid_len > IEEE80211_MAX_SSID_LEN) { | ||
3434 | wl1271_error("SSID is too long!"); | ||
3435 | return -EINVAL; | ||
3436 | } | ||
3437 | |||
3438 | wlvif->ssid_len = ssid_len; | ||
3439 | memcpy(wlvif->ssid, ptr+2, ssid_len); | ||
3440 | return 0; | ||
3441 | } | ||
3442 | |||
3443 | static void wl12xx_remove_ie(struct sk_buff *skb, u8 eid, int ieoffset) | 3592 | static void wl12xx_remove_ie(struct sk_buff *skb, u8 eid, int ieoffset) |
3444 | { | 3593 | { |
3445 | int len; | 3594 | int len; |
@@ -3620,7 +3769,7 @@ static int wlcore_set_beacon_template(struct wl1271 *wl, | |||
3620 | 3769 | ||
3621 | wl1271_debug(DEBUG_MASTER, "beacon updated"); | 3770 | wl1271_debug(DEBUG_MASTER, "beacon updated"); |
3622 | 3771 | ||
3623 | ret = wl1271_ssid_set(vif, beacon, ieoffset); | 3772 | ret = wl1271_ssid_set(wlvif, beacon, ieoffset); |
3624 | if (ret < 0) { | 3773 | if (ret < 0) { |
3625 | dev_kfree_skb(beacon); | 3774 | dev_kfree_skb(beacon); |
3626 | goto out; | 3775 | goto out; |
@@ -3637,6 +3786,12 @@ static int wlcore_set_beacon_template(struct wl1271 *wl, | |||
3637 | goto out; | 3786 | goto out; |
3638 | } | 3787 | } |
3639 | 3788 | ||
3789 | wlvif->wmm_enabled = | ||
3790 | cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, | ||
3791 | WLAN_OUI_TYPE_MICROSOFT_WMM, | ||
3792 | beacon->data + ieoffset, | ||
3793 | beacon->len - ieoffset); | ||
3794 | |||
3640 | /* | 3795 | /* |
3641 | * In case we already have a probe-resp beacon set explicitly | 3796 | * In case we already have a probe-resp beacon set explicitly |
3642 | * by usermode, don't use the beacon data. | 3797 | * by usermode, don't use the beacon data. |
@@ -3690,7 +3845,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, | |||
3690 | bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); | 3845 | bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); |
3691 | int ret = 0; | 3846 | int ret = 0; |
3692 | 3847 | ||
3693 | if ((changed & BSS_CHANGED_BEACON_INT)) { | 3848 | if (changed & BSS_CHANGED_BEACON_INT) { |
3694 | wl1271_debug(DEBUG_MASTER, "beacon interval updated: %d", | 3849 | wl1271_debug(DEBUG_MASTER, "beacon interval updated: %d", |
3695 | bss_conf->beacon_int); | 3850 | bss_conf->beacon_int); |
3696 | 3851 | ||
@@ -3703,7 +3858,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, | |||
3703 | wl1271_ap_set_probe_resp_tmpl(wl, rate, vif); | 3858 | wl1271_ap_set_probe_resp_tmpl(wl, rate, vif); |
3704 | } | 3859 | } |
3705 | 3860 | ||
3706 | if ((changed & BSS_CHANGED_BEACON)) { | 3861 | if (changed & BSS_CHANGED_BEACON) { |
3707 | ret = wlcore_set_beacon_template(wl, vif, is_ap); | 3862 | ret = wlcore_set_beacon_template(wl, vif, is_ap); |
3708 | if (ret < 0) | 3863 | if (ret < 0) |
3709 | goto out; | 3864 | goto out; |
@@ -3724,7 +3879,7 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, | |||
3724 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | 3879 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); |
3725 | int ret = 0; | 3880 | int ret = 0; |
3726 | 3881 | ||
3727 | if ((changed & BSS_CHANGED_BASIC_RATES)) { | 3882 | if (changed & BSS_CHANGED_BASIC_RATES) { |
3728 | u32 rates = bss_conf->basic_rates; | 3883 | u32 rates = bss_conf->basic_rates; |
3729 | 3884 | ||
3730 | wlvif->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates, | 3885 | wlvif->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates, |
@@ -3755,7 +3910,7 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, | |||
3755 | if (ret < 0) | 3910 | if (ret < 0) |
3756 | goto out; | 3911 | goto out; |
3757 | 3912 | ||
3758 | if ((changed & BSS_CHANGED_BEACON_ENABLED)) { | 3913 | if (changed & BSS_CHANGED_BEACON_ENABLED) { |
3759 | if (bss_conf->enable_beacon) { | 3914 | if (bss_conf->enable_beacon) { |
3760 | if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) { | 3915 | if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) { |
3761 | ret = wl12xx_cmd_role_start_ap(wl, wlvif); | 3916 | ret = wl12xx_cmd_role_start_ap(wl, wlvif); |
@@ -3802,6 +3957,79 @@ out: | |||
3802 | return; | 3957 | return; |
3803 | } | 3958 | } |
3804 | 3959 | ||
3960 | static int wlcore_set_bssid(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
3961 | struct ieee80211_bss_conf *bss_conf, | ||
3962 | u32 sta_rate_set) | ||
3963 | { | ||
3964 | u32 rates; | ||
3965 | int ret; | ||
3966 | |||
3967 | wl1271_debug(DEBUG_MAC80211, | ||
3968 | "changed_bssid: %pM, aid: %d, bcn_int: %d, brates: 0x%x sta_rate_set: 0x%x", | ||
3969 | bss_conf->bssid, bss_conf->aid, | ||
3970 | bss_conf->beacon_int, | ||
3971 | bss_conf->basic_rates, sta_rate_set); | ||
3972 | |||
3973 | wlvif->beacon_int = bss_conf->beacon_int; | ||
3974 | rates = bss_conf->basic_rates; | ||
3975 | wlvif->basic_rate_set = | ||
3976 | wl1271_tx_enabled_rates_get(wl, rates, | ||
3977 | wlvif->band); | ||
3978 | wlvif->basic_rate = | ||
3979 | wl1271_tx_min_rate_get(wl, | ||
3980 | wlvif->basic_rate_set); | ||
3981 | |||
3982 | if (sta_rate_set) | ||
3983 | wlvif->rate_set = | ||
3984 | wl1271_tx_enabled_rates_get(wl, | ||
3985 | sta_rate_set, | ||
3986 | wlvif->band); | ||
3987 | |||
3988 | /* we only support sched_scan while not connected */ | ||
3989 | if (wl->sched_vif == wlvif) | ||
3990 | wl->ops->sched_scan_stop(wl, wlvif); | ||
3991 | |||
3992 | ret = wl1271_acx_sta_rate_policies(wl, wlvif); | ||
3993 | if (ret < 0) | ||
3994 | return ret; | ||
3995 | |||
3996 | ret = wl12xx_cmd_build_null_data(wl, wlvif); | ||
3997 | if (ret < 0) | ||
3998 | return ret; | ||
3999 | |||
4000 | ret = wl1271_build_qos_null_data(wl, wl12xx_wlvif_to_vif(wlvif)); | ||
4001 | if (ret < 0) | ||
4002 | return ret; | ||
4003 | |||
4004 | wlcore_set_ssid(wl, wlvif); | ||
4005 | |||
4006 | set_bit(WLVIF_FLAG_IN_USE, &wlvif->flags); | ||
4007 | |||
4008 | return 0; | ||
4009 | } | ||
4010 | |||
4011 | static int wlcore_clear_bssid(struct wl1271 *wl, struct wl12xx_vif *wlvif) | ||
4012 | { | ||
4013 | int ret; | ||
4014 | |||
4015 | /* revert back to minimum rates for the current band */ | ||
4016 | wl1271_set_band_rate(wl, wlvif); | ||
4017 | wlvif->basic_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); | ||
4018 | |||
4019 | ret = wl1271_acx_sta_rate_policies(wl, wlvif); | ||
4020 | if (ret < 0) | ||
4021 | return ret; | ||
4022 | |||
4023 | if (wlvif->bss_type == BSS_TYPE_STA_BSS && | ||
4024 | test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags)) { | ||
4025 | ret = wl12xx_cmd_role_stop_sta(wl, wlvif); | ||
4026 | if (ret < 0) | ||
4027 | return ret; | ||
4028 | } | ||
4029 | |||
4030 | clear_bit(WLVIF_FLAG_IN_USE, &wlvif->flags); | ||
4031 | return 0; | ||
4032 | } | ||
3805 | /* STA/IBSS mode changes */ | 4033 | /* STA/IBSS mode changes */ |
3806 | static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | 4034 | static void wl1271_bss_info_changed_sta(struct wl1271 *wl, |
3807 | struct ieee80211_vif *vif, | 4035 | struct ieee80211_vif *vif, |
@@ -3809,7 +4037,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
3809 | u32 changed) | 4037 | u32 changed) |
3810 | { | 4038 | { |
3811 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | 4039 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); |
3812 | bool do_join = false, set_assoc = false; | 4040 | bool do_join = false; |
3813 | bool is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS); | 4041 | bool is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS); |
3814 | bool ibss_joined = false; | 4042 | bool ibss_joined = false; |
3815 | u32 sta_rate_set = 0; | 4043 | u32 sta_rate_set = 0; |
@@ -3830,9 +4058,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
3830 | set_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags); | 4058 | set_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags); |
3831 | ibss_joined = true; | 4059 | ibss_joined = true; |
3832 | } else { | 4060 | } else { |
3833 | if (test_and_clear_bit(WLVIF_FLAG_IBSS_JOINED, | 4061 | wlcore_unset_assoc(wl, wlvif); |
3834 | &wlvif->flags)) | 4062 | wl12xx_cmd_role_stop_sta(wl, wlvif); |
3835 | wl1271_unjoin(wl, wlvif); | ||
3836 | } | 4063 | } |
3837 | } | 4064 | } |
3838 | 4065 | ||
@@ -3850,13 +4077,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
3850 | do_join = true; | 4077 | do_join = true; |
3851 | } | 4078 | } |
3852 | 4079 | ||
3853 | if (changed & BSS_CHANGED_IDLE && !is_ibss) { | 4080 | if (changed & BSS_CHANGED_CQM) { |
3854 | ret = wl1271_sta_handle_idle(wl, wlvif, bss_conf->idle); | ||
3855 | if (ret < 0) | ||
3856 | wl1271_warning("idle mode change failed %d", ret); | ||
3857 | } | ||
3858 | |||
3859 | if ((changed & BSS_CHANGED_CQM)) { | ||
3860 | bool enable = false; | 4081 | bool enable = false; |
3861 | if (bss_conf->cqm_rssi_thold) | 4082 | if (bss_conf->cqm_rssi_thold) |
3862 | enable = true; | 4083 | enable = true; |
@@ -3868,150 +4089,39 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
3868 | wlvif->rssi_thold = bss_conf->cqm_rssi_thold; | 4089 | wlvif->rssi_thold = bss_conf->cqm_rssi_thold; |
3869 | } | 4090 | } |
3870 | 4091 | ||
3871 | if (changed & BSS_CHANGED_BSSID) | 4092 | if (changed & (BSS_CHANGED_BSSID | BSS_CHANGED_HT | |
3872 | if (!is_zero_ether_addr(bss_conf->bssid)) { | 4093 | BSS_CHANGED_ASSOC)) { |
3873 | ret = wl12xx_cmd_build_null_data(wl, wlvif); | ||
3874 | if (ret < 0) | ||
3875 | goto out; | ||
3876 | |||
3877 | ret = wl1271_build_qos_null_data(wl, vif); | ||
3878 | if (ret < 0) | ||
3879 | goto out; | ||
3880 | } | ||
3881 | |||
3882 | if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) { | ||
3883 | rcu_read_lock(); | 4094 | rcu_read_lock(); |
3884 | sta = ieee80211_find_sta(vif, bss_conf->bssid); | 4095 | sta = ieee80211_find_sta(vif, bss_conf->bssid); |
3885 | if (!sta) | 4096 | if (sta) { |
3886 | goto sta_not_found; | 4097 | u8 *rx_mask = sta->ht_cap.mcs.rx_mask; |
3887 | 4098 | ||
3888 | /* save the supp_rates of the ap */ | 4099 | /* save the supp_rates of the ap */ |
3889 | sta_rate_set = sta->supp_rates[wl->hw->conf.channel->band]; | 4100 | sta_rate_set = sta->supp_rates[wlvif->band]; |
3890 | if (sta->ht_cap.ht_supported) | 4101 | if (sta->ht_cap.ht_supported) |
3891 | sta_rate_set |= | 4102 | sta_rate_set |= |
3892 | (sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET) | | 4103 | (rx_mask[0] << HW_HT_RATES_OFFSET) | |
3893 | (sta->ht_cap.mcs.rx_mask[1] << HW_MIMO_RATES_OFFSET); | 4104 | (rx_mask[1] << HW_MIMO_RATES_OFFSET); |
3894 | sta_ht_cap = sta->ht_cap; | 4105 | sta_ht_cap = sta->ht_cap; |
3895 | sta_exists = true; | 4106 | sta_exists = true; |
3896 | 4107 | } | |
3897 | sta_not_found: | 4108 | |
3898 | rcu_read_unlock(); | 4109 | rcu_read_unlock(); |
3899 | } | 4110 | } |
3900 | 4111 | ||
3901 | if ((changed & BSS_CHANGED_ASSOC)) { | 4112 | if (changed & BSS_CHANGED_BSSID) { |
3902 | if (bss_conf->assoc) { | 4113 | if (!is_zero_ether_addr(bss_conf->bssid)) { |
3903 | u32 rates; | 4114 | ret = wlcore_set_bssid(wl, wlvif, bss_conf, |
3904 | int ieoffset; | 4115 | sta_rate_set); |
3905 | wlvif->aid = bss_conf->aid; | ||
3906 | wlvif->channel_type = | ||
3907 | cfg80211_get_chandef_type(&bss_conf->chandef); | ||
3908 | wlvif->beacon_int = bss_conf->beacon_int; | ||
3909 | do_join = true; | ||
3910 | set_assoc = true; | ||
3911 | |||
3912 | /* | ||
3913 | * use basic rates from AP, and determine lowest rate | ||
3914 | * to use with control frames. | ||
3915 | */ | ||
3916 | rates = bss_conf->basic_rates; | ||
3917 | wlvif->basic_rate_set = | ||
3918 | wl1271_tx_enabled_rates_get(wl, rates, | ||
3919 | wlvif->band); | ||
3920 | wlvif->basic_rate = | ||
3921 | wl1271_tx_min_rate_get(wl, | ||
3922 | wlvif->basic_rate_set); | ||
3923 | if (sta_rate_set) | ||
3924 | wlvif->rate_set = | ||
3925 | wl1271_tx_enabled_rates_get(wl, | ||
3926 | sta_rate_set, | ||
3927 | wlvif->band); | ||
3928 | ret = wl1271_acx_sta_rate_policies(wl, wlvif); | ||
3929 | if (ret < 0) | ||
3930 | goto out; | ||
3931 | |||
3932 | /* | ||
3933 | * with wl1271, we don't need to update the | ||
3934 | * beacon_int and dtim_period, because the firmware | ||
3935 | * updates it by itself when the first beacon is | ||
3936 | * received after a join. | ||
3937 | */ | ||
3938 | ret = wl1271_cmd_build_ps_poll(wl, wlvif, wlvif->aid); | ||
3939 | if (ret < 0) | 4116 | if (ret < 0) |
3940 | goto out; | 4117 | goto out; |
3941 | 4118 | ||
3942 | /* | 4119 | /* Need to update the BSSID (for filtering etc) */ |
3943 | * Get a template for hardware connection maintenance | 4120 | do_join = true; |
3944 | */ | ||
3945 | dev_kfree_skb(wlvif->probereq); | ||
3946 | wlvif->probereq = wl1271_cmd_build_ap_probe_req(wl, | ||
3947 | wlvif, | ||
3948 | NULL); | ||
3949 | ieoffset = offsetof(struct ieee80211_mgmt, | ||
3950 | u.probe_req.variable); | ||
3951 | wl1271_ssid_set(vif, wlvif->probereq, ieoffset); | ||
3952 | |||
3953 | /* enable the connection monitoring feature */ | ||
3954 | ret = wl1271_acx_conn_monit_params(wl, wlvif, true); | ||
3955 | if (ret < 0) | ||
3956 | goto out; | ||
3957 | } else { | 4121 | } else { |
3958 | /* use defaults when not associated */ | 4122 | ret = wlcore_clear_bssid(wl, wlvif); |
3959 | bool was_assoc = | ||
3960 | !!test_and_clear_bit(WLVIF_FLAG_STA_ASSOCIATED, | ||
3961 | &wlvif->flags); | ||
3962 | bool was_ifup = | ||
3963 | !!test_and_clear_bit(WLVIF_FLAG_STA_STATE_SENT, | ||
3964 | &wlvif->flags); | ||
3965 | wlvif->aid = 0; | ||
3966 | |||
3967 | /* free probe-request template */ | ||
3968 | dev_kfree_skb(wlvif->probereq); | ||
3969 | wlvif->probereq = NULL; | ||
3970 | |||
3971 | /* revert back to minimum rates for the current band */ | ||
3972 | wl1271_set_band_rate(wl, wlvif); | ||
3973 | wlvif->basic_rate = | ||
3974 | wl1271_tx_min_rate_get(wl, | ||
3975 | wlvif->basic_rate_set); | ||
3976 | ret = wl1271_acx_sta_rate_policies(wl, wlvif); | ||
3977 | if (ret < 0) | ||
3978 | goto out; | ||
3979 | |||
3980 | /* disable connection monitor features */ | ||
3981 | ret = wl1271_acx_conn_monit_params(wl, wlvif, false); | ||
3982 | |||
3983 | /* Disable the keep-alive feature */ | ||
3984 | ret = wl1271_acx_keep_alive_mode(wl, wlvif, false); | ||
3985 | if (ret < 0) | 4123 | if (ret < 0) |
3986 | goto out; | 4124 | goto out; |
3987 | |||
3988 | /* restore the bssid filter and go to dummy bssid */ | ||
3989 | if (was_assoc) { | ||
3990 | /* | ||
3991 | * we might have to disable roc, if there was | ||
3992 | * no IF_OPER_UP notification. | ||
3993 | */ | ||
3994 | if (!was_ifup) { | ||
3995 | ret = wl12xx_croc(wl, wlvif->role_id); | ||
3996 | if (ret < 0) | ||
3997 | goto out; | ||
3998 | } | ||
3999 | /* | ||
4000 | * (we also need to disable roc in case of | ||
4001 | * roaming on the same channel. until we will | ||
4002 | * have a better flow...) | ||
4003 | */ | ||
4004 | if (test_bit(wlvif->dev_role_id, wl->roc_map)) { | ||
4005 | ret = wl12xx_croc(wl, | ||
4006 | wlvif->dev_role_id); | ||
4007 | if (ret < 0) | ||
4008 | goto out; | ||
4009 | } | ||
4010 | |||
4011 | wl1271_unjoin(wl, wlvif); | ||
4012 | if (!bss_conf->idle) | ||
4013 | wl12xx_start_dev(wl, wlvif); | ||
4014 | } | ||
4015 | } | 4125 | } |
4016 | } | 4126 | } |
4017 | 4127 | ||
@@ -4041,71 +4151,87 @@ sta_not_found: | |||
4041 | goto out; | 4151 | goto out; |
4042 | 4152 | ||
4043 | if (do_join) { | 4153 | if (do_join) { |
4044 | ret = wl1271_join(wl, wlvif, set_assoc); | 4154 | ret = wlcore_join(wl, wlvif); |
4045 | if (ret < 0) { | 4155 | if (ret < 0) { |
4046 | wl1271_warning("cmd join failed %d", ret); | 4156 | wl1271_warning("cmd join failed %d", ret); |
4047 | goto out; | 4157 | goto out; |
4048 | } | 4158 | } |
4159 | } | ||
4049 | 4160 | ||
4050 | /* ROC until connected (after EAPOL exchange) */ | 4161 | if (changed & BSS_CHANGED_ASSOC) { |
4051 | if (!is_ibss) { | 4162 | if (bss_conf->assoc) { |
4052 | ret = wl12xx_roc(wl, wlvif, wlvif->role_id); | 4163 | ret = wlcore_set_assoc(wl, wlvif, bss_conf, |
4164 | sta_rate_set); | ||
4053 | if (ret < 0) | 4165 | if (ret < 0) |
4054 | goto out; | 4166 | goto out; |
4055 | 4167 | ||
4056 | if (test_bit(WLVIF_FLAG_STA_AUTHORIZED, &wlvif->flags)) | 4168 | if (test_bit(WLVIF_FLAG_STA_AUTHORIZED, &wlvif->flags)) |
4057 | wl12xx_set_authorized(wl, wlvif); | 4169 | wl12xx_set_authorized(wl, wlvif); |
4170 | } else { | ||
4171 | wlcore_unset_assoc(wl, wlvif); | ||
4058 | } | 4172 | } |
4059 | /* | 4173 | } |
4060 | * stop device role if started (we might already be in | 4174 | |
4061 | * STA/IBSS role). | 4175 | if (changed & BSS_CHANGED_PS) { |
4062 | */ | 4176 | if ((bss_conf->ps) && |
4063 | if (wl12xx_dev_role_started(wlvif)) { | 4177 | test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) && |
4064 | ret = wl12xx_stop_dev(wl, wlvif); | 4178 | !test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags)) { |
4179 | int ps_mode; | ||
4180 | char *ps_mode_str; | ||
4181 | |||
4182 | if (wl->conf.conn.forced_ps) { | ||
4183 | ps_mode = STATION_POWER_SAVE_MODE; | ||
4184 | ps_mode_str = "forced"; | ||
4185 | } else { | ||
4186 | ps_mode = STATION_AUTO_PS_MODE; | ||
4187 | ps_mode_str = "auto"; | ||
4188 | } | ||
4189 | |||
4190 | wl1271_debug(DEBUG_PSM, "%s ps enabled", ps_mode_str); | ||
4191 | |||
4192 | ret = wl1271_ps_set_mode(wl, wlvif, ps_mode); | ||
4065 | if (ret < 0) | 4193 | if (ret < 0) |
4066 | goto out; | 4194 | wl1271_warning("enter %s ps failed %d", |
4195 | ps_mode_str, ret); | ||
4196 | } else if (!bss_conf->ps && | ||
4197 | test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags)) { | ||
4198 | wl1271_debug(DEBUG_PSM, "auto ps disabled"); | ||
4199 | |||
4200 | ret = wl1271_ps_set_mode(wl, wlvif, | ||
4201 | STATION_ACTIVE_MODE); | ||
4202 | if (ret < 0) | ||
4203 | wl1271_warning("exit auto ps failed %d", ret); | ||
4067 | } | 4204 | } |
4068 | } | 4205 | } |
4069 | 4206 | ||
4070 | /* Handle new association with HT. Do this after join. */ | 4207 | /* Handle new association with HT. Do this after join. */ |
4071 | if (sta_exists) { | 4208 | if (sta_exists && |
4072 | if ((changed & BSS_CHANGED_HT) && | 4209 | (changed & BSS_CHANGED_HT)) { |
4073 | (bss_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT)) { | 4210 | bool enabled = |
4074 | ret = wl1271_acx_set_ht_capabilities(wl, | 4211 | bss_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT; |
4075 | &sta_ht_cap, | 4212 | |
4076 | true, | 4213 | ret = wlcore_hw_set_peer_cap(wl, |
4077 | wlvif->sta.hlid); | 4214 | &sta_ht_cap, |
4078 | if (ret < 0) { | 4215 | enabled, |
4079 | wl1271_warning("Set ht cap true failed %d", | 4216 | wlvif->rate_set, |
4080 | ret); | 4217 | wlvif->sta.hlid); |
4081 | goto out; | 4218 | if (ret < 0) { |
4082 | } | 4219 | wl1271_warning("Set ht cap failed %d", ret); |
4220 | goto out; | ||
4221 | |||
4083 | } | 4222 | } |
4084 | /* handle new association without HT and disassociation */ | 4223 | |
4085 | else if (changed & BSS_CHANGED_ASSOC) { | 4224 | if (enabled) { |
4086 | ret = wl1271_acx_set_ht_capabilities(wl, | 4225 | ret = wl1271_acx_set_ht_information(wl, wlvif, |
4087 | &sta_ht_cap, | 4226 | bss_conf->ht_operation_mode); |
4088 | false, | ||
4089 | wlvif->sta.hlid); | ||
4090 | if (ret < 0) { | 4227 | if (ret < 0) { |
4091 | wl1271_warning("Set ht cap false failed %d", | 4228 | wl1271_warning("Set ht information failed %d", |
4092 | ret); | 4229 | ret); |
4093 | goto out; | 4230 | goto out; |
4094 | } | 4231 | } |
4095 | } | 4232 | } |
4096 | } | 4233 | } |
4097 | 4234 | ||
4098 | /* Handle HT information change. Done after join. */ | ||
4099 | if ((changed & BSS_CHANGED_HT) && | ||
4100 | (bss_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT)) { | ||
4101 | ret = wl1271_acx_set_ht_information(wl, wlvif, | ||
4102 | bss_conf->ht_operation_mode); | ||
4103 | if (ret < 0) { | ||
4104 | wl1271_warning("Set ht information failed %d", ret); | ||
4105 | goto out; | ||
4106 | } | ||
4107 | } | ||
4108 | |||
4109 | /* Handle arp filtering. Done after join. */ | 4235 | /* Handle arp filtering. Done after join. */ |
4110 | if ((changed & BSS_CHANGED_ARP_FILTER) || | 4236 | if ((changed & BSS_CHANGED_ARP_FILTER) || |
4111 | (!is_ibss && (changed & BSS_CHANGED_QOS))) { | 4237 | (!is_ibss && (changed & BSS_CHANGED_QOS))) { |
@@ -4113,8 +4239,7 @@ sta_not_found: | |||
4113 | wlvif->sta.qos = bss_conf->qos; | 4239 | wlvif->sta.qos = bss_conf->qos; |
4114 | WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS); | 4240 | WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS); |
4115 | 4241 | ||
4116 | if (bss_conf->arp_addr_cnt == 1 && | 4242 | if (bss_conf->arp_addr_cnt == 1 && bss_conf->assoc) { |
4117 | bss_conf->arp_filter_enabled) { | ||
4118 | wlvif->ip_addr = addr; | 4243 | wlvif->ip_addr = addr; |
4119 | /* | 4244 | /* |
4120 | * The template should have been configured only upon | 4245 | * The template should have been configured only upon |
@@ -4155,15 +4280,15 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
4155 | bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); | 4280 | bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); |
4156 | int ret; | 4281 | int ret; |
4157 | 4282 | ||
4158 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed 0x%x", | 4283 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info role %d changed 0x%x", |
4159 | (int)changed); | 4284 | wlvif->role_id, (int)changed); |
4160 | 4285 | ||
4161 | /* | 4286 | /* |
4162 | * make sure to cancel pending disconnections if our association | 4287 | * make sure to cancel pending disconnections if our association |
4163 | * state changed | 4288 | * state changed |
4164 | */ | 4289 | */ |
4165 | if (!is_ap && (changed & BSS_CHANGED_ASSOC)) | 4290 | if (!is_ap && (changed & BSS_CHANGED_ASSOC)) |
4166 | cancel_delayed_work_sync(&wl->connection_loss_work); | 4291 | cancel_delayed_work_sync(&wlvif->connection_loss_work); |
4167 | 4292 | ||
4168 | if (is_ap && (changed & BSS_CHANGED_BEACON_ENABLED) && | 4293 | if (is_ap && (changed & BSS_CHANGED_BEACON_ENABLED) && |
4169 | !bss_conf->enable_beacon) | 4294 | !bss_conf->enable_beacon) |
@@ -4192,6 +4317,76 @@ out: | |||
4192 | mutex_unlock(&wl->mutex); | 4317 | mutex_unlock(&wl->mutex); |
4193 | } | 4318 | } |
4194 | 4319 | ||
4320 | static int wlcore_op_add_chanctx(struct ieee80211_hw *hw, | ||
4321 | struct ieee80211_chanctx_conf *ctx) | ||
4322 | { | ||
4323 | wl1271_debug(DEBUG_MAC80211, "mac80211 add chanctx %d (type %d)", | ||
4324 | ieee80211_frequency_to_channel(ctx->def.chan->center_freq), | ||
4325 | cfg80211_get_chandef_type(&ctx->def)); | ||
4326 | return 0; | ||
4327 | } | ||
4328 | |||
4329 | static void wlcore_op_remove_chanctx(struct ieee80211_hw *hw, | ||
4330 | struct ieee80211_chanctx_conf *ctx) | ||
4331 | { | ||
4332 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove chanctx %d (type %d)", | ||
4333 | ieee80211_frequency_to_channel(ctx->def.chan->center_freq), | ||
4334 | cfg80211_get_chandef_type(&ctx->def)); | ||
4335 | } | ||
4336 | |||
4337 | static void wlcore_op_change_chanctx(struct ieee80211_hw *hw, | ||
4338 | struct ieee80211_chanctx_conf *ctx, | ||
4339 | u32 changed) | ||
4340 | { | ||
4341 | wl1271_debug(DEBUG_MAC80211, | ||
4342 | "mac80211 change chanctx %d (type %d) changed 0x%x", | ||
4343 | ieee80211_frequency_to_channel(ctx->def.chan->center_freq), | ||
4344 | cfg80211_get_chandef_type(&ctx->def), changed); | ||
4345 | } | ||
4346 | |||
4347 | static int wlcore_op_assign_vif_chanctx(struct ieee80211_hw *hw, | ||
4348 | struct ieee80211_vif *vif, | ||
4349 | struct ieee80211_chanctx_conf *ctx) | ||
4350 | { | ||
4351 | struct wl1271 *wl = hw->priv; | ||
4352 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
4353 | int channel = ieee80211_frequency_to_channel( | ||
4354 | ctx->def.chan->center_freq); | ||
4355 | |||
4356 | wl1271_debug(DEBUG_MAC80211, | ||
4357 | "mac80211 assign chanctx (role %d) %d (type %d)", | ||
4358 | wlvif->role_id, channel, cfg80211_get_chandef_type(&ctx->def)); | ||
4359 | |||
4360 | mutex_lock(&wl->mutex); | ||
4361 | |||
4362 | wlvif->band = ctx->def.chan->band; | ||
4363 | wlvif->channel = channel; | ||
4364 | wlvif->channel_type = cfg80211_get_chandef_type(&ctx->def); | ||
4365 | |||
4366 | /* update default rates according to the band */ | ||
4367 | wl1271_set_band_rate(wl, wlvif); | ||
4368 | |||
4369 | mutex_unlock(&wl->mutex); | ||
4370 | |||
4371 | return 0; | ||
4372 | } | ||
4373 | |||
4374 | static void wlcore_op_unassign_vif_chanctx(struct ieee80211_hw *hw, | ||
4375 | struct ieee80211_vif *vif, | ||
4376 | struct ieee80211_chanctx_conf *ctx) | ||
4377 | { | ||
4378 | struct wl1271 *wl = hw->priv; | ||
4379 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
4380 | |||
4381 | wl1271_debug(DEBUG_MAC80211, | ||
4382 | "mac80211 unassign chanctx (role %d) %d (type %d)", | ||
4383 | wlvif->role_id, | ||
4384 | ieee80211_frequency_to_channel(ctx->def.chan->center_freq), | ||
4385 | cfg80211_get_chandef_type(&ctx->def)); | ||
4386 | |||
4387 | wl1271_tx_flush(wl); | ||
4388 | } | ||
4389 | |||
4195 | static int wl1271_op_conf_tx(struct ieee80211_hw *hw, | 4390 | static int wl1271_op_conf_tx(struct ieee80211_hw *hw, |
4196 | struct ieee80211_vif *vif, u16 queue, | 4391 | struct ieee80211_vif *vif, u16 queue, |
4197 | const struct ieee80211_tx_queue_params *params) | 4392 | const struct ieee80211_tx_queue_params *params) |
@@ -4319,8 +4514,6 @@ void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid) | |||
4319 | return; | 4514 | return; |
4320 | 4515 | ||
4321 | clear_bit(hlid, wlvif->ap.sta_hlid_map); | 4516 | clear_bit(hlid, wlvif->ap.sta_hlid_map); |
4322 | memset(wl->links[hlid].addr, 0, ETH_ALEN); | ||
4323 | wl->links[hlid].ba_bitmap = 0; | ||
4324 | __clear_bit(hlid, &wl->ap_ps_map); | 4517 | __clear_bit(hlid, &wl->ap_ps_map); |
4325 | __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | 4518 | __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); |
4326 | wl12xx_free_link(wl, wlvif, &hlid); | 4519 | wl12xx_free_link(wl, wlvif, &hlid); |
@@ -4380,6 +4573,45 @@ static int wl12xx_sta_remove(struct wl1271 *wl, | |||
4380 | return ret; | 4573 | return ret; |
4381 | } | 4574 | } |
4382 | 4575 | ||
4576 | static void wlcore_roc_if_possible(struct wl1271 *wl, | ||
4577 | struct wl12xx_vif *wlvif) | ||
4578 | { | ||
4579 | if (find_first_bit(wl->roc_map, | ||
4580 | WL12XX_MAX_ROLES) < WL12XX_MAX_ROLES) | ||
4581 | return; | ||
4582 | |||
4583 | if (WARN_ON(wlvif->role_id == WL12XX_INVALID_ROLE_ID)) | ||
4584 | return; | ||
4585 | |||
4586 | wl12xx_roc(wl, wlvif, wlvif->role_id, wlvif->band, wlvif->channel); | ||
4587 | } | ||
4588 | |||
4589 | static void wlcore_update_inconn_sta(struct wl1271 *wl, | ||
4590 | struct wl12xx_vif *wlvif, | ||
4591 | struct wl1271_station *wl_sta, | ||
4592 | bool in_connection) | ||
4593 | { | ||
4594 | if (in_connection) { | ||
4595 | if (WARN_ON(wl_sta->in_connection)) | ||
4596 | return; | ||
4597 | wl_sta->in_connection = true; | ||
4598 | if (!wlvif->inconn_count++) | ||
4599 | wlcore_roc_if_possible(wl, wlvif); | ||
4600 | } else { | ||
4601 | if (!wl_sta->in_connection) | ||
4602 | return; | ||
4603 | |||
4604 | wl_sta->in_connection = false; | ||
4605 | wlvif->inconn_count--; | ||
4606 | if (WARN_ON(wlvif->inconn_count < 0)) | ||
4607 | return; | ||
4608 | |||
4609 | if (!wlvif->inconn_count) | ||
4610 | if (test_bit(wlvif->role_id, wl->roc_map)) | ||
4611 | wl12xx_croc(wl, wlvif->role_id); | ||
4612 | } | ||
4613 | } | ||
4614 | |||
4383 | static int wl12xx_update_sta_state(struct wl1271 *wl, | 4615 | static int wl12xx_update_sta_state(struct wl1271 *wl, |
4384 | struct wl12xx_vif *wlvif, | 4616 | struct wl12xx_vif *wlvif, |
4385 | struct ieee80211_sta *sta, | 4617 | struct ieee80211_sta *sta, |
@@ -4398,8 +4630,13 @@ static int wl12xx_update_sta_state(struct wl1271 *wl, | |||
4398 | /* Add station (AP mode) */ | 4630 | /* Add station (AP mode) */ |
4399 | if (is_ap && | 4631 | if (is_ap && |
4400 | old_state == IEEE80211_STA_NOTEXIST && | 4632 | old_state == IEEE80211_STA_NOTEXIST && |
4401 | new_state == IEEE80211_STA_NONE) | 4633 | new_state == IEEE80211_STA_NONE) { |
4402 | return wl12xx_sta_add(wl, wlvif, sta); | 4634 | ret = wl12xx_sta_add(wl, wlvif, sta); |
4635 | if (ret) | ||
4636 | return ret; | ||
4637 | |||
4638 | wlcore_update_inconn_sta(wl, wlvif, wl_sta, true); | ||
4639 | } | ||
4403 | 4640 | ||
4404 | /* Remove station (AP mode) */ | 4641 | /* Remove station (AP mode) */ |
4405 | if (is_ap && | 4642 | if (is_ap && |
@@ -4407,35 +4644,59 @@ static int wl12xx_update_sta_state(struct wl1271 *wl, | |||
4407 | new_state == IEEE80211_STA_NOTEXIST) { | 4644 | new_state == IEEE80211_STA_NOTEXIST) { |
4408 | /* must not fail */ | 4645 | /* must not fail */ |
4409 | wl12xx_sta_remove(wl, wlvif, sta); | 4646 | wl12xx_sta_remove(wl, wlvif, sta); |
4410 | return 0; | 4647 | |
4648 | wlcore_update_inconn_sta(wl, wlvif, wl_sta, false); | ||
4411 | } | 4649 | } |
4412 | 4650 | ||
4413 | /* Authorize station (AP mode) */ | 4651 | /* Authorize station (AP mode) */ |
4414 | if (is_ap && | 4652 | if (is_ap && |
4415 | new_state == IEEE80211_STA_AUTHORIZED) { | 4653 | new_state == IEEE80211_STA_AUTHORIZED) { |
4416 | ret = wl12xx_cmd_set_peer_state(wl, hlid); | 4654 | ret = wl12xx_cmd_set_peer_state(wl, wlvif, hlid); |
4417 | if (ret < 0) | 4655 | if (ret < 0) |
4418 | return ret; | 4656 | return ret; |
4419 | 4657 | ||
4420 | ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true, | 4658 | ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true, |
4421 | hlid); | 4659 | hlid); |
4422 | return ret; | 4660 | if (ret) |
4661 | return ret; | ||
4662 | |||
4663 | wlcore_update_inconn_sta(wl, wlvif, wl_sta, false); | ||
4423 | } | 4664 | } |
4424 | 4665 | ||
4425 | /* Authorize station */ | 4666 | /* Authorize station */ |
4426 | if (is_sta && | 4667 | if (is_sta && |
4427 | new_state == IEEE80211_STA_AUTHORIZED) { | 4668 | new_state == IEEE80211_STA_AUTHORIZED) { |
4428 | set_bit(WLVIF_FLAG_STA_AUTHORIZED, &wlvif->flags); | 4669 | set_bit(WLVIF_FLAG_STA_AUTHORIZED, &wlvif->flags); |
4429 | return wl12xx_set_authorized(wl, wlvif); | 4670 | ret = wl12xx_set_authorized(wl, wlvif); |
4671 | if (ret) | ||
4672 | return ret; | ||
4430 | } | 4673 | } |
4431 | 4674 | ||
4432 | if (is_sta && | 4675 | if (is_sta && |
4433 | old_state == IEEE80211_STA_AUTHORIZED && | 4676 | old_state == IEEE80211_STA_AUTHORIZED && |
4434 | new_state == IEEE80211_STA_ASSOC) { | 4677 | new_state == IEEE80211_STA_ASSOC) { |
4435 | clear_bit(WLVIF_FLAG_STA_AUTHORIZED, &wlvif->flags); | 4678 | clear_bit(WLVIF_FLAG_STA_AUTHORIZED, &wlvif->flags); |
4436 | return 0; | 4679 | clear_bit(WLVIF_FLAG_STA_STATE_SENT, &wlvif->flags); |
4437 | } | 4680 | } |
4438 | 4681 | ||
4682 | /* clear ROCs on failure or authorization */ | ||
4683 | if (is_sta && | ||
4684 | (new_state == IEEE80211_STA_AUTHORIZED || | ||
4685 | new_state == IEEE80211_STA_NOTEXIST)) { | ||
4686 | if (test_bit(wlvif->role_id, wl->roc_map)) | ||
4687 | wl12xx_croc(wl, wlvif->role_id); | ||
4688 | } | ||
4689 | |||
4690 | if (is_sta && | ||
4691 | old_state == IEEE80211_STA_NOTEXIST && | ||
4692 | new_state == IEEE80211_STA_NONE) { | ||
4693 | if (find_first_bit(wl->roc_map, | ||
4694 | WL12XX_MAX_ROLES) >= WL12XX_MAX_ROLES) { | ||
4695 | WARN_ON(wlvif->role_id == WL12XX_INVALID_ROLE_ID); | ||
4696 | wl12xx_roc(wl, wlvif, wlvif->role_id, | ||
4697 | wlvif->band, wlvif->channel); | ||
4698 | } | ||
4699 | } | ||
4439 | return 0; | 4700 | return 0; |
4440 | } | 4701 | } |
4441 | 4702 | ||
@@ -4500,18 +4761,18 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, | |||
4500 | 4761 | ||
4501 | if (wlvif->bss_type == BSS_TYPE_STA_BSS) { | 4762 | if (wlvif->bss_type == BSS_TYPE_STA_BSS) { |
4502 | hlid = wlvif->sta.hlid; | 4763 | hlid = wlvif->sta.hlid; |
4503 | ba_bitmap = &wlvif->sta.ba_rx_bitmap; | ||
4504 | } else if (wlvif->bss_type == BSS_TYPE_AP_BSS) { | 4764 | } else if (wlvif->bss_type == BSS_TYPE_AP_BSS) { |
4505 | struct wl1271_station *wl_sta; | 4765 | struct wl1271_station *wl_sta; |
4506 | 4766 | ||
4507 | wl_sta = (struct wl1271_station *)sta->drv_priv; | 4767 | wl_sta = (struct wl1271_station *)sta->drv_priv; |
4508 | hlid = wl_sta->hlid; | 4768 | hlid = wl_sta->hlid; |
4509 | ba_bitmap = &wl->links[hlid].ba_bitmap; | ||
4510 | } else { | 4769 | } else { |
4511 | ret = -EINVAL; | 4770 | ret = -EINVAL; |
4512 | goto out; | 4771 | goto out; |
4513 | } | 4772 | } |
4514 | 4773 | ||
4774 | ba_bitmap = &wl->links[hlid].ba_bitmap; | ||
4775 | |||
4515 | ret = wl1271_ps_elp_wakeup(wl); | 4776 | ret = wl1271_ps_elp_wakeup(wl); |
4516 | if (ret < 0) | 4777 | if (ret < 0) |
4517 | goto out; | 4778 | goto out; |
@@ -4665,12 +4926,23 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, | |||
4665 | 4926 | ||
4666 | /* TODO: change mac80211 to pass vif as param */ | 4927 | /* TODO: change mac80211 to pass vif as param */ |
4667 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | 4928 | wl12xx_for_each_wlvif_sta(wl, wlvif) { |
4668 | ret = wl12xx_cmd_channel_switch(wl, wlvif, ch_switch); | 4929 | unsigned long delay_usec; |
4930 | |||
4931 | ret = wl->ops->channel_switch(wl, wlvif, ch_switch); | ||
4932 | if (ret) | ||
4933 | goto out_sleep; | ||
4934 | |||
4935 | set_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags); | ||
4669 | 4936 | ||
4670 | if (!ret) | 4937 | /* indicate failure 5 seconds after channel switch time */ |
4671 | set_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags); | 4938 | delay_usec = ieee80211_tu_to_usec(wlvif->beacon_int) * |
4939 | ch_switch->count; | ||
4940 | ieee80211_queue_delayed_work(hw, &wlvif->channel_switch_work, | ||
4941 | usecs_to_jiffies(delay_usec) + | ||
4942 | msecs_to_jiffies(5000)); | ||
4672 | } | 4943 | } |
4673 | 4944 | ||
4945 | out_sleep: | ||
4674 | wl1271_ps_elp_sleep(wl); | 4946 | wl1271_ps_elp_sleep(wl); |
4675 | 4947 | ||
4676 | out: | 4948 | out: |
@@ -4684,6 +4956,144 @@ static void wlcore_op_flush(struct ieee80211_hw *hw, bool drop) | |||
4684 | wl1271_tx_flush(wl); | 4956 | wl1271_tx_flush(wl); |
4685 | } | 4957 | } |
4686 | 4958 | ||
4959 | static int wlcore_op_remain_on_channel(struct ieee80211_hw *hw, | ||
4960 | struct ieee80211_vif *vif, | ||
4961 | struct ieee80211_channel *chan, | ||
4962 | int duration) | ||
4963 | { | ||
4964 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
4965 | struct wl1271 *wl = hw->priv; | ||
4966 | int channel, ret = 0; | ||
4967 | |||
4968 | channel = ieee80211_frequency_to_channel(chan->center_freq); | ||
4969 | |||
4970 | wl1271_debug(DEBUG_MAC80211, "mac80211 roc %d (%d)", | ||
4971 | channel, wlvif->role_id); | ||
4972 | |||
4973 | mutex_lock(&wl->mutex); | ||
4974 | |||
4975 | if (unlikely(wl->state != WLCORE_STATE_ON)) | ||
4976 | goto out; | ||
4977 | |||
4978 | /* return EBUSY if we can't ROC right now */ | ||
4979 | if (WARN_ON(wl->roc_vif || | ||
4980 | find_first_bit(wl->roc_map, | ||
4981 | WL12XX_MAX_ROLES) < WL12XX_MAX_ROLES)) { | ||
4982 | ret = -EBUSY; | ||
4983 | goto out; | ||
4984 | } | ||
4985 | |||
4986 | ret = wl1271_ps_elp_wakeup(wl); | ||
4987 | if (ret < 0) | ||
4988 | goto out; | ||
4989 | |||
4990 | ret = wl12xx_start_dev(wl, wlvif, chan->band, channel); | ||
4991 | if (ret < 0) | ||
4992 | goto out_sleep; | ||
4993 | |||
4994 | wl->roc_vif = vif; | ||
4995 | ieee80211_queue_delayed_work(hw, &wl->roc_complete_work, | ||
4996 | msecs_to_jiffies(duration)); | ||
4997 | out_sleep: | ||
4998 | wl1271_ps_elp_sleep(wl); | ||
4999 | out: | ||
5000 | mutex_unlock(&wl->mutex); | ||
5001 | return ret; | ||
5002 | } | ||
5003 | |||
5004 | static int __wlcore_roc_completed(struct wl1271 *wl) | ||
5005 | { | ||
5006 | struct wl12xx_vif *wlvif; | ||
5007 | int ret; | ||
5008 | |||
5009 | /* already completed */ | ||
5010 | if (unlikely(!wl->roc_vif)) | ||
5011 | return 0; | ||
5012 | |||
5013 | wlvif = wl12xx_vif_to_data(wl->roc_vif); | ||
5014 | |||
5015 | if (!test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)) | ||
5016 | return -EBUSY; | ||
5017 | |||
5018 | ret = wl12xx_stop_dev(wl, wlvif); | ||
5019 | if (ret < 0) | ||
5020 | return ret; | ||
5021 | |||
5022 | wl->roc_vif = NULL; | ||
5023 | |||
5024 | return 0; | ||
5025 | } | ||
5026 | |||
5027 | static int wlcore_roc_completed(struct wl1271 *wl) | ||
5028 | { | ||
5029 | int ret; | ||
5030 | |||
5031 | wl1271_debug(DEBUG_MAC80211, "roc complete"); | ||
5032 | |||
5033 | mutex_lock(&wl->mutex); | ||
5034 | |||
5035 | if (unlikely(wl->state != WLCORE_STATE_ON)) { | ||
5036 | ret = -EBUSY; | ||
5037 | goto out; | ||
5038 | } | ||
5039 | |||
5040 | ret = wl1271_ps_elp_wakeup(wl); | ||
5041 | if (ret < 0) | ||
5042 | goto out; | ||
5043 | |||
5044 | ret = __wlcore_roc_completed(wl); | ||
5045 | |||
5046 | wl1271_ps_elp_sleep(wl); | ||
5047 | out: | ||
5048 | mutex_unlock(&wl->mutex); | ||
5049 | |||
5050 | return ret; | ||
5051 | } | ||
5052 | |||
5053 | static void wlcore_roc_complete_work(struct work_struct *work) | ||
5054 | { | ||
5055 | struct delayed_work *dwork; | ||
5056 | struct wl1271 *wl; | ||
5057 | int ret; | ||
5058 | |||
5059 | dwork = container_of(work, struct delayed_work, work); | ||
5060 | wl = container_of(dwork, struct wl1271, roc_complete_work); | ||
5061 | |||
5062 | ret = wlcore_roc_completed(wl); | ||
5063 | if (!ret) | ||
5064 | ieee80211_remain_on_channel_expired(wl->hw); | ||
5065 | } | ||
5066 | |||
5067 | static int wlcore_op_cancel_remain_on_channel(struct ieee80211_hw *hw) | ||
5068 | { | ||
5069 | struct wl1271 *wl = hw->priv; | ||
5070 | |||
5071 | wl1271_debug(DEBUG_MAC80211, "mac80211 croc"); | ||
5072 | |||
5073 | /* TODO: per-vif */ | ||
5074 | wl1271_tx_flush(wl); | ||
5075 | |||
5076 | /* | ||
5077 | * we can't just flush_work here, because it might deadlock | ||
5078 | * (as we might get called from the same workqueue) | ||
5079 | */ | ||
5080 | cancel_delayed_work_sync(&wl->roc_complete_work); | ||
5081 | wlcore_roc_completed(wl); | ||
5082 | |||
5083 | return 0; | ||
5084 | } | ||
5085 | |||
5086 | static void wlcore_op_sta_rc_update(struct ieee80211_hw *hw, | ||
5087 | struct ieee80211_vif *vif, | ||
5088 | struct ieee80211_sta *sta, | ||
5089 | u32 changed) | ||
5090 | { | ||
5091 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
5092 | struct wl1271 *wl = hw->priv; | ||
5093 | |||
5094 | wlcore_hw_sta_rc_update(wl, wlvif, sta, changed); | ||
5095 | } | ||
5096 | |||
4687 | static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) | 5097 | static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) |
4688 | { | 5098 | { |
4689 | struct wl1271 *wl = hw->priv; | 5099 | struct wl1271 *wl = hw->priv; |
@@ -4747,20 +5157,20 @@ static struct ieee80211_rate wl1271_rates[] = { | |||
4747 | 5157 | ||
4748 | /* can't be const, mac80211 writes to this */ | 5158 | /* can't be const, mac80211 writes to this */ |
4749 | static struct ieee80211_channel wl1271_channels[] = { | 5159 | static struct ieee80211_channel wl1271_channels[] = { |
4750 | { .hw_value = 1, .center_freq = 2412, .max_power = 25 }, | 5160 | { .hw_value = 1, .center_freq = 2412, .max_power = WLCORE_MAX_TXPWR }, |
4751 | { .hw_value = 2, .center_freq = 2417, .max_power = 25 }, | 5161 | { .hw_value = 2, .center_freq = 2417, .max_power = WLCORE_MAX_TXPWR }, |
4752 | { .hw_value = 3, .center_freq = 2422, .max_power = 25 }, | 5162 | { .hw_value = 3, .center_freq = 2422, .max_power = WLCORE_MAX_TXPWR }, |
4753 | { .hw_value = 4, .center_freq = 2427, .max_power = 25 }, | 5163 | { .hw_value = 4, .center_freq = 2427, .max_power = WLCORE_MAX_TXPWR }, |
4754 | { .hw_value = 5, .center_freq = 2432, .max_power = 25 }, | 5164 | { .hw_value = 5, .center_freq = 2432, .max_power = WLCORE_MAX_TXPWR }, |
4755 | { .hw_value = 6, .center_freq = 2437, .max_power = 25 }, | 5165 | { .hw_value = 6, .center_freq = 2437, .max_power = WLCORE_MAX_TXPWR }, |
4756 | { .hw_value = 7, .center_freq = 2442, .max_power = 25 }, | 5166 | { .hw_value = 7, .center_freq = 2442, .max_power = WLCORE_MAX_TXPWR }, |
4757 | { .hw_value = 8, .center_freq = 2447, .max_power = 25 }, | 5167 | { .hw_value = 8, .center_freq = 2447, .max_power = WLCORE_MAX_TXPWR }, |
4758 | { .hw_value = 9, .center_freq = 2452, .max_power = 25 }, | 5168 | { .hw_value = 9, .center_freq = 2452, .max_power = WLCORE_MAX_TXPWR }, |
4759 | { .hw_value = 10, .center_freq = 2457, .max_power = 25 }, | 5169 | { .hw_value = 10, .center_freq = 2457, .max_power = WLCORE_MAX_TXPWR }, |
4760 | { .hw_value = 11, .center_freq = 2462, .max_power = 25 }, | 5170 | { .hw_value = 11, .center_freq = 2462, .max_power = WLCORE_MAX_TXPWR }, |
4761 | { .hw_value = 12, .center_freq = 2467, .max_power = 25 }, | 5171 | { .hw_value = 12, .center_freq = 2467, .max_power = WLCORE_MAX_TXPWR }, |
4762 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, | 5172 | { .hw_value = 13, .center_freq = 2472, .max_power = WLCORE_MAX_TXPWR }, |
4763 | { .hw_value = 14, .center_freq = 2484, .max_power = 25 }, | 5173 | { .hw_value = 14, .center_freq = 2484, .max_power = WLCORE_MAX_TXPWR }, |
4764 | }; | 5174 | }; |
4765 | 5175 | ||
4766 | /* can't be const, mac80211 writes to this */ | 5176 | /* can't be const, mac80211 writes to this */ |
@@ -4801,40 +5211,40 @@ static struct ieee80211_rate wl1271_rates_5ghz[] = { | |||
4801 | 5211 | ||
4802 | /* 5 GHz band channels for WL1273 */ | 5212 | /* 5 GHz band channels for WL1273 */ |
4803 | static struct ieee80211_channel wl1271_channels_5ghz[] = { | 5213 | static struct ieee80211_channel wl1271_channels_5ghz[] = { |
4804 | { .hw_value = 7, .center_freq = 5035, .max_power = 25 }, | 5214 | { .hw_value = 7, .center_freq = 5035, .max_power = WLCORE_MAX_TXPWR }, |
4805 | { .hw_value = 8, .center_freq = 5040, .max_power = 25 }, | 5215 | { .hw_value = 8, .center_freq = 5040, .max_power = WLCORE_MAX_TXPWR }, |
4806 | { .hw_value = 9, .center_freq = 5045, .max_power = 25 }, | 5216 | { .hw_value = 9, .center_freq = 5045, .max_power = WLCORE_MAX_TXPWR }, |
4807 | { .hw_value = 11, .center_freq = 5055, .max_power = 25 }, | 5217 | { .hw_value = 11, .center_freq = 5055, .max_power = WLCORE_MAX_TXPWR }, |
4808 | { .hw_value = 12, .center_freq = 5060, .max_power = 25 }, | 5218 | { .hw_value = 12, .center_freq = 5060, .max_power = WLCORE_MAX_TXPWR }, |
4809 | { .hw_value = 16, .center_freq = 5080, .max_power = 25 }, | 5219 | { .hw_value = 16, .center_freq = 5080, .max_power = WLCORE_MAX_TXPWR }, |
4810 | { .hw_value = 34, .center_freq = 5170, .max_power = 25 }, | 5220 | { .hw_value = 34, .center_freq = 5170, .max_power = WLCORE_MAX_TXPWR }, |
4811 | { .hw_value = 36, .center_freq = 5180, .max_power = 25 }, | 5221 | { .hw_value = 36, .center_freq = 5180, .max_power = WLCORE_MAX_TXPWR }, |
4812 | { .hw_value = 38, .center_freq = 5190, .max_power = 25 }, | 5222 | { .hw_value = 38, .center_freq = 5190, .max_power = WLCORE_MAX_TXPWR }, |
4813 | { .hw_value = 40, .center_freq = 5200, .max_power = 25 }, | 5223 | { .hw_value = 40, .center_freq = 5200, .max_power = WLCORE_MAX_TXPWR }, |
4814 | { .hw_value = 42, .center_freq = 5210, .max_power = 25 }, | 5224 | { .hw_value = 42, .center_freq = 5210, .max_power = WLCORE_MAX_TXPWR }, |
4815 | { .hw_value = 44, .center_freq = 5220, .max_power = 25 }, | 5225 | { .hw_value = 44, .center_freq = 5220, .max_power = WLCORE_MAX_TXPWR }, |
4816 | { .hw_value = 46, .center_freq = 5230, .max_power = 25 }, | 5226 | { .hw_value = 46, .center_freq = 5230, .max_power = WLCORE_MAX_TXPWR }, |
4817 | { .hw_value = 48, .center_freq = 5240, .max_power = 25 }, | 5227 | { .hw_value = 48, .center_freq = 5240, .max_power = WLCORE_MAX_TXPWR }, |
4818 | { .hw_value = 52, .center_freq = 5260, .max_power = 25 }, | 5228 | { .hw_value = 52, .center_freq = 5260, .max_power = WLCORE_MAX_TXPWR }, |
4819 | { .hw_value = 56, .center_freq = 5280, .max_power = 25 }, | 5229 | { .hw_value = 56, .center_freq = 5280, .max_power = WLCORE_MAX_TXPWR }, |
4820 | { .hw_value = 60, .center_freq = 5300, .max_power = 25 }, | 5230 | { .hw_value = 60, .center_freq = 5300, .max_power = WLCORE_MAX_TXPWR }, |
4821 | { .hw_value = 64, .center_freq = 5320, .max_power = 25 }, | 5231 | { .hw_value = 64, .center_freq = 5320, .max_power = WLCORE_MAX_TXPWR }, |
4822 | { .hw_value = 100, .center_freq = 5500, .max_power = 25 }, | 5232 | { .hw_value = 100, .center_freq = 5500, .max_power = WLCORE_MAX_TXPWR }, |
4823 | { .hw_value = 104, .center_freq = 5520, .max_power = 25 }, | 5233 | { .hw_value = 104, .center_freq = 5520, .max_power = WLCORE_MAX_TXPWR }, |
4824 | { .hw_value = 108, .center_freq = 5540, .max_power = 25 }, | 5234 | { .hw_value = 108, .center_freq = 5540, .max_power = WLCORE_MAX_TXPWR }, |
4825 | { .hw_value = 112, .center_freq = 5560, .max_power = 25 }, | 5235 | { .hw_value = 112, .center_freq = 5560, .max_power = WLCORE_MAX_TXPWR }, |
4826 | { .hw_value = 116, .center_freq = 5580, .max_power = 25 }, | 5236 | { .hw_value = 116, .center_freq = 5580, .max_power = WLCORE_MAX_TXPWR }, |
4827 | { .hw_value = 120, .center_freq = 5600, .max_power = 25 }, | 5237 | { .hw_value = 120, .center_freq = 5600, .max_power = WLCORE_MAX_TXPWR }, |
4828 | { .hw_value = 124, .center_freq = 5620, .max_power = 25 }, | 5238 | { .hw_value = 124, .center_freq = 5620, .max_power = WLCORE_MAX_TXPWR }, |
4829 | { .hw_value = 128, .center_freq = 5640, .max_power = 25 }, | 5239 | { .hw_value = 128, .center_freq = 5640, .max_power = WLCORE_MAX_TXPWR }, |
4830 | { .hw_value = 132, .center_freq = 5660, .max_power = 25 }, | 5240 | { .hw_value = 132, .center_freq = 5660, .max_power = WLCORE_MAX_TXPWR }, |
4831 | { .hw_value = 136, .center_freq = 5680, .max_power = 25 }, | 5241 | { .hw_value = 136, .center_freq = 5680, .max_power = WLCORE_MAX_TXPWR }, |
4832 | { .hw_value = 140, .center_freq = 5700, .max_power = 25 }, | 5242 | { .hw_value = 140, .center_freq = 5700, .max_power = WLCORE_MAX_TXPWR }, |
4833 | { .hw_value = 149, .center_freq = 5745, .max_power = 25 }, | 5243 | { .hw_value = 149, .center_freq = 5745, .max_power = WLCORE_MAX_TXPWR }, |
4834 | { .hw_value = 153, .center_freq = 5765, .max_power = 25 }, | 5244 | { .hw_value = 153, .center_freq = 5765, .max_power = WLCORE_MAX_TXPWR }, |
4835 | { .hw_value = 157, .center_freq = 5785, .max_power = 25 }, | 5245 | { .hw_value = 157, .center_freq = 5785, .max_power = WLCORE_MAX_TXPWR }, |
4836 | { .hw_value = 161, .center_freq = 5805, .max_power = 25 }, | 5246 | { .hw_value = 161, .center_freq = 5805, .max_power = WLCORE_MAX_TXPWR }, |
4837 | { .hw_value = 165, .center_freq = 5825, .max_power = 25 }, | 5247 | { .hw_value = 165, .center_freq = 5825, .max_power = WLCORE_MAX_TXPWR }, |
4838 | }; | 5248 | }; |
4839 | 5249 | ||
4840 | static struct ieee80211_supported_band wl1271_band_5ghz = { | 5250 | static struct ieee80211_supported_band wl1271_band_5ghz = { |
@@ -4875,6 +5285,14 @@ static const struct ieee80211_ops wl1271_ops = { | |||
4875 | .set_bitrate_mask = wl12xx_set_bitrate_mask, | 5285 | .set_bitrate_mask = wl12xx_set_bitrate_mask, |
4876 | .channel_switch = wl12xx_op_channel_switch, | 5286 | .channel_switch = wl12xx_op_channel_switch, |
4877 | .flush = wlcore_op_flush, | 5287 | .flush = wlcore_op_flush, |
5288 | .remain_on_channel = wlcore_op_remain_on_channel, | ||
5289 | .cancel_remain_on_channel = wlcore_op_cancel_remain_on_channel, | ||
5290 | .add_chanctx = wlcore_op_add_chanctx, | ||
5291 | .remove_chanctx = wlcore_op_remove_chanctx, | ||
5292 | .change_chanctx = wlcore_op_change_chanctx, | ||
5293 | .assign_vif_chanctx = wlcore_op_assign_vif_chanctx, | ||
5294 | .unassign_vif_chanctx = wlcore_op_unassign_vif_chanctx, | ||
5295 | .sta_rc_update = wlcore_op_sta_rc_update, | ||
4878 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | 5296 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) |
4879 | }; | 5297 | }; |
4880 | 5298 | ||
@@ -5044,34 +5462,6 @@ static struct bin_attribute fwlog_attr = { | |||
5044 | .read = wl1271_sysfs_read_fwlog, | 5462 | .read = wl1271_sysfs_read_fwlog, |
5045 | }; | 5463 | }; |
5046 | 5464 | ||
5047 | static void wl1271_connection_loss_work(struct work_struct *work) | ||
5048 | { | ||
5049 | struct delayed_work *dwork; | ||
5050 | struct wl1271 *wl; | ||
5051 | struct ieee80211_vif *vif; | ||
5052 | struct wl12xx_vif *wlvif; | ||
5053 | |||
5054 | dwork = container_of(work, struct delayed_work, work); | ||
5055 | wl = container_of(dwork, struct wl1271, connection_loss_work); | ||
5056 | |||
5057 | wl1271_info("Connection loss work."); | ||
5058 | |||
5059 | mutex_lock(&wl->mutex); | ||
5060 | |||
5061 | if (unlikely(wl->state != WLCORE_STATE_ON)) | ||
5062 | goto out; | ||
5063 | |||
5064 | /* Call mac80211 connection loss */ | ||
5065 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
5066 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | ||
5067 | goto out; | ||
5068 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
5069 | ieee80211_connection_loss(vif); | ||
5070 | } | ||
5071 | out: | ||
5072 | mutex_unlock(&wl->mutex); | ||
5073 | } | ||
5074 | |||
5075 | static void wl12xx_derive_mac_addresses(struct wl1271 *wl, u32 oui, u32 nic) | 5465 | static void wl12xx_derive_mac_addresses(struct wl1271 *wl, u32 oui, u32 nic) |
5076 | { | 5466 | { |
5077 | int i; | 5467 | int i; |
@@ -5117,7 +5507,7 @@ static int wl12xx_get_hw_info(struct wl1271 *wl) | |||
5117 | 5507 | ||
5118 | ret = wl12xx_set_power_on(wl); | 5508 | ret = wl12xx_set_power_on(wl); |
5119 | if (ret < 0) | 5509 | if (ret < 0) |
5120 | goto out; | 5510 | return ret; |
5121 | 5511 | ||
5122 | ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &wl->chip.id); | 5512 | ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &wl->chip.id); |
5123 | if (ret < 0) | 5513 | if (ret < 0) |
@@ -5207,10 +5597,9 @@ static const struct ieee80211_iface_limit wlcore_iface_limits[] = { | |||
5207 | }, | 5597 | }, |
5208 | }; | 5598 | }; |
5209 | 5599 | ||
5210 | static const struct ieee80211_iface_combination | 5600 | static struct ieee80211_iface_combination |
5211 | wlcore_iface_combinations[] = { | 5601 | wlcore_iface_combinations[] = { |
5212 | { | 5602 | { |
5213 | .num_different_channels = 1, | ||
5214 | .max_interfaces = 3, | 5603 | .max_interfaces = 3, |
5215 | .limits = wlcore_iface_limits, | 5604 | .limits = wlcore_iface_limits, |
5216 | .n_limits = ARRAY_SIZE(wlcore_iface_limits), | 5605 | .n_limits = ARRAY_SIZE(wlcore_iface_limits), |
@@ -5219,6 +5608,7 @@ wlcore_iface_combinations[] = { | |||
5219 | 5608 | ||
5220 | static int wl1271_init_ieee80211(struct wl1271 *wl) | 5609 | static int wl1271_init_ieee80211(struct wl1271 *wl) |
5221 | { | 5610 | { |
5611 | int i; | ||
5222 | static const u32 cipher_suites[] = { | 5612 | static const u32 cipher_suites[] = { |
5223 | WLAN_CIPHER_SUITE_WEP40, | 5613 | WLAN_CIPHER_SUITE_WEP40, |
5224 | WLAN_CIPHER_SUITE_WEP104, | 5614 | WLAN_CIPHER_SUITE_WEP104, |
@@ -5249,7 +5639,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
5249 | IEEE80211_HW_AP_LINK_PS | | 5639 | IEEE80211_HW_AP_LINK_PS | |
5250 | IEEE80211_HW_AMPDU_AGGREGATION | | 5640 | IEEE80211_HW_AMPDU_AGGREGATION | |
5251 | IEEE80211_HW_TX_AMPDU_SETUP_IN_HW | | 5641 | IEEE80211_HW_TX_AMPDU_SETUP_IN_HW | |
5252 | IEEE80211_HW_SCAN_WHILE_IDLE; | 5642 | IEEE80211_HW_SCAN_WHILE_IDLE | |
5643 | IEEE80211_HW_QUEUE_CONTROL; | ||
5253 | 5644 | ||
5254 | wl->hw->wiphy->cipher_suites = cipher_suites; | 5645 | wl->hw->wiphy->cipher_suites = cipher_suites; |
5255 | wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | 5646 | wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); |
@@ -5271,6 +5662,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
5271 | wl->hw->wiphy->max_sched_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - | 5662 | wl->hw->wiphy->max_sched_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - |
5272 | sizeof(struct ieee80211_header); | 5663 | sizeof(struct ieee80211_header); |
5273 | 5664 | ||
5665 | wl->hw->wiphy->max_remain_on_channel_duration = 5000; | ||
5666 | |||
5274 | wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD | | 5667 | wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD | |
5275 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | 5668 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; |
5276 | 5669 | ||
@@ -5279,6 +5672,22 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
5279 | ARRAY_SIZE(wl1271_channels_5ghz) > | 5672 | ARRAY_SIZE(wl1271_channels_5ghz) > |
5280 | WL1271_MAX_CHANNELS); | 5673 | WL1271_MAX_CHANNELS); |
5281 | /* | 5674 | /* |
5675 | * clear channel flags from the previous usage | ||
5676 | * and restore max_power & max_antenna_gain values. | ||
5677 | */ | ||
5678 | for (i = 0; i < ARRAY_SIZE(wl1271_channels); i++) { | ||
5679 | wl1271_band_2ghz.channels[i].flags = 0; | ||
5680 | wl1271_band_2ghz.channels[i].max_power = WLCORE_MAX_TXPWR; | ||
5681 | wl1271_band_2ghz.channels[i].max_antenna_gain = 0; | ||
5682 | } | ||
5683 | |||
5684 | for (i = 0; i < ARRAY_SIZE(wl1271_channels_5ghz); i++) { | ||
5685 | wl1271_band_5ghz.channels[i].flags = 0; | ||
5686 | wl1271_band_5ghz.channels[i].max_power = WLCORE_MAX_TXPWR; | ||
5687 | wl1271_band_5ghz.channels[i].max_antenna_gain = 0; | ||
5688 | } | ||
5689 | |||
5690 | /* | ||
5282 | * We keep local copies of the band structs because we need to | 5691 | * We keep local copies of the band structs because we need to |
5283 | * modify them on a per-device basis. | 5692 | * modify them on a per-device basis. |
5284 | */ | 5693 | */ |
@@ -5298,7 +5707,14 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
5298 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | 5707 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = |
5299 | &wl->bands[IEEE80211_BAND_5GHZ]; | 5708 | &wl->bands[IEEE80211_BAND_5GHZ]; |
5300 | 5709 | ||
5301 | wl->hw->queues = 4; | 5710 | /* |
5711 | * allow 4 queues per mac address we support + | ||
5712 | * 1 cab queue per mac + one global offchannel Tx queue | ||
5713 | */ | ||
5714 | wl->hw->queues = (NUM_TX_QUEUES + 1) * WLCORE_NUM_MAC_ADDRESSES + 1; | ||
5715 | |||
5716 | /* the last queue is the offchannel queue */ | ||
5717 | wl->hw->offchannel_tx_hw_queue = wl->hw->queues - 1; | ||
5302 | wl->hw->max_rates = 1; | 5718 | wl->hw->max_rates = 1; |
5303 | 5719 | ||
5304 | wl->hw->wiphy->reg_notifier = wl1271_reg_notify; | 5720 | wl->hw->wiphy->reg_notifier = wl1271_reg_notify; |
@@ -5311,6 +5727,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
5311 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; | 5727 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; |
5312 | 5728 | ||
5313 | /* allowed interface combinations */ | 5729 | /* allowed interface combinations */ |
5730 | wlcore_iface_combinations[0].num_different_channels = wl->num_channels; | ||
5314 | wl->hw->wiphy->iface_combinations = wlcore_iface_combinations; | 5731 | wl->hw->wiphy->iface_combinations = wlcore_iface_combinations; |
5315 | wl->hw->wiphy->n_iface_combinations = | 5732 | wl->hw->wiphy->n_iface_combinations = |
5316 | ARRAY_SIZE(wlcore_iface_combinations); | 5733 | ARRAY_SIZE(wlcore_iface_combinations); |
@@ -5327,7 +5744,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
5327 | 5744 | ||
5328 | #define WL1271_DEFAULT_CHANNEL 0 | 5745 | #define WL1271_DEFAULT_CHANNEL 0 |
5329 | 5746 | ||
5330 | struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size) | 5747 | struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size, |
5748 | u32 mbox_size) | ||
5331 | { | 5749 | { |
5332 | struct ieee80211_hw *hw; | 5750 | struct ieee80211_hw *hw; |
5333 | struct wl1271 *wl; | 5751 | struct wl1271 *wl; |
@@ -5369,9 +5787,8 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size) | |||
5369 | INIT_WORK(&wl->tx_work, wl1271_tx_work); | 5787 | INIT_WORK(&wl->tx_work, wl1271_tx_work); |
5370 | INIT_WORK(&wl->recovery_work, wl1271_recovery_work); | 5788 | INIT_WORK(&wl->recovery_work, wl1271_recovery_work); |
5371 | INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work); | 5789 | INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work); |
5790 | INIT_DELAYED_WORK(&wl->roc_complete_work, wlcore_roc_complete_work); | ||
5372 | INIT_DELAYED_WORK(&wl->tx_watchdog_work, wl12xx_tx_watchdog_work); | 5791 | INIT_DELAYED_WORK(&wl->tx_watchdog_work, wl12xx_tx_watchdog_work); |
5373 | INIT_DELAYED_WORK(&wl->connection_loss_work, | ||
5374 | wl1271_connection_loss_work); | ||
5375 | 5792 | ||
5376 | wl->freezable_wq = create_freezable_workqueue("wl12xx_wq"); | 5793 | wl->freezable_wq = create_freezable_workqueue("wl12xx_wq"); |
5377 | if (!wl->freezable_wq) { | 5794 | if (!wl->freezable_wq) { |
@@ -5387,14 +5804,15 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size) | |||
5387 | wl->flags = 0; | 5804 | wl->flags = 0; |
5388 | wl->sg_enabled = true; | 5805 | wl->sg_enabled = true; |
5389 | wl->sleep_auth = WL1271_PSM_ILLEGAL; | 5806 | wl->sleep_auth = WL1271_PSM_ILLEGAL; |
5807 | wl->recovery_count = 0; | ||
5390 | wl->hw_pg_ver = -1; | 5808 | wl->hw_pg_ver = -1; |
5391 | wl->ap_ps_map = 0; | 5809 | wl->ap_ps_map = 0; |
5392 | wl->ap_fw_ps_map = 0; | 5810 | wl->ap_fw_ps_map = 0; |
5393 | wl->quirks = 0; | 5811 | wl->quirks = 0; |
5394 | wl->platform_quirks = 0; | 5812 | wl->platform_quirks = 0; |
5395 | wl->sched_scanning = false; | ||
5396 | wl->system_hlid = WL12XX_SYSTEM_HLID; | 5813 | wl->system_hlid = WL12XX_SYSTEM_HLID; |
5397 | wl->active_sta_count = 0; | 5814 | wl->active_sta_count = 0; |
5815 | wl->active_link_count = 0; | ||
5398 | wl->fwlog_size = 0; | 5816 | wl->fwlog_size = 0; |
5399 | init_waitqueue_head(&wl->fwlog_waitq); | 5817 | init_waitqueue_head(&wl->fwlog_waitq); |
5400 | 5818 | ||
@@ -5434,14 +5852,24 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size) | |||
5434 | goto err_dummy_packet; | 5852 | goto err_dummy_packet; |
5435 | } | 5853 | } |
5436 | 5854 | ||
5437 | wl->mbox = kmalloc(sizeof(*wl->mbox), GFP_KERNEL | GFP_DMA); | 5855 | wl->mbox_size = mbox_size; |
5856 | wl->mbox = kmalloc(wl->mbox_size, GFP_KERNEL | GFP_DMA); | ||
5438 | if (!wl->mbox) { | 5857 | if (!wl->mbox) { |
5439 | ret = -ENOMEM; | 5858 | ret = -ENOMEM; |
5440 | goto err_fwlog; | 5859 | goto err_fwlog; |
5441 | } | 5860 | } |
5442 | 5861 | ||
5862 | wl->buffer_32 = kmalloc(sizeof(*wl->buffer_32), GFP_KERNEL); | ||
5863 | if (!wl->buffer_32) { | ||
5864 | ret = -ENOMEM; | ||
5865 | goto err_mbox; | ||
5866 | } | ||
5867 | |||
5443 | return hw; | 5868 | return hw; |
5444 | 5869 | ||
5870 | err_mbox: | ||
5871 | kfree(wl->mbox); | ||
5872 | |||
5445 | err_fwlog: | 5873 | err_fwlog: |
5446 | free_page((unsigned long)wl->fwlog); | 5874 | free_page((unsigned long)wl->fwlog); |
5447 | 5875 | ||
@@ -5480,6 +5908,8 @@ int wlcore_free_hw(struct wl1271 *wl) | |||
5480 | device_remove_file(wl->dev, &dev_attr_hw_pg_ver); | 5908 | device_remove_file(wl->dev, &dev_attr_hw_pg_ver); |
5481 | 5909 | ||
5482 | device_remove_file(wl->dev, &dev_attr_bt_coex_state); | 5910 | device_remove_file(wl->dev, &dev_attr_bt_coex_state); |
5911 | kfree(wl->buffer_32); | ||
5912 | kfree(wl->mbox); | ||
5483 | free_page((unsigned long)wl->fwlog); | 5913 | free_page((unsigned long)wl->fwlog); |
5484 | dev_kfree_skb(wl->dummy_packet); | 5914 | dev_kfree_skb(wl->dummy_packet); |
5485 | free_pages((unsigned long)wl->aggr_buf, get_order(wl->aggr_buf_size)); | 5915 | free_pages((unsigned long)wl->aggr_buf, get_order(wl->aggr_buf_size)); |
@@ -5712,10 +6142,10 @@ module_param_named(fwlog, fwlog_param, charp, 0); | |||
5712 | MODULE_PARM_DESC(fwlog, | 6142 | MODULE_PARM_DESC(fwlog, |
5713 | "FW logger options: continuous, ondemand, dbgpins or disable"); | 6143 | "FW logger options: continuous, ondemand, dbgpins or disable"); |
5714 | 6144 | ||
5715 | module_param(bug_on_recovery, bool, S_IRUSR | S_IWUSR); | 6145 | module_param(bug_on_recovery, int, S_IRUSR | S_IWUSR); |
5716 | MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery"); | 6146 | MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery"); |
5717 | 6147 | ||
5718 | module_param(no_recovery, bool, S_IRUSR | S_IWUSR); | 6148 | module_param(no_recovery, int, S_IRUSR | S_IWUSR); |
5719 | MODULE_PARM_DESC(no_recovery, "Prevent HW recovery. FW will remain stuck."); | 6149 | MODULE_PARM_DESC(no_recovery, "Prevent HW recovery. FW will remain stuck."); |
5720 | 6150 | ||
5721 | MODULE_LICENSE("GPL"); | 6151 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/net/wireless/ti/wlcore/ps.c b/drivers/net/wireless/ti/wlcore/ps.c index 4d1414a673fb..9b7b6e2e4fbc 100644 --- a/drivers/net/wireless/ti/wlcore/ps.c +++ b/drivers/net/wireless/ti/wlcore/ps.c | |||
@@ -151,9 +151,6 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl) | |||
151 | wl12xx_queue_recovery_work(wl); | 151 | wl12xx_queue_recovery_work(wl); |
152 | ret = -ETIMEDOUT; | 152 | ret = -ETIMEDOUT; |
153 | goto err; | 153 | goto err; |
154 | } else if (ret < 0) { | ||
155 | wl1271_error("ELP wakeup completion error."); | ||
156 | goto err; | ||
157 | } | 154 | } |
158 | } | 155 | } |
159 | 156 | ||
@@ -242,11 +239,12 @@ static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid) | |||
242 | struct ieee80211_tx_info *info; | 239 | struct ieee80211_tx_info *info; |
243 | unsigned long flags; | 240 | unsigned long flags; |
244 | int filtered[NUM_TX_QUEUES]; | 241 | int filtered[NUM_TX_QUEUES]; |
242 | struct wl1271_link *lnk = &wl->links[hlid]; | ||
245 | 243 | ||
246 | /* filter all frames currently in the low level queues for this hlid */ | 244 | /* filter all frames currently in the low level queues for this hlid */ |
247 | for (i = 0; i < NUM_TX_QUEUES; i++) { | 245 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
248 | filtered[i] = 0; | 246 | filtered[i] = 0; |
249 | while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) { | 247 | while ((skb = skb_dequeue(&lnk->tx_queue[i]))) { |
250 | filtered[i]++; | 248 | filtered[i]++; |
251 | 249 | ||
252 | if (WARN_ON(wl12xx_is_dummy_packet(wl, skb))) | 250 | if (WARN_ON(wl12xx_is_dummy_packet(wl, skb))) |
@@ -260,8 +258,11 @@ static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid) | |||
260 | } | 258 | } |
261 | 259 | ||
262 | spin_lock_irqsave(&wl->wl_lock, flags); | 260 | spin_lock_irqsave(&wl->wl_lock, flags); |
263 | for (i = 0; i < NUM_TX_QUEUES; i++) | 261 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
264 | wl->tx_queue_count[i] -= filtered[i]; | 262 | wl->tx_queue_count[i] -= filtered[i]; |
263 | if (lnk->wlvif) | ||
264 | lnk->wlvif->tx_queue_count[i] -= filtered[i]; | ||
265 | } | ||
265 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 266 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
266 | 267 | ||
267 | wl1271_handle_tx_low_watermark(wl); | 268 | wl1271_handle_tx_low_watermark(wl); |
diff --git a/drivers/net/wireless/ti/wlcore/rx.c b/drivers/net/wireless/ti/wlcore/rx.c index 9ee0ec6fd1db..6791a1a6afba 100644 --- a/drivers/net/wireless/ti/wlcore/rx.c +++ b/drivers/net/wireless/ti/wlcore/rx.c | |||
@@ -92,11 +92,16 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
92 | status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED | | 92 | status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED | |
93 | RX_FLAG_DECRYPTED; | 93 | RX_FLAG_DECRYPTED; |
94 | 94 | ||
95 | if (unlikely(desc_err_code == WL1271_RX_DESC_MIC_FAIL)) { | 95 | if (unlikely(desc_err_code & WL1271_RX_DESC_MIC_FAIL)) { |
96 | status->flag |= RX_FLAG_MMIC_ERROR; | 96 | status->flag |= RX_FLAG_MMIC_ERROR; |
97 | wl1271_warning("Michael MIC error"); | 97 | wl1271_warning("Michael MIC error. Desc: 0x%x", |
98 | desc_err_code); | ||
98 | } | 99 | } |
99 | } | 100 | } |
101 | |||
102 | if (beacon) | ||
103 | wlcore_set_pending_regdomain_ch(wl, (u16)desc->channel, | ||
104 | status->band); | ||
100 | } | 105 | } |
101 | 106 | ||
102 | static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | 107 | static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, |
@@ -108,7 +113,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
108 | u8 *buf; | 113 | u8 *buf; |
109 | u8 beacon = 0; | 114 | u8 beacon = 0; |
110 | u8 is_data = 0; | 115 | u8 is_data = 0; |
111 | u8 reserved = 0; | 116 | u8 reserved = 0, offset_to_data = 0; |
112 | u16 seq_num; | 117 | u16 seq_num; |
113 | u32 pkt_data_len; | 118 | u32 pkt_data_len; |
114 | 119 | ||
@@ -128,6 +133,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
128 | 133 | ||
129 | if (rx_align == WLCORE_RX_BUF_UNALIGNED) | 134 | if (rx_align == WLCORE_RX_BUF_UNALIGNED) |
130 | reserved = RX_BUF_ALIGN; | 135 | reserved = RX_BUF_ALIGN; |
136 | else if (rx_align == WLCORE_RX_BUF_PADDED) | ||
137 | offset_to_data = RX_BUF_ALIGN; | ||
131 | 138 | ||
132 | /* the data read starts with the descriptor */ | 139 | /* the data read starts with the descriptor */ |
133 | desc = (struct wl1271_rx_descriptor *) data; | 140 | desc = (struct wl1271_rx_descriptor *) data; |
@@ -139,19 +146,15 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
139 | return 0; | 146 | return 0; |
140 | } | 147 | } |
141 | 148 | ||
142 | switch (desc->status & WL1271_RX_DESC_STATUS_MASK) { | ||
143 | /* discard corrupted packets */ | 149 | /* discard corrupted packets */ |
144 | case WL1271_RX_DESC_DRIVER_RX_Q_FAIL: | 150 | if (desc->status & WL1271_RX_DESC_DECRYPT_FAIL) { |
145 | case WL1271_RX_DESC_DECRYPT_FAIL: | 151 | hdr = (void *)(data + sizeof(*desc) + offset_to_data); |
146 | wl1271_warning("corrupted packet in RX with status: 0x%x", | 152 | wl1271_warning("corrupted packet in RX: status: 0x%x len: %d", |
147 | desc->status & WL1271_RX_DESC_STATUS_MASK); | 153 | desc->status & WL1271_RX_DESC_STATUS_MASK, |
148 | return -EINVAL; | 154 | pkt_data_len); |
149 | case WL1271_RX_DESC_SUCCESS: | 155 | wl1271_dump((DEBUG_RX|DEBUG_CMD), "PKT: ", data + sizeof(*desc), |
150 | case WL1271_RX_DESC_MIC_FAIL: | 156 | min(pkt_data_len, |
151 | break; | 157 | ieee80211_hdrlen(hdr->frame_control))); |
152 | default: | ||
153 | wl1271_error("invalid RX descriptor status: 0x%x", | ||
154 | desc->status & WL1271_RX_DESC_STATUS_MASK); | ||
155 | return -EINVAL; | 158 | return -EINVAL; |
156 | } | 159 | } |
157 | 160 | ||
diff --git a/drivers/net/wireless/ti/wlcore/rx.h b/drivers/net/wireless/ti/wlcore/rx.h index 71eba1899915..3363f60fb7da 100644 --- a/drivers/net/wireless/ti/wlcore/rx.h +++ b/drivers/net/wireless/ti/wlcore/rx.h | |||
@@ -84,12 +84,11 @@ | |||
84 | * Bits 3-5 - process_id tag (AP mode FW) | 84 | * Bits 3-5 - process_id tag (AP mode FW) |
85 | * Bits 6-7 - reserved | 85 | * Bits 6-7 - reserved |
86 | */ | 86 | */ |
87 | #define WL1271_RX_DESC_STATUS_MASK 0x03 | 87 | #define WL1271_RX_DESC_STATUS_MASK 0x07 |
88 | 88 | ||
89 | #define WL1271_RX_DESC_SUCCESS 0x00 | 89 | #define WL1271_RX_DESC_SUCCESS 0x00 |
90 | #define WL1271_RX_DESC_DECRYPT_FAIL 0x01 | 90 | #define WL1271_RX_DESC_DECRYPT_FAIL 0x01 |
91 | #define WL1271_RX_DESC_MIC_FAIL 0x02 | 91 | #define WL1271_RX_DESC_MIC_FAIL 0x02 |
92 | #define WL1271_RX_DESC_DRIVER_RX_Q_FAIL 0x03 | ||
93 | 92 | ||
94 | #define RX_MEM_BLOCK_MASK 0xFF | 93 | #define RX_MEM_BLOCK_MASK 0xFF |
95 | #define RX_BUF_SIZE_MASK 0xFFF00 | 94 | #define RX_BUF_SIZE_MASK 0xFFF00 |
diff --git a/drivers/net/wireless/ti/wlcore/scan.c b/drivers/net/wireless/ti/wlcore/scan.c index d00501493dfe..f407101e525b 100644 --- a/drivers/net/wireless/ti/wlcore/scan.c +++ b/drivers/net/wireless/ti/wlcore/scan.c | |||
@@ -35,7 +35,6 @@ void wl1271_scan_complete_work(struct work_struct *work) | |||
35 | { | 35 | { |
36 | struct delayed_work *dwork; | 36 | struct delayed_work *dwork; |
37 | struct wl1271 *wl; | 37 | struct wl1271 *wl; |
38 | struct ieee80211_vif *vif; | ||
39 | struct wl12xx_vif *wlvif; | 38 | struct wl12xx_vif *wlvif; |
40 | int ret; | 39 | int ret; |
41 | 40 | ||
@@ -52,8 +51,7 @@ void wl1271_scan_complete_work(struct work_struct *work) | |||
52 | if (wl->scan.state == WL1271_SCAN_STATE_IDLE) | 51 | if (wl->scan.state == WL1271_SCAN_STATE_IDLE) |
53 | goto out; | 52 | goto out; |
54 | 53 | ||
55 | vif = wl->scan_vif; | 54 | wlvif = wl->scan_wlvif; |
56 | wlvif = wl12xx_vif_to_data(vif); | ||
57 | 55 | ||
58 | /* | 56 | /* |
59 | * Rearm the tx watchdog just before idling scan. This | 57 | * Rearm the tx watchdog just before idling scan. This |
@@ -64,7 +62,7 @@ void wl1271_scan_complete_work(struct work_struct *work) | |||
64 | wl->scan.state = WL1271_SCAN_STATE_IDLE; | 62 | wl->scan.state = WL1271_SCAN_STATE_IDLE; |
65 | memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); | 63 | memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); |
66 | wl->scan.req = NULL; | 64 | wl->scan.req = NULL; |
67 | wl->scan_vif = NULL; | 65 | wl->scan_wlvif = NULL; |
68 | 66 | ||
69 | ret = wl1271_ps_elp_wakeup(wl); | 67 | ret = wl1271_ps_elp_wakeup(wl); |
70 | if (ret < 0) | 68 | if (ret < 0) |
@@ -82,6 +80,8 @@ void wl1271_scan_complete_work(struct work_struct *work) | |||
82 | wl12xx_queue_recovery_work(wl); | 80 | wl12xx_queue_recovery_work(wl); |
83 | } | 81 | } |
84 | 82 | ||
83 | wlcore_cmd_regdomain_config_locked(wl); | ||
84 | |||
85 | ieee80211_scan_completed(wl->hw, false); | 85 | ieee80211_scan_completed(wl->hw, false); |
86 | 86 | ||
87 | out: | 87 | out: |
@@ -89,371 +89,99 @@ out: | |||
89 | 89 | ||
90 | } | 90 | } |
91 | 91 | ||
92 | 92 | static void wlcore_started_vifs_iter(void *data, u8 *mac, | |
93 | static int wl1271_get_scan_channels(struct wl1271 *wl, | 93 | struct ieee80211_vif *vif) |
94 | struct cfg80211_scan_request *req, | ||
95 | struct basic_scan_channel_params *channels, | ||
96 | enum ieee80211_band band, bool passive) | ||
97 | { | ||
98 | struct conf_scan_settings *c = &wl->conf.scan; | ||
99 | int i, j; | ||
100 | u32 flags; | ||
101 | |||
102 | for (i = 0, j = 0; | ||
103 | i < req->n_channels && j < WL1271_SCAN_MAX_CHANNELS; | ||
104 | i++) { | ||
105 | flags = req->channels[i]->flags; | ||
106 | |||
107 | if (!test_bit(i, wl->scan.scanned_ch) && | ||
108 | !(flags & IEEE80211_CHAN_DISABLED) && | ||
109 | (req->channels[i]->band == band) && | ||
110 | /* | ||
111 | * In passive scans, we scan all remaining | ||
112 | * channels, even if not marked as such. | ||
113 | * In active scans, we only scan channels not | ||
114 | * marked as passive. | ||
115 | */ | ||
116 | (passive || !(flags & IEEE80211_CHAN_PASSIVE_SCAN))) { | ||
117 | wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ", | ||
118 | req->channels[i]->band, | ||
119 | req->channels[i]->center_freq); | ||
120 | wl1271_debug(DEBUG_SCAN, "hw_value %d, flags %X", | ||
121 | req->channels[i]->hw_value, | ||
122 | req->channels[i]->flags); | ||
123 | wl1271_debug(DEBUG_SCAN, | ||
124 | "max_antenna_gain %d, max_power %d", | ||
125 | req->channels[i]->max_antenna_gain, | ||
126 | req->channels[i]->max_power); | ||
127 | wl1271_debug(DEBUG_SCAN, "beacon_found %d", | ||
128 | req->channels[i]->beacon_found); | ||
129 | |||
130 | if (!passive) { | ||
131 | channels[j].min_duration = | ||
132 | cpu_to_le32(c->min_dwell_time_active); | ||
133 | channels[j].max_duration = | ||
134 | cpu_to_le32(c->max_dwell_time_active); | ||
135 | } else { | ||
136 | channels[j].min_duration = | ||
137 | cpu_to_le32(c->min_dwell_time_passive); | ||
138 | channels[j].max_duration = | ||
139 | cpu_to_le32(c->max_dwell_time_passive); | ||
140 | } | ||
141 | channels[j].early_termination = 0; | ||
142 | channels[j].tx_power_att = req->channels[i]->max_power; | ||
143 | channels[j].channel = req->channels[i]->hw_value; | ||
144 | |||
145 | memset(&channels[j].bssid_lsb, 0xff, 4); | ||
146 | memset(&channels[j].bssid_msb, 0xff, 2); | ||
147 | |||
148 | /* Mark the channels we already used */ | ||
149 | set_bit(i, wl->scan.scanned_ch); | ||
150 | |||
151 | j++; | ||
152 | } | ||
153 | } | ||
154 | |||
155 | return j; | ||
156 | } | ||
157 | |||
158 | #define WL1271_NOTHING_TO_SCAN 1 | ||
159 | |||
160 | static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif, | ||
161 | enum ieee80211_band band, | ||
162 | bool passive, u32 basic_rate) | ||
163 | { | 94 | { |
164 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | 95 | int *count = (int *)data; |
165 | struct wl1271_cmd_scan *cmd; | ||
166 | struct wl1271_cmd_trigger_scan_to *trigger; | ||
167 | int ret; | ||
168 | u16 scan_options = 0; | ||
169 | |||
170 | /* skip active scans if we don't have SSIDs */ | ||
171 | if (!passive && wl->scan.req->n_ssids == 0) | ||
172 | return WL1271_NOTHING_TO_SCAN; | ||
173 | |||
174 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
175 | trigger = kzalloc(sizeof(*trigger), GFP_KERNEL); | ||
176 | if (!cmd || !trigger) { | ||
177 | ret = -ENOMEM; | ||
178 | goto out; | ||
179 | } | ||
180 | |||
181 | if (wl->conf.scan.split_scan_timeout) | ||
182 | scan_options |= WL1271_SCAN_OPT_SPLIT_SCAN; | ||
183 | |||
184 | if (passive) | ||
185 | scan_options |= WL1271_SCAN_OPT_PASSIVE; | ||
186 | |||
187 | cmd->params.role_id = wlvif->role_id; | ||
188 | |||
189 | if (WARN_ON(cmd->params.role_id == WL12XX_INVALID_ROLE_ID)) { | ||
190 | ret = -EINVAL; | ||
191 | goto out; | ||
192 | } | ||
193 | |||
194 | cmd->params.scan_options = cpu_to_le16(scan_options); | ||
195 | |||
196 | cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req, | ||
197 | cmd->channels, | ||
198 | band, passive); | ||
199 | if (cmd->params.n_ch == 0) { | ||
200 | ret = WL1271_NOTHING_TO_SCAN; | ||
201 | goto out; | ||
202 | } | ||
203 | |||
204 | cmd->params.tx_rate = cpu_to_le32(basic_rate); | ||
205 | cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs; | ||
206 | cmd->params.tid_trigger = CONF_TX_AC_ANY_TID; | ||
207 | cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; | ||
208 | |||
209 | if (band == IEEE80211_BAND_2GHZ) | ||
210 | cmd->params.band = WL1271_SCAN_BAND_2_4_GHZ; | ||
211 | else | ||
212 | cmd->params.band = WL1271_SCAN_BAND_5_GHZ; | ||
213 | |||
214 | if (wl->scan.ssid_len && wl->scan.ssid) { | ||
215 | cmd->params.ssid_len = wl->scan.ssid_len; | ||
216 | memcpy(cmd->params.ssid, wl->scan.ssid, wl->scan.ssid_len); | ||
217 | } | ||
218 | |||
219 | memcpy(cmd->addr, vif->addr, ETH_ALEN); | ||
220 | |||
221 | ret = wl12xx_cmd_build_probe_req(wl, wlvif, | ||
222 | cmd->params.role_id, band, | ||
223 | wl->scan.ssid, wl->scan.ssid_len, | ||
224 | wl->scan.req->ie, | ||
225 | wl->scan.req->ie_len, false); | ||
226 | if (ret < 0) { | ||
227 | wl1271_error("PROBE request template failed"); | ||
228 | goto out; | ||
229 | } | ||
230 | |||
231 | trigger->timeout = cpu_to_le32(wl->conf.scan.split_scan_timeout); | ||
232 | ret = wl1271_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger, | ||
233 | sizeof(*trigger), 0); | ||
234 | if (ret < 0) { | ||
235 | wl1271_error("trigger scan to failed for hw scan"); | ||
236 | goto out; | ||
237 | } | ||
238 | |||
239 | wl1271_dump(DEBUG_SCAN, "SCAN: ", cmd, sizeof(*cmd)); | ||
240 | 96 | ||
241 | ret = wl1271_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd), 0); | 97 | if (!vif->bss_conf.idle) |
242 | if (ret < 0) { | 98 | (*count)++; |
243 | wl1271_error("SCAN failed"); | ||
244 | goto out; | ||
245 | } | ||
246 | |||
247 | out: | ||
248 | kfree(cmd); | ||
249 | kfree(trigger); | ||
250 | return ret; | ||
251 | } | 99 | } |
252 | 100 | ||
253 | void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif) | 101 | static int wlcore_count_started_vifs(struct wl1271 *wl) |
254 | { | 102 | { |
255 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | 103 | int count = 0; |
256 | int ret = 0; | ||
257 | enum ieee80211_band band; | ||
258 | u32 rate, mask; | ||
259 | |||
260 | switch (wl->scan.state) { | ||
261 | case WL1271_SCAN_STATE_IDLE: | ||
262 | break; | ||
263 | |||
264 | case WL1271_SCAN_STATE_2GHZ_ACTIVE: | ||
265 | band = IEEE80211_BAND_2GHZ; | ||
266 | mask = wlvif->bitrate_masks[band]; | ||
267 | if (wl->scan.req->no_cck) { | ||
268 | mask &= ~CONF_TX_CCK_RATES; | ||
269 | if (!mask) | ||
270 | mask = CONF_TX_RATE_MASK_BASIC_P2P; | ||
271 | } | ||
272 | rate = wl1271_tx_min_rate_get(wl, mask); | ||
273 | ret = wl1271_scan_send(wl, vif, band, false, rate); | ||
274 | if (ret == WL1271_NOTHING_TO_SCAN) { | ||
275 | wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE; | ||
276 | wl1271_scan_stm(wl, vif); | ||
277 | } | ||
278 | |||
279 | break; | ||
280 | |||
281 | case WL1271_SCAN_STATE_2GHZ_PASSIVE: | ||
282 | band = IEEE80211_BAND_2GHZ; | ||
283 | mask = wlvif->bitrate_masks[band]; | ||
284 | if (wl->scan.req->no_cck) { | ||
285 | mask &= ~CONF_TX_CCK_RATES; | ||
286 | if (!mask) | ||
287 | mask = CONF_TX_RATE_MASK_BASIC_P2P; | ||
288 | } | ||
289 | rate = wl1271_tx_min_rate_get(wl, mask); | ||
290 | ret = wl1271_scan_send(wl, vif, band, true, rate); | ||
291 | if (ret == WL1271_NOTHING_TO_SCAN) { | ||
292 | if (wl->enable_11a) | ||
293 | wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE; | ||
294 | else | ||
295 | wl->scan.state = WL1271_SCAN_STATE_DONE; | ||
296 | wl1271_scan_stm(wl, vif); | ||
297 | } | ||
298 | |||
299 | break; | ||
300 | 104 | ||
301 | case WL1271_SCAN_STATE_5GHZ_ACTIVE: | 105 | ieee80211_iterate_active_interfaces_atomic(wl->hw, |
302 | band = IEEE80211_BAND_5GHZ; | 106 | IEEE80211_IFACE_ITER_RESUME_ALL, |
303 | rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); | 107 | wlcore_started_vifs_iter, &count); |
304 | ret = wl1271_scan_send(wl, vif, band, false, rate); | 108 | return count; |
305 | if (ret == WL1271_NOTHING_TO_SCAN) { | ||
306 | wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE; | ||
307 | wl1271_scan_stm(wl, vif); | ||
308 | } | ||
309 | |||
310 | break; | ||
311 | |||
312 | case WL1271_SCAN_STATE_5GHZ_PASSIVE: | ||
313 | band = IEEE80211_BAND_5GHZ; | ||
314 | rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); | ||
315 | ret = wl1271_scan_send(wl, vif, band, true, rate); | ||
316 | if (ret == WL1271_NOTHING_TO_SCAN) { | ||
317 | wl->scan.state = WL1271_SCAN_STATE_DONE; | ||
318 | wl1271_scan_stm(wl, vif); | ||
319 | } | ||
320 | |||
321 | break; | ||
322 | |||
323 | case WL1271_SCAN_STATE_DONE: | ||
324 | wl->scan.failed = false; | ||
325 | cancel_delayed_work(&wl->scan_complete_work); | ||
326 | ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, | ||
327 | msecs_to_jiffies(0)); | ||
328 | break; | ||
329 | |||
330 | default: | ||
331 | wl1271_error("invalid scan state"); | ||
332 | break; | ||
333 | } | ||
334 | |||
335 | if (ret < 0) { | ||
336 | cancel_delayed_work(&wl->scan_complete_work); | ||
337 | ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, | ||
338 | msecs_to_jiffies(0)); | ||
339 | } | ||
340 | } | ||
341 | |||
342 | int wl1271_scan(struct wl1271 *wl, struct ieee80211_vif *vif, | ||
343 | const u8 *ssid, size_t ssid_len, | ||
344 | struct cfg80211_scan_request *req) | ||
345 | { | ||
346 | /* | ||
347 | * cfg80211 should guarantee that we don't get more channels | ||
348 | * than what we have registered. | ||
349 | */ | ||
350 | BUG_ON(req->n_channels > WL1271_MAX_CHANNELS); | ||
351 | |||
352 | if (wl->scan.state != WL1271_SCAN_STATE_IDLE) | ||
353 | return -EBUSY; | ||
354 | |||
355 | wl->scan.state = WL1271_SCAN_STATE_2GHZ_ACTIVE; | ||
356 | |||
357 | if (ssid_len && ssid) { | ||
358 | wl->scan.ssid_len = ssid_len; | ||
359 | memcpy(wl->scan.ssid, ssid, ssid_len); | ||
360 | } else { | ||
361 | wl->scan.ssid_len = 0; | ||
362 | } | ||
363 | |||
364 | wl->scan_vif = vif; | ||
365 | wl->scan.req = req; | ||
366 | memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); | ||
367 | |||
368 | /* we assume failure so that timeout scenarios are handled correctly */ | ||
369 | wl->scan.failed = true; | ||
370 | ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, | ||
371 | msecs_to_jiffies(WL1271_SCAN_TIMEOUT)); | ||
372 | |||
373 | wl1271_scan_stm(wl, vif); | ||
374 | |||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | int wl1271_scan_stop(struct wl1271 *wl) | ||
379 | { | ||
380 | struct wl1271_cmd_header *cmd = NULL; | ||
381 | int ret = 0; | ||
382 | |||
383 | if (WARN_ON(wl->scan.state == WL1271_SCAN_STATE_IDLE)) | ||
384 | return -EINVAL; | ||
385 | |||
386 | wl1271_debug(DEBUG_CMD, "cmd scan stop"); | ||
387 | |||
388 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
389 | if (!cmd) { | ||
390 | ret = -ENOMEM; | ||
391 | goto out; | ||
392 | } | ||
393 | |||
394 | ret = wl1271_cmd_send(wl, CMD_STOP_SCAN, cmd, | ||
395 | sizeof(*cmd), 0); | ||
396 | if (ret < 0) { | ||
397 | wl1271_error("cmd stop_scan failed"); | ||
398 | goto out; | ||
399 | } | ||
400 | out: | ||
401 | kfree(cmd); | ||
402 | return ret; | ||
403 | } | 109 | } |
404 | 110 | ||
405 | static int | 111 | static int |
406 | wl1271_scan_get_sched_scan_channels(struct wl1271 *wl, | 112 | wlcore_scan_get_channels(struct wl1271 *wl, |
407 | struct cfg80211_sched_scan_request *req, | 113 | struct ieee80211_channel *req_channels[], |
408 | struct conn_scan_ch_params *channels, | 114 | u32 n_channels, |
409 | u32 band, bool radar, bool passive, | 115 | u32 n_ssids, |
410 | int start, int max_channels, | 116 | struct conn_scan_ch_params *channels, |
411 | u8 *n_pactive_ch) | 117 | u32 band, bool radar, bool passive, |
118 | int start, int max_channels, | ||
119 | u8 *n_pactive_ch, | ||
120 | int scan_type) | ||
412 | { | 121 | { |
413 | struct conf_sched_scan_settings *c = &wl->conf.sched_scan; | ||
414 | int i, j; | 122 | int i, j; |
415 | u32 flags; | 123 | u32 flags; |
416 | bool force_passive = !req->n_ssids; | 124 | bool force_passive = !n_ssids; |
417 | u32 min_dwell_time_active, max_dwell_time_active, delta_per_probe; | 125 | u32 min_dwell_time_active, max_dwell_time_active; |
418 | u32 dwell_time_passive, dwell_time_dfs; | 126 | u32 dwell_time_passive, dwell_time_dfs; |
419 | 127 | ||
420 | if (band == IEEE80211_BAND_5GHZ) | 128 | /* configure dwell times according to scan type */ |
421 | delta_per_probe = c->dwell_time_delta_per_probe_5; | 129 | if (scan_type == SCAN_TYPE_SEARCH) { |
422 | else | 130 | struct conf_scan_settings *c = &wl->conf.scan; |
423 | delta_per_probe = c->dwell_time_delta_per_probe; | 131 | bool active_vif_exists = !!wlcore_count_started_vifs(wl); |
132 | |||
133 | min_dwell_time_active = active_vif_exists ? | ||
134 | c->min_dwell_time_active : | ||
135 | c->min_dwell_time_active_long; | ||
136 | max_dwell_time_active = active_vif_exists ? | ||
137 | c->max_dwell_time_active : | ||
138 | c->max_dwell_time_active_long; | ||
139 | dwell_time_passive = c->dwell_time_passive; | ||
140 | dwell_time_dfs = c->dwell_time_dfs; | ||
141 | } else { | ||
142 | struct conf_sched_scan_settings *c = &wl->conf.sched_scan; | ||
143 | u32 delta_per_probe; | ||
424 | 144 | ||
425 | min_dwell_time_active = c->base_dwell_time + | 145 | if (band == IEEE80211_BAND_5GHZ) |
426 | req->n_ssids * c->num_probe_reqs * delta_per_probe; | 146 | delta_per_probe = c->dwell_time_delta_per_probe_5; |
147 | else | ||
148 | delta_per_probe = c->dwell_time_delta_per_probe; | ||
427 | 149 | ||
428 | max_dwell_time_active = min_dwell_time_active + c->max_dwell_time_delta; | 150 | min_dwell_time_active = c->base_dwell_time + |
151 | n_ssids * c->num_probe_reqs * delta_per_probe; | ||
429 | 152 | ||
153 | max_dwell_time_active = min_dwell_time_active + | ||
154 | c->max_dwell_time_delta; | ||
155 | dwell_time_passive = c->dwell_time_passive; | ||
156 | dwell_time_dfs = c->dwell_time_dfs; | ||
157 | } | ||
430 | min_dwell_time_active = DIV_ROUND_UP(min_dwell_time_active, 1000); | 158 | min_dwell_time_active = DIV_ROUND_UP(min_dwell_time_active, 1000); |
431 | max_dwell_time_active = DIV_ROUND_UP(max_dwell_time_active, 1000); | 159 | max_dwell_time_active = DIV_ROUND_UP(max_dwell_time_active, 1000); |
432 | dwell_time_passive = DIV_ROUND_UP(c->dwell_time_passive, 1000); | 160 | dwell_time_passive = DIV_ROUND_UP(dwell_time_passive, 1000); |
433 | dwell_time_dfs = DIV_ROUND_UP(c->dwell_time_dfs, 1000); | 161 | dwell_time_dfs = DIV_ROUND_UP(dwell_time_dfs, 1000); |
434 | 162 | ||
435 | for (i = 0, j = start; | 163 | for (i = 0, j = start; |
436 | i < req->n_channels && j < max_channels; | 164 | i < n_channels && j < max_channels; |
437 | i++) { | 165 | i++) { |
438 | flags = req->channels[i]->flags; | 166 | flags = req_channels[i]->flags; |
439 | 167 | ||
440 | if (force_passive) | 168 | if (force_passive) |
441 | flags |= IEEE80211_CHAN_PASSIVE_SCAN; | 169 | flags |= IEEE80211_CHAN_PASSIVE_SCAN; |
442 | 170 | ||
443 | if ((req->channels[i]->band == band) && | 171 | if ((req_channels[i]->band == band) && |
444 | !(flags & IEEE80211_CHAN_DISABLED) && | 172 | !(flags & IEEE80211_CHAN_DISABLED) && |
445 | (!!(flags & IEEE80211_CHAN_RADAR) == radar) && | 173 | (!!(flags & IEEE80211_CHAN_RADAR) == radar) && |
446 | /* if radar is set, we ignore the passive flag */ | 174 | /* if radar is set, we ignore the passive flag */ |
447 | (radar || | 175 | (radar || |
448 | !!(flags & IEEE80211_CHAN_PASSIVE_SCAN) == passive)) { | 176 | !!(flags & IEEE80211_CHAN_PASSIVE_SCAN) == passive)) { |
449 | wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ", | 177 | wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ", |
450 | req->channels[i]->band, | 178 | req_channels[i]->band, |
451 | req->channels[i]->center_freq); | 179 | req_channels[i]->center_freq); |
452 | wl1271_debug(DEBUG_SCAN, "hw_value %d, flags %X", | 180 | wl1271_debug(DEBUG_SCAN, "hw_value %d, flags %X", |
453 | req->channels[i]->hw_value, | 181 | req_channels[i]->hw_value, |
454 | req->channels[i]->flags); | 182 | req_channels[i]->flags); |
455 | wl1271_debug(DEBUG_SCAN, "max_power %d", | 183 | wl1271_debug(DEBUG_SCAN, "max_power %d", |
456 | req->channels[i]->max_power); | 184 | req_channels[i]->max_power); |
457 | wl1271_debug(DEBUG_SCAN, "min_dwell_time %d max dwell time %d", | 185 | wl1271_debug(DEBUG_SCAN, "min_dwell_time %d max dwell time %d", |
458 | min_dwell_time_active, | 186 | min_dwell_time_active, |
459 | max_dwell_time_active); | 187 | max_dwell_time_active); |
@@ -473,10 +201,11 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl, | |||
473 | channels[j].max_duration = | 201 | channels[j].max_duration = |
474 | cpu_to_le16(max_dwell_time_active); | 202 | cpu_to_le16(max_dwell_time_active); |
475 | 203 | ||
476 | channels[j].tx_power_att = req->channels[i]->max_power; | 204 | channels[j].tx_power_att = req_channels[i]->max_power; |
477 | channels[j].channel = req->channels[i]->hw_value; | 205 | channels[j].channel = req_channels[i]->hw_value; |
478 | 206 | ||
479 | if ((band == IEEE80211_BAND_2GHZ) && | 207 | if (n_pactive_ch && |
208 | (band == IEEE80211_BAND_2GHZ) && | ||
480 | (channels[j].channel >= 12) && | 209 | (channels[j].channel >= 12) && |
481 | (channels[j].channel <= 14) && | 210 | (channels[j].channel <= 14) && |
482 | (flags & IEEE80211_CHAN_PASSIVE_SCAN) && | 211 | (flags & IEEE80211_CHAN_PASSIVE_SCAN) && |
@@ -500,51 +229,80 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl, | |||
500 | return j - start; | 229 | return j - start; |
501 | } | 230 | } |
502 | 231 | ||
503 | static bool | 232 | bool |
504 | wl1271_scan_sched_scan_channels(struct wl1271 *wl, | 233 | wlcore_set_scan_chan_params(struct wl1271 *wl, |
505 | struct cfg80211_sched_scan_request *req, | 234 | struct wlcore_scan_channels *cfg, |
506 | struct wl1271_cmd_sched_scan_config *cfg) | 235 | struct ieee80211_channel *channels[], |
236 | u32 n_channels, | ||
237 | u32 n_ssids, | ||
238 | int scan_type) | ||
507 | { | 239 | { |
508 | u8 n_pactive_ch = 0; | 240 | u8 n_pactive_ch = 0; |
509 | 241 | ||
510 | cfg->passive[0] = | 242 | cfg->passive[0] = |
511 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_2, | 243 | wlcore_scan_get_channels(wl, |
512 | IEEE80211_BAND_2GHZ, | 244 | channels, |
513 | false, true, 0, | 245 | n_channels, |
514 | MAX_CHANNELS_2GHZ, | 246 | n_ssids, |
515 | &n_pactive_ch); | 247 | cfg->channels_2, |
248 | IEEE80211_BAND_2GHZ, | ||
249 | false, true, 0, | ||
250 | MAX_CHANNELS_2GHZ, | ||
251 | &n_pactive_ch, | ||
252 | scan_type); | ||
516 | cfg->active[0] = | 253 | cfg->active[0] = |
517 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_2, | 254 | wlcore_scan_get_channels(wl, |
518 | IEEE80211_BAND_2GHZ, | 255 | channels, |
519 | false, false, | 256 | n_channels, |
520 | cfg->passive[0], | 257 | n_ssids, |
521 | MAX_CHANNELS_2GHZ, | 258 | cfg->channels_2, |
522 | &n_pactive_ch); | 259 | IEEE80211_BAND_2GHZ, |
260 | false, false, | ||
261 | cfg->passive[0], | ||
262 | MAX_CHANNELS_2GHZ, | ||
263 | &n_pactive_ch, | ||
264 | scan_type); | ||
523 | cfg->passive[1] = | 265 | cfg->passive[1] = |
524 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5, | 266 | wlcore_scan_get_channels(wl, |
525 | IEEE80211_BAND_5GHZ, | 267 | channels, |
526 | false, true, 0, | 268 | n_channels, |
527 | MAX_CHANNELS_5GHZ, | 269 | n_ssids, |
528 | &n_pactive_ch); | 270 | cfg->channels_5, |
271 | IEEE80211_BAND_5GHZ, | ||
272 | false, true, 0, | ||
273 | wl->max_channels_5, | ||
274 | &n_pactive_ch, | ||
275 | scan_type); | ||
529 | cfg->dfs = | 276 | cfg->dfs = |
530 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5, | 277 | wlcore_scan_get_channels(wl, |
531 | IEEE80211_BAND_5GHZ, | 278 | channels, |
532 | true, true, | 279 | n_channels, |
533 | cfg->passive[1], | 280 | n_ssids, |
534 | MAX_CHANNELS_5GHZ, | 281 | cfg->channels_5, |
535 | &n_pactive_ch); | 282 | IEEE80211_BAND_5GHZ, |
283 | true, true, | ||
284 | cfg->passive[1], | ||
285 | wl->max_channels_5, | ||
286 | &n_pactive_ch, | ||
287 | scan_type); | ||
536 | cfg->active[1] = | 288 | cfg->active[1] = |
537 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5, | 289 | wlcore_scan_get_channels(wl, |
538 | IEEE80211_BAND_5GHZ, | 290 | channels, |
539 | false, false, | 291 | n_channels, |
540 | cfg->passive[1] + cfg->dfs, | 292 | n_ssids, |
541 | MAX_CHANNELS_5GHZ, | 293 | cfg->channels_5, |
542 | &n_pactive_ch); | 294 | IEEE80211_BAND_5GHZ, |
295 | false, false, | ||
296 | cfg->passive[1] + cfg->dfs, | ||
297 | wl->max_channels_5, | ||
298 | &n_pactive_ch, | ||
299 | scan_type); | ||
300 | |||
543 | /* 802.11j channels are not supported yet */ | 301 | /* 802.11j channels are not supported yet */ |
544 | cfg->passive[2] = 0; | 302 | cfg->passive[2] = 0; |
545 | cfg->active[2] = 0; | 303 | cfg->active[2] = 0; |
546 | 304 | ||
547 | cfg->n_pactive_ch = n_pactive_ch; | 305 | cfg->passive_active = n_pactive_ch; |
548 | 306 | ||
549 | wl1271_debug(DEBUG_SCAN, " 2.4GHz: active %d passive %d", | 307 | wl1271_debug(DEBUG_SCAN, " 2.4GHz: active %d passive %d", |
550 | cfg->active[0], cfg->passive[0]); | 308 | cfg->active[0], cfg->passive[0]); |
@@ -556,10 +314,48 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl, | |||
556 | cfg->passive[1] || cfg->active[1] || cfg->dfs || | 314 | cfg->passive[1] || cfg->active[1] || cfg->dfs || |
557 | cfg->passive[2] || cfg->active[2]; | 315 | cfg->passive[2] || cfg->active[2]; |
558 | } | 316 | } |
317 | EXPORT_SYMBOL_GPL(wlcore_set_scan_chan_params); | ||
318 | |||
319 | int wlcore_scan(struct wl1271 *wl, struct ieee80211_vif *vif, | ||
320 | const u8 *ssid, size_t ssid_len, | ||
321 | struct cfg80211_scan_request *req) | ||
322 | { | ||
323 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
324 | |||
325 | /* | ||
326 | * cfg80211 should guarantee that we don't get more channels | ||
327 | * than what we have registered. | ||
328 | */ | ||
329 | BUG_ON(req->n_channels > WL1271_MAX_CHANNELS); | ||
330 | |||
331 | if (wl->scan.state != WL1271_SCAN_STATE_IDLE) | ||
332 | return -EBUSY; | ||
333 | |||
334 | wl->scan.state = WL1271_SCAN_STATE_2GHZ_ACTIVE; | ||
335 | |||
336 | if (ssid_len && ssid) { | ||
337 | wl->scan.ssid_len = ssid_len; | ||
338 | memcpy(wl->scan.ssid, ssid, ssid_len); | ||
339 | } else { | ||
340 | wl->scan.ssid_len = 0; | ||
341 | } | ||
342 | |||
343 | wl->scan_wlvif = wlvif; | ||
344 | wl->scan.req = req; | ||
345 | memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); | ||
346 | |||
347 | /* we assume failure so that timeout scenarios are handled correctly */ | ||
348 | wl->scan.failed = true; | ||
349 | ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, | ||
350 | msecs_to_jiffies(WL1271_SCAN_TIMEOUT)); | ||
559 | 351 | ||
352 | wl->ops->scan_start(wl, wlvif, req); | ||
353 | |||
354 | return 0; | ||
355 | } | ||
560 | /* Returns the scan type to be used or a negative value on error */ | 356 | /* Returns the scan type to be used or a negative value on error */ |
561 | static int | 357 | int |
562 | wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, | 358 | wlcore_scan_sched_scan_ssid_list(struct wl1271 *wl, |
563 | struct wl12xx_vif *wlvif, | 359 | struct wl12xx_vif *wlvif, |
564 | struct cfg80211_sched_scan_request *req) | 360 | struct cfg80211_sched_scan_request *req) |
565 | { | 361 | { |
@@ -662,160 +458,12 @@ out: | |||
662 | return ret; | 458 | return ret; |
663 | return type; | 459 | return type; |
664 | } | 460 | } |
461 | EXPORT_SYMBOL_GPL(wlcore_scan_sched_scan_ssid_list); | ||
665 | 462 | ||
666 | int wl1271_scan_sched_scan_config(struct wl1271 *wl, | 463 | void wlcore_scan_sched_scan_results(struct wl1271 *wl) |
667 | struct wl12xx_vif *wlvif, | ||
668 | struct cfg80211_sched_scan_request *req, | ||
669 | struct ieee80211_sched_scan_ies *ies) | ||
670 | { | ||
671 | struct wl1271_cmd_sched_scan_config *cfg = NULL; | ||
672 | struct conf_sched_scan_settings *c = &wl->conf.sched_scan; | ||
673 | int i, ret; | ||
674 | bool force_passive = !req->n_ssids; | ||
675 | |||
676 | wl1271_debug(DEBUG_CMD, "cmd sched_scan scan config"); | ||
677 | |||
678 | cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); | ||
679 | if (!cfg) | ||
680 | return -ENOMEM; | ||
681 | |||
682 | cfg->role_id = wlvif->role_id; | ||
683 | cfg->rssi_threshold = c->rssi_threshold; | ||
684 | cfg->snr_threshold = c->snr_threshold; | ||
685 | cfg->n_probe_reqs = c->num_probe_reqs; | ||
686 | /* cycles set to 0 it means infinite (until manually stopped) */ | ||
687 | cfg->cycles = 0; | ||
688 | /* report APs when at least 1 is found */ | ||
689 | cfg->report_after = 1; | ||
690 | /* don't stop scanning automatically when something is found */ | ||
691 | cfg->terminate = 0; | ||
692 | cfg->tag = WL1271_SCAN_DEFAULT_TAG; | ||
693 | /* don't filter on BSS type */ | ||
694 | cfg->bss_type = SCAN_BSS_TYPE_ANY; | ||
695 | /* currently NL80211 supports only a single interval */ | ||
696 | for (i = 0; i < SCAN_MAX_CYCLE_INTERVALS; i++) | ||
697 | cfg->intervals[i] = cpu_to_le32(req->interval); | ||
698 | |||
699 | cfg->ssid_len = 0; | ||
700 | ret = wl12xx_scan_sched_scan_ssid_list(wl, wlvif, req); | ||
701 | if (ret < 0) | ||
702 | goto out; | ||
703 | |||
704 | cfg->filter_type = ret; | ||
705 | |||
706 | wl1271_debug(DEBUG_SCAN, "filter_type = %d", cfg->filter_type); | ||
707 | |||
708 | if (!wl1271_scan_sched_scan_channels(wl, req, cfg)) { | ||
709 | wl1271_error("scan channel list is empty"); | ||
710 | ret = -EINVAL; | ||
711 | goto out; | ||
712 | } | ||
713 | |||
714 | if (!force_passive && cfg->active[0]) { | ||
715 | u8 band = IEEE80211_BAND_2GHZ; | ||
716 | ret = wl12xx_cmd_build_probe_req(wl, wlvif, | ||
717 | wlvif->role_id, band, | ||
718 | req->ssids[0].ssid, | ||
719 | req->ssids[0].ssid_len, | ||
720 | ies->ie[band], | ||
721 | ies->len[band], true); | ||
722 | if (ret < 0) { | ||
723 | wl1271_error("2.4GHz PROBE request template failed"); | ||
724 | goto out; | ||
725 | } | ||
726 | } | ||
727 | |||
728 | if (!force_passive && cfg->active[1]) { | ||
729 | u8 band = IEEE80211_BAND_5GHZ; | ||
730 | ret = wl12xx_cmd_build_probe_req(wl, wlvif, | ||
731 | wlvif->role_id, band, | ||
732 | req->ssids[0].ssid, | ||
733 | req->ssids[0].ssid_len, | ||
734 | ies->ie[band], | ||
735 | ies->len[band], true); | ||
736 | if (ret < 0) { | ||
737 | wl1271_error("5GHz PROBE request template failed"); | ||
738 | goto out; | ||
739 | } | ||
740 | } | ||
741 | |||
742 | wl1271_dump(DEBUG_SCAN, "SCAN_CFG: ", cfg, sizeof(*cfg)); | ||
743 | |||
744 | ret = wl1271_cmd_send(wl, CMD_CONNECTION_SCAN_CFG, cfg, | ||
745 | sizeof(*cfg), 0); | ||
746 | if (ret < 0) { | ||
747 | wl1271_error("SCAN configuration failed"); | ||
748 | goto out; | ||
749 | } | ||
750 | out: | ||
751 | kfree(cfg); | ||
752 | return ret; | ||
753 | } | ||
754 | |||
755 | int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif) | ||
756 | { | ||
757 | struct wl1271_cmd_sched_scan_start *start; | ||
758 | int ret = 0; | ||
759 | |||
760 | wl1271_debug(DEBUG_CMD, "cmd periodic scan start"); | ||
761 | |||
762 | if (wlvif->bss_type != BSS_TYPE_STA_BSS) | ||
763 | return -EOPNOTSUPP; | ||
764 | |||
765 | if ((wl->quirks & WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN) && | ||
766 | test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags)) | ||
767 | return -EBUSY; | ||
768 | |||
769 | start = kzalloc(sizeof(*start), GFP_KERNEL); | ||
770 | if (!start) | ||
771 | return -ENOMEM; | ||
772 | |||
773 | start->role_id = wlvif->role_id; | ||
774 | start->tag = WL1271_SCAN_DEFAULT_TAG; | ||
775 | |||
776 | ret = wl1271_cmd_send(wl, CMD_START_PERIODIC_SCAN, start, | ||
777 | sizeof(*start), 0); | ||
778 | if (ret < 0) { | ||
779 | wl1271_error("failed to send scan start command"); | ||
780 | goto out_free; | ||
781 | } | ||
782 | |||
783 | out_free: | ||
784 | kfree(start); | ||
785 | return ret; | ||
786 | } | ||
787 | |||
788 | void wl1271_scan_sched_scan_results(struct wl1271 *wl) | ||
789 | { | 464 | { |
790 | wl1271_debug(DEBUG_SCAN, "got periodic scan results"); | 465 | wl1271_debug(DEBUG_SCAN, "got periodic scan results"); |
791 | 466 | ||
792 | ieee80211_sched_scan_results(wl->hw); | 467 | ieee80211_sched_scan_results(wl->hw); |
793 | } | 468 | } |
794 | 469 | EXPORT_SYMBOL_GPL(wlcore_scan_sched_scan_results); | |
795 | void wl1271_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif) | ||
796 | { | ||
797 | struct wl1271_cmd_sched_scan_stop *stop; | ||
798 | int ret = 0; | ||
799 | |||
800 | wl1271_debug(DEBUG_CMD, "cmd periodic scan stop"); | ||
801 | |||
802 | /* FIXME: what to do if alloc'ing to stop fails? */ | ||
803 | stop = kzalloc(sizeof(*stop), GFP_KERNEL); | ||
804 | if (!stop) { | ||
805 | wl1271_error("failed to alloc memory to send sched scan stop"); | ||
806 | return; | ||
807 | } | ||
808 | |||
809 | stop->role_id = wlvif->role_id; | ||
810 | stop->tag = WL1271_SCAN_DEFAULT_TAG; | ||
811 | |||
812 | ret = wl1271_cmd_send(wl, CMD_STOP_PERIODIC_SCAN, stop, | ||
813 | sizeof(*stop), 0); | ||
814 | if (ret < 0) { | ||
815 | wl1271_error("failed to send sched scan stop command"); | ||
816 | goto out_free; | ||
817 | } | ||
818 | |||
819 | out_free: | ||
820 | kfree(stop); | ||
821 | } | ||
diff --git a/drivers/net/wireless/ti/wlcore/scan.h b/drivers/net/wireless/ti/wlcore/scan.h index 29f3c8d6b046..a6ab24b5c0f9 100644 --- a/drivers/net/wireless/ti/wlcore/scan.h +++ b/drivers/net/wireless/ti/wlcore/scan.h | |||
@@ -26,22 +26,20 @@ | |||
26 | 26 | ||
27 | #include "wlcore.h" | 27 | #include "wlcore.h" |
28 | 28 | ||
29 | int wl1271_scan(struct wl1271 *wl, struct ieee80211_vif *vif, | 29 | int wlcore_scan(struct wl1271 *wl, struct ieee80211_vif *vif, |
30 | const u8 *ssid, size_t ssid_len, | 30 | const u8 *ssid, size_t ssid_len, |
31 | struct cfg80211_scan_request *req); | 31 | struct cfg80211_scan_request *req); |
32 | int wl1271_scan_stop(struct wl1271 *wl); | ||
33 | int wl1271_scan_build_probe_req(struct wl1271 *wl, | 32 | int wl1271_scan_build_probe_req(struct wl1271 *wl, |
34 | const u8 *ssid, size_t ssid_len, | 33 | const u8 *ssid, size_t ssid_len, |
35 | const u8 *ie, size_t ie_len, u8 band); | 34 | const u8 *ie, size_t ie_len, u8 band); |
36 | void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif); | 35 | void wl1271_scan_stm(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
37 | void wl1271_scan_complete_work(struct work_struct *work); | 36 | void wl1271_scan_complete_work(struct work_struct *work); |
38 | int wl1271_scan_sched_scan_config(struct wl1271 *wl, | 37 | int wl1271_scan_sched_scan_config(struct wl1271 *wl, |
39 | struct wl12xx_vif *wlvif, | 38 | struct wl12xx_vif *wlvif, |
40 | struct cfg80211_sched_scan_request *req, | 39 | struct cfg80211_sched_scan_request *req, |
41 | struct ieee80211_sched_scan_ies *ies); | 40 | struct ieee80211_sched_scan_ies *ies); |
42 | int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 41 | int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
43 | void wl1271_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 42 | void wlcore_scan_sched_scan_results(struct wl1271 *wl); |
44 | void wl1271_scan_sched_scan_results(struct wl1271 *wl); | ||
45 | 43 | ||
46 | #define WL1271_SCAN_MAX_CHANNELS 24 | 44 | #define WL1271_SCAN_MAX_CHANNELS 24 |
47 | #define WL1271_SCAN_DEFAULT_TAG 1 | 45 | #define WL1271_SCAN_DEFAULT_TAG 1 |
@@ -66,56 +64,6 @@ enum { | |||
66 | WL1271_SCAN_STATE_DONE | 64 | WL1271_SCAN_STATE_DONE |
67 | }; | 65 | }; |
68 | 66 | ||
69 | struct basic_scan_params { | ||
70 | /* Scan option flags (WL1271_SCAN_OPT_*) */ | ||
71 | __le16 scan_options; | ||
72 | u8 role_id; | ||
73 | /* Number of scan channels in the list (maximum 30) */ | ||
74 | u8 n_ch; | ||
75 | /* This field indicates the number of probe requests to send | ||
76 | per channel for an active scan */ | ||
77 | u8 n_probe_reqs; | ||
78 | u8 tid_trigger; | ||
79 | u8 ssid_len; | ||
80 | u8 use_ssid_list; | ||
81 | |||
82 | /* Rate bit field for sending the probes */ | ||
83 | __le32 tx_rate; | ||
84 | |||
85 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | ||
86 | /* Band to scan */ | ||
87 | u8 band; | ||
88 | |||
89 | u8 scan_tag; | ||
90 | u8 padding2[2]; | ||
91 | } __packed; | ||
92 | |||
93 | struct basic_scan_channel_params { | ||
94 | /* Duration in TU to wait for frames on a channel for active scan */ | ||
95 | __le32 min_duration; | ||
96 | __le32 max_duration; | ||
97 | __le32 bssid_lsb; | ||
98 | __le16 bssid_msb; | ||
99 | u8 early_termination; | ||
100 | u8 tx_power_att; | ||
101 | u8 channel; | ||
102 | /* FW internal use only! */ | ||
103 | u8 dfs_candidate; | ||
104 | u8 activity_detected; | ||
105 | u8 pad; | ||
106 | } __packed; | ||
107 | |||
108 | struct wl1271_cmd_scan { | ||
109 | struct wl1271_cmd_header header; | ||
110 | |||
111 | struct basic_scan_params params; | ||
112 | struct basic_scan_channel_params channels[WL1271_SCAN_MAX_CHANNELS]; | ||
113 | |||
114 | /* src mac address */ | ||
115 | u8 addr[ETH_ALEN]; | ||
116 | u8 padding[2]; | ||
117 | } __packed; | ||
118 | |||
119 | struct wl1271_cmd_trigger_scan_to { | 67 | struct wl1271_cmd_trigger_scan_to { |
120 | struct wl1271_cmd_header header; | 68 | struct wl1271_cmd_header header; |
121 | 69 | ||
@@ -123,9 +71,17 @@ struct wl1271_cmd_trigger_scan_to { | |||
123 | } __packed; | 71 | } __packed; |
124 | 72 | ||
125 | #define MAX_CHANNELS_2GHZ 14 | 73 | #define MAX_CHANNELS_2GHZ 14 |
126 | #define MAX_CHANNELS_5GHZ 23 | ||
127 | #define MAX_CHANNELS_4GHZ 4 | 74 | #define MAX_CHANNELS_4GHZ 4 |
128 | 75 | ||
76 | /* | ||
77 | * This max value here is used only for the struct definition of | ||
78 | * wlcore_scan_channels. This struct is used by both 12xx | ||
79 | * and 18xx (which have different max 5ghz channels value). | ||
80 | * In order to make sure this is large enough, just use the | ||
81 | * max possible 5ghz channels. | ||
82 | */ | ||
83 | #define MAX_CHANNELS_5GHZ 42 | ||
84 | |||
129 | #define SCAN_MAX_CYCLE_INTERVALS 16 | 85 | #define SCAN_MAX_CYCLE_INTERVALS 16 |
130 | #define SCAN_MAX_BANDS 3 | 86 | #define SCAN_MAX_BANDS 3 |
131 | 87 | ||
@@ -160,43 +116,6 @@ struct conn_scan_ch_params { | |||
160 | u8 padding[3]; | 116 | u8 padding[3]; |
161 | } __packed; | 117 | } __packed; |
162 | 118 | ||
163 | struct wl1271_cmd_sched_scan_config { | ||
164 | struct wl1271_cmd_header header; | ||
165 | |||
166 | __le32 intervals[SCAN_MAX_CYCLE_INTERVALS]; | ||
167 | |||
168 | s8 rssi_threshold; /* for filtering (in dBm) */ | ||
169 | s8 snr_threshold; /* for filtering (in dB) */ | ||
170 | |||
171 | u8 cycles; /* maximum number of scan cycles */ | ||
172 | u8 report_after; /* report when this number of results are received */ | ||
173 | u8 terminate; /* stop scanning after reporting */ | ||
174 | |||
175 | u8 tag; | ||
176 | u8 bss_type; /* for filtering */ | ||
177 | u8 filter_type; | ||
178 | |||
179 | u8 ssid_len; /* For SCAN_SSID_FILTER_SPECIFIC */ | ||
180 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | ||
181 | |||
182 | u8 n_probe_reqs; /* Number of probes requests per channel */ | ||
183 | |||
184 | u8 passive[SCAN_MAX_BANDS]; | ||
185 | u8 active[SCAN_MAX_BANDS]; | ||
186 | |||
187 | u8 dfs; | ||
188 | |||
189 | u8 n_pactive_ch; /* number of pactive (passive until fw detects energy) | ||
190 | channels in BG band */ | ||
191 | u8 role_id; | ||
192 | u8 padding[1]; | ||
193 | |||
194 | struct conn_scan_ch_params channels_2[MAX_CHANNELS_2GHZ]; | ||
195 | struct conn_scan_ch_params channels_5[MAX_CHANNELS_5GHZ]; | ||
196 | struct conn_scan_ch_params channels_4[MAX_CHANNELS_4GHZ]; | ||
197 | } __packed; | ||
198 | |||
199 | |||
200 | #define SCHED_SCAN_MAX_SSIDS 16 | 119 | #define SCHED_SCAN_MAX_SSIDS 16 |
201 | 120 | ||
202 | enum { | 121 | enum { |
@@ -220,21 +139,34 @@ struct wl1271_cmd_sched_scan_ssid_list { | |||
220 | u8 padding[2]; | 139 | u8 padding[2]; |
221 | } __packed; | 140 | } __packed; |
222 | 141 | ||
223 | struct wl1271_cmd_sched_scan_start { | 142 | struct wlcore_scan_channels { |
224 | struct wl1271_cmd_header header; | 143 | u8 passive[SCAN_MAX_BANDS]; /* number of passive scan channels */ |
144 | u8 active[SCAN_MAX_BANDS]; /* number of active scan channels */ | ||
145 | u8 dfs; /* number of dfs channels in 5ghz */ | ||
146 | u8 passive_active; /* number of passive before active channels 2.4ghz */ | ||
225 | 147 | ||
226 | u8 tag; | 148 | struct conn_scan_ch_params channels_2[MAX_CHANNELS_2GHZ]; |
227 | u8 role_id; | 149 | struct conn_scan_ch_params channels_5[MAX_CHANNELS_5GHZ]; |
228 | u8 padding[2]; | 150 | struct conn_scan_ch_params channels_4[MAX_CHANNELS_4GHZ]; |
229 | } __packed; | 151 | }; |
230 | |||
231 | struct wl1271_cmd_sched_scan_stop { | ||
232 | struct wl1271_cmd_header header; | ||
233 | 152 | ||
234 | u8 tag; | 153 | enum { |
235 | u8 role_id; | 154 | SCAN_TYPE_SEARCH = 0, |
236 | u8 padding[2]; | 155 | SCAN_TYPE_PERIODIC = 1, |
237 | } __packed; | 156 | SCAN_TYPE_TRACKING = 2, |
157 | }; | ||
238 | 158 | ||
159 | bool | ||
160 | wlcore_set_scan_chan_params(struct wl1271 *wl, | ||
161 | struct wlcore_scan_channels *cfg, | ||
162 | struct ieee80211_channel *channels[], | ||
163 | u32 n_channels, | ||
164 | u32 n_ssids, | ||
165 | int scan_type); | ||
166 | |||
167 | int | ||
168 | wlcore_scan_sched_scan_ssid_list(struct wl1271 *wl, | ||
169 | struct wl12xx_vif *wlvif, | ||
170 | struct cfg80211_sched_scan_request *req); | ||
239 | 171 | ||
240 | #endif /* __WL1271_SCAN_H__ */ | 172 | #endif /* __WL1271_SCAN_H__ */ |
diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c index a3a20be2036f..75622f6f3e6c 100644 --- a/drivers/net/wireless/ti/wlcore/sdio.c +++ b/drivers/net/wireless/ti/wlcore/sdio.c | |||
@@ -324,8 +324,7 @@ static void wl1271_remove(struct sdio_func *func) | |||
324 | /* Undo decrement done above in wl1271_probe */ | 324 | /* Undo decrement done above in wl1271_probe */ |
325 | pm_runtime_get_noresume(&func->dev); | 325 | pm_runtime_get_noresume(&func->dev); |
326 | 326 | ||
327 | platform_device_del(glue->core); | 327 | platform_device_unregister(glue->core); |
328 | platform_device_put(glue->core); | ||
329 | kfree(glue); | 328 | kfree(glue); |
330 | } | 329 | } |
331 | 330 | ||
diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index 18cadc07b754..53790d1d0d27 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c | |||
@@ -264,7 +264,7 @@ static int __must_check wl12xx_spi_raw_write(struct device *child, int addr, | |||
264 | void *buf, size_t len, bool fixed) | 264 | void *buf, size_t len, bool fixed) |
265 | { | 265 | { |
266 | struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); | 266 | struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); |
267 | struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS]; | 267 | struct spi_transfer t[2 * (WSPI_MAX_NUM_OF_CHUNKS + 1)]; |
268 | struct spi_message m; | 268 | struct spi_message m; |
269 | u32 commands[WSPI_MAX_NUM_OF_CHUNKS]; | 269 | u32 commands[WSPI_MAX_NUM_OF_CHUNKS]; |
270 | u32 *cmd; | 270 | u32 *cmd; |
@@ -399,8 +399,7 @@ static int wl1271_remove(struct spi_device *spi) | |||
399 | { | 399 | { |
400 | struct wl12xx_spi_glue *glue = spi_get_drvdata(spi); | 400 | struct wl12xx_spi_glue *glue = spi_get_drvdata(spi); |
401 | 401 | ||
402 | platform_device_del(glue->core); | 402 | platform_device_unregister(glue->core); |
403 | platform_device_put(glue->core); | ||
404 | kfree(glue); | 403 | kfree(glue); |
405 | 404 | ||
406 | return 0; | 405 | return 0; |
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index a90d3cd09408..ece392c54d9c 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c | |||
@@ -104,7 +104,7 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl, | |||
104 | struct wl12xx_vif *wlvif, | 104 | struct wl12xx_vif *wlvif, |
105 | u8 hlid) | 105 | u8 hlid) |
106 | { | 106 | { |
107 | bool fw_ps, single_sta; | 107 | bool fw_ps, single_link; |
108 | u8 tx_pkts; | 108 | u8 tx_pkts; |
109 | 109 | ||
110 | if (WARN_ON(!test_bit(hlid, wlvif->links_map))) | 110 | if (WARN_ON(!test_bit(hlid, wlvif->links_map))) |
@@ -112,15 +112,15 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl, | |||
112 | 112 | ||
113 | fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | 113 | fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); |
114 | tx_pkts = wl->links[hlid].allocated_pkts; | 114 | tx_pkts = wl->links[hlid].allocated_pkts; |
115 | single_sta = (wl->active_sta_count == 1); | 115 | single_link = (wl->active_link_count == 1); |
116 | 116 | ||
117 | /* | 117 | /* |
118 | * if in FW PS and there is enough data in FW we can put the link | 118 | * if in FW PS and there is enough data in FW we can put the link |
119 | * into high-level PS and clean out its TX queues. | 119 | * into high-level PS and clean out its TX queues. |
120 | * Make an exception if this is the only connected station. In this | 120 | * Make an exception if this is the only connected link. In this |
121 | * case FW-memory congestion is not a problem. | 121 | * case FW-memory congestion is less of a problem. |
122 | */ | 122 | */ |
123 | if (!single_sta && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) | 123 | if (!single_link && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) |
124 | wl12xx_ps_link_start(wl, wlvif, hlid, true); | 124 | wl12xx_ps_link_start(wl, wlvif, hlid, true); |
125 | } | 125 | } |
126 | 126 | ||
@@ -155,21 +155,18 @@ static u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
155 | u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 155 | u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
156 | struct sk_buff *skb, struct ieee80211_sta *sta) | 156 | struct sk_buff *skb, struct ieee80211_sta *sta) |
157 | { | 157 | { |
158 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 158 | struct ieee80211_tx_info *control; |
159 | |||
160 | if (!wlvif || wl12xx_is_dummy_packet(wl, skb)) | ||
161 | return wl->system_hlid; | ||
162 | 159 | ||
163 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) | 160 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) |
164 | return wl12xx_tx_get_hlid_ap(wl, wlvif, skb, sta); | 161 | return wl12xx_tx_get_hlid_ap(wl, wlvif, skb, sta); |
165 | 162 | ||
166 | if ((test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) || | 163 | control = IEEE80211_SKB_CB(skb); |
167 | test_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags)) && | 164 | if (control->flags & IEEE80211_TX_CTL_TX_OFFCHAN) { |
168 | !ieee80211_is_auth(hdr->frame_control) && | 165 | wl1271_debug(DEBUG_TX, "tx offchannel"); |
169 | !ieee80211_is_assoc_req(hdr->frame_control)) | ||
170 | return wlvif->sta.hlid; | ||
171 | else | ||
172 | return wlvif->dev_hlid; | 166 | return wlvif->dev_hlid; |
167 | } | ||
168 | |||
169 | return wlvif->sta.hlid; | ||
173 | } | 170 | } |
174 | 171 | ||
175 | unsigned int wlcore_calc_packet_alignment(struct wl1271 *wl, | 172 | unsigned int wlcore_calc_packet_alignment(struct wl1271 *wl, |
@@ -224,9 +221,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
224 | ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); | 221 | ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); |
225 | wl->tx_allocated_pkts[ac]++; | 222 | wl->tx_allocated_pkts[ac]++; |
226 | 223 | ||
227 | if (!wl12xx_is_dummy_packet(wl, skb) && wlvif && | 224 | if (test_bit(hlid, wl->links_map)) |
228 | wlvif->bss_type == BSS_TYPE_AP_BSS && | ||
229 | test_bit(hlid, wlvif->ap.sta_hlid_map)) | ||
230 | wl->links[hlid].allocated_pkts++; | 225 | wl->links[hlid].allocated_pkts++; |
231 | 226 | ||
232 | ret = 0; | 227 | ret = 0; |
@@ -293,9 +288,14 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
293 | 288 | ||
294 | tx_attr |= TX_HW_ATTR_TX_DUMMY_REQ; | 289 | tx_attr |= TX_HW_ATTR_TX_DUMMY_REQ; |
295 | } else if (wlvif) { | 290 | } else if (wlvif) { |
291 | u8 session_id = wl->session_ids[hlid]; | ||
292 | |||
293 | if ((wl->quirks & WLCORE_QUIRK_AP_ZERO_SESSION_ID) && | ||
294 | (wlvif->bss_type == BSS_TYPE_AP_BSS)) | ||
295 | session_id = 0; | ||
296 | |||
296 | /* configure the tx attributes */ | 297 | /* configure the tx attributes */ |
297 | tx_attr = wlvif->session_counter << | 298 | tx_attr = session_id << TX_HW_ATTR_OFST_SESSION_COUNTER; |
298 | TX_HW_ATTR_OFST_SESSION_COUNTER; | ||
299 | } | 299 | } |
300 | 300 | ||
301 | desc->hlid = hlid; | 301 | desc->hlid = hlid; |
@@ -452,20 +452,22 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set, | |||
452 | void wl1271_handle_tx_low_watermark(struct wl1271 *wl) | 452 | void wl1271_handle_tx_low_watermark(struct wl1271 *wl) |
453 | { | 453 | { |
454 | int i; | 454 | int i; |
455 | struct wl12xx_vif *wlvif; | ||
455 | 456 | ||
456 | for (i = 0; i < NUM_TX_QUEUES; i++) { | 457 | wl12xx_for_each_wlvif(wl, wlvif) { |
457 | if (wlcore_is_queue_stopped_by_reason(wl, i, | 458 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
458 | WLCORE_QUEUE_STOP_REASON_WATERMARK) && | 459 | if (wlcore_is_queue_stopped_by_reason(wl, wlvif, i, |
459 | wl->tx_queue_count[i] <= WL1271_TX_QUEUE_LOW_WATERMARK) { | 460 | WLCORE_QUEUE_STOP_REASON_WATERMARK) && |
460 | /* firmware buffer has space, restart queues */ | 461 | wlvif->tx_queue_count[i] <= |
461 | wlcore_wake_queue(wl, i, | 462 | WL1271_TX_QUEUE_LOW_WATERMARK) |
462 | WLCORE_QUEUE_STOP_REASON_WATERMARK); | 463 | /* firmware buffer has space, restart queues */ |
464 | wlcore_wake_queue(wl, wlvif, i, | ||
465 | WLCORE_QUEUE_STOP_REASON_WATERMARK); | ||
463 | } | 466 | } |
464 | } | 467 | } |
465 | } | 468 | } |
466 | 469 | ||
467 | static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl, | 470 | static int wlcore_select_ac(struct wl1271 *wl) |
468 | struct sk_buff_head *queues) | ||
469 | { | 471 | { |
470 | int i, q = -1, ac; | 472 | int i, q = -1, ac; |
471 | u32 min_pkts = 0xffffffff; | 473 | u32 min_pkts = 0xffffffff; |
@@ -479,45 +481,60 @@ static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl, | |||
479 | */ | 481 | */ |
480 | for (i = 0; i < NUM_TX_QUEUES; i++) { | 482 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
481 | ac = wl1271_tx_get_queue(i); | 483 | ac = wl1271_tx_get_queue(i); |
482 | if (!skb_queue_empty(&queues[ac]) && | 484 | if (wl->tx_queue_count[ac] && |
483 | (wl->tx_allocated_pkts[ac] < min_pkts)) { | 485 | wl->tx_allocated_pkts[ac] < min_pkts) { |
484 | q = ac; | 486 | q = ac; |
485 | min_pkts = wl->tx_allocated_pkts[q]; | 487 | min_pkts = wl->tx_allocated_pkts[q]; |
486 | } | 488 | } |
487 | } | 489 | } |
488 | 490 | ||
489 | if (q == -1) | 491 | return q; |
490 | return NULL; | ||
491 | |||
492 | return &queues[q]; | ||
493 | } | 492 | } |
494 | 493 | ||
495 | static struct sk_buff *wl12xx_lnk_skb_dequeue(struct wl1271 *wl, | 494 | static struct sk_buff *wlcore_lnk_dequeue(struct wl1271 *wl, |
496 | struct wl1271_link *lnk) | 495 | struct wl1271_link *lnk, u8 q) |
497 | { | 496 | { |
498 | struct sk_buff *skb; | 497 | struct sk_buff *skb; |
499 | unsigned long flags; | 498 | unsigned long flags; |
500 | struct sk_buff_head *queue; | ||
501 | 499 | ||
502 | queue = wl1271_select_queue(wl, lnk->tx_queue); | 500 | skb = skb_dequeue(&lnk->tx_queue[q]); |
503 | if (!queue) | ||
504 | return NULL; | ||
505 | |||
506 | skb = skb_dequeue(queue); | ||
507 | if (skb) { | 501 | if (skb) { |
508 | int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); | ||
509 | spin_lock_irqsave(&wl->wl_lock, flags); | 502 | spin_lock_irqsave(&wl->wl_lock, flags); |
510 | WARN_ON_ONCE(wl->tx_queue_count[q] <= 0); | 503 | WARN_ON_ONCE(wl->tx_queue_count[q] <= 0); |
511 | wl->tx_queue_count[q]--; | 504 | wl->tx_queue_count[q]--; |
505 | if (lnk->wlvif) { | ||
506 | WARN_ON_ONCE(lnk->wlvif->tx_queue_count[q] <= 0); | ||
507 | lnk->wlvif->tx_queue_count[q]--; | ||
508 | } | ||
512 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 509 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
513 | } | 510 | } |
514 | 511 | ||
515 | return skb; | 512 | return skb; |
516 | } | 513 | } |
517 | 514 | ||
518 | static struct sk_buff *wl12xx_vif_skb_dequeue(struct wl1271 *wl, | 515 | static struct sk_buff *wlcore_lnk_dequeue_high_prio(struct wl1271 *wl, |
519 | struct wl12xx_vif *wlvif, | 516 | u8 hlid, u8 ac, |
520 | u8 *hlid) | 517 | u8 *low_prio_hlid) |
518 | { | ||
519 | struct wl1271_link *lnk = &wl->links[hlid]; | ||
520 | |||
521 | if (!wlcore_hw_lnk_high_prio(wl, hlid, lnk)) { | ||
522 | if (*low_prio_hlid == WL12XX_INVALID_LINK_ID && | ||
523 | !skb_queue_empty(&lnk->tx_queue[ac]) && | ||
524 | wlcore_hw_lnk_low_prio(wl, hlid, lnk)) | ||
525 | /* we found the first non-empty low priority queue */ | ||
526 | *low_prio_hlid = hlid; | ||
527 | |||
528 | return NULL; | ||
529 | } | ||
530 | |||
531 | return wlcore_lnk_dequeue(wl, lnk, ac); | ||
532 | } | ||
533 | |||
534 | static struct sk_buff *wlcore_vif_dequeue_high_prio(struct wl1271 *wl, | ||
535 | struct wl12xx_vif *wlvif, | ||
536 | u8 ac, u8 *hlid, | ||
537 | u8 *low_prio_hlid) | ||
521 | { | 538 | { |
522 | struct sk_buff *skb = NULL; | 539 | struct sk_buff *skb = NULL; |
523 | int i, h, start_hlid; | 540 | int i, h, start_hlid; |
@@ -533,7 +550,8 @@ static struct sk_buff *wl12xx_vif_skb_dequeue(struct wl1271 *wl, | |||
533 | if (!test_bit(h, wlvif->links_map)) | 550 | if (!test_bit(h, wlvif->links_map)) |
534 | continue; | 551 | continue; |
535 | 552 | ||
536 | skb = wl12xx_lnk_skb_dequeue(wl, &wl->links[h]); | 553 | skb = wlcore_lnk_dequeue_high_prio(wl, h, ac, |
554 | low_prio_hlid); | ||
537 | if (!skb) | 555 | if (!skb) |
538 | continue; | 556 | continue; |
539 | 557 | ||
@@ -553,42 +571,74 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl, u8 *hlid) | |||
553 | unsigned long flags; | 571 | unsigned long flags; |
554 | struct wl12xx_vif *wlvif = wl->last_wlvif; | 572 | struct wl12xx_vif *wlvif = wl->last_wlvif; |
555 | struct sk_buff *skb = NULL; | 573 | struct sk_buff *skb = NULL; |
574 | int ac; | ||
575 | u8 low_prio_hlid = WL12XX_INVALID_LINK_ID; | ||
576 | |||
577 | ac = wlcore_select_ac(wl); | ||
578 | if (ac < 0) | ||
579 | goto out; | ||
556 | 580 | ||
557 | /* continue from last wlvif (round robin) */ | 581 | /* continue from last wlvif (round robin) */ |
558 | if (wlvif) { | 582 | if (wlvif) { |
559 | wl12xx_for_each_wlvif_continue(wl, wlvif) { | 583 | wl12xx_for_each_wlvif_continue(wl, wlvif) { |
560 | skb = wl12xx_vif_skb_dequeue(wl, wlvif, hlid); | 584 | if (!wlvif->tx_queue_count[ac]) |
561 | if (skb) { | 585 | continue; |
562 | wl->last_wlvif = wlvif; | 586 | |
563 | break; | 587 | skb = wlcore_vif_dequeue_high_prio(wl, wlvif, ac, hlid, |
564 | } | 588 | &low_prio_hlid); |
589 | if (!skb) | ||
590 | continue; | ||
591 | |||
592 | wl->last_wlvif = wlvif; | ||
593 | break; | ||
565 | } | 594 | } |
566 | } | 595 | } |
567 | 596 | ||
568 | /* dequeue from the system HLID before the restarting wlvif list */ | 597 | /* dequeue from the system HLID before the restarting wlvif list */ |
569 | if (!skb) { | 598 | if (!skb) { |
570 | skb = wl12xx_lnk_skb_dequeue(wl, &wl->links[wl->system_hlid]); | 599 | skb = wlcore_lnk_dequeue_high_prio(wl, wl->system_hlid, |
571 | *hlid = wl->system_hlid; | 600 | ac, &low_prio_hlid); |
601 | if (skb) { | ||
602 | *hlid = wl->system_hlid; | ||
603 | wl->last_wlvif = NULL; | ||
604 | } | ||
572 | } | 605 | } |
573 | 606 | ||
574 | /* do a new pass over the wlvif list */ | 607 | /* Do a new pass over the wlvif list. But no need to continue |
608 | * after last_wlvif. The previous pass should have found it. */ | ||
575 | if (!skb) { | 609 | if (!skb) { |
576 | wl12xx_for_each_wlvif(wl, wlvif) { | 610 | wl12xx_for_each_wlvif(wl, wlvif) { |
577 | skb = wl12xx_vif_skb_dequeue(wl, wlvif, hlid); | 611 | if (!wlvif->tx_queue_count[ac]) |
612 | goto next; | ||
613 | |||
614 | skb = wlcore_vif_dequeue_high_prio(wl, wlvif, ac, hlid, | ||
615 | &low_prio_hlid); | ||
578 | if (skb) { | 616 | if (skb) { |
579 | wl->last_wlvif = wlvif; | 617 | wl->last_wlvif = wlvif; |
580 | break; | 618 | break; |
581 | } | 619 | } |
582 | 620 | ||
583 | /* | 621 | next: |
584 | * No need to continue after last_wlvif. The previous | ||
585 | * pass should have found it. | ||
586 | */ | ||
587 | if (wlvif == wl->last_wlvif) | 622 | if (wlvif == wl->last_wlvif) |
588 | break; | 623 | break; |
589 | } | 624 | } |
590 | } | 625 | } |
591 | 626 | ||
627 | /* no high priority skbs found - but maybe a low priority one? */ | ||
628 | if (!skb && low_prio_hlid != WL12XX_INVALID_LINK_ID) { | ||
629 | struct wl1271_link *lnk = &wl->links[low_prio_hlid]; | ||
630 | skb = wlcore_lnk_dequeue(wl, lnk, ac); | ||
631 | |||
632 | WARN_ON(!skb); /* we checked this before */ | ||
633 | *hlid = low_prio_hlid; | ||
634 | |||
635 | /* ensure proper round robin in the vif/link levels */ | ||
636 | wl->last_wlvif = lnk->wlvif; | ||
637 | if (lnk->wlvif) | ||
638 | lnk->wlvif->last_tx_hlid = low_prio_hlid; | ||
639 | |||
640 | } | ||
641 | |||
592 | if (!skb && | 642 | if (!skb && |
593 | test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) { | 643 | test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) { |
594 | int q; | 644 | int q; |
@@ -602,6 +652,7 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl, u8 *hlid) | |||
602 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 652 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
603 | } | 653 | } |
604 | 654 | ||
655 | out: | ||
605 | return skb; | 656 | return skb; |
606 | } | 657 | } |
607 | 658 | ||
@@ -623,6 +674,8 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
623 | 674 | ||
624 | spin_lock_irqsave(&wl->wl_lock, flags); | 675 | spin_lock_irqsave(&wl->wl_lock, flags); |
625 | wl->tx_queue_count[q]++; | 676 | wl->tx_queue_count[q]++; |
677 | if (wlvif) | ||
678 | wlvif->tx_queue_count[q]++; | ||
626 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 679 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
627 | } | 680 | } |
628 | 681 | ||
@@ -699,7 +752,7 @@ int wlcore_tx_work_locked(struct wl1271 *wl) | |||
699 | bool has_data = false; | 752 | bool has_data = false; |
700 | 753 | ||
701 | wlvif = NULL; | 754 | wlvif = NULL; |
702 | if (!wl12xx_is_dummy_packet(wl, skb) && info->control.vif) | 755 | if (!wl12xx_is_dummy_packet(wl, skb)) |
703 | wlvif = wl12xx_vif_to_data(info->control.vif); | 756 | wlvif = wl12xx_vif_to_data(info->control.vif); |
704 | else | 757 | else |
705 | hlid = wl->system_hlid; | 758 | hlid = wl->system_hlid; |
@@ -972,10 +1025,11 @@ void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid) | |||
972 | unsigned long flags; | 1025 | unsigned long flags; |
973 | struct ieee80211_tx_info *info; | 1026 | struct ieee80211_tx_info *info; |
974 | int total[NUM_TX_QUEUES]; | 1027 | int total[NUM_TX_QUEUES]; |
1028 | struct wl1271_link *lnk = &wl->links[hlid]; | ||
975 | 1029 | ||
976 | for (i = 0; i < NUM_TX_QUEUES; i++) { | 1030 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
977 | total[i] = 0; | 1031 | total[i] = 0; |
978 | while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) { | 1032 | while ((skb = skb_dequeue(&lnk->tx_queue[i]))) { |
979 | wl1271_debug(DEBUG_TX, "link freeing skb 0x%p", skb); | 1033 | wl1271_debug(DEBUG_TX, "link freeing skb 0x%p", skb); |
980 | 1034 | ||
981 | if (!wl12xx_is_dummy_packet(wl, skb)) { | 1035 | if (!wl12xx_is_dummy_packet(wl, skb)) { |
@@ -990,8 +1044,11 @@ void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid) | |||
990 | } | 1044 | } |
991 | 1045 | ||
992 | spin_lock_irqsave(&wl->wl_lock, flags); | 1046 | spin_lock_irqsave(&wl->wl_lock, flags); |
993 | for (i = 0; i < NUM_TX_QUEUES; i++) | 1047 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
994 | wl->tx_queue_count[i] -= total[i]; | 1048 | wl->tx_queue_count[i] -= total[i]; |
1049 | if (lnk->wlvif) | ||
1050 | lnk->wlvif->tx_queue_count[i] -= total[i]; | ||
1051 | } | ||
995 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 1052 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
996 | 1053 | ||
997 | wl1271_handle_tx_low_watermark(wl); | 1054 | wl1271_handle_tx_low_watermark(wl); |
@@ -1004,16 +1061,18 @@ void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
1004 | 1061 | ||
1005 | /* TX failure */ | 1062 | /* TX failure */ |
1006 | for_each_set_bit(i, wlvif->links_map, WL12XX_MAX_LINKS) { | 1063 | for_each_set_bit(i, wlvif->links_map, WL12XX_MAX_LINKS) { |
1007 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) | 1064 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) { |
1065 | /* this calls wl12xx_free_link */ | ||
1008 | wl1271_free_sta(wl, wlvif, i); | 1066 | wl1271_free_sta(wl, wlvif, i); |
1009 | else | 1067 | } else { |
1010 | wlvif->sta.ba_rx_bitmap = 0; | 1068 | u8 hlid = i; |
1011 | 1069 | wl12xx_free_link(wl, wlvif, &hlid); | |
1012 | wl->links[i].allocated_pkts = 0; | 1070 | } |
1013 | wl->links[i].prev_freed_pkts = 0; | ||
1014 | } | 1071 | } |
1015 | wlvif->last_tx_hlid = 0; | 1072 | wlvif->last_tx_hlid = 0; |
1016 | 1073 | ||
1074 | for (i = 0; i < NUM_TX_QUEUES; i++) | ||
1075 | wlvif->tx_queue_count[i] = 0; | ||
1017 | } | 1076 | } |
1018 | /* caller must hold wl->mutex and TX must be stopped */ | 1077 | /* caller must hold wl->mutex and TX must be stopped */ |
1019 | void wl12xx_tx_reset(struct wl1271 *wl) | 1078 | void wl12xx_tx_reset(struct wl1271 *wl) |
@@ -1023,7 +1082,7 @@ void wl12xx_tx_reset(struct wl1271 *wl) | |||
1023 | struct ieee80211_tx_info *info; | 1082 | struct ieee80211_tx_info *info; |
1024 | 1083 | ||
1025 | /* only reset the queues if something bad happened */ | 1084 | /* only reset the queues if something bad happened */ |
1026 | if (WARN_ON_ONCE(wl1271_tx_total_queue_count(wl) != 0)) { | 1085 | if (wl1271_tx_total_queue_count(wl) != 0) { |
1027 | for (i = 0; i < WL12XX_MAX_LINKS; i++) | 1086 | for (i = 0; i < WL12XX_MAX_LINKS; i++) |
1028 | wl1271_tx_reset_link_queues(wl, i); | 1087 | wl1271_tx_reset_link_queues(wl, i); |
1029 | 1088 | ||
@@ -1135,45 +1194,48 @@ u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set) | |||
1135 | 1194 | ||
1136 | return BIT(__ffs(rate_set)); | 1195 | return BIT(__ffs(rate_set)); |
1137 | } | 1196 | } |
1197 | EXPORT_SYMBOL_GPL(wl1271_tx_min_rate_get); | ||
1138 | 1198 | ||
1139 | void wlcore_stop_queue_locked(struct wl1271 *wl, u8 queue, | 1199 | void wlcore_stop_queue_locked(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
1140 | enum wlcore_queue_stop_reason reason) | 1200 | u8 queue, enum wlcore_queue_stop_reason reason) |
1141 | { | 1201 | { |
1142 | bool stopped = !!wl->queue_stop_reasons[queue]; | 1202 | int hwq = wlcore_tx_get_mac80211_queue(wlvif, queue); |
1203 | bool stopped = !!wl->queue_stop_reasons[hwq]; | ||
1143 | 1204 | ||
1144 | /* queue should not be stopped for this reason */ | 1205 | /* queue should not be stopped for this reason */ |
1145 | WARN_ON(test_and_set_bit(reason, &wl->queue_stop_reasons[queue])); | 1206 | WARN_ON_ONCE(test_and_set_bit(reason, &wl->queue_stop_reasons[hwq])); |
1146 | 1207 | ||
1147 | if (stopped) | 1208 | if (stopped) |
1148 | return; | 1209 | return; |
1149 | 1210 | ||
1150 | ieee80211_stop_queue(wl->hw, wl1271_tx_get_mac80211_queue(queue)); | 1211 | ieee80211_stop_queue(wl->hw, hwq); |
1151 | } | 1212 | } |
1152 | 1213 | ||
1153 | void wlcore_stop_queue(struct wl1271 *wl, u8 queue, | 1214 | void wlcore_stop_queue(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 queue, |
1154 | enum wlcore_queue_stop_reason reason) | 1215 | enum wlcore_queue_stop_reason reason) |
1155 | { | 1216 | { |
1156 | unsigned long flags; | 1217 | unsigned long flags; |
1157 | 1218 | ||
1158 | spin_lock_irqsave(&wl->wl_lock, flags); | 1219 | spin_lock_irqsave(&wl->wl_lock, flags); |
1159 | wlcore_stop_queue_locked(wl, queue, reason); | 1220 | wlcore_stop_queue_locked(wl, wlvif, queue, reason); |
1160 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 1221 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
1161 | } | 1222 | } |
1162 | 1223 | ||
1163 | void wlcore_wake_queue(struct wl1271 *wl, u8 queue, | 1224 | void wlcore_wake_queue(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 queue, |
1164 | enum wlcore_queue_stop_reason reason) | 1225 | enum wlcore_queue_stop_reason reason) |
1165 | { | 1226 | { |
1166 | unsigned long flags; | 1227 | unsigned long flags; |
1228 | int hwq = wlcore_tx_get_mac80211_queue(wlvif, queue); | ||
1167 | 1229 | ||
1168 | spin_lock_irqsave(&wl->wl_lock, flags); | 1230 | spin_lock_irqsave(&wl->wl_lock, flags); |
1169 | 1231 | ||
1170 | /* queue should not be clear for this reason */ | 1232 | /* queue should not be clear for this reason */ |
1171 | WARN_ON(!test_and_clear_bit(reason, &wl->queue_stop_reasons[queue])); | 1233 | WARN_ON_ONCE(!test_and_clear_bit(reason, &wl->queue_stop_reasons[hwq])); |
1172 | 1234 | ||
1173 | if (wl->queue_stop_reasons[queue]) | 1235 | if (wl->queue_stop_reasons[hwq]) |
1174 | goto out; | 1236 | goto out; |
1175 | 1237 | ||
1176 | ieee80211_wake_queue(wl->hw, wl1271_tx_get_mac80211_queue(queue)); | 1238 | ieee80211_wake_queue(wl->hw, hwq); |
1177 | 1239 | ||
1178 | out: | 1240 | out: |
1179 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 1241 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
@@ -1183,48 +1245,74 @@ void wlcore_stop_queues(struct wl1271 *wl, | |||
1183 | enum wlcore_queue_stop_reason reason) | 1245 | enum wlcore_queue_stop_reason reason) |
1184 | { | 1246 | { |
1185 | int i; | 1247 | int i; |
1248 | unsigned long flags; | ||
1186 | 1249 | ||
1187 | for (i = 0; i < NUM_TX_QUEUES; i++) | 1250 | spin_lock_irqsave(&wl->wl_lock, flags); |
1188 | wlcore_stop_queue(wl, i, reason); | 1251 | |
1252 | /* mark all possible queues as stopped */ | ||
1253 | for (i = 0; i < WLCORE_NUM_MAC_ADDRESSES * NUM_TX_QUEUES; i++) | ||
1254 | WARN_ON_ONCE(test_and_set_bit(reason, | ||
1255 | &wl->queue_stop_reasons[i])); | ||
1256 | |||
1257 | /* use the global version to make sure all vifs in mac80211 we don't | ||
1258 | * know are stopped. | ||
1259 | */ | ||
1260 | ieee80211_stop_queues(wl->hw); | ||
1261 | |||
1262 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
1189 | } | 1263 | } |
1190 | EXPORT_SYMBOL_GPL(wlcore_stop_queues); | ||
1191 | 1264 | ||
1192 | void wlcore_wake_queues(struct wl1271 *wl, | 1265 | void wlcore_wake_queues(struct wl1271 *wl, |
1193 | enum wlcore_queue_stop_reason reason) | 1266 | enum wlcore_queue_stop_reason reason) |
1194 | { | 1267 | { |
1195 | int i; | 1268 | int i; |
1269 | unsigned long flags; | ||
1196 | 1270 | ||
1197 | for (i = 0; i < NUM_TX_QUEUES; i++) | 1271 | spin_lock_irqsave(&wl->wl_lock, flags); |
1198 | wlcore_wake_queue(wl, i, reason); | 1272 | |
1273 | /* mark all possible queues as awake */ | ||
1274 | for (i = 0; i < WLCORE_NUM_MAC_ADDRESSES * NUM_TX_QUEUES; i++) | ||
1275 | WARN_ON_ONCE(!test_and_clear_bit(reason, | ||
1276 | &wl->queue_stop_reasons[i])); | ||
1277 | |||
1278 | /* use the global version to make sure all vifs in mac80211 we don't | ||
1279 | * know are woken up. | ||
1280 | */ | ||
1281 | ieee80211_wake_queues(wl->hw); | ||
1282 | |||
1283 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
1199 | } | 1284 | } |
1200 | EXPORT_SYMBOL_GPL(wlcore_wake_queues); | ||
1201 | 1285 | ||
1202 | void wlcore_reset_stopped_queues(struct wl1271 *wl) | 1286 | bool wlcore_is_queue_stopped_by_reason(struct wl1271 *wl, |
1287 | struct wl12xx_vif *wlvif, u8 queue, | ||
1288 | enum wlcore_queue_stop_reason reason) | ||
1203 | { | 1289 | { |
1204 | int i; | ||
1205 | unsigned long flags; | 1290 | unsigned long flags; |
1291 | bool stopped; | ||
1206 | 1292 | ||
1207 | spin_lock_irqsave(&wl->wl_lock, flags); | 1293 | spin_lock_irqsave(&wl->wl_lock, flags); |
1208 | 1294 | stopped = wlcore_is_queue_stopped_by_reason_locked(wl, wlvif, queue, | |
1209 | for (i = 0; i < NUM_TX_QUEUES; i++) { | 1295 | reason); |
1210 | if (!wl->queue_stop_reasons[i]) | ||
1211 | continue; | ||
1212 | |||
1213 | wl->queue_stop_reasons[i] = 0; | ||
1214 | ieee80211_wake_queue(wl->hw, | ||
1215 | wl1271_tx_get_mac80211_queue(i)); | ||
1216 | } | ||
1217 | |||
1218 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 1296 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
1297 | |||
1298 | return stopped; | ||
1219 | } | 1299 | } |
1220 | 1300 | ||
1221 | bool wlcore_is_queue_stopped_by_reason(struct wl1271 *wl, u8 queue, | 1301 | bool wlcore_is_queue_stopped_by_reason_locked(struct wl1271 *wl, |
1222 | enum wlcore_queue_stop_reason reason) | 1302 | struct wl12xx_vif *wlvif, u8 queue, |
1303 | enum wlcore_queue_stop_reason reason) | ||
1223 | { | 1304 | { |
1224 | return test_bit(reason, &wl->queue_stop_reasons[queue]); | 1305 | int hwq = wlcore_tx_get_mac80211_queue(wlvif, queue); |
1306 | |||
1307 | WARN_ON_ONCE(!spin_is_locked(&wl->wl_lock)); | ||
1308 | return test_bit(reason, &wl->queue_stop_reasons[hwq]); | ||
1225 | } | 1309 | } |
1226 | 1310 | ||
1227 | bool wlcore_is_queue_stopped(struct wl1271 *wl, u8 queue) | 1311 | bool wlcore_is_queue_stopped_locked(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
1312 | u8 queue) | ||
1228 | { | 1313 | { |
1229 | return !!wl->queue_stop_reasons[queue]; | 1314 | int hwq = wlcore_tx_get_mac80211_queue(wlvif, queue); |
1315 | |||
1316 | WARN_ON_ONCE(!spin_is_locked(&wl->wl_lock)); | ||
1317 | return !!wl->queue_stop_reasons[hwq]; | ||
1230 | } | 1318 | } |
diff --git a/drivers/net/wireless/ti/wlcore/tx.h b/drivers/net/wireless/ti/wlcore/tx.h index 349520d8b724..55aa4acf9105 100644 --- a/drivers/net/wireless/ti/wlcore/tx.h +++ b/drivers/net/wireless/ti/wlcore/tx.h | |||
@@ -207,19 +207,22 @@ static inline int wl1271_tx_get_queue(int queue) | |||
207 | } | 207 | } |
208 | } | 208 | } |
209 | 209 | ||
210 | static inline int wl1271_tx_get_mac80211_queue(int queue) | 210 | static inline |
211 | int wlcore_tx_get_mac80211_queue(struct wl12xx_vif *wlvif, int queue) | ||
211 | { | 212 | { |
213 | int mac_queue = wlvif->hw_queue_base; | ||
214 | |||
212 | switch (queue) { | 215 | switch (queue) { |
213 | case CONF_TX_AC_VO: | 216 | case CONF_TX_AC_VO: |
214 | return 0; | 217 | return mac_queue + 0; |
215 | case CONF_TX_AC_VI: | 218 | case CONF_TX_AC_VI: |
216 | return 1; | 219 | return mac_queue + 1; |
217 | case CONF_TX_AC_BE: | 220 | case CONF_TX_AC_BE: |
218 | return 2; | 221 | return mac_queue + 2; |
219 | case CONF_TX_AC_BK: | 222 | case CONF_TX_AC_BK: |
220 | return 3; | 223 | return mac_queue + 3; |
221 | default: | 224 | default: |
222 | return 2; | 225 | return mac_queue + 2; |
223 | } | 226 | } |
224 | } | 227 | } |
225 | 228 | ||
@@ -252,20 +255,26 @@ void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids); | |||
252 | unsigned int wlcore_calc_packet_alignment(struct wl1271 *wl, | 255 | unsigned int wlcore_calc_packet_alignment(struct wl1271 *wl, |
253 | unsigned int packet_length); | 256 | unsigned int packet_length); |
254 | void wl1271_free_tx_id(struct wl1271 *wl, int id); | 257 | void wl1271_free_tx_id(struct wl1271 *wl, int id); |
255 | void wlcore_stop_queue_locked(struct wl1271 *wl, u8 queue, | 258 | void wlcore_stop_queue_locked(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
256 | enum wlcore_queue_stop_reason reason); | 259 | u8 queue, enum wlcore_queue_stop_reason reason); |
257 | void wlcore_stop_queue(struct wl1271 *wl, u8 queue, | 260 | void wlcore_stop_queue(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 queue, |
258 | enum wlcore_queue_stop_reason reason); | 261 | enum wlcore_queue_stop_reason reason); |
259 | void wlcore_wake_queue(struct wl1271 *wl, u8 queue, | 262 | void wlcore_wake_queue(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 queue, |
260 | enum wlcore_queue_stop_reason reason); | 263 | enum wlcore_queue_stop_reason reason); |
261 | void wlcore_stop_queues(struct wl1271 *wl, | 264 | void wlcore_stop_queues(struct wl1271 *wl, |
262 | enum wlcore_queue_stop_reason reason); | 265 | enum wlcore_queue_stop_reason reason); |
263 | void wlcore_wake_queues(struct wl1271 *wl, | 266 | void wlcore_wake_queues(struct wl1271 *wl, |
264 | enum wlcore_queue_stop_reason reason); | 267 | enum wlcore_queue_stop_reason reason); |
265 | void wlcore_reset_stopped_queues(struct wl1271 *wl); | 268 | bool wlcore_is_queue_stopped_by_reason(struct wl1271 *wl, |
266 | bool wlcore_is_queue_stopped_by_reason(struct wl1271 *wl, u8 queue, | 269 | struct wl12xx_vif *wlvif, u8 queue, |
267 | enum wlcore_queue_stop_reason reason); | 270 | enum wlcore_queue_stop_reason reason); |
268 | bool wlcore_is_queue_stopped(struct wl1271 *wl, u8 queue); | 271 | bool |
272 | wlcore_is_queue_stopped_by_reason_locked(struct wl1271 *wl, | ||
273 | struct wl12xx_vif *wlvif, | ||
274 | u8 queue, | ||
275 | enum wlcore_queue_stop_reason reason); | ||
276 | bool wlcore_is_queue_stopped_locked(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
277 | u8 queue); | ||
269 | 278 | ||
270 | /* from main.c */ | 279 | /* from main.c */ |
271 | void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid); | 280 | void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid); |
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index c3884937c007..ebd8c6fad7cd 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h | |||
@@ -37,6 +37,9 @@ | |||
37 | */ | 37 | */ |
38 | #define WLCORE_NUM_MAC_ADDRESSES 3 | 38 | #define WLCORE_NUM_MAC_ADDRESSES 3 |
39 | 39 | ||
40 | /* wl12xx/wl18xx maximum transmission power (in dBm) */ | ||
41 | #define WLCORE_MAX_TXPWR 25 | ||
42 | |||
40 | /* forward declaration */ | 43 | /* forward declaration */ |
41 | struct wl1271_tx_hw_descr; | 44 | struct wl1271_tx_hw_descr; |
42 | enum wl_rx_buf_align; | 45 | enum wl_rx_buf_align; |
@@ -51,6 +54,9 @@ struct wlcore_ops { | |||
51 | int (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr, | 54 | int (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr, |
52 | void *buf, size_t len); | 55 | void *buf, size_t len); |
53 | int (*ack_event)(struct wl1271 *wl); | 56 | int (*ack_event)(struct wl1271 *wl); |
57 | int (*wait_for_event)(struct wl1271 *wl, enum wlcore_wait_event event, | ||
58 | bool *timeout); | ||
59 | int (*process_mailbox_events)(struct wl1271 *wl); | ||
54 | u32 (*calc_tx_blocks)(struct wl1271 *wl, u32 len, u32 spare_blks); | 60 | u32 (*calc_tx_blocks)(struct wl1271 *wl, u32 len, u32 spare_blks); |
55 | void (*set_tx_desc_blocks)(struct wl1271 *wl, | 61 | void (*set_tx_desc_blocks)(struct wl1271 *wl, |
56 | struct wl1271_tx_hw_descr *desc, | 62 | struct wl1271_tx_hw_descr *desc, |
@@ -82,12 +88,32 @@ struct wlcore_ops { | |||
82 | int (*debugfs_init)(struct wl1271 *wl, struct dentry *rootdir); | 88 | int (*debugfs_init)(struct wl1271 *wl, struct dentry *rootdir); |
83 | int (*handle_static_data)(struct wl1271 *wl, | 89 | int (*handle_static_data)(struct wl1271 *wl, |
84 | struct wl1271_static_data *static_data); | 90 | struct wl1271_static_data *static_data); |
91 | int (*scan_start)(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
92 | struct cfg80211_scan_request *req); | ||
93 | int (*scan_stop)(struct wl1271 *wl, struct wl12xx_vif *wlvif); | ||
94 | int (*sched_scan_start)(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
95 | struct cfg80211_sched_scan_request *req, | ||
96 | struct ieee80211_sched_scan_ies *ies); | ||
97 | void (*sched_scan_stop)(struct wl1271 *wl, struct wl12xx_vif *wlvif); | ||
85 | int (*get_spare_blocks)(struct wl1271 *wl, bool is_gem); | 98 | int (*get_spare_blocks)(struct wl1271 *wl, bool is_gem); |
86 | int (*set_key)(struct wl1271 *wl, enum set_key_cmd cmd, | 99 | int (*set_key)(struct wl1271 *wl, enum set_key_cmd cmd, |
87 | struct ieee80211_vif *vif, | 100 | struct ieee80211_vif *vif, |
88 | struct ieee80211_sta *sta, | 101 | struct ieee80211_sta *sta, |
89 | struct ieee80211_key_conf *key_conf); | 102 | struct ieee80211_key_conf *key_conf); |
103 | int (*channel_switch)(struct wl1271 *wl, | ||
104 | struct wl12xx_vif *wlvif, | ||
105 | struct ieee80211_channel_switch *ch_switch); | ||
90 | u32 (*pre_pkt_send)(struct wl1271 *wl, u32 buf_offset, u32 last_len); | 106 | u32 (*pre_pkt_send)(struct wl1271 *wl, u32 buf_offset, u32 last_len); |
107 | void (*sta_rc_update)(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
108 | struct ieee80211_sta *sta, u32 changed); | ||
109 | int (*set_peer_cap)(struct wl1271 *wl, | ||
110 | struct ieee80211_sta_ht_cap *ht_cap, | ||
111 | bool allow_ht_operation, | ||
112 | u32 rate_set, u8 hlid); | ||
113 | bool (*lnk_high_prio)(struct wl1271 *wl, u8 hlid, | ||
114 | struct wl1271_link *lnk); | ||
115 | bool (*lnk_low_prio)(struct wl1271 *wl, u8 hlid, | ||
116 | struct wl1271_link *lnk); | ||
91 | }; | 117 | }; |
92 | 118 | ||
93 | enum wlcore_partitions { | 119 | enum wlcore_partitions { |
@@ -202,6 +228,8 @@ struct wl1271 { | |||
202 | unsigned long klv_templates_map[ | 228 | unsigned long klv_templates_map[ |
203 | BITS_TO_LONGS(WLCORE_MAX_KLV_TEMPLATES)]; | 229 | BITS_TO_LONGS(WLCORE_MAX_KLV_TEMPLATES)]; |
204 | 230 | ||
231 | u8 session_ids[WL12XX_MAX_LINKS]; | ||
232 | |||
205 | struct list_head wlvif_list; | 233 | struct list_head wlvif_list; |
206 | 234 | ||
207 | u8 sta_count; | 235 | u8 sta_count; |
@@ -227,7 +255,8 @@ struct wl1271 { | |||
227 | 255 | ||
228 | /* Frames scheduled for transmission, not handled yet */ | 256 | /* Frames scheduled for transmission, not handled yet */ |
229 | int tx_queue_count[NUM_TX_QUEUES]; | 257 | int tx_queue_count[NUM_TX_QUEUES]; |
230 | unsigned long queue_stop_reasons[NUM_TX_QUEUES]; | 258 | unsigned long queue_stop_reasons[ |
259 | NUM_TX_QUEUES * WLCORE_NUM_MAC_ADDRESSES]; | ||
231 | 260 | ||
232 | /* Frames received, not handled yet by mac80211 */ | 261 | /* Frames received, not handled yet by mac80211 */ |
233 | struct sk_buff_head deferred_rx_queue; | 262 | struct sk_buff_head deferred_rx_queue; |
@@ -269,24 +298,30 @@ struct wl1271 { | |||
269 | struct work_struct recovery_work; | 298 | struct work_struct recovery_work; |
270 | bool watchdog_recovery; | 299 | bool watchdog_recovery; |
271 | 300 | ||
301 | /* Reg domain last configuration */ | ||
302 | u32 reg_ch_conf_last[2]; | ||
303 | /* Reg domain pending configuration */ | ||
304 | u32 reg_ch_conf_pending[2]; | ||
305 | |||
272 | /* Pointer that holds DMA-friendly block for the mailbox */ | 306 | /* Pointer that holds DMA-friendly block for the mailbox */ |
273 | struct event_mailbox *mbox; | 307 | void *mbox; |
274 | 308 | ||
275 | /* The mbox event mask */ | 309 | /* The mbox event mask */ |
276 | u32 event_mask; | 310 | u32 event_mask; |
277 | 311 | ||
278 | /* Mailbox pointers */ | 312 | /* Mailbox pointers */ |
313 | u32 mbox_size; | ||
279 | u32 mbox_ptr[2]; | 314 | u32 mbox_ptr[2]; |
280 | 315 | ||
281 | /* Are we currently scanning */ | 316 | /* Are we currently scanning */ |
282 | struct ieee80211_vif *scan_vif; | 317 | struct wl12xx_vif *scan_wlvif; |
283 | struct wl1271_scan scan; | 318 | struct wl1271_scan scan; |
284 | struct delayed_work scan_complete_work; | 319 | struct delayed_work scan_complete_work; |
285 | 320 | ||
286 | /* Connection loss work */ | 321 | struct ieee80211_vif *roc_vif; |
287 | struct delayed_work connection_loss_work; | 322 | struct delayed_work roc_complete_work; |
288 | 323 | ||
289 | bool sched_scanning; | 324 | struct wl12xx_vif *sched_vif; |
290 | 325 | ||
291 | /* The current band */ | 326 | /* The current band */ |
292 | enum ieee80211_band band; | 327 | enum ieee80211_band band; |
@@ -299,7 +334,7 @@ struct wl1271 { | |||
299 | 334 | ||
300 | struct wl1271_stats stats; | 335 | struct wl1271_stats stats; |
301 | 336 | ||
302 | __le32 buffer_32; | 337 | __le32 *buffer_32; |
303 | u32 buffer_cmd; | 338 | u32 buffer_cmd; |
304 | u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; | 339 | u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; |
305 | 340 | ||
@@ -314,6 +349,8 @@ struct wl1271 { | |||
314 | 349 | ||
315 | bool enable_11a; | 350 | bool enable_11a; |
316 | 351 | ||
352 | int recovery_count; | ||
353 | |||
317 | /* Most recently reported noise in dBm */ | 354 | /* Most recently reported noise in dBm */ |
318 | s8 noise; | 355 | s8 noise; |
319 | 356 | ||
@@ -333,6 +370,12 @@ struct wl1271 { | |||
333 | */ | 370 | */ |
334 | struct wl1271_link links[WL12XX_MAX_LINKS]; | 371 | struct wl1271_link links[WL12XX_MAX_LINKS]; |
335 | 372 | ||
373 | /* number of currently active links */ | ||
374 | int active_link_count; | ||
375 | |||
376 | /* Fast/slow links bitmap according to FW */ | ||
377 | u32 fw_fast_lnk_map; | ||
378 | |||
336 | /* AP-mode - a bitmap of links currently in PS mode according to FW */ | 379 | /* AP-mode - a bitmap of links currently in PS mode according to FW */ |
337 | u32 ap_fw_ps_map; | 380 | u32 ap_fw_ps_map; |
338 | 381 | ||
@@ -367,6 +410,12 @@ struct wl1271 { | |||
367 | const char *sr_fw_name; | 410 | const char *sr_fw_name; |
368 | const char *mr_fw_name; | 411 | const char *mr_fw_name; |
369 | 412 | ||
413 | u8 scan_templ_id_2_4; | ||
414 | u8 scan_templ_id_5; | ||
415 | u8 sched_scan_templ_id_2_4; | ||
416 | u8 sched_scan_templ_id_5; | ||
417 | u8 max_channels_5; | ||
418 | |||
370 | /* per-chip-family private structure */ | 419 | /* per-chip-family private structure */ |
371 | void *priv; | 420 | void *priv; |
372 | 421 | ||
@@ -408,20 +457,28 @@ struct wl1271 { | |||
408 | /* the number of allocated MAC addresses in this chip */ | 457 | /* the number of allocated MAC addresses in this chip */ |
409 | int num_mac_addr; | 458 | int num_mac_addr; |
410 | 459 | ||
411 | /* the minimum FW version required for the driver to work */ | 460 | /* minimum FW version required for the driver to work in single-role */ |
412 | unsigned int min_fw_ver[NUM_FW_VER]; | 461 | unsigned int min_sr_fw_ver[NUM_FW_VER]; |
462 | |||
463 | /* minimum FW version required for the driver to work in multi-role */ | ||
464 | unsigned int min_mr_fw_ver[NUM_FW_VER]; | ||
413 | 465 | ||
414 | struct completion nvs_loading_complete; | 466 | struct completion nvs_loading_complete; |
467 | |||
468 | /* number of concurrent channels the HW supports */ | ||
469 | u32 num_channels; | ||
415 | }; | 470 | }; |
416 | 471 | ||
417 | int wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); | 472 | int wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); |
418 | int wlcore_remove(struct platform_device *pdev); | 473 | int wlcore_remove(struct platform_device *pdev); |
419 | struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size); | 474 | struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size, |
475 | u32 mbox_size); | ||
420 | int wlcore_free_hw(struct wl1271 *wl); | 476 | int wlcore_free_hw(struct wl1271 *wl); |
421 | int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, | 477 | int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, |
422 | struct ieee80211_vif *vif, | 478 | struct ieee80211_vif *vif, |
423 | struct ieee80211_sta *sta, | 479 | struct ieee80211_sta *sta, |
424 | struct ieee80211_key_conf *key_conf); | 480 | struct ieee80211_key_conf *key_conf); |
481 | void wlcore_regdomain_config(struct wl1271 *wl); | ||
425 | 482 | ||
426 | static inline void | 483 | static inline void |
427 | wlcore_set_ht_cap(struct wl1271 *wl, enum ieee80211_band band, | 484 | wlcore_set_ht_cap(struct wl1271 *wl, enum ieee80211_band band, |
@@ -430,16 +487,27 @@ wlcore_set_ht_cap(struct wl1271 *wl, enum ieee80211_band band, | |||
430 | memcpy(&wl->ht_cap[band], ht_cap, sizeof(*ht_cap)); | 487 | memcpy(&wl->ht_cap[band], ht_cap, sizeof(*ht_cap)); |
431 | } | 488 | } |
432 | 489 | ||
490 | /* Tell wlcore not to care about this element when checking the version */ | ||
491 | #define WLCORE_FW_VER_IGNORE -1 | ||
492 | |||
433 | static inline void | 493 | static inline void |
434 | wlcore_set_min_fw_ver(struct wl1271 *wl, unsigned int chip, | 494 | wlcore_set_min_fw_ver(struct wl1271 *wl, unsigned int chip, |
435 | unsigned int iftype, unsigned int major, | 495 | unsigned int iftype_sr, unsigned int major_sr, |
436 | unsigned int subtype, unsigned int minor) | 496 | unsigned int subtype_sr, unsigned int minor_sr, |
497 | unsigned int iftype_mr, unsigned int major_mr, | ||
498 | unsigned int subtype_mr, unsigned int minor_mr) | ||
437 | { | 499 | { |
438 | wl->min_fw_ver[FW_VER_CHIP] = chip; | 500 | wl->min_sr_fw_ver[FW_VER_CHIP] = chip; |
439 | wl->min_fw_ver[FW_VER_IF_TYPE] = iftype; | 501 | wl->min_sr_fw_ver[FW_VER_IF_TYPE] = iftype_sr; |
440 | wl->min_fw_ver[FW_VER_MAJOR] = major; | 502 | wl->min_sr_fw_ver[FW_VER_MAJOR] = major_sr; |
441 | wl->min_fw_ver[FW_VER_SUBTYPE] = subtype; | 503 | wl->min_sr_fw_ver[FW_VER_SUBTYPE] = subtype_sr; |
442 | wl->min_fw_ver[FW_VER_MINOR] = minor; | 504 | wl->min_sr_fw_ver[FW_VER_MINOR] = minor_sr; |
505 | |||
506 | wl->min_mr_fw_ver[FW_VER_CHIP] = chip; | ||
507 | wl->min_mr_fw_ver[FW_VER_IF_TYPE] = iftype_mr; | ||
508 | wl->min_mr_fw_ver[FW_VER_MAJOR] = major_mr; | ||
509 | wl->min_mr_fw_ver[FW_VER_SUBTYPE] = subtype_mr; | ||
510 | wl->min_mr_fw_ver[FW_VER_MINOR] = minor_mr; | ||
443 | } | 511 | } |
444 | 512 | ||
445 | /* Firmware image load chunk size */ | 513 | /* Firmware image load chunk size */ |
@@ -450,6 +518,9 @@ wlcore_set_min_fw_ver(struct wl1271 *wl, unsigned int chip, | |||
450 | /* Each RX/TX transaction requires an end-of-transaction transfer */ | 518 | /* Each RX/TX transaction requires an end-of-transaction transfer */ |
451 | #define WLCORE_QUIRK_END_OF_TRANSACTION BIT(0) | 519 | #define WLCORE_QUIRK_END_OF_TRANSACTION BIT(0) |
452 | 520 | ||
521 | /* the first start_role(sta) sometimes doesn't work on wl12xx */ | ||
522 | #define WLCORE_QUIRK_START_STA_FAILS BIT(1) | ||
523 | |||
453 | /* wl127x and SPI don't support SDIO block size alignment */ | 524 | /* wl127x and SPI don't support SDIO block size alignment */ |
454 | #define WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN BIT(2) | 525 | #define WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN BIT(2) |
455 | 526 | ||
@@ -462,9 +533,6 @@ wlcore_set_min_fw_ver(struct wl1271 *wl, unsigned int chip, | |||
462 | /* Older firmwares use an old NVS format */ | 533 | /* Older firmwares use an old NVS format */ |
463 | #define WLCORE_QUIRK_LEGACY_NVS BIT(5) | 534 | #define WLCORE_QUIRK_LEGACY_NVS BIT(5) |
464 | 535 | ||
465 | /* Some firmwares may not support ELP */ | ||
466 | #define WLCORE_QUIRK_NO_ELP BIT(6) | ||
467 | |||
468 | /* pad only the last frame in the aggregate buffer */ | 536 | /* pad only the last frame in the aggregate buffer */ |
469 | #define WLCORE_QUIRK_TX_PAD_LAST_FRAME BIT(7) | 537 | #define WLCORE_QUIRK_TX_PAD_LAST_FRAME BIT(7) |
470 | 538 | ||
@@ -477,11 +545,11 @@ wlcore_set_min_fw_ver(struct wl1271 *wl, unsigned int chip, | |||
477 | /* separate probe response templates for one-shot and sched scans */ | 545 | /* separate probe response templates for one-shot and sched scans */ |
478 | #define WLCORE_QUIRK_DUAL_PROBE_TMPL BIT(10) | 546 | #define WLCORE_QUIRK_DUAL_PROBE_TMPL BIT(10) |
479 | 547 | ||
480 | /* TODO: move to the lower drivers when all usages are abstracted */ | 548 | /* Firmware requires reg domain configuration for active calibration */ |
481 | #define CHIP_ID_1271_PG10 (0x4030101) | 549 | #define WLCORE_QUIRK_REGDOMAIN_CONF BIT(11) |
482 | #define CHIP_ID_1271_PG20 (0x4030111) | 550 | |
483 | #define CHIP_ID_1283_PG10 (0x05030101) | 551 | /* The FW only support a zero session id for AP */ |
484 | #define CHIP_ID_1283_PG20 (0x05030111) | 552 | #define WLCORE_QUIRK_AP_ZERO_SESSION_ID BIT(12) |
485 | 553 | ||
486 | /* TODO: move all these common registers and values elsewhere */ | 554 | /* TODO: move all these common registers and values elsewhere */ |
487 | #define HW_ACCESS_ELP_CTRL_REG 0x1FFFC | 555 | #define HW_ACCESS_ELP_CTRL_REG 0x1FFFC |
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h index 5ce26cf402fc..910f8e2e556a 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h | |||
@@ -109,17 +109,6 @@ enum { | |||
109 | NUM_FW_VER | 109 | NUM_FW_VER |
110 | }; | 110 | }; |
111 | 111 | ||
112 | #define FW_VER_CHIP_WL127X 6 | ||
113 | #define FW_VER_CHIP_WL128X 7 | ||
114 | |||
115 | #define FW_VER_IF_TYPE_STA 1 | ||
116 | #define FW_VER_IF_TYPE_AP 2 | ||
117 | |||
118 | #define FW_VER_MINOR_1_SPARE_STA_MIN 58 | ||
119 | #define FW_VER_MINOR_1_SPARE_AP_MIN 47 | ||
120 | |||
121 | #define FW_VER_MINOR_FWLOG_STA_MIN 70 | ||
122 | |||
123 | struct wl1271_chip { | 112 | struct wl1271_chip { |
124 | u32 id; | 113 | u32 id; |
125 | char fw_ver_str[ETHTOOL_FWVERS_LEN]; | 114 | char fw_ver_str[ETHTOOL_FWVERS_LEN]; |
@@ -141,7 +130,10 @@ struct wl_fw_packet_counters { | |||
141 | /* Cumulative counter of released Voice memory blocks */ | 130 | /* Cumulative counter of released Voice memory blocks */ |
142 | u8 tx_voice_released_blks; | 131 | u8 tx_voice_released_blks; |
143 | 132 | ||
144 | u8 padding[3]; | 133 | /* Tx rate of the last transmitted packet */ |
134 | u8 tx_last_rate; | ||
135 | |||
136 | u8 padding[2]; | ||
145 | } __packed; | 137 | } __packed; |
146 | 138 | ||
147 | /* FW status registers */ | 139 | /* FW status registers */ |
@@ -260,6 +252,8 @@ enum wl12xx_vif_flags { | |||
260 | WLVIF_FLAG_IN_USE, | 252 | WLVIF_FLAG_IN_USE, |
261 | }; | 253 | }; |
262 | 254 | ||
255 | struct wl12xx_vif; | ||
256 | |||
263 | struct wl1271_link { | 257 | struct wl1271_link { |
264 | /* AP-mode - TX queue per AC in link */ | 258 | /* AP-mode - TX queue per AC in link */ |
265 | struct sk_buff_head tx_queue[NUM_TX_QUEUES]; | 259 | struct sk_buff_head tx_queue[NUM_TX_QUEUES]; |
@@ -272,6 +266,9 @@ struct wl1271_link { | |||
272 | 266 | ||
273 | /* bitmap of TIDs where RX BA sessions are active for this link */ | 267 | /* bitmap of TIDs where RX BA sessions are active for this link */ |
274 | u8 ba_bitmap; | 268 | u8 ba_bitmap; |
269 | |||
270 | /* The wlvif this link belongs to. Might be null for global links */ | ||
271 | struct wl12xx_vif *wlvif; | ||
275 | }; | 272 | }; |
276 | 273 | ||
277 | #define WL1271_MAX_RX_FILTERS 5 | 274 | #define WL1271_MAX_RX_FILTERS 5 |
@@ -315,6 +312,7 @@ struct wl12xx_rx_filter { | |||
315 | 312 | ||
316 | struct wl1271_station { | 313 | struct wl1271_station { |
317 | u8 hlid; | 314 | u8 hlid; |
315 | bool in_connection; | ||
318 | }; | 316 | }; |
319 | 317 | ||
320 | struct wl12xx_vif { | 318 | struct wl12xx_vif { |
@@ -332,7 +330,6 @@ struct wl12xx_vif { | |||
332 | union { | 330 | union { |
333 | struct { | 331 | struct { |
334 | u8 hlid; | 332 | u8 hlid; |
335 | u8 ba_rx_bitmap; | ||
336 | 333 | ||
337 | u8 basic_rate_idx; | 334 | u8 basic_rate_idx; |
338 | u8 ap_rate_idx; | 335 | u8 ap_rate_idx; |
@@ -341,6 +338,8 @@ struct wl12xx_vif { | |||
341 | u8 klv_template_id; | 338 | u8 klv_template_id; |
342 | 339 | ||
343 | bool qos; | 340 | bool qos; |
341 | /* channel type we started the STA role with */ | ||
342 | enum nl80211_channel_type role_chan_type; | ||
344 | } sta; | 343 | } sta; |
345 | struct { | 344 | struct { |
346 | u8 global_hlid; | 345 | u8 global_hlid; |
@@ -362,6 +361,9 @@ struct wl12xx_vif { | |||
362 | /* the hlid of the last transmitted skb */ | 361 | /* the hlid of the last transmitted skb */ |
363 | int last_tx_hlid; | 362 | int last_tx_hlid; |
364 | 363 | ||
364 | /* counters of packets per AC, across all links in the vif */ | ||
365 | int tx_queue_count[NUM_TX_QUEUES]; | ||
366 | |||
365 | unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)]; | 367 | unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)]; |
366 | 368 | ||
367 | u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; | 369 | u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; |
@@ -396,9 +398,6 @@ struct wl12xx_vif { | |||
396 | /* Our association ID */ | 398 | /* Our association ID */ |
397 | u16 aid; | 399 | u16 aid; |
398 | 400 | ||
399 | /* Session counter for the chipset */ | ||
400 | int session_counter; | ||
401 | |||
402 | /* retry counter for PSM entries */ | 401 | /* retry counter for PSM entries */ |
403 | u8 psm_entry_retry; | 402 | u8 psm_entry_retry; |
404 | 403 | ||
@@ -416,11 +415,28 @@ struct wl12xx_vif { | |||
416 | bool ba_support; | 415 | bool ba_support; |
417 | bool ba_allowed; | 416 | bool ba_allowed; |
418 | 417 | ||
418 | bool wmm_enabled; | ||
419 | |||
419 | /* Rx Streaming */ | 420 | /* Rx Streaming */ |
420 | struct work_struct rx_streaming_enable_work; | 421 | struct work_struct rx_streaming_enable_work; |
421 | struct work_struct rx_streaming_disable_work; | 422 | struct work_struct rx_streaming_disable_work; |
422 | struct timer_list rx_streaming_timer; | 423 | struct timer_list rx_streaming_timer; |
423 | 424 | ||
425 | struct delayed_work channel_switch_work; | ||
426 | struct delayed_work connection_loss_work; | ||
427 | |||
428 | /* number of in connection stations */ | ||
429 | int inconn_count; | ||
430 | |||
431 | /* | ||
432 | * This vif's queues are mapped to mac80211 HW queues as: | ||
433 | * VO - hw_queue_base | ||
434 | * VI - hw_queue_base + 1 | ||
435 | * BE - hw_queue_base + 2 | ||
436 | * BK - hw_queue_base + 3 | ||
437 | */ | ||
438 | int hw_queue_base; | ||
439 | |||
424 | /* | 440 | /* |
425 | * This struct must be last! | 441 | * This struct must be last! |
426 | * data that has to be saved acrossed reconfigs (e.g. recovery) | 442 | * data that has to be saved acrossed reconfigs (e.g. recovery) |
@@ -443,6 +459,7 @@ struct wl12xx_vif { | |||
443 | 459 | ||
444 | static inline struct wl12xx_vif *wl12xx_vif_to_data(struct ieee80211_vif *vif) | 460 | static inline struct wl12xx_vif *wl12xx_vif_to_data(struct ieee80211_vif *vif) |
445 | { | 461 | { |
462 | WARN_ON(!vif); | ||
446 | return (struct wl12xx_vif *)vif->drv_priv; | 463 | return (struct wl12xx_vif *)vif->drv_priv; |
447 | } | 464 | } |
448 | 465 | ||