diff options
Diffstat (limited to 'drivers/net/wireless/intel')
20 files changed, 184 insertions, 74 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/Kconfig b/drivers/net/wireless/intel/iwlwifi/Kconfig index c5f2ddf9b0fe..e5a2fc738ac3 100644 --- a/drivers/net/wireless/intel/iwlwifi/Kconfig +++ b/drivers/net/wireless/intel/iwlwifi/Kconfig | |||
@@ -91,7 +91,6 @@ config IWLWIFI_BCAST_FILTERING | |||
91 | config IWLWIFI_PCIE_RTPM | 91 | config IWLWIFI_PCIE_RTPM |
92 | bool "Enable runtime power management mode for PCIe devices" | 92 | bool "Enable runtime power management mode for PCIe devices" |
93 | depends on IWLMVM && PM && EXPERT | 93 | depends on IWLMVM && PM && EXPERT |
94 | default false | ||
95 | help | 94 | help |
96 | Say Y here to enable runtime power management for PCIe | 95 | Say Y here to enable runtime power management for PCIe |
97 | devices. If enabled, the device will go into low power mode | 96 | devices. If enabled, the device will go into low power mode |
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h b/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h index 3721a3ed358b..f824bebceb06 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h | |||
@@ -211,7 +211,7 @@ enum { | |||
211 | * @TE_V2_NOTIF_HOST_FRAG_END:request/receive notification on frag end | 211 | * @TE_V2_NOTIF_HOST_FRAG_END:request/receive notification on frag end |
212 | * @TE_V2_NOTIF_INTERNAL_FRAG_START: internal FW use. | 212 | * @TE_V2_NOTIF_INTERNAL_FRAG_START: internal FW use. |
213 | * @TE_V2_NOTIF_INTERNAL_FRAG_END: internal FW use. | 213 | * @TE_V2_NOTIF_INTERNAL_FRAG_END: internal FW use. |
214 | * @T2_V2_START_IMMEDIATELY: start time event immediately | 214 | * @TE_V2_START_IMMEDIATELY: start time event immediately |
215 | * @TE_V2_DEP_OTHER: depends on another time event | 215 | * @TE_V2_DEP_OTHER: depends on another time event |
216 | * @TE_V2_DEP_TSF: depends on a specific time | 216 | * @TE_V2_DEP_TSF: depends on a specific time |
217 | * @TE_V2_EVENT_SOCIOPATHIC: can't co-exist with other events of tha same MAC | 217 | * @TE_V2_EVENT_SOCIOPATHIC: can't co-exist with other events of tha same MAC |
@@ -230,7 +230,7 @@ enum iwl_time_event_policy { | |||
230 | TE_V2_NOTIF_HOST_FRAG_END = BIT(5), | 230 | TE_V2_NOTIF_HOST_FRAG_END = BIT(5), |
231 | TE_V2_NOTIF_INTERNAL_FRAG_START = BIT(6), | 231 | TE_V2_NOTIF_INTERNAL_FRAG_START = BIT(6), |
232 | TE_V2_NOTIF_INTERNAL_FRAG_END = BIT(7), | 232 | TE_V2_NOTIF_INTERNAL_FRAG_END = BIT(7), |
233 | T2_V2_START_IMMEDIATELY = BIT(11), | 233 | TE_V2_START_IMMEDIATELY = BIT(11), |
234 | 234 | ||
235 | /* placement characteristics */ | 235 | /* placement characteristics */ |
236 | TE_V2_DEP_OTHER = BIT(TE_V2_PLACEMENT_POS), | 236 | TE_V2_DEP_OTHER = BIT(TE_V2_PLACEMENT_POS), |
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 67aefc8fc9ac..7bd704a3e640 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
10 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH |
11 | * Copyright(c) 2018 Intel Corporation | ||
11 | * | 12 | * |
12 | * This program is free software; you can redistribute it and/or modify | 13 | * 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 | 14 | * it under the terms of version 2 of the GNU General Public License as |
@@ -33,6 +34,7 @@ | |||
33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. | 34 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
34 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 35 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
35 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH | 36 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH |
37 | * Copyright(c) 2018 Intel Corporation | ||
36 | * All rights reserved. | 38 | * All rights reserved. |
37 | * | 39 | * |
38 | * Redistribution and use in source and binary forms, with or without | 40 | * Redistribution and use in source and binary forms, with or without |
@@ -942,7 +944,6 @@ dump_trans_data: | |||
942 | 944 | ||
943 | out: | 945 | out: |
944 | iwl_fw_free_dump_desc(fwrt); | 946 | iwl_fw_free_dump_desc(fwrt); |
945 | fwrt->dump.trig = NULL; | ||
946 | clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status); | 947 | clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status); |
947 | IWL_DEBUG_INFO(fwrt, "WRT dump done\n"); | 948 | IWL_DEBUG_INFO(fwrt, "WRT dump done\n"); |
948 | } | 949 | } |
@@ -1112,6 +1113,14 @@ void iwl_fw_error_dump_wk(struct work_struct *work) | |||
1112 | fwrt->ops->dump_start(fwrt->ops_ctx)) | 1113 | fwrt->ops->dump_start(fwrt->ops_ctx)) |
1113 | return; | 1114 | return; |
1114 | 1115 | ||
1116 | if (fwrt->ops && fwrt->ops->fw_running && | ||
1117 | !fwrt->ops->fw_running(fwrt->ops_ctx)) { | ||
1118 | IWL_ERR(fwrt, "Firmware not running - cannot dump error\n"); | ||
1119 | iwl_fw_free_dump_desc(fwrt); | ||
1120 | clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status); | ||
1121 | goto out; | ||
1122 | } | ||
1123 | |||
1115 | if (fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) { | 1124 | if (fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) { |
1116 | /* stop recording */ | 1125 | /* stop recording */ |
1117 | iwl_fw_dbg_stop_recording(fwrt); | 1126 | iwl_fw_dbg_stop_recording(fwrt); |
@@ -1145,7 +1154,7 @@ void iwl_fw_error_dump_wk(struct work_struct *work) | |||
1145 | iwl_write_prph(fwrt->trans, DBGC_OUT_CTRL, out_ctrl); | 1154 | iwl_write_prph(fwrt->trans, DBGC_OUT_CTRL, out_ctrl); |
1146 | } | 1155 | } |
1147 | } | 1156 | } |
1148 | 1157 | out: | |
1149 | if (fwrt->ops && fwrt->ops->dump_end) | 1158 | if (fwrt->ops && fwrt->ops->dump_end) |
1150 | fwrt->ops->dump_end(fwrt->ops_ctx); | 1159 | fwrt->ops->dump_end(fwrt->ops_ctx); |
1151 | } | 1160 | } |
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index 223fb77a3aa9..72259bff9922 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h | |||
@@ -8,6 +8,7 @@ | |||
8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
10 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH |
11 | * Copyright(c) 2018 Intel Corporation | ||
11 | * | 12 | * |
12 | * This program is free software; you can redistribute it and/or modify | 13 | * 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 | 14 | * it under the terms of version 2 of the GNU General Public License as |
@@ -33,6 +34,7 @@ | |||
33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. | 34 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
34 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 35 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
35 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH | 36 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH |
37 | * Copyright(c) 2018 Intel Corporation | ||
36 | * All rights reserved. | 38 | * All rights reserved. |
37 | * | 39 | * |
38 | * Redistribution and use in source and binary forms, with or without | 40 | * Redistribution and use in source and binary forms, with or without |
@@ -91,6 +93,7 @@ static inline void iwl_fw_free_dump_desc(struct iwl_fw_runtime *fwrt) | |||
91 | if (fwrt->dump.desc != &iwl_dump_desc_assert) | 93 | if (fwrt->dump.desc != &iwl_dump_desc_assert) |
92 | kfree(fwrt->dump.desc); | 94 | kfree(fwrt->dump.desc); |
93 | fwrt->dump.desc = NULL; | 95 | fwrt->dump.desc = NULL; |
96 | fwrt->dump.trig = NULL; | ||
94 | } | 97 | } |
95 | 98 | ||
96 | void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt); | 99 | void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt); |
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.h b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.h index e57ff92a68ae..3da468d2cc92 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.h | |||
@@ -75,6 +75,20 @@ static inline void iwl_fw_cancel_timestamp(struct iwl_fw_runtime *fwrt) | |||
75 | cancel_delayed_work_sync(&fwrt->timestamp.wk); | 75 | cancel_delayed_work_sync(&fwrt->timestamp.wk); |
76 | } | 76 | } |
77 | 77 | ||
78 | static inline void iwl_fw_suspend_timestamp(struct iwl_fw_runtime *fwrt) | ||
79 | { | ||
80 | cancel_delayed_work_sync(&fwrt->timestamp.wk); | ||
81 | } | ||
82 | |||
83 | static inline void iwl_fw_resume_timestamp(struct iwl_fw_runtime *fwrt) | ||
84 | { | ||
85 | if (!fwrt->timestamp.delay) | ||
86 | return; | ||
87 | |||
88 | schedule_delayed_work(&fwrt->timestamp.wk, | ||
89 | round_jiffies_relative(fwrt->timestamp.delay)); | ||
90 | } | ||
91 | |||
78 | #else | 92 | #else |
79 | static inline int iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, | 93 | static inline int iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, |
80 | struct dentry *dbgfs_dir) | 94 | struct dentry *dbgfs_dir) |
@@ -84,4 +98,8 @@ static inline int iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, | |||
84 | 98 | ||
85 | static inline void iwl_fw_cancel_timestamp(struct iwl_fw_runtime *fwrt) {} | 99 | static inline void iwl_fw_cancel_timestamp(struct iwl_fw_runtime *fwrt) {} |
86 | 100 | ||
101 | static inline void iwl_fw_suspend_timestamp(struct iwl_fw_runtime *fwrt) {} | ||
102 | |||
103 | static inline void iwl_fw_resume_timestamp(struct iwl_fw_runtime *fwrt) {} | ||
104 | |||
87 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | 105 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ |
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/init.c b/drivers/net/wireless/intel/iwlwifi/fw/init.c index c39fe84bb4c4..2efac307909e 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/init.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/init.c | |||
@@ -77,8 +77,14 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans, | |||
77 | } | 77 | } |
78 | IWL_EXPORT_SYMBOL(iwl_fw_runtime_init); | 78 | IWL_EXPORT_SYMBOL(iwl_fw_runtime_init); |
79 | 79 | ||
80 | void iwl_fw_runtime_exit(struct iwl_fw_runtime *fwrt) | 80 | void iwl_fw_runtime_suspend(struct iwl_fw_runtime *fwrt) |
81 | { | 81 | { |
82 | iwl_fw_cancel_timestamp(fwrt); | 82 | iwl_fw_suspend_timestamp(fwrt); |
83 | } | 83 | } |
84 | IWL_EXPORT_SYMBOL(iwl_fw_runtime_exit); | 84 | IWL_EXPORT_SYMBOL(iwl_fw_runtime_suspend); |
85 | |||
86 | void iwl_fw_runtime_resume(struct iwl_fw_runtime *fwrt) | ||
87 | { | ||
88 | iwl_fw_resume_timestamp(fwrt); | ||
89 | } | ||
90 | IWL_EXPORT_SYMBOL(iwl_fw_runtime_resume); | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index e25c049f980f..3fb940ebd74a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h | |||
@@ -6,6 +6,7 @@ | |||
6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
7 | * | 7 | * |
8 | * Copyright(c) 2017 Intel Deutschland GmbH | 8 | * Copyright(c) 2017 Intel Deutschland GmbH |
9 | * Copyright(c) 2018 Intel Corporation | ||
9 | * | 10 | * |
10 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of version 2 of the GNU General Public License as | 12 | * it under the terms of version 2 of the GNU General Public License as |
@@ -26,6 +27,7 @@ | |||
26 | * BSD LICENSE | 27 | * BSD LICENSE |
27 | * | 28 | * |
28 | * Copyright(c) 2017 Intel Deutschland GmbH | 29 | * Copyright(c) 2017 Intel Deutschland GmbH |
30 | * Copyright(c) 2018 Intel Corporation | ||
29 | * All rights reserved. | 31 | * All rights reserved. |
30 | * | 32 | * |
31 | * Redistribution and use in source and binary forms, with or without | 33 | * Redistribution and use in source and binary forms, with or without |
@@ -68,6 +70,7 @@ | |||
68 | struct iwl_fw_runtime_ops { | 70 | struct iwl_fw_runtime_ops { |
69 | int (*dump_start)(void *ctx); | 71 | int (*dump_start)(void *ctx); |
70 | void (*dump_end)(void *ctx); | 72 | void (*dump_end)(void *ctx); |
73 | bool (*fw_running)(void *ctx); | ||
71 | }; | 74 | }; |
72 | 75 | ||
73 | #define MAX_NUM_LMAC 2 | 76 | #define MAX_NUM_LMAC 2 |
@@ -150,6 +153,10 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans, | |||
150 | 153 | ||
151 | void iwl_fw_runtime_exit(struct iwl_fw_runtime *fwrt); | 154 | void iwl_fw_runtime_exit(struct iwl_fw_runtime *fwrt); |
152 | 155 | ||
156 | void iwl_fw_runtime_suspend(struct iwl_fw_runtime *fwrt); | ||
157 | |||
158 | void iwl_fw_runtime_resume(struct iwl_fw_runtime *fwrt); | ||
159 | |||
153 | static inline void iwl_fw_set_current_image(struct iwl_fw_runtime *fwrt, | 160 | static inline void iwl_fw_set_current_image(struct iwl_fw_runtime *fwrt, |
154 | enum iwl_ucode_type cur_fw_img) | 161 | enum iwl_ucode_type cur_fw_img) |
155 | { | 162 | { |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 0e6cf39285f4..2efe9b099556 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c | |||
@@ -1098,6 +1098,8 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
1098 | /* make sure the d0i3 exit work is not pending */ | 1098 | /* make sure the d0i3 exit work is not pending */ |
1099 | flush_work(&mvm->d0i3_exit_work); | 1099 | flush_work(&mvm->d0i3_exit_work); |
1100 | 1100 | ||
1101 | iwl_fw_runtime_suspend(&mvm->fwrt); | ||
1102 | |||
1101 | ret = iwl_trans_suspend(trans); | 1103 | ret = iwl_trans_suspend(trans); |
1102 | if (ret) | 1104 | if (ret) |
1103 | return ret; | 1105 | return ret; |
@@ -2012,6 +2014,8 @@ int iwl_mvm_resume(struct ieee80211_hw *hw) | |||
2012 | 2014 | ||
2013 | mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED; | 2015 | mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED; |
2014 | 2016 | ||
2017 | iwl_fw_runtime_resume(&mvm->fwrt); | ||
2018 | |||
2015 | return ret; | 2019 | return ret; |
2016 | } | 2020 | } |
2017 | 2021 | ||
@@ -2038,6 +2042,8 @@ static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file) | |||
2038 | 2042 | ||
2039 | mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_D3; | 2043 | mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_D3; |
2040 | 2044 | ||
2045 | iwl_fw_runtime_suspend(&mvm->fwrt); | ||
2046 | |||
2041 | /* start pseudo D3 */ | 2047 | /* start pseudo D3 */ |
2042 | rtnl_lock(); | 2048 | rtnl_lock(); |
2043 | err = __iwl_mvm_suspend(mvm->hw, mvm->hw->wiphy->wowlan_config, true); | 2049 | err = __iwl_mvm_suspend(mvm->hw, mvm->hw->wiphy->wowlan_config, true); |
@@ -2098,6 +2104,8 @@ static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file) | |||
2098 | __iwl_mvm_resume(mvm, true); | 2104 | __iwl_mvm_resume(mvm, true); |
2099 | rtnl_unlock(); | 2105 | rtnl_unlock(); |
2100 | 2106 | ||
2107 | iwl_fw_runtime_resume(&mvm->fwrt); | ||
2108 | |||
2101 | mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED; | 2109 | mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED; |
2102 | 2110 | ||
2103 | iwl_abort_notification_waits(&mvm->notif_wait); | 2111 | iwl_abort_notification_waits(&mvm->notif_wait); |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index a7892c1254a2..9c436d8d001d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | |||
@@ -8,6 +8,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 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
11 | * Copyright(c) 2018 Intel Corporation | ||
11 | * | 12 | * |
12 | * This program is free software; you can redistribute it and/or modify | 13 | * 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 | 14 | * it under the terms of version 2 of the GNU General Public License as |
@@ -35,6 +36,7 @@ | |||
35 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 36 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
36 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 37 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
37 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 38 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
39 | * Copyright(c) 2018 Intel Corporation | ||
38 | * All rights reserved. | 40 | * All rights reserved. |
39 | * | 41 | * |
40 | * Redistribution and use in source and binary forms, with or without | 42 | * Redistribution and use in source and binary forms, with or without |
@@ -1281,9 +1283,6 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm, | |||
1281 | { | 1283 | { |
1282 | int ret; | 1284 | int ret; |
1283 | 1285 | ||
1284 | if (!iwl_mvm_firmware_running(mvm)) | ||
1285 | return -EIO; | ||
1286 | |||
1287 | ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE); | 1286 | ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE); |
1288 | if (ret) | 1287 | if (ret) |
1289 | return ret; | 1288 | return ret; |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 2f22e14e00fe..8ba16fc24e3a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | |||
@@ -438,7 +438,8 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
438 | } | 438 | } |
439 | 439 | ||
440 | /* Allocate the CAB queue for softAP and GO interfaces */ | 440 | /* Allocate the CAB queue for softAP and GO interfaces */ |
441 | if (vif->type == NL80211_IFTYPE_AP) { | 441 | if (vif->type == NL80211_IFTYPE_AP || |
442 | vif->type == NL80211_IFTYPE_ADHOC) { | ||
442 | /* | 443 | /* |
443 | * For TVQM this will be overwritten later with the FW assigned | 444 | * For TVQM this will be overwritten later with the FW assigned |
444 | * queue value (when queue is enabled). | 445 | * queue value (when queue is enabled). |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 8aed40a8bc38..ebf511150f4d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | |||
@@ -8,6 +8,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 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
11 | * Copyright(c) 2018 Intel Corporation | ||
11 | * | 12 | * |
12 | * This program is free software; you can redistribute it and/or modify | 13 | * 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 | 14 | * it under the terms of version 2 of the GNU General Public License as |
@@ -2106,15 +2107,40 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, | |||
2106 | if (ret) | 2107 | if (ret) |
2107 | goto out_remove; | 2108 | goto out_remove; |
2108 | 2109 | ||
2109 | ret = iwl_mvm_add_mcast_sta(mvm, vif); | 2110 | /* |
2110 | if (ret) | 2111 | * This is not very nice, but the simplest: |
2111 | goto out_unbind; | 2112 | * For older FWs adding the mcast sta before the bcast station may |
2112 | 2113 | * cause assert 0x2b00. | |
2113 | /* Send the bcast station. At this stage the TBTT and DTIM time events | 2114 | * This is fixed in later FW so make the order of removal depend on |
2114 | * are added and applied to the scheduler */ | 2115 | * the TLV |
2115 | ret = iwl_mvm_send_add_bcast_sta(mvm, vif); | 2116 | */ |
2116 | if (ret) | 2117 | if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STA_TYPE)) { |
2117 | goto out_rm_mcast; | 2118 | ret = iwl_mvm_add_mcast_sta(mvm, vif); |
2119 | if (ret) | ||
2120 | goto out_unbind; | ||
2121 | /* | ||
2122 | * Send the bcast station. At this stage the TBTT and DTIM time | ||
2123 | * events are added and applied to the scheduler | ||
2124 | */ | ||
2125 | ret = iwl_mvm_send_add_bcast_sta(mvm, vif); | ||
2126 | if (ret) { | ||
2127 | iwl_mvm_rm_mcast_sta(mvm, vif); | ||
2128 | goto out_unbind; | ||
2129 | } | ||
2130 | } else { | ||
2131 | /* | ||
2132 | * Send the bcast station. At this stage the TBTT and DTIM time | ||
2133 | * events are added and applied to the scheduler | ||
2134 | */ | ||
2135 | iwl_mvm_send_add_bcast_sta(mvm, vif); | ||
2136 | if (ret) | ||
2137 | goto out_unbind; | ||
2138 | iwl_mvm_add_mcast_sta(mvm, vif); | ||
2139 | if (ret) { | ||
2140 | iwl_mvm_send_rm_bcast_sta(mvm, vif); | ||
2141 | goto out_unbind; | ||
2142 | } | ||
2143 | } | ||
2118 | 2144 | ||
2119 | /* must be set before quota calculations */ | 2145 | /* must be set before quota calculations */ |
2120 | mvmvif->ap_ibss_active = true; | 2146 | mvmvif->ap_ibss_active = true; |
@@ -2144,7 +2170,6 @@ out_quota_failed: | |||
2144 | iwl_mvm_power_update_mac(mvm); | 2170 | iwl_mvm_power_update_mac(mvm); |
2145 | mvmvif->ap_ibss_active = false; | 2171 | mvmvif->ap_ibss_active = false; |
2146 | iwl_mvm_send_rm_bcast_sta(mvm, vif); | 2172 | iwl_mvm_send_rm_bcast_sta(mvm, vif); |
2147 | out_rm_mcast: | ||
2148 | iwl_mvm_rm_mcast_sta(mvm, vif); | 2173 | iwl_mvm_rm_mcast_sta(mvm, vif); |
2149 | out_unbind: | 2174 | out_unbind: |
2150 | iwl_mvm_binding_remove_vif(mvm, vif); | 2175 | iwl_mvm_binding_remove_vif(mvm, vif); |
@@ -2682,6 +2707,10 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, | |||
2682 | 2707 | ||
2683 | /* enable beacon filtering */ | 2708 | /* enable beacon filtering */ |
2684 | WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0)); | 2709 | WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0)); |
2710 | |||
2711 | iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band, | ||
2712 | false); | ||
2713 | |||
2685 | ret = 0; | 2714 | ret = 0; |
2686 | } else if (old_state == IEEE80211_STA_AUTHORIZED && | 2715 | } else if (old_state == IEEE80211_STA_AUTHORIZED && |
2687 | new_state == IEEE80211_STA_ASSOC) { | 2716 | new_state == IEEE80211_STA_ASSOC) { |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 2d28e0804218..89ff02d7c876 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | |||
@@ -90,6 +90,7 @@ | |||
90 | #include "fw/runtime.h" | 90 | #include "fw/runtime.h" |
91 | #include "fw/dbg.h" | 91 | #include "fw/dbg.h" |
92 | #include "fw/acpi.h" | 92 | #include "fw/acpi.h" |
93 | #include "fw/debugfs.h" | ||
93 | 94 | ||
94 | #define IWL_MVM_MAX_ADDRESSES 5 | 95 | #define IWL_MVM_MAX_ADDRESSES 5 |
95 | /* RSSI offset for WkP */ | 96 | /* RSSI offset for WkP */ |
@@ -1783,6 +1784,7 @@ static inline u32 iwl_mvm_flushable_queues(struct iwl_mvm *mvm) | |||
1783 | 1784 | ||
1784 | static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm) | 1785 | static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm) |
1785 | { | 1786 | { |
1787 | iwl_fw_cancel_timestamp(&mvm->fwrt); | ||
1786 | iwl_free_fw_paging(&mvm->fwrt); | 1788 | iwl_free_fw_paging(&mvm->fwrt); |
1787 | clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status); | 1789 | clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status); |
1788 | iwl_fw_dump_conf_clear(&mvm->fwrt); | 1790 | iwl_fw_dump_conf_clear(&mvm->fwrt); |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 5d525a0023dc..ab7fb5aad984 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c | |||
@@ -8,6 +8,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 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
11 | * Copyright(c) 2018 Intel Corporation | ||
11 | * | 12 | * |
12 | * This program is free software; you can redistribute it and/or modify | 13 | * 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 | 14 | * it under the terms of version 2 of the GNU General Public License as |
@@ -35,6 +36,7 @@ | |||
35 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 36 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
36 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 37 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
37 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 38 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
39 | * Copyright(c) 2018 Intel Corporation | ||
38 | * All rights reserved. | 40 | * All rights reserved. |
39 | * | 41 | * |
40 | * Redistribution and use in source and binary forms, with or without | 42 | * Redistribution and use in source and binary forms, with or without |
@@ -552,9 +554,15 @@ static void iwl_mvm_fwrt_dump_end(void *ctx) | |||
552 | iwl_mvm_unref(mvm, IWL_MVM_REF_FW_DBG_COLLECT); | 554 | iwl_mvm_unref(mvm, IWL_MVM_REF_FW_DBG_COLLECT); |
553 | } | 555 | } |
554 | 556 | ||
557 | static bool iwl_mvm_fwrt_fw_running(void *ctx) | ||
558 | { | ||
559 | return iwl_mvm_firmware_running(ctx); | ||
560 | } | ||
561 | |||
555 | static const struct iwl_fw_runtime_ops iwl_mvm_fwrt_ops = { | 562 | static const struct iwl_fw_runtime_ops iwl_mvm_fwrt_ops = { |
556 | .dump_start = iwl_mvm_fwrt_dump_start, | 563 | .dump_start = iwl_mvm_fwrt_dump_start, |
557 | .dump_end = iwl_mvm_fwrt_dump_end, | 564 | .dump_end = iwl_mvm_fwrt_dump_end, |
565 | .fw_running = iwl_mvm_fwrt_fw_running, | ||
558 | }; | 566 | }; |
559 | 567 | ||
560 | static struct iwl_op_mode * | 568 | static struct iwl_op_mode * |
@@ -802,7 +810,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
802 | iwl_mvm_leds_exit(mvm); | 810 | iwl_mvm_leds_exit(mvm); |
803 | iwl_mvm_thermal_exit(mvm); | 811 | iwl_mvm_thermal_exit(mvm); |
804 | out_free: | 812 | out_free: |
805 | iwl_fw_runtime_exit(&mvm->fwrt); | ||
806 | iwl_fw_flush_dump(&mvm->fwrt); | 813 | iwl_fw_flush_dump(&mvm->fwrt); |
807 | 814 | ||
808 | if (iwlmvm_mod_params.init_dbg) | 815 | if (iwlmvm_mod_params.init_dbg) |
@@ -843,7 +850,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) | |||
843 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS) | 850 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS) |
844 | kfree(mvm->d3_resume_sram); | 851 | kfree(mvm->d3_resume_sram); |
845 | #endif | 852 | #endif |
846 | iwl_fw_runtime_exit(&mvm->fwrt); | ||
847 | iwl_trans_op_mode_leave(mvm->trans); | 853 | iwl_trans_op_mode_leave(mvm->trans); |
848 | 854 | ||
849 | iwl_phy_db_free(mvm->phy_db); | 855 | iwl_phy_db_free(mvm->phy_db); |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index 60abb0084ee5..47f4c7a1d80d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c | |||
@@ -2684,7 +2684,8 @@ static void rs_get_initial_rate(struct iwl_mvm *mvm, | |||
2684 | struct ieee80211_sta *sta, | 2684 | struct ieee80211_sta *sta, |
2685 | struct iwl_lq_sta *lq_sta, | 2685 | struct iwl_lq_sta *lq_sta, |
2686 | enum nl80211_band band, | 2686 | enum nl80211_band band, |
2687 | struct rs_rate *rate) | 2687 | struct rs_rate *rate, |
2688 | bool init) | ||
2688 | { | 2689 | { |
2689 | int i, nentries; | 2690 | int i, nentries; |
2690 | unsigned long active_rate; | 2691 | unsigned long active_rate; |
@@ -2738,14 +2739,25 @@ static void rs_get_initial_rate(struct iwl_mvm *mvm, | |||
2738 | */ | 2739 | */ |
2739 | if (sta->vht_cap.vht_supported && | 2740 | if (sta->vht_cap.vht_supported && |
2740 | best_rssi > IWL_RS_LOW_RSSI_THRESHOLD) { | 2741 | best_rssi > IWL_RS_LOW_RSSI_THRESHOLD) { |
2741 | switch (sta->bandwidth) { | 2742 | /* |
2742 | case IEEE80211_STA_RX_BW_160: | 2743 | * In AP mode, when a new station associates, rs is initialized |
2743 | case IEEE80211_STA_RX_BW_80: | 2744 | * immediately upon association completion, before the phy |
2744 | case IEEE80211_STA_RX_BW_40: | 2745 | * context is updated with the association parameters, so the |
2746 | * sta bandwidth might be wider than the phy context allows. | ||
2747 | * To avoid this issue, always initialize rs with 20mhz | ||
2748 | * bandwidth rate, and after authorization, when the phy context | ||
2749 | * is already up-to-date, re-init rs with the correct bw. | ||
2750 | */ | ||
2751 | u32 bw = init ? RATE_MCS_CHAN_WIDTH_20 : rs_bw_from_sta_bw(sta); | ||
2752 | |||
2753 | switch (bw) { | ||
2754 | case RATE_MCS_CHAN_WIDTH_40: | ||
2755 | case RATE_MCS_CHAN_WIDTH_80: | ||
2756 | case RATE_MCS_CHAN_WIDTH_160: | ||
2745 | initial_rates = rs_optimal_rates_vht; | 2757 | initial_rates = rs_optimal_rates_vht; |
2746 | nentries = ARRAY_SIZE(rs_optimal_rates_vht); | 2758 | nentries = ARRAY_SIZE(rs_optimal_rates_vht); |
2747 | break; | 2759 | break; |
2748 | case IEEE80211_STA_RX_BW_20: | 2760 | case RATE_MCS_CHAN_WIDTH_20: |
2749 | initial_rates = rs_optimal_rates_vht_20mhz; | 2761 | initial_rates = rs_optimal_rates_vht_20mhz; |
2750 | nentries = ARRAY_SIZE(rs_optimal_rates_vht_20mhz); | 2762 | nentries = ARRAY_SIZE(rs_optimal_rates_vht_20mhz); |
2751 | break; | 2763 | break; |
@@ -2756,7 +2768,7 @@ static void rs_get_initial_rate(struct iwl_mvm *mvm, | |||
2756 | 2768 | ||
2757 | active_rate = lq_sta->active_siso_rate; | 2769 | active_rate = lq_sta->active_siso_rate; |
2758 | rate->type = LQ_VHT_SISO; | 2770 | rate->type = LQ_VHT_SISO; |
2759 | rate->bw = rs_bw_from_sta_bw(sta); | 2771 | rate->bw = bw; |
2760 | } else if (sta->ht_cap.ht_supported && | 2772 | } else if (sta->ht_cap.ht_supported && |
2761 | best_rssi > IWL_RS_LOW_RSSI_THRESHOLD) { | 2773 | best_rssi > IWL_RS_LOW_RSSI_THRESHOLD) { |
2762 | initial_rates = rs_optimal_rates_ht; | 2774 | initial_rates = rs_optimal_rates_ht; |
@@ -2839,7 +2851,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm, | |||
2839 | tbl = &(lq_sta->lq_info[active_tbl]); | 2851 | tbl = &(lq_sta->lq_info[active_tbl]); |
2840 | rate = &tbl->rate; | 2852 | rate = &tbl->rate; |
2841 | 2853 | ||
2842 | rs_get_initial_rate(mvm, sta, lq_sta, band, rate); | 2854 | rs_get_initial_rate(mvm, sta, lq_sta, band, rate, init); |
2843 | rs_init_optimal_rate(mvm, sta, lq_sta); | 2855 | rs_init_optimal_rate(mvm, sta, lq_sta); |
2844 | 2856 | ||
2845 | WARN_ONCE(rate->ant != ANT_A && rate->ant != ANT_B, | 2857 | WARN_ONCE(rate->ant != ANT_A && rate->ant != ANT_B, |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index a3f7c1bf3cc8..580de5851fc7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | |||
@@ -71,6 +71,7 @@ static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
71 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 71 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
72 | struct ieee80211_rx_status *stats = IEEE80211_SKB_RXCB(skb); | 72 | struct ieee80211_rx_status *stats = IEEE80211_SKB_RXCB(skb); |
73 | struct iwl_mvm_key_pn *ptk_pn; | 73 | struct iwl_mvm_key_pn *ptk_pn; |
74 | int res; | ||
74 | u8 tid, keyidx; | 75 | u8 tid, keyidx; |
75 | u8 pn[IEEE80211_CCMP_PN_LEN]; | 76 | u8 pn[IEEE80211_CCMP_PN_LEN]; |
76 | u8 *extiv; | 77 | u8 *extiv; |
@@ -127,12 +128,13 @@ static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
127 | pn[4] = extiv[1]; | 128 | pn[4] = extiv[1]; |
128 | pn[5] = extiv[0]; | 129 | pn[5] = extiv[0]; |
129 | 130 | ||
130 | if (memcmp(pn, ptk_pn->q[queue].pn[tid], | 131 | res = memcmp(pn, ptk_pn->q[queue].pn[tid], IEEE80211_CCMP_PN_LEN); |
131 | IEEE80211_CCMP_PN_LEN) <= 0) | 132 | if (res < 0) |
133 | return -1; | ||
134 | if (!res && !(stats->flag & RX_FLAG_ALLOW_SAME_PN)) | ||
132 | return -1; | 135 | return -1; |
133 | 136 | ||
134 | if (!(stats->flag & RX_FLAG_AMSDU_MORE)) | 137 | memcpy(ptk_pn->q[queue].pn[tid], pn, IEEE80211_CCMP_PN_LEN); |
135 | memcpy(ptk_pn->q[queue].pn[tid], pn, IEEE80211_CCMP_PN_LEN); | ||
136 | stats->flag |= RX_FLAG_PN_VALIDATED; | 138 | stats->flag |= RX_FLAG_PN_VALIDATED; |
137 | 139 | ||
138 | return 0; | 140 | return 0; |
@@ -314,28 +316,21 @@ static void iwl_mvm_rx_csum(struct ieee80211_sta *sta, | |||
314 | } | 316 | } |
315 | 317 | ||
316 | /* | 318 | /* |
317 | * returns true if a packet outside BA session is a duplicate and | 319 | * returns true if a packet is a duplicate and should be dropped. |
318 | * should be dropped | 320 | * Updates AMSDU PN tracking info |
319 | */ | 321 | */ |
320 | static bool iwl_mvm_is_nonagg_dup(struct ieee80211_sta *sta, int queue, | 322 | static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue, |
321 | struct ieee80211_rx_status *rx_status, | 323 | struct ieee80211_rx_status *rx_status, |
322 | struct ieee80211_hdr *hdr, | 324 | struct ieee80211_hdr *hdr, |
323 | struct iwl_rx_mpdu_desc *desc) | 325 | struct iwl_rx_mpdu_desc *desc) |
324 | { | 326 | { |
325 | struct iwl_mvm_sta *mvm_sta; | 327 | struct iwl_mvm_sta *mvm_sta; |
326 | struct iwl_mvm_rxq_dup_data *dup_data; | 328 | struct iwl_mvm_rxq_dup_data *dup_data; |
327 | u8 baid, tid, sub_frame_idx; | 329 | u8 tid, sub_frame_idx; |
328 | 330 | ||
329 | if (WARN_ON(IS_ERR_OR_NULL(sta))) | 331 | if (WARN_ON(IS_ERR_OR_NULL(sta))) |
330 | return false; | 332 | return false; |
331 | 333 | ||
332 | baid = (le32_to_cpu(desc->reorder_data) & | ||
333 | IWL_RX_MPDU_REORDER_BAID_MASK) >> | ||
334 | IWL_RX_MPDU_REORDER_BAID_SHIFT; | ||
335 | |||
336 | if (baid != IWL_RX_REORDER_DATA_INVALID_BAID) | ||
337 | return false; | ||
338 | |||
339 | mvm_sta = iwl_mvm_sta_from_mac80211(sta); | 334 | mvm_sta = iwl_mvm_sta_from_mac80211(sta); |
340 | dup_data = &mvm_sta->dup_data[queue]; | 335 | dup_data = &mvm_sta->dup_data[queue]; |
341 | 336 | ||
@@ -365,6 +360,12 @@ static bool iwl_mvm_is_nonagg_dup(struct ieee80211_sta *sta, int queue, | |||
365 | dup_data->last_sub_frame[tid] >= sub_frame_idx)) | 360 | dup_data->last_sub_frame[tid] >= sub_frame_idx)) |
366 | return true; | 361 | return true; |
367 | 362 | ||
363 | /* Allow same PN as the first subframe for following sub frames */ | ||
364 | if (dup_data->last_seq[tid] == hdr->seq_ctrl && | ||
365 | sub_frame_idx > dup_data->last_sub_frame[tid] && | ||
366 | desc->mac_flags2 & IWL_RX_MPDU_MFLG2_AMSDU) | ||
367 | rx_status->flag |= RX_FLAG_ALLOW_SAME_PN; | ||
368 | |||
368 | dup_data->last_seq[tid] = hdr->seq_ctrl; | 369 | dup_data->last_seq[tid] = hdr->seq_ctrl; |
369 | dup_data->last_sub_frame[tid] = sub_frame_idx; | 370 | dup_data->last_sub_frame[tid] = sub_frame_idx; |
370 | 371 | ||
@@ -971,7 +972,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, | |||
971 | if (ieee80211_is_data(hdr->frame_control)) | 972 | if (ieee80211_is_data(hdr->frame_control)) |
972 | iwl_mvm_rx_csum(sta, skb, desc); | 973 | iwl_mvm_rx_csum(sta, skb, desc); |
973 | 974 | ||
974 | if (iwl_mvm_is_nonagg_dup(sta, queue, rx_status, hdr, desc)) { | 975 | if (iwl_mvm_is_dup(sta, queue, rx_status, hdr, desc)) { |
975 | kfree_skb(skb); | 976 | kfree_skb(skb); |
976 | goto out; | 977 | goto out; |
977 | } | 978 | } |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 6b2674e02606..630e23cb0ffb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c | |||
@@ -2039,7 +2039,7 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
2039 | struct iwl_trans_txq_scd_cfg cfg = { | 2039 | struct iwl_trans_txq_scd_cfg cfg = { |
2040 | .fifo = IWL_MVM_TX_FIFO_MCAST, | 2040 | .fifo = IWL_MVM_TX_FIFO_MCAST, |
2041 | .sta_id = msta->sta_id, | 2041 | .sta_id = msta->sta_id, |
2042 | .tid = IWL_MAX_TID_COUNT, | 2042 | .tid = 0, |
2043 | .aggregate = false, | 2043 | .aggregate = false, |
2044 | .frame_limit = IWL_FRAME_LIMIT, | 2044 | .frame_limit = IWL_FRAME_LIMIT, |
2045 | }; | 2045 | }; |
@@ -2053,6 +2053,17 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
2053 | return -ENOTSUPP; | 2053 | return -ENOTSUPP; |
2054 | 2054 | ||
2055 | /* | 2055 | /* |
2056 | * In IBSS, ieee80211_check_queues() sets the cab_queue to be | ||
2057 | * invalid, so make sure we use the queue we want. | ||
2058 | * Note that this is done here as we want to avoid making DQA | ||
2059 | * changes in mac80211 layer. | ||
2060 | */ | ||
2061 | if (vif->type == NL80211_IFTYPE_ADHOC) { | ||
2062 | vif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE; | ||
2063 | mvmvif->cab_queue = vif->cab_queue; | ||
2064 | } | ||
2065 | |||
2066 | /* | ||
2056 | * While in previous FWs we had to exclude cab queue from TFD queue | 2067 | * While in previous FWs we had to exclude cab queue from TFD queue |
2057 | * mask, now it is needed as any other queue. | 2068 | * mask, now it is needed as any other queue. |
2058 | */ | 2069 | */ |
@@ -2079,24 +2090,13 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
2079 | if (iwl_mvm_has_new_tx_api(mvm)) { | 2090 | if (iwl_mvm_has_new_tx_api(mvm)) { |
2080 | int queue = iwl_mvm_tvqm_enable_txq(mvm, vif->cab_queue, | 2091 | int queue = iwl_mvm_tvqm_enable_txq(mvm, vif->cab_queue, |
2081 | msta->sta_id, | 2092 | msta->sta_id, |
2082 | IWL_MAX_TID_COUNT, | 2093 | 0, |
2083 | timeout); | 2094 | timeout); |
2084 | mvmvif->cab_queue = queue; | 2095 | mvmvif->cab_queue = queue; |
2085 | } else if (!fw_has_api(&mvm->fw->ucode_capa, | 2096 | } else if (!fw_has_api(&mvm->fw->ucode_capa, |
2086 | IWL_UCODE_TLV_API_STA_TYPE)) { | 2097 | IWL_UCODE_TLV_API_STA_TYPE)) |
2087 | /* | ||
2088 | * In IBSS, ieee80211_check_queues() sets the cab_queue to be | ||
2089 | * invalid, so make sure we use the queue we want. | ||
2090 | * Note that this is done here as we want to avoid making DQA | ||
2091 | * changes in mac80211 layer. | ||
2092 | */ | ||
2093 | if (vif->type == NL80211_IFTYPE_ADHOC) { | ||
2094 | vif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE; | ||
2095 | mvmvif->cab_queue = vif->cab_queue; | ||
2096 | } | ||
2097 | iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0, | 2098 | iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0, |
2098 | &cfg, timeout); | 2099 | &cfg, timeout); |
2099 | } | ||
2100 | 2100 | ||
2101 | return 0; | 2101 | return 0; |
2102 | } | 2102 | } |
@@ -2115,7 +2115,7 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
2115 | iwl_mvm_flush_sta(mvm, &mvmvif->mcast_sta, true, 0); | 2115 | iwl_mvm_flush_sta(mvm, &mvmvif->mcast_sta, true, 0); |
2116 | 2116 | ||
2117 | iwl_mvm_disable_txq(mvm, mvmvif->cab_queue, vif->cab_queue, | 2117 | iwl_mvm_disable_txq(mvm, mvmvif->cab_queue, vif->cab_queue, |
2118 | IWL_MAX_TID_COUNT, 0); | 2118 | 0, 0); |
2119 | 2119 | ||
2120 | ret = iwl_mvm_rm_sta_common(mvm, mvmvif->mcast_sta.sta_id); | 2120 | ret = iwl_mvm_rm_sta_common(mvm, mvmvif->mcast_sta.sta_id); |
2121 | if (ret) | 2121 | if (ret) |
@@ -3170,8 +3170,9 @@ static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id, | |||
3170 | int ret, size; | 3170 | int ret, size; |
3171 | u32 status; | 3171 | u32 status; |
3172 | 3172 | ||
3173 | /* This is a valid situation for GTK removal */ | ||
3173 | if (sta_id == IWL_MVM_INVALID_STA) | 3174 | if (sta_id == IWL_MVM_INVALID_STA) |
3174 | return -EINVAL; | 3175 | return 0; |
3175 | 3176 | ||
3176 | key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) & | 3177 | key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) & |
3177 | STA_KEY_FLG_KEYID_MSK); | 3178 | STA_KEY_FLG_KEYID_MSK); |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index 200ab50ec86b..acb217e666db 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c | |||
@@ -616,7 +616,7 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm, | |||
616 | time_cmd.repeat = 1; | 616 | time_cmd.repeat = 1; |
617 | time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | | 617 | time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | |
618 | TE_V2_NOTIF_HOST_EVENT_END | | 618 | TE_V2_NOTIF_HOST_EVENT_END | |
619 | T2_V2_START_IMMEDIATELY); | 619 | TE_V2_START_IMMEDIATELY); |
620 | 620 | ||
621 | if (!wait_for_notif) { | 621 | if (!wait_for_notif) { |
622 | iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); | 622 | iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); |
@@ -803,7 +803,7 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
803 | time_cmd.repeat = 1; | 803 | time_cmd.repeat = 1; |
804 | time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | | 804 | time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | |
805 | TE_V2_NOTIF_HOST_EVENT_END | | 805 | TE_V2_NOTIF_HOST_EVENT_END | |
806 | T2_V2_START_IMMEDIATELY); | 806 | TE_V2_START_IMMEDIATELY); |
807 | 807 | ||
808 | return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); | 808 | return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); |
809 | } | 809 | } |
@@ -913,6 +913,8 @@ int iwl_mvm_schedule_csa_period(struct iwl_mvm *mvm, | |||
913 | time_cmd.interval = cpu_to_le32(1); | 913 | time_cmd.interval = cpu_to_le32(1); |
914 | time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | | 914 | time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | |
915 | TE_V2_ABSENCE); | 915 | TE_V2_ABSENCE); |
916 | if (!apply_time) | ||
917 | time_cmd.policy |= cpu_to_le16(TE_V2_START_IMMEDIATELY); | ||
916 | 918 | ||
917 | return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); | 919 | return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); |
918 | } | 920 | } |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index dda77b327c98..af6dfceab6b8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c | |||
@@ -419,11 +419,11 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm, | |||
419 | { | 419 | { |
420 | struct ieee80211_key_conf *keyconf = info->control.hw_key; | 420 | struct ieee80211_key_conf *keyconf = info->control.hw_key; |
421 | u8 *crypto_hdr = skb_frag->data + hdrlen; | 421 | u8 *crypto_hdr = skb_frag->data + hdrlen; |
422 | enum iwl_tx_cmd_sec_ctrl type = TX_CMD_SEC_CCM; | ||
422 | u64 pn; | 423 | u64 pn; |
423 | 424 | ||
424 | switch (keyconf->cipher) { | 425 | switch (keyconf->cipher) { |
425 | case WLAN_CIPHER_SUITE_CCMP: | 426 | case WLAN_CIPHER_SUITE_CCMP: |
426 | case WLAN_CIPHER_SUITE_CCMP_256: | ||
427 | iwl_mvm_set_tx_cmd_ccmp(info, tx_cmd); | 427 | iwl_mvm_set_tx_cmd_ccmp(info, tx_cmd); |
428 | iwl_mvm_set_tx_cmd_pn(info, crypto_hdr); | 428 | iwl_mvm_set_tx_cmd_pn(info, crypto_hdr); |
429 | break; | 429 | break; |
@@ -447,13 +447,16 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm, | |||
447 | break; | 447 | break; |
448 | case WLAN_CIPHER_SUITE_GCMP: | 448 | case WLAN_CIPHER_SUITE_GCMP: |
449 | case WLAN_CIPHER_SUITE_GCMP_256: | 449 | case WLAN_CIPHER_SUITE_GCMP_256: |
450 | type = TX_CMD_SEC_GCMP; | ||
451 | /* Fall through */ | ||
452 | case WLAN_CIPHER_SUITE_CCMP_256: | ||
450 | /* TODO: Taking the key from the table might introduce a race | 453 | /* TODO: Taking the key from the table might introduce a race |
451 | * when PTK rekeying is done, having an old packets with a PN | 454 | * when PTK rekeying is done, having an old packets with a PN |
452 | * based on the old key but the message encrypted with a new | 455 | * based on the old key but the message encrypted with a new |
453 | * one. | 456 | * one. |
454 | * Need to handle this. | 457 | * Need to handle this. |
455 | */ | 458 | */ |
456 | tx_cmd->sec_ctl |= TX_CMD_SEC_GCMP | TX_CMD_SEC_KEY_FROM_TABLE; | 459 | tx_cmd->sec_ctl |= type | TX_CMD_SEC_KEY_FROM_TABLE; |
457 | tx_cmd->key[0] = keyconf->hw_key_idx; | 460 | tx_cmd->key[0] = keyconf->hw_key_idx; |
458 | iwl_mvm_set_tx_cmd_pn(info, crypto_hdr); | 461 | iwl_mvm_set_tx_cmd_pn(info, crypto_hdr); |
459 | break; | 462 | break; |
@@ -645,7 +648,11 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) | |||
645 | if (info.control.vif->type == NL80211_IFTYPE_P2P_DEVICE || | 648 | if (info.control.vif->type == NL80211_IFTYPE_P2P_DEVICE || |
646 | info.control.vif->type == NL80211_IFTYPE_AP || | 649 | info.control.vif->type == NL80211_IFTYPE_AP || |
647 | info.control.vif->type == NL80211_IFTYPE_ADHOC) { | 650 | info.control.vif->type == NL80211_IFTYPE_ADHOC) { |
648 | sta_id = mvmvif->bcast_sta.sta_id; | 651 | if (info.control.vif->type == NL80211_IFTYPE_P2P_DEVICE) |
652 | sta_id = mvmvif->bcast_sta.sta_id; | ||
653 | else | ||
654 | sta_id = mvmvif->mcast_sta.sta_id; | ||
655 | |||
649 | queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info, | 656 | queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info, |
650 | hdr->frame_control); | 657 | hdr->frame_control); |
651 | if (queue < 0) | 658 | if (queue < 0) |
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index 6d0a907d5ba5..fabae0f60683 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c | |||
@@ -147,7 +147,7 @@ static void iwl_pcie_gen2_tfd_unmap(struct iwl_trans *trans, | |||
147 | /* Sanity check on number of chunks */ | 147 | /* Sanity check on number of chunks */ |
148 | num_tbs = iwl_pcie_gen2_get_num_tbs(trans, tfd); | 148 | num_tbs = iwl_pcie_gen2_get_num_tbs(trans, tfd); |
149 | 149 | ||
150 | if (num_tbs >= trans_pcie->max_tbs) { | 150 | if (num_tbs > trans_pcie->max_tbs) { |
151 | IWL_ERR(trans, "Too many chunks: %i\n", num_tbs); | 151 | IWL_ERR(trans, "Too many chunks: %i\n", num_tbs); |
152 | return; | 152 | return; |
153 | } | 153 | } |
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 3f85713c41dc..1a566287993d 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c | |||
@@ -378,7 +378,7 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans, | |||
378 | /* Sanity check on number of chunks */ | 378 | /* Sanity check on number of chunks */ |
379 | num_tbs = iwl_pcie_tfd_get_num_tbs(trans, tfd); | 379 | num_tbs = iwl_pcie_tfd_get_num_tbs(trans, tfd); |
380 | 380 | ||
381 | if (num_tbs >= trans_pcie->max_tbs) { | 381 | if (num_tbs > trans_pcie->max_tbs) { |
382 | IWL_ERR(trans, "Too many chunks: %i\n", num_tbs); | 382 | IWL_ERR(trans, "Too many chunks: %i\n", num_tbs); |
383 | /* @todo issue fatal error, it is quite serious situation */ | 383 | /* @todo issue fatal error, it is quite serious situation */ |
384 | return; | 384 | return; |