diff options
author | Kalle Valo <kvalo@codeaurora.org> | 2018-03-27 03:06:18 -0400 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2018-03-27 03:06:18 -0400 |
commit | abd5f00844ec7fa507064ee4a22b3605c64c7d31 (patch) | |
tree | bdfab7c73070807f2667cfd14d16e75ca988f83f | |
parent | 996bfed118748c128ad4b6c05c09fd2f5fdfa1b4 (diff) | |
parent | 6767b302e1c961f0775abaa068495aa137331191 (diff) |
Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for 4.17. Major changes:
wil6210
* support multiple virtual interfaces
43 files changed, 3446 insertions, 1015 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index f3ec13b80b20..830b7fe466f3 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2005-2011 Atheros Communications Inc. | 2 | * Copyright (c) 2005-2011 Atheros Communications Inc. |
3 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. | 3 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. |
4 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
4 | * | 5 | * |
5 | * Permission to use, copy, modify, and/or distribute this software for any | 6 | * Permission to use, copy, modify, and/or distribute this software for any |
6 | * purpose with or without fee is hereby granted, provided that the above | 7 | * purpose with or without fee is hereby granted, provided that the above |
@@ -2439,7 +2440,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar) | |||
2439 | 2440 | ||
2440 | ret = ath10k_hif_power_up(ar); | 2441 | ret = ath10k_hif_power_up(ar); |
2441 | if (ret) { | 2442 | if (ret) { |
2442 | ath10k_err(ar, "could not start pci hif (%d)\n", ret); | 2443 | ath10k_err(ar, "could not power on hif bus (%d)\n", ret); |
2443 | return ret; | 2444 | return ret; |
2444 | } | 2445 | } |
2445 | 2446 | ||
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index fe6b30356d3b..73712c830be7 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2005-2011 Atheros Communications Inc. | 2 | * Copyright (c) 2005-2011 Atheros Communications Inc. |
3 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. | 3 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. |
4 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
4 | * | 5 | * |
5 | * Permission to use, copy, modify, and/or distribute this software for any | 6 | * Permission to use, copy, modify, and/or distribute this software for any |
6 | * purpose with or without fee is hereby granted, provided that the above | 7 | * purpose with or without fee is hereby granted, provided that the above |
@@ -324,6 +325,27 @@ struct ath10k_tpc_stats { | |||
324 | struct ath10k_tpc_table tpc_table[WMI_TPC_FLAG]; | 325 | struct ath10k_tpc_table tpc_table[WMI_TPC_FLAG]; |
325 | }; | 326 | }; |
326 | 327 | ||
328 | struct ath10k_tpc_table_final { | ||
329 | u32 pream_idx[WMI_TPC_FINAL_RATE_MAX]; | ||
330 | u8 rate_code[WMI_TPC_FINAL_RATE_MAX]; | ||
331 | char tpc_value[WMI_TPC_FINAL_RATE_MAX][WMI_TPC_TX_N_CHAIN * WMI_TPC_BUF_SIZE]; | ||
332 | }; | ||
333 | |||
334 | struct ath10k_tpc_stats_final { | ||
335 | u32 reg_domain; | ||
336 | u32 chan_freq; | ||
337 | u32 phy_mode; | ||
338 | u32 twice_antenna_reduction; | ||
339 | u32 twice_max_rd_power; | ||
340 | s32 twice_antenna_gain; | ||
341 | u32 power_limit; | ||
342 | u32 num_tx_chain; | ||
343 | u32 ctl; | ||
344 | u32 rate_max; | ||
345 | u8 flag[WMI_TPC_FLAG]; | ||
346 | struct ath10k_tpc_table_final tpc_table_final[WMI_TPC_FLAG]; | ||
347 | }; | ||
348 | |||
327 | struct ath10k_dfs_stats { | 349 | struct ath10k_dfs_stats { |
328 | u32 phy_errors; | 350 | u32 phy_errors; |
329 | u32 pulses_total; | 351 | u32 pulses_total; |
@@ -354,6 +376,45 @@ struct ath10k_txq { | |||
354 | unsigned long num_push_allowed; | 376 | unsigned long num_push_allowed; |
355 | }; | 377 | }; |
356 | 378 | ||
379 | enum ath10k_pkt_rx_err { | ||
380 | ATH10K_PKT_RX_ERR_FCS, | ||
381 | ATH10K_PKT_RX_ERR_TKIP, | ||
382 | ATH10K_PKT_RX_ERR_CRYPT, | ||
383 | ATH10K_PKT_RX_ERR_PEER_IDX_INVAL, | ||
384 | ATH10K_PKT_RX_ERR_MAX, | ||
385 | }; | ||
386 | |||
387 | enum ath10k_ampdu_subfrm_num { | ||
388 | ATH10K_AMPDU_SUBFRM_NUM_10, | ||
389 | ATH10K_AMPDU_SUBFRM_NUM_20, | ||
390 | ATH10K_AMPDU_SUBFRM_NUM_30, | ||
391 | ATH10K_AMPDU_SUBFRM_NUM_40, | ||
392 | ATH10K_AMPDU_SUBFRM_NUM_50, | ||
393 | ATH10K_AMPDU_SUBFRM_NUM_60, | ||
394 | ATH10K_AMPDU_SUBFRM_NUM_MORE, | ||
395 | ATH10K_AMPDU_SUBFRM_NUM_MAX, | ||
396 | }; | ||
397 | |||
398 | enum ath10k_amsdu_subfrm_num { | ||
399 | ATH10K_AMSDU_SUBFRM_NUM_1, | ||
400 | ATH10K_AMSDU_SUBFRM_NUM_2, | ||
401 | ATH10K_AMSDU_SUBFRM_NUM_3, | ||
402 | ATH10K_AMSDU_SUBFRM_NUM_4, | ||
403 | ATH10K_AMSDU_SUBFRM_NUM_MORE, | ||
404 | ATH10K_AMSDU_SUBFRM_NUM_MAX, | ||
405 | }; | ||
406 | |||
407 | struct ath10k_sta_tid_stats { | ||
408 | unsigned long int rx_pkt_from_fw; | ||
409 | unsigned long int rx_pkt_unchained; | ||
410 | unsigned long int rx_pkt_drop_chained; | ||
411 | unsigned long int rx_pkt_drop_filter; | ||
412 | unsigned long int rx_pkt_err[ATH10K_PKT_RX_ERR_MAX]; | ||
413 | unsigned long int rx_pkt_queued_for_mac; | ||
414 | unsigned long int rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_MAX]; | ||
415 | unsigned long int rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_MAX]; | ||
416 | }; | ||
417 | |||
357 | struct ath10k_sta { | 418 | struct ath10k_sta { |
358 | struct ath10k_vif *arvif; | 419 | struct ath10k_vif *arvif; |
359 | 420 | ||
@@ -371,6 +432,9 @@ struct ath10k_sta { | |||
371 | #ifdef CONFIG_MAC80211_DEBUGFS | 432 | #ifdef CONFIG_MAC80211_DEBUGFS |
372 | /* protected by conf_mutex */ | 433 | /* protected by conf_mutex */ |
373 | bool aggr_mode; | 434 | bool aggr_mode; |
435 | |||
436 | /* Protected with ar->data_lock */ | ||
437 | struct ath10k_sta_tid_stats tid_stats[IEEE80211_NUM_TIDS + 1]; | ||
374 | #endif | 438 | #endif |
375 | }; | 439 | }; |
376 | 440 | ||
@@ -487,6 +551,7 @@ struct ath10k_debug { | |||
487 | 551 | ||
488 | /* used for tpc-dump storage, protected by data-lock */ | 552 | /* used for tpc-dump storage, protected by data-lock */ |
489 | struct ath10k_tpc_stats *tpc_stats; | 553 | struct ath10k_tpc_stats *tpc_stats; |
554 | struct ath10k_tpc_stats_final *tpc_stats_final; | ||
490 | 555 | ||
491 | struct completion tpc_complete; | 556 | struct completion tpc_complete; |
492 | 557 | ||
@@ -1019,6 +1084,8 @@ struct ath10k { | |||
1019 | 1084 | ||
1020 | void *ce_priv; | 1085 | void *ce_priv; |
1021 | 1086 | ||
1087 | u32 sta_tid_stats_mask; | ||
1088 | |||
1022 | /* must be last */ | 1089 | /* must be last */ |
1023 | u8 drv_priv[0] __aligned(sizeof(void *)); | 1090 | u8 drv_priv[0] __aligned(sizeof(void *)); |
1024 | }; | 1091 | }; |
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 554cd7856cb6..bac832ce1873 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c | |||
@@ -1480,6 +1480,19 @@ void ath10k_debug_tpc_stats_process(struct ath10k *ar, | |||
1480 | spin_unlock_bh(&ar->data_lock); | 1480 | spin_unlock_bh(&ar->data_lock); |
1481 | } | 1481 | } |
1482 | 1482 | ||
1483 | void | ||
1484 | ath10k_debug_tpc_stats_final_process(struct ath10k *ar, | ||
1485 | struct ath10k_tpc_stats_final *tpc_stats) | ||
1486 | { | ||
1487 | spin_lock_bh(&ar->data_lock); | ||
1488 | |||
1489 | kfree(ar->debug.tpc_stats_final); | ||
1490 | ar->debug.tpc_stats_final = tpc_stats; | ||
1491 | complete(&ar->debug.tpc_complete); | ||
1492 | |||
1493 | spin_unlock_bh(&ar->data_lock); | ||
1494 | } | ||
1495 | |||
1483 | static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats, | 1496 | static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats, |
1484 | unsigned int j, char *buf, size_t *len) | 1497 | unsigned int j, char *buf, size_t *len) |
1485 | { | 1498 | { |
@@ -2143,6 +2156,137 @@ static const struct file_operations fops_fw_checksums = { | |||
2143 | .llseek = default_llseek, | 2156 | .llseek = default_llseek, |
2144 | }; | 2157 | }; |
2145 | 2158 | ||
2159 | static ssize_t ath10k_sta_tid_stats_mask_read(struct file *file, | ||
2160 | char __user *user_buf, | ||
2161 | size_t count, loff_t *ppos) | ||
2162 | { | ||
2163 | struct ath10k *ar = file->private_data; | ||
2164 | char buf[32]; | ||
2165 | size_t len; | ||
2166 | |||
2167 | len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->sta_tid_stats_mask); | ||
2168 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
2169 | } | ||
2170 | |||
2171 | static ssize_t ath10k_sta_tid_stats_mask_write(struct file *file, | ||
2172 | const char __user *user_buf, | ||
2173 | size_t count, loff_t *ppos) | ||
2174 | { | ||
2175 | struct ath10k *ar = file->private_data; | ||
2176 | char buf[32]; | ||
2177 | ssize_t len; | ||
2178 | u32 mask; | ||
2179 | |||
2180 | len = min(count, sizeof(buf) - 1); | ||
2181 | if (copy_from_user(buf, user_buf, len)) | ||
2182 | return -EFAULT; | ||
2183 | |||
2184 | buf[len] = '\0'; | ||
2185 | if (kstrtoint(buf, 0, &mask)) | ||
2186 | return -EINVAL; | ||
2187 | |||
2188 | ar->sta_tid_stats_mask = mask; | ||
2189 | |||
2190 | return len; | ||
2191 | } | ||
2192 | |||
2193 | static const struct file_operations fops_sta_tid_stats_mask = { | ||
2194 | .read = ath10k_sta_tid_stats_mask_read, | ||
2195 | .write = ath10k_sta_tid_stats_mask_write, | ||
2196 | .open = simple_open, | ||
2197 | .owner = THIS_MODULE, | ||
2198 | .llseek = default_llseek, | ||
2199 | }; | ||
2200 | |||
2201 | static int ath10k_debug_tpc_stats_final_request(struct ath10k *ar) | ||
2202 | { | ||
2203 | int ret; | ||
2204 | unsigned long time_left; | ||
2205 | |||
2206 | lockdep_assert_held(&ar->conf_mutex); | ||
2207 | |||
2208 | reinit_completion(&ar->debug.tpc_complete); | ||
2209 | |||
2210 | ret = ath10k_wmi_pdev_get_tpc_table_cmdid(ar, WMI_TPC_CONFIG_PARAM); | ||
2211 | if (ret) { | ||
2212 | ath10k_warn(ar, "failed to request tpc table cmdid: %d\n", ret); | ||
2213 | return ret; | ||
2214 | } | ||
2215 | |||
2216 | time_left = wait_for_completion_timeout(&ar->debug.tpc_complete, | ||
2217 | 1 * HZ); | ||
2218 | if (time_left == 0) | ||
2219 | return -ETIMEDOUT; | ||
2220 | |||
2221 | return 0; | ||
2222 | } | ||
2223 | |||
2224 | static int ath10k_tpc_stats_final_open(struct inode *inode, struct file *file) | ||
2225 | { | ||
2226 | struct ath10k *ar = inode->i_private; | ||
2227 | void *buf; | ||
2228 | int ret; | ||
2229 | |||
2230 | mutex_lock(&ar->conf_mutex); | ||
2231 | |||
2232 | if (ar->state != ATH10K_STATE_ON) { | ||
2233 | ret = -ENETDOWN; | ||
2234 | goto err_unlock; | ||
2235 | } | ||
2236 | |||
2237 | buf = vmalloc(ATH10K_TPC_CONFIG_BUF_SIZE); | ||
2238 | if (!buf) { | ||
2239 | ret = -ENOMEM; | ||
2240 | goto err_unlock; | ||
2241 | } | ||
2242 | |||
2243 | ret = ath10k_debug_tpc_stats_final_request(ar); | ||
2244 | if (ret) { | ||
2245 | ath10k_warn(ar, "failed to request tpc stats final: %d\n", | ||
2246 | ret); | ||
2247 | goto err_free; | ||
2248 | } | ||
2249 | |||
2250 | ath10k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf); | ||
2251 | file->private_data = buf; | ||
2252 | |||
2253 | mutex_unlock(&ar->conf_mutex); | ||
2254 | return 0; | ||
2255 | |||
2256 | err_free: | ||
2257 | vfree(buf); | ||
2258 | |||
2259 | err_unlock: | ||
2260 | mutex_unlock(&ar->conf_mutex); | ||
2261 | return ret; | ||
2262 | } | ||
2263 | |||
2264 | static int ath10k_tpc_stats_final_release(struct inode *inode, | ||
2265 | struct file *file) | ||
2266 | { | ||
2267 | vfree(file->private_data); | ||
2268 | |||
2269 | return 0; | ||
2270 | } | ||
2271 | |||
2272 | static ssize_t ath10k_tpc_stats_final_read(struct file *file, | ||
2273 | char __user *user_buf, | ||
2274 | size_t count, loff_t *ppos) | ||
2275 | { | ||
2276 | const char *buf = file->private_data; | ||
2277 | unsigned int len = strlen(buf); | ||
2278 | |||
2279 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
2280 | } | ||
2281 | |||
2282 | static const struct file_operations fops_tpc_stats_final = { | ||
2283 | .open = ath10k_tpc_stats_final_open, | ||
2284 | .release = ath10k_tpc_stats_final_release, | ||
2285 | .read = ath10k_tpc_stats_final_read, | ||
2286 | .owner = THIS_MODULE, | ||
2287 | .llseek = default_llseek, | ||
2288 | }; | ||
2289 | |||
2146 | int ath10k_debug_create(struct ath10k *ar) | 2290 | int ath10k_debug_create(struct ath10k *ar) |
2147 | { | 2291 | { |
2148 | ar->debug.cal_data = vzalloc(ATH10K_DEBUG_CAL_DATA_LEN); | 2292 | ar->debug.cal_data = vzalloc(ATH10K_DEBUG_CAL_DATA_LEN); |
@@ -2258,6 +2402,16 @@ int ath10k_debug_register(struct ath10k *ar) | |||
2258 | debugfs_create_file("fw_checksums", 0400, ar->debug.debugfs_phy, ar, | 2402 | debugfs_create_file("fw_checksums", 0400, ar->debug.debugfs_phy, ar, |
2259 | &fops_fw_checksums); | 2403 | &fops_fw_checksums); |
2260 | 2404 | ||
2405 | if (IS_ENABLED(CONFIG_MAC80211_DEBUGFS)) | ||
2406 | debugfs_create_file("sta_tid_stats_mask", 0600, | ||
2407 | ar->debug.debugfs_phy, | ||
2408 | ar, &fops_sta_tid_stats_mask); | ||
2409 | |||
2410 | if (test_bit(WMI_SERVICE_TPC_STATS_FINAL, ar->wmi.svc_map)) | ||
2411 | debugfs_create_file("tpc_stats_final", 0400, | ||
2412 | ar->debug.debugfs_phy, ar, | ||
2413 | &fops_tpc_stats_final); | ||
2414 | |||
2261 | return 0; | 2415 | return 0; |
2262 | } | 2416 | } |
2263 | 2417 | ||
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index e54308889e59..0afca5c106b6 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2005-2011 Atheros Communications Inc. | 2 | * Copyright (c) 2005-2011 Atheros Communications Inc. |
3 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. | 3 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. |
4 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
4 | * | 5 | * |
5 | * Permission to use, copy, modify, and/or distribute this software for any | 6 | * Permission to use, copy, modify, and/or distribute this software for any |
6 | * purpose with or without fee is hereby granted, provided that the above | 7 | * purpose with or without fee is hereby granted, provided that the above |
@@ -101,6 +102,9 @@ void ath10k_debug_unregister(struct ath10k *ar); | |||
101 | void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb); | 102 | void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb); |
102 | void ath10k_debug_tpc_stats_process(struct ath10k *ar, | 103 | void ath10k_debug_tpc_stats_process(struct ath10k *ar, |
103 | struct ath10k_tpc_stats *tpc_stats); | 104 | struct ath10k_tpc_stats *tpc_stats); |
105 | void | ||
106 | ath10k_debug_tpc_stats_final_process(struct ath10k *ar, | ||
107 | struct ath10k_tpc_stats_final *tpc_stats); | ||
104 | void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len); | 108 | void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len); |
105 | 109 | ||
106 | #define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++) | 110 | #define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++) |
@@ -164,6 +168,13 @@ static inline void ath10k_debug_tpc_stats_process(struct ath10k *ar, | |||
164 | kfree(tpc_stats); | 168 | kfree(tpc_stats); |
165 | } | 169 | } |
166 | 170 | ||
171 | static inline void | ||
172 | ath10k_debug_tpc_stats_final_process(struct ath10k *ar, | ||
173 | struct ath10k_tpc_stats_final *tpc_stats) | ||
174 | { | ||
175 | kfree(tpc_stats); | ||
176 | } | ||
177 | |||
167 | static inline void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, | 178 | static inline void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, |
168 | int len) | 179 | int len) |
169 | { | 180 | { |
@@ -191,12 +202,42 @@ void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
191 | struct ieee80211_sta *sta, struct dentry *dir); | 202 | struct ieee80211_sta *sta, struct dentry *dir); |
192 | void ath10k_sta_update_rx_duration(struct ath10k *ar, | 203 | void ath10k_sta_update_rx_duration(struct ath10k *ar, |
193 | struct ath10k_fw_stats *stats); | 204 | struct ath10k_fw_stats *stats); |
205 | void ath10k_sta_update_rx_tid_stats(struct ath10k *ar, u8 *first_hdr, | ||
206 | unsigned long int num_msdus, | ||
207 | enum ath10k_pkt_rx_err err, | ||
208 | unsigned long int unchain_cnt, | ||
209 | unsigned long int drop_cnt, | ||
210 | unsigned long int drop_cnt_filter, | ||
211 | unsigned long int queued_msdus); | ||
212 | void ath10k_sta_update_rx_tid_stats_ampdu(struct ath10k *ar, | ||
213 | u16 peer_id, u8 tid, | ||
214 | struct htt_rx_indication_mpdu_range *ranges, | ||
215 | int num_ranges); | ||
194 | #else | 216 | #else |
195 | static inline | 217 | static inline |
196 | void ath10k_sta_update_rx_duration(struct ath10k *ar, | 218 | void ath10k_sta_update_rx_duration(struct ath10k *ar, |
197 | struct ath10k_fw_stats *stats) | 219 | struct ath10k_fw_stats *stats) |
198 | { | 220 | { |
199 | } | 221 | } |
222 | |||
223 | static inline | ||
224 | void ath10k_sta_update_rx_tid_stats(struct ath10k *ar, u8 *first_hdr, | ||
225 | unsigned long int num_msdus, | ||
226 | enum ath10k_pkt_rx_err err, | ||
227 | unsigned long int unchain_cnt, | ||
228 | unsigned long int drop_cnt, | ||
229 | unsigned long int drop_cnt_filter, | ||
230 | unsigned long int queued_msdus) | ||
231 | { | ||
232 | } | ||
233 | |||
234 | static inline | ||
235 | void ath10k_sta_update_rx_tid_stats_ampdu(struct ath10k *ar, | ||
236 | u16 peer_id, u8 tid, | ||
237 | struct htt_rx_indication_mpdu_range *ranges, | ||
238 | int num_ranges) | ||
239 | { | ||
240 | } | ||
200 | #endif /* CONFIG_MAC80211_DEBUGFS */ | 241 | #endif /* CONFIG_MAC80211_DEBUGFS */ |
201 | 242 | ||
202 | #ifdef CONFIG_ATH10K_DEBUG | 243 | #ifdef CONFIG_ATH10K_DEBUG |
diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c index b260b09dd4d3..8f688f136c22 100644 --- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. |
3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -16,8 +17,125 @@ | |||
16 | 17 | ||
17 | #include "core.h" | 18 | #include "core.h" |
18 | #include "wmi-ops.h" | 19 | #include "wmi-ops.h" |
20 | #include "txrx.h" | ||
19 | #include "debug.h" | 21 | #include "debug.h" |
20 | 22 | ||
23 | static void ath10k_rx_stats_update_amsdu_subfrm(struct ath10k *ar, | ||
24 | struct ath10k_sta_tid_stats *stats, | ||
25 | u32 msdu_count) | ||
26 | { | ||
27 | if (msdu_count == 1) | ||
28 | stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_1]++; | ||
29 | else if (msdu_count == 2) | ||
30 | stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_2]++; | ||
31 | else if (msdu_count == 3) | ||
32 | stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_3]++; | ||
33 | else if (msdu_count == 4) | ||
34 | stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_4]++; | ||
35 | else if (msdu_count > 4) | ||
36 | stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_MORE]++; | ||
37 | } | ||
38 | |||
39 | static void ath10k_rx_stats_update_ampdu_subfrm(struct ath10k *ar, | ||
40 | struct ath10k_sta_tid_stats *stats, | ||
41 | u32 mpdu_count) | ||
42 | { | ||
43 | if (mpdu_count <= 10) | ||
44 | stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_10]++; | ||
45 | else if (mpdu_count <= 20) | ||
46 | stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_20]++; | ||
47 | else if (mpdu_count <= 30) | ||
48 | stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_30]++; | ||
49 | else if (mpdu_count <= 40) | ||
50 | stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_40]++; | ||
51 | else if (mpdu_count <= 50) | ||
52 | stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_50]++; | ||
53 | else if (mpdu_count <= 60) | ||
54 | stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_60]++; | ||
55 | else if (mpdu_count > 60) | ||
56 | stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_MORE]++; | ||
57 | } | ||
58 | |||
59 | void ath10k_sta_update_rx_tid_stats_ampdu(struct ath10k *ar, u16 peer_id, u8 tid, | ||
60 | struct htt_rx_indication_mpdu_range *ranges, | ||
61 | int num_ranges) | ||
62 | { | ||
63 | struct ath10k_sta *arsta; | ||
64 | struct ath10k_peer *peer; | ||
65 | int i; | ||
66 | |||
67 | if (tid > IEEE80211_NUM_TIDS || !(ar->sta_tid_stats_mask & BIT(tid))) | ||
68 | return; | ||
69 | |||
70 | rcu_read_lock(); | ||
71 | spin_lock_bh(&ar->data_lock); | ||
72 | |||
73 | peer = ath10k_peer_find_by_id(ar, peer_id); | ||
74 | if (!peer) | ||
75 | goto out; | ||
76 | |||
77 | arsta = (struct ath10k_sta *)peer->sta->drv_priv; | ||
78 | |||
79 | for (i = 0; i < num_ranges; i++) | ||
80 | ath10k_rx_stats_update_ampdu_subfrm(ar, | ||
81 | &arsta->tid_stats[tid], | ||
82 | ranges[i].mpdu_count); | ||
83 | |||
84 | out: | ||
85 | spin_unlock_bh(&ar->data_lock); | ||
86 | rcu_read_unlock(); | ||
87 | } | ||
88 | |||
89 | void ath10k_sta_update_rx_tid_stats(struct ath10k *ar, u8 *first_hdr, | ||
90 | unsigned long int num_msdus, | ||
91 | enum ath10k_pkt_rx_err err, | ||
92 | unsigned long int unchain_cnt, | ||
93 | unsigned long int drop_cnt, | ||
94 | unsigned long int drop_cnt_filter, | ||
95 | unsigned long int queued_msdus) | ||
96 | { | ||
97 | struct ieee80211_sta *sta; | ||
98 | struct ath10k_sta *arsta; | ||
99 | struct ieee80211_hdr *hdr; | ||
100 | struct ath10k_sta_tid_stats *stats; | ||
101 | u8 tid = IEEE80211_NUM_TIDS; | ||
102 | bool non_data_frm = false; | ||
103 | |||
104 | hdr = (struct ieee80211_hdr *)first_hdr; | ||
105 | if (!ieee80211_is_data(hdr->frame_control)) | ||
106 | non_data_frm = true; | ||
107 | |||
108 | if (ieee80211_is_data_qos(hdr->frame_control)) | ||
109 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; | ||
110 | |||
111 | if (!(ar->sta_tid_stats_mask & BIT(tid)) || non_data_frm) | ||
112 | return; | ||
113 | |||
114 | rcu_read_lock(); | ||
115 | |||
116 | sta = ieee80211_find_sta_by_ifaddr(ar->hw, hdr->addr2, NULL); | ||
117 | if (!sta) | ||
118 | goto exit; | ||
119 | |||
120 | arsta = (struct ath10k_sta *)sta->drv_priv; | ||
121 | |||
122 | spin_lock_bh(&ar->data_lock); | ||
123 | stats = &arsta->tid_stats[tid]; | ||
124 | stats->rx_pkt_from_fw += num_msdus; | ||
125 | stats->rx_pkt_unchained += unchain_cnt; | ||
126 | stats->rx_pkt_drop_chained += drop_cnt; | ||
127 | stats->rx_pkt_drop_filter += drop_cnt_filter; | ||
128 | if (err != ATH10K_PKT_RX_ERR_MAX) | ||
129 | stats->rx_pkt_err[err] += queued_msdus; | ||
130 | stats->rx_pkt_queued_for_mac += queued_msdus; | ||
131 | ath10k_rx_stats_update_amsdu_subfrm(ar, &arsta->tid_stats[tid], | ||
132 | num_msdus); | ||
133 | spin_unlock_bh(&ar->data_lock); | ||
134 | |||
135 | exit: | ||
136 | rcu_read_unlock(); | ||
137 | } | ||
138 | |||
21 | static void ath10k_sta_update_extd_stats_rx_duration(struct ath10k *ar, | 139 | static void ath10k_sta_update_extd_stats_rx_duration(struct ath10k *ar, |
22 | struct ath10k_fw_stats *stats) | 140 | struct ath10k_fw_stats *stats) |
23 | { | 141 | { |
@@ -342,6 +460,172 @@ static const struct file_operations fops_peer_debug_trigger = { | |||
342 | .llseek = default_llseek, | 460 | .llseek = default_llseek, |
343 | }; | 461 | }; |
344 | 462 | ||
463 | static char *get_err_str(enum ath10k_pkt_rx_err i) | ||
464 | { | ||
465 | switch (i) { | ||
466 | case ATH10K_PKT_RX_ERR_FCS: | ||
467 | return "fcs_err"; | ||
468 | case ATH10K_PKT_RX_ERR_TKIP: | ||
469 | return "tkip_err"; | ||
470 | case ATH10K_PKT_RX_ERR_CRYPT: | ||
471 | return "crypt_err"; | ||
472 | case ATH10K_PKT_RX_ERR_PEER_IDX_INVAL: | ||
473 | return "peer_idx_inval"; | ||
474 | case ATH10K_PKT_RX_ERR_MAX: | ||
475 | return "unknown"; | ||
476 | } | ||
477 | |||
478 | return "unknown"; | ||
479 | } | ||
480 | |||
481 | static char *get_num_ampdu_subfrm_str(enum ath10k_ampdu_subfrm_num i) | ||
482 | { | ||
483 | switch (i) { | ||
484 | case ATH10K_AMPDU_SUBFRM_NUM_10: | ||
485 | return "upto 10"; | ||
486 | case ATH10K_AMPDU_SUBFRM_NUM_20: | ||
487 | return "11-20"; | ||
488 | case ATH10K_AMPDU_SUBFRM_NUM_30: | ||
489 | return "21-30"; | ||
490 | case ATH10K_AMPDU_SUBFRM_NUM_40: | ||
491 | return "31-40"; | ||
492 | case ATH10K_AMPDU_SUBFRM_NUM_50: | ||
493 | return "41-50"; | ||
494 | case ATH10K_AMPDU_SUBFRM_NUM_60: | ||
495 | return "51-60"; | ||
496 | case ATH10K_AMPDU_SUBFRM_NUM_MORE: | ||
497 | return ">60"; | ||
498 | case ATH10K_AMPDU_SUBFRM_NUM_MAX: | ||
499 | return "0"; | ||
500 | } | ||
501 | |||
502 | return "0"; | ||
503 | } | ||
504 | |||
505 | static char *get_num_amsdu_subfrm_str(enum ath10k_amsdu_subfrm_num i) | ||
506 | { | ||
507 | switch (i) { | ||
508 | case ATH10K_AMSDU_SUBFRM_NUM_1: | ||
509 | return "1"; | ||
510 | case ATH10K_AMSDU_SUBFRM_NUM_2: | ||
511 | return "2"; | ||
512 | case ATH10K_AMSDU_SUBFRM_NUM_3: | ||
513 | return "3"; | ||
514 | case ATH10K_AMSDU_SUBFRM_NUM_4: | ||
515 | return "4"; | ||
516 | case ATH10K_AMSDU_SUBFRM_NUM_MORE: | ||
517 | return ">4"; | ||
518 | case ATH10K_AMSDU_SUBFRM_NUM_MAX: | ||
519 | return "0"; | ||
520 | } | ||
521 | |||
522 | return "0"; | ||
523 | } | ||
524 | |||
525 | #define PRINT_TID_STATS(_field, _tabs) \ | ||
526 | do { \ | ||
527 | int k = 0; \ | ||
528 | for (j = 0; j <= IEEE80211_NUM_TIDS; j++) { \ | ||
529 | if (ar->sta_tid_stats_mask & BIT(j)) { \ | ||
530 | len += scnprintf(buf + len, buf_len - len, \ | ||
531 | "[%02d] %-10lu ", \ | ||
532 | j, stats[j]._field); \ | ||
533 | k++; \ | ||
534 | if (k % 8 == 0) { \ | ||
535 | len += scnprintf(buf + len, \ | ||
536 | buf_len - len, "\n"); \ | ||
537 | len += scnprintf(buf + len, \ | ||
538 | buf_len - len, \ | ||
539 | _tabs); \ | ||
540 | } \ | ||
541 | } \ | ||
542 | } \ | ||
543 | len += scnprintf(buf + len, buf_len - len, "\n"); \ | ||
544 | } while (0) | ||
545 | |||
546 | static ssize_t ath10k_dbg_sta_read_tid_stats(struct file *file, | ||
547 | char __user *user_buf, | ||
548 | size_t count, loff_t *ppos) | ||
549 | { | ||
550 | struct ieee80211_sta *sta = file->private_data; | ||
551 | struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; | ||
552 | struct ath10k *ar = arsta->arvif->ar; | ||
553 | struct ath10k_sta_tid_stats *stats = arsta->tid_stats; | ||
554 | size_t len = 0, buf_len = 1048 * IEEE80211_NUM_TIDS; | ||
555 | char *buf; | ||
556 | int i, j; | ||
557 | ssize_t ret; | ||
558 | |||
559 | buf = kzalloc(buf_len, GFP_KERNEL); | ||
560 | if (!buf) | ||
561 | return -ENOMEM; | ||
562 | |||
563 | mutex_lock(&ar->conf_mutex); | ||
564 | |||
565 | spin_lock_bh(&ar->data_lock); | ||
566 | |||
567 | len += scnprintf(buf + len, buf_len - len, | ||
568 | "\n\t\tDriver Rx pkt stats per tid, ([tid] count)\n"); | ||
569 | len += scnprintf(buf + len, buf_len - len, | ||
570 | "\t\t------------------------------------------\n"); | ||
571 | len += scnprintf(buf + len, buf_len - len, "MSDUs from FW\t\t\t"); | ||
572 | PRINT_TID_STATS(rx_pkt_from_fw, "\t\t\t\t"); | ||
573 | |||
574 | len += scnprintf(buf + len, buf_len - len, "MSDUs unchained\t\t\t"); | ||
575 | PRINT_TID_STATS(rx_pkt_unchained, "\t\t\t\t"); | ||
576 | |||
577 | len += scnprintf(buf + len, buf_len - len, | ||
578 | "MSDUs locally dropped:chained\t"); | ||
579 | PRINT_TID_STATS(rx_pkt_drop_chained, "\t\t\t\t"); | ||
580 | |||
581 | len += scnprintf(buf + len, buf_len - len, | ||
582 | "MSDUs locally dropped:filtered\t"); | ||
583 | PRINT_TID_STATS(rx_pkt_drop_filter, "\t\t\t\t"); | ||
584 | |||
585 | len += scnprintf(buf + len, buf_len - len, | ||
586 | "MSDUs queued for mac80211\t"); | ||
587 | PRINT_TID_STATS(rx_pkt_queued_for_mac, "\t\t\t\t"); | ||
588 | |||
589 | for (i = 0; i < ATH10K_PKT_RX_ERR_MAX; i++) { | ||
590 | len += scnprintf(buf + len, buf_len - len, | ||
591 | "MSDUs with error:%s\t", get_err_str(i)); | ||
592 | PRINT_TID_STATS(rx_pkt_err[i], "\t\t\t\t"); | ||
593 | } | ||
594 | |||
595 | len += scnprintf(buf + len, buf_len - len, "\n"); | ||
596 | for (i = 0; i < ATH10K_AMPDU_SUBFRM_NUM_MAX; i++) { | ||
597 | len += scnprintf(buf + len, buf_len - len, | ||
598 | "A-MPDU num subframes %s\t", | ||
599 | get_num_ampdu_subfrm_str(i)); | ||
600 | PRINT_TID_STATS(rx_pkt_ampdu[i], "\t\t\t\t"); | ||
601 | } | ||
602 | |||
603 | len += scnprintf(buf + len, buf_len - len, "\n"); | ||
604 | for (i = 0; i < ATH10K_AMSDU_SUBFRM_NUM_MAX; i++) { | ||
605 | len += scnprintf(buf + len, buf_len - len, | ||
606 | "A-MSDU num subframes %s\t\t", | ||
607 | get_num_amsdu_subfrm_str(i)); | ||
608 | PRINT_TID_STATS(rx_pkt_amsdu[i], "\t\t\t\t"); | ||
609 | } | ||
610 | |||
611 | spin_unlock_bh(&ar->data_lock); | ||
612 | |||
613 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
614 | |||
615 | kfree(buf); | ||
616 | |||
617 | mutex_unlock(&ar->conf_mutex); | ||
618 | |||
619 | return ret; | ||
620 | } | ||
621 | |||
622 | static const struct file_operations fops_tid_stats_dump = { | ||
623 | .open = simple_open, | ||
624 | .read = ath10k_dbg_sta_read_tid_stats, | ||
625 | .owner = THIS_MODULE, | ||
626 | .llseek = default_llseek, | ||
627 | }; | ||
628 | |||
345 | void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 629 | void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
346 | struct ieee80211_sta *sta, struct dentry *dir) | 630 | struct ieee80211_sta *sta, struct dentry *dir) |
347 | { | 631 | { |
@@ -351,4 +635,6 @@ void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
351 | debugfs_create_file("delba", 0200, dir, sta, &fops_delba); | 635 | debugfs_create_file("delba", 0200, dir, sta, &fops_delba); |
352 | debugfs_create_file("peer_debug_trigger", 0600, dir, sta, | 636 | debugfs_create_file("peer_debug_trigger", 0600, dir, sta, |
353 | &fops_peer_debug_trigger); | 637 | &fops_peer_debug_trigger); |
638 | debugfs_create_file("dump_tid_stats", 0400, dir, sta, | ||
639 | &fops_tid_stats_dump); | ||
354 | } | 640 | } |
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 6d96f9560950..64996aba1485 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2005-2011 Atheros Communications Inc. | 2 | * Copyright (c) 2005-2011 Atheros Communications Inc. |
3 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. | 3 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. |
4 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
4 | * | 5 | * |
5 | * Permission to use, copy, modify, and/or distribute this software for any | 6 | * Permission to use, copy, modify, and/or distribute this software for any |
6 | * purpose with or without fee is hereby granted, provided that the above | 7 | * purpose with or without fee is hereby granted, provided that the above |
@@ -1502,7 +1503,9 @@ static void ath10k_htt_rx_h_csum_offload(struct sk_buff *msdu) | |||
1502 | static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, | 1503 | static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, |
1503 | struct sk_buff_head *amsdu, | 1504 | struct sk_buff_head *amsdu, |
1504 | struct ieee80211_rx_status *status, | 1505 | struct ieee80211_rx_status *status, |
1505 | bool fill_crypt_header) | 1506 | bool fill_crypt_header, |
1507 | u8 *rx_hdr, | ||
1508 | enum ath10k_pkt_rx_err *err) | ||
1506 | { | 1509 | { |
1507 | struct sk_buff *first; | 1510 | struct sk_buff *first; |
1508 | struct sk_buff *last; | 1511 | struct sk_buff *last; |
@@ -1538,6 +1541,9 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, | |||
1538 | hdr = (void *)rxd->rx_hdr_status; | 1541 | hdr = (void *)rxd->rx_hdr_status; |
1539 | memcpy(first_hdr, hdr, RX_HTT_HDR_STATUS_LEN); | 1542 | memcpy(first_hdr, hdr, RX_HTT_HDR_STATUS_LEN); |
1540 | 1543 | ||
1544 | if (rx_hdr) | ||
1545 | memcpy(rx_hdr, hdr, RX_HTT_HDR_STATUS_LEN); | ||
1546 | |||
1541 | /* Each A-MSDU subframe will use the original header as the base and be | 1547 | /* Each A-MSDU subframe will use the original header as the base and be |
1542 | * reported as a separate MSDU so strip the A-MSDU bit from QoS Ctl. | 1548 | * reported as a separate MSDU so strip the A-MSDU bit from QoS Ctl. |
1543 | */ | 1549 | */ |
@@ -1581,6 +1587,17 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, | |||
1581 | if (has_tkip_err) | 1587 | if (has_tkip_err) |
1582 | status->flag |= RX_FLAG_MMIC_ERROR; | 1588 | status->flag |= RX_FLAG_MMIC_ERROR; |
1583 | 1589 | ||
1590 | if (err) { | ||
1591 | if (has_fcs_err) | ||
1592 | *err = ATH10K_PKT_RX_ERR_FCS; | ||
1593 | else if (has_tkip_err) | ||
1594 | *err = ATH10K_PKT_RX_ERR_TKIP; | ||
1595 | else if (has_crypto_err) | ||
1596 | *err = ATH10K_PKT_RX_ERR_CRYPT; | ||
1597 | else if (has_peer_idx_invalid) | ||
1598 | *err = ATH10K_PKT_RX_ERR_PEER_IDX_INVAL; | ||
1599 | } | ||
1600 | |||
1584 | /* Firmware reports all necessary management frames via WMI already. | 1601 | /* Firmware reports all necessary management frames via WMI already. |
1585 | * They are not reported to monitor interfaces at all so pass the ones | 1602 | * They are not reported to monitor interfaces at all so pass the ones |
1586 | * coming via HTT to monitor interfaces instead. This simplifies | 1603 | * coming via HTT to monitor interfaces instead. This simplifies |
@@ -1651,11 +1668,13 @@ static void ath10k_htt_rx_h_enqueue(struct ath10k *ar, | |||
1651 | } | 1668 | } |
1652 | } | 1669 | } |
1653 | 1670 | ||
1654 | static int ath10k_unchain_msdu(struct sk_buff_head *amsdu) | 1671 | static int ath10k_unchain_msdu(struct sk_buff_head *amsdu, |
1672 | unsigned long int *unchain_cnt) | ||
1655 | { | 1673 | { |
1656 | struct sk_buff *skb, *first; | 1674 | struct sk_buff *skb, *first; |
1657 | int space; | 1675 | int space; |
1658 | int total_len = 0; | 1676 | int total_len = 0; |
1677 | int amsdu_len = skb_queue_len(amsdu); | ||
1659 | 1678 | ||
1660 | /* TODO: Might could optimize this by using | 1679 | /* TODO: Might could optimize this by using |
1661 | * skb_try_coalesce or similar method to | 1680 | * skb_try_coalesce or similar method to |
@@ -1691,11 +1710,16 @@ static int ath10k_unchain_msdu(struct sk_buff_head *amsdu) | |||
1691 | } | 1710 | } |
1692 | 1711 | ||
1693 | __skb_queue_head(amsdu, first); | 1712 | __skb_queue_head(amsdu, first); |
1713 | |||
1714 | *unchain_cnt += amsdu_len - 1; | ||
1715 | |||
1694 | return 0; | 1716 | return 0; |
1695 | } | 1717 | } |
1696 | 1718 | ||
1697 | static void ath10k_htt_rx_h_unchain(struct ath10k *ar, | 1719 | static void ath10k_htt_rx_h_unchain(struct ath10k *ar, |
1698 | struct sk_buff_head *amsdu) | 1720 | struct sk_buff_head *amsdu, |
1721 | unsigned long int *drop_cnt, | ||
1722 | unsigned long int *unchain_cnt) | ||
1699 | { | 1723 | { |
1700 | struct sk_buff *first; | 1724 | struct sk_buff *first; |
1701 | struct htt_rx_desc *rxd; | 1725 | struct htt_rx_desc *rxd; |
@@ -1713,11 +1737,12 @@ static void ath10k_htt_rx_h_unchain(struct ath10k *ar, | |||
1713 | */ | 1737 | */ |
1714 | if (decap != RX_MSDU_DECAP_RAW || | 1738 | if (decap != RX_MSDU_DECAP_RAW || |
1715 | skb_queue_len(amsdu) != 1 + rxd->frag_info.ring2_more_count) { | 1739 | skb_queue_len(amsdu) != 1 + rxd->frag_info.ring2_more_count) { |
1740 | *drop_cnt += skb_queue_len(amsdu); | ||
1716 | __skb_queue_purge(amsdu); | 1741 | __skb_queue_purge(amsdu); |
1717 | return; | 1742 | return; |
1718 | } | 1743 | } |
1719 | 1744 | ||
1720 | ath10k_unchain_msdu(amsdu); | 1745 | ath10k_unchain_msdu(amsdu, unchain_cnt); |
1721 | } | 1746 | } |
1722 | 1747 | ||
1723 | static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar, | 1748 | static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar, |
@@ -1743,7 +1768,8 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar, | |||
1743 | 1768 | ||
1744 | static void ath10k_htt_rx_h_filter(struct ath10k *ar, | 1769 | static void ath10k_htt_rx_h_filter(struct ath10k *ar, |
1745 | struct sk_buff_head *amsdu, | 1770 | struct sk_buff_head *amsdu, |
1746 | struct ieee80211_rx_status *rx_status) | 1771 | struct ieee80211_rx_status *rx_status, |
1772 | unsigned long int *drop_cnt) | ||
1747 | { | 1773 | { |
1748 | if (skb_queue_empty(amsdu)) | 1774 | if (skb_queue_empty(amsdu)) |
1749 | return; | 1775 | return; |
@@ -1751,6 +1777,9 @@ static void ath10k_htt_rx_h_filter(struct ath10k *ar, | |||
1751 | if (ath10k_htt_rx_amsdu_allowed(ar, amsdu, rx_status)) | 1777 | if (ath10k_htt_rx_amsdu_allowed(ar, amsdu, rx_status)) |
1752 | return; | 1778 | return; |
1753 | 1779 | ||
1780 | if (drop_cnt) | ||
1781 | *drop_cnt += skb_queue_len(amsdu); | ||
1782 | |||
1754 | __skb_queue_purge(amsdu); | 1783 | __skb_queue_purge(amsdu); |
1755 | } | 1784 | } |
1756 | 1785 | ||
@@ -1760,6 +1789,12 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt) | |||
1760 | struct ieee80211_rx_status *rx_status = &htt->rx_status; | 1789 | struct ieee80211_rx_status *rx_status = &htt->rx_status; |
1761 | struct sk_buff_head amsdu; | 1790 | struct sk_buff_head amsdu; |
1762 | int ret; | 1791 | int ret; |
1792 | unsigned long int drop_cnt = 0; | ||
1793 | unsigned long int unchain_cnt = 0; | ||
1794 | unsigned long int drop_cnt_filter = 0; | ||
1795 | unsigned long int msdus_to_queue, num_msdus; | ||
1796 | enum ath10k_pkt_rx_err err = ATH10K_PKT_RX_ERR_MAX; | ||
1797 | u8 first_hdr[RX_HTT_HDR_STATUS_LEN]; | ||
1763 | 1798 | ||
1764 | __skb_queue_head_init(&amsdu); | 1799 | __skb_queue_head_init(&amsdu); |
1765 | 1800 | ||
@@ -1781,16 +1816,23 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt) | |||
1781 | return ret; | 1816 | return ret; |
1782 | } | 1817 | } |
1783 | 1818 | ||
1819 | num_msdus = skb_queue_len(&amsdu); | ||
1820 | |||
1784 | ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff); | 1821 | ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff); |
1785 | 1822 | ||
1786 | /* only for ret = 1 indicates chained msdus */ | 1823 | /* only for ret = 1 indicates chained msdus */ |
1787 | if (ret > 0) | 1824 | if (ret > 0) |
1788 | ath10k_htt_rx_h_unchain(ar, &amsdu); | 1825 | ath10k_htt_rx_h_unchain(ar, &amsdu, &drop_cnt, &unchain_cnt); |
1789 | 1826 | ||
1790 | ath10k_htt_rx_h_filter(ar, &amsdu, rx_status); | 1827 | ath10k_htt_rx_h_filter(ar, &amsdu, rx_status, &drop_cnt_filter); |
1791 | ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true); | 1828 | ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true, first_hdr, &err); |
1829 | msdus_to_queue = skb_queue_len(&amsdu); | ||
1792 | ath10k_htt_rx_h_enqueue(ar, &amsdu, rx_status); | 1830 | ath10k_htt_rx_h_enqueue(ar, &amsdu, rx_status); |
1793 | 1831 | ||
1832 | ath10k_sta_update_rx_tid_stats(ar, first_hdr, num_msdus, err, | ||
1833 | unchain_cnt, drop_cnt, drop_cnt_filter, | ||
1834 | msdus_to_queue); | ||
1835 | |||
1794 | return 0; | 1836 | return 0; |
1795 | } | 1837 | } |
1796 | 1838 | ||
@@ -1801,9 +1843,14 @@ static void ath10k_htt_rx_proc_rx_ind(struct ath10k_htt *htt, | |||
1801 | struct htt_rx_indication_mpdu_range *mpdu_ranges; | 1843 | struct htt_rx_indication_mpdu_range *mpdu_ranges; |
1802 | int num_mpdu_ranges; | 1844 | int num_mpdu_ranges; |
1803 | int i, mpdu_count = 0; | 1845 | int i, mpdu_count = 0; |
1846 | u16 peer_id; | ||
1847 | u8 tid; | ||
1804 | 1848 | ||
1805 | num_mpdu_ranges = MS(__le32_to_cpu(rx->hdr.info1), | 1849 | num_mpdu_ranges = MS(__le32_to_cpu(rx->hdr.info1), |
1806 | HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES); | 1850 | HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES); |
1851 | peer_id = __le16_to_cpu(rx->hdr.peer_id); | ||
1852 | tid = MS(rx->hdr.info0, HTT_RX_INDICATION_INFO0_EXT_TID); | ||
1853 | |||
1807 | mpdu_ranges = htt_rx_ind_get_mpdu_ranges(rx); | 1854 | mpdu_ranges = htt_rx_ind_get_mpdu_ranges(rx); |
1808 | 1855 | ||
1809 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx ind: ", | 1856 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx ind: ", |
@@ -1815,6 +1862,9 @@ static void ath10k_htt_rx_proc_rx_ind(struct ath10k_htt *htt, | |||
1815 | mpdu_count += mpdu_ranges[i].mpdu_count; | 1862 | mpdu_count += mpdu_ranges[i].mpdu_count; |
1816 | 1863 | ||
1817 | atomic_add(mpdu_count, &htt->num_mpdus_ready); | 1864 | atomic_add(mpdu_count, &htt->num_mpdus_ready); |
1865 | |||
1866 | ath10k_sta_update_rx_tid_stats_ampdu(ar, peer_id, tid, mpdu_ranges, | ||
1867 | num_mpdu_ranges); | ||
1818 | } | 1868 | } |
1819 | 1869 | ||
1820 | static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, | 1870 | static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, |
@@ -2124,8 +2174,9 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) | |||
2124 | * should still give an idea about rx rate to the user. | 2174 | * should still give an idea about rx rate to the user. |
2125 | */ | 2175 | */ |
2126 | ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id); | 2176 | ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id); |
2127 | ath10k_htt_rx_h_filter(ar, &amsdu, status); | 2177 | ath10k_htt_rx_h_filter(ar, &amsdu, status, NULL); |
2128 | ath10k_htt_rx_h_mpdu(ar, &amsdu, status, false); | 2178 | ath10k_htt_rx_h_mpdu(ar, &amsdu, status, false, NULL, |
2179 | NULL); | ||
2129 | ath10k_htt_rx_h_enqueue(ar, &amsdu, status); | 2180 | ath10k_htt_rx_h_enqueue(ar, &amsdu, status); |
2130 | break; | 2181 | break; |
2131 | case -EAGAIN: | 2182 | case -EAGAIN: |
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index ebb3f1b046f3..02674ee04435 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2005-2011 Atheros Communications Inc. | 2 | * Copyright (c) 2005-2011 Atheros Communications Inc. |
3 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. | 3 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. |
4 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
4 | * | 5 | * |
5 | * Permission to use, copy, modify, and/or distribute this software for any | 6 | * Permission to use, copy, modify, and/or distribute this software for any |
6 | * purpose with or without fee is hereby granted, provided that the above | 7 | * purpose with or without fee is hereby granted, provided that the above |
@@ -3808,6 +3809,7 @@ void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work) | |||
3808 | { | 3809 | { |
3809 | struct ath10k *ar = container_of(work, struct ath10k, wmi_mgmt_tx_work); | 3810 | struct ath10k *ar = container_of(work, struct ath10k, wmi_mgmt_tx_work); |
3810 | struct sk_buff *skb; | 3811 | struct sk_buff *skb; |
3812 | dma_addr_t paddr; | ||
3811 | int ret; | 3813 | int ret; |
3812 | 3814 | ||
3813 | for (;;) { | 3815 | for (;;) { |
@@ -3815,11 +3817,27 @@ void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work) | |||
3815 | if (!skb) | 3817 | if (!skb) |
3816 | break; | 3818 | break; |
3817 | 3819 | ||
3818 | ret = ath10k_wmi_mgmt_tx(ar, skb); | 3820 | if (test_bit(ATH10K_FW_FEATURE_MGMT_TX_BY_REF, |
3819 | if (ret) { | 3821 | ar->running_fw->fw_file.fw_features)) { |
3820 | ath10k_warn(ar, "failed to transmit management frame via WMI: %d\n", | 3822 | paddr = dma_map_single(ar->dev, skb->data, |
3821 | ret); | 3823 | skb->len, DMA_TO_DEVICE); |
3822 | ieee80211_free_txskb(ar->hw, skb); | 3824 | if (!paddr) |
3825 | continue; | ||
3826 | ret = ath10k_wmi_mgmt_tx_send(ar, skb, paddr); | ||
3827 | if (ret) { | ||
3828 | ath10k_warn(ar, "failed to transmit management frame by ref via WMI: %d\n", | ||
3829 | ret); | ||
3830 | dma_unmap_single(ar->dev, paddr, skb->len, | ||
3831 | DMA_FROM_DEVICE); | ||
3832 | ieee80211_free_txskb(ar->hw, skb); | ||
3833 | } | ||
3834 | } else { | ||
3835 | ret = ath10k_wmi_mgmt_tx(ar, skb); | ||
3836 | if (ret) { | ||
3837 | ath10k_warn(ar, "failed to transmit management frame via WMI: %d\n", | ||
3838 | ret); | ||
3839 | ieee80211_free_txskb(ar->hw, skb); | ||
3840 | } | ||
3823 | } | 3841 | } |
3824 | } | 3842 | } |
3825 | } | 3843 | } |
@@ -7085,10 +7103,20 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw, | |||
7085 | { | 7103 | { |
7086 | struct ath10k *ar = hw->priv; | 7104 | struct ath10k *ar = hw->priv; |
7087 | struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; | 7105 | struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; |
7106 | struct ath10k_vif *arvif = (void *)vif->drv_priv; | ||
7107 | struct ath10k_peer *peer; | ||
7088 | u32 bw, smps; | 7108 | u32 bw, smps; |
7089 | 7109 | ||
7090 | spin_lock_bh(&ar->data_lock); | 7110 | spin_lock_bh(&ar->data_lock); |
7091 | 7111 | ||
7112 | peer = ath10k_peer_find(ar, arvif->vdev_id, sta->addr); | ||
7113 | if (!peer) { | ||
7114 | spin_unlock_bh(&ar->data_lock); | ||
7115 | ath10k_warn(ar, "mac sta rc update failed to find peer %pM on vdev %i\n", | ||
7116 | sta->addr, arvif->vdev_id); | ||
7117 | return; | ||
7118 | } | ||
7119 | |||
7092 | ath10k_dbg(ar, ATH10K_DBG_MAC, | 7120 | ath10k_dbg(ar, ATH10K_DBG_MAC, |
7093 | "mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n", | 7121 | "mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n", |
7094 | sta->addr, changed, sta->bandwidth, sta->rx_nss, | 7122 | sta->addr, changed, sta->bandwidth, sta->rx_nss, |
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 1b266cd0c2ec..808f3d67ba90 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c | |||
@@ -2221,7 +2221,7 @@ static int ath10k_pci_get_num_banks(struct ath10k *ar) | |||
2221 | } | 2221 | } |
2222 | break; | 2222 | break; |
2223 | case QCA9377_1_0_DEVICE_ID: | 2223 | case QCA9377_1_0_DEVICE_ID: |
2224 | return 4; | 2224 | return 9; |
2225 | } | 2225 | } |
2226 | 2226 | ||
2227 | ath10k_warn(ar, "unknown number of banks, assuming 1\n"); | 2227 | ath10k_warn(ar, "unknown number of banks, assuming 1\n"); |
diff --git a/drivers/net/wireless/ath/ath10k/trace.h b/drivers/net/wireless/ath/ath10k/trace.h index e40edced1d82..7d2fac342150 100644 --- a/drivers/net/wireless/ath/ath10k/trace.h +++ b/drivers/net/wireless/ath/ath10k/trace.h | |||
@@ -152,10 +152,9 @@ TRACE_EVENT(ath10k_log_dbg_dump, | |||
152 | ); | 152 | ); |
153 | 153 | ||
154 | TRACE_EVENT(ath10k_wmi_cmd, | 154 | TRACE_EVENT(ath10k_wmi_cmd, |
155 | TP_PROTO(struct ath10k *ar, int id, const void *buf, size_t buf_len, | 155 | TP_PROTO(struct ath10k *ar, int id, const void *buf, size_t buf_len), |
156 | int ret), | ||
157 | 156 | ||
158 | TP_ARGS(ar, id, buf, buf_len, ret), | 157 | TP_ARGS(ar, id, buf, buf_len), |
159 | 158 | ||
160 | TP_STRUCT__entry( | 159 | TP_STRUCT__entry( |
161 | __string(device, dev_name(ar->dev)) | 160 | __string(device, dev_name(ar->dev)) |
@@ -163,7 +162,6 @@ TRACE_EVENT(ath10k_wmi_cmd, | |||
163 | __field(unsigned int, id) | 162 | __field(unsigned int, id) |
164 | __field(size_t, buf_len) | 163 | __field(size_t, buf_len) |
165 | __dynamic_array(u8, buf, buf_len) | 164 | __dynamic_array(u8, buf, buf_len) |
166 | __field(int, ret) | ||
167 | ), | 165 | ), |
168 | 166 | ||
169 | TP_fast_assign( | 167 | TP_fast_assign( |
@@ -171,17 +169,15 @@ TRACE_EVENT(ath10k_wmi_cmd, | |||
171 | __assign_str(driver, dev_driver_string(ar->dev)); | 169 | __assign_str(driver, dev_driver_string(ar->dev)); |
172 | __entry->id = id; | 170 | __entry->id = id; |
173 | __entry->buf_len = buf_len; | 171 | __entry->buf_len = buf_len; |
174 | __entry->ret = ret; | ||
175 | memcpy(__get_dynamic_array(buf), buf, buf_len); | 172 | memcpy(__get_dynamic_array(buf), buf, buf_len); |
176 | ), | 173 | ), |
177 | 174 | ||
178 | TP_printk( | 175 | TP_printk( |
179 | "%s %s id %d len %zu ret %d", | 176 | "%s %s id %d len %zu", |
180 | __get_str(driver), | 177 | __get_str(driver), |
181 | __get_str(device), | 178 | __get_str(device), |
182 | __entry->id, | 179 | __entry->id, |
183 | __entry->buf_len, | 180 | __entry->buf_len |
184 | __entry->ret | ||
185 | ) | 181 | ) |
186 | ); | 182 | ); |
187 | 183 | ||
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index 5b3b021526ab..70e23bbf7171 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c | |||
@@ -102,11 +102,6 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt, | |||
102 | memset(&info->status, 0, sizeof(info->status)); | 102 | memset(&info->status, 0, sizeof(info->status)); |
103 | trace_ath10k_txrx_tx_unref(ar, tx_done->msdu_id); | 103 | trace_ath10k_txrx_tx_unref(ar, tx_done->msdu_id); |
104 | 104 | ||
105 | if (tx_done->status == HTT_TX_COMPL_STATE_DISCARD) { | ||
106 | ieee80211_free_txskb(htt->ar->hw, msdu); | ||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) | 105 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) |
111 | info->flags |= IEEE80211_TX_STAT_ACK; | 106 | info->flags |= IEEE80211_TX_STAT_ACK; |
112 | 107 | ||
@@ -117,6 +112,13 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt, | |||
117 | (info->flags & IEEE80211_TX_CTL_NO_ACK)) | 112 | (info->flags & IEEE80211_TX_CTL_NO_ACK)) |
118 | info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; | 113 | info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; |
119 | 114 | ||
115 | if (tx_done->status == HTT_TX_COMPL_STATE_DISCARD) { | ||
116 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) | ||
117 | info->flags &= ~IEEE80211_TX_STAT_NOACK_TRANSMITTED; | ||
118 | else | ||
119 | info->flags &= ~IEEE80211_TX_STAT_ACK; | ||
120 | } | ||
121 | |||
120 | ieee80211_tx_status(htt->ar->hw, msdu); | 122 | ieee80211_tx_status(htt->ar->hw, msdu); |
121 | /* we do not own the msdu anymore */ | 123 | /* we do not own the msdu anymore */ |
122 | 124 | ||
diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h index 14093cfdc505..c35e45340b4f 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-ops.h +++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2005-2011 Atheros Communications Inc. | 2 | * Copyright (c) 2005-2011 Atheros Communications Inc. |
3 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. | 3 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. |
4 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
4 | * | 5 | * |
5 | * Permission to use, copy, modify, and/or distribute this software for any | 6 | * Permission to use, copy, modify, and/or distribute this software for any |
6 | * purpose with or without fee is hereby granted, provided that the above | 7 | * purpose with or without fee is hereby granted, provided that the above |
@@ -125,6 +126,9 @@ struct wmi_ops { | |||
125 | enum wmi_force_fw_hang_type type, | 126 | enum wmi_force_fw_hang_type type, |
126 | u32 delay_ms); | 127 | u32 delay_ms); |
127 | struct sk_buff *(*gen_mgmt_tx)(struct ath10k *ar, struct sk_buff *skb); | 128 | struct sk_buff *(*gen_mgmt_tx)(struct ath10k *ar, struct sk_buff *skb); |
129 | struct sk_buff *(*gen_mgmt_tx_send)(struct ath10k *ar, | ||
130 | struct sk_buff *skb, | ||
131 | dma_addr_t paddr); | ||
128 | struct sk_buff *(*gen_dbglog_cfg)(struct ath10k *ar, u64 module_enable, | 132 | struct sk_buff *(*gen_dbglog_cfg)(struct ath10k *ar, u64 module_enable, |
129 | u32 log_level); | 133 | u32 log_level); |
130 | struct sk_buff *(*gen_pktlog_enable)(struct ath10k *ar, u32 filter); | 134 | struct sk_buff *(*gen_pktlog_enable)(struct ath10k *ar, u32 filter); |
@@ -197,6 +201,9 @@ struct wmi_ops { | |||
197 | (struct ath10k *ar, | 201 | (struct ath10k *ar, |
198 | enum wmi_bss_survey_req_type type); | 202 | enum wmi_bss_survey_req_type type); |
199 | struct sk_buff *(*gen_echo)(struct ath10k *ar, u32 value); | 203 | struct sk_buff *(*gen_echo)(struct ath10k *ar, u32 value); |
204 | struct sk_buff *(*gen_pdev_get_tpc_table_cmdid)(struct ath10k *ar, | ||
205 | u32 param); | ||
206 | |||
200 | }; | 207 | }; |
201 | 208 | ||
202 | int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); | 209 | int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); |
@@ -372,12 +379,33 @@ ath10k_wmi_get_txbf_conf_scheme(struct ath10k *ar) | |||
372 | } | 379 | } |
373 | 380 | ||
374 | static inline int | 381 | static inline int |
382 | ath10k_wmi_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu, | ||
383 | dma_addr_t paddr) | ||
384 | { | ||
385 | struct sk_buff *skb; | ||
386 | int ret; | ||
387 | |||
388 | if (!ar->wmi.ops->gen_mgmt_tx_send) | ||
389 | return -EOPNOTSUPP; | ||
390 | |||
391 | skb = ar->wmi.ops->gen_mgmt_tx_send(ar, msdu, paddr); | ||
392 | if (IS_ERR(skb)) | ||
393 | return PTR_ERR(skb); | ||
394 | |||
395 | ret = ath10k_wmi_cmd_send(ar, skb, | ||
396 | ar->wmi.cmd->mgmt_tx_send_cmdid); | ||
397 | if (ret) | ||
398 | return ret; | ||
399 | |||
400 | return 0; | ||
401 | } | ||
402 | |||
403 | static inline int | ||
375 | ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu) | 404 | ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu) |
376 | { | 405 | { |
377 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(msdu); | 406 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(msdu); |
378 | struct sk_buff *skb; | 407 | struct sk_buff *skb; |
379 | int ret; | 408 | int ret; |
380 | u32 mgmt_tx_cmdid; | ||
381 | 409 | ||
382 | if (!ar->wmi.ops->gen_mgmt_tx) | 410 | if (!ar->wmi.ops->gen_mgmt_tx) |
383 | return -EOPNOTSUPP; | 411 | return -EOPNOTSUPP; |
@@ -386,13 +414,8 @@ ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu) | |||
386 | if (IS_ERR(skb)) | 414 | if (IS_ERR(skb)) |
387 | return PTR_ERR(skb); | 415 | return PTR_ERR(skb); |
388 | 416 | ||
389 | if (test_bit(ATH10K_FW_FEATURE_MGMT_TX_BY_REF, | 417 | ret = ath10k_wmi_cmd_send(ar, skb, |
390 | ar->running_fw->fw_file.fw_features)) | 418 | ar->wmi.cmd->mgmt_tx_cmdid); |
391 | mgmt_tx_cmdid = ar->wmi.cmd->mgmt_tx_send_cmdid; | ||
392 | else | ||
393 | mgmt_tx_cmdid = ar->wmi.cmd->mgmt_tx_cmdid; | ||
394 | |||
395 | ret = ath10k_wmi_cmd_send(ar, skb, mgmt_tx_cmdid); | ||
396 | if (ret) | 419 | if (ret) |
397 | return ret; | 420 | return ret; |
398 | 421 | ||
@@ -1425,4 +1448,21 @@ ath10k_wmi_echo(struct ath10k *ar, u32 value) | |||
1425 | return ath10k_wmi_cmd_send(ar, skb, wmi->cmd->echo_cmdid); | 1448 | return ath10k_wmi_cmd_send(ar, skb, wmi->cmd->echo_cmdid); |
1426 | } | 1449 | } |
1427 | 1450 | ||
1451 | static inline int | ||
1452 | ath10k_wmi_pdev_get_tpc_table_cmdid(struct ath10k *ar, u32 param) | ||
1453 | { | ||
1454 | struct sk_buff *skb; | ||
1455 | |||
1456 | if (!ar->wmi.ops->gen_pdev_get_tpc_table_cmdid) | ||
1457 | return -EOPNOTSUPP; | ||
1458 | |||
1459 | skb = ar->wmi.ops->gen_pdev_get_tpc_table_cmdid(ar, param); | ||
1460 | |||
1461 | if (IS_ERR(skb)) | ||
1462 | return PTR_ERR(skb); | ||
1463 | |||
1464 | return ath10k_wmi_cmd_send(ar, skb, | ||
1465 | ar->wmi.cmd->pdev_get_tpc_table_cmdid); | ||
1466 | } | ||
1467 | |||
1428 | #endif | 1468 | #endif |
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index ae77a007ae07..523af3f8bb62 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2005-2011 Atheros Communications Inc. | 2 | * Copyright (c) 2005-2011 Atheros Communications Inc. |
3 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. | 3 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. |
4 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
4 | * | 5 | * |
5 | * Permission to use, copy, modify, and/or distribute this software for any | 6 | * Permission to use, copy, modify, and/or distribute this software for any |
6 | * purpose with or without fee is hereby granted, provided that the above | 7 | * purpose with or without fee is hereby granted, provided that the above |
@@ -2484,19 +2485,19 @@ ath10k_wmi_tlv_op_gen_request_stats(struct ath10k *ar, u32 stats_mask) | |||
2484 | } | 2485 | } |
2485 | 2486 | ||
2486 | static struct sk_buff * | 2487 | static struct sk_buff * |
2487 | ath10k_wmi_tlv_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu) | 2488 | ath10k_wmi_tlv_op_gen_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu, |
2489 | dma_addr_t paddr) | ||
2488 | { | 2490 | { |
2489 | struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu); | 2491 | struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu); |
2490 | struct wmi_tlv_mgmt_tx_cmd *cmd; | 2492 | struct wmi_tlv_mgmt_tx_cmd *cmd; |
2491 | struct wmi_tlv *tlv; | ||
2492 | struct ieee80211_hdr *hdr; | 2493 | struct ieee80211_hdr *hdr; |
2494 | struct ath10k_vif *arvif; | ||
2495 | u32 buf_len = msdu->len; | ||
2496 | struct wmi_tlv *tlv; | ||
2493 | struct sk_buff *skb; | 2497 | struct sk_buff *skb; |
2498 | u32 vdev_id; | ||
2494 | void *ptr; | 2499 | void *ptr; |
2495 | int len; | 2500 | int len; |
2496 | u32 buf_len = msdu->len; | ||
2497 | struct ath10k_vif *arvif; | ||
2498 | dma_addr_t mgmt_frame_dma; | ||
2499 | u32 vdev_id; | ||
2500 | 2501 | ||
2501 | if (!cb->vif) | 2502 | if (!cb->vif) |
2502 | return ERR_PTR(-EINVAL); | 2503 | return ERR_PTR(-EINVAL); |
@@ -2537,12 +2538,7 @@ ath10k_wmi_tlv_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu) | |||
2537 | cmd->chanfreq = 0; | 2538 | cmd->chanfreq = 0; |
2538 | cmd->buf_len = __cpu_to_le32(buf_len); | 2539 | cmd->buf_len = __cpu_to_le32(buf_len); |
2539 | cmd->frame_len = __cpu_to_le32(msdu->len); | 2540 | cmd->frame_len = __cpu_to_le32(msdu->len); |
2540 | mgmt_frame_dma = dma_map_single(arvif->ar->dev, msdu->data, | 2541 | cmd->paddr = __cpu_to_le64(paddr); |
2541 | msdu->len, DMA_TO_DEVICE); | ||
2542 | if (!mgmt_frame_dma) | ||
2543 | return ERR_PTR(-ENOMEM); | ||
2544 | |||
2545 | cmd->paddr = __cpu_to_le64(mgmt_frame_dma); | ||
2546 | 2542 | ||
2547 | ptr += sizeof(*tlv); | 2543 | ptr += sizeof(*tlv); |
2548 | ptr += sizeof(*cmd); | 2544 | ptr += sizeof(*cmd); |
@@ -3701,7 +3697,7 @@ static const struct wmi_ops wmi_tlv_ops = { | |||
3701 | .gen_request_stats = ath10k_wmi_tlv_op_gen_request_stats, | 3697 | .gen_request_stats = ath10k_wmi_tlv_op_gen_request_stats, |
3702 | .gen_force_fw_hang = ath10k_wmi_tlv_op_gen_force_fw_hang, | 3698 | .gen_force_fw_hang = ath10k_wmi_tlv_op_gen_force_fw_hang, |
3703 | /* .gen_mgmt_tx = not implemented; HTT is used */ | 3699 | /* .gen_mgmt_tx = not implemented; HTT is used */ |
3704 | .gen_mgmt_tx = ath10k_wmi_tlv_op_gen_mgmt_tx, | 3700 | .gen_mgmt_tx_send = ath10k_wmi_tlv_op_gen_mgmt_tx_send, |
3705 | .gen_dbglog_cfg = ath10k_wmi_tlv_op_gen_dbglog_cfg, | 3701 | .gen_dbglog_cfg = ath10k_wmi_tlv_op_gen_dbglog_cfg, |
3706 | .gen_pktlog_enable = ath10k_wmi_tlv_op_gen_pktlog_enable, | 3702 | .gen_pktlog_enable = ath10k_wmi_tlv_op_gen_pktlog_enable, |
3707 | .gen_pktlog_disable = ath10k_wmi_tlv_op_gen_pktlog_disable, | 3703 | .gen_pktlog_disable = ath10k_wmi_tlv_op_gen_pktlog_disable, |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 58dc2189ba49..9649bb752bbd 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2005-2011 Atheros Communications Inc. | 2 | * Copyright (c) 2005-2011 Atheros Communications Inc. |
3 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. | 3 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. |
4 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
4 | * | 5 | * |
5 | * Permission to use, copy, modify, and/or distribute this software for any | 6 | * Permission to use, copy, modify, and/or distribute this software for any |
6 | * purpose with or without fee is hereby granted, provided that the above | 7 | * purpose with or without fee is hereby granted, provided that the above |
@@ -196,6 +197,7 @@ static struct wmi_cmd_map wmi_cmd_map = { | |||
196 | .mu_cal_start_cmdid = WMI_CMD_UNSUPPORTED, | 197 | .mu_cal_start_cmdid = WMI_CMD_UNSUPPORTED, |
197 | .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED, | 198 | .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED, |
198 | .pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED, | 199 | .pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED, |
200 | .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED, | ||
199 | }; | 201 | }; |
200 | 202 | ||
201 | /* 10.X WMI cmd track */ | 203 | /* 10.X WMI cmd track */ |
@@ -362,6 +364,7 @@ static struct wmi_cmd_map wmi_10x_cmd_map = { | |||
362 | .mu_cal_start_cmdid = WMI_CMD_UNSUPPORTED, | 364 | .mu_cal_start_cmdid = WMI_CMD_UNSUPPORTED, |
363 | .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED, | 365 | .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED, |
364 | .pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED, | 366 | .pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED, |
367 | .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED, | ||
365 | }; | 368 | }; |
366 | 369 | ||
367 | /* 10.2.4 WMI cmd track */ | 370 | /* 10.2.4 WMI cmd track */ |
@@ -528,6 +531,7 @@ static struct wmi_cmd_map wmi_10_2_4_cmd_map = { | |||
528 | .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED, | 531 | .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED, |
529 | .pdev_bss_chan_info_request_cmdid = | 532 | .pdev_bss_chan_info_request_cmdid = |
530 | WMI_10_2_PDEV_BSS_CHAN_INFO_REQUEST_CMDID, | 533 | WMI_10_2_PDEV_BSS_CHAN_INFO_REQUEST_CMDID, |
534 | .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED, | ||
531 | }; | 535 | }; |
532 | 536 | ||
533 | /* 10.4 WMI cmd track */ | 537 | /* 10.4 WMI cmd track */ |
@@ -1480,6 +1484,7 @@ static struct wmi_cmd_map wmi_10_2_cmd_map = { | |||
1480 | .pdev_get_ani_cck_config_cmdid = WMI_CMD_UNSUPPORTED, | 1484 | .pdev_get_ani_cck_config_cmdid = WMI_CMD_UNSUPPORTED, |
1481 | .pdev_get_ani_ofdm_config_cmdid = WMI_CMD_UNSUPPORTED, | 1485 | .pdev_get_ani_ofdm_config_cmdid = WMI_CMD_UNSUPPORTED, |
1482 | .pdev_reserve_ast_entry_cmdid = WMI_CMD_UNSUPPORTED, | 1486 | .pdev_reserve_ast_entry_cmdid = WMI_CMD_UNSUPPORTED, |
1487 | .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED, | ||
1483 | }; | 1488 | }; |
1484 | 1489 | ||
1485 | static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = { | 1490 | static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = { |
@@ -1742,8 +1747,8 @@ int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb, | |||
1742 | cmd_hdr->cmd_id = __cpu_to_le32(cmd); | 1747 | cmd_hdr->cmd_id = __cpu_to_le32(cmd); |
1743 | 1748 | ||
1744 | memset(skb_cb, 0, sizeof(*skb_cb)); | 1749 | memset(skb_cb, 0, sizeof(*skb_cb)); |
1750 | trace_ath10k_wmi_cmd(ar, cmd_id, skb->data, skb->len); | ||
1745 | ret = ath10k_htc_send(&ar->htc, ar->wmi.eid, skb); | 1751 | ret = ath10k_htc_send(&ar->htc, ar->wmi.eid, skb); |
1746 | trace_ath10k_wmi_cmd(ar, cmd_id, skb->data, skb->len, ret); | ||
1747 | 1752 | ||
1748 | if (ret) | 1753 | if (ret) |
1749 | goto err_pull; | 1754 | goto err_pull; |
@@ -4313,19 +4318,11 @@ static void ath10k_tpc_config_disp_tables(struct ath10k *ar, | |||
4313 | } | 4318 | } |
4314 | } | 4319 | } |
4315 | 4320 | ||
4316 | void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb) | 4321 | void ath10k_wmi_tpc_config_get_rate_code(u8 *rate_code, u16 *pream_table, |
4322 | u32 num_tx_chain) | ||
4317 | { | 4323 | { |
4318 | u32 i, j, pream_idx, num_tx_chain; | 4324 | u32 i, j, pream_idx; |
4319 | u8 rate_code[WMI_TPC_RATE_MAX], rate_idx; | 4325 | u8 rate_idx; |
4320 | u16 pream_table[WMI_TPC_PREAM_TABLE_MAX]; | ||
4321 | struct wmi_pdev_tpc_config_event *ev; | ||
4322 | struct ath10k_tpc_stats *tpc_stats; | ||
4323 | |||
4324 | ev = (struct wmi_pdev_tpc_config_event *)skb->data; | ||
4325 | |||
4326 | tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC); | ||
4327 | if (!tpc_stats) | ||
4328 | return; | ||
4329 | 4326 | ||
4330 | /* Create the rate code table based on the chains supported */ | 4327 | /* Create the rate code table based on the chains supported */ |
4331 | rate_idx = 0; | 4328 | rate_idx = 0; |
@@ -4349,8 +4346,6 @@ void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb) | |||
4349 | pream_table[pream_idx] = rate_idx; | 4346 | pream_table[pream_idx] = rate_idx; |
4350 | pream_idx++; | 4347 | pream_idx++; |
4351 | 4348 | ||
4352 | num_tx_chain = __le32_to_cpu(ev->num_tx_chain); | ||
4353 | |||
4354 | /* Fill HT20 rate code */ | 4349 | /* Fill HT20 rate code */ |
4355 | for (i = 0; i < num_tx_chain; i++) { | 4350 | for (i = 0; i < num_tx_chain; i++) { |
4356 | for (j = 0; j < 8; j++) { | 4351 | for (j = 0; j < 8; j++) { |
@@ -4374,7 +4369,7 @@ void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb) | |||
4374 | pream_idx++; | 4369 | pream_idx++; |
4375 | 4370 | ||
4376 | /* Fill VHT20 rate code */ | 4371 | /* Fill VHT20 rate code */ |
4377 | for (i = 0; i < __le32_to_cpu(ev->num_tx_chain); i++) { | 4372 | for (i = 0; i < num_tx_chain; i++) { |
4378 | for (j = 0; j < 10; j++) { | 4373 | for (j = 0; j < 10; j++) { |
4379 | rate_code[rate_idx] = | 4374 | rate_code[rate_idx] = |
4380 | ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_VHT); | 4375 | ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_VHT); |
@@ -4418,6 +4413,26 @@ void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb) | |||
4418 | ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_OFDM); | 4413 | ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_OFDM); |
4419 | 4414 | ||
4420 | pream_table[pream_idx] = ATH10K_TPC_PREAM_TABLE_END; | 4415 | pream_table[pream_idx] = ATH10K_TPC_PREAM_TABLE_END; |
4416 | } | ||
4417 | |||
4418 | void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb) | ||
4419 | { | ||
4420 | u32 num_tx_chain; | ||
4421 | u8 rate_code[WMI_TPC_RATE_MAX]; | ||
4422 | u16 pream_table[WMI_TPC_PREAM_TABLE_MAX]; | ||
4423 | struct wmi_pdev_tpc_config_event *ev; | ||
4424 | struct ath10k_tpc_stats *tpc_stats; | ||
4425 | |||
4426 | ev = (struct wmi_pdev_tpc_config_event *)skb->data; | ||
4427 | |||
4428 | tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC); | ||
4429 | if (!tpc_stats) | ||
4430 | return; | ||
4431 | |||
4432 | num_tx_chain = __le32_to_cpu(ev->num_tx_chain); | ||
4433 | |||
4434 | ath10k_wmi_tpc_config_get_rate_code(rate_code, pream_table, | ||
4435 | num_tx_chain); | ||
4421 | 4436 | ||
4422 | tpc_stats->chan_freq = __le32_to_cpu(ev->chan_freq); | 4437 | tpc_stats->chan_freq = __le32_to_cpu(ev->chan_freq); |
4423 | tpc_stats->phy_mode = __le32_to_cpu(ev->phy_mode); | 4438 | tpc_stats->phy_mode = __le32_to_cpu(ev->phy_mode); |
@@ -4457,6 +4472,246 @@ void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb) | |||
4457 | __le32_to_cpu(ev->rate_max)); | 4472 | __le32_to_cpu(ev->rate_max)); |
4458 | } | 4473 | } |
4459 | 4474 | ||
4475 | static u8 | ||
4476 | ath10k_wmi_tpc_final_get_rate(struct ath10k *ar, | ||
4477 | struct wmi_pdev_tpc_final_table_event *ev, | ||
4478 | u32 rate_idx, u32 num_chains, | ||
4479 | u32 rate_code, u8 type, u32 pream_idx) | ||
4480 | { | ||
4481 | u8 tpc, num_streams, preamble, ch, stm_idx; | ||
4482 | s8 pow_agcdd, pow_agstbc, pow_agtxbf; | ||
4483 | int pream; | ||
4484 | |||
4485 | num_streams = ATH10K_HW_NSS(rate_code); | ||
4486 | preamble = ATH10K_HW_PREAMBLE(rate_code); | ||
4487 | ch = num_chains - 1; | ||
4488 | stm_idx = num_streams - 1; | ||
4489 | pream = -1; | ||
4490 | |||
4491 | if (__le32_to_cpu(ev->chan_freq) <= 2483) { | ||
4492 | switch (pream_idx) { | ||
4493 | case WMI_TPC_PREAM_2GHZ_CCK: | ||
4494 | pream = 0; | ||
4495 | break; | ||
4496 | case WMI_TPC_PREAM_2GHZ_OFDM: | ||
4497 | pream = 1; | ||
4498 | break; | ||
4499 | case WMI_TPC_PREAM_2GHZ_HT20: | ||
4500 | case WMI_TPC_PREAM_2GHZ_VHT20: | ||
4501 | pream = 2; | ||
4502 | break; | ||
4503 | case WMI_TPC_PREAM_2GHZ_HT40: | ||
4504 | case WMI_TPC_PREAM_2GHZ_VHT40: | ||
4505 | pream = 3; | ||
4506 | break; | ||
4507 | case WMI_TPC_PREAM_2GHZ_VHT80: | ||
4508 | pream = 4; | ||
4509 | break; | ||
4510 | default: | ||
4511 | pream = -1; | ||
4512 | break; | ||
4513 | } | ||
4514 | } | ||
4515 | |||
4516 | if (__le32_to_cpu(ev->chan_freq) >= 5180) { | ||
4517 | switch (pream_idx) { | ||
4518 | case WMI_TPC_PREAM_5GHZ_OFDM: | ||
4519 | pream = 0; | ||
4520 | break; | ||
4521 | case WMI_TPC_PREAM_5GHZ_HT20: | ||
4522 | case WMI_TPC_PREAM_5GHZ_VHT20: | ||
4523 | pream = 1; | ||
4524 | break; | ||
4525 | case WMI_TPC_PREAM_5GHZ_HT40: | ||
4526 | case WMI_TPC_PREAM_5GHZ_VHT40: | ||
4527 | pream = 2; | ||
4528 | break; | ||
4529 | case WMI_TPC_PREAM_5GHZ_VHT80: | ||
4530 | pream = 3; | ||
4531 | break; | ||
4532 | case WMI_TPC_PREAM_5GHZ_HTCUP: | ||
4533 | pream = 4; | ||
4534 | break; | ||
4535 | default: | ||
4536 | pream = -1; | ||
4537 | break; | ||
4538 | } | ||
4539 | } | ||
4540 | |||
4541 | if (pream == 4) | ||
4542 | tpc = min_t(u8, ev->rates_array[rate_idx], | ||
4543 | ev->max_reg_allow_pow[ch]); | ||
4544 | else | ||
4545 | tpc = min_t(u8, min_t(u8, ev->rates_array[rate_idx], | ||
4546 | ev->max_reg_allow_pow[ch]), | ||
4547 | ev->ctl_power_table[0][pream][stm_idx]); | ||
4548 | |||
4549 | if (__le32_to_cpu(ev->num_tx_chain) <= 1) | ||
4550 | goto out; | ||
4551 | |||
4552 | if (preamble == WMI_RATE_PREAMBLE_CCK) | ||
4553 | goto out; | ||
4554 | |||
4555 | if (num_chains <= num_streams) | ||
4556 | goto out; | ||
4557 | |||
4558 | switch (type) { | ||
4559 | case WMI_TPC_TABLE_TYPE_STBC: | ||
4560 | pow_agstbc = ev->max_reg_allow_pow_agstbc[ch - 1][stm_idx]; | ||
4561 | if (pream == 4) | ||
4562 | tpc = min_t(u8, tpc, pow_agstbc); | ||
4563 | else | ||
4564 | tpc = min_t(u8, min_t(u8, tpc, pow_agstbc), | ||
4565 | ev->ctl_power_table[0][pream][stm_idx]); | ||
4566 | break; | ||
4567 | case WMI_TPC_TABLE_TYPE_TXBF: | ||
4568 | pow_agtxbf = ev->max_reg_allow_pow_agtxbf[ch - 1][stm_idx]; | ||
4569 | if (pream == 4) | ||
4570 | tpc = min_t(u8, tpc, pow_agtxbf); | ||
4571 | else | ||
4572 | tpc = min_t(u8, min_t(u8, tpc, pow_agtxbf), | ||
4573 | ev->ctl_power_table[1][pream][stm_idx]); | ||
4574 | break; | ||
4575 | case WMI_TPC_TABLE_TYPE_CDD: | ||
4576 | pow_agcdd = ev->max_reg_allow_pow_agcdd[ch - 1][stm_idx]; | ||
4577 | if (pream == 4) | ||
4578 | tpc = min_t(u8, tpc, pow_agcdd); | ||
4579 | else | ||
4580 | tpc = min_t(u8, min_t(u8, tpc, pow_agcdd), | ||
4581 | ev->ctl_power_table[0][pream][stm_idx]); | ||
4582 | break; | ||
4583 | default: | ||
4584 | ath10k_warn(ar, "unknown wmi tpc final table type: %d\n", type); | ||
4585 | tpc = 0; | ||
4586 | break; | ||
4587 | } | ||
4588 | |||
4589 | out: | ||
4590 | return tpc; | ||
4591 | } | ||
4592 | |||
4593 | static void | ||
4594 | ath10k_wmi_tpc_stats_final_disp_tables(struct ath10k *ar, | ||
4595 | struct wmi_pdev_tpc_final_table_event *ev, | ||
4596 | struct ath10k_tpc_stats_final *tpc_stats, | ||
4597 | u8 *rate_code, u16 *pream_table, u8 type) | ||
4598 | { | ||
4599 | u32 i, j, pream_idx, flags; | ||
4600 | u8 tpc[WMI_TPC_TX_N_CHAIN]; | ||
4601 | char tpc_value[WMI_TPC_TX_N_CHAIN * WMI_TPC_BUF_SIZE]; | ||
4602 | char buff[WMI_TPC_BUF_SIZE]; | ||
4603 | |||
4604 | flags = __le32_to_cpu(ev->flags); | ||
4605 | |||
4606 | switch (type) { | ||
4607 | case WMI_TPC_TABLE_TYPE_CDD: | ||
4608 | if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_CDD)) { | ||
4609 | ath10k_dbg(ar, ATH10K_DBG_WMI, "CDD not supported\n"); | ||
4610 | tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG; | ||
4611 | return; | ||
4612 | } | ||
4613 | break; | ||
4614 | case WMI_TPC_TABLE_TYPE_STBC: | ||
4615 | if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_STBC)) { | ||
4616 | ath10k_dbg(ar, ATH10K_DBG_WMI, "STBC not supported\n"); | ||
4617 | tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG; | ||
4618 | return; | ||
4619 | } | ||
4620 | break; | ||
4621 | case WMI_TPC_TABLE_TYPE_TXBF: | ||
4622 | if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_TXBF)) { | ||
4623 | ath10k_dbg(ar, ATH10K_DBG_WMI, "TXBF not supported\n"); | ||
4624 | tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG; | ||
4625 | return; | ||
4626 | } | ||
4627 | break; | ||
4628 | default: | ||
4629 | ath10k_dbg(ar, ATH10K_DBG_WMI, | ||
4630 | "invalid table type in wmi tpc event: %d\n", type); | ||
4631 | return; | ||
4632 | } | ||
4633 | |||
4634 | pream_idx = 0; | ||
4635 | for (i = 0; i < __le32_to_cpu(ev->rate_max); i++) { | ||
4636 | memset(tpc_value, 0, sizeof(tpc_value)); | ||
4637 | memset(buff, 0, sizeof(buff)); | ||
4638 | if (i == pream_table[pream_idx]) | ||
4639 | pream_idx++; | ||
4640 | |||
4641 | for (j = 0; j < WMI_TPC_TX_N_CHAIN; j++) { | ||
4642 | if (j >= __le32_to_cpu(ev->num_tx_chain)) | ||
4643 | break; | ||
4644 | |||
4645 | tpc[j] = ath10k_wmi_tpc_final_get_rate(ar, ev, i, j + 1, | ||
4646 | rate_code[i], | ||
4647 | type, pream_idx); | ||
4648 | snprintf(buff, sizeof(buff), "%8d ", tpc[j]); | ||
4649 | strncat(tpc_value, buff, strlen(buff)); | ||
4650 | } | ||
4651 | tpc_stats->tpc_table_final[type].pream_idx[i] = pream_idx; | ||
4652 | tpc_stats->tpc_table_final[type].rate_code[i] = rate_code[i]; | ||
4653 | memcpy(tpc_stats->tpc_table_final[type].tpc_value[i], | ||
4654 | tpc_value, sizeof(tpc_value)); | ||
4655 | } | ||
4656 | } | ||
4657 | |||
4658 | void ath10k_wmi_event_tpc_final_table(struct ath10k *ar, struct sk_buff *skb) | ||
4659 | { | ||
4660 | u32 num_tx_chain; | ||
4661 | u8 rate_code[WMI_TPC_FINAL_RATE_MAX]; | ||
4662 | u16 pream_table[WMI_TPC_PREAM_TABLE_MAX]; | ||
4663 | struct wmi_pdev_tpc_final_table_event *ev; | ||
4664 | struct ath10k_tpc_stats_final *tpc_stats; | ||
4665 | |||
4666 | ev = (struct wmi_pdev_tpc_final_table_event *)skb->data; | ||
4667 | |||
4668 | tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC); | ||
4669 | if (!tpc_stats) | ||
4670 | return; | ||
4671 | |||
4672 | num_tx_chain = __le32_to_cpu(ev->num_tx_chain); | ||
4673 | |||
4674 | ath10k_wmi_tpc_config_get_rate_code(rate_code, pream_table, | ||
4675 | num_tx_chain); | ||
4676 | |||
4677 | tpc_stats->chan_freq = __le32_to_cpu(ev->chan_freq); | ||
4678 | tpc_stats->phy_mode = __le32_to_cpu(ev->phy_mode); | ||
4679 | tpc_stats->ctl = __le32_to_cpu(ev->ctl); | ||
4680 | tpc_stats->reg_domain = __le32_to_cpu(ev->reg_domain); | ||
4681 | tpc_stats->twice_antenna_gain = a_sle32_to_cpu(ev->twice_antenna_gain); | ||
4682 | tpc_stats->twice_antenna_reduction = | ||
4683 | __le32_to_cpu(ev->twice_antenna_reduction); | ||
4684 | tpc_stats->power_limit = __le32_to_cpu(ev->power_limit); | ||
4685 | tpc_stats->twice_max_rd_power = __le32_to_cpu(ev->twice_max_rd_power); | ||
4686 | tpc_stats->num_tx_chain = __le32_to_cpu(ev->num_tx_chain); | ||
4687 | tpc_stats->rate_max = __le32_to_cpu(ev->rate_max); | ||
4688 | |||
4689 | ath10k_wmi_tpc_stats_final_disp_tables(ar, ev, tpc_stats, | ||
4690 | rate_code, pream_table, | ||
4691 | WMI_TPC_TABLE_TYPE_CDD); | ||
4692 | ath10k_wmi_tpc_stats_final_disp_tables(ar, ev, tpc_stats, | ||
4693 | rate_code, pream_table, | ||
4694 | WMI_TPC_TABLE_TYPE_STBC); | ||
4695 | ath10k_wmi_tpc_stats_final_disp_tables(ar, ev, tpc_stats, | ||
4696 | rate_code, pream_table, | ||
4697 | WMI_TPC_TABLE_TYPE_TXBF); | ||
4698 | |||
4699 | ath10k_debug_tpc_stats_final_process(ar, tpc_stats); | ||
4700 | |||
4701 | ath10k_dbg(ar, ATH10K_DBG_WMI, | ||
4702 | "wmi event tpc final table channel %d mode %d ctl %d regd %d gain %d %d limit %d max_power %d tx_chanins %d rates %d\n", | ||
4703 | __le32_to_cpu(ev->chan_freq), | ||
4704 | __le32_to_cpu(ev->phy_mode), | ||
4705 | __le32_to_cpu(ev->ctl), | ||
4706 | __le32_to_cpu(ev->reg_domain), | ||
4707 | a_sle32_to_cpu(ev->twice_antenna_gain), | ||
4708 | __le32_to_cpu(ev->twice_antenna_reduction), | ||
4709 | __le32_to_cpu(ev->power_limit), | ||
4710 | __le32_to_cpu(ev->twice_max_rd_power) / 2, | ||
4711 | __le32_to_cpu(ev->num_tx_chain), | ||
4712 | __le32_to_cpu(ev->rate_max)); | ||
4713 | } | ||
4714 | |||
4460 | static void | 4715 | static void |
4461 | ath10k_wmi_handle_tdls_peer_event(struct ath10k *ar, struct sk_buff *skb) | 4716 | ath10k_wmi_handle_tdls_peer_event(struct ath10k *ar, struct sk_buff *skb) |
4462 | { | 4717 | { |
@@ -5549,6 +5804,9 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb) | |||
5549 | case WMI_10_4_TDLS_PEER_EVENTID: | 5804 | case WMI_10_4_TDLS_PEER_EVENTID: |
5550 | ath10k_wmi_handle_tdls_peer_event(ar, skb); | 5805 | ath10k_wmi_handle_tdls_peer_event(ar, skb); |
5551 | break; | 5806 | break; |
5807 | case WMI_10_4_PDEV_TPC_TABLE_EVENTID: | ||
5808 | ath10k_wmi_event_tpc_final_table(ar, skb); | ||
5809 | break; | ||
5552 | default: | 5810 | default: |
5553 | ath10k_warn(ar, "Unknown eventid: %d\n", id); | 5811 | ath10k_warn(ar, "Unknown eventid: %d\n", id); |
5554 | break; | 5812 | break; |
@@ -7990,6 +8248,24 @@ static u32 ath10k_wmi_prepare_peer_qos(u8 uapsd_queues, u8 sp) | |||
7990 | } | 8248 | } |
7991 | 8249 | ||
7992 | static struct sk_buff * | 8250 | static struct sk_buff * |
8251 | ath10k_wmi_10_4_op_gen_pdev_get_tpc_table_cmdid(struct ath10k *ar, u32 param) | ||
8252 | { | ||
8253 | struct wmi_pdev_get_tpc_table_cmd *cmd; | ||
8254 | struct sk_buff *skb; | ||
8255 | |||
8256 | skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); | ||
8257 | if (!skb) | ||
8258 | return ERR_PTR(-ENOMEM); | ||
8259 | |||
8260 | cmd = (struct wmi_pdev_get_tpc_table_cmd *)skb->data; | ||
8261 | cmd->param = __cpu_to_le32(param); | ||
8262 | |||
8263 | ath10k_dbg(ar, ATH10K_DBG_WMI, | ||
8264 | "wmi pdev get tpc table param:%d\n", param); | ||
8265 | return skb; | ||
8266 | } | ||
8267 | |||
8268 | static struct sk_buff * | ||
7993 | ath10k_wmi_10_4_gen_tdls_peer_update(struct ath10k *ar, | 8269 | ath10k_wmi_10_4_gen_tdls_peer_update(struct ath10k *ar, |
7994 | const struct wmi_tdls_peer_update_cmd_arg *arg, | 8270 | const struct wmi_tdls_peer_update_cmd_arg *arg, |
7995 | const struct wmi_tdls_peer_capab_arg *cap, | 8271 | const struct wmi_tdls_peer_capab_arg *cap, |
@@ -8430,6 +8706,8 @@ static const struct wmi_ops wmi_10_4_ops = { | |||
8430 | .ext_resource_config = ath10k_wmi_10_4_ext_resource_config, | 8706 | .ext_resource_config = ath10k_wmi_10_4_ext_resource_config, |
8431 | .gen_update_fw_tdls_state = ath10k_wmi_10_4_gen_update_fw_tdls_state, | 8707 | .gen_update_fw_tdls_state = ath10k_wmi_10_4_gen_update_fw_tdls_state, |
8432 | .gen_tdls_peer_update = ath10k_wmi_10_4_gen_tdls_peer_update, | 8708 | .gen_tdls_peer_update = ath10k_wmi_10_4_gen_tdls_peer_update, |
8709 | .gen_pdev_get_tpc_table_cmdid = | ||
8710 | ath10k_wmi_10_4_op_gen_pdev_get_tpc_table_cmdid, | ||
8433 | 8711 | ||
8434 | /* shared with 10.2 */ | 8712 | /* shared with 10.2 */ |
8435 | .pull_echo_ev = ath10k_wmi_op_pull_echo_ev, | 8713 | .pull_echo_ev = ath10k_wmi_op_pull_echo_ev, |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index c7b30ed9015d..c8fc45d8090e 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2005-2011 Atheros Communications Inc. | 2 | * Copyright (c) 2005-2011 Atheros Communications Inc. |
3 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. | 3 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. |
4 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
4 | * | 5 | * |
5 | * Permission to use, copy, modify, and/or distribute this software for any | 6 | * Permission to use, copy, modify, and/or distribute this software for any |
6 | * purpose with or without fee is hereby granted, provided that the above | 7 | * purpose with or without fee is hereby granted, provided that the above |
@@ -197,6 +198,9 @@ enum wmi_service { | |||
197 | WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY, | 198 | WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY, |
198 | WMI_SERVICE_MGMT_TX_WMI, | 199 | WMI_SERVICE_MGMT_TX_WMI, |
199 | WMI_SERVICE_TDLS_WIDER_BANDWIDTH, | 200 | WMI_SERVICE_TDLS_WIDER_BANDWIDTH, |
201 | WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS, | ||
202 | WMI_SERVICE_HOST_DFS_CHECK_SUPPORT, | ||
203 | WMI_SERVICE_TPC_STATS_FINAL, | ||
200 | 204 | ||
201 | /* keep last */ | 205 | /* keep last */ |
202 | WMI_SERVICE_MAX, | 206 | WMI_SERVICE_MAX, |
@@ -339,6 +343,9 @@ enum wmi_10_4_service { | |||
339 | WMI_10_4_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE, | 343 | WMI_10_4_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE, |
340 | WMI_10_4_SERVICE_TDLS_EXPLICIT_MODE_ONLY, | 344 | WMI_10_4_SERVICE_TDLS_EXPLICIT_MODE_ONLY, |
341 | WMI_10_4_SERVICE_TDLS_WIDER_BANDWIDTH, | 345 | WMI_10_4_SERVICE_TDLS_WIDER_BANDWIDTH, |
346 | WMI_10_4_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS, | ||
347 | WMI_10_4_SERVICE_HOST_DFS_CHECK_SUPPORT, | ||
348 | WMI_10_4_SERVICE_TPC_STATS_FINAL, | ||
342 | }; | 349 | }; |
343 | 350 | ||
344 | static inline char *wmi_service_name(int service_id) | 351 | static inline char *wmi_service_name(int service_id) |
@@ -448,6 +455,9 @@ static inline char *wmi_service_name(int service_id) | |||
448 | SVCSTR(WMI_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE); | 455 | SVCSTR(WMI_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE); |
449 | SVCSTR(WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY); | 456 | SVCSTR(WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY); |
450 | SVCSTR(WMI_SERVICE_TDLS_WIDER_BANDWIDTH); | 457 | SVCSTR(WMI_SERVICE_TDLS_WIDER_BANDWIDTH); |
458 | SVCSTR(WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS); | ||
459 | SVCSTR(WMI_SERVICE_HOST_DFS_CHECK_SUPPORT); | ||
460 | SVCSTR(WMI_SERVICE_TPC_STATS_FINAL); | ||
451 | default: | 461 | default: |
452 | return NULL; | 462 | return NULL; |
453 | } | 463 | } |
@@ -746,6 +756,12 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out, | |||
746 | WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY, len); | 756 | WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY, len); |
747 | SVCMAP(WMI_10_4_SERVICE_TDLS_WIDER_BANDWIDTH, | 757 | SVCMAP(WMI_10_4_SERVICE_TDLS_WIDER_BANDWIDTH, |
748 | WMI_SERVICE_TDLS_WIDER_BANDWIDTH, len); | 758 | WMI_SERVICE_TDLS_WIDER_BANDWIDTH, len); |
759 | SVCMAP(WMI_10_4_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS, | ||
760 | WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS, len); | ||
761 | SVCMAP(WMI_10_4_SERVICE_HOST_DFS_CHECK_SUPPORT, | ||
762 | WMI_SERVICE_HOST_DFS_CHECK_SUPPORT, len); | ||
763 | SVCMAP(WMI_10_4_SERVICE_TPC_STATS_FINAL, | ||
764 | WMI_SERVICE_TPC_STATS_FINAL, len); | ||
749 | } | 765 | } |
750 | 766 | ||
751 | #undef SVCMAP | 767 | #undef SVCMAP |
@@ -3993,10 +4009,12 @@ struct wmi_pdev_get_tpc_config_cmd { | |||
3993 | 4009 | ||
3994 | #define WMI_TPC_CONFIG_PARAM 1 | 4010 | #define WMI_TPC_CONFIG_PARAM 1 |
3995 | #define WMI_TPC_RATE_MAX 160 | 4011 | #define WMI_TPC_RATE_MAX 160 |
4012 | #define WMI_TPC_FINAL_RATE_MAX 240 | ||
3996 | #define WMI_TPC_TX_N_CHAIN 4 | 4013 | #define WMI_TPC_TX_N_CHAIN 4 |
3997 | #define WMI_TPC_PREAM_TABLE_MAX 10 | 4014 | #define WMI_TPC_PREAM_TABLE_MAX 10 |
3998 | #define WMI_TPC_FLAG 3 | 4015 | #define WMI_TPC_FLAG 3 |
3999 | #define WMI_TPC_BUF_SIZE 10 | 4016 | #define WMI_TPC_BUF_SIZE 10 |
4017 | #define WMI_TPC_BEAMFORMING 2 | ||
4000 | 4018 | ||
4001 | enum wmi_tpc_table_type { | 4019 | enum wmi_tpc_table_type { |
4002 | WMI_TPC_TABLE_TYPE_CDD = 0, | 4020 | WMI_TPC_TABLE_TYPE_CDD = 0, |
@@ -4039,6 +4057,51 @@ enum wmi_tp_scale { | |||
4039 | WMI_TP_SCALE_SIZE = 5, /* max num of enum */ | 4057 | WMI_TP_SCALE_SIZE = 5, /* max num of enum */ |
4040 | }; | 4058 | }; |
4041 | 4059 | ||
4060 | struct wmi_pdev_tpc_final_table_event { | ||
4061 | __le32 reg_domain; | ||
4062 | __le32 chan_freq; | ||
4063 | __le32 phy_mode; | ||
4064 | __le32 twice_antenna_reduction; | ||
4065 | __le32 twice_max_rd_power; | ||
4066 | a_sle32 twice_antenna_gain; | ||
4067 | __le32 power_limit; | ||
4068 | __le32 rate_max; | ||
4069 | __le32 num_tx_chain; | ||
4070 | __le32 ctl; | ||
4071 | __le32 flags; | ||
4072 | s8 max_reg_allow_pow[WMI_TPC_TX_N_CHAIN]; | ||
4073 | s8 max_reg_allow_pow_agcdd[WMI_TPC_TX_N_CHAIN][WMI_TPC_TX_N_CHAIN]; | ||
4074 | s8 max_reg_allow_pow_agstbc[WMI_TPC_TX_N_CHAIN][WMI_TPC_TX_N_CHAIN]; | ||
4075 | s8 max_reg_allow_pow_agtxbf[WMI_TPC_TX_N_CHAIN][WMI_TPC_TX_N_CHAIN]; | ||
4076 | u8 rates_array[WMI_TPC_FINAL_RATE_MAX]; | ||
4077 | u8 ctl_power_table[WMI_TPC_BEAMFORMING][WMI_TPC_TX_N_CHAIN] | ||
4078 | [WMI_TPC_TX_N_CHAIN]; | ||
4079 | } __packed; | ||
4080 | |||
4081 | struct wmi_pdev_get_tpc_table_cmd { | ||
4082 | __le32 param; | ||
4083 | } __packed; | ||
4084 | |||
4085 | enum wmi_tpc_pream_2ghz { | ||
4086 | WMI_TPC_PREAM_2GHZ_CCK = 0, | ||
4087 | WMI_TPC_PREAM_2GHZ_OFDM, | ||
4088 | WMI_TPC_PREAM_2GHZ_HT20, | ||
4089 | WMI_TPC_PREAM_2GHZ_HT40, | ||
4090 | WMI_TPC_PREAM_2GHZ_VHT20, | ||
4091 | WMI_TPC_PREAM_2GHZ_VHT40, | ||
4092 | WMI_TPC_PREAM_2GHZ_VHT80, | ||
4093 | }; | ||
4094 | |||
4095 | enum wmi_tpc_pream_5ghz { | ||
4096 | WMI_TPC_PREAM_5GHZ_OFDM = 1, | ||
4097 | WMI_TPC_PREAM_5GHZ_HT20, | ||
4098 | WMI_TPC_PREAM_5GHZ_HT40, | ||
4099 | WMI_TPC_PREAM_5GHZ_VHT20, | ||
4100 | WMI_TPC_PREAM_5GHZ_VHT40, | ||
4101 | WMI_TPC_PREAM_5GHZ_VHT80, | ||
4102 | WMI_TPC_PREAM_5GHZ_HTCUP, | ||
4103 | }; | ||
4104 | |||
4042 | struct wmi_pdev_chanlist_update_event { | 4105 | struct wmi_pdev_chanlist_update_event { |
4043 | /* number of channels */ | 4106 | /* number of channels */ |
4044 | __le32 num_chan; | 4107 | __le32 num_chan; |
@@ -6979,5 +7042,8 @@ void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar, | |||
6979 | int ath10k_wmi_op_get_vdev_subtype(struct ath10k *ar, | 7042 | int ath10k_wmi_op_get_vdev_subtype(struct ath10k *ar, |
6980 | enum wmi_vdev_subtype subtype); | 7043 | enum wmi_vdev_subtype subtype); |
6981 | int ath10k_wmi_barrier(struct ath10k *ar); | 7044 | int ath10k_wmi_barrier(struct ath10k *ar); |
7045 | void ath10k_wmi_tpc_config_get_rate_code(u8 *rate_code, u16 *pream_table, | ||
7046 | u32 num_tx_chain); | ||
7047 | void ath10k_wmi_event_tpc_final_table(struct ath10k *ar, struct sk_buff *skb); | ||
6982 | 7048 | ||
6983 | #endif /* _WMI_H_ */ | 7049 | #endif /* _WMI_H_ */ |
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index beda11ce34a7..147947f632f7 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c | |||
@@ -327,8 +327,6 @@ ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
327 | 327 | ||
328 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | 328 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); |
329 | 329 | ||
330 | tq = &ah->ah_txq[queue]; | ||
331 | |||
332 | /* Skip if queue inactive or if we are on AR5210 | 330 | /* Skip if queue inactive or if we are on AR5210 |
333 | * that doesn't have QCU/DCU */ | 331 | * that doesn't have QCU/DCU */ |
334 | if ((ah->ah_version == AR5K_AR5210) || | 332 | if ((ah->ah_version == AR5K_AR5210) || |
diff --git a/drivers/net/wireless/ath/ath9k/common-init.c b/drivers/net/wireless/ath/ath9k/common-init.c index 8b4f7fdabf58..82de0fadbc95 100644 --- a/drivers/net/wireless/ath/ath9k/common-init.c +++ b/drivers/net/wireless/ath/ath9k/common-init.c | |||
@@ -88,7 +88,7 @@ static const struct ieee80211_channel ath9k_5ghz_chantable[] = { | |||
88 | CHAN5G(5825, 37), /* Channel 165 */ | 88 | CHAN5G(5825, 37), /* Channel 165 */ |
89 | }; | 89 | }; |
90 | 90 | ||
91 | /* Atheros hardware rate code addition for short premble */ | 91 | /* Atheros hardware rate code addition for short preamble */ |
92 | #define SHPCHECK(__hw_rate, __flags) \ | 92 | #define SHPCHECK(__hw_rate, __flags) \ |
93 | ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04 ) : 0) | 93 | ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04 ) : 0) |
94 | 94 | ||
diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c index 5e77fe1f5b0d..a41bcbda1d9e 100644 --- a/drivers/net/wireless/ath/ath9k/common-spectral.c +++ b/drivers/net/wireless/ath/ath9k/common-spectral.c | |||
@@ -479,14 +479,16 @@ ath_cmn_is_fft_buf_full(struct ath_spec_scan_priv *spec_priv) | |||
479 | { | 479 | { |
480 | int i = 0; | 480 | int i = 0; |
481 | int ret = 0; | 481 | int ret = 0; |
482 | struct rchan_buf *buf; | ||
482 | struct rchan *rc = spec_priv->rfs_chan_spec_scan; | 483 | struct rchan *rc = spec_priv->rfs_chan_spec_scan; |
483 | 484 | ||
484 | for_each_online_cpu(i) | 485 | for_each_possible_cpu(i) { |
485 | ret += relay_buf_full(*per_cpu_ptr(rc->buf, i)); | 486 | if ((buf = *per_cpu_ptr(rc->buf, i))) { |
486 | 487 | ret += relay_buf_full(buf); | |
487 | i = num_online_cpus(); | 488 | } |
489 | } | ||
488 | 490 | ||
489 | if (ret == i) | 491 | if (ret) |
490 | return 1; | 492 | return 1; |
491 | else | 493 | else |
492 | return 0; | 494 | return 0; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index cd0f023ccf77..6b37036b2d36 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -184,7 +184,8 @@ u16 ath9k_hw_computetxtime(struct ath_hw *ah, | |||
184 | break; | 184 | break; |
185 | case WLAN_RC_PHY_OFDM: | 185 | case WLAN_RC_PHY_OFDM: |
186 | if (ah->curchan && IS_CHAN_QUARTER_RATE(ah->curchan)) { | 186 | if (ah->curchan && IS_CHAN_QUARTER_RATE(ah->curchan)) { |
187 | bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000; | 187 | bitsPerSymbol = |
188 | ((kbps >> 2) * OFDM_SYMBOL_TIME_QUARTER) / 1000; | ||
188 | numBits = OFDM_PLCP_BITS + (frameLen << 3); | 189 | numBits = OFDM_PLCP_BITS + (frameLen << 3); |
189 | numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol); | 190 | numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol); |
190 | txTime = OFDM_SIFS_TIME_QUARTER | 191 | txTime = OFDM_SIFS_TIME_QUARTER |
@@ -192,7 +193,8 @@ u16 ath9k_hw_computetxtime(struct ath_hw *ah, | |||
192 | + (numSymbols * OFDM_SYMBOL_TIME_QUARTER); | 193 | + (numSymbols * OFDM_SYMBOL_TIME_QUARTER); |
193 | } else if (ah->curchan && | 194 | } else if (ah->curchan && |
194 | IS_CHAN_HALF_RATE(ah->curchan)) { | 195 | IS_CHAN_HALF_RATE(ah->curchan)) { |
195 | bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_HALF) / 1000; | 196 | bitsPerSymbol = |
197 | ((kbps >> 1) * OFDM_SYMBOL_TIME_HALF) / 1000; | ||
196 | numBits = OFDM_PLCP_BITS + (frameLen << 3); | 198 | numBits = OFDM_PLCP_BITS + (frameLen << 3); |
197 | numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol); | 199 | numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol); |
198 | txTime = OFDM_SIFS_TIME_HALF + | 200 | txTime = OFDM_SIFS_TIME_HALF + |
@@ -1036,7 +1038,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) | |||
1036 | int acktimeout, ctstimeout, ack_offset = 0; | 1038 | int acktimeout, ctstimeout, ack_offset = 0; |
1037 | int slottime; | 1039 | int slottime; |
1038 | int sifstime; | 1040 | int sifstime; |
1039 | int rx_lat = 0, tx_lat = 0, eifs = 0; | 1041 | int rx_lat = 0, tx_lat = 0, eifs = 0, ack_shift = 0; |
1040 | u32 reg; | 1042 | u32 reg; |
1041 | 1043 | ||
1042 | ath_dbg(ath9k_hw_common(ah), RESET, "ah->misc_mode 0x%x\n", | 1044 | ath_dbg(ath9k_hw_common(ah), RESET, "ah->misc_mode 0x%x\n", |
@@ -1068,6 +1070,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) | |||
1068 | 1070 | ||
1069 | sifstime = 32; | 1071 | sifstime = 32; |
1070 | ack_offset = 16; | 1072 | ack_offset = 16; |
1073 | ack_shift = 3; | ||
1071 | slottime = 13; | 1074 | slottime = 13; |
1072 | } else if (IS_CHAN_QUARTER_RATE(chan)) { | 1075 | } else if (IS_CHAN_QUARTER_RATE(chan)) { |
1073 | eifs = 340; | 1076 | eifs = 340; |
@@ -1078,6 +1081,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) | |||
1078 | 1081 | ||
1079 | sifstime = 64; | 1082 | sifstime = 64; |
1080 | ack_offset = 32; | 1083 | ack_offset = 32; |
1084 | ack_shift = 1; | ||
1081 | slottime = 21; | 1085 | slottime = 21; |
1082 | } else { | 1086 | } else { |
1083 | if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) { | 1087 | if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) { |
@@ -1134,6 +1138,10 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) | |||
1134 | SM(tx_lat, AR_USEC_TX_LAT), | 1138 | SM(tx_lat, AR_USEC_TX_LAT), |
1135 | AR_USEC_TX_LAT | AR_USEC_RX_LAT | AR_USEC_USEC); | 1139 | AR_USEC_TX_LAT | AR_USEC_RX_LAT | AR_USEC_USEC); |
1136 | 1140 | ||
1141 | if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) | ||
1142 | REG_RMW(ah, AR_TXSIFS, | ||
1143 | sifstime | SM(ack_shift, AR_TXSIFS_ACK_SHIFT), | ||
1144 | (AR_TXSIFS_TIME | AR_TXSIFS_ACK_SHIFT)); | ||
1137 | } | 1145 | } |
1138 | EXPORT_SYMBOL(ath9k_hw_init_global_settings); | 1146 | EXPORT_SYMBOL(ath9k_hw_init_global_settings); |
1139 | 1147 | ||
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 396bf05c6bf6..d8b041f48ca8 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -2892,6 +2892,8 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) | |||
2892 | struct ath_txq *txq; | 2892 | struct ath_txq *txq; |
2893 | int tidno; | 2893 | int tidno; |
2894 | 2894 | ||
2895 | rcu_read_lock(); | ||
2896 | |||
2895 | for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) { | 2897 | for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) { |
2896 | tid = ath_node_to_tid(an, tidno); | 2898 | tid = ath_node_to_tid(an, tidno); |
2897 | txq = tid->txq; | 2899 | txq = tid->txq; |
@@ -2909,6 +2911,8 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) | |||
2909 | if (!an->sta) | 2911 | if (!an->sta) |
2910 | break; /* just one multicast ath_atx_tid */ | 2912 | break; /* just one multicast ath_atx_tid */ |
2911 | } | 2913 | } |
2914 | |||
2915 | rcu_read_unlock(); | ||
2912 | } | 2916 | } |
2913 | 2917 | ||
2914 | #ifdef CONFIG_ATH9K_TX99 | 2918 | #ifdef CONFIG_ATH9K_TX99 |
diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.c b/drivers/net/wireless/ath/dfs_pattern_detector.c index 4100ffd42a43..448b83eea810 100644 --- a/drivers/net/wireless/ath/dfs_pattern_detector.c +++ b/drivers/net/wireless/ath/dfs_pattern_detector.c | |||
@@ -115,7 +115,7 @@ static const struct radar_detector_specs jp_radar_ref_types[] = { | |||
115 | JP_PATTERN(4, 0, 5, 150, 230, 1, 23, 50, false), | 115 | JP_PATTERN(4, 0, 5, 150, 230, 1, 23, 50, false), |
116 | JP_PATTERN(5, 6, 10, 200, 500, 1, 16, 50, false), | 116 | JP_PATTERN(5, 6, 10, 200, 500, 1, 16, 50, false), |
117 | JP_PATTERN(6, 11, 20, 200, 500, 1, 12, 50, false), | 117 | JP_PATTERN(6, 11, 20, 200, 500, 1, 12, 50, false), |
118 | JP_PATTERN(7, 50, 100, 1000, 2000, 1, 3, 50, false), | 118 | JP_PATTERN(7, 50, 100, 1000, 2000, 1, 3, 50, true), |
119 | JP_PATTERN(5, 0, 1, 333, 333, 1, 9, 50, false), | 119 | JP_PATTERN(5, 0, 1, 333, 333, 1, 9, 50, false), |
120 | }; | 120 | }; |
121 | 121 | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index a3f1f7d042a4..7d5ecaf02288 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.c +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c | |||
@@ -376,7 +376,7 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) | |||
376 | spin_lock_irqsave(&ch->lock, flags); | 376 | spin_lock_irqsave(&ch->lock, flags); |
377 | ctl = ch->tail_blk_ctl; | 377 | ctl = ch->tail_blk_ctl; |
378 | do { | 378 | do { |
379 | if (ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK) | 379 | if (ctl->desc->ctrl & WCN36xx_DXE_CTRL_VLD) |
380 | break; | 380 | break; |
381 | if (ctl->skb) { | 381 | if (ctl->skb) { |
382 | dma_unmap_single(wcn->dev, ctl->desc->src_addr_l, | 382 | dma_unmap_single(wcn->dev, ctl->desc->src_addr_l, |
@@ -397,7 +397,7 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) | |||
397 | } | 397 | } |
398 | ctl = ctl->next; | 398 | ctl = ctl->next; |
399 | } while (ctl != ch->head_blk_ctl && | 399 | } while (ctl != ch->head_blk_ctl && |
400 | !(ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)); | 400 | !(ctl->desc->ctrl & WCN36xx_DXE_CTRL_VLD)); |
401 | 401 | ||
402 | ch->tail_blk_ctl = ctl; | 402 | ch->tail_blk_ctl = ctl; |
403 | spin_unlock_irqrestore(&ch->lock, flags); | 403 | spin_unlock_irqrestore(&ch->lock, flags); |
@@ -415,14 +415,31 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) | |||
415 | WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_H, | 415 | WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_H, |
416 | &int_reason); | 416 | &int_reason); |
417 | 417 | ||
418 | /* TODO: Check int_reason */ | ||
419 | |||
420 | wcn36xx_dxe_write_register(wcn, | 418 | wcn36xx_dxe_write_register(wcn, |
421 | WCN36XX_DXE_0_INT_CLR, | 419 | WCN36XX_DXE_0_INT_CLR, |
422 | WCN36XX_INT_MASK_CHAN_TX_H); | 420 | WCN36XX_INT_MASK_CHAN_TX_H); |
423 | 421 | ||
424 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_ED_CLR, | 422 | if (int_reason & WCN36XX_CH_STAT_INT_ERR_MASK ) { |
425 | WCN36XX_INT_MASK_CHAN_TX_H); | 423 | wcn36xx_dxe_write_register(wcn, |
424 | WCN36XX_DXE_0_INT_ERR_CLR, | ||
425 | WCN36XX_INT_MASK_CHAN_TX_H); | ||
426 | |||
427 | wcn36xx_err("DXE IRQ reported error: 0x%x in high TX channel\n", | ||
428 | int_src); | ||
429 | } | ||
430 | |||
431 | if (int_reason & WCN36XX_CH_STAT_INT_DONE_MASK) { | ||
432 | wcn36xx_dxe_write_register(wcn, | ||
433 | WCN36XX_DXE_0_INT_DONE_CLR, | ||
434 | WCN36XX_INT_MASK_CHAN_TX_H); | ||
435 | } | ||
436 | |||
437 | if (int_reason & WCN36XX_CH_STAT_INT_ED_MASK) { | ||
438 | wcn36xx_dxe_write_register(wcn, | ||
439 | WCN36XX_DXE_0_INT_ED_CLR, | ||
440 | WCN36XX_INT_MASK_CHAN_TX_H); | ||
441 | } | ||
442 | |||
426 | wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready high\n"); | 443 | wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready high\n"); |
427 | reap_tx_dxes(wcn, &wcn->dxe_tx_h_ch); | 444 | reap_tx_dxes(wcn, &wcn->dxe_tx_h_ch); |
428 | } | 445 | } |
@@ -431,14 +448,33 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) | |||
431 | wcn36xx_dxe_read_register(wcn, | 448 | wcn36xx_dxe_read_register(wcn, |
432 | WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_L, | 449 | WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_L, |
433 | &int_reason); | 450 | &int_reason); |
434 | /* TODO: Check int_reason */ | ||
435 | 451 | ||
436 | wcn36xx_dxe_write_register(wcn, | 452 | wcn36xx_dxe_write_register(wcn, |
437 | WCN36XX_DXE_0_INT_CLR, | 453 | WCN36XX_DXE_0_INT_CLR, |
438 | WCN36XX_INT_MASK_CHAN_TX_L); | 454 | WCN36XX_INT_MASK_CHAN_TX_L); |
439 | 455 | ||
440 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_ED_CLR, | 456 | |
441 | WCN36XX_INT_MASK_CHAN_TX_L); | 457 | if (int_reason & WCN36XX_CH_STAT_INT_ERR_MASK ) { |
458 | wcn36xx_dxe_write_register(wcn, | ||
459 | WCN36XX_DXE_0_INT_ERR_CLR, | ||
460 | WCN36XX_INT_MASK_CHAN_TX_L); | ||
461 | |||
462 | wcn36xx_err("DXE IRQ reported error: 0x%x in low TX channel\n", | ||
463 | int_src); | ||
464 | } | ||
465 | |||
466 | if (int_reason & WCN36XX_CH_STAT_INT_DONE_MASK) { | ||
467 | wcn36xx_dxe_write_register(wcn, | ||
468 | WCN36XX_DXE_0_INT_DONE_CLR, | ||
469 | WCN36XX_INT_MASK_CHAN_TX_L); | ||
470 | } | ||
471 | |||
472 | if (int_reason & WCN36XX_CH_STAT_INT_ED_MASK) { | ||
473 | wcn36xx_dxe_write_register(wcn, | ||
474 | WCN36XX_DXE_0_INT_ED_CLR, | ||
475 | WCN36XX_INT_MASK_CHAN_TX_L); | ||
476 | } | ||
477 | |||
442 | wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready low\n"); | 478 | wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready low\n"); |
443 | reap_tx_dxes(wcn, &wcn->dxe_tx_l_ch); | 479 | reap_tx_dxes(wcn, &wcn->dxe_tx_l_ch); |
444 | } | 480 | } |
@@ -503,7 +539,7 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn, | |||
503 | int_mask = WCN36XX_DXE_INT_CH3_MASK; | 539 | int_mask = WCN36XX_DXE_INT_CH3_MASK; |
504 | } | 540 | } |
505 | 541 | ||
506 | while (!(dxe->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)) { | 542 | while (!(dxe->ctrl & WCN36xx_DXE_CTRL_VLD)) { |
507 | skb = ctl->skb; | 543 | skb = ctl->skb; |
508 | dma_addr = dxe->dst_addr_l; | 544 | dma_addr = dxe->dst_addr_l; |
509 | ret = wcn36xx_dxe_fill_skb(wcn->dev, ctl); | 545 | ret = wcn36xx_dxe_fill_skb(wcn->dev, ctl); |
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.h b/drivers/net/wireless/ath/wcn36xx/dxe.h index c012e807753b..2bc376c5391b 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.h +++ b/drivers/net/wireless/ath/wcn36xx/dxe.h | |||
@@ -33,15 +33,106 @@ H2H_TEST_RX_TX = DMA2 | |||
33 | #define WCN36XX_CCU_DXE_INT_SELECT_RIVA 0x310 | 33 | #define WCN36XX_CCU_DXE_INT_SELECT_RIVA 0x310 |
34 | #define WCN36XX_CCU_DXE_INT_SELECT_PRONTO 0x10dc | 34 | #define WCN36XX_CCU_DXE_INT_SELECT_PRONTO 0x10dc |
35 | 35 | ||
36 | /* TODO This must calculated properly but not hardcoded */ | 36 | /* Descriptor valid */ |
37 | #define WCN36XX_DXE_CTRL_TX_L 0x328a44 | 37 | #define WCN36xx_DXE_CTRL_VLD BIT(0) |
38 | #define WCN36XX_DXE_CTRL_TX_H 0x32ce44 | 38 | /* End of packet */ |
39 | #define WCN36XX_DXE_CTRL_RX_L 0x12ad2f | 39 | #define WCN36xx_DXE_CTRL_EOP BIT(3) |
40 | #define WCN36XX_DXE_CTRL_RX_H 0x12d12f | 40 | /* BD handling bit */ |
41 | #define WCN36XX_DXE_CTRL_TX_H_BD 0x30ce45 | 41 | #define WCN36xx_DXE_CTRL_BDH BIT(4) |
42 | #define WCN36XX_DXE_CTRL_TX_H_SKB 0x32ce4d | 42 | /* Source is a queue */ |
43 | #define WCN36XX_DXE_CTRL_TX_L_BD 0x308a45 | 43 | #define WCN36xx_DXE_CTRL_SIQ BIT(5) |
44 | #define WCN36XX_DXE_CTRL_TX_L_SKB 0x328a4d | 44 | /* Destination is a queue */ |
45 | #define WCN36xx_DXE_CTRL_DIQ BIT(6) | ||
46 | /* Pointer address is a queue */ | ||
47 | #define WCN36xx_DXE_CTRL_PIQ BIT(7) | ||
48 | /* Release PDU when done */ | ||
49 | #define WCN36xx_DXE_CTRL_PDU_REL BIT(8) | ||
50 | /* STOP channel processing */ | ||
51 | #define WCN36xx_DXE_CTRL_STOP BIT(16) | ||
52 | /* INT on descriptor done */ | ||
53 | #define WCN36xx_DXE_CTRL_INT BIT(17) | ||
54 | /* Endian byte swap enable */ | ||
55 | #define WCN36xx_DXE_CTRL_SWAP BIT(20) | ||
56 | /* Master endianness */ | ||
57 | #define WCN36xx_DXE_CTRL_ENDIANNESS BIT(21) | ||
58 | |||
59 | /* Transfer type */ | ||
60 | #define WCN36xx_DXE_CTRL_XTYPE_SHIFT 1 | ||
61 | #define WCN36xx_DXE_CTRL_XTYPE_MASK GENMASK(2, WCN36xx_DXE_CTRL_XTYPE_SHIFT) | ||
62 | #define WCN36xx_DXE_CTRL_XTYPE_SET(x) ((x) << WCN36xx_DXE_CTRL_XTYPE_SHIFT) | ||
63 | |||
64 | /* BMU Threshold select */ | ||
65 | #define WCN36xx_DXE_CTRL_BTHLD_SEL_SHIFT 9 | ||
66 | #define WCN36xx_DXE_CTRL_BTHLD_SEL_MASK GENMASK(12, WCN36xx_DXE_CTRL_BTHLD_SEL_SHIFT) | ||
67 | #define WCN36xx_DXE_CTRL_BTHLD_SEL_SET(x) ((x) << WCN36xx_DXE_CTRL_BTHLD_SEL_SHIFT) | ||
68 | |||
69 | /* Priority */ | ||
70 | #define WCN36xx_DXE_CTRL_PRIO_SHIFT 13 | ||
71 | #define WCN36xx_DXE_CTRL_PRIO_MASK GENMASK(15, WCN36xx_DXE_CTRL_PRIO_SHIFT) | ||
72 | #define WCN36xx_DXE_CTRL_PRIO_SET(x) ((x) << WCN36xx_DXE_CTRL_PRIO_SHIFT) | ||
73 | |||
74 | /* BD Template index */ | ||
75 | #define WCN36xx_DXE_CTRL_BDT_IDX_SHIFT 18 | ||
76 | #define WCN36xx_DXE_CTRL_BDT_IDX_MASK GENMASK(19, WCN36xx_DXE_CTRL_BDT_IDX_SHIFT) | ||
77 | #define WCN36xx_DXE_CTRL_BDT_IDX_SET(x) ((x) << WCN36xx_DXE_CTRL_BDT_IDX_SHIFT) | ||
78 | |||
79 | /* Transfer types: */ | ||
80 | /* Host to host */ | ||
81 | #define WCN36xx_DXE_XTYPE_H2H (0) | ||
82 | /* Host to BMU */ | ||
83 | #define WCN36xx_DXE_XTYPE_H2B (2) | ||
84 | /* BMU to host */ | ||
85 | #define WCN36xx_DXE_XTYPE_B2H (3) | ||
86 | |||
87 | #define WCN36XX_DXE_CTRL_TX_L (WCN36xx_DXE_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_H2B) | \ | ||
88 | WCN36xx_DXE_CTRL_DIQ | WCN36xx_DXE_CTRL_BTHLD_SEL_SET(5) | \ | ||
89 | WCN36xx_DXE_CTRL_PRIO_SET(4) | WCN36xx_DXE_CTRL_INT | \ | ||
90 | WCN36xx_DXE_CTRL_SWAP | WCN36xx_DXE_CTRL_ENDIANNESS) | ||
91 | |||
92 | #define WCN36XX_DXE_CTRL_TX_H (WCN36xx_DXE_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_H2B) | \ | ||
93 | WCN36xx_DXE_CTRL_DIQ | WCN36xx_DXE_CTRL_BTHLD_SEL_SET(7) | \ | ||
94 | WCN36xx_DXE_CTRL_PRIO_SET(6) | WCN36xx_DXE_CTRL_INT | \ | ||
95 | WCN36xx_DXE_CTRL_SWAP | WCN36xx_DXE_CTRL_ENDIANNESS) | ||
96 | |||
97 | #define WCN36XX_DXE_CTRL_RX_L (WCN36xx_DXE_CTRL_VLD | \ | ||
98 | WCN36xx_DXE_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_B2H) | \ | ||
99 | WCN36xx_DXE_CTRL_EOP | WCN36xx_DXE_CTRL_SIQ | \ | ||
100 | WCN36xx_DXE_CTRL_PDU_REL | WCN36xx_DXE_CTRL_BTHLD_SEL_SET(6) | \ | ||
101 | WCN36xx_DXE_CTRL_PRIO_SET(5) | WCN36xx_DXE_CTRL_INT | \ | ||
102 | WCN36xx_DXE_CTRL_SWAP) | ||
103 | |||
104 | #define WCN36XX_DXE_CTRL_RX_H (WCN36xx_DXE_CTRL_VLD | \ | ||
105 | WCN36xx_DXE_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_B2H) | \ | ||
106 | WCN36xx_DXE_CTRL_EOP | WCN36xx_DXE_CTRL_SIQ | \ | ||
107 | WCN36xx_DXE_CTRL_PDU_REL | WCN36xx_DXE_CTRL_BTHLD_SEL_SET(8) | \ | ||
108 | WCN36xx_DXE_CTRL_PRIO_SET(6) | WCN36xx_DXE_CTRL_INT | \ | ||
109 | WCN36xx_DXE_CTRL_SWAP) | ||
110 | |||
111 | #define WCN36XX_DXE_CTRL_TX_H_BD (WCN36xx_DXE_CTRL_VLD | \ | ||
112 | WCN36xx_DXE_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_H2B) | \ | ||
113 | WCN36xx_DXE_CTRL_DIQ | WCN36xx_DXE_CTRL_BTHLD_SEL_SET(7) | \ | ||
114 | WCN36xx_DXE_CTRL_PRIO_SET(6) | WCN36xx_DXE_CTRL_SWAP | \ | ||
115 | WCN36xx_DXE_CTRL_ENDIANNESS) | ||
116 | |||
117 | #define WCN36XX_DXE_CTRL_TX_H_SKB (WCN36xx_DXE_CTRL_VLD | \ | ||
118 | WCN36xx_DXE_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_H2B) | \ | ||
119 | WCN36xx_DXE_CTRL_EOP | WCN36xx_DXE_CTRL_DIQ | \ | ||
120 | WCN36xx_DXE_CTRL_BTHLD_SEL_SET(7) | WCN36xx_DXE_CTRL_PRIO_SET(6) | \ | ||
121 | WCN36xx_DXE_CTRL_INT | WCN36xx_DXE_CTRL_SWAP | \ | ||
122 | WCN36xx_DXE_CTRL_ENDIANNESS) | ||
123 | |||
124 | #define WCN36XX_DXE_CTRL_TX_L_BD (WCN36xx_DXE_CTRL_VLD | \ | ||
125 | WCN36xx_DXE_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_H2B) | \ | ||
126 | WCN36xx_DXE_CTRL_DIQ | WCN36xx_DXE_CTRL_BTHLD_SEL_SET(5) | \ | ||
127 | WCN36xx_DXE_CTRL_PRIO_SET(4) | WCN36xx_DXE_CTRL_SWAP | \ | ||
128 | WCN36xx_DXE_CTRL_ENDIANNESS) | ||
129 | |||
130 | #define WCN36XX_DXE_CTRL_TX_L_SKB (WCN36xx_DXE_CTRL_VLD | \ | ||
131 | WCN36xx_DXE_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_H2B) | \ | ||
132 | WCN36xx_DXE_CTRL_EOP | WCN36xx_DXE_CTRL_DIQ | \ | ||
133 | WCN36xx_DXE_CTRL_BTHLD_SEL_SET(5) | WCN36xx_DXE_CTRL_PRIO_SET(4) | \ | ||
134 | WCN36xx_DXE_CTRL_INT | WCN36xx_DXE_CTRL_SWAP | \ | ||
135 | WCN36xx_DXE_CTRL_ENDIANNESS) | ||
45 | 136 | ||
46 | /* TODO This must calculated properly but not hardcoded */ | 137 | /* TODO This must calculated properly but not hardcoded */ |
47 | #define WCN36XX_DXE_WQ_TX_L 0x17 | 138 | #define WCN36XX_DXE_WQ_TX_L 0x17 |
@@ -49,15 +140,106 @@ H2H_TEST_RX_TX = DMA2 | |||
49 | #define WCN36XX_DXE_WQ_RX_L 0xB | 140 | #define WCN36XX_DXE_WQ_RX_L 0xB |
50 | #define WCN36XX_DXE_WQ_RX_H 0x4 | 141 | #define WCN36XX_DXE_WQ_RX_H 0x4 |
51 | 142 | ||
52 | /* DXE descriptor control filed */ | 143 | /* Channel enable or restart */ |
53 | #define WCN36XX_DXE_CTRL_VALID_MASK (0x00000001) | 144 | #define WCN36xx_DXE_CH_CTRL_EN BIT(0) |
145 | /* End of packet bit */ | ||
146 | #define WCN36xx_DXE_CH_CTRL_EOP BIT(3) | ||
147 | /* BD Handling bit */ | ||
148 | #define WCN36xx_DXE_CH_CTRL_BDH BIT(4) | ||
149 | /* Source is queue */ | ||
150 | #define WCN36xx_DXE_CH_CTRL_SIQ BIT(5) | ||
151 | /* Destination is queue */ | ||
152 | #define WCN36xx_DXE_CH_CTRL_DIQ BIT(6) | ||
153 | /* Pointer descriptor is queue */ | ||
154 | #define WCN36xx_DXE_CH_CTRL_PIQ BIT(7) | ||
155 | /* Relase PDU when done */ | ||
156 | #define WCN36xx_DXE_CH_CTRL_PDU_REL BIT(8) | ||
157 | /* Stop channel processing */ | ||
158 | #define WCN36xx_DXE_CH_CTRL_STOP BIT(16) | ||
159 | /* Enable external descriptor interrupt */ | ||
160 | #define WCN36xx_DXE_CH_CTRL_INE_ED BIT(17) | ||
161 | /* Enable channel interrupt on errors */ | ||
162 | #define WCN36xx_DXE_CH_CTRL_INE_ERR BIT(18) | ||
163 | /* Enable Channel interrupt when done */ | ||
164 | #define WCN36xx_DXE_CH_CTRL_INE_DONE BIT(19) | ||
165 | /* External descriptor enable */ | ||
166 | #define WCN36xx_DXE_CH_CTRL_EDEN BIT(20) | ||
167 | /* Wait for valid bit */ | ||
168 | #define WCN36xx_DXE_CH_CTRL_EDVEN BIT(21) | ||
169 | /* Endianness is little endian*/ | ||
170 | #define WCN36xx_DXE_CH_CTRL_ENDIANNESS BIT(26) | ||
171 | /* Abort transfer */ | ||
172 | #define WCN36xx_DXE_CH_CTRL_ABORT BIT(27) | ||
173 | /* Long descriptor format */ | ||
174 | #define WCN36xx_DXE_CH_CTRL_DFMT BIT(28) | ||
175 | /* Endian byte swap enable */ | ||
176 | #define WCN36xx_DXE_CH_CTRL_SWAP BIT(31) | ||
177 | |||
178 | /* Transfer type */ | ||
179 | #define WCN36xx_DXE_CH_CTRL_XTYPE_SHIFT 1 | ||
180 | #define WCN36xx_DXE_CH_CTRL_XTYPE_MASK GENMASK(2, WCN36xx_DXE_CH_CTRL_XTYPE_SHIFT) | ||
181 | #define WCN36xx_DXE_CH_CTRL_XTYPE_SET(x) ((x) << WCN36xx_DXE_CH_CTRL_XTYPE_SHIFT) | ||
182 | |||
183 | /* Channel BMU Threshold select */ | ||
184 | #define WCN36xx_DXE_CH_CTRL_BTHLD_SEL_SHIFT 9 | ||
185 | #define WCN36xx_DXE_CH_CTRL_BTHLD_SEL_MASK GENMASK(12, WCN36xx_DXE_CH_CTRL_BTHLD_SEL_SHIFT) | ||
186 | #define WCN36xx_DXE_CH_CTRL_BTHLD_SEL_SET(x) ((x) << WCN36xx_DXE_CH_CTRL_BTHLD_SEL_SHIFT) | ||
187 | |||
188 | /* Channel Priority */ | ||
189 | #define WCN36xx_DXE_CH_CTRL_PRIO_SHIFT 13 | ||
190 | #define WCN36xx_DXE_CH_CTRL_PRIO_MASK GENMASK(15, WCN36xx_DXE_CH_CTRL_PRIO_SHIFT) | ||
191 | #define WCN36xx_DXE_CH_CTRL_PRIO_SET(x) ((x) << WCN36xx_DXE_CH_CTRL_PRIO_SHIFT) | ||
192 | |||
193 | /* Counter select */ | ||
194 | #define WCN36xx_DXE_CH_CTRL_SEL_SHIFT 22 | ||
195 | #define WCN36xx_DXE_CH_CTRL_SEL_MASK GENMASK(25, WCN36xx_DXE_CH_CTRL_SEL_SHIFT) | ||
196 | #define WCN36xx_DXE_CH_CTRL_SEL_SET(x) ((x) << WCN36xx_DXE_CH_CTRL_SEL_SHIFT) | ||
197 | |||
198 | /* Channel BD template index */ | ||
199 | #define WCN36xx_DXE_CH_CTRL_BDT_IDX_SHIFT 29 | ||
200 | #define WCN36xx_DXE_CH_CTRL_BDT_IDX_MASK GENMASK(30, WCN36xx_DXE_CH_CTRL_BDT_IDX_SHIFT) | ||
201 | #define WCN36xx_DXE_CH_CTRL_BDT_IDX_SET(x) ((x) << WCN36xx_DXE_CH_CTRL_BDT_IDX_SHIFT) | ||
54 | 202 | ||
55 | /* TODO This must calculated properly but not hardcoded */ | ||
56 | /* DXE default control register values */ | 203 | /* DXE default control register values */ |
57 | #define WCN36XX_DXE_CH_DEFAULT_CTL_RX_L 0x847EAD2F | 204 | #define WCN36XX_DXE_CH_DEFAULT_CTL_RX_L (WCN36xx_DXE_CH_CTRL_EN | \ |
58 | #define WCN36XX_DXE_CH_DEFAULT_CTL_RX_H 0x84FED12F | 205 | WCN36xx_DXE_CH_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_B2H) | \ |
59 | #define WCN36XX_DXE_CH_DEFAULT_CTL_TX_H 0x853ECF4D | 206 | WCN36xx_DXE_CH_CTRL_EOP | WCN36xx_DXE_CH_CTRL_SIQ | \ |
60 | #define WCN36XX_DXE_CH_DEFAULT_CTL_TX_L 0x843e8b4d | 207 | WCN36xx_DXE_CH_CTRL_PDU_REL | WCN36xx_DXE_CH_CTRL_BTHLD_SEL_SET(6) | \ |
208 | WCN36xx_DXE_CH_CTRL_PRIO_SET(5) | WCN36xx_DXE_CH_CTRL_INE_ED | \ | ||
209 | WCN36xx_DXE_CH_CTRL_INE_ERR | WCN36xx_DXE_CH_CTRL_INE_DONE | \ | ||
210 | WCN36xx_DXE_CH_CTRL_EDEN | WCN36xx_DXE_CH_CTRL_EDVEN | \ | ||
211 | WCN36xx_DXE_CH_CTRL_SEL_SET(1) | WCN36xx_DXE_CH_CTRL_ENDIANNESS | \ | ||
212 | WCN36xx_DXE_CH_CTRL_SWAP) | ||
213 | |||
214 | #define WCN36XX_DXE_CH_DEFAULT_CTL_RX_H (WCN36xx_DXE_CH_CTRL_EN | \ | ||
215 | WCN36xx_DXE_CH_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_B2H) | \ | ||
216 | WCN36xx_DXE_CH_CTRL_EOP | WCN36xx_DXE_CH_CTRL_SIQ | \ | ||
217 | WCN36xx_DXE_CH_CTRL_PDU_REL | WCN36xx_DXE_CH_CTRL_BTHLD_SEL_SET(8) | \ | ||
218 | WCN36xx_DXE_CH_CTRL_PRIO_SET(6) | WCN36xx_DXE_CH_CTRL_INE_ED | \ | ||
219 | WCN36xx_DXE_CH_CTRL_INE_ERR | WCN36xx_DXE_CH_CTRL_INE_DONE | \ | ||
220 | WCN36xx_DXE_CH_CTRL_EDEN | WCN36xx_DXE_CH_CTRL_EDVEN | \ | ||
221 | WCN36xx_DXE_CH_CTRL_SEL_SET(3) | WCN36xx_DXE_CH_CTRL_ENDIANNESS | \ | ||
222 | WCN36xx_DXE_CH_CTRL_SWAP) | ||
223 | |||
224 | #define WCN36XX_DXE_CH_DEFAULT_CTL_TX_H (WCN36xx_DXE_CH_CTRL_EN | \ | ||
225 | WCN36xx_DXE_CH_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_H2B) | \ | ||
226 | WCN36xx_DXE_CH_CTRL_EOP | WCN36xx_DXE_CH_CTRL_DIQ | \ | ||
227 | WCN36xx_DXE_CH_CTRL_PDU_REL | WCN36xx_DXE_CH_CTRL_BTHLD_SEL_SET(7) | \ | ||
228 | WCN36xx_DXE_CH_CTRL_PRIO_SET(6) | WCN36xx_DXE_CH_CTRL_INE_ED | \ | ||
229 | WCN36xx_DXE_CH_CTRL_INE_ERR | WCN36xx_DXE_CH_CTRL_INE_DONE | \ | ||
230 | WCN36xx_DXE_CH_CTRL_EDEN | WCN36xx_DXE_CH_CTRL_EDVEN | \ | ||
231 | WCN36xx_DXE_CH_CTRL_SEL_SET(4) | WCN36xx_DXE_CH_CTRL_ENDIANNESS | \ | ||
232 | WCN36xx_DXE_CH_CTRL_SWAP) | ||
233 | |||
234 | #define WCN36XX_DXE_CH_DEFAULT_CTL_TX_L (WCN36xx_DXE_CH_CTRL_EN | \ | ||
235 | WCN36xx_DXE_CH_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_H2B) | \ | ||
236 | WCN36xx_DXE_CH_CTRL_EOP | WCN36xx_DXE_CH_CTRL_DIQ | \ | ||
237 | WCN36xx_DXE_CH_CTRL_PDU_REL | WCN36xx_DXE_CH_CTRL_BTHLD_SEL_SET(5) | \ | ||
238 | WCN36xx_DXE_CH_CTRL_PRIO_SET(4) | WCN36xx_DXE_CH_CTRL_INE_ED | \ | ||
239 | WCN36xx_DXE_CH_CTRL_INE_ERR | WCN36xx_DXE_CH_CTRL_INE_DONE | \ | ||
240 | WCN36xx_DXE_CH_CTRL_EDEN | WCN36xx_DXE_CH_CTRL_EDVEN | \ | ||
241 | WCN36xx_DXE_CH_CTRL_SEL_SET(0) | WCN36xx_DXE_CH_CTRL_ENDIANNESS | \ | ||
242 | WCN36xx_DXE_CH_CTRL_SWAP) | ||
61 | 243 | ||
62 | /* Common DXE registers */ | 244 | /* Common DXE registers */ |
63 | #define WCN36XX_DXE_MEM_CSR (WCN36XX_DXE_MEM_REG + 0x00) | 245 | #define WCN36XX_DXE_MEM_CSR (WCN36XX_DXE_MEM_REG + 0x00) |
@@ -80,6 +262,10 @@ H2H_TEST_RX_TX = DMA2 | |||
80 | #define WCN36XX_DXE_0_INT_DONE_CLR (WCN36XX_DXE_MEM_REG + 0x38) | 262 | #define WCN36XX_DXE_0_INT_DONE_CLR (WCN36XX_DXE_MEM_REG + 0x38) |
81 | #define WCN36XX_DXE_0_INT_ERR_CLR (WCN36XX_DXE_MEM_REG + 0x3C) | 263 | #define WCN36XX_DXE_0_INT_ERR_CLR (WCN36XX_DXE_MEM_REG + 0x3C) |
82 | 264 | ||
265 | #define WCN36XX_CH_STAT_INT_DONE_MASK 0x00008000 | ||
266 | #define WCN36XX_CH_STAT_INT_ERR_MASK 0x00004000 | ||
267 | #define WCN36XX_CH_STAT_INT_ED_MASK 0x00002000 | ||
268 | |||
83 | #define WCN36XX_DXE_0_CH0_STATUS (WCN36XX_DXE_MEM_REG + 0x404) | 269 | #define WCN36XX_DXE_0_CH0_STATUS (WCN36XX_DXE_MEM_REG + 0x404) |
84 | #define WCN36XX_DXE_0_CH1_STATUS (WCN36XX_DXE_MEM_REG + 0x444) | 270 | #define WCN36XX_DXE_0_CH1_STATUS (WCN36XX_DXE_MEM_REG + 0x444) |
85 | #define WCN36XX_DXE_0_CH2_STATUS (WCN36XX_DXE_MEM_REG + 0x484) | 271 | #define WCN36XX_DXE_0_CH2_STATUS (WCN36XX_DXE_MEM_REG + 0x484) |
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index ab5be6d2c691..621e72b6ec99 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c | |||
@@ -261,7 +261,7 @@ static void wcn36xx_feat_caps_info(struct wcn36xx *wcn) | |||
261 | 261 | ||
262 | for (i = 0; i < MAX_FEATURE_SUPPORTED; i++) { | 262 | for (i = 0; i < MAX_FEATURE_SUPPORTED; i++) { |
263 | if (get_feat_caps(wcn->fw_feat_caps, i)) | 263 | if (get_feat_caps(wcn->fw_feat_caps, i)) |
264 | wcn36xx_info("FW Cap %s\n", wcn36xx_get_cap_name(i)); | 264 | wcn36xx_dbg(WCN36XX_DBG_MAC, "FW Cap %s\n", wcn36xx_get_cap_name(i)); |
265 | } | 265 | } |
266 | } | 266 | } |
267 | 267 | ||
@@ -666,16 +666,13 @@ static void wcn36xx_cancel_hw_scan(struct ieee80211_hw *hw, | |||
666 | { | 666 | { |
667 | struct wcn36xx *wcn = hw->priv; | 667 | struct wcn36xx *wcn = hw->priv; |
668 | 668 | ||
669 | if (!wcn36xx_smd_stop_hw_scan(wcn)) { | ||
670 | struct cfg80211_scan_info scan_info = { .aborted = true }; | ||
671 | |||
672 | ieee80211_scan_completed(wcn->hw, &scan_info); | ||
673 | } | ||
674 | |||
675 | mutex_lock(&wcn->scan_lock); | 669 | mutex_lock(&wcn->scan_lock); |
676 | wcn->scan_aborted = true; | 670 | wcn->scan_aborted = true; |
677 | mutex_unlock(&wcn->scan_lock); | 671 | mutex_unlock(&wcn->scan_lock); |
678 | 672 | ||
673 | /* ieee80211_scan_completed will be called on FW scan indication */ | ||
674 | wcn36xx_smd_stop_hw_scan(wcn); | ||
675 | |||
679 | cancel_work_sync(&wcn->scan_work); | 676 | cancel_work_sync(&wcn->scan_work); |
680 | } | 677 | } |
681 | 678 | ||
@@ -1283,6 +1280,7 @@ static int wcn36xx_probe(struct platform_device *pdev) | |||
1283 | wcn = hw->priv; | 1280 | wcn = hw->priv; |
1284 | wcn->hw = hw; | 1281 | wcn->hw = hw; |
1285 | wcn->dev = &pdev->dev; | 1282 | wcn->dev = &pdev->dev; |
1283 | wcn->first_boot = true; | ||
1286 | mutex_init(&wcn->conf_mutex); | 1284 | mutex_init(&wcn->conf_mutex); |
1287 | mutex_init(&wcn->hal_mutex); | 1285 | mutex_init(&wcn->hal_mutex); |
1288 | mutex_init(&wcn->scan_lock); | 1286 | mutex_init(&wcn->scan_lock); |
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 2a4871ca9c72..def6b23b777f 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c | |||
@@ -409,15 +409,17 @@ static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len) | |||
409 | wcn->fw_minor = rsp->start_rsp_params.version.minor; | 409 | wcn->fw_minor = rsp->start_rsp_params.version.minor; |
410 | wcn->fw_major = rsp->start_rsp_params.version.major; | 410 | wcn->fw_major = rsp->start_rsp_params.version.major; |
411 | 411 | ||
412 | wcn36xx_info("firmware WLAN version '%s' and CRM version '%s'\n", | 412 | if (wcn->first_boot) { |
413 | wcn->wlan_version, wcn->crm_version); | 413 | wcn->first_boot = false; |
414 | 414 | wcn36xx_info("firmware WLAN version '%s' and CRM version '%s'\n", | |
415 | wcn36xx_info("firmware API %u.%u.%u.%u, %u stations, %u bssids\n", | 415 | wcn->wlan_version, wcn->crm_version); |
416 | wcn->fw_major, wcn->fw_minor, | ||
417 | wcn->fw_version, wcn->fw_revision, | ||
418 | rsp->start_rsp_params.stations, | ||
419 | rsp->start_rsp_params.bssids); | ||
420 | 416 | ||
417 | wcn36xx_info("firmware API %u.%u.%u.%u, %u stations, %u bssids\n", | ||
418 | wcn->fw_major, wcn->fw_minor, | ||
419 | wcn->fw_version, wcn->fw_revision, | ||
420 | rsp->start_rsp_params.stations, | ||
421 | rsp->start_rsp_params.bssids); | ||
422 | } | ||
421 | return 0; | 423 | return 0; |
422 | } | 424 | } |
423 | 425 | ||
@@ -2138,6 +2140,8 @@ static int wcn36xx_smd_hw_scan_ind(struct wcn36xx *wcn, void *buf, size_t len) | |||
2138 | case WCN36XX_HAL_SCAN_IND_COMPLETED: | 2140 | case WCN36XX_HAL_SCAN_IND_COMPLETED: |
2139 | mutex_lock(&wcn->scan_lock); | 2141 | mutex_lock(&wcn->scan_lock); |
2140 | wcn->scan_req = NULL; | 2142 | wcn->scan_req = NULL; |
2143 | if (wcn->scan_aborted) | ||
2144 | scan_info.aborted = true; | ||
2141 | mutex_unlock(&wcn->scan_lock); | 2145 | mutex_unlock(&wcn->scan_lock); |
2142 | ieee80211_scan_completed(wcn->hw, &scan_info); | 2146 | ieee80211_scan_completed(wcn->hw, &scan_info); |
2143 | break; | 2147 | break; |
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h index 81017e6703b4..5854adf43f3a 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h | |||
@@ -192,6 +192,8 @@ struct wcn36xx { | |||
192 | u8 crm_version[WCN36XX_HAL_VERSION_LENGTH + 1]; | 192 | u8 crm_version[WCN36XX_HAL_VERSION_LENGTH + 1]; |
193 | u8 wlan_version[WCN36XX_HAL_VERSION_LENGTH + 1]; | 193 | u8 wlan_version[WCN36XX_HAL_VERSION_LENGTH + 1]; |
194 | 194 | ||
195 | bool first_boot; | ||
196 | |||
195 | /* IRQs */ | 197 | /* IRQs */ |
196 | int tx_irq; | 198 | int tx_irq; |
197 | int rx_irq; | 199 | int rx_irq; |
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index b799a5384abb..cdbb393863f3 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. |
3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -17,8 +18,10 @@ | |||
17 | #include <linux/etherdevice.h> | 18 | #include <linux/etherdevice.h> |
18 | #include <linux/moduleparam.h> | 19 | #include <linux/moduleparam.h> |
19 | #include <net/netlink.h> | 20 | #include <net/netlink.h> |
21 | #include <net/cfg80211.h> | ||
20 | #include "wil6210.h" | 22 | #include "wil6210.h" |
21 | #include "wmi.h" | 23 | #include "wmi.h" |
24 | #include "fw.h" | ||
22 | 25 | ||
23 | #define WIL_MAX_ROC_DURATION_MS 5000 | 26 | #define WIL_MAX_ROC_DURATION_MS 5000 |
24 | 27 | ||
@@ -258,9 +261,10 @@ int wil_iftype_nl2wmi(enum nl80211_iftype type) | |||
258 | return -EOPNOTSUPP; | 261 | return -EOPNOTSUPP; |
259 | } | 262 | } |
260 | 263 | ||
261 | int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid, | 264 | int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid, |
262 | struct station_info *sinfo) | 265 | struct station_info *sinfo) |
263 | { | 266 | { |
267 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
264 | struct wmi_notify_req_cmd cmd = { | 268 | struct wmi_notify_req_cmd cmd = { |
265 | .cid = cid, | 269 | .cid = cid, |
266 | .interval_usec = 0, | 270 | .interval_usec = 0, |
@@ -272,17 +276,17 @@ int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid, | |||
272 | struct wil_net_stats *stats = &wil->sta[cid].stats; | 276 | struct wil_net_stats *stats = &wil->sta[cid].stats; |
273 | int rc; | 277 | int rc; |
274 | 278 | ||
275 | rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd), | 279 | rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, vif->mid, &cmd, sizeof(cmd), |
276 | WMI_NOTIFY_REQ_DONE_EVENTID, &reply, sizeof(reply), 20); | 280 | WMI_NOTIFY_REQ_DONE_EVENTID, &reply, sizeof(reply), 20); |
277 | if (rc) | 281 | if (rc) |
278 | return rc; | 282 | return rc; |
279 | 283 | ||
280 | wil_dbg_wmi(wil, "Link status for CID %d: {\n" | 284 | wil_dbg_wmi(wil, "Link status for CID %d MID %d: {\n" |
281 | " MCS %d TSF 0x%016llx\n" | 285 | " MCS %d TSF 0x%016llx\n" |
282 | " BF status 0x%08x RSSI %d SQI %d%%\n" | 286 | " BF status 0x%08x RSSI %d SQI %d%%\n" |
283 | " Tx Tpt %d goodput %d Rx goodput %d\n" | 287 | " Tx Tpt %d goodput %d Rx goodput %d\n" |
284 | " Sectors(rx:tx) my %d:%d peer %d:%d\n""}\n", | 288 | " Sectors(rx:tx) my %d:%d peer %d:%d\n""}\n", |
285 | cid, le16_to_cpu(reply.evt.bf_mcs), | 289 | cid, vif->mid, le16_to_cpu(reply.evt.bf_mcs), |
286 | le64_to_cpu(reply.evt.tsf), reply.evt.status, | 290 | le64_to_cpu(reply.evt.tsf), reply.evt.status, |
287 | reply.evt.rssi, | 291 | reply.evt.rssi, |
288 | reply.evt.sqi, | 292 | reply.evt.sqi, |
@@ -315,7 +319,7 @@ int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid, | |||
315 | sinfo->tx_packets = stats->tx_packets; | 319 | sinfo->tx_packets = stats->tx_packets; |
316 | sinfo->tx_failed = stats->tx_errors; | 320 | sinfo->tx_failed = stats->tx_errors; |
317 | 321 | ||
318 | if (test_bit(wil_status_fwconnected, wil->status)) { | 322 | if (test_bit(wil_vif_fwconnected, vif->status)) { |
319 | sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); | 323 | sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); |
320 | if (test_bit(WMI_FW_CAPABILITY_RSSI_REPORTING, | 324 | if (test_bit(WMI_FW_CAPABILITY_RSSI_REPORTING, |
321 | wil->fw_capabilities)) | 325 | wil->fw_capabilities)) |
@@ -331,30 +335,34 @@ static int wil_cfg80211_get_station(struct wiphy *wiphy, | |||
331 | struct net_device *ndev, | 335 | struct net_device *ndev, |
332 | const u8 *mac, struct station_info *sinfo) | 336 | const u8 *mac, struct station_info *sinfo) |
333 | { | 337 | { |
338 | struct wil6210_vif *vif = ndev_to_vif(ndev); | ||
334 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 339 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
335 | int rc; | 340 | int rc; |
336 | 341 | ||
337 | int cid = wil_find_cid(wil, mac); | 342 | int cid = wil_find_cid(wil, vif->mid, mac); |
338 | 343 | ||
339 | wil_dbg_misc(wil, "get_station: %pM CID %d\n", mac, cid); | 344 | wil_dbg_misc(wil, "get_station: %pM CID %d MID %d\n", mac, cid, |
345 | vif->mid); | ||
340 | if (cid < 0) | 346 | if (cid < 0) |
341 | return cid; | 347 | return cid; |
342 | 348 | ||
343 | rc = wil_cid_fill_sinfo(wil, cid, sinfo); | 349 | rc = wil_cid_fill_sinfo(vif, cid, sinfo); |
344 | 350 | ||
345 | return rc; | 351 | return rc; |
346 | } | 352 | } |
347 | 353 | ||
348 | /* | 354 | /* |
349 | * Find @idx-th active STA for station dump. | 355 | * Find @idx-th active STA for specific MID for station dump. |
350 | */ | 356 | */ |
351 | static int wil_find_cid_by_idx(struct wil6210_priv *wil, int idx) | 357 | static int wil_find_cid_by_idx(struct wil6210_priv *wil, u8 mid, int idx) |
352 | { | 358 | { |
353 | int i; | 359 | int i; |
354 | 360 | ||
355 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { | 361 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { |
356 | if (wil->sta[i].status == wil_sta_unused) | 362 | if (wil->sta[i].status == wil_sta_unused) |
357 | continue; | 363 | continue; |
364 | if (wil->sta[i].mid != mid) | ||
365 | continue; | ||
358 | if (idx == 0) | 366 | if (idx == 0) |
359 | return i; | 367 | return i; |
360 | idx--; | 368 | idx--; |
@@ -367,17 +375,19 @@ static int wil_cfg80211_dump_station(struct wiphy *wiphy, | |||
367 | struct net_device *dev, int idx, | 375 | struct net_device *dev, int idx, |
368 | u8 *mac, struct station_info *sinfo) | 376 | u8 *mac, struct station_info *sinfo) |
369 | { | 377 | { |
378 | struct wil6210_vif *vif = ndev_to_vif(dev); | ||
370 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 379 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
371 | int rc; | 380 | int rc; |
372 | int cid = wil_find_cid_by_idx(wil, idx); | 381 | int cid = wil_find_cid_by_idx(wil, vif->mid, idx); |
373 | 382 | ||
374 | if (cid < 0) | 383 | if (cid < 0) |
375 | return -ENOENT; | 384 | return -ENOENT; |
376 | 385 | ||
377 | ether_addr_copy(mac, wil->sta[cid].addr); | 386 | ether_addr_copy(mac, wil->sta[cid].addr); |
378 | wil_dbg_misc(wil, "dump_station: %pM CID %d\n", mac, cid); | 387 | wil_dbg_misc(wil, "dump_station: %pM CID %d MID %d\n", mac, cid, |
388 | vif->mid); | ||
379 | 389 | ||
380 | rc = wil_cid_fill_sinfo(wil, cid, sinfo); | 390 | rc = wil_cid_fill_sinfo(vif, cid, sinfo); |
381 | 391 | ||
382 | return rc; | 392 | return rc; |
383 | } | 393 | } |
@@ -388,7 +398,7 @@ static int wil_cfg80211_start_p2p_device(struct wiphy *wiphy, | |||
388 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 398 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
389 | 399 | ||
390 | wil_dbg_misc(wil, "start_p2p_device: entered\n"); | 400 | wil_dbg_misc(wil, "start_p2p_device: entered\n"); |
391 | wil->p2p.p2p_dev_started = 1; | 401 | wil->p2p_dev_started = 1; |
392 | return 0; | 402 | return 0; |
393 | } | 403 | } |
394 | 404 | ||
@@ -396,20 +406,66 @@ static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy, | |||
396 | struct wireless_dev *wdev) | 406 | struct wireless_dev *wdev) |
397 | { | 407 | { |
398 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 408 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
399 | struct wil_p2p_info *p2p = &wil->p2p; | ||
400 | 409 | ||
401 | if (!p2p->p2p_dev_started) | 410 | if (!wil->p2p_dev_started) |
402 | return; | 411 | return; |
403 | 412 | ||
404 | wil_dbg_misc(wil, "stop_p2p_device: entered\n"); | 413 | wil_dbg_misc(wil, "stop_p2p_device: entered\n"); |
405 | mutex_lock(&wil->mutex); | 414 | mutex_lock(&wil->mutex); |
406 | mutex_lock(&wil->p2p_wdev_mutex); | 415 | mutex_lock(&wil->vif_mutex); |
407 | wil_p2p_stop_radio_operations(wil); | 416 | wil_p2p_stop_radio_operations(wil); |
408 | p2p->p2p_dev_started = 0; | 417 | wil->p2p_dev_started = 0; |
409 | mutex_unlock(&wil->p2p_wdev_mutex); | 418 | mutex_unlock(&wil->vif_mutex); |
410 | mutex_unlock(&wil->mutex); | 419 | mutex_unlock(&wil->mutex); |
411 | } | 420 | } |
412 | 421 | ||
422 | static int wil_cfg80211_validate_add_iface(struct wil6210_priv *wil, | ||
423 | enum nl80211_iftype new_type) | ||
424 | { | ||
425 | int i; | ||
426 | struct wireless_dev *wdev; | ||
427 | struct iface_combination_params params = { | ||
428 | .num_different_channels = 1, | ||
429 | }; | ||
430 | |||
431 | for (i = 0; i < wil->max_vifs; i++) { | ||
432 | if (wil->vifs[i]) { | ||
433 | wdev = vif_to_wdev(wil->vifs[i]); | ||
434 | params.iftype_num[wdev->iftype]++; | ||
435 | } | ||
436 | } | ||
437 | params.iftype_num[new_type]++; | ||
438 | return cfg80211_check_combinations(wil->wiphy, ¶ms); | ||
439 | } | ||
440 | |||
441 | static int wil_cfg80211_validate_change_iface(struct wil6210_priv *wil, | ||
442 | struct wil6210_vif *vif, | ||
443 | enum nl80211_iftype new_type) | ||
444 | { | ||
445 | int i, ret = 0; | ||
446 | struct wireless_dev *wdev; | ||
447 | struct iface_combination_params params = { | ||
448 | .num_different_channels = 1, | ||
449 | }; | ||
450 | bool check_combos = false; | ||
451 | |||
452 | for (i = 0; i < wil->max_vifs; i++) { | ||
453 | struct wil6210_vif *vif_pos = wil->vifs[i]; | ||
454 | |||
455 | if (vif_pos && vif != vif_pos) { | ||
456 | wdev = vif_to_wdev(vif_pos); | ||
457 | params.iftype_num[wdev->iftype]++; | ||
458 | check_combos = true; | ||
459 | } | ||
460 | } | ||
461 | |||
462 | if (check_combos) { | ||
463 | params.iftype_num[new_type]++; | ||
464 | ret = cfg80211_check_combinations(wil->wiphy, ¶ms); | ||
465 | } | ||
466 | return ret; | ||
467 | } | ||
468 | |||
413 | static struct wireless_dev * | 469 | static struct wireless_dev * |
414 | wil_cfg80211_add_iface(struct wiphy *wiphy, const char *name, | 470 | wil_cfg80211_add_iface(struct wiphy *wiphy, const char *name, |
415 | unsigned char name_assign_type, | 471 | unsigned char name_assign_type, |
@@ -417,51 +473,137 @@ wil_cfg80211_add_iface(struct wiphy *wiphy, const char *name, | |||
417 | struct vif_params *params) | 473 | struct vif_params *params) |
418 | { | 474 | { |
419 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 475 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
420 | struct net_device *ndev = wil_to_ndev(wil); | 476 | struct net_device *ndev_main = wil->main_ndev, *ndev; |
421 | struct wireless_dev *p2p_wdev; | 477 | struct wil6210_vif *vif; |
478 | struct wireless_dev *p2p_wdev, *wdev; | ||
479 | int rc; | ||
422 | 480 | ||
423 | wil_dbg_misc(wil, "add_iface\n"); | 481 | wil_dbg_misc(wil, "add_iface, type %d\n", type); |
424 | 482 | ||
425 | if (type != NL80211_IFTYPE_P2P_DEVICE) { | 483 | /* P2P device is not a real virtual interface, it is a management-only |
426 | wil_err(wil, "unsupported iftype %d\n", type); | 484 | * interface that shares the main interface. |
427 | return ERR_PTR(-EINVAL); | 485 | * Skip concurrency checks here. |
486 | */ | ||
487 | if (type == NL80211_IFTYPE_P2P_DEVICE) { | ||
488 | if (wil->p2p_wdev) { | ||
489 | wil_err(wil, "P2P_DEVICE interface already created\n"); | ||
490 | return ERR_PTR(-EINVAL); | ||
491 | } | ||
492 | |||
493 | p2p_wdev = kzalloc(sizeof(*p2p_wdev), GFP_KERNEL); | ||
494 | if (!p2p_wdev) | ||
495 | return ERR_PTR(-ENOMEM); | ||
496 | |||
497 | p2p_wdev->iftype = type; | ||
498 | p2p_wdev->wiphy = wiphy; | ||
499 | /* use our primary ethernet address */ | ||
500 | ether_addr_copy(p2p_wdev->address, ndev_main->perm_addr); | ||
501 | |||
502 | wil->p2p_wdev = p2p_wdev; | ||
503 | |||
504 | return p2p_wdev; | ||
428 | } | 505 | } |
429 | 506 | ||
430 | if (wil->p2p_wdev) { | 507 | if (!wil->wiphy->n_iface_combinations) { |
431 | wil_err(wil, "P2P_DEVICE interface already created\n"); | 508 | wil_err(wil, "virtual interfaces not supported\n"); |
432 | return ERR_PTR(-EINVAL); | 509 | return ERR_PTR(-EINVAL); |
433 | } | 510 | } |
434 | 511 | ||
435 | p2p_wdev = kzalloc(sizeof(*p2p_wdev), GFP_KERNEL); | 512 | rc = wil_cfg80211_validate_add_iface(wil, type); |
436 | if (!p2p_wdev) | 513 | if (rc) { |
437 | return ERR_PTR(-ENOMEM); | 514 | wil_err(wil, "iface validation failed, err=%d\n", rc); |
515 | return ERR_PTR(rc); | ||
516 | } | ||
438 | 517 | ||
439 | p2p_wdev->iftype = type; | 518 | vif = wil_vif_alloc(wil, name, name_assign_type, type); |
440 | p2p_wdev->wiphy = wiphy; | 519 | if (IS_ERR(vif)) |
441 | /* use our primary ethernet address */ | 520 | return ERR_CAST(vif); |
442 | ether_addr_copy(p2p_wdev->address, ndev->perm_addr); | 521 | |
522 | ndev = vif_to_ndev(vif); | ||
523 | ether_addr_copy(ndev->perm_addr, ndev_main->perm_addr); | ||
524 | if (is_valid_ether_addr(params->macaddr)) { | ||
525 | ether_addr_copy(ndev->dev_addr, params->macaddr); | ||
526 | } else { | ||
527 | ether_addr_copy(ndev->dev_addr, ndev_main->perm_addr); | ||
528 | ndev->dev_addr[0] = (ndev->dev_addr[0] ^ (1 << vif->mid)) | | ||
529 | 0x2; /* locally administered */ | ||
530 | } | ||
531 | wdev = vif_to_wdev(vif); | ||
532 | ether_addr_copy(wdev->address, ndev->dev_addr); | ||
443 | 533 | ||
444 | wil->p2p_wdev = p2p_wdev; | 534 | rc = wil_vif_add(wil, vif); |
535 | if (rc) | ||
536 | goto out; | ||
445 | 537 | ||
446 | return p2p_wdev; | 538 | wil_info(wil, "added VIF, mid %d iftype %d MAC %pM\n", |
539 | vif->mid, type, wdev->address); | ||
540 | return wdev; | ||
541 | out: | ||
542 | wil_vif_free(vif); | ||
543 | return ERR_PTR(rc); | ||
544 | } | ||
545 | |||
546 | int wil_vif_prepare_stop(struct wil6210_vif *vif) | ||
547 | { | ||
548 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
549 | struct wireless_dev *wdev = vif_to_wdev(vif); | ||
550 | struct net_device *ndev; | ||
551 | int rc; | ||
552 | |||
553 | if (wdev->iftype != NL80211_IFTYPE_AP) | ||
554 | return 0; | ||
555 | |||
556 | ndev = vif_to_ndev(vif); | ||
557 | if (netif_carrier_ok(ndev)) { | ||
558 | rc = wmi_pcp_stop(vif); | ||
559 | if (rc) { | ||
560 | wil_info(wil, "failed to stop AP, status %d\n", | ||
561 | rc); | ||
562 | /* continue */ | ||
563 | } | ||
564 | wil_bcast_fini(vif); | ||
565 | netif_carrier_off(ndev); | ||
566 | } | ||
567 | |||
568 | return 0; | ||
447 | } | 569 | } |
448 | 570 | ||
449 | static int wil_cfg80211_del_iface(struct wiphy *wiphy, | 571 | static int wil_cfg80211_del_iface(struct wiphy *wiphy, |
450 | struct wireless_dev *wdev) | 572 | struct wireless_dev *wdev) |
451 | { | 573 | { |
452 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 574 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
575 | struct wil6210_vif *vif = wdev_to_vif(wil, wdev); | ||
576 | int rc; | ||
453 | 577 | ||
454 | wil_dbg_misc(wil, "del_iface\n"); | 578 | wil_dbg_misc(wil, "del_iface\n"); |
455 | 579 | ||
456 | if (wdev != wil->p2p_wdev) { | 580 | if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) { |
457 | wil_err(wil, "delete of incorrect interface 0x%p\n", wdev); | 581 | if (wdev != wil->p2p_wdev) { |
582 | wil_err(wil, "delete of incorrect interface 0x%p\n", | ||
583 | wdev); | ||
584 | return -EINVAL; | ||
585 | } | ||
586 | |||
587 | wil_cfg80211_stop_p2p_device(wiphy, wdev); | ||
588 | wil_p2p_wdev_free(wil); | ||
589 | return 0; | ||
590 | } | ||
591 | |||
592 | if (vif->mid == 0) { | ||
593 | wil_err(wil, "cannot remove the main interface\n"); | ||
458 | return -EINVAL; | 594 | return -EINVAL; |
459 | } | 595 | } |
460 | 596 | ||
461 | wil_cfg80211_stop_p2p_device(wiphy, wdev); | 597 | rc = wil_vif_prepare_stop(vif); |
462 | wil_p2p_wdev_free(wil); | 598 | if (rc) |
599 | goto out; | ||
600 | |||
601 | wil_info(wil, "deleted VIF, mid %d iftype %d MAC %pM\n", | ||
602 | vif->mid, wdev->iftype, wdev->address); | ||
463 | 603 | ||
464 | return 0; | 604 | wil_vif_remove(wil, vif->mid); |
605 | out: | ||
606 | return rc; | ||
465 | } | 607 | } |
466 | 608 | ||
467 | static int wil_cfg80211_change_iface(struct wiphy *wiphy, | 609 | static int wil_cfg80211_change_iface(struct wiphy *wiphy, |
@@ -470,12 +612,26 @@ static int wil_cfg80211_change_iface(struct wiphy *wiphy, | |||
470 | struct vif_params *params) | 612 | struct vif_params *params) |
471 | { | 613 | { |
472 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 614 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
473 | struct wireless_dev *wdev = wil_to_wdev(wil); | 615 | struct wil6210_vif *vif = ndev_to_vif(ndev); |
616 | struct wireless_dev *wdev = vif_to_wdev(vif); | ||
474 | int rc; | 617 | int rc; |
618 | bool fw_reset = false; | ||
475 | 619 | ||
476 | wil_dbg_misc(wil, "change_iface: type=%d\n", type); | 620 | wil_dbg_misc(wil, "change_iface: type=%d\n", type); |
477 | 621 | ||
478 | if (netif_running(wil_to_ndev(wil)) && !wil_is_recovery_blocked(wil)) { | 622 | if (wiphy->n_iface_combinations) { |
623 | rc = wil_cfg80211_validate_change_iface(wil, vif, type); | ||
624 | if (rc) { | ||
625 | wil_err(wil, "iface validation failed, err=%d\n", rc); | ||
626 | return rc; | ||
627 | } | ||
628 | } | ||
629 | |||
630 | /* do not reset FW when there are active VIFs, | ||
631 | * because it can cause significant disruption | ||
632 | */ | ||
633 | if (!wil_has_other_active_ifaces(wil, ndev, true, false) && | ||
634 | netif_running(ndev) && !wil_is_recovery_blocked(wil)) { | ||
479 | wil_dbg_misc(wil, "interface is up. resetting...\n"); | 635 | wil_dbg_misc(wil, "interface is up. resetting...\n"); |
480 | mutex_lock(&wil->mutex); | 636 | mutex_lock(&wil->mutex); |
481 | __wil_down(wil); | 637 | __wil_down(wil); |
@@ -484,6 +640,7 @@ static int wil_cfg80211_change_iface(struct wiphy *wiphy, | |||
484 | 640 | ||
485 | if (rc) | 641 | if (rc) |
486 | return rc; | 642 | return rc; |
643 | fw_reset = true; | ||
487 | } | 644 | } |
488 | 645 | ||
489 | switch (type) { | 646 | switch (type) { |
@@ -500,8 +657,18 @@ static int wil_cfg80211_change_iface(struct wiphy *wiphy, | |||
500 | return -EOPNOTSUPP; | 657 | return -EOPNOTSUPP; |
501 | } | 658 | } |
502 | 659 | ||
503 | wdev->iftype = type; | 660 | if (vif->mid != 0 && wil_has_active_ifaces(wil, true, false)) { |
661 | if (!fw_reset) | ||
662 | wil_vif_prepare_stop(vif); | ||
663 | rc = wmi_port_delete(wil, vif->mid); | ||
664 | if (rc) | ||
665 | return rc; | ||
666 | rc = wmi_port_allocate(wil, vif->mid, ndev->dev_addr, type); | ||
667 | if (rc) | ||
668 | return rc; | ||
669 | } | ||
504 | 670 | ||
671 | wdev->iftype = type; | ||
505 | return 0; | 672 | return 0; |
506 | } | 673 | } |
507 | 674 | ||
@@ -510,6 +677,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, | |||
510 | { | 677 | { |
511 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 678 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
512 | struct wireless_dev *wdev = request->wdev; | 679 | struct wireless_dev *wdev = request->wdev; |
680 | struct wil6210_vif *vif = wdev_to_vif(wil, wdev); | ||
513 | struct { | 681 | struct { |
514 | struct wmi_start_scan_cmd cmd; | 682 | struct wmi_start_scan_cmd cmd; |
515 | u16 chnl[4]; | 683 | u16 chnl[4]; |
@@ -537,35 +705,38 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, | |||
537 | 705 | ||
538 | mutex_lock(&wil->mutex); | 706 | mutex_lock(&wil->mutex); |
539 | 707 | ||
540 | mutex_lock(&wil->p2p_wdev_mutex); | 708 | mutex_lock(&wil->vif_mutex); |
541 | if (wil->scan_request || wil->p2p.discovery_started) { | 709 | if (vif->scan_request || vif->p2p.discovery_started) { |
542 | wil_err(wil, "Already scanning\n"); | 710 | wil_err(wil, "Already scanning\n"); |
543 | mutex_unlock(&wil->p2p_wdev_mutex); | 711 | mutex_unlock(&wil->vif_mutex); |
544 | rc = -EAGAIN; | 712 | rc = -EAGAIN; |
545 | goto out; | 713 | goto out; |
546 | } | 714 | } |
547 | mutex_unlock(&wil->p2p_wdev_mutex); | 715 | mutex_unlock(&wil->vif_mutex); |
548 | 716 | ||
549 | if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) { | 717 | if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) { |
550 | if (!wil->p2p.p2p_dev_started) { | 718 | if (!wil->p2p_dev_started) { |
551 | wil_err(wil, "P2P search requested on stopped P2P device\n"); | 719 | wil_err(wil, "P2P search requested on stopped P2P device\n"); |
552 | rc = -EIO; | 720 | rc = -EIO; |
553 | goto out; | 721 | goto out; |
554 | } | 722 | } |
555 | /* social scan on P2P_DEVICE is handled as p2p search */ | 723 | /* social scan on P2P_DEVICE is handled as p2p search */ |
556 | if (wil_p2p_is_social_scan(request)) { | 724 | if (wil_p2p_is_social_scan(request)) { |
557 | wil->scan_request = request; | 725 | vif->scan_request = request; |
558 | wil->radio_wdev = wdev; | 726 | if (vif->mid == 0) |
559 | rc = wil_p2p_search(wil, request); | 727 | wil->radio_wdev = wdev; |
728 | rc = wil_p2p_search(vif, request); | ||
560 | if (rc) { | 729 | if (rc) { |
561 | wil->radio_wdev = wil_to_wdev(wil); | 730 | if (vif->mid == 0) |
562 | wil->scan_request = NULL; | 731 | wil->radio_wdev = |
732 | wil->main_ndev->ieee80211_ptr; | ||
733 | vif->scan_request = NULL; | ||
563 | } | 734 | } |
564 | goto out; | 735 | goto out; |
565 | } | 736 | } |
566 | } | 737 | } |
567 | 738 | ||
568 | (void)wil_p2p_stop_discovery(wil); | 739 | (void)wil_p2p_stop_discovery(vif); |
569 | 740 | ||
570 | wil_dbg_misc(wil, "Start scan_request 0x%p\n", request); | 741 | wil_dbg_misc(wil, "Start scan_request 0x%p\n", request); |
571 | wil_dbg_misc(wil, "SSID count: %d", request->n_ssids); | 742 | wil_dbg_misc(wil, "SSID count: %d", request->n_ssids); |
@@ -578,18 +749,18 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, | |||
578 | } | 749 | } |
579 | 750 | ||
580 | if (request->n_ssids) | 751 | if (request->n_ssids) |
581 | rc = wmi_set_ssid(wil, request->ssids[0].ssid_len, | 752 | rc = wmi_set_ssid(vif, request->ssids[0].ssid_len, |
582 | request->ssids[0].ssid); | 753 | request->ssids[0].ssid); |
583 | else | 754 | else |
584 | rc = wmi_set_ssid(wil, 0, NULL); | 755 | rc = wmi_set_ssid(vif, 0, NULL); |
585 | 756 | ||
586 | if (rc) { | 757 | if (rc) { |
587 | wil_err(wil, "set SSID for scan request failed: %d\n", rc); | 758 | wil_err(wil, "set SSID for scan request failed: %d\n", rc); |
588 | goto out; | 759 | goto out; |
589 | } | 760 | } |
590 | 761 | ||
591 | wil->scan_request = request; | 762 | vif->scan_request = request; |
592 | mod_timer(&wil->scan_timer, jiffies + WIL6210_SCAN_TO); | 763 | mod_timer(&vif->scan_timer, jiffies + WIL6210_SCAN_TO); |
593 | 764 | ||
594 | memset(&cmd, 0, sizeof(cmd)); | 765 | memset(&cmd, 0, sizeof(cmd)); |
595 | cmd.cmd.scan_type = WMI_ACTIVE_SCAN; | 766 | cmd.cmd.scan_type = WMI_ACTIVE_SCAN; |
@@ -616,7 +787,8 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, | |||
616 | else | 787 | else |
617 | wil_dbg_misc(wil, "Scan has no IE's\n"); | 788 | wil_dbg_misc(wil, "Scan has no IE's\n"); |
618 | 789 | ||
619 | rc = wmi_set_ie(wil, WMI_FRAME_PROBE_REQ, request->ie_len, request->ie); | 790 | rc = wmi_set_ie(vif, WMI_FRAME_PROBE_REQ, |
791 | request->ie_len, request->ie); | ||
620 | if (rc) | 792 | if (rc) |
621 | goto out_restore; | 793 | goto out_restore; |
622 | 794 | ||
@@ -625,15 +797,18 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, | |||
625 | wil_dbg_misc(wil, "active scan with discovery_mode=1\n"); | 797 | wil_dbg_misc(wil, "active scan with discovery_mode=1\n"); |
626 | } | 798 | } |
627 | 799 | ||
628 | wil->radio_wdev = wdev; | 800 | if (vif->mid == 0) |
629 | rc = wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) + | 801 | wil->radio_wdev = wdev; |
630 | cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0])); | 802 | rc = wmi_send(wil, WMI_START_SCAN_CMDID, vif->mid, |
803 | &cmd, sizeof(cmd.cmd) + | ||
804 | cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0])); | ||
631 | 805 | ||
632 | out_restore: | 806 | out_restore: |
633 | if (rc) { | 807 | if (rc) { |
634 | del_timer_sync(&wil->scan_timer); | 808 | del_timer_sync(&vif->scan_timer); |
635 | wil->radio_wdev = wil_to_wdev(wil); | 809 | if (vif->mid == 0) |
636 | wil->scan_request = NULL; | 810 | wil->radio_wdev = wil->main_ndev->ieee80211_ptr; |
811 | vif->scan_request = NULL; | ||
637 | } | 812 | } |
638 | out: | 813 | out: |
639 | mutex_unlock(&wil->mutex); | 814 | mutex_unlock(&wil->mutex); |
@@ -644,27 +819,28 @@ static void wil_cfg80211_abort_scan(struct wiphy *wiphy, | |||
644 | struct wireless_dev *wdev) | 819 | struct wireless_dev *wdev) |
645 | { | 820 | { |
646 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 821 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
822 | struct wil6210_vif *vif = wdev_to_vif(wil, wdev); | ||
647 | 823 | ||
648 | wil_dbg_misc(wil, "wdev=0x%p iftype=%d\n", wdev, wdev->iftype); | 824 | wil_dbg_misc(wil, "wdev=0x%p iftype=%d\n", wdev, wdev->iftype); |
649 | 825 | ||
650 | mutex_lock(&wil->mutex); | 826 | mutex_lock(&wil->mutex); |
651 | mutex_lock(&wil->p2p_wdev_mutex); | 827 | mutex_lock(&wil->vif_mutex); |
652 | 828 | ||
653 | if (!wil->scan_request) | 829 | if (!vif->scan_request) |
654 | goto out; | 830 | goto out; |
655 | 831 | ||
656 | if (wdev != wil->scan_request->wdev) { | 832 | if (wdev != vif->scan_request->wdev) { |
657 | wil_dbg_misc(wil, "abort scan was called on the wrong iface\n"); | 833 | wil_dbg_misc(wil, "abort scan was called on the wrong iface\n"); |
658 | goto out; | 834 | goto out; |
659 | } | 835 | } |
660 | 836 | ||
661 | if (wil->radio_wdev == wil->p2p_wdev) | 837 | if (wdev == wil->p2p_wdev && wil->radio_wdev == wil->p2p_wdev) |
662 | wil_p2p_stop_radio_operations(wil); | 838 | wil_p2p_stop_radio_operations(wil); |
663 | else | 839 | else |
664 | wil_abort_scan(wil, true); | 840 | wil_abort_scan(vif, true); |
665 | 841 | ||
666 | out: | 842 | out: |
667 | mutex_unlock(&wil->p2p_wdev_mutex); | 843 | mutex_unlock(&wil->vif_mutex); |
668 | mutex_unlock(&wil->mutex); | 844 | mutex_unlock(&wil->mutex); |
669 | } | 845 | } |
670 | 846 | ||
@@ -715,6 +891,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, | |||
715 | struct cfg80211_connect_params *sme) | 891 | struct cfg80211_connect_params *sme) |
716 | { | 892 | { |
717 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 893 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
894 | struct wil6210_vif *vif = ndev_to_vif(ndev); | ||
718 | struct cfg80211_bss *bss; | 895 | struct cfg80211_bss *bss; |
719 | struct wmi_connect_cmd conn; | 896 | struct wmi_connect_cmd conn; |
720 | const u8 *ssid_eid; | 897 | const u8 *ssid_eid; |
@@ -723,11 +900,11 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, | |||
723 | int rc = 0; | 900 | int rc = 0; |
724 | enum ieee80211_bss_type bss_type = IEEE80211_BSS_TYPE_ESS; | 901 | enum ieee80211_bss_type bss_type = IEEE80211_BSS_TYPE_ESS; |
725 | 902 | ||
726 | wil_dbg_misc(wil, "connect\n"); | 903 | wil_dbg_misc(wil, "connect, mid=%d\n", vif->mid); |
727 | wil_print_connect_params(wil, sme); | 904 | wil_print_connect_params(wil, sme); |
728 | 905 | ||
729 | if (test_bit(wil_status_fwconnecting, wil->status) || | 906 | if (test_bit(wil_vif_fwconnecting, vif->status) || |
730 | test_bit(wil_status_fwconnected, wil->status)) | 907 | test_bit(wil_vif_fwconnected, vif->status)) |
731 | return -EALREADY; | 908 | return -EALREADY; |
732 | 909 | ||
733 | if (sme->ie_len > WMI_MAX_IE_LEN) { | 910 | if (sme->ie_len > WMI_MAX_IE_LEN) { |
@@ -758,18 +935,18 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, | |||
758 | rc = -ENOENT; | 935 | rc = -ENOENT; |
759 | goto out; | 936 | goto out; |
760 | } | 937 | } |
761 | wil->privacy = sme->privacy; | 938 | vif->privacy = sme->privacy; |
762 | wil->pbss = sme->pbss; | 939 | vif->pbss = sme->pbss; |
763 | 940 | ||
764 | if (wil->privacy) { | 941 | if (vif->privacy) { |
765 | /* For secure assoc, remove old keys */ | 942 | /* For secure assoc, remove old keys */ |
766 | rc = wmi_del_cipher_key(wil, 0, bss->bssid, | 943 | rc = wmi_del_cipher_key(vif, 0, bss->bssid, |
767 | WMI_KEY_USE_PAIRWISE); | 944 | WMI_KEY_USE_PAIRWISE); |
768 | if (rc) { | 945 | if (rc) { |
769 | wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD(PTK) failed\n"); | 946 | wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD(PTK) failed\n"); |
770 | goto out; | 947 | goto out; |
771 | } | 948 | } |
772 | rc = wmi_del_cipher_key(wil, 0, bss->bssid, | 949 | rc = wmi_del_cipher_key(vif, 0, bss->bssid, |
773 | WMI_KEY_USE_RX_GROUP); | 950 | WMI_KEY_USE_RX_GROUP); |
774 | if (rc) { | 951 | if (rc) { |
775 | wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD(GTK) failed\n"); | 952 | wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD(GTK) failed\n"); |
@@ -781,7 +958,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, | |||
781 | * elements. Send it also in case it's empty, to erase previously set | 958 | * elements. Send it also in case it's empty, to erase previously set |
782 | * ies in FW. | 959 | * ies in FW. |
783 | */ | 960 | */ |
784 | rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie); | 961 | rc = wmi_set_ie(vif, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie); |
785 | if (rc) | 962 | if (rc) |
786 | goto out; | 963 | goto out; |
787 | 964 | ||
@@ -799,7 +976,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, | |||
799 | bss->capability); | 976 | bss->capability); |
800 | goto out; | 977 | goto out; |
801 | } | 978 | } |
802 | if (wil->privacy) { | 979 | if (vif->privacy) { |
803 | if (rsn_eid) { /* regular secure connection */ | 980 | if (rsn_eid) { /* regular secure connection */ |
804 | conn.dot11_auth_mode = WMI_AUTH11_SHARED; | 981 | conn.dot11_auth_mode = WMI_AUTH11_SHARED; |
805 | conn.auth_mode = WMI_AUTH_WPA2_PSK; | 982 | conn.auth_mode = WMI_AUTH_WPA2_PSK; |
@@ -831,18 +1008,19 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, | |||
831 | ether_addr_copy(conn.bssid, bss->bssid); | 1008 | ether_addr_copy(conn.bssid, bss->bssid); |
832 | ether_addr_copy(conn.dst_mac, bss->bssid); | 1009 | ether_addr_copy(conn.dst_mac, bss->bssid); |
833 | 1010 | ||
834 | set_bit(wil_status_fwconnecting, wil->status); | 1011 | set_bit(wil_vif_fwconnecting, vif->status); |
835 | 1012 | ||
836 | rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn)); | 1013 | rc = wmi_send(wil, WMI_CONNECT_CMDID, vif->mid, &conn, sizeof(conn)); |
837 | if (rc == 0) { | 1014 | if (rc == 0) { |
838 | netif_carrier_on(ndev); | 1015 | netif_carrier_on(ndev); |
839 | wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS); | 1016 | if (!wil_has_other_active_ifaces(wil, ndev, false, true)) |
840 | wil->bss = bss; | 1017 | wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS); |
1018 | vif->bss = bss; | ||
841 | /* Connect can take lots of time */ | 1019 | /* Connect can take lots of time */ |
842 | mod_timer(&wil->connect_timer, | 1020 | mod_timer(&vif->connect_timer, |
843 | jiffies + msecs_to_jiffies(5000)); | 1021 | jiffies + msecs_to_jiffies(5000)); |
844 | } else { | 1022 | } else { |
845 | clear_bit(wil_status_fwconnecting, wil->status); | 1023 | clear_bit(wil_vif_fwconnecting, vif->status); |
846 | } | 1024 | } |
847 | 1025 | ||
848 | out: | 1026 | out: |
@@ -857,17 +1035,19 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy, | |||
857 | { | 1035 | { |
858 | int rc; | 1036 | int rc; |
859 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 1037 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
1038 | struct wil6210_vif *vif = ndev_to_vif(ndev); | ||
860 | 1039 | ||
861 | wil_dbg_misc(wil, "disconnect: reason=%d\n", reason_code); | 1040 | wil_dbg_misc(wil, "disconnect: reason=%d, mid=%d\n", |
1041 | reason_code, vif->mid); | ||
862 | 1042 | ||
863 | if (!(test_bit(wil_status_fwconnecting, wil->status) || | 1043 | if (!(test_bit(wil_vif_fwconnecting, vif->status) || |
864 | test_bit(wil_status_fwconnected, wil->status))) { | 1044 | test_bit(wil_vif_fwconnected, vif->status))) { |
865 | wil_err(wil, "Disconnect was called while disconnected\n"); | 1045 | wil_err(wil, "Disconnect was called while disconnected\n"); |
866 | return 0; | 1046 | return 0; |
867 | } | 1047 | } |
868 | 1048 | ||
869 | wil->locally_generated_disc = true; | 1049 | vif->locally_generated_disc = true; |
870 | rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0, | 1050 | rc = wmi_call(wil, WMI_DISCONNECT_CMDID, vif->mid, NULL, 0, |
871 | WMI_DISCONNECT_EVENTID, NULL, 0, | 1051 | WMI_DISCONNECT_EVENTID, NULL, 0, |
872 | WIL6210_DISCONNECT_TO_MS); | 1052 | WIL6210_DISCONNECT_TO_MS); |
873 | if (rc) | 1053 | if (rc) |
@@ -903,6 +1083,7 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
903 | const u8 *buf = params->buf; | 1083 | const u8 *buf = params->buf; |
904 | size_t len = params->len, total; | 1084 | size_t len = params->len, total; |
905 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 1085 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
1086 | struct wil6210_vif *vif = wdev_to_vif(wil, wdev); | ||
906 | int rc; | 1087 | int rc; |
907 | bool tx_status = false; | 1088 | bool tx_status = false; |
908 | struct ieee80211_mgmt *mgmt_frame = (void *)buf; | 1089 | struct ieee80211_mgmt *mgmt_frame = (void *)buf; |
@@ -919,7 +1100,7 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
919 | * different from currently "listened" channel and fail if it is. | 1100 | * different from currently "listened" channel and fail if it is. |
920 | */ | 1101 | */ |
921 | 1102 | ||
922 | wil_dbg_misc(wil, "mgmt_tx\n"); | 1103 | wil_dbg_misc(wil, "mgmt_tx mid %d\n", vif->mid); |
923 | wil_hex_dump_misc("mgmt tx frame ", DUMP_PREFIX_OFFSET, 16, 1, buf, | 1104 | wil_hex_dump_misc("mgmt tx frame ", DUMP_PREFIX_OFFSET, 16, 1, buf, |
924 | len, true); | 1105 | len, true); |
925 | 1106 | ||
@@ -940,7 +1121,7 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
940 | cmd->len = cpu_to_le16(len); | 1121 | cmd->len = cpu_to_le16(len); |
941 | memcpy(cmd->payload, buf, len); | 1122 | memcpy(cmd->payload, buf, len); |
942 | 1123 | ||
943 | rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, cmd, total, | 1124 | rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, vif->mid, cmd, total, |
944 | WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000); | 1125 | WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000); |
945 | if (rc == 0) | 1126 | if (rc == 0) |
946 | tx_status = !evt.evt.status; | 1127 | tx_status = !evt.evt.status; |
@@ -962,10 +1143,10 @@ static int wil_cfg80211_set_channel(struct wiphy *wiphy, | |||
962 | return 0; | 1143 | return 0; |
963 | } | 1144 | } |
964 | 1145 | ||
965 | static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil, | 1146 | static enum wmi_key_usage wil_detect_key_usage(struct wireless_dev *wdev, |
966 | bool pairwise) | 1147 | bool pairwise) |
967 | { | 1148 | { |
968 | struct wireless_dev *wdev = wil_to_wdev(wil); | 1149 | struct wil6210_priv *wil = wdev_to_wil(wdev); |
969 | enum wmi_key_usage rc; | 1150 | enum wmi_key_usage rc; |
970 | 1151 | ||
971 | if (pairwise) { | 1152 | if (pairwise) { |
@@ -993,7 +1174,7 @@ static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil, | |||
993 | } | 1174 | } |
994 | 1175 | ||
995 | static struct wil_sta_info * | 1176 | static struct wil_sta_info * |
996 | wil_find_sta_by_key_usage(struct wil6210_priv *wil, | 1177 | wil_find_sta_by_key_usage(struct wil6210_priv *wil, u8 mid, |
997 | enum wmi_key_usage key_usage, const u8 *mac_addr) | 1178 | enum wmi_key_usage key_usage, const u8 *mac_addr) |
998 | { | 1179 | { |
999 | int cid = -EINVAL; | 1180 | int cid = -EINVAL; |
@@ -1003,9 +1184,9 @@ wil_find_sta_by_key_usage(struct wil6210_priv *wil, | |||
1003 | 1184 | ||
1004 | /* supplicant provides Rx group key in STA mode with NULL MAC address */ | 1185 | /* supplicant provides Rx group key in STA mode with NULL MAC address */ |
1005 | if (mac_addr) | 1186 | if (mac_addr) |
1006 | cid = wil_find_cid(wil, mac_addr); | 1187 | cid = wil_find_cid(wil, mid, mac_addr); |
1007 | else if (key_usage == WMI_KEY_USE_RX_GROUP) | 1188 | else if (key_usage == WMI_KEY_USE_RX_GROUP) |
1008 | cid = wil_find_cid_by_idx(wil, 0); | 1189 | cid = wil_find_cid_by_idx(wil, mid, 0); |
1009 | if (cid < 0) { | 1190 | if (cid < 0) { |
1010 | wil_err(wil, "No CID for %pM %s\n", mac_addr, | 1191 | wil_err(wil, "No CID for %pM %s\n", mac_addr, |
1011 | key_usage_str[key_usage]); | 1192 | key_usage_str[key_usage]); |
@@ -1082,9 +1263,12 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy, | |||
1082 | struct key_params *params) | 1263 | struct key_params *params) |
1083 | { | 1264 | { |
1084 | int rc; | 1265 | int rc; |
1266 | struct wil6210_vif *vif = ndev_to_vif(ndev); | ||
1085 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 1267 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
1086 | enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise); | 1268 | struct wireless_dev *wdev = vif_to_wdev(vif); |
1087 | struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, key_usage, | 1269 | enum wmi_key_usage key_usage = wil_detect_key_usage(wdev, pairwise); |
1270 | struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, vif->mid, | ||
1271 | key_usage, | ||
1088 | mac_addr); | 1272 | mac_addr); |
1089 | 1273 | ||
1090 | if (!params) { | 1274 | if (!params) { |
@@ -1114,7 +1298,7 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy, | |||
1114 | return -EINVAL; | 1298 | return -EINVAL; |
1115 | } | 1299 | } |
1116 | 1300 | ||
1117 | rc = wmi_add_cipher_key(wil, key_index, mac_addr, params->key_len, | 1301 | rc = wmi_add_cipher_key(vif, key_index, mac_addr, params->key_len, |
1118 | params->key, key_usage); | 1302 | params->key, key_usage); |
1119 | if (!rc) | 1303 | if (!rc) |
1120 | wil_set_crypto_rx(key_index, key_usage, cs, params); | 1304 | wil_set_crypto_rx(key_index, key_usage, cs, params); |
@@ -1127,9 +1311,12 @@ static int wil_cfg80211_del_key(struct wiphy *wiphy, | |||
1127 | u8 key_index, bool pairwise, | 1311 | u8 key_index, bool pairwise, |
1128 | const u8 *mac_addr) | 1312 | const u8 *mac_addr) |
1129 | { | 1313 | { |
1314 | struct wil6210_vif *vif = ndev_to_vif(ndev); | ||
1130 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 1315 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
1131 | enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise); | 1316 | struct wireless_dev *wdev = vif_to_wdev(vif); |
1132 | struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, key_usage, | 1317 | enum wmi_key_usage key_usage = wil_detect_key_usage(wdev, pairwise); |
1318 | struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, vif->mid, | ||
1319 | key_usage, | ||
1133 | mac_addr); | 1320 | mac_addr); |
1134 | 1321 | ||
1135 | wil_dbg_misc(wil, "del_key: %pM %s[%d]\n", mac_addr, | 1322 | wil_dbg_misc(wil, "del_key: %pM %s[%d]\n", mac_addr, |
@@ -1142,7 +1329,7 @@ static int wil_cfg80211_del_key(struct wiphy *wiphy, | |||
1142 | if (!IS_ERR_OR_NULL(cs)) | 1329 | if (!IS_ERR_OR_NULL(cs)) |
1143 | wil_del_rx_key(key_index, key_usage, cs); | 1330 | wil_del_rx_key(key_index, key_usage, cs); |
1144 | 1331 | ||
1145 | return wmi_del_cipher_key(wil, key_index, mac_addr, key_usage); | 1332 | return wmi_del_cipher_key(vif, key_index, mac_addr, key_usage); |
1146 | } | 1333 | } |
1147 | 1334 | ||
1148 | /* Need to be present or wiphy_new() will WARN */ | 1335 | /* Need to be present or wiphy_new() will WARN */ |
@@ -1179,10 +1366,11 @@ static int wil_cancel_remain_on_channel(struct wiphy *wiphy, | |||
1179 | u64 cookie) | 1366 | u64 cookie) |
1180 | { | 1367 | { |
1181 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 1368 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
1369 | struct wil6210_vif *vif = wdev_to_vif(wil, wdev); | ||
1182 | 1370 | ||
1183 | wil_dbg_misc(wil, "cancel_remain_on_channel\n"); | 1371 | wil_dbg_misc(wil, "cancel_remain_on_channel\n"); |
1184 | 1372 | ||
1185 | return wil_p2p_cancel_listen(wil, cookie); | 1373 | return wil_p2p_cancel_listen(vif, cookie); |
1186 | } | 1374 | } |
1187 | 1375 | ||
1188 | /** | 1376 | /** |
@@ -1275,11 +1463,10 @@ static void wil_print_bcon_data(struct cfg80211_beacon_data *b) | |||
1275 | } | 1463 | } |
1276 | 1464 | ||
1277 | /* internal functions for device reset and starting AP */ | 1465 | /* internal functions for device reset and starting AP */ |
1278 | static int _wil_cfg80211_set_ies(struct wiphy *wiphy, | 1466 | static int _wil_cfg80211_set_ies(struct wil6210_vif *vif, |
1279 | struct cfg80211_beacon_data *bcon) | 1467 | struct cfg80211_beacon_data *bcon) |
1280 | { | 1468 | { |
1281 | int rc; | 1469 | int rc; |
1282 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
1283 | u16 len = 0, proberesp_len = 0; | 1470 | u16 len = 0, proberesp_len = 0; |
1284 | u8 *ies = NULL, *proberesp = NULL; | 1471 | u8 *ies = NULL, *proberesp = NULL; |
1285 | 1472 | ||
@@ -1300,20 +1487,21 @@ static int _wil_cfg80211_set_ies(struct wiphy *wiphy, | |||
1300 | if (rc) | 1487 | if (rc) |
1301 | goto out; | 1488 | goto out; |
1302 | 1489 | ||
1303 | rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, len, ies); | 1490 | rc = wmi_set_ie(vif, WMI_FRAME_PROBE_RESP, len, ies); |
1304 | if (rc) | 1491 | if (rc) |
1305 | goto out; | 1492 | goto out; |
1306 | 1493 | ||
1307 | if (bcon->assocresp_ies) | 1494 | if (bcon->assocresp_ies) |
1308 | rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, | 1495 | rc = wmi_set_ie(vif, WMI_FRAME_ASSOC_RESP, |
1309 | bcon->assocresp_ies_len, bcon->assocresp_ies); | 1496 | bcon->assocresp_ies_len, bcon->assocresp_ies); |
1310 | else | 1497 | else |
1311 | rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, len, ies); | 1498 | rc = wmi_set_ie(vif, WMI_FRAME_ASSOC_RESP, len, ies); |
1312 | #if 0 /* to use beacon IE's, remove this #if 0 */ | 1499 | #if 0 /* to use beacon IE's, remove this #if 0 */ |
1313 | if (rc) | 1500 | if (rc) |
1314 | goto out; | 1501 | goto out; |
1315 | 1502 | ||
1316 | rc = wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->tail_len, bcon->tail); | 1503 | rc = wmi_set_ie(vif, WMI_FRAME_BEACON, |
1504 | bcon->tail_len, bcon->tail); | ||
1317 | #endif | 1505 | #endif |
1318 | out: | 1506 | out: |
1319 | kfree(ies); | 1507 | kfree(ies); |
@@ -1328,6 +1516,7 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy, | |||
1328 | u8 hidden_ssid, u32 pbss) | 1516 | u8 hidden_ssid, u32 pbss) |
1329 | { | 1517 | { |
1330 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 1518 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
1519 | struct wil6210_vif *vif = ndev_to_vif(ndev); | ||
1331 | int rc; | 1520 | int rc; |
1332 | struct wireless_dev *wdev = ndev->ieee80211_ptr; | 1521 | struct wireless_dev *wdev = ndev->ieee80211_ptr; |
1333 | u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); | 1522 | u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); |
@@ -1336,7 +1525,7 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy, | |||
1336 | if (pbss) | 1525 | if (pbss) |
1337 | wmi_nettype = WMI_NETTYPE_P2P; | 1526 | wmi_nettype = WMI_NETTYPE_P2P; |
1338 | 1527 | ||
1339 | wil_dbg_misc(wil, "start_ap: is_go=%d\n", is_go); | 1528 | wil_dbg_misc(wil, "start_ap: mid=%d, is_go=%d\n", vif->mid, is_go); |
1340 | if (is_go && !pbss) { | 1529 | if (is_go && !pbss) { |
1341 | wil_err(wil, "P2P GO must be in PBSS\n"); | 1530 | wil_err(wil, "P2P GO must be in PBSS\n"); |
1342 | return -ENOTSUPP; | 1531 | return -ENOTSUPP; |
@@ -1346,42 +1535,46 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy, | |||
1346 | 1535 | ||
1347 | mutex_lock(&wil->mutex); | 1536 | mutex_lock(&wil->mutex); |
1348 | 1537 | ||
1349 | __wil_down(wil); | 1538 | if (!wil_has_other_active_ifaces(wil, ndev, true, false)) { |
1350 | rc = __wil_up(wil); | 1539 | __wil_down(wil); |
1351 | if (rc) | 1540 | rc = __wil_up(wil); |
1352 | goto out; | 1541 | if (rc) |
1542 | goto out; | ||
1543 | } | ||
1353 | 1544 | ||
1354 | rc = wmi_set_ssid(wil, ssid_len, ssid); | 1545 | rc = wmi_set_ssid(vif, ssid_len, ssid); |
1355 | if (rc) | 1546 | if (rc) |
1356 | goto out; | 1547 | goto out; |
1357 | 1548 | ||
1358 | rc = _wil_cfg80211_set_ies(wiphy, bcon); | 1549 | rc = _wil_cfg80211_set_ies(vif, bcon); |
1359 | if (rc) | 1550 | if (rc) |
1360 | goto out; | 1551 | goto out; |
1361 | 1552 | ||
1362 | wil->privacy = privacy; | 1553 | vif->privacy = privacy; |
1363 | wil->channel = chan; | 1554 | vif->channel = chan; |
1364 | wil->hidden_ssid = hidden_ssid; | 1555 | vif->hidden_ssid = hidden_ssid; |
1365 | wil->pbss = pbss; | 1556 | vif->pbss = pbss; |
1366 | 1557 | ||
1367 | netif_carrier_on(ndev); | 1558 | netif_carrier_on(ndev); |
1368 | wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS); | 1559 | if (!wil_has_other_active_ifaces(wil, ndev, false, true)) |
1560 | wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS); | ||
1369 | 1561 | ||
1370 | rc = wmi_pcp_start(wil, bi, wmi_nettype, chan, hidden_ssid, is_go); | 1562 | rc = wmi_pcp_start(vif, bi, wmi_nettype, chan, hidden_ssid, is_go); |
1371 | if (rc) | 1563 | if (rc) |
1372 | goto err_pcp_start; | 1564 | goto err_pcp_start; |
1373 | 1565 | ||
1374 | rc = wil_bcast_init(wil); | 1566 | rc = wil_bcast_init(vif); |
1375 | if (rc) | 1567 | if (rc) |
1376 | goto err_bcast; | 1568 | goto err_bcast; |
1377 | 1569 | ||
1378 | goto out; /* success */ | 1570 | goto out; /* success */ |
1379 | 1571 | ||
1380 | err_bcast: | 1572 | err_bcast: |
1381 | wmi_pcp_stop(wil); | 1573 | wmi_pcp_stop(vif); |
1382 | err_pcp_start: | 1574 | err_pcp_start: |
1383 | netif_carrier_off(ndev); | 1575 | netif_carrier_off(ndev); |
1384 | wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS); | 1576 | if (!wil_has_other_active_ifaces(wil, ndev, false, true)) |
1577 | wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS); | ||
1385 | out: | 1578 | out: |
1386 | mutex_unlock(&wil->mutex); | 1579 | mutex_unlock(&wil->mutex); |
1387 | return rc; | 1580 | return rc; |
@@ -1392,10 +1585,11 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy, | |||
1392 | struct cfg80211_beacon_data *bcon) | 1585 | struct cfg80211_beacon_data *bcon) |
1393 | { | 1586 | { |
1394 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 1587 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
1588 | struct wil6210_vif *vif = ndev_to_vif(ndev); | ||
1395 | int rc; | 1589 | int rc; |
1396 | u32 privacy = 0; | 1590 | u32 privacy = 0; |
1397 | 1591 | ||
1398 | wil_dbg_misc(wil, "change_beacon\n"); | 1592 | wil_dbg_misc(wil, "change_beacon, mid=%d\n", vif->mid); |
1399 | wil_print_bcon_data(bcon); | 1593 | wil_print_bcon_data(bcon); |
1400 | 1594 | ||
1401 | if (bcon->tail && | 1595 | if (bcon->tail && |
@@ -1404,20 +1598,20 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy, | |||
1404 | privacy = 1; | 1598 | privacy = 1; |
1405 | 1599 | ||
1406 | /* in case privacy has changed, need to restart the AP */ | 1600 | /* in case privacy has changed, need to restart the AP */ |
1407 | if (wil->privacy != privacy) { | 1601 | if (vif->privacy != privacy) { |
1408 | struct wireless_dev *wdev = ndev->ieee80211_ptr; | 1602 | struct wireless_dev *wdev = ndev->ieee80211_ptr; |
1409 | 1603 | ||
1410 | wil_dbg_misc(wil, "privacy changed %d=>%d. Restarting AP\n", | 1604 | wil_dbg_misc(wil, "privacy changed %d=>%d. Restarting AP\n", |
1411 | wil->privacy, privacy); | 1605 | vif->privacy, privacy); |
1412 | 1606 | ||
1413 | rc = _wil_cfg80211_start_ap(wiphy, ndev, wdev->ssid, | 1607 | rc = _wil_cfg80211_start_ap(wiphy, ndev, wdev->ssid, |
1414 | wdev->ssid_len, privacy, | 1608 | wdev->ssid_len, privacy, |
1415 | wdev->beacon_interval, | 1609 | wdev->beacon_interval, |
1416 | wil->channel, bcon, | 1610 | vif->channel, bcon, |
1417 | wil->hidden_ssid, | 1611 | vif->hidden_ssid, |
1418 | wil->pbss); | 1612 | vif->pbss); |
1419 | } else { | 1613 | } else { |
1420 | rc = _wil_cfg80211_set_ies(wiphy, bcon); | 1614 | rc = _wil_cfg80211_set_ies(vif, bcon); |
1421 | } | 1615 | } |
1422 | 1616 | ||
1423 | return rc; | 1617 | return rc; |
@@ -1484,20 +1678,27 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy, | |||
1484 | struct net_device *ndev) | 1678 | struct net_device *ndev) |
1485 | { | 1679 | { |
1486 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 1680 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
1681 | struct wil6210_vif *vif = ndev_to_vif(ndev); | ||
1682 | bool last; | ||
1487 | 1683 | ||
1488 | wil_dbg_misc(wil, "stop_ap\n"); | 1684 | wil_dbg_misc(wil, "stop_ap, mid=%d\n", vif->mid); |
1489 | 1685 | ||
1490 | netif_carrier_off(ndev); | 1686 | netif_carrier_off(ndev); |
1491 | wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS); | 1687 | last = !wil_has_other_active_ifaces(wil, ndev, false, true); |
1492 | wil_set_recovery_state(wil, fw_recovery_idle); | 1688 | if (last) { |
1493 | 1689 | wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS); | |
1494 | set_bit(wil_status_resetting, wil->status); | 1690 | wil_set_recovery_state(wil, fw_recovery_idle); |
1691 | set_bit(wil_status_resetting, wil->status); | ||
1692 | } | ||
1495 | 1693 | ||
1496 | mutex_lock(&wil->mutex); | 1694 | mutex_lock(&wil->mutex); |
1497 | 1695 | ||
1498 | wmi_pcp_stop(wil); | 1696 | wmi_pcp_stop(vif); |
1499 | 1697 | ||
1500 | __wil_down(wil); | 1698 | if (last) |
1699 | __wil_down(wil); | ||
1700 | else | ||
1701 | wil_bcast_fini(vif); | ||
1501 | 1702 | ||
1502 | mutex_unlock(&wil->mutex); | 1703 | mutex_unlock(&wil->mutex); |
1503 | 1704 | ||
@@ -1509,9 +1710,11 @@ static int wil_cfg80211_add_station(struct wiphy *wiphy, | |||
1509 | const u8 *mac, | 1710 | const u8 *mac, |
1510 | struct station_parameters *params) | 1711 | struct station_parameters *params) |
1511 | { | 1712 | { |
1713 | struct wil6210_vif *vif = ndev_to_vif(dev); | ||
1512 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 1714 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
1513 | 1715 | ||
1514 | wil_dbg_misc(wil, "add station %pM aid %d\n", mac, params->aid); | 1716 | wil_dbg_misc(wil, "add station %pM aid %d mid %d\n", |
1717 | mac, params->aid, vif->mid); | ||
1515 | 1718 | ||
1516 | if (!disable_ap_sme) { | 1719 | if (!disable_ap_sme) { |
1517 | wil_err(wil, "not supported with AP SME enabled\n"); | 1720 | wil_err(wil, "not supported with AP SME enabled\n"); |
@@ -1523,20 +1726,21 @@ static int wil_cfg80211_add_station(struct wiphy *wiphy, | |||
1523 | return -EINVAL; | 1726 | return -EINVAL; |
1524 | } | 1727 | } |
1525 | 1728 | ||
1526 | return wmi_new_sta(wil, mac, params->aid); | 1729 | return wmi_new_sta(vif, mac, params->aid); |
1527 | } | 1730 | } |
1528 | 1731 | ||
1529 | static int wil_cfg80211_del_station(struct wiphy *wiphy, | 1732 | static int wil_cfg80211_del_station(struct wiphy *wiphy, |
1530 | struct net_device *dev, | 1733 | struct net_device *dev, |
1531 | struct station_del_parameters *params) | 1734 | struct station_del_parameters *params) |
1532 | { | 1735 | { |
1736 | struct wil6210_vif *vif = ndev_to_vif(dev); | ||
1533 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 1737 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
1534 | 1738 | ||
1535 | wil_dbg_misc(wil, "del_station: %pM, reason=%d\n", params->mac, | 1739 | wil_dbg_misc(wil, "del_station: %pM, reason=%d mid=%d\n", |
1536 | params->reason_code); | 1740 | params->mac, params->reason_code, vif->mid); |
1537 | 1741 | ||
1538 | mutex_lock(&wil->mutex); | 1742 | mutex_lock(&wil->mutex); |
1539 | wil6210_disconnect(wil, params->mac, params->reason_code, false); | 1743 | wil6210_disconnect(vif, params->mac, params->reason_code, false); |
1540 | mutex_unlock(&wil->mutex); | 1744 | mutex_unlock(&wil->mutex); |
1541 | 1745 | ||
1542 | return 0; | 1746 | return 0; |
@@ -1547,13 +1751,15 @@ static int wil_cfg80211_change_station(struct wiphy *wiphy, | |||
1547 | const u8 *mac, | 1751 | const u8 *mac, |
1548 | struct station_parameters *params) | 1752 | struct station_parameters *params) |
1549 | { | 1753 | { |
1754 | struct wil6210_vif *vif = ndev_to_vif(dev); | ||
1550 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 1755 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
1551 | int authorize; | 1756 | int authorize; |
1552 | int cid, i; | 1757 | int cid, i; |
1553 | struct vring_tx_data *txdata = NULL; | 1758 | struct vring_tx_data *txdata = NULL; |
1554 | 1759 | ||
1555 | wil_dbg_misc(wil, "change station %pM mask 0x%x set 0x%x\n", mac, | 1760 | wil_dbg_misc(wil, "change station %pM mask 0x%x set 0x%x mid %d\n", |
1556 | params->sta_flags_mask, params->sta_flags_set); | 1761 | mac, params->sta_flags_mask, params->sta_flags_set, |
1762 | vif->mid); | ||
1557 | 1763 | ||
1558 | if (!disable_ap_sme) { | 1764 | if (!disable_ap_sme) { |
1559 | wil_dbg_misc(wil, "not supported with AP SME enabled\n"); | 1765 | wil_dbg_misc(wil, "not supported with AP SME enabled\n"); |
@@ -1563,7 +1769,7 @@ static int wil_cfg80211_change_station(struct wiphy *wiphy, | |||
1563 | if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))) | 1769 | if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))) |
1564 | return 0; | 1770 | return 0; |
1565 | 1771 | ||
1566 | cid = wil_find_cid(wil, mac); | 1772 | cid = wil_find_cid(wil, vif->mid, mac); |
1567 | if (cid < 0) { | 1773 | if (cid < 0) { |
1568 | wil_err(wil, "station not found\n"); | 1774 | wil_err(wil, "station not found\n"); |
1569 | return -ENOLINK; | 1775 | return -ENOLINK; |
@@ -1590,9 +1796,10 @@ static int wil_cfg80211_change_station(struct wiphy *wiphy, | |||
1590 | 1796 | ||
1591 | /* probe_client handling */ | 1797 | /* probe_client handling */ |
1592 | static void wil_probe_client_handle(struct wil6210_priv *wil, | 1798 | static void wil_probe_client_handle(struct wil6210_priv *wil, |
1799 | struct wil6210_vif *vif, | ||
1593 | struct wil_probe_client_req *req) | 1800 | struct wil_probe_client_req *req) |
1594 | { | 1801 | { |
1595 | struct net_device *ndev = wil_to_ndev(wil); | 1802 | struct net_device *ndev = vif_to_ndev(vif); |
1596 | struct wil_sta_info *sta = &wil->sta[req->cid]; | 1803 | struct wil_sta_info *sta = &wil->sta[req->cid]; |
1597 | /* assume STA is alive if it is still connected, | 1804 | /* assume STA is alive if it is still connected, |
1598 | * else FW will disconnect it | 1805 | * else FW will disconnect it |
@@ -1603,51 +1810,53 @@ static void wil_probe_client_handle(struct wil6210_priv *wil, | |||
1603 | 0, false, GFP_KERNEL); | 1810 | 0, false, GFP_KERNEL); |
1604 | } | 1811 | } |
1605 | 1812 | ||
1606 | static struct list_head *next_probe_client(struct wil6210_priv *wil) | 1813 | static struct list_head *next_probe_client(struct wil6210_vif *vif) |
1607 | { | 1814 | { |
1608 | struct list_head *ret = NULL; | 1815 | struct list_head *ret = NULL; |
1609 | 1816 | ||
1610 | mutex_lock(&wil->probe_client_mutex); | 1817 | mutex_lock(&vif->probe_client_mutex); |
1611 | 1818 | ||
1612 | if (!list_empty(&wil->probe_client_pending)) { | 1819 | if (!list_empty(&vif->probe_client_pending)) { |
1613 | ret = wil->probe_client_pending.next; | 1820 | ret = vif->probe_client_pending.next; |
1614 | list_del(ret); | 1821 | list_del(ret); |
1615 | } | 1822 | } |
1616 | 1823 | ||
1617 | mutex_unlock(&wil->probe_client_mutex); | 1824 | mutex_unlock(&vif->probe_client_mutex); |
1618 | 1825 | ||
1619 | return ret; | 1826 | return ret; |
1620 | } | 1827 | } |
1621 | 1828 | ||
1622 | void wil_probe_client_worker(struct work_struct *work) | 1829 | void wil_probe_client_worker(struct work_struct *work) |
1623 | { | 1830 | { |
1624 | struct wil6210_priv *wil = container_of(work, struct wil6210_priv, | 1831 | struct wil6210_vif *vif = container_of(work, struct wil6210_vif, |
1625 | probe_client_worker); | 1832 | probe_client_worker); |
1833 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1626 | struct wil_probe_client_req *req; | 1834 | struct wil_probe_client_req *req; |
1627 | struct list_head *lh; | 1835 | struct list_head *lh; |
1628 | 1836 | ||
1629 | while ((lh = next_probe_client(wil)) != NULL) { | 1837 | while ((lh = next_probe_client(vif)) != NULL) { |
1630 | req = list_entry(lh, struct wil_probe_client_req, list); | 1838 | req = list_entry(lh, struct wil_probe_client_req, list); |
1631 | 1839 | ||
1632 | wil_probe_client_handle(wil, req); | 1840 | wil_probe_client_handle(wil, vif, req); |
1633 | kfree(req); | 1841 | kfree(req); |
1634 | } | 1842 | } |
1635 | } | 1843 | } |
1636 | 1844 | ||
1637 | void wil_probe_client_flush(struct wil6210_priv *wil) | 1845 | void wil_probe_client_flush(struct wil6210_vif *vif) |
1638 | { | 1846 | { |
1639 | struct wil_probe_client_req *req, *t; | 1847 | struct wil_probe_client_req *req, *t; |
1848 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1640 | 1849 | ||
1641 | wil_dbg_misc(wil, "probe_client_flush\n"); | 1850 | wil_dbg_misc(wil, "probe_client_flush\n"); |
1642 | 1851 | ||
1643 | mutex_lock(&wil->probe_client_mutex); | 1852 | mutex_lock(&vif->probe_client_mutex); |
1644 | 1853 | ||
1645 | list_for_each_entry_safe(req, t, &wil->probe_client_pending, list) { | 1854 | list_for_each_entry_safe(req, t, &vif->probe_client_pending, list) { |
1646 | list_del(&req->list); | 1855 | list_del(&req->list); |
1647 | kfree(req); | 1856 | kfree(req); |
1648 | } | 1857 | } |
1649 | 1858 | ||
1650 | mutex_unlock(&wil->probe_client_mutex); | 1859 | mutex_unlock(&vif->probe_client_mutex); |
1651 | } | 1860 | } |
1652 | 1861 | ||
1653 | static int wil_cfg80211_probe_client(struct wiphy *wiphy, | 1862 | static int wil_cfg80211_probe_client(struct wiphy *wiphy, |
@@ -1655,10 +1864,12 @@ static int wil_cfg80211_probe_client(struct wiphy *wiphy, | |||
1655 | const u8 *peer, u64 *cookie) | 1864 | const u8 *peer, u64 *cookie) |
1656 | { | 1865 | { |
1657 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 1866 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
1867 | struct wil6210_vif *vif = ndev_to_vif(dev); | ||
1658 | struct wil_probe_client_req *req; | 1868 | struct wil_probe_client_req *req; |
1659 | int cid = wil_find_cid(wil, peer); | 1869 | int cid = wil_find_cid(wil, vif->mid, peer); |
1660 | 1870 | ||
1661 | wil_dbg_misc(wil, "probe_client: %pM => CID %d\n", peer, cid); | 1871 | wil_dbg_misc(wil, "probe_client: %pM => CID %d MID %d\n", |
1872 | peer, cid, vif->mid); | ||
1662 | 1873 | ||
1663 | if (cid < 0) | 1874 | if (cid < 0) |
1664 | return -ENOLINK; | 1875 | return -ENOLINK; |
@@ -1670,12 +1881,12 @@ static int wil_cfg80211_probe_client(struct wiphy *wiphy, | |||
1670 | req->cid = cid; | 1881 | req->cid = cid; |
1671 | req->cookie = cid; | 1882 | req->cookie = cid; |
1672 | 1883 | ||
1673 | mutex_lock(&wil->probe_client_mutex); | 1884 | mutex_lock(&vif->probe_client_mutex); |
1674 | list_add_tail(&req->list, &wil->probe_client_pending); | 1885 | list_add_tail(&req->list, &vif->probe_client_pending); |
1675 | mutex_unlock(&wil->probe_client_mutex); | 1886 | mutex_unlock(&vif->probe_client_mutex); |
1676 | 1887 | ||
1677 | *cookie = req->cookie; | 1888 | *cookie = req->cookie; |
1678 | queue_work(wil->wq_service, &wil->probe_client_worker); | 1889 | queue_work(wil->wq_service, &vif->probe_client_worker); |
1679 | return 0; | 1890 | return 0; |
1680 | } | 1891 | } |
1681 | 1892 | ||
@@ -1684,11 +1895,12 @@ static int wil_cfg80211_change_bss(struct wiphy *wiphy, | |||
1684 | struct bss_parameters *params) | 1895 | struct bss_parameters *params) |
1685 | { | 1896 | { |
1686 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 1897 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
1898 | struct wil6210_vif *vif = ndev_to_vif(dev); | ||
1687 | 1899 | ||
1688 | if (params->ap_isolate >= 0) { | 1900 | if (params->ap_isolate >= 0) { |
1689 | wil_dbg_misc(wil, "change_bss: ap_isolate %d => %d\n", | 1901 | wil_dbg_misc(wil, "change_bss: ap_isolate MID %d, %d => %d\n", |
1690 | wil->ap_isolate, params->ap_isolate); | 1902 | vif->mid, vif->ap_isolate, params->ap_isolate); |
1691 | wil->ap_isolate = params->ap_isolate; | 1903 | vif->ap_isolate = params->ap_isolate; |
1692 | } | 1904 | } |
1693 | 1905 | ||
1694 | return 0; | 1906 | return 0; |
@@ -1732,10 +1944,10 @@ static int wil_cfg80211_suspend(struct wiphy *wiphy, | |||
1732 | wil_dbg_pm(wil, "suspending\n"); | 1944 | wil_dbg_pm(wil, "suspending\n"); |
1733 | 1945 | ||
1734 | mutex_lock(&wil->mutex); | 1946 | mutex_lock(&wil->mutex); |
1735 | mutex_lock(&wil->p2p_wdev_mutex); | 1947 | mutex_lock(&wil->vif_mutex); |
1736 | wil_p2p_stop_radio_operations(wil); | 1948 | wil_p2p_stop_radio_operations(wil); |
1737 | wil_abort_scan(wil, true); | 1949 | wil_abort_scan_all_vifs(wil, true); |
1738 | mutex_unlock(&wil->p2p_wdev_mutex); | 1950 | mutex_unlock(&wil->vif_mutex); |
1739 | mutex_unlock(&wil->mutex); | 1951 | mutex_unlock(&wil->mutex); |
1740 | 1952 | ||
1741 | out: | 1953 | out: |
@@ -1757,8 +1969,12 @@ wil_cfg80211_sched_scan_start(struct wiphy *wiphy, | |||
1757 | struct cfg80211_sched_scan_request *request) | 1969 | struct cfg80211_sched_scan_request *request) |
1758 | { | 1970 | { |
1759 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 1971 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
1972 | struct wil6210_vif *vif = ndev_to_vif(dev); | ||
1760 | int i, rc; | 1973 | int i, rc; |
1761 | 1974 | ||
1975 | if (vif->mid != 0) | ||
1976 | return -EOPNOTSUPP; | ||
1977 | |||
1762 | wil_dbg_misc(wil, | 1978 | wil_dbg_misc(wil, |
1763 | "sched scan start: n_ssids %d, ie_len %zu, flags 0x%x\n", | 1979 | "sched scan start: n_ssids %d, ie_len %zu, flags 0x%x\n", |
1764 | request->n_ssids, request->ie_len, request->flags); | 1980 | request->n_ssids, request->ie_len, request->flags); |
@@ -1792,7 +2008,8 @@ wil_cfg80211_sched_scan_start(struct wiphy *wiphy, | |||
1792 | i, sp->interval, sp->iterations); | 2008 | i, sp->interval, sp->iterations); |
1793 | } | 2009 | } |
1794 | 2010 | ||
1795 | rc = wmi_set_ie(wil, WMI_FRAME_PROBE_REQ, request->ie_len, request->ie); | 2011 | rc = wmi_set_ie(vif, WMI_FRAME_PROBE_REQ, |
2012 | request->ie_len, request->ie); | ||
1796 | if (rc) | 2013 | if (rc) |
1797 | return rc; | 2014 | return rc; |
1798 | return wmi_start_sched_scan(wil, request); | 2015 | return wmi_start_sched_scan(wil, request); |
@@ -1803,8 +2020,12 @@ wil_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev, | |||
1803 | u64 reqid) | 2020 | u64 reqid) |
1804 | { | 2021 | { |
1805 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 2022 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
2023 | struct wil6210_vif *vif = ndev_to_vif(dev); | ||
1806 | int rc; | 2024 | int rc; |
1807 | 2025 | ||
2026 | if (vif->mid != 0) | ||
2027 | return -EOPNOTSUPP; | ||
2028 | |||
1808 | rc = wmi_stop_sched_scan(wil); | 2029 | rc = wmi_stop_sched_scan(wil); |
1809 | /* device would return error if it thinks PNO is already stopped. | 2030 | /* device would return error if it thinks PNO is already stopped. |
1810 | * ignore the return code so user space and driver gets back in-sync | 2031 | * ignore the return code so user space and driver gets back in-sync |
@@ -1893,57 +2114,132 @@ static void wil_wiphy_init(struct wiphy *wiphy) | |||
1893 | #endif | 2114 | #endif |
1894 | } | 2115 | } |
1895 | 2116 | ||
1896 | struct wireless_dev *wil_cfg80211_init(struct device *dev) | 2117 | int wil_cfg80211_iface_combinations_from_fw( |
2118 | struct wil6210_priv *wil, const struct wil_fw_record_concurrency *conc) | ||
1897 | { | 2119 | { |
1898 | int rc = 0; | 2120 | struct wiphy *wiphy = wil_to_wiphy(wil); |
1899 | struct wireless_dev *wdev; | 2121 | u32 total_limits = 0; |
2122 | u16 n_combos; | ||
2123 | const struct wil_fw_concurrency_combo *combo; | ||
2124 | const struct wil_fw_concurrency_limit *limit; | ||
2125 | struct ieee80211_iface_combination *iface_combinations; | ||
2126 | struct ieee80211_iface_limit *iface_limit; | ||
2127 | int i, j; | ||
2128 | |||
2129 | if (wiphy->iface_combinations) { | ||
2130 | wil_dbg_misc(wil, "iface_combinations already set, skipping\n"); | ||
2131 | return 0; | ||
2132 | } | ||
1900 | 2133 | ||
1901 | dev_dbg(dev, "%s()\n", __func__); | 2134 | combo = conc->combos; |
2135 | n_combos = le16_to_cpu(conc->n_combos); | ||
2136 | for (i = 0; i < n_combos; i++) { | ||
2137 | total_limits += combo->n_limits; | ||
2138 | limit = combo->limits + combo->n_limits; | ||
2139 | combo = (struct wil_fw_concurrency_combo *)limit; | ||
2140 | } | ||
1902 | 2141 | ||
1903 | wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); | 2142 | iface_combinations = |
1904 | if (!wdev) | 2143 | kzalloc(n_combos * sizeof(struct ieee80211_iface_combination) + |
1905 | return ERR_PTR(-ENOMEM); | 2144 | total_limits * sizeof(struct ieee80211_iface_limit), |
2145 | GFP_KERNEL); | ||
2146 | if (!iface_combinations) | ||
2147 | return -ENOMEM; | ||
2148 | iface_limit = (struct ieee80211_iface_limit *)(iface_combinations + | ||
2149 | n_combos); | ||
2150 | combo = conc->combos; | ||
2151 | for (i = 0; i < n_combos; i++) { | ||
2152 | iface_combinations[i].max_interfaces = combo->max_interfaces; | ||
2153 | iface_combinations[i].num_different_channels = | ||
2154 | combo->n_diff_channels; | ||
2155 | iface_combinations[i].beacon_int_infra_match = | ||
2156 | combo->same_bi; | ||
2157 | iface_combinations[i].n_limits = combo->n_limits; | ||
2158 | wil_dbg_misc(wil, | ||
2159 | "iface_combination %d: max_if %d, num_ch %d, bi_match %d\n", | ||
2160 | i, iface_combinations[i].max_interfaces, | ||
2161 | iface_combinations[i].num_different_channels, | ||
2162 | iface_combinations[i].beacon_int_infra_match); | ||
2163 | limit = combo->limits; | ||
2164 | for (j = 0; j < combo->n_limits; j++) { | ||
2165 | iface_limit[j].max = le16_to_cpu(limit[j].max); | ||
2166 | iface_limit[j].types = le16_to_cpu(limit[j].types); | ||
2167 | wil_dbg_misc(wil, | ||
2168 | "limit %d: max %d types 0x%x\n", j, | ||
2169 | iface_limit[j].max, iface_limit[j].types); | ||
2170 | } | ||
2171 | iface_combinations[i].limits = iface_limit; | ||
2172 | iface_limit += combo->n_limits; | ||
2173 | limit += combo->n_limits; | ||
2174 | combo = (struct wil_fw_concurrency_combo *)limit; | ||
2175 | } | ||
1906 | 2176 | ||
1907 | wdev->wiphy = wiphy_new(&wil_cfg80211_ops, | 2177 | wil_dbg_misc(wil, "multiple VIFs supported, n_mids %d\n", conc->n_mids); |
1908 | sizeof(struct wil6210_priv)); | 2178 | wil->max_vifs = conc->n_mids + 1; /* including main interface */ |
1909 | if (!wdev->wiphy) { | 2179 | if (wil->max_vifs > WIL_MAX_VIFS) { |
1910 | rc = -ENOMEM; | 2180 | wil_info(wil, "limited number of VIFs supported(%d, FW %d)\n", |
1911 | goto out; | 2181 | WIL_MAX_VIFS, wil->max_vifs); |
2182 | wil->max_vifs = WIL_MAX_VIFS; | ||
1912 | } | 2183 | } |
2184 | wiphy->n_iface_combinations = n_combos; | ||
2185 | wiphy->iface_combinations = iface_combinations; | ||
2186 | return 0; | ||
2187 | } | ||
1913 | 2188 | ||
1914 | set_wiphy_dev(wdev->wiphy, dev); | 2189 | struct wil6210_priv *wil_cfg80211_init(struct device *dev) |
1915 | wil_wiphy_init(wdev->wiphy); | 2190 | { |
2191 | struct wiphy *wiphy; | ||
2192 | struct wil6210_priv *wil; | ||
2193 | struct ieee80211_channel *ch; | ||
1916 | 2194 | ||
1917 | return wdev; | 2195 | dev_dbg(dev, "%s()\n", __func__); |
1918 | 2196 | ||
1919 | out: | 2197 | /* Note: the wireless_dev structure is no longer allocated here. |
1920 | kfree(wdev); | 2198 | * Instead, it is allocated as part of the net_device structure |
2199 | * for main interface and each VIF. | ||
2200 | */ | ||
2201 | wiphy = wiphy_new(&wil_cfg80211_ops, sizeof(struct wil6210_priv)); | ||
2202 | if (!wiphy) | ||
2203 | return ERR_PTR(-ENOMEM); | ||
1921 | 2204 | ||
1922 | return ERR_PTR(rc); | 2205 | set_wiphy_dev(wiphy, dev); |
2206 | wil_wiphy_init(wiphy); | ||
2207 | |||
2208 | wil = wiphy_to_wil(wiphy); | ||
2209 | wil->wiphy = wiphy; | ||
2210 | |||
2211 | /* default monitor channel */ | ||
2212 | ch = wiphy->bands[NL80211_BAND_60GHZ]->channels; | ||
2213 | cfg80211_chandef_create(&wil->monitor_chandef, ch, NL80211_CHAN_NO_HT); | ||
2214 | |||
2215 | return wil; | ||
1923 | } | 2216 | } |
1924 | 2217 | ||
1925 | void wil_wdev_free(struct wil6210_priv *wil) | 2218 | void wil_cfg80211_deinit(struct wil6210_priv *wil) |
1926 | { | 2219 | { |
1927 | struct wireless_dev *wdev = wil_to_wdev(wil); | 2220 | struct wiphy *wiphy = wil_to_wiphy(wil); |
1928 | 2221 | ||
1929 | dev_dbg(wil_to_dev(wil), "%s()\n", __func__); | 2222 | dev_dbg(wil_to_dev(wil), "%s()\n", __func__); |
1930 | 2223 | ||
1931 | if (!wdev) | 2224 | if (!wiphy) |
1932 | return; | 2225 | return; |
1933 | 2226 | ||
1934 | wiphy_free(wdev->wiphy); | 2227 | kfree(wiphy->iface_combinations); |
1935 | kfree(wdev); | 2228 | wiphy->iface_combinations = NULL; |
2229 | |||
2230 | wiphy_free(wiphy); | ||
2231 | /* do not access wil6210_priv after returning from here */ | ||
1936 | } | 2232 | } |
1937 | 2233 | ||
1938 | void wil_p2p_wdev_free(struct wil6210_priv *wil) | 2234 | void wil_p2p_wdev_free(struct wil6210_priv *wil) |
1939 | { | 2235 | { |
1940 | struct wireless_dev *p2p_wdev; | 2236 | struct wireless_dev *p2p_wdev; |
1941 | 2237 | ||
1942 | mutex_lock(&wil->p2p_wdev_mutex); | 2238 | mutex_lock(&wil->vif_mutex); |
1943 | p2p_wdev = wil->p2p_wdev; | 2239 | p2p_wdev = wil->p2p_wdev; |
1944 | wil->p2p_wdev = NULL; | 2240 | wil->p2p_wdev = NULL; |
1945 | wil->radio_wdev = wil_to_wdev(wil); | 2241 | wil->radio_wdev = wil->main_ndev->ieee80211_ptr; |
1946 | mutex_unlock(&wil->p2p_wdev_mutex); | 2242 | mutex_unlock(&wil->vif_mutex); |
1947 | if (p2p_wdev) { | 2243 | if (p2p_wdev) { |
1948 | cfg80211_unregister_wdev(p2p_wdev); | 2244 | cfg80211_unregister_wdev(p2p_wdev); |
1949 | kfree(p2p_wdev); | 2245 | kfree(p2p_wdev); |
@@ -1971,6 +2267,7 @@ static int wil_rf_sector_get_cfg(struct wiphy *wiphy, | |||
1971 | const void *data, int data_len) | 2267 | const void *data, int data_len) |
1972 | { | 2268 | { |
1973 | struct wil6210_priv *wil = wdev_to_wil(wdev); | 2269 | struct wil6210_priv *wil = wdev_to_wil(wdev); |
2270 | struct wil6210_vif *vif = wdev_to_vif(wil, wdev); | ||
1974 | int rc; | 2271 | int rc; |
1975 | struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1]; | 2272 | struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1]; |
1976 | u16 sector_index; | 2273 | u16 sector_index; |
@@ -2027,8 +2324,8 @@ static int wil_rf_sector_get_cfg(struct wiphy *wiphy, | |||
2027 | cmd.sector_type = sector_type; | 2324 | cmd.sector_type = sector_type; |
2028 | cmd.rf_modules_vec = rf_modules_vec & 0xFF; | 2325 | cmd.rf_modules_vec = rf_modules_vec & 0xFF; |
2029 | memset(&reply, 0, sizeof(reply)); | 2326 | memset(&reply, 0, sizeof(reply)); |
2030 | rc = wmi_call(wil, WMI_GET_RF_SECTOR_PARAMS_CMDID, &cmd, sizeof(cmd), | 2327 | rc = wmi_call(wil, WMI_GET_RF_SECTOR_PARAMS_CMDID, vif->mid, |
2031 | WMI_GET_RF_SECTOR_PARAMS_DONE_EVENTID, | 2328 | &cmd, sizeof(cmd), WMI_GET_RF_SECTOR_PARAMS_DONE_EVENTID, |
2032 | &reply, sizeof(reply), | 2329 | &reply, sizeof(reply), |
2033 | 500); | 2330 | 500); |
2034 | if (rc) | 2331 | if (rc) |
@@ -2090,6 +2387,7 @@ static int wil_rf_sector_set_cfg(struct wiphy *wiphy, | |||
2090 | const void *data, int data_len) | 2387 | const void *data, int data_len) |
2091 | { | 2388 | { |
2092 | struct wil6210_priv *wil = wdev_to_wil(wdev); | 2389 | struct wil6210_priv *wil = wdev_to_wil(wdev); |
2390 | struct wil6210_vif *vif = wdev_to_vif(wil, wdev); | ||
2093 | int rc, tmp; | 2391 | int rc, tmp; |
2094 | struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1]; | 2392 | struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1]; |
2095 | struct nlattr *tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_MAX + 1]; | 2393 | struct nlattr *tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_MAX + 1]; |
@@ -2184,8 +2482,8 @@ static int wil_rf_sector_set_cfg(struct wiphy *wiphy, | |||
2184 | 2482 | ||
2185 | cmd.rf_modules_vec = rf_modules_vec & 0xFF; | 2483 | cmd.rf_modules_vec = rf_modules_vec & 0xFF; |
2186 | memset(&reply, 0, sizeof(reply)); | 2484 | memset(&reply, 0, sizeof(reply)); |
2187 | rc = wmi_call(wil, WMI_SET_RF_SECTOR_PARAMS_CMDID, &cmd, sizeof(cmd), | 2485 | rc = wmi_call(wil, WMI_SET_RF_SECTOR_PARAMS_CMDID, vif->mid, |
2188 | WMI_SET_RF_SECTOR_PARAMS_DONE_EVENTID, | 2486 | &cmd, sizeof(cmd), WMI_SET_RF_SECTOR_PARAMS_DONE_EVENTID, |
2189 | &reply, sizeof(reply), | 2487 | &reply, sizeof(reply), |
2190 | 500); | 2488 | 500); |
2191 | if (rc) | 2489 | if (rc) |
@@ -2198,6 +2496,7 @@ static int wil_rf_sector_get_selected(struct wiphy *wiphy, | |||
2198 | const void *data, int data_len) | 2496 | const void *data, int data_len) |
2199 | { | 2497 | { |
2200 | struct wil6210_priv *wil = wdev_to_wil(wdev); | 2498 | struct wil6210_priv *wil = wdev_to_wil(wdev); |
2499 | struct wil6210_vif *vif = wdev_to_vif(wil, wdev); | ||
2201 | int rc; | 2500 | int rc; |
2202 | struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1]; | 2501 | struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1]; |
2203 | u8 sector_type, mac_addr[ETH_ALEN]; | 2502 | u8 sector_type, mac_addr[ETH_ALEN]; |
@@ -2231,13 +2530,13 @@ static int wil_rf_sector_get_selected(struct wiphy *wiphy, | |||
2231 | 2530 | ||
2232 | if (tb[QCA_ATTR_MAC_ADDR]) { | 2531 | if (tb[QCA_ATTR_MAC_ADDR]) { |
2233 | ether_addr_copy(mac_addr, nla_data(tb[QCA_ATTR_MAC_ADDR])); | 2532 | ether_addr_copy(mac_addr, nla_data(tb[QCA_ATTR_MAC_ADDR])); |
2234 | cid = wil_find_cid(wil, mac_addr); | 2533 | cid = wil_find_cid(wil, vif->mid, mac_addr); |
2235 | if (cid < 0) { | 2534 | if (cid < 0) { |
2236 | wil_err(wil, "invalid MAC address %pM\n", mac_addr); | 2535 | wil_err(wil, "invalid MAC address %pM\n", mac_addr); |
2237 | return -ENOENT; | 2536 | return -ENOENT; |
2238 | } | 2537 | } |
2239 | } else { | 2538 | } else { |
2240 | if (test_bit(wil_status_fwconnected, wil->status)) { | 2539 | if (test_bit(wil_vif_fwconnected, vif->status)) { |
2241 | wil_err(wil, "must specify MAC address when connected\n"); | 2540 | wil_err(wil, "must specify MAC address when connected\n"); |
2242 | return -EINVAL; | 2541 | return -EINVAL; |
2243 | } | 2542 | } |
@@ -2247,7 +2546,7 @@ static int wil_rf_sector_get_selected(struct wiphy *wiphy, | |||
2247 | cmd.cid = (u8)cid; | 2546 | cmd.cid = (u8)cid; |
2248 | cmd.sector_type = sector_type; | 2547 | cmd.sector_type = sector_type; |
2249 | memset(&reply, 0, sizeof(reply)); | 2548 | memset(&reply, 0, sizeof(reply)); |
2250 | rc = wmi_call(wil, WMI_GET_SELECTED_RF_SECTOR_INDEX_CMDID, | 2549 | rc = wmi_call(wil, WMI_GET_SELECTED_RF_SECTOR_INDEX_CMDID, vif->mid, |
2251 | &cmd, sizeof(cmd), | 2550 | &cmd, sizeof(cmd), |
2252 | WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID, | 2551 | WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID, |
2253 | &reply, sizeof(reply), | 2552 | &reply, sizeof(reply), |
@@ -2280,7 +2579,7 @@ nla_put_failure: | |||
2280 | } | 2579 | } |
2281 | 2580 | ||
2282 | static int wil_rf_sector_wmi_set_selected(struct wil6210_priv *wil, | 2581 | static int wil_rf_sector_wmi_set_selected(struct wil6210_priv *wil, |
2283 | u16 sector_index, | 2582 | u8 mid, u16 sector_index, |
2284 | u8 sector_type, u8 cid) | 2583 | u8 sector_type, u8 cid) |
2285 | { | 2584 | { |
2286 | struct wmi_set_selected_rf_sector_index_cmd cmd; | 2585 | struct wmi_set_selected_rf_sector_index_cmd cmd; |
@@ -2295,7 +2594,7 @@ static int wil_rf_sector_wmi_set_selected(struct wil6210_priv *wil, | |||
2295 | cmd.sector_type = sector_type; | 2594 | cmd.sector_type = sector_type; |
2296 | cmd.cid = (u8)cid; | 2595 | cmd.cid = (u8)cid; |
2297 | memset(&reply, 0, sizeof(reply)); | 2596 | memset(&reply, 0, sizeof(reply)); |
2298 | rc = wmi_call(wil, WMI_SET_SELECTED_RF_SECTOR_INDEX_CMDID, | 2597 | rc = wmi_call(wil, WMI_SET_SELECTED_RF_SECTOR_INDEX_CMDID, mid, |
2299 | &cmd, sizeof(cmd), | 2598 | &cmd, sizeof(cmd), |
2300 | WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID, | 2599 | WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID, |
2301 | &reply, sizeof(reply), | 2600 | &reply, sizeof(reply), |
@@ -2310,6 +2609,7 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy, | |||
2310 | const void *data, int data_len) | 2609 | const void *data, int data_len) |
2311 | { | 2610 | { |
2312 | struct wil6210_priv *wil = wdev_to_wil(wdev); | 2611 | struct wil6210_priv *wil = wdev_to_wil(wdev); |
2612 | struct wil6210_vif *vif = wdev_to_vif(wil, wdev); | ||
2313 | int rc; | 2613 | int rc; |
2314 | struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1]; | 2614 | struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1]; |
2315 | u16 sector_index; | 2615 | u16 sector_index; |
@@ -2349,7 +2649,7 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy, | |||
2349 | if (tb[QCA_ATTR_MAC_ADDR]) { | 2649 | if (tb[QCA_ATTR_MAC_ADDR]) { |
2350 | ether_addr_copy(mac_addr, nla_data(tb[QCA_ATTR_MAC_ADDR])); | 2650 | ether_addr_copy(mac_addr, nla_data(tb[QCA_ATTR_MAC_ADDR])); |
2351 | if (!is_broadcast_ether_addr(mac_addr)) { | 2651 | if (!is_broadcast_ether_addr(mac_addr)) { |
2352 | cid = wil_find_cid(wil, mac_addr); | 2652 | cid = wil_find_cid(wil, vif->mid, mac_addr); |
2353 | if (cid < 0) { | 2653 | if (cid < 0) { |
2354 | wil_err(wil, "invalid MAC address %pM\n", | 2654 | wil_err(wil, "invalid MAC address %pM\n", |
2355 | mac_addr); | 2655 | mac_addr); |
@@ -2363,7 +2663,7 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy, | |||
2363 | cid = -1; | 2663 | cid = -1; |
2364 | } | 2664 | } |
2365 | } else { | 2665 | } else { |
2366 | if (test_bit(wil_status_fwconnected, wil->status)) { | 2666 | if (test_bit(wil_vif_fwconnected, vif->status)) { |
2367 | wil_err(wil, "must specify MAC address when connected\n"); | 2667 | wil_err(wil, "must specify MAC address when connected\n"); |
2368 | return -EINVAL; | 2668 | return -EINVAL; |
2369 | } | 2669 | } |
@@ -2371,17 +2671,20 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy, | |||
2371 | } | 2671 | } |
2372 | 2672 | ||
2373 | if (cid >= 0) { | 2673 | if (cid >= 0) { |
2374 | rc = wil_rf_sector_wmi_set_selected(wil, sector_index, | 2674 | rc = wil_rf_sector_wmi_set_selected(wil, vif->mid, sector_index, |
2375 | sector_type, cid); | 2675 | sector_type, cid); |
2376 | } else { | 2676 | } else { |
2377 | /* unlock all cids */ | 2677 | /* unlock all cids */ |
2378 | rc = wil_rf_sector_wmi_set_selected( | 2678 | rc = wil_rf_sector_wmi_set_selected( |
2379 | wil, WMI_INVALID_RF_SECTOR_INDEX, sector_type, | 2679 | wil, vif->mid, WMI_INVALID_RF_SECTOR_INDEX, |
2380 | WIL_CID_ALL); | 2680 | sector_type, WIL_CID_ALL); |
2381 | if (rc == -EINVAL) { | 2681 | if (rc == -EINVAL) { |
2382 | for (i = 0; i < WIL6210_MAX_CID; i++) { | 2682 | for (i = 0; i < WIL6210_MAX_CID; i++) { |
2683 | if (wil->sta[i].mid != vif->mid) | ||
2684 | continue; | ||
2383 | rc = wil_rf_sector_wmi_set_selected( | 2685 | rc = wil_rf_sector_wmi_set_selected( |
2384 | wil, WMI_INVALID_RF_SECTOR_INDEX, | 2686 | wil, vif->mid, |
2687 | WMI_INVALID_RF_SECTOR_INDEX, | ||
2385 | sector_type, i); | 2688 | sector_type, i); |
2386 | /* the FW will silently ignore and return | 2689 | /* the FW will silently ignore and return |
2387 | * success for unused cid, so abort the loop | 2690 | * success for unused cid, so abort the loop |
diff --git a/drivers/net/wireless/ath/wil6210/debug.c b/drivers/net/wireless/ath/wil6210/debug.c index 217a4591bde4..a9befb971cc4 100644 --- a/drivers/net/wireless/ath/wil6210/debug.c +++ b/drivers/net/wireless/ath/wil6210/debug.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2013,2016 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2013,2016 Qualcomm Atheros, Inc. |
3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -25,7 +26,7 @@ void __wil_err(struct wil6210_priv *wil, const char *fmt, ...) | |||
25 | va_start(args, fmt); | 26 | va_start(args, fmt); |
26 | vaf.fmt = fmt; | 27 | vaf.fmt = fmt; |
27 | vaf.va = &args; | 28 | vaf.va = &args; |
28 | netdev_err(wil_to_ndev(wil), "%pV", &vaf); | 29 | netdev_err(wil->main_ndev, "%pV", &vaf); |
29 | trace_wil6210_log_err(&vaf); | 30 | trace_wil6210_log_err(&vaf); |
30 | va_end(args); | 31 | va_end(args); |
31 | } | 32 | } |
@@ -41,7 +42,7 @@ void __wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...) | |||
41 | va_start(args, fmt); | 42 | va_start(args, fmt); |
42 | vaf.fmt = fmt; | 43 | vaf.fmt = fmt; |
43 | vaf.va = &args; | 44 | vaf.va = &args; |
44 | netdev_err(wil_to_ndev(wil), "%pV", &vaf); | 45 | netdev_err(wil->main_ndev, "%pV", &vaf); |
45 | trace_wil6210_log_err(&vaf); | 46 | trace_wil6210_log_err(&vaf); |
46 | va_end(args); | 47 | va_end(args); |
47 | } | 48 | } |
@@ -57,7 +58,7 @@ void wil_dbg_ratelimited(const struct wil6210_priv *wil, const char *fmt, ...) | |||
57 | va_start(args, fmt); | 58 | va_start(args, fmt); |
58 | vaf.fmt = fmt; | 59 | vaf.fmt = fmt; |
59 | vaf.va = &args; | 60 | vaf.va = &args; |
60 | netdev_dbg(wil_to_ndev(wil), "%pV", &vaf); | 61 | netdev_dbg(wil->main_ndev, "%pV", &vaf); |
61 | trace_wil6210_log_dbg(&vaf); | 62 | trace_wil6210_log_dbg(&vaf); |
62 | va_end(args); | 63 | va_end(args); |
63 | } | 64 | } |
@@ -70,7 +71,7 @@ void __wil_info(struct wil6210_priv *wil, const char *fmt, ...) | |||
70 | va_start(args, fmt); | 71 | va_start(args, fmt); |
71 | vaf.fmt = fmt; | 72 | vaf.fmt = fmt; |
72 | vaf.va = &args; | 73 | vaf.va = &args; |
73 | netdev_info(wil_to_ndev(wil), "%pV", &vaf); | 74 | netdev_info(wil->main_ndev, "%pV", &vaf); |
74 | trace_wil6210_log_info(&vaf); | 75 | trace_wil6210_log_info(&vaf); |
75 | va_end(args); | 76 | va_end(args); |
76 | } | 77 | } |
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 4a4888246e8c..8c90b3111f0b 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. |
3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -621,7 +622,7 @@ static ssize_t wil_write_file_reset(struct file *file, const char __user *buf, | |||
621 | size_t len, loff_t *ppos) | 622 | size_t len, loff_t *ppos) |
622 | { | 623 | { |
623 | struct wil6210_priv *wil = file->private_data; | 624 | struct wil6210_priv *wil = file->private_data; |
624 | struct net_device *ndev = wil_to_ndev(wil); | 625 | struct net_device *ndev = wil->main_ndev; |
625 | 626 | ||
626 | /** | 627 | /** |
627 | * BUG: | 628 | * BUG: |
@@ -716,27 +717,44 @@ static ssize_t wil_write_back(struct file *file, const char __user *buf, | |||
716 | if (rc < 2) | 717 | if (rc < 2) |
717 | return -EINVAL; | 718 | return -EINVAL; |
718 | 719 | ||
719 | if (0 == strcmp(cmd, "add")) { | 720 | if ((strcmp(cmd, "add") == 0) || |
720 | if (rc < 3) { | 721 | (strcmp(cmd, "del_tx") == 0)) { |
721 | wil_err(wil, "BACK: add require at least 2 params\n"); | 722 | struct vring_tx_data *txdata; |
723 | |||
724 | if (p1 < 0 || p1 >= WIL6210_MAX_TX_RINGS) { | ||
725 | wil_err(wil, "BACK: invalid ring id %d\n", p1); | ||
722 | return -EINVAL; | 726 | return -EINVAL; |
723 | } | 727 | } |
724 | if (rc < 4) | 728 | txdata = &wil->vring_tx_data[p1]; |
725 | p3 = 0; | 729 | if (strcmp(cmd, "add") == 0) { |
726 | wmi_addba(wil, p1, p2, p3); | 730 | if (rc < 3) { |
727 | } else if (0 == strcmp(cmd, "del_tx")) { | 731 | wil_err(wil, "BACK: add require at least 2 params\n"); |
728 | if (rc < 3) | 732 | return -EINVAL; |
729 | p2 = WLAN_REASON_QSTA_LEAVE_QBSS; | 733 | } |
730 | wmi_delba_tx(wil, p1, p2); | 734 | if (rc < 4) |
731 | } else if (0 == strcmp(cmd, "del_rx")) { | 735 | p3 = 0; |
736 | wmi_addba(wil, txdata->mid, p1, p2, p3); | ||
737 | } else { | ||
738 | if (rc < 3) | ||
739 | p2 = WLAN_REASON_QSTA_LEAVE_QBSS; | ||
740 | wmi_delba_tx(wil, txdata->mid, p1, p2); | ||
741 | } | ||
742 | } else if (strcmp(cmd, "del_rx") == 0) { | ||
743 | struct wil_sta_info *sta; | ||
744 | |||
732 | if (rc < 3) { | 745 | if (rc < 3) { |
733 | wil_err(wil, | 746 | wil_err(wil, |
734 | "BACK: del_rx require at least 2 params\n"); | 747 | "BACK: del_rx require at least 2 params\n"); |
735 | return -EINVAL; | 748 | return -EINVAL; |
736 | } | 749 | } |
750 | if (p1 < 0 || p1 >= WIL6210_MAX_CID) { | ||
751 | wil_err(wil, "BACK: invalid CID %d\n", p1); | ||
752 | return -EINVAL; | ||
753 | } | ||
737 | if (rc < 4) | 754 | if (rc < 4) |
738 | p3 = WLAN_REASON_QSTA_LEAVE_QBSS; | 755 | p3 = WLAN_REASON_QSTA_LEAVE_QBSS; |
739 | wmi_delba_rx(wil, mk_cidxtid(p1, p2), p3); | 756 | sta = &wil->sta[p1]; |
757 | wmi_delba_rx(wil, sta->mid, mk_cidxtid(p1, p2), p3); | ||
740 | } else { | 758 | } else { |
741 | wil_err(wil, "BACK: Unrecognized command \"%s\"\n", cmd); | 759 | wil_err(wil, "BACK: Unrecognized command \"%s\"\n", cmd); |
742 | return -EINVAL; | 760 | return -EINVAL; |
@@ -855,7 +873,7 @@ static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf, | |||
855 | { | 873 | { |
856 | struct wil6210_priv *wil = file->private_data; | 874 | struct wil6210_priv *wil = file->private_data; |
857 | struct wiphy *wiphy = wil_to_wiphy(wil); | 875 | struct wiphy *wiphy = wil_to_wiphy(wil); |
858 | struct wireless_dev *wdev = wil_to_wdev(wil); | 876 | struct wireless_dev *wdev = wil->main_ndev->ieee80211_ptr; |
859 | struct cfg80211_mgmt_tx_params params; | 877 | struct cfg80211_mgmt_tx_params params; |
860 | int rc; | 878 | int rc; |
861 | void *frame; | 879 | void *frame; |
@@ -890,6 +908,7 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf, | |||
890 | size_t len, loff_t *ppos) | 908 | size_t len, loff_t *ppos) |
891 | { | 909 | { |
892 | struct wil6210_priv *wil = file->private_data; | 910 | struct wil6210_priv *wil = file->private_data; |
911 | struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); | ||
893 | struct wmi_cmd_hdr *wmi; | 912 | struct wmi_cmd_hdr *wmi; |
894 | void *cmd; | 913 | void *cmd; |
895 | int cmdlen = len - sizeof(struct wmi_cmd_hdr); | 914 | int cmdlen = len - sizeof(struct wmi_cmd_hdr); |
@@ -912,7 +931,7 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf, | |||
912 | cmd = (cmdlen > 0) ? &wmi[1] : NULL; | 931 | cmd = (cmdlen > 0) ? &wmi[1] : NULL; |
913 | cmdid = le16_to_cpu(wmi->command_id); | 932 | cmdid = le16_to_cpu(wmi->command_id); |
914 | 933 | ||
915 | rc1 = wmi_send(wil, cmdid, cmd, cmdlen); | 934 | rc1 = wmi_send(wil, cmdid, vif->mid, cmd, cmdlen); |
916 | kfree(wmi); | 935 | kfree(wmi); |
917 | 936 | ||
918 | wil_info(wil, "0x%04x[%d] -> %d\n", cmdid, cmdlen, rc1); | 937 | wil_info(wil, "0x%04x[%d] -> %d\n", cmdid, cmdlen, rc1); |
@@ -1050,6 +1069,7 @@ static int wil_bf_debugfs_show(struct seq_file *s, void *data) | |||
1050 | int rc; | 1069 | int rc; |
1051 | int i; | 1070 | int i; |
1052 | struct wil6210_priv *wil = s->private; | 1071 | struct wil6210_priv *wil = s->private; |
1072 | struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); | ||
1053 | struct wmi_notify_req_cmd cmd = { | 1073 | struct wmi_notify_req_cmd cmd = { |
1054 | .interval_usec = 0, | 1074 | .interval_usec = 0, |
1055 | }; | 1075 | }; |
@@ -1062,7 +1082,8 @@ static int wil_bf_debugfs_show(struct seq_file *s, void *data) | |||
1062 | u32 status; | 1082 | u32 status; |
1063 | 1083 | ||
1064 | cmd.cid = i; | 1084 | cmd.cid = i; |
1065 | rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd), | 1085 | rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, vif->mid, |
1086 | &cmd, sizeof(cmd), | ||
1066 | WMI_NOTIFY_REQ_DONE_EVENTID, &reply, | 1087 | WMI_NOTIFY_REQ_DONE_EVENTID, &reply, |
1067 | sizeof(reply), 20); | 1088 | sizeof(reply), 20); |
1068 | /* if reply is all-0, ignore this CID */ | 1089 | /* if reply is all-0, ignore this CID */ |
@@ -1155,7 +1176,7 @@ static const struct file_operations fops_temp = { | |||
1155 | static int wil_freq_debugfs_show(struct seq_file *s, void *data) | 1176 | static int wil_freq_debugfs_show(struct seq_file *s, void *data) |
1156 | { | 1177 | { |
1157 | struct wil6210_priv *wil = s->private; | 1178 | struct wil6210_priv *wil = s->private; |
1158 | struct wireless_dev *wdev = wil_to_wdev(wil); | 1179 | struct wireless_dev *wdev = wil->main_ndev->ieee80211_ptr; |
1159 | u16 freq = wdev->chandef.chan ? wdev->chandef.chan->center_freq : 0; | 1180 | u16 freq = wdev->chandef.chan ? wdev->chandef.chan->center_freq : 0; |
1160 | 1181 | ||
1161 | seq_printf(s, "Freq = %d\n", freq); | 1182 | seq_printf(s, "Freq = %d\n", freq); |
@@ -1185,6 +1206,8 @@ static int wil_link_debugfs_show(struct seq_file *s, void *data) | |||
1185 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { | 1206 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { |
1186 | struct wil_sta_info *p = &wil->sta[i]; | 1207 | struct wil_sta_info *p = &wil->sta[i]; |
1187 | char *status = "unknown"; | 1208 | char *status = "unknown"; |
1209 | struct wil6210_vif *vif; | ||
1210 | u8 mid; | ||
1188 | 1211 | ||
1189 | switch (p->status) { | 1212 | switch (p->status) { |
1190 | case wil_sta_unused: | 1213 | case wil_sta_unused: |
@@ -1197,16 +1220,24 @@ static int wil_link_debugfs_show(struct seq_file *s, void *data) | |||
1197 | status = "connected"; | 1220 | status = "connected"; |
1198 | break; | 1221 | break; |
1199 | } | 1222 | } |
1200 | seq_printf(s, "[%d] %pM %s\n", i, p->addr, status); | 1223 | mid = (p->status != wil_sta_unused) ? p->mid : U8_MAX; |
1224 | seq_printf(s, "[%d][MID %d] %pM %s\n", | ||
1225 | i, mid, p->addr, status); | ||
1201 | 1226 | ||
1202 | if (p->status == wil_sta_connected) { | 1227 | if (p->status != wil_sta_connected) |
1203 | rc = wil_cid_fill_sinfo(wil, i, &sinfo); | 1228 | continue; |
1229 | |||
1230 | vif = (mid < wil->max_vifs) ? wil->vifs[mid] : NULL; | ||
1231 | if (vif) { | ||
1232 | rc = wil_cid_fill_sinfo(vif, i, &sinfo); | ||
1204 | if (rc) | 1233 | if (rc) |
1205 | return rc; | 1234 | return rc; |
1206 | 1235 | ||
1207 | seq_printf(s, " Tx_mcs = %d\n", sinfo.txrate.mcs); | 1236 | seq_printf(s, " Tx_mcs = %d\n", sinfo.txrate.mcs); |
1208 | seq_printf(s, " Rx_mcs = %d\n", sinfo.rxrate.mcs); | 1237 | seq_printf(s, " Rx_mcs = %d\n", sinfo.rxrate.mcs); |
1209 | seq_printf(s, " SQ = %d\n", sinfo.signal); | 1238 | seq_printf(s, " SQ = %d\n", sinfo.signal); |
1239 | } else { | ||
1240 | seq_puts(s, " INVALID MID\n"); | ||
1210 | } | 1241 | } |
1211 | } | 1242 | } |
1212 | 1243 | ||
@@ -1229,7 +1260,7 @@ static const struct file_operations fops_link = { | |||
1229 | static int wil_info_debugfs_show(struct seq_file *s, void *data) | 1260 | static int wil_info_debugfs_show(struct seq_file *s, void *data) |
1230 | { | 1261 | { |
1231 | struct wil6210_priv *wil = s->private; | 1262 | struct wil6210_priv *wil = s->private; |
1232 | struct net_device *ndev = wil_to_ndev(wil); | 1263 | struct net_device *ndev = wil->main_ndev; |
1233 | int is_ac = power_supply_is_system_supplied(); | 1264 | int is_ac = power_supply_is_system_supplied(); |
1234 | int rx = atomic_xchg(&wil->isr_count_rx, 0); | 1265 | int rx = atomic_xchg(&wil->isr_count_rx, 0); |
1235 | int tx = atomic_xchg(&wil->isr_count_tx, 0); | 1266 | int tx = atomic_xchg(&wil->isr_count_tx, 0); |
@@ -1398,6 +1429,7 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) | |||
1398 | struct wil_sta_info *p = &wil->sta[i]; | 1429 | struct wil_sta_info *p = &wil->sta[i]; |
1399 | char *status = "unknown"; | 1430 | char *status = "unknown"; |
1400 | u8 aid = 0; | 1431 | u8 aid = 0; |
1432 | u8 mid; | ||
1401 | 1433 | ||
1402 | switch (p->status) { | 1434 | switch (p->status) { |
1403 | case wil_sta_unused: | 1435 | case wil_sta_unused: |
@@ -1411,7 +1443,9 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) | |||
1411 | aid = p->aid; | 1443 | aid = p->aid; |
1412 | break; | 1444 | break; |
1413 | } | 1445 | } |
1414 | seq_printf(s, "[%d] %pM %s AID %d\n", i, p->addr, status, aid); | 1446 | mid = (p->status != wil_sta_unused) ? p->mid : U8_MAX; |
1447 | seq_printf(s, "[%d] %pM %s MID %d AID %d\n", i, p->addr, status, | ||
1448 | mid, aid); | ||
1415 | 1449 | ||
1416 | if (p->status == wil_sta_connected) { | 1450 | if (p->status == wil_sta_connected) { |
1417 | spin_lock_bh(&p->tid_rx_lock); | 1451 | spin_lock_bh(&p->tid_rx_lock); |
@@ -1461,6 +1495,42 @@ static const struct file_operations fops_sta = { | |||
1461 | .llseek = seq_lseek, | 1495 | .llseek = seq_lseek, |
1462 | }; | 1496 | }; |
1463 | 1497 | ||
1498 | static int wil_mids_debugfs_show(struct seq_file *s, void *data) | ||
1499 | { | ||
1500 | struct wil6210_priv *wil = s->private; | ||
1501 | struct wil6210_vif *vif; | ||
1502 | struct net_device *ndev; | ||
1503 | int i; | ||
1504 | |||
1505 | mutex_lock(&wil->vif_mutex); | ||
1506 | for (i = 0; i < wil->max_vifs; i++) { | ||
1507 | vif = wil->vifs[i]; | ||
1508 | |||
1509 | if (vif) { | ||
1510 | ndev = vif_to_ndev(vif); | ||
1511 | seq_printf(s, "[%d] %pM %s\n", i, ndev->dev_addr, | ||
1512 | ndev->name); | ||
1513 | } else { | ||
1514 | seq_printf(s, "[%d] unused\n", i); | ||
1515 | } | ||
1516 | } | ||
1517 | mutex_unlock(&wil->vif_mutex); | ||
1518 | |||
1519 | return 0; | ||
1520 | } | ||
1521 | |||
1522 | static int wil_mids_seq_open(struct inode *inode, struct file *file) | ||
1523 | { | ||
1524 | return single_open(file, wil_mids_debugfs_show, inode->i_private); | ||
1525 | } | ||
1526 | |||
1527 | static const struct file_operations fops_mids = { | ||
1528 | .open = wil_mids_seq_open, | ||
1529 | .release = single_release, | ||
1530 | .read = seq_read, | ||
1531 | .llseek = seq_lseek, | ||
1532 | }; | ||
1533 | |||
1464 | static ssize_t wil_read_file_led_cfg(struct file *file, char __user *user_buf, | 1534 | static ssize_t wil_read_file_led_cfg(struct file *file, char __user *user_buf, |
1465 | size_t count, loff_t *ppos) | 1535 | size_t count, loff_t *ppos) |
1466 | { | 1536 | { |
@@ -1715,6 +1785,7 @@ static const struct { | |||
1715 | {"mbox", 0444, &fops_mbox}, | 1785 | {"mbox", 0444, &fops_mbox}, |
1716 | {"vrings", 0444, &fops_vring}, | 1786 | {"vrings", 0444, &fops_vring}, |
1717 | {"stations", 0444, &fops_sta}, | 1787 | {"stations", 0444, &fops_sta}, |
1788 | {"mids", 0444, &fops_mids}, | ||
1718 | {"desc", 0444, &fops_txdesc}, | 1789 | {"desc", 0444, &fops_txdesc}, |
1719 | {"bf", 0444, &fops_bf}, | 1790 | {"bf", 0444, &fops_bf}, |
1720 | {"mem_val", 0644, &fops_memread}, | 1791 | {"mem_val", 0644, &fops_memread}, |
@@ -1773,11 +1844,9 @@ static void wil6210_debugfs_init_isr(struct wil6210_priv *wil, | |||
1773 | 1844 | ||
1774 | /* fields in struct wil6210_priv */ | 1845 | /* fields in struct wil6210_priv */ |
1775 | static const struct dbg_off dbg_wil_off[] = { | 1846 | static const struct dbg_off dbg_wil_off[] = { |
1776 | WIL_FIELD(privacy, 0444, doff_u32), | ||
1777 | WIL_FIELD(status[0], 0644, doff_ulong), | 1847 | WIL_FIELD(status[0], 0644, doff_ulong), |
1778 | WIL_FIELD(hw_version, 0444, doff_x32), | 1848 | WIL_FIELD(hw_version, 0444, doff_x32), |
1779 | WIL_FIELD(recovery_count, 0444, doff_u32), | 1849 | WIL_FIELD(recovery_count, 0444, doff_u32), |
1780 | WIL_FIELD(ap_isolate, 0444, doff_u32), | ||
1781 | WIL_FIELD(discovery_mode, 0644, doff_u8), | 1850 | WIL_FIELD(discovery_mode, 0644, doff_u8), |
1782 | WIL_FIELD(chip_revision, 0444, doff_u8), | 1851 | WIL_FIELD(chip_revision, 0444, doff_u8), |
1783 | WIL_FIELD(abft_len, 0644, doff_u8), | 1852 | WIL_FIELD(abft_len, 0644, doff_u8), |
diff --git a/drivers/net/wireless/ath/wil6210/ethtool.c b/drivers/net/wireless/ath/wil6210/ethtool.c index 66200f616a37..e7ff41e623d2 100644 --- a/drivers/net/wireless/ath/wil6210/ethtool.c +++ b/drivers/net/wireless/ath/wil6210/ethtool.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2014,2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2014,2017 Qualcomm Atheros, Inc. |
3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -74,12 +75,13 @@ static int wil_ethtoolops_set_coalesce(struct net_device *ndev, | |||
74 | struct ethtool_coalesce *cp) | 75 | struct ethtool_coalesce *cp) |
75 | { | 76 | { |
76 | struct wil6210_priv *wil = ndev_to_wil(ndev); | 77 | struct wil6210_priv *wil = ndev_to_wil(ndev); |
78 | struct wireless_dev *wdev = ndev->ieee80211_ptr; | ||
77 | int ret; | 79 | int ret; |
78 | 80 | ||
79 | wil_dbg_misc(wil, "ethtoolops_set_coalesce: rx %d usec, tx %d usec\n", | 81 | wil_dbg_misc(wil, "ethtoolops_set_coalesce: rx %d usec, tx %d usec\n", |
80 | cp->rx_coalesce_usecs, cp->tx_coalesce_usecs); | 82 | cp->rx_coalesce_usecs, cp->tx_coalesce_usecs); |
81 | 83 | ||
82 | if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { | 84 | if (wdev->iftype == NL80211_IFTYPE_MONITOR) { |
83 | wil_dbg_misc(wil, "No IRQ coalescing in monitor mode\n"); | 85 | wil_dbg_misc(wil, "No IRQ coalescing in monitor mode\n"); |
84 | return -EINVAL; | 86 | return -EINVAL; |
85 | } | 87 | } |
diff --git a/drivers/net/wireless/ath/wil6210/fw.h b/drivers/net/wireless/ath/wil6210/fw.h index 2c7b24f61587..3e7a28045cab 100644 --- a/drivers/net/wireless/ath/wil6210/fw.h +++ b/drivers/net/wireless/ath/wil6210/fw.h | |||
@@ -14,6 +14,8 @@ | |||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
16 | */ | 16 | */ |
17 | #ifndef __WIL_FW_H__ | ||
18 | #define __WIL_FW_H__ | ||
17 | 19 | ||
18 | #define WIL_FW_SIGNATURE (0x36323130) /* '0126' */ | 20 | #define WIL_FW_SIGNATURE (0x36323130) /* '0126' */ |
19 | #define WIL_FW_FMT_VERSION (1) /* format version driver supports */ | 21 | #define WIL_FW_FMT_VERSION (1) /* format version driver supports */ |
@@ -71,7 +73,39 @@ struct wil_fw_record_capabilities { /* type == wil_fw_type_comment */ | |||
71 | struct wil_fw_record_comment_hdr hdr; | 73 | struct wil_fw_record_comment_hdr hdr; |
72 | /* capabilities (variable size), see enum wmi_fw_capability */ | 74 | /* capabilities (variable size), see enum wmi_fw_capability */ |
73 | u8 capabilities[0]; | 75 | u8 capabilities[0]; |
74 | }; | 76 | } __packed; |
77 | |||
78 | /* FW VIF concurrency encoded inside a comment record | ||
79 | * Format is similar to wiphy->iface_combinations | ||
80 | */ | ||
81 | #define WIL_FW_CONCURRENCY_MAGIC (0xfedccdef) | ||
82 | #define WIL_FW_CONCURRENCY_REC_VER 1 | ||
83 | struct wil_fw_concurrency_limit { | ||
84 | __le16 max; /* maximum number of interfaces of these types */ | ||
85 | __le16 types; /* interface types (bit mask of enum nl80211_iftype) */ | ||
86 | } __packed; | ||
87 | |||
88 | struct wil_fw_concurrency_combo { | ||
89 | u8 n_limits; /* number of wil_fw_concurrency_limit entries */ | ||
90 | u8 max_interfaces; /* max number of concurrent interfaces allowed */ | ||
91 | u8 n_diff_channels; /* total number of different channels allowed */ | ||
92 | u8 same_bi; /* for APs, 1 if all APs must have same BI */ | ||
93 | /* keep last - concurrency limits, variable size by n_limits */ | ||
94 | struct wil_fw_concurrency_limit limits[0]; | ||
95 | } __packed; | ||
96 | |||
97 | struct wil_fw_record_concurrency { /* type == wil_fw_type_comment */ | ||
98 | /* identifies concurrency record */ | ||
99 | __le32 magic; | ||
100 | /* structure version, currently always 1 */ | ||
101 | u8 version; | ||
102 | /* maximum number of supported MIDs _in addition_ to MID 0 */ | ||
103 | u8 n_mids; | ||
104 | /* number of concurrency combinations that follow */ | ||
105 | __le16 n_combos; | ||
106 | /* keep last - combinations, variable size by n_combos */ | ||
107 | struct wil_fw_concurrency_combo combos[0]; | ||
108 | } __packed; | ||
75 | 109 | ||
76 | /* brd file info encoded inside a comment record */ | 110 | /* brd file info encoded inside a comment record */ |
77 | #define WIL_BRD_FILE_MAGIC (0xabcddcbb) | 111 | #define WIL_BRD_FILE_MAGIC (0xabcddcbb) |
@@ -175,3 +209,5 @@ struct wil_fw_record_gateway_data4 { /* type == wil_fw_type_gateway_data4 */ | |||
175 | __le32 command; | 209 | __le32 command; |
176 | struct wil_fw_data_gw4 data[0]; /* total size [data_size], see above */ | 210 | struct wil_fw_data_gw4 data[0]; /* total size [data_size], see above */ |
177 | } __packed; | 211 | } __packed; |
212 | |||
213 | #endif /* __WIL_FW_H__ */ | ||
diff --git a/drivers/net/wireless/ath/wil6210/fw_inc.c b/drivers/net/wireless/ath/wil6210/fw_inc.c index 914c0106e94b..718161b829c2 100644 --- a/drivers/net/wireless/ath/wil6210/fw_inc.c +++ b/drivers/net/wireless/ath/wil6210/fw_inc.c | |||
@@ -136,8 +136,8 @@ fw_handle_capabilities(struct wil6210_priv *wil, const void *data, | |||
136 | size_t capa_size; | 136 | size_t capa_size; |
137 | 137 | ||
138 | if (size < sizeof(*rec)) { | 138 | if (size < sizeof(*rec)) { |
139 | wil_hex_dump_fw("", DUMP_PREFIX_OFFSET, 16, 1, | 139 | wil_err_fw(wil, "capabilities record too short: %zu\n", size); |
140 | data, size, true); | 140 | /* let the FW load anyway */ |
141 | return 0; | 141 | return 0; |
142 | } | 142 | } |
143 | 143 | ||
@@ -158,8 +158,7 @@ fw_handle_brd_file(struct wil6210_priv *wil, const void *data, | |||
158 | const struct wil_fw_record_brd_file *rec = data; | 158 | const struct wil_fw_record_brd_file *rec = data; |
159 | 159 | ||
160 | if (size < sizeof(*rec)) { | 160 | if (size < sizeof(*rec)) { |
161 | wil_hex_dump_fw("", DUMP_PREFIX_OFFSET, 16, 1, | 161 | wil_err_fw(wil, "brd_file record too short: %zu\n", size); |
162 | data, size, true); | ||
163 | return 0; | 162 | return 0; |
164 | } | 163 | } |
165 | 164 | ||
@@ -173,6 +172,44 @@ fw_handle_brd_file(struct wil6210_priv *wil, const void *data, | |||
173 | } | 172 | } |
174 | 173 | ||
175 | static int | 174 | static int |
175 | fw_handle_concurrency(struct wil6210_priv *wil, const void *data, | ||
176 | size_t size) | ||
177 | { | ||
178 | const struct wil_fw_record_concurrency *rec = data; | ||
179 | const struct wil_fw_concurrency_combo *combo; | ||
180 | const struct wil_fw_concurrency_limit *limit; | ||
181 | size_t remain, lsize; | ||
182 | int i, n_combos; | ||
183 | |||
184 | if (size < sizeof(*rec)) { | ||
185 | wil_err_fw(wil, "concurrency record too short: %zu\n", size); | ||
186 | /* continue, let the FW load anyway */ | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | n_combos = le16_to_cpu(rec->n_combos); | ||
191 | remain = size - offsetof(struct wil_fw_record_concurrency, combos); | ||
192 | combo = rec->combos; | ||
193 | for (i = 0; i < n_combos; i++) { | ||
194 | if (remain < sizeof(*combo)) | ||
195 | goto out_short; | ||
196 | remain -= sizeof(*combo); | ||
197 | limit = combo->limits; | ||
198 | lsize = combo->n_limits * sizeof(*limit); | ||
199 | if (remain < lsize) | ||
200 | goto out_short; | ||
201 | remain -= lsize; | ||
202 | limit += combo->n_limits; | ||
203 | combo = (struct wil_fw_concurrency_combo *)limit; | ||
204 | } | ||
205 | |||
206 | return wil_cfg80211_iface_combinations_from_fw(wil, rec); | ||
207 | out_short: | ||
208 | wil_err_fw(wil, "concurrency record truncated\n"); | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static int | ||
176 | fw_handle_comment(struct wil6210_priv *wil, const void *data, | 213 | fw_handle_comment(struct wil6210_priv *wil, const void *data, |
177 | size_t size) | 214 | size_t size) |
178 | { | 215 | { |
@@ -194,6 +231,13 @@ fw_handle_comment(struct wil6210_priv *wil, const void *data, | |||
194 | wil_dbg_fw(wil, "magic is WIL_BRD_FILE_MAGIC\n"); | 231 | wil_dbg_fw(wil, "magic is WIL_BRD_FILE_MAGIC\n"); |
195 | rc = fw_handle_brd_file(wil, data, size); | 232 | rc = fw_handle_brd_file(wil, data, size); |
196 | break; | 233 | break; |
234 | case WIL_FW_CONCURRENCY_MAGIC: | ||
235 | wil_dbg_fw(wil, "magic is WIL_FW_CONCURRENCY_MAGIC\n"); | ||
236 | rc = fw_handle_concurrency(wil, data, size); | ||
237 | break; | ||
238 | default: | ||
239 | wil_hex_dump_fw("", DUMP_PREFIX_OFFSET, 16, 1, | ||
240 | data, size, true); | ||
197 | } | 241 | } |
198 | 242 | ||
199 | return rc; | 243 | return rc; |
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index 1835187ea075..84e9840c1752 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c | |||
@@ -127,7 +127,7 @@ void wil6210_unmask_irq_tx(struct wil6210_priv *wil) | |||
127 | 127 | ||
128 | void wil6210_unmask_irq_rx(struct wil6210_priv *wil) | 128 | void wil6210_unmask_irq_rx(struct wil6210_priv *wil) |
129 | { | 129 | { |
130 | bool unmask_rx_htrsh = test_bit(wil_status_fwconnected, wil->status); | 130 | bool unmask_rx_htrsh = atomic_read(&wil->connected_vifs) > 0; |
131 | 131 | ||
132 | wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, IMC), | 132 | wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, IMC), |
133 | unmask_rx_htrsh ? WIL6210_IMC_RX : WIL6210_IMC_RX_NO_RX_HTRSH); | 133 | unmask_rx_htrsh ? WIL6210_IMC_RX : WIL6210_IMC_RX_NO_RX_HTRSH); |
@@ -188,12 +188,14 @@ void wil_unmask_irq(struct wil6210_priv *wil) | |||
188 | 188 | ||
189 | void wil_configure_interrupt_moderation(struct wil6210_priv *wil) | 189 | void wil_configure_interrupt_moderation(struct wil6210_priv *wil) |
190 | { | 190 | { |
191 | struct wireless_dev *wdev = wil->main_ndev->ieee80211_ptr; | ||
192 | |||
191 | wil_dbg_irq(wil, "configure_interrupt_moderation\n"); | 193 | wil_dbg_irq(wil, "configure_interrupt_moderation\n"); |
192 | 194 | ||
193 | /* disable interrupt moderation for monitor | 195 | /* disable interrupt moderation for monitor |
194 | * to get better timestamp precision | 196 | * to get better timestamp precision |
195 | */ | 197 | */ |
196 | if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) | 198 | if (wdev->iftype == NL80211_IFTYPE_MONITOR) |
197 | return; | 199 | return; |
198 | 200 | ||
199 | /* Disable and clear tx counter before (re)configuration */ | 201 | /* Disable and clear tx counter before (re)configuration */ |
@@ -340,7 +342,7 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie) | |||
340 | 342 | ||
341 | static void wil_notify_fw_error(struct wil6210_priv *wil) | 343 | static void wil_notify_fw_error(struct wil6210_priv *wil) |
342 | { | 344 | { |
343 | struct device *dev = &wil_to_ndev(wil)->dev; | 345 | struct device *dev = &wil->main_ndev->dev; |
344 | char *envp[3] = { | 346 | char *envp[3] = { |
345 | [0] = "SOURCE=wil6210", | 347 | [0] = "SOURCE=wil6210", |
346 | [1] = "EVENT=FW_ERROR", | 348 | [1] = "EVENT=FW_ERROR", |
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 0c61a6c13991..a4b413e8d55a 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c | |||
@@ -160,24 +160,34 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, | |||
160 | } | 160 | } |
161 | } | 161 | } |
162 | 162 | ||
163 | static void wil_disconnect_cid(struct wil6210_priv *wil, int cid, | 163 | static void wil_disconnect_cid(struct wil6210_vif *vif, int cid, |
164 | u16 reason_code, bool from_event) | 164 | u16 reason_code, bool from_event) |
165 | __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | 165 | __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) |
166 | { | 166 | { |
167 | uint i; | 167 | uint i; |
168 | struct net_device *ndev = wil_to_ndev(wil); | 168 | struct wil6210_priv *wil = vif_to_wil(vif); |
169 | struct wireless_dev *wdev = wil->wdev; | 169 | struct net_device *ndev = vif_to_ndev(vif); |
170 | struct wireless_dev *wdev = vif_to_wdev(vif); | ||
170 | struct wil_sta_info *sta = &wil->sta[cid]; | 171 | struct wil_sta_info *sta = &wil->sta[cid]; |
171 | 172 | ||
172 | might_sleep(); | 173 | might_sleep(); |
173 | wil_dbg_misc(wil, "disconnect_cid: CID %d, status %d\n", | 174 | wil_dbg_misc(wil, "disconnect_cid: CID %d, MID %d, status %d\n", |
174 | cid, sta->status); | 175 | cid, sta->mid, sta->status); |
175 | /* inform upper/lower layers */ | 176 | /* inform upper/lower layers */ |
176 | if (sta->status != wil_sta_unused) { | 177 | if (sta->status != wil_sta_unused) { |
178 | if (vif->mid != sta->mid) { | ||
179 | wil_err(wil, "STA MID mismatch with VIF MID(%d)\n", | ||
180 | vif->mid); | ||
181 | /* let FW override sta->mid but be more strict with | ||
182 | * user space requests | ||
183 | */ | ||
184 | if (!from_event) | ||
185 | return; | ||
186 | } | ||
177 | if (!from_event) { | 187 | if (!from_event) { |
178 | bool del_sta = (wdev->iftype == NL80211_IFTYPE_AP) ? | 188 | bool del_sta = (wdev->iftype == NL80211_IFTYPE_AP) ? |
179 | disable_ap_sme : false; | 189 | disable_ap_sme : false; |
180 | wmi_disconnect_sta(wil, sta->addr, reason_code, | 190 | wmi_disconnect_sta(vif, sta->addr, reason_code, |
181 | true, del_sta); | 191 | true, del_sta); |
182 | } | 192 | } |
183 | 193 | ||
@@ -191,6 +201,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | |||
191 | break; | 201 | break; |
192 | } | 202 | } |
193 | sta->status = wil_sta_unused; | 203 | sta->status = wil_sta_unused; |
204 | sta->mid = U8_MAX; | ||
194 | } | 205 | } |
195 | /* reorder buffers */ | 206 | /* reorder buffers */ |
196 | for (i = 0; i < WIL_STA_TID_NUM; i++) { | 207 | for (i = 0; i < WIL_STA_TID_NUM; i++) { |
@@ -216,28 +227,33 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | |||
216 | memset(&sta->stats, 0, sizeof(sta->stats)); | 227 | memset(&sta->stats, 0, sizeof(sta->stats)); |
217 | } | 228 | } |
218 | 229 | ||
219 | static bool wil_is_connected(struct wil6210_priv *wil) | 230 | static bool wil_vif_is_connected(struct wil6210_priv *wil, u8 mid) |
220 | { | 231 | { |
221 | int i; | 232 | int i; |
222 | 233 | ||
223 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { | 234 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { |
224 | if (wil->sta[i].status == wil_sta_connected) | 235 | if (wil->sta[i].mid == mid && |
236 | wil->sta[i].status == wil_sta_connected) | ||
225 | return true; | 237 | return true; |
226 | } | 238 | } |
227 | 239 | ||
228 | return false; | 240 | return false; |
229 | } | 241 | } |
230 | 242 | ||
231 | static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, | 243 | static void _wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, |
232 | u16 reason_code, bool from_event) | 244 | u16 reason_code, bool from_event) |
233 | { | 245 | { |
246 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
234 | int cid = -ENOENT; | 247 | int cid = -ENOENT; |
235 | struct net_device *ndev = wil_to_ndev(wil); | 248 | struct net_device *ndev; |
236 | struct wireless_dev *wdev = wil->wdev; | 249 | struct wireless_dev *wdev; |
237 | 250 | ||
238 | if (unlikely(!ndev)) | 251 | if (unlikely(!vif)) |
239 | return; | 252 | return; |
240 | 253 | ||
254 | ndev = vif_to_ndev(vif); | ||
255 | wdev = vif_to_wdev(vif); | ||
256 | |||
241 | might_sleep(); | 257 | might_sleep(); |
242 | wil_info(wil, "bssid=%pM, reason=%d, ev%s\n", bssid, | 258 | wil_info(wil, "bssid=%pM, reason=%d, ev%s\n", bssid, |
243 | reason_code, from_event ? "+" : "-"); | 259 | reason_code, from_event ? "+" : "-"); |
@@ -254,48 +270,51 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, | |||
254 | */ | 270 | */ |
255 | if (bssid && !is_broadcast_ether_addr(bssid) && | 271 | if (bssid && !is_broadcast_ether_addr(bssid) && |
256 | !ether_addr_equal_unaligned(ndev->dev_addr, bssid)) { | 272 | !ether_addr_equal_unaligned(ndev->dev_addr, bssid)) { |
257 | cid = wil_find_cid(wil, bssid); | 273 | cid = wil_find_cid(wil, vif->mid, bssid); |
258 | wil_dbg_misc(wil, "Disconnect %pM, CID=%d, reason=%d\n", | 274 | wil_dbg_misc(wil, "Disconnect %pM, CID=%d, reason=%d\n", |
259 | bssid, cid, reason_code); | 275 | bssid, cid, reason_code); |
260 | if (cid >= 0) /* disconnect 1 peer */ | 276 | if (cid >= 0) /* disconnect 1 peer */ |
261 | wil_disconnect_cid(wil, cid, reason_code, from_event); | 277 | wil_disconnect_cid(vif, cid, reason_code, from_event); |
262 | } else { /* all */ | 278 | } else { /* all */ |
263 | wil_dbg_misc(wil, "Disconnect all\n"); | 279 | wil_dbg_misc(wil, "Disconnect all\n"); |
264 | for (cid = 0; cid < WIL6210_MAX_CID; cid++) | 280 | for (cid = 0; cid < WIL6210_MAX_CID; cid++) |
265 | wil_disconnect_cid(wil, cid, reason_code, from_event); | 281 | wil_disconnect_cid(vif, cid, reason_code, from_event); |
266 | } | 282 | } |
267 | 283 | ||
268 | /* link state */ | 284 | /* link state */ |
269 | switch (wdev->iftype) { | 285 | switch (wdev->iftype) { |
270 | case NL80211_IFTYPE_STATION: | 286 | case NL80211_IFTYPE_STATION: |
271 | case NL80211_IFTYPE_P2P_CLIENT: | 287 | case NL80211_IFTYPE_P2P_CLIENT: |
272 | wil_bcast_fini(wil); | 288 | wil_bcast_fini(vif); |
273 | wil_update_net_queues_bh(wil, NULL, true); | 289 | wil_update_net_queues_bh(wil, vif, NULL, true); |
274 | netif_carrier_off(ndev); | 290 | netif_carrier_off(ndev); |
275 | wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS); | 291 | if (!wil_has_other_active_ifaces(wil, ndev, false, true)) |
292 | wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS); | ||
276 | 293 | ||
277 | if (test_bit(wil_status_fwconnected, wil->status)) { | 294 | if (test_and_clear_bit(wil_vif_fwconnected, vif->status)) { |
278 | clear_bit(wil_status_fwconnected, wil->status); | 295 | atomic_dec(&wil->connected_vifs); |
279 | cfg80211_disconnected(ndev, reason_code, | 296 | cfg80211_disconnected(ndev, reason_code, |
280 | NULL, 0, | 297 | NULL, 0, |
281 | wil->locally_generated_disc, | 298 | vif->locally_generated_disc, |
282 | GFP_KERNEL); | 299 | GFP_KERNEL); |
283 | wil->locally_generated_disc = false; | 300 | vif->locally_generated_disc = false; |
284 | } else if (test_bit(wil_status_fwconnecting, wil->status)) { | 301 | } else if (test_bit(wil_vif_fwconnecting, vif->status)) { |
285 | cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0, | 302 | cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0, |
286 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 303 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
287 | GFP_KERNEL); | 304 | GFP_KERNEL); |
288 | wil->bss = NULL; | 305 | vif->bss = NULL; |
289 | } | 306 | } |
290 | clear_bit(wil_status_fwconnecting, wil->status); | 307 | clear_bit(wil_vif_fwconnecting, vif->status); |
291 | break; | 308 | break; |
292 | case NL80211_IFTYPE_AP: | 309 | case NL80211_IFTYPE_AP: |
293 | case NL80211_IFTYPE_P2P_GO: | 310 | case NL80211_IFTYPE_P2P_GO: |
294 | if (!wil_is_connected(wil)) { | 311 | if (!wil_vif_is_connected(wil, vif->mid)) { |
295 | wil_update_net_queues_bh(wil, NULL, true); | 312 | wil_update_net_queues_bh(wil, vif, NULL, true); |
296 | clear_bit(wil_status_fwconnected, wil->status); | 313 | if (test_and_clear_bit(wil_vif_fwconnected, |
314 | vif->status)) | ||
315 | atomic_dec(&wil->connected_vifs); | ||
297 | } else { | 316 | } else { |
298 | wil_update_net_queues_bh(wil, NULL, false); | 317 | wil_update_net_queues_bh(wil, vif, NULL, false); |
299 | } | 318 | } |
300 | break; | 319 | break; |
301 | default: | 320 | default: |
@@ -303,26 +322,27 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, | |||
303 | } | 322 | } |
304 | } | 323 | } |
305 | 324 | ||
306 | static void wil_disconnect_worker(struct work_struct *work) | 325 | void wil_disconnect_worker(struct work_struct *work) |
307 | { | 326 | { |
308 | struct wil6210_priv *wil = container_of(work, | 327 | struct wil6210_vif *vif = container_of(work, |
309 | struct wil6210_priv, disconnect_worker); | 328 | struct wil6210_vif, disconnect_worker); |
310 | struct net_device *ndev = wil_to_ndev(wil); | 329 | struct wil6210_priv *wil = vif_to_wil(vif); |
330 | struct net_device *ndev = vif_to_ndev(vif); | ||
311 | int rc; | 331 | int rc; |
312 | struct { | 332 | struct { |
313 | struct wmi_cmd_hdr wmi; | 333 | struct wmi_cmd_hdr wmi; |
314 | struct wmi_disconnect_event evt; | 334 | struct wmi_disconnect_event evt; |
315 | } __packed reply; | 335 | } __packed reply; |
316 | 336 | ||
317 | if (test_bit(wil_status_fwconnected, wil->status)) | 337 | if (test_bit(wil_vif_fwconnected, vif->status)) |
318 | /* connect succeeded after all */ | 338 | /* connect succeeded after all */ |
319 | return; | 339 | return; |
320 | 340 | ||
321 | if (!test_bit(wil_status_fwconnecting, wil->status)) | 341 | if (!test_bit(wil_vif_fwconnecting, vif->status)) |
322 | /* already disconnected */ | 342 | /* already disconnected */ |
323 | return; | 343 | return; |
324 | 344 | ||
325 | rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0, | 345 | rc = wmi_call(wil, WMI_DISCONNECT_CMDID, vif->mid, NULL, 0, |
326 | WMI_DISCONNECT_EVENTID, &reply, sizeof(reply), | 346 | WMI_DISCONNECT_EVENTID, &reply, sizeof(reply), |
327 | WIL6210_DISCONNECT_TO_MS); | 347 | WIL6210_DISCONNECT_TO_MS); |
328 | if (rc) { | 348 | if (rc) { |
@@ -330,35 +350,11 @@ static void wil_disconnect_worker(struct work_struct *work) | |||
330 | return; | 350 | return; |
331 | } | 351 | } |
332 | 352 | ||
333 | wil_update_net_queues_bh(wil, NULL, true); | 353 | wil_update_net_queues_bh(wil, vif, NULL, true); |
334 | netif_carrier_off(ndev); | 354 | netif_carrier_off(ndev); |
335 | cfg80211_connect_result(ndev, NULL, NULL, 0, NULL, 0, | 355 | cfg80211_connect_result(ndev, NULL, NULL, 0, NULL, 0, |
336 | WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL); | 356 | WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL); |
337 | clear_bit(wil_status_fwconnecting, wil->status); | 357 | clear_bit(wil_vif_fwconnecting, vif->status); |
338 | } | ||
339 | |||
340 | static void wil_connect_timer_fn(struct timer_list *t) | ||
341 | { | ||
342 | struct wil6210_priv *wil = from_timer(wil, t, connect_timer); | ||
343 | bool q; | ||
344 | |||
345 | wil_err(wil, "Connect timeout detected, disconnect station\n"); | ||
346 | |||
347 | /* reschedule to thread context - disconnect won't | ||
348 | * run from atomic context. | ||
349 | * queue on wmi_wq to prevent race with connect event. | ||
350 | */ | ||
351 | q = queue_work(wil->wmi_wq, &wil->disconnect_worker); | ||
352 | wil_dbg_wmi(wil, "queue_work of disconnect_worker -> %d\n", q); | ||
353 | } | ||
354 | |||
355 | static void wil_scan_timer_fn(struct timer_list *t) | ||
356 | { | ||
357 | struct wil6210_priv *wil = from_timer(wil, t, scan_timer); | ||
358 | |||
359 | clear_bit(wil_status_fwready, wil->status); | ||
360 | wil_err(wil, "Scan timeout detected, start fw error recovery\n"); | ||
361 | wil_fw_error_recovery(wil); | ||
362 | } | 358 | } |
363 | 359 | ||
364 | static int wil_wait_for_recovery(struct wil6210_priv *wil) | 360 | static int wil_wait_for_recovery(struct wil6210_priv *wil) |
@@ -394,12 +390,12 @@ static void wil_fw_error_worker(struct work_struct *work) | |||
394 | { | 390 | { |
395 | struct wil6210_priv *wil = container_of(work, struct wil6210_priv, | 391 | struct wil6210_priv *wil = container_of(work, struct wil6210_priv, |
396 | fw_error_worker); | 392 | fw_error_worker); |
397 | struct wireless_dev *wdev = wil->wdev; | 393 | struct net_device *ndev = wil->main_ndev; |
398 | struct net_device *ndev = wil_to_ndev(wil); | 394 | struct wireless_dev *wdev = ndev->ieee80211_ptr; |
399 | 395 | ||
400 | wil_dbg_misc(wil, "fw error worker\n"); | 396 | wil_dbg_misc(wil, "fw error worker\n"); |
401 | 397 | ||
402 | if (!(ndev->flags & IFF_UP)) { | 398 | if (!ndev || !(ndev->flags & IFF_UP)) { |
403 | wil_info(wil, "No recovery - interface is down\n"); | 399 | wil_info(wil, "No recovery - interface is down\n"); |
404 | return; | 400 | return; |
405 | } | 401 | } |
@@ -429,6 +425,10 @@ static void wil_fw_error_worker(struct work_struct *work) | |||
429 | return; | 425 | return; |
430 | 426 | ||
431 | mutex_lock(&wil->mutex); | 427 | mutex_lock(&wil->mutex); |
428 | /* Needs adaptation for multiple VIFs | ||
429 | * need to go over all VIFs and consider the appropriate | ||
430 | * recovery. | ||
431 | */ | ||
432 | switch (wdev->iftype) { | 432 | switch (wdev->iftype) { |
433 | case NL80211_IFTYPE_STATION: | 433 | case NL80211_IFTYPE_STATION: |
434 | case NL80211_IFTYPE_P2P_CLIENT: | 434 | case NL80211_IFTYPE_P2P_CLIENT: |
@@ -461,8 +461,9 @@ static int wil_find_free_vring(struct wil6210_priv *wil) | |||
461 | return -EINVAL; | 461 | return -EINVAL; |
462 | } | 462 | } |
463 | 463 | ||
464 | int wil_tx_init(struct wil6210_priv *wil, int cid) | 464 | int wil_tx_init(struct wil6210_vif *vif, int cid) |
465 | { | 465 | { |
466 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
466 | int rc = -EINVAL, ringid; | 467 | int rc = -EINVAL, ringid; |
467 | 468 | ||
468 | if (cid < 0) { | 469 | if (cid < 0) { |
@@ -475,21 +476,22 @@ int wil_tx_init(struct wil6210_priv *wil, int cid) | |||
475 | goto out; | 476 | goto out; |
476 | } | 477 | } |
477 | 478 | ||
478 | wil_dbg_wmi(wil, "Configure for connection CID %d vring %d\n", | 479 | wil_dbg_wmi(wil, "Configure for connection CID %d MID %d vring %d\n", |
479 | cid, ringid); | 480 | cid, vif->mid, ringid); |
480 | 481 | ||
481 | rc = wil_vring_init_tx(wil, ringid, 1 << tx_ring_order, cid, 0); | 482 | rc = wil_vring_init_tx(vif, ringid, 1 << tx_ring_order, cid, 0); |
482 | if (rc) | 483 | if (rc) |
483 | wil_err(wil, "wil_vring_init_tx for CID %d vring %d failed\n", | 484 | wil_err(wil, "init TX for CID %d MID %d vring %d failed\n", |
484 | cid, ringid); | 485 | cid, vif->mid, ringid); |
485 | 486 | ||
486 | out: | 487 | out: |
487 | return rc; | 488 | return rc; |
488 | } | 489 | } |
489 | 490 | ||
490 | int wil_bcast_init(struct wil6210_priv *wil) | 491 | int wil_bcast_init(struct wil6210_vif *vif) |
491 | { | 492 | { |
492 | int ri = wil->bcast_vring, rc; | 493 | struct wil6210_priv *wil = vif_to_wil(vif); |
494 | int ri = vif->bcast_vring, rc; | ||
493 | 495 | ||
494 | if ((ri >= 0) && wil->vring_tx[ri].va) | 496 | if ((ri >= 0) && wil->vring_tx[ri].va) |
495 | return 0; | 497 | return 0; |
@@ -498,25 +500,38 @@ int wil_bcast_init(struct wil6210_priv *wil) | |||
498 | if (ri < 0) | 500 | if (ri < 0) |
499 | return ri; | 501 | return ri; |
500 | 502 | ||
501 | wil->bcast_vring = ri; | 503 | vif->bcast_vring = ri; |
502 | rc = wil_vring_init_bcast(wil, ri, 1 << bcast_ring_order); | 504 | rc = wil_vring_init_bcast(vif, ri, 1 << bcast_ring_order); |
503 | if (rc) | 505 | if (rc) |
504 | wil->bcast_vring = -1; | 506 | vif->bcast_vring = -1; |
505 | 507 | ||
506 | return rc; | 508 | return rc; |
507 | } | 509 | } |
508 | 510 | ||
509 | void wil_bcast_fini(struct wil6210_priv *wil) | 511 | void wil_bcast_fini(struct wil6210_vif *vif) |
510 | { | 512 | { |
511 | int ri = wil->bcast_vring; | 513 | struct wil6210_priv *wil = vif_to_wil(vif); |
514 | int ri = vif->bcast_vring; | ||
512 | 515 | ||
513 | if (ri < 0) | 516 | if (ri < 0) |
514 | return; | 517 | return; |
515 | 518 | ||
516 | wil->bcast_vring = -1; | 519 | vif->bcast_vring = -1; |
517 | wil_vring_fini_tx(wil, ri); | 520 | wil_vring_fini_tx(wil, ri); |
518 | } | 521 | } |
519 | 522 | ||
523 | void wil_bcast_fini_all(struct wil6210_priv *wil) | ||
524 | { | ||
525 | int i; | ||
526 | struct wil6210_vif *vif; | ||
527 | |||
528 | for (i = 0; i < wil->max_vifs; i++) { | ||
529 | vif = wil->vifs[i]; | ||
530 | if (vif) | ||
531 | wil_bcast_fini(vif); | ||
532 | } | ||
533 | } | ||
534 | |||
520 | int wil_priv_init(struct wil6210_priv *wil) | 535 | int wil_priv_init(struct wil6210_priv *wil) |
521 | { | 536 | { |
522 | uint i; | 537 | uint i; |
@@ -524,38 +539,29 @@ int wil_priv_init(struct wil6210_priv *wil) | |||
524 | wil_dbg_misc(wil, "priv_init\n"); | 539 | wil_dbg_misc(wil, "priv_init\n"); |
525 | 540 | ||
526 | memset(wil->sta, 0, sizeof(wil->sta)); | 541 | memset(wil->sta, 0, sizeof(wil->sta)); |
527 | for (i = 0; i < WIL6210_MAX_CID; i++) | 542 | for (i = 0; i < WIL6210_MAX_CID; i++) { |
528 | spin_lock_init(&wil->sta[i].tid_rx_lock); | 543 | spin_lock_init(&wil->sta[i].tid_rx_lock); |
544 | wil->sta[i].mid = U8_MAX; | ||
545 | } | ||
529 | 546 | ||
530 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) | 547 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) |
531 | spin_lock_init(&wil->vring_tx_data[i].lock); | 548 | spin_lock_init(&wil->vring_tx_data[i].lock); |
532 | 549 | ||
533 | mutex_init(&wil->mutex); | 550 | mutex_init(&wil->mutex); |
551 | mutex_init(&wil->vif_mutex); | ||
534 | mutex_init(&wil->wmi_mutex); | 552 | mutex_init(&wil->wmi_mutex); |
535 | mutex_init(&wil->probe_client_mutex); | ||
536 | mutex_init(&wil->p2p_wdev_mutex); | ||
537 | mutex_init(&wil->halp.lock); | 553 | mutex_init(&wil->halp.lock); |
538 | 554 | ||
539 | init_completion(&wil->wmi_ready); | 555 | init_completion(&wil->wmi_ready); |
540 | init_completion(&wil->wmi_call); | 556 | init_completion(&wil->wmi_call); |
541 | init_completion(&wil->halp.comp); | 557 | init_completion(&wil->halp.comp); |
542 | 558 | ||
543 | wil->bcast_vring = -1; | ||
544 | timer_setup(&wil->connect_timer, wil_connect_timer_fn, 0); | ||
545 | timer_setup(&wil->scan_timer, wil_scan_timer_fn, 0); | ||
546 | timer_setup(&wil->p2p.discovery_timer, wil_p2p_discovery_timer_fn, 0); | ||
547 | |||
548 | INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); | ||
549 | INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); | 559 | INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); |
550 | INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker); | 560 | INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker); |
551 | INIT_WORK(&wil->probe_client_worker, wil_probe_client_worker); | ||
552 | INIT_WORK(&wil->p2p.delayed_listen_work, wil_p2p_delayed_listen_work); | ||
553 | 561 | ||
554 | INIT_LIST_HEAD(&wil->pending_wmi_ev); | 562 | INIT_LIST_HEAD(&wil->pending_wmi_ev); |
555 | INIT_LIST_HEAD(&wil->probe_client_pending); | ||
556 | spin_lock_init(&wil->wmi_ev_lock); | 563 | spin_lock_init(&wil->wmi_ev_lock); |
557 | spin_lock_init(&wil->net_queue_lock); | 564 | spin_lock_init(&wil->net_queue_lock); |
558 | wil->net_queue_stopped = 1; | ||
559 | init_waitqueue_head(&wil->wq); | 565 | init_waitqueue_head(&wil->wq); |
560 | 566 | ||
561 | wil->wmi_wq = create_singlethread_workqueue(WIL_NAME "_wmi"); | 567 | wil->wmi_wq = create_singlethread_workqueue(WIL_NAME "_wmi"); |
@@ -582,6 +588,9 @@ int wil_priv_init(struct wil6210_priv *wil) | |||
582 | memset(&wil->suspend_stats, 0, sizeof(wil->suspend_stats)); | 588 | memset(&wil->suspend_stats, 0, sizeof(wil->suspend_stats)); |
583 | wil->vring_idle_trsh = 16; | 589 | wil->vring_idle_trsh = 16; |
584 | 590 | ||
591 | wil->reply_mid = U8_MAX; | ||
592 | wil->max_vifs = 1; | ||
593 | |||
585 | return 0; | 594 | return 0; |
586 | 595 | ||
587 | out_wmi_wq: | 596 | out_wmi_wq: |
@@ -600,7 +609,7 @@ void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps) | |||
600 | 609 | ||
601 | /** | 610 | /** |
602 | * wil6210_disconnect - disconnect one connection | 611 | * wil6210_disconnect - disconnect one connection |
603 | * @wil: driver context | 612 | * @vif: virtual interface context |
604 | * @bssid: peer to disconnect, NULL to disconnect all | 613 | * @bssid: peer to disconnect, NULL to disconnect all |
605 | * @reason_code: Reason code for the Disassociation frame | 614 | * @reason_code: Reason code for the Disassociation frame |
606 | * @from_event: whether is invoked from FW event handler | 615 | * @from_event: whether is invoked from FW event handler |
@@ -608,13 +617,15 @@ void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps) | |||
608 | * Disconnect and release associated resources. If invoked not from the | 617 | * Disconnect and release associated resources. If invoked not from the |
609 | * FW event handler, issue WMI command(s) to trigger MAC disconnect. | 618 | * FW event handler, issue WMI command(s) to trigger MAC disconnect. |
610 | */ | 619 | */ |
611 | void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, | 620 | void wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, |
612 | u16 reason_code, bool from_event) | 621 | u16 reason_code, bool from_event) |
613 | { | 622 | { |
623 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
624 | |||
614 | wil_dbg_misc(wil, "disconnect\n"); | 625 | wil_dbg_misc(wil, "disconnect\n"); |
615 | 626 | ||
616 | del_timer_sync(&wil->connect_timer); | 627 | del_timer_sync(&vif->connect_timer); |
617 | _wil6210_disconnect(wil, bssid, reason_code, from_event); | 628 | _wil6210_disconnect(vif, bssid, reason_code, from_event); |
618 | } | 629 | } |
619 | 630 | ||
620 | void wil_priv_deinit(struct wil6210_priv *wil) | 631 | void wil_priv_deinit(struct wil6210_priv *wil) |
@@ -622,18 +633,8 @@ void wil_priv_deinit(struct wil6210_priv *wil) | |||
622 | wil_dbg_misc(wil, "priv_deinit\n"); | 633 | wil_dbg_misc(wil, "priv_deinit\n"); |
623 | 634 | ||
624 | wil_set_recovery_state(wil, fw_recovery_idle); | 635 | wil_set_recovery_state(wil, fw_recovery_idle); |
625 | del_timer_sync(&wil->scan_timer); | ||
626 | del_timer_sync(&wil->p2p.discovery_timer); | ||
627 | cancel_work_sync(&wil->disconnect_worker); | ||
628 | cancel_work_sync(&wil->fw_error_worker); | 636 | cancel_work_sync(&wil->fw_error_worker); |
629 | cancel_work_sync(&wil->p2p.discovery_expired_work); | ||
630 | cancel_work_sync(&wil->p2p.delayed_listen_work); | ||
631 | mutex_lock(&wil->mutex); | ||
632 | wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false); | ||
633 | mutex_unlock(&wil->mutex); | ||
634 | wmi_event_flush(wil); | 637 | wmi_event_flush(wil); |
635 | wil_probe_client_flush(wil); | ||
636 | cancel_work_sync(&wil->probe_client_worker); | ||
637 | destroy_workqueue(wil->wq_service); | 638 | destroy_workqueue(wil->wq_service); |
638 | destroy_workqueue(wil->wmi_wq); | 639 | destroy_workqueue(wil->wmi_wq); |
639 | } | 640 | } |
@@ -715,7 +716,7 @@ static void wil_bl_prepare_halt(struct wil6210_priv *wil) | |||
715 | offsetof(struct bl_dedicated_registers_v0, | 716 | offsetof(struct bl_dedicated_registers_v0, |
716 | boot_loader_struct_version)); | 717 | boot_loader_struct_version)); |
717 | if (!tmp) { | 718 | if (!tmp) { |
718 | wil_dbg_misc(wil, "old BL, skipping halt preperation\n"); | 719 | wil_dbg_misc(wil, "old BL, skipping halt preparation\n"); |
719 | return; | 720 | return; |
720 | } | 721 | } |
721 | 722 | ||
@@ -943,7 +944,7 @@ void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r) | |||
943 | 944 | ||
944 | static int wil_get_bl_info(struct wil6210_priv *wil) | 945 | static int wil_get_bl_info(struct wil6210_priv *wil) |
945 | { | 946 | { |
946 | struct net_device *ndev = wil_to_ndev(wil); | 947 | struct net_device *ndev = wil->main_ndev; |
947 | struct wiphy *wiphy = wil_to_wiphy(wil); | 948 | struct wiphy *wiphy = wil_to_wiphy(wil); |
948 | union { | 949 | union { |
949 | struct bl_dedicated_registers_v0 bl0; | 950 | struct bl_dedicated_registers_v0 bl0; |
@@ -1035,7 +1036,7 @@ static void wil_bl_crash_info(struct wil6210_priv *wil, bool is_err) | |||
1035 | 1036 | ||
1036 | static int wil_get_otp_info(struct wil6210_priv *wil) | 1037 | static int wil_get_otp_info(struct wil6210_priv *wil) |
1037 | { | 1038 | { |
1038 | struct net_device *ndev = wil_to_ndev(wil); | 1039 | struct net_device *ndev = wil->main_ndev; |
1039 | struct wiphy *wiphy = wil_to_wiphy(wil); | 1040 | struct wiphy *wiphy = wil_to_wiphy(wil); |
1040 | u8 mac[8]; | 1041 | u8 mac[8]; |
1041 | 1042 | ||
@@ -1069,31 +1070,46 @@ static int wil_wait_for_fw_ready(struct wil6210_priv *wil) | |||
1069 | return 0; | 1070 | return 0; |
1070 | } | 1071 | } |
1071 | 1072 | ||
1072 | void wil_abort_scan(struct wil6210_priv *wil, bool sync) | 1073 | void wil_abort_scan(struct wil6210_vif *vif, bool sync) |
1073 | { | 1074 | { |
1075 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1074 | int rc; | 1076 | int rc; |
1075 | struct cfg80211_scan_info info = { | 1077 | struct cfg80211_scan_info info = { |
1076 | .aborted = true, | 1078 | .aborted = true, |
1077 | }; | 1079 | }; |
1078 | 1080 | ||
1079 | lockdep_assert_held(&wil->p2p_wdev_mutex); | 1081 | lockdep_assert_held(&wil->vif_mutex); |
1080 | 1082 | ||
1081 | if (!wil->scan_request) | 1083 | if (!vif->scan_request) |
1082 | return; | 1084 | return; |
1083 | 1085 | ||
1084 | wil_dbg_misc(wil, "Abort scan_request 0x%p\n", wil->scan_request); | 1086 | wil_dbg_misc(wil, "Abort scan_request 0x%p\n", vif->scan_request); |
1085 | del_timer_sync(&wil->scan_timer); | 1087 | del_timer_sync(&vif->scan_timer); |
1086 | mutex_unlock(&wil->p2p_wdev_mutex); | 1088 | mutex_unlock(&wil->vif_mutex); |
1087 | rc = wmi_abort_scan(wil); | 1089 | rc = wmi_abort_scan(vif); |
1088 | if (!rc && sync) | 1090 | if (!rc && sync) |
1089 | wait_event_interruptible_timeout(wil->wq, !wil->scan_request, | 1091 | wait_event_interruptible_timeout(wil->wq, !vif->scan_request, |
1090 | msecs_to_jiffies( | 1092 | msecs_to_jiffies( |
1091 | WAIT_FOR_SCAN_ABORT_MS)); | 1093 | WAIT_FOR_SCAN_ABORT_MS)); |
1092 | 1094 | ||
1093 | mutex_lock(&wil->p2p_wdev_mutex); | 1095 | mutex_lock(&wil->vif_mutex); |
1094 | if (wil->scan_request) { | 1096 | if (vif->scan_request) { |
1095 | cfg80211_scan_done(wil->scan_request, &info); | 1097 | cfg80211_scan_done(vif->scan_request, &info); |
1096 | wil->scan_request = NULL; | 1098 | vif->scan_request = NULL; |
1099 | } | ||
1100 | } | ||
1101 | |||
1102 | void wil_abort_scan_all_vifs(struct wil6210_priv *wil, bool sync) | ||
1103 | { | ||
1104 | int i; | ||
1105 | |||
1106 | lockdep_assert_held(&wil->vif_mutex); | ||
1107 | |||
1108 | for (i = 0; i < wil->max_vifs; i++) { | ||
1109 | struct wil6210_vif *vif = wil->vifs[i]; | ||
1110 | |||
1111 | if (vif) | ||
1112 | wil_abort_scan(vif, sync); | ||
1097 | } | 1113 | } |
1098 | } | 1114 | } |
1099 | 1115 | ||
@@ -1138,6 +1154,34 @@ static void wil_pre_fw_config(struct wil6210_priv *wil) | |||
1138 | } | 1154 | } |
1139 | } | 1155 | } |
1140 | 1156 | ||
1157 | static int wil_restore_vifs(struct wil6210_priv *wil) | ||
1158 | { | ||
1159 | struct wil6210_vif *vif; | ||
1160 | struct net_device *ndev; | ||
1161 | struct wireless_dev *wdev; | ||
1162 | int i, rc; | ||
1163 | |||
1164 | for (i = 0; i < wil->max_vifs; i++) { | ||
1165 | vif = wil->vifs[i]; | ||
1166 | if (!vif) | ||
1167 | continue; | ||
1168 | vif->ap_isolate = 0; | ||
1169 | if (vif->mid) { | ||
1170 | ndev = vif_to_ndev(vif); | ||
1171 | wdev = vif_to_wdev(vif); | ||
1172 | rc = wmi_port_allocate(wil, vif->mid, ndev->dev_addr, | ||
1173 | wdev->iftype); | ||
1174 | if (rc) { | ||
1175 | wil_err(wil, "fail to restore VIF %d type %d, rc %d\n", | ||
1176 | i, wdev->iftype, rc); | ||
1177 | return rc; | ||
1178 | } | ||
1179 | } | ||
1180 | } | ||
1181 | |||
1182 | return 0; | ||
1183 | } | ||
1184 | |||
1141 | /* | 1185 | /* |
1142 | * We reset all the structures, and we reset the UMAC. | 1186 | * We reset all the structures, and we reset the UMAC. |
1143 | * After calling this routine, you're expected to reload | 1187 | * After calling this routine, you're expected to reload |
@@ -1145,9 +1189,10 @@ static void wil_pre_fw_config(struct wil6210_priv *wil) | |||
1145 | */ | 1189 | */ |
1146 | int wil_reset(struct wil6210_priv *wil, bool load_fw) | 1190 | int wil_reset(struct wil6210_priv *wil, bool load_fw) |
1147 | { | 1191 | { |
1148 | int rc; | 1192 | int rc, i; |
1149 | unsigned long status_flags = BIT(wil_status_resetting); | 1193 | unsigned long status_flags = BIT(wil_status_resetting); |
1150 | int no_flash; | 1194 | int no_flash; |
1195 | struct wil6210_vif *vif; | ||
1151 | 1196 | ||
1152 | wil_dbg_misc(wil, "reset\n"); | 1197 | wil_dbg_misc(wil, "reset\n"); |
1153 | 1198 | ||
@@ -1158,7 +1203,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) | |||
1158 | static const u8 mac[ETH_ALEN] = { | 1203 | static const u8 mac[ETH_ALEN] = { |
1159 | 0x00, 0xde, 0xad, 0x12, 0x34, 0x56, | 1204 | 0x00, 0xde, 0xad, 0x12, 0x34, 0x56, |
1160 | }; | 1205 | }; |
1161 | struct net_device *ndev = wil_to_ndev(wil); | 1206 | struct net_device *ndev = wil->main_ndev; |
1162 | 1207 | ||
1163 | ether_addr_copy(ndev->perm_addr, mac); | 1208 | ether_addr_copy(ndev->perm_addr, mac); |
1164 | ether_addr_copy(ndev->dev_addr, ndev->perm_addr); | 1209 | ether_addr_copy(ndev->dev_addr, ndev->perm_addr); |
@@ -1196,17 +1241,23 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) | |||
1196 | goto out; | 1241 | goto out; |
1197 | } | 1242 | } |
1198 | 1243 | ||
1199 | cancel_work_sync(&wil->disconnect_worker); | 1244 | mutex_lock(&wil->vif_mutex); |
1200 | wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false); | 1245 | wil_abort_scan_all_vifs(wil, false); |
1201 | wil_bcast_fini(wil); | 1246 | mutex_unlock(&wil->vif_mutex); |
1247 | |||
1248 | for (i = 0; i < wil->max_vifs; i++) { | ||
1249 | vif = wil->vifs[i]; | ||
1250 | if (vif) { | ||
1251 | cancel_work_sync(&vif->disconnect_worker); | ||
1252 | wil6210_disconnect(vif, NULL, | ||
1253 | WLAN_REASON_DEAUTH_LEAVING, false); | ||
1254 | } | ||
1255 | } | ||
1256 | wil_bcast_fini_all(wil); | ||
1202 | 1257 | ||
1203 | /* Disable device led before reset*/ | 1258 | /* Disable device led before reset*/ |
1204 | wmi_led_cfg(wil, false); | 1259 | wmi_led_cfg(wil, false); |
1205 | 1260 | ||
1206 | mutex_lock(&wil->p2p_wdev_mutex); | ||
1207 | wil_abort_scan(wil, false); | ||
1208 | mutex_unlock(&wil->p2p_wdev_mutex); | ||
1209 | |||
1210 | /* prevent NAPI from being scheduled and prevent wmi commands */ | 1261 | /* prevent NAPI from being scheduled and prevent wmi commands */ |
1211 | mutex_lock(&wil->wmi_mutex); | 1262 | mutex_lock(&wil->wmi_mutex); |
1212 | if (test_bit(wil_status_suspending, wil->status)) | 1263 | if (test_bit(wil_status_suspending, wil->status)) |
@@ -1276,7 +1327,6 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) | |||
1276 | } | 1327 | } |
1277 | 1328 | ||
1278 | /* init after reset */ | 1329 | /* init after reset */ |
1279 | wil->ap_isolate = 0; | ||
1280 | reinit_completion(&wil->wmi_ready); | 1330 | reinit_completion(&wil->wmi_ready); |
1281 | reinit_completion(&wil->wmi_call); | 1331 | reinit_completion(&wil->wmi_call); |
1282 | reinit_completion(&wil->halp.comp); | 1332 | reinit_completion(&wil->halp.comp); |
@@ -1299,6 +1349,12 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) | |||
1299 | return rc; | 1349 | return rc; |
1300 | } | 1350 | } |
1301 | 1351 | ||
1352 | rc = wil_restore_vifs(wil); | ||
1353 | if (rc) { | ||
1354 | wil_err(wil, "failed to restore vifs, rc %d\n", rc); | ||
1355 | return rc; | ||
1356 | } | ||
1357 | |||
1302 | wil_collect_fw_info(wil); | 1358 | wil_collect_fw_info(wil); |
1303 | 1359 | ||
1304 | if (wil->ps_profile != WMI_PS_PROFILE_TYPE_DEFAULT) | 1360 | if (wil->ps_profile != WMI_PS_PROFILE_TYPE_DEFAULT) |
@@ -1337,8 +1393,8 @@ void wil_fw_error_recovery(struct wil6210_priv *wil) | |||
1337 | 1393 | ||
1338 | int __wil_up(struct wil6210_priv *wil) | 1394 | int __wil_up(struct wil6210_priv *wil) |
1339 | { | 1395 | { |
1340 | struct net_device *ndev = wil_to_ndev(wil); | 1396 | struct net_device *ndev = wil->main_ndev; |
1341 | struct wireless_dev *wdev = wil->wdev; | 1397 | struct wireless_dev *wdev = ndev->ieee80211_ptr; |
1342 | int rc; | 1398 | int rc; |
1343 | 1399 | ||
1344 | WARN_ON(!mutex_is_locked(&wil->mutex)); | 1400 | WARN_ON(!mutex_is_locked(&wil->mutex)); |
@@ -1420,10 +1476,10 @@ int __wil_down(struct wil6210_priv *wil) | |||
1420 | } | 1476 | } |
1421 | wil_enable_irq(wil); | 1477 | wil_enable_irq(wil); |
1422 | 1478 | ||
1423 | mutex_lock(&wil->p2p_wdev_mutex); | 1479 | mutex_lock(&wil->vif_mutex); |
1424 | wil_p2p_stop_radio_operations(wil); | 1480 | wil_p2p_stop_radio_operations(wil); |
1425 | wil_abort_scan(wil, false); | 1481 | wil_abort_scan_all_vifs(wil, false); |
1426 | mutex_unlock(&wil->p2p_wdev_mutex); | 1482 | mutex_unlock(&wil->vif_mutex); |
1427 | 1483 | ||
1428 | return wil_reset(wil, false); | 1484 | return wil_reset(wil, false); |
1429 | } | 1485 | } |
@@ -1442,13 +1498,14 @@ int wil_down(struct wil6210_priv *wil) | |||
1442 | return rc; | 1498 | return rc; |
1443 | } | 1499 | } |
1444 | 1500 | ||
1445 | int wil_find_cid(struct wil6210_priv *wil, const u8 *mac) | 1501 | int wil_find_cid(struct wil6210_priv *wil, u8 mid, const u8 *mac) |
1446 | { | 1502 | { |
1447 | int i; | 1503 | int i; |
1448 | int rc = -ENOENT; | 1504 | int rc = -ENOENT; |
1449 | 1505 | ||
1450 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { | 1506 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { |
1451 | if ((wil->sta[i].status != wil_sta_unused) && | 1507 | if (wil->sta[i].mid == mid && |
1508 | wil->sta[i].status != wil_sta_unused && | ||
1452 | ether_addr_equal(wil->sta[i].addr, mac)) { | 1509 | ether_addr_equal(wil->sta[i].addr, mac)) { |
1453 | rc = i; | 1510 | rc = i; |
1454 | break; | 1511 | break; |
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index 7ba4e0af8f57..05e9408e7ea3 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. |
3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -15,13 +16,41 @@ | |||
15 | */ | 16 | */ |
16 | 17 | ||
17 | #include <linux/etherdevice.h> | 18 | #include <linux/etherdevice.h> |
19 | #include <linux/rtnetlink.h> | ||
18 | #include "wil6210.h" | 20 | #include "wil6210.h" |
19 | #include "txrx.h" | 21 | #include "txrx.h" |
20 | 22 | ||
23 | bool wil_has_other_active_ifaces(struct wil6210_priv *wil, | ||
24 | struct net_device *ndev, bool up, bool ok) | ||
25 | { | ||
26 | int i; | ||
27 | struct wil6210_vif *vif; | ||
28 | struct net_device *ndev_i; | ||
29 | |||
30 | for (i = 0; i < wil->max_vifs; i++) { | ||
31 | vif = wil->vifs[i]; | ||
32 | if (vif) { | ||
33 | ndev_i = vif_to_ndev(vif); | ||
34 | if (ndev_i != ndev) | ||
35 | if ((up && (ndev_i->flags & IFF_UP)) || | ||
36 | (ok && netif_carrier_ok(ndev_i))) | ||
37 | return true; | ||
38 | } | ||
39 | } | ||
40 | |||
41 | return false; | ||
42 | } | ||
43 | |||
44 | bool wil_has_active_ifaces(struct wil6210_priv *wil, bool up, bool ok) | ||
45 | { | ||
46 | /* use NULL ndev argument to check all interfaces */ | ||
47 | return wil_has_other_active_ifaces(wil, NULL, up, ok); | ||
48 | } | ||
49 | |||
21 | static int wil_open(struct net_device *ndev) | 50 | static int wil_open(struct net_device *ndev) |
22 | { | 51 | { |
23 | struct wil6210_priv *wil = ndev_to_wil(ndev); | 52 | struct wil6210_priv *wil = ndev_to_wil(ndev); |
24 | int rc; | 53 | int rc = 0; |
25 | 54 | ||
26 | wil_dbg_misc(wil, "open\n"); | 55 | wil_dbg_misc(wil, "open\n"); |
27 | 56 | ||
@@ -31,13 +60,16 @@ static int wil_open(struct net_device *ndev) | |||
31 | return -EINVAL; | 60 | return -EINVAL; |
32 | } | 61 | } |
33 | 62 | ||
34 | rc = wil_pm_runtime_get(wil); | 63 | if (!wil_has_other_active_ifaces(wil, ndev, true, false)) { |
35 | if (rc < 0) | 64 | wil_dbg_misc(wil, "open, first iface\n"); |
36 | return rc; | 65 | rc = wil_pm_runtime_get(wil); |
66 | if (rc < 0) | ||
67 | return rc; | ||
37 | 68 | ||
38 | rc = wil_up(wil); | 69 | rc = wil_up(wil); |
39 | if (rc) | 70 | if (rc) |
40 | wil_pm_runtime_put(wil); | 71 | wil_pm_runtime_put(wil); |
72 | } | ||
41 | 73 | ||
42 | return rc; | 74 | return rc; |
43 | } | 75 | } |
@@ -45,13 +77,16 @@ static int wil_open(struct net_device *ndev) | |||
45 | static int wil_stop(struct net_device *ndev) | 77 | static int wil_stop(struct net_device *ndev) |
46 | { | 78 | { |
47 | struct wil6210_priv *wil = ndev_to_wil(ndev); | 79 | struct wil6210_priv *wil = ndev_to_wil(ndev); |
48 | int rc; | 80 | int rc = 0; |
49 | 81 | ||
50 | wil_dbg_misc(wil, "stop\n"); | 82 | wil_dbg_misc(wil, "stop\n"); |
51 | 83 | ||
52 | rc = wil_down(wil); | 84 | if (!wil_has_other_active_ifaces(wil, ndev, true, false)) { |
53 | if (!rc) | 85 | wil_dbg_misc(wil, "stop, last iface\n"); |
54 | wil_pm_runtime_put(wil); | 86 | rc = wil_down(wil); |
87 | if (!rc) | ||
88 | wil_pm_runtime_put(wil); | ||
89 | } | ||
55 | 90 | ||
56 | return rc; | 91 | return rc; |
57 | } | 92 | } |
@@ -96,11 +131,19 @@ static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget) | |||
96 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { | 131 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { |
97 | struct vring *vring = &wil->vring_tx[i]; | 132 | struct vring *vring = &wil->vring_tx[i]; |
98 | struct vring_tx_data *txdata = &wil->vring_tx_data[i]; | 133 | struct vring_tx_data *txdata = &wil->vring_tx_data[i]; |
134 | struct wil6210_vif *vif; | ||
99 | 135 | ||
100 | if (!vring->va || !txdata->enabled) | 136 | if (!vring->va || !txdata->enabled || |
137 | txdata->mid >= wil->max_vifs) | ||
101 | continue; | 138 | continue; |
102 | 139 | ||
103 | tx_done += wil_tx_complete(wil, i); | 140 | vif = wil->vifs[txdata->mid]; |
141 | if (unlikely(!vif)) { | ||
142 | wil_dbg_txrx(wil, "Invalid MID %d\n", txdata->mid); | ||
143 | continue; | ||
144 | } | ||
145 | |||
146 | tx_done += wil_tx_complete(vif, i); | ||
104 | } | 147 | } |
105 | 148 | ||
106 | if (tx_done < budget) { | 149 | if (tx_done < budget) { |
@@ -121,44 +164,137 @@ static void wil_dev_setup(struct net_device *dev) | |||
121 | dev->tx_queue_len = WIL_TX_Q_LEN_DEFAULT; | 164 | dev->tx_queue_len = WIL_TX_Q_LEN_DEFAULT; |
122 | } | 165 | } |
123 | 166 | ||
124 | void *wil_if_alloc(struct device *dev) | 167 | static void wil_vif_deinit(struct wil6210_vif *vif) |
125 | { | 168 | { |
126 | struct net_device *ndev; | 169 | del_timer_sync(&vif->scan_timer); |
127 | struct wireless_dev *wdev; | 170 | del_timer_sync(&vif->p2p.discovery_timer); |
128 | struct wil6210_priv *wil; | 171 | cancel_work_sync(&vif->disconnect_worker); |
129 | struct ieee80211_channel *ch; | 172 | cancel_work_sync(&vif->p2p.discovery_expired_work); |
130 | int rc = 0; | 173 | cancel_work_sync(&vif->p2p.delayed_listen_work); |
174 | wil_probe_client_flush(vif); | ||
175 | cancel_work_sync(&vif->probe_client_worker); | ||
176 | } | ||
131 | 177 | ||
132 | wdev = wil_cfg80211_init(dev); | 178 | void wil_vif_free(struct wil6210_vif *vif) |
133 | if (IS_ERR(wdev)) { | 179 | { |
134 | dev_err(dev, "wil_cfg80211_init failed\n"); | 180 | struct net_device *ndev = vif_to_ndev(vif); |
135 | return wdev; | ||
136 | } | ||
137 | 181 | ||
138 | wil = wdev_to_wil(wdev); | 182 | wil_vif_deinit(vif); |
139 | wil->wdev = wdev; | 183 | free_netdev(ndev); |
140 | wil->radio_wdev = wdev; | 184 | } |
141 | 185 | ||
142 | wil_dbg_misc(wil, "if_alloc\n"); | 186 | static void wil_ndev_destructor(struct net_device *ndev) |
187 | { | ||
188 | struct wil6210_vif *vif = ndev_to_vif(ndev); | ||
143 | 189 | ||
144 | rc = wil_priv_init(wil); | 190 | wil_vif_deinit(vif); |
145 | if (rc) { | 191 | } |
146 | dev_err(dev, "wil_priv_init failed\n"); | 192 | |
147 | goto out_wdev; | 193 | static void wil_connect_timer_fn(struct timer_list *t) |
194 | { | ||
195 | struct wil6210_vif *vif = from_timer(vif, t, connect_timer); | ||
196 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
197 | bool q; | ||
198 | |||
199 | wil_err(wil, "Connect timeout detected, disconnect station\n"); | ||
200 | |||
201 | /* reschedule to thread context - disconnect won't | ||
202 | * run from atomic context. | ||
203 | * queue on wmi_wq to prevent race with connect event. | ||
204 | */ | ||
205 | q = queue_work(wil->wmi_wq, &vif->disconnect_worker); | ||
206 | wil_dbg_wmi(wil, "queue_work of disconnect_worker -> %d\n", q); | ||
207 | } | ||
208 | |||
209 | static void wil_scan_timer_fn(struct timer_list *t) | ||
210 | { | ||
211 | struct wil6210_vif *vif = from_timer(vif, t, scan_timer); | ||
212 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
213 | |||
214 | clear_bit(wil_status_fwready, wil->status); | ||
215 | wil_err(wil, "Scan timeout detected, start fw error recovery\n"); | ||
216 | wil_fw_error_recovery(wil); | ||
217 | } | ||
218 | |||
219 | static void wil_p2p_discovery_timer_fn(struct timer_list *t) | ||
220 | { | ||
221 | struct wil6210_vif *vif = from_timer(vif, t, p2p.discovery_timer); | ||
222 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
223 | |||
224 | wil_dbg_misc(wil, "p2p_discovery_timer_fn\n"); | ||
225 | |||
226 | schedule_work(&vif->p2p.discovery_expired_work); | ||
227 | } | ||
228 | |||
229 | static void wil_vif_init(struct wil6210_vif *vif) | ||
230 | { | ||
231 | vif->bcast_vring = -1; | ||
232 | |||
233 | mutex_init(&vif->probe_client_mutex); | ||
234 | |||
235 | timer_setup(&vif->connect_timer, wil_connect_timer_fn, 0); | ||
236 | timer_setup(&vif->scan_timer, wil_scan_timer_fn, 0); | ||
237 | timer_setup(&vif->p2p.discovery_timer, wil_p2p_discovery_timer_fn, 0); | ||
238 | |||
239 | INIT_WORK(&vif->probe_client_worker, wil_probe_client_worker); | ||
240 | INIT_WORK(&vif->disconnect_worker, wil_disconnect_worker); | ||
241 | INIT_WORK(&vif->p2p.delayed_listen_work, wil_p2p_delayed_listen_work); | ||
242 | |||
243 | INIT_LIST_HEAD(&vif->probe_client_pending); | ||
244 | |||
245 | vif->net_queue_stopped = 1; | ||
246 | } | ||
247 | |||
248 | static u8 wil_vif_find_free_mid(struct wil6210_priv *wil) | ||
249 | { | ||
250 | u8 i; | ||
251 | |||
252 | for (i = 0; i < wil->max_vifs; i++) { | ||
253 | if (!wil->vifs[i]) | ||
254 | return i; | ||
148 | } | 255 | } |
149 | 256 | ||
150 | wdev->iftype = NL80211_IFTYPE_STATION; /* TODO */ | 257 | return U8_MAX; |
151 | /* default monitor channel */ | 258 | } |
152 | ch = wdev->wiphy->bands[NL80211_BAND_60GHZ]->channels; | 259 | |
153 | cfg80211_chandef_create(&wil->monitor_chandef, ch, NL80211_CHAN_NO_HT); | 260 | struct wil6210_vif * |
261 | wil_vif_alloc(struct wil6210_priv *wil, const char *name, | ||
262 | unsigned char name_assign_type, enum nl80211_iftype iftype) | ||
263 | { | ||
264 | struct net_device *ndev; | ||
265 | struct wireless_dev *wdev; | ||
266 | struct wil6210_vif *vif; | ||
267 | u8 mid; | ||
268 | |||
269 | mid = wil_vif_find_free_mid(wil); | ||
270 | if (mid == U8_MAX) { | ||
271 | wil_err(wil, "no available virtual interface\n"); | ||
272 | return ERR_PTR(-EINVAL); | ||
273 | } | ||
154 | 274 | ||
155 | ndev = alloc_netdev(0, "wlan%d", NET_NAME_UNKNOWN, wil_dev_setup); | 275 | ndev = alloc_netdev(sizeof(*vif), name, name_assign_type, |
276 | wil_dev_setup); | ||
156 | if (!ndev) { | 277 | if (!ndev) { |
157 | dev_err(dev, "alloc_netdev_mqs failed\n"); | 278 | dev_err(wil_to_dev(wil), "alloc_netdev failed\n"); |
158 | rc = -ENOMEM; | 279 | return ERR_PTR(-ENOMEM); |
159 | goto out_priv; | 280 | } |
281 | if (mid == 0) { | ||
282 | wil->main_ndev = ndev; | ||
283 | } else { | ||
284 | ndev->priv_destructor = wil_ndev_destructor; | ||
285 | ndev->needs_free_netdev = true; | ||
160 | } | 286 | } |
161 | 287 | ||
288 | vif = ndev_to_vif(ndev); | ||
289 | vif->ndev = ndev; | ||
290 | vif->wil = wil; | ||
291 | vif->mid = mid; | ||
292 | wil_vif_init(vif); | ||
293 | |||
294 | wdev = &vif->wdev; | ||
295 | wdev->wiphy = wil->wiphy; | ||
296 | wdev->iftype = iftype; | ||
297 | |||
162 | ndev->netdev_ops = &wil_netdev_ops; | 298 | ndev->netdev_ops = &wil_netdev_ops; |
163 | wil_set_ethtoolops(ndev); | 299 | wil_set_ethtoolops(ndev); |
164 | ndev->ieee80211_ptr = wdev; | 300 | ndev->ieee80211_ptr = wdev; |
@@ -170,21 +306,53 @@ void *wil_if_alloc(struct device *dev) | |||
170 | ndev->features |= ndev->hw_features; | 306 | ndev->features |= ndev->hw_features; |
171 | SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); | 307 | SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); |
172 | wdev->netdev = ndev; | 308 | wdev->netdev = ndev; |
309 | return vif; | ||
310 | } | ||
311 | |||
312 | void *wil_if_alloc(struct device *dev) | ||
313 | { | ||
314 | struct wil6210_priv *wil; | ||
315 | struct wil6210_vif *vif; | ||
316 | int rc = 0; | ||
317 | |||
318 | wil = wil_cfg80211_init(dev); | ||
319 | if (IS_ERR(wil)) { | ||
320 | dev_err(dev, "wil_cfg80211_init failed\n"); | ||
321 | return wil; | ||
322 | } | ||
323 | |||
324 | rc = wil_priv_init(wil); | ||
325 | if (rc) { | ||
326 | dev_err(dev, "wil_priv_init failed\n"); | ||
327 | goto out_cfg; | ||
328 | } | ||
329 | |||
330 | wil_dbg_misc(wil, "if_alloc\n"); | ||
331 | |||
332 | vif = wil_vif_alloc(wil, "wlan%d", NET_NAME_UNKNOWN, | ||
333 | NL80211_IFTYPE_STATION); | ||
334 | if (IS_ERR(vif)) { | ||
335 | dev_err(dev, "wil_vif_alloc failed\n"); | ||
336 | rc = -ENOMEM; | ||
337 | goto out_priv; | ||
338 | } | ||
339 | |||
340 | wil->radio_wdev = vif_to_wdev(vif); | ||
173 | 341 | ||
174 | return wil; | 342 | return wil; |
175 | 343 | ||
176 | out_priv: | 344 | out_priv: |
177 | wil_priv_deinit(wil); | 345 | wil_priv_deinit(wil); |
178 | 346 | ||
179 | out_wdev: | 347 | out_cfg: |
180 | wil_wdev_free(wil); | 348 | wil_cfg80211_deinit(wil); |
181 | 349 | ||
182 | return ERR_PTR(rc); | 350 | return ERR_PTR(rc); |
183 | } | 351 | } |
184 | 352 | ||
185 | void wil_if_free(struct wil6210_priv *wil) | 353 | void wil_if_free(struct wil6210_priv *wil) |
186 | { | 354 | { |
187 | struct net_device *ndev = wil_to_ndev(wil); | 355 | struct net_device *ndev = wil->main_ndev; |
188 | 356 | ||
189 | wil_dbg_misc(wil, "if_free\n"); | 357 | wil_dbg_misc(wil, "if_free\n"); |
190 | 358 | ||
@@ -193,17 +361,50 @@ void wil_if_free(struct wil6210_priv *wil) | |||
193 | 361 | ||
194 | wil_priv_deinit(wil); | 362 | wil_priv_deinit(wil); |
195 | 363 | ||
196 | wil_to_ndev(wil) = NULL; | 364 | wil->main_ndev = NULL; |
365 | wil_ndev_destructor(ndev); | ||
197 | free_netdev(ndev); | 366 | free_netdev(ndev); |
198 | 367 | ||
199 | wil_wdev_free(wil); | 368 | wil_cfg80211_deinit(wil); |
369 | } | ||
370 | |||
371 | int wil_vif_add(struct wil6210_priv *wil, struct wil6210_vif *vif) | ||
372 | { | ||
373 | struct net_device *ndev = vif_to_ndev(vif); | ||
374 | struct wireless_dev *wdev = vif_to_wdev(vif); | ||
375 | bool any_active = wil_has_active_ifaces(wil, true, false); | ||
376 | int rc; | ||
377 | |||
378 | ASSERT_RTNL(); | ||
379 | |||
380 | if (wil->vifs[vif->mid]) { | ||
381 | dev_err(&ndev->dev, "VIF with mid %d already in use\n", | ||
382 | vif->mid); | ||
383 | return -EEXIST; | ||
384 | } | ||
385 | if (any_active && vif->mid != 0) { | ||
386 | rc = wmi_port_allocate(wil, vif->mid, ndev->dev_addr, | ||
387 | wdev->iftype); | ||
388 | if (rc) | ||
389 | return rc; | ||
390 | } | ||
391 | rc = register_netdevice(ndev); | ||
392 | if (rc < 0) { | ||
393 | dev_err(&ndev->dev, "Failed to register netdev: %d\n", rc); | ||
394 | if (any_active && vif->mid != 0) | ||
395 | wmi_port_delete(wil, vif->mid); | ||
396 | return rc; | ||
397 | } | ||
398 | |||
399 | wil->vifs[vif->mid] = vif; | ||
400 | return 0; | ||
200 | } | 401 | } |
201 | 402 | ||
202 | int wil_if_add(struct wil6210_priv *wil) | 403 | int wil_if_add(struct wil6210_priv *wil) |
203 | { | 404 | { |
204 | struct wireless_dev *wdev = wil_to_wdev(wil); | 405 | struct wiphy *wiphy = wil->wiphy; |
205 | struct wiphy *wiphy = wdev->wiphy; | 406 | struct net_device *ndev = wil->main_ndev; |
206 | struct net_device *ndev = wil_to_ndev(wil); | 407 | struct wil6210_vif *vif = ndev_to_vif(ndev); |
207 | int rc; | 408 | int rc; |
208 | 409 | ||
209 | wil_dbg_misc(wil, "entered"); | 410 | wil_dbg_misc(wil, "entered"); |
@@ -216,33 +417,94 @@ int wil_if_add(struct wil6210_priv *wil) | |||
216 | return rc; | 417 | return rc; |
217 | } | 418 | } |
218 | 419 | ||
219 | netif_napi_add(ndev, &wil->napi_rx, wil6210_netdev_poll_rx, | 420 | init_dummy_netdev(&wil->napi_ndev); |
421 | netif_napi_add(&wil->napi_ndev, &wil->napi_rx, wil6210_netdev_poll_rx, | ||
220 | WIL6210_NAPI_BUDGET); | 422 | WIL6210_NAPI_BUDGET); |
221 | netif_tx_napi_add(ndev, &wil->napi_tx, wil6210_netdev_poll_tx, | 423 | netif_tx_napi_add(&wil->napi_ndev, |
424 | &wil->napi_tx, wil6210_netdev_poll_tx, | ||
222 | WIL6210_NAPI_BUDGET); | 425 | WIL6210_NAPI_BUDGET); |
223 | 426 | ||
224 | wil_update_net_queues_bh(wil, NULL, true); | 427 | wil_update_net_queues_bh(wil, vif, NULL, true); |
225 | 428 | ||
226 | rc = register_netdev(ndev); | 429 | rtnl_lock(); |
227 | if (rc < 0) { | 430 | rc = wil_vif_add(wil, vif); |
228 | dev_err(&ndev->dev, "Failed to register netdev: %d\n", rc); | 431 | rtnl_unlock(); |
432 | if (rc < 0) | ||
229 | goto out_wiphy; | 433 | goto out_wiphy; |
230 | } | ||
231 | 434 | ||
232 | return 0; | 435 | return 0; |
233 | 436 | ||
234 | out_wiphy: | 437 | out_wiphy: |
235 | wiphy_unregister(wdev->wiphy); | 438 | wiphy_unregister(wiphy); |
236 | return rc; | 439 | return rc; |
237 | } | 440 | } |
238 | 441 | ||
442 | void wil_vif_remove(struct wil6210_priv *wil, u8 mid) | ||
443 | { | ||
444 | struct wil6210_vif *vif; | ||
445 | struct net_device *ndev; | ||
446 | bool any_active = wil_has_active_ifaces(wil, true, false); | ||
447 | |||
448 | ASSERT_RTNL(); | ||
449 | if (mid >= wil->max_vifs) { | ||
450 | wil_err(wil, "invalid MID: %d\n", mid); | ||
451 | return; | ||
452 | } | ||
453 | |||
454 | vif = wil->vifs[mid]; | ||
455 | if (!vif) { | ||
456 | wil_err(wil, "MID %d not registered\n", mid); | ||
457 | return; | ||
458 | } | ||
459 | |||
460 | ndev = vif_to_ndev(vif); | ||
461 | /* during unregister_netdevice cfg80211_leave may perform operations | ||
462 | * such as stop AP, disconnect, so we only clear the VIF afterwards | ||
463 | */ | ||
464 | unregister_netdevice(ndev); | ||
465 | |||
466 | mutex_lock(&wil->mutex); | ||
467 | wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING, false); | ||
468 | mutex_unlock(&wil->mutex); | ||
469 | |||
470 | if (any_active && vif->mid != 0) | ||
471 | wmi_port_delete(wil, vif->mid); | ||
472 | |||
473 | /* make sure no one is accessing the VIF before removing */ | ||
474 | mutex_lock(&wil->vif_mutex); | ||
475 | wil->vifs[mid] = NULL; | ||
476 | /* ensure NAPI code will see the NULL VIF */ | ||
477 | wmb(); | ||
478 | if (test_bit(wil_status_napi_en, wil->status)) { | ||
479 | napi_synchronize(&wil->napi_rx); | ||
480 | napi_synchronize(&wil->napi_tx); | ||
481 | } | ||
482 | mutex_unlock(&wil->vif_mutex); | ||
483 | |||
484 | flush_work(&wil->wmi_event_worker); | ||
485 | del_timer_sync(&vif->connect_timer); | ||
486 | cancel_work_sync(&vif->disconnect_worker); | ||
487 | wil_probe_client_flush(vif); | ||
488 | cancel_work_sync(&vif->probe_client_worker); | ||
489 | /* for VIFs, ndev will be freed by destructor after RTNL is unlocked. | ||
490 | * the main interface will be freed in wil_if_free, we need to keep it | ||
491 | * a bit longer so logging macros will work. | ||
492 | */ | ||
493 | } | ||
494 | |||
239 | void wil_if_remove(struct wil6210_priv *wil) | 495 | void wil_if_remove(struct wil6210_priv *wil) |
240 | { | 496 | { |
241 | struct net_device *ndev = wil_to_ndev(wil); | 497 | struct net_device *ndev = wil->main_ndev; |
242 | struct wireless_dev *wdev = wil_to_wdev(wil); | 498 | struct wireless_dev *wdev = ndev->ieee80211_ptr; |
243 | 499 | ||
244 | wil_dbg_misc(wil, "if_remove\n"); | 500 | wil_dbg_misc(wil, "if_remove\n"); |
245 | 501 | ||
246 | unregister_netdev(ndev); | 502 | rtnl_lock(); |
503 | wil_vif_remove(wil, 0); | ||
504 | rtnl_unlock(); | ||
505 | |||
506 | netif_napi_del(&wil->napi_tx); | ||
507 | netif_napi_del(&wil->napi_rx); | ||
508 | |||
247 | wiphy_unregister(wdev->wiphy); | 509 | wiphy_unregister(wdev->wiphy); |
248 | } | 510 | } |
diff --git a/drivers/net/wireless/ath/wil6210/p2p.c b/drivers/net/wireless/ath/wil6210/p2p.c index 7dbee2c3e482..db087ea58ddf 100644 --- a/drivers/net/wireless/ath/wil6210/p2p.c +++ b/drivers/net/wireless/ath/wil6210/p2p.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. |
3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -22,27 +23,28 @@ | |||
22 | #define P2P_SEARCH_DURATION_MS 500 | 23 | #define P2P_SEARCH_DURATION_MS 500 |
23 | #define P2P_DEFAULT_BI 100 | 24 | #define P2P_DEFAULT_BI 100 |
24 | 25 | ||
25 | static int wil_p2p_start_listen(struct wil6210_priv *wil) | 26 | static int wil_p2p_start_listen(struct wil6210_vif *vif) |
26 | { | 27 | { |
27 | struct wil_p2p_info *p2p = &wil->p2p; | 28 | struct wil6210_priv *wil = vif_to_wil(vif); |
29 | struct wil_p2p_info *p2p = &vif->p2p; | ||
28 | u8 channel = p2p->listen_chan.hw_value; | 30 | u8 channel = p2p->listen_chan.hw_value; |
29 | int rc; | 31 | int rc; |
30 | 32 | ||
31 | lockdep_assert_held(&wil->mutex); | 33 | lockdep_assert_held(&wil->mutex); |
32 | 34 | ||
33 | rc = wmi_p2p_cfg(wil, channel, P2P_DEFAULT_BI); | 35 | rc = wmi_p2p_cfg(vif, channel, P2P_DEFAULT_BI); |
34 | if (rc) { | 36 | if (rc) { |
35 | wil_err(wil, "wmi_p2p_cfg failed\n"); | 37 | wil_err(wil, "wmi_p2p_cfg failed\n"); |
36 | goto out; | 38 | goto out; |
37 | } | 39 | } |
38 | 40 | ||
39 | rc = wmi_set_ssid(wil, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID); | 41 | rc = wmi_set_ssid(vif, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID); |
40 | if (rc) { | 42 | if (rc) { |
41 | wil_err(wil, "wmi_set_ssid failed\n"); | 43 | wil_err(wil, "wmi_set_ssid failed\n"); |
42 | goto out_stop; | 44 | goto out_stop; |
43 | } | 45 | } |
44 | 46 | ||
45 | rc = wmi_start_listen(wil); | 47 | rc = wmi_start_listen(vif); |
46 | if (rc) { | 48 | if (rc) { |
47 | wil_err(wil, "wmi_start_listen failed\n"); | 49 | wil_err(wil, "wmi_start_listen failed\n"); |
48 | goto out_stop; | 50 | goto out_stop; |
@@ -53,7 +55,7 @@ static int wil_p2p_start_listen(struct wil6210_priv *wil) | |||
53 | jiffies + msecs_to_jiffies(p2p->listen_duration)); | 55 | jiffies + msecs_to_jiffies(p2p->listen_duration)); |
54 | out_stop: | 56 | out_stop: |
55 | if (rc) | 57 | if (rc) |
56 | wmi_stop_discovery(wil); | 58 | wmi_stop_discovery(vif); |
57 | 59 | ||
58 | out: | 60 | out: |
59 | return rc; | 61 | return rc; |
@@ -65,20 +67,12 @@ bool wil_p2p_is_social_scan(struct cfg80211_scan_request *request) | |||
65 | (request->channels[0]->hw_value == P2P_DMG_SOCIAL_CHANNEL); | 67 | (request->channels[0]->hw_value == P2P_DMG_SOCIAL_CHANNEL); |
66 | } | 68 | } |
67 | 69 | ||
68 | void wil_p2p_discovery_timer_fn(struct timer_list *t) | 70 | int wil_p2p_search(struct wil6210_vif *vif, |
69 | { | ||
70 | struct wil6210_priv *wil = from_timer(wil, t, p2p.discovery_timer); | ||
71 | |||
72 | wil_dbg_misc(wil, "p2p_discovery_timer_fn\n"); | ||
73 | |||
74 | schedule_work(&wil->p2p.discovery_expired_work); | ||
75 | } | ||
76 | |||
77 | int wil_p2p_search(struct wil6210_priv *wil, | ||
78 | struct cfg80211_scan_request *request) | 71 | struct cfg80211_scan_request *request) |
79 | { | 72 | { |
73 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
80 | int rc; | 74 | int rc; |
81 | struct wil_p2p_info *p2p = &wil->p2p; | 75 | struct wil_p2p_info *p2p = &vif->p2p; |
82 | 76 | ||
83 | wil_dbg_misc(wil, "p2p_search: channel %d\n", P2P_DMG_SOCIAL_CHANNEL); | 77 | wil_dbg_misc(wil, "p2p_search: channel %d\n", P2P_DMG_SOCIAL_CHANNEL); |
84 | 78 | ||
@@ -90,20 +84,20 @@ int wil_p2p_search(struct wil6210_priv *wil, | |||
90 | goto out; | 84 | goto out; |
91 | } | 85 | } |
92 | 86 | ||
93 | rc = wmi_p2p_cfg(wil, P2P_DMG_SOCIAL_CHANNEL, P2P_DEFAULT_BI); | 87 | rc = wmi_p2p_cfg(vif, P2P_DMG_SOCIAL_CHANNEL, P2P_DEFAULT_BI); |
94 | if (rc) { | 88 | if (rc) { |
95 | wil_err(wil, "wmi_p2p_cfg failed\n"); | 89 | wil_err(wil, "wmi_p2p_cfg failed\n"); |
96 | goto out; | 90 | goto out; |
97 | } | 91 | } |
98 | 92 | ||
99 | rc = wmi_set_ssid(wil, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID); | 93 | rc = wmi_set_ssid(vif, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID); |
100 | if (rc) { | 94 | if (rc) { |
101 | wil_err(wil, "wmi_set_ssid failed\n"); | 95 | wil_err(wil, "wmi_set_ssid failed\n"); |
102 | goto out_stop; | 96 | goto out_stop; |
103 | } | 97 | } |
104 | 98 | ||
105 | /* Set application IE to probe request and probe response */ | 99 | /* Set application IE to probe request and probe response */ |
106 | rc = wmi_set_ie(wil, WMI_FRAME_PROBE_REQ, | 100 | rc = wmi_set_ie(vif, WMI_FRAME_PROBE_REQ, |
107 | request->ie_len, request->ie); | 101 | request->ie_len, request->ie); |
108 | if (rc) { | 102 | if (rc) { |
109 | wil_err(wil, "wmi_set_ie(WMI_FRAME_PROBE_REQ) failed\n"); | 103 | wil_err(wil, "wmi_set_ie(WMI_FRAME_PROBE_REQ) failed\n"); |
@@ -113,14 +107,14 @@ int wil_p2p_search(struct wil6210_priv *wil, | |||
113 | /* supplicant doesn't provide Probe Response IEs. As a workaround - | 107 | /* supplicant doesn't provide Probe Response IEs. As a workaround - |
114 | * re-use Probe Request IEs | 108 | * re-use Probe Request IEs |
115 | */ | 109 | */ |
116 | rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, | 110 | rc = wmi_set_ie(vif, WMI_FRAME_PROBE_RESP, |
117 | request->ie_len, request->ie); | 111 | request->ie_len, request->ie); |
118 | if (rc) { | 112 | if (rc) { |
119 | wil_err(wil, "wmi_set_ie(WMI_FRAME_PROBE_RESP) failed\n"); | 113 | wil_err(wil, "wmi_set_ie(WMI_FRAME_PROBE_RESP) failed\n"); |
120 | goto out_stop; | 114 | goto out_stop; |
121 | } | 115 | } |
122 | 116 | ||
123 | rc = wmi_start_search(wil); | 117 | rc = wmi_start_search(vif); |
124 | if (rc) { | 118 | if (rc) { |
125 | wil_err(wil, "wmi_start_search failed\n"); | 119 | wil_err(wil, "wmi_start_search failed\n"); |
126 | goto out_stop; | 120 | goto out_stop; |
@@ -133,7 +127,7 @@ int wil_p2p_search(struct wil6210_priv *wil, | |||
133 | 127 | ||
134 | out_stop: | 128 | out_stop: |
135 | if (rc) | 129 | if (rc) |
136 | wmi_stop_discovery(wil); | 130 | wmi_stop_discovery(vif); |
137 | 131 | ||
138 | out: | 132 | out: |
139 | return rc; | 133 | return rc; |
@@ -143,7 +137,8 @@ int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev, | |||
143 | unsigned int duration, struct ieee80211_channel *chan, | 137 | unsigned int duration, struct ieee80211_channel *chan, |
144 | u64 *cookie) | 138 | u64 *cookie) |
145 | { | 139 | { |
146 | struct wil_p2p_info *p2p = &wil->p2p; | 140 | struct wil6210_vif *vif = wdev_to_vif(wil, wdev); |
141 | struct wil_p2p_info *p2p = &vif->p2p; | ||
147 | int rc; | 142 | int rc; |
148 | 143 | ||
149 | if (!chan) | 144 | if (!chan) |
@@ -163,23 +158,24 @@ int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev, | |||
163 | *cookie = ++p2p->cookie; | 158 | *cookie = ++p2p->cookie; |
164 | p2p->listen_duration = duration; | 159 | p2p->listen_duration = duration; |
165 | 160 | ||
166 | mutex_lock(&wil->p2p_wdev_mutex); | 161 | mutex_lock(&wil->vif_mutex); |
167 | if (wil->scan_request) { | 162 | if (vif->scan_request) { |
168 | wil_dbg_misc(wil, "Delaying p2p listen until scan done\n"); | 163 | wil_dbg_misc(wil, "Delaying p2p listen until scan done\n"); |
169 | p2p->pending_listen_wdev = wdev; | 164 | p2p->pending_listen_wdev = wdev; |
170 | p2p->discovery_started = 1; | 165 | p2p->discovery_started = 1; |
171 | rc = 0; | 166 | rc = 0; |
172 | mutex_unlock(&wil->p2p_wdev_mutex); | 167 | mutex_unlock(&wil->vif_mutex); |
173 | goto out; | 168 | goto out; |
174 | } | 169 | } |
175 | mutex_unlock(&wil->p2p_wdev_mutex); | 170 | mutex_unlock(&wil->vif_mutex); |
176 | 171 | ||
177 | rc = wil_p2p_start_listen(wil); | 172 | rc = wil_p2p_start_listen(vif); |
178 | if (rc) | 173 | if (rc) |
179 | goto out; | 174 | goto out; |
180 | 175 | ||
181 | p2p->discovery_started = 1; | 176 | p2p->discovery_started = 1; |
182 | wil->radio_wdev = wdev; | 177 | if (vif->mid == 0) |
178 | wil->radio_wdev = wdev; | ||
183 | 179 | ||
184 | cfg80211_ready_on_channel(wdev, *cookie, chan, duration, | 180 | cfg80211_ready_on_channel(wdev, *cookie, chan, duration, |
185 | GFP_KERNEL); | 181 | GFP_KERNEL); |
@@ -189,9 +185,9 @@ out: | |||
189 | return rc; | 185 | return rc; |
190 | } | 186 | } |
191 | 187 | ||
192 | u8 wil_p2p_stop_discovery(struct wil6210_priv *wil) | 188 | u8 wil_p2p_stop_discovery(struct wil6210_vif *vif) |
193 | { | 189 | { |
194 | struct wil_p2p_info *p2p = &wil->p2p; | 190 | struct wil_p2p_info *p2p = &vif->p2p; |
195 | u8 started = p2p->discovery_started; | 191 | u8 started = p2p->discovery_started; |
196 | 192 | ||
197 | if (p2p->discovery_started) { | 193 | if (p2p->discovery_started) { |
@@ -200,7 +196,7 @@ u8 wil_p2p_stop_discovery(struct wil6210_priv *wil) | |||
200 | p2p->pending_listen_wdev = NULL; | 196 | p2p->pending_listen_wdev = NULL; |
201 | } else { | 197 | } else { |
202 | del_timer_sync(&p2p->discovery_timer); | 198 | del_timer_sync(&p2p->discovery_timer); |
203 | wmi_stop_discovery(wil); | 199 | wmi_stop_discovery(vif); |
204 | } | 200 | } |
205 | p2p->discovery_started = 0; | 201 | p2p->discovery_started = 0; |
206 | } | 202 | } |
@@ -208,9 +204,10 @@ u8 wil_p2p_stop_discovery(struct wil6210_priv *wil) | |||
208 | return started; | 204 | return started; |
209 | } | 205 | } |
210 | 206 | ||
211 | int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie) | 207 | int wil_p2p_cancel_listen(struct wil6210_vif *vif, u64 cookie) |
212 | { | 208 | { |
213 | struct wil_p2p_info *p2p = &wil->p2p; | 209 | struct wil6210_priv *wil = vif_to_wil(vif); |
210 | struct wil_p2p_info *p2p = &vif->p2p; | ||
214 | u8 started; | 211 | u8 started; |
215 | 212 | ||
216 | mutex_lock(&wil->mutex); | 213 | mutex_lock(&wil->mutex); |
@@ -222,7 +219,7 @@ int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie) | |||
222 | return -ENOENT; | 219 | return -ENOENT; |
223 | } | 220 | } |
224 | 221 | ||
225 | started = wil_p2p_stop_discovery(wil); | 222 | started = wil_p2p_stop_discovery(vif); |
226 | 223 | ||
227 | mutex_unlock(&wil->mutex); | 224 | mutex_unlock(&wil->mutex); |
228 | 225 | ||
@@ -231,13 +228,14 @@ int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie) | |||
231 | return -ENOENT; | 228 | return -ENOENT; |
232 | } | 229 | } |
233 | 230 | ||
234 | mutex_lock(&wil->p2p_wdev_mutex); | 231 | mutex_lock(&wil->vif_mutex); |
235 | cfg80211_remain_on_channel_expired(wil->radio_wdev, | 232 | cfg80211_remain_on_channel_expired(vif_to_radio_wdev(wil, vif), |
236 | p2p->cookie, | 233 | p2p->cookie, |
237 | &p2p->listen_chan, | 234 | &p2p->listen_chan, |
238 | GFP_KERNEL); | 235 | GFP_KERNEL); |
239 | wil->radio_wdev = wil->wdev; | 236 | if (vif->mid == 0) |
240 | mutex_unlock(&wil->p2p_wdev_mutex); | 237 | wil->radio_wdev = wil->main_ndev->ieee80211_ptr; |
238 | mutex_unlock(&wil->vif_mutex); | ||
241 | return 0; | 239 | return 0; |
242 | } | 240 | } |
243 | 241 | ||
@@ -245,40 +243,43 @@ void wil_p2p_listen_expired(struct work_struct *work) | |||
245 | { | 243 | { |
246 | struct wil_p2p_info *p2p = container_of(work, | 244 | struct wil_p2p_info *p2p = container_of(work, |
247 | struct wil_p2p_info, discovery_expired_work); | 245 | struct wil_p2p_info, discovery_expired_work); |
248 | struct wil6210_priv *wil = container_of(p2p, | 246 | struct wil6210_vif *vif = container_of(p2p, |
249 | struct wil6210_priv, p2p); | 247 | struct wil6210_vif, p2p); |
248 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
250 | u8 started; | 249 | u8 started; |
251 | 250 | ||
252 | wil_dbg_misc(wil, "p2p_listen_expired\n"); | 251 | wil_dbg_misc(wil, "p2p_listen_expired\n"); |
253 | 252 | ||
254 | mutex_lock(&wil->mutex); | 253 | mutex_lock(&wil->mutex); |
255 | started = wil_p2p_stop_discovery(wil); | 254 | started = wil_p2p_stop_discovery(vif); |
256 | mutex_unlock(&wil->mutex); | 255 | mutex_unlock(&wil->mutex); |
257 | 256 | ||
258 | if (started) { | 257 | if (!started) |
259 | mutex_lock(&wil->p2p_wdev_mutex); | 258 | return; |
260 | cfg80211_remain_on_channel_expired(wil->radio_wdev, | ||
261 | p2p->cookie, | ||
262 | &p2p->listen_chan, | ||
263 | GFP_KERNEL); | ||
264 | wil->radio_wdev = wil->wdev; | ||
265 | mutex_unlock(&wil->p2p_wdev_mutex); | ||
266 | } | ||
267 | 259 | ||
260 | mutex_lock(&wil->vif_mutex); | ||
261 | cfg80211_remain_on_channel_expired(vif_to_radio_wdev(wil, vif), | ||
262 | p2p->cookie, | ||
263 | &p2p->listen_chan, | ||
264 | GFP_KERNEL); | ||
265 | if (vif->mid == 0) | ||
266 | wil->radio_wdev = wil->main_ndev->ieee80211_ptr; | ||
267 | mutex_unlock(&wil->vif_mutex); | ||
268 | } | 268 | } |
269 | 269 | ||
270 | void wil_p2p_search_expired(struct work_struct *work) | 270 | void wil_p2p_search_expired(struct work_struct *work) |
271 | { | 271 | { |
272 | struct wil_p2p_info *p2p = container_of(work, | 272 | struct wil_p2p_info *p2p = container_of(work, |
273 | struct wil_p2p_info, discovery_expired_work); | 273 | struct wil_p2p_info, discovery_expired_work); |
274 | struct wil6210_priv *wil = container_of(p2p, | 274 | struct wil6210_vif *vif = container_of(p2p, |
275 | struct wil6210_priv, p2p); | 275 | struct wil6210_vif, p2p); |
276 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
276 | u8 started; | 277 | u8 started; |
277 | 278 | ||
278 | wil_dbg_misc(wil, "p2p_search_expired\n"); | 279 | wil_dbg_misc(wil, "p2p_search_expired\n"); |
279 | 280 | ||
280 | mutex_lock(&wil->mutex); | 281 | mutex_lock(&wil->mutex); |
281 | started = wil_p2p_stop_discovery(wil); | 282 | started = wil_p2p_stop_discovery(vif); |
282 | mutex_unlock(&wil->mutex); | 283 | mutex_unlock(&wil->mutex); |
283 | 284 | ||
284 | if (started) { | 285 | if (started) { |
@@ -286,13 +287,15 @@ void wil_p2p_search_expired(struct work_struct *work) | |||
286 | .aborted = false, | 287 | .aborted = false, |
287 | }; | 288 | }; |
288 | 289 | ||
289 | mutex_lock(&wil->p2p_wdev_mutex); | 290 | mutex_lock(&wil->vif_mutex); |
290 | if (wil->scan_request) { | 291 | if (vif->scan_request) { |
291 | cfg80211_scan_done(wil->scan_request, &info); | 292 | cfg80211_scan_done(vif->scan_request, &info); |
292 | wil->scan_request = NULL; | 293 | vif->scan_request = NULL; |
293 | wil->radio_wdev = wil->wdev; | 294 | if (vif->mid == 0) |
295 | wil->radio_wdev = | ||
296 | wil->main_ndev->ieee80211_ptr; | ||
294 | } | 297 | } |
295 | mutex_unlock(&wil->p2p_wdev_mutex); | 298 | mutex_unlock(&wil->vif_mutex); |
296 | } | 299 | } |
297 | } | 300 | } |
298 | 301 | ||
@@ -300,8 +303,9 @@ void wil_p2p_delayed_listen_work(struct work_struct *work) | |||
300 | { | 303 | { |
301 | struct wil_p2p_info *p2p = container_of(work, | 304 | struct wil_p2p_info *p2p = container_of(work, |
302 | struct wil_p2p_info, delayed_listen_work); | 305 | struct wil_p2p_info, delayed_listen_work); |
303 | struct wil6210_priv *wil = container_of(p2p, | 306 | struct wil6210_vif *vif = container_of(p2p, |
304 | struct wil6210_priv, p2p); | 307 | struct wil6210_vif, p2p); |
308 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
305 | int rc; | 309 | int rc; |
306 | 310 | ||
307 | mutex_lock(&wil->mutex); | 311 | mutex_lock(&wil->mutex); |
@@ -310,31 +314,33 @@ void wil_p2p_delayed_listen_work(struct work_struct *work) | |||
310 | if (!p2p->discovery_started || !p2p->pending_listen_wdev) | 314 | if (!p2p->discovery_started || !p2p->pending_listen_wdev) |
311 | goto out; | 315 | goto out; |
312 | 316 | ||
313 | mutex_lock(&wil->p2p_wdev_mutex); | 317 | mutex_lock(&wil->vif_mutex); |
314 | if (wil->scan_request) { | 318 | if (vif->scan_request) { |
315 | /* another scan started, wait again... */ | 319 | /* another scan started, wait again... */ |
316 | mutex_unlock(&wil->p2p_wdev_mutex); | 320 | mutex_unlock(&wil->vif_mutex); |
317 | goto out; | 321 | goto out; |
318 | } | 322 | } |
319 | mutex_unlock(&wil->p2p_wdev_mutex); | 323 | mutex_unlock(&wil->vif_mutex); |
320 | 324 | ||
321 | rc = wil_p2p_start_listen(wil); | 325 | rc = wil_p2p_start_listen(vif); |
322 | 326 | ||
323 | mutex_lock(&wil->p2p_wdev_mutex); | 327 | mutex_lock(&wil->vif_mutex); |
324 | if (rc) { | 328 | if (rc) { |
325 | cfg80211_remain_on_channel_expired(p2p->pending_listen_wdev, | 329 | cfg80211_remain_on_channel_expired(p2p->pending_listen_wdev, |
326 | p2p->cookie, | 330 | p2p->cookie, |
327 | &p2p->listen_chan, | 331 | &p2p->listen_chan, |
328 | GFP_KERNEL); | 332 | GFP_KERNEL); |
329 | wil->radio_wdev = wil->wdev; | 333 | if (vif->mid == 0) |
334 | wil->radio_wdev = wil->main_ndev->ieee80211_ptr; | ||
330 | } else { | 335 | } else { |
331 | cfg80211_ready_on_channel(p2p->pending_listen_wdev, p2p->cookie, | 336 | cfg80211_ready_on_channel(p2p->pending_listen_wdev, p2p->cookie, |
332 | &p2p->listen_chan, | 337 | &p2p->listen_chan, |
333 | p2p->listen_duration, GFP_KERNEL); | 338 | p2p->listen_duration, GFP_KERNEL); |
334 | wil->radio_wdev = p2p->pending_listen_wdev; | 339 | if (vif->mid == 0) |
340 | wil->radio_wdev = p2p->pending_listen_wdev; | ||
335 | } | 341 | } |
336 | p2p->pending_listen_wdev = NULL; | 342 | p2p->pending_listen_wdev = NULL; |
337 | mutex_unlock(&wil->p2p_wdev_mutex); | 343 | mutex_unlock(&wil->vif_mutex); |
338 | 344 | ||
339 | out: | 345 | out: |
340 | mutex_unlock(&wil->mutex); | 346 | mutex_unlock(&wil->mutex); |
@@ -342,34 +348,35 @@ out: | |||
342 | 348 | ||
343 | void wil_p2p_stop_radio_operations(struct wil6210_priv *wil) | 349 | void wil_p2p_stop_radio_operations(struct wil6210_priv *wil) |
344 | { | 350 | { |
345 | struct wil_p2p_info *p2p = &wil->p2p; | 351 | struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); |
352 | struct wil_p2p_info *p2p = &vif->p2p; | ||
346 | struct cfg80211_scan_info info = { | 353 | struct cfg80211_scan_info info = { |
347 | .aborted = true, | 354 | .aborted = true, |
348 | }; | 355 | }; |
349 | 356 | ||
350 | lockdep_assert_held(&wil->mutex); | 357 | lockdep_assert_held(&wil->mutex); |
351 | lockdep_assert_held(&wil->p2p_wdev_mutex); | 358 | lockdep_assert_held(&wil->vif_mutex); |
352 | 359 | ||
353 | if (wil->radio_wdev != wil->p2p_wdev) | 360 | if (wil->radio_wdev != wil->p2p_wdev) |
354 | goto out; | 361 | goto out; |
355 | 362 | ||
356 | if (!p2p->discovery_started) { | 363 | if (!p2p->discovery_started) { |
357 | /* Regular scan on the p2p device */ | 364 | /* Regular scan on the p2p device */ |
358 | if (wil->scan_request && | 365 | if (vif->scan_request && |
359 | wil->scan_request->wdev == wil->p2p_wdev) | 366 | vif->scan_request->wdev == wil->p2p_wdev) |
360 | wil_abort_scan(wil, true); | 367 | wil_abort_scan(vif, true); |
361 | goto out; | 368 | goto out; |
362 | } | 369 | } |
363 | 370 | ||
364 | /* Search or listen on p2p device */ | 371 | /* Search or listen on p2p device */ |
365 | mutex_unlock(&wil->p2p_wdev_mutex); | 372 | mutex_unlock(&wil->vif_mutex); |
366 | wil_p2p_stop_discovery(wil); | 373 | wil_p2p_stop_discovery(vif); |
367 | mutex_lock(&wil->p2p_wdev_mutex); | 374 | mutex_lock(&wil->vif_mutex); |
368 | 375 | ||
369 | if (wil->scan_request) { | 376 | if (vif->scan_request) { |
370 | /* search */ | 377 | /* search */ |
371 | cfg80211_scan_done(wil->scan_request, &info); | 378 | cfg80211_scan_done(vif->scan_request, &info); |
372 | wil->scan_request = NULL; | 379 | vif->scan_request = NULL; |
373 | } else { | 380 | } else { |
374 | /* listen */ | 381 | /* listen */ |
375 | cfg80211_remain_on_channel_expired(wil->radio_wdev, | 382 | cfg80211_remain_on_channel_expired(wil->radio_wdev, |
@@ -379,5 +386,5 @@ void wil_p2p_stop_radio_operations(struct wil6210_priv *wil) | |||
379 | } | 386 | } |
380 | 387 | ||
381 | out: | 388 | out: |
382 | wil->radio_wdev = wil->wdev; | 389 | wil->radio_wdev = wil->main_ndev->ieee80211_ptr; |
383 | } | 390 | } |
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index 809092a49192..19cbc6add637 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c | |||
@@ -137,6 +137,20 @@ void wil_enable_irq(struct wil6210_priv *wil) | |||
137 | enable_irq(wil->pdev->irq); | 137 | enable_irq(wil->pdev->irq); |
138 | } | 138 | } |
139 | 139 | ||
140 | static void wil_remove_all_additional_vifs(struct wil6210_priv *wil) | ||
141 | { | ||
142 | struct wil6210_vif *vif; | ||
143 | int i; | ||
144 | |||
145 | for (i = 1; i < wil->max_vifs; i++) { | ||
146 | vif = wil->vifs[i]; | ||
147 | if (vif) { | ||
148 | wil_vif_prepare_stop(vif); | ||
149 | wil_vif_remove(wil, vif->mid); | ||
150 | } | ||
151 | } | ||
152 | } | ||
153 | |||
140 | /* Bus ops */ | 154 | /* Bus ops */ |
141 | static int wil_if_pcie_enable(struct wil6210_priv *wil) | 155 | static int wil_if_pcie_enable(struct wil6210_priv *wil) |
142 | { | 156 | { |
@@ -148,10 +162,8 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil) | |||
148 | */ | 162 | */ |
149 | int msi_only = pdev->msi_enabled; | 163 | int msi_only = pdev->msi_enabled; |
150 | bool _use_msi = use_msi; | 164 | bool _use_msi = use_msi; |
151 | bool wmi_only = test_bit(WMI_FW_CAPABILITY_WMI_ONLY, | ||
152 | wil->fw_capabilities); | ||
153 | 165 | ||
154 | wil_dbg_misc(wil, "if_pcie_enable, wmi_only %d\n", wmi_only); | 166 | wil_dbg_misc(wil, "if_pcie_enable\n"); |
155 | 167 | ||
156 | pci_set_master(pdev); | 168 | pci_set_master(pdev); |
157 | 169 | ||
@@ -172,11 +184,9 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil) | |||
172 | if (rc) | 184 | if (rc) |
173 | goto stop_master; | 185 | goto stop_master; |
174 | 186 | ||
175 | /* need reset here to obtain MAC or in case of WMI-only FW, full reset | 187 | /* need reset here to obtain MAC */ |
176 | * and fw loading takes place | ||
177 | */ | ||
178 | mutex_lock(&wil->mutex); | 188 | mutex_lock(&wil->mutex); |
179 | rc = wil_reset(wil, wmi_only); | 189 | rc = wil_reset(wil, false); |
180 | mutex_unlock(&wil->mutex); | 190 | mutex_unlock(&wil->mutex); |
181 | if (rc) | 191 | if (rc) |
182 | goto release_irq; | 192 | goto release_irq; |
@@ -356,6 +366,18 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
356 | goto bus_disable; | 366 | goto bus_disable; |
357 | } | 367 | } |
358 | 368 | ||
369 | /* in case of WMI-only FW, perform full reset and FW loading */ | ||
370 | if (test_bit(WMI_FW_CAPABILITY_WMI_ONLY, wil->fw_capabilities)) { | ||
371 | wil_dbg_misc(wil, "Loading WMI only FW\n"); | ||
372 | mutex_lock(&wil->mutex); | ||
373 | rc = wil_reset(wil, true); | ||
374 | mutex_unlock(&wil->mutex); | ||
375 | if (rc) { | ||
376 | wil_err(wil, "failed to load WMI only FW\n"); | ||
377 | goto if_remove; | ||
378 | } | ||
379 | } | ||
380 | |||
359 | if (IS_ENABLED(CONFIG_PM)) | 381 | if (IS_ENABLED(CONFIG_PM)) |
360 | wil->pm_notify.notifier_call = wil6210_pm_notify; | 382 | wil->pm_notify.notifier_call = wil6210_pm_notify; |
361 | 383 | ||
@@ -372,6 +394,8 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
372 | 394 | ||
373 | return 0; | 395 | return 0; |
374 | 396 | ||
397 | if_remove: | ||
398 | wil_if_remove(wil); | ||
375 | bus_disable: | 399 | bus_disable: |
376 | wil_if_pcie_disable(wil); | 400 | wil_if_pcie_disable(wil); |
377 | err_iounmap: | 401 | err_iounmap: |
@@ -402,6 +426,7 @@ static void wil_pcie_remove(struct pci_dev *pdev) | |||
402 | wil6210_debugfs_remove(wil); | 426 | wil6210_debugfs_remove(wil); |
403 | rtnl_lock(); | 427 | rtnl_lock(); |
404 | wil_p2p_wdev_free(wil); | 428 | wil_p2p_wdev_free(wil); |
429 | wil_remove_all_additional_vifs(wil); | ||
405 | rtnl_unlock(); | 430 | rtnl_unlock(); |
406 | wil_if_remove(wil); | 431 | wil_if_remove(wil); |
407 | wil_if_pcie_disable(wil); | 432 | wil_if_pcie_disable(wil); |
@@ -425,12 +450,15 @@ static int wil6210_suspend(struct device *dev, bool is_runtime) | |||
425 | int rc = 0; | 450 | int rc = 0; |
426 | struct pci_dev *pdev = to_pci_dev(dev); | 451 | struct pci_dev *pdev = to_pci_dev(dev); |
427 | struct wil6210_priv *wil = pci_get_drvdata(pdev); | 452 | struct wil6210_priv *wil = pci_get_drvdata(pdev); |
428 | struct net_device *ndev = wil_to_ndev(wil); | 453 | bool keep_radio_on, active_ifaces; |
429 | bool keep_radio_on = ndev->flags & IFF_UP && | ||
430 | wil->keep_radio_on_during_sleep; | ||
431 | 454 | ||
432 | wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system"); | 455 | wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system"); |
433 | 456 | ||
457 | mutex_lock(&wil->vif_mutex); | ||
458 | active_ifaces = wil_has_active_ifaces(wil, true, false); | ||
459 | mutex_unlock(&wil->vif_mutex); | ||
460 | keep_radio_on = active_ifaces && wil->keep_radio_on_during_sleep; | ||
461 | |||
434 | rc = wil_can_suspend(wil, is_runtime); | 462 | rc = wil_can_suspend(wil, is_runtime); |
435 | if (rc) | 463 | if (rc) |
436 | goto out; | 464 | goto out; |
@@ -457,12 +485,15 @@ static int wil6210_resume(struct device *dev, bool is_runtime) | |||
457 | int rc = 0; | 485 | int rc = 0; |
458 | struct pci_dev *pdev = to_pci_dev(dev); | 486 | struct pci_dev *pdev = to_pci_dev(dev); |
459 | struct wil6210_priv *wil = pci_get_drvdata(pdev); | 487 | struct wil6210_priv *wil = pci_get_drvdata(pdev); |
460 | struct net_device *ndev = wil_to_ndev(wil); | 488 | bool keep_radio_on, active_ifaces; |
461 | bool keep_radio_on = ndev->flags & IFF_UP && | ||
462 | wil->keep_radio_on_during_sleep; | ||
463 | 489 | ||
464 | wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system"); | 490 | wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system"); |
465 | 491 | ||
492 | mutex_lock(&wil->vif_mutex); | ||
493 | active_ifaces = wil_has_active_ifaces(wil, true, false); | ||
494 | mutex_unlock(&wil->vif_mutex); | ||
495 | keep_radio_on = active_ifaces && wil->keep_radio_on_during_sleep; | ||
496 | |||
466 | /* In case radio stays on, platform device will control | 497 | /* In case radio stays on, platform device will control |
467 | * PCIe master | 498 | * PCIe master |
468 | */ | 499 | */ |
diff --git a/drivers/net/wireless/ath/wil6210/pm.c b/drivers/net/wireless/ath/wil6210/pm.c index 0a96518a566f..ba81fb3ac96f 100644 --- a/drivers/net/wireless/ath/wil6210/pm.c +++ b/drivers/net/wireless/ath/wil6210/pm.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2014,2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2014,2017 Qualcomm Atheros, Inc. |
3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -20,13 +21,72 @@ | |||
20 | 21 | ||
21 | #define WIL6210_AUTOSUSPEND_DELAY_MS (1000) | 22 | #define WIL6210_AUTOSUSPEND_DELAY_MS (1000) |
22 | 23 | ||
24 | static void wil_pm_wake_connected_net_queues(struct wil6210_priv *wil) | ||
25 | { | ||
26 | int i; | ||
27 | |||
28 | mutex_lock(&wil->vif_mutex); | ||
29 | for (i = 0; i < wil->max_vifs; i++) { | ||
30 | struct wil6210_vif *vif = wil->vifs[i]; | ||
31 | |||
32 | if (vif && test_bit(wil_vif_fwconnected, vif->status)) | ||
33 | wil_update_net_queues_bh(wil, vif, NULL, false); | ||
34 | } | ||
35 | mutex_unlock(&wil->vif_mutex); | ||
36 | } | ||
37 | |||
38 | static void wil_pm_stop_all_net_queues(struct wil6210_priv *wil) | ||
39 | { | ||
40 | int i; | ||
41 | |||
42 | mutex_lock(&wil->vif_mutex); | ||
43 | for (i = 0; i < wil->max_vifs; i++) { | ||
44 | struct wil6210_vif *vif = wil->vifs[i]; | ||
45 | |||
46 | if (vif) | ||
47 | wil_update_net_queues_bh(wil, vif, NULL, true); | ||
48 | } | ||
49 | mutex_unlock(&wil->vif_mutex); | ||
50 | } | ||
51 | |||
52 | static bool | ||
53 | wil_can_suspend_vif(struct wil6210_priv *wil, struct wil6210_vif *vif, | ||
54 | bool is_runtime) | ||
55 | { | ||
56 | struct wireless_dev *wdev = vif_to_wdev(vif); | ||
57 | |||
58 | switch (wdev->iftype) { | ||
59 | case NL80211_IFTYPE_MONITOR: | ||
60 | wil_dbg_pm(wil, "Sniffer\n"); | ||
61 | return false; | ||
62 | |||
63 | /* for STA-like interface, don't runtime suspend */ | ||
64 | case NL80211_IFTYPE_STATION: | ||
65 | case NL80211_IFTYPE_P2P_CLIENT: | ||
66 | if (test_bit(wil_vif_fwconnecting, vif->status)) { | ||
67 | wil_dbg_pm(wil, "Delay suspend when connecting\n"); | ||
68 | return false; | ||
69 | } | ||
70 | if (is_runtime) { | ||
71 | wil_dbg_pm(wil, "STA-like interface\n"); | ||
72 | return false; | ||
73 | } | ||
74 | break; | ||
75 | /* AP-like interface - can't suspend */ | ||
76 | default: | ||
77 | wil_dbg_pm(wil, "AP-like interface\n"); | ||
78 | return false; | ||
79 | } | ||
80 | |||
81 | return true; | ||
82 | } | ||
83 | |||
23 | int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime) | 84 | int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime) |
24 | { | 85 | { |
25 | int rc = 0; | 86 | int rc = 0, i; |
26 | struct wireless_dev *wdev = wil->wdev; | ||
27 | struct net_device *ndev = wil_to_ndev(wil); | ||
28 | bool wmi_only = test_bit(WMI_FW_CAPABILITY_WMI_ONLY, | 87 | bool wmi_only = test_bit(WMI_FW_CAPABILITY_WMI_ONLY, |
29 | wil->fw_capabilities); | 88 | wil->fw_capabilities); |
89 | bool active_ifaces; | ||
30 | 90 | ||
31 | wil_dbg_pm(wil, "can_suspend: %s\n", is_runtime ? "runtime" : "system"); | 91 | wil_dbg_pm(wil, "can_suspend: %s\n", is_runtime ? "runtime" : "system"); |
32 | 92 | ||
@@ -40,7 +100,12 @@ int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime) | |||
40 | rc = -EBUSY; | 100 | rc = -EBUSY; |
41 | goto out; | 101 | goto out; |
42 | } | 102 | } |
43 | if (!(ndev->flags & IFF_UP)) { | 103 | |
104 | mutex_lock(&wil->vif_mutex); | ||
105 | active_ifaces = wil_has_active_ifaces(wil, true, false); | ||
106 | mutex_unlock(&wil->vif_mutex); | ||
107 | |||
108 | if (!active_ifaces) { | ||
44 | /* can always sleep when down */ | 109 | /* can always sleep when down */ |
45 | wil_dbg_pm(wil, "Interface is down\n"); | 110 | wil_dbg_pm(wil, "Interface is down\n"); |
46 | goto out; | 111 | goto out; |
@@ -57,32 +122,19 @@ int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime) | |||
57 | } | 122 | } |
58 | 123 | ||
59 | /* interface is running */ | 124 | /* interface is running */ |
60 | switch (wdev->iftype) { | 125 | mutex_lock(&wil->vif_mutex); |
61 | case NL80211_IFTYPE_MONITOR: | 126 | for (i = 0; i < wil->max_vifs; i++) { |
62 | wil_dbg_pm(wil, "Sniffer\n"); | 127 | struct wil6210_vif *vif = wil->vifs[i]; |
63 | rc = -EBUSY; | 128 | |
64 | goto out; | 129 | if (!vif) |
65 | /* for STA-like interface, don't runtime suspend */ | 130 | continue; |
66 | case NL80211_IFTYPE_STATION: | 131 | if (!wil_can_suspend_vif(wil, vif, is_runtime)) { |
67 | case NL80211_IFTYPE_P2P_CLIENT: | ||
68 | if (test_bit(wil_status_fwconnecting, wil->status)) { | ||
69 | wil_dbg_pm(wil, "Delay suspend when connecting\n"); | ||
70 | rc = -EBUSY; | ||
71 | goto out; | ||
72 | } | ||
73 | /* Runtime pm not supported in case the interface is up */ | ||
74 | if (is_runtime) { | ||
75 | wil_dbg_pm(wil, "STA-like interface\n"); | ||
76 | rc = -EBUSY; | 132 | rc = -EBUSY; |
133 | mutex_unlock(&wil->vif_mutex); | ||
77 | goto out; | 134 | goto out; |
78 | } | 135 | } |
79 | break; | ||
80 | /* AP-like interface - can't suspend */ | ||
81 | default: | ||
82 | wil_dbg_pm(wil, "AP-like interface\n"); | ||
83 | rc = -EBUSY; | ||
84 | break; | ||
85 | } | 136 | } |
137 | mutex_unlock(&wil->vif_mutex); | ||
86 | 138 | ||
87 | out: | 139 | out: |
88 | wil_dbg_pm(wil, "can_suspend: %s => %s (%d)\n", | 140 | wil_dbg_pm(wil, "can_suspend: %s => %s (%d)\n", |
@@ -127,8 +179,7 @@ static int wil_resume_keep_radio_on(struct wil6210_priv *wil) | |||
127 | } | 179 | } |
128 | 180 | ||
129 | /* Wake all queues */ | 181 | /* Wake all queues */ |
130 | if (test_bit(wil_status_fwconnected, wil->status)) | 182 | wil_pm_wake_connected_net_queues(wil); |
131 | wil_update_net_queues_bh(wil, NULL, false); | ||
132 | 183 | ||
133 | out: | 184 | out: |
134 | if (rc) | 185 | if (rc) |
@@ -152,7 +203,7 @@ static int wil_suspend_keep_radio_on(struct wil6210_priv *wil) | |||
152 | wil->suspend_stats.rejected_by_host++; | 203 | wil->suspend_stats.rejected_by_host++; |
153 | return -EBUSY; | 204 | return -EBUSY; |
154 | } | 205 | } |
155 | wil_update_net_queues_bh(wil, NULL, true); | 206 | wil_pm_stop_all_net_queues(wil); |
156 | 207 | ||
157 | if (!wil_is_tx_idle(wil)) { | 208 | if (!wil_is_tx_idle(wil)) { |
158 | wil_dbg_pm(wil, "Pending TX data, reject suspend\n"); | 209 | wil_dbg_pm(wil, "Pending TX data, reject suspend\n"); |
@@ -243,22 +294,20 @@ resume_after_fail: | |||
243 | /* if resume succeeded, reject the suspend */ | 294 | /* if resume succeeded, reject the suspend */ |
244 | if (!rc) { | 295 | if (!rc) { |
245 | rc = -EBUSY; | 296 | rc = -EBUSY; |
246 | if (test_bit(wil_status_fwconnected, wil->status)) | 297 | wil_pm_wake_connected_net_queues(wil); |
247 | wil_update_net_queues_bh(wil, NULL, false); | ||
248 | } | 298 | } |
249 | return rc; | 299 | return rc; |
250 | 300 | ||
251 | reject_suspend: | 301 | reject_suspend: |
252 | clear_bit(wil_status_suspending, wil->status); | 302 | clear_bit(wil_status_suspending, wil->status); |
253 | if (test_bit(wil_status_fwconnected, wil->status)) | 303 | wil_pm_wake_connected_net_queues(wil); |
254 | wil_update_net_queues_bh(wil, NULL, false); | ||
255 | return -EBUSY; | 304 | return -EBUSY; |
256 | } | 305 | } |
257 | 306 | ||
258 | static int wil_suspend_radio_off(struct wil6210_priv *wil) | 307 | static int wil_suspend_radio_off(struct wil6210_priv *wil) |
259 | { | 308 | { |
260 | int rc = 0; | 309 | int rc = 0; |
261 | struct net_device *ndev = wil_to_ndev(wil); | 310 | bool active_ifaces; |
262 | 311 | ||
263 | wil_dbg_pm(wil, "suspend radio off\n"); | 312 | wil_dbg_pm(wil, "suspend radio off\n"); |
264 | 313 | ||
@@ -272,7 +321,11 @@ static int wil_suspend_radio_off(struct wil6210_priv *wil) | |||
272 | } | 321 | } |
273 | 322 | ||
274 | /* if netif up, hardware is alive, shut it down */ | 323 | /* if netif up, hardware is alive, shut it down */ |
275 | if (ndev->flags & IFF_UP) { | 324 | mutex_lock(&wil->vif_mutex); |
325 | active_ifaces = wil_has_active_ifaces(wil, true, false); | ||
326 | mutex_unlock(&wil->vif_mutex); | ||
327 | |||
328 | if (active_ifaces) { | ||
276 | rc = wil_down(wil); | 329 | rc = wil_down(wil); |
277 | if (rc) { | 330 | if (rc) { |
278 | wil_err(wil, "wil_down : %d\n", rc); | 331 | wil_err(wil, "wil_down : %d\n", rc); |
@@ -306,16 +359,19 @@ out: | |||
306 | static int wil_resume_radio_off(struct wil6210_priv *wil) | 359 | static int wil_resume_radio_off(struct wil6210_priv *wil) |
307 | { | 360 | { |
308 | int rc = 0; | 361 | int rc = 0; |
309 | struct net_device *ndev = wil_to_ndev(wil); | 362 | bool active_ifaces; |
310 | 363 | ||
311 | wil_dbg_pm(wil, "Enabling PCIe IRQ\n"); | 364 | wil_dbg_pm(wil, "Enabling PCIe IRQ\n"); |
312 | wil_enable_irq(wil); | 365 | wil_enable_irq(wil); |
313 | /* if netif up, bring hardware up | 366 | /* if any netif up, bring hardware up |
314 | * During open(), IFF_UP set after actual device method | 367 | * During open(), IFF_UP set after actual device method |
315 | * invocation. This prevent recursive call to wil_up() | 368 | * invocation. This prevent recursive call to wil_up() |
316 | * wil_status_suspended will be cleared in wil_reset | 369 | * wil_status_suspended will be cleared in wil_reset |
317 | */ | 370 | */ |
318 | if (ndev->flags & IFF_UP) | 371 | mutex_lock(&wil->vif_mutex); |
372 | active_ifaces = wil_has_active_ifaces(wil, true, false); | ||
373 | mutex_unlock(&wil->vif_mutex); | ||
374 | if (active_ifaces) | ||
319 | rc = wil_up(wil); | 375 | rc = wil_up(wil); |
320 | else | 376 | else |
321 | clear_bit(wil_status_suspended, wil->status); | 377 | clear_bit(wil_status_suspended, wil->status); |
diff --git a/drivers/net/wireless/ath/wil6210/pmc.c b/drivers/net/wireless/ath/wil6210/pmc.c index 4ea27b0bd278..c49f7988369e 100644 --- a/drivers/net/wireless/ath/wil6210/pmc.c +++ b/drivers/net/wireless/ath/wil6210/pmc.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012-2015,2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2015,2017 Qualcomm Atheros, Inc. |
3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -53,6 +54,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil, | |||
53 | u32 i; | 54 | u32 i; |
54 | struct pmc_ctx *pmc = &wil->pmc; | 55 | struct pmc_ctx *pmc = &wil->pmc; |
55 | struct device *dev = wil_to_dev(wil); | 56 | struct device *dev = wil_to_dev(wil); |
57 | struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); | ||
56 | struct wmi_pmc_cmd pmc_cmd = {0}; | 58 | struct wmi_pmc_cmd pmc_cmd = {0}; |
57 | int last_cmd_err = -ENOMEM; | 59 | int last_cmd_err = -ENOMEM; |
58 | 60 | ||
@@ -186,6 +188,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil, | |||
186 | wil_dbg_misc(wil, "pmc_alloc: send WMI_PMC_CMD with ALLOCATE op\n"); | 188 | wil_dbg_misc(wil, "pmc_alloc: send WMI_PMC_CMD with ALLOCATE op\n"); |
187 | pmc->last_cmd_status = wmi_send(wil, | 189 | pmc->last_cmd_status = wmi_send(wil, |
188 | WMI_PMC_CMDID, | 190 | WMI_PMC_CMDID, |
191 | vif->mid, | ||
189 | &pmc_cmd, | 192 | &pmc_cmd, |
190 | sizeof(pmc_cmd)); | 193 | sizeof(pmc_cmd)); |
191 | if (pmc->last_cmd_status) { | 194 | if (pmc->last_cmd_status) { |
@@ -236,6 +239,7 @@ void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd) | |||
236 | { | 239 | { |
237 | struct pmc_ctx *pmc = &wil->pmc; | 240 | struct pmc_ctx *pmc = &wil->pmc; |
238 | struct device *dev = wil_to_dev(wil); | 241 | struct device *dev = wil_to_dev(wil); |
242 | struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); | ||
239 | struct wmi_pmc_cmd pmc_cmd = {0}; | 243 | struct wmi_pmc_cmd pmc_cmd = {0}; |
240 | 244 | ||
241 | mutex_lock(&pmc->lock); | 245 | mutex_lock(&pmc->lock); |
@@ -254,8 +258,8 @@ void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd) | |||
254 | wil_dbg_misc(wil, "send WMI_PMC_CMD with RELEASE op\n"); | 258 | wil_dbg_misc(wil, "send WMI_PMC_CMD with RELEASE op\n"); |
255 | pmc_cmd.op = WMI_PMC_RELEASE; | 259 | pmc_cmd.op = WMI_PMC_RELEASE; |
256 | pmc->last_cmd_status = | 260 | pmc->last_cmd_status = |
257 | wmi_send(wil, WMI_PMC_CMDID, &pmc_cmd, | 261 | wmi_send(wil, WMI_PMC_CMDID, vif->mid, |
258 | sizeof(pmc_cmd)); | 262 | &pmc_cmd, sizeof(pmc_cmd)); |
259 | if (pmc->last_cmd_status) { | 263 | if (pmc->last_cmd_status) { |
260 | wil_err(wil, | 264 | wil_err(wil, |
261 | "WMI_PMC_CMD with RELEASE op failed, status %d", | 265 | "WMI_PMC_CMD with RELEASE op failed, status %d", |
diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c index a43cffcf1bbf..14dcb0698dee 100644 --- a/drivers/net/wireless/ath/wil6210/rx_reorder.c +++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. |
3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -40,11 +41,10 @@ static inline int reorder_index(struct wil_tid_ampdu_rx *r, u16 seq) | |||
40 | return seq_sub(seq, r->ssn) % r->buf_size; | 41 | return seq_sub(seq, r->ssn) % r->buf_size; |
41 | } | 42 | } |
42 | 43 | ||
43 | static void wil_release_reorder_frame(struct wil6210_priv *wil, | 44 | static void wil_release_reorder_frame(struct net_device *ndev, |
44 | struct wil_tid_ampdu_rx *r, | 45 | struct wil_tid_ampdu_rx *r, |
45 | int index) | 46 | int index) |
46 | { | 47 | { |
47 | struct net_device *ndev = wil_to_ndev(wil); | ||
48 | struct sk_buff *skb = r->reorder_buf[index]; | 48 | struct sk_buff *skb = r->reorder_buf[index]; |
49 | 49 | ||
50 | if (!skb) | 50 | if (!skb) |
@@ -59,7 +59,7 @@ no_frame: | |||
59 | r->head_seq_num = seq_inc(r->head_seq_num); | 59 | r->head_seq_num = seq_inc(r->head_seq_num); |
60 | } | 60 | } |
61 | 61 | ||
62 | static void wil_release_reorder_frames(struct wil6210_priv *wil, | 62 | static void wil_release_reorder_frames(struct net_device *ndev, |
63 | struct wil_tid_ampdu_rx *r, | 63 | struct wil_tid_ampdu_rx *r, |
64 | u16 hseq) | 64 | u16 hseq) |
65 | { | 65 | { |
@@ -73,18 +73,18 @@ static void wil_release_reorder_frames(struct wil6210_priv *wil, | |||
73 | */ | 73 | */ |
74 | while (seq_less(r->head_seq_num, hseq) && r->stored_mpdu_num) { | 74 | while (seq_less(r->head_seq_num, hseq) && r->stored_mpdu_num) { |
75 | index = reorder_index(r, r->head_seq_num); | 75 | index = reorder_index(r, r->head_seq_num); |
76 | wil_release_reorder_frame(wil, r, index); | 76 | wil_release_reorder_frame(ndev, r, index); |
77 | } | 77 | } |
78 | r->head_seq_num = hseq; | 78 | r->head_seq_num = hseq; |
79 | } | 79 | } |
80 | 80 | ||
81 | static void wil_reorder_release(struct wil6210_priv *wil, | 81 | static void wil_reorder_release(struct net_device *ndev, |
82 | struct wil_tid_ampdu_rx *r) | 82 | struct wil_tid_ampdu_rx *r) |
83 | { | 83 | { |
84 | int index = reorder_index(r, r->head_seq_num); | 84 | int index = reorder_index(r, r->head_seq_num); |
85 | 85 | ||
86 | while (r->reorder_buf[index]) { | 86 | while (r->reorder_buf[index]) { |
87 | wil_release_reorder_frame(wil, r, index); | 87 | wil_release_reorder_frame(ndev, r, index); |
88 | index = reorder_index(r, r->head_seq_num); | 88 | index = reorder_index(r, r->head_seq_num); |
89 | } | 89 | } |
90 | } | 90 | } |
@@ -93,7 +93,8 @@ static void wil_reorder_release(struct wil6210_priv *wil, | |||
93 | void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb) | 93 | void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb) |
94 | __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | 94 | __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) |
95 | { | 95 | { |
96 | struct net_device *ndev = wil_to_ndev(wil); | 96 | struct wil6210_vif *vif; |
97 | struct net_device *ndev; | ||
97 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); | 98 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); |
98 | int tid = wil_rxdesc_tid(d); | 99 | int tid = wil_rxdesc_tid(d); |
99 | int cid = wil_rxdesc_cid(d); | 100 | int cid = wil_rxdesc_cid(d); |
@@ -108,6 +109,14 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | |||
108 | wil_dbg_txrx(wil, "MID %d CID %d TID %d Seq 0x%03x mcast %01x\n", | 109 | wil_dbg_txrx(wil, "MID %d CID %d TID %d Seq 0x%03x mcast %01x\n", |
109 | mid, cid, tid, seq, mcast); | 110 | mid, cid, tid, seq, mcast); |
110 | 111 | ||
112 | vif = wil->vifs[mid]; | ||
113 | if (unlikely(!vif)) { | ||
114 | wil_dbg_txrx(wil, "invalid VIF, mid %d\n", mid); | ||
115 | dev_kfree_skb(skb); | ||
116 | return; | ||
117 | } | ||
118 | ndev = vif_to_ndev(vif); | ||
119 | |||
111 | if (unlikely(mcast)) { | 120 | if (unlikely(mcast)) { |
112 | wil_netif_rx_any(skb, ndev); | 121 | wil_netif_rx_any(skb, ndev); |
113 | return; | 122 | return; |
@@ -168,7 +177,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | |||
168 | if (!seq_less(seq, r->head_seq_num + r->buf_size)) { | 177 | if (!seq_less(seq, r->head_seq_num + r->buf_size)) { |
169 | hseq = seq_inc(seq_sub(seq, r->buf_size)); | 178 | hseq = seq_inc(seq_sub(seq, r->buf_size)); |
170 | /* release stored frames up to new head to stack */ | 179 | /* release stored frames up to new head to stack */ |
171 | wil_release_reorder_frames(wil, r, hseq); | 180 | wil_release_reorder_frames(ndev, r, hseq); |
172 | } | 181 | } |
173 | 182 | ||
174 | /* Now the new frame is always in the range of the reordering buffer */ | 183 | /* Now the new frame is always in the range of the reordering buffer */ |
@@ -199,16 +208,18 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | |||
199 | r->reorder_buf[index] = skb; | 208 | r->reorder_buf[index] = skb; |
200 | r->reorder_time[index] = jiffies; | 209 | r->reorder_time[index] = jiffies; |
201 | r->stored_mpdu_num++; | 210 | r->stored_mpdu_num++; |
202 | wil_reorder_release(wil, r); | 211 | wil_reorder_release(ndev, r); |
203 | 212 | ||
204 | out: | 213 | out: |
205 | spin_unlock(&sta->tid_rx_lock); | 214 | spin_unlock(&sta->tid_rx_lock); |
206 | } | 215 | } |
207 | 216 | ||
208 | /* process BAR frame, called in NAPI context */ | 217 | /* process BAR frame, called in NAPI context */ |
209 | void wil_rx_bar(struct wil6210_priv *wil, u8 cid, u8 tid, u16 seq) | 218 | void wil_rx_bar(struct wil6210_priv *wil, struct wil6210_vif *vif, |
219 | u8 cid, u8 tid, u16 seq) | ||
210 | { | 220 | { |
211 | struct wil_sta_info *sta = &wil->sta[cid]; | 221 | struct wil_sta_info *sta = &wil->sta[cid]; |
222 | struct net_device *ndev = vif_to_ndev(vif); | ||
212 | struct wil_tid_ampdu_rx *r; | 223 | struct wil_tid_ampdu_rx *r; |
213 | 224 | ||
214 | spin_lock(&sta->tid_rx_lock); | 225 | spin_lock(&sta->tid_rx_lock); |
@@ -223,9 +234,9 @@ void wil_rx_bar(struct wil6210_priv *wil, u8 cid, u8 tid, u16 seq) | |||
223 | seq, r->head_seq_num); | 234 | seq, r->head_seq_num); |
224 | goto out; | 235 | goto out; |
225 | } | 236 | } |
226 | wil_dbg_txrx(wil, "BAR: CID %d TID %d Seq 0x%03x head 0x%03x\n", | 237 | wil_dbg_txrx(wil, "BAR: CID %d MID %d TID %d Seq 0x%03x head 0x%03x\n", |
227 | cid, tid, seq, r->head_seq_num); | 238 | cid, vif->mid, tid, seq, r->head_seq_num); |
228 | wil_release_reorder_frames(wil, r, seq); | 239 | wil_release_reorder_frames(ndev, r, seq); |
229 | 240 | ||
230 | out: | 241 | out: |
231 | spin_unlock(&sta->tid_rx_lock); | 242 | spin_unlock(&sta->tid_rx_lock); |
@@ -292,8 +303,8 @@ static u16 wil_agg_size(struct wil6210_priv *wil, u16 req_agg_wsize) | |||
292 | } | 303 | } |
293 | 304 | ||
294 | /* Block Ack - Rx side (recipient) */ | 305 | /* Block Ack - Rx side (recipient) */ |
295 | int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid, | 306 | int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid, |
296 | u8 dialog_token, __le16 ba_param_set, | 307 | u8 cidxtid, u8 dialog_token, __le16 ba_param_set, |
297 | __le16 ba_timeout, __le16 ba_seq_ctrl) | 308 | __le16 ba_timeout, __le16 ba_seq_ctrl) |
298 | __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | 309 | __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) |
299 | { | 310 | { |
@@ -354,7 +365,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | |||
354 | } | 365 | } |
355 | } | 366 | } |
356 | 367 | ||
357 | rc = wmi_addba_rx_resp(wil, cid, tid, dialog_token, status, | 368 | rc = wmi_addba_rx_resp(wil, mid, cid, tid, dialog_token, status, |
358 | agg_amsdu, agg_wsize, agg_timeout); | 369 | agg_amsdu, agg_wsize, agg_timeout); |
359 | if (rc || (status != WLAN_STATUS_SUCCESS)) { | 370 | if (rc || (status != WLAN_STATUS_SUCCESS)) { |
360 | wil_err(wil, "do not apply ba, rc(%d), status(%d)\n", rc, | 371 | wil_err(wil, "do not apply ba, rc(%d), status(%d)\n", rc, |
@@ -393,7 +404,7 @@ int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize) | |||
393 | goto out; | 404 | goto out; |
394 | } | 405 | } |
395 | txdata->addba_in_progress = true; | 406 | txdata->addba_in_progress = true; |
396 | rc = wmi_addba(wil, ringid, agg_wsize, agg_timeout); | 407 | rc = wmi_addba(wil, txdata->mid, ringid, agg_wsize, agg_timeout); |
397 | if (rc) { | 408 | if (rc) { |
398 | wil_err(wil, "wmi_addba failed, rc (%d)", rc); | 409 | wil_err(wil, "wmi_addba failed, rc (%d)", rc); |
399 | txdata->addba_in_progress = false; | 410 | txdata->addba_in_progress = false; |
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 16b8a4e5201f..b60b9fcaaebd 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. |
3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -474,7 +475,8 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, | |||
474 | struct vring *vring) | 475 | struct vring *vring) |
475 | { | 476 | { |
476 | struct device *dev = wil_to_dev(wil); | 477 | struct device *dev = wil_to_dev(wil); |
477 | struct net_device *ndev = wil_to_ndev(wil); | 478 | struct wil6210_vif *vif; |
479 | struct net_device *ndev; | ||
478 | volatile struct vring_rx_desc *_d; | 480 | volatile struct vring_rx_desc *_d; |
479 | struct vring_rx_desc *d; | 481 | struct vring_rx_desc *d; |
480 | struct sk_buff *skb; | 482 | struct sk_buff *skb; |
@@ -483,7 +485,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, | |||
483 | unsigned int sz = wil->rx_buf_len + ETH_HLEN + snaplen; | 485 | unsigned int sz = wil->rx_buf_len + ETH_HLEN + snaplen; |
484 | u16 dmalen; | 486 | u16 dmalen; |
485 | u8 ftype; | 487 | u8 ftype; |
486 | int cid; | 488 | int cid, mid; |
487 | int i; | 489 | int i; |
488 | struct wil_net_stats *stats; | 490 | struct wil_net_stats *stats; |
489 | 491 | ||
@@ -520,6 +522,16 @@ again: | |||
520 | (const void *)d, sizeof(*d), false); | 522 | (const void *)d, sizeof(*d), false); |
521 | 523 | ||
522 | cid = wil_rxdesc_cid(d); | 524 | cid = wil_rxdesc_cid(d); |
525 | mid = wil_rxdesc_mid(d); | ||
526 | vif = wil->vifs[mid]; | ||
527 | |||
528 | if (unlikely(!vif)) { | ||
529 | wil_dbg_txrx(wil, "skipped RX descriptor with invalid mid %d", | ||
530 | mid); | ||
531 | kfree_skb(skb); | ||
532 | goto again; | ||
533 | } | ||
534 | ndev = vif_to_ndev(vif); | ||
523 | stats = &wil->sta[cid].stats; | 535 | stats = &wil->sta[cid].stats; |
524 | 536 | ||
525 | if (unlikely(dmalen > sz)) { | 537 | if (unlikely(dmalen > sz)) { |
@@ -553,7 +565,6 @@ again: | |||
553 | ftype = wil_rxdesc_ftype(d) << 2; | 565 | ftype = wil_rxdesc_ftype(d) << 2; |
554 | if (unlikely(ftype != IEEE80211_FTYPE_DATA)) { | 566 | if (unlikely(ftype != IEEE80211_FTYPE_DATA)) { |
555 | u8 fc1 = wil_rxdesc_fc1(d); | 567 | u8 fc1 = wil_rxdesc_fc1(d); |
556 | int mid = wil_rxdesc_mid(d); | ||
557 | int tid = wil_rxdesc_tid(d); | 568 | int tid = wil_rxdesc_tid(d); |
558 | u16 seq = wil_rxdesc_seq(d); | 569 | u16 seq = wil_rxdesc_seq(d); |
559 | 570 | ||
@@ -565,7 +576,7 @@ again: | |||
565 | wil_dbg_txrx(wil, | 576 | wil_dbg_txrx(wil, |
566 | "BAR: MID %d CID %d TID %d Seq 0x%03x\n", | 577 | "BAR: MID %d CID %d TID %d Seq 0x%03x\n", |
567 | mid, cid, tid, seq); | 578 | mid, cid, tid, seq); |
568 | wil_rx_bar(wil, cid, tid, seq); | 579 | wil_rx_bar(wil, vif, cid, tid, seq); |
569 | } else { | 580 | } else { |
570 | /* print again all info. One can enable only this | 581 | /* print again all info. One can enable only this |
571 | * without overhead for printing every Rx frame | 582 | * without overhead for printing every Rx frame |
@@ -621,10 +632,15 @@ again: | |||
621 | /** | 632 | /** |
622 | * allocate and fill up to @count buffers in rx ring | 633 | * allocate and fill up to @count buffers in rx ring |
623 | * buffers posted at @swtail | 634 | * buffers posted at @swtail |
635 | * Note: we have a single RX queue for servicing all VIFs, but we | ||
636 | * allocate skbs with headroom according to main interface only. This | ||
637 | * means it will not work with monitor interface together with other VIFs. | ||
638 | * Currently we only support monitor interface on its own without other VIFs, | ||
639 | * and we will need to fix this code once we add support. | ||
624 | */ | 640 | */ |
625 | static int wil_rx_refill(struct wil6210_priv *wil, int count) | 641 | static int wil_rx_refill(struct wil6210_priv *wil, int count) |
626 | { | 642 | { |
627 | struct net_device *ndev = wil_to_ndev(wil); | 643 | struct net_device *ndev = wil->main_ndev; |
628 | struct vring *v = &wil->vring_rx; | 644 | struct vring *v = &wil->vring_rx; |
629 | u32 next_tail; | 645 | u32 next_tail; |
630 | int rc = 0; | 646 | int rc = 0; |
@@ -713,8 +729,9 @@ static int wil_rx_crypto_check(struct wil6210_priv *wil, struct sk_buff *skb) | |||
713 | void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) | 729 | void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) |
714 | { | 730 | { |
715 | gro_result_t rc = GRO_NORMAL; | 731 | gro_result_t rc = GRO_NORMAL; |
732 | struct wil6210_vif *vif = ndev_to_vif(ndev); | ||
716 | struct wil6210_priv *wil = ndev_to_wil(ndev); | 733 | struct wil6210_priv *wil = ndev_to_wil(ndev); |
717 | struct wireless_dev *wdev = wil_to_wdev(wil); | 734 | struct wireless_dev *wdev = vif_to_wdev(vif); |
718 | unsigned int len = skb->len; | 735 | unsigned int len = skb->len; |
719 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); | 736 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); |
720 | int cid = wil_rxdesc_cid(d); /* always 0..7, no need to check */ | 737 | int cid = wil_rxdesc_cid(d); /* always 0..7, no need to check */ |
@@ -751,14 +768,15 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) | |||
751 | goto stats; | 768 | goto stats; |
752 | } | 769 | } |
753 | 770 | ||
754 | if (wdev->iftype == NL80211_IFTYPE_AP && !wil->ap_isolate) { | 771 | if (wdev->iftype == NL80211_IFTYPE_AP && !vif->ap_isolate) { |
755 | if (mcast) { | 772 | if (mcast) { |
756 | /* send multicast frames both to higher layers in | 773 | /* send multicast frames both to higher layers in |
757 | * local net stack and back to the wireless medium | 774 | * local net stack and back to the wireless medium |
758 | */ | 775 | */ |
759 | xmit_skb = skb_copy(skb, GFP_ATOMIC); | 776 | xmit_skb = skb_copy(skb, GFP_ATOMIC); |
760 | } else { | 777 | } else { |
761 | int xmit_cid = wil_find_cid(wil, eth->h_dest); | 778 | int xmit_cid = wil_find_cid(wil, vif->mid, |
779 | eth->h_dest); | ||
762 | 780 | ||
763 | if (xmit_cid >= 0) { | 781 | if (xmit_cid >= 0) { |
764 | /* The destination station is associated to | 782 | /* The destination station is associated to |
@@ -786,8 +804,8 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) | |||
786 | } | 804 | } |
787 | 805 | ||
788 | if (skb) { /* deliver to local stack */ | 806 | if (skb) { /* deliver to local stack */ |
789 | |||
790 | skb->protocol = eth_type_trans(skb, ndev); | 807 | skb->protocol = eth_type_trans(skb, ndev); |
808 | skb->dev = ndev; | ||
791 | rc = napi_gro_receive(&wil->napi_rx, skb); | 809 | rc = napi_gro_receive(&wil->napi_rx, skb); |
792 | wil_dbg_txrx(wil, "Rx complete %d bytes => %s\n", | 810 | wil_dbg_txrx(wil, "Rx complete %d bytes => %s\n", |
793 | len, gro_res_str[rc]); | 811 | len, gro_res_str[rc]); |
@@ -815,7 +833,8 @@ stats: | |||
815 | */ | 833 | */ |
816 | void wil_rx_handle(struct wil6210_priv *wil, int *quota) | 834 | void wil_rx_handle(struct wil6210_priv *wil, int *quota) |
817 | { | 835 | { |
818 | struct net_device *ndev = wil_to_ndev(wil); | 836 | struct net_device *ndev = wil->main_ndev; |
837 | struct wireless_dev *wdev = ndev->ieee80211_ptr; | ||
819 | struct vring *v = &wil->vring_rx; | 838 | struct vring *v = &wil->vring_rx; |
820 | struct sk_buff *skb; | 839 | struct sk_buff *skb; |
821 | 840 | ||
@@ -827,7 +846,8 @@ void wil_rx_handle(struct wil6210_priv *wil, int *quota) | |||
827 | while ((*quota > 0) && (NULL != (skb = wil_vring_reap_rx(wil, v)))) { | 846 | while ((*quota > 0) && (NULL != (skb = wil_vring_reap_rx(wil, v)))) { |
828 | (*quota)--; | 847 | (*quota)--; |
829 | 848 | ||
830 | if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { | 849 | /* monitor is currently supported on main interface only */ |
850 | if (wdev->iftype == NL80211_IFTYPE_MONITOR) { | ||
831 | skb->dev = ndev; | 851 | skb->dev = ndev; |
832 | skb_reset_mac_header(skb); | 852 | skb_reset_mac_header(skb); |
833 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 853 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
@@ -911,12 +931,14 @@ static inline void wil_tx_data_init(struct vring_tx_data *txdata) | |||
911 | txdata->agg_timeout = 0; | 931 | txdata->agg_timeout = 0; |
912 | txdata->agg_amsdu = 0; | 932 | txdata->agg_amsdu = 0; |
913 | txdata->addba_in_progress = false; | 933 | txdata->addba_in_progress = false; |
934 | txdata->mid = U8_MAX; | ||
914 | spin_unlock_bh(&txdata->lock); | 935 | spin_unlock_bh(&txdata->lock); |
915 | } | 936 | } |
916 | 937 | ||
917 | int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | 938 | int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size, |
918 | int cid, int tid) | 939 | int cid, int tid) |
919 | { | 940 | { |
941 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
920 | int rc; | 942 | int rc; |
921 | struct wmi_vring_cfg_cmd cmd = { | 943 | struct wmi_vring_cfg_cmd cmd = { |
922 | .action = cpu_to_le32(WMI_VRING_CMD_ADD), | 944 | .action = cpu_to_le32(WMI_VRING_CMD_ADD), |
@@ -966,9 +988,9 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | |||
966 | 988 | ||
967 | cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); | 989 | cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); |
968 | 990 | ||
969 | if (!wil->privacy) | 991 | if (!vif->privacy) |
970 | txdata->dot1x_open = true; | 992 | txdata->dot1x_open = true; |
971 | rc = wmi_call(wil, WMI_VRING_CFG_CMDID, &cmd, sizeof(cmd), | 993 | rc = wmi_call(wil, WMI_VRING_CFG_CMDID, vif->mid, &cmd, sizeof(cmd), |
972 | WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100); | 994 | WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100); |
973 | if (rc) | 995 | if (rc) |
974 | goto out_free; | 996 | goto out_free; |
@@ -982,6 +1004,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | |||
982 | 1004 | ||
983 | spin_lock_bh(&txdata->lock); | 1005 | spin_lock_bh(&txdata->lock); |
984 | vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); | 1006 | vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); |
1007 | txdata->mid = vif->mid; | ||
985 | txdata->enabled = 1; | 1008 | txdata->enabled = 1; |
986 | spin_unlock_bh(&txdata->lock); | 1009 | spin_unlock_bh(&txdata->lock); |
987 | 1010 | ||
@@ -1003,8 +1026,9 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | |||
1003 | return rc; | 1026 | return rc; |
1004 | } | 1027 | } |
1005 | 1028 | ||
1006 | int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size) | 1029 | int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size) |
1007 | { | 1030 | { |
1031 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1008 | int rc; | 1032 | int rc; |
1009 | struct wmi_bcast_vring_cfg_cmd cmd = { | 1033 | struct wmi_bcast_vring_cfg_cmd cmd = { |
1010 | .action = cpu_to_le32(WMI_VRING_CMD_ADD), | 1034 | .action = cpu_to_le32(WMI_VRING_CMD_ADD), |
@@ -1046,9 +1070,10 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size) | |||
1046 | 1070 | ||
1047 | cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); | 1071 | cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); |
1048 | 1072 | ||
1049 | if (!wil->privacy) | 1073 | if (!vif->privacy) |
1050 | txdata->dot1x_open = true; | 1074 | txdata->dot1x_open = true; |
1051 | rc = wmi_call(wil, WMI_BCAST_VRING_CFG_CMDID, &cmd, sizeof(cmd), | 1075 | rc = wmi_call(wil, WMI_BCAST_VRING_CFG_CMDID, vif->mid, |
1076 | &cmd, sizeof(cmd), | ||
1052 | WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100); | 1077 | WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100); |
1053 | if (rc) | 1078 | if (rc) |
1054 | goto out_free; | 1079 | goto out_free; |
@@ -1062,6 +1087,7 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size) | |||
1062 | 1087 | ||
1063 | spin_lock_bh(&txdata->lock); | 1088 | spin_lock_bh(&txdata->lock); |
1064 | vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); | 1089 | vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); |
1090 | txdata->mid = vif->mid; | ||
1065 | txdata->enabled = 1; | 1091 | txdata->enabled = 1; |
1066 | spin_unlock_bh(&txdata->lock); | 1092 | spin_unlock_bh(&txdata->lock); |
1067 | 1093 | ||
@@ -1091,6 +1117,7 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id) | |||
1091 | 1117 | ||
1092 | spin_lock_bh(&txdata->lock); | 1118 | spin_lock_bh(&txdata->lock); |
1093 | txdata->dot1x_open = false; | 1119 | txdata->dot1x_open = false; |
1120 | txdata->mid = U8_MAX; | ||
1094 | txdata->enabled = 0; /* no Tx can be in progress or start anew */ | 1121 | txdata->enabled = 0; /* no Tx can be in progress or start anew */ |
1095 | spin_unlock_bh(&txdata->lock); | 1122 | spin_unlock_bh(&txdata->lock); |
1096 | /* napi_synchronize waits for completion of the current NAPI but will | 1123 | /* napi_synchronize waits for completion of the current NAPI but will |
@@ -1108,11 +1135,12 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id) | |||
1108 | } | 1135 | } |
1109 | 1136 | ||
1110 | static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil, | 1137 | static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil, |
1138 | struct wil6210_vif *vif, | ||
1111 | struct sk_buff *skb) | 1139 | struct sk_buff *skb) |
1112 | { | 1140 | { |
1113 | int i; | 1141 | int i; |
1114 | struct ethhdr *eth = (void *)skb->data; | 1142 | struct ethhdr *eth = (void *)skb->data; |
1115 | int cid = wil_find_cid(wil, eth->h_dest); | 1143 | int cid = wil_find_cid(wil, vif->mid, eth->h_dest); |
1116 | 1144 | ||
1117 | if (cid < 0) | 1145 | if (cid < 0) |
1118 | return NULL; | 1146 | return NULL; |
@@ -1142,10 +1170,11 @@ static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil, | |||
1142 | return NULL; | 1170 | return NULL; |
1143 | } | 1171 | } |
1144 | 1172 | ||
1145 | static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | 1173 | static int wil_tx_vring(struct wil6210_priv *wil, struct wil6210_vif *vif, |
1146 | struct sk_buff *skb); | 1174 | struct vring *vring, struct sk_buff *skb); |
1147 | 1175 | ||
1148 | static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil, | 1176 | static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil, |
1177 | struct wil6210_vif *vif, | ||
1149 | struct sk_buff *skb) | 1178 | struct sk_buff *skb) |
1150 | { | 1179 | { |
1151 | struct vring *v; | 1180 | struct vring *v; |
@@ -1160,7 +1189,7 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil, | |||
1160 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { | 1189 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { |
1161 | v = &wil->vring_tx[i]; | 1190 | v = &wil->vring_tx[i]; |
1162 | txdata = &wil->vring_tx_data[i]; | 1191 | txdata = &wil->vring_tx_data[i]; |
1163 | if (!v->va || !txdata->enabled) | 1192 | if (!v->va || !txdata->enabled || txdata->mid != vif->mid) |
1164 | continue; | 1193 | continue; |
1165 | 1194 | ||
1166 | cid = wil->vring2cid_tid[i][0]; | 1195 | cid = wil->vring2cid_tid[i][0]; |
@@ -1193,11 +1222,12 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil, | |||
1193 | * - for PBSS | 1222 | * - for PBSS |
1194 | */ | 1223 | */ |
1195 | static struct vring *wil_find_tx_bcast_1(struct wil6210_priv *wil, | 1224 | static struct vring *wil_find_tx_bcast_1(struct wil6210_priv *wil, |
1225 | struct wil6210_vif *vif, | ||
1196 | struct sk_buff *skb) | 1226 | struct sk_buff *skb) |
1197 | { | 1227 | { |
1198 | struct vring *v; | 1228 | struct vring *v; |
1199 | struct vring_tx_data *txdata; | 1229 | struct vring_tx_data *txdata; |
1200 | int i = wil->bcast_vring; | 1230 | int i = vif->bcast_vring; |
1201 | 1231 | ||
1202 | if (i < 0) | 1232 | if (i < 0) |
1203 | return NULL; | 1233 | return NULL; |
@@ -1222,6 +1252,7 @@ static void wil_set_da_for_vring(struct wil6210_priv *wil, | |||
1222 | } | 1252 | } |
1223 | 1253 | ||
1224 | static struct vring *wil_find_tx_bcast_2(struct wil6210_priv *wil, | 1254 | static struct vring *wil_find_tx_bcast_2(struct wil6210_priv *wil, |
1255 | struct wil6210_vif *vif, | ||
1225 | struct sk_buff *skb) | 1256 | struct sk_buff *skb) |
1226 | { | 1257 | { |
1227 | struct vring *v, *v2; | 1258 | struct vring *v, *v2; |
@@ -1230,13 +1261,13 @@ static struct vring *wil_find_tx_bcast_2(struct wil6210_priv *wil, | |||
1230 | u8 cid; | 1261 | u8 cid; |
1231 | struct ethhdr *eth = (void *)skb->data; | 1262 | struct ethhdr *eth = (void *)skb->data; |
1232 | char *src = eth->h_source; | 1263 | char *src = eth->h_source; |
1233 | struct vring_tx_data *txdata; | 1264 | struct vring_tx_data *txdata, *txdata2; |
1234 | 1265 | ||
1235 | /* find 1-st vring eligible for data */ | 1266 | /* find 1-st vring eligible for data */ |
1236 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { | 1267 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { |
1237 | v = &wil->vring_tx[i]; | 1268 | v = &wil->vring_tx[i]; |
1238 | txdata = &wil->vring_tx_data[i]; | 1269 | txdata = &wil->vring_tx_data[i]; |
1239 | if (!v->va || !txdata->enabled) | 1270 | if (!v->va || !txdata->enabled || txdata->mid != vif->mid) |
1240 | continue; | 1271 | continue; |
1241 | 1272 | ||
1242 | cid = wil->vring2cid_tid[i][0]; | 1273 | cid = wil->vring2cid_tid[i][0]; |
@@ -1264,7 +1295,8 @@ found: | |||
1264 | /* find other active vrings and duplicate skb for each */ | 1295 | /* find other active vrings and duplicate skb for each */ |
1265 | for (i++; i < WIL6210_MAX_TX_RINGS; i++) { | 1296 | for (i++; i < WIL6210_MAX_TX_RINGS; i++) { |
1266 | v2 = &wil->vring_tx[i]; | 1297 | v2 = &wil->vring_tx[i]; |
1267 | if (!v2->va) | 1298 | txdata2 = &wil->vring_tx_data[i]; |
1299 | if (!v2->va || txdata2->mid != vif->mid) | ||
1268 | continue; | 1300 | continue; |
1269 | cid = wil->vring2cid_tid[i][0]; | 1301 | cid = wil->vring2cid_tid[i][0]; |
1270 | if (cid >= WIL6210_MAX_CID) /* skip BCAST */ | 1302 | if (cid >= WIL6210_MAX_CID) /* skip BCAST */ |
@@ -1280,7 +1312,7 @@ found: | |||
1280 | if (skb2) { | 1312 | if (skb2) { |
1281 | wil_dbg_txrx(wil, "BCAST DUP -> ring %d\n", i); | 1313 | wil_dbg_txrx(wil, "BCAST DUP -> ring %d\n", i); |
1282 | wil_set_da_for_vring(wil, skb2, i); | 1314 | wil_set_da_for_vring(wil, skb2, i); |
1283 | wil_tx_vring(wil, v2, skb2); | 1315 | wil_tx_vring(wil, vif, v2, skb2); |
1284 | } else { | 1316 | } else { |
1285 | wil_err(wil, "skb_copy failed\n"); | 1317 | wil_err(wil, "skb_copy failed\n"); |
1286 | } | 1318 | } |
@@ -1417,8 +1449,8 @@ static inline void wil_set_tx_desc_last_tso(volatile struct vring_tx_desc *d) | |||
1417 | DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_POS; | 1449 | DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_POS; |
1418 | } | 1450 | } |
1419 | 1451 | ||
1420 | static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring, | 1452 | static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct wil6210_vif *vif, |
1421 | struct sk_buff *skb) | 1453 | struct vring *vring, struct sk_buff *skb) |
1422 | { | 1454 | { |
1423 | struct device *dev = wil_to_dev(wil); | 1455 | struct device *dev = wil_to_dev(wil); |
1424 | 1456 | ||
@@ -1710,8 +1742,8 @@ err_exit: | |||
1710 | return rc; | 1742 | return rc; |
1711 | } | 1743 | } |
1712 | 1744 | ||
1713 | static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | 1745 | static int __wil_tx_vring(struct wil6210_priv *wil, struct wil6210_vif *vif, |
1714 | struct sk_buff *skb) | 1746 | struct vring *vring, struct sk_buff *skb) |
1715 | { | 1747 | { |
1716 | struct device *dev = wil_to_dev(wil); | 1748 | struct device *dev = wil_to_dev(wil); |
1717 | struct vring_tx_desc dd, *d = ⅆ | 1749 | struct vring_tx_desc dd, *d = ⅆ |
@@ -1725,7 +1757,7 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
1725 | uint i = swhead; | 1757 | uint i = swhead; |
1726 | dma_addr_t pa; | 1758 | dma_addr_t pa; |
1727 | int used; | 1759 | int used; |
1728 | bool mcast = (vring_index == wil->bcast_vring); | 1760 | bool mcast = (vring_index == vif->bcast_vring); |
1729 | uint len = skb_headlen(skb); | 1761 | uint len = skb_headlen(skb); |
1730 | 1762 | ||
1731 | wil_dbg_txrx(wil, "tx_vring: %d bytes to vring %d\n", skb->len, | 1763 | wil_dbg_txrx(wil, "tx_vring: %d bytes to vring %d\n", skb->len, |
@@ -1860,8 +1892,8 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
1860 | return -EINVAL; | 1892 | return -EINVAL; |
1861 | } | 1893 | } |
1862 | 1894 | ||
1863 | static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | 1895 | static int wil_tx_vring(struct wil6210_priv *wil, struct wil6210_vif *vif, |
1864 | struct sk_buff *skb) | 1896 | struct vring *vring, struct sk_buff *skb) |
1865 | { | 1897 | { |
1866 | int vring_index = vring - wil->vring_tx; | 1898 | int vring_index = vring - wil->vring_tx; |
1867 | struct vring_tx_data *txdata = &wil->vring_tx_data[vring_index]; | 1899 | struct vring_tx_data *txdata = &wil->vring_tx_data[vring_index]; |
@@ -1879,7 +1911,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
1879 | } | 1911 | } |
1880 | 1912 | ||
1881 | rc = (skb_is_gso(skb) ? __wil_tx_vring_tso : __wil_tx_vring) | 1913 | rc = (skb_is_gso(skb) ? __wil_tx_vring_tso : __wil_tx_vring) |
1882 | (wil, vring, skb); | 1914 | (wil, vif, vring, skb); |
1883 | 1915 | ||
1884 | spin_unlock(&txdata->lock); | 1916 | spin_unlock(&txdata->lock); |
1885 | 1917 | ||
@@ -1888,6 +1920,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
1888 | 1920 | ||
1889 | /** | 1921 | /** |
1890 | * Check status of tx vrings and stop/wake net queues if needed | 1922 | * Check status of tx vrings and stop/wake net queues if needed |
1923 | * It will start/stop net queues of a specific VIF net_device. | ||
1891 | * | 1924 | * |
1892 | * This function does one of two checks: | 1925 | * This function does one of two checks: |
1893 | * In case check_stop is true, will check if net queues need to be stopped. If | 1926 | * In case check_stop is true, will check if net queues need to be stopped. If |
@@ -1903,28 +1936,32 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
1903 | * availability and modified vring has high descriptor availability. | 1936 | * availability and modified vring has high descriptor availability. |
1904 | */ | 1937 | */ |
1905 | static inline void __wil_update_net_queues(struct wil6210_priv *wil, | 1938 | static inline void __wil_update_net_queues(struct wil6210_priv *wil, |
1939 | struct wil6210_vif *vif, | ||
1906 | struct vring *vring, | 1940 | struct vring *vring, |
1907 | bool check_stop) | 1941 | bool check_stop) |
1908 | { | 1942 | { |
1909 | int i; | 1943 | int i; |
1910 | 1944 | ||
1945 | if (unlikely(!vif)) | ||
1946 | return; | ||
1947 | |||
1911 | if (vring) | 1948 | if (vring) |
1912 | wil_dbg_txrx(wil, "vring %d, check_stop=%d, stopped=%d", | 1949 | wil_dbg_txrx(wil, "vring %d, mid %d, check_stop=%d, stopped=%d", |
1913 | (int)(vring - wil->vring_tx), check_stop, | 1950 | (int)(vring - wil->vring_tx), vif->mid, check_stop, |
1914 | wil->net_queue_stopped); | 1951 | vif->net_queue_stopped); |
1915 | else | 1952 | else |
1916 | wil_dbg_txrx(wil, "check_stop=%d, stopped=%d", | 1953 | wil_dbg_txrx(wil, "check_stop=%d, mid=%d, stopped=%d", |
1917 | check_stop, wil->net_queue_stopped); | 1954 | check_stop, vif->mid, vif->net_queue_stopped); |
1918 | 1955 | ||
1919 | if (check_stop == wil->net_queue_stopped) | 1956 | if (check_stop == vif->net_queue_stopped) |
1920 | /* net queues already in desired state */ | 1957 | /* net queues already in desired state */ |
1921 | return; | 1958 | return; |
1922 | 1959 | ||
1923 | if (check_stop) { | 1960 | if (check_stop) { |
1924 | if (!vring || unlikely(wil_vring_avail_low(vring))) { | 1961 | if (!vring || unlikely(wil_vring_avail_low(vring))) { |
1925 | /* not enough room in the vring */ | 1962 | /* not enough room in the vring */ |
1926 | netif_tx_stop_all_queues(wil_to_ndev(wil)); | 1963 | netif_tx_stop_all_queues(vif_to_ndev(vif)); |
1927 | wil->net_queue_stopped = true; | 1964 | vif->net_queue_stopped = true; |
1928 | wil_dbg_txrx(wil, "netif_tx_stop called\n"); | 1965 | wil_dbg_txrx(wil, "netif_tx_stop called\n"); |
1929 | } | 1966 | } |
1930 | return; | 1967 | return; |
@@ -1940,7 +1977,8 @@ static inline void __wil_update_net_queues(struct wil6210_priv *wil, | |||
1940 | struct vring *cur_vring = &wil->vring_tx[i]; | 1977 | struct vring *cur_vring = &wil->vring_tx[i]; |
1941 | struct vring_tx_data *txdata = &wil->vring_tx_data[i]; | 1978 | struct vring_tx_data *txdata = &wil->vring_tx_data[i]; |
1942 | 1979 | ||
1943 | if (!cur_vring->va || !txdata->enabled || cur_vring == vring) | 1980 | if (txdata->mid != vif->mid || !cur_vring->va || |
1981 | !txdata->enabled || cur_vring == vring) | ||
1944 | continue; | 1982 | continue; |
1945 | 1983 | ||
1946 | if (wil_vring_avail_low(cur_vring)) { | 1984 | if (wil_vring_avail_low(cur_vring)) { |
@@ -1953,30 +1991,31 @@ static inline void __wil_update_net_queues(struct wil6210_priv *wil, | |||
1953 | if (!vring || wil_vring_avail_high(vring)) { | 1991 | if (!vring || wil_vring_avail_high(vring)) { |
1954 | /* enough room in the vring */ | 1992 | /* enough room in the vring */ |
1955 | wil_dbg_txrx(wil, "calling netif_tx_wake\n"); | 1993 | wil_dbg_txrx(wil, "calling netif_tx_wake\n"); |
1956 | netif_tx_wake_all_queues(wil_to_ndev(wil)); | 1994 | netif_tx_wake_all_queues(vif_to_ndev(vif)); |
1957 | wil->net_queue_stopped = false; | 1995 | vif->net_queue_stopped = false; |
1958 | } | 1996 | } |
1959 | } | 1997 | } |
1960 | 1998 | ||
1961 | void wil_update_net_queues(struct wil6210_priv *wil, struct vring *vring, | 1999 | void wil_update_net_queues(struct wil6210_priv *wil, struct wil6210_vif *vif, |
1962 | bool check_stop) | 2000 | struct vring *vring, bool check_stop) |
1963 | { | 2001 | { |
1964 | spin_lock(&wil->net_queue_lock); | 2002 | spin_lock(&wil->net_queue_lock); |
1965 | __wil_update_net_queues(wil, vring, check_stop); | 2003 | __wil_update_net_queues(wil, vif, vring, check_stop); |
1966 | spin_unlock(&wil->net_queue_lock); | 2004 | spin_unlock(&wil->net_queue_lock); |
1967 | } | 2005 | } |
1968 | 2006 | ||
1969 | void wil_update_net_queues_bh(struct wil6210_priv *wil, struct vring *vring, | 2007 | void wil_update_net_queues_bh(struct wil6210_priv *wil, struct wil6210_vif *vif, |
1970 | bool check_stop) | 2008 | struct vring *vring, bool check_stop) |
1971 | { | 2009 | { |
1972 | spin_lock_bh(&wil->net_queue_lock); | 2010 | spin_lock_bh(&wil->net_queue_lock); |
1973 | __wil_update_net_queues(wil, vring, check_stop); | 2011 | __wil_update_net_queues(wil, vif, vring, check_stop); |
1974 | spin_unlock_bh(&wil->net_queue_lock); | 2012 | spin_unlock_bh(&wil->net_queue_lock); |
1975 | } | 2013 | } |
1976 | 2014 | ||
1977 | netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) | 2015 | netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) |
1978 | { | 2016 | { |
1979 | struct wil6210_priv *wil = ndev_to_wil(ndev); | 2017 | struct wil6210_vif *vif = ndev_to_vif(ndev); |
2018 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1980 | struct ethhdr *eth = (void *)skb->data; | 2019 | struct ethhdr *eth = (void *)skb->data; |
1981 | bool bcast = is_multicast_ether_addr(eth->h_dest); | 2020 | bool bcast = is_multicast_ether_addr(eth->h_dest); |
1982 | struct vring *vring; | 2021 | struct vring *vring; |
@@ -1991,49 +2030,50 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
1991 | } | 2030 | } |
1992 | goto drop; | 2031 | goto drop; |
1993 | } | 2032 | } |
1994 | if (unlikely(!test_bit(wil_status_fwconnected, wil->status))) { | 2033 | if (unlikely(!test_bit(wil_vif_fwconnected, vif->status))) { |
1995 | wil_dbg_ratelimited(wil, "FW not connected, packet dropped\n"); | 2034 | wil_dbg_ratelimited(wil, |
2035 | "VIF not connected, packet dropped\n"); | ||
1996 | goto drop; | 2036 | goto drop; |
1997 | } | 2037 | } |
1998 | if (unlikely(wil->wdev->iftype == NL80211_IFTYPE_MONITOR)) { | 2038 | if (unlikely(vif->wdev.iftype == NL80211_IFTYPE_MONITOR)) { |
1999 | wil_err(wil, "Xmit in monitor mode not supported\n"); | 2039 | wil_err(wil, "Xmit in monitor mode not supported\n"); |
2000 | goto drop; | 2040 | goto drop; |
2001 | } | 2041 | } |
2002 | pr_once_fw = false; | 2042 | pr_once_fw = false; |
2003 | 2043 | ||
2004 | /* find vring */ | 2044 | /* find vring */ |
2005 | if (wil->wdev->iftype == NL80211_IFTYPE_STATION && !wil->pbss) { | 2045 | if (vif->wdev.iftype == NL80211_IFTYPE_STATION && !vif->pbss) { |
2006 | /* in STA mode (ESS), all to same VRING (to AP) */ | 2046 | /* in STA mode (ESS), all to same VRING (to AP) */ |
2007 | vring = wil_find_tx_vring_sta(wil, skb); | 2047 | vring = wil_find_tx_vring_sta(wil, vif, skb); |
2008 | } else if (bcast) { | 2048 | } else if (bcast) { |
2009 | if (wil->pbss) | 2049 | if (vif->pbss) |
2010 | /* in pbss, no bcast VRING - duplicate skb in | 2050 | /* in pbss, no bcast VRING - duplicate skb in |
2011 | * all stations VRINGs | 2051 | * all stations VRINGs |
2012 | */ | 2052 | */ |
2013 | vring = wil_find_tx_bcast_2(wil, skb); | 2053 | vring = wil_find_tx_bcast_2(wil, vif, skb); |
2014 | else if (wil->wdev->iftype == NL80211_IFTYPE_AP) | 2054 | else if (vif->wdev.iftype == NL80211_IFTYPE_AP) |
2015 | /* AP has a dedicated bcast VRING */ | 2055 | /* AP has a dedicated bcast VRING */ |
2016 | vring = wil_find_tx_bcast_1(wil, skb); | 2056 | vring = wil_find_tx_bcast_1(wil, vif, skb); |
2017 | else | 2057 | else |
2018 | /* unexpected combination, fallback to duplicating | 2058 | /* unexpected combination, fallback to duplicating |
2019 | * the skb in all stations VRINGs | 2059 | * the skb in all stations VRINGs |
2020 | */ | 2060 | */ |
2021 | vring = wil_find_tx_bcast_2(wil, skb); | 2061 | vring = wil_find_tx_bcast_2(wil, vif, skb); |
2022 | } else { | 2062 | } else { |
2023 | /* unicast, find specific VRING by dest. address */ | 2063 | /* unicast, find specific VRING by dest. address */ |
2024 | vring = wil_find_tx_ucast(wil, skb); | 2064 | vring = wil_find_tx_ucast(wil, vif, skb); |
2025 | } | 2065 | } |
2026 | if (unlikely(!vring)) { | 2066 | if (unlikely(!vring)) { |
2027 | wil_dbg_txrx(wil, "No Tx VRING found for %pM\n", eth->h_dest); | 2067 | wil_dbg_txrx(wil, "No Tx VRING found for %pM\n", eth->h_dest); |
2028 | goto drop; | 2068 | goto drop; |
2029 | } | 2069 | } |
2030 | /* set up vring entry */ | 2070 | /* set up vring entry */ |
2031 | rc = wil_tx_vring(wil, vring, skb); | 2071 | rc = wil_tx_vring(wil, vif, vring, skb); |
2032 | 2072 | ||
2033 | switch (rc) { | 2073 | switch (rc) { |
2034 | case 0: | 2074 | case 0: |
2035 | /* shall we stop net queues? */ | 2075 | /* shall we stop net queues? */ |
2036 | wil_update_net_queues_bh(wil, vring, true); | 2076 | wil_update_net_queues_bh(wil, vif, vring, true); |
2037 | /* statistics will be updated on the tx_complete */ | 2077 | /* statistics will be updated on the tx_complete */ |
2038 | dev_kfree_skb_any(skb); | 2078 | dev_kfree_skb_any(skb); |
2039 | return NETDEV_TX_OK; | 2079 | return NETDEV_TX_OK; |
@@ -2072,9 +2112,10 @@ static inline void wil_consume_skb(struct sk_buff *skb, bool acked) | |||
2072 | * | 2112 | * |
2073 | * Safe to call from IRQ | 2113 | * Safe to call from IRQ |
2074 | */ | 2114 | */ |
2075 | int wil_tx_complete(struct wil6210_priv *wil, int ringid) | 2115 | int wil_tx_complete(struct wil6210_vif *vif, int ringid) |
2076 | { | 2116 | { |
2077 | struct net_device *ndev = wil_to_ndev(wil); | 2117 | struct wil6210_priv *wil = vif_to_wil(vif); |
2118 | struct net_device *ndev = vif_to_ndev(vif); | ||
2078 | struct device *dev = wil_to_dev(wil); | 2119 | struct device *dev = wil_to_dev(wil); |
2079 | struct vring *vring = &wil->vring_tx[ringid]; | 2120 | struct vring *vring = &wil->vring_tx[ringid]; |
2080 | struct vring_tx_data *txdata = &wil->vring_tx_data[ringid]; | 2121 | struct vring_tx_data *txdata = &wil->vring_tx_data[ringid]; |
@@ -2184,7 +2225,7 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid) | |||
2184 | 2225 | ||
2185 | /* shall we wake net queues? */ | 2226 | /* shall we wake net queues? */ |
2186 | if (done) | 2227 | if (done) |
2187 | wil_update_net_queues(wil, vring, false); | 2228 | wil_update_net_queues(wil, vif, vring, false); |
2188 | 2229 | ||
2189 | return done; | 2230 | return done; |
2190 | } | 2231 | } |
diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h index fcdffaa8251b..5f07717acc2c 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.h +++ b/drivers/net/wireless/ath/wil6210/txrx.h | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. |
3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -63,7 +64,9 @@ static inline void wil_desc_addr_set(struct vring_dma_addr *addr, | |||
63 | * [dword 1] | 64 | * [dword 1] |
64 | * bit 0.. 3 : pkt_mode:4 | 65 | * bit 0.. 3 : pkt_mode:4 |
65 | * bit 4 : pkt_mode_en:1 | 66 | * bit 4 : pkt_mode_en:1 |
66 | * bit 5..14 : reserved0:10 | 67 | * bit 5 : mac_id_en:1 |
68 | * bit 6..7 : mac_id:2 | ||
69 | * bit 8..14 : reserved0:7 | ||
67 | * bit 15 : ack_policy_en:1 | 70 | * bit 15 : ack_policy_en:1 |
68 | * bit 16..19 : dst_index:4 | 71 | * bit 16..19 : dst_index:4 |
69 | * bit 20 : dst_index_en:1 | 72 | * bit 20 : dst_index_en:1 |
@@ -132,6 +135,14 @@ struct vring_tx_mac { | |||
132 | #define MAC_CFG_DESC_TX_1_PKT_MODE_EN_LEN 1 | 135 | #define MAC_CFG_DESC_TX_1_PKT_MODE_EN_LEN 1 |
133 | #define MAC_CFG_DESC_TX_1_PKT_MODE_EN_MSK 0x10 | 136 | #define MAC_CFG_DESC_TX_1_PKT_MODE_EN_MSK 0x10 |
134 | 137 | ||
138 | #define MAC_CFG_DESC_TX_1_MAC_ID_EN_POS 5 | ||
139 | #define MAC_CFG_DESC_TX_1_MAC_ID_EN_LEN 1 | ||
140 | #define MAC_CFG_DESC_TX_1_MAC_ID_EN_MSK 0x20 | ||
141 | |||
142 | #define MAC_CFG_DESC_TX_1_MAC_ID_POS 6 | ||
143 | #define MAC_CFG_DESC_TX_1_MAC_ID_LEN 2 | ||
144 | #define MAC_CFG_DESC_TX_1_MAC_ID_MSK 0xc0 | ||
145 | |||
135 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_POS 15 | 146 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_POS 15 |
136 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_LEN 1 | 147 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_LEN 1 |
137 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_MSK 0x8000 | 148 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_MSK 0x8000 |
@@ -304,7 +315,7 @@ enum { | |||
304 | * bit 0.. 3 : tid:4 The QoS (b3-0) TID Field | 315 | * bit 0.. 3 : tid:4 The QoS (b3-0) TID Field |
305 | * bit 4.. 6 : cid:3 The Source index that was found during parsing the TA. | 316 | * bit 4.. 6 : cid:3 The Source index that was found during parsing the TA. |
306 | * This field is used to define the source of the packet | 317 | * This field is used to define the source of the packet |
307 | * bit 7 : reserved:1 | 318 | * bit 7 : MAC_id_valid:1, 1 if MAC virtual number is valid. |
308 | * bit 8.. 9 : mid:2 The MAC virtual number | 319 | * bit 8.. 9 : mid:2 The MAC virtual number |
309 | * bit 10..11 : frame_type:2 : The FC (b3-2) - MPDU Type | 320 | * bit 10..11 : frame_type:2 : The FC (b3-2) - MPDU Type |
310 | * (management, data, control and extension) | 321 | * (management, data, control and extension) |
@@ -395,6 +406,7 @@ struct vring_rx_mac { | |||
395 | #define RX_DMA_D0_CMD_DMA_EOP BIT(8) | 406 | #define RX_DMA_D0_CMD_DMA_EOP BIT(8) |
396 | #define RX_DMA_D0_CMD_DMA_RT BIT(9) /* always 1 */ | 407 | #define RX_DMA_D0_CMD_DMA_RT BIT(9) /* always 1 */ |
397 | #define RX_DMA_D0_CMD_DMA_IT BIT(10) /* interrupt */ | 408 | #define RX_DMA_D0_CMD_DMA_IT BIT(10) /* interrupt */ |
409 | #define RX_MAC_D0_MAC_ID_VALID BIT(7) | ||
398 | 410 | ||
399 | /* Error field */ | 411 | /* Error field */ |
400 | #define RX_DMA_ERROR_FCS BIT(0) | 412 | #define RX_DMA_ERROR_FCS BIT(0) |
@@ -451,7 +463,8 @@ static inline int wil_rxdesc_cid(struct vring_rx_desc *d) | |||
451 | 463 | ||
452 | static inline int wil_rxdesc_mid(struct vring_rx_desc *d) | 464 | static inline int wil_rxdesc_mid(struct vring_rx_desc *d) |
453 | { | 465 | { |
454 | return WIL_GET_BITS(d->mac.d0, 8, 9); | 466 | return (d->mac.d0 & RX_MAC_D0_MAC_ID_VALID) ? |
467 | WIL_GET_BITS(d->mac.d0, 8, 9) : 0; | ||
455 | } | 468 | } |
456 | 469 | ||
457 | static inline int wil_rxdesc_ftype(struct vring_rx_desc *d) | 470 | static inline int wil_rxdesc_ftype(struct vring_rx_desc *d) |
@@ -517,7 +530,8 @@ static inline struct vring_rx_desc *wil_skb_rxdesc(struct sk_buff *skb) | |||
517 | 530 | ||
518 | void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev); | 531 | void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev); |
519 | void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb); | 532 | void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb); |
520 | void wil_rx_bar(struct wil6210_priv *wil, u8 cid, u8 tid, u16 seq); | 533 | void wil_rx_bar(struct wil6210_priv *wil, struct wil6210_vif *vif, |
534 | u8 cid, u8 tid, u16 seq); | ||
521 | struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil, | 535 | struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil, |
522 | int size, u16 ssn); | 536 | int size, u16 ssn); |
523 | void wil_tid_ampdu_rx_free(struct wil6210_priv *wil, | 537 | void wil_tid_ampdu_rx_free(struct wil6210_priv *wil, |
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 0df2aada6659..f9c5155025bc 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/types.h> | 26 | #include <linux/types.h> |
27 | #include "wmi.h" | 27 | #include "wmi.h" |
28 | #include "wil_platform.h" | 28 | #include "wil_platform.h" |
29 | #include "fw.h" | ||
29 | 30 | ||
30 | extern bool no_fw_recovery; | 31 | extern bool no_fw_recovery; |
31 | extern unsigned int mtu_max; | 32 | extern unsigned int mtu_max; |
@@ -49,6 +50,11 @@ extern bool disable_ap_sme; | |||
49 | #define WIL_DEFAULT_BUS_REQUEST_KBPS 128000 /* ~1Gbps */ | 50 | #define WIL_DEFAULT_BUS_REQUEST_KBPS 128000 /* ~1Gbps */ |
50 | #define WIL_MAX_BUS_REQUEST_KBPS 800000 /* ~6.1Gbps */ | 51 | #define WIL_MAX_BUS_REQUEST_KBPS 800000 /* ~6.1Gbps */ |
51 | 52 | ||
53 | /* maximum number of virtual interfaces the driver supports | ||
54 | * (including the main interface) | ||
55 | */ | ||
56 | #define WIL_MAX_VIFS 4 | ||
57 | |||
52 | /** | 58 | /** |
53 | * extract bits [@b0:@b1] (inclusive) from the value @x | 59 | * extract bits [@b0:@b1] (inclusive) from the value @x |
54 | * it should be @b0 <= @b1, or result is incorrect | 60 | * it should be @b0 <= @b1, or result is incorrect |
@@ -463,13 +469,12 @@ struct vring_tx_data { | |||
463 | u16 agg_timeout; | 469 | u16 agg_timeout; |
464 | u8 agg_amsdu; | 470 | u8 agg_amsdu; |
465 | bool addba_in_progress; /* if set, agg_xxx is for request in progress */ | 471 | bool addba_in_progress; /* if set, agg_xxx is for request in progress */ |
472 | u8 mid; | ||
466 | spinlock_t lock; | 473 | spinlock_t lock; |
467 | }; | 474 | }; |
468 | 475 | ||
469 | enum { /* for wil6210_priv.status */ | 476 | enum { /* for wil6210_priv.status */ |
470 | wil_status_fwready = 0, /* FW operational */ | 477 | wil_status_fwready = 0, /* FW operational */ |
471 | wil_status_fwconnecting, | ||
472 | wil_status_fwconnected, | ||
473 | wil_status_dontscan, | 478 | wil_status_dontscan, |
474 | wil_status_mbox_ready, /* MBOX structures ready */ | 479 | wil_status_mbox_ready, /* MBOX structures ready */ |
475 | wil_status_irqen, /* interrupts enabled - for debug */ | 480 | wil_status_irqen, /* interrupts enabled - for debug */ |
@@ -541,7 +546,6 @@ struct wil_tid_crypto_rx { | |||
541 | struct wil_p2p_info { | 546 | struct wil_p2p_info { |
542 | struct ieee80211_channel listen_chan; | 547 | struct ieee80211_channel listen_chan; |
543 | u8 discovery_started; | 548 | u8 discovery_started; |
544 | u8 p2p_dev_started; | ||
545 | u64 cookie; | 549 | u64 cookie; |
546 | struct wireless_dev *pending_listen_wdev; | 550 | struct wireless_dev *pending_listen_wdev; |
547 | unsigned int listen_duration; | 551 | unsigned int listen_duration; |
@@ -584,6 +588,7 @@ struct wil_net_stats { | |||
584 | */ | 588 | */ |
585 | struct wil_sta_info { | 589 | struct wil_sta_info { |
586 | u8 addr[ETH_ALEN]; | 590 | u8 addr[ETH_ALEN]; |
591 | u8 mid; | ||
587 | enum wil_sta_status status; | 592 | enum wil_sta_status status; |
588 | struct wil_net_stats stats; | 593 | struct wil_net_stats stats; |
589 | /* Rx BACK */ | 594 | /* Rx BACK */ |
@@ -669,10 +674,44 @@ extern struct blink_on_off_time led_blink_time[WIL_LED_TIME_LAST]; | |||
669 | extern u8 led_id; | 674 | extern u8 led_id; |
670 | extern u8 led_polarity; | 675 | extern u8 led_polarity; |
671 | 676 | ||
677 | enum wil6210_vif_status { | ||
678 | wil_vif_fwconnecting, | ||
679 | wil_vif_fwconnected, | ||
680 | wil_vif_status_last /* keep last */ | ||
681 | }; | ||
682 | |||
683 | struct wil6210_vif { | ||
684 | struct wireless_dev wdev; | ||
685 | struct net_device *ndev; | ||
686 | struct wil6210_priv *wil; | ||
687 | u8 mid; | ||
688 | DECLARE_BITMAP(status, wil_vif_status_last); | ||
689 | u32 privacy; /* secure connection? */ | ||
690 | u16 channel; /* relevant in AP mode */ | ||
691 | u8 hidden_ssid; /* relevant in AP mode */ | ||
692 | u32 ap_isolate; /* no intra-BSS communication */ | ||
693 | bool pbss; | ||
694 | int bcast_vring; | ||
695 | struct cfg80211_bss *bss; /* connected bss, relevant in STA mode */ | ||
696 | int locally_generated_disc; /* relevant in STA mode */ | ||
697 | struct timer_list connect_timer; | ||
698 | struct work_struct disconnect_worker; | ||
699 | /* scan */ | ||
700 | struct cfg80211_scan_request *scan_request; | ||
701 | struct timer_list scan_timer; /* detect scan timeout */ | ||
702 | struct wil_p2p_info p2p; | ||
703 | /* keep alive */ | ||
704 | struct list_head probe_client_pending; | ||
705 | struct mutex probe_client_mutex; /* protect @probe_client_pending */ | ||
706 | struct work_struct probe_client_worker; | ||
707 | int net_queue_stopped; /* netif_tx_stop_all_queues invoked */ | ||
708 | }; | ||
709 | |||
672 | struct wil6210_priv { | 710 | struct wil6210_priv { |
673 | struct pci_dev *pdev; | 711 | struct pci_dev *pdev; |
674 | u32 bar_size; | 712 | u32 bar_size; |
675 | struct wireless_dev *wdev; | 713 | struct wiphy *wiphy; |
714 | struct net_device *main_ndev; | ||
676 | void __iomem *csr; | 715 | void __iomem *csr; |
677 | DECLARE_BITMAP(status, wil_status_last); | 716 | DECLARE_BITMAP(status, wil_status_last); |
678 | u8 fw_version[ETHTOOL_FWVERS_LEN]; | 717 | u8 fw_version[ETHTOOL_FWVERS_LEN]; |
@@ -686,21 +725,18 @@ struct wil6210_priv { | |||
686 | DECLARE_BITMAP(hw_capa, hw_capa_last); | 725 | DECLARE_BITMAP(hw_capa, hw_capa_last); |
687 | DECLARE_BITMAP(fw_capabilities, WMI_FW_CAPABILITY_MAX); | 726 | DECLARE_BITMAP(fw_capabilities, WMI_FW_CAPABILITY_MAX); |
688 | DECLARE_BITMAP(platform_capa, WIL_PLATFORM_CAPA_MAX); | 727 | DECLARE_BITMAP(platform_capa, WIL_PLATFORM_CAPA_MAX); |
689 | u8 n_mids; /* number of additional MIDs as reported by FW */ | ||
690 | u32 recovery_count; /* num of FW recovery attempts in a short time */ | 728 | u32 recovery_count; /* num of FW recovery attempts in a short time */ |
691 | u32 recovery_state; /* FW recovery state machine */ | 729 | u32 recovery_state; /* FW recovery state machine */ |
692 | unsigned long last_fw_recovery; /* jiffies of last fw recovery */ | 730 | unsigned long last_fw_recovery; /* jiffies of last fw recovery */ |
693 | wait_queue_head_t wq; /* for all wait_event() use */ | 731 | wait_queue_head_t wq; /* for all wait_event() use */ |
732 | u8 max_vifs; /* maximum number of interfaces, including main */ | ||
733 | struct wil6210_vif *vifs[WIL_MAX_VIFS]; | ||
734 | struct mutex vif_mutex; /* protects access to VIF entries */ | ||
735 | atomic_t connected_vifs; | ||
694 | /* profile */ | 736 | /* profile */ |
695 | struct cfg80211_chan_def monitor_chandef; | 737 | struct cfg80211_chan_def monitor_chandef; |
696 | u32 monitor_flags; | 738 | u32 monitor_flags; |
697 | u32 privacy; /* secure connection? */ | ||
698 | u8 hidden_ssid; /* relevant in AP mode */ | ||
699 | u16 channel; /* relevant in AP mode */ | ||
700 | int sinfo_gen; | 739 | int sinfo_gen; |
701 | u32 ap_isolate; /* no intra-BSS communication */ | ||
702 | struct cfg80211_bss *bss; /* connected bss, relevant in STA mode */ | ||
703 | int locally_generated_disc; /* relevant in STA mode */ | ||
704 | /* interrupt moderation */ | 740 | /* interrupt moderation */ |
705 | u32 tx_max_burst_duration; | 741 | u32 tx_max_burst_duration; |
706 | u32 tx_interframe_timeout; | 742 | u32 tx_interframe_timeout; |
@@ -715,15 +751,13 @@ struct wil6210_priv { | |||
715 | struct completion wmi_call; | 751 | struct completion wmi_call; |
716 | u16 wmi_seq; | 752 | u16 wmi_seq; |
717 | u16 reply_id; /**< wait for this WMI event */ | 753 | u16 reply_id; /**< wait for this WMI event */ |
754 | u8 reply_mid; | ||
718 | void *reply_buf; | 755 | void *reply_buf; |
719 | u16 reply_size; | 756 | u16 reply_size; |
720 | struct workqueue_struct *wmi_wq; /* for deferred calls */ | 757 | struct workqueue_struct *wmi_wq; /* for deferred calls */ |
721 | struct work_struct wmi_event_worker; | 758 | struct work_struct wmi_event_worker; |
722 | struct workqueue_struct *wq_service; | 759 | struct workqueue_struct *wq_service; |
723 | struct work_struct disconnect_worker; | ||
724 | struct work_struct fw_error_worker; /* for FW error recovery */ | 760 | struct work_struct fw_error_worker; /* for FW error recovery */ |
725 | struct timer_list connect_timer; | ||
726 | struct timer_list scan_timer; /* detect scan timeout */ | ||
727 | struct list_head pending_wmi_ev; | 761 | struct list_head pending_wmi_ev; |
728 | /* | 762 | /* |
729 | * protect pending_wmi_ev | 763 | * protect pending_wmi_ev |
@@ -732,13 +766,10 @@ struct wil6210_priv { | |||
732 | */ | 766 | */ |
733 | spinlock_t wmi_ev_lock; | 767 | spinlock_t wmi_ev_lock; |
734 | spinlock_t net_queue_lock; /* guarding stop/wake netif queue */ | 768 | spinlock_t net_queue_lock; /* guarding stop/wake netif queue */ |
735 | int net_queue_stopped; /* netif_tx_stop_all_queues invoked */ | ||
736 | struct napi_struct napi_rx; | 769 | struct napi_struct napi_rx; |
737 | struct napi_struct napi_tx; | 770 | struct napi_struct napi_tx; |
738 | /* keep alive */ | 771 | struct net_device napi_ndev; /* dummy net_device serving all VIFs */ |
739 | struct list_head probe_client_pending; | 772 | |
740 | struct mutex probe_client_mutex; /* protect @probe_client_pending */ | ||
741 | struct work_struct probe_client_worker; | ||
742 | /* DMA related */ | 773 | /* DMA related */ |
743 | struct vring vring_rx; | 774 | struct vring vring_rx; |
744 | unsigned int rx_buf_len; | 775 | unsigned int rx_buf_len; |
@@ -746,11 +777,8 @@ struct wil6210_priv { | |||
746 | struct vring_tx_data vring_tx_data[WIL6210_MAX_TX_RINGS]; | 777 | struct vring_tx_data vring_tx_data[WIL6210_MAX_TX_RINGS]; |
747 | u8 vring2cid_tid[WIL6210_MAX_TX_RINGS][2]; /* [0] - CID, [1] - TID */ | 778 | u8 vring2cid_tid[WIL6210_MAX_TX_RINGS][2]; /* [0] - CID, [1] - TID */ |
748 | struct wil_sta_info sta[WIL6210_MAX_CID]; | 779 | struct wil_sta_info sta[WIL6210_MAX_CID]; |
749 | int bcast_vring; | ||
750 | u32 vring_idle_trsh; /* HW fetches up to 16 descriptors at once */ | 780 | u32 vring_idle_trsh; /* HW fetches up to 16 descriptors at once */ |
751 | u32 dma_addr_size; /* indicates dma addr size */ | 781 | u32 dma_addr_size; /* indicates dma addr size */ |
752 | /* scan */ | ||
753 | struct cfg80211_scan_request *scan_request; | ||
754 | 782 | ||
755 | struct mutex mutex; /* for wil6210_priv access in wil_{up|down} */ | 783 | struct mutex mutex; /* for wil6210_priv access in wil_{up|down} */ |
756 | /* statistics */ | 784 | /* statistics */ |
@@ -770,13 +798,10 @@ struct wil6210_priv { | |||
770 | 798 | ||
771 | struct pmc_ctx pmc; | 799 | struct pmc_ctx pmc; |
772 | 800 | ||
773 | bool pbss; | 801 | u8 p2p_dev_started; |
774 | |||
775 | struct wil_p2p_info p2p; | ||
776 | 802 | ||
777 | /* P2P_DEVICE vif */ | 803 | /* P2P_DEVICE vif */ |
778 | struct wireless_dev *p2p_wdev; | 804 | struct wireless_dev *p2p_wdev; |
779 | struct mutex p2p_wdev_mutex; /* protect @p2p_wdev and @scan_request */ | ||
780 | struct wireless_dev *radio_wdev; | 805 | struct wireless_dev *radio_wdev; |
781 | 806 | ||
782 | /* High Access Latency Policy voting */ | 807 | /* High Access Latency Policy voting */ |
@@ -798,13 +823,35 @@ struct wil6210_priv { | |||
798 | u32 iccm_base; | 823 | u32 iccm_base; |
799 | }; | 824 | }; |
800 | 825 | ||
801 | #define wil_to_wiphy(i) (i->wdev->wiphy) | 826 | #define wil_to_wiphy(i) (i->wiphy) |
802 | #define wil_to_dev(i) (wiphy_dev(wil_to_wiphy(i))) | 827 | #define wil_to_dev(i) (wiphy_dev(wil_to_wiphy(i))) |
803 | #define wiphy_to_wil(w) (struct wil6210_priv *)(wiphy_priv(w)) | 828 | #define wiphy_to_wil(w) (struct wil6210_priv *)(wiphy_priv(w)) |
804 | #define wil_to_wdev(i) (i->wdev) | ||
805 | #define wdev_to_wil(w) (struct wil6210_priv *)(wdev_priv(w)) | 829 | #define wdev_to_wil(w) (struct wil6210_priv *)(wdev_priv(w)) |
806 | #define wil_to_ndev(i) (wil_to_wdev(i)->netdev) | ||
807 | #define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr)) | 830 | #define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr)) |
831 | #define ndev_to_vif(n) (struct wil6210_vif *)(netdev_priv(n)) | ||
832 | #define vif_to_wil(v) (v->wil) | ||
833 | #define vif_to_ndev(v) (v->ndev) | ||
834 | #define vif_to_wdev(v) (&v->wdev) | ||
835 | |||
836 | static inline struct wil6210_vif *wdev_to_vif(struct wil6210_priv *wil, | ||
837 | struct wireless_dev *wdev) | ||
838 | { | ||
839 | /* main interface is shared with P2P device */ | ||
840 | if (wdev == wil->p2p_wdev) | ||
841 | return ndev_to_vif(wil->main_ndev); | ||
842 | else | ||
843 | return container_of(wdev, struct wil6210_vif, wdev); | ||
844 | } | ||
845 | |||
846 | static inline struct wireless_dev * | ||
847 | vif_to_radio_wdev(struct wil6210_priv *wil, struct wil6210_vif *vif) | ||
848 | { | ||
849 | /* main interface is shared with P2P device */ | ||
850 | if (vif->mid) | ||
851 | return vif_to_wdev(vif); | ||
852 | else | ||
853 | return wil->radio_wdev; | ||
854 | } | ||
808 | 855 | ||
809 | __printf(2, 3) | 856 | __printf(2, 3) |
810 | void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...); | 857 | void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...); |
@@ -817,7 +864,7 @@ void __wil_info(struct wil6210_priv *wil, const char *fmt, ...); | |||
817 | __printf(2, 3) | 864 | __printf(2, 3) |
818 | void wil_dbg_ratelimited(const struct wil6210_priv *wil, const char *fmt, ...); | 865 | void wil_dbg_ratelimited(const struct wil6210_priv *wil, const char *fmt, ...); |
819 | #define wil_dbg(wil, fmt, arg...) do { \ | 866 | #define wil_dbg(wil, fmt, arg...) do { \ |
820 | netdev_dbg(wil_to_ndev(wil), fmt, ##arg); \ | 867 | netdev_dbg(wil->main_ndev, fmt, ##arg); \ |
821 | wil_dbg_trace(wil, fmt, ##arg); \ | 868 | wil_dbg_trace(wil, fmt, ##arg); \ |
822 | } while (0) | 869 | } while (0) |
823 | 870 | ||
@@ -900,9 +947,18 @@ void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, | |||
900 | void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, | 947 | void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, |
901 | size_t count); | 948 | size_t count); |
902 | 949 | ||
950 | struct wil6210_vif * | ||
951 | wil_vif_alloc(struct wil6210_priv *wil, const char *name, | ||
952 | unsigned char name_assign_type, enum nl80211_iftype iftype); | ||
953 | void wil_vif_free(struct wil6210_vif *vif); | ||
903 | void *wil_if_alloc(struct device *dev); | 954 | void *wil_if_alloc(struct device *dev); |
955 | bool wil_has_other_active_ifaces(struct wil6210_priv *wil, | ||
956 | struct net_device *ndev, bool up, bool ok); | ||
957 | bool wil_has_active_ifaces(struct wil6210_priv *wil, bool up, bool ok); | ||
904 | void wil_if_free(struct wil6210_priv *wil); | 958 | void wil_if_free(struct wil6210_priv *wil); |
959 | int wil_vif_add(struct wil6210_priv *wil, struct wil6210_vif *vif); | ||
905 | int wil_if_add(struct wil6210_priv *wil); | 960 | int wil_if_add(struct wil6210_priv *wil); |
961 | void wil_vif_remove(struct wil6210_priv *wil, u8 mid); | ||
906 | void wil_if_remove(struct wil6210_priv *wil); | 962 | void wil_if_remove(struct wil6210_priv *wil); |
907 | int wil_priv_init(struct wil6210_priv *wil); | 963 | int wil_priv_init(struct wil6210_priv *wil); |
908 | void wil_priv_deinit(struct wil6210_priv *wil); | 964 | void wil_priv_deinit(struct wil6210_priv *wil); |
@@ -918,7 +974,7 @@ int wil_down(struct wil6210_priv *wil); | |||
918 | int __wil_down(struct wil6210_priv *wil); | 974 | int __wil_down(struct wil6210_priv *wil); |
919 | void wil_refresh_fw_capabilities(struct wil6210_priv *wil); | 975 | void wil_refresh_fw_capabilities(struct wil6210_priv *wil); |
920 | void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r); | 976 | void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r); |
921 | int wil_find_cid(struct wil6210_priv *wil, const u8 *mac); | 977 | int wil_find_cid(struct wil6210_priv *wil, u8 mid, const u8 *mac); |
922 | void wil_set_ethtoolops(struct net_device *ndev); | 978 | void wil_set_ethtoolops(struct net_device *ndev); |
923 | 979 | ||
924 | struct fw_map *wil_find_fw_mapping(const char *section); | 980 | struct fw_map *wil_find_fw_mapping(const char *section); |
@@ -927,40 +983,45 @@ void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr); | |||
927 | void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr); | 983 | void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr); |
928 | int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, | 984 | int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, |
929 | struct wil6210_mbox_hdr *hdr); | 985 | struct wil6210_mbox_hdr *hdr); |
930 | int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len); | 986 | int wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len); |
931 | void wmi_recv_cmd(struct wil6210_priv *wil); | 987 | void wmi_recv_cmd(struct wil6210_priv *wil); |
932 | int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, | 988 | int wmi_call(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len, |
933 | u16 reply_id, void *reply, u8 reply_size, int to_msec); | 989 | u16 reply_id, void *reply, u8 reply_size, int to_msec); |
934 | void wmi_event_worker(struct work_struct *work); | 990 | void wmi_event_worker(struct work_struct *work); |
935 | void wmi_event_flush(struct wil6210_priv *wil); | 991 | void wmi_event_flush(struct wil6210_priv *wil); |
936 | int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid); | 992 | int wmi_set_ssid(struct wil6210_vif *vif, u8 ssid_len, const void *ssid); |
937 | int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid); | 993 | int wmi_get_ssid(struct wil6210_vif *vif, u8 *ssid_len, void *ssid); |
938 | int wmi_set_channel(struct wil6210_priv *wil, int channel); | 994 | int wmi_set_channel(struct wil6210_priv *wil, int channel); |
939 | int wmi_get_channel(struct wil6210_priv *wil, int *channel); | 995 | int wmi_get_channel(struct wil6210_priv *wil, int *channel); |
940 | int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index, | 996 | int wmi_del_cipher_key(struct wil6210_vif *vif, u8 key_index, |
941 | const void *mac_addr, int key_usage); | 997 | const void *mac_addr, int key_usage); |
942 | int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, | 998 | int wmi_add_cipher_key(struct wil6210_vif *vif, u8 key_index, |
943 | const void *mac_addr, int key_len, const void *key, | 999 | const void *mac_addr, int key_len, const void *key, |
944 | int key_usage); | 1000 | int key_usage); |
945 | int wmi_echo(struct wil6210_priv *wil); | 1001 | int wmi_echo(struct wil6210_priv *wil); |
946 | int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie); | 1002 | int wmi_set_ie(struct wil6210_vif *vif, u8 type, u16 ie_len, const void *ie); |
947 | int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring); | 1003 | int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring); |
948 | int wmi_rxon(struct wil6210_priv *wil, bool on); | 1004 | int wmi_rxon(struct wil6210_priv *wil, bool on); |
949 | int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r); | 1005 | int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r); |
950 | int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, | 1006 | int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac, |
951 | u16 reason, bool full_disconnect, bool del_sta); | 1007 | u16 reason, bool full_disconnect, bool del_sta); |
952 | int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout); | 1008 | int wmi_addba(struct wil6210_priv *wil, u8 mid, |
953 | int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason); | 1009 | u8 ringid, u8 size, u16 timeout); |
954 | int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason); | 1010 | int wmi_delba_tx(struct wil6210_priv *wil, u8 mid, u8 ringid, u16 reason); |
955 | int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token, | 1011 | int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cidxtid, u16 reason); |
1012 | int wmi_addba_rx_resp(struct wil6210_priv *wil, | ||
1013 | u8 mid, u8 cid, u8 tid, u8 token, | ||
956 | u16 status, bool amsdu, u16 agg_wsize, u16 timeout); | 1014 | u16 status, bool amsdu, u16 agg_wsize, u16 timeout); |
957 | int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil, | 1015 | int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil, |
958 | enum wmi_ps_profile_type ps_profile); | 1016 | enum wmi_ps_profile_type ps_profile); |
959 | int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short); | 1017 | int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short); |
960 | int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short); | 1018 | int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short); |
961 | int wmi_new_sta(struct wil6210_priv *wil, const u8 *mac, u8 aid); | 1019 | int wmi_new_sta(struct wil6210_vif *vif, const u8 *mac, u8 aid); |
962 | int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid, | 1020 | int wmi_port_allocate(struct wil6210_priv *wil, u8 mid, |
963 | u8 dialog_token, __le16 ba_param_set, | 1021 | const u8 *mac, enum nl80211_iftype iftype); |
1022 | int wmi_port_delete(struct wil6210_priv *wil, u8 mid); | ||
1023 | int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid, | ||
1024 | u8 cidxtid, u8 dialog_token, __le16 ba_param_set, | ||
964 | __le16 ba_timeout, __le16 ba_seq_ctrl); | 1025 | __le16 ba_timeout, __le16 ba_seq_ctrl); |
965 | int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize); | 1026 | int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize); |
966 | 1027 | ||
@@ -976,28 +1037,31 @@ void wil6210_mask_halp(struct wil6210_priv *wil); | |||
976 | 1037 | ||
977 | /* P2P */ | 1038 | /* P2P */ |
978 | bool wil_p2p_is_social_scan(struct cfg80211_scan_request *request); | 1039 | bool wil_p2p_is_social_scan(struct cfg80211_scan_request *request); |
979 | void wil_p2p_discovery_timer_fn(struct timer_list *t); | 1040 | int wil_p2p_search(struct wil6210_vif *vif, |
980 | int wil_p2p_search(struct wil6210_priv *wil, | ||
981 | struct cfg80211_scan_request *request); | 1041 | struct cfg80211_scan_request *request); |
982 | int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev, | 1042 | int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev, |
983 | unsigned int duration, struct ieee80211_channel *chan, | 1043 | unsigned int duration, struct ieee80211_channel *chan, |
984 | u64 *cookie); | 1044 | u64 *cookie); |
985 | u8 wil_p2p_stop_discovery(struct wil6210_priv *wil); | 1045 | u8 wil_p2p_stop_discovery(struct wil6210_vif *vif); |
986 | int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie); | 1046 | int wil_p2p_cancel_listen(struct wil6210_vif *vif, u64 cookie); |
987 | void wil_p2p_listen_expired(struct work_struct *work); | 1047 | void wil_p2p_listen_expired(struct work_struct *work); |
988 | void wil_p2p_search_expired(struct work_struct *work); | 1048 | void wil_p2p_search_expired(struct work_struct *work); |
989 | void wil_p2p_stop_radio_operations(struct wil6210_priv *wil); | 1049 | void wil_p2p_stop_radio_operations(struct wil6210_priv *wil); |
990 | void wil_p2p_delayed_listen_work(struct work_struct *work); | 1050 | void wil_p2p_delayed_listen_work(struct work_struct *work); |
991 | 1051 | ||
992 | /* WMI for P2P */ | 1052 | /* WMI for P2P */ |
993 | int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi); | 1053 | int wmi_p2p_cfg(struct wil6210_vif *vif, int channel, int bi); |
994 | int wmi_start_listen(struct wil6210_priv *wil); | 1054 | int wmi_start_listen(struct wil6210_vif *vif); |
995 | int wmi_start_search(struct wil6210_priv *wil); | 1055 | int wmi_start_search(struct wil6210_vif *vif); |
996 | int wmi_stop_discovery(struct wil6210_priv *wil); | 1056 | int wmi_stop_discovery(struct wil6210_vif *vif); |
997 | 1057 | ||
998 | int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | 1058 | int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, |
999 | struct cfg80211_mgmt_tx_params *params, | 1059 | struct cfg80211_mgmt_tx_params *params, |
1000 | u64 *cookie); | 1060 | u64 *cookie); |
1061 | int wil_cfg80211_iface_combinations_from_fw( | ||
1062 | struct wil6210_priv *wil, | ||
1063 | const struct wil_fw_record_concurrency *conc); | ||
1064 | int wil_vif_prepare_stop(struct wil6210_vif *vif); | ||
1001 | 1065 | ||
1002 | #if defined(CONFIG_WIL6210_DEBUGFS) | 1066 | #if defined(CONFIG_WIL6210_DEBUGFS) |
1003 | int wil6210_debugfs_init(struct wil6210_priv *wil); | 1067 | int wil6210_debugfs_init(struct wil6210_priv *wil); |
@@ -1007,44 +1071,47 @@ static inline int wil6210_debugfs_init(struct wil6210_priv *wil) { return 0; } | |||
1007 | static inline void wil6210_debugfs_remove(struct wil6210_priv *wil) {} | 1071 | static inline void wil6210_debugfs_remove(struct wil6210_priv *wil) {} |
1008 | #endif | 1072 | #endif |
1009 | 1073 | ||
1010 | int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid, | 1074 | int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid, |
1011 | struct station_info *sinfo); | 1075 | struct station_info *sinfo); |
1012 | 1076 | ||
1013 | struct wireless_dev *wil_cfg80211_init(struct device *dev); | 1077 | struct wil6210_priv *wil_cfg80211_init(struct device *dev); |
1014 | void wil_wdev_free(struct wil6210_priv *wil); | 1078 | void wil_cfg80211_deinit(struct wil6210_priv *wil); |
1015 | void wil_p2p_wdev_free(struct wil6210_priv *wil); | 1079 | void wil_p2p_wdev_free(struct wil6210_priv *wil); |
1016 | 1080 | ||
1017 | int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); | 1081 | int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); |
1018 | int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, | 1082 | int wmi_pcp_start(struct wil6210_vif *vif, int bi, u8 wmi_nettype, u8 chan, |
1019 | u8 chan, u8 hidden_ssid, u8 is_go); | 1083 | u8 hidden_ssid, u8 is_go); |
1020 | int wmi_pcp_stop(struct wil6210_priv *wil); | 1084 | int wmi_pcp_stop(struct wil6210_vif *vif); |
1021 | int wmi_led_cfg(struct wil6210_priv *wil, bool enable); | 1085 | int wmi_led_cfg(struct wil6210_priv *wil, bool enable); |
1022 | int wmi_abort_scan(struct wil6210_priv *wil); | 1086 | int wmi_abort_scan(struct wil6210_vif *vif); |
1023 | void wil_abort_scan(struct wil6210_priv *wil, bool sync); | 1087 | void wil_abort_scan(struct wil6210_vif *vif, bool sync); |
1088 | void wil_abort_scan_all_vifs(struct wil6210_priv *wil, bool sync); | ||
1024 | void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps); | 1089 | void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps); |
1025 | void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, | 1090 | void wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, |
1026 | u16 reason_code, bool from_event); | 1091 | u16 reason_code, bool from_event); |
1027 | void wil_probe_client_flush(struct wil6210_priv *wil); | 1092 | void wil_probe_client_flush(struct wil6210_vif *vif); |
1028 | void wil_probe_client_worker(struct work_struct *work); | 1093 | void wil_probe_client_worker(struct work_struct *work); |
1094 | void wil_disconnect_worker(struct work_struct *work); | ||
1029 | 1095 | ||
1030 | int wil_rx_init(struct wil6210_priv *wil, u16 size); | 1096 | int wil_rx_init(struct wil6210_priv *wil, u16 size); |
1031 | void wil_rx_fini(struct wil6210_priv *wil); | 1097 | void wil_rx_fini(struct wil6210_priv *wil); |
1032 | 1098 | ||
1033 | /* TX API */ | 1099 | /* TX API */ |
1034 | int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | 1100 | int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size, |
1035 | int cid, int tid); | 1101 | int cid, int tid); |
1036 | void wil_vring_fini_tx(struct wil6210_priv *wil, int id); | 1102 | void wil_vring_fini_tx(struct wil6210_priv *wil, int id); |
1037 | int wil_tx_init(struct wil6210_priv *wil, int cid); | 1103 | int wil_tx_init(struct wil6210_vif *vif, int cid); |
1038 | int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size); | 1104 | int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size); |
1039 | int wil_bcast_init(struct wil6210_priv *wil); | 1105 | int wil_bcast_init(struct wil6210_vif *vif); |
1040 | void wil_bcast_fini(struct wil6210_priv *wil); | 1106 | void wil_bcast_fini(struct wil6210_vif *vif); |
1041 | 1107 | void wil_bcast_fini_all(struct wil6210_priv *wil); | |
1042 | void wil_update_net_queues(struct wil6210_priv *wil, struct vring *vring, | 1108 | |
1043 | bool should_stop); | 1109 | void wil_update_net_queues(struct wil6210_priv *wil, struct wil6210_vif *vif, |
1044 | void wil_update_net_queues_bh(struct wil6210_priv *wil, struct vring *vring, | 1110 | struct vring *vring, bool should_stop); |
1045 | bool check_stop); | 1111 | void wil_update_net_queues_bh(struct wil6210_priv *wil, struct wil6210_vif *vif, |
1112 | struct vring *vring, bool check_stop); | ||
1046 | netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev); | 1113 | netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev); |
1047 | int wil_tx_complete(struct wil6210_priv *wil, int ringid); | 1114 | int wil_tx_complete(struct wil6210_vif *vif, int ringid); |
1048 | void wil6210_unmask_irq_tx(struct wil6210_priv *wil); | 1115 | void wil6210_unmask_irq_tx(struct wil6210_priv *wil); |
1049 | 1116 | ||
1050 | /* RX API */ | 1117 | /* RX API */ |
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index b31e2514f8c2..a3dda9a97c1f 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c | |||
@@ -341,6 +341,10 @@ static const char *cmdid2name(u16 cmdid) | |||
341 | return "WMI_GET_PCP_CHANNEL_CMD"; | 341 | return "WMI_GET_PCP_CHANNEL_CMD"; |
342 | case WMI_P2P_CFG_CMDID: | 342 | case WMI_P2P_CFG_CMDID: |
343 | return "WMI_P2P_CFG_CMD"; | 343 | return "WMI_P2P_CFG_CMD"; |
344 | case WMI_PORT_ALLOCATE_CMDID: | ||
345 | return "WMI_PORT_ALLOCATE_CMD"; | ||
346 | case WMI_PORT_DELETE_CMDID: | ||
347 | return "WMI_PORT_DELETE_CMD"; | ||
344 | case WMI_START_LISTEN_CMDID: | 348 | case WMI_START_LISTEN_CMDID: |
345 | return "WMI_START_LISTEN_CMD"; | 349 | return "WMI_START_LISTEN_CMD"; |
346 | case WMI_START_SEARCH_CMDID: | 350 | case WMI_START_SEARCH_CMDID: |
@@ -479,6 +483,10 @@ static const char *eventid2name(u16 eventid) | |||
479 | return "WMI_GET_PCP_CHANNEL_EVENT"; | 483 | return "WMI_GET_PCP_CHANNEL_EVENT"; |
480 | case WMI_P2P_CFG_DONE_EVENTID: | 484 | case WMI_P2P_CFG_DONE_EVENTID: |
481 | return "WMI_P2P_CFG_DONE_EVENT"; | 485 | return "WMI_P2P_CFG_DONE_EVENT"; |
486 | case WMI_PORT_ALLOCATED_EVENTID: | ||
487 | return "WMI_PORT_ALLOCATED_EVENT"; | ||
488 | case WMI_PORT_DELETED_EVENTID: | ||
489 | return "WMI_PORT_DELETED_EVENT"; | ||
482 | case WMI_LISTEN_STARTED_EVENTID: | 490 | case WMI_LISTEN_STARTED_EVENTID: |
483 | return "WMI_LISTEN_STARTED_EVENT"; | 491 | return "WMI_LISTEN_STARTED_EVENT"; |
484 | case WMI_SEARCH_STARTED_EVENTID: | 492 | case WMI_SEARCH_STARTED_EVENTID: |
@@ -516,7 +524,8 @@ static const char *eventid2name(u16 eventid) | |||
516 | } | 524 | } |
517 | } | 525 | } |
518 | 526 | ||
519 | static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) | 527 | static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid, |
528 | void *buf, u16 len) | ||
520 | { | 529 | { |
521 | struct { | 530 | struct { |
522 | struct wil6210_mbox_hdr hdr; | 531 | struct wil6210_mbox_hdr hdr; |
@@ -528,7 +537,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) | |||
528 | .len = cpu_to_le16(sizeof(cmd.wmi) + len), | 537 | .len = cpu_to_le16(sizeof(cmd.wmi) + len), |
529 | }, | 538 | }, |
530 | .wmi = { | 539 | .wmi = { |
531 | .mid = 0, | 540 | .mid = mid, |
532 | .command_id = cpu_to_le16(cmdid), | 541 | .command_id = cpu_to_le16(cmdid), |
533 | }, | 542 | }, |
534 | }; | 543 | }; |
@@ -612,8 +621,8 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) | |||
612 | } | 621 | } |
613 | cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq); | 622 | cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq); |
614 | /* set command */ | 623 | /* set command */ |
615 | wil_dbg_wmi(wil, "sending %s (0x%04x) [%d]\n", | 624 | wil_dbg_wmi(wil, "sending %s (0x%04x) [%d] mid %d\n", |
616 | cmdid2name(cmdid), cmdid, len); | 625 | cmdid2name(cmdid), cmdid, len, mid); |
617 | wil_hex_dump_wmi("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd, | 626 | wil_hex_dump_wmi("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd, |
618 | sizeof(cmd), true); | 627 | sizeof(cmd), true); |
619 | wil_hex_dump_wmi("cmd ", DUMP_PREFIX_OFFSET, 16, 1, buf, | 628 | wil_hex_dump_wmi("cmd ", DUMP_PREFIX_OFFSET, 16, 1, buf, |
@@ -637,31 +646,34 @@ out: | |||
637 | return rc; | 646 | return rc; |
638 | } | 647 | } |
639 | 648 | ||
640 | int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) | 649 | int wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len) |
641 | { | 650 | { |
642 | int rc; | 651 | int rc; |
643 | 652 | ||
644 | mutex_lock(&wil->wmi_mutex); | 653 | mutex_lock(&wil->wmi_mutex); |
645 | rc = __wmi_send(wil, cmdid, buf, len); | 654 | rc = __wmi_send(wil, cmdid, mid, buf, len); |
646 | mutex_unlock(&wil->wmi_mutex); | 655 | mutex_unlock(&wil->wmi_mutex); |
647 | 656 | ||
648 | return rc; | 657 | return rc; |
649 | } | 658 | } |
650 | 659 | ||
651 | /*=== Event handlers ===*/ | 660 | /*=== Event handlers ===*/ |
652 | static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len) | 661 | static void wmi_evt_ready(struct wil6210_vif *vif, int id, void *d, int len) |
653 | { | 662 | { |
654 | struct wireless_dev *wdev = wil->wdev; | 663 | struct wil6210_priv *wil = vif_to_wil(vif); |
664 | struct wiphy *wiphy = wil_to_wiphy(wil); | ||
655 | struct wmi_ready_event *evt = d; | 665 | struct wmi_ready_event *evt = d; |
656 | 666 | ||
657 | wil->n_mids = evt->numof_additional_mids; | ||
658 | |||
659 | wil_info(wil, "FW ver. %s(SW %d); MAC %pM; %d MID's\n", | 667 | wil_info(wil, "FW ver. %s(SW %d); MAC %pM; %d MID's\n", |
660 | wil->fw_version, le32_to_cpu(evt->sw_version), | 668 | wil->fw_version, le32_to_cpu(evt->sw_version), |
661 | evt->mac, wil->n_mids); | 669 | evt->mac, evt->numof_additional_mids); |
670 | if (evt->numof_additional_mids + 1 < wil->max_vifs) { | ||
671 | wil_err(wil, "FW does not support enough MIDs (need %d)", | ||
672 | wil->max_vifs - 1); | ||
673 | return; /* FW load will fail after timeout */ | ||
674 | } | ||
662 | /* ignore MAC address, we already have it from the boot loader */ | 675 | /* ignore MAC address, we already have it from the boot loader */ |
663 | strlcpy(wdev->wiphy->fw_version, wil->fw_version, | 676 | strlcpy(wiphy->fw_version, wil->fw_version, sizeof(wiphy->fw_version)); |
664 | sizeof(wdev->wiphy->fw_version)); | ||
665 | 677 | ||
666 | if (len > offsetof(struct wmi_ready_event, rfc_read_calib_result)) { | 678 | if (len > offsetof(struct wmi_ready_event, rfc_read_calib_result)) { |
667 | wil_dbg_wmi(wil, "rfc calibration result %d\n", | 679 | wil_dbg_wmi(wil, "rfc calibration result %d\n", |
@@ -674,8 +686,9 @@ static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len) | |||
674 | complete(&wil->wmi_ready); | 686 | complete(&wil->wmi_ready); |
675 | } | 687 | } |
676 | 688 | ||
677 | static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) | 689 | static void wmi_evt_rx_mgmt(struct wil6210_vif *vif, int id, void *d, int len) |
678 | { | 690 | { |
691 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
679 | struct wmi_rx_mgmt_packet_event *data = d; | 692 | struct wmi_rx_mgmt_packet_event *data = d; |
680 | struct wiphy *wiphy = wil_to_wiphy(wil); | 693 | struct wiphy *wiphy = wil_to_wiphy(wil); |
681 | struct ieee80211_mgmt *rx_mgmt_frame = | 694 | struct ieee80211_mgmt *rx_mgmt_frame = |
@@ -753,14 +766,14 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) | |||
753 | wil_err(wil, "cfg80211_inform_bss_frame() failed\n"); | 766 | wil_err(wil, "cfg80211_inform_bss_frame() failed\n"); |
754 | } | 767 | } |
755 | } else { | 768 | } else { |
756 | mutex_lock(&wil->p2p_wdev_mutex); | 769 | mutex_lock(&wil->vif_mutex); |
757 | cfg80211_rx_mgmt(wil->radio_wdev, freq, signal, | 770 | cfg80211_rx_mgmt(vif_to_radio_wdev(wil, vif), freq, signal, |
758 | (void *)rx_mgmt_frame, d_len, 0); | 771 | (void *)rx_mgmt_frame, d_len, 0); |
759 | mutex_unlock(&wil->p2p_wdev_mutex); | 772 | mutex_unlock(&wil->vif_mutex); |
760 | } | 773 | } |
761 | } | 774 | } |
762 | 775 | ||
763 | static void wmi_evt_tx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) | 776 | static void wmi_evt_tx_mgmt(struct wil6210_vif *vif, int id, void *d, int len) |
764 | { | 777 | { |
765 | struct wmi_tx_mgmt_packet_event *data = d; | 778 | struct wmi_tx_mgmt_packet_event *data = d; |
766 | struct ieee80211_mgmt *mgmt_frame = | 779 | struct ieee80211_mgmt *mgmt_frame = |
@@ -771,11 +784,13 @@ static void wmi_evt_tx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) | |||
771 | flen, true); | 784 | flen, true); |
772 | } | 785 | } |
773 | 786 | ||
774 | static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id, | 787 | static void wmi_evt_scan_complete(struct wil6210_vif *vif, int id, |
775 | void *d, int len) | 788 | void *d, int len) |
776 | { | 789 | { |
777 | mutex_lock(&wil->p2p_wdev_mutex); | 790 | struct wil6210_priv *wil = vif_to_wil(vif); |
778 | if (wil->scan_request) { | 791 | |
792 | mutex_lock(&wil->vif_mutex); | ||
793 | if (vif->scan_request) { | ||
779 | struct wmi_scan_complete_event *data = d; | 794 | struct wmi_scan_complete_event *data = d; |
780 | int status = le32_to_cpu(data->status); | 795 | int status = le32_to_cpu(data->status); |
781 | struct cfg80211_scan_info info = { | 796 | struct cfg80211_scan_info info = { |
@@ -785,26 +800,28 @@ static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id, | |||
785 | 800 | ||
786 | wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", status); | 801 | wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", status); |
787 | wil_dbg_misc(wil, "Complete scan_request 0x%p aborted %d\n", | 802 | wil_dbg_misc(wil, "Complete scan_request 0x%p aborted %d\n", |
788 | wil->scan_request, info.aborted); | 803 | vif->scan_request, info.aborted); |
789 | del_timer_sync(&wil->scan_timer); | 804 | del_timer_sync(&vif->scan_timer); |
790 | cfg80211_scan_done(wil->scan_request, &info); | 805 | cfg80211_scan_done(vif->scan_request, &info); |
791 | wil->radio_wdev = wil->wdev; | 806 | if (vif->mid == 0) |
792 | wil->scan_request = NULL; | 807 | wil->radio_wdev = wil->main_ndev->ieee80211_ptr; |
808 | vif->scan_request = NULL; | ||
793 | wake_up_interruptible(&wil->wq); | 809 | wake_up_interruptible(&wil->wq); |
794 | if (wil->p2p.pending_listen_wdev) { | 810 | if (vif->p2p.pending_listen_wdev) { |
795 | wil_dbg_misc(wil, "Scheduling delayed listen\n"); | 811 | wil_dbg_misc(wil, "Scheduling delayed listen\n"); |
796 | schedule_work(&wil->p2p.delayed_listen_work); | 812 | schedule_work(&vif->p2p.delayed_listen_work); |
797 | } | 813 | } |
798 | } else { | 814 | } else { |
799 | wil_err(wil, "SCAN_COMPLETE while not scanning\n"); | 815 | wil_err(wil, "SCAN_COMPLETE while not scanning\n"); |
800 | } | 816 | } |
801 | mutex_unlock(&wil->p2p_wdev_mutex); | 817 | mutex_unlock(&wil->vif_mutex); |
802 | } | 818 | } |
803 | 819 | ||
804 | static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) | 820 | static void wmi_evt_connect(struct wil6210_vif *vif, int id, void *d, int len) |
805 | { | 821 | { |
806 | struct net_device *ndev = wil_to_ndev(wil); | 822 | struct wil6210_priv *wil = vif_to_wil(vif); |
807 | struct wireless_dev *wdev = wil->wdev; | 823 | struct net_device *ndev = vif_to_ndev(vif); |
824 | struct wireless_dev *wdev = vif_to_wdev(vif); | ||
808 | struct wmi_connect_event *evt = d; | 825 | struct wmi_connect_event *evt = d; |
809 | int ch; /* channel number */ | 826 | int ch; /* channel number */ |
810 | struct station_info sinfo; | 827 | struct station_info sinfo; |
@@ -869,12 +886,12 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) | |||
869 | 886 | ||
870 | if ((wdev->iftype == NL80211_IFTYPE_STATION) || | 887 | if ((wdev->iftype == NL80211_IFTYPE_STATION) || |
871 | (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { | 888 | (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { |
872 | if (!test_bit(wil_status_fwconnecting, wil->status)) { | 889 | if (!test_bit(wil_vif_fwconnecting, vif->status)) { |
873 | wil_err(wil, "Not in connecting state\n"); | 890 | wil_err(wil, "Not in connecting state\n"); |
874 | mutex_unlock(&wil->mutex); | 891 | mutex_unlock(&wil->mutex); |
875 | return; | 892 | return; |
876 | } | 893 | } |
877 | del_timer_sync(&wil->connect_timer); | 894 | del_timer_sync(&vif->connect_timer); |
878 | } else if ((wdev->iftype == NL80211_IFTYPE_AP) || | 895 | } else if ((wdev->iftype == NL80211_IFTYPE_AP) || |
879 | (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { | 896 | (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { |
880 | if (wil->sta[evt->cid].status != wil_sta_unused) { | 897 | if (wil->sta[evt->cid].status != wil_sta_unused) { |
@@ -886,13 +903,14 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) | |||
886 | } | 903 | } |
887 | 904 | ||
888 | ether_addr_copy(wil->sta[evt->cid].addr, evt->bssid); | 905 | ether_addr_copy(wil->sta[evt->cid].addr, evt->bssid); |
906 | wil->sta[evt->cid].mid = vif->mid; | ||
889 | wil->sta[evt->cid].status = wil_sta_conn_pending; | 907 | wil->sta[evt->cid].status = wil_sta_conn_pending; |
890 | 908 | ||
891 | rc = wil_tx_init(wil, evt->cid); | 909 | rc = wil_tx_init(vif, evt->cid); |
892 | if (rc) { | 910 | if (rc) { |
893 | wil_err(wil, "config tx vring failed for CID %d, rc (%d)\n", | 911 | wil_err(wil, "config tx vring failed for CID %d, rc (%d)\n", |
894 | evt->cid, rc); | 912 | evt->cid, rc); |
895 | wmi_disconnect_sta(wil, wil->sta[evt->cid].addr, | 913 | wmi_disconnect_sta(vif, wil->sta[evt->cid].addr, |
896 | WLAN_REASON_UNSPECIFIED, false, false); | 914 | WLAN_REASON_UNSPECIFIED, false, false); |
897 | } else { | 915 | } else { |
898 | wil_info(wil, "successful connection to CID %d\n", evt->cid); | 916 | wil_info(wil, "successful connection to CID %d\n", evt->cid); |
@@ -912,14 +930,14 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) | |||
912 | } else { | 930 | } else { |
913 | struct wiphy *wiphy = wil_to_wiphy(wil); | 931 | struct wiphy *wiphy = wil_to_wiphy(wil); |
914 | 932 | ||
915 | cfg80211_ref_bss(wiphy, wil->bss); | 933 | cfg80211_ref_bss(wiphy, vif->bss); |
916 | cfg80211_connect_bss(ndev, evt->bssid, wil->bss, | 934 | cfg80211_connect_bss(ndev, evt->bssid, vif->bss, |
917 | assoc_req_ie, assoc_req_ielen, | 935 | assoc_req_ie, assoc_req_ielen, |
918 | assoc_resp_ie, assoc_resp_ielen, | 936 | assoc_resp_ie, assoc_resp_ielen, |
919 | WLAN_STATUS_SUCCESS, GFP_KERNEL, | 937 | WLAN_STATUS_SUCCESS, GFP_KERNEL, |
920 | NL80211_TIMEOUT_UNSPECIFIED); | 938 | NL80211_TIMEOUT_UNSPECIFIED); |
921 | } | 939 | } |
922 | wil->bss = NULL; | 940 | vif->bss = NULL; |
923 | } else if ((wdev->iftype == NL80211_IFTYPE_AP) || | 941 | } else if ((wdev->iftype == NL80211_IFTYPE_AP) || |
924 | (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { | 942 | (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { |
925 | if (rc) { | 943 | if (rc) { |
@@ -947,19 +965,23 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) | |||
947 | 965 | ||
948 | wil->sta[evt->cid].status = wil_sta_connected; | 966 | wil->sta[evt->cid].status = wil_sta_connected; |
949 | wil->sta[evt->cid].aid = evt->aid; | 967 | wil->sta[evt->cid].aid = evt->aid; |
950 | set_bit(wil_status_fwconnected, wil->status); | 968 | if (!test_and_set_bit(wil_vif_fwconnected, vif->status)) |
951 | wil_update_net_queues_bh(wil, NULL, false); | 969 | atomic_inc(&wil->connected_vifs); |
970 | wil_update_net_queues_bh(wil, vif, NULL, false); | ||
952 | 971 | ||
953 | out: | 972 | out: |
954 | if (rc) | 973 | if (rc) { |
955 | wil->sta[evt->cid].status = wil_sta_unused; | 974 | wil->sta[evt->cid].status = wil_sta_unused; |
956 | clear_bit(wil_status_fwconnecting, wil->status); | 975 | wil->sta[evt->cid].mid = U8_MAX; |
976 | } | ||
977 | clear_bit(wil_vif_fwconnecting, vif->status); | ||
957 | mutex_unlock(&wil->mutex); | 978 | mutex_unlock(&wil->mutex); |
958 | } | 979 | } |
959 | 980 | ||
960 | static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, | 981 | static void wmi_evt_disconnect(struct wil6210_vif *vif, int id, |
961 | void *d, int len) | 982 | void *d, int len) |
962 | { | 983 | { |
984 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
963 | struct wmi_disconnect_event *evt = d; | 985 | struct wmi_disconnect_event *evt = d; |
964 | u16 reason_code = le16_to_cpu(evt->protocol_reason_status); | 986 | u16 reason_code = le16_to_cpu(evt->protocol_reason_status); |
965 | 987 | ||
@@ -976,7 +998,7 @@ static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, | |||
976 | } | 998 | } |
977 | 999 | ||
978 | mutex_lock(&wil->mutex); | 1000 | mutex_lock(&wil->mutex); |
979 | wil6210_disconnect(wil, evt->bssid, reason_code, true); | 1001 | wil6210_disconnect(vif, evt->bssid, reason_code, true); |
980 | mutex_unlock(&wil->mutex); | 1002 | mutex_unlock(&wil->mutex); |
981 | } | 1003 | } |
982 | 1004 | ||
@@ -984,10 +1006,10 @@ static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, | |||
984 | * Firmware reports EAPOL frame using WME event. | 1006 | * Firmware reports EAPOL frame using WME event. |
985 | * Reconstruct Ethernet frame and deliver it via normal Rx | 1007 | * Reconstruct Ethernet frame and deliver it via normal Rx |
986 | */ | 1008 | */ |
987 | static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id, | 1009 | static void wmi_evt_eapol_rx(struct wil6210_vif *vif, int id, void *d, int len) |
988 | void *d, int len) | ||
989 | { | 1010 | { |
990 | struct net_device *ndev = wil_to_ndev(wil); | 1011 | struct wil6210_priv *wil = vif_to_wil(vif); |
1012 | struct net_device *ndev = vif_to_ndev(vif); | ||
991 | struct wmi_eapol_rx_event *evt = d; | 1013 | struct wmi_eapol_rx_event *evt = d; |
992 | u16 eapol_len = le16_to_cpu(evt->eapol_len); | 1014 | u16 eapol_len = le16_to_cpu(evt->eapol_len); |
993 | int sz = eapol_len + ETH_HLEN; | 1015 | int sz = eapol_len + ETH_HLEN; |
@@ -996,10 +1018,10 @@ static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id, | |||
996 | int cid; | 1018 | int cid; |
997 | struct wil_net_stats *stats = NULL; | 1019 | struct wil_net_stats *stats = NULL; |
998 | 1020 | ||
999 | wil_dbg_wmi(wil, "EAPOL len %d from %pM\n", eapol_len, | 1021 | wil_dbg_wmi(wil, "EAPOL len %d from %pM MID %d\n", eapol_len, |
1000 | evt->src_mac); | 1022 | evt->src_mac, vif->mid); |
1001 | 1023 | ||
1002 | cid = wil_find_cid(wil, evt->src_mac); | 1024 | cid = wil_find_cid(wil, vif->mid, evt->src_mac); |
1003 | if (cid >= 0) | 1025 | if (cid >= 0) |
1004 | stats = &wil->sta[cid].stats; | 1026 | stats = &wil->sta[cid].stats; |
1005 | 1027 | ||
@@ -1034,13 +1056,14 @@ static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id, | |||
1034 | } | 1056 | } |
1035 | } | 1057 | } |
1036 | 1058 | ||
1037 | static void wmi_evt_vring_en(struct wil6210_priv *wil, int id, void *d, int len) | 1059 | static void wmi_evt_vring_en(struct wil6210_vif *vif, int id, void *d, int len) |
1038 | { | 1060 | { |
1061 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1039 | struct wmi_vring_en_event *evt = d; | 1062 | struct wmi_vring_en_event *evt = d; |
1040 | u8 vri = evt->vring_index; | 1063 | u8 vri = evt->vring_index; |
1041 | struct wireless_dev *wdev = wil_to_wdev(wil); | 1064 | struct wireless_dev *wdev = vif_to_wdev(vif); |
1042 | 1065 | ||
1043 | wil_dbg_wmi(wil, "Enable vring %d\n", vri); | 1066 | wil_dbg_wmi(wil, "Enable vring %d MID %d\n", vri, vif->mid); |
1044 | 1067 | ||
1045 | if (vri >= ARRAY_SIZE(wil->vring_tx)) { | 1068 | if (vri >= ARRAY_SIZE(wil->vring_tx)) { |
1046 | wil_err(wil, "Enable for invalid vring %d\n", vri); | 1069 | wil_err(wil, "Enable for invalid vring %d\n", vri); |
@@ -1052,15 +1075,16 @@ static void wmi_evt_vring_en(struct wil6210_priv *wil, int id, void *d, int len) | |||
1052 | * wil_cfg80211_change_station() | 1075 | * wil_cfg80211_change_station() |
1053 | */ | 1076 | */ |
1054 | wil->vring_tx_data[vri].dot1x_open = true; | 1077 | wil->vring_tx_data[vri].dot1x_open = true; |
1055 | if (vri == wil->bcast_vring) /* no BA for bcast */ | 1078 | if (vri == vif->bcast_vring) /* no BA for bcast */ |
1056 | return; | 1079 | return; |
1057 | if (agg_wsize >= 0) | 1080 | if (agg_wsize >= 0) |
1058 | wil_addba_tx_request(wil, vri, agg_wsize); | 1081 | wil_addba_tx_request(wil, vri, agg_wsize); |
1059 | } | 1082 | } |
1060 | 1083 | ||
1061 | static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d, | 1084 | static void wmi_evt_ba_status(struct wil6210_vif *vif, int id, |
1062 | int len) | 1085 | void *d, int len) |
1063 | { | 1086 | { |
1087 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1064 | struct wmi_ba_status_event *evt = d; | 1088 | struct wmi_ba_status_event *evt = d; |
1065 | struct vring_tx_data *txdata; | 1089 | struct vring_tx_data *txdata; |
1066 | 1090 | ||
@@ -1089,19 +1113,21 @@ static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d, | |||
1089 | txdata->addba_in_progress = false; | 1113 | txdata->addba_in_progress = false; |
1090 | } | 1114 | } |
1091 | 1115 | ||
1092 | static void wmi_evt_addba_rx_req(struct wil6210_priv *wil, int id, void *d, | 1116 | static void wmi_evt_addba_rx_req(struct wil6210_vif *vif, int id, |
1093 | int len) | 1117 | void *d, int len) |
1094 | { | 1118 | { |
1119 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1095 | struct wmi_rcp_addba_req_event *evt = d; | 1120 | struct wmi_rcp_addba_req_event *evt = d; |
1096 | 1121 | ||
1097 | wil_addba_rx_request(wil, evt->cidxtid, evt->dialog_token, | 1122 | wil_addba_rx_request(wil, vif->mid, evt->cidxtid, evt->dialog_token, |
1098 | evt->ba_param_set, evt->ba_timeout, | 1123 | evt->ba_param_set, evt->ba_timeout, |
1099 | evt->ba_seq_ctrl); | 1124 | evt->ba_seq_ctrl); |
1100 | } | 1125 | } |
1101 | 1126 | ||
1102 | static void wmi_evt_delba(struct wil6210_priv *wil, int id, void *d, int len) | 1127 | static void wmi_evt_delba(struct wil6210_vif *vif, int id, void *d, int len) |
1103 | __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | 1128 | __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) |
1104 | { | 1129 | { |
1130 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1105 | struct wmi_delba_event *evt = d; | 1131 | struct wmi_delba_event *evt = d; |
1106 | u8 cid, tid; | 1132 | u8 cid, tid; |
1107 | u16 reason = __le16_to_cpu(evt->reason); | 1133 | u16 reason = __le16_to_cpu(evt->reason); |
@@ -1110,8 +1136,8 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | |||
1110 | 1136 | ||
1111 | might_sleep(); | 1137 | might_sleep(); |
1112 | parse_cidxtid(evt->cidxtid, &cid, &tid); | 1138 | parse_cidxtid(evt->cidxtid, &cid, &tid); |
1113 | wil_dbg_wmi(wil, "DELBA CID %d TID %d from %s reason %d\n", | 1139 | wil_dbg_wmi(wil, "DELBA MID %d CID %d TID %d from %s reason %d\n", |
1114 | cid, tid, | 1140 | vif->mid, cid, tid, |
1115 | evt->from_initiator ? "originator" : "recipient", | 1141 | evt->from_initiator ? "originator" : "recipient", |
1116 | reason); | 1142 | reason); |
1117 | if (!evt->from_initiator) { | 1143 | if (!evt->from_initiator) { |
@@ -1148,8 +1174,9 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | |||
1148 | } | 1174 | } |
1149 | 1175 | ||
1150 | static void | 1176 | static void |
1151 | wmi_evt_sched_scan_result(struct wil6210_priv *wil, int id, void *d, int len) | 1177 | wmi_evt_sched_scan_result(struct wil6210_vif *vif, int id, void *d, int len) |
1152 | { | 1178 | { |
1179 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1153 | struct wmi_sched_scan_result_event *data = d; | 1180 | struct wmi_sched_scan_result_event *data = d; |
1154 | struct wiphy *wiphy = wil_to_wiphy(wil); | 1181 | struct wiphy *wiphy = wil_to_wiphy(wil); |
1155 | struct ieee80211_mgmt *rx_mgmt_frame = | 1182 | struct ieee80211_mgmt *rx_mgmt_frame = |
@@ -1220,15 +1247,17 @@ wmi_evt_sched_scan_result(struct wil6210_priv *wil, int id, void *d, int len) | |||
1220 | * Some events are ignored for purpose; and need not be interpreted as | 1247 | * Some events are ignored for purpose; and need not be interpreted as |
1221 | * "unhandled events" | 1248 | * "unhandled events" |
1222 | */ | 1249 | */ |
1223 | static void wmi_evt_ignore(struct wil6210_priv *wil, int id, void *d, int len) | 1250 | static void wmi_evt_ignore(struct wil6210_vif *vif, int id, void *d, int len) |
1224 | { | 1251 | { |
1252 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1253 | |||
1225 | wil_dbg_wmi(wil, "Ignore event 0x%04x len %d\n", id, len); | 1254 | wil_dbg_wmi(wil, "Ignore event 0x%04x len %d\n", id, len); |
1226 | } | 1255 | } |
1227 | 1256 | ||
1228 | static const struct { | 1257 | static const struct { |
1229 | int eventid; | 1258 | int eventid; |
1230 | void (*handler)(struct wil6210_priv *wil, int eventid, | 1259 | void (*handler)(struct wil6210_vif *vif, |
1231 | void *data, int data_len); | 1260 | int eventid, void *data, int data_len); |
1232 | } wmi_evt_handlers[] = { | 1261 | } wmi_evt_handlers[] = { |
1233 | {WMI_READY_EVENTID, wmi_evt_ready}, | 1262 | {WMI_READY_EVENTID, wmi_evt_ready}, |
1234 | {WMI_FW_READY_EVENTID, wmi_evt_ignore}, | 1263 | {WMI_FW_READY_EVENTID, wmi_evt_ignore}, |
@@ -1325,6 +1354,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) | |||
1325 | (len >= sizeof(struct wmi_cmd_hdr))) { | 1354 | (len >= sizeof(struct wmi_cmd_hdr))) { |
1326 | struct wmi_cmd_hdr *wmi = &evt->event.wmi; | 1355 | struct wmi_cmd_hdr *wmi = &evt->event.wmi; |
1327 | u16 id = le16_to_cpu(wmi->command_id); | 1356 | u16 id = le16_to_cpu(wmi->command_id); |
1357 | u8 mid = wmi->mid; | ||
1328 | u32 tstamp = le32_to_cpu(wmi->fw_timestamp); | 1358 | u32 tstamp = le32_to_cpu(wmi->fw_timestamp); |
1329 | if (test_bit(wil_status_resuming, wil->status)) { | 1359 | if (test_bit(wil_status_resuming, wil->status)) { |
1330 | if (id == WMI_TRAFFIC_RESUME_EVENTID) | 1360 | if (id == WMI_TRAFFIC_RESUME_EVENTID) |
@@ -1336,7 +1366,8 @@ void wmi_recv_cmd(struct wil6210_priv *wil) | |||
1336 | id); | 1366 | id); |
1337 | } | 1367 | } |
1338 | spin_lock_irqsave(&wil->wmi_ev_lock, flags); | 1368 | spin_lock_irqsave(&wil->wmi_ev_lock, flags); |
1339 | if (wil->reply_id && wil->reply_id == id) { | 1369 | if (wil->reply_id && wil->reply_id == id && |
1370 | wil->reply_mid == mid) { | ||
1340 | if (wil->reply_buf) { | 1371 | if (wil->reply_buf) { |
1341 | memcpy(wil->reply_buf, wmi, | 1372 | memcpy(wil->reply_buf, wmi, |
1342 | min(len, wil->reply_size)); | 1373 | min(len, wil->reply_size)); |
@@ -1384,7 +1415,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) | |||
1384 | n - num_immed_reply, num_immed_reply); | 1415 | n - num_immed_reply, num_immed_reply); |
1385 | } | 1416 | } |
1386 | 1417 | ||
1387 | int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, | 1418 | int wmi_call(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len, |
1388 | u16 reply_id, void *reply, u8 reply_size, int to_msec) | 1419 | u16 reply_id, void *reply, u8 reply_size, int to_msec) |
1389 | { | 1420 | { |
1390 | int rc; | 1421 | int rc; |
@@ -1394,12 +1425,13 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, | |||
1394 | 1425 | ||
1395 | spin_lock(&wil->wmi_ev_lock); | 1426 | spin_lock(&wil->wmi_ev_lock); |
1396 | wil->reply_id = reply_id; | 1427 | wil->reply_id = reply_id; |
1428 | wil->reply_mid = mid; | ||
1397 | wil->reply_buf = reply; | 1429 | wil->reply_buf = reply; |
1398 | wil->reply_size = reply_size; | 1430 | wil->reply_size = reply_size; |
1399 | reinit_completion(&wil->wmi_call); | 1431 | reinit_completion(&wil->wmi_call); |
1400 | spin_unlock(&wil->wmi_ev_lock); | 1432 | spin_unlock(&wil->wmi_ev_lock); |
1401 | 1433 | ||
1402 | rc = __wmi_send(wil, cmdid, buf, len); | 1434 | rc = __wmi_send(wil, cmdid, mid, buf, len); |
1403 | if (rc) | 1435 | if (rc) |
1404 | goto out; | 1436 | goto out; |
1405 | 1437 | ||
@@ -1419,6 +1451,7 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, | |||
1419 | out: | 1451 | out: |
1420 | spin_lock(&wil->wmi_ev_lock); | 1452 | spin_lock(&wil->wmi_ev_lock); |
1421 | wil->reply_id = 0; | 1453 | wil->reply_id = 0; |
1454 | wil->reply_mid = U8_MAX; | ||
1422 | wil->reply_buf = NULL; | 1455 | wil->reply_buf = NULL; |
1423 | wil->reply_size = 0; | 1456 | wil->reply_size = 0; |
1424 | spin_unlock(&wil->wmi_ev_lock); | 1457 | spin_unlock(&wil->wmi_ev_lock); |
@@ -1430,27 +1463,31 @@ out: | |||
1430 | 1463 | ||
1431 | int wmi_echo(struct wil6210_priv *wil) | 1464 | int wmi_echo(struct wil6210_priv *wil) |
1432 | { | 1465 | { |
1466 | struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); | ||
1433 | struct wmi_echo_cmd cmd = { | 1467 | struct wmi_echo_cmd cmd = { |
1434 | .value = cpu_to_le32(0x12345678), | 1468 | .value = cpu_to_le32(0x12345678), |
1435 | }; | 1469 | }; |
1436 | 1470 | ||
1437 | return wmi_call(wil, WMI_ECHO_CMDID, &cmd, sizeof(cmd), | 1471 | return wmi_call(wil, WMI_ECHO_CMDID, vif->mid, &cmd, sizeof(cmd), |
1438 | WMI_ECHO_RSP_EVENTID, NULL, 0, 50); | 1472 | WMI_ECHO_RSP_EVENTID, NULL, 0, 50); |
1439 | } | 1473 | } |
1440 | 1474 | ||
1441 | int wmi_set_mac_address(struct wil6210_priv *wil, void *addr) | 1475 | int wmi_set_mac_address(struct wil6210_priv *wil, void *addr) |
1442 | { | 1476 | { |
1477 | struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); | ||
1443 | struct wmi_set_mac_address_cmd cmd; | 1478 | struct wmi_set_mac_address_cmd cmd; |
1444 | 1479 | ||
1445 | ether_addr_copy(cmd.mac, addr); | 1480 | ether_addr_copy(cmd.mac, addr); |
1446 | 1481 | ||
1447 | wil_dbg_wmi(wil, "Set MAC %pM\n", addr); | 1482 | wil_dbg_wmi(wil, "Set MAC %pM\n", addr); |
1448 | 1483 | ||
1449 | return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd)); | 1484 | return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, vif->mid, |
1485 | &cmd, sizeof(cmd)); | ||
1450 | } | 1486 | } |
1451 | 1487 | ||
1452 | int wmi_led_cfg(struct wil6210_priv *wil, bool enable) | 1488 | int wmi_led_cfg(struct wil6210_priv *wil, bool enable) |
1453 | { | 1489 | { |
1490 | struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); | ||
1454 | int rc = 0; | 1491 | int rc = 0; |
1455 | struct wmi_led_cfg_cmd cmd = { | 1492 | struct wmi_led_cfg_cmd cmd = { |
1456 | .led_mode = enable, | 1493 | .led_mode = enable, |
@@ -1487,7 +1524,7 @@ int wmi_led_cfg(struct wil6210_priv *wil, bool enable) | |||
1487 | "%s led %d\n", | 1524 | "%s led %d\n", |
1488 | enable ? "enabling" : "disabling", led_id); | 1525 | enable ? "enabling" : "disabling", led_id); |
1489 | 1526 | ||
1490 | rc = wmi_call(wil, WMI_LED_CFG_CMDID, &cmd, sizeof(cmd), | 1527 | rc = wmi_call(wil, WMI_LED_CFG_CMDID, vif->mid, &cmd, sizeof(cmd), |
1491 | WMI_LED_CFG_DONE_EVENTID, &reply, sizeof(reply), | 1528 | WMI_LED_CFG_DONE_EVENTID, &reply, sizeof(reply), |
1492 | 100); | 1529 | 100); |
1493 | if (rc) | 1530 | if (rc) |
@@ -1503,9 +1540,10 @@ out: | |||
1503 | return rc; | 1540 | return rc; |
1504 | } | 1541 | } |
1505 | 1542 | ||
1506 | int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, | 1543 | int wmi_pcp_start(struct wil6210_vif *vif, |
1507 | u8 chan, u8 hidden_ssid, u8 is_go) | 1544 | int bi, u8 wmi_nettype, u8 chan, u8 hidden_ssid, u8 is_go) |
1508 | { | 1545 | { |
1546 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1509 | int rc; | 1547 | int rc; |
1510 | 1548 | ||
1511 | struct wmi_pcp_start_cmd cmd = { | 1549 | struct wmi_pcp_start_cmd cmd = { |
@@ -1524,7 +1562,7 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, | |||
1524 | struct wmi_pcp_started_event evt; | 1562 | struct wmi_pcp_started_event evt; |
1525 | } __packed reply; | 1563 | } __packed reply; |
1526 | 1564 | ||
1527 | if (!wil->privacy) | 1565 | if (!vif->privacy) |
1528 | cmd.disable_sec = 1; | 1566 | cmd.disable_sec = 1; |
1529 | 1567 | ||
1530 | if ((cmd.pcp_max_assoc_sta > WIL6210_MAX_CID) || | 1568 | if ((cmd.pcp_max_assoc_sta > WIL6210_MAX_CID) || |
@@ -1546,7 +1584,7 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, | |||
1546 | * Processing time may be huge, in case of secure AP it takes about | 1584 | * Processing time may be huge, in case of secure AP it takes about |
1547 | * 3500ms for FW to start AP | 1585 | * 3500ms for FW to start AP |
1548 | */ | 1586 | */ |
1549 | rc = wmi_call(wil, WMI_PCP_START_CMDID, &cmd, sizeof(cmd), | 1587 | rc = wmi_call(wil, WMI_PCP_START_CMDID, vif->mid, &cmd, sizeof(cmd), |
1550 | WMI_PCP_STARTED_EVENTID, &reply, sizeof(reply), 5000); | 1588 | WMI_PCP_STARTED_EVENTID, &reply, sizeof(reply), 5000); |
1551 | if (rc) | 1589 | if (rc) |
1552 | return rc; | 1590 | return rc; |
@@ -1561,20 +1599,22 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, | |||
1561 | return rc; | 1599 | return rc; |
1562 | } | 1600 | } |
1563 | 1601 | ||
1564 | int wmi_pcp_stop(struct wil6210_priv *wil) | 1602 | int wmi_pcp_stop(struct wil6210_vif *vif) |
1565 | { | 1603 | { |
1604 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1566 | int rc; | 1605 | int rc; |
1567 | 1606 | ||
1568 | rc = wmi_led_cfg(wil, false); | 1607 | rc = wmi_led_cfg(wil, false); |
1569 | if (rc) | 1608 | if (rc) |
1570 | return rc; | 1609 | return rc; |
1571 | 1610 | ||
1572 | return wmi_call(wil, WMI_PCP_STOP_CMDID, NULL, 0, | 1611 | return wmi_call(wil, WMI_PCP_STOP_CMDID, vif->mid, NULL, 0, |
1573 | WMI_PCP_STOPPED_EVENTID, NULL, 0, 20); | 1612 | WMI_PCP_STOPPED_EVENTID, NULL, 0, 20); |
1574 | } | 1613 | } |
1575 | 1614 | ||
1576 | int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid) | 1615 | int wmi_set_ssid(struct wil6210_vif *vif, u8 ssid_len, const void *ssid) |
1577 | { | 1616 | { |
1617 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1578 | struct wmi_set_ssid_cmd cmd = { | 1618 | struct wmi_set_ssid_cmd cmd = { |
1579 | .ssid_len = cpu_to_le32(ssid_len), | 1619 | .ssid_len = cpu_to_le32(ssid_len), |
1580 | }; | 1620 | }; |
@@ -1584,11 +1624,12 @@ int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid) | |||
1584 | 1624 | ||
1585 | memcpy(cmd.ssid, ssid, ssid_len); | 1625 | memcpy(cmd.ssid, ssid, ssid_len); |
1586 | 1626 | ||
1587 | return wmi_send(wil, WMI_SET_SSID_CMDID, &cmd, sizeof(cmd)); | 1627 | return wmi_send(wil, WMI_SET_SSID_CMDID, vif->mid, &cmd, sizeof(cmd)); |
1588 | } | 1628 | } |
1589 | 1629 | ||
1590 | int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid) | 1630 | int wmi_get_ssid(struct wil6210_vif *vif, u8 *ssid_len, void *ssid) |
1591 | { | 1631 | { |
1632 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1592 | int rc; | 1633 | int rc; |
1593 | struct { | 1634 | struct { |
1594 | struct wmi_cmd_hdr wmi; | 1635 | struct wmi_cmd_hdr wmi; |
@@ -1596,8 +1637,8 @@ int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid) | |||
1596 | } __packed reply; | 1637 | } __packed reply; |
1597 | int len; /* reply.cmd.ssid_len in CPU order */ | 1638 | int len; /* reply.cmd.ssid_len in CPU order */ |
1598 | 1639 | ||
1599 | rc = wmi_call(wil, WMI_GET_SSID_CMDID, NULL, 0, WMI_GET_SSID_EVENTID, | 1640 | rc = wmi_call(wil, WMI_GET_SSID_CMDID, vif->mid, NULL, 0, |
1600 | &reply, sizeof(reply), 20); | 1641 | WMI_GET_SSID_EVENTID, &reply, sizeof(reply), 20); |
1601 | if (rc) | 1642 | if (rc) |
1602 | return rc; | 1643 | return rc; |
1603 | 1644 | ||
@@ -1613,22 +1654,25 @@ int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid) | |||
1613 | 1654 | ||
1614 | int wmi_set_channel(struct wil6210_priv *wil, int channel) | 1655 | int wmi_set_channel(struct wil6210_priv *wil, int channel) |
1615 | { | 1656 | { |
1657 | struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); | ||
1616 | struct wmi_set_pcp_channel_cmd cmd = { | 1658 | struct wmi_set_pcp_channel_cmd cmd = { |
1617 | .channel = channel - 1, | 1659 | .channel = channel - 1, |
1618 | }; | 1660 | }; |
1619 | 1661 | ||
1620 | return wmi_send(wil, WMI_SET_PCP_CHANNEL_CMDID, &cmd, sizeof(cmd)); | 1662 | return wmi_send(wil, WMI_SET_PCP_CHANNEL_CMDID, vif->mid, |
1663 | &cmd, sizeof(cmd)); | ||
1621 | } | 1664 | } |
1622 | 1665 | ||
1623 | int wmi_get_channel(struct wil6210_priv *wil, int *channel) | 1666 | int wmi_get_channel(struct wil6210_priv *wil, int *channel) |
1624 | { | 1667 | { |
1668 | struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); | ||
1625 | int rc; | 1669 | int rc; |
1626 | struct { | 1670 | struct { |
1627 | struct wmi_cmd_hdr wmi; | 1671 | struct wmi_cmd_hdr wmi; |
1628 | struct wmi_set_pcp_channel_cmd cmd; | 1672 | struct wmi_set_pcp_channel_cmd cmd; |
1629 | } __packed reply; | 1673 | } __packed reply; |
1630 | 1674 | ||
1631 | rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, NULL, 0, | 1675 | rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, vif->mid, NULL, 0, |
1632 | WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply), 20); | 1676 | WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply), 20); |
1633 | if (rc) | 1677 | if (rc) |
1634 | return rc; | 1678 | return rc; |
@@ -1641,8 +1685,9 @@ int wmi_get_channel(struct wil6210_priv *wil, int *channel) | |||
1641 | return 0; | 1685 | return 0; |
1642 | } | 1686 | } |
1643 | 1687 | ||
1644 | int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi) | 1688 | int wmi_p2p_cfg(struct wil6210_vif *vif, int channel, int bi) |
1645 | { | 1689 | { |
1690 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1646 | int rc; | 1691 | int rc; |
1647 | struct wmi_p2p_cfg_cmd cmd = { | 1692 | struct wmi_p2p_cfg_cmd cmd = { |
1648 | .discovery_mode = WMI_DISCOVERY_MODE_PEER2PEER, | 1693 | .discovery_mode = WMI_DISCOVERY_MODE_PEER2PEER, |
@@ -1656,7 +1701,7 @@ int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi) | |||
1656 | 1701 | ||
1657 | wil_dbg_wmi(wil, "sending WMI_P2P_CFG_CMDID\n"); | 1702 | wil_dbg_wmi(wil, "sending WMI_P2P_CFG_CMDID\n"); |
1658 | 1703 | ||
1659 | rc = wmi_call(wil, WMI_P2P_CFG_CMDID, &cmd, sizeof(cmd), | 1704 | rc = wmi_call(wil, WMI_P2P_CFG_CMDID, vif->mid, &cmd, sizeof(cmd), |
1660 | WMI_P2P_CFG_DONE_EVENTID, &reply, sizeof(reply), 300); | 1705 | WMI_P2P_CFG_DONE_EVENTID, &reply, sizeof(reply), 300); |
1661 | if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) { | 1706 | if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) { |
1662 | wil_err(wil, "P2P_CFG failed. status %d\n", reply.evt.status); | 1707 | wil_err(wil, "P2P_CFG failed. status %d\n", reply.evt.status); |
@@ -1666,8 +1711,9 @@ int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi) | |||
1666 | return rc; | 1711 | return rc; |
1667 | } | 1712 | } |
1668 | 1713 | ||
1669 | int wmi_start_listen(struct wil6210_priv *wil) | 1714 | int wmi_start_listen(struct wil6210_vif *vif) |
1670 | { | 1715 | { |
1716 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1671 | int rc; | 1717 | int rc; |
1672 | struct { | 1718 | struct { |
1673 | struct wmi_cmd_hdr wmi; | 1719 | struct wmi_cmd_hdr wmi; |
@@ -1676,7 +1722,7 @@ int wmi_start_listen(struct wil6210_priv *wil) | |||
1676 | 1722 | ||
1677 | wil_dbg_wmi(wil, "sending WMI_START_LISTEN_CMDID\n"); | 1723 | wil_dbg_wmi(wil, "sending WMI_START_LISTEN_CMDID\n"); |
1678 | 1724 | ||
1679 | rc = wmi_call(wil, WMI_START_LISTEN_CMDID, NULL, 0, | 1725 | rc = wmi_call(wil, WMI_START_LISTEN_CMDID, vif->mid, NULL, 0, |
1680 | WMI_LISTEN_STARTED_EVENTID, &reply, sizeof(reply), 300); | 1726 | WMI_LISTEN_STARTED_EVENTID, &reply, sizeof(reply), 300); |
1681 | if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) { | 1727 | if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) { |
1682 | wil_err(wil, "device failed to start listen. status %d\n", | 1728 | wil_err(wil, "device failed to start listen. status %d\n", |
@@ -1687,8 +1733,9 @@ int wmi_start_listen(struct wil6210_priv *wil) | |||
1687 | return rc; | 1733 | return rc; |
1688 | } | 1734 | } |
1689 | 1735 | ||
1690 | int wmi_start_search(struct wil6210_priv *wil) | 1736 | int wmi_start_search(struct wil6210_vif *vif) |
1691 | { | 1737 | { |
1738 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1692 | int rc; | 1739 | int rc; |
1693 | struct { | 1740 | struct { |
1694 | struct wmi_cmd_hdr wmi; | 1741 | struct wmi_cmd_hdr wmi; |
@@ -1697,7 +1744,7 @@ int wmi_start_search(struct wil6210_priv *wil) | |||
1697 | 1744 | ||
1698 | wil_dbg_wmi(wil, "sending WMI_START_SEARCH_CMDID\n"); | 1745 | wil_dbg_wmi(wil, "sending WMI_START_SEARCH_CMDID\n"); |
1699 | 1746 | ||
1700 | rc = wmi_call(wil, WMI_START_SEARCH_CMDID, NULL, 0, | 1747 | rc = wmi_call(wil, WMI_START_SEARCH_CMDID, vif->mid, NULL, 0, |
1701 | WMI_SEARCH_STARTED_EVENTID, &reply, sizeof(reply), 300); | 1748 | WMI_SEARCH_STARTED_EVENTID, &reply, sizeof(reply), 300); |
1702 | if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) { | 1749 | if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) { |
1703 | wil_err(wil, "device failed to start search. status %d\n", | 1750 | wil_err(wil, "device failed to start search. status %d\n", |
@@ -1708,13 +1755,14 @@ int wmi_start_search(struct wil6210_priv *wil) | |||
1708 | return rc; | 1755 | return rc; |
1709 | } | 1756 | } |
1710 | 1757 | ||
1711 | int wmi_stop_discovery(struct wil6210_priv *wil) | 1758 | int wmi_stop_discovery(struct wil6210_vif *vif) |
1712 | { | 1759 | { |
1760 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1713 | int rc; | 1761 | int rc; |
1714 | 1762 | ||
1715 | wil_dbg_wmi(wil, "sending WMI_DISCOVERY_STOP_CMDID\n"); | 1763 | wil_dbg_wmi(wil, "sending WMI_DISCOVERY_STOP_CMDID\n"); |
1716 | 1764 | ||
1717 | rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, NULL, 0, | 1765 | rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, vif->mid, NULL, 0, |
1718 | WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 100); | 1766 | WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 100); |
1719 | 1767 | ||
1720 | if (rc) | 1768 | if (rc) |
@@ -1723,9 +1771,10 @@ int wmi_stop_discovery(struct wil6210_priv *wil) | |||
1723 | return rc; | 1771 | return rc; |
1724 | } | 1772 | } |
1725 | 1773 | ||
1726 | int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index, | 1774 | int wmi_del_cipher_key(struct wil6210_vif *vif, u8 key_index, |
1727 | const void *mac_addr, int key_usage) | 1775 | const void *mac_addr, int key_usage) |
1728 | { | 1776 | { |
1777 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1729 | struct wmi_delete_cipher_key_cmd cmd = { | 1778 | struct wmi_delete_cipher_key_cmd cmd = { |
1730 | .key_index = key_index, | 1779 | .key_index = key_index, |
1731 | }; | 1780 | }; |
@@ -1733,13 +1782,15 @@ int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index, | |||
1733 | if (mac_addr) | 1782 | if (mac_addr) |
1734 | memcpy(cmd.mac, mac_addr, WMI_MAC_LEN); | 1783 | memcpy(cmd.mac, mac_addr, WMI_MAC_LEN); |
1735 | 1784 | ||
1736 | return wmi_send(wil, WMI_DELETE_CIPHER_KEY_CMDID, &cmd, sizeof(cmd)); | 1785 | return wmi_send(wil, WMI_DELETE_CIPHER_KEY_CMDID, vif->mid, |
1786 | &cmd, sizeof(cmd)); | ||
1737 | } | 1787 | } |
1738 | 1788 | ||
1739 | int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, | 1789 | int wmi_add_cipher_key(struct wil6210_vif *vif, u8 key_index, |
1740 | const void *mac_addr, int key_len, const void *key, | 1790 | const void *mac_addr, int key_len, const void *key, |
1741 | int key_usage) | 1791 | int key_usage) |
1742 | { | 1792 | { |
1793 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1743 | struct wmi_add_cipher_key_cmd cmd = { | 1794 | struct wmi_add_cipher_key_cmd cmd = { |
1744 | .key_index = key_index, | 1795 | .key_index = key_index, |
1745 | .key_usage = key_usage, | 1796 | .key_usage = key_usage, |
@@ -1753,11 +1804,13 @@ int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, | |||
1753 | if (mac_addr) | 1804 | if (mac_addr) |
1754 | memcpy(cmd.mac, mac_addr, WMI_MAC_LEN); | 1805 | memcpy(cmd.mac, mac_addr, WMI_MAC_LEN); |
1755 | 1806 | ||
1756 | return wmi_send(wil, WMI_ADD_CIPHER_KEY_CMDID, &cmd, sizeof(cmd)); | 1807 | return wmi_send(wil, WMI_ADD_CIPHER_KEY_CMDID, vif->mid, |
1808 | &cmd, sizeof(cmd)); | ||
1757 | } | 1809 | } |
1758 | 1810 | ||
1759 | int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie) | 1811 | int wmi_set_ie(struct wil6210_vif *vif, u8 type, u16 ie_len, const void *ie) |
1760 | { | 1812 | { |
1813 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1761 | static const char *const names[] = { | 1814 | static const char *const names[] = { |
1762 | [WMI_FRAME_BEACON] = "BEACON", | 1815 | [WMI_FRAME_BEACON] = "BEACON", |
1763 | [WMI_FRAME_PROBE_REQ] = "PROBE_REQ", | 1816 | [WMI_FRAME_PROBE_REQ] = "PROBE_REQ", |
@@ -1786,7 +1839,7 @@ int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie) | |||
1786 | /* BUG: FW API define ieLen as u8. Will fix FW */ | 1839 | /* BUG: FW API define ieLen as u8. Will fix FW */ |
1787 | cmd->ie_len = cpu_to_le16(ie_len); | 1840 | cmd->ie_len = cpu_to_le16(ie_len); |
1788 | memcpy(cmd->ie_info, ie, ie_len); | 1841 | memcpy(cmd->ie_info, ie, ie_len); |
1789 | rc = wmi_send(wil, WMI_SET_APPIE_CMDID, cmd, len); | 1842 | rc = wmi_send(wil, WMI_SET_APPIE_CMDID, vif->mid, cmd, len); |
1790 | kfree(cmd); | 1843 | kfree(cmd); |
1791 | out: | 1844 | out: |
1792 | if (rc) { | 1845 | if (rc) { |
@@ -1808,6 +1861,7 @@ out: | |||
1808 | */ | 1861 | */ |
1809 | int wmi_rxon(struct wil6210_priv *wil, bool on) | 1862 | int wmi_rxon(struct wil6210_priv *wil, bool on) |
1810 | { | 1863 | { |
1864 | struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); | ||
1811 | int rc; | 1865 | int rc; |
1812 | struct { | 1866 | struct { |
1813 | struct wmi_cmd_hdr wmi; | 1867 | struct wmi_cmd_hdr wmi; |
@@ -1817,13 +1871,13 @@ int wmi_rxon(struct wil6210_priv *wil, bool on) | |||
1817 | wil_info(wil, "(%s)\n", on ? "on" : "off"); | 1871 | wil_info(wil, "(%s)\n", on ? "on" : "off"); |
1818 | 1872 | ||
1819 | if (on) { | 1873 | if (on) { |
1820 | rc = wmi_call(wil, WMI_START_LISTEN_CMDID, NULL, 0, | 1874 | rc = wmi_call(wil, WMI_START_LISTEN_CMDID, vif->mid, NULL, 0, |
1821 | WMI_LISTEN_STARTED_EVENTID, | 1875 | WMI_LISTEN_STARTED_EVENTID, |
1822 | &reply, sizeof(reply), 100); | 1876 | &reply, sizeof(reply), 100); |
1823 | if ((rc == 0) && (reply.evt.status != WMI_FW_STATUS_SUCCESS)) | 1877 | if ((rc == 0) && (reply.evt.status != WMI_FW_STATUS_SUCCESS)) |
1824 | rc = -EINVAL; | 1878 | rc = -EINVAL; |
1825 | } else { | 1879 | } else { |
1826 | rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, NULL, 0, | 1880 | rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, vif->mid, NULL, 0, |
1827 | WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 20); | 1881 | WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 20); |
1828 | } | 1882 | } |
1829 | 1883 | ||
@@ -1832,8 +1886,9 @@ int wmi_rxon(struct wil6210_priv *wil, bool on) | |||
1832 | 1886 | ||
1833 | int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) | 1887 | int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) |
1834 | { | 1888 | { |
1835 | struct wireless_dev *wdev = wil->wdev; | 1889 | struct net_device *ndev = wil->main_ndev; |
1836 | struct net_device *ndev = wil_to_ndev(wil); | 1890 | struct wireless_dev *wdev = ndev->ieee80211_ptr; |
1891 | struct wil6210_vif *vif = ndev_to_vif(ndev); | ||
1837 | struct wmi_cfg_rx_chain_cmd cmd = { | 1892 | struct wmi_cfg_rx_chain_cmd cmd = { |
1838 | .action = WMI_RX_CHAIN_ADD, | 1893 | .action = WMI_RX_CHAIN_ADD, |
1839 | .rx_sw_ring = { | 1894 | .rx_sw_ring = { |
@@ -1877,7 +1932,7 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) | |||
1877 | L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK; | 1932 | L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK; |
1878 | 1933 | ||
1879 | /* typical time for secure PCP is 840ms */ | 1934 | /* typical time for secure PCP is 840ms */ |
1880 | rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd), | 1935 | rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, vif->mid, &cmd, sizeof(cmd), |
1881 | WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000); | 1936 | WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000); |
1882 | if (rc) | 1937 | if (rc) |
1883 | return rc; | 1938 | return rc; |
@@ -1895,6 +1950,7 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) | |||
1895 | 1950 | ||
1896 | int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf) | 1951 | int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf) |
1897 | { | 1952 | { |
1953 | struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); | ||
1898 | int rc; | 1954 | int rc; |
1899 | struct wmi_temp_sense_cmd cmd = { | 1955 | struct wmi_temp_sense_cmd cmd = { |
1900 | .measure_baseband_en = cpu_to_le32(!!t_bb), | 1956 | .measure_baseband_en = cpu_to_le32(!!t_bb), |
@@ -1906,7 +1962,7 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf) | |||
1906 | struct wmi_temp_sense_done_event evt; | 1962 | struct wmi_temp_sense_done_event evt; |
1907 | } __packed reply; | 1963 | } __packed reply; |
1908 | 1964 | ||
1909 | rc = wmi_call(wil, WMI_TEMP_SENSE_CMDID, &cmd, sizeof(cmd), | 1965 | rc = wmi_call(wil, WMI_TEMP_SENSE_CMDID, vif->mid, &cmd, sizeof(cmd), |
1910 | WMI_TEMP_SENSE_DONE_EVENTID, &reply, sizeof(reply), 100); | 1966 | WMI_TEMP_SENSE_DONE_EVENTID, &reply, sizeof(reply), 100); |
1911 | if (rc) | 1967 | if (rc) |
1912 | return rc; | 1968 | return rc; |
@@ -1919,9 +1975,10 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf) | |||
1919 | return 0; | 1975 | return 0; |
1920 | } | 1976 | } |
1921 | 1977 | ||
1922 | int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, | 1978 | int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac, |
1923 | u16 reason, bool full_disconnect, bool del_sta) | 1979 | u16 reason, bool full_disconnect, bool del_sta) |
1924 | { | 1980 | { |
1981 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
1925 | int rc; | 1982 | int rc; |
1926 | u16 reason_code; | 1983 | u16 reason_code; |
1927 | struct wmi_disconnect_sta_cmd disc_sta_cmd = { | 1984 | struct wmi_disconnect_sta_cmd disc_sta_cmd = { |
@@ -1937,16 +1994,17 @@ int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, | |||
1937 | 1994 | ||
1938 | wil_dbg_wmi(wil, "disconnect_sta: (%pM, reason %d)\n", mac, reason); | 1995 | wil_dbg_wmi(wil, "disconnect_sta: (%pM, reason %d)\n", mac, reason); |
1939 | 1996 | ||
1940 | wil->locally_generated_disc = true; | 1997 | vif->locally_generated_disc = true; |
1941 | if (del_sta) { | 1998 | if (del_sta) { |
1942 | ether_addr_copy(del_sta_cmd.dst_mac, mac); | 1999 | ether_addr_copy(del_sta_cmd.dst_mac, mac); |
1943 | rc = wmi_call(wil, WMI_DEL_STA_CMDID, &del_sta_cmd, | 2000 | rc = wmi_call(wil, WMI_DEL_STA_CMDID, vif->mid, &del_sta_cmd, |
1944 | sizeof(del_sta_cmd), WMI_DISCONNECT_EVENTID, | 2001 | sizeof(del_sta_cmd), WMI_DISCONNECT_EVENTID, |
1945 | &reply, sizeof(reply), 1000); | 2002 | &reply, sizeof(reply), 1000); |
1946 | } else { | 2003 | } else { |
1947 | ether_addr_copy(disc_sta_cmd.dst_mac, mac); | 2004 | ether_addr_copy(disc_sta_cmd.dst_mac, mac); |
1948 | rc = wmi_call(wil, WMI_DISCONNECT_STA_CMDID, &disc_sta_cmd, | 2005 | rc = wmi_call(wil, WMI_DISCONNECT_STA_CMDID, vif->mid, |
1949 | sizeof(disc_sta_cmd), WMI_DISCONNECT_EVENTID, | 2006 | &disc_sta_cmd, sizeof(disc_sta_cmd), |
2007 | WMI_DISCONNECT_EVENTID, | ||
1950 | &reply, sizeof(reply), 1000); | 2008 | &reply, sizeof(reply), 1000); |
1951 | } | 2009 | } |
1952 | /* failure to disconnect in reasonable time treated as FW error */ | 2010 | /* failure to disconnect in reasonable time treated as FW error */ |
@@ -1967,12 +2025,13 @@ int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, | |||
1967 | reply.evt.disconnect_reason); | 2025 | reply.evt.disconnect_reason); |
1968 | 2026 | ||
1969 | wil->sinfo_gen++; | 2027 | wil->sinfo_gen++; |
1970 | wil6210_disconnect(wil, reply.evt.bssid, reason_code, true); | 2028 | wil6210_disconnect(vif, reply.evt.bssid, reason_code, true); |
1971 | } | 2029 | } |
1972 | return 0; | 2030 | return 0; |
1973 | } | 2031 | } |
1974 | 2032 | ||
1975 | int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout) | 2033 | int wmi_addba(struct wil6210_priv *wil, u8 mid, |
2034 | u8 ringid, u8 size, u16 timeout) | ||
1976 | { | 2035 | { |
1977 | struct wmi_vring_ba_en_cmd cmd = { | 2036 | struct wmi_vring_ba_en_cmd cmd = { |
1978 | .ringid = ringid, | 2037 | .ringid = ringid, |
@@ -1984,10 +2043,10 @@ int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout) | |||
1984 | wil_dbg_wmi(wil, "addba: (ring %d size %d timeout %d)\n", ringid, size, | 2043 | wil_dbg_wmi(wil, "addba: (ring %d size %d timeout %d)\n", ringid, size, |
1985 | timeout); | 2044 | timeout); |
1986 | 2045 | ||
1987 | return wmi_send(wil, WMI_VRING_BA_EN_CMDID, &cmd, sizeof(cmd)); | 2046 | return wmi_send(wil, WMI_VRING_BA_EN_CMDID, mid, &cmd, sizeof(cmd)); |
1988 | } | 2047 | } |
1989 | 2048 | ||
1990 | int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason) | 2049 | int wmi_delba_tx(struct wil6210_priv *wil, u8 mid, u8 ringid, u16 reason) |
1991 | { | 2050 | { |
1992 | struct wmi_vring_ba_dis_cmd cmd = { | 2051 | struct wmi_vring_ba_dis_cmd cmd = { |
1993 | .ringid = ringid, | 2052 | .ringid = ringid, |
@@ -1996,10 +2055,10 @@ int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason) | |||
1996 | 2055 | ||
1997 | wil_dbg_wmi(wil, "delba_tx: (ring %d reason %d)\n", ringid, reason); | 2056 | wil_dbg_wmi(wil, "delba_tx: (ring %d reason %d)\n", ringid, reason); |
1998 | 2057 | ||
1999 | return wmi_send(wil, WMI_VRING_BA_DIS_CMDID, &cmd, sizeof(cmd)); | 2058 | return wmi_send(wil, WMI_VRING_BA_DIS_CMDID, mid, &cmd, sizeof(cmd)); |
2000 | } | 2059 | } |
2001 | 2060 | ||
2002 | int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason) | 2061 | int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cidxtid, u16 reason) |
2003 | { | 2062 | { |
2004 | struct wmi_rcp_delba_cmd cmd = { | 2063 | struct wmi_rcp_delba_cmd cmd = { |
2005 | .cidxtid = cidxtid, | 2064 | .cidxtid = cidxtid, |
@@ -2009,10 +2068,11 @@ int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason) | |||
2009 | wil_dbg_wmi(wil, "delba_rx: (CID %d TID %d reason %d)\n", cidxtid & 0xf, | 2068 | wil_dbg_wmi(wil, "delba_rx: (CID %d TID %d reason %d)\n", cidxtid & 0xf, |
2010 | (cidxtid >> 4) & 0xf, reason); | 2069 | (cidxtid >> 4) & 0xf, reason); |
2011 | 2070 | ||
2012 | return wmi_send(wil, WMI_RCP_DELBA_CMDID, &cmd, sizeof(cmd)); | 2071 | return wmi_send(wil, WMI_RCP_DELBA_CMDID, mid, &cmd, sizeof(cmd)); |
2013 | } | 2072 | } |
2014 | 2073 | ||
2015 | int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token, | 2074 | int wmi_addba_rx_resp(struct wil6210_priv *wil, |
2075 | u8 mid, u8 cid, u8 tid, u8 token, | ||
2016 | u16 status, bool amsdu, u16 agg_wsize, u16 timeout) | 2076 | u16 status, bool amsdu, u16 agg_wsize, u16 timeout) |
2017 | { | 2077 | { |
2018 | int rc; | 2078 | int rc; |
@@ -2035,10 +2095,11 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token, | |||
2035 | } __packed reply; | 2095 | } __packed reply; |
2036 | 2096 | ||
2037 | wil_dbg_wmi(wil, | 2097 | wil_dbg_wmi(wil, |
2038 | "ADDBA response for CID %d TID %d size %d timeout %d status %d AMSDU%s\n", | 2098 | "ADDBA response for MID %d CID %d TID %d size %d timeout %d status %d AMSDU%s\n", |
2039 | cid, tid, agg_wsize, timeout, status, amsdu ? "+" : "-"); | 2099 | mid, cid, tid, agg_wsize, |
2100 | timeout, status, amsdu ? "+" : "-"); | ||
2040 | 2101 | ||
2041 | rc = wmi_call(wil, WMI_RCP_ADDBA_RESP_CMDID, &cmd, sizeof(cmd), | 2102 | rc = wmi_call(wil, WMI_RCP_ADDBA_RESP_CMDID, mid, &cmd, sizeof(cmd), |
2042 | WMI_RCP_ADDBA_RESP_SENT_EVENTID, &reply, sizeof(reply), | 2103 | WMI_RCP_ADDBA_RESP_SENT_EVENTID, &reply, sizeof(reply), |
2043 | 100); | 2104 | 100); |
2044 | if (rc) | 2105 | if (rc) |
@@ -2056,6 +2117,7 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token, | |||
2056 | int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil, | 2117 | int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil, |
2057 | enum wmi_ps_profile_type ps_profile) | 2118 | enum wmi_ps_profile_type ps_profile) |
2058 | { | 2119 | { |
2120 | struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); | ||
2059 | int rc; | 2121 | int rc; |
2060 | struct wmi_ps_dev_profile_cfg_cmd cmd = { | 2122 | struct wmi_ps_dev_profile_cfg_cmd cmd = { |
2061 | .ps_profile = ps_profile, | 2123 | .ps_profile = ps_profile, |
@@ -2070,7 +2132,8 @@ int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil, | |||
2070 | 2132 | ||
2071 | reply.evt.status = cpu_to_le32(WMI_PS_CFG_CMD_STATUS_ERROR); | 2133 | reply.evt.status = cpu_to_le32(WMI_PS_CFG_CMD_STATUS_ERROR); |
2072 | 2134 | ||
2073 | rc = wmi_call(wil, WMI_PS_DEV_PROFILE_CFG_CMDID, &cmd, sizeof(cmd), | 2135 | rc = wmi_call(wil, WMI_PS_DEV_PROFILE_CFG_CMDID, vif->mid, |
2136 | &cmd, sizeof(cmd), | ||
2074 | WMI_PS_DEV_PROFILE_CFG_EVENTID, &reply, sizeof(reply), | 2137 | WMI_PS_DEV_PROFILE_CFG_EVENTID, &reply, sizeof(reply), |
2075 | 100); | 2138 | 100); |
2076 | if (rc) | 2139 | if (rc) |
@@ -2089,6 +2152,7 @@ int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil, | |||
2089 | 2152 | ||
2090 | int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short) | 2153 | int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short) |
2091 | { | 2154 | { |
2155 | struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); | ||
2092 | int rc; | 2156 | int rc; |
2093 | struct wmi_set_mgmt_retry_limit_cmd cmd = { | 2157 | struct wmi_set_mgmt_retry_limit_cmd cmd = { |
2094 | .mgmt_retry_limit = retry_short, | 2158 | .mgmt_retry_limit = retry_short, |
@@ -2105,7 +2169,8 @@ int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short) | |||
2105 | 2169 | ||
2106 | reply.evt.status = WMI_FW_STATUS_FAILURE; | 2170 | reply.evt.status = WMI_FW_STATUS_FAILURE; |
2107 | 2171 | ||
2108 | rc = wmi_call(wil, WMI_SET_MGMT_RETRY_LIMIT_CMDID, &cmd, sizeof(cmd), | 2172 | rc = wmi_call(wil, WMI_SET_MGMT_RETRY_LIMIT_CMDID, vif->mid, |
2173 | &cmd, sizeof(cmd), | ||
2109 | WMI_SET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply), | 2174 | WMI_SET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply), |
2110 | 100); | 2175 | 100); |
2111 | if (rc) | 2176 | if (rc) |
@@ -2122,6 +2187,7 @@ int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short) | |||
2122 | 2187 | ||
2123 | int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short) | 2188 | int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short) |
2124 | { | 2189 | { |
2190 | struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); | ||
2125 | int rc; | 2191 | int rc; |
2126 | struct { | 2192 | struct { |
2127 | struct wmi_cmd_hdr wmi; | 2193 | struct wmi_cmd_hdr wmi; |
@@ -2134,7 +2200,7 @@ int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short) | |||
2134 | return -ENOTSUPP; | 2200 | return -ENOTSUPP; |
2135 | 2201 | ||
2136 | reply.evt.mgmt_retry_limit = 0; | 2202 | reply.evt.mgmt_retry_limit = 0; |
2137 | rc = wmi_call(wil, WMI_GET_MGMT_RETRY_LIMIT_CMDID, NULL, 0, | 2203 | rc = wmi_call(wil, WMI_GET_MGMT_RETRY_LIMIT_CMDID, vif->mid, NULL, 0, |
2138 | WMI_GET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply), | 2204 | WMI_GET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply), |
2139 | 100); | 2205 | 100); |
2140 | if (rc) | 2206 | if (rc) |
@@ -2146,21 +2212,23 @@ int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short) | |||
2146 | return 0; | 2212 | return 0; |
2147 | } | 2213 | } |
2148 | 2214 | ||
2149 | int wmi_abort_scan(struct wil6210_priv *wil) | 2215 | int wmi_abort_scan(struct wil6210_vif *vif) |
2150 | { | 2216 | { |
2217 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
2151 | int rc; | 2218 | int rc; |
2152 | 2219 | ||
2153 | wil_dbg_wmi(wil, "sending WMI_ABORT_SCAN_CMDID\n"); | 2220 | wil_dbg_wmi(wil, "sending WMI_ABORT_SCAN_CMDID\n"); |
2154 | 2221 | ||
2155 | rc = wmi_send(wil, WMI_ABORT_SCAN_CMDID, NULL, 0); | 2222 | rc = wmi_send(wil, WMI_ABORT_SCAN_CMDID, vif->mid, NULL, 0); |
2156 | if (rc) | 2223 | if (rc) |
2157 | wil_err(wil, "Failed to abort scan (%d)\n", rc); | 2224 | wil_err(wil, "Failed to abort scan (%d)\n", rc); |
2158 | 2225 | ||
2159 | return rc; | 2226 | return rc; |
2160 | } | 2227 | } |
2161 | 2228 | ||
2162 | int wmi_new_sta(struct wil6210_priv *wil, const u8 *mac, u8 aid) | 2229 | int wmi_new_sta(struct wil6210_vif *vif, const u8 *mac, u8 aid) |
2163 | { | 2230 | { |
2231 | struct wil6210_priv *wil = vif_to_wil(vif); | ||
2164 | int rc; | 2232 | int rc; |
2165 | struct wmi_new_sta_cmd cmd = { | 2233 | struct wmi_new_sta_cmd cmd = { |
2166 | .aid = aid, | 2234 | .aid = aid, |
@@ -2170,7 +2238,7 @@ int wmi_new_sta(struct wil6210_priv *wil, const u8 *mac, u8 aid) | |||
2170 | 2238 | ||
2171 | ether_addr_copy(cmd.dst_mac, mac); | 2239 | ether_addr_copy(cmd.dst_mac, mac); |
2172 | 2240 | ||
2173 | rc = wmi_send(wil, WMI_NEW_STA_CMDID, &cmd, sizeof(cmd)); | 2241 | rc = wmi_send(wil, WMI_NEW_STA_CMDID, vif->mid, &cmd, sizeof(cmd)); |
2174 | if (rc) | 2242 | if (rc) |
2175 | wil_err(wil, "Failed to send new sta (%d)\n", rc); | 2243 | wil_err(wil, "Failed to send new sta (%d)\n", rc); |
2176 | 2244 | ||
@@ -2206,6 +2274,7 @@ static const char *suspend_status2name(u8 status) | |||
2206 | 2274 | ||
2207 | int wmi_suspend(struct wil6210_priv *wil) | 2275 | int wmi_suspend(struct wil6210_priv *wil) |
2208 | { | 2276 | { |
2277 | struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); | ||
2209 | int rc; | 2278 | int rc; |
2210 | struct wmi_traffic_suspend_cmd cmd = { | 2279 | struct wmi_traffic_suspend_cmd cmd = { |
2211 | .wakeup_trigger = wil->wakeup_trigger, | 2280 | .wakeup_trigger = wil->wakeup_trigger, |
@@ -2221,7 +2290,8 @@ int wmi_suspend(struct wil6210_priv *wil) | |||
2221 | 2290 | ||
2222 | reply.evt.status = WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE; | 2291 | reply.evt.status = WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE; |
2223 | 2292 | ||
2224 | rc = wmi_call(wil, WMI_TRAFFIC_SUSPEND_CMDID, &cmd, sizeof(cmd), | 2293 | rc = wmi_call(wil, WMI_TRAFFIC_SUSPEND_CMDID, vif->mid, |
2294 | &cmd, sizeof(cmd), | ||
2225 | WMI_TRAFFIC_SUSPEND_EVENTID, &reply, sizeof(reply), | 2295 | WMI_TRAFFIC_SUSPEND_EVENTID, &reply, sizeof(reply), |
2226 | suspend_to); | 2296 | suspend_to); |
2227 | if (rc) { | 2297 | if (rc) { |
@@ -2289,6 +2359,7 @@ static void resume_triggers2string(u32 triggers, char *string, int str_size) | |||
2289 | 2359 | ||
2290 | int wmi_resume(struct wil6210_priv *wil) | 2360 | int wmi_resume(struct wil6210_priv *wil) |
2291 | { | 2361 | { |
2362 | struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); | ||
2292 | int rc; | 2363 | int rc; |
2293 | char string[100]; | 2364 | char string[100]; |
2294 | struct { | 2365 | struct { |
@@ -2299,7 +2370,7 @@ int wmi_resume(struct wil6210_priv *wil) | |||
2299 | reply.evt.status = WMI_TRAFFIC_RESUME_FAILED; | 2370 | reply.evt.status = WMI_TRAFFIC_RESUME_FAILED; |
2300 | reply.evt.resume_triggers = WMI_RESUME_TRIGGER_UNKNOWN; | 2371 | reply.evt.resume_triggers = WMI_RESUME_TRIGGER_UNKNOWN; |
2301 | 2372 | ||
2302 | rc = wmi_call(wil, WMI_TRAFFIC_RESUME_CMDID, NULL, 0, | 2373 | rc = wmi_call(wil, WMI_TRAFFIC_RESUME_CMDID, vif->mid, NULL, 0, |
2303 | WMI_TRAFFIC_RESUME_EVENTID, &reply, sizeof(reply), | 2374 | WMI_TRAFFIC_RESUME_EVENTID, &reply, sizeof(reply), |
2304 | WIL_WAIT_FOR_SUSPEND_RESUME_COMP); | 2375 | WIL_WAIT_FOR_SUSPEND_RESUME_COMP); |
2305 | if (rc) | 2376 | if (rc) |
@@ -2313,14 +2384,100 @@ int wmi_resume(struct wil6210_priv *wil) | |||
2313 | return reply.evt.status; | 2384 | return reply.evt.status; |
2314 | } | 2385 | } |
2315 | 2386 | ||
2316 | static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id, | 2387 | int wmi_port_allocate(struct wil6210_priv *wil, u8 mid, |
2388 | const u8 *mac, enum nl80211_iftype iftype) | ||
2389 | { | ||
2390 | int rc; | ||
2391 | struct wmi_port_allocate_cmd cmd = { | ||
2392 | .mid = mid, | ||
2393 | }; | ||
2394 | struct { | ||
2395 | struct wmi_cmd_hdr wmi; | ||
2396 | struct wmi_port_allocated_event evt; | ||
2397 | } __packed reply; | ||
2398 | |||
2399 | wil_dbg_misc(wil, "port allocate, mid %d iftype %d, mac %pM\n", | ||
2400 | mid, iftype, mac); | ||
2401 | |||
2402 | ether_addr_copy(cmd.mac, mac); | ||
2403 | switch (iftype) { | ||
2404 | case NL80211_IFTYPE_STATION: | ||
2405 | cmd.port_role = WMI_PORT_STA; | ||
2406 | break; | ||
2407 | case NL80211_IFTYPE_AP: | ||
2408 | cmd.port_role = WMI_PORT_AP; | ||
2409 | break; | ||
2410 | case NL80211_IFTYPE_P2P_CLIENT: | ||
2411 | cmd.port_role = WMI_PORT_P2P_CLIENT; | ||
2412 | break; | ||
2413 | case NL80211_IFTYPE_P2P_GO: | ||
2414 | cmd.port_role = WMI_PORT_P2P_GO; | ||
2415 | break; | ||
2416 | /* what about monitor??? */ | ||
2417 | default: | ||
2418 | wil_err(wil, "unsupported iftype: %d\n", iftype); | ||
2419 | return -EINVAL; | ||
2420 | } | ||
2421 | |||
2422 | reply.evt.status = WMI_FW_STATUS_FAILURE; | ||
2423 | |||
2424 | rc = wmi_call(wil, WMI_PORT_ALLOCATE_CMDID, mid, | ||
2425 | &cmd, sizeof(cmd), | ||
2426 | WMI_PORT_ALLOCATED_EVENTID, &reply, | ||
2427 | sizeof(reply), 300); | ||
2428 | if (rc) { | ||
2429 | wil_err(wil, "failed to allocate port, status %d\n", rc); | ||
2430 | return rc; | ||
2431 | } | ||
2432 | if (reply.evt.status != WMI_FW_STATUS_SUCCESS) { | ||
2433 | wil_err(wil, "WMI_PORT_ALLOCATE returned status %d\n", | ||
2434 | reply.evt.status); | ||
2435 | return -EINVAL; | ||
2436 | } | ||
2437 | |||
2438 | return 0; | ||
2439 | } | ||
2440 | |||
2441 | int wmi_port_delete(struct wil6210_priv *wil, u8 mid) | ||
2442 | { | ||
2443 | int rc; | ||
2444 | struct wmi_port_delete_cmd cmd = { | ||
2445 | .mid = mid, | ||
2446 | }; | ||
2447 | struct { | ||
2448 | struct wmi_cmd_hdr wmi; | ||
2449 | struct wmi_port_deleted_event evt; | ||
2450 | } __packed reply; | ||
2451 | |||
2452 | wil_dbg_misc(wil, "port delete, mid %d\n", mid); | ||
2453 | |||
2454 | reply.evt.status = WMI_FW_STATUS_FAILURE; | ||
2455 | |||
2456 | rc = wmi_call(wil, WMI_PORT_DELETE_CMDID, mid, | ||
2457 | &cmd, sizeof(cmd), | ||
2458 | WMI_PORT_DELETED_EVENTID, &reply, | ||
2459 | sizeof(reply), 2000); | ||
2460 | if (rc) { | ||
2461 | wil_err(wil, "failed to delete port, status %d\n", rc); | ||
2462 | return rc; | ||
2463 | } | ||
2464 | if (reply.evt.status != WMI_FW_STATUS_SUCCESS) { | ||
2465 | wil_err(wil, "WMI_PORT_DELETE returned status %d\n", | ||
2466 | reply.evt.status); | ||
2467 | return -EINVAL; | ||
2468 | } | ||
2469 | |||
2470 | return 0; | ||
2471 | } | ||
2472 | |||
2473 | static bool wmi_evt_call_handler(struct wil6210_vif *vif, int id, | ||
2317 | void *d, int len) | 2474 | void *d, int len) |
2318 | { | 2475 | { |
2319 | uint i; | 2476 | uint i; |
2320 | 2477 | ||
2321 | for (i = 0; i < ARRAY_SIZE(wmi_evt_handlers); i++) { | 2478 | for (i = 0; i < ARRAY_SIZE(wmi_evt_handlers); i++) { |
2322 | if (wmi_evt_handlers[i].eventid == id) { | 2479 | if (wmi_evt_handlers[i].eventid == id) { |
2323 | wmi_evt_handlers[i].handler(wil, id, d, len); | 2480 | wmi_evt_handlers[i].handler(vif, id, d, len); |
2324 | return true; | 2481 | return true; |
2325 | } | 2482 | } |
2326 | } | 2483 | } |
@@ -2332,19 +2489,39 @@ static void wmi_event_handle(struct wil6210_priv *wil, | |||
2332 | struct wil6210_mbox_hdr *hdr) | 2489 | struct wil6210_mbox_hdr *hdr) |
2333 | { | 2490 | { |
2334 | u16 len = le16_to_cpu(hdr->len); | 2491 | u16 len = le16_to_cpu(hdr->len); |
2492 | struct wil6210_vif *vif; | ||
2335 | 2493 | ||
2336 | if ((hdr->type == WIL_MBOX_HDR_TYPE_WMI) && | 2494 | if ((hdr->type == WIL_MBOX_HDR_TYPE_WMI) && |
2337 | (len >= sizeof(struct wmi_cmd_hdr))) { | 2495 | (len >= sizeof(struct wmi_cmd_hdr))) { |
2338 | struct wmi_cmd_hdr *wmi = (void *)(&hdr[1]); | 2496 | struct wmi_cmd_hdr *wmi = (void *)(&hdr[1]); |
2339 | void *evt_data = (void *)(&wmi[1]); | 2497 | void *evt_data = (void *)(&wmi[1]); |
2340 | u16 id = le16_to_cpu(wmi->command_id); | 2498 | u16 id = le16_to_cpu(wmi->command_id); |
2499 | u8 mid = wmi->mid; | ||
2500 | |||
2501 | wil_dbg_wmi(wil, "Handle %s (0x%04x) (reply_id 0x%04x,%d)\n", | ||
2502 | eventid2name(id), id, wil->reply_id, | ||
2503 | wil->reply_mid); | ||
2504 | |||
2505 | if (mid == MID_BROADCAST) | ||
2506 | mid = 0; | ||
2507 | if (mid >= wil->max_vifs) { | ||
2508 | wil_dbg_wmi(wil, "invalid mid %d, event skipped\n", | ||
2509 | mid); | ||
2510 | return; | ||
2511 | } | ||
2512 | vif = wil->vifs[mid]; | ||
2513 | if (!vif) { | ||
2514 | wil_dbg_wmi(wil, "event for empty VIF(%d), skipped\n", | ||
2515 | mid); | ||
2516 | return; | ||
2517 | } | ||
2341 | 2518 | ||
2342 | wil_dbg_wmi(wil, "Handle %s (0x%04x) (reply_id 0x%04x)\n", | ||
2343 | eventid2name(id), id, wil->reply_id); | ||
2344 | /* check if someone waits for this event */ | 2519 | /* check if someone waits for this event */ |
2345 | if (wil->reply_id && wil->reply_id == id) { | 2520 | if (wil->reply_id && wil->reply_id == id && |
2521 | wil->reply_mid == mid) { | ||
2346 | WARN_ON(wil->reply_buf); | 2522 | WARN_ON(wil->reply_buf); |
2347 | wmi_evt_call_handler(wil, id, evt_data, | 2523 | |
2524 | wmi_evt_call_handler(vif, id, evt_data, | ||
2348 | len - sizeof(*wmi)); | 2525 | len - sizeof(*wmi)); |
2349 | wil_dbg_wmi(wil, "event_handle: Complete WMI 0x%04x\n", | 2526 | wil_dbg_wmi(wil, "event_handle: Complete WMI 0x%04x\n", |
2350 | id); | 2527 | id); |
@@ -2353,7 +2530,7 @@ static void wmi_event_handle(struct wil6210_priv *wil, | |||
2353 | } | 2530 | } |
2354 | /* unsolicited event */ | 2531 | /* unsolicited event */ |
2355 | /* search for handler */ | 2532 | /* search for handler */ |
2356 | if (!wmi_evt_call_handler(wil, id, evt_data, | 2533 | if (!wmi_evt_call_handler(vif, id, evt_data, |
2357 | len - sizeof(*wmi))) { | 2534 | len - sizeof(*wmi))) { |
2358 | wil_info(wil, "Unhandled event 0x%04x\n", id); | 2535 | wil_info(wil, "Unhandled event 0x%04x\n", id); |
2359 | } | 2536 | } |
@@ -2523,6 +2700,7 @@ wmi_sched_scan_set_plans(struct wil6210_priv *wil, | |||
2523 | int wmi_start_sched_scan(struct wil6210_priv *wil, | 2700 | int wmi_start_sched_scan(struct wil6210_priv *wil, |
2524 | struct cfg80211_sched_scan_request *request) | 2701 | struct cfg80211_sched_scan_request *request) |
2525 | { | 2702 | { |
2703 | struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); | ||
2526 | int rc; | 2704 | int rc; |
2527 | struct wmi_start_sched_scan_cmd cmd = { | 2705 | struct wmi_start_sched_scan_cmd cmd = { |
2528 | .min_rssi_threshold = S8_MIN, | 2706 | .min_rssi_threshold = S8_MIN, |
@@ -2549,7 +2727,8 @@ int wmi_start_sched_scan(struct wil6210_priv *wil, | |||
2549 | 2727 | ||
2550 | reply.evt.result = WMI_PNO_REJECT; | 2728 | reply.evt.result = WMI_PNO_REJECT; |
2551 | 2729 | ||
2552 | rc = wmi_call(wil, WMI_START_SCHED_SCAN_CMDID, &cmd, sizeof(cmd), | 2730 | rc = wmi_call(wil, WMI_START_SCHED_SCAN_CMDID, vif->mid, |
2731 | &cmd, sizeof(cmd), | ||
2553 | WMI_START_SCHED_SCAN_EVENTID, &reply, sizeof(reply), | 2732 | WMI_START_SCHED_SCAN_EVENTID, &reply, sizeof(reply), |
2554 | WIL_WMI_CALL_GENERAL_TO_MS); | 2733 | WIL_WMI_CALL_GENERAL_TO_MS); |
2555 | if (rc) | 2734 | if (rc) |
@@ -2566,6 +2745,7 @@ int wmi_start_sched_scan(struct wil6210_priv *wil, | |||
2566 | 2745 | ||
2567 | int wmi_stop_sched_scan(struct wil6210_priv *wil) | 2746 | int wmi_stop_sched_scan(struct wil6210_priv *wil) |
2568 | { | 2747 | { |
2748 | struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); | ||
2569 | int rc; | 2749 | int rc; |
2570 | struct { | 2750 | struct { |
2571 | struct wmi_cmd_hdr wmi; | 2751 | struct wmi_cmd_hdr wmi; |
@@ -2577,7 +2757,7 @@ int wmi_stop_sched_scan(struct wil6210_priv *wil) | |||
2577 | 2757 | ||
2578 | reply.evt.result = WMI_PNO_REJECT; | 2758 | reply.evt.result = WMI_PNO_REJECT; |
2579 | 2759 | ||
2580 | rc = wmi_call(wil, WMI_STOP_SCHED_SCAN_CMDID, NULL, 0, | 2760 | rc = wmi_call(wil, WMI_STOP_SCHED_SCAN_CMDID, vif->mid, NULL, 0, |
2581 | WMI_STOP_SCHED_SCAN_EVENTID, &reply, sizeof(reply), | 2761 | WMI_STOP_SCHED_SCAN_EVENTID, &reply, sizeof(reply), |
2582 | WIL_WMI_CALL_GENERAL_TO_MS); | 2762 | WIL_WMI_CALL_GENERAL_TO_MS); |
2583 | if (rc) | 2763 | if (rc) |