aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/intel/iwlwifi/mvm
diff options
context:
space:
mode:
authorSara Sharon <sara.sharon@intel.com>2015-12-29 04:07:15 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2016-02-01 09:40:22 -0500
commit0db056d32490181be48efc2ca7cfa7494b13e6b5 (patch)
tree76e3ba5172c16b09412d02e56b6ac8337ec0bc8b /drivers/net/wireless/intel/iwlwifi/mvm
parent7869318e4296e27d4cb97505e8739d62b48b2d58 (diff)
iwlwifi: mvm: support beacon storing
Currently firmware is configured to filter out beacons. In case a beacon was changed - it is waking the host. However, some vendors change their IEs frequently without any significant change, and redundant wakeups are triggered as a result. As a solution disable beacon filtering when entering d0i3. Instead, firmware will store the latest beacon and upon exiting d0i3 it will send it up to the host, so the host can act upon changes (if there were any). This beacon will arrive as a dedicated notification - support it as well. Signed-off-by: Sara Sharon <sara.sharon@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/d3.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h29
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c41
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c22
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/power.c33
7 files changed, 117 insertions, 14 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index 78572ef89b26..346376187ef8 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -853,7 +853,8 @@ iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm,
853 wowlan_config_cmd->is_11n_connection = 853 wowlan_config_cmd->is_11n_connection =
854 ap_sta->ht_cap.ht_supported; 854 ap_sta->ht_cap.ht_supported;
855 wowlan_config_cmd->flags = ENABLE_L3_FILTERING | 855 wowlan_config_cmd->flags = ENABLE_L3_FILTERING |
856 ENABLE_NBNS_FILTERING | ENABLE_DHCP_FILTERING; 856 ENABLE_NBNS_FILTERING | ENABLE_DHCP_FILTERING |
857 ENABLE_STORE_BEACON;
857 858
858 /* Query the last used seqno and set it */ 859 /* Query the last used seqno and set it */
859 ret = iwl_mvm_get_last_nonqos_seq(mvm, vif); 860 ret = iwl_mvm_get_last_nonqos_seq(mvm, vif);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h
index 62b9a0a96700..eec52c57f718 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h
@@ -251,6 +251,7 @@ enum iwl_wowlan_flags {
251 ENABLE_L3_FILTERING = BIT(1), 251 ENABLE_L3_FILTERING = BIT(1),
252 ENABLE_NBNS_FILTERING = BIT(2), 252 ENABLE_NBNS_FILTERING = BIT(2),
253 ENABLE_DHCP_FILTERING = BIT(3), 253 ENABLE_DHCP_FILTERING = BIT(3),
254 ENABLE_STORE_BEACON = BIT(4),
254}; 255};
255 256
256struct iwl_wowlan_config_cmd { 257struct iwl_wowlan_config_cmd {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
index 82049bb139c2..b6b57273b8ba 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
@@ -280,11 +280,16 @@ enum iwl_phy_ops_subcmd_ids {
280 DTS_MEASUREMENT_NOTIF_WIDE = 0xFF, 280 DTS_MEASUREMENT_NOTIF_WIDE = 0xFF,
281}; 281};
282 282
283enum iwl_prot_offload_subcmd_ids {
284 STORED_BEACON_NTF = 0xFF,
285};
286
283/* command groups */ 287/* command groups */
284enum { 288enum {
285 LEGACY_GROUP = 0x0, 289 LEGACY_GROUP = 0x0,
286 LONG_GROUP = 0x1, 290 LONG_GROUP = 0x1,
287 PHY_OPS_GROUP = 0x4, 291 PHY_OPS_GROUP = 0x4,
292 PROT_OFFLOAD_GROUP = 0xb,
288}; 293};
289 294
290/** 295/**
@@ -1851,4 +1856,28 @@ struct iwl_shared_mem_cfg {
1851 __le32 page_buff_size; 1856 __le32 page_buff_size;
1852} __packed; /* SHARED_MEM_ALLOC_API_S_VER_1 */ 1857} __packed; /* SHARED_MEM_ALLOC_API_S_VER_1 */
1853 1858
1859#define MAX_STORED_BEACON_SIZE 600
1860
1861/**
1862 * Stored beacon notification
1863 *
1864 * @system_time: system time on air rise
1865 * @tsf: TSF on air rise
1866 * @beacon_timestamp: beacon on air rise
1867 * @phy_flags: general phy flags: band, modulation, etc.
1868 * @channel: channel this beacon was received on
1869 * @rates: rate in ucode internal format
1870 * @byte_count: frame's byte count
1871 */
1872struct iwl_stored_beacon_notif {
1873 __le32 system_time;
1874 __le64 tsf;
1875 __le32 beacon_timestamp;
1876 __le16 phy_flags;
1877 __le16 channel;
1878 __le32 rates;
1879 __le32 byte_count;
1880 u8 data[MAX_STORED_BEACON_SIZE];
1881} __packed; /* WOWLAN_STROED_BEACON_INFO_S_VER_1 */
1882
1854#endif /* __fw_api_h__ */ 1883#endif /* __fw_api_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index bf1e5eb5dbdb..62927f567afc 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -7,7 +7,7 @@
7 * 7 *
8 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. 8 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
9 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH 9 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
10 * Copyright(c) 2015 Intel Deutschland GmbH 10 * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
11 * 11 *
12 * This program is free software; you can redistribute it and/or modify 12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of version 2 of the GNU General Public License as 13 * it under the terms of version 2 of the GNU General Public License as
@@ -34,7 +34,7 @@
34 * 34 *
35 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. 35 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
36 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH 36 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
37 * Copyright(c) 2015 Intel Deutschland GmbH 37 * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
38 * All rights reserved. 38 * All rights reserved.
39 * 39 *
40 * Redistribution and use in source and binary forms, with or without 40 * Redistribution and use in source and binary forms, with or without
@@ -1462,3 +1462,40 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
1462 iwl_mvm_beacon_loss_iterator, 1462 iwl_mvm_beacon_loss_iterator,
1463 mb); 1463 mb);
1464} 1464}
1465
1466void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm,
1467 struct iwl_rx_cmd_buffer *rxb)
1468{
1469 struct iwl_rx_packet *pkt = rxb_addr(rxb);
1470 struct iwl_stored_beacon_notif *sb = (void *)pkt->data;
1471 struct ieee80211_rx_status rx_status;
1472 struct sk_buff *skb;
1473 u32 size = le32_to_cpu(sb->byte_count);
1474
1475 if (size == 0)
1476 return;
1477
1478 skb = alloc_skb(size, GFP_ATOMIC);
1479 if (!skb) {
1480 IWL_ERR(mvm, "alloc_skb failed\n");
1481 return;
1482 }
1483
1484 /* update rx_status according to the notification's metadata */
1485 memset(&rx_status, 0, sizeof(rx_status));
1486 rx_status.mactime = le64_to_cpu(sb->tsf);
1487 rx_status.device_timestamp = le32_to_cpu(sb->system_time);
1488 rx_status.band =
1489 (sb->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_BAND_24)) ?
1490 IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
1491 rx_status.freq =
1492 ieee80211_channel_to_frequency(le16_to_cpu(sb->channel),
1493 rx_status.band);
1494
1495 /* copy the data */
1496 memcpy(skb_put(skb, size), sb->data, size);
1497 memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
1498
1499 /* pass it as regular rx to mac80211 */
1500 ieee80211_rx_napi(mvm->hw, skb, NULL);
1501}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 216c8d6275a1..b45cf4f63781 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1192,6 +1192,8 @@ void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
1192 struct iwl_rx_cmd_buffer *rxb); 1192 struct iwl_rx_cmd_buffer *rxb);
1193void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, 1193void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
1194 struct iwl_rx_cmd_buffer *rxb); 1194 struct iwl_rx_cmd_buffer *rxb);
1195void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm,
1196 struct iwl_rx_cmd_buffer *rxb);
1195void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm, 1197void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm,
1196 struct ieee80211_vif *vif); 1198 struct ieee80211_vif *vif);
1197unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm, 1199unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 6bf2bde239a0..3c869ad6aaec 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -33,6 +33,7 @@
33 * 33 *
34 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. 34 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
35 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH 35 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
36 * Copyright(c) 2016 Intel Deutschland GmbH
36 * All rights reserved. 37 * All rights reserved.
37 * 38 *
38 * Redistribution and use in source and binary forms, with or without 39 * Redistribution and use in source and binary forms, with or without
@@ -267,6 +268,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
267 true), 268 true),
268 RX_HANDLER(MFUART_LOAD_NOTIFICATION, iwl_mvm_rx_mfuart_notif, false), 269 RX_HANDLER(MFUART_LOAD_NOTIFICATION, iwl_mvm_rx_mfuart_notif, false),
269 RX_HANDLER(TOF_NOTIFICATION, iwl_mvm_tof_resp_handler, true), 270 RX_HANDLER(TOF_NOTIFICATION, iwl_mvm_tof_resp_handler, true),
271 RX_HANDLER_GRP(PROT_OFFLOAD_GROUP, STORED_BEACON_NTF,
272 iwl_mvm_rx_stored_beacon_notif, false),
270 273
271}; 274};
272#undef RX_HANDLER 275#undef RX_HANDLER
@@ -386,10 +389,18 @@ static const struct iwl_hcmd_names iwl_mvm_phy_names[] = {
386 HCMD_NAME(DTS_MEASUREMENT_NOTIF_WIDE), 389 HCMD_NAME(DTS_MEASUREMENT_NOTIF_WIDE),
387}; 390};
388 391
392/* Please keep this array *SORTED* by hex value.
393 * Access is done through binary search
394 */
395static const struct iwl_hcmd_names iwl_mvm_prot_offload_names[] = {
396 HCMD_NAME(STORED_BEACON_NTF),
397};
398
389static const struct iwl_hcmd_arr iwl_mvm_groups[] = { 399static const struct iwl_hcmd_arr iwl_mvm_groups[] = {
390 [LEGACY_GROUP] = HCMD_ARR(iwl_mvm_legacy_names), 400 [LEGACY_GROUP] = HCMD_ARR(iwl_mvm_legacy_names),
391 [LONG_GROUP] = HCMD_ARR(iwl_mvm_legacy_names), 401 [LONG_GROUP] = HCMD_ARR(iwl_mvm_legacy_names),
392 [PHY_OPS_GROUP] = HCMD_ARR(iwl_mvm_phy_names), 402 [PHY_OPS_GROUP] = HCMD_ARR(iwl_mvm_phy_names),
403 [PROT_OFFLOAD_GROUP] = HCMD_ARR(iwl_mvm_prot_offload_names),
393}; 404};
394 405
395/* this forward declaration can avoid to export the function */ 406/* this forward declaration can avoid to export the function */
@@ -1195,7 +1206,7 @@ static void iwl_mvm_set_wowlan_data(struct iwl_mvm *mvm,
1195 cmd->is_11n_connection = ap_sta->ht_cap.ht_supported; 1206 cmd->is_11n_connection = ap_sta->ht_cap.ht_supported;
1196 cmd->offloading_tid = iter_data->offloading_tid; 1207 cmd->offloading_tid = iter_data->offloading_tid;
1197 cmd->flags = ENABLE_L3_FILTERING | ENABLE_NBNS_FILTERING | 1208 cmd->flags = ENABLE_L3_FILTERING | ENABLE_NBNS_FILTERING |
1198 ENABLE_DHCP_FILTERING; 1209 ENABLE_DHCP_FILTERING | ENABLE_STORE_BEACON;
1199 /* 1210 /*
1200 * The d0i3 uCode takes care of the nonqos counters, 1211 * The d0i3 uCode takes care of the nonqos counters,
1201 * so configure only the qos seq ones. 1212 * so configure only the qos seq ones.
@@ -1216,8 +1227,7 @@ int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode)
1216 struct iwl_wowlan_config_cmd wowlan_config_cmd = { 1227 struct iwl_wowlan_config_cmd wowlan_config_cmd = {
1217 .wakeup_filter = cpu_to_le32(IWL_WOWLAN_WAKEUP_RX_FRAME | 1228 .wakeup_filter = cpu_to_le32(IWL_WOWLAN_WAKEUP_RX_FRAME |
1218 IWL_WOWLAN_WAKEUP_BEACON_MISS | 1229 IWL_WOWLAN_WAKEUP_BEACON_MISS |
1219 IWL_WOWLAN_WAKEUP_LINK_CHANGE | 1230 IWL_WOWLAN_WAKEUP_LINK_CHANGE),
1220 IWL_WOWLAN_WAKEUP_BCN_FILTERING),
1221 }; 1231 };
1222 struct iwl_d3_manager_config d3_cfg_cmd = { 1232 struct iwl_d3_manager_config d3_cfg_cmd = {
1223 .min_sleep_time = cpu_to_le32(1000), 1233 .min_sleep_time = cpu_to_le32(1000),
@@ -1267,6 +1277,12 @@ int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode)
1267 1277
1268 /* configure wowlan configuration only if needed */ 1278 /* configure wowlan configuration only if needed */
1269 if (mvm->d0i3_ap_sta_id != IWL_MVM_STATION_COUNT) { 1279 if (mvm->d0i3_ap_sta_id != IWL_MVM_STATION_COUNT) {
1280 /* wake on beacons only if beacon storing isn't supported */
1281 if (!fw_has_capa(&mvm->fw->ucode_capa,
1282 IWL_UCODE_TLV_CAPA_BEACON_STORING))
1283 wowlan_config_cmd.wakeup_filter |=
1284 cpu_to_le32(IWL_WOWLAN_WAKEUP_BCN_FILTERING);
1285
1270 iwl_mvm_wowlan_config_key_params(mvm, 1286 iwl_mvm_wowlan_config_key_params(mvm,
1271 d0i3_iter_data.connected_vif, 1287 d0i3_iter_data.connected_vif,
1272 true, flags); 1288 true, flags);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c
index 16b3e36fb1ba..0d03b3e3cf4e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c
@@ -7,7 +7,7 @@
7 * 7 *
8 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. 8 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
9 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH 9 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
10 * Copyright(c) 2015 Intel Deutschland GmbH 10 * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
11 * 11 *
12 * This program is free software; you can redistribute it and/or modify 12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of version 2 of the GNU General Public License as 13 * it under the terms of version 2 of the GNU General Public License as
@@ -34,7 +34,7 @@
34 * 34 *
35 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. 35 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
36 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH 36 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
37 * Copyright(c) 2015 Intel Deutschland GmbH 37 * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
38 * All rights reserved. 38 * All rights reserved.
39 * 39 *
40 * Redistribution and use in source and binary forms, with or without 40 * Redistribution and use in source and binary forms, with or without
@@ -903,9 +903,9 @@ static int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,
903 return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0, false); 903 return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0, false);
904} 904}
905 905
906int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, 906static int _iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
907 struct ieee80211_vif *vif, 907 struct ieee80211_vif *vif,
908 u32 flags) 908 u32 flags, bool d0i3)
909{ 909{
910 struct iwl_beacon_filter_cmd cmd = {}; 910 struct iwl_beacon_filter_cmd cmd = {};
911 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 911 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -916,12 +916,20 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
916 916
917 ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, flags); 917 ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, flags);
918 918
919 if (!ret) 919 /* don't change bf_enabled in case of temporary d0i3 configuration */
920 if (!ret && !d0i3)
920 mvmvif->bf_data.bf_enabled = false; 921 mvmvif->bf_data.bf_enabled = false;
921 922
922 return ret; 923 return ret;
923} 924}
924 925
926int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
927 struct ieee80211_vif *vif,
928 u32 flags)
929{
930 return _iwl_mvm_disable_beacon_filter(mvm, vif, flags, false);
931}
932
925static int iwl_mvm_power_set_ps(struct iwl_mvm *mvm) 933static int iwl_mvm_power_set_ps(struct iwl_mvm *mvm)
926{ 934{
927 bool disable_ps; 935 bool disable_ps;
@@ -1058,8 +1066,17 @@ int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm,
1058 IWL_BF_CMD_CONFIG_D0I3, 1066 IWL_BF_CMD_CONFIG_D0I3,
1059 .bf_enable_beacon_filter = cpu_to_le32(1), 1067 .bf_enable_beacon_filter = cpu_to_le32(1),
1060 }; 1068 };
1061 ret = _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd_bf, 1069 /*
1062 flags, true); 1070 * When beacon storing is supported - disable beacon filtering
1071 * altogether - the latest beacon will be sent when exiting d0i3
1072 */
1073 if (fw_has_capa(&mvm->fw->ucode_capa,
1074 IWL_UCODE_TLV_CAPA_BEACON_STORING))
1075 ret = _iwl_mvm_disable_beacon_filter(mvm, vif, flags,
1076 true);
1077 else
1078 ret = _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd_bf,
1079 flags, true);
1063 } else { 1080 } else {
1064 if (mvmvif->bf_data.bf_enabled) 1081 if (mvmvif->bf_data.bf_enabled)
1065 ret = iwl_mvm_enable_beacon_filter(mvm, vif, flags); 1082 ret = iwl_mvm_enable_beacon_filter(mvm, vif, flags);