diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-08-02 15:37:34 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-08-02 15:37:34 -0400 |
commit | 204162296edf0d0ac3e4dfd5bd0cac4af731b583 (patch) | |
tree | fdf941fd23fae6097500db4998d4ca96467fc352 | |
parent | e3d5291436ff9efeeb968459724af5332305dded (diff) | |
parent | 147fc9be81d10e6e863323c0b54e140b42fd1ed6 (diff) |
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
48 files changed, 1309 insertions, 893 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 7a403ba167d2..2a3faf5b8301 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -4362,7 +4362,7 @@ F: drivers/net/wireless/iwlegacy/ | |||
4362 | 4362 | ||
4363 | INTEL WIRELESS WIFI LINK (iwlwifi) | 4363 | INTEL WIRELESS WIFI LINK (iwlwifi) |
4364 | M: Johannes Berg <johannes.berg@intel.com> | 4364 | M: Johannes Berg <johannes.berg@intel.com> |
4365 | M: Wey-Yi Guy <wey-yi.w.guy@intel.com> | 4365 | M: Emmanuel Grumbach <emmanuel.grumbach@intel.com> |
4366 | M: Intel Linux Wireless <ilw@linux.intel.com> | 4366 | M: Intel Linux Wireless <ilw@linux.intel.com> |
4367 | L: linux-wireless@vger.kernel.org | 4367 | L: linux-wireless@vger.kernel.org |
4368 | W: http://intellinuxwireless.org | 4368 | W: http://intellinuxwireless.org |
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index cbaa5c2c410f..e5c133ee7901 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -127,20 +127,3 @@ config IWLWIFI_DEVICE_TRACING | |||
127 | If unsure, say Y so we can help you better when problems | 127 | If unsure, say Y so we can help you better when problems |
128 | occur. | 128 | occur. |
129 | endmenu | 129 | endmenu |
130 | |||
131 | config IWLWIFI_P2P | ||
132 | def_bool y | ||
133 | bool "iwlwifi experimental P2P support" | ||
134 | depends on IWLWIFI | ||
135 | help | ||
136 | This option enables experimental P2P support for some devices | ||
137 | based on microcode support. Since P2P support is still under | ||
138 | development, this option may even enable it for some devices | ||
139 | now that turn out to not support it in the future due to | ||
140 | microcode restrictions. | ||
141 | |||
142 | To determine if your microcode supports the experimental P2P | ||
143 | offered by this option, check if the driver advertises AP | ||
144 | support when it is loaded. | ||
145 | |||
146 | Say Y only if you want to experiment with P2P. | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h index 18355110deff..f2a86ffc3b4c 100644 --- a/drivers/net/wireless/iwlwifi/dvm/agn.h +++ b/drivers/net/wireless/iwlwifi/dvm/agn.h | |||
@@ -106,7 +106,6 @@ extern const struct iwl_dvm_cfg iwl_dvm_6030_cfg; | |||
106 | #define STATUS_CHANNEL_SWITCH_PENDING 11 | 106 | #define STATUS_CHANNEL_SWITCH_PENDING 11 |
107 | #define STATUS_SCAN_COMPLETE 12 | 107 | #define STATUS_SCAN_COMPLETE 12 |
108 | #define STATUS_POWER_PMI 13 | 108 | #define STATUS_POWER_PMI 13 |
109 | #define STATUS_SCAN_ROC_EXPIRED 14 | ||
110 | 109 | ||
111 | struct iwl_ucode_capabilities; | 110 | struct iwl_ucode_capabilities; |
112 | 111 | ||
@@ -250,7 +249,6 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid); | |||
250 | 249 | ||
251 | /* scan */ | 250 | /* scan */ |
252 | void iwlagn_post_scan(struct iwl_priv *priv); | 251 | void iwlagn_post_scan(struct iwl_priv *priv); |
253 | void iwlagn_disable_roc(struct iwl_priv *priv); | ||
254 | int iwl_force_rf_reset(struct iwl_priv *priv, bool external); | 252 | int iwl_force_rf_reset(struct iwl_priv *priv, bool external); |
255 | void iwl_init_scan_params(struct iwl_priv *priv); | 253 | void iwl_init_scan_params(struct iwl_priv *priv); |
256 | int iwl_scan_cancel(struct iwl_priv *priv); | 254 | int iwl_scan_cancel(struct iwl_priv *priv); |
@@ -265,10 +263,6 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, | |||
265 | enum iwl_scan_type scan_type, | 263 | enum iwl_scan_type scan_type, |
266 | enum ieee80211_band band); | 264 | enum ieee80211_band band); |
267 | 265 | ||
268 | void iwl_scan_roc_expired(struct iwl_priv *priv); | ||
269 | void iwl_scan_offchannel_skb(struct iwl_priv *priv); | ||
270 | void iwl_scan_offchannel_skb_status(struct iwl_priv *priv); | ||
271 | |||
272 | /* For faster active scanning, scan will move to the next channel if fewer than | 266 | /* For faster active scanning, scan will move to the next channel if fewer than |
273 | * PLCP_QUIET_THRESH packets are heard on this channel within | 267 | * PLCP_QUIET_THRESH packets are heard on this channel within |
274 | * ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell | 268 | * ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell |
diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c index d5329489245a..d94f8ab15004 100644 --- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c | |||
@@ -69,19 +69,7 @@ | |||
69 | } while (0) | 69 | } while (0) |
70 | 70 | ||
71 | /* file operation */ | 71 | /* file operation */ |
72 | #define DEBUGFS_READ_FUNC(name) \ | ||
73 | static ssize_t iwl_dbgfs_##name##_read(struct file *file, \ | ||
74 | char __user *user_buf, \ | ||
75 | size_t count, loff_t *ppos); | ||
76 | |||
77 | #define DEBUGFS_WRITE_FUNC(name) \ | ||
78 | static ssize_t iwl_dbgfs_##name##_write(struct file *file, \ | ||
79 | const char __user *user_buf, \ | ||
80 | size_t count, loff_t *ppos); | ||
81 | |||
82 | |||
83 | #define DEBUGFS_READ_FILE_OPS(name) \ | 72 | #define DEBUGFS_READ_FILE_OPS(name) \ |
84 | DEBUGFS_READ_FUNC(name); \ | ||
85 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ | 73 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ |
86 | .read = iwl_dbgfs_##name##_read, \ | 74 | .read = iwl_dbgfs_##name##_read, \ |
87 | .open = simple_open, \ | 75 | .open = simple_open, \ |
@@ -89,7 +77,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ | |||
89 | }; | 77 | }; |
90 | 78 | ||
91 | #define DEBUGFS_WRITE_FILE_OPS(name) \ | 79 | #define DEBUGFS_WRITE_FILE_OPS(name) \ |
92 | DEBUGFS_WRITE_FUNC(name); \ | ||
93 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ | 80 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ |
94 | .write = iwl_dbgfs_##name##_write, \ | 81 | .write = iwl_dbgfs_##name##_write, \ |
95 | .open = simple_open, \ | 82 | .open = simple_open, \ |
@@ -98,8 +85,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ | |||
98 | 85 | ||
99 | 86 | ||
100 | #define DEBUGFS_READ_WRITE_FILE_OPS(name) \ | 87 | #define DEBUGFS_READ_WRITE_FILE_OPS(name) \ |
101 | DEBUGFS_READ_FUNC(name); \ | ||
102 | DEBUGFS_WRITE_FUNC(name); \ | ||
103 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ | 88 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ |
104 | .write = iwl_dbgfs_##name##_write, \ | 89 | .write = iwl_dbgfs_##name##_write, \ |
105 | .read = iwl_dbgfs_##name##_read, \ | 90 | .read = iwl_dbgfs_##name##_read, \ |
diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h index 60a4e0d15715..a79fdd137f95 100644 --- a/drivers/net/wireless/iwlwifi/dvm/dev.h +++ b/drivers/net/wireless/iwlwifi/dvm/dev.h | |||
@@ -540,7 +540,6 @@ struct iwl_rxon_context { | |||
540 | enum iwl_scan_type { | 540 | enum iwl_scan_type { |
541 | IWL_SCAN_NORMAL, | 541 | IWL_SCAN_NORMAL, |
542 | IWL_SCAN_RADIO_RESET, | 542 | IWL_SCAN_RADIO_RESET, |
543 | IWL_SCAN_ROC, | ||
544 | }; | 543 | }; |
545 | 544 | ||
546 | /** | 545 | /** |
@@ -825,12 +824,6 @@ struct iwl_priv { | |||
825 | struct reply_tx_error_statistics reply_tx_stats; | 824 | struct reply_tx_error_statistics reply_tx_stats; |
826 | struct reply_agg_tx_error_statistics reply_agg_tx_stats; | 825 | struct reply_agg_tx_error_statistics reply_agg_tx_stats; |
827 | 826 | ||
828 | /* remain-on-channel offload support */ | ||
829 | struct ieee80211_channel *hw_roc_channel; | ||
830 | struct delayed_work hw_roc_disable_work; | ||
831 | int hw_roc_duration; | ||
832 | bool hw_roc_setup, hw_roc_start_notified; | ||
833 | |||
834 | /* bt coex */ | 827 | /* bt coex */ |
835 | u8 bt_enable_flag; | 828 | u8 bt_enable_flag; |
836 | u8 bt_status; | 829 | u8 bt_status; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 822f1a00efbb..f0a2c957d503 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -76,29 +76,6 @@ static const struct ieee80211_iface_limit iwlagn_2sta_limits[] = { | |||
76 | }, | 76 | }, |
77 | }; | 77 | }; |
78 | 78 | ||
79 | static const struct ieee80211_iface_limit iwlagn_p2p_sta_go_limits[] = { | ||
80 | { | ||
81 | .max = 1, | ||
82 | .types = BIT(NL80211_IFTYPE_STATION), | ||
83 | }, | ||
84 | { | ||
85 | .max = 1, | ||
86 | .types = BIT(NL80211_IFTYPE_P2P_GO) | | ||
87 | BIT(NL80211_IFTYPE_AP), | ||
88 | }, | ||
89 | }; | ||
90 | |||
91 | static const struct ieee80211_iface_limit iwlagn_p2p_2sta_limits[] = { | ||
92 | { | ||
93 | .max = 2, | ||
94 | .types = BIT(NL80211_IFTYPE_STATION), | ||
95 | }, | ||
96 | { | ||
97 | .max = 1, | ||
98 | .types = BIT(NL80211_IFTYPE_P2P_CLIENT), | ||
99 | }, | ||
100 | }; | ||
101 | |||
102 | static const struct ieee80211_iface_combination | 79 | static const struct ieee80211_iface_combination |
103 | iwlagn_iface_combinations_dualmode[] = { | 80 | iwlagn_iface_combinations_dualmode[] = { |
104 | { .num_different_channels = 1, | 81 | { .num_different_channels = 1, |
@@ -114,21 +91,6 @@ iwlagn_iface_combinations_dualmode[] = { | |||
114 | }, | 91 | }, |
115 | }; | 92 | }; |
116 | 93 | ||
117 | static const struct ieee80211_iface_combination | ||
118 | iwlagn_iface_combinations_p2p[] = { | ||
119 | { .num_different_channels = 1, | ||
120 | .max_interfaces = 2, | ||
121 | .beacon_int_infra_match = true, | ||
122 | .limits = iwlagn_p2p_sta_go_limits, | ||
123 | .n_limits = ARRAY_SIZE(iwlagn_p2p_sta_go_limits), | ||
124 | }, | ||
125 | { .num_different_channels = 1, | ||
126 | .max_interfaces = 2, | ||
127 | .limits = iwlagn_p2p_2sta_limits, | ||
128 | .n_limits = ARRAY_SIZE(iwlagn_p2p_2sta_limits), | ||
129 | }, | ||
130 | }; | ||
131 | |||
132 | /* | 94 | /* |
133 | * Not a mac80211 entry point function, but it fits in with all the | 95 | * Not a mac80211 entry point function, but it fits in with all the |
134 | * other mac80211 functions grouped here. | 96 | * other mac80211 functions grouped here. |
@@ -186,19 +148,13 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | |||
186 | 148 | ||
187 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); | 149 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); |
188 | 150 | ||
189 | if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) { | 151 | if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) { |
190 | hw->wiphy->iface_combinations = iwlagn_iface_combinations_p2p; | ||
191 | hw->wiphy->n_iface_combinations = | ||
192 | ARRAY_SIZE(iwlagn_iface_combinations_p2p); | ||
193 | } else if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) { | ||
194 | hw->wiphy->iface_combinations = | 152 | hw->wiphy->iface_combinations = |
195 | iwlagn_iface_combinations_dualmode; | 153 | iwlagn_iface_combinations_dualmode; |
196 | hw->wiphy->n_iface_combinations = | 154 | hw->wiphy->n_iface_combinations = |
197 | ARRAY_SIZE(iwlagn_iface_combinations_dualmode); | 155 | ARRAY_SIZE(iwlagn_iface_combinations_dualmode); |
198 | } | 156 | } |
199 | 157 | ||
200 | hw->wiphy->max_remain_on_channel_duration = 500; | ||
201 | |||
202 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | | 158 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | |
203 | WIPHY_FLAG_DISABLE_BEACON_HINTS | | 159 | WIPHY_FLAG_DISABLE_BEACON_HINTS | |
204 | WIPHY_FLAG_IBSS_RSN; | 160 | WIPHY_FLAG_IBSS_RSN; |
@@ -1156,126 +1112,6 @@ done: | |||
1156 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 1112 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
1157 | } | 1113 | } |
1158 | 1114 | ||
1159 | static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw, | ||
1160 | struct ieee80211_vif *vif, | ||
1161 | struct ieee80211_channel *channel, | ||
1162 | int duration, | ||
1163 | enum ieee80211_roc_type type) | ||
1164 | { | ||
1165 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||
1166 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; | ||
1167 | int err = 0; | ||
1168 | |||
1169 | if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) | ||
1170 | return -EOPNOTSUPP; | ||
1171 | |||
1172 | if (!(ctx->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT))) | ||
1173 | return -EOPNOTSUPP; | ||
1174 | |||
1175 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
1176 | mutex_lock(&priv->mutex); | ||
1177 | |||
1178 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { | ||
1179 | /* mac80211 should not scan while ROC or ROC while scanning */ | ||
1180 | if (WARN_ON_ONCE(priv->scan_type != IWL_SCAN_RADIO_RESET)) { | ||
1181 | err = -EBUSY; | ||
1182 | goto out; | ||
1183 | } | ||
1184 | |||
1185 | iwl_scan_cancel_timeout(priv, 100); | ||
1186 | |||
1187 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { | ||
1188 | err = -EBUSY; | ||
1189 | goto out; | ||
1190 | } | ||
1191 | } | ||
1192 | |||
1193 | priv->hw_roc_channel = channel; | ||
1194 | /* convert from ms to TU */ | ||
1195 | priv->hw_roc_duration = DIV_ROUND_UP(1000 * duration, 1024); | ||
1196 | priv->hw_roc_start_notified = false; | ||
1197 | cancel_delayed_work(&priv->hw_roc_disable_work); | ||
1198 | |||
1199 | if (!ctx->is_active) { | ||
1200 | static const struct iwl_qos_info default_qos_data = { | ||
1201 | .def_qos_parm = { | ||
1202 | .ac[0] = { | ||
1203 | .cw_min = cpu_to_le16(3), | ||
1204 | .cw_max = cpu_to_le16(7), | ||
1205 | .aifsn = 2, | ||
1206 | .edca_txop = cpu_to_le16(1504), | ||
1207 | }, | ||
1208 | .ac[1] = { | ||
1209 | .cw_min = cpu_to_le16(7), | ||
1210 | .cw_max = cpu_to_le16(15), | ||
1211 | .aifsn = 2, | ||
1212 | .edca_txop = cpu_to_le16(3008), | ||
1213 | }, | ||
1214 | .ac[2] = { | ||
1215 | .cw_min = cpu_to_le16(15), | ||
1216 | .cw_max = cpu_to_le16(1023), | ||
1217 | .aifsn = 3, | ||
1218 | }, | ||
1219 | .ac[3] = { | ||
1220 | .cw_min = cpu_to_le16(15), | ||
1221 | .cw_max = cpu_to_le16(1023), | ||
1222 | .aifsn = 7, | ||
1223 | }, | ||
1224 | }, | ||
1225 | }; | ||
1226 | |||
1227 | ctx->is_active = true; | ||
1228 | ctx->qos_data = default_qos_data; | ||
1229 | ctx->staging.dev_type = RXON_DEV_TYPE_P2P; | ||
1230 | memcpy(ctx->staging.node_addr, | ||
1231 | priv->contexts[IWL_RXON_CTX_BSS].staging.node_addr, | ||
1232 | ETH_ALEN); | ||
1233 | memcpy(ctx->staging.bssid_addr, | ||
1234 | priv->contexts[IWL_RXON_CTX_BSS].staging.node_addr, | ||
1235 | ETH_ALEN); | ||
1236 | err = iwlagn_commit_rxon(priv, ctx); | ||
1237 | if (err) | ||
1238 | goto out; | ||
1239 | ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK | | ||
1240 | RXON_FILTER_PROMISC_MSK | | ||
1241 | RXON_FILTER_CTL2HOST_MSK; | ||
1242 | |||
1243 | err = iwlagn_commit_rxon(priv, ctx); | ||
1244 | if (err) { | ||
1245 | iwlagn_disable_roc(priv); | ||
1246 | goto out; | ||
1247 | } | ||
1248 | priv->hw_roc_setup = true; | ||
1249 | } | ||
1250 | |||
1251 | err = iwl_scan_initiate(priv, ctx->vif, IWL_SCAN_ROC, channel->band); | ||
1252 | if (err) | ||
1253 | iwlagn_disable_roc(priv); | ||
1254 | |||
1255 | out: | ||
1256 | mutex_unlock(&priv->mutex); | ||
1257 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
1258 | |||
1259 | return err; | ||
1260 | } | ||
1261 | |||
1262 | static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) | ||
1263 | { | ||
1264 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||
1265 | |||
1266 | if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) | ||
1267 | return -EOPNOTSUPP; | ||
1268 | |||
1269 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
1270 | mutex_lock(&priv->mutex); | ||
1271 | iwl_scan_cancel_timeout(priv, priv->hw_roc_duration); | ||
1272 | iwlagn_disable_roc(priv); | ||
1273 | mutex_unlock(&priv->mutex); | ||
1274 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
1275 | |||
1276 | return 0; | ||
1277 | } | ||
1278 | |||
1279 | static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, | 1115 | static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, |
1280 | struct ieee80211_vif *vif, | 1116 | struct ieee80211_vif *vif, |
1281 | enum ieee80211_rssi_event rssi_event) | 1117 | enum ieee80211_rssi_event rssi_event) |
@@ -1431,12 +1267,8 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw, | |||
1431 | IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", | 1267 | IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", |
1432 | viftype, vif->addr); | 1268 | viftype, vif->addr); |
1433 | 1269 | ||
1434 | cancel_delayed_work_sync(&priv->hw_roc_disable_work); | ||
1435 | |||
1436 | mutex_lock(&priv->mutex); | 1270 | mutex_lock(&priv->mutex); |
1437 | 1271 | ||
1438 | iwlagn_disable_roc(priv); | ||
1439 | |||
1440 | if (!iwl_is_ready_rf(priv)) { | 1272 | if (!iwl_is_ready_rf(priv)) { |
1441 | IWL_WARN(priv, "Try to add interface when device not ready\n"); | 1273 | IWL_WARN(priv, "Try to add interface when device not ready\n"); |
1442 | err = -EINVAL; | 1274 | err = -EINVAL; |
@@ -1763,8 +1595,6 @@ struct ieee80211_ops iwlagn_hw_ops = { | |||
1763 | .channel_switch = iwlagn_mac_channel_switch, | 1595 | .channel_switch = iwlagn_mac_channel_switch, |
1764 | .flush = iwlagn_mac_flush, | 1596 | .flush = iwlagn_mac_flush, |
1765 | .tx_last_beacon = iwlagn_mac_tx_last_beacon, | 1597 | .tx_last_beacon = iwlagn_mac_tx_last_beacon, |
1766 | .remain_on_channel = iwlagn_mac_remain_on_channel, | ||
1767 | .cancel_remain_on_channel = iwlagn_mac_cancel_remain_on_channel, | ||
1768 | .rssi_callback = iwlagn_mac_rssi_callback, | 1598 | .rssi_callback = iwlagn_mac_rssi_callback, |
1769 | .set_tim = iwlagn_mac_set_tim, | 1599 | .set_tim = iwlagn_mac_set_tim, |
1770 | }; | 1600 | }; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index 1531a4fc0960..7aad766865cf 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c | |||
@@ -587,11 +587,6 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | |||
587 | priv->contexts[IWL_RXON_CTX_PAN].interface_modes = | 587 | priv->contexts[IWL_RXON_CTX_PAN].interface_modes = |
588 | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP); | 588 | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP); |
589 | 589 | ||
590 | if (ucode_flags & IWL_UCODE_TLV_FLAGS_P2P) | ||
591 | priv->contexts[IWL_RXON_CTX_PAN].interface_modes |= | ||
592 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
593 | BIT(NL80211_IFTYPE_P2P_GO); | ||
594 | |||
595 | priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP; | 590 | priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP; |
596 | priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA; | 591 | priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA; |
597 | priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P; | 592 | priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P; |
@@ -854,14 +849,6 @@ void iwl_down(struct iwl_priv *priv) | |||
854 | 849 | ||
855 | iwl_scan_cancel_timeout(priv, 200); | 850 | iwl_scan_cancel_timeout(priv, 200); |
856 | 851 | ||
857 | /* | ||
858 | * If active, scanning won't cancel it, so say it expired. | ||
859 | * No race since we hold the mutex here and a new one | ||
860 | * can't come in at this time. | ||
861 | */ | ||
862 | if (priv->ucode_loaded && priv->cur_ucode != IWL_UCODE_INIT) | ||
863 | ieee80211_remain_on_channel_expired(priv->hw); | ||
864 | |||
865 | exit_pending = | 852 | exit_pending = |
866 | test_and_set_bit(STATUS_EXIT_PENDING, &priv->status); | 853 | test_and_set_bit(STATUS_EXIT_PENDING, &priv->status); |
867 | 854 | ||
@@ -1002,41 +989,6 @@ static void iwl_bg_restart(struct work_struct *data) | |||
1002 | } | 989 | } |
1003 | } | 990 | } |
1004 | 991 | ||
1005 | |||
1006 | |||
1007 | |||
1008 | void iwlagn_disable_roc(struct iwl_priv *priv) | ||
1009 | { | ||
1010 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; | ||
1011 | |||
1012 | lockdep_assert_held(&priv->mutex); | ||
1013 | |||
1014 | if (!priv->hw_roc_setup) | ||
1015 | return; | ||
1016 | |||
1017 | ctx->staging.dev_type = RXON_DEV_TYPE_P2P; | ||
1018 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | ||
1019 | |||
1020 | priv->hw_roc_channel = NULL; | ||
1021 | |||
1022 | memset(ctx->staging.node_addr, 0, ETH_ALEN); | ||
1023 | |||
1024 | iwlagn_commit_rxon(priv, ctx); | ||
1025 | |||
1026 | ctx->is_active = false; | ||
1027 | priv->hw_roc_setup = false; | ||
1028 | } | ||
1029 | |||
1030 | static void iwlagn_disable_roc_work(struct work_struct *work) | ||
1031 | { | ||
1032 | struct iwl_priv *priv = container_of(work, struct iwl_priv, | ||
1033 | hw_roc_disable_work.work); | ||
1034 | |||
1035 | mutex_lock(&priv->mutex); | ||
1036 | iwlagn_disable_roc(priv); | ||
1037 | mutex_unlock(&priv->mutex); | ||
1038 | } | ||
1039 | |||
1040 | /***************************************************************************** | 992 | /***************************************************************************** |
1041 | * | 993 | * |
1042 | * driver setup and teardown | 994 | * driver setup and teardown |
@@ -1053,8 +1005,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) | |||
1053 | INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush); | 1005 | INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush); |
1054 | INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency); | 1006 | INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency); |
1055 | INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config); | 1007 | INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config); |
1056 | INIT_DELAYED_WORK(&priv->hw_roc_disable_work, | ||
1057 | iwlagn_disable_roc_work); | ||
1058 | 1008 | ||
1059 | iwl_setup_scan_deferred_work(priv); | 1009 | iwl_setup_scan_deferred_work(priv); |
1060 | 1010 | ||
@@ -1082,7 +1032,6 @@ void iwl_cancel_deferred_work(struct iwl_priv *priv) | |||
1082 | 1032 | ||
1083 | cancel_work_sync(&priv->bt_full_concurrency); | 1033 | cancel_work_sync(&priv->bt_full_concurrency); |
1084 | cancel_work_sync(&priv->bt_runtime_config); | 1034 | cancel_work_sync(&priv->bt_runtime_config); |
1085 | cancel_delayed_work_sync(&priv->hw_roc_disable_work); | ||
1086 | 1035 | ||
1087 | del_timer_sync(&priv->statistics_periodic); | 1036 | del_timer_sync(&priv->statistics_periodic); |
1088 | del_timer_sync(&priv->ucode_trace); | 1037 | del_timer_sync(&priv->ucode_trace); |
@@ -1169,12 +1118,6 @@ static void iwl_option_config(struct iwl_priv *priv) | |||
1169 | #else | 1118 | #else |
1170 | IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TRACING disabled\n"); | 1119 | IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TRACING disabled\n"); |
1171 | #endif | 1120 | #endif |
1172 | |||
1173 | #ifdef CONFIG_IWLWIFI_P2P | ||
1174 | IWL_INFO(priv, "CONFIG_IWLWIFI_P2P enabled\n"); | ||
1175 | #else | ||
1176 | IWL_INFO(priv, "CONFIG_IWLWIFI_P2P disabled\n"); | ||
1177 | #endif | ||
1178 | } | 1121 | } |
1179 | 1122 | ||
1180 | static int iwl_eeprom_init_hw_params(struct iwl_priv *priv) | 1123 | static int iwl_eeprom_init_hw_params(struct iwl_priv *priv) |
@@ -1315,10 +1258,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1315 | 1258 | ||
1316 | ucode_flags = fw->ucode_capa.flags; | 1259 | ucode_flags = fw->ucode_capa.flags; |
1317 | 1260 | ||
1318 | #ifndef CONFIG_IWLWIFI_P2P | ||
1319 | ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P; | ||
1320 | #endif | ||
1321 | |||
1322 | if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) { | 1261 | if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) { |
1323 | priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; | 1262 | priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; |
1324 | trans_cfg.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; | 1263 | trans_cfg.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; |
@@ -1413,7 +1352,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1413 | * if not PAN, then don't support P2P -- might be a uCode | 1352 | * if not PAN, then don't support P2P -- might be a uCode |
1414 | * packaging bug or due to the eeprom check above | 1353 | * packaging bug or due to the eeprom check above |
1415 | */ | 1354 | */ |
1416 | ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P; | ||
1417 | priv->sta_key_max_num = STA_KEY_MAX_NUM; | 1355 | priv->sta_key_max_num = STA_KEY_MAX_NUM; |
1418 | trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; | 1356 | trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; |
1419 | 1357 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c index 91eb09b9b56f..b647e506564c 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rs.c +++ b/drivers/net/wireless/iwlwifi/dvm/rs.c | |||
@@ -2826,9 +2826,6 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i | |||
2826 | 2826 | ||
2827 | lq_sta->flush_timer = 0; | 2827 | lq_sta->flush_timer = 0; |
2828 | lq_sta->supp_rates = sta->supp_rates[sband->band]; | 2828 | lq_sta->supp_rates = sta->supp_rates[sband->band]; |
2829 | for (j = 0; j < LQ_SIZE; j++) | ||
2830 | for (i = 0; i < IWL_RATE_COUNT; i++) | ||
2831 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); | ||
2832 | 2829 | ||
2833 | IWL_DEBUG_RATE(priv, "LQ: *** rate scale station global init for station %d ***\n", | 2830 | IWL_DEBUG_RATE(priv, "LQ: *** rate scale station global init for station %d ***\n", |
2834 | sta_id); | 2831 | sta_id); |
diff --git a/drivers/net/wireless/iwlwifi/dvm/rxon.c b/drivers/net/wireless/iwlwifi/dvm/rxon.c index cd1ad0019185..d7ce2f12a907 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rxon.c +++ b/drivers/net/wireless/iwlwifi/dvm/rxon.c | |||
@@ -564,11 +564,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) | |||
564 | cmd.slots[0].type = 0; /* BSS */ | 564 | cmd.slots[0].type = 0; /* BSS */ |
565 | cmd.slots[1].type = 1; /* PAN */ | 565 | cmd.slots[1].type = 1; /* PAN */ |
566 | 566 | ||
567 | if (priv->hw_roc_setup) { | 567 | if (ctx_bss->vif && ctx_pan->vif) { |
568 | /* both contexts must be used for this to happen */ | ||
569 | slot1 = IWL_MIN_SLOT_TIME; | ||
570 | slot0 = 3000; | ||
571 | } else if (ctx_bss->vif && ctx_pan->vif) { | ||
572 | int bcnint = ctx_pan->beacon_int; | 568 | int bcnint = ctx_pan->beacon_int; |
573 | int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1; | 569 | int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1; |
574 | 570 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/scan.c b/drivers/net/wireless/iwlwifi/dvm/scan.c index 8c686a5b90ac..35e0ee8b4e5b 100644 --- a/drivers/net/wireless/iwlwifi/dvm/scan.c +++ b/drivers/net/wireless/iwlwifi/dvm/scan.c | |||
@@ -100,9 +100,6 @@ static void iwl_complete_scan(struct iwl_priv *priv, bool aborted) | |||
100 | ieee80211_scan_completed(priv->hw, aborted); | 100 | ieee80211_scan_completed(priv->hw, aborted); |
101 | } | 101 | } |
102 | 102 | ||
103 | if (priv->scan_type == IWL_SCAN_ROC) | ||
104 | iwl_scan_roc_expired(priv); | ||
105 | |||
106 | priv->scan_type = IWL_SCAN_NORMAL; | 103 | priv->scan_type = IWL_SCAN_NORMAL; |
107 | priv->scan_vif = NULL; | 104 | priv->scan_vif = NULL; |
108 | priv->scan_request = NULL; | 105 | priv->scan_request = NULL; |
@@ -130,9 +127,6 @@ static void iwl_process_scan_complete(struct iwl_priv *priv) | |||
130 | goto out_settings; | 127 | goto out_settings; |
131 | } | 128 | } |
132 | 129 | ||
133 | if (priv->scan_type == IWL_SCAN_ROC) | ||
134 | iwl_scan_roc_expired(priv); | ||
135 | |||
136 | if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) { | 130 | if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) { |
137 | int err; | 131 | int err; |
138 | 132 | ||
@@ -284,12 +278,6 @@ static int iwl_rx_scan_start_notif(struct iwl_priv *priv, | |||
284 | le32_to_cpu(notif->tsf_low), | 278 | le32_to_cpu(notif->tsf_low), |
285 | notif->status, notif->beacon_timer); | 279 | notif->status, notif->beacon_timer); |
286 | 280 | ||
287 | if (priv->scan_type == IWL_SCAN_ROC && | ||
288 | !priv->hw_roc_start_notified) { | ||
289 | ieee80211_ready_on_channel(priv->hw); | ||
290 | priv->hw_roc_start_notified = true; | ||
291 | } | ||
292 | |||
293 | return 0; | 281 | return 0; |
294 | } | 282 | } |
295 | 283 | ||
@@ -697,8 +685,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
697 | scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; | 685 | scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; |
698 | scan->quiet_time = IWL_ACTIVE_QUIET_TIME; | 686 | scan->quiet_time = IWL_ACTIVE_QUIET_TIME; |
699 | 687 | ||
700 | if (priv->scan_type != IWL_SCAN_ROC && | 688 | if (iwl_is_any_associated(priv)) { |
701 | iwl_is_any_associated(priv)) { | ||
702 | u16 interval = 0; | 689 | u16 interval = 0; |
703 | u32 extra; | 690 | u32 extra; |
704 | u32 suspend_time = 100; | 691 | u32 suspend_time = 100; |
@@ -706,9 +693,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
706 | 693 | ||
707 | IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); | 694 | IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); |
708 | switch (priv->scan_type) { | 695 | switch (priv->scan_type) { |
709 | case IWL_SCAN_ROC: | ||
710 | WARN_ON(1); | ||
711 | break; | ||
712 | case IWL_SCAN_RADIO_RESET: | 696 | case IWL_SCAN_RADIO_RESET: |
713 | interval = 0; | 697 | interval = 0; |
714 | break; | 698 | break; |
@@ -728,11 +712,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
728 | scan->suspend_time = cpu_to_le32(scan_suspend_time); | 712 | scan->suspend_time = cpu_to_le32(scan_suspend_time); |
729 | IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", | 713 | IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", |
730 | scan_suspend_time, interval); | 714 | scan_suspend_time, interval); |
731 | } else if (priv->scan_type == IWL_SCAN_ROC) { | ||
732 | scan->suspend_time = 0; | ||
733 | scan->max_out_time = 0; | ||
734 | scan->quiet_time = 0; | ||
735 | scan->quiet_plcp_th = 0; | ||
736 | } | 715 | } |
737 | 716 | ||
738 | switch (priv->scan_type) { | 717 | switch (priv->scan_type) { |
@@ -774,9 +753,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
774 | } else | 753 | } else |
775 | IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); | 754 | IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); |
776 | break; | 755 | break; |
777 | case IWL_SCAN_ROC: | ||
778 | IWL_DEBUG_SCAN(priv, "Start ROC scan.\n"); | ||
779 | break; | ||
780 | } | 756 | } |
781 | 757 | ||
782 | scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; | 758 | scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; |
@@ -898,7 +874,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
898 | scan_cmd_size - sizeof(*scan)); | 874 | scan_cmd_size - sizeof(*scan)); |
899 | break; | 875 | break; |
900 | case IWL_SCAN_RADIO_RESET: | 876 | case IWL_SCAN_RADIO_RESET: |
901 | case IWL_SCAN_ROC: | ||
902 | /* use bcast addr, will not be transmitted but must be valid */ | 877 | /* use bcast addr, will not be transmitted but must be valid */ |
903 | cmd_len = iwl_fill_probe_req( | 878 | cmd_len = iwl_fill_probe_req( |
904 | (struct ieee80211_mgmt *)scan->data, | 879 | (struct ieee80211_mgmt *)scan->data, |
@@ -926,46 +901,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
926 | is_active, n_probes, | 901 | is_active, n_probes, |
927 | (void *)&scan->data[cmd_len]); | 902 | (void *)&scan->data[cmd_len]); |
928 | break; | 903 | break; |
929 | case IWL_SCAN_ROC: { | ||
930 | struct iwl_scan_channel *scan_ch; | ||
931 | int n_chan, i; | ||
932 | u16 dwell; | ||
933 | |||
934 | dwell = iwl_limit_dwell(priv, priv->hw_roc_duration); | ||
935 | n_chan = DIV_ROUND_UP(priv->hw_roc_duration, dwell); | ||
936 | |||
937 | scan->channel_count = n_chan; | ||
938 | |||
939 | scan_ch = (void *)&scan->data[cmd_len]; | ||
940 | |||
941 | for (i = 0; i < n_chan; i++) { | ||
942 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; | ||
943 | scan_ch->channel = | ||
944 | cpu_to_le16(priv->hw_roc_channel->hw_value); | ||
945 | |||
946 | if (i == n_chan - 1) | ||
947 | dwell = priv->hw_roc_duration - i * dwell; | ||
948 | |||
949 | scan_ch->active_dwell = | ||
950 | scan_ch->passive_dwell = cpu_to_le16(dwell); | ||
951 | |||
952 | /* Set txpower levels to defaults */ | ||
953 | scan_ch->dsp_atten = 110; | ||
954 | |||
955 | /* NOTE: if we were doing 6Mb OFDM for scans we'd use | ||
956 | * power level: | ||
957 | * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; | ||
958 | */ | ||
959 | if (priv->hw_roc_channel->band == IEEE80211_BAND_5GHZ) | ||
960 | scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; | ||
961 | else | ||
962 | scan_ch->tx_gain = ((1 << 5) | (5 << 3)); | ||
963 | |||
964 | scan_ch++; | ||
965 | } | ||
966 | } | ||
967 | |||
968 | break; | ||
969 | } | 904 | } |
970 | 905 | ||
971 | if (scan->channel_count == 0) { | 906 | if (scan->channel_count == 0) { |
@@ -1035,7 +970,6 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, | |||
1035 | 970 | ||
1036 | IWL_DEBUG_SCAN(priv, "Starting %sscan...\n", | 971 | IWL_DEBUG_SCAN(priv, "Starting %sscan...\n", |
1037 | scan_type == IWL_SCAN_NORMAL ? "" : | 972 | scan_type == IWL_SCAN_NORMAL ? "" : |
1038 | scan_type == IWL_SCAN_ROC ? "remain-on-channel " : | ||
1039 | "internal short "); | 973 | "internal short "); |
1040 | 974 | ||
1041 | set_bit(STATUS_SCANNING, &priv->status); | 975 | set_bit(STATUS_SCANNING, &priv->status); |
@@ -1149,40 +1083,3 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv) | |||
1149 | mutex_unlock(&priv->mutex); | 1083 | mutex_unlock(&priv->mutex); |
1150 | } | 1084 | } |
1151 | } | 1085 | } |
1152 | |||
1153 | void iwl_scan_roc_expired(struct iwl_priv *priv) | ||
1154 | { | ||
1155 | /* | ||
1156 | * The status bit should be set here, to prevent a race | ||
1157 | * where the atomic_read returns 1, but before the execution continues | ||
1158 | * iwl_scan_offchannel_skb_status() checks if the status bit is set | ||
1159 | */ | ||
1160 | set_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status); | ||
1161 | |||
1162 | if (atomic_read(&priv->num_aux_in_flight) == 0) { | ||
1163 | ieee80211_remain_on_channel_expired(priv->hw); | ||
1164 | priv->hw_roc_channel = NULL; | ||
1165 | schedule_delayed_work(&priv->hw_roc_disable_work, | ||
1166 | 10 * HZ); | ||
1167 | |||
1168 | clear_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status); | ||
1169 | } else { | ||
1170 | IWL_DEBUG_SCAN(priv, "ROC done with %d frames in aux\n", | ||
1171 | atomic_read(&priv->num_aux_in_flight)); | ||
1172 | } | ||
1173 | } | ||
1174 | |||
1175 | void iwl_scan_offchannel_skb(struct iwl_priv *priv) | ||
1176 | { | ||
1177 | WARN_ON(!priv->hw_roc_start_notified); | ||
1178 | atomic_inc(&priv->num_aux_in_flight); | ||
1179 | } | ||
1180 | |||
1181 | void iwl_scan_offchannel_skb_status(struct iwl_priv *priv) | ||
1182 | { | ||
1183 | if (atomic_dec_return(&priv->num_aux_in_flight) == 0 && | ||
1184 | test_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status)) { | ||
1185 | IWL_DEBUG_SCAN(priv, "0 aux frames. Calling ROC expired\n"); | ||
1186 | iwl_scan_roc_expired(priv); | ||
1187 | } | ||
1188 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index 5ee983faa679..3db0bbb1d123 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
@@ -478,9 +478,6 @@ int iwlagn_tx_skb(struct iwl_priv *priv, | |||
478 | if (sta_priv && sta_priv->client && !is_agg) | 478 | if (sta_priv && sta_priv->client && !is_agg) |
479 | atomic_inc(&sta_priv->pending_frames); | 479 | atomic_inc(&sta_priv->pending_frames); |
480 | 480 | ||
481 | if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) | ||
482 | iwl_scan_offchannel_skb(priv); | ||
483 | |||
484 | return 0; | 481 | return 0; |
485 | 482 | ||
486 | drop_unlock_sta: | 483 | drop_unlock_sta: |
@@ -1158,7 +1155,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1158 | struct sk_buff *skb; | 1155 | struct sk_buff *skb; |
1159 | struct iwl_rxon_context *ctx; | 1156 | struct iwl_rxon_context *ctx; |
1160 | bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); | 1157 | bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); |
1161 | bool is_offchannel_skb; | ||
1162 | 1158 | ||
1163 | tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> | 1159 | tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> |
1164 | IWLAGN_TX_RES_TID_POS; | 1160 | IWLAGN_TX_RES_TID_POS; |
@@ -1178,8 +1174,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1178 | 1174 | ||
1179 | __skb_queue_head_init(&skbs); | 1175 | __skb_queue_head_init(&skbs); |
1180 | 1176 | ||
1181 | is_offchannel_skb = false; | ||
1182 | |||
1183 | if (tx_resp->frame_count == 1) { | 1177 | if (tx_resp->frame_count == 1) { |
1184 | u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl); | 1178 | u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl); |
1185 | next_reclaimed = IEEE80211_SEQ_TO_SN(next_reclaimed + 0x10); | 1179 | next_reclaimed = IEEE80211_SEQ_TO_SN(next_reclaimed + 0x10); |
@@ -1256,8 +1250,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1256 | if (!is_agg) | 1250 | if (!is_agg) |
1257 | iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); | 1251 | iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); |
1258 | 1252 | ||
1259 | is_offchannel_skb = | ||
1260 | (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN); | ||
1261 | freed++; | 1253 | freed++; |
1262 | } | 1254 | } |
1263 | 1255 | ||
@@ -1271,14 +1263,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1271 | if (!is_agg && freed != 1) | 1263 | if (!is_agg && freed != 1) |
1272 | IWL_ERR(priv, "Q: %d, freed %d\n", txq_id, freed); | 1264 | IWL_ERR(priv, "Q: %d, freed %d\n", txq_id, freed); |
1273 | 1265 | ||
1274 | /* | ||
1275 | * An offchannel frame can be send only on the AUX queue, where | ||
1276 | * there is no aggregation (and reordering) so it only is single | ||
1277 | * skb is expected to be processed. | ||
1278 | */ | ||
1279 | if (is_offchannel_skb && freed != 1) | ||
1280 | IWL_ERR(priv, "OFFCHANNEL SKB freed %d\n", freed); | ||
1281 | |||
1282 | IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x)\n", txq_id, | 1266 | IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x)\n", txq_id, |
1283 | iwl_get_tx_fail_reason(status), status); | 1267 | iwl_get_tx_fail_reason(status), status); |
1284 | 1268 | ||
@@ -1298,9 +1282,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1298 | ieee80211_tx_status_ni(priv->hw, skb); | 1282 | ieee80211_tx_status_ni(priv->hw, skb); |
1299 | } | 1283 | } |
1300 | 1284 | ||
1301 | if (is_offchannel_skb) | ||
1302 | iwl_scan_offchannel_skb_status(priv); | ||
1303 | |||
1304 | return 0; | 1285 | return 0; |
1305 | } | 1286 | } |
1306 | 1287 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 22b7fa5b971a..76e14c046d94 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c | |||
@@ -99,6 +99,7 @@ static const struct iwl_base_params iwl7000_base_params = { | |||
99 | .wd_timeout = IWL_LONG_WD_TIMEOUT, | 99 | .wd_timeout = IWL_LONG_WD_TIMEOUT, |
100 | .max_event_log_size = 512, | 100 | .max_event_log_size = 512, |
101 | .shadow_reg_enable = true, | 101 | .shadow_reg_enable = true, |
102 | .pcie_l1_allowed = true, | ||
102 | }; | 103 | }; |
103 | 104 | ||
104 | static const struct iwl_ht_params iwl7000_ht_params = { | 105 | static const struct iwl_ht_params iwl7000_ht_params = { |
@@ -126,6 +127,16 @@ const struct iwl_cfg iwl7260_2ac_cfg = { | |||
126 | .nvm_calib_ver = IWL7260_TX_POWER_VERSION, | 127 | .nvm_calib_ver = IWL7260_TX_POWER_VERSION, |
127 | }; | 128 | }; |
128 | 129 | ||
130 | const struct iwl_cfg iwl7260_2ac_cfg_high_temp = { | ||
131 | .name = "Intel(R) Dual Band Wireless AC 7260", | ||
132 | .fw_name_pre = IWL7260_FW_PRE, | ||
133 | IWL_DEVICE_7000, | ||
134 | .ht_params = &iwl7000_ht_params, | ||
135 | .nvm_ver = IWL7260_NVM_VERSION, | ||
136 | .nvm_calib_ver = IWL7260_TX_POWER_VERSION, | ||
137 | .high_temp = true, | ||
138 | }; | ||
139 | |||
129 | const struct iwl_cfg iwl7260_2n_cfg = { | 140 | const struct iwl_cfg iwl7260_2n_cfg = { |
130 | .name = "Intel(R) Dual Band Wireless N 7260", | 141 | .name = "Intel(R) Dual Band Wireless N 7260", |
131 | .fw_name_pre = IWL7260_FW_PRE, | 142 | .fw_name_pre = IWL7260_FW_PRE, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index 83b9ff6ff3ad..e4d370bff306 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h | |||
@@ -152,6 +152,7 @@ struct iwl_base_params { | |||
152 | unsigned int wd_timeout; | 152 | unsigned int wd_timeout; |
153 | u32 max_event_log_size; | 153 | u32 max_event_log_size; |
154 | const bool shadow_reg_enable; | 154 | const bool shadow_reg_enable; |
155 | const bool pcie_l1_allowed; | ||
155 | }; | 156 | }; |
156 | 157 | ||
157 | /* | 158 | /* |
@@ -205,6 +206,7 @@ struct iwl_eeprom_params { | |||
205 | * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off) | 206 | * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off) |
206 | * @rx_with_siso_diversity: 1x1 device with rx antenna diversity | 207 | * @rx_with_siso_diversity: 1x1 device with rx antenna diversity |
207 | * @internal_wimax_coex: internal wifi/wimax combo device | 208 | * @internal_wimax_coex: internal wifi/wimax combo device |
209 | * @high_temp: Is this NIC is designated to be in high temperature. | ||
208 | * | 210 | * |
209 | * We enable the driver to be backward compatible wrt. hardware features. | 211 | * We enable the driver to be backward compatible wrt. hardware features. |
210 | * API differences in uCode shouldn't be handled here but through TLVs | 212 | * API differences in uCode shouldn't be handled here but through TLVs |
@@ -233,6 +235,7 @@ struct iwl_cfg { | |||
233 | enum iwl_led_mode led_mode; | 235 | enum iwl_led_mode led_mode; |
234 | const bool rx_with_siso_diversity; | 236 | const bool rx_with_siso_diversity; |
235 | const bool internal_wimax_coex; | 237 | const bool internal_wimax_coex; |
238 | bool high_temp; | ||
236 | }; | 239 | }; |
237 | 240 | ||
238 | /* | 241 | /* |
@@ -283,6 +286,7 @@ extern const struct iwl_cfg iwl135_bgn_cfg; | |||
283 | #endif /* CONFIG_IWLDVM */ | 286 | #endif /* CONFIG_IWLDVM */ |
284 | #if IS_ENABLED(CONFIG_IWLMVM) | 287 | #if IS_ENABLED(CONFIG_IWLMVM) |
285 | extern const struct iwl_cfg iwl7260_2ac_cfg; | 288 | extern const struct iwl_cfg iwl7260_2ac_cfg; |
289 | extern const struct iwl_cfg iwl7260_2ac_cfg_high_temp; | ||
286 | extern const struct iwl_cfg iwl7260_2n_cfg; | 290 | extern const struct iwl_cfg iwl7260_2n_cfg; |
287 | extern const struct iwl_cfg iwl7260_n_cfg; | 291 | extern const struct iwl_cfg iwl7260_n_cfg; |
288 | extern const struct iwl_cfg iwl3160_2ac_cfg; | 292 | extern const struct iwl_cfg iwl3160_2ac_cfg; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index f844d5c748c0..bd335f0c40d1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h | |||
@@ -74,13 +74,22 @@ | |||
74 | * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). | 74 | * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). |
75 | * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P. | 75 | * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P. |
76 | * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS | 76 | * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS |
77 | * @IWL_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD | ||
78 | * @IWL_UCODE_TLV_FLAGS_RX_ENERGY_API: supports rx signal strength api | ||
79 | * @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six | ||
80 | * (rather than two) IPv6 addresses | ||
81 | * @IWL_UCODE_TLV_FLAGS_BF_UPDATED: new beacon filtering API | ||
77 | */ | 82 | */ |
78 | enum iwl_ucode_tlv_flag { | 83 | enum iwl_ucode_tlv_flag { |
79 | IWL_UCODE_TLV_FLAGS_PAN = BIT(0), | 84 | IWL_UCODE_TLV_FLAGS_PAN = BIT(0), |
80 | IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1), | 85 | IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1), |
81 | IWL_UCODE_TLV_FLAGS_MFP = BIT(2), | 86 | IWL_UCODE_TLV_FLAGS_MFP = BIT(2), |
82 | IWL_UCODE_TLV_FLAGS_P2P = BIT(3), | 87 | IWL_UCODE_TLV_FLAGS_P2P = BIT(3), |
83 | IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4), | 88 | IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4), |
89 | IWL_UCODE_TLV_FLAGS_UAPSD = BIT(6), | ||
90 | IWL_UCODE_TLV_FLAGS_RX_ENERGY_API = BIT(8), | ||
91 | IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS = BIT(10), | ||
92 | IWL_UCODE_TLV_FLAGS_BF_UPDATED = BIT(11), | ||
84 | }; | 93 | }; |
85 | 94 | ||
86 | /* The default calibrate table size if not specified by firmware file */ | 95 | /* The default calibrate table size if not specified by firmware file */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index 305c81f2c2b4..dfa4d2e3aaa2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c | |||
@@ -33,6 +33,8 @@ | |||
33 | #include "iwl-io.h" | 33 | #include "iwl-io.h" |
34 | #include "iwl-csr.h" | 34 | #include "iwl-csr.h" |
35 | #include "iwl-debug.h" | 35 | #include "iwl-debug.h" |
36 | #include "iwl-fh.h" | ||
37 | #include "iwl-csr.h" | ||
36 | 38 | ||
37 | #define IWL_POLL_INTERVAL 10 /* microseconds */ | 39 | #define IWL_POLL_INTERVAL 10 /* microseconds */ |
38 | 40 | ||
@@ -166,3 +168,68 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) | |||
166 | } | 168 | } |
167 | } | 169 | } |
168 | IWL_EXPORT_SYMBOL(iwl_clear_bits_prph); | 170 | IWL_EXPORT_SYMBOL(iwl_clear_bits_prph); |
171 | |||
172 | static const char *get_fh_string(int cmd) | ||
173 | { | ||
174 | #define IWL_CMD(x) case x: return #x | ||
175 | switch (cmd) { | ||
176 | IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); | ||
177 | IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG); | ||
178 | IWL_CMD(FH_RSCSR_CHNL0_WPTR); | ||
179 | IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG); | ||
180 | IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG); | ||
181 | IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG); | ||
182 | IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV); | ||
183 | IWL_CMD(FH_TSSR_TX_STATUS_REG); | ||
184 | IWL_CMD(FH_TSSR_TX_ERROR_REG); | ||
185 | default: | ||
186 | return "UNKNOWN"; | ||
187 | } | ||
188 | #undef IWL_CMD | ||
189 | } | ||
190 | |||
191 | int iwl_dump_fh(struct iwl_trans *trans, char **buf) | ||
192 | { | ||
193 | int i; | ||
194 | static const u32 fh_tbl[] = { | ||
195 | FH_RSCSR_CHNL0_STTS_WPTR_REG, | ||
196 | FH_RSCSR_CHNL0_RBDCB_BASE_REG, | ||
197 | FH_RSCSR_CHNL0_WPTR, | ||
198 | FH_MEM_RCSR_CHNL0_CONFIG_REG, | ||
199 | FH_MEM_RSSR_SHARED_CTRL_REG, | ||
200 | FH_MEM_RSSR_RX_STATUS_REG, | ||
201 | FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV, | ||
202 | FH_TSSR_TX_STATUS_REG, | ||
203 | FH_TSSR_TX_ERROR_REG | ||
204 | }; | ||
205 | |||
206 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
207 | if (buf) { | ||
208 | int pos = 0; | ||
209 | size_t bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; | ||
210 | |||
211 | *buf = kmalloc(bufsz, GFP_KERNEL); | ||
212 | if (!*buf) | ||
213 | return -ENOMEM; | ||
214 | |||
215 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
216 | "FH register values:\n"); | ||
217 | |||
218 | for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) | ||
219 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
220 | " %34s: 0X%08x\n", | ||
221 | get_fh_string(fh_tbl[i]), | ||
222 | iwl_read_direct32(trans, fh_tbl[i])); | ||
223 | |||
224 | return pos; | ||
225 | } | ||
226 | #endif | ||
227 | |||
228 | IWL_ERR(trans, "FH register values:\n"); | ||
229 | for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) | ||
230 | IWL_ERR(trans, " %34s: 0X%08x\n", | ||
231 | get_fh_string(fh_tbl[i]), | ||
232 | iwl_read_direct32(trans, fh_tbl[i])); | ||
233 | |||
234 | return 0; | ||
235 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index fd9f5b97fff3..63d10ec08dbc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h | |||
@@ -77,4 +77,7 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, | |||
77 | u32 bits, u32 mask); | 77 | u32 bits, u32 mask); |
78 | void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); | 78 | void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); |
79 | 79 | ||
80 | /* Error handling */ | ||
81 | int iwl_dump_fh(struct iwl_trans *trans, char **buf); | ||
82 | |||
80 | #endif | 83 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index acd2665afb8c..b76a9a8fc0b3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | |||
@@ -118,6 +118,7 @@ static const u8 iwl_nvm_channels[] = { | |||
118 | #define LAST_2GHZ_HT_PLUS 9 | 118 | #define LAST_2GHZ_HT_PLUS 9 |
119 | #define LAST_5GHZ_HT 161 | 119 | #define LAST_5GHZ_HT 161 |
120 | 120 | ||
121 | #define DEFAULT_MAX_TX_POWER 16 | ||
121 | 122 | ||
122 | /* rate data (static) */ | 123 | /* rate data (static) */ |
123 | static struct ieee80211_rate iwl_cfg80211_rates[] = { | 124 | static struct ieee80211_rate iwl_cfg80211_rates[] = { |
@@ -232,8 +233,11 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
232 | 233 | ||
233 | /* Initialize regulatory-based run-time data */ | 234 | /* Initialize regulatory-based run-time data */ |
234 | 235 | ||
235 | /* TODO: read the real value from the NVM */ | 236 | /* |
236 | channel->max_power = 0; | 237 | * Default value - highest tx power value. max_power |
238 | * is not used in mvm, and is used for backwards compatibility | ||
239 | */ | ||
240 | channel->max_power = DEFAULT_MAX_TX_POWER; | ||
237 | is_5ghz = channel->band == IEEE80211_BAND_5GHZ; | 241 | is_5ghz = channel->band == IEEE80211_BAND_5GHZ; |
238 | IWL_DEBUG_EEPROM(dev, | 242 | IWL_DEBUG_EEPROM(dev, |
239 | "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n", | 243 | "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n", |
diff --git a/drivers/net/wireless/iwlwifi/mvm/Makefile b/drivers/net/wireless/iwlwifi/mvm/Makefile index ff856e543ae8..6d73817850ce 100644 --- a/drivers/net/wireless/iwlwifi/mvm/Makefile +++ b/drivers/net/wireless/iwlwifi/mvm/Makefile | |||
@@ -2,7 +2,7 @@ obj-$(CONFIG_IWLMVM) += iwlmvm.o | |||
2 | iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o | 2 | iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o |
3 | iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o | 3 | iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o |
4 | iwlmvm-y += scan.o time-event.o rs.o | 4 | iwlmvm-y += scan.o time-event.o rs.o |
5 | iwlmvm-y += power.o bt-coex.o | 5 | iwlmvm-y += power.o power_legacy.o bt-coex.o |
6 | iwlmvm-y += led.o tt.o | 6 | iwlmvm-y += led.o tt.o |
7 | iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o | 7 | iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o |
8 | iwlmvm-$(CONFIG_PM_SLEEP) += d3.o | 8 | iwlmvm-$(CONFIG_PM_SLEEP) += d3.o |
diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c index dbd622a3929c..0fad98b85f60 100644 --- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c | |||
@@ -220,66 +220,87 @@ static const __le32 iwl_single_shared_ant_lookup[BT_COEX_LUT_SIZE] = { | |||
220 | 220 | ||
221 | int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | 221 | int iwl_send_bt_init_conf(struct iwl_mvm *mvm) |
222 | { | 222 | { |
223 | struct iwl_bt_coex_cmd cmd = { | 223 | struct iwl_bt_coex_cmd *bt_cmd; |
224 | .max_kill = 5, | 224 | struct iwl_host_cmd cmd = { |
225 | .bt3_time_t7_value = 1, | 225 | .id = BT_CONFIG, |
226 | .bt3_prio_sample_time = 2, | 226 | .len = { sizeof(*bt_cmd), }, |
227 | .bt3_timer_t2_value = 0xc, | 227 | .dataflags = { IWL_HCMD_DFL_NOCOPY, }, |
228 | .flags = CMD_SYNC, | ||
228 | }; | 229 | }; |
229 | int ret; | 230 | int ret; |
230 | 231 | ||
231 | cmd.flags = iwlwifi_mod_params.bt_coex_active ? | 232 | /* go to CALIB state in internal BT-Coex state machine */ |
233 | ret = iwl_send_bt_env(mvm, BT_COEX_ENV_OPEN, | ||
234 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); | ||
235 | if (ret) | ||
236 | return ret; | ||
237 | |||
238 | ret = iwl_send_bt_env(mvm, BT_COEX_ENV_CLOSE, | ||
239 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); | ||
240 | if (ret) | ||
241 | return ret; | ||
242 | |||
243 | bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL); | ||
244 | if (!bt_cmd) | ||
245 | return -ENOMEM; | ||
246 | cmd.data[0] = bt_cmd; | ||
247 | |||
248 | bt_cmd->max_kill = 5; | ||
249 | bt_cmd->bt3_time_t7_value = 1; | ||
250 | bt_cmd->bt3_prio_sample_time = 2; | ||
251 | bt_cmd->bt3_timer_t2_value = 0xc; | ||
252 | |||
253 | bt_cmd->flags = iwlwifi_mod_params.bt_coex_active ? | ||
232 | BT_COEX_NW : BT_COEX_DISABLE; | 254 | BT_COEX_NW : BT_COEX_DISABLE; |
233 | cmd.flags |= BT_CH_PRIMARY_EN | BT_SYNC_2_BT_DISABLE; | 255 | bt_cmd->flags |= BT_CH_PRIMARY_EN | BT_SYNC_2_BT_DISABLE; |
234 | 256 | ||
235 | cmd.valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE | | 257 | bt_cmd->valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE | |
236 | BT_VALID_BT_PRIO_BOOST | | 258 | BT_VALID_BT_PRIO_BOOST | |
237 | BT_VALID_MAX_KILL | | 259 | BT_VALID_MAX_KILL | |
238 | BT_VALID_3W_TMRS | | 260 | BT_VALID_3W_TMRS | |
239 | BT_VALID_KILL_ACK | | 261 | BT_VALID_KILL_ACK | |
240 | BT_VALID_KILL_CTS | | 262 | BT_VALID_KILL_CTS | |
241 | BT_VALID_REDUCED_TX_POWER | | 263 | BT_VALID_REDUCED_TX_POWER | |
242 | BT_VALID_LUT); | 264 | BT_VALID_LUT); |
243 | 265 | ||
244 | if (mvm->cfg->bt_shared_single_ant) | 266 | if (mvm->cfg->bt_shared_single_ant) |
245 | memcpy(&cmd.decision_lut, iwl_single_shared_ant_lookup, | 267 | memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant_lookup, |
246 | sizeof(iwl_single_shared_ant_lookup)); | 268 | sizeof(iwl_single_shared_ant_lookup)); |
247 | else if (is_loose_coex()) | 269 | else if (is_loose_coex()) |
248 | memcpy(&cmd.decision_lut, iwl_loose_lookup, | 270 | memcpy(&bt_cmd->decision_lut, iwl_loose_lookup, |
249 | sizeof(iwl_tight_lookup)); | 271 | sizeof(iwl_tight_lookup)); |
250 | else | 272 | else |
251 | memcpy(&cmd.decision_lut, iwl_tight_lookup, | 273 | memcpy(&bt_cmd->decision_lut, iwl_tight_lookup, |
252 | sizeof(iwl_tight_lookup)); | 274 | sizeof(iwl_tight_lookup)); |
253 | 275 | ||
254 | cmd.bt_prio_boost = cpu_to_le32(IWL_BT_DEFAULT_BOOST); | 276 | bt_cmd->bt_prio_boost = cpu_to_le32(IWL_BT_DEFAULT_BOOST); |
255 | cmd.kill_ack_msk = | 277 | bt_cmd->kill_ack_msk = |
256 | cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]); | 278 | cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]); |
257 | cmd.kill_cts_msk = | 279 | bt_cmd->kill_cts_msk = |
258 | cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]); | 280 | cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]); |
259 | 281 | ||
260 | memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); | 282 | memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); |
261 | 283 | ||
262 | /* go to CALIB state in internal BT-Coex state machine */ | 284 | ret = iwl_mvm_send_cmd(mvm, &cmd); |
263 | ret = iwl_send_bt_env(mvm, BT_COEX_ENV_OPEN, | ||
264 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); | ||
265 | if (ret) | ||
266 | return ret; | ||
267 | |||
268 | ret = iwl_send_bt_env(mvm, BT_COEX_ENV_CLOSE, | ||
269 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); | ||
270 | if (ret) | ||
271 | return ret; | ||
272 | 285 | ||
273 | return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC, | 286 | kfree(bt_cmd); |
274 | sizeof(cmd), &cmd); | 287 | return ret; |
275 | } | 288 | } |
276 | 289 | ||
277 | static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm, | 290 | static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm, |
278 | bool reduced_tx_power) | 291 | bool reduced_tx_power) |
279 | { | 292 | { |
280 | enum iwl_bt_kill_msk bt_kill_msk; | 293 | enum iwl_bt_kill_msk bt_kill_msk; |
281 | struct iwl_bt_coex_cmd cmd = {}; | 294 | struct iwl_bt_coex_cmd *bt_cmd; |
282 | struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif; | 295 | struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif; |
296 | struct iwl_host_cmd cmd = { | ||
297 | .id = BT_CONFIG, | ||
298 | .data[0] = &bt_cmd, | ||
299 | .len = { sizeof(*bt_cmd), }, | ||
300 | .dataflags = { IWL_HCMD_DFL_NOCOPY, }, | ||
301 | .flags = CMD_SYNC, | ||
302 | }; | ||
303 | int ret = 0; | ||
283 | 304 | ||
284 | lockdep_assert_held(&mvm->mutex); | 305 | lockdep_assert_held(&mvm->mutex); |
285 | 306 | ||
@@ -308,24 +329,40 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm, | |||
308 | return 0; | 329 | return 0; |
309 | 330 | ||
310 | mvm->bt_kill_msk = bt_kill_msk; | 331 | mvm->bt_kill_msk = bt_kill_msk; |
311 | cmd.kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]); | 332 | |
312 | cmd.kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]); | 333 | bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL); |
313 | cmd.valid_bit_msk = cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS); | 334 | if (!bt_cmd) |
335 | return -ENOMEM; | ||
336 | cmd.data[0] = bt_cmd; | ||
337 | |||
338 | bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]); | ||
339 | bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]); | ||
340 | bt_cmd->valid_bit_msk = | ||
341 | cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS); | ||
314 | 342 | ||
315 | IWL_DEBUG_COEX(mvm, "bt_kill_msk = %d\n", bt_kill_msk); | 343 | IWL_DEBUG_COEX(mvm, "bt_kill_msk = %d\n", bt_kill_msk); |
316 | return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC, | 344 | |
317 | sizeof(cmd), &cmd); | 345 | ret = iwl_mvm_send_cmd(mvm, &cmd); |
346 | |||
347 | kfree(bt_cmd); | ||
348 | return ret; | ||
318 | } | 349 | } |
319 | 350 | ||
320 | static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, | 351 | static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, |
321 | bool enable) | 352 | bool enable) |
322 | { | 353 | { |
323 | struct iwl_bt_coex_cmd cmd = { | 354 | struct iwl_bt_coex_cmd *bt_cmd; |
324 | .valid_bit_msk = cpu_to_le16(BT_VALID_REDUCED_TX_POWER), | 355 | /* Send ASYNC since this can be sent from an atomic context */ |
325 | .bt_reduced_tx_power = sta_id, | 356 | struct iwl_host_cmd cmd = { |
357 | .id = BT_CONFIG, | ||
358 | .len = { sizeof(*bt_cmd), }, | ||
359 | .dataflags = { IWL_HCMD_DFL_DUP, }, | ||
360 | .flags = CMD_ASYNC, | ||
326 | }; | 361 | }; |
362 | |||
327 | struct ieee80211_sta *sta; | 363 | struct ieee80211_sta *sta; |
328 | struct iwl_mvm_sta *mvmsta; | 364 | struct iwl_mvm_sta *mvmsta; |
365 | int ret; | ||
329 | 366 | ||
330 | /* This can happen if the station has been removed right now */ | 367 | /* This can happen if the station has been removed right now */ |
331 | if (sta_id == IWL_MVM_STATION_COUNT) | 368 | if (sta_id == IWL_MVM_STATION_COUNT) |
@@ -339,17 +376,26 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, | |||
339 | if (mvmsta->bt_reduced_txpower == enable) | 376 | if (mvmsta->bt_reduced_txpower == enable) |
340 | return 0; | 377 | return 0; |
341 | 378 | ||
379 | bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_ATOMIC); | ||
380 | if (!bt_cmd) | ||
381 | return -ENOMEM; | ||
382 | cmd.data[0] = bt_cmd; | ||
383 | |||
384 | bt_cmd->valid_bit_msk = cpu_to_le16(BT_VALID_REDUCED_TX_POWER), | ||
385 | bt_cmd->bt_reduced_tx_power = sta_id; | ||
386 | |||
342 | if (enable) | 387 | if (enable) |
343 | cmd.bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT; | 388 | bt_cmd->bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT; |
344 | 389 | ||
345 | IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n", | 390 | IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n", |
346 | enable ? "en" : "dis", sta_id); | 391 | enable ? "en" : "dis", sta_id); |
347 | 392 | ||
348 | mvmsta->bt_reduced_txpower = enable; | 393 | mvmsta->bt_reduced_txpower = enable; |
349 | 394 | ||
350 | /* Send ASYNC since this can be sent from an atomic context */ | 395 | ret = iwl_mvm_send_cmd(mvm, &cmd); |
351 | return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_ASYNC, | 396 | |
352 | sizeof(cmd), &cmd); | 397 | kfree(bt_cmd); |
398 | return ret; | ||
353 | } | 399 | } |
354 | 400 | ||
355 | struct iwl_bt_iterator_data { | 401 | struct iwl_bt_iterator_data { |
@@ -384,6 +430,10 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
384 | 430 | ||
385 | smps_mode = IEEE80211_SMPS_AUTOMATIC; | 431 | smps_mode = IEEE80211_SMPS_AUTOMATIC; |
386 | 432 | ||
433 | /* non associated BSSes aren't to be considered */ | ||
434 | if (!vif->bss_conf.assoc) | ||
435 | return; | ||
436 | |||
387 | if (band != IEEE80211_BAND_2GHZ) { | 437 | if (band != IEEE80211_BAND_2GHZ) { |
388 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, | 438 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, |
389 | smps_mode); | 439 | smps_mode); |
@@ -523,6 +573,8 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac, | |||
523 | lockdep_is_held(&mvm->mutex)); | 573 | lockdep_is_held(&mvm->mutex)); |
524 | mvmsta = (void *)sta->drv_priv; | 574 | mvmsta = (void *)sta->drv_priv; |
525 | 575 | ||
576 | data->num_bss_ifaces++; | ||
577 | |||
526 | /* | 578 | /* |
527 | * This interface doesn't support reduced Tx power (because of low | 579 | * This interface doesn't support reduced Tx power (because of low |
528 | * RSSI probably), then set bt_kill_msk to default values. | 580 | * RSSI probably), then set bt_kill_msk to default values. |
@@ -588,23 +640,5 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
588 | 640 | ||
589 | void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | 641 | void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif) |
590 | { | 642 | { |
591 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
592 | enum ieee80211_band band; | ||
593 | |||
594 | rcu_read_lock(); | ||
595 | chanctx_conf = rcu_dereference(vif->chanctx_conf); | ||
596 | if (chanctx_conf && chanctx_conf->def.chan) | ||
597 | band = chanctx_conf->def.chan->band; | ||
598 | else | ||
599 | band = -1; | ||
600 | rcu_read_unlock(); | ||
601 | |||
602 | /* if we are in 2GHz we will get a notification from the fw */ | ||
603 | if (band == IEEE80211_BAND_2GHZ) | ||
604 | return; | ||
605 | |||
606 | /* else, we can remove all the constraints */ | ||
607 | memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); | ||
608 | |||
609 | iwl_mvm_bt_coex_notif_handle(mvm); | 643 | iwl_mvm_bt_coex_notif_handle(mvm); |
610 | } | 644 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h new file mode 100644 index 000000000000..64656e0c8f91 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/mvm/constants.h | |||
@@ -0,0 +1,71 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * 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 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called COPYING. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | #ifndef __MVM_CONSTANTS_H | ||
64 | #define __MVM_CONSTANTS_H | ||
65 | |||
66 | #define IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT (100 * USEC_PER_MSEC) | ||
67 | #define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC) | ||
68 | #define IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT (10 * USEC_PER_MSEC) | ||
69 | #define IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT (10 * USEC_PER_MSEC) | ||
70 | |||
71 | #endif /* __MVM_CONSTANTS_H */ | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index 7e5e5c2f9f87..ebf7f9468926 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c | |||
@@ -105,7 +105,7 @@ void iwl_mvm_ipv6_addr_change(struct ieee80211_hw *hw, | |||
105 | list_for_each_entry(ifa, &idev->addr_list, if_list) { | 105 | list_for_each_entry(ifa, &idev->addr_list, if_list) { |
106 | mvmvif->target_ipv6_addrs[idx] = ifa->addr; | 106 | mvmvif->target_ipv6_addrs[idx] = ifa->addr; |
107 | idx++; | 107 | idx++; |
108 | if (idx >= IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS) | 108 | if (idx >= IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX) |
109 | break; | 109 | break; |
110 | } | 110 | } |
111 | read_unlock_bh(&idev->lock); | 111 | read_unlock_bh(&idev->lock); |
@@ -373,36 +373,68 @@ static int iwl_mvm_send_patterns(struct iwl_mvm *mvm, | |||
373 | static int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, | 373 | static int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, |
374 | struct ieee80211_vif *vif) | 374 | struct ieee80211_vif *vif) |
375 | { | 375 | { |
376 | struct iwl_proto_offload_cmd cmd = {}; | 376 | union { |
377 | struct iwl_proto_offload_cmd_v1 v1; | ||
378 | struct iwl_proto_offload_cmd_v2 v2; | ||
379 | } cmd = {}; | ||
380 | struct iwl_proto_offload_cmd_common *common; | ||
381 | u32 enabled = 0, size; | ||
377 | #if IS_ENABLED(CONFIG_IPV6) | 382 | #if IS_ENABLED(CONFIG_IPV6) |
378 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 383 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
379 | int i; | 384 | int i; |
380 | 385 | ||
381 | if (mvmvif->num_target_ipv6_addrs) { | 386 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS) { |
382 | cmd.enabled |= cpu_to_le32(IWL_D3_PROTO_OFFLOAD_NS); | 387 | if (mvmvif->num_target_ipv6_addrs) { |
383 | memcpy(cmd.ndp_mac_addr, vif->addr, ETH_ALEN); | 388 | enabled |= IWL_D3_PROTO_OFFLOAD_NS; |
384 | } | 389 | memcpy(cmd.v2.ndp_mac_addr, vif->addr, ETH_ALEN); |
390 | } | ||
391 | |||
392 | BUILD_BUG_ON(sizeof(cmd.v2.target_ipv6_addr[0]) != | ||
393 | sizeof(mvmvif->target_ipv6_addrs[0])); | ||
394 | |||
395 | for (i = 0; i < min(mvmvif->num_target_ipv6_addrs, | ||
396 | IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2); i++) | ||
397 | memcpy(cmd.v2.target_ipv6_addr[i], | ||
398 | &mvmvif->target_ipv6_addrs[i], | ||
399 | sizeof(cmd.v2.target_ipv6_addr[i])); | ||
400 | } else { | ||
401 | if (mvmvif->num_target_ipv6_addrs) { | ||
402 | enabled |= IWL_D3_PROTO_OFFLOAD_NS; | ||
403 | memcpy(cmd.v1.ndp_mac_addr, vif->addr, ETH_ALEN); | ||
404 | } | ||
385 | 405 | ||
386 | BUILD_BUG_ON(sizeof(cmd.target_ipv6_addr[i]) != | 406 | BUILD_BUG_ON(sizeof(cmd.v1.target_ipv6_addr[0]) != |
387 | sizeof(mvmvif->target_ipv6_addrs[i])); | 407 | sizeof(mvmvif->target_ipv6_addrs[0])); |
388 | 408 | ||
389 | for (i = 0; i < mvmvif->num_target_ipv6_addrs; i++) | 409 | for (i = 0; i < min(mvmvif->num_target_ipv6_addrs, |
390 | memcpy(cmd.target_ipv6_addr[i], | 410 | IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1); i++) |
391 | &mvmvif->target_ipv6_addrs[i], | 411 | memcpy(cmd.v1.target_ipv6_addr[i], |
392 | sizeof(cmd.target_ipv6_addr[i])); | 412 | &mvmvif->target_ipv6_addrs[i], |
413 | sizeof(cmd.v1.target_ipv6_addr[i])); | ||
414 | } | ||
393 | #endif | 415 | #endif |
394 | 416 | ||
417 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS) { | ||
418 | common = &cmd.v2.common; | ||
419 | size = sizeof(cmd.v2); | ||
420 | } else { | ||
421 | common = &cmd.v1.common; | ||
422 | size = sizeof(cmd.v1); | ||
423 | } | ||
424 | |||
395 | if (vif->bss_conf.arp_addr_cnt) { | 425 | if (vif->bss_conf.arp_addr_cnt) { |
396 | cmd.enabled |= cpu_to_le32(IWL_D3_PROTO_OFFLOAD_ARP); | 426 | enabled |= IWL_D3_PROTO_OFFLOAD_ARP; |
397 | cmd.host_ipv4_addr = vif->bss_conf.arp_addr_list[0]; | 427 | common->host_ipv4_addr = vif->bss_conf.arp_addr_list[0]; |
398 | memcpy(cmd.arp_mac_addr, vif->addr, ETH_ALEN); | 428 | memcpy(common->arp_mac_addr, vif->addr, ETH_ALEN); |
399 | } | 429 | } |
400 | 430 | ||
401 | if (!cmd.enabled) | 431 | if (!enabled) |
402 | return 0; | 432 | return 0; |
403 | 433 | ||
434 | common->enabled = cpu_to_le32(enabled); | ||
435 | |||
404 | return iwl_mvm_send_cmd_pdu(mvm, PROT_OFFLOAD_CONFIG_CMD, CMD_SYNC, | 436 | return iwl_mvm_send_cmd_pdu(mvm, PROT_OFFLOAD_CONFIG_CMD, CMD_SYNC, |
405 | sizeof(cmd), &cmd); | 437 | size, &cmd); |
406 | } | 438 | } |
407 | 439 | ||
408 | enum iwl_mvm_tcp_packet_type { | 440 | enum iwl_mvm_tcp_packet_type { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index c24a744910ac..56f6827b19e5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c | |||
@@ -424,40 +424,11 @@ static ssize_t iwl_dbgfs_pm_params_read(struct file *file, | |||
424 | struct ieee80211_vif *vif = file->private_data; | 424 | struct ieee80211_vif *vif = file->private_data; |
425 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 425 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
426 | struct iwl_mvm *mvm = mvmvif->dbgfs_data; | 426 | struct iwl_mvm *mvm = mvmvif->dbgfs_data; |
427 | struct iwl_powertable_cmd cmd = {}; | ||
428 | char buf[256]; | 427 | char buf[256]; |
429 | int bufsz = sizeof(buf); | 428 | int bufsz = sizeof(buf); |
430 | int pos = 0; | 429 | int pos; |
431 | 430 | ||
432 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); | 431 | pos = iwl_mvm_power_dbgfs_read(mvm, vif, buf, bufsz); |
433 | |||
434 | pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n", | ||
435 | (cmd.flags & | ||
436 | cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ? | ||
437 | 0 : 1); | ||
438 | pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n", | ||
439 | le32_to_cpu(cmd.skip_dtim_periods)); | ||
440 | pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n", | ||
441 | iwlmvm_mod_params.power_scheme); | ||
442 | pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n", | ||
443 | le16_to_cpu(cmd.flags)); | ||
444 | pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n", | ||
445 | cmd.keep_alive_seconds); | ||
446 | |||
447 | if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) { | ||
448 | pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n", | ||
449 | (cmd.flags & | ||
450 | cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ? | ||
451 | 1 : 0); | ||
452 | pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n", | ||
453 | le32_to_cpu(cmd.rx_data_timeout)); | ||
454 | pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n", | ||
455 | le32_to_cpu(cmd.tx_data_timeout)); | ||
456 | if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK)) | ||
457 | pos += scnprintf(buf+pos, bufsz-pos, | ||
458 | "lprx_rssi_threshold = %d\n", | ||
459 | le32_to_cpu(cmd.lprx_rssi_threshold)); | ||
460 | } | ||
461 | 432 | ||
462 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 433 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
463 | } | 434 | } |
@@ -626,20 +597,19 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct file *file, | |||
626 | size_t count, loff_t *ppos) | 597 | size_t count, loff_t *ppos) |
627 | { | 598 | { |
628 | struct iwl_mvm *mvm = file->private_data; | 599 | struct iwl_mvm *mvm = file->private_data; |
629 | bool restart_fw = iwlwifi_mod_params.restart_fw; | ||
630 | int ret; | 600 | int ret; |
631 | 601 | ||
632 | iwlwifi_mod_params.restart_fw = true; | ||
633 | |||
634 | mutex_lock(&mvm->mutex); | 602 | mutex_lock(&mvm->mutex); |
635 | 603 | ||
604 | /* allow one more restart that we're provoking here */ | ||
605 | if (mvm->restart_fw >= 0) | ||
606 | mvm->restart_fw++; | ||
607 | |||
636 | /* take the return value to make compiler happy - it will fail anyway */ | 608 | /* take the return value to make compiler happy - it will fail anyway */ |
637 | ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_ERROR, CMD_SYNC, 0, NULL); | 609 | ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_ERROR, CMD_SYNC, 0, NULL); |
638 | 610 | ||
639 | mutex_unlock(&mvm->mutex); | 611 | mutex_unlock(&mvm->mutex); |
640 | 612 | ||
641 | iwlwifi_mod_params.restart_fw = restart_fw; | ||
642 | |||
643 | return count; | 613 | return count; |
644 | } | 614 | } |
645 | 615 | ||
@@ -661,8 +631,14 @@ static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif, | |||
661 | case MVM_DEBUGFS_BF_ROAMING_STATE: | 631 | case MVM_DEBUGFS_BF_ROAMING_STATE: |
662 | dbgfs_bf->bf_roaming_state = value; | 632 | dbgfs_bf->bf_roaming_state = value; |
663 | break; | 633 | break; |
664 | case MVM_DEBUGFS_BF_TEMPERATURE_DELTA: | 634 | case MVM_DEBUGFS_BF_TEMP_THRESHOLD: |
665 | dbgfs_bf->bf_temperature_delta = value; | 635 | dbgfs_bf->bf_temp_threshold = value; |
636 | break; | ||
637 | case MVM_DEBUGFS_BF_TEMP_FAST_FILTER: | ||
638 | dbgfs_bf->bf_temp_fast_filter = value; | ||
639 | break; | ||
640 | case MVM_DEBUGFS_BF_TEMP_SLOW_FILTER: | ||
641 | dbgfs_bf->bf_temp_slow_filter = value; | ||
666 | break; | 642 | break; |
667 | case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER: | 643 | case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER: |
668 | dbgfs_bf->bf_enable_beacon_filter = value; | 644 | dbgfs_bf->bf_enable_beacon_filter = value; |
@@ -721,13 +697,27 @@ static ssize_t iwl_dbgfs_bf_params_write(struct file *file, | |||
721 | value > IWL_BF_ROAMING_STATE_MAX) | 697 | value > IWL_BF_ROAMING_STATE_MAX) |
722 | return -EINVAL; | 698 | return -EINVAL; |
723 | param = MVM_DEBUGFS_BF_ROAMING_STATE; | 699 | param = MVM_DEBUGFS_BF_ROAMING_STATE; |
724 | } else if (!strncmp("bf_temperature_delta=", buf, 21)) { | 700 | } else if (!strncmp("bf_temp_threshold=", buf, 18)) { |
725 | if (sscanf(buf+21, "%d", &value) != 1) | 701 | if (sscanf(buf+18, "%d", &value) != 1) |
702 | return -EINVAL; | ||
703 | if (value < IWL_BF_TEMP_THRESHOLD_MIN || | ||
704 | value > IWL_BF_TEMP_THRESHOLD_MAX) | ||
705 | return -EINVAL; | ||
706 | param = MVM_DEBUGFS_BF_TEMP_THRESHOLD; | ||
707 | } else if (!strncmp("bf_temp_fast_filter=", buf, 20)) { | ||
708 | if (sscanf(buf+20, "%d", &value) != 1) | ||
709 | return -EINVAL; | ||
710 | if (value < IWL_BF_TEMP_FAST_FILTER_MIN || | ||
711 | value > IWL_BF_TEMP_FAST_FILTER_MAX) | ||
712 | return -EINVAL; | ||
713 | param = MVM_DEBUGFS_BF_TEMP_FAST_FILTER; | ||
714 | } else if (!strncmp("bf_temp_slow_filter=", buf, 20)) { | ||
715 | if (sscanf(buf+20, "%d", &value) != 1) | ||
726 | return -EINVAL; | 716 | return -EINVAL; |
727 | if (value < IWL_BF_TEMPERATURE_DELTA_MIN || | 717 | if (value < IWL_BF_TEMP_SLOW_FILTER_MIN || |
728 | value > IWL_BF_TEMPERATURE_DELTA_MAX) | 718 | value > IWL_BF_TEMP_SLOW_FILTER_MAX) |
729 | return -EINVAL; | 719 | return -EINVAL; |
730 | param = MVM_DEBUGFS_BF_TEMPERATURE_DELTA; | 720 | param = MVM_DEBUGFS_BF_TEMP_SLOW_FILTER; |
731 | } else if (!strncmp("bf_enable_beacon_filter=", buf, 24)) { | 721 | } else if (!strncmp("bf_enable_beacon_filter=", buf, 24)) { |
732 | if (sscanf(buf+24, "%d", &value) != 1) | 722 | if (sscanf(buf+24, "%d", &value) != 1) |
733 | return -EINVAL; | 723 | return -EINVAL; |
@@ -789,41 +779,41 @@ static ssize_t iwl_dbgfs_bf_params_read(struct file *file, | |||
789 | int pos = 0; | 779 | int pos = 0; |
790 | const size_t bufsz = sizeof(buf); | 780 | const size_t bufsz = sizeof(buf); |
791 | struct iwl_beacon_filter_cmd cmd = { | 781 | struct iwl_beacon_filter_cmd cmd = { |
792 | .bf_energy_delta = IWL_BF_ENERGY_DELTA_DEFAULT, | 782 | IWL_BF_CMD_CONFIG_DEFAULTS, |
793 | .bf_roaming_energy_delta = IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT, | 783 | .bf_enable_beacon_filter = |
794 | .bf_roaming_state = IWL_BF_ROAMING_STATE_DEFAULT, | 784 | cpu_to_le32(IWL_BF_ENABLE_BEACON_FILTER_DEFAULT), |
795 | .bf_temperature_delta = IWL_BF_TEMPERATURE_DELTA_DEFAULT, | 785 | .ba_enable_beacon_abort = |
796 | .bf_enable_beacon_filter = IWL_BF_ENABLE_BEACON_FILTER_DEFAULT, | 786 | cpu_to_le32(IWL_BA_ENABLE_BEACON_ABORT_DEFAULT), |
797 | .bf_debug_flag = IWL_BF_DEBUG_FLAG_DEFAULT, | ||
798 | .bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT), | ||
799 | .ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT), | ||
800 | .ba_enable_beacon_abort = IWL_BA_ENABLE_BEACON_ABORT_DEFAULT, | ||
801 | }; | 787 | }; |
802 | 788 | ||
803 | iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); | 789 | iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); |
804 | if (mvmvif->bf_enabled) | 790 | if (mvmvif->bf_enabled) |
805 | cmd.bf_enable_beacon_filter = 1; | 791 | cmd.bf_enable_beacon_filter = cpu_to_le32(1); |
806 | else | 792 | else |
807 | cmd.bf_enable_beacon_filter = 0; | 793 | cmd.bf_enable_beacon_filter = 0; |
808 | 794 | ||
809 | pos += scnprintf(buf+pos, bufsz-pos, "bf_energy_delta = %d\n", | 795 | pos += scnprintf(buf+pos, bufsz-pos, "bf_energy_delta = %d\n", |
810 | cmd.bf_energy_delta); | 796 | le32_to_cpu(cmd.bf_energy_delta)); |
811 | pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_energy_delta = %d\n", | 797 | pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_energy_delta = %d\n", |
812 | cmd.bf_roaming_energy_delta); | 798 | le32_to_cpu(cmd.bf_roaming_energy_delta)); |
813 | pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_state = %d\n", | 799 | pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_state = %d\n", |
814 | cmd.bf_roaming_state); | 800 | le32_to_cpu(cmd.bf_roaming_state)); |
815 | pos += scnprintf(buf+pos, bufsz-pos, "bf_temperature_delta = %d\n", | 801 | pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_threshold = %d\n", |
816 | cmd.bf_temperature_delta); | 802 | le32_to_cpu(cmd.bf_temp_threshold)); |
803 | pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_fast_filter = %d\n", | ||
804 | le32_to_cpu(cmd.bf_temp_fast_filter)); | ||
805 | pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_slow_filter = %d\n", | ||
806 | le32_to_cpu(cmd.bf_temp_slow_filter)); | ||
817 | pos += scnprintf(buf+pos, bufsz-pos, "bf_enable_beacon_filter = %d\n", | 807 | pos += scnprintf(buf+pos, bufsz-pos, "bf_enable_beacon_filter = %d\n", |
818 | cmd.bf_enable_beacon_filter); | 808 | le32_to_cpu(cmd.bf_enable_beacon_filter)); |
819 | pos += scnprintf(buf+pos, bufsz-pos, "bf_debug_flag = %d\n", | 809 | pos += scnprintf(buf+pos, bufsz-pos, "bf_debug_flag = %d\n", |
820 | cmd.bf_debug_flag); | 810 | le32_to_cpu(cmd.bf_debug_flag)); |
821 | pos += scnprintf(buf+pos, bufsz-pos, "bf_escape_timer = %d\n", | 811 | pos += scnprintf(buf+pos, bufsz-pos, "bf_escape_timer = %d\n", |
822 | cmd.bf_escape_timer); | 812 | le32_to_cpu(cmd.bf_escape_timer)); |
823 | pos += scnprintf(buf+pos, bufsz-pos, "ba_escape_timer = %d\n", | 813 | pos += scnprintf(buf+pos, bufsz-pos, "ba_escape_timer = %d\n", |
824 | cmd.ba_escape_timer); | 814 | le32_to_cpu(cmd.ba_escape_timer)); |
825 | pos += scnprintf(buf+pos, bufsz-pos, "ba_enable_beacon_abort = %d\n", | 815 | pos += scnprintf(buf+pos, bufsz-pos, "ba_enable_beacon_abort = %d\n", |
826 | cmd.ba_enable_beacon_abort); | 816 | le32_to_cpu(cmd.ba_enable_beacon_abort)); |
827 | 817 | ||
828 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 818 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
829 | } | 819 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h index 6f8b2c16ae17..df72fcdf8170 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h | |||
@@ -98,34 +98,63 @@ enum iwl_proto_offloads { | |||
98 | IWL_D3_PROTO_OFFLOAD_NS = BIT(1), | 98 | IWL_D3_PROTO_OFFLOAD_NS = BIT(1), |
99 | }; | 99 | }; |
100 | 100 | ||
101 | #define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS 2 | 101 | #define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1 2 |
102 | #define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2 6 | ||
103 | #define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX 6 | ||
102 | 104 | ||
103 | /** | 105 | /** |
104 | * struct iwl_proto_offload_cmd - ARP/NS offload configuration | 106 | * struct iwl_proto_offload_cmd_common - ARP/NS offload common part |
105 | * @enabled: enable flags | 107 | * @enabled: enable flags |
106 | * @remote_ipv4_addr: remote address to answer to (or zero if all) | 108 | * @remote_ipv4_addr: remote address to answer to (or zero if all) |
107 | * @host_ipv4_addr: our IPv4 address to respond to queries for | 109 | * @host_ipv4_addr: our IPv4 address to respond to queries for |
108 | * @arp_mac_addr: our MAC address for ARP responses | 110 | * @arp_mac_addr: our MAC address for ARP responses |
109 | * @remote_ipv6_addr: remote address to answer to (or zero if all) | 111 | * @reserved: unused |
110 | * @solicited_node_ipv6_addr: broken -- solicited node address exists | ||
111 | * for each target address | ||
112 | * @target_ipv6_addr: our target addresses | ||
113 | * @ndp_mac_addr: neighbor soliciation response MAC address | ||
114 | */ | 112 | */ |
115 | struct iwl_proto_offload_cmd { | 113 | struct iwl_proto_offload_cmd_common { |
116 | __le32 enabled; | 114 | __le32 enabled; |
117 | __be32 remote_ipv4_addr; | 115 | __be32 remote_ipv4_addr; |
118 | __be32 host_ipv4_addr; | 116 | __be32 host_ipv4_addr; |
119 | u8 arp_mac_addr[ETH_ALEN]; | 117 | u8 arp_mac_addr[ETH_ALEN]; |
120 | __le16 reserved1; | 118 | __le16 reserved; |
119 | } __packed; | ||
121 | 120 | ||
121 | /** | ||
122 | * struct iwl_proto_offload_cmd_v1 - ARP/NS offload configuration | ||
123 | * @common: common/IPv4 configuration | ||
124 | * @remote_ipv6_addr: remote address to answer to (or zero if all) | ||
125 | * @solicited_node_ipv6_addr: broken -- solicited node address exists | ||
126 | * for each target address | ||
127 | * @target_ipv6_addr: our target addresses | ||
128 | * @ndp_mac_addr: neighbor soliciation response MAC address | ||
129 | */ | ||
130 | struct iwl_proto_offload_cmd_v1 { | ||
131 | struct iwl_proto_offload_cmd_common common; | ||
122 | u8 remote_ipv6_addr[16]; | 132 | u8 remote_ipv6_addr[16]; |
123 | u8 solicited_node_ipv6_addr[16]; | 133 | u8 solicited_node_ipv6_addr[16]; |
124 | u8 target_ipv6_addr[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS][16]; | 134 | u8 target_ipv6_addr[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1][16]; |
125 | u8 ndp_mac_addr[ETH_ALEN]; | 135 | u8 ndp_mac_addr[ETH_ALEN]; |
126 | __le16 reserved2; | 136 | __le16 reserved2; |
127 | } __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_1 */ | 137 | } __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_1 */ |
128 | 138 | ||
139 | /** | ||
140 | * struct iwl_proto_offload_cmd_v2 - ARP/NS offload configuration | ||
141 | * @common: common/IPv4 configuration | ||
142 | * @remote_ipv6_addr: remote address to answer to (or zero if all) | ||
143 | * @solicited_node_ipv6_addr: broken -- solicited node address exists | ||
144 | * for each target address | ||
145 | * @target_ipv6_addr: our target addresses | ||
146 | * @ndp_mac_addr: neighbor soliciation response MAC address | ||
147 | */ | ||
148 | struct iwl_proto_offload_cmd_v2 { | ||
149 | struct iwl_proto_offload_cmd_common common; | ||
150 | u8 remote_ipv6_addr[16]; | ||
151 | u8 solicited_node_ipv6_addr[16]; | ||
152 | u8 target_ipv6_addr[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2][16]; | ||
153 | u8 ndp_mac_addr[ETH_ALEN]; | ||
154 | u8 numValidIPv6Addresses; | ||
155 | u8 reserved2[3]; | ||
156 | } __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_2 */ | ||
157 | |||
129 | 158 | ||
130 | /* | 159 | /* |
131 | * WOWLAN_PATTERNS | 160 | * WOWLAN_PATTERNS |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h index a6da359a80c3..060e630b3d82 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h | |||
@@ -79,6 +79,10 @@ | |||
79 | * '1' Driver enables PM (use rest of parameters) | 79 | * '1' Driver enables PM (use rest of parameters) |
80 | * @POWER_FLAGS_SKIP_OVER_DTIM_MSK: '0' PM have to walk up every DTIM, | 80 | * @POWER_FLAGS_SKIP_OVER_DTIM_MSK: '0' PM have to walk up every DTIM, |
81 | * '1' PM could sleep over DTIM till listen Interval. | 81 | * '1' PM could sleep over DTIM till listen Interval. |
82 | * @POWER_FLAGS_SNOOZE_ENA_MSK: Enable snoozing only if uAPSD is enabled and all | ||
83 | * access categories are both delivery and trigger enabled. | ||
84 | * @POWER_FLAGS_BT_SCO_ENA: Enable BT SCO coex only if uAPSD and | ||
85 | * PBW Snoozing enabled | ||
82 | * @POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask | 86 | * @POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask |
83 | * @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable. | 87 | * @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable. |
84 | */ | 88 | */ |
@@ -86,6 +90,8 @@ enum iwl_power_flags { | |||
86 | POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0), | 90 | POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0), |
87 | POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK = BIT(1), | 91 | POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK = BIT(1), |
88 | POWER_FLAGS_SKIP_OVER_DTIM_MSK = BIT(2), | 92 | POWER_FLAGS_SKIP_OVER_DTIM_MSK = BIT(2), |
93 | POWER_FLAGS_SNOOZE_ENA_MSK = BIT(5), | ||
94 | POWER_FLAGS_BT_SCO_ENA = BIT(8), | ||
89 | POWER_FLAGS_ADVANCE_PM_ENA_MSK = BIT(9), | 95 | POWER_FLAGS_ADVANCE_PM_ENA_MSK = BIT(9), |
90 | POWER_FLAGS_LPRX_ENA_MSK = BIT(11), | 96 | POWER_FLAGS_LPRX_ENA_MSK = BIT(11), |
91 | }; | 97 | }; |
@@ -93,7 +99,8 @@ enum iwl_power_flags { | |||
93 | #define IWL_POWER_VEC_SIZE 5 | 99 | #define IWL_POWER_VEC_SIZE 5 |
94 | 100 | ||
95 | /** | 101 | /** |
96 | * struct iwl_powertable_cmd - Power Table Command | 102 | * struct iwl_powertable_cmd - legacy power command. Beside old API support this |
103 | * is used also with a new power API for device wide power settings. | ||
97 | * POWER_TABLE_CMD = 0x77 (command, has simple generic response) | 104 | * POWER_TABLE_CMD = 0x77 (command, has simple generic response) |
98 | * | 105 | * |
99 | * @flags: Power table command flags from POWER_FLAGS_* | 106 | * @flags: Power table command flags from POWER_FLAGS_* |
@@ -125,6 +132,72 @@ struct iwl_powertable_cmd { | |||
125 | } __packed; | 132 | } __packed; |
126 | 133 | ||
127 | /** | 134 | /** |
135 | * struct iwl_mac_power_cmd - New power command containing uAPSD support | ||
136 | * MAC_PM_POWER_TABLE = 0xA9 (command, has simple generic response) | ||
137 | * @id_and_color: MAC contex identifier | ||
138 | * @flags: Power table command flags from POWER_FLAGS_* | ||
139 | * @keep_alive_seconds: Keep alive period in seconds. Default - 25 sec. | ||
140 | * Minimum allowed:- 3 * DTIM. Keep alive period must be | ||
141 | * set regardless of power scheme or current power state. | ||
142 | * FW use this value also when PM is disabled. | ||
143 | * @rx_data_timeout: Minimum time (usec) from last Rx packet for AM to | ||
144 | * PSM transition - legacy PM | ||
145 | * @tx_data_timeout: Minimum time (usec) from last Tx packet for AM to | ||
146 | * PSM transition - legacy PM | ||
147 | * @sleep_interval: not in use | ||
148 | * @skip_dtim_periods: Number of DTIM periods to skip if Skip over DTIM flag | ||
149 | * is set. For example, if it is required to skip over | ||
150 | * one DTIM, this value need to be set to 2 (DTIM periods). | ||
151 | * @rx_data_timeout_uapsd: Minimum time (usec) from last Rx packet for AM to | ||
152 | * PSM transition - uAPSD | ||
153 | * @tx_data_timeout_uapsd: Minimum time (usec) from last Tx packet for AM to | ||
154 | * PSM transition - uAPSD | ||
155 | * @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled. | ||
156 | * Default: 80dbm | ||
157 | * @num_skip_dtim: Number of DTIMs to skip if Skip over DTIM flag is set | ||
158 | * @snooze_interval: TBD | ||
159 | * @snooze_window: TBD | ||
160 | * @snooze_step: TBD | ||
161 | * @qndp_tid: TID client shall use for uAPSD QNDP triggers | ||
162 | * @uapsd_ac_flags: Set trigger-enabled and delivery-enabled indication for | ||
163 | * each corresponding AC. | ||
164 | * Use IEEE80211_WMM_IE_STA_QOSINFO_AC* for correct values. | ||
165 | * @uapsd_max_sp: Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct | ||
166 | * values. | ||
167 | * @heavy_traffic_thr_tx_pkts: TX threshold measured in number of packets | ||
168 | * @heavy_traffic_thr_rx_pkts: RX threshold measured in number of packets | ||
169 | * @heavy_traffic_thr_tx_load: TX threshold measured in load's percentage | ||
170 | * @heavy_traffic_thr_rx_load: RX threshold measured in load's percentage | ||
171 | * @limited_ps_threshold: | ||
172 | */ | ||
173 | struct iwl_mac_power_cmd { | ||
174 | /* CONTEXT_DESC_API_T_VER_1 */ | ||
175 | __le32 id_and_color; | ||
176 | |||
177 | /* CLIENT_PM_POWER_TABLE_S_VER_1 */ | ||
178 | __le16 flags; | ||
179 | __le16 keep_alive_seconds; | ||
180 | __le32 rx_data_timeout; | ||
181 | __le32 tx_data_timeout; | ||
182 | __le32 rx_data_timeout_uapsd; | ||
183 | __le32 tx_data_timeout_uapsd; | ||
184 | u8 lprx_rssi_threshold; | ||
185 | u8 skip_dtim_periods; | ||
186 | __le16 snooze_interval; | ||
187 | __le16 snooze_window; | ||
188 | u8 snooze_step; | ||
189 | u8 qndp_tid; | ||
190 | u8 uapsd_ac_flags; | ||
191 | u8 uapsd_max_sp; | ||
192 | u8 heavy_traffic_threshold_tx_packets; | ||
193 | u8 heavy_traffic_threshold_rx_packets; | ||
194 | u8 heavy_traffic_threshold_tx_percentage; | ||
195 | u8 heavy_traffic_threshold_rx_percentage; | ||
196 | u8 limited_ps_threshold; | ||
197 | u8 reserved; | ||
198 | } __packed; | ||
199 | |||
200 | /** | ||
128 | * struct iwl_beacon_filter_cmd | 201 | * struct iwl_beacon_filter_cmd |
129 | * REPLY_BEACON_FILTERING_CMD = 0xd2 (command) | 202 | * REPLY_BEACON_FILTERING_CMD = 0xd2 (command) |
130 | * @id_and_color: MAC contex identifier | 203 | * @id_and_color: MAC contex identifier |
@@ -143,11 +216,21 @@ struct iwl_powertable_cmd { | |||
143 | * calculated for current beacon is less than the threshold, use | 216 | * calculated for current beacon is less than the threshold, use |
144 | * Roaming Energy Delta Threshold, otherwise use normal Energy Delta | 217 | * Roaming Energy Delta Threshold, otherwise use normal Energy Delta |
145 | * Threshold. Typical energy threshold is -72dBm. | 218 | * Threshold. Typical energy threshold is -72dBm. |
146 | * @bf_temperature_delta: Send Beacon to driver if delta in temperature values | 219 | * @bf_temp_threshold: This threshold determines the type of temperature |
147 | * calculated for this and the last passed beacon is greater than this | 220 | * filtering (Slow or Fast) that is selected (Units are in Celsuis): |
148 | * threshold. Zero value means that the temperature changeis ignored for | 221 | * If the current temperature is above this threshold - Fast filter |
222 | * will be used, If the current temperature is below this threshold - | ||
223 | * Slow filter will be used. | ||
224 | * @bf_temp_fast_filter: Send Beacon to driver if delta in temperature values | ||
225 | * calculated for this and the last passed beacon is greater than this | ||
226 | * threshold. Zero value means that the temperature change is ignored for | ||
149 | * beacon filtering; beacons will not be forced to be sent to driver | 227 | * beacon filtering; beacons will not be forced to be sent to driver |
150 | * regardless of whether its temerature has been changed. | 228 | * regardless of whether its temerature has been changed. |
229 | * @bf_temp_slow_filter: Send Beacon to driver if delta in temperature values | ||
230 | * calculated for this and the last passed beacon is greater than this | ||
231 | * threshold. Zero value means that the temperature change is ignored for | ||
232 | * beacon filtering; beacons will not be forced to be sent to driver | ||
233 | * regardless of whether its temerature has been changed. | ||
151 | * @bf_enable_beacon_filter: 1, beacon filtering is enabled; 0, disabled. | 234 | * @bf_enable_beacon_filter: 1, beacon filtering is enabled; 0, disabled. |
152 | * @bf_filter_escape_timer: Send beacons to to driver if no beacons were passed | 235 | * @bf_filter_escape_timer: Send beacons to to driver if no beacons were passed |
153 | * for a specific period of time. Units: Beacons. | 236 | * for a specific period of time. Units: Beacons. |
@@ -156,17 +239,17 @@ struct iwl_powertable_cmd { | |||
156 | * @ba_enable_beacon_abort: 1, beacon abort is enabled; 0, disabled. | 239 | * @ba_enable_beacon_abort: 1, beacon abort is enabled; 0, disabled. |
157 | */ | 240 | */ |
158 | struct iwl_beacon_filter_cmd { | 241 | struct iwl_beacon_filter_cmd { |
159 | u8 bf_energy_delta; | 242 | __le32 bf_energy_delta; |
160 | u8 bf_roaming_energy_delta; | 243 | __le32 bf_roaming_energy_delta; |
161 | u8 bf_roaming_state; | 244 | __le32 bf_roaming_state; |
162 | u8 bf_temperature_delta; | 245 | __le32 bf_temp_threshold; |
163 | u8 bf_enable_beacon_filter; | 246 | __le32 bf_temp_fast_filter; |
164 | u8 bf_debug_flag; | 247 | __le32 bf_temp_slow_filter; |
165 | __le16 reserved1; | 248 | __le32 bf_enable_beacon_filter; |
249 | __le32 bf_debug_flag; | ||
166 | __le32 bf_escape_timer; | 250 | __le32 bf_escape_timer; |
167 | __le32 ba_escape_timer; | 251 | __le32 ba_escape_timer; |
168 | u8 ba_enable_beacon_abort; | 252 | __le32 ba_enable_beacon_abort; |
169 | u8 reserved2[3]; | ||
170 | } __packed; | 253 | } __packed; |
171 | 254 | ||
172 | /* Beacon filtering and beacon abort */ | 255 | /* Beacon filtering and beacon abort */ |
@@ -182,9 +265,17 @@ struct iwl_beacon_filter_cmd { | |||
182 | #define IWL_BF_ROAMING_STATE_MAX 255 | 265 | #define IWL_BF_ROAMING_STATE_MAX 255 |
183 | #define IWL_BF_ROAMING_STATE_MIN 0 | 266 | #define IWL_BF_ROAMING_STATE_MIN 0 |
184 | 267 | ||
185 | #define IWL_BF_TEMPERATURE_DELTA_DEFAULT 5 | 268 | #define IWL_BF_TEMP_THRESHOLD_DEFAULT 112 |
186 | #define IWL_BF_TEMPERATURE_DELTA_MAX 255 | 269 | #define IWL_BF_TEMP_THRESHOLD_MAX 255 |
187 | #define IWL_BF_TEMPERATURE_DELTA_MIN 0 | 270 | #define IWL_BF_TEMP_THRESHOLD_MIN 0 |
271 | |||
272 | #define IWL_BF_TEMP_FAST_FILTER_DEFAULT 1 | ||
273 | #define IWL_BF_TEMP_FAST_FILTER_MAX 255 | ||
274 | #define IWL_BF_TEMP_FAST_FILTER_MIN 0 | ||
275 | |||
276 | #define IWL_BF_TEMP_SLOW_FILTER_DEFAULT 5 | ||
277 | #define IWL_BF_TEMP_SLOW_FILTER_MAX 255 | ||
278 | #define IWL_BF_TEMP_SLOW_FILTER_MIN 0 | ||
188 | 279 | ||
189 | #define IWL_BF_ENABLE_BEACON_FILTER_DEFAULT 1 | 280 | #define IWL_BF_ENABLE_BEACON_FILTER_DEFAULT 1 |
190 | 281 | ||
@@ -194,19 +285,23 @@ struct iwl_beacon_filter_cmd { | |||
194 | #define IWL_BF_ESCAPE_TIMER_MAX 1024 | 285 | #define IWL_BF_ESCAPE_TIMER_MAX 1024 |
195 | #define IWL_BF_ESCAPE_TIMER_MIN 0 | 286 | #define IWL_BF_ESCAPE_TIMER_MIN 0 |
196 | 287 | ||
197 | #define IWL_BA_ESCAPE_TIMER_DEFAULT 3 | 288 | #define IWL_BA_ESCAPE_TIMER_DEFAULT 6 |
289 | #define IWL_BA_ESCAPE_TIMER_D3 6 | ||
198 | #define IWL_BA_ESCAPE_TIMER_MAX 1024 | 290 | #define IWL_BA_ESCAPE_TIMER_MAX 1024 |
199 | #define IWL_BA_ESCAPE_TIMER_MIN 0 | 291 | #define IWL_BA_ESCAPE_TIMER_MIN 0 |
200 | 292 | ||
201 | #define IWL_BA_ENABLE_BEACON_ABORT_DEFAULT 1 | 293 | #define IWL_BA_ENABLE_BEACON_ABORT_DEFAULT 1 |
202 | 294 | ||
203 | #define IWL_BF_CMD_CONFIG_DEFAULTS \ | 295 | #define IWL_BF_CMD_CONFIG_DEFAULTS \ |
204 | .bf_energy_delta = IWL_BF_ENERGY_DELTA_DEFAULT, \ | 296 | .bf_energy_delta = cpu_to_le32(IWL_BF_ENERGY_DELTA_DEFAULT), \ |
205 | .bf_roaming_energy_delta = IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT, \ | 297 | .bf_roaming_energy_delta = \ |
206 | .bf_roaming_state = IWL_BF_ROAMING_STATE_DEFAULT, \ | 298 | cpu_to_le32(IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT), \ |
207 | .bf_temperature_delta = IWL_BF_TEMPERATURE_DELTA_DEFAULT, \ | 299 | .bf_roaming_state = cpu_to_le32(IWL_BF_ROAMING_STATE_DEFAULT), \ |
208 | .bf_debug_flag = IWL_BF_DEBUG_FLAG_DEFAULT, \ | 300 | .bf_temp_threshold = cpu_to_le32(IWL_BF_TEMP_THRESHOLD_DEFAULT), \ |
209 | .bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT), \ | 301 | .bf_temp_fast_filter = cpu_to_le32(IWL_BF_TEMP_FAST_FILTER_DEFAULT), \ |
302 | .bf_temp_slow_filter = cpu_to_le32(IWL_BF_TEMP_SLOW_FILTER_DEFAULT), \ | ||
303 | .bf_debug_flag = cpu_to_le32(IWL_BF_DEBUG_FLAG_DEFAULT), \ | ||
304 | .bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT), \ | ||
210 | .ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT) | 305 | .ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT) |
211 | 306 | ||
212 | #endif | 307 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h index b60d14151721..c33ff8e61f4f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h | |||
@@ -138,6 +138,8 @@ struct iwl_ssid_ie { | |||
138 | *@SCAN_FLAGS_DELAYED_SCAN_LOWBAND: | 138 | *@SCAN_FLAGS_DELAYED_SCAN_LOWBAND: |
139 | *@SCAN_FLAGS_DELAYED_SCAN_HIGHBAND: | 139 | *@SCAN_FLAGS_DELAYED_SCAN_HIGHBAND: |
140 | *@SCAN_FLAGS_FRAGMENTED_SCAN: | 140 | *@SCAN_FLAGS_FRAGMENTED_SCAN: |
141 | *@SCAN_FLAGS_PASSIVE2ACTIVE: use active scan on channels that was active | ||
142 | * in the past hour, even if they are marked as passive. | ||
141 | */ | 143 | */ |
142 | enum iwl_scan_flags { | 144 | enum iwl_scan_flags { |
143 | SCAN_FLAGS_PERIODIC_SCAN = BIT(0), | 145 | SCAN_FLAGS_PERIODIC_SCAN = BIT(0), |
@@ -145,6 +147,7 @@ enum iwl_scan_flags { | |||
145 | SCAN_FLAGS_DELAYED_SCAN_LOWBAND = BIT(2), | 147 | SCAN_FLAGS_DELAYED_SCAN_LOWBAND = BIT(2), |
146 | SCAN_FLAGS_DELAYED_SCAN_HIGHBAND = BIT(3), | 148 | SCAN_FLAGS_DELAYED_SCAN_HIGHBAND = BIT(3), |
147 | SCAN_FLAGS_FRAGMENTED_SCAN = BIT(4), | 149 | SCAN_FLAGS_FRAGMENTED_SCAN = BIT(4), |
150 | SCAN_FLAGS_PASSIVE2ACTIVE = BIT(5), | ||
148 | }; | 151 | }; |
149 | 152 | ||
150 | /** | 153 | /** |
@@ -179,7 +182,7 @@ enum iwl_scan_type { | |||
179 | * @quiet_time: in msecs, dwell this time for active scan on quiet channels | 182 | * @quiet_time: in msecs, dwell this time for active scan on quiet channels |
180 | * @quiet_plcp_th: quiet PLCP threshold (channel is quiet if less than | 183 | * @quiet_plcp_th: quiet PLCP threshold (channel is quiet if less than |
181 | * this number of packets were received (typically 1) | 184 | * this number of packets were received (typically 1) |
182 | * @passive2active: is auto switching from passive to active allowed (0 or 1) | 185 | * @passive2active: is auto switching from passive to active during scan allowed |
183 | * @rxchain_sel_flags: RXON_RX_CHAIN_* | 186 | * @rxchain_sel_flags: RXON_RX_CHAIN_* |
184 | * @max_out_time: in usecs, max out of serving channel time | 187 | * @max_out_time: in usecs, max out of serving channel time |
185 | * @suspend_time: how long to pause scan when returning to service channel: | 188 | * @suspend_time: how long to pause scan when returning to service channel: |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h index 700cce731770..d606197bde8f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h | |||
@@ -91,7 +91,6 @@ | |||
91 | * @TX_CMD_FLG_RESP_TO_DRV: zero this if the response should go only to FW | 91 | * @TX_CMD_FLG_RESP_TO_DRV: zero this if the response should go only to FW |
92 | * @TX_CMD_FLG_CCMP_AGG: this frame uses CCMP for aggregation acceleration | 92 | * @TX_CMD_FLG_CCMP_AGG: this frame uses CCMP for aggregation acceleration |
93 | * @TX_CMD_FLG_TKIP_MIC_DONE: FW already performed TKIP MIC calculation | 93 | * @TX_CMD_FLG_TKIP_MIC_DONE: FW already performed TKIP MIC calculation |
94 | * @TX_CMD_FLG_CTS_ONLY: send CTS only, no data after that | ||
95 | * @TX_CMD_FLG_DUR: disable duration overwriting used in PS-Poll Assoc-id | 94 | * @TX_CMD_FLG_DUR: disable duration overwriting used in PS-Poll Assoc-id |
96 | * @TX_CMD_FLG_FW_DROP: FW should mark frame to be dropped | 95 | * @TX_CMD_FLG_FW_DROP: FW should mark frame to be dropped |
97 | * @TX_CMD_FLG_EXEC_PAPD: execute PAPD | 96 | * @TX_CMD_FLG_EXEC_PAPD: execute PAPD |
@@ -120,7 +119,6 @@ enum iwl_tx_flags { | |||
120 | TX_CMD_FLG_RESP_TO_DRV = BIT(21), | 119 | TX_CMD_FLG_RESP_TO_DRV = BIT(21), |
121 | TX_CMD_FLG_CCMP_AGG = BIT(22), | 120 | TX_CMD_FLG_CCMP_AGG = BIT(22), |
122 | TX_CMD_FLG_TKIP_MIC_DONE = BIT(23), | 121 | TX_CMD_FLG_TKIP_MIC_DONE = BIT(23), |
123 | TX_CMD_FLG_CTS_ONLY = BIT(24), | ||
124 | TX_CMD_FLG_DUR = BIT(25), | 122 | TX_CMD_FLG_DUR = BIT(25), |
125 | TX_CMD_FLG_FW_DROP = BIT(26), | 123 | TX_CMD_FLG_FW_DROP = BIT(26), |
126 | TX_CMD_FLG_EXEC_PAPD = BIT(27), | 124 | TX_CMD_FLG_EXEC_PAPD = BIT(27), |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index cbfb3beae783..55854a309f94 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
@@ -136,7 +136,7 @@ enum { | |||
136 | CALIB_RES_NOTIF_PHY_DB = 0x6b, | 136 | CALIB_RES_NOTIF_PHY_DB = 0x6b, |
137 | /* PHY_DB_CMD = 0x6c, */ | 137 | /* PHY_DB_CMD = 0x6c, */ |
138 | 138 | ||
139 | /* Power */ | 139 | /* Power - legacy power table command */ |
140 | POWER_TABLE_CMD = 0x77, | 140 | POWER_TABLE_CMD = 0x77, |
141 | 141 | ||
142 | /* Thermal Throttling*/ | 142 | /* Thermal Throttling*/ |
@@ -159,6 +159,7 @@ enum { | |||
159 | TX_ANT_CONFIGURATION_CMD = 0x98, | 159 | TX_ANT_CONFIGURATION_CMD = 0x98, |
160 | BT_CONFIG = 0x9b, | 160 | BT_CONFIG = 0x9b, |
161 | STATISTICS_NOTIFICATION = 0x9d, | 161 | STATISTICS_NOTIFICATION = 0x9d, |
162 | REDUCE_TX_POWER_CMD = 0x9f, | ||
162 | 163 | ||
163 | /* RF-KILL commands and notifications */ | 164 | /* RF-KILL commands and notifications */ |
164 | CARD_STATE_CMD = 0xa0, | 165 | CARD_STATE_CMD = 0xa0, |
@@ -166,6 +167,9 @@ enum { | |||
166 | 167 | ||
167 | MISSED_BEACONS_NOTIFICATION = 0xa2, | 168 | MISSED_BEACONS_NOTIFICATION = 0xa2, |
168 | 169 | ||
170 | /* Power - new power table command */ | ||
171 | MAC_PM_POWER_TABLE = 0xa9, | ||
172 | |||
169 | REPLY_RX_PHY_CMD = 0xc0, | 173 | REPLY_RX_PHY_CMD = 0xc0, |
170 | REPLY_RX_MPDU_CMD = 0xc1, | 174 | REPLY_RX_MPDU_CMD = 0xc1, |
171 | BA_NOTIF = 0xc5, | 175 | BA_NOTIF = 0xc5, |
@@ -223,6 +227,19 @@ struct iwl_tx_ant_cfg_cmd { | |||
223 | __le32 valid; | 227 | __le32 valid; |
224 | } __packed; | 228 | } __packed; |
225 | 229 | ||
230 | /** | ||
231 | * struct iwl_reduce_tx_power_cmd - TX power reduction command | ||
232 | * REDUCE_TX_POWER_CMD = 0x9f | ||
233 | * @flags: (reserved for future implementation) | ||
234 | * @mac_context_id: id of the mac ctx for which we are reducing TX power. | ||
235 | * @pwr_restriction: TX power restriction in dBms. | ||
236 | */ | ||
237 | struct iwl_reduce_tx_power_cmd { | ||
238 | u8 flags; | ||
239 | u8 mac_context_id; | ||
240 | __le16 pwr_restriction; | ||
241 | } __packed; /* TX_REDUCED_POWER_API_S_VER_1 */ | ||
242 | |||
226 | /* | 243 | /* |
227 | * Calibration control struct. | 244 | * Calibration control struct. |
228 | * Sent as part of the phy configuration command. | 245 | * Sent as part of the phy configuration command. |
@@ -765,6 +782,14 @@ struct iwl_phy_context_cmd { | |||
765 | } __packed; /* PHY_CONTEXT_CMD_API_VER_1 */ | 782 | } __packed; /* PHY_CONTEXT_CMD_API_VER_1 */ |
766 | 783 | ||
767 | #define IWL_RX_INFO_PHY_CNT 8 | 784 | #define IWL_RX_INFO_PHY_CNT 8 |
785 | #define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1 | ||
786 | #define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff | ||
787 | #define IWL_RX_INFO_ENERGY_ANT_B_MSK 0x0000ff00 | ||
788 | #define IWL_RX_INFO_ENERGY_ANT_C_MSK 0x00ff0000 | ||
789 | #define IWL_RX_INFO_ENERGY_ANT_A_POS 0 | ||
790 | #define IWL_RX_INFO_ENERGY_ANT_B_POS 8 | ||
791 | #define IWL_RX_INFO_ENERGY_ANT_C_POS 16 | ||
792 | |||
768 | #define IWL_RX_INFO_AGC_IDX 1 | 793 | #define IWL_RX_INFO_AGC_IDX 1 |
769 | #define IWL_RX_INFO_RSSI_AB_IDX 2 | 794 | #define IWL_RX_INFO_RSSI_AB_IDX 2 |
770 | #define IWL_OFDM_AGC_A_MSK 0x0000007f | 795 | #define IWL_OFDM_AGC_A_MSK 0x0000007f |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index cd7c0032cc58..c76299a3a1e0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
@@ -78,22 +78,6 @@ | |||
78 | 78 | ||
79 | #define UCODE_VALID_OK cpu_to_le32(0x1) | 79 | #define UCODE_VALID_OK cpu_to_le32(0x1) |
80 | 80 | ||
81 | /* Default calibration values for WkP - set to INIT image w/o running */ | ||
82 | static const u8 wkp_calib_values_rx_iq_skew[] = { 0x00, 0x00, 0x01, 0x00 }; | ||
83 | static const u8 wkp_calib_values_tx_iq_skew[] = { 0x01, 0x00, 0x00, 0x00 }; | ||
84 | |||
85 | struct iwl_calib_default_data { | ||
86 | u16 size; | ||
87 | void *data; | ||
88 | }; | ||
89 | |||
90 | #define CALIB_SIZE_N_DATA(_buf) {.size = sizeof(_buf), .data = &_buf} | ||
91 | |||
92 | static const struct iwl_calib_default_data wkp_calib_default_data[12] = { | ||
93 | [9] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq_skew), | ||
94 | [11] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq_skew), | ||
95 | }; | ||
96 | |||
97 | struct iwl_mvm_alive_data { | 81 | struct iwl_mvm_alive_data { |
98 | bool valid; | 82 | bool valid; |
99 | u32 scd_base_addr; | 83 | u32 scd_base_addr; |
@@ -248,40 +232,6 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm) | |||
248 | sizeof(phy_cfg_cmd), &phy_cfg_cmd); | 232 | sizeof(phy_cfg_cmd), &phy_cfg_cmd); |
249 | } | 233 | } |
250 | 234 | ||
251 | static int iwl_set_default_calibrations(struct iwl_mvm *mvm) | ||
252 | { | ||
253 | u8 cmd_raw[16]; /* holds the variable size commands */ | ||
254 | struct iwl_set_calib_default_cmd *cmd = | ||
255 | (struct iwl_set_calib_default_cmd *)cmd_raw; | ||
256 | int ret, i; | ||
257 | |||
258 | /* Setting default values for calibrations we don't run */ | ||
259 | for (i = 0; i < ARRAY_SIZE(wkp_calib_default_data); i++) { | ||
260 | u16 cmd_len; | ||
261 | |||
262 | if (wkp_calib_default_data[i].size == 0) | ||
263 | continue; | ||
264 | |||
265 | memset(cmd_raw, 0, sizeof(cmd_raw)); | ||
266 | cmd_len = wkp_calib_default_data[i].size + sizeof(cmd); | ||
267 | cmd->calib_index = cpu_to_le16(i); | ||
268 | cmd->length = cpu_to_le16(wkp_calib_default_data[i].size); | ||
269 | if (WARN_ONCE(cmd_len > sizeof(cmd_raw), | ||
270 | "Need to enlarge cmd_raw to %d\n", cmd_len)) | ||
271 | break; | ||
272 | memcpy(cmd->data, wkp_calib_default_data[i].data, | ||
273 | wkp_calib_default_data[i].size); | ||
274 | ret = iwl_mvm_send_cmd_pdu(mvm, SET_CALIB_DEFAULT_CMD, 0, | ||
275 | sizeof(*cmd) + | ||
276 | wkp_calib_default_data[i].size, | ||
277 | cmd); | ||
278 | if (ret) | ||
279 | return ret; | ||
280 | } | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | 235 | int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) |
286 | { | 236 | { |
287 | struct iwl_notification_wait calib_wait; | 237 | struct iwl_notification_wait calib_wait; |
@@ -342,11 +292,6 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
342 | if (ret) | 292 | if (ret) |
343 | goto error; | 293 | goto error; |
344 | 294 | ||
345 | /* need to set default values */ | ||
346 | ret = iwl_set_default_calibrations(mvm); | ||
347 | if (ret) | ||
348 | goto error; | ||
349 | |||
350 | /* | 295 | /* |
351 | * Send phy configurations command to init uCode | 296 | * Send phy configurations command to init uCode |
352 | * to start the 16.0 uCode init image internal calibrations. | 297 | * to start the 16.0 uCode init image internal calibrations. |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 94aae9c8562c..5fe23a5ea9b6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |||
@@ -264,7 +264,8 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm, | |||
264 | return 0; | 264 | return 0; |
265 | 265 | ||
266 | /* Therefore, in recovery, we can't get here */ | 266 | /* Therefore, in recovery, we can't get here */ |
267 | WARN_ON_ONCE(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)); | 267 | if (WARN_ON_ONCE(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))) |
268 | return -EBUSY; | ||
268 | 269 | ||
269 | mvmvif->id = find_first_bit(data.available_mac_ids, | 270 | mvmvif->id = find_first_bit(data.available_mac_ids, |
270 | NUM_MAC_INDEX_DRIVER); | 271 | NUM_MAC_INDEX_DRIVER); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 1eedc424051c..fc61b274780c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -153,7 +153,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
153 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | | 153 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | |
154 | IEEE80211_HW_AMPDU_AGGREGATION | | 154 | IEEE80211_HW_AMPDU_AGGREGATION | |
155 | IEEE80211_HW_TIMING_BEACON_ONLY | | 155 | IEEE80211_HW_TIMING_BEACON_ONLY | |
156 | IEEE80211_HW_CONNECTION_MONITOR; | 156 | IEEE80211_HW_CONNECTION_MONITOR | |
157 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | ||
158 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; | ||
157 | 159 | ||
158 | hw->queues = IWL_MVM_FIRST_AGG_QUEUE; | 160 | hw->queues = IWL_MVM_FIRST_AGG_QUEUE; |
159 | hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE; | 161 | hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE; |
@@ -531,6 +533,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
531 | goto out_release; | 533 | goto out_release; |
532 | } | 534 | } |
533 | 535 | ||
536 | iwl_mvm_vif_dbgfs_register(mvm, vif); | ||
534 | goto out_unlock; | 537 | goto out_unlock; |
535 | } | 538 | } |
536 | 539 | ||
@@ -567,7 +570,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
567 | 570 | ||
568 | /* beacon filtering */ | 571 | /* beacon filtering */ |
569 | if (!mvm->bf_allowed_vif && | 572 | if (!mvm->bf_allowed_vif && |
570 | vif->type == NL80211_IFTYPE_STATION && !vif->p2p){ | 573 | vif->type == NL80211_IFTYPE_STATION && !vif->p2p && |
574 | mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BF_UPDATED){ | ||
571 | mvm->bf_allowed_vif = mvmvif; | 575 | mvm->bf_allowed_vif = mvmvif; |
572 | vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; | 576 | vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; |
573 | } | 577 | } |
@@ -719,6 +723,20 @@ out_release: | |||
719 | mutex_unlock(&mvm->mutex); | 723 | mutex_unlock(&mvm->mutex); |
720 | } | 724 | } |
721 | 725 | ||
726 | static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | ||
727 | s8 tx_power) | ||
728 | { | ||
729 | /* FW is in charge of regulatory enforcement */ | ||
730 | struct iwl_reduce_tx_power_cmd reduce_txpwr_cmd = { | ||
731 | .mac_context_id = iwl_mvm_vif_from_mac80211(vif)->id, | ||
732 | .pwr_restriction = cpu_to_le16(tx_power), | ||
733 | }; | ||
734 | |||
735 | return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, CMD_SYNC, | ||
736 | sizeof(reduce_txpwr_cmd), | ||
737 | &reduce_txpwr_cmd); | ||
738 | } | ||
739 | |||
722 | static int iwl_mvm_mac_config(struct ieee80211_hw *hw, u32 changed) | 740 | static int iwl_mvm_mac_config(struct ieee80211_hw *hw, u32 changed) |
723 | { | 741 | { |
724 | return 0; | 742 | return 0; |
@@ -766,7 +784,6 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
766 | IWL_ERR(mvm, "failed to update quotas\n"); | 784 | IWL_ERR(mvm, "failed to update quotas\n"); |
767 | return; | 785 | return; |
768 | } | 786 | } |
769 | iwl_mvm_bt_coex_vif_assoc(mvm, vif); | ||
770 | iwl_mvm_configure_mcast_filter(mvm, vif); | 787 | iwl_mvm_configure_mcast_filter(mvm, vif); |
771 | } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) { | 788 | } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) { |
772 | /* remove AP station now that the MAC is unassoc */ | 789 | /* remove AP station now that the MAC is unassoc */ |
@@ -779,9 +796,15 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
779 | if (ret) | 796 | if (ret) |
780 | IWL_ERR(mvm, "failed to update quotas\n"); | 797 | IWL_ERR(mvm, "failed to update quotas\n"); |
781 | } | 798 | } |
782 | ret = iwl_mvm_power_update_mode(mvm, vif); | 799 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD)) { |
783 | if (ret) | 800 | /* Workaround for FW bug, otherwise FW disables device |
784 | IWL_ERR(mvm, "failed to update power mode\n"); | 801 | * power save upon disassociation |
802 | */ | ||
803 | ret = iwl_mvm_power_update_mode(mvm, vif); | ||
804 | if (ret) | ||
805 | IWL_ERR(mvm, "failed to update power mode\n"); | ||
806 | } | ||
807 | iwl_mvm_bt_coex_vif_assoc(mvm, vif); | ||
785 | } else if (changes & BSS_CHANGED_BEACON_INFO) { | 808 | } else if (changes & BSS_CHANGED_BEACON_INFO) { |
786 | /* | 809 | /* |
787 | * We received a beacon _after_ association so | 810 | * We received a beacon _after_ association so |
@@ -794,6 +817,11 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
794 | if (ret) | 817 | if (ret) |
795 | IWL_ERR(mvm, "failed to update power mode\n"); | 818 | IWL_ERR(mvm, "failed to update power mode\n"); |
796 | } | 819 | } |
820 | if (changes & BSS_CHANGED_TXPOWER) { | ||
821 | IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d\n", | ||
822 | bss_conf->txpower); | ||
823 | iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower); | ||
824 | } | ||
797 | } | 825 | } |
798 | 826 | ||
799 | static int iwl_mvm_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | 827 | static int iwl_mvm_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 420e82d379d9..29bebae7f003 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -76,6 +76,7 @@ | |||
76 | #include "iwl-trans.h" | 76 | #include "iwl-trans.h" |
77 | #include "sta.h" | 77 | #include "sta.h" |
78 | #include "fw-api.h" | 78 | #include "fw-api.h" |
79 | #include "constants.h" | ||
79 | 80 | ||
80 | #define IWL_INVALID_MAC80211_QUEUE 0xff | 81 | #define IWL_INVALID_MAC80211_QUEUE 0xff |
81 | #define IWL_MVM_MAX_ADDRESSES 5 | 82 | #define IWL_MVM_MAX_ADDRESSES 5 |
@@ -91,6 +92,9 @@ enum iwl_mvm_tx_fifo { | |||
91 | }; | 92 | }; |
92 | 93 | ||
93 | extern struct ieee80211_ops iwl_mvm_hw_ops; | 94 | extern struct ieee80211_ops iwl_mvm_hw_ops; |
95 | extern const struct iwl_mvm_power_ops pm_legacy_ops; | ||
96 | extern const struct iwl_mvm_power_ops pm_mac_ops; | ||
97 | |||
94 | /** | 98 | /** |
95 | * struct iwl_mvm_mod_params - module parameters for iwlmvm | 99 | * struct iwl_mvm_mod_params - module parameters for iwlmvm |
96 | * @init_dbg: if true, then the NIC won't be stopped if the INIT fw asserted. | 100 | * @init_dbg: if true, then the NIC won't be stopped if the INIT fw asserted. |
@@ -150,6 +154,17 @@ enum iwl_power_scheme { | |||
150 | 154 | ||
151 | #define IWL_CONN_MAX_LISTEN_INTERVAL 70 | 155 | #define IWL_CONN_MAX_LISTEN_INTERVAL 70 |
152 | 156 | ||
157 | struct iwl_mvm_power_ops { | ||
158 | int (*power_update_mode)(struct iwl_mvm *mvm, | ||
159 | struct ieee80211_vif *vif); | ||
160 | int (*power_disable)(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | ||
161 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
162 | int (*power_dbgfs_read)(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | ||
163 | char *buf, int bufsz); | ||
164 | #endif | ||
165 | }; | ||
166 | |||
167 | |||
153 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 168 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
154 | enum iwl_dbgfs_pm_mask { | 169 | enum iwl_dbgfs_pm_mask { |
155 | MVM_DEBUGFS_PM_KEEP_ALIVE = BIT(0), | 170 | MVM_DEBUGFS_PM_KEEP_ALIVE = BIT(0), |
@@ -163,7 +178,7 @@ enum iwl_dbgfs_pm_mask { | |||
163 | }; | 178 | }; |
164 | 179 | ||
165 | struct iwl_dbgfs_pm { | 180 | struct iwl_dbgfs_pm { |
166 | u8 keep_alive_seconds; | 181 | u16 keep_alive_seconds; |
167 | u32 rx_data_timeout; | 182 | u32 rx_data_timeout; |
168 | u32 tx_data_timeout; | 183 | u32 tx_data_timeout; |
169 | bool skip_over_dtim; | 184 | bool skip_over_dtim; |
@@ -180,24 +195,28 @@ enum iwl_dbgfs_bf_mask { | |||
180 | MVM_DEBUGFS_BF_ENERGY_DELTA = BIT(0), | 195 | MVM_DEBUGFS_BF_ENERGY_DELTA = BIT(0), |
181 | MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA = BIT(1), | 196 | MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA = BIT(1), |
182 | MVM_DEBUGFS_BF_ROAMING_STATE = BIT(2), | 197 | MVM_DEBUGFS_BF_ROAMING_STATE = BIT(2), |
183 | MVM_DEBUGFS_BF_TEMPERATURE_DELTA = BIT(3), | 198 | MVM_DEBUGFS_BF_TEMP_THRESHOLD = BIT(3), |
184 | MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER = BIT(4), | 199 | MVM_DEBUGFS_BF_TEMP_FAST_FILTER = BIT(4), |
185 | MVM_DEBUGFS_BF_DEBUG_FLAG = BIT(5), | 200 | MVM_DEBUGFS_BF_TEMP_SLOW_FILTER = BIT(5), |
186 | MVM_DEBUGFS_BF_ESCAPE_TIMER = BIT(6), | 201 | MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER = BIT(6), |
187 | MVM_DEBUGFS_BA_ESCAPE_TIMER = BIT(7), | 202 | MVM_DEBUGFS_BF_DEBUG_FLAG = BIT(7), |
188 | MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT = BIT(8), | 203 | MVM_DEBUGFS_BF_ESCAPE_TIMER = BIT(8), |
204 | MVM_DEBUGFS_BA_ESCAPE_TIMER = BIT(9), | ||
205 | MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT = BIT(10), | ||
189 | }; | 206 | }; |
190 | 207 | ||
191 | struct iwl_dbgfs_bf { | 208 | struct iwl_dbgfs_bf { |
192 | u8 bf_energy_delta; | 209 | u32 bf_energy_delta; |
193 | u8 bf_roaming_energy_delta; | 210 | u32 bf_roaming_energy_delta; |
194 | u8 bf_roaming_state; | 211 | u32 bf_roaming_state; |
195 | u8 bf_temperature_delta; | 212 | u32 bf_temp_threshold; |
196 | u8 bf_enable_beacon_filter; | 213 | u32 bf_temp_fast_filter; |
197 | u8 bf_debug_flag; | 214 | u32 bf_temp_slow_filter; |
215 | u32 bf_enable_beacon_filter; | ||
216 | u32 bf_debug_flag; | ||
198 | u32 bf_escape_timer; | 217 | u32 bf_escape_timer; |
199 | u32 ba_escape_timer; | 218 | u32 ba_escape_timer; |
200 | u8 ba_enable_beacon_abort; | 219 | u32 ba_enable_beacon_abort; |
201 | int mask; | 220 | int mask; |
202 | }; | 221 | }; |
203 | #endif | 222 | #endif |
@@ -268,7 +287,7 @@ struct iwl_mvm_vif { | |||
268 | 287 | ||
269 | #if IS_ENABLED(CONFIG_IPV6) | 288 | #if IS_ENABLED(CONFIG_IPV6) |
270 | /* IPv6 addresses for WoWLAN */ | 289 | /* IPv6 addresses for WoWLAN */ |
271 | struct in6_addr target_ipv6_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS]; | 290 | struct in6_addr target_ipv6_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX]; |
272 | int num_target_ipv6_addrs; | 291 | int num_target_ipv6_addrs; |
273 | #endif | 292 | #endif |
274 | #endif | 293 | #endif |
@@ -459,6 +478,9 @@ struct iwl_mvm { | |||
459 | */ | 478 | */ |
460 | u8 vif_count; | 479 | u8 vif_count; |
461 | 480 | ||
481 | /* -1 for always, 0 for never, >0 for that many times */ | ||
482 | s8 restart_fw; | ||
483 | |||
462 | struct led_classdev led; | 484 | struct led_classdev led; |
463 | 485 | ||
464 | struct ieee80211_vif *p2p_device_vif; | 486 | struct ieee80211_vif *p2p_device_vif; |
@@ -482,6 +504,8 @@ struct iwl_mvm { | |||
482 | /* Thermal Throttling and CTkill */ | 504 | /* Thermal Throttling and CTkill */ |
483 | struct iwl_mvm_tt_mgmt thermal_throttle; | 505 | struct iwl_mvm_tt_mgmt thermal_throttle; |
484 | s32 temperature; /* Celsius */ | 506 | s32 temperature; /* Celsius */ |
507 | |||
508 | const struct iwl_mvm_power_ops *pm_ops; | ||
485 | }; | 509 | }; |
486 | 510 | ||
487 | /* Extract MVM priv from op_mode and _hw */ | 511 | /* Extract MVM priv from op_mode and _hw */ |
@@ -525,6 +549,7 @@ int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags, | |||
525 | enum ieee80211_band band); | 549 | enum ieee80211_band band); |
526 | u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx); | 550 | u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx); |
527 | void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm); | 551 | void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm); |
552 | void iwl_mvm_dump_sram(struct iwl_mvm *mvm); | ||
528 | u8 first_antenna(u8 mask); | 553 | u8 first_antenna(u8 mask); |
529 | u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx); | 554 | u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx); |
530 | 555 | ||
@@ -660,10 +685,26 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, | |||
660 | u8 flags, bool init); | 685 | u8 flags, bool init); |
661 | 686 | ||
662 | /* power managment */ | 687 | /* power managment */ |
663 | int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 688 | static inline int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, |
664 | int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 689 | struct ieee80211_vif *vif) |
665 | void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 690 | { |
666 | struct iwl_powertable_cmd *cmd); | 691 | return mvm->pm_ops->power_update_mode(mvm, vif); |
692 | } | ||
693 | |||
694 | static inline int iwl_mvm_power_disable(struct iwl_mvm *mvm, | ||
695 | struct ieee80211_vif *vif) | ||
696 | { | ||
697 | return mvm->pm_ops->power_disable(mvm, vif); | ||
698 | } | ||
699 | |||
700 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
701 | static inline int iwl_mvm_power_dbgfs_read(struct iwl_mvm *mvm, | ||
702 | struct ieee80211_vif *vif, | ||
703 | char *buf, int bufsz) | ||
704 | { | ||
705 | return mvm->pm_ops->power_dbgfs_read(mvm, vif, buf, bufsz); | ||
706 | } | ||
707 | #endif | ||
667 | 708 | ||
668 | int iwl_mvm_leds_init(struct iwl_mvm *mvm); | 709 | int iwl_mvm_leds_init(struct iwl_mvm *mvm); |
669 | void iwl_mvm_leds_exit(struct iwl_mvm *mvm); | 710 | void iwl_mvm_leds_exit(struct iwl_mvm *mvm); |
@@ -707,6 +748,10 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, | |||
707 | struct ieee80211_vif *vif); | 748 | struct ieee80211_vif *vif); |
708 | int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, | 749 | int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, |
709 | struct ieee80211_vif *vif); | 750 | struct ieee80211_vif *vif); |
751 | int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm, | ||
752 | struct iwl_beacon_filter_cmd *cmd); | ||
753 | int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm, | ||
754 | struct ieee80211_vif *vif, bool enable); | ||
710 | 755 | ||
711 | /* SMPS */ | 756 | /* SMPS */ |
712 | void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 757 | void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index af79a14063a9..65e5fb86291f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -275,6 +275,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { | |||
275 | CMD(BEACON_NOTIFICATION), | 275 | CMD(BEACON_NOTIFICATION), |
276 | CMD(BEACON_TEMPLATE_CMD), | 276 | CMD(BEACON_TEMPLATE_CMD), |
277 | CMD(STATISTICS_NOTIFICATION), | 277 | CMD(STATISTICS_NOTIFICATION), |
278 | CMD(REDUCE_TX_POWER_CMD), | ||
278 | CMD(TX_ANT_CONFIGURATION_CMD), | 279 | CMD(TX_ANT_CONFIGURATION_CMD), |
279 | CMD(D3_CONFIG_CMD), | 280 | CMD(D3_CONFIG_CMD), |
280 | CMD(PROT_OFFLOAD_CONFIG_CMD), | 281 | CMD(PROT_OFFLOAD_CONFIG_CMD), |
@@ -301,6 +302,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { | |||
301 | CMD(MCAST_FILTER_CMD), | 302 | CMD(MCAST_FILTER_CMD), |
302 | CMD(REPLY_BEACON_FILTERING_CMD), | 303 | CMD(REPLY_BEACON_FILTERING_CMD), |
303 | CMD(REPLY_THERMAL_MNG_BACKOFF), | 304 | CMD(REPLY_THERMAL_MNG_BACKOFF), |
305 | CMD(MAC_PM_POWER_TABLE), | ||
304 | }; | 306 | }; |
305 | #undef CMD | 307 | #undef CMD |
306 | 308 | ||
@@ -340,6 +342,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
340 | mvm->fw = fw; | 342 | mvm->fw = fw; |
341 | mvm->hw = hw; | 343 | mvm->hw = hw; |
342 | 344 | ||
345 | mvm->restart_fw = iwlwifi_mod_params.restart_fw ? -1 : 0; | ||
346 | |||
343 | mutex_init(&mvm->mutex); | 347 | mutex_init(&mvm->mutex); |
344 | spin_lock_init(&mvm->async_handlers_lock); | 348 | spin_lock_init(&mvm->async_handlers_lock); |
345 | INIT_LIST_HEAD(&mvm->time_event_list); | 349 | INIT_LIST_HEAD(&mvm->time_event_list); |
@@ -431,6 +435,11 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
431 | if (err) | 435 | if (err) |
432 | goto out_unregister; | 436 | goto out_unregister; |
433 | 437 | ||
438 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD) | ||
439 | mvm->pm_ops = &pm_mac_ops; | ||
440 | else | ||
441 | mvm->pm_ops = &pm_legacy_ops; | ||
442 | |||
434 | return op_mode; | 443 | return op_mode; |
435 | 444 | ||
436 | out_unregister: | 445 | out_unregister: |
@@ -638,6 +647,22 @@ static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) | |||
638 | ieee80211_free_txskb(mvm->hw, skb); | 647 | ieee80211_free_txskb(mvm->hw, skb); |
639 | } | 648 | } |
640 | 649 | ||
650 | struct iwl_mvm_reprobe { | ||
651 | struct device *dev; | ||
652 | struct work_struct work; | ||
653 | }; | ||
654 | |||
655 | static void iwl_mvm_reprobe_wk(struct work_struct *wk) | ||
656 | { | ||
657 | struct iwl_mvm_reprobe *reprobe; | ||
658 | |||
659 | reprobe = container_of(wk, struct iwl_mvm_reprobe, work); | ||
660 | if (device_reprobe(reprobe->dev)) | ||
661 | dev_err(reprobe->dev, "reprobe failed!\n"); | ||
662 | kfree(reprobe); | ||
663 | module_put(THIS_MODULE); | ||
664 | } | ||
665 | |||
641 | static void iwl_mvm_nic_restart(struct iwl_mvm *mvm) | 666 | static void iwl_mvm_nic_restart(struct iwl_mvm *mvm) |
642 | { | 667 | { |
643 | iwl_abort_notification_waits(&mvm->notif_wait); | 668 | iwl_abort_notification_waits(&mvm->notif_wait); |
@@ -649,9 +674,30 @@ static void iwl_mvm_nic_restart(struct iwl_mvm *mvm) | |||
649 | * can't recover this since we're already half suspended. | 674 | * can't recover this since we're already half suspended. |
650 | */ | 675 | */ |
651 | if (test_and_set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { | 676 | if (test_and_set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { |
652 | IWL_ERR(mvm, "Firmware error during reconfiguration! Abort.\n"); | 677 | struct iwl_mvm_reprobe *reprobe; |
653 | } else if (mvm->cur_ucode == IWL_UCODE_REGULAR && | 678 | |
654 | iwlwifi_mod_params.restart_fw) { | 679 | IWL_ERR(mvm, |
680 | "Firmware error during reconfiguration - reprobe!\n"); | ||
681 | |||
682 | /* | ||
683 | * get a module reference to avoid doing this while unloading | ||
684 | * anyway and to avoid scheduling a work with code that's | ||
685 | * being removed. | ||
686 | */ | ||
687 | if (!try_module_get(THIS_MODULE)) { | ||
688 | IWL_ERR(mvm, "Module is being unloaded - abort\n"); | ||
689 | return; | ||
690 | } | ||
691 | |||
692 | reprobe = kzalloc(sizeof(*reprobe), GFP_ATOMIC); | ||
693 | if (!reprobe) { | ||
694 | module_put(THIS_MODULE); | ||
695 | return; | ||
696 | } | ||
697 | reprobe->dev = mvm->trans->dev; | ||
698 | INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk); | ||
699 | schedule_work(&reprobe->work); | ||
700 | } else if (mvm->cur_ucode == IWL_UCODE_REGULAR && mvm->restart_fw) { | ||
655 | /* | 701 | /* |
656 | * This is a bit racy, but worst case we tell mac80211 about | 702 | * This is a bit racy, but worst case we tell mac80211 about |
657 | * a stopped/aborted (sched) scan when that was already done | 703 | * a stopped/aborted (sched) scan when that was already done |
@@ -669,6 +715,8 @@ static void iwl_mvm_nic_restart(struct iwl_mvm *mvm) | |||
669 | break; | 715 | break; |
670 | } | 716 | } |
671 | 717 | ||
718 | if (mvm->restart_fw > 0) | ||
719 | mvm->restart_fw--; | ||
672 | ieee80211_restart_hw(mvm->hw); | 720 | ieee80211_restart_hw(mvm->hw); |
673 | } | 721 | } |
674 | } | 722 | } |
@@ -678,6 +726,8 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode) | |||
678 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | 726 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); |
679 | 727 | ||
680 | iwl_mvm_dump_nic_error_log(mvm); | 728 | iwl_mvm_dump_nic_error_log(mvm); |
729 | if (!mvm->restart_fw) | ||
730 | iwl_mvm_dump_sram(mvm); | ||
681 | 731 | ||
682 | iwl_mvm_nic_restart(mvm); | 732 | iwl_mvm_nic_restart(mvm); |
683 | } | 733 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index e7ca965a89b8..4e7c9f245846 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c | |||
@@ -75,8 +75,8 @@ | |||
75 | 75 | ||
76 | #define POWER_KEEP_ALIVE_PERIOD_SEC 25 | 76 | #define POWER_KEEP_ALIVE_PERIOD_SEC 25 |
77 | 77 | ||
78 | static int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm, | 78 | int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm, |
79 | struct iwl_beacon_filter_cmd *cmd) | 79 | struct iwl_beacon_filter_cmd *cmd) |
80 | { | 80 | { |
81 | int ret; | 81 | int ret; |
82 | 82 | ||
@@ -85,52 +85,60 @@ static int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm, | |||
85 | 85 | ||
86 | if (!ret) { | 86 | if (!ret) { |
87 | IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n", | 87 | IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n", |
88 | cmd->ba_enable_beacon_abort); | 88 | le32_to_cpu(cmd->ba_enable_beacon_abort)); |
89 | IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n", | 89 | IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n", |
90 | cmd->ba_escape_timer); | 90 | le32_to_cpu(cmd->ba_escape_timer)); |
91 | IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n", | 91 | IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n", |
92 | cmd->bf_debug_flag); | 92 | le32_to_cpu(cmd->bf_debug_flag)); |
93 | IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n", | 93 | IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n", |
94 | cmd->bf_enable_beacon_filter); | 94 | le32_to_cpu(cmd->bf_enable_beacon_filter)); |
95 | IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n", | 95 | IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n", |
96 | cmd->bf_energy_delta); | 96 | le32_to_cpu(cmd->bf_energy_delta)); |
97 | IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n", | 97 | IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n", |
98 | cmd->bf_escape_timer); | 98 | le32_to_cpu(cmd->bf_escape_timer)); |
99 | IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n", | 99 | IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n", |
100 | cmd->bf_roaming_energy_delta); | 100 | le32_to_cpu(cmd->bf_roaming_energy_delta)); |
101 | IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n", | 101 | IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n", |
102 | cmd->bf_roaming_state); | 102 | le32_to_cpu(cmd->bf_roaming_state)); |
103 | IWL_DEBUG_POWER(mvm, "bf_temperature_delta is: %d\n", | 103 | IWL_DEBUG_POWER(mvm, "bf_temp_threshold is: %d\n", |
104 | cmd->bf_temperature_delta); | 104 | le32_to_cpu(cmd->bf_temp_threshold)); |
105 | IWL_DEBUG_POWER(mvm, "bf_temp_fast_filter is: %d\n", | ||
106 | le32_to_cpu(cmd->bf_temp_fast_filter)); | ||
107 | IWL_DEBUG_POWER(mvm, "bf_temp_slow_filter is: %d\n", | ||
108 | le32_to_cpu(cmd->bf_temp_slow_filter)); | ||
105 | } | 109 | } |
106 | return ret; | 110 | return ret; |
107 | } | 111 | } |
108 | 112 | ||
109 | static int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm, | 113 | int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm, |
110 | struct ieee80211_vif *vif, bool enable) | 114 | struct ieee80211_vif *vif, bool enable) |
111 | { | 115 | { |
112 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 116 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
113 | struct iwl_beacon_filter_cmd cmd = { | 117 | struct iwl_beacon_filter_cmd cmd = { |
114 | IWL_BF_CMD_CONFIG_DEFAULTS, | 118 | IWL_BF_CMD_CONFIG_DEFAULTS, |
115 | .bf_enable_beacon_filter = 1, | 119 | .bf_enable_beacon_filter = cpu_to_le32(1), |
116 | .ba_enable_beacon_abort = enable, | 120 | .ba_enable_beacon_abort = cpu_to_le32(enable), |
117 | }; | 121 | }; |
118 | 122 | ||
119 | if (!mvmvif->bf_enabled) | 123 | if (!mvmvif->bf_enabled) |
120 | return 0; | 124 | return 0; |
121 | 125 | ||
126 | if (mvm->cur_ucode == IWL_UCODE_WOWLAN) | ||
127 | cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3); | ||
128 | |||
122 | iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); | 129 | iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); |
123 | return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); | 130 | return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); |
124 | } | 131 | } |
125 | 132 | ||
126 | static void iwl_mvm_power_log(struct iwl_mvm *mvm, | 133 | static void iwl_mvm_power_log(struct iwl_mvm *mvm, |
127 | struct iwl_powertable_cmd *cmd) | 134 | struct iwl_mac_power_cmd *cmd) |
128 | { | 135 | { |
129 | IWL_DEBUG_POWER(mvm, | 136 | IWL_DEBUG_POWER(mvm, |
130 | "Sending power table command for power level %d, flags = 0x%X\n", | 137 | "Sending power table command on mac id 0x%X for power level %d, flags = 0x%X\n", |
131 | iwlmvm_mod_params.power_scheme, | 138 | cmd->id_and_color, iwlmvm_mod_params.power_scheme, |
132 | le16_to_cpu(cmd->flags)); | 139 | le16_to_cpu(cmd->flags)); |
133 | IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n", cmd->keep_alive_seconds); | 140 | IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n", |
141 | le16_to_cpu(cmd->keep_alive_seconds)); | ||
134 | 142 | ||
135 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) { | 143 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) { |
136 | IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n", | 144 | IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n", |
@@ -139,15 +147,16 @@ static void iwl_mvm_power_log(struct iwl_mvm *mvm, | |||
139 | le32_to_cpu(cmd->tx_data_timeout)); | 147 | le32_to_cpu(cmd->tx_data_timeout)); |
140 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) | 148 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) |
141 | IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n", | 149 | IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n", |
142 | le32_to_cpu(cmd->skip_dtim_periods)); | 150 | cmd->skip_dtim_periods); |
143 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK)) | 151 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK)) |
144 | IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n", | 152 | IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n", |
145 | le32_to_cpu(cmd->lprx_rssi_threshold)); | 153 | cmd->lprx_rssi_threshold); |
146 | } | 154 | } |
147 | } | 155 | } |
148 | 156 | ||
149 | void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 157 | static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, |
150 | struct iwl_powertable_cmd *cmd) | 158 | struct ieee80211_vif *vif, |
159 | struct iwl_mac_power_cmd *cmd) | ||
151 | { | 160 | { |
152 | struct ieee80211_hw *hw = mvm->hw; | 161 | struct ieee80211_hw *hw = mvm->hw; |
153 | struct ieee80211_chanctx_conf *chanctx_conf; | 162 | struct ieee80211_chanctx_conf *chanctx_conf; |
@@ -158,19 +167,26 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
158 | struct iwl_mvm_vif *mvmvif __maybe_unused = | 167 | struct iwl_mvm_vif *mvmvif __maybe_unused = |
159 | iwl_mvm_vif_from_mac80211(vif); | 168 | iwl_mvm_vif_from_mac80211(vif); |
160 | 169 | ||
170 | cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, | ||
171 | mvmvif->color)); | ||
172 | dtimper = hw->conf.ps_dtim_period ?: 1; | ||
173 | |||
161 | /* | 174 | /* |
162 | * Regardless of power management state the driver must set | 175 | * Regardless of power management state the driver must set |
163 | * keep alive period. FW will use it for sending keep alive NDPs | 176 | * keep alive period. FW will use it for sending keep alive NDPs |
164 | * immediately after association. | 177 | * immediately after association. Check that keep alive period |
178 | * is at least 3 * DTIM | ||
165 | */ | 179 | */ |
166 | cmd->keep_alive_seconds = POWER_KEEP_ALIVE_PERIOD_SEC; | 180 | dtimper_msec = dtimper * vif->bss_conf.beacon_int; |
181 | keep_alive = max_t(int, 3 * dtimper_msec, | ||
182 | MSEC_PER_SEC * POWER_KEEP_ALIVE_PERIOD_SEC); | ||
183 | keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC); | ||
184 | cmd->keep_alive_seconds = cpu_to_le16(keep_alive); | ||
167 | 185 | ||
168 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) | 186 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) |
169 | return; | 187 | return; |
170 | 188 | ||
171 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); | 189 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); |
172 | if (!vif->bss_conf.assoc) | ||
173 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); | ||
174 | 190 | ||
175 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 191 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
176 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF && | 192 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF && |
@@ -186,12 +202,9 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
186 | (vif->bss_conf.beacon_rate->bitrate == 10 || | 202 | (vif->bss_conf.beacon_rate->bitrate == 10 || |
187 | vif->bss_conf.beacon_rate->bitrate == 60)) { | 203 | vif->bss_conf.beacon_rate->bitrate == 60)) { |
188 | cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK); | 204 | cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK); |
189 | cmd->lprx_rssi_threshold = | 205 | cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD; |
190 | cpu_to_le32(POWER_LPRX_RSSI_THRESHOLD); | ||
191 | } | 206 | } |
192 | 207 | ||
193 | dtimper = hw->conf.ps_dtim_period ?: 1; | ||
194 | |||
195 | /* Check if radar detection is required on current channel */ | 208 | /* Check if radar detection is required on current channel */ |
196 | rcu_read_lock(); | 209 | rcu_read_lock(); |
197 | chanctx_conf = rcu_dereference(vif->chanctx_conf); | 210 | chanctx_conf = rcu_dereference(vif->chanctx_conf); |
@@ -207,27 +220,25 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
207 | (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP || | 220 | (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP || |
208 | mvm->cur_ucode == IWL_UCODE_WOWLAN)) { | 221 | mvm->cur_ucode == IWL_UCODE_WOWLAN)) { |
209 | cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); | 222 | cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); |
210 | cmd->skip_dtim_periods = cpu_to_le32(3); | 223 | cmd->skip_dtim_periods = 3; |
211 | } | 224 | } |
212 | 225 | ||
213 | /* Check that keep alive period is at least 3 * DTIM */ | ||
214 | dtimper_msec = dtimper * vif->bss_conf.beacon_int; | ||
215 | keep_alive = max_t(int, 3 * dtimper_msec, | ||
216 | MSEC_PER_SEC * cmd->keep_alive_seconds); | ||
217 | keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC); | ||
218 | cmd->keep_alive_seconds = keep_alive; | ||
219 | |||
220 | if (mvm->cur_ucode != IWL_UCODE_WOWLAN) { | 226 | if (mvm->cur_ucode != IWL_UCODE_WOWLAN) { |
221 | cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC); | 227 | cmd->rx_data_timeout = |
222 | cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC); | 228 | cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT); |
229 | cmd->tx_data_timeout = | ||
230 | cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT); | ||
223 | } else { | 231 | } else { |
224 | cmd->rx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC); | 232 | cmd->rx_data_timeout = |
225 | cmd->tx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC); | 233 | cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT); |
234 | cmd->tx_data_timeout = | ||
235 | cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); | ||
226 | } | 236 | } |
227 | 237 | ||
228 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 238 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
229 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE) | 239 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE) |
230 | cmd->keep_alive_seconds = mvmvif->dbgfs_pm.keep_alive_seconds; | 240 | cmd->keep_alive_seconds = |
241 | cpu_to_le16(mvmvif->dbgfs_pm.keep_alive_seconds); | ||
231 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) { | 242 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) { |
232 | if (mvmvif->dbgfs_pm.skip_over_dtim) | 243 | if (mvmvif->dbgfs_pm.skip_over_dtim) |
233 | cmd->flags |= | 244 | cmd->flags |= |
@@ -243,8 +254,7 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
243 | cmd->tx_data_timeout = | 254 | cmd->tx_data_timeout = |
244 | cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout); | 255 | cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout); |
245 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS) | 256 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS) |
246 | cmd->skip_dtim_periods = | 257 | cmd->skip_dtim_periods = mvmvif->dbgfs_pm.skip_dtim_periods; |
247 | cpu_to_le32(mvmvif->dbgfs_pm.skip_dtim_periods); | ||
248 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) { | 258 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) { |
249 | if (mvmvif->dbgfs_pm.lprx_ena) | 259 | if (mvmvif->dbgfs_pm.lprx_ena) |
250 | cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK); | 260 | cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK); |
@@ -252,16 +262,16 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
252 | cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK); | 262 | cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK); |
253 | } | 263 | } |
254 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD) | 264 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD) |
255 | cmd->lprx_rssi_threshold = | 265 | cmd->lprx_rssi_threshold = mvmvif->dbgfs_pm.lprx_rssi_threshold; |
256 | cpu_to_le32(mvmvif->dbgfs_pm.lprx_rssi_threshold); | ||
257 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | 266 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ |
258 | } | 267 | } |
259 | 268 | ||
260 | int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | 269 | static int iwl_mvm_power_mac_update_mode(struct iwl_mvm *mvm, |
270 | struct ieee80211_vif *vif) | ||
261 | { | 271 | { |
262 | int ret; | 272 | int ret; |
263 | bool ba_enable; | 273 | bool ba_enable; |
264 | struct iwl_powertable_cmd cmd = {}; | 274 | struct iwl_mac_power_cmd cmd = {}; |
265 | 275 | ||
266 | if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) | 276 | if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) |
267 | return 0; | 277 | return 0; |
@@ -280,7 +290,7 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
280 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); | 290 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); |
281 | iwl_mvm_power_log(mvm, &cmd); | 291 | iwl_mvm_power_log(mvm, &cmd); |
282 | 292 | ||
283 | ret = iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC, | 293 | ret = iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, CMD_SYNC, |
284 | sizeof(cmd), &cmd); | 294 | sizeof(cmd), &cmd); |
285 | if (ret) | 295 | if (ret) |
286 | return ret; | 296 | return ret; |
@@ -291,15 +301,19 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
291 | return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable); | 301 | return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable); |
292 | } | 302 | } |
293 | 303 | ||
294 | int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | 304 | static int iwl_mvm_power_mac_disable(struct iwl_mvm *mvm, |
305 | struct ieee80211_vif *vif) | ||
295 | { | 306 | { |
296 | struct iwl_powertable_cmd cmd = {}; | 307 | struct iwl_mac_power_cmd cmd = {}; |
297 | struct iwl_mvm_vif *mvmvif __maybe_unused = | 308 | struct iwl_mvm_vif *mvmvif __maybe_unused = |
298 | iwl_mvm_vif_from_mac80211(vif); | 309 | iwl_mvm_vif_from_mac80211(vif); |
299 | 310 | ||
300 | if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) | 311 | if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) |
301 | return 0; | 312 | return 0; |
302 | 313 | ||
314 | cmd.id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, | ||
315 | mvmvif->color)); | ||
316 | |||
303 | if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM) | 317 | if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM) |
304 | cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); | 318 | cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); |
305 | 319 | ||
@@ -310,11 +324,50 @@ int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
310 | #endif | 324 | #endif |
311 | iwl_mvm_power_log(mvm, &cmd); | 325 | iwl_mvm_power_log(mvm, &cmd); |
312 | 326 | ||
313 | return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC, | 327 | return iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, CMD_ASYNC, |
314 | sizeof(cmd), &cmd); | 328 | sizeof(cmd), &cmd); |
315 | } | 329 | } |
316 | 330 | ||
317 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 331 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
332 | static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, | ||
333 | struct ieee80211_vif *vif, char *buf, | ||
334 | int bufsz) | ||
335 | { | ||
336 | struct iwl_mac_power_cmd cmd = {}; | ||
337 | int pos = 0; | ||
338 | |||
339 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); | ||
340 | |||
341 | pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n", | ||
342 | (cmd.flags & | ||
343 | cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ? | ||
344 | 0 : 1); | ||
345 | pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n", | ||
346 | cmd.skip_dtim_periods); | ||
347 | pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n", | ||
348 | iwlmvm_mod_params.power_scheme); | ||
349 | pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n", | ||
350 | le16_to_cpu(cmd.flags)); | ||
351 | pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n", | ||
352 | le16_to_cpu(cmd.keep_alive_seconds)); | ||
353 | |||
354 | if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) { | ||
355 | pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n", | ||
356 | (cmd.flags & | ||
357 | cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ? | ||
358 | 1 : 0); | ||
359 | pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n", | ||
360 | le32_to_cpu(cmd.rx_data_timeout)); | ||
361 | pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n", | ||
362 | le32_to_cpu(cmd.tx_data_timeout)); | ||
363 | if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK)) | ||
364 | pos += scnprintf(buf+pos, bufsz-pos, | ||
365 | "lprx_rssi_threshold = %d\n", | ||
366 | cmd.lprx_rssi_threshold); | ||
367 | } | ||
368 | return pos; | ||
369 | } | ||
370 | |||
318 | void | 371 | void |
319 | iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif, | 372 | iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif, |
320 | struct iwl_beacon_filter_cmd *cmd) | 373 | struct iwl_beacon_filter_cmd *cmd) |
@@ -323,22 +376,30 @@ iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif, | |||
323 | struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf; | 376 | struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf; |
324 | 377 | ||
325 | if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ENERGY_DELTA) | 378 | if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ENERGY_DELTA) |
326 | cmd->bf_energy_delta = dbgfs_bf->bf_energy_delta; | 379 | cmd->bf_energy_delta = cpu_to_le32(dbgfs_bf->bf_energy_delta); |
327 | if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA) | 380 | if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA) |
328 | cmd->bf_roaming_energy_delta = | 381 | cmd->bf_roaming_energy_delta = |
329 | dbgfs_bf->bf_roaming_energy_delta; | 382 | cpu_to_le32(dbgfs_bf->bf_roaming_energy_delta); |
330 | if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_STATE) | 383 | if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_STATE) |
331 | cmd->bf_roaming_state = dbgfs_bf->bf_roaming_state; | 384 | cmd->bf_roaming_state = cpu_to_le32(dbgfs_bf->bf_roaming_state); |
332 | if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMPERATURE_DELTA) | 385 | if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_THRESHOLD) |
333 | cmd->bf_temperature_delta = dbgfs_bf->bf_temperature_delta; | 386 | cmd->bf_temp_threshold = |
387 | cpu_to_le32(dbgfs_bf->bf_temp_threshold); | ||
388 | if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_FAST_FILTER) | ||
389 | cmd->bf_temp_fast_filter = | ||
390 | cpu_to_le32(dbgfs_bf->bf_temp_fast_filter); | ||
391 | if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_SLOW_FILTER) | ||
392 | cmd->bf_temp_slow_filter = | ||
393 | cpu_to_le32(dbgfs_bf->bf_temp_slow_filter); | ||
334 | if (dbgfs_bf->mask & MVM_DEBUGFS_BF_DEBUG_FLAG) | 394 | if (dbgfs_bf->mask & MVM_DEBUGFS_BF_DEBUG_FLAG) |
335 | cmd->bf_debug_flag = dbgfs_bf->bf_debug_flag; | 395 | cmd->bf_debug_flag = cpu_to_le32(dbgfs_bf->bf_debug_flag); |
336 | if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ESCAPE_TIMER) | 396 | if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ESCAPE_TIMER) |
337 | cmd->bf_escape_timer = cpu_to_le32(dbgfs_bf->bf_escape_timer); | 397 | cmd->bf_escape_timer = cpu_to_le32(dbgfs_bf->bf_escape_timer); |
338 | if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ESCAPE_TIMER) | 398 | if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ESCAPE_TIMER) |
339 | cmd->ba_escape_timer = cpu_to_le32(dbgfs_bf->ba_escape_timer); | 399 | cmd->ba_escape_timer = cpu_to_le32(dbgfs_bf->ba_escape_timer); |
340 | if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT) | 400 | if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT) |
341 | cmd->ba_enable_beacon_abort = dbgfs_bf->ba_enable_beacon_abort; | 401 | cmd->ba_enable_beacon_abort = |
402 | cpu_to_le32(dbgfs_bf->ba_enable_beacon_abort); | ||
342 | } | 403 | } |
343 | #endif | 404 | #endif |
344 | 405 | ||
@@ -348,7 +409,7 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, | |||
348 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 409 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
349 | struct iwl_beacon_filter_cmd cmd = { | 410 | struct iwl_beacon_filter_cmd cmd = { |
350 | IWL_BF_CMD_CONFIG_DEFAULTS, | 411 | IWL_BF_CMD_CONFIG_DEFAULTS, |
351 | .bf_enable_beacon_filter = 1, | 412 | .bf_enable_beacon_filter = cpu_to_le32(1), |
352 | }; | 413 | }; |
353 | int ret; | 414 | int ret; |
354 | 415 | ||
@@ -372,7 +433,8 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, | |||
372 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 433 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
373 | int ret; | 434 | int ret; |
374 | 435 | ||
375 | if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) | 436 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BF_UPDATED) || |
437 | vif->type != NL80211_IFTYPE_STATION || vif->p2p) | ||
376 | return 0; | 438 | return 0; |
377 | 439 | ||
378 | ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); | 440 | ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); |
@@ -382,3 +444,11 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, | |||
382 | 444 | ||
383 | return ret; | 445 | return ret; |
384 | } | 446 | } |
447 | |||
448 | const struct iwl_mvm_power_ops pm_mac_ops = { | ||
449 | .power_update_mode = iwl_mvm_power_mac_update_mode, | ||
450 | .power_disable = iwl_mvm_power_mac_disable, | ||
451 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
452 | .power_dbgfs_read = iwl_mvm_power_mac_dbgfs_read, | ||
453 | #endif | ||
454 | }; | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/power_legacy.c b/drivers/net/wireless/iwlwifi/mvm/power_legacy.c new file mode 100644 index 000000000000..2ce79bad5845 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/mvm/power_legacy.c | |||
@@ -0,0 +1,319 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * 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 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called COPYING. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | |||
64 | #include <linux/kernel.h> | ||
65 | #include <linux/module.h> | ||
66 | #include <linux/slab.h> | ||
67 | #include <linux/init.h> | ||
68 | |||
69 | #include <net/mac80211.h> | ||
70 | |||
71 | #include "iwl-debug.h" | ||
72 | #include "mvm.h" | ||
73 | #include "iwl-modparams.h" | ||
74 | #include "fw-api-power.h" | ||
75 | |||
76 | #define POWER_KEEP_ALIVE_PERIOD_SEC 25 | ||
77 | |||
78 | static void iwl_mvm_power_log(struct iwl_mvm *mvm, | ||
79 | struct iwl_powertable_cmd *cmd) | ||
80 | { | ||
81 | IWL_DEBUG_POWER(mvm, | ||
82 | "Sending power table command for power level %d, flags = 0x%X\n", | ||
83 | iwlmvm_mod_params.power_scheme, | ||
84 | le16_to_cpu(cmd->flags)); | ||
85 | IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n", cmd->keep_alive_seconds); | ||
86 | |||
87 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) { | ||
88 | IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n", | ||
89 | le32_to_cpu(cmd->rx_data_timeout)); | ||
90 | IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n", | ||
91 | le32_to_cpu(cmd->tx_data_timeout)); | ||
92 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) | ||
93 | IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n", | ||
94 | le32_to_cpu(cmd->skip_dtim_periods)); | ||
95 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK)) | ||
96 | IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n", | ||
97 | le32_to_cpu(cmd->lprx_rssi_threshold)); | ||
98 | } | ||
99 | } | ||
100 | |||
101 | static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | ||
102 | struct ieee80211_vif *vif, | ||
103 | struct iwl_powertable_cmd *cmd) | ||
104 | { | ||
105 | struct ieee80211_hw *hw = mvm->hw; | ||
106 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
107 | struct ieee80211_channel *chan; | ||
108 | int dtimper, dtimper_msec; | ||
109 | int keep_alive; | ||
110 | bool radar_detect = false; | ||
111 | struct iwl_mvm_vif *mvmvif __maybe_unused = | ||
112 | iwl_mvm_vif_from_mac80211(vif); | ||
113 | |||
114 | /* | ||
115 | * Regardless of power management state the driver must set | ||
116 | * keep alive period. FW will use it for sending keep alive NDPs | ||
117 | * immediately after association. | ||
118 | */ | ||
119 | cmd->keep_alive_seconds = POWER_KEEP_ALIVE_PERIOD_SEC; | ||
120 | |||
121 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) | ||
122 | return; | ||
123 | |||
124 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); | ||
125 | if (!vif->bss_conf.assoc) | ||
126 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); | ||
127 | |||
128 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
129 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF && | ||
130 | mvmvif->dbgfs_pm.disable_power_off) | ||
131 | cmd->flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK); | ||
132 | #endif | ||
133 | if (!vif->bss_conf.ps) | ||
134 | return; | ||
135 | |||
136 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); | ||
137 | |||
138 | if (vif->bss_conf.beacon_rate && | ||
139 | (vif->bss_conf.beacon_rate->bitrate == 10 || | ||
140 | vif->bss_conf.beacon_rate->bitrate == 60)) { | ||
141 | cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK); | ||
142 | cmd->lprx_rssi_threshold = | ||
143 | cpu_to_le32(POWER_LPRX_RSSI_THRESHOLD); | ||
144 | } | ||
145 | |||
146 | dtimper = hw->conf.ps_dtim_period ?: 1; | ||
147 | |||
148 | /* Check if radar detection is required on current channel */ | ||
149 | rcu_read_lock(); | ||
150 | chanctx_conf = rcu_dereference(vif->chanctx_conf); | ||
151 | WARN_ON(!chanctx_conf); | ||
152 | if (chanctx_conf) { | ||
153 | chan = chanctx_conf->def.chan; | ||
154 | radar_detect = chan->flags & IEEE80211_CHAN_RADAR; | ||
155 | } | ||
156 | rcu_read_unlock(); | ||
157 | |||
158 | /* Check skip over DTIM conditions */ | ||
159 | if (!radar_detect && (dtimper <= 10) && | ||
160 | (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP || | ||
161 | mvm->cur_ucode == IWL_UCODE_WOWLAN)) { | ||
162 | cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); | ||
163 | cmd->skip_dtim_periods = cpu_to_le32(3); | ||
164 | } | ||
165 | |||
166 | /* Check that keep alive period is at least 3 * DTIM */ | ||
167 | dtimper_msec = dtimper * vif->bss_conf.beacon_int; | ||
168 | keep_alive = max_t(int, 3 * dtimper_msec, | ||
169 | MSEC_PER_SEC * cmd->keep_alive_seconds); | ||
170 | keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC); | ||
171 | cmd->keep_alive_seconds = keep_alive; | ||
172 | |||
173 | if (mvm->cur_ucode != IWL_UCODE_WOWLAN) { | ||
174 | cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC); | ||
175 | cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC); | ||
176 | } else { | ||
177 | cmd->rx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC); | ||
178 | cmd->tx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC); | ||
179 | } | ||
180 | |||
181 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
182 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE) | ||
183 | cmd->keep_alive_seconds = mvmvif->dbgfs_pm.keep_alive_seconds; | ||
184 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) { | ||
185 | if (mvmvif->dbgfs_pm.skip_over_dtim) | ||
186 | cmd->flags |= | ||
187 | cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); | ||
188 | else | ||
189 | cmd->flags &= | ||
190 | cpu_to_le16(~POWER_FLAGS_SKIP_OVER_DTIM_MSK); | ||
191 | } | ||
192 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_RX_DATA_TIMEOUT) | ||
193 | cmd->rx_data_timeout = | ||
194 | cpu_to_le32(mvmvif->dbgfs_pm.rx_data_timeout); | ||
195 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_TX_DATA_TIMEOUT) | ||
196 | cmd->tx_data_timeout = | ||
197 | cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout); | ||
198 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS) | ||
199 | cmd->skip_dtim_periods = | ||
200 | cpu_to_le32(mvmvif->dbgfs_pm.skip_dtim_periods); | ||
201 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) { | ||
202 | if (mvmvif->dbgfs_pm.lprx_ena) | ||
203 | cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK); | ||
204 | else | ||
205 | cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK); | ||
206 | } | ||
207 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD) | ||
208 | cmd->lprx_rssi_threshold = | ||
209 | cpu_to_le32(mvmvif->dbgfs_pm.lprx_rssi_threshold); | ||
210 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | ||
211 | } | ||
212 | |||
213 | static int iwl_mvm_power_legacy_update_mode(struct iwl_mvm *mvm, | ||
214 | struct ieee80211_vif *vif) | ||
215 | { | ||
216 | int ret; | ||
217 | bool ba_enable; | ||
218 | struct iwl_powertable_cmd cmd = {}; | ||
219 | |||
220 | if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) | ||
221 | return 0; | ||
222 | |||
223 | /* | ||
224 | * TODO: The following vif_count verification is temporary condition. | ||
225 | * Avoid power mode update if more than one interface is currently | ||
226 | * active. Remove this condition when FW will support power management | ||
227 | * on multiple MACs. | ||
228 | */ | ||
229 | IWL_DEBUG_POWER(mvm, "Currently %d interfaces active\n", | ||
230 | mvm->vif_count); | ||
231 | if (mvm->vif_count > 1) | ||
232 | return 0; | ||
233 | |||
234 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); | ||
235 | iwl_mvm_power_log(mvm, &cmd); | ||
236 | |||
237 | ret = iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC, | ||
238 | sizeof(cmd), &cmd); | ||
239 | if (ret) | ||
240 | return ret; | ||
241 | |||
242 | ba_enable = !!(cmd.flags & | ||
243 | cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)); | ||
244 | |||
245 | return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable); | ||
246 | } | ||
247 | |||
248 | static int iwl_mvm_power_legacy_disable(struct iwl_mvm *mvm, | ||
249 | struct ieee80211_vif *vif) | ||
250 | { | ||
251 | struct iwl_powertable_cmd cmd = {}; | ||
252 | struct iwl_mvm_vif *mvmvif __maybe_unused = | ||
253 | iwl_mvm_vif_from_mac80211(vif); | ||
254 | |||
255 | if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) | ||
256 | return 0; | ||
257 | |||
258 | if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM) | ||
259 | cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); | ||
260 | |||
261 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
262 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF && | ||
263 | mvmvif->dbgfs_pm.disable_power_off) | ||
264 | cmd.flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK); | ||
265 | #endif | ||
266 | iwl_mvm_power_log(mvm, &cmd); | ||
267 | |||
268 | return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC, | ||
269 | sizeof(cmd), &cmd); | ||
270 | } | ||
271 | |||
272 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
273 | static int iwl_mvm_power_legacy_dbgfs_read(struct iwl_mvm *mvm, | ||
274 | struct ieee80211_vif *vif, char *buf, | ||
275 | int bufsz) | ||
276 | { | ||
277 | struct iwl_powertable_cmd cmd = {}; | ||
278 | int pos = 0; | ||
279 | |||
280 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); | ||
281 | |||
282 | pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n", | ||
283 | (cmd.flags & | ||
284 | cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ? | ||
285 | 0 : 1); | ||
286 | pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n", | ||
287 | le32_to_cpu(cmd.skip_dtim_periods)); | ||
288 | pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n", | ||
289 | iwlmvm_mod_params.power_scheme); | ||
290 | pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n", | ||
291 | le16_to_cpu(cmd.flags)); | ||
292 | pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n", | ||
293 | cmd.keep_alive_seconds); | ||
294 | |||
295 | if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) { | ||
296 | pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n", | ||
297 | (cmd.flags & | ||
298 | cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ? | ||
299 | 1 : 0); | ||
300 | pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n", | ||
301 | le32_to_cpu(cmd.rx_data_timeout)); | ||
302 | pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n", | ||
303 | le32_to_cpu(cmd.tx_data_timeout)); | ||
304 | if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK)) | ||
305 | pos += scnprintf(buf+pos, bufsz-pos, | ||
306 | "lprx_rssi_threshold = %d\n", | ||
307 | le32_to_cpu(cmd.lprx_rssi_threshold)); | ||
308 | } | ||
309 | return pos; | ||
310 | } | ||
311 | #endif | ||
312 | |||
313 | const struct iwl_mvm_power_ops pm_legacy_ops = { | ||
314 | .power_update_mode = iwl_mvm_power_legacy_update_mode, | ||
315 | .power_disable = iwl_mvm_power_legacy_disable, | ||
316 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
317 | .power_dbgfs_read = iwl_mvm_power_legacy_dbgfs_read, | ||
318 | #endif | ||
319 | }; | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c index 29d49cf0fdb2..18973874b77a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/quota.c +++ b/drivers/net/wireless/iwlwifi/mvm/quota.c | |||
@@ -132,7 +132,7 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac, | |||
132 | int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) | 132 | int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) |
133 | { | 133 | { |
134 | struct iwl_time_quota_cmd cmd; | 134 | struct iwl_time_quota_cmd cmd; |
135 | int i, idx, ret, num_active_bindings, quota, quota_rem; | 135 | int i, idx, ret, num_active_macs, quota, quota_rem; |
136 | struct iwl_mvm_quota_iterator_data data = { | 136 | struct iwl_mvm_quota_iterator_data data = { |
137 | .n_interfaces = {}, | 137 | .n_interfaces = {}, |
138 | .colors = { -1, -1, -1, -1 }, | 138 | .colors = { -1, -1, -1, -1 }, |
@@ -162,18 +162,17 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) | |||
162 | * IWL_MVM_MAX_QUOTA fragments. Divide these fragments | 162 | * IWL_MVM_MAX_QUOTA fragments. Divide these fragments |
163 | * equally between all the bindings that require quota | 163 | * equally between all the bindings that require quota |
164 | */ | 164 | */ |
165 | num_active_bindings = 0; | 165 | num_active_macs = 0; |
166 | for (i = 0; i < MAX_BINDINGS; i++) { | 166 | for (i = 0; i < MAX_BINDINGS; i++) { |
167 | cmd.quotas[i].id_and_color = cpu_to_le32(FW_CTXT_INVALID); | 167 | cmd.quotas[i].id_and_color = cpu_to_le32(FW_CTXT_INVALID); |
168 | if (data.n_interfaces[i] > 0) | 168 | num_active_macs += data.n_interfaces[i]; |
169 | num_active_bindings++; | ||
170 | } | 169 | } |
171 | 170 | ||
172 | quota = 0; | 171 | quota = 0; |
173 | quota_rem = 0; | 172 | quota_rem = 0; |
174 | if (num_active_bindings) { | 173 | if (num_active_macs) { |
175 | quota = IWL_MVM_MAX_QUOTA / num_active_bindings; | 174 | quota = IWL_MVM_MAX_QUOTA / num_active_macs; |
176 | quota_rem = IWL_MVM_MAX_QUOTA % num_active_bindings; | 175 | quota_rem = IWL_MVM_MAX_QUOTA % num_active_macs; |
177 | } | 176 | } |
178 | 177 | ||
179 | for (idx = 0, i = 0; i < MAX_BINDINGS; i++) { | 178 | for (idx = 0, i = 0; i < MAX_BINDINGS; i++) { |
@@ -187,7 +186,8 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) | |||
187 | cmd.quotas[idx].quota = cpu_to_le32(0); | 186 | cmd.quotas[idx].quota = cpu_to_le32(0); |
188 | cmd.quotas[idx].max_duration = cpu_to_le32(0); | 187 | cmd.quotas[idx].max_duration = cpu_to_le32(0); |
189 | } else { | 188 | } else { |
190 | cmd.quotas[idx].quota = cpu_to_le32(quota); | 189 | cmd.quotas[idx].quota = |
190 | cpu_to_le32(quota * data.n_interfaces[i]); | ||
191 | cmd.quotas[idx].max_duration = | 191 | cmd.quotas[idx].max_duration = |
192 | cpu_to_le32(IWL_MVM_MAX_QUOTA); | 192 | cpu_to_le32(IWL_MVM_MAX_QUOTA); |
193 | } | 193 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 376ea2112de2..9eeb21f62ef7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
@@ -2688,9 +2688,6 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
2688 | 2688 | ||
2689 | lq_sta->flush_timer = 0; | 2689 | lq_sta->flush_timer = 0; |
2690 | lq_sta->supp_rates = sta->supp_rates[sband->band]; | 2690 | lq_sta->supp_rates = sta->supp_rates[sband->band]; |
2691 | for (j = 0; j < LQ_SIZE; j++) | ||
2692 | for (i = 0; i < IWL_RATE_COUNT; i++) | ||
2693 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); | ||
2694 | 2691 | ||
2695 | IWL_DEBUG_RATE(mvm, | 2692 | IWL_DEBUG_RATE(mvm, |
2696 | "LQ: *** rate scale station global init for station %d ***\n", | 2693 | "LQ: *** rate scale station global init for station %d ***\n", |
@@ -3194,13 +3191,14 @@ void iwl_mvm_rate_control_unregister(void) | |||
3194 | * iwl_mvm_tx_protection - Gets LQ command, change it to enable/disable | 3191 | * iwl_mvm_tx_protection - Gets LQ command, change it to enable/disable |
3195 | * Tx protection, according to this rquest and previous requests, | 3192 | * Tx protection, according to this rquest and previous requests, |
3196 | * and send the LQ command. | 3193 | * and send the LQ command. |
3197 | * @lq: The LQ command | ||
3198 | * @mvmsta: The station | 3194 | * @mvmsta: The station |
3199 | * @enable: Enable Tx protection? | 3195 | * @enable: Enable Tx protection? |
3200 | */ | 3196 | */ |
3201 | int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, | 3197 | int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, |
3202 | struct iwl_mvm_sta *mvmsta, bool enable) | 3198 | bool enable) |
3203 | { | 3199 | { |
3200 | struct iwl_lq_cmd *lq = &mvmsta->lq_sta.lq; | ||
3201 | |||
3204 | lockdep_assert_held(&mvm->mutex); | 3202 | lockdep_assert_held(&mvm->mutex); |
3205 | 3203 | ||
3206 | if (enable) { | 3204 | if (enable) { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index cff4f6da7733..29d699ac07c9 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h | |||
@@ -404,7 +404,7 @@ extern void iwl_mvm_rate_control_unregister(void); | |||
404 | 404 | ||
405 | struct iwl_mvm_sta; | 405 | struct iwl_mvm_sta; |
406 | 406 | ||
407 | int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, | 407 | int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, |
408 | struct iwl_mvm_sta *mvmsta, bool enable); | 408 | bool enable); |
409 | 409 | ||
410 | #endif /* __rs__ */ | 410 | #endif /* __rs__ */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index e4930d5027d2..6fd7fae30c0a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c | |||
@@ -124,24 +124,15 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm, | |||
124 | ieee80211_rx_ni(mvm->hw, skb); | 124 | ieee80211_rx_ni(mvm->hw, skb); |
125 | } | 125 | } |
126 | 126 | ||
127 | /* | 127 | static void iwl_mvm_calc_rssi(struct iwl_mvm *mvm, |
128 | * iwl_mvm_calc_rssi - calculate the rssi in dBm | 128 | struct iwl_rx_phy_info *phy_info, |
129 | * @phy_info: the phy information for the coming packet | 129 | struct ieee80211_rx_status *rx_status) |
130 | */ | ||
131 | static int iwl_mvm_calc_rssi(struct iwl_mvm *mvm, | ||
132 | struct iwl_rx_phy_info *phy_info) | ||
133 | { | 130 | { |
134 | int rssi_a, rssi_b, rssi_a_dbm, rssi_b_dbm, max_rssi_dbm; | 131 | int rssi_a, rssi_b, rssi_a_dbm, rssi_b_dbm, max_rssi_dbm; |
135 | int rssi_all_band_a, rssi_all_band_b; | 132 | int rssi_all_band_a, rssi_all_band_b; |
136 | u32 agc_a, agc_b, max_agc; | 133 | u32 agc_a, agc_b, max_agc; |
137 | u32 val; | 134 | u32 val; |
138 | 135 | ||
139 | /* Find max rssi among 2 possible receivers. | ||
140 | * These values are measured by the Digital Signal Processor (DSP). | ||
141 | * They should stay fairly constant even as the signal strength varies, | ||
142 | * if the radio's Automatic Gain Control (AGC) is working right. | ||
143 | * AGC value (see below) will provide the "interesting" info. | ||
144 | */ | ||
145 | val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]); | 136 | val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]); |
146 | agc_a = (val & IWL_OFDM_AGC_A_MSK) >> IWL_OFDM_AGC_A_POS; | 137 | agc_a = (val & IWL_OFDM_AGC_A_MSK) >> IWL_OFDM_AGC_A_POS; |
147 | agc_b = (val & IWL_OFDM_AGC_B_MSK) >> IWL_OFDM_AGC_B_POS; | 138 | agc_b = (val & IWL_OFDM_AGC_B_MSK) >> IWL_OFDM_AGC_B_POS; |
@@ -166,7 +157,45 @@ static int iwl_mvm_calc_rssi(struct iwl_mvm *mvm, | |||
166 | IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d Max %d AGCA %d AGCB %d\n", | 157 | IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d Max %d AGCA %d AGCB %d\n", |
167 | rssi_a_dbm, rssi_b_dbm, max_rssi_dbm, agc_a, agc_b); | 158 | rssi_a_dbm, rssi_b_dbm, max_rssi_dbm, agc_a, agc_b); |
168 | 159 | ||
169 | return max_rssi_dbm; | 160 | rx_status->signal = max_rssi_dbm; |
161 | rx_status->chains = (le16_to_cpu(phy_info->phy_flags) & | ||
162 | RX_RES_PHY_FLAGS_ANTENNA) | ||
163 | >> RX_RES_PHY_FLAGS_ANTENNA_POS; | ||
164 | rx_status->chain_signal[0] = rssi_a_dbm; | ||
165 | rx_status->chain_signal[1] = rssi_b_dbm; | ||
166 | } | ||
167 | |||
168 | /* | ||
169 | * iwl_mvm_get_signal_strength - use new rx PHY INFO API | ||
170 | */ | ||
171 | static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm, | ||
172 | struct iwl_rx_phy_info *phy_info, | ||
173 | struct ieee80211_rx_status *rx_status) | ||
174 | { | ||
175 | int energy_a, energy_b, energy_c, max_energy; | ||
176 | u32 val; | ||
177 | |||
178 | val = | ||
179 | le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_ENERGY_ANT_ABC_IDX]); | ||
180 | energy_a = -((val & IWL_RX_INFO_ENERGY_ANT_A_MSK) >> | ||
181 | IWL_RX_INFO_ENERGY_ANT_A_POS); | ||
182 | energy_b = -((val & IWL_RX_INFO_ENERGY_ANT_B_MSK) >> | ||
183 | IWL_RX_INFO_ENERGY_ANT_B_POS); | ||
184 | energy_c = -((val & IWL_RX_INFO_ENERGY_ANT_C_MSK) >> | ||
185 | IWL_RX_INFO_ENERGY_ANT_C_POS); | ||
186 | max_energy = max(energy_a, energy_b); | ||
187 | max_energy = max(max_energy, energy_c); | ||
188 | |||
189 | IWL_DEBUG_STATS(mvm, "energy In A %d B %d C %d , and max %d\n", | ||
190 | energy_a, energy_b, energy_c, max_energy); | ||
191 | |||
192 | rx_status->signal = max_energy; | ||
193 | rx_status->chains = (le16_to_cpu(phy_info->phy_flags) & | ||
194 | RX_RES_PHY_FLAGS_ANTENNA) | ||
195 | >> RX_RES_PHY_FLAGS_ANTENNA_POS; | ||
196 | rx_status->chain_signal[0] = energy_a; | ||
197 | rx_status->chain_signal[1] = energy_b; | ||
198 | rx_status->chain_signal[2] = energy_c; | ||
170 | } | 199 | } |
171 | 200 | ||
172 | /* | 201 | /* |
@@ -289,29 +318,14 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
289 | */ | 318 | */ |
290 | /*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/ | 319 | /*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/ |
291 | 320 | ||
292 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ | 321 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_RX_ENERGY_API) |
293 | rx_status.signal = iwl_mvm_calc_rssi(mvm, phy_info); | 322 | iwl_mvm_get_signal_strength(mvm, phy_info, &rx_status); |
323 | else | ||
324 | iwl_mvm_calc_rssi(mvm, phy_info, &rx_status); | ||
294 | 325 | ||
295 | IWL_DEBUG_STATS_LIMIT(mvm, "Rssi %d, TSF %llu\n", rx_status.signal, | 326 | IWL_DEBUG_STATS_LIMIT(mvm, "Rssi %d, TSF %llu\n", rx_status.signal, |
296 | (unsigned long long)rx_status.mactime); | 327 | (unsigned long long)rx_status.mactime); |
297 | 328 | ||
298 | /* | ||
299 | * "antenna number" | ||
300 | * | ||
301 | * It seems that the antenna field in the phy flags value | ||
302 | * is actually a bit field. This is undefined by radiotap, | ||
303 | * it wants an actual antenna number but I always get "7" | ||
304 | * for most legacy frames I receive indicating that the | ||
305 | * same frame was received on all three RX chains. | ||
306 | * | ||
307 | * I think this field should be removed in favor of a | ||
308 | * new 802.11n radiotap field "RX chains" that is defined | ||
309 | * as a bitmask. | ||
310 | */ | ||
311 | rx_status.antenna = (le16_to_cpu(phy_info->phy_flags) & | ||
312 | RX_RES_PHY_FLAGS_ANTENNA) | ||
313 | >> RX_RES_PHY_FLAGS_ANTENNA_POS; | ||
314 | |||
315 | /* set the preamble flag if appropriate */ | 329 | /* set the preamble flag if appropriate */ |
316 | if (phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_SHORT_PREAMBLE)) | 330 | if (phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_SHORT_PREAMBLE)) |
317 | rx_status.flag |= RX_FLAG_SHORTPRE; | 331 | rx_status.flag |= RX_FLAG_SHORTPRE; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 268f027b45b0..14c1b457ca50 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
@@ -308,10 +308,12 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, | |||
308 | */ | 308 | */ |
309 | if (req->n_ssids > 0) { | 309 | if (req->n_ssids > 0) { |
310 | cmd->passive2active = cpu_to_le16(1); | 310 | cmd->passive2active = cpu_to_le16(1); |
311 | cmd->scan_flags |= SCAN_FLAGS_PASSIVE2ACTIVE; | ||
311 | ssid = req->ssids[0].ssid; | 312 | ssid = req->ssids[0].ssid; |
312 | ssid_len = req->ssids[0].ssid_len; | 313 | ssid_len = req->ssids[0].ssid_len; |
313 | } else { | 314 | } else { |
314 | cmd->passive2active = 0; | 315 | cmd->passive2active = 0; |
316 | cmd->scan_flags &= ~SCAN_FLAGS_PASSIVE2ACTIVE; | ||
315 | } | 317 | } |
316 | 318 | ||
317 | iwl_mvm_scan_fill_ssids(cmd, req); | 319 | iwl_mvm_scan_fill_ssids(cmd, req); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 85d4bbe52157..8b302774b70c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
@@ -826,8 +826,7 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
826 | * method for HT traffic | 826 | * method for HT traffic |
827 | * this function also sends the LQ command | 827 | * this function also sends the LQ command |
828 | */ | 828 | */ |
829 | return iwl_mvm_tx_protection(mvm, &mvmsta->lq_sta.lq, | 829 | return iwl_mvm_tx_protection(mvm, mvmsta, true); |
830 | mvmsta, true); | ||
831 | /* | 830 | /* |
832 | * TODO: remove the TLC_RTS flag when we tear down the last | 831 | * TODO: remove the TLC_RTS flag when we tear down the last |
833 | * AGG session (agg_tids_count in DVM) | 832 | * AGG session (agg_tids_count in DVM) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c index d6ae7f16ac11..1f3282dff513 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/iwlwifi/mvm/tt.c | |||
@@ -391,8 +391,7 @@ static void iwl_mvm_tt_tx_protection(struct iwl_mvm *mvm, bool enable) | |||
391 | mvmsta = (void *)sta->drv_priv; | 391 | mvmsta = (void *)sta->drv_priv; |
392 | if (enable == mvmsta->tt_tx_protection) | 392 | if (enable == mvmsta->tt_tx_protection) |
393 | continue; | 393 | continue; |
394 | err = iwl_mvm_tx_protection(mvm, &mvmsta->lq_sta.lq, | 394 | err = iwl_mvm_tx_protection(mvm, mvmsta, enable); |
395 | mvmsta, enable); | ||
396 | if (err) { | 395 | if (err) { |
397 | IWL_ERR(mvm, "Failed to %s Tx protection\n", | 396 | IWL_ERR(mvm, "Failed to %s Tx protection\n", |
398 | enable ? "enable" : "disable"); | 397 | enable ? "enable" : "disable"); |
@@ -513,12 +512,39 @@ static const struct iwl_tt_params iwl7000_tt_params = { | |||
513 | .support_tx_backoff = true, | 512 | .support_tx_backoff = true, |
514 | }; | 513 | }; |
515 | 514 | ||
515 | static const struct iwl_tt_params iwl7000_high_temp_tt_params = { | ||
516 | .ct_kill_entry = 118, | ||
517 | .ct_kill_exit = 96, | ||
518 | .ct_kill_duration = 5, | ||
519 | .dynamic_smps_entry = 114, | ||
520 | .dynamic_smps_exit = 110, | ||
521 | .tx_protection_entry = 114, | ||
522 | .tx_protection_exit = 108, | ||
523 | .tx_backoff = { | ||
524 | {.temperature = 112, .backoff = 300}, | ||
525 | {.temperature = 113, .backoff = 800}, | ||
526 | {.temperature = 114, .backoff = 1500}, | ||
527 | {.temperature = 115, .backoff = 3000}, | ||
528 | {.temperature = 116, .backoff = 5000}, | ||
529 | {.temperature = 117, .backoff = 10000}, | ||
530 | }, | ||
531 | .support_ct_kill = true, | ||
532 | .support_dynamic_smps = true, | ||
533 | .support_tx_protection = true, | ||
534 | .support_tx_backoff = true, | ||
535 | }; | ||
536 | |||
516 | void iwl_mvm_tt_initialize(struct iwl_mvm *mvm) | 537 | void iwl_mvm_tt_initialize(struct iwl_mvm *mvm) |
517 | { | 538 | { |
518 | struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle; | 539 | struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle; |
519 | 540 | ||
520 | IWL_DEBUG_TEMP(mvm, "Initialize Thermal Throttling\n"); | 541 | IWL_DEBUG_TEMP(mvm, "Initialize Thermal Throttling\n"); |
521 | tt->params = &iwl7000_tt_params; | 542 | |
543 | if (mvm->cfg->high_temp) | ||
544 | tt->params = &iwl7000_high_temp_tt_params; | ||
545 | else | ||
546 | tt->params = &iwl7000_tt_params; | ||
547 | |||
522 | tt->throttle = false; | 548 | tt->throttle = false; |
523 | INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill); | 549 | INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill); |
524 | } | 550 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index f0e96a927407..7694b8fa4c37 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
@@ -123,6 +123,8 @@ static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
123 | * it | 123 | * it |
124 | */ | 124 | */ |
125 | WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU); | 125 | WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU); |
126 | } else if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { | ||
127 | tx_cmd->pm_frame_timeout = cpu_to_le16(2); | ||
126 | } else { | 128 | } else { |
127 | tx_cmd->pm_frame_timeout = 0; | 129 | tx_cmd->pm_frame_timeout = 0; |
128 | } | 130 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index 1e1332839e4a..a9c357491434 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c | |||
@@ -453,6 +453,29 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) | |||
453 | IWL_ERR(mvm, "0x%08X | flow_handler\n", table.flow_handler); | 453 | IWL_ERR(mvm, "0x%08X | flow_handler\n", table.flow_handler); |
454 | } | 454 | } |
455 | 455 | ||
456 | void iwl_mvm_dump_sram(struct iwl_mvm *mvm) | ||
457 | { | ||
458 | const struct fw_img *img; | ||
459 | int ofs, len = 0; | ||
460 | u8 *buf; | ||
461 | |||
462 | if (!mvm->ucode_loaded) | ||
463 | return; | ||
464 | |||
465 | img = &mvm->fw->img[mvm->cur_ucode]; | ||
466 | ofs = img->sec[IWL_UCODE_SECTION_DATA].offset; | ||
467 | len = img->sec[IWL_UCODE_SECTION_DATA].len; | ||
468 | |||
469 | buf = kzalloc(len, GFP_KERNEL); | ||
470 | if (!buf) | ||
471 | return; | ||
472 | |||
473 | iwl_trans_read_mem_bytes(mvm->trans, ofs, buf, len); | ||
474 | iwl_print_hex_error(mvm->trans, buf, len); | ||
475 | |||
476 | kfree(buf); | ||
477 | } | ||
478 | |||
456 | /** | 479 | /** |
457 | * iwl_mvm_send_lq_cmd() - Send link quality command | 480 | * iwl_mvm_send_lq_cmd() - Send link quality command |
458 | * @init: This command is sent as part of station initialization right | 481 | * @init: This command is sent as part of station initialization right |
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 81f3ea5b09a4..db6be2491d7c 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c | |||
@@ -272,9 +272,9 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | |||
272 | {IWL_PCI_DEVICE(0x08B1, 0x4462, iwl7260_n_cfg)}, | 272 | {IWL_PCI_DEVICE(0x08B1, 0x4462, iwl7260_n_cfg)}, |
273 | {IWL_PCI_DEVICE(0x08B1, 0x4870, iwl7260_2ac_cfg)}, | 273 | {IWL_PCI_DEVICE(0x08B1, 0x4870, iwl7260_2ac_cfg)}, |
274 | {IWL_PCI_DEVICE(0x08B1, 0x486E, iwl7260_2ac_cfg)}, | 274 | {IWL_PCI_DEVICE(0x08B1, 0x486E, iwl7260_2ac_cfg)}, |
275 | {IWL_PCI_DEVICE(0x08B1, 0x4A70, iwl7260_2ac_cfg)}, | 275 | {IWL_PCI_DEVICE(0x08B1, 0x4A70, iwl7260_2ac_cfg_high_temp)}, |
276 | {IWL_PCI_DEVICE(0x08B1, 0x4A6E, iwl7260_2ac_cfg)}, | 276 | {IWL_PCI_DEVICE(0x08B1, 0x4A6E, iwl7260_2ac_cfg_high_temp)}, |
277 | {IWL_PCI_DEVICE(0x08B1, 0x4A6C, iwl7260_2ac_cfg)}, | 277 | {IWL_PCI_DEVICE(0x08B1, 0x4A6C, iwl7260_2ac_cfg_high_temp)}, |
278 | {IWL_PCI_DEVICE(0x08B1, 0x4020, iwl7260_2n_cfg)}, | 278 | {IWL_PCI_DEVICE(0x08B1, 0x4020, iwl7260_2n_cfg)}, |
279 | {IWL_PCI_DEVICE(0x08B2, 0x4220, iwl7260_2n_cfg)}, | 279 | {IWL_PCI_DEVICE(0x08B2, 0x4220, iwl7260_2n_cfg)}, |
280 | {IWL_PCI_DEVICE(0x08B1, 0x4420, iwl7260_2n_cfg)}, | 280 | {IWL_PCI_DEVICE(0x08B1, 0x4420, iwl7260_2n_cfg)}, |
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index b654dcdd048a..fa22639b63c9 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
@@ -392,7 +392,6 @@ void iwl_trans_pcie_tx_reset(struct iwl_trans *trans); | |||
392 | /***************************************************** | 392 | /***************************************************** |
393 | * Error handling | 393 | * Error handling |
394 | ******************************************************/ | 394 | ******************************************************/ |
395 | int iwl_pcie_dump_fh(struct iwl_trans *trans, char **buf); | ||
396 | void iwl_pcie_dump_csr(struct iwl_trans *trans); | 395 | void iwl_pcie_dump_csr(struct iwl_trans *trans); |
397 | 396 | ||
398 | /***************************************************** | 397 | /***************************************************** |
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index fd848cd1583e..5fdb4eea146d 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c | |||
@@ -793,7 +793,7 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans) | |||
793 | } | 793 | } |
794 | 794 | ||
795 | iwl_pcie_dump_csr(trans); | 795 | iwl_pcie_dump_csr(trans); |
796 | iwl_pcie_dump_fh(trans, NULL); | 796 | iwl_dump_fh(trans, NULL); |
797 | 797 | ||
798 | set_bit(STATUS_FW_ERROR, &trans_pcie->status); | 798 | set_bit(STATUS_FW_ERROR, &trans_pcie->status); |
799 | clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); | 799 | clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 826c15602c46..cec0c8991285 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -1033,71 +1033,6 @@ static void iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans, u32 reg, | |||
1033 | spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); | 1033 | spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); |
1034 | } | 1034 | } |
1035 | 1035 | ||
1036 | static const char *get_fh_string(int cmd) | ||
1037 | { | ||
1038 | #define IWL_CMD(x) case x: return #x | ||
1039 | switch (cmd) { | ||
1040 | IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); | ||
1041 | IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG); | ||
1042 | IWL_CMD(FH_RSCSR_CHNL0_WPTR); | ||
1043 | IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG); | ||
1044 | IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG); | ||
1045 | IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG); | ||
1046 | IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV); | ||
1047 | IWL_CMD(FH_TSSR_TX_STATUS_REG); | ||
1048 | IWL_CMD(FH_TSSR_TX_ERROR_REG); | ||
1049 | default: | ||
1050 | return "UNKNOWN"; | ||
1051 | } | ||
1052 | #undef IWL_CMD | ||
1053 | } | ||
1054 | |||
1055 | int iwl_pcie_dump_fh(struct iwl_trans *trans, char **buf) | ||
1056 | { | ||
1057 | int i; | ||
1058 | static const u32 fh_tbl[] = { | ||
1059 | FH_RSCSR_CHNL0_STTS_WPTR_REG, | ||
1060 | FH_RSCSR_CHNL0_RBDCB_BASE_REG, | ||
1061 | FH_RSCSR_CHNL0_WPTR, | ||
1062 | FH_MEM_RCSR_CHNL0_CONFIG_REG, | ||
1063 | FH_MEM_RSSR_SHARED_CTRL_REG, | ||
1064 | FH_MEM_RSSR_RX_STATUS_REG, | ||
1065 | FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV, | ||
1066 | FH_TSSR_TX_STATUS_REG, | ||
1067 | FH_TSSR_TX_ERROR_REG | ||
1068 | }; | ||
1069 | |||
1070 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
1071 | if (buf) { | ||
1072 | int pos = 0; | ||
1073 | size_t bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; | ||
1074 | |||
1075 | *buf = kmalloc(bufsz, GFP_KERNEL); | ||
1076 | if (!*buf) | ||
1077 | return -ENOMEM; | ||
1078 | |||
1079 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
1080 | "FH register values:\n"); | ||
1081 | |||
1082 | for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) | ||
1083 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
1084 | " %34s: 0X%08x\n", | ||
1085 | get_fh_string(fh_tbl[i]), | ||
1086 | iwl_read_direct32(trans, fh_tbl[i])); | ||
1087 | |||
1088 | return pos; | ||
1089 | } | ||
1090 | #endif | ||
1091 | |||
1092 | IWL_ERR(trans, "FH register values:\n"); | ||
1093 | for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) | ||
1094 | IWL_ERR(trans, " %34s: 0X%08x\n", | ||
1095 | get_fh_string(fh_tbl[i]), | ||
1096 | iwl_read_direct32(trans, fh_tbl[i])); | ||
1097 | |||
1098 | return 0; | ||
1099 | } | ||
1100 | |||
1101 | static const char *get_csr_string(int cmd) | 1036 | static const char *get_csr_string(int cmd) |
1102 | { | 1037 | { |
1103 | #define IWL_CMD(x) case x: return #x | 1038 | #define IWL_CMD(x) case x: return #x |
@@ -1178,18 +1113,7 @@ void iwl_pcie_dump_csr(struct iwl_trans *trans) | |||
1178 | } while (0) | 1113 | } while (0) |
1179 | 1114 | ||
1180 | /* file operation */ | 1115 | /* file operation */ |
1181 | #define DEBUGFS_READ_FUNC(name) \ | ||
1182 | static ssize_t iwl_dbgfs_##name##_read(struct file *file, \ | ||
1183 | char __user *user_buf, \ | ||
1184 | size_t count, loff_t *ppos); | ||
1185 | |||
1186 | #define DEBUGFS_WRITE_FUNC(name) \ | ||
1187 | static ssize_t iwl_dbgfs_##name##_write(struct file *file, \ | ||
1188 | const char __user *user_buf, \ | ||
1189 | size_t count, loff_t *ppos); | ||
1190 | |||
1191 | #define DEBUGFS_READ_FILE_OPS(name) \ | 1116 | #define DEBUGFS_READ_FILE_OPS(name) \ |
1192 | DEBUGFS_READ_FUNC(name); \ | ||
1193 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ | 1117 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ |
1194 | .read = iwl_dbgfs_##name##_read, \ | 1118 | .read = iwl_dbgfs_##name##_read, \ |
1195 | .open = simple_open, \ | 1119 | .open = simple_open, \ |
@@ -1197,7 +1121,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ | |||
1197 | }; | 1121 | }; |
1198 | 1122 | ||
1199 | #define DEBUGFS_WRITE_FILE_OPS(name) \ | 1123 | #define DEBUGFS_WRITE_FILE_OPS(name) \ |
1200 | DEBUGFS_WRITE_FUNC(name); \ | ||
1201 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ | 1124 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ |
1202 | .write = iwl_dbgfs_##name##_write, \ | 1125 | .write = iwl_dbgfs_##name##_write, \ |
1203 | .open = simple_open, \ | 1126 | .open = simple_open, \ |
@@ -1205,8 +1128,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ | |||
1205 | }; | 1128 | }; |
1206 | 1129 | ||
1207 | #define DEBUGFS_READ_WRITE_FILE_OPS(name) \ | 1130 | #define DEBUGFS_READ_WRITE_FILE_OPS(name) \ |
1208 | DEBUGFS_READ_FUNC(name); \ | ||
1209 | DEBUGFS_WRITE_FUNC(name); \ | ||
1210 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ | 1131 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ |
1211 | .write = iwl_dbgfs_##name##_write, \ | 1132 | .write = iwl_dbgfs_##name##_write, \ |
1212 | .read = iwl_dbgfs_##name##_read, \ | 1133 | .read = iwl_dbgfs_##name##_read, \ |
@@ -1390,7 +1311,7 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, | |||
1390 | int pos = 0; | 1311 | int pos = 0; |
1391 | ssize_t ret = -EFAULT; | 1312 | ssize_t ret = -EFAULT; |
1392 | 1313 | ||
1393 | ret = pos = iwl_pcie_dump_fh(trans, &buf); | 1314 | ret = pos = iwl_dump_fh(trans, &buf); |
1394 | if (buf) { | 1315 | if (buf) { |
1395 | ret = simple_read_from_buffer(user_buf, | 1316 | ret = simple_read_from_buffer(user_buf, |
1396 | count, ppos, buf, pos); | 1317 | count, ppos, buf, pos); |
@@ -1497,10 +1418,16 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
1497 | spin_lock_init(&trans_pcie->reg_lock); | 1418 | spin_lock_init(&trans_pcie->reg_lock); |
1498 | init_waitqueue_head(&trans_pcie->ucode_write_waitq); | 1419 | init_waitqueue_head(&trans_pcie->ucode_write_waitq); |
1499 | 1420 | ||
1500 | /* W/A - seems to solve weird behavior. We need to remove this if we | 1421 | if (!cfg->base_params->pcie_l1_allowed) { |
1501 | * don't want to stay in L1 all the time. This wastes a lot of power */ | 1422 | /* |
1502 | pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | | 1423 | * W/A - seems to solve weird behavior. We need to remove this |
1503 | PCIE_LINK_STATE_CLKPM); | 1424 | * if we don't want to stay in L1 all the time. This wastes a |
1425 | * lot of power. | ||
1426 | */ | ||
1427 | pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | | ||
1428 | PCIE_LINK_STATE_L1 | | ||
1429 | PCIE_LINK_STATE_CLKPM); | ||
1430 | } | ||
1504 | 1431 | ||
1505 | if (pci_enable_device(pdev)) { | 1432 | if (pci_enable_device(pdev)) { |
1506 | err = -ENODEV; | 1433 | err = -ENODEV; |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index c47c92165aba..134f7a109f47 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -1619,10 +1619,9 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1619 | txq = &trans_pcie->txq[txq_id]; | 1619 | txq = &trans_pcie->txq[txq_id]; |
1620 | q = &txq->q; | 1620 | q = &txq->q; |
1621 | 1621 | ||
1622 | if (unlikely(!test_bit(txq_id, trans_pcie->queue_used))) { | 1622 | if (WARN_ONCE(!test_bit(txq_id, trans_pcie->queue_used), |
1623 | WARN_ON_ONCE(1); | 1623 | "TX on unused queue %d\n", txq_id)) |
1624 | return -EINVAL; | 1624 | return -EINVAL; |
1625 | } | ||
1626 | 1625 | ||
1627 | spin_lock(&txq->lock); | 1626 | spin_lock(&txq->lock); |
1628 | 1627 | ||