aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ti
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-04-22 09:31:43 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-04-22 09:31:43 -0400
commita42c74ee608a424342ef7069ccddf196d873040c (patch)
tree75adfb9f5e06ebb7c7d5d5e5a5408fa0d6d504b9 /drivers/net/wireless/ti
parent97990a060e6757f48b931a3946b17c1c4362c3fb (diff)
parent9b383672452bb1097124c76fcb4903e0021f6baf (diff)
Merge remote-tracking branch 'wireless-next/master' into mac80211-next
Diffstat (limited to 'drivers/net/wireless/ti')
-rw-r--r--drivers/net/wireless/ti/wl1251/sdio.c4
-rw-r--r--drivers/net/wireless/ti/wl12xx/main.c1
-rw-r--r--drivers/net/wireless/ti/wl12xx/wl12xx.h2
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c25
-rw-r--r--drivers/net/wireless/ti/wl18xx/reg.h29
-rw-r--r--drivers/net/wireless/ti/wl18xx/wl18xx.h4
-rw-r--r--drivers/net/wireless/ti/wlcore/acx.c29
-rw-r--r--drivers/net/wireless/ti/wlcore/acx.h16
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.c32
-rw-r--r--drivers/net/wireless/ti/wlcore/debug.h33
-rw-r--r--drivers/net/wireless/ti/wlcore/debugfs.c3
-rw-r--r--drivers/net/wireless/ti/wlcore/event.c9
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c198
-rw-r--r--drivers/net/wireless/ti/wlcore/ps.c4
-rw-r--r--drivers/net/wireless/ti/wlcore/tx.c39
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore.h3
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore_i.h29
17 files changed, 330 insertions, 130 deletions
diff --git a/drivers/net/wireless/ti/wl1251/sdio.c b/drivers/net/wireless/ti/wl1251/sdio.c
index e57ee48edff6..e2b3d9c541e8 100644
--- a/drivers/net/wireless/ti/wl1251/sdio.c
+++ b/drivers/net/wireless/ti/wl1251/sdio.c
@@ -186,8 +186,10 @@ static int wl1251_sdio_set_power(struct wl1251 *wl, bool enable)
186 wl->set_power(true); 186 wl->set_power(true);
187 187
188 ret = pm_runtime_get_sync(&func->dev); 188 ret = pm_runtime_get_sync(&func->dev);
189 if (ret < 0) 189 if (ret < 0) {
190 pm_runtime_put_sync(&func->dev);
190 goto out; 191 goto out;
192 }
191 193
192 sdio_claim_host(func); 194 sdio_claim_host(func);
193 sdio_enable_func(func); 195 sdio_enable_func(func);
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index 09694e39bb14..1c627da85083 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -723,6 +723,7 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
723 wl->sched_scan_templ_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4; 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; 724 wl->sched_scan_templ_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5;
725 wl->max_channels_5 = WL12XX_MAX_CHANNELS_5GHZ; 725 wl->max_channels_5 = WL12XX_MAX_CHANNELS_5GHZ;
726 wl->ba_rx_session_count_max = WL12XX_RX_BA_MAX_SESSIONS;
726out: 727out:
727 return ret; 728 return ret;
728} 729}
diff --git a/drivers/net/wireless/ti/wl12xx/wl12xx.h b/drivers/net/wireless/ti/wl12xx/wl12xx.h
index d4552857480c..222d03540200 100644
--- a/drivers/net/wireless/ti/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h
@@ -63,6 +63,8 @@
63 63
64#define WL12XX_NUM_MAC_ADDRESSES 2 64#define WL12XX_NUM_MAC_ADDRESSES 2
65 65
66#define WL12XX_RX_BA_MAX_SESSIONS 3
67
66struct wl127x_rx_mem_pool_addr { 68struct wl127x_rx_mem_pool_addr {
67 u32 addr; 69 u32 addr;
68 u32 addr_extra; 70 u32 addr_extra;
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index da3ef1b10a9c..9fa692d11025 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -678,6 +678,7 @@ static int wl18xx_identify_chip(struct wl1271 *wl)
678 wl->sched_scan_templ_id_2_4 = CMD_TEMPL_PROBE_REQ_2_4_PERIODIC; 678 wl->sched_scan_templ_id_2_4 = CMD_TEMPL_PROBE_REQ_2_4_PERIODIC;
679 wl->sched_scan_templ_id_5 = CMD_TEMPL_PROBE_REQ_5_PERIODIC; 679 wl->sched_scan_templ_id_5 = CMD_TEMPL_PROBE_REQ_5_PERIODIC;
680 wl->max_channels_5 = WL18XX_MAX_CHANNELS_5GHZ; 680 wl->max_channels_5 = WL18XX_MAX_CHANNELS_5GHZ;
681 wl->ba_rx_session_count_max = WL18XX_RX_BA_MAX_SESSIONS;
681out: 682out:
682 return ret; 683 return ret;
683} 684}
@@ -1144,6 +1145,7 @@ static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl,
1144static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver) 1145static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver)
1145{ 1146{
1146 u32 fuse; 1147 u32 fuse;
1148 s8 rom = 0, metal = 0, pg_ver = 0, rdl_ver = 0;
1147 int ret; 1149 int ret;
1148 1150
1149 ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); 1151 ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
@@ -1154,8 +1156,29 @@ static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver)
1154 if (ret < 0) 1156 if (ret < 0)
1155 goto out; 1157 goto out;
1156 1158
1159 pg_ver = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET;
1160 rom = (fuse & WL18XX_ROM_VER_MASK) >> WL18XX_ROM_VER_OFFSET;
1161
1162 if (rom <= 0xE)
1163 metal = (fuse & WL18XX_METAL_VER_MASK) >>
1164 WL18XX_METAL_VER_OFFSET;
1165 else
1166 metal = (fuse & WL18XX_NEW_METAL_VER_MASK) >>
1167 WL18XX_NEW_METAL_VER_OFFSET;
1168
1169 ret = wlcore_read32(wl, WL18XX_REG_FUSE_DATA_2_3, &fuse);
1170 if (ret < 0)
1171 goto out;
1172
1173 rdl_ver = (fuse & WL18XX_RDL_VER_MASK) >> WL18XX_RDL_VER_OFFSET;
1174 if (rdl_ver > RDL_MAX)
1175 rdl_ver = RDL_NONE;
1176
1177 wl1271_info("wl18xx HW: RDL %d, %s, PG %x.%x (ROM %x)",
1178 rdl_ver, rdl_names[rdl_ver], pg_ver, metal, rom);
1179
1157 if (ver) 1180 if (ver)
1158 *ver = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET; 1181 *ver = pg_ver;
1159 1182
1160 ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); 1183 ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
1161 1184
diff --git a/drivers/net/wireless/ti/wl18xx/reg.h b/drivers/net/wireless/ti/wl18xx/reg.h
index 937b71d8783f..6306e04cd258 100644
--- a/drivers/net/wireless/ti/wl18xx/reg.h
+++ b/drivers/net/wireless/ti/wl18xx/reg.h
@@ -131,6 +131,16 @@
131#define WL18XX_REG_FUSE_DATA_1_3 0xA0260C 131#define WL18XX_REG_FUSE_DATA_1_3 0xA0260C
132#define WL18XX_PG_VER_MASK 0x70 132#define WL18XX_PG_VER_MASK 0x70
133#define WL18XX_PG_VER_OFFSET 4 133#define WL18XX_PG_VER_OFFSET 4
134#define WL18XX_ROM_VER_MASK 0x3
135#define WL18XX_ROM_VER_OFFSET 0
136#define WL18XX_METAL_VER_MASK 0xC
137#define WL18XX_METAL_VER_OFFSET 2
138#define WL18XX_NEW_METAL_VER_MASK 0x180
139#define WL18XX_NEW_METAL_VER_OFFSET 7
140
141#define WL18XX_REG_FUSE_DATA_2_3 0xA02614
142#define WL18XX_RDL_VER_MASK 0x1f00
143#define WL18XX_RDL_VER_OFFSET 8
134 144
135#define WL18XX_REG_FUSE_BD_ADDR_1 0xA02602 145#define WL18XX_REG_FUSE_BD_ADDR_1 0xA02602
136#define WL18XX_REG_FUSE_BD_ADDR_2 0xA02606 146#define WL18XX_REG_FUSE_BD_ADDR_2 0xA02606
@@ -188,4 +198,23 @@ enum {
188 NUM_BOARD_TYPES, 198 NUM_BOARD_TYPES,
189}; 199};
190 200
201enum {
202 RDL_NONE = 0,
203 RDL_1_HP = 1,
204 RDL_2_SP = 2,
205 RDL_3_HP = 3,
206 RDL_4_SP = 4,
207
208 _RDL_LAST,
209 RDL_MAX = _RDL_LAST - 1,
210};
211
212static const char * const rdl_names[] = {
213 [RDL_NONE] = "",
214 [RDL_1_HP] = "1853 SISO",
215 [RDL_2_SP] = "1857 MIMO",
216 [RDL_3_HP] = "1893 SISO",
217 [RDL_4_SP] = "1897 MIMO",
218};
219
191#endif /* __REG_H__ */ 220#endif /* __REG_H__ */
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h
index b6739e79efcf..9204e07ee432 100644
--- a/drivers/net/wireless/ti/wl18xx/wl18xx.h
+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h
@@ -29,7 +29,7 @@
29#define WL18XX_IFTYPE_VER 5 29#define WL18XX_IFTYPE_VER 5
30#define WL18XX_MAJOR_VER WLCORE_FW_VER_IGNORE 30#define WL18XX_MAJOR_VER WLCORE_FW_VER_IGNORE
31#define WL18XX_SUBTYPE_VER WLCORE_FW_VER_IGNORE 31#define WL18XX_SUBTYPE_VER WLCORE_FW_VER_IGNORE
32#define WL18XX_MINOR_VER 28 32#define WL18XX_MINOR_VER 39
33 33
34#define WL18XX_CMD_MAX_SIZE 740 34#define WL18XX_CMD_MAX_SIZE 740
35 35
@@ -40,6 +40,8 @@
40 40
41#define WL18XX_NUM_MAC_ADDRESSES 3 41#define WL18XX_NUM_MAC_ADDRESSES 3
42 42
43#define WL18XX_RX_BA_MAX_SESSIONS 5
44
43struct wl18xx_priv { 45struct wl18xx_priv {
44 /* buffer for sending commands to FW */ 46 /* buffer for sending commands to FW */
45 u8 cmd_buf[WL18XX_CMD_MAX_SIZE]; 47 u8 cmd_buf[WL18XX_CMD_MAX_SIZE];
diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c
index c79654323396..7a970cd9c555 100644
--- a/drivers/net/wireless/ti/wlcore/acx.c
+++ b/drivers/net/wireless/ti/wlcore/acx.c
@@ -1736,6 +1736,35 @@ out:
1736 1736
1737} 1737}
1738 1738
1739int wlcore_acx_average_rssi(struct wl1271 *wl, struct wl12xx_vif *wlvif,
1740 s8 *avg_rssi)
1741{
1742 struct acx_roaming_stats *acx;
1743 int ret = 0;
1744
1745 wl1271_debug(DEBUG_ACX, "acx roaming statistics");
1746
1747 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
1748 if (!acx) {
1749 ret = -ENOMEM;
1750 goto out;
1751 }
1752
1753 acx->role_id = wlvif->role_id;
1754 ret = wl1271_cmd_interrogate(wl, ACX_ROAMING_STATISTICS_TBL,
1755 acx, sizeof(*acx));
1756 if (ret < 0) {
1757 wl1271_warning("acx roaming statistics failed: %d", ret);
1758 ret = -ENOMEM;
1759 goto out;
1760 }
1761
1762 *avg_rssi = acx->rssi_beacon;
1763out:
1764 kfree(acx);
1765 return ret;
1766}
1767
1739#ifdef CONFIG_PM 1768#ifdef CONFIG_PM
1740/* Set the global behaviour of RX filters - On/Off + default action */ 1769/* Set the global behaviour of RX filters - On/Off + default action */
1741int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable, 1770int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable,
diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h
index 126536c6a393..6dcfad9b0472 100644
--- a/drivers/net/wireless/ti/wlcore/acx.h
+++ b/drivers/net/wireless/ti/wlcore/acx.h
@@ -728,8 +728,6 @@ struct wl1271_acx_ht_information {
728 u8 padding[2]; 728 u8 padding[2];
729} __packed; 729} __packed;
730 730
731#define RX_BA_MAX_SESSIONS 3
732
733struct wl1271_acx_ba_initiator_policy { 731struct wl1271_acx_ba_initiator_policy {
734 struct acx_header header; 732 struct acx_header header;
735 733
@@ -955,6 +953,18 @@ struct acx_rx_filter_cfg {
955 u8 fields[0]; 953 u8 fields[0];
956} __packed; 954} __packed;
957 955
956struct acx_roaming_stats {
957 struct acx_header header;
958
959 u8 role_id;
960 u8 pad[3];
961 u32 missed_beacons;
962 u8 snr_data;
963 u8 snr_bacon;
964 s8 rssi_data;
965 s8 rssi_beacon;
966} __packed;
967
958enum { 968enum {
959 ACX_WAKE_UP_CONDITIONS = 0x0000, 969 ACX_WAKE_UP_CONDITIONS = 0x0000,
960 ACX_MEM_CFG = 0x0001, 970 ACX_MEM_CFG = 0x0001,
@@ -1112,6 +1122,8 @@ int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
1112int wl1271_acx_fm_coex(struct wl1271 *wl); 1122int wl1271_acx_fm_coex(struct wl1271 *wl);
1113int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl); 1123int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl);
1114int wl12xx_acx_config_hangover(struct wl1271 *wl); 1124int wl12xx_acx_config_hangover(struct wl1271 *wl);
1125int wlcore_acx_average_rssi(struct wl1271 *wl, struct wl12xx_vif *wlvif,
1126 s8 *avg_rssi);
1115 1127
1116#ifdef CONFIG_PM 1128#ifdef CONFIG_PM
1117int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable, 1129int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable,
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index 6331f9e1cb39..c9e060795d13 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -327,6 +327,14 @@ int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
327 wl->links[link].prev_freed_pkts = 327 wl->links[link].prev_freed_pkts =
328 wl->fw_status_2->counters.tx_lnk_free_pkts[link]; 328 wl->fw_status_2->counters.tx_lnk_free_pkts[link];
329 wl->links[link].wlvif = wlvif; 329 wl->links[link].wlvif = wlvif;
330
331 /*
332 * Take saved value for total freed packets from wlvif, in case this is
333 * recovery/resume
334 */
335 if (wlvif->bss_type != BSS_TYPE_AP_BSS)
336 wl->links[link].total_freed_pkts = wlvif->total_freed_pkts;
337
330 *hlid = link; 338 *hlid = link;
331 339
332 wl->active_link_count++; 340 wl->active_link_count++;
@@ -358,6 +366,26 @@ void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
358 wl1271_tx_reset_link_queues(wl, *hlid); 366 wl1271_tx_reset_link_queues(wl, *hlid);
359 wl->links[*hlid].wlvif = NULL; 367 wl->links[*hlid].wlvif = NULL;
360 368
369 if (wlvif->bss_type == BSS_TYPE_STA_BSS ||
370 (wlvif->bss_type == BSS_TYPE_AP_BSS &&
371 *hlid == wlvif->ap.bcast_hlid)) {
372 /*
373 * save the total freed packets in the wlvif, in case this is
374 * recovery or suspend
375 */
376 wlvif->total_freed_pkts = wl->links[*hlid].total_freed_pkts;
377
378 /*
379 * increment the initial seq number on recovery to account for
380 * transmitted packets that we haven't yet got in the FW status
381 */
382 if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
383 wlvif->total_freed_pkts +=
384 WL1271_TX_SQN_POST_RECOVERY_PADDING;
385 }
386
387 wl->links[*hlid].total_freed_pkts = 0;
388
361 *hlid = WL12XX_INVALID_LINK_ID; 389 *hlid = WL12XX_INVALID_LINK_ID;
362 wl->active_link_count--; 390 wl->active_link_count--;
363 WARN_ON_ONCE(wl->active_link_count < 0); 391 WARN_ON_ONCE(wl->active_link_count < 0);
@@ -609,6 +637,10 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)
609 if (ret < 0) 637 if (ret < 0)
610 goto out_free_global; 638 goto out_free_global;
611 639
640 /* use the previous security seq, if this is a recovery/resume */
641 wl->links[wlvif->ap.bcast_hlid].total_freed_pkts =
642 wlvif->total_freed_pkts;
643
612 cmd->role_id = wlvif->role_id; 644 cmd->role_id = wlvif->role_id;
613 cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); 645 cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period);
614 cmd->ap.bss_index = WL1271_AP_BSS_INDEX; 646 cmd->ap.bss_index = WL1271_AP_BSS_INDEX;
diff --git a/drivers/net/wireless/ti/wlcore/debug.h b/drivers/net/wireless/ti/wlcore/debug.h
index db4bf5a68ce2..0420bd45e4ee 100644
--- a/drivers/net/wireless/ti/wlcore/debug.h
+++ b/drivers/net/wireless/ti/wlcore/debug.h
@@ -89,25 +89,24 @@ extern u32 wl12xx_debug_level;
89 } while (0) 89 } while (0)
90#endif 90#endif
91 91
92/* TODO: use pr_debug_hex_dump when it becomes available */ 92#define wl1271_dump(level, prefix, buf, len) \
93#define wl1271_dump(level, prefix, buf, len) \ 93 do { \
94 do { \ 94 if (level & wl12xx_debug_level) \
95 if (level & wl12xx_debug_level) \ 95 print_hex_dump_debug(DRIVER_PREFIX prefix, \
96 print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ 96 DUMP_PREFIX_OFFSET, 16, 1, \
97 DUMP_PREFIX_OFFSET, 16, 1, \ 97 buf, \
98 buf, \ 98 min_t(size_t, len, DEBUG_DUMP_LIMIT), \
99 min_t(size_t, len, DEBUG_DUMP_LIMIT), \ 99 0); \
100 0); \
101 } while (0) 100 } while (0)
102 101
103#define wl1271_dump_ascii(level, prefix, buf, len) \ 102#define wl1271_dump_ascii(level, prefix, buf, len) \
104 do { \ 103 do { \
105 if (level & wl12xx_debug_level) \ 104 if (level & wl12xx_debug_level) \
106 print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ 105 print_hex_dump_debug(DRIVER_PREFIX prefix, \
107 DUMP_PREFIX_OFFSET, 16, 1, \ 106 DUMP_PREFIX_OFFSET, 16, 1, \
108 buf, \ 107 buf, \
109 min_t(size_t, len, DEBUG_DUMP_LIMIT), \ 108 min_t(size_t, len, DEBUG_DUMP_LIMIT), \
110 true); \ 109 true); \
111 } while (0) 110 } while (0)
112 111
113#endif /* __DEBUG_H__ */ 112#endif /* __DEBUG_H__ */
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c
index e70a7c864865..c3e1f79c7856 100644
--- a/drivers/net/wireless/ti/wlcore/debugfs.c
+++ b/drivers/net/wireless/ti/wlcore/debugfs.c
@@ -598,8 +598,7 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
598 VIF_STATE_PRINT_INT(last_rssi_event); 598 VIF_STATE_PRINT_INT(last_rssi_event);
599 VIF_STATE_PRINT_INT(ba_support); 599 VIF_STATE_PRINT_INT(ba_support);
600 VIF_STATE_PRINT_INT(ba_allowed); 600 VIF_STATE_PRINT_INT(ba_allowed);
601 VIF_STATE_PRINT_LLHEX(tx_security_seq); 601 VIF_STATE_PRINT_LLHEX(total_freed_pkts);
602 VIF_STATE_PRINT_INT(tx_security_last_seq_lsb);
603 } 602 }
604 603
605#undef VIF_STATE_PRINT_INT 604#undef VIF_STATE_PRINT_INT
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c
index 70f289aa1bc6..67f61689b49e 100644
--- a/drivers/net/wireless/ti/wlcore/event.c
+++ b/drivers/net/wireless/ti/wlcore/event.c
@@ -237,6 +237,14 @@ void wlcore_event_beacon_loss(struct wl1271 *wl, unsigned long roles_bitmap)
237 !test_bit(wlvif->role_id , &roles_bitmap)) 237 !test_bit(wlvif->role_id , &roles_bitmap))
238 continue; 238 continue;
239 239
240 vif = wl12xx_wlvif_to_vif(wlvif);
241
242 /* don't attempt roaming in case of p2p */
243 if (wlvif->p2p) {
244 ieee80211_connection_loss(vif);
245 continue;
246 }
247
240 /* 248 /*
241 * if the work is already queued, it should take place. 249 * if the work is already queued, it should take place.
242 * We don't want to delay the connection loss 250 * We don't want to delay the connection loss
@@ -246,7 +254,6 @@ void wlcore_event_beacon_loss(struct wl1271 *wl, unsigned long roles_bitmap)
246 &wlvif->connection_loss_work, 254 &wlvif->connection_loss_work,
247 msecs_to_jiffies(delay)); 255 msecs_to_jiffies(delay));
248 256
249 vif = wl12xx_wlvif_to_vif(wlvif);
250 ieee80211_cqm_rssi_notify( 257 ieee80211_cqm_rssi_notify(
251 vif, 258 vif,
252 NL80211_CQM_RSSI_BEACON_LOSS_EVENT, 259 NL80211_CQM_RSSI_BEACON_LOSS_EVENT,
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index c26cb095010c..953111a502ee 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -108,8 +108,7 @@ static void wl1271_reg_notify(struct wiphy *wiphy,
108 108
109 } 109 }
110 110
111 if (likely(wl->state == WLCORE_STATE_ON)) 111 wlcore_regdomain_config(wl);
112 wlcore_regdomain_config(wl);
113} 112}
114 113
115static int wl1271_set_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, 114static int wl1271_set_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif,
@@ -332,10 +331,9 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl,
332 struct wl12xx_vif *wlvif, 331 struct wl12xx_vif *wlvif,
333 u8 hlid, u8 tx_pkts) 332 u8 hlid, u8 tx_pkts)
334{ 333{
335 bool fw_ps, single_link; 334 bool fw_ps;
336 335
337 fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); 336 fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
338 single_link = (wl->active_link_count == 1);
339 337
340 /* 338 /*
341 * Wake up from high level PS if the STA is asleep with too little 339 * Wake up from high level PS if the STA is asleep with too little
@@ -348,8 +346,13 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl,
348 * Start high-level PS if the STA is asleep with enough blocks in FW. 346 * Start high-level PS if the STA is asleep with enough blocks in FW.
349 * Make an exception if this is the only connected link. In this 347 * Make an exception if this is the only connected link. In this
350 * case FW-memory congestion is less of a problem. 348 * case FW-memory congestion is less of a problem.
349 * Note that a single connected STA means 3 active links, since we must
350 * account for the global and broadcast AP links. The "fw_ps" check
351 * assures us the third link is a STA connected to the AP. Otherwise
352 * the FW would not set the PSM bit.
351 */ 353 */
352 else if (!single_link && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) 354 else if (wl->active_link_count > 3 && fw_ps &&
355 tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
353 wl12xx_ps_link_start(wl, wlvif, hlid, true); 356 wl12xx_ps_link_start(wl, wlvif, hlid, true);
354} 357}
355 358
@@ -414,13 +417,21 @@ static int wlcore_fw_status(struct wl1271 *wl,
414 417
415 418
416 for_each_set_bit(i, wl->links_map, WL12XX_MAX_LINKS) { 419 for_each_set_bit(i, wl->links_map, WL12XX_MAX_LINKS) {
420 u8 diff;
417 lnk = &wl->links[i]; 421 lnk = &wl->links[i];
422
418 /* prevent wrap-around in freed-packets counter */ 423 /* prevent wrap-around in freed-packets counter */
419 lnk->allocated_pkts -= 424 diff = (status_2->counters.tx_lnk_free_pkts[i] -
420 (status_2->counters.tx_lnk_free_pkts[i] - 425 lnk->prev_freed_pkts) & 0xff;
421 lnk->prev_freed_pkts) & 0xff; 426
427 if (diff == 0)
428 continue;
422 429
430 lnk->allocated_pkts -= diff;
423 lnk->prev_freed_pkts = status_2->counters.tx_lnk_free_pkts[i]; 431 lnk->prev_freed_pkts = status_2->counters.tx_lnk_free_pkts[i];
432
433 /* accumulate the prev_freed_pkts counter */
434 lnk->total_freed_pkts += diff;
424 } 435 }
425 436
426 /* prevent wrap-around in total blocks counter */ 437 /* prevent wrap-around in total blocks counter */
@@ -640,6 +651,25 @@ static irqreturn_t wlcore_irq(int irq, void *cookie)
640 unsigned long flags; 651 unsigned long flags;
641 struct wl1271 *wl = cookie; 652 struct wl1271 *wl = cookie;
642 653
654 /* complete the ELP completion */
655 spin_lock_irqsave(&wl->wl_lock, flags);
656 set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
657 if (wl->elp_compl) {
658 complete(wl->elp_compl);
659 wl->elp_compl = NULL;
660 }
661
662 if (test_bit(WL1271_FLAG_SUSPENDED, &wl->flags)) {
663 /* don't enqueue a work right now. mark it as pending */
664 set_bit(WL1271_FLAG_PENDING_WORK, &wl->flags);
665 wl1271_debug(DEBUG_IRQ, "should not enqueue work");
666 disable_irq_nosync(wl->irq);
667 pm_wakeup_event(wl->dev, 0);
668 spin_unlock_irqrestore(&wl->wl_lock, flags);
669 return IRQ_HANDLED;
670 }
671 spin_unlock_irqrestore(&wl->wl_lock, flags);
672
643 /* TX might be handled here, avoid redundant work */ 673 /* TX might be handled here, avoid redundant work */
644 set_bit(WL1271_FLAG_TX_PENDING, &wl->flags); 674 set_bit(WL1271_FLAG_TX_PENDING, &wl->flags);
645 cancel_work_sync(&wl->tx_work); 675 cancel_work_sync(&wl->tx_work);
@@ -919,18 +949,6 @@ static void wl1271_recovery_work(struct work_struct *work)
919 goto out_unlock; 949 goto out_unlock;
920 } 950 }
921 951
922 /*
923 * Advance security sequence number to overcome potential progress
924 * in the firmware during recovery. This doens't hurt if the network is
925 * not encrypted.
926 */
927 wl12xx_for_each_wlvif(wl, wlvif) {
928 if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) ||
929 test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags))
930 wlvif->tx_security_seq +=
931 WL1271_TX_SQN_POST_RECOVERY_PADDING;
932 }
933
934 /* Prevent spurious TX during FW restart */ 952 /* Prevent spurious TX during FW restart */
935 wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_FW_RESTART); 953 wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_FW_RESTART);
936 954
@@ -2523,6 +2541,8 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
2523 wl1271_ps_elp_sleep(wl); 2541 wl1271_ps_elp_sleep(wl);
2524 } 2542 }
2525deinit: 2543deinit:
2544 wl12xx_tx_reset_wlvif(wl, wlvif);
2545
2526 /* clear all hlids (except system_hlid) */ 2546 /* clear all hlids (except system_hlid) */
2527 wlvif->dev_hlid = WL12XX_INVALID_LINK_ID; 2547 wlvif->dev_hlid = WL12XX_INVALID_LINK_ID;
2528 2548
@@ -2546,7 +2566,6 @@ deinit:
2546 2566
2547 dev_kfree_skb(wlvif->probereq); 2567 dev_kfree_skb(wlvif->probereq);
2548 wlvif->probereq = NULL; 2568 wlvif->probereq = NULL;
2549 wl12xx_tx_reset_wlvif(wl, wlvif);
2550 if (wl->last_wlvif == wlvif) 2569 if (wl->last_wlvif == wlvif)
2551 wl->last_wlvif = NULL; 2570 wl->last_wlvif = NULL;
2552 list_del(&wlvif->list); 2571 list_del(&wlvif->list);
@@ -2860,10 +2879,6 @@ static int wlcore_unset_assoc(struct wl1271 *wl, struct wl12xx_vif *wlvif)
2860 wlvif->sta.klv_template_id, 2879 wlvif->sta.klv_template_id,
2861 ACX_KEEP_ALIVE_TPL_INVALID); 2880 ACX_KEEP_ALIVE_TPL_INVALID);
2862 2881
2863 /* reset TX security counters on a clean disconnect */
2864 wlvif->tx_security_last_seq_lsb = 0;
2865 wlvif->tx_security_seq = 0;
2866
2867 return 0; 2882 return 0;
2868} 2883}
2869 2884
@@ -3262,6 +3277,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
3262 u32 tx_seq_32 = 0; 3277 u32 tx_seq_32 = 0;
3263 u16 tx_seq_16 = 0; 3278 u16 tx_seq_16 = 0;
3264 u8 key_type; 3279 u8 key_type;
3280 u8 hlid;
3265 3281
3266 wl1271_debug(DEBUG_MAC80211, "mac80211 set key"); 3282 wl1271_debug(DEBUG_MAC80211, "mac80211 set key");
3267 3283
@@ -3271,6 +3287,22 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
3271 key_conf->keylen, key_conf->flags); 3287 key_conf->keylen, key_conf->flags);
3272 wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen); 3288 wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen);
3273 3289
3290 if (wlvif->bss_type == BSS_TYPE_AP_BSS)
3291 if (sta) {
3292 struct wl1271_station *wl_sta = (void *)sta->drv_priv;
3293 hlid = wl_sta->hlid;
3294 } else {
3295 hlid = wlvif->ap.bcast_hlid;
3296 }
3297 else
3298 hlid = wlvif->sta.hlid;
3299
3300 if (hlid != WL12XX_INVALID_LINK_ID) {
3301 u64 tx_seq = wl->links[hlid].total_freed_pkts;
3302 tx_seq_32 = WL1271_TX_SECURITY_HI32(tx_seq);
3303 tx_seq_16 = WL1271_TX_SECURITY_LO16(tx_seq);
3304 }
3305
3274 switch (key_conf->cipher) { 3306 switch (key_conf->cipher) {
3275 case WLAN_CIPHER_SUITE_WEP40: 3307 case WLAN_CIPHER_SUITE_WEP40:
3276 case WLAN_CIPHER_SUITE_WEP104: 3308 case WLAN_CIPHER_SUITE_WEP104:
@@ -3280,22 +3312,14 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
3280 break; 3312 break;
3281 case WLAN_CIPHER_SUITE_TKIP: 3313 case WLAN_CIPHER_SUITE_TKIP:
3282 key_type = KEY_TKIP; 3314 key_type = KEY_TKIP;
3283
3284 key_conf->hw_key_idx = key_conf->keyidx; 3315 key_conf->hw_key_idx = key_conf->keyidx;
3285 tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq);
3286 tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq);
3287 break; 3316 break;
3288 case WLAN_CIPHER_SUITE_CCMP: 3317 case WLAN_CIPHER_SUITE_CCMP:
3289 key_type = KEY_AES; 3318 key_type = KEY_AES;
3290
3291 key_conf->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE; 3319 key_conf->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
3292 tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq);
3293 tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq);
3294 break; 3320 break;
3295 case WL1271_CIPHER_SUITE_GEM: 3321 case WL1271_CIPHER_SUITE_GEM:
3296 key_type = KEY_GEM; 3322 key_type = KEY_GEM;
3297 tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq);
3298 tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq);
3299 break; 3323 break;
3300 default: 3324 default:
3301 wl1271_error("Unknown key algo 0x%x", key_conf->cipher); 3325 wl1271_error("Unknown key algo 0x%x", key_conf->cipher);
@@ -3358,6 +3382,10 @@ void wlcore_regdomain_config(struct wl1271 *wl)
3358 return; 3382 return;
3359 3383
3360 mutex_lock(&wl->mutex); 3384 mutex_lock(&wl->mutex);
3385
3386 if (unlikely(wl->state != WLCORE_STATE_ON))
3387 goto out;
3388
3361 ret = wl1271_ps_elp_wakeup(wl); 3389 ret = wl1271_ps_elp_wakeup(wl);
3362 if (ret < 0) 3390 if (ret < 0)
3363 goto out; 3391 goto out;
@@ -4499,6 +4527,9 @@ static int wl1271_allocate_sta(struct wl1271 *wl,
4499 return -EBUSY; 4527 return -EBUSY;
4500 } 4528 }
4501 4529
4530 /* use the previous security seq, if this is a recovery/resume */
4531 wl->links[wl_sta->hlid].total_freed_pkts = wl_sta->total_freed_pkts;
4532
4502 set_bit(wl_sta->hlid, wlvif->ap.sta_hlid_map); 4533 set_bit(wl_sta->hlid, wlvif->ap.sta_hlid_map);
4503 memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN); 4534 memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN);
4504 wl->active_sta_count++; 4535 wl->active_sta_count++;
@@ -4507,12 +4538,37 @@ static int wl1271_allocate_sta(struct wl1271 *wl,
4507 4538
4508void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid) 4539void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid)
4509{ 4540{
4541 struct wl1271_station *wl_sta;
4542 struct ieee80211_sta *sta;
4543 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
4544
4510 if (!test_bit(hlid, wlvif->ap.sta_hlid_map)) 4545 if (!test_bit(hlid, wlvif->ap.sta_hlid_map))
4511 return; 4546 return;
4512 4547
4513 clear_bit(hlid, wlvif->ap.sta_hlid_map); 4548 clear_bit(hlid, wlvif->ap.sta_hlid_map);
4514 __clear_bit(hlid, &wl->ap_ps_map); 4549 __clear_bit(hlid, &wl->ap_ps_map);
4515 __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); 4550 __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
4551
4552 /*
4553 * save the last used PN in the private part of iee80211_sta,
4554 * in case of recovery/suspend
4555 */
4556 rcu_read_lock();
4557 sta = ieee80211_find_sta(vif, wl->links[hlid].addr);
4558 if (sta) {
4559 wl_sta = (void *)sta->drv_priv;
4560 wl_sta->total_freed_pkts = wl->links[hlid].total_freed_pkts;
4561
4562 /*
4563 * increment the initial seq number on recovery to account for
4564 * transmitted packets that we haven't yet got in the FW status
4565 */
4566 if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
4567 wl_sta->total_freed_pkts +=
4568 WL1271_TX_SQN_POST_RECOVERY_PADDING;
4569 }
4570 rcu_read_unlock();
4571
4516 wl12xx_free_link(wl, wlvif, &hlid); 4572 wl12xx_free_link(wl, wlvif, &hlid);
4517 wl->active_sta_count--; 4573 wl->active_sta_count--;
4518 4574
@@ -4616,13 +4672,11 @@ static int wl12xx_update_sta_state(struct wl1271 *wl,
4616 enum ieee80211_sta_state new_state) 4672 enum ieee80211_sta_state new_state)
4617{ 4673{
4618 struct wl1271_station *wl_sta; 4674 struct wl1271_station *wl_sta;
4619 u8 hlid;
4620 bool is_ap = wlvif->bss_type == BSS_TYPE_AP_BSS; 4675 bool is_ap = wlvif->bss_type == BSS_TYPE_AP_BSS;
4621 bool is_sta = wlvif->bss_type == BSS_TYPE_STA_BSS; 4676 bool is_sta = wlvif->bss_type == BSS_TYPE_STA_BSS;
4622 int ret; 4677 int ret;
4623 4678
4624 wl_sta = (struct wl1271_station *)sta->drv_priv; 4679 wl_sta = (struct wl1271_station *)sta->drv_priv;
4625 hlid = wl_sta->hlid;
4626 4680
4627 /* Add station (AP mode) */ 4681 /* Add station (AP mode) */
4628 if (is_ap && 4682 if (is_ap &&
@@ -4648,12 +4702,12 @@ static int wl12xx_update_sta_state(struct wl1271 *wl,
4648 /* Authorize station (AP mode) */ 4702 /* Authorize station (AP mode) */
4649 if (is_ap && 4703 if (is_ap &&
4650 new_state == IEEE80211_STA_AUTHORIZED) { 4704 new_state == IEEE80211_STA_AUTHORIZED) {
4651 ret = wl12xx_cmd_set_peer_state(wl, wlvif, hlid); 4705 ret = wl12xx_cmd_set_peer_state(wl, wlvif, wl_sta->hlid);
4652 if (ret < 0) 4706 if (ret < 0)
4653 return ret; 4707 return ret;
4654 4708
4655 ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true, 4709 ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true,
4656 hlid); 4710 wl_sta->hlid);
4657 if (ret) 4711 if (ret)
4658 return ret; 4712 return ret;
4659 4713
@@ -4784,7 +4838,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
4784 break; 4838 break;
4785 } 4839 }
4786 4840
4787 if (wl->ba_rx_session_count >= RX_BA_MAX_SESSIONS) { 4841 if (wl->ba_rx_session_count >= wl->ba_rx_session_count_max) {
4788 ret = -EBUSY; 4842 ret = -EBUSY;
4789 wl1271_error("exceeded max RX BA sessions"); 4843 wl1271_error("exceeded max RX BA sessions");
4790 break; 4844 break;
@@ -5092,6 +5146,39 @@ static void wlcore_op_sta_rc_update(struct ieee80211_hw *hw,
5092 wlcore_hw_sta_rc_update(wl, wlvif, sta, changed); 5146 wlcore_hw_sta_rc_update(wl, wlvif, sta, changed);
5093} 5147}
5094 5148
5149static int wlcore_op_get_rssi(struct ieee80211_hw *hw,
5150 struct ieee80211_vif *vif,
5151 struct ieee80211_sta *sta,
5152 s8 *rssi_dbm)
5153{
5154 struct wl1271 *wl = hw->priv;
5155 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
5156 int ret = 0;
5157
5158 wl1271_debug(DEBUG_MAC80211, "mac80211 get_rssi");
5159
5160 mutex_lock(&wl->mutex);
5161
5162 if (unlikely(wl->state != WLCORE_STATE_ON))
5163 goto out;
5164
5165 ret = wl1271_ps_elp_wakeup(wl);
5166 if (ret < 0)
5167 goto out_sleep;
5168
5169 ret = wlcore_acx_average_rssi(wl, wlvif, rssi_dbm);
5170 if (ret < 0)
5171 goto out_sleep;
5172
5173out_sleep:
5174 wl1271_ps_elp_sleep(wl);
5175
5176out:
5177 mutex_unlock(&wl->mutex);
5178
5179 return ret;
5180}
5181
5095static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) 5182static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
5096{ 5183{
5097 struct wl1271 *wl = hw->priv; 5184 struct wl1271 *wl = hw->priv;
@@ -5291,6 +5378,7 @@ static const struct ieee80211_ops wl1271_ops = {
5291 .assign_vif_chanctx = wlcore_op_assign_vif_chanctx, 5378 .assign_vif_chanctx = wlcore_op_assign_vif_chanctx,
5292 .unassign_vif_chanctx = wlcore_op_unassign_vif_chanctx, 5379 .unassign_vif_chanctx = wlcore_op_unassign_vif_chanctx,
5293 .sta_rc_update = wlcore_op_sta_rc_update, 5380 .sta_rc_update = wlcore_op_sta_rc_update,
5381 .get_rssi = wlcore_op_get_rssi,
5294 CFG80211_TESTMODE_CMD(wl1271_tm_cmd) 5382 CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
5295}; 5383};
5296 5384
@@ -5930,35 +6018,6 @@ int wlcore_free_hw(struct wl1271 *wl)
5930} 6018}
5931EXPORT_SYMBOL_GPL(wlcore_free_hw); 6019EXPORT_SYMBOL_GPL(wlcore_free_hw);
5932 6020
5933static irqreturn_t wl12xx_hardirq(int irq, void *cookie)
5934{
5935 struct wl1271 *wl = cookie;
5936 unsigned long flags;
5937
5938 wl1271_debug(DEBUG_IRQ, "IRQ");
5939
5940 /* complete the ELP completion */
5941 spin_lock_irqsave(&wl->wl_lock, flags);
5942 set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
5943 if (wl->elp_compl) {
5944 complete(wl->elp_compl);
5945 wl->elp_compl = NULL;
5946 }
5947
5948 if (test_bit(WL1271_FLAG_SUSPENDED, &wl->flags)) {
5949 /* don't enqueue a work right now. mark it as pending */
5950 set_bit(WL1271_FLAG_PENDING_WORK, &wl->flags);
5951 wl1271_debug(DEBUG_IRQ, "should not enqueue work");
5952 disable_irq_nosync(wl->irq);
5953 pm_wakeup_event(wl->dev, 0);
5954 spin_unlock_irqrestore(&wl->wl_lock, flags);
5955 return IRQ_HANDLED;
5956 }
5957 spin_unlock_irqrestore(&wl->wl_lock, flags);
5958
5959 return IRQ_WAKE_THREAD;
5960}
5961
5962static void wlcore_nvs_cb(const struct firmware *fw, void *context) 6021static void wlcore_nvs_cb(const struct firmware *fw, void *context)
5963{ 6022{
5964 struct wl1271 *wl = context; 6023 struct wl1271 *wl = context;
@@ -6000,9 +6059,8 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context)
6000 else 6059 else
6001 irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; 6060 irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT;
6002 6061
6003 ret = request_threaded_irq(wl->irq, wl12xx_hardirq, wlcore_irq, 6062 ret = request_threaded_irq(wl->irq, NULL, wlcore_irq,
6004 irqflags, 6063 irqflags, pdev->name, wl);
6005 pdev->name, wl);
6006 if (ret < 0) { 6064 if (ret < 0) {
6007 wl1271_error("request_irq() failed: %d", ret); 6065 wl1271_error("request_irq() failed: %d", ret);
6008 goto out_free_nvs; 6066 goto out_free_nvs;
diff --git a/drivers/net/wireless/ti/wlcore/ps.c b/drivers/net/wireless/ti/wlcore/ps.c
index 9b7b6e2e4fbc..9654577efd01 100644
--- a/drivers/net/wireless/ti/wlcore/ps.c
+++ b/drivers/net/wireless/ti/wlcore/ps.c
@@ -29,6 +29,7 @@
29#define WL1271_WAKEUP_TIMEOUT 500 29#define WL1271_WAKEUP_TIMEOUT 500
30 30
31#define ELP_ENTRY_DELAY 30 31#define ELP_ENTRY_DELAY 30
32#define ELP_ENTRY_DELAY_FORCE_PS 5
32 33
33void wl1271_elp_work(struct work_struct *work) 34void wl1271_elp_work(struct work_struct *work)
34{ 35{
@@ -98,7 +99,8 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
98 return; 99 return;
99 } 100 }
100 101
101 timeout = ELP_ENTRY_DELAY; 102 timeout = wl->conf.conn.forced_ps ?
103 ELP_ENTRY_DELAY_FORCE_PS : ELP_ENTRY_DELAY;
102 ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, 104 ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
103 msecs_to_jiffies(timeout)); 105 msecs_to_jiffies(timeout));
104} 106}
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
index ece392c54d9c..004d02e71f01 100644
--- a/drivers/net/wireless/ti/wlcore/tx.c
+++ b/drivers/net/wireless/ti/wlcore/tx.c
@@ -24,6 +24,7 @@
24#include <linux/kernel.h> 24#include <linux/kernel.h>
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/etherdevice.h> 26#include <linux/etherdevice.h>
27#include <linux/spinlock.h>
27 28
28#include "wlcore.h" 29#include "wlcore.h"
29#include "debug.h" 30#include "debug.h"
@@ -104,7 +105,7 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl,
104 struct wl12xx_vif *wlvif, 105 struct wl12xx_vif *wlvif,
105 u8 hlid) 106 u8 hlid)
106{ 107{
107 bool fw_ps, single_link; 108 bool fw_ps;
108 u8 tx_pkts; 109 u8 tx_pkts;
109 110
110 if (WARN_ON(!test_bit(hlid, wlvif->links_map))) 111 if (WARN_ON(!test_bit(hlid, wlvif->links_map)))
@@ -112,15 +113,19 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl,
112 113
113 fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); 114 fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
114 tx_pkts = wl->links[hlid].allocated_pkts; 115 tx_pkts = wl->links[hlid].allocated_pkts;
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 link. In this 120 * Make an exception if this is the only connected link. In this
121 * case FW-memory congestion is less of a problem. 121 * case FW-memory congestion is less of a problem.
122 * Note that a single connected STA means 3 active links, since we must
123 * account for the global and broadcast AP links. The "fw_ps" check
124 * assures us the third link is a STA connected to the AP. Otherwise
125 * the FW would not set the PSM bit.
122 */ 126 */
123 if (!single_link && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) 127 if (wl->active_link_count > 3 && fw_ps &&
128 tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
124 wl12xx_ps_link_start(wl, wlvif, hlid, true); 129 wl12xx_ps_link_start(wl, wlvif, hlid, true);
125} 130}
126 131
@@ -639,6 +644,7 @@ next:
639 644
640 } 645 }
641 646
647out:
642 if (!skb && 648 if (!skb &&
643 test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) { 649 test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) {
644 int q; 650 int q;
@@ -652,7 +658,6 @@ next:
652 spin_unlock_irqrestore(&wl->wl_lock, flags); 658 spin_unlock_irqrestore(&wl->wl_lock, flags);
653 } 659 }
654 660
655out:
656 return skb; 661 return skb;
657} 662}
658 663
@@ -928,25 +933,6 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
928 933
929 wl->stats.retry_count += result->ack_failures; 934 wl->stats.retry_count += result->ack_failures;
930 935
931 /*
932 * update sequence number only when relevant, i.e. only in
933 * sessions of TKIP, AES and GEM (not in open or WEP sessions)
934 */
935 if (info->control.hw_key &&
936 (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP ||
937 info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP ||
938 info->control.hw_key->cipher == WL1271_CIPHER_SUITE_GEM)) {
939 u8 fw_lsb = result->tx_security_sequence_number_lsb;
940 u8 cur_lsb = wlvif->tx_security_last_seq_lsb;
941
942 /*
943 * update security sequence number, taking care of potential
944 * wrap-around
945 */
946 wlvif->tx_security_seq += (fw_lsb - cur_lsb) & 0xff;
947 wlvif->tx_security_last_seq_lsb = fw_lsb;
948 }
949
950 /* remove private header from packet */ 936 /* remove private header from packet */
951 skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); 937 skb_pull(skb, sizeof(struct wl1271_tx_hw_descr));
952 938
@@ -1061,7 +1047,8 @@ void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif)
1061 1047
1062 /* TX failure */ 1048 /* TX failure */
1063 for_each_set_bit(i, wlvif->links_map, WL12XX_MAX_LINKS) { 1049 for_each_set_bit(i, wlvif->links_map, WL12XX_MAX_LINKS) {
1064 if (wlvif->bss_type == BSS_TYPE_AP_BSS) { 1050 if (wlvif->bss_type == BSS_TYPE_AP_BSS &&
1051 i != wlvif->ap.bcast_hlid && i != wlvif->ap.global_hlid) {
1065 /* this calls wl12xx_free_link */ 1052 /* this calls wl12xx_free_link */
1066 wl1271_free_sta(wl, wlvif, i); 1053 wl1271_free_sta(wl, wlvif, i);
1067 } else { 1054 } else {
@@ -1304,7 +1291,7 @@ bool wlcore_is_queue_stopped_by_reason_locked(struct wl1271 *wl,
1304{ 1291{
1305 int hwq = wlcore_tx_get_mac80211_queue(wlvif, queue); 1292 int hwq = wlcore_tx_get_mac80211_queue(wlvif, queue);
1306 1293
1307 WARN_ON_ONCE(!spin_is_locked(&wl->wl_lock)); 1294 assert_spin_locked(&wl->wl_lock);
1308 return test_bit(reason, &wl->queue_stop_reasons[hwq]); 1295 return test_bit(reason, &wl->queue_stop_reasons[hwq]);
1309} 1296}
1310 1297
@@ -1313,6 +1300,6 @@ bool wlcore_is_queue_stopped_locked(struct wl1271 *wl, struct wl12xx_vif *wlvif,
1313{ 1300{
1314 int hwq = wlcore_tx_get_mac80211_queue(wlvif, queue); 1301 int hwq = wlcore_tx_get_mac80211_queue(wlvif, queue);
1315 1302
1316 WARN_ON_ONCE(!spin_is_locked(&wl->wl_lock)); 1303 assert_spin_locked(&wl->wl_lock);
1317 return !!wl->queue_stop_reasons[hwq]; 1304 return !!wl->queue_stop_reasons[hwq];
1318} 1305}
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index af9fecaefc30..0034979e97cb 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -390,6 +390,9 @@ struct wl1271 {
390 /* number of currently active RX BA sessions */ 390 /* number of currently active RX BA sessions */
391 int ba_rx_session_count; 391 int ba_rx_session_count;
392 392
393 /* Maximum number of supported RX BA sessions */
394 int ba_rx_session_count_max;
395
393 /* AP-mode - number of currently connected stations */ 396 /* AP-mode - number of currently connected stations */
394 int active_sta_count; 397 int active_sta_count;
395 398
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index 508f5b0f8a70..e5e146435fe7 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -274,6 +274,13 @@ struct wl1271_link {
274 274
275 /* The wlvif this link belongs to. Might be null for global links */ 275 /* The wlvif this link belongs to. Might be null for global links */
276 struct wl12xx_vif *wlvif; 276 struct wl12xx_vif *wlvif;
277
278 /*
279 * total freed FW packets on the link - used for tracking the
280 * AES/TKIP PN across recoveries. Re-initialized each time
281 * from the wl1271_station structure.
282 */
283 u64 total_freed_pkts;
277}; 284};
278 285
279#define WL1271_MAX_RX_FILTERS 5 286#define WL1271_MAX_RX_FILTERS 5
@@ -318,6 +325,13 @@ struct wl12xx_rx_filter {
318struct wl1271_station { 325struct wl1271_station {
319 u8 hlid; 326 u8 hlid;
320 bool in_connection; 327 bool in_connection;
328
329 /*
330 * total freed FW packets on the link to the STA - used for tracking the
331 * AES/TKIP PN across recoveries. Re-initialized each time from the
332 * wl1271_station structure.
333 */
334 u64 total_freed_pkts;
321}; 335};
322 336
323struct wl12xx_vif { 337struct wl12xx_vif {
@@ -449,16 +463,15 @@ struct wl12xx_vif {
449 */ 463 */
450 struct { 464 struct {
451 u8 persistent[0]; 465 u8 persistent[0];
466
452 /* 467 /*
453 * Security sequence number 468 * total freed FW packets on the link - used for
454 * bits 0-15: lower 16 bits part of sequence number 469 * storing the AES/TKIP PN during recovery, as this
455 * bits 16-47: higher 32 bits part of sequence number 470 * structure is not zeroed out.
456 * bits 48-63: not in use 471 * For STA this holds the PN of the link to the AP.
472 * For AP this holds the PN of the broadcast link.
457 */ 473 */
458 u64 tx_security_seq; 474 u64 total_freed_pkts;
459
460 /* 8 bits of the last sequence number in use */
461 u8 tx_security_last_seq_lsb;
462 }; 475 };
463}; 476};
464 477