diff options
author | John W. Linville <linville@tuxdriver.com> | 2014-01-17 14:43:17 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-01-17 14:43:17 -0500 |
commit | 7916a075571f0ccd0830cf3da293188a8b6045e3 (patch) | |
tree | 119c5bb9e513c8205efed485c2dc7b8271123326 /drivers/net/wireless | |
parent | cf84eb0b09c0f09b4c70a648b9dfeec78be61f07 (diff) | |
parent | e4e19c031901e95dc7d1cf0a2c9c50525d71651f (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Diffstat (limited to 'drivers/net/wireless')
84 files changed, 2580 insertions, 1497 deletions
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 55eda7afc041..f35f93c31b09 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c | |||
@@ -1865,7 +1865,6 @@ static int adm8211_probe(struct pci_dev *pdev, | |||
1865 | dev->flags = IEEE80211_HW_SIGNAL_UNSPEC; | 1865 | dev->flags = IEEE80211_HW_SIGNAL_UNSPEC; |
1866 | dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | 1866 | dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); |
1867 | 1867 | ||
1868 | dev->channel_change_time = 1000; | ||
1869 | dev->max_signal = 100; /* FIXME: find better value */ | 1868 | dev->max_signal = 100; /* FIXME: find better value */ |
1870 | 1869 | ||
1871 | dev->queues = 1; /* ADM8211C supports more, maybe ADM8211B too */ | 1870 | dev->queues = 1; /* ADM8211C supports more, maybe ADM8211B too */ |
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 031d4ec64779..99b3bfa717d5 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c | |||
@@ -2112,7 +2112,6 @@ static struct at76_priv *at76_alloc_new_device(struct usb_device *udev) | |||
2112 | priv->pm_period = 0; | 2112 | priv->pm_period = 0; |
2113 | 2113 | ||
2114 | /* unit us */ | 2114 | /* unit us */ |
2115 | priv->hw->channel_change_time = 100000; | ||
2116 | 2115 | ||
2117 | return priv; | 2116 | return priv; |
2118 | } | 2117 | } |
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index e0ba7cd14252..b59cfbe0276b 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h | |||
@@ -17,6 +17,7 @@ | |||
17 | #ifndef ATH_H | 17 | #ifndef ATH_H |
18 | #define ATH_H | 18 | #define ATH_H |
19 | 19 | ||
20 | #include <linux/etherdevice.h> | ||
20 | #include <linux/skbuff.h> | 21 | #include <linux/skbuff.h> |
21 | #include <linux/if_ether.h> | 22 | #include <linux/if_ether.h> |
22 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
@@ -165,6 +166,7 @@ struct ath_common { | |||
165 | struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, | 166 | struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, |
166 | u32 len, | 167 | u32 len, |
167 | gfp_t gfp_mask); | 168 | gfp_t gfp_mask); |
169 | bool ath_is_mybeacon(struct ath_common *common, struct ieee80211_hdr *hdr); | ||
168 | 170 | ||
169 | void ath_hw_setbssidmask(struct ath_common *common); | 171 | void ath_hw_setbssidmask(struct ath_common *common); |
170 | void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key); | 172 | void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key); |
diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig index 82e8088ca9b4..a6f5285235af 100644 --- a/drivers/net/wireless/ath/ath10k/Kconfig +++ b/drivers/net/wireless/ath/ath10k/Kconfig | |||
@@ -37,3 +37,10 @@ config ATH10K_TRACING | |||
37 | ---help--- | 37 | ---help--- |
38 | Select this to ath10k use tracing infrastructure. | 38 | Select this to ath10k use tracing infrastructure. |
39 | 39 | ||
40 | config ATH10K_DFS_CERTIFIED | ||
41 | bool "Atheros DFS support for certified platforms" | ||
42 | depends on ATH10K && CFG80211_CERTIFICATION_ONUS | ||
43 | default n | ||
44 | ---help--- | ||
45 | This option enables DFS support for initiating radiation on | ||
46 | ath10k. | ||
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 79726e0fe2f0..ade1781c7186 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h | |||
@@ -253,6 +253,9 @@ struct ath10k_vif { | |||
253 | u8 bssid[ETH_ALEN]; | 253 | u8 bssid[ETH_ALEN]; |
254 | } ibss; | 254 | } ibss; |
255 | } u; | 255 | } u; |
256 | |||
257 | u8 fixed_rate; | ||
258 | u8 fixed_nss; | ||
256 | }; | 259 | }; |
257 | 260 | ||
258 | struct ath10k_vif_iter { | 261 | struct ath10k_vif_iter { |
@@ -272,6 +275,8 @@ struct ath10k_debug { | |||
272 | struct delayed_work htt_stats_dwork; | 275 | struct delayed_work htt_stats_dwork; |
273 | struct ath10k_dfs_stats dfs_stats; | 276 | struct ath10k_dfs_stats dfs_stats; |
274 | struct ath_dfs_pool_stats dfs_pool_stats; | 277 | struct ath_dfs_pool_stats dfs_pool_stats; |
278 | |||
279 | u32 fw_dbglog_mask; | ||
275 | }; | 280 | }; |
276 | 281 | ||
277 | enum ath10k_state { | 282 | enum ath10k_state { |
@@ -306,6 +311,9 @@ enum ath10k_fw_features { | |||
306 | /* firmware support tx frame management over WMI, otherwise it's HTT */ | 311 | /* firmware support tx frame management over WMI, otherwise it's HTT */ |
307 | ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX = 2, | 312 | ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX = 2, |
308 | 313 | ||
314 | /* Firmware does not support P2P */ | ||
315 | ATH10K_FW_FEATURE_NO_P2P = 3, | ||
316 | |||
309 | /* keep last */ | 317 | /* keep last */ |
310 | ATH10K_FW_FEATURE_COUNT, | 318 | ATH10K_FW_FEATURE_COUNT, |
311 | }; | 319 | }; |
@@ -429,6 +437,9 @@ struct ath10k { | |||
429 | struct list_head peers; | 437 | struct list_head peers; |
430 | wait_queue_head_t peer_mapping_wq; | 438 | wait_queue_head_t peer_mapping_wq; |
431 | 439 | ||
440 | /* number of created peers; protected by data_lock */ | ||
441 | int num_peers; | ||
442 | |||
432 | struct work_struct offchan_tx_work; | 443 | struct work_struct offchan_tx_work; |
433 | struct sk_buff_head offchan_tx_queue; | 444 | struct sk_buff_head offchan_tx_queue; |
434 | struct completion offchan_tx_completed; | 445 | struct completion offchan_tx_completed; |
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 6bdfad3144af..6debd281350a 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c | |||
@@ -614,6 +614,61 @@ static const struct file_operations fops_htt_stats_mask = { | |||
614 | .llseek = default_llseek, | 614 | .llseek = default_llseek, |
615 | }; | 615 | }; |
616 | 616 | ||
617 | static ssize_t ath10k_read_fw_dbglog(struct file *file, | ||
618 | char __user *user_buf, | ||
619 | size_t count, loff_t *ppos) | ||
620 | { | ||
621 | struct ath10k *ar = file->private_data; | ||
622 | unsigned int len; | ||
623 | char buf[32]; | ||
624 | |||
625 | len = scnprintf(buf, sizeof(buf), "0x%08x\n", | ||
626 | ar->debug.fw_dbglog_mask); | ||
627 | |||
628 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
629 | } | ||
630 | |||
631 | static ssize_t ath10k_write_fw_dbglog(struct file *file, | ||
632 | const char __user *user_buf, | ||
633 | size_t count, loff_t *ppos) | ||
634 | { | ||
635 | struct ath10k *ar = file->private_data; | ||
636 | unsigned long mask; | ||
637 | int ret; | ||
638 | |||
639 | ret = kstrtoul_from_user(user_buf, count, 0, &mask); | ||
640 | if (ret) | ||
641 | return ret; | ||
642 | |||
643 | mutex_lock(&ar->conf_mutex); | ||
644 | |||
645 | ar->debug.fw_dbglog_mask = mask; | ||
646 | |||
647 | if (ar->state == ATH10K_STATE_ON) { | ||
648 | ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask); | ||
649 | if (ret) { | ||
650 | ath10k_warn("dbglog cfg failed from debugfs: %d\n", | ||
651 | ret); | ||
652 | goto exit; | ||
653 | } | ||
654 | } | ||
655 | |||
656 | ret = count; | ||
657 | |||
658 | exit: | ||
659 | mutex_unlock(&ar->conf_mutex); | ||
660 | |||
661 | return ret; | ||
662 | } | ||
663 | |||
664 | static const struct file_operations fops_fw_dbglog = { | ||
665 | .read = ath10k_read_fw_dbglog, | ||
666 | .write = ath10k_write_fw_dbglog, | ||
667 | .open = simple_open, | ||
668 | .owner = THIS_MODULE, | ||
669 | .llseek = default_llseek, | ||
670 | }; | ||
671 | |||
617 | int ath10k_debug_start(struct ath10k *ar) | 672 | int ath10k_debug_start(struct ath10k *ar) |
618 | { | 673 | { |
619 | int ret; | 674 | int ret; |
@@ -625,6 +680,14 @@ int ath10k_debug_start(struct ath10k *ar) | |||
625 | /* continue normally anyway, this isn't serious */ | 680 | /* continue normally anyway, this isn't serious */ |
626 | ath10k_warn("failed to start htt stats workqueue: %d\n", ret); | 681 | ath10k_warn("failed to start htt stats workqueue: %d\n", ret); |
627 | 682 | ||
683 | if (ar->debug.fw_dbglog_mask) { | ||
684 | ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask); | ||
685 | if (ret) | ||
686 | /* not serious */ | ||
687 | ath10k_warn("failed to enable dbglog during start: %d", | ||
688 | ret); | ||
689 | } | ||
690 | |||
628 | return 0; | 691 | return 0; |
629 | } | 692 | } |
630 | 693 | ||
@@ -747,6 +810,9 @@ int ath10k_debug_create(struct ath10k *ar) | |||
747 | debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy, | 810 | debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy, |
748 | ar, &fops_htt_stats_mask); | 811 | ar, &fops_htt_stats_mask); |
749 | 812 | ||
813 | debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy, | ||
814 | ar, &fops_fw_dbglog); | ||
815 | |||
750 | if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) { | 816 | if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) { |
751 | debugfs_create_file("dfs_simulate_radar", S_IWUSR, | 817 | debugfs_create_file("dfs_simulate_radar", S_IWUSR, |
752 | ar->debug.debugfs_phy, ar, | 818 | ar->debug.debugfs_phy, ar, |
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 7fc7919ea5f5..b93ae355bc08 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h | |||
@@ -1183,6 +1183,7 @@ struct htt_rx_info { | |||
1183 | } rate; | 1183 | } rate; |
1184 | bool fcs_err; | 1184 | bool fcs_err; |
1185 | bool amsdu_more; | 1185 | bool amsdu_more; |
1186 | bool mic_err; | ||
1186 | }; | 1187 | }; |
1187 | 1188 | ||
1188 | struct ath10k_htt { | 1189 | struct ath10k_htt { |
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index fcb534f2f28f..fe8bd1b59f0e 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c | |||
@@ -838,6 +838,20 @@ static bool ath10k_htt_rx_has_fcs_err(struct sk_buff *skb) | |||
838 | return false; | 838 | return false; |
839 | } | 839 | } |
840 | 840 | ||
841 | static bool ath10k_htt_rx_has_mic_err(struct sk_buff *skb) | ||
842 | { | ||
843 | struct htt_rx_desc *rxd; | ||
844 | u32 flags; | ||
845 | |||
846 | rxd = (void *)skb->data - sizeof(*rxd); | ||
847 | flags = __le32_to_cpu(rxd->attention.flags); | ||
848 | |||
849 | if (flags & RX_ATTENTION_FLAGS_TKIP_MIC_ERR) | ||
850 | return true; | ||
851 | |||
852 | return false; | ||
853 | } | ||
854 | |||
841 | static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb) | 855 | static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb) |
842 | { | 856 | { |
843 | struct htt_rx_desc *rxd; | 857 | struct htt_rx_desc *rxd; |
@@ -960,6 +974,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, | |||
960 | 974 | ||
961 | info.skb = msdu_head; | 975 | info.skb = msdu_head; |
962 | info.fcs_err = ath10k_htt_rx_has_fcs_err(msdu_head); | 976 | info.fcs_err = ath10k_htt_rx_has_fcs_err(msdu_head); |
977 | info.mic_err = ath10k_htt_rx_has_mic_err(msdu_head); | ||
963 | info.signal = ATH10K_DEFAULT_NOISE_FLOOR; | 978 | info.signal = ATH10K_DEFAULT_NOISE_FLOOR; |
964 | info.signal += rx->ppdu.combined_rssi; | 979 | info.signal += rx->ppdu.combined_rssi; |
965 | 980 | ||
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 9535eaa09f09..f1505a25d810 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h | |||
@@ -115,6 +115,7 @@ enum ath10k_mcast2ucast_mode { | |||
115 | #define TARGET_10X_MAC_AGGR_DELIM 0 | 115 | #define TARGET_10X_MAC_AGGR_DELIM 0 |
116 | #define TARGET_10X_AST_SKID_LIMIT 16 | 116 | #define TARGET_10X_AST_SKID_LIMIT 16 |
117 | #define TARGET_10X_NUM_PEERS (128 + (TARGET_10X_NUM_VDEVS)) | 117 | #define TARGET_10X_NUM_PEERS (128 + (TARGET_10X_NUM_VDEVS)) |
118 | #define TARGET_10X_NUM_PEERS_MAX 128 | ||
118 | #define TARGET_10X_NUM_OFFLOAD_PEERS 0 | 119 | #define TARGET_10X_NUM_OFFLOAD_PEERS 0 |
119 | #define TARGET_10X_NUM_OFFLOAD_REORDER_BUFS 0 | 120 | #define TARGET_10X_NUM_OFFLOAD_REORDER_BUFS 0 |
120 | #define TARGET_10X_NUM_PEER_KEYS 2 | 121 | #define TARGET_10X_NUM_PEER_KEYS 2 |
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index ce9ef3499ecb..776e364eadcd 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
@@ -332,6 +332,9 @@ static int ath10k_peer_create(struct ath10k *ar, u32 vdev_id, const u8 *addr) | |||
332 | ath10k_warn("Failed to wait for created wmi peer: %i\n", ret); | 332 | ath10k_warn("Failed to wait for created wmi peer: %i\n", ret); |
333 | return ret; | 333 | return ret; |
334 | } | 334 | } |
335 | spin_lock_bh(&ar->data_lock); | ||
336 | ar->num_peers++; | ||
337 | spin_unlock_bh(&ar->data_lock); | ||
335 | 338 | ||
336 | return 0; | 339 | return 0; |
337 | } | 340 | } |
@@ -377,6 +380,10 @@ static int ath10k_peer_delete(struct ath10k *ar, u32 vdev_id, const u8 *addr) | |||
377 | if (ret) | 380 | if (ret) |
378 | return ret; | 381 | return ret; |
379 | 382 | ||
383 | spin_lock_bh(&ar->data_lock); | ||
384 | ar->num_peers--; | ||
385 | spin_unlock_bh(&ar->data_lock); | ||
386 | |||
380 | return 0; | 387 | return 0; |
381 | } | 388 | } |
382 | 389 | ||
@@ -396,6 +403,7 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id) | |||
396 | 403 | ||
397 | list_del(&peer->list); | 404 | list_del(&peer->list); |
398 | kfree(peer); | 405 | kfree(peer); |
406 | ar->num_peers--; | ||
399 | } | 407 | } |
400 | spin_unlock_bh(&ar->data_lock); | 408 | spin_unlock_bh(&ar->data_lock); |
401 | } | 409 | } |
@@ -411,6 +419,7 @@ static void ath10k_peer_cleanup_all(struct ath10k *ar) | |||
411 | list_del(&peer->list); | 419 | list_del(&peer->list); |
412 | kfree(peer); | 420 | kfree(peer); |
413 | } | 421 | } |
422 | ar->num_peers = 0; | ||
414 | spin_unlock_bh(&ar->data_lock); | 423 | spin_unlock_bh(&ar->data_lock); |
415 | } | 424 | } |
416 | 425 | ||
@@ -2205,7 +2214,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
2205 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | 2214 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); |
2206 | enum wmi_sta_powersave_param param; | 2215 | enum wmi_sta_powersave_param param; |
2207 | int ret = 0; | 2216 | int ret = 0; |
2208 | u32 value; | 2217 | u32 value, param_id; |
2209 | int bit; | 2218 | int bit; |
2210 | u32 vdev_param; | 2219 | u32 vdev_param; |
2211 | 2220 | ||
@@ -2297,6 +2306,13 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
2297 | ath10k_warn("Failed to create peer for AP: %d\n", ret); | 2306 | ath10k_warn("Failed to create peer for AP: %d\n", ret); |
2298 | goto err_vdev_delete; | 2307 | goto err_vdev_delete; |
2299 | } | 2308 | } |
2309 | |||
2310 | param_id = ar->wmi.pdev_param->sta_kickout_th; | ||
2311 | |||
2312 | /* Disable STA KICKOUT functionality in FW */ | ||
2313 | ret = ath10k_wmi_pdev_set_param(ar, param_id, 0); | ||
2314 | if (ret) | ||
2315 | ath10k_warn("Failed to disable STA KICKOUT\n"); | ||
2300 | } | 2316 | } |
2301 | 2317 | ||
2302 | if (arvif->vdev_type == WMI_VDEV_TYPE_STA) { | 2318 | if (arvif->vdev_type == WMI_VDEV_TYPE_STA) { |
@@ -2842,6 +2858,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
2842 | { | 2858 | { |
2843 | struct ath10k *ar = hw->priv; | 2859 | struct ath10k *ar = hw->priv; |
2844 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | 2860 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); |
2861 | int max_num_peers; | ||
2845 | int ret = 0; | 2862 | int ret = 0; |
2846 | 2863 | ||
2847 | mutex_lock(&ar->conf_mutex); | 2864 | mutex_lock(&ar->conf_mutex); |
@@ -2852,9 +2869,21 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
2852 | /* | 2869 | /* |
2853 | * New station addition. | 2870 | * New station addition. |
2854 | */ | 2871 | */ |
2872 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) | ||
2873 | max_num_peers = TARGET_10X_NUM_PEERS_MAX - 1; | ||
2874 | else | ||
2875 | max_num_peers = TARGET_NUM_PEERS; | ||
2876 | |||
2877 | if (ar->num_peers >= max_num_peers) { | ||
2878 | ath10k_warn("Number of peers exceeded: peers number %d (max peers %d)\n", | ||
2879 | ar->num_peers, max_num_peers); | ||
2880 | ret = -ENOBUFS; | ||
2881 | goto exit; | ||
2882 | } | ||
2883 | |||
2855 | ath10k_dbg(ATH10K_DBG_MAC, | 2884 | ath10k_dbg(ATH10K_DBG_MAC, |
2856 | "mac vdev %d peer create %pM (new sta)\n", | 2885 | "mac vdev %d peer create %pM (new sta) num_peers %d\n", |
2857 | arvif->vdev_id, sta->addr); | 2886 | arvif->vdev_id, sta->addr, ar->num_peers); |
2858 | 2887 | ||
2859 | ret = ath10k_peer_create(ar, arvif->vdev_id, sta->addr); | 2888 | ret = ath10k_peer_create(ar, arvif->vdev_id, sta->addr); |
2860 | if (ret) | 2889 | if (ret) |
@@ -2904,7 +2933,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
2904 | ath10k_warn("Failed to disassociate station: %pM\n", | 2933 | ath10k_warn("Failed to disassociate station: %pM\n", |
2905 | sta->addr); | 2934 | sta->addr); |
2906 | } | 2935 | } |
2907 | 2936 | exit: | |
2908 | mutex_unlock(&ar->conf_mutex); | 2937 | mutex_unlock(&ar->conf_mutex); |
2909 | return ret; | 2938 | return ret; |
2910 | } | 2939 | } |
@@ -3310,6 +3339,307 @@ exit: | |||
3310 | return ret; | 3339 | return ret; |
3311 | } | 3340 | } |
3312 | 3341 | ||
3342 | /* Helper table for legacy fixed_rate/bitrate_mask */ | ||
3343 | static const u8 cck_ofdm_rate[] = { | ||
3344 | /* CCK */ | ||
3345 | 3, /* 1Mbps */ | ||
3346 | 2, /* 2Mbps */ | ||
3347 | 1, /* 5.5Mbps */ | ||
3348 | 0, /* 11Mbps */ | ||
3349 | /* OFDM */ | ||
3350 | 3, /* 6Mbps */ | ||
3351 | 7, /* 9Mbps */ | ||
3352 | 2, /* 12Mbps */ | ||
3353 | 6, /* 18Mbps */ | ||
3354 | 1, /* 24Mbps */ | ||
3355 | 5, /* 36Mbps */ | ||
3356 | 0, /* 48Mbps */ | ||
3357 | 4, /* 54Mbps */ | ||
3358 | }; | ||
3359 | |||
3360 | /* Check if only one bit set */ | ||
3361 | static int ath10k_check_single_mask(u32 mask) | ||
3362 | { | ||
3363 | int bit; | ||
3364 | |||
3365 | bit = ffs(mask); | ||
3366 | if (!bit) | ||
3367 | return 0; | ||
3368 | |||
3369 | mask &= ~BIT(bit - 1); | ||
3370 | if (mask) | ||
3371 | return 2; | ||
3372 | |||
3373 | return 1; | ||
3374 | } | ||
3375 | |||
3376 | static bool | ||
3377 | ath10k_default_bitrate_mask(struct ath10k *ar, | ||
3378 | enum ieee80211_band band, | ||
3379 | const struct cfg80211_bitrate_mask *mask) | ||
3380 | { | ||
3381 | u32 legacy = 0x00ff; | ||
3382 | u8 ht = 0xff, i; | ||
3383 | u16 vht = 0x3ff; | ||
3384 | |||
3385 | switch (band) { | ||
3386 | case IEEE80211_BAND_2GHZ: | ||
3387 | legacy = 0x00fff; | ||
3388 | vht = 0; | ||
3389 | break; | ||
3390 | case IEEE80211_BAND_5GHZ: | ||
3391 | break; | ||
3392 | default: | ||
3393 | return false; | ||
3394 | } | ||
3395 | |||
3396 | if (mask->control[band].legacy != legacy) | ||
3397 | return false; | ||
3398 | |||
3399 | for (i = 0; i < ar->num_rf_chains; i++) | ||
3400 | if (mask->control[band].ht_mcs[i] != ht) | ||
3401 | return false; | ||
3402 | |||
3403 | for (i = 0; i < ar->num_rf_chains; i++) | ||
3404 | if (mask->control[band].vht_mcs[i] != vht) | ||
3405 | return false; | ||
3406 | |||
3407 | return true; | ||
3408 | } | ||
3409 | |||
3410 | static bool | ||
3411 | ath10k_bitrate_mask_nss(const struct cfg80211_bitrate_mask *mask, | ||
3412 | enum ieee80211_band band, | ||
3413 | u8 *fixed_nss) | ||
3414 | { | ||
3415 | int ht_nss = 0, vht_nss = 0, i; | ||
3416 | |||
3417 | /* check legacy */ | ||
3418 | if (ath10k_check_single_mask(mask->control[band].legacy)) | ||
3419 | return false; | ||
3420 | |||
3421 | /* check HT */ | ||
3422 | for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) { | ||
3423 | if (mask->control[band].ht_mcs[i] == 0xff) | ||
3424 | continue; | ||
3425 | else if (mask->control[band].ht_mcs[i] == 0x00) | ||
3426 | break; | ||
3427 | else | ||
3428 | return false; | ||
3429 | } | ||
3430 | |||
3431 | ht_nss = i; | ||
3432 | |||
3433 | /* check VHT */ | ||
3434 | for (i = 0; i < NL80211_VHT_NSS_MAX; i++) { | ||
3435 | if (mask->control[band].vht_mcs[i] == 0x03ff) | ||
3436 | continue; | ||
3437 | else if (mask->control[band].vht_mcs[i] == 0x0000) | ||
3438 | break; | ||
3439 | else | ||
3440 | return false; | ||
3441 | } | ||
3442 | |||
3443 | vht_nss = i; | ||
3444 | |||
3445 | if (ht_nss > 0 && vht_nss > 0) | ||
3446 | return false; | ||
3447 | |||
3448 | if (ht_nss) | ||
3449 | *fixed_nss = ht_nss; | ||
3450 | else if (vht_nss) | ||
3451 | *fixed_nss = vht_nss; | ||
3452 | else | ||
3453 | return false; | ||
3454 | |||
3455 | return true; | ||
3456 | } | ||
3457 | |||
3458 | static bool | ||
3459 | ath10k_bitrate_mask_correct(const struct cfg80211_bitrate_mask *mask, | ||
3460 | enum ieee80211_band band, | ||
3461 | enum wmi_rate_preamble *preamble) | ||
3462 | { | ||
3463 | int legacy = 0, ht = 0, vht = 0, i; | ||
3464 | |||
3465 | *preamble = WMI_RATE_PREAMBLE_OFDM; | ||
3466 | |||
3467 | /* check legacy */ | ||
3468 | legacy = ath10k_check_single_mask(mask->control[band].legacy); | ||
3469 | if (legacy > 1) | ||
3470 | return false; | ||
3471 | |||
3472 | /* check HT */ | ||
3473 | for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) | ||
3474 | ht += ath10k_check_single_mask(mask->control[band].ht_mcs[i]); | ||
3475 | if (ht > 1) | ||
3476 | return false; | ||
3477 | |||
3478 | /* check VHT */ | ||
3479 | for (i = 0; i < NL80211_VHT_NSS_MAX; i++) | ||
3480 | vht += ath10k_check_single_mask(mask->control[band].vht_mcs[i]); | ||
3481 | if (vht > 1) | ||
3482 | return false; | ||
3483 | |||
3484 | /* Currently we support only one fixed_rate */ | ||
3485 | if ((legacy + ht + vht) != 1) | ||
3486 | return false; | ||
3487 | |||
3488 | if (ht) | ||
3489 | *preamble = WMI_RATE_PREAMBLE_HT; | ||
3490 | else if (vht) | ||
3491 | *preamble = WMI_RATE_PREAMBLE_VHT; | ||
3492 | |||
3493 | return true; | ||
3494 | } | ||
3495 | |||
3496 | static bool | ||
3497 | ath10k_bitrate_mask_rate(const struct cfg80211_bitrate_mask *mask, | ||
3498 | enum ieee80211_band band, | ||
3499 | u8 *fixed_rate, | ||
3500 | u8 *fixed_nss) | ||
3501 | { | ||
3502 | u8 rate = 0, pream = 0, nss = 0, i; | ||
3503 | enum wmi_rate_preamble preamble; | ||
3504 | |||
3505 | /* Check if single rate correct */ | ||
3506 | if (!ath10k_bitrate_mask_correct(mask, band, &preamble)) | ||
3507 | return false; | ||
3508 | |||
3509 | pream = preamble; | ||
3510 | |||
3511 | switch (preamble) { | ||
3512 | case WMI_RATE_PREAMBLE_CCK: | ||
3513 | case WMI_RATE_PREAMBLE_OFDM: | ||
3514 | i = ffs(mask->control[band].legacy) - 1; | ||
3515 | |||
3516 | if (band == IEEE80211_BAND_2GHZ && i < 4) | ||
3517 | pream = WMI_RATE_PREAMBLE_CCK; | ||
3518 | |||
3519 | if (band == IEEE80211_BAND_5GHZ) | ||
3520 | i += 4; | ||
3521 | |||
3522 | if (i >= ARRAY_SIZE(cck_ofdm_rate)) | ||
3523 | return false; | ||
3524 | |||
3525 | rate = cck_ofdm_rate[i]; | ||
3526 | break; | ||
3527 | case WMI_RATE_PREAMBLE_HT: | ||
3528 | for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) | ||
3529 | if (mask->control[band].ht_mcs[i]) | ||
3530 | break; | ||
3531 | |||
3532 | if (i == IEEE80211_HT_MCS_MASK_LEN) | ||
3533 | return false; | ||
3534 | |||
3535 | rate = ffs(mask->control[band].ht_mcs[i]) - 1; | ||
3536 | nss = i; | ||
3537 | break; | ||
3538 | case WMI_RATE_PREAMBLE_VHT: | ||
3539 | for (i = 0; i < NL80211_VHT_NSS_MAX; i++) | ||
3540 | if (mask->control[band].vht_mcs[i]) | ||
3541 | break; | ||
3542 | |||
3543 | if (i == NL80211_VHT_NSS_MAX) | ||
3544 | return false; | ||
3545 | |||
3546 | rate = ffs(mask->control[band].vht_mcs[i]) - 1; | ||
3547 | nss = i; | ||
3548 | break; | ||
3549 | } | ||
3550 | |||
3551 | *fixed_nss = nss + 1; | ||
3552 | nss <<= 4; | ||
3553 | pream <<= 6; | ||
3554 | |||
3555 | ath10k_dbg(ATH10K_DBG_MAC, "mac fixed rate pream 0x%02x nss 0x%02x rate 0x%02x\n", | ||
3556 | pream, nss, rate); | ||
3557 | |||
3558 | *fixed_rate = pream | nss | rate; | ||
3559 | |||
3560 | return true; | ||
3561 | } | ||
3562 | |||
3563 | static bool ath10k_get_fixed_rate_nss(const struct cfg80211_bitrate_mask *mask, | ||
3564 | enum ieee80211_band band, | ||
3565 | u8 *fixed_rate, | ||
3566 | u8 *fixed_nss) | ||
3567 | { | ||
3568 | /* First check full NSS mask, if we can simply limit NSS */ | ||
3569 | if (ath10k_bitrate_mask_nss(mask, band, fixed_nss)) | ||
3570 | return true; | ||
3571 | |||
3572 | /* Next Check single rate is set */ | ||
3573 | return ath10k_bitrate_mask_rate(mask, band, fixed_rate, fixed_nss); | ||
3574 | } | ||
3575 | |||
3576 | static int ath10k_set_fixed_rate_param(struct ath10k_vif *arvif, | ||
3577 | u8 fixed_rate, | ||
3578 | u8 fixed_nss) | ||
3579 | { | ||
3580 | struct ath10k *ar = arvif->ar; | ||
3581 | u32 vdev_param; | ||
3582 | int ret = 0; | ||
3583 | |||
3584 | mutex_lock(&ar->conf_mutex); | ||
3585 | |||
3586 | if (arvif->fixed_rate == fixed_rate && | ||
3587 | arvif->fixed_nss == fixed_nss) | ||
3588 | goto exit; | ||
3589 | |||
3590 | if (fixed_rate == WMI_FIXED_RATE_NONE) | ||
3591 | ath10k_dbg(ATH10K_DBG_MAC, "mac disable fixed bitrate mask\n"); | ||
3592 | |||
3593 | vdev_param = ar->wmi.vdev_param->fixed_rate; | ||
3594 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, | ||
3595 | vdev_param, fixed_rate); | ||
3596 | if (ret) { | ||
3597 | ath10k_warn("Could not set fixed_rate param 0x%02x: %d\n", | ||
3598 | fixed_rate, ret); | ||
3599 | ret = -EINVAL; | ||
3600 | goto exit; | ||
3601 | } | ||
3602 | |||
3603 | arvif->fixed_rate = fixed_rate; | ||
3604 | |||
3605 | vdev_param = ar->wmi.vdev_param->nss; | ||
3606 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, | ||
3607 | vdev_param, fixed_nss); | ||
3608 | |||
3609 | if (ret) { | ||
3610 | ath10k_warn("Could not set fixed_nss param %d: %d\n", | ||
3611 | fixed_nss, ret); | ||
3612 | ret = -EINVAL; | ||
3613 | goto exit; | ||
3614 | } | ||
3615 | |||
3616 | arvif->fixed_nss = fixed_nss; | ||
3617 | |||
3618 | exit: | ||
3619 | mutex_unlock(&ar->conf_mutex); | ||
3620 | return ret; | ||
3621 | } | ||
3622 | |||
3623 | static int ath10k_set_bitrate_mask(struct ieee80211_hw *hw, | ||
3624 | struct ieee80211_vif *vif, | ||
3625 | const struct cfg80211_bitrate_mask *mask) | ||
3626 | { | ||
3627 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | ||
3628 | struct ath10k *ar = arvif->ar; | ||
3629 | enum ieee80211_band band = ar->hw->conf.chandef.chan->band; | ||
3630 | u8 fixed_rate = WMI_FIXED_RATE_NONE; | ||
3631 | u8 fixed_nss = ar->num_rf_chains; | ||
3632 | |||
3633 | if (!ath10k_default_bitrate_mask(ar, band, mask)) { | ||
3634 | if (!ath10k_get_fixed_rate_nss(mask, band, | ||
3635 | &fixed_rate, | ||
3636 | &fixed_nss)) | ||
3637 | return -EINVAL; | ||
3638 | } | ||
3639 | |||
3640 | return ath10k_set_fixed_rate_param(arvif, fixed_rate, fixed_nss); | ||
3641 | } | ||
3642 | |||
3313 | static const struct ieee80211_ops ath10k_ops = { | 3643 | static const struct ieee80211_ops ath10k_ops = { |
3314 | .tx = ath10k_tx, | 3644 | .tx = ath10k_tx, |
3315 | .start = ath10k_start, | 3645 | .start = ath10k_start, |
@@ -3332,6 +3662,7 @@ static const struct ieee80211_ops ath10k_ops = { | |||
3332 | .tx_last_beacon = ath10k_tx_last_beacon, | 3662 | .tx_last_beacon = ath10k_tx_last_beacon, |
3333 | .restart_complete = ath10k_restart_complete, | 3663 | .restart_complete = ath10k_restart_complete, |
3334 | .get_survey = ath10k_get_survey, | 3664 | .get_survey = ath10k_get_survey, |
3665 | .set_bitrate_mask = ath10k_set_bitrate_mask, | ||
3335 | #ifdef CONFIG_PM | 3666 | #ifdef CONFIG_PM |
3336 | .suspend = ath10k_suspend, | 3667 | .suspend = ath10k_suspend, |
3337 | .resume = ath10k_resume, | 3668 | .resume = ath10k_resume, |
@@ -3464,14 +3795,12 @@ static const struct ieee80211_iface_limit ath10k_if_limits[] = { | |||
3464 | }, | 3795 | }, |
3465 | }; | 3796 | }; |
3466 | 3797 | ||
3467 | #ifdef CONFIG_ATH10K_DFS_CERTIFIED | 3798 | static const struct ieee80211_iface_limit ath10k_10x_if_limits[] = { |
3468 | static const struct ieee80211_iface_limit ath10k_if_dfs_limits[] = { | ||
3469 | { | 3799 | { |
3470 | .max = 8, | 3800 | .max = 8, |
3471 | .types = BIT(NL80211_IFTYPE_AP) | 3801 | .types = BIT(NL80211_IFTYPE_AP) |
3472 | }, | 3802 | }, |
3473 | }; | 3803 | }; |
3474 | #endif | ||
3475 | 3804 | ||
3476 | static const struct ieee80211_iface_combination ath10k_if_comb[] = { | 3805 | static const struct ieee80211_iface_combination ath10k_if_comb[] = { |
3477 | { | 3806 | { |
@@ -3481,19 +3810,22 @@ static const struct ieee80211_iface_combination ath10k_if_comb[] = { | |||
3481 | .num_different_channels = 1, | 3810 | .num_different_channels = 1, |
3482 | .beacon_int_infra_match = true, | 3811 | .beacon_int_infra_match = true, |
3483 | }, | 3812 | }, |
3484 | #ifdef CONFIG_ATH10K_DFS_CERTIFIED | 3813 | }; |
3814 | |||
3815 | static const struct ieee80211_iface_combination ath10k_10x_if_comb[] = { | ||
3485 | { | 3816 | { |
3486 | .limits = ath10k_if_dfs_limits, | 3817 | .limits = ath10k_10x_if_limits, |
3487 | .n_limits = ARRAY_SIZE(ath10k_if_dfs_limits), | 3818 | .n_limits = ARRAY_SIZE(ath10k_10x_if_limits), |
3488 | .max_interfaces = 8, | 3819 | .max_interfaces = 8, |
3489 | .num_different_channels = 1, | 3820 | .num_different_channels = 1, |
3490 | .beacon_int_infra_match = true, | 3821 | .beacon_int_infra_match = true, |
3822 | #ifdef CONFIG_ATH10K_DFS_CERTIFIED | ||
3491 | .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | | 3823 | .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | |
3492 | BIT(NL80211_CHAN_WIDTH_20) | | 3824 | BIT(NL80211_CHAN_WIDTH_20) | |
3493 | BIT(NL80211_CHAN_WIDTH_40) | | 3825 | BIT(NL80211_CHAN_WIDTH_40) | |
3494 | BIT(NL80211_CHAN_WIDTH_80), | 3826 | BIT(NL80211_CHAN_WIDTH_80), |
3495 | } | ||
3496 | #endif | 3827 | #endif |
3828 | }, | ||
3497 | }; | 3829 | }; |
3498 | 3830 | ||
3499 | static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) | 3831 | static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) |
@@ -3672,9 +4004,12 @@ int ath10k_mac_register(struct ath10k *ar) | |||
3672 | ar->hw->wiphy->interface_modes = | 4004 | ar->hw->wiphy->interface_modes = |
3673 | BIT(NL80211_IFTYPE_STATION) | | 4005 | BIT(NL80211_IFTYPE_STATION) | |
3674 | BIT(NL80211_IFTYPE_ADHOC) | | 4006 | BIT(NL80211_IFTYPE_ADHOC) | |
3675 | BIT(NL80211_IFTYPE_AP) | | 4007 | BIT(NL80211_IFTYPE_AP); |
3676 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | 4008 | |
3677 | BIT(NL80211_IFTYPE_P2P_GO); | 4009 | if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features)) |
4010 | ar->hw->wiphy->interface_modes |= | ||
4011 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
4012 | BIT(NL80211_IFTYPE_P2P_GO); | ||
3678 | 4013 | ||
3679 | ar->hw->flags = IEEE80211_HW_SIGNAL_DBM | | 4014 | ar->hw->flags = IEEE80211_HW_SIGNAL_DBM | |
3680 | IEEE80211_HW_SUPPORTS_PS | | 4015 | IEEE80211_HW_SUPPORTS_PS | |
@@ -3704,7 +4039,6 @@ int ath10k_mac_register(struct ath10k *ar) | |||
3704 | 4039 | ||
3705 | ar->hw->vif_data_size = sizeof(struct ath10k_vif); | 4040 | ar->hw->vif_data_size = sizeof(struct ath10k_vif); |
3706 | 4041 | ||
3707 | ar->hw->channel_change_time = 5000; | ||
3708 | ar->hw->max_listen_interval = ATH10K_MAX_HW_LISTEN_INTERVAL; | 4042 | ar->hw->max_listen_interval = ATH10K_MAX_HW_LISTEN_INTERVAL; |
3709 | 4043 | ||
3710 | ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | 4044 | ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; |
@@ -3717,8 +4051,15 @@ int ath10k_mac_register(struct ath10k *ar) | |||
3717 | */ | 4051 | */ |
3718 | ar->hw->queues = 4; | 4052 | ar->hw->queues = 4; |
3719 | 4053 | ||
3720 | ar->hw->wiphy->iface_combinations = ath10k_if_comb; | 4054 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { |
3721 | ar->hw->wiphy->n_iface_combinations = ARRAY_SIZE(ath10k_if_comb); | 4055 | ar->hw->wiphy->iface_combinations = ath10k_10x_if_comb; |
4056 | ar->hw->wiphy->n_iface_combinations = | ||
4057 | ARRAY_SIZE(ath10k_10x_if_comb); | ||
4058 | } else { | ||
4059 | ar->hw->wiphy->iface_combinations = ath10k_if_comb; | ||
4060 | ar->hw->wiphy->n_iface_combinations = | ||
4061 | ARRAY_SIZE(ath10k_if_comb); | ||
4062 | } | ||
3722 | 4063 | ||
3723 | ar->hw->netdev_features = NETIF_F_HW_CSUM; | 4064 | ar->hw->netdev_features = NETIF_F_HW_CSUM; |
3724 | 4065 | ||
diff --git a/drivers/net/wireless/ath/ath10k/trace.h b/drivers/net/wireless/ath/ath10k/trace.h index 90817ddc92ba..4eb2ecbc06ef 100644 --- a/drivers/net/wireless/ath/ath10k/trace.h +++ b/drivers/net/wireless/ath/ath10k/trace.h | |||
@@ -182,6 +182,27 @@ TRACE_EVENT(ath10k_htt_stats, | |||
182 | ) | 182 | ) |
183 | ); | 183 | ); |
184 | 184 | ||
185 | TRACE_EVENT(ath10k_wmi_dbglog, | ||
186 | TP_PROTO(void *buf, size_t buf_len), | ||
187 | |||
188 | TP_ARGS(buf, buf_len), | ||
189 | |||
190 | TP_STRUCT__entry( | ||
191 | __field(size_t, buf_len) | ||
192 | __dynamic_array(u8, buf, buf_len) | ||
193 | ), | ||
194 | |||
195 | TP_fast_assign( | ||
196 | __entry->buf_len = buf_len; | ||
197 | memcpy(__get_dynamic_array(buf), buf, buf_len); | ||
198 | ), | ||
199 | |||
200 | TP_printk( | ||
201 | "len %zu", | ||
202 | __entry->buf_len | ||
203 | ) | ||
204 | ); | ||
205 | |||
185 | #endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/ | 206 | #endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/ |
186 | 207 | ||
187 | /* we don't want to use include/trace/events */ | 208 | /* we don't want to use include/trace/events */ |
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index 22829803f087..74f45fa6f428 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c | |||
@@ -231,7 +231,7 @@ void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info) | |||
231 | ~IEEE80211_FCTL_PROTECTED); | 231 | ~IEEE80211_FCTL_PROTECTED); |
232 | } | 232 | } |
233 | 233 | ||
234 | if (info->status == HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR) | 234 | if (info->mic_err) |
235 | status->flag |= RX_FLAG_MMIC_ERROR; | 235 | status->flag |= RX_FLAG_MMIC_ERROR; |
236 | 236 | ||
237 | if (info->fcs_err) | 237 | if (info->fcs_err) |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 1260a8d15dc3..712a606a080a 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/skbuff.h> | 18 | #include <linux/skbuff.h> |
19 | #include <linux/ctype.h> | ||
19 | 20 | ||
20 | #include "core.h" | 21 | #include "core.h" |
21 | #include "htc.h" | 22 | #include "htc.h" |
@@ -875,6 +876,7 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) | |||
875 | struct wmi_mgmt_rx_event_v2 *ev_v2; | 876 | struct wmi_mgmt_rx_event_v2 *ev_v2; |
876 | struct wmi_mgmt_rx_hdr_v1 *ev_hdr; | 877 | struct wmi_mgmt_rx_hdr_v1 *ev_hdr; |
877 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 878 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
879 | struct ieee80211_channel *ch; | ||
878 | struct ieee80211_hdr *hdr; | 880 | struct ieee80211_hdr *hdr; |
879 | u32 rx_status; | 881 | u32 rx_status; |
880 | u32 channel; | 882 | u32 channel; |
@@ -927,7 +929,25 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) | |||
927 | if (rx_status & WMI_RX_STATUS_ERR_MIC) | 929 | if (rx_status & WMI_RX_STATUS_ERR_MIC) |
928 | status->flag |= RX_FLAG_MMIC_ERROR; | 930 | status->flag |= RX_FLAG_MMIC_ERROR; |
929 | 931 | ||
930 | status->band = phy_mode_to_band(phy_mode); | 932 | /* HW can Rx CCK rates on 5GHz. In that case phy_mode is set to |
933 | * MODE_11B. This means phy_mode is not a reliable source for the band | ||
934 | * of mgmt rx. */ | ||
935 | |||
936 | ch = ar->scan_channel; | ||
937 | if (!ch) | ||
938 | ch = ar->rx_channel; | ||
939 | |||
940 | if (ch) { | ||
941 | status->band = ch->band; | ||
942 | |||
943 | if (phy_mode == MODE_11B && | ||
944 | status->band == IEEE80211_BAND_5GHZ) | ||
945 | ath10k_dbg(ATH10K_DBG_MGMT, "wmi mgmt rx 11b (CCK) on 5GHz\n"); | ||
946 | } else { | ||
947 | ath10k_warn("using (unreliable) phy_mode to extract band for mgmt rx\n"); | ||
948 | status->band = phy_mode_to_band(phy_mode); | ||
949 | } | ||
950 | |||
931 | status->freq = ieee80211_channel_to_frequency(channel, status->band); | 951 | status->freq = ieee80211_channel_to_frequency(channel, status->band); |
932 | status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR; | 952 | status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR; |
933 | status->rate_idx = get_rate_idx(rate, status->band); | 953 | status->rate_idx = get_rate_idx(rate, status->band); |
@@ -937,7 +957,11 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) | |||
937 | hdr = (struct ieee80211_hdr *)skb->data; | 957 | hdr = (struct ieee80211_hdr *)skb->data; |
938 | fc = le16_to_cpu(hdr->frame_control); | 958 | fc = le16_to_cpu(hdr->frame_control); |
939 | 959 | ||
940 | if (fc & IEEE80211_FCTL_PROTECTED) { | 960 | /* FW delivers WEP Shared Auth frame with Protected Bit set and |
961 | * encrypted payload. However in case of PMF it delivers decrypted | ||
962 | * frames with Protected Bit set. */ | ||
963 | if (ieee80211_has_protected(hdr->frame_control) && | ||
964 | !ieee80211_is_auth(hdr->frame_control)) { | ||
941 | status->flag |= RX_FLAG_DECRYPTED | RX_FLAG_IV_STRIPPED | | 965 | status->flag |= RX_FLAG_DECRYPTED | RX_FLAG_IV_STRIPPED | |
942 | RX_FLAG_MMIC_STRIPPED; | 966 | RX_FLAG_MMIC_STRIPPED; |
943 | hdr->frame_control = __cpu_to_le16(fc & | 967 | hdr->frame_control = __cpu_to_le16(fc & |
@@ -1047,9 +1071,14 @@ static void ath10k_wmi_event_echo(struct ath10k *ar, struct sk_buff *skb) | |||
1047 | ath10k_dbg(ATH10K_DBG_WMI, "WMI_ECHO_EVENTID\n"); | 1071 | ath10k_dbg(ATH10K_DBG_WMI, "WMI_ECHO_EVENTID\n"); |
1048 | } | 1072 | } |
1049 | 1073 | ||
1050 | static void ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb) | 1074 | static int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb) |
1051 | { | 1075 | { |
1052 | ath10k_dbg(ATH10K_DBG_WMI, "WMI_DEBUG_MESG_EVENTID\n"); | 1076 | ath10k_dbg(ATH10K_DBG_WMI, "wmi event debug mesg len %d\n", |
1077 | skb->len); | ||
1078 | |||
1079 | trace_ath10k_wmi_dbglog(skb->data, skb->len); | ||
1080 | |||
1081 | return 0; | ||
1053 | } | 1082 | } |
1054 | 1083 | ||
1055 | static void ath10k_wmi_event_update_stats(struct ath10k *ar, | 1084 | static void ath10k_wmi_event_update_stats(struct ath10k *ar, |
@@ -1653,9 +1682,37 @@ static void ath10k_wmi_event_profile_match(struct ath10k *ar, | |||
1653 | } | 1682 | } |
1654 | 1683 | ||
1655 | static void ath10k_wmi_event_debug_print(struct ath10k *ar, | 1684 | static void ath10k_wmi_event_debug_print(struct ath10k *ar, |
1656 | struct sk_buff *skb) | 1685 | struct sk_buff *skb) |
1657 | { | 1686 | { |
1658 | ath10k_dbg(ATH10K_DBG_WMI, "WMI_DEBUG_PRINT_EVENTID\n"); | 1687 | char buf[101], c; |
1688 | int i; | ||
1689 | |||
1690 | for (i = 0; i < sizeof(buf) - 1; i++) { | ||
1691 | if (i >= skb->len) | ||
1692 | break; | ||
1693 | |||
1694 | c = skb->data[i]; | ||
1695 | |||
1696 | if (c == '\0') | ||
1697 | break; | ||
1698 | |||
1699 | if (isascii(c) && isprint(c)) | ||
1700 | buf[i] = c; | ||
1701 | else | ||
1702 | buf[i] = '.'; | ||
1703 | } | ||
1704 | |||
1705 | if (i == sizeof(buf) - 1) | ||
1706 | ath10k_warn("wmi debug print truncated: %d\n", skb->len); | ||
1707 | |||
1708 | /* for some reason the debug prints end with \n, remove that */ | ||
1709 | if (skb->data[i - 1] == '\n') | ||
1710 | i--; | ||
1711 | |||
1712 | /* the last byte is always reserved for the null character */ | ||
1713 | buf[i] = '\0'; | ||
1714 | |||
1715 | ath10k_dbg(ATH10K_DBG_WMI, "wmi event debug print '%s'\n", buf); | ||
1659 | } | 1716 | } |
1660 | 1717 | ||
1661 | static void ath10k_wmi_event_pdev_qvit(struct ath10k *ar, struct sk_buff *skb) | 1718 | static void ath10k_wmi_event_pdev_qvit(struct ath10k *ar, struct sk_buff *skb) |
@@ -3445,3 +3502,40 @@ int ath10k_wmi_force_fw_hang(struct ath10k *ar, | |||
3445 | type, delay_ms); | 3502 | type, delay_ms); |
3446 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->force_fw_hang_cmdid); | 3503 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->force_fw_hang_cmdid); |
3447 | } | 3504 | } |
3505 | |||
3506 | int ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable) | ||
3507 | { | ||
3508 | struct wmi_dbglog_cfg_cmd *cmd; | ||
3509 | struct sk_buff *skb; | ||
3510 | u32 cfg; | ||
3511 | |||
3512 | skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); | ||
3513 | if (!skb) | ||
3514 | return -ENOMEM; | ||
3515 | |||
3516 | cmd = (struct wmi_dbglog_cfg_cmd *)skb->data; | ||
3517 | |||
3518 | if (module_enable) { | ||
3519 | cfg = SM(ATH10K_DBGLOG_LEVEL_VERBOSE, | ||
3520 | ATH10K_DBGLOG_CFG_LOG_LVL); | ||
3521 | } else { | ||
3522 | /* set back defaults, all modules with WARN level */ | ||
3523 | cfg = SM(ATH10K_DBGLOG_LEVEL_WARN, | ||
3524 | ATH10K_DBGLOG_CFG_LOG_LVL); | ||
3525 | module_enable = ~0; | ||
3526 | } | ||
3527 | |||
3528 | cmd->module_enable = __cpu_to_le32(module_enable); | ||
3529 | cmd->module_valid = __cpu_to_le32(~0); | ||
3530 | cmd->config_enable = __cpu_to_le32(cfg); | ||
3531 | cmd->config_valid = __cpu_to_le32(ATH10K_DBGLOG_CFG_LOG_LVL_MASK); | ||
3532 | |||
3533 | ath10k_dbg(ATH10K_DBG_WMI, | ||
3534 | "wmi dbglog cfg modules %08x %08x config %08x %08x\n", | ||
3535 | __le32_to_cpu(cmd->module_enable), | ||
3536 | __le32_to_cpu(cmd->module_valid), | ||
3537 | __le32_to_cpu(cmd->config_enable), | ||
3538 | __le32_to_cpu(cmd->config_valid)); | ||
3539 | |||
3540 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->dbglog_cfg_cmdid); | ||
3541 | } | ||
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 0087d699b85b..4b5e7d3d32b6 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h | |||
@@ -3003,6 +3003,18 @@ struct wmi_vdev_install_key_arg { | |||
3003 | const void *key_data; | 3003 | const void *key_data; |
3004 | }; | 3004 | }; |
3005 | 3005 | ||
3006 | /* | ||
3007 | * vdev fixed rate format: | ||
3008 | * - preamble - b7:b6 - see WMI_RATE_PREMABLE_ | ||
3009 | * - nss - b5:b4 - ss number (0 mean 1ss) | ||
3010 | * - rate_mcs - b3:b0 - as below | ||
3011 | * CCK: 0 - 11Mbps, 1 - 5,5Mbps, 2 - 2Mbps, 3 - 1Mbps, | ||
3012 | * 4 - 11Mbps (s), 5 - 5,5Mbps (s), 6 - 2Mbps (s) | ||
3013 | * OFDM: 0 - 48Mbps, 1 - 24Mbps, 2 - 12Mbps, 3 - 6Mbps, | ||
3014 | * 4 - 54Mbps, 5 - 36Mbps, 6 - 18Mbps, 7 - 9Mbps | ||
3015 | * HT/VHT: MCS index | ||
3016 | */ | ||
3017 | |||
3006 | /* Preamble types to be used with VDEV fixed rate configuration */ | 3018 | /* Preamble types to be used with VDEV fixed rate configuration */ |
3007 | enum wmi_rate_preamble { | 3019 | enum wmi_rate_preamble { |
3008 | WMI_RATE_PREAMBLE_OFDM, | 3020 | WMI_RATE_PREAMBLE_OFDM, |
@@ -4090,6 +4102,54 @@ struct wmi_force_fw_hang_cmd { | |||
4090 | __le32 delay_ms; | 4102 | __le32 delay_ms; |
4091 | } __packed; | 4103 | } __packed; |
4092 | 4104 | ||
4105 | enum ath10k_dbglog_level { | ||
4106 | ATH10K_DBGLOG_LEVEL_VERBOSE = 0, | ||
4107 | ATH10K_DBGLOG_LEVEL_INFO = 1, | ||
4108 | ATH10K_DBGLOG_LEVEL_WARN = 2, | ||
4109 | ATH10K_DBGLOG_LEVEL_ERR = 3, | ||
4110 | }; | ||
4111 | |||
4112 | /* VAP ids to enable dbglog */ | ||
4113 | #define ATH10K_DBGLOG_CFG_VAP_LOG_LSB 0 | ||
4114 | #define ATH10K_DBGLOG_CFG_VAP_LOG_MASK 0x0000ffff | ||
4115 | |||
4116 | /* to enable dbglog in the firmware */ | ||
4117 | #define ATH10K_DBGLOG_CFG_REPORTING_ENABLE_LSB 16 | ||
4118 | #define ATH10K_DBGLOG_CFG_REPORTING_ENABLE_MASK 0x00010000 | ||
4119 | |||
4120 | /* timestamp resolution */ | ||
4121 | #define ATH10K_DBGLOG_CFG_RESOLUTION_LSB 17 | ||
4122 | #define ATH10K_DBGLOG_CFG_RESOLUTION_MASK 0x000E0000 | ||
4123 | |||
4124 | /* number of queued messages before sending them to the host */ | ||
4125 | #define ATH10K_DBGLOG_CFG_REPORT_SIZE_LSB 20 | ||
4126 | #define ATH10K_DBGLOG_CFG_REPORT_SIZE_MASK 0x0ff00000 | ||
4127 | |||
4128 | /* | ||
4129 | * Log levels to enable. This defines the minimum level to enable, this is | ||
4130 | * not a bitmask. See enum ath10k_dbglog_level for the values. | ||
4131 | */ | ||
4132 | #define ATH10K_DBGLOG_CFG_LOG_LVL_LSB 28 | ||
4133 | #define ATH10K_DBGLOG_CFG_LOG_LVL_MASK 0x70000000 | ||
4134 | |||
4135 | /* | ||
4136 | * Note: this is a cleaned up version of a struct firmware uses. For | ||
4137 | * example, config_valid was hidden inside an array. | ||
4138 | */ | ||
4139 | struct wmi_dbglog_cfg_cmd { | ||
4140 | /* bitmask to hold mod id config*/ | ||
4141 | __le32 module_enable; | ||
4142 | |||
4143 | /* see ATH10K_DBGLOG_CFG_ */ | ||
4144 | __le32 config_enable; | ||
4145 | |||
4146 | /* mask of module id bits to be changed */ | ||
4147 | __le32 module_valid; | ||
4148 | |||
4149 | /* mask of config bits to be changed, see ATH10K_DBGLOG_CFG_ */ | ||
4150 | __le32 config_valid; | ||
4151 | } __packed; | ||
4152 | |||
4093 | #define ATH10K_RTS_MAX 2347 | 4153 | #define ATH10K_RTS_MAX 2347 |
4094 | #define ATH10K_FRAGMT_THRESHOLD_MIN 540 | 4154 | #define ATH10K_FRAGMT_THRESHOLD_MIN 540 |
4095 | #define ATH10K_FRAGMT_THRESHOLD_MAX 2346 | 4155 | #define ATH10K_FRAGMT_THRESHOLD_MAX 2346 |
@@ -4167,5 +4227,6 @@ int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id); | |||
4167 | int ath10k_wmi_force_fw_hang(struct ath10k *ar, | 4227 | int ath10k_wmi_force_fw_hang(struct ath10k *ar, |
4168 | enum wmi_force_fw_hang_type type, u32 delay_ms); | 4228 | enum wmi_force_fw_hang_type type, u32 delay_ms); |
4169 | int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb); | 4229 | int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb); |
4230 | int ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable); | ||
4170 | 4231 | ||
4171 | #endif /* _WMI_H_ */ | 4232 | #endif /* _WMI_H_ */ |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 6396ad4bce67..ef35da84f63b 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -1238,14 +1238,11 @@ static void | |||
1238 | ath5k_check_ibss_tsf(struct ath5k_hw *ah, struct sk_buff *skb, | 1238 | ath5k_check_ibss_tsf(struct ath5k_hw *ah, struct sk_buff *skb, |
1239 | struct ieee80211_rx_status *rxs) | 1239 | struct ieee80211_rx_status *rxs) |
1240 | { | 1240 | { |
1241 | struct ath_common *common = ath5k_hw_common(ah); | ||
1242 | u64 tsf, bc_tstamp; | 1241 | u64 tsf, bc_tstamp; |
1243 | u32 hw_tu; | 1242 | u32 hw_tu; |
1244 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; | 1243 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; |
1245 | 1244 | ||
1246 | if (ieee80211_is_beacon(mgmt->frame_control) && | 1245 | if (le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS) { |
1247 | le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS && | ||
1248 | ether_addr_equal_64bits(mgmt->bssid, common->curbssid)) { | ||
1249 | /* | 1246 | /* |
1250 | * Received an IBSS beacon with the same BSSID. Hardware *must* | 1247 | * Received an IBSS beacon with the same BSSID. Hardware *must* |
1251 | * have updated the local TSF. We have to work around various | 1248 | * have updated the local TSF. We have to work around various |
@@ -1301,23 +1298,6 @@ ath5k_check_ibss_tsf(struct ath5k_hw *ah, struct sk_buff *skb, | |||
1301 | } | 1298 | } |
1302 | } | 1299 | } |
1303 | 1300 | ||
1304 | static void | ||
1305 | ath5k_update_beacon_rssi(struct ath5k_hw *ah, struct sk_buff *skb, int rssi) | ||
1306 | { | ||
1307 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; | ||
1308 | struct ath_common *common = ath5k_hw_common(ah); | ||
1309 | |||
1310 | /* only beacons from our BSSID */ | ||
1311 | if (!ieee80211_is_beacon(mgmt->frame_control) || | ||
1312 | !ether_addr_equal_64bits(mgmt->bssid, common->curbssid)) | ||
1313 | return; | ||
1314 | |||
1315 | ewma_add(&ah->ah_beacon_rssi_avg, rssi); | ||
1316 | |||
1317 | /* in IBSS mode we should keep RSSI statistics per neighbour */ | ||
1318 | /* le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS */ | ||
1319 | } | ||
1320 | |||
1321 | /* | 1301 | /* |
1322 | * Compute padding position. skb must contain an IEEE 802.11 frame | 1302 | * Compute padding position. skb must contain an IEEE 802.11 frame |
1323 | */ | 1303 | */ |
@@ -1390,6 +1370,7 @@ ath5k_receive_frame(struct ath5k_hw *ah, struct sk_buff *skb, | |||
1390 | struct ath5k_rx_status *rs) | 1370 | struct ath5k_rx_status *rs) |
1391 | { | 1371 | { |
1392 | struct ieee80211_rx_status *rxs; | 1372 | struct ieee80211_rx_status *rxs; |
1373 | struct ath_common *common = ath5k_hw_common(ah); | ||
1393 | 1374 | ||
1394 | ath5k_remove_padding(skb); | 1375 | ath5k_remove_padding(skb); |
1395 | 1376 | ||
@@ -1442,11 +1423,13 @@ ath5k_receive_frame(struct ath5k_hw *ah, struct sk_buff *skb, | |||
1442 | 1423 | ||
1443 | trace_ath5k_rx(ah, skb); | 1424 | trace_ath5k_rx(ah, skb); |
1444 | 1425 | ||
1445 | ath5k_update_beacon_rssi(ah, skb, rs->rs_rssi); | 1426 | if (ath_is_mybeacon(common, (struct ieee80211_hdr *)skb->data)) { |
1427 | ewma_add(&ah->ah_beacon_rssi_avg, rs->rs_rssi); | ||
1446 | 1428 | ||
1447 | /* check beacons in IBSS mode */ | 1429 | /* check beacons in IBSS mode */ |
1448 | if (ah->opmode == NL80211_IFTYPE_ADHOC) | 1430 | if (ah->opmode == NL80211_IFTYPE_ADHOC) |
1449 | ath5k_check_ibss_tsf(ah, skb, rxs); | 1431 | ath5k_check_ibss_tsf(ah, skb, rxs); |
1432 | } | ||
1450 | 1433 | ||
1451 | ieee80211_rx(ah->hw, skb); | 1434 | ieee80211_rx(ah->hw, skb); |
1452 | } | 1435 | } |
@@ -2549,7 +2532,6 @@ ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops) | |||
2549 | hw->wiphy->available_antennas_rx = 0x3; | 2532 | hw->wiphy->available_antennas_rx = 0x3; |
2550 | 2533 | ||
2551 | hw->extra_tx_headroom = 2; | 2534 | hw->extra_tx_headroom = 2; |
2552 | hw->channel_change_time = 5000; | ||
2553 | 2535 | ||
2554 | /* | 2536 | /* |
2555 | * Mark the device as detached to avoid processing | 2537 | * Mark the device as detached to avoid processing |
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 30d273c61bff..7b96b3e5712d 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig | |||
@@ -65,6 +65,14 @@ config ATH9K_DEBUGFS | |||
65 | 65 | ||
66 | Also required for changing debug message flags at run time. | 66 | Also required for changing debug message flags at run time. |
67 | 67 | ||
68 | config ATH9K_STATION_STATISTICS | ||
69 | bool "Detailed station statistics" | ||
70 | depends on ATH9K && ATH9K_DEBUGFS && DEBUG_FS | ||
71 | select MAC80211_DEBUGFS | ||
72 | default n | ||
73 | ---help--- | ||
74 | This option enables detailed statistics for association stations. | ||
75 | |||
68 | config ATH9K_DFS_CERTIFIED | 76 | config ATH9K_DFS_CERTIFIED |
69 | bool "Atheros DFS support for certified platforms" | 77 | bool "Atheros DFS support for certified platforms" |
70 | depends on ATH9K && CFG80211_CERTIFICATION_ONUS | 78 | depends on ATH9K && CFG80211_CERTIFICATION_ONUS |
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index e9904e5ccd81..a40e5c5d7418 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -19,6 +19,8 @@ ath9k-$(CONFIG_ATH9K_WOW) += wow.o | |||
19 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o \ | 19 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o \ |
20 | spectral.o | 20 | spectral.o |
21 | 21 | ||
22 | ath9k-$(CONFIG_ATH9K_STATION_STATISTICS) += debug_sta.o | ||
23 | |||
22 | obj-$(CONFIG_ATH9K) += ath9k.o | 24 | obj-$(CONFIG_ATH9K) += ath9k.o |
23 | 25 | ||
24 | ath9k_hw-y:= \ | 26 | ath9k_hw-y:= \ |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 8c145cd98c1c..a352128c40ad 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
@@ -565,7 +565,7 @@ static bool ar9003_hw_solve_iq_cal(struct ath_hw *ah, | |||
565 | const s32 result_shift = 1 << 15; | 565 | const s32 result_shift = 1 << 15; |
566 | struct ath_common *common = ath9k_hw_common(ah); | 566 | struct ath_common *common = ath9k_hw_common(ah); |
567 | 567 | ||
568 | f2 = (f1 * f1 + f3 * f3) / result_shift; | 568 | f2 = ((f1 >> 3) * (f1 >> 3) + (f3 >> 3) * (f3 >> 3)) >> 9; |
569 | 569 | ||
570 | if (!f2) { | 570 | if (!f2) { |
571 | ath_dbg(common, CALIBRATE, "Divide by 0\n"); | 571 | ath_dbg(common, CALIBRATE, "Divide by 0\n"); |
@@ -655,8 +655,8 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, | |||
655 | if (i2_m_q2_a0_d1 > 0x800) | 655 | if (i2_m_q2_a0_d1 > 0x800) |
656 | i2_m_q2_a0_d1 = -((0xfff - i2_m_q2_a0_d1) + 1); | 656 | i2_m_q2_a0_d1 = -((0xfff - i2_m_q2_a0_d1) + 1); |
657 | 657 | ||
658 | if (i2_p_q2_a0_d1 > 0x800) | 658 | if (i2_p_q2_a0_d1 > 0x1000) |
659 | i2_p_q2_a0_d1 = -((0xfff - i2_p_q2_a0_d1) + 1); | 659 | i2_p_q2_a0_d1 = -((0x1fff - i2_p_q2_a0_d1) + 1); |
660 | 660 | ||
661 | if (iq_corr_a0_d1 > 0x800) | 661 | if (iq_corr_a0_d1 > 0x800) |
662 | iq_corr_a0_d1 = -((0xfff - iq_corr_a0_d1) + 1); | 662 | iq_corr_a0_d1 = -((0xfff - iq_corr_a0_d1) + 1); |
@@ -700,6 +700,19 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, | |||
700 | return false; | 700 | return false; |
701 | } | 701 | } |
702 | 702 | ||
703 | if ((i2_p_q2_a0_d0 < 1024) || (i2_p_q2_a0_d0 > 2047) || | ||
704 | (i2_p_q2_a1_d0 < 0) || (i2_p_q2_a1_d1 < 0) || | ||
705 | (i2_p_q2_a0_d0 <= i2_m_q2_a0_d0) || | ||
706 | (i2_p_q2_a0_d0 <= iq_corr_a0_d0) || | ||
707 | (i2_p_q2_a0_d1 <= i2_m_q2_a0_d1) || | ||
708 | (i2_p_q2_a0_d1 <= iq_corr_a0_d1) || | ||
709 | (i2_p_q2_a1_d0 <= i2_m_q2_a1_d0) || | ||
710 | (i2_p_q2_a1_d0 <= iq_corr_a1_d0) || | ||
711 | (i2_p_q2_a1_d1 <= i2_m_q2_a1_d1) || | ||
712 | (i2_p_q2_a1_d1 <= iq_corr_a1_d1)) { | ||
713 | return false; | ||
714 | } | ||
715 | |||
703 | mag_a0_d0 = (i2_m_q2_a0_d0 * res_scale) / i2_p_q2_a0_d0; | 716 | mag_a0_d0 = (i2_m_q2_a0_d0 * res_scale) / i2_p_q2_a0_d0; |
704 | phs_a0_d0 = (iq_corr_a0_d0 * res_scale) / i2_p_q2_a0_d0; | 717 | phs_a0_d0 = (iq_corr_a0_d0 * res_scale) / i2_p_q2_a0_d0; |
705 | 718 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index f622a986c8cc..b5ac32cfbeb8 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -146,7 +146,9 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
146 | 146 | ||
147 | #define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)]) | 147 | #define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)]) |
148 | 148 | ||
149 | #define IS_CCK_RATE(rate) ((rate >= 0x18) && (rate <= 0x1e)) | 149 | #define IS_HT_RATE(rate) (rate & 0x80) |
150 | #define IS_CCK_RATE(rate) ((rate >= 0x18) && (rate <= 0x1e)) | ||
151 | #define IS_OFDM_RATE(rate) ((rate >= 0x8) && (rate <= 0xf)) | ||
150 | 152 | ||
151 | struct ath_txq { | 153 | struct ath_txq { |
152 | int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */ | 154 | int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */ |
@@ -262,6 +264,10 @@ struct ath_node { | |||
262 | 264 | ||
263 | bool sleeping; | 265 | bool sleeping; |
264 | bool no_ps_filter; | 266 | bool no_ps_filter; |
267 | |||
268 | #ifdef CONFIG_ATH9K_STATION_STATISTICS | ||
269 | struct ath_rx_rate_stats rx_rate_stats; | ||
270 | #endif | ||
265 | }; | 271 | }; |
266 | 272 | ||
267 | struct ath_tx_control { | 273 | struct ath_tx_control { |
@@ -685,6 +691,7 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs); | |||
685 | #define DEFAULT_CACHELINE 32 | 691 | #define DEFAULT_CACHELINE 32 |
686 | #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ | 692 | #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ |
687 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ | 693 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ |
694 | #define MAX_GTT_CNT 5 | ||
688 | 695 | ||
689 | enum sc_op_flags { | 696 | enum sc_op_flags { |
690 | SC_OP_INVALID, | 697 | SC_OP_INVALID, |
@@ -727,6 +734,7 @@ struct ath_softc { | |||
727 | unsigned long sc_flags; | 734 | unsigned long sc_flags; |
728 | unsigned long driver_data; | 735 | unsigned long driver_data; |
729 | 736 | ||
737 | u8 gtt_cnt; | ||
730 | u32 intrstatus; | 738 | u32 intrstatus; |
731 | u16 ps_flags; /* PS_* */ | 739 | u16 ps_flags; /* PS_* */ |
732 | u16 curtxpow; | 740 | u16 curtxpow; |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index b041052a10ee..ab7264c1d8f7 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -943,14 +943,10 @@ static const struct file_operations fops_reset = { | |||
943 | static ssize_t read_file_recv(struct file *file, char __user *user_buf, | 943 | static ssize_t read_file_recv(struct file *file, char __user *user_buf, |
944 | size_t count, loff_t *ppos) | 944 | size_t count, loff_t *ppos) |
945 | { | 945 | { |
946 | #define PHY_ERR(s, p) \ | ||
947 | len += scnprintf(buf + len, size - len, "%22s : %10u\n", s, \ | ||
948 | sc->debug.stats.rxstats.phy_err_stats[p]); | ||
949 | |||
950 | #define RXS_ERR(s, e) \ | 946 | #define RXS_ERR(s, e) \ |
951 | do { \ | 947 | do { \ |
952 | len += scnprintf(buf + len, size - len, \ | 948 | len += scnprintf(buf + len, size - len, \ |
953 | "%22s : %10u\n", s, \ | 949 | "%18s : %10u\n", s, \ |
954 | sc->debug.stats.rxstats.e);\ | 950 | sc->debug.stats.rxstats.e);\ |
955 | } while (0) | 951 | } while (0) |
956 | 952 | ||
@@ -963,6 +959,12 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
963 | if (buf == NULL) | 959 | if (buf == NULL) |
964 | return -ENOMEM; | 960 | return -ENOMEM; |
965 | 961 | ||
962 | RXS_ERR("PKTS-ALL", rx_pkts_all); | ||
963 | RXS_ERR("BYTES-ALL", rx_bytes_all); | ||
964 | RXS_ERR("BEACONS", rx_beacons); | ||
965 | RXS_ERR("FRAGS", rx_frags); | ||
966 | RXS_ERR("SPECTRAL", rx_spectral); | ||
967 | |||
966 | RXS_ERR("CRC ERR", crc_err); | 968 | RXS_ERR("CRC ERR", crc_err); |
967 | RXS_ERR("DECRYPT CRC ERR", decrypt_crc_err); | 969 | RXS_ERR("DECRYPT CRC ERR", decrypt_crc_err); |
968 | RXS_ERR("PHY ERR", phy_err); | 970 | RXS_ERR("PHY ERR", phy_err); |
@@ -970,43 +972,10 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
970 | RXS_ERR("PRE-DELIM CRC ERR", pre_delim_crc_err); | 972 | RXS_ERR("PRE-DELIM CRC ERR", pre_delim_crc_err); |
971 | RXS_ERR("POST-DELIM CRC ERR", post_delim_crc_err); | 973 | RXS_ERR("POST-DELIM CRC ERR", post_delim_crc_err); |
972 | RXS_ERR("DECRYPT BUSY ERR", decrypt_busy_err); | 974 | RXS_ERR("DECRYPT BUSY ERR", decrypt_busy_err); |
973 | RXS_ERR("RX-LENGTH-ERR", rx_len_err); | 975 | RXS_ERR("LENGTH-ERR", rx_len_err); |
974 | RXS_ERR("RX-OOM-ERR", rx_oom_err); | 976 | RXS_ERR("OOM-ERR", rx_oom_err); |
975 | RXS_ERR("RX-RATE-ERR", rx_rate_err); | 977 | RXS_ERR("RATE-ERR", rx_rate_err); |
976 | RXS_ERR("RX-TOO-MANY-FRAGS", rx_too_many_frags_err); | 978 | RXS_ERR("TOO-MANY-FRAGS", rx_too_many_frags_err); |
977 | |||
978 | PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN); | ||
979 | PHY_ERR("TIMING ERR", ATH9K_PHYERR_TIMING); | ||
980 | PHY_ERR("PARITY ERR", ATH9K_PHYERR_PARITY); | ||
981 | PHY_ERR("RATE ERR", ATH9K_PHYERR_RATE); | ||
982 | PHY_ERR("LENGTH ERR", ATH9K_PHYERR_LENGTH); | ||
983 | PHY_ERR("RADAR ERR", ATH9K_PHYERR_RADAR); | ||
984 | PHY_ERR("SERVICE ERR", ATH9K_PHYERR_SERVICE); | ||
985 | PHY_ERR("TOR ERR", ATH9K_PHYERR_TOR); | ||
986 | PHY_ERR("OFDM-TIMING ERR", ATH9K_PHYERR_OFDM_TIMING); | ||
987 | PHY_ERR("OFDM-SIGNAL-PARITY ERR", ATH9K_PHYERR_OFDM_SIGNAL_PARITY); | ||
988 | PHY_ERR("OFDM-RATE ERR", ATH9K_PHYERR_OFDM_RATE_ILLEGAL); | ||
989 | PHY_ERR("OFDM-LENGTH ERR", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL); | ||
990 | PHY_ERR("OFDM-POWER-DROP ERR", ATH9K_PHYERR_OFDM_POWER_DROP); | ||
991 | PHY_ERR("OFDM-SERVICE ERR", ATH9K_PHYERR_OFDM_SERVICE); | ||
992 | PHY_ERR("OFDM-RESTART ERR", ATH9K_PHYERR_OFDM_RESTART); | ||
993 | PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT); | ||
994 | PHY_ERR("CCK-TIMING ERR", ATH9K_PHYERR_CCK_TIMING); | ||
995 | PHY_ERR("CCK-HEADER-CRC ERR", ATH9K_PHYERR_CCK_HEADER_CRC); | ||
996 | PHY_ERR("CCK-RATE ERR", ATH9K_PHYERR_CCK_RATE_ILLEGAL); | ||
997 | PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE); | ||
998 | PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART); | ||
999 | PHY_ERR("CCK-LENGTH ERR", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL); | ||
1000 | PHY_ERR("CCK-POWER-DROP ERR", ATH9K_PHYERR_CCK_POWER_DROP); | ||
1001 | PHY_ERR("HT-CRC ERR", ATH9K_PHYERR_HT_CRC_ERROR); | ||
1002 | PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); | ||
1003 | PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL); | ||
1004 | |||
1005 | RXS_ERR("RX-Pkts-All", rx_pkts_all); | ||
1006 | RXS_ERR("RX-Bytes-All", rx_bytes_all); | ||
1007 | RXS_ERR("RX-Beacons", rx_beacons); | ||
1008 | RXS_ERR("RX-Frags", rx_frags); | ||
1009 | RXS_ERR("RX-Spectral", rx_spectral); | ||
1010 | 979 | ||
1011 | if (len > size) | 980 | if (len > size) |
1012 | len = size; | 981 | len = size; |
@@ -1017,7 +986,6 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
1017 | return retval; | 986 | return retval; |
1018 | 987 | ||
1019 | #undef RXS_ERR | 988 | #undef RXS_ERR |
1020 | #undef PHY_ERR | ||
1021 | } | 989 | } |
1022 | 990 | ||
1023 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) | 991 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) |
@@ -1056,6 +1024,67 @@ static const struct file_operations fops_recv = { | |||
1056 | .llseek = default_llseek, | 1024 | .llseek = default_llseek, |
1057 | }; | 1025 | }; |
1058 | 1026 | ||
1027 | static ssize_t read_file_phy_err(struct file *file, char __user *user_buf, | ||
1028 | size_t count, loff_t *ppos) | ||
1029 | { | ||
1030 | #define PHY_ERR(s, p) \ | ||
1031 | len += scnprintf(buf + len, size - len, "%22s : %10u\n", s, \ | ||
1032 | sc->debug.stats.rxstats.phy_err_stats[p]); | ||
1033 | |||
1034 | struct ath_softc *sc = file->private_data; | ||
1035 | char *buf; | ||
1036 | unsigned int len = 0, size = 1600; | ||
1037 | ssize_t retval = 0; | ||
1038 | |||
1039 | buf = kzalloc(size, GFP_KERNEL); | ||
1040 | if (buf == NULL) | ||
1041 | return -ENOMEM; | ||
1042 | |||
1043 | PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN); | ||
1044 | PHY_ERR("TIMING ERR", ATH9K_PHYERR_TIMING); | ||
1045 | PHY_ERR("PARITY ERR", ATH9K_PHYERR_PARITY); | ||
1046 | PHY_ERR("RATE ERR", ATH9K_PHYERR_RATE); | ||
1047 | PHY_ERR("LENGTH ERR", ATH9K_PHYERR_LENGTH); | ||
1048 | PHY_ERR("RADAR ERR", ATH9K_PHYERR_RADAR); | ||
1049 | PHY_ERR("SERVICE ERR", ATH9K_PHYERR_SERVICE); | ||
1050 | PHY_ERR("TOR ERR", ATH9K_PHYERR_TOR); | ||
1051 | PHY_ERR("OFDM-TIMING ERR", ATH9K_PHYERR_OFDM_TIMING); | ||
1052 | PHY_ERR("OFDM-SIGNAL-PARITY ERR", ATH9K_PHYERR_OFDM_SIGNAL_PARITY); | ||
1053 | PHY_ERR("OFDM-RATE ERR", ATH9K_PHYERR_OFDM_RATE_ILLEGAL); | ||
1054 | PHY_ERR("OFDM-LENGTH ERR", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL); | ||
1055 | PHY_ERR("OFDM-POWER-DROP ERR", ATH9K_PHYERR_OFDM_POWER_DROP); | ||
1056 | PHY_ERR("OFDM-SERVICE ERR", ATH9K_PHYERR_OFDM_SERVICE); | ||
1057 | PHY_ERR("OFDM-RESTART ERR", ATH9K_PHYERR_OFDM_RESTART); | ||
1058 | PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT); | ||
1059 | PHY_ERR("CCK-TIMING ERR", ATH9K_PHYERR_CCK_TIMING); | ||
1060 | PHY_ERR("CCK-HEADER-CRC ERR", ATH9K_PHYERR_CCK_HEADER_CRC); | ||
1061 | PHY_ERR("CCK-RATE ERR", ATH9K_PHYERR_CCK_RATE_ILLEGAL); | ||
1062 | PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE); | ||
1063 | PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART); | ||
1064 | PHY_ERR("CCK-LENGTH ERR", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL); | ||
1065 | PHY_ERR("CCK-POWER-DROP ERR", ATH9K_PHYERR_CCK_POWER_DROP); | ||
1066 | PHY_ERR("HT-CRC ERR", ATH9K_PHYERR_HT_CRC_ERROR); | ||
1067 | PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); | ||
1068 | PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL); | ||
1069 | |||
1070 | if (len > size) | ||
1071 | len = size; | ||
1072 | |||
1073 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
1074 | kfree(buf); | ||
1075 | |||
1076 | return retval; | ||
1077 | |||
1078 | #undef PHY_ERR | ||
1079 | } | ||
1080 | |||
1081 | static const struct file_operations fops_phy_err = { | ||
1082 | .read = read_file_phy_err, | ||
1083 | .open = simple_open, | ||
1084 | .owner = THIS_MODULE, | ||
1085 | .llseek = default_llseek, | ||
1086 | }; | ||
1087 | |||
1059 | static ssize_t read_file_regidx(struct file *file, char __user *user_buf, | 1088 | static ssize_t read_file_regidx(struct file *file, char __user *user_buf, |
1060 | size_t count, loff_t *ppos) | 1089 | size_t count, loff_t *ppos) |
1061 | { | 1090 | { |
@@ -1322,86 +1351,6 @@ static const struct file_operations fops_btcoex = { | |||
1322 | }; | 1351 | }; |
1323 | #endif | 1352 | #endif |
1324 | 1353 | ||
1325 | static ssize_t read_file_node_stat(struct file *file, char __user *user_buf, | ||
1326 | size_t count, loff_t *ppos) | ||
1327 | { | ||
1328 | struct ath_node *an = file->private_data; | ||
1329 | struct ath_softc *sc = an->sc; | ||
1330 | struct ath_atx_tid *tid; | ||
1331 | struct ath_atx_ac *ac; | ||
1332 | struct ath_txq *txq; | ||
1333 | u32 len = 0, size = 4096; | ||
1334 | char *buf; | ||
1335 | size_t retval; | ||
1336 | int tidno, acno; | ||
1337 | |||
1338 | buf = kzalloc(size, GFP_KERNEL); | ||
1339 | if (buf == NULL) | ||
1340 | return -ENOMEM; | ||
1341 | |||
1342 | if (!an->sta->ht_cap.ht_supported) { | ||
1343 | len = scnprintf(buf, size, "%s\n", | ||
1344 | "HT not supported"); | ||
1345 | goto exit; | ||
1346 | } | ||
1347 | |||
1348 | len = scnprintf(buf, size, "Max-AMPDU: %d\n", | ||
1349 | an->maxampdu); | ||
1350 | len += scnprintf(buf + len, size - len, "MPDU Density: %d\n\n", | ||
1351 | an->mpdudensity); | ||
1352 | |||
1353 | len += scnprintf(buf + len, size - len, | ||
1354 | "%2s%7s\n", "AC", "SCHED"); | ||
1355 | |||
1356 | for (acno = 0, ac = &an->ac[acno]; | ||
1357 | acno < IEEE80211_NUM_ACS; acno++, ac++) { | ||
1358 | txq = ac->txq; | ||
1359 | ath_txq_lock(sc, txq); | ||
1360 | len += scnprintf(buf + len, size - len, | ||
1361 | "%2d%7d\n", | ||
1362 | acno, ac->sched); | ||
1363 | ath_txq_unlock(sc, txq); | ||
1364 | } | ||
1365 | |||
1366 | len += scnprintf(buf + len, size - len, | ||
1367 | "\n%3s%11s%10s%10s%10s%10s%9s%6s%8s\n", | ||
1368 | "TID", "SEQ_START", "SEQ_NEXT", "BAW_SIZE", | ||
1369 | "BAW_HEAD", "BAW_TAIL", "BAR_IDX", "SCHED", "PAUSED"); | ||
1370 | |||
1371 | for (tidno = 0, tid = &an->tid[tidno]; | ||
1372 | tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { | ||
1373 | txq = tid->ac->txq; | ||
1374 | ath_txq_lock(sc, txq); | ||
1375 | len += scnprintf(buf + len, size - len, | ||
1376 | "%3d%11d%10d%10d%10d%10d%9d%6d%8d\n", | ||
1377 | tid->tidno, tid->seq_start, tid->seq_next, | ||
1378 | tid->baw_size, tid->baw_head, tid->baw_tail, | ||
1379 | tid->bar_index, tid->sched, tid->paused); | ||
1380 | ath_txq_unlock(sc, txq); | ||
1381 | } | ||
1382 | exit: | ||
1383 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
1384 | kfree(buf); | ||
1385 | |||
1386 | return retval; | ||
1387 | } | ||
1388 | |||
1389 | static const struct file_operations fops_node_stat = { | ||
1390 | .read = read_file_node_stat, | ||
1391 | .open = simple_open, | ||
1392 | .owner = THIS_MODULE, | ||
1393 | .llseek = default_llseek, | ||
1394 | }; | ||
1395 | |||
1396 | void ath9k_sta_add_debugfs(struct ieee80211_hw *hw, | ||
1397 | struct ieee80211_vif *vif, | ||
1398 | struct ieee80211_sta *sta, | ||
1399 | struct dentry *dir) | ||
1400 | { | ||
1401 | struct ath_node *an = (struct ath_node *)sta->drv_priv; | ||
1402 | debugfs_create_file("node_stat", S_IRUGO, dir, an, &fops_node_stat); | ||
1403 | } | ||
1404 | |||
1405 | /* Ethtool support for get-stats */ | 1354 | /* Ethtool support for get-stats */ |
1406 | 1355 | ||
1407 | #define AMKSTR(nm) #nm "_BE", #nm "_BK", #nm "_VI", #nm "_VO" | 1356 | #define AMKSTR(nm) #nm "_BE", #nm "_BK", #nm "_VI", #nm "_VO" |
@@ -1569,6 +1518,8 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
1569 | &fops_reset); | 1518 | &fops_reset); |
1570 | debugfs_create_file("recv", S_IRUSR, sc->debug.debugfs_phy, sc, | 1519 | debugfs_create_file("recv", S_IRUSR, sc->debug.debugfs_phy, sc, |
1571 | &fops_recv); | 1520 | &fops_recv); |
1521 | debugfs_create_file("phy_err", S_IRUSR, sc->debug.debugfs_phy, sc, | ||
1522 | &fops_phy_err); | ||
1572 | debugfs_create_u8("rx_chainmask", S_IRUSR, sc->debug.debugfs_phy, | 1523 | debugfs_create_u8("rx_chainmask", S_IRUSR, sc->debug.debugfs_phy, |
1573 | &ah->rxchainmask); | 1524 | &ah->rxchainmask); |
1574 | debugfs_create_u8("tx_chainmask", S_IRUSR, sc->debug.debugfs_phy, | 1525 | debugfs_create_u8("tx_chainmask", S_IRUSR, sc->debug.debugfs_phy, |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index ec02d38ea8ea..cc7a025d833e 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -27,11 +27,13 @@ struct fft_sample_tlv; | |||
27 | 27 | ||
28 | #ifdef CONFIG_ATH9K_DEBUGFS | 28 | #ifdef CONFIG_ATH9K_DEBUGFS |
29 | #define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++ | 29 | #define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++ |
30 | #define RX_STAT_INC(c) (sc->debug.stats.rxstats.c++) | ||
30 | #define RESET_STAT_INC(sc, type) sc->debug.stats.reset[type]++ | 31 | #define RESET_STAT_INC(sc, type) sc->debug.stats.reset[type]++ |
31 | #define ANT_STAT_INC(i, c) sc->debug.stats.ant_stats[i].c++ | 32 | #define ANT_STAT_INC(i, c) sc->debug.stats.ant_stats[i].c++ |
32 | #define ANT_LNA_INC(i, c) sc->debug.stats.ant_stats[i].lna_recv_cnt[c]++; | 33 | #define ANT_LNA_INC(i, c) sc->debug.stats.ant_stats[i].lna_recv_cnt[c]++; |
33 | #else | 34 | #else |
34 | #define TX_STAT_INC(q, c) do { } while (0) | 35 | #define TX_STAT_INC(q, c) do { } while (0) |
36 | #define RX_STAT_INC(c) | ||
35 | #define RESET_STAT_INC(sc, type) do { } while (0) | 37 | #define RESET_STAT_INC(sc, type) do { } while (0) |
36 | #define ANT_STAT_INC(i, c) do { } while (0) | 38 | #define ANT_STAT_INC(i, c) do { } while (0) |
37 | #define ANT_LNA_INC(i, c) do { } while (0) | 39 | #define ANT_LNA_INC(i, c) do { } while (0) |
@@ -42,6 +44,7 @@ enum ath_reset_type { | |||
42 | RESET_TYPE_BB_WATCHDOG, | 44 | RESET_TYPE_BB_WATCHDOG, |
43 | RESET_TYPE_FATAL_INT, | 45 | RESET_TYPE_FATAL_INT, |
44 | RESET_TYPE_TX_ERROR, | 46 | RESET_TYPE_TX_ERROR, |
47 | RESET_TYPE_TX_GTT, | ||
45 | RESET_TYPE_TX_HANG, | 48 | RESET_TYPE_TX_HANG, |
46 | RESET_TYPE_PLL_HANG, | 49 | RESET_TYPE_PLL_HANG, |
47 | RESET_TYPE_MAC_HANG, | 50 | RESET_TYPE_MAC_HANG, |
@@ -201,7 +204,23 @@ struct ath_tx_stats { | |||
201 | TXSTATS[PR_QNUM(IEEE80211_AC_VO)].elem); \ | 204 | TXSTATS[PR_QNUM(IEEE80211_AC_VO)].elem); \ |
202 | } while(0) | 205 | } while(0) |
203 | 206 | ||
204 | #define RX_STAT_INC(c) (sc->debug.stats.rxstats.c++) | 207 | struct ath_rx_rate_stats { |
208 | struct { | ||
209 | u32 ht20_cnt; | ||
210 | u32 ht40_cnt; | ||
211 | u32 sgi_cnt; | ||
212 | u32 lgi_cnt; | ||
213 | } ht_stats[24]; | ||
214 | |||
215 | struct { | ||
216 | u32 ofdm_cnt; | ||
217 | } ofdm_stats[8]; | ||
218 | |||
219 | struct { | ||
220 | u32 cck_lp_cnt; | ||
221 | u32 cck_sp_cnt; | ||
222 | } cck_stats[4]; | ||
223 | }; | ||
205 | 224 | ||
206 | /** | 225 | /** |
207 | * struct ath_rx_stats - RX Statistics | 226 | * struct ath_rx_stats - RX Statistics |
@@ -299,8 +318,6 @@ void ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause); | |||
299 | 318 | ||
300 | #else | 319 | #else |
301 | 320 | ||
302 | #define RX_STAT_INC(c) /* NOP */ | ||
303 | |||
304 | static inline int ath9k_init_debug(struct ath_hw *ah) | 321 | static inline int ath9k_init_debug(struct ath_hw *ah) |
305 | { | 322 | { |
306 | return 0; | 323 | return 0; |
@@ -338,4 +355,16 @@ ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause) | |||
338 | 355 | ||
339 | #endif /* CONFIG_ATH9K_DEBUGFS */ | 356 | #endif /* CONFIG_ATH9K_DEBUGFS */ |
340 | 357 | ||
358 | #ifdef CONFIG_ATH9K_STATION_STATISTICS | ||
359 | void ath_debug_rate_stats(struct ath_softc *sc, | ||
360 | struct ath_rx_status *rs, | ||
361 | struct sk_buff *skb); | ||
362 | #else | ||
363 | static inline void ath_debug_rate_stats(struct ath_softc *sc, | ||
364 | struct ath_rx_status *rs, | ||
365 | struct sk_buff *skb) | ||
366 | { | ||
367 | } | ||
368 | #endif /* CONFIG_ATH9K_STATION_STATISTICS */ | ||
369 | |||
341 | #endif /* DEBUG_H */ | 370 | #endif /* DEBUG_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/debug_sta.c b/drivers/net/wireless/ath/ath9k/debug_sta.c new file mode 100644 index 000000000000..d76e6e0120d2 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/debug_sta.c | |||
@@ -0,0 +1,269 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * 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 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "ath9k.h" | ||
18 | |||
19 | /*************/ | ||
20 | /* node_aggr */ | ||
21 | /*************/ | ||
22 | |||
23 | static ssize_t read_file_node_aggr(struct file *file, char __user *user_buf, | ||
24 | size_t count, loff_t *ppos) | ||
25 | { | ||
26 | struct ath_node *an = file->private_data; | ||
27 | struct ath_softc *sc = an->sc; | ||
28 | struct ath_atx_tid *tid; | ||
29 | struct ath_atx_ac *ac; | ||
30 | struct ath_txq *txq; | ||
31 | u32 len = 0, size = 4096; | ||
32 | char *buf; | ||
33 | size_t retval; | ||
34 | int tidno, acno; | ||
35 | |||
36 | buf = kzalloc(size, GFP_KERNEL); | ||
37 | if (buf == NULL) | ||
38 | return -ENOMEM; | ||
39 | |||
40 | if (!an->sta->ht_cap.ht_supported) { | ||
41 | len = scnprintf(buf, size, "%s\n", | ||
42 | "HT not supported"); | ||
43 | goto exit; | ||
44 | } | ||
45 | |||
46 | len = scnprintf(buf, size, "Max-AMPDU: %d\n", | ||
47 | an->maxampdu); | ||
48 | len += scnprintf(buf + len, size - len, "MPDU Density: %d\n\n", | ||
49 | an->mpdudensity); | ||
50 | |||
51 | len += scnprintf(buf + len, size - len, | ||
52 | "%2s%7s\n", "AC", "SCHED"); | ||
53 | |||
54 | for (acno = 0, ac = &an->ac[acno]; | ||
55 | acno < IEEE80211_NUM_ACS; acno++, ac++) { | ||
56 | txq = ac->txq; | ||
57 | ath_txq_lock(sc, txq); | ||
58 | len += scnprintf(buf + len, size - len, | ||
59 | "%2d%7d\n", | ||
60 | acno, ac->sched); | ||
61 | ath_txq_unlock(sc, txq); | ||
62 | } | ||
63 | |||
64 | len += scnprintf(buf + len, size - len, | ||
65 | "\n%3s%11s%10s%10s%10s%10s%9s%6s%8s\n", | ||
66 | "TID", "SEQ_START", "SEQ_NEXT", "BAW_SIZE", | ||
67 | "BAW_HEAD", "BAW_TAIL", "BAR_IDX", "SCHED", "PAUSED"); | ||
68 | |||
69 | for (tidno = 0, tid = &an->tid[tidno]; | ||
70 | tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { | ||
71 | txq = tid->ac->txq; | ||
72 | ath_txq_lock(sc, txq); | ||
73 | if (tid->active) { | ||
74 | len += scnprintf(buf + len, size - len, | ||
75 | "%3d%11d%10d%10d%10d%10d%9d%6d%8d\n", | ||
76 | tid->tidno, | ||
77 | tid->seq_start, | ||
78 | tid->seq_next, | ||
79 | tid->baw_size, | ||
80 | tid->baw_head, | ||
81 | tid->baw_tail, | ||
82 | tid->bar_index, | ||
83 | tid->sched, | ||
84 | tid->paused); | ||
85 | } | ||
86 | ath_txq_unlock(sc, txq); | ||
87 | } | ||
88 | exit: | ||
89 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
90 | kfree(buf); | ||
91 | |||
92 | return retval; | ||
93 | } | ||
94 | |||
95 | static const struct file_operations fops_node_aggr = { | ||
96 | .read = read_file_node_aggr, | ||
97 | .open = simple_open, | ||
98 | .owner = THIS_MODULE, | ||
99 | .llseek = default_llseek, | ||
100 | }; | ||
101 | |||
102 | /*************/ | ||
103 | /* node_recv */ | ||
104 | /*************/ | ||
105 | |||
106 | void ath_debug_rate_stats(struct ath_softc *sc, | ||
107 | struct ath_rx_status *rs, | ||
108 | struct sk_buff *skb) | ||
109 | { | ||
110 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
111 | struct ath_hw *ah = sc->sc_ah; | ||
112 | struct ieee80211_rx_status *rxs; | ||
113 | struct ath_rx_rate_stats *rstats; | ||
114 | struct ieee80211_sta *sta; | ||
115 | struct ath_node *an; | ||
116 | |||
117 | if (!ieee80211_is_data(hdr->frame_control)) | ||
118 | return; | ||
119 | |||
120 | rcu_read_lock(); | ||
121 | |||
122 | sta = ieee80211_find_sta_by_ifaddr(sc->hw, hdr->addr2, NULL); | ||
123 | if (!sta) | ||
124 | goto exit; | ||
125 | |||
126 | an = (struct ath_node *) sta->drv_priv; | ||
127 | rstats = &an->rx_rate_stats; | ||
128 | rxs = IEEE80211_SKB_RXCB(skb); | ||
129 | |||
130 | if (IS_HT_RATE(rs->rs_rate)) { | ||
131 | if (rxs->rate_idx >= ARRAY_SIZE(rstats->ht_stats)) | ||
132 | goto exit; | ||
133 | |||
134 | if (rxs->flag & RX_FLAG_40MHZ) | ||
135 | rstats->ht_stats[rxs->rate_idx].ht40_cnt++; | ||
136 | else | ||
137 | rstats->ht_stats[rxs->rate_idx].ht20_cnt++; | ||
138 | |||
139 | if (rxs->flag & RX_FLAG_SHORT_GI) | ||
140 | rstats->ht_stats[rxs->rate_idx].sgi_cnt++; | ||
141 | else | ||
142 | rstats->ht_stats[rxs->rate_idx].lgi_cnt++; | ||
143 | |||
144 | goto exit; | ||
145 | } | ||
146 | |||
147 | if (IS_CCK_RATE(rs->rs_rate)) { | ||
148 | if (rxs->flag & RX_FLAG_SHORTPRE) | ||
149 | rstats->cck_stats[rxs->rate_idx].cck_sp_cnt++; | ||
150 | else | ||
151 | rstats->cck_stats[rxs->rate_idx].cck_lp_cnt++; | ||
152 | |||
153 | goto exit; | ||
154 | } | ||
155 | |||
156 | if (IS_OFDM_RATE(rs->rs_rate)) { | ||
157 | if (ah->curchan->chan->band == IEEE80211_BAND_2GHZ) | ||
158 | rstats->ofdm_stats[rxs->rate_idx - 4].ofdm_cnt++; | ||
159 | else | ||
160 | rstats->ofdm_stats[rxs->rate_idx].ofdm_cnt++; | ||
161 | } | ||
162 | exit: | ||
163 | rcu_read_unlock(); | ||
164 | } | ||
165 | |||
166 | #define PRINT_CCK_RATE(str, i, sp) \ | ||
167 | do { \ | ||
168 | len += scnprintf(buf + len, size - len, \ | ||
169 | "%11s : %10u\n", \ | ||
170 | str, \ | ||
171 | (sp) ? rstats->cck_stats[i].cck_sp_cnt : \ | ||
172 | rstats->cck_stats[i].cck_lp_cnt); \ | ||
173 | } while (0) | ||
174 | |||
175 | #define PRINT_OFDM_RATE(str, i) \ | ||
176 | do { \ | ||
177 | len += scnprintf(buf + len, size - len, \ | ||
178 | "%11s : %10u\n", \ | ||
179 | str, \ | ||
180 | rstats->ofdm_stats[i].ofdm_cnt); \ | ||
181 | } while (0) | ||
182 | |||
183 | static ssize_t read_file_node_recv(struct file *file, char __user *user_buf, | ||
184 | size_t count, loff_t *ppos) | ||
185 | { | ||
186 | struct ath_node *an = file->private_data; | ||
187 | struct ath_softc *sc = an->sc; | ||
188 | struct ath_hw *ah = sc->sc_ah; | ||
189 | struct ath_rx_rate_stats *rstats; | ||
190 | struct ieee80211_sta *sta = an->sta; | ||
191 | enum ieee80211_band band; | ||
192 | u32 len = 0, size = 4096; | ||
193 | char *buf; | ||
194 | size_t retval; | ||
195 | int i; | ||
196 | |||
197 | buf = kzalloc(size, GFP_KERNEL); | ||
198 | if (buf == NULL) | ||
199 | return -ENOMEM; | ||
200 | |||
201 | band = ah->curchan->chan->band; | ||
202 | rstats = &an->rx_rate_stats; | ||
203 | |||
204 | if (!sta->ht_cap.ht_supported) | ||
205 | goto legacy; | ||
206 | |||
207 | len += scnprintf(buf + len, size - len, | ||
208 | "%24s%10s%10s%10s\n", | ||
209 | "HT20", "HT40", "SGI", "LGI"); | ||
210 | |||
211 | for (i = 0; i < 24; i++) { | ||
212 | len += scnprintf(buf + len, size - len, | ||
213 | "%8s%3u : %10u%10u%10u%10u\n", | ||
214 | "MCS", i, | ||
215 | rstats->ht_stats[i].ht20_cnt, | ||
216 | rstats->ht_stats[i].ht40_cnt, | ||
217 | rstats->ht_stats[i].sgi_cnt, | ||
218 | rstats->ht_stats[i].lgi_cnt); | ||
219 | } | ||
220 | |||
221 | len += scnprintf(buf + len, size - len, "\n"); | ||
222 | |||
223 | legacy: | ||
224 | if (band == IEEE80211_BAND_2GHZ) { | ||
225 | PRINT_CCK_RATE("CCK-1M/LP", 0, false); | ||
226 | PRINT_CCK_RATE("CCK-2M/LP", 1, false); | ||
227 | PRINT_CCK_RATE("CCK-5.5M/LP", 2, false); | ||
228 | PRINT_CCK_RATE("CCK-11M/LP", 3, false); | ||
229 | |||
230 | PRINT_CCK_RATE("CCK-2M/SP", 1, true); | ||
231 | PRINT_CCK_RATE("CCK-5.5M/SP", 2, true); | ||
232 | PRINT_CCK_RATE("CCK-11M/SP", 3, true); | ||
233 | } | ||
234 | |||
235 | PRINT_OFDM_RATE("OFDM-6M", 0); | ||
236 | PRINT_OFDM_RATE("OFDM-9M", 1); | ||
237 | PRINT_OFDM_RATE("OFDM-12M", 2); | ||
238 | PRINT_OFDM_RATE("OFDM-18M", 3); | ||
239 | PRINT_OFDM_RATE("OFDM-24M", 4); | ||
240 | PRINT_OFDM_RATE("OFDM-36M", 5); | ||
241 | PRINT_OFDM_RATE("OFDM-48M", 6); | ||
242 | PRINT_OFDM_RATE("OFDM-54M", 7); | ||
243 | |||
244 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
245 | kfree(buf); | ||
246 | |||
247 | return retval; | ||
248 | } | ||
249 | |||
250 | #undef PRINT_OFDM_RATE | ||
251 | #undef PRINT_CCK_RATE | ||
252 | |||
253 | static const struct file_operations fops_node_recv = { | ||
254 | .read = read_file_node_recv, | ||
255 | .open = simple_open, | ||
256 | .owner = THIS_MODULE, | ||
257 | .llseek = default_llseek, | ||
258 | }; | ||
259 | |||
260 | void ath9k_sta_add_debugfs(struct ieee80211_hw *hw, | ||
261 | struct ieee80211_vif *vif, | ||
262 | struct ieee80211_sta *sta, | ||
263 | struct dentry *dir) | ||
264 | { | ||
265 | struct ath_node *an = (struct ath_node *)sta->drv_priv; | ||
266 | |||
267 | debugfs_create_file("node_aggr", S_IRUGO, dir, an, &fops_node_aggr); | ||
268 | debugfs_create_file("node_recv", S_IRUGO, dir, an, &fops_node_recv); | ||
269 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index b576c44bb314..f4e1de20d99c 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -748,7 +748,6 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, | |||
748 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | 748 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; |
749 | 749 | ||
750 | hw->queues = 4; | 750 | hw->queues = 4; |
751 | hw->channel_change_time = 5000; | ||
752 | hw->max_listen_interval = 1; | 751 | hw->max_listen_interval = 1; |
753 | 752 | ||
754 | hw->vif_data_size = sizeof(struct ath9k_htc_vif); | 753 | hw->vif_data_size = sizeof(struct ath9k_htc_vif); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index b41e008298dc..12e0f32a4905 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |||
@@ -1075,9 +1075,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, | |||
1075 | 1075 | ||
1076 | last_rssi = priv->rx.last_rssi; | 1076 | last_rssi = priv->rx.last_rssi; |
1077 | 1077 | ||
1078 | if (ieee80211_is_beacon(hdr->frame_control) && | 1078 | if (ath_is_mybeacon(common, hdr)) { |
1079 | !is_zero_ether_addr(common->curbssid) && | ||
1080 | ether_addr_equal_64bits(hdr->addr3, common->curbssid)) { | ||
1081 | s8 rssi = rxbuf->rxstatus.rs_rssi; | 1079 | s8 rssi = rxbuf->rxstatus.rs_rssi; |
1082 | 1080 | ||
1083 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) | 1081 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index f2a17fcf1ae4..c36de303c8f3 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -946,7 +946,6 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
946 | 946 | ||
947 | hw->queues = 4; | 947 | hw->queues = 4; |
948 | hw->max_rates = 4; | 948 | hw->max_rates = 4; |
949 | hw->channel_change_time = 5000; | ||
950 | hw->max_listen_interval = 1; | 949 | hw->max_listen_interval = 1; |
951 | hw->max_rate_tries = 10; | 950 | hw->max_rate_tries = 10; |
952 | hw->sta_data_size = sizeof(struct ath_node); | 951 | hw->sta_data_size = sizeof(struct ath_node); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index d0c3aec7c74e..73a36551a5ed 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -258,6 +258,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) | |||
258 | } | 258 | } |
259 | } | 259 | } |
260 | 260 | ||
261 | sc->gtt_cnt = 0; | ||
261 | ieee80211_wake_queues(sc->hw); | 262 | ieee80211_wake_queues(sc->hw); |
262 | 263 | ||
263 | return true; | 264 | return true; |
@@ -476,6 +477,19 @@ void ath9k_tasklet(unsigned long data) | |||
476 | } | 477 | } |
477 | } | 478 | } |
478 | 479 | ||
480 | if (status & ATH9K_INT_GTT) { | ||
481 | sc->gtt_cnt++; | ||
482 | |||
483 | if ((sc->gtt_cnt >= MAX_GTT_CNT) && !ath9k_hw_check_alive(ah)) { | ||
484 | type = RESET_TYPE_TX_GTT; | ||
485 | ath9k_queue_reset(sc, type); | ||
486 | atomic_inc(&ah->intr_ref_cnt); | ||
487 | ath_dbg(common, ANY, | ||
488 | "GTT: Skipping interrupts\n"); | ||
489 | goto out; | ||
490 | } | ||
491 | } | ||
492 | |||
479 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | 493 | spin_lock_irqsave(&sc->sc_pm_lock, flags); |
480 | if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) { | 494 | if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) { |
481 | /* | 495 | /* |
@@ -503,10 +517,19 @@ void ath9k_tasklet(unsigned long data) | |||
503 | } | 517 | } |
504 | 518 | ||
505 | if (status & ATH9K_INT_TX) { | 519 | if (status & ATH9K_INT_TX) { |
506 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | 520 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { |
521 | /* | ||
522 | * For EDMA chips, TX completion is enabled for the | ||
523 | * beacon queue, so if a beacon has been transmitted | ||
524 | * successfully after a GTT interrupt, the GTT counter | ||
525 | * gets reset to zero here. | ||
526 | */ | ||
527 | /* sc->gtt_cnt = 0; */ | ||
528 | |||
507 | ath_tx_edma_tasklet(sc); | 529 | ath_tx_edma_tasklet(sc); |
508 | else | 530 | } else { |
509 | ath_tx_tasklet(sc); | 531 | ath_tx_tasklet(sc); |
532 | } | ||
510 | 533 | ||
511 | wake_up(&sc->tx_wait); | 534 | wake_up(&sc->tx_wait); |
512 | } | 535 | } |
@@ -536,13 +559,13 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
536 | ATH9K_INT_TX | \ | 559 | ATH9K_INT_TX | \ |
537 | ATH9K_INT_BMISS | \ | 560 | ATH9K_INT_BMISS | \ |
538 | ATH9K_INT_CST | \ | 561 | ATH9K_INT_CST | \ |
562 | ATH9K_INT_GTT | \ | ||
539 | ATH9K_INT_TSFOOR | \ | 563 | ATH9K_INT_TSFOOR | \ |
540 | ATH9K_INT_GENTIMER | \ | 564 | ATH9K_INT_GENTIMER | \ |
541 | ATH9K_INT_MCI) | 565 | ATH9K_INT_MCI) |
542 | 566 | ||
543 | struct ath_softc *sc = dev; | 567 | struct ath_softc *sc = dev; |
544 | struct ath_hw *ah = sc->sc_ah; | 568 | struct ath_hw *ah = sc->sc_ah; |
545 | struct ath_common *common = ath9k_hw_common(ah); | ||
546 | enum ath9k_int status; | 569 | enum ath9k_int status; |
547 | u32 sync_cause = 0; | 570 | u32 sync_cause = 0; |
548 | bool sched = false; | 571 | bool sched = false; |
@@ -603,14 +626,12 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
603 | #ifdef CONFIG_ATH9K_WOW | 626 | #ifdef CONFIG_ATH9K_WOW |
604 | if (status & ATH9K_INT_BMISS) { | 627 | if (status & ATH9K_INT_BMISS) { |
605 | if (atomic_read(&sc->wow_sleep_proc_intr) == 0) { | 628 | if (atomic_read(&sc->wow_sleep_proc_intr) == 0) { |
606 | ath_dbg(common, ANY, "during WoW we got a BMISS\n"); | ||
607 | atomic_inc(&sc->wow_got_bmiss_intr); | 629 | atomic_inc(&sc->wow_got_bmiss_intr); |
608 | atomic_dec(&sc->wow_sleep_proc_intr); | 630 | atomic_dec(&sc->wow_sleep_proc_intr); |
609 | } | 631 | } |
610 | } | 632 | } |
611 | #endif | 633 | #endif |
612 | 634 | ||
613 | |||
614 | if (status & ATH9K_INT_SWBA) | 635 | if (status & ATH9K_INT_SWBA) |
615 | tasklet_schedule(&sc->bcon_tasklet); | 636 | tasklet_schedule(&sc->bcon_tasklet); |
616 | 637 | ||
@@ -735,7 +756,12 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
735 | if (ah->config.hw_hang_checks & HW_BB_WATCHDOG) | 756 | if (ah->config.hw_hang_checks & HW_BB_WATCHDOG) |
736 | ah->imask |= ATH9K_INT_BB_WATCHDOG; | 757 | ah->imask |= ATH9K_INT_BB_WATCHDOG; |
737 | 758 | ||
738 | ah->imask |= ATH9K_INT_GTT; | 759 | /* |
760 | * Enable GTT interrupts only for AR9003/AR9004 chips | ||
761 | * for now. | ||
762 | */ | ||
763 | if (AR_SREV_9300_20_OR_LATER(ah)) | ||
764 | ah->imask |= ATH9K_INT_GTT; | ||
739 | 765 | ||
740 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) | 766 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) |
741 | ah->imask |= ATH9K_INT_CST; | 767 | ah->imask |= ATH9K_INT_CST; |
@@ -2111,7 +2137,7 @@ struct ieee80211_ops ath9k_ops = { | |||
2111 | .get_et_strings = ath9k_get_et_strings, | 2137 | .get_et_strings = ath9k_get_et_strings, |
2112 | #endif | 2138 | #endif |
2113 | 2139 | ||
2114 | #if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS) | 2140 | #if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_STATION_STATISTICS) |
2115 | .sta_add_debugfs = ath9k_sta_add_debugfs, | 2141 | .sta_add_debugfs = ath9k_sta_add_debugfs, |
2116 | #endif | 2142 | #endif |
2117 | .sw_scan_start = ath9k_sw_scan_start, | 2143 | .sw_scan_start = ath9k_sw_scan_start, |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index f7cc5b37a18f..a0ebdd000fc2 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -969,21 +969,6 @@ static void ath9k_process_tsf(struct ath_rx_status *rs, | |||
969 | rxs->mactime += 0x100000000ULL; | 969 | rxs->mactime += 0x100000000ULL; |
970 | } | 970 | } |
971 | 971 | ||
972 | static bool ath9k_is_mybeacon(struct ath_softc *sc, struct ieee80211_hdr *hdr) | ||
973 | { | ||
974 | struct ath_hw *ah = sc->sc_ah; | ||
975 | struct ath_common *common = ath9k_hw_common(ah); | ||
976 | |||
977 | if (ieee80211_is_beacon(hdr->frame_control)) { | ||
978 | RX_STAT_INC(rx_beacons); | ||
979 | if (!is_zero_ether_addr(common->curbssid) && | ||
980 | ether_addr_equal_64bits(hdr->addr3, common->curbssid)) | ||
981 | return true; | ||
982 | } | ||
983 | |||
984 | return false; | ||
985 | } | ||
986 | |||
987 | /* | 972 | /* |
988 | * For Decrypt or Demic errors, we only mark packet status here and always push | 973 | * For Decrypt or Demic errors, we only mark packet status here and always push |
989 | * up the frame up to let mac80211 handle the actual error case, be it no | 974 | * up the frame up to let mac80211 handle the actual error case, be it no |
@@ -1071,7 +1056,10 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc, | |||
1071 | goto exit; | 1056 | goto exit; |
1072 | } | 1057 | } |
1073 | 1058 | ||
1074 | rx_stats->is_mybeacon = ath9k_is_mybeacon(sc, hdr); | 1059 | if (ath_is_mybeacon(common, hdr)) { |
1060 | RX_STAT_INC(rx_beacons); | ||
1061 | rx_stats->is_mybeacon = true; | ||
1062 | } | ||
1075 | 1063 | ||
1076 | /* | 1064 | /* |
1077 | * This shouldn't happen, but have a safety check anyway. | 1065 | * This shouldn't happen, but have a safety check anyway. |
@@ -1354,8 +1342,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1354 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | 1342 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
1355 | 1343 | ||
1356 | ath9k_antenna_check(sc, &rs); | 1344 | ath9k_antenna_check(sc, &rs); |
1357 | |||
1358 | ath9k_apply_ampdu_details(sc, &rs, rxs); | 1345 | ath9k_apply_ampdu_details(sc, &rs, rxs); |
1346 | ath_debug_rate_stats(sc, &rs, skb); | ||
1359 | 1347 | ||
1360 | ieee80211_rx(hw, skb); | 1348 | ieee80211_rx(hw, skb); |
1361 | 1349 | ||
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index e8d0e7fc77da..0a75e2f68c9d 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -47,8 +47,6 @@ static u16 bits_per_symbol[][2] = { | |||
47 | { 260, 540 }, /* 7: 64-QAM 5/6 */ | 47 | { 260, 540 }, /* 7: 64-QAM 5/6 */ |
48 | }; | 48 | }; |
49 | 49 | ||
50 | #define IS_HT_RATE(_rate) ((_rate) & 0x80) | ||
51 | |||
52 | static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, | 50 | static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, |
53 | struct ath_atx_tid *tid, struct sk_buff *skb); | 51 | struct ath_atx_tid *tid, struct sk_buff *skb); |
54 | static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | 52 | static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, |
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 4c3f576c3144..4c8cdb097b65 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c | |||
@@ -1967,18 +1967,6 @@ static int carl9170_parse_eeprom(struct ar9170 *ar) | |||
1967 | return -ENOMEM; | 1967 | return -ENOMEM; |
1968 | ar->num_channels = chans; | 1968 | ar->num_channels = chans; |
1969 | 1969 | ||
1970 | /* | ||
1971 | * I measured this, a bandswitch takes roughly | ||
1972 | * 135 ms and a frequency switch about 80. | ||
1973 | * | ||
1974 | * FIXME: measure these values again once EEPROM settings | ||
1975 | * are used, that will influence them! | ||
1976 | */ | ||
1977 | if (bands == 2) | ||
1978 | ar->hw->channel_change_time = 135 * 1000; | ||
1979 | else | ||
1980 | ar->hw->channel_change_time = 80 * 1000; | ||
1981 | |||
1982 | regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]); | 1970 | regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]); |
1983 | 1971 | ||
1984 | /* second part of wiphy init */ | 1972 | /* second part of wiphy init */ |
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c index 1b1b20751ead..536bc46a2912 100644 --- a/drivers/net/wireless/ath/carl9170/rx.c +++ b/drivers/net/wireless/ath/carl9170/rx.c | |||
@@ -519,6 +519,7 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len) | |||
519 | { | 519 | { |
520 | struct ieee80211_hdr *hdr = data; | 520 | struct ieee80211_hdr *hdr = data; |
521 | struct ieee80211_tim_ie *tim_ie; | 521 | struct ieee80211_tim_ie *tim_ie; |
522 | struct ath_common *common = &ar->common; | ||
522 | u8 *tim; | 523 | u8 *tim; |
523 | u8 tim_len; | 524 | u8 tim_len; |
524 | bool cam; | 525 | bool cam; |
@@ -526,17 +527,13 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len) | |||
526 | if (likely(!(ar->hw->conf.flags & IEEE80211_CONF_PS))) | 527 | if (likely(!(ar->hw->conf.flags & IEEE80211_CONF_PS))) |
527 | return; | 528 | return; |
528 | 529 | ||
529 | /* check if this really is a beacon */ | ||
530 | if (!ieee80211_is_beacon(hdr->frame_control)) | ||
531 | return; | ||
532 | |||
533 | /* min. beacon length + FCS_LEN */ | 530 | /* min. beacon length + FCS_LEN */ |
534 | if (len <= 40 + FCS_LEN) | 531 | if (len <= 40 + FCS_LEN) |
535 | return; | 532 | return; |
536 | 533 | ||
534 | /* check if this really is a beacon */ | ||
537 | /* and only beacons from the associated BSSID, please */ | 535 | /* and only beacons from the associated BSSID, please */ |
538 | if (!ether_addr_equal_64bits(hdr->addr3, ar->common.curbssid) || | 536 | if (!ath_is_mybeacon(common, hdr) || !common->curaid) |
539 | !ar->common.curaid) | ||
540 | return; | 537 | return; |
541 | 538 | ||
542 | ar->ps.last_beacon = jiffies; | 539 | ar->ps.last_beacon = jiffies; |
diff --git a/drivers/net/wireless/ath/main.c b/drivers/net/wireless/ath/main.c index 8e99540cd90e..8b0ac14d5c32 100644 --- a/drivers/net/wireless/ath/main.c +++ b/drivers/net/wireless/ath/main.c | |||
@@ -59,6 +59,14 @@ struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, | |||
59 | } | 59 | } |
60 | EXPORT_SYMBOL(ath_rxbuf_alloc); | 60 | EXPORT_SYMBOL(ath_rxbuf_alloc); |
61 | 61 | ||
62 | bool ath_is_mybeacon(struct ath_common *common, struct ieee80211_hdr *hdr) | ||
63 | { | ||
64 | return ieee80211_is_beacon(hdr->frame_control) && | ||
65 | !is_zero_ether_addr(common->curbssid) && | ||
66 | ether_addr_equal_64bits(hdr->addr3, common->curbssid); | ||
67 | } | ||
68 | EXPORT_SYMBOL(ath_is_mybeacon); | ||
69 | |||
62 | void ath_printk(const char *level, const struct ath_common* common, | 70 | void ath_printk(const char *level, const struct ath_common* common, |
63 | const char *fmt, ...) | 71 | const char *fmt, ...) |
64 | { | 72 | { |
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 9e154732afaa..e5e905910db4 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c | |||
@@ -632,7 +632,8 @@ ath_regd_init_wiphy(struct ath_regulatory *reg, | |||
632 | const struct ieee80211_regdomain *regd; | 632 | const struct ieee80211_regdomain *regd; |
633 | 633 | ||
634 | wiphy->reg_notifier = reg_notifier; | 634 | wiphy->reg_notifier = reg_notifier; |
635 | wiphy->regulatory_flags |= REGULATORY_STRICT_REG; | 635 | wiphy->regulatory_flags |= REGULATORY_STRICT_REG | |
636 | REGULATORY_CUSTOM_REG; | ||
636 | 637 | ||
637 | if (ath_is_world_regd(reg)) { | 638 | if (ath_is_world_regd(reg)) { |
638 | /* | 639 | /* |
@@ -640,8 +641,7 @@ ath_regd_init_wiphy(struct ath_regulatory *reg, | |||
640 | * saved on the wiphy orig_* parameters | 641 | * saved on the wiphy orig_* parameters |
641 | */ | 642 | */ |
642 | regd = ath_world_regdomain(reg); | 643 | regd = ath_world_regdomain(reg); |
643 | wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | | 644 | wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_FOLLOW_POWER; |
644 | REGULATORY_COUNTRY_IE_FOLLOW_POWER; | ||
645 | } else { | 645 | } else { |
646 | /* | 646 | /* |
647 | * This gets applied in the case of the absence of CRDA, | 647 | * This gets applied in the case of the absence of CRDA, |
@@ -650,6 +650,7 @@ ath_regd_init_wiphy(struct ath_regulatory *reg, | |||
650 | */ | 650 | */ |
651 | regd = ath_default_world_regdomain(); | 651 | regd = ath_default_world_regdomain(); |
652 | } | 652 | } |
653 | |||
653 | wiphy_apply_custom_regulatory(wiphy, regd); | 654 | wiphy_apply_custom_regulatory(wiphy, regd); |
654 | ath_reg_apply_radar_flags(wiphy); | 655 | ath_reg_apply_radar_flags(wiphy); |
655 | ath_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg); | 656 | ath_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg); |
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 9b88440ef05b..0b0975d88b43 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <linux/ip.h> | 21 | #include <linux/ip.h> |
22 | #include <linux/ipv6.h> | 22 | #include <linux/ipv6.h> |
23 | #include <net/ipv6.h> | 23 | #include <net/ipv6.h> |
24 | #include <asm/processor.h> | 24 | #include <linux/prefetch.h> |
25 | 25 | ||
26 | #include "wil6210.h" | 26 | #include "wil6210.h" |
27 | #include "wmi.h" | 27 | #include "wmi.h" |
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 7f3d461f7e8d..54376fddfaf9 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -731,8 +731,6 @@ enum b43_firmware_file_type { | |||
731 | struct b43_request_fw_context { | 731 | struct b43_request_fw_context { |
732 | /* The device we are requesting the fw for. */ | 732 | /* The device we are requesting the fw for. */ |
733 | struct b43_wldev *dev; | 733 | struct b43_wldev *dev; |
734 | /* a completion event structure needed if this call is asynchronous */ | ||
735 | struct completion fw_load_complete; | ||
736 | /* a pointer to the firmware object */ | 734 | /* a pointer to the firmware object */ |
737 | const struct firmware *blob; | 735 | const struct firmware *blob; |
738 | /* The type of firmware to request. */ | 736 | /* The type of firmware to request. */ |
@@ -809,6 +807,8 @@ enum { | |||
809 | struct b43_wldev { | 807 | struct b43_wldev { |
810 | struct b43_bus_dev *dev; | 808 | struct b43_bus_dev *dev; |
811 | struct b43_wl *wl; | 809 | struct b43_wl *wl; |
810 | /* a completion event structure needed if this call is asynchronous */ | ||
811 | struct completion fw_load_complete; | ||
812 | 812 | ||
813 | /* The device initialization status. | 813 | /* The device initialization status. |
814 | * Use b43_status() to query. */ | 814 | * Use b43_status() to query. */ |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index ccd24f0acb8d..c75237eb55a1 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -2070,6 +2070,7 @@ void b43_do_release_fw(struct b43_firmware_file *fw) | |||
2070 | 2070 | ||
2071 | static void b43_release_firmware(struct b43_wldev *dev) | 2071 | static void b43_release_firmware(struct b43_wldev *dev) |
2072 | { | 2072 | { |
2073 | complete(&dev->fw_load_complete); | ||
2073 | b43_do_release_fw(&dev->fw.ucode); | 2074 | b43_do_release_fw(&dev->fw.ucode); |
2074 | b43_do_release_fw(&dev->fw.pcm); | 2075 | b43_do_release_fw(&dev->fw.pcm); |
2075 | b43_do_release_fw(&dev->fw.initvals); | 2076 | b43_do_release_fw(&dev->fw.initvals); |
@@ -2095,7 +2096,7 @@ static void b43_fw_cb(const struct firmware *firmware, void *context) | |||
2095 | struct b43_request_fw_context *ctx = context; | 2096 | struct b43_request_fw_context *ctx = context; |
2096 | 2097 | ||
2097 | ctx->blob = firmware; | 2098 | ctx->blob = firmware; |
2098 | complete(&ctx->fw_load_complete); | 2099 | complete(&ctx->dev->fw_load_complete); |
2099 | } | 2100 | } |
2100 | 2101 | ||
2101 | int b43_do_request_fw(struct b43_request_fw_context *ctx, | 2102 | int b43_do_request_fw(struct b43_request_fw_context *ctx, |
@@ -2142,7 +2143,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, | |||
2142 | } | 2143 | } |
2143 | if (async) { | 2144 | if (async) { |
2144 | /* do this part asynchronously */ | 2145 | /* do this part asynchronously */ |
2145 | init_completion(&ctx->fw_load_complete); | 2146 | init_completion(&ctx->dev->fw_load_complete); |
2146 | err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname, | 2147 | err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname, |
2147 | ctx->dev->dev->dev, GFP_KERNEL, | 2148 | ctx->dev->dev->dev, GFP_KERNEL, |
2148 | ctx, b43_fw_cb); | 2149 | ctx, b43_fw_cb); |
@@ -2150,12 +2151,11 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, | |||
2150 | pr_err("Unable to load firmware\n"); | 2151 | pr_err("Unable to load firmware\n"); |
2151 | return err; | 2152 | return err; |
2152 | } | 2153 | } |
2153 | /* stall here until fw ready */ | 2154 | wait_for_completion(&ctx->dev->fw_load_complete); |
2154 | wait_for_completion(&ctx->fw_load_complete); | ||
2155 | if (ctx->blob) | 2155 | if (ctx->blob) |
2156 | goto fw_ready; | 2156 | goto fw_ready; |
2157 | /* On some ARM systems, the async request will fail, but the next sync | 2157 | /* On some ARM systems, the async request will fail, but the next sync |
2158 | * request works. For this reason, we dall through here | 2158 | * request works. For this reason, we fall through here |
2159 | */ | 2159 | */ |
2160 | } | 2160 | } |
2161 | err = request_firmware(&ctx->blob, ctx->fwname, | 2161 | err = request_firmware(&ctx->blob, ctx->fwname, |
@@ -2424,6 +2424,7 @@ error: | |||
2424 | 2424 | ||
2425 | static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl); | 2425 | static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl); |
2426 | static void b43_one_core_detach(struct b43_bus_dev *dev); | 2426 | static void b43_one_core_detach(struct b43_bus_dev *dev); |
2427 | static int b43_rng_init(struct b43_wl *wl); | ||
2427 | 2428 | ||
2428 | static void b43_request_firmware(struct work_struct *work) | 2429 | static void b43_request_firmware(struct work_struct *work) |
2429 | { | 2430 | { |
@@ -2475,6 +2476,10 @@ start_ieee80211: | |||
2475 | goto err_one_core_detach; | 2476 | goto err_one_core_detach; |
2476 | wl->hw_registred = true; | 2477 | wl->hw_registred = true; |
2477 | b43_leds_register(wl->current_dev); | 2478 | b43_leds_register(wl->current_dev); |
2479 | |||
2480 | /* Register HW RNG driver */ | ||
2481 | b43_rng_init(wl); | ||
2482 | |||
2478 | goto out; | 2483 | goto out; |
2479 | 2484 | ||
2480 | err_one_core_detach: | 2485 | err_one_core_detach: |
@@ -4636,9 +4641,6 @@ static void b43_wireless_core_exit(struct b43_wldev *dev) | |||
4636 | if (!dev || b43_status(dev) != B43_STAT_INITIALIZED) | 4641 | if (!dev || b43_status(dev) != B43_STAT_INITIALIZED) |
4637 | return; | 4642 | return; |
4638 | 4643 | ||
4639 | /* Unregister HW RNG driver */ | ||
4640 | b43_rng_exit(dev->wl); | ||
4641 | |||
4642 | b43_set_status(dev, B43_STAT_UNINIT); | 4644 | b43_set_status(dev, B43_STAT_UNINIT); |
4643 | 4645 | ||
4644 | /* Stop the microcode PSM. */ | 4646 | /* Stop the microcode PSM. */ |
@@ -4795,9 +4797,6 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | |||
4795 | 4797 | ||
4796 | b43_set_status(dev, B43_STAT_INITIALIZED); | 4798 | b43_set_status(dev, B43_STAT_INITIALIZED); |
4797 | 4799 | ||
4798 | /* Register HW RNG driver */ | ||
4799 | b43_rng_init(dev->wl); | ||
4800 | |||
4801 | out: | 4800 | out: |
4802 | return err; | 4801 | return err; |
4803 | 4802 | ||
@@ -5464,6 +5463,9 @@ static void b43_bcma_remove(struct bcma_device *core) | |||
5464 | 5463 | ||
5465 | b43_one_core_detach(wldev->dev); | 5464 | b43_one_core_detach(wldev->dev); |
5466 | 5465 | ||
5466 | /* Unregister HW RNG driver */ | ||
5467 | b43_rng_exit(wl); | ||
5468 | |||
5467 | b43_leds_unregister(wl); | 5469 | b43_leds_unregister(wl); |
5468 | 5470 | ||
5469 | ieee80211_free_hw(wl->hw); | 5471 | ieee80211_free_hw(wl->hw); |
@@ -5541,6 +5543,9 @@ static void b43_ssb_remove(struct ssb_device *sdev) | |||
5541 | 5543 | ||
5542 | b43_one_core_detach(dev); | 5544 | b43_one_core_detach(dev); |
5543 | 5545 | ||
5546 | /* Unregister HW RNG driver */ | ||
5547 | b43_rng_exit(wl); | ||
5548 | |||
5544 | if (list_empty(&wl->devlist)) { | 5549 | if (list_empty(&wl->devlist)) { |
5545 | b43_leds_unregister(wl); | 5550 | b43_leds_unregister(wl); |
5546 | /* Last core on the chip unregistered. | 5551 | /* Last core on the chip unregistered. |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 572668821862..349c77605231 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -3919,6 +3919,7 @@ static void b43legacy_remove(struct ssb_device *dev) | |||
3919 | * as the ieee80211 unreg will destroy the workqueue. */ | 3919 | * as the ieee80211 unreg will destroy the workqueue. */ |
3920 | cancel_work_sync(&wldev->restart_work); | 3920 | cancel_work_sync(&wldev->restart_work); |
3921 | cancel_work_sync(&wl->firmware_load); | 3921 | cancel_work_sync(&wl->firmware_load); |
3922 | complete(&wldev->fw_load_complete); | ||
3922 | 3923 | ||
3923 | B43legacy_WARN_ON(!wl); | 3924 | B43legacy_WARN_ON(!wl); |
3924 | if (!wldev->fw.ucode) | 3925 | if (!wldev->fw.ucode) |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile index 5681b9862023..57cddee03252 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile +++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile | |||
@@ -32,6 +32,7 @@ brcmfmac-objs += \ | |||
32 | bcdc.o \ | 32 | bcdc.o \ |
33 | dhd_common.o \ | 33 | dhd_common.o \ |
34 | dhd_linux.o \ | 34 | dhd_linux.o \ |
35 | nvram.o \ | ||
35 | btcoex.o | 36 | btcoex.o |
36 | brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \ | 37 | brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \ |
37 | dhd_sdio.o \ | 38 | dhd_sdio.o \ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 34c993dd0602..fa35b23bbaa7 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
@@ -287,6 +287,9 @@ static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
287 | s32 retry = 0; | 287 | s32 retry = 0; |
288 | int ret; | 288 | int ret; |
289 | 289 | ||
290 | if (sdiodev->bus_if->state == BRCMF_BUS_NOMEDIUM) | ||
291 | return -ENOMEDIUM; | ||
292 | |||
290 | /* | 293 | /* |
291 | * figure out how to read the register based on address range | 294 | * figure out how to read the register based on address range |
292 | * 0x00 ~ 0x7FF: function 0 CCCR and FBR | 295 | * 0x00 ~ 0x7FF: function 0 CCCR and FBR |
@@ -306,9 +309,12 @@ static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
306 | usleep_range(1000, 2000); | 309 | usleep_range(1000, 2000); |
307 | ret = brcmf_sdiod_request_data(sdiodev, func_num, addr, regsz, | 310 | ret = brcmf_sdiod_request_data(sdiodev, func_num, addr, regsz, |
308 | data, write); | 311 | data, write); |
309 | } while (ret != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); | 312 | } while (ret != 0 && ret != -ENOMEDIUM && |
313 | retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); | ||
310 | 314 | ||
311 | if (ret != 0) | 315 | if (ret == -ENOMEDIUM) |
316 | brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_NOMEDIUM); | ||
317 | else if (ret != 0) | ||
312 | brcmf_err("failed with %d\n", ret); | 318 | brcmf_err("failed with %d\n", ret); |
313 | 319 | ||
314 | return ret; | 320 | return ret; |
@@ -320,6 +326,9 @@ brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) | |||
320 | int err = 0, i; | 326 | int err = 0, i; |
321 | u8 addr[3]; | 327 | u8 addr[3]; |
322 | 328 | ||
329 | if (sdiodev->bus_if->state == BRCMF_BUS_NOMEDIUM) | ||
330 | return -ENOMEDIUM; | ||
331 | |||
323 | addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK; | 332 | addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK; |
324 | addr[1] = (address >> 16) & SBSDIO_SBADDRMID_MASK; | 333 | addr[1] = (address >> 16) & SBSDIO_SBADDRMID_MASK; |
325 | addr[2] = (address >> 24) & SBSDIO_SBADDRHIGH_MASK; | 334 | addr[2] = (address >> 24) & SBSDIO_SBADDRHIGH_MASK; |
@@ -429,6 +438,7 @@ static int brcmf_sdiod_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
429 | bool write, u32 addr, struct sk_buff *pkt) | 438 | bool write, u32 addr, struct sk_buff *pkt) |
430 | { | 439 | { |
431 | unsigned int req_sz; | 440 | unsigned int req_sz; |
441 | int err; | ||
432 | 442 | ||
433 | brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait); | 443 | brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait); |
434 | if (brcmf_sdiod_pm_resume_error(sdiodev)) | 444 | if (brcmf_sdiod_pm_resume_error(sdiodev)) |
@@ -439,18 +449,18 @@ static int brcmf_sdiod_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
439 | req_sz &= (uint)~3; | 449 | req_sz &= (uint)~3; |
440 | 450 | ||
441 | if (write) | 451 | if (write) |
442 | return sdio_memcpy_toio(sdiodev->func[fn], addr, | 452 | err = sdio_memcpy_toio(sdiodev->func[fn], addr, |
443 | ((u8 *)(pkt->data)), | 453 | ((u8 *)(pkt->data)), req_sz); |
444 | req_sz); | ||
445 | else if (fn == 1) | 454 | else if (fn == 1) |
446 | return sdio_memcpy_fromio(sdiodev->func[fn], | 455 | err = sdio_memcpy_fromio(sdiodev->func[fn], ((u8 *)(pkt->data)), |
447 | ((u8 *)(pkt->data)), | 456 | addr, req_sz); |
448 | addr, req_sz); | ||
449 | else | 457 | else |
450 | /* function 2 read is FIFO operation */ | 458 | /* function 2 read is FIFO operation */ |
451 | return sdio_readsb(sdiodev->func[fn], | 459 | err = sdio_readsb(sdiodev->func[fn], ((u8 *)(pkt->data)), addr, |
452 | ((u8 *)(pkt->data)), addr, | 460 | req_sz); |
453 | req_sz); | 461 | if (err == -ENOMEDIUM) |
462 | brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_NOMEDIUM); | ||
463 | return err; | ||
454 | } | 464 | } |
455 | 465 | ||
456 | /** | 466 | /** |
@@ -593,7 +603,11 @@ static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
593 | mmc_wait_for_req(sdiodev->func[fn]->card->host, &mmc_req); | 603 | mmc_wait_for_req(sdiodev->func[fn]->card->host, &mmc_req); |
594 | 604 | ||
595 | ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error; | 605 | ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error; |
596 | if (ret != 0) { | 606 | if (ret == -ENOMEDIUM) { |
607 | brcmf_bus_change_state(sdiodev->bus_if, | ||
608 | BRCMF_BUS_NOMEDIUM); | ||
609 | break; | ||
610 | } else if (ret != 0) { | ||
597 | brcmf_err("CMD53 sg block %s failed %d\n", | 611 | brcmf_err("CMD53 sg block %s failed %d\n", |
598 | write ? "write" : "read", ret); | 612 | write ? "write" : "read", ret); |
599 | ret = -EIO; | 613 | ret = -EIO; |
@@ -852,8 +866,6 @@ int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn) | |||
852 | 866 | ||
853 | static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev) | 867 | static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev) |
854 | { | 868 | { |
855 | sdiodev->bus_if->state = BRCMF_BUS_DOWN; | ||
856 | |||
857 | if (sdiodev->bus) { | 869 | if (sdiodev->bus) { |
858 | brcmf_sdio_remove(sdiodev->bus); | 870 | brcmf_sdio_remove(sdiodev->bus); |
859 | sdiodev->bus = NULL; | 871 | sdiodev->bus = NULL; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index 5c12a07673fa..c4535616064e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h | |||
@@ -17,8 +17,12 @@ | |||
17 | #ifndef _BRCMF_BUS_H_ | 17 | #ifndef _BRCMF_BUS_H_ |
18 | #define _BRCMF_BUS_H_ | 18 | #define _BRCMF_BUS_H_ |
19 | 19 | ||
20 | #include "dhd_dbg.h" | ||
21 | |||
20 | /* The level of bus communication with the dongle */ | 22 | /* The level of bus communication with the dongle */ |
21 | enum brcmf_bus_state { | 23 | enum brcmf_bus_state { |
24 | BRCMF_BUS_UNKNOWN, /* Not determined yet */ | ||
25 | BRCMF_BUS_NOMEDIUM, /* No medium access to dongle */ | ||
22 | BRCMF_BUS_DOWN, /* Not ready for frame transfers */ | 26 | BRCMF_BUS_DOWN, /* Not ready for frame transfers */ |
23 | BRCMF_BUS_LOAD, /* Download access only (CPU reset) */ | 27 | BRCMF_BUS_LOAD, /* Download access only (CPU reset) */ |
24 | BRCMF_BUS_DATA /* Ready for frame transfers */ | 28 | BRCMF_BUS_DATA /* Ready for frame transfers */ |
@@ -144,6 +148,23 @@ struct pktq *brcmf_bus_gettxq(struct brcmf_bus *bus) | |||
144 | 148 | ||
145 | return bus->ops->gettxq(bus->dev); | 149 | return bus->ops->gettxq(bus->dev); |
146 | } | 150 | } |
151 | |||
152 | static inline bool brcmf_bus_ready(struct brcmf_bus *bus) | ||
153 | { | ||
154 | return bus->state == BRCMF_BUS_LOAD || bus->state == BRCMF_BUS_DATA; | ||
155 | } | ||
156 | |||
157 | static inline void brcmf_bus_change_state(struct brcmf_bus *bus, | ||
158 | enum brcmf_bus_state new_state) | ||
159 | { | ||
160 | /* NOMEDIUM is permanent */ | ||
161 | if (bus->state == BRCMF_BUS_NOMEDIUM) | ||
162 | return; | ||
163 | |||
164 | brcmf_dbg(TRACE, "%d -> %d\n", bus->state, new_state); | ||
165 | bus->state = new_state; | ||
166 | } | ||
167 | |||
147 | /* | 168 | /* |
148 | * interface functions from common layer | 169 | * interface functions from common layer |
149 | */ | 170 | */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index af39edae8c62..d4d966beb840 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | |||
@@ -934,7 +934,7 @@ int brcmf_bus_start(struct device *dev) | |||
934 | p2p_ifp = NULL; | 934 | p2p_ifp = NULL; |
935 | 935 | ||
936 | /* signal bus ready */ | 936 | /* signal bus ready */ |
937 | bus_if->state = BRCMF_BUS_DATA; | 937 | brcmf_bus_change_state(bus_if, BRCMF_BUS_DATA); |
938 | 938 | ||
939 | /* Bus is ready, do any initialization */ | 939 | /* Bus is ready, do any initialization */ |
940 | ret = brcmf_c_preinit_dcmds(ifp); | 940 | ret = brcmf_c_preinit_dcmds(ifp); |
@@ -1029,6 +1029,8 @@ void brcmf_detach(struct device *dev) | |||
1029 | /* stop firmware event handling */ | 1029 | /* stop firmware event handling */ |
1030 | brcmf_fweh_detach(drvr); | 1030 | brcmf_fweh_detach(drvr); |
1031 | 1031 | ||
1032 | brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN); | ||
1033 | |||
1032 | /* make sure primary interface removed last */ | 1034 | /* make sure primary interface removed last */ |
1033 | for (i = BRCMF_MAX_IFS-1; i > -1; i--) | 1035 | for (i = BRCMF_MAX_IFS-1; i > -1; i--) |
1034 | if (drvr->iflist[i]) { | 1036 | if (drvr->iflist[i]) { |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 9c7f08a13105..3e991897d7ca 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <soc.h> | 41 | #include <soc.h> |
42 | #include "sdio_host.h" | 42 | #include "sdio_host.h" |
43 | #include "sdio_chip.h" | 43 | #include "sdio_chip.h" |
44 | #include "nvram.h" | ||
44 | 45 | ||
45 | #define DCMD_RESP_TIMEOUT 2000 /* In milli second */ | 46 | #define DCMD_RESP_TIMEOUT 2000 /* In milli second */ |
46 | 47 | ||
@@ -368,9 +369,7 @@ struct brcmf_sdio_hdrinfo { | |||
368 | /* Private data for SDIO bus interaction */ | 369 | /* Private data for SDIO bus interaction */ |
369 | struct brcmf_sdio { | 370 | struct brcmf_sdio { |
370 | struct brcmf_sdio_dev *sdiodev; /* sdio device handler */ | 371 | struct brcmf_sdio_dev *sdiodev; /* sdio device handler */ |
371 | struct chip_info *ci; /* Chip info struct */ | 372 | struct brcmf_chip *ci; /* Chip info struct */ |
372 | char *vars; /* Variables (from CIS and/or other) */ | ||
373 | uint varsz; /* Size of variables buffer */ | ||
374 | 373 | ||
375 | u32 ramsize; /* Size of RAM in SOCRAM (bytes) */ | 374 | u32 ramsize; /* Size of RAM in SOCRAM (bytes) */ |
376 | 375 | ||
@@ -1083,10 +1082,6 @@ static void brcmf_sdio_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) | |||
1083 | 1082 | ||
1084 | /* Clear partial in any case */ | 1083 | /* Clear partial in any case */ |
1085 | bus->cur_read.len = 0; | 1084 | bus->cur_read.len = 0; |
1086 | |||
1087 | /* If we can't reach the device, signal failure */ | ||
1088 | if (err) | ||
1089 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | ||
1090 | } | 1085 | } |
1091 | 1086 | ||
1092 | /* return total length of buffer chain */ | 1087 | /* return total length of buffer chain */ |
@@ -1683,8 +1678,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1683 | bus->rxpending = true; | 1678 | bus->rxpending = true; |
1684 | 1679 | ||
1685 | for (rd->seq_num = bus->rx_seq, rxleft = maxframes; | 1680 | for (rd->seq_num = bus->rx_seq, rxleft = maxframes; |
1686 | !bus->rxskip && rxleft && | 1681 | !bus->rxskip && rxleft && brcmf_bus_ready(bus->sdiodev->bus_if); |
1687 | bus->sdiodev->bus_if->state != BRCMF_BUS_DOWN; | ||
1688 | rd->seq_num++, rxleft--) { | 1682 | rd->seq_num++, rxleft--) { |
1689 | 1683 | ||
1690 | /* Handle glomming separately */ | 1684 | /* Handle glomming separately */ |
@@ -2233,41 +2227,37 @@ static void brcmf_sdio_bus_stop(struct device *dev) | |||
2233 | bus->watchdog_tsk = NULL; | 2227 | bus->watchdog_tsk = NULL; |
2234 | } | 2228 | } |
2235 | 2229 | ||
2236 | sdio_claim_host(bus->sdiodev->func[1]); | 2230 | if (bus_if->state == BRCMF_BUS_DOWN) { |
2237 | 2231 | sdio_claim_host(sdiodev->func[1]); | |
2238 | /* Enable clock for device interrupts */ | 2232 | |
2239 | brcmf_sdio_bus_sleep(bus, false, false); | 2233 | /* Enable clock for device interrupts */ |
2234 | brcmf_sdio_bus_sleep(bus, false, false); | ||
2235 | |||
2236 | /* Disable and clear interrupts at the chip level also */ | ||
2237 | w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask)); | ||
2238 | local_hostintmask = bus->hostintmask; | ||
2239 | bus->hostintmask = 0; | ||
2240 | |||
2241 | /* Force backplane clocks to assure F2 interrupt propagates */ | ||
2242 | saveclk = brcmf_sdiod_regrb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, | ||
2243 | &err); | ||
2244 | if (!err) | ||
2245 | brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, | ||
2246 | (saveclk | SBSDIO_FORCE_HT), &err); | ||
2247 | if (err) | ||
2248 | brcmf_err("Failed to force clock for F2: err %d\n", | ||
2249 | err); | ||
2240 | 2250 | ||
2241 | /* Disable and clear interrupts at the chip level also */ | 2251 | /* Turn off the bus (F2), free any pending packets */ |
2242 | w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask)); | 2252 | brcmf_dbg(INTR, "disable SDIO interrupts\n"); |
2243 | local_hostintmask = bus->hostintmask; | 2253 | sdio_disable_func(sdiodev->func[SDIO_FUNC_2]); |
2244 | bus->hostintmask = 0; | ||
2245 | 2254 | ||
2246 | /* Change our idea of bus state */ | 2255 | /* Clear any pending interrupts now that F2 is disabled */ |
2247 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 2256 | w_sdreg32(bus, local_hostintmask, |
2257 | offsetof(struct sdpcmd_regs, intstatus)); | ||
2248 | 2258 | ||
2249 | /* Force clocks on backplane to be sure F2 interrupt propagates */ | 2259 | sdio_release_host(sdiodev->func[1]); |
2250 | saveclk = brcmf_sdiod_regrb(bus->sdiodev, | ||
2251 | SBSDIO_FUNC1_CHIPCLKCSR, &err); | ||
2252 | if (!err) { | ||
2253 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, | ||
2254 | (saveclk | SBSDIO_FORCE_HT), &err); | ||
2255 | } | 2260 | } |
2256 | if (err) | ||
2257 | brcmf_err("Failed to force clock for F2: err %d\n", err); | ||
2258 | |||
2259 | /* Turn off the bus (F2), free any pending packets */ | ||
2260 | brcmf_dbg(INTR, "disable SDIO interrupts\n"); | ||
2261 | sdio_disable_func(bus->sdiodev->func[SDIO_FUNC_2]); | ||
2262 | |||
2263 | /* Clear any pending interrupts now that F2 is disabled */ | ||
2264 | w_sdreg32(bus, local_hostintmask, | ||
2265 | offsetof(struct sdpcmd_regs, intstatus)); | ||
2266 | |||
2267 | /* Turn off the backplane clock (only) */ | ||
2268 | brcmf_sdio_clkctl(bus, CLK_SDONLY, false); | ||
2269 | sdio_release_host(bus->sdiodev->func[1]); | ||
2270 | |||
2271 | /* Clear the data packet queues */ | 2261 | /* Clear the data packet queues */ |
2272 | brcmu_pktq_flush(&bus->txq, true, NULL, NULL); | 2262 | brcmu_pktq_flush(&bus->txq, true, NULL, NULL); |
2273 | 2263 | ||
@@ -2357,20 +2347,11 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus) | |||
2357 | /* Check for inconsistent device control */ | 2347 | /* Check for inconsistent device control */ |
2358 | devctl = brcmf_sdiod_regrb(bus->sdiodev, | 2348 | devctl = brcmf_sdiod_regrb(bus->sdiodev, |
2359 | SBSDIO_DEVICE_CTL, &err); | 2349 | SBSDIO_DEVICE_CTL, &err); |
2360 | if (err) { | ||
2361 | brcmf_err("error reading DEVCTL: %d\n", err); | ||
2362 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | ||
2363 | } | ||
2364 | #endif /* DEBUG */ | 2350 | #endif /* DEBUG */ |
2365 | 2351 | ||
2366 | /* Read CSR, if clock on switch to AVAIL, else ignore */ | 2352 | /* Read CSR, if clock on switch to AVAIL, else ignore */ |
2367 | clkctl = brcmf_sdiod_regrb(bus->sdiodev, | 2353 | clkctl = brcmf_sdiod_regrb(bus->sdiodev, |
2368 | SBSDIO_FUNC1_CHIPCLKCSR, &err); | 2354 | SBSDIO_FUNC1_CHIPCLKCSR, &err); |
2369 | if (err) { | ||
2370 | brcmf_err("error reading CSR: %d\n", | ||
2371 | err); | ||
2372 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | ||
2373 | } | ||
2374 | 2355 | ||
2375 | brcmf_dbg(SDIO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", | 2356 | brcmf_dbg(SDIO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", |
2376 | devctl, clkctl); | 2357 | devctl, clkctl); |
@@ -2378,19 +2359,9 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus) | |||
2378 | if (SBSDIO_HTAV(clkctl)) { | 2359 | if (SBSDIO_HTAV(clkctl)) { |
2379 | devctl = brcmf_sdiod_regrb(bus->sdiodev, | 2360 | devctl = brcmf_sdiod_regrb(bus->sdiodev, |
2380 | SBSDIO_DEVICE_CTL, &err); | 2361 | SBSDIO_DEVICE_CTL, &err); |
2381 | if (err) { | ||
2382 | brcmf_err("error reading DEVCTL: %d\n", | ||
2383 | err); | ||
2384 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | ||
2385 | } | ||
2386 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; | 2362 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; |
2387 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, | 2363 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, |
2388 | devctl, &err); | 2364 | devctl, &err); |
2389 | if (err) { | ||
2390 | brcmf_err("error writing DEVCTL: %d\n", | ||
2391 | err); | ||
2392 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | ||
2393 | } | ||
2394 | bus->clkstate = CLK_AVAIL; | 2365 | bus->clkstate = CLK_AVAIL; |
2395 | } | 2366 | } |
2396 | } | 2367 | } |
@@ -2525,9 +2496,8 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus) | |||
2525 | txlimit -= framecnt; | 2496 | txlimit -= framecnt; |
2526 | } | 2497 | } |
2527 | 2498 | ||
2528 | if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) || (err != 0)) { | 2499 | if (!brcmf_bus_ready(bus->sdiodev->bus_if) || (err != 0)) { |
2529 | brcmf_err("failed backplane access over SDIO, halting operation\n"); | 2500 | brcmf_err("failed backplane access over SDIO, halting operation\n"); |
2530 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | ||
2531 | atomic_set(&bus->intstatus, 0); | 2501 | atomic_set(&bus->intstatus, 0); |
2532 | } else if (atomic_read(&bus->intstatus) || | 2502 | } else if (atomic_read(&bus->intstatus) || |
2533 | atomic_read(&bus->ipend) > 0 || | 2503 | atomic_read(&bus->ipend) > 0 || |
@@ -3195,46 +3165,69 @@ brcmf_sdio_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen) | |||
3195 | return rxlen ? (int)rxlen : -ETIMEDOUT; | 3165 | return rxlen ? (int)rxlen : -ETIMEDOUT; |
3196 | } | 3166 | } |
3197 | 3167 | ||
3198 | static bool brcmf_sdio_download_state(struct brcmf_sdio *bus, bool enter) | 3168 | #ifdef DEBUG |
3169 | static bool | ||
3170 | brcmf_sdio_verifymemory(struct brcmf_sdio_dev *sdiodev, u32 ram_addr, | ||
3171 | u8 *ram_data, uint ram_sz) | ||
3199 | { | 3172 | { |
3200 | struct chip_info *ci = bus->ci; | 3173 | char *ram_cmp; |
3201 | 3174 | int err; | |
3202 | /* To enter download state, disable ARM and reset SOCRAM. | 3175 | bool ret = true; |
3203 | * To exit download state, simply reset ARM (default is RAM boot). | 3176 | int address; |
3204 | */ | 3177 | int offset; |
3205 | if (enter) { | 3178 | int len; |
3206 | bus->alp_only = true; | ||
3207 | |||
3208 | brcmf_sdio_chip_enter_download(bus->sdiodev, ci); | ||
3209 | } else { | ||
3210 | if (!brcmf_sdio_chip_exit_download(bus->sdiodev, ci, bus->vars, | ||
3211 | bus->varsz)) | ||
3212 | return false; | ||
3213 | 3179 | ||
3214 | /* Allow HT Clock now that the ARM is running. */ | 3180 | /* read back and verify */ |
3215 | bus->alp_only = false; | 3181 | brcmf_dbg(INFO, "Compare RAM dl & ul at 0x%08x; size=%d\n", ram_addr, |
3182 | ram_sz); | ||
3183 | ram_cmp = kmalloc(MEMBLOCK, GFP_KERNEL); | ||
3184 | /* do not proceed while no memory but */ | ||
3185 | if (!ram_cmp) | ||
3186 | return true; | ||
3216 | 3187 | ||
3217 | bus->sdiodev->bus_if->state = BRCMF_BUS_LOAD; | 3188 | address = ram_addr; |
3189 | offset = 0; | ||
3190 | while (offset < ram_sz) { | ||
3191 | len = ((offset + MEMBLOCK) < ram_sz) ? MEMBLOCK : | ||
3192 | ram_sz - offset; | ||
3193 | err = brcmf_sdiod_ramrw(sdiodev, false, address, ram_cmp, len); | ||
3194 | if (err) { | ||
3195 | brcmf_err("error %d on reading %d membytes at 0x%08x\n", | ||
3196 | err, len, address); | ||
3197 | ret = false; | ||
3198 | break; | ||
3199 | } else if (memcmp(ram_cmp, &ram_data[offset], len)) { | ||
3200 | brcmf_err("Downloaded RAM image is corrupted, block offset is %d, len is %d\n", | ||
3201 | offset, len); | ||
3202 | ret = false; | ||
3203 | break; | ||
3204 | } | ||
3205 | offset += len; | ||
3206 | address += len; | ||
3218 | } | 3207 | } |
3219 | 3208 | ||
3209 | kfree(ram_cmp); | ||
3210 | |||
3211 | return ret; | ||
3212 | } | ||
3213 | #else /* DEBUG */ | ||
3214 | static bool | ||
3215 | brcmf_sdio_verifymemory(struct brcmf_sdio_dev *sdiodev, u32 ram_addr, | ||
3216 | u8 *ram_data, uint ram_sz) | ||
3217 | { | ||
3220 | return true; | 3218 | return true; |
3221 | } | 3219 | } |
3220 | #endif /* DEBUG */ | ||
3222 | 3221 | ||
3223 | static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus) | 3222 | static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus, |
3223 | const struct firmware *fw) | ||
3224 | { | 3224 | { |
3225 | const struct firmware *fw; | ||
3226 | int err; | 3225 | int err; |
3227 | int offset; | 3226 | int offset; |
3228 | int address; | 3227 | int address; |
3229 | int len; | 3228 | int len; |
3230 | 3229 | ||
3231 | fw = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_BIN); | 3230 | brcmf_dbg(TRACE, "Enter\n"); |
3232 | if (fw == NULL) | ||
3233 | return -ENOENT; | ||
3234 | |||
3235 | if (brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_ARM_CR4) != | ||
3236 | BRCMF_MAX_CORENUM) | ||
3237 | memcpy(&bus->ci->rst_vec, fw->data, sizeof(bus->ci->rst_vec)); | ||
3238 | 3231 | ||
3239 | err = 0; | 3232 | err = 0; |
3240 | offset = 0; | 3233 | offset = 0; |
@@ -3247,138 +3240,96 @@ static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus) | |||
3247 | if (err) { | 3240 | if (err) { |
3248 | brcmf_err("error %d on writing %d membytes at 0x%08x\n", | 3241 | brcmf_err("error %d on writing %d membytes at 0x%08x\n", |
3249 | err, len, address); | 3242 | err, len, address); |
3250 | goto failure; | 3243 | return err; |
3251 | } | 3244 | } |
3252 | offset += len; | 3245 | offset += len; |
3253 | address += len; | 3246 | address += len; |
3254 | } | 3247 | } |
3255 | 3248 | if (!err) | |
3256 | failure: | 3249 | if (!brcmf_sdio_verifymemory(bus->sdiodev, bus->ci->rambase, |
3257 | release_firmware(fw); | 3250 | (u8 *)fw->data, fw->size)) |
3251 | err = -EIO; | ||
3258 | 3252 | ||
3259 | return err; | 3253 | return err; |
3260 | } | 3254 | } |
3261 | 3255 | ||
3262 | /* | 3256 | static int brcmf_sdio_download_nvram(struct brcmf_sdio *bus, |
3263 | * ProcessVars:Takes a buffer of "<var>=<value>\n" lines read from a file | 3257 | const struct firmware *nv) |
3264 | * and ending in a NUL. | ||
3265 | * Removes carriage returns, empty lines, comment lines, and converts | ||
3266 | * newlines to NULs. | ||
3267 | * Shortens buffer as needed and pads with NULs. End of buffer is marked | ||
3268 | * by two NULs. | ||
3269 | */ | ||
3270 | |||
3271 | static int brcmf_sdio_strip_nvram(struct brcmf_sdio *bus, | ||
3272 | const struct firmware *nv) | ||
3273 | { | 3258 | { |
3274 | char *varbuf; | 3259 | void *vars; |
3275 | char *dp; | 3260 | u32 varsz; |
3276 | bool findNewline; | 3261 | int address; |
3277 | int column; | 3262 | int err; |
3278 | int ret = 0; | ||
3279 | uint buf_len, n, len; | ||
3280 | |||
3281 | len = nv->size; | ||
3282 | varbuf = vmalloc(len); | ||
3283 | if (!varbuf) | ||
3284 | return -ENOMEM; | ||
3285 | |||
3286 | memcpy(varbuf, nv->data, len); | ||
3287 | dp = varbuf; | ||
3288 | |||
3289 | findNewline = false; | ||
3290 | column = 0; | ||
3291 | |||
3292 | for (n = 0; n < len; n++) { | ||
3293 | if (varbuf[n] == 0) | ||
3294 | break; | ||
3295 | if (varbuf[n] == '\r') | ||
3296 | continue; | ||
3297 | if (findNewline && varbuf[n] != '\n') | ||
3298 | continue; | ||
3299 | findNewline = false; | ||
3300 | if (varbuf[n] == '#') { | ||
3301 | findNewline = true; | ||
3302 | continue; | ||
3303 | } | ||
3304 | if (varbuf[n] == '\n') { | ||
3305 | if (column == 0) | ||
3306 | continue; | ||
3307 | *dp++ = 0; | ||
3308 | column = 0; | ||
3309 | continue; | ||
3310 | } | ||
3311 | *dp++ = varbuf[n]; | ||
3312 | column++; | ||
3313 | } | ||
3314 | buf_len = dp - varbuf; | ||
3315 | while (dp < varbuf + n) | ||
3316 | *dp++ = 0; | ||
3317 | |||
3318 | kfree(bus->vars); | ||
3319 | /* roundup needed for download to device */ | ||
3320 | bus->varsz = roundup(buf_len + 1, 4); | ||
3321 | bus->vars = kmalloc(bus->varsz, GFP_KERNEL); | ||
3322 | if (bus->vars == NULL) { | ||
3323 | bus->varsz = 0; | ||
3324 | ret = -ENOMEM; | ||
3325 | goto err; | ||
3326 | } | ||
3327 | 3263 | ||
3328 | /* copy the processed variables and add null termination */ | 3264 | brcmf_dbg(TRACE, "Enter\n"); |
3329 | memcpy(bus->vars, varbuf, buf_len); | ||
3330 | bus->vars[buf_len] = 0; | ||
3331 | err: | ||
3332 | vfree(varbuf); | ||
3333 | return ret; | ||
3334 | } | ||
3335 | 3265 | ||
3336 | static int brcmf_sdio_download_nvram(struct brcmf_sdio *bus) | 3266 | vars = brcmf_nvram_strip(nv, &varsz); |
3337 | { | ||
3338 | const struct firmware *nv; | ||
3339 | int ret; | ||
3340 | 3267 | ||
3341 | nv = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_NVRAM); | 3268 | if (vars == NULL) |
3342 | if (nv == NULL) | 3269 | return -EINVAL; |
3343 | return -ENOENT; | ||
3344 | 3270 | ||
3345 | ret = brcmf_sdio_strip_nvram(bus, nv); | 3271 | address = bus->ci->ramsize - varsz + bus->ci->rambase; |
3272 | err = brcmf_sdiod_ramrw(bus->sdiodev, true, address, vars, varsz); | ||
3273 | if (err) | ||
3274 | brcmf_err("error %d on writing %d nvram bytes at 0x%08x\n", | ||
3275 | err, varsz, address); | ||
3276 | else if (!brcmf_sdio_verifymemory(bus->sdiodev, address, vars, varsz)) | ||
3277 | err = -EIO; | ||
3346 | 3278 | ||
3347 | release_firmware(nv); | 3279 | brcmf_nvram_free(vars); |
3348 | 3280 | ||
3349 | return ret; | 3281 | return err; |
3350 | } | 3282 | } |
3351 | 3283 | ||
3352 | static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus) | 3284 | static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus) |
3353 | { | 3285 | { |
3354 | int bcmerror = -EFAULT; | 3286 | int bcmerror = -EFAULT; |
3355 | 3287 | const struct firmware *fw; | |
3288 | u32 rstvec; | ||
3356 | 3289 | ||
3357 | sdio_claim_host(bus->sdiodev->func[1]); | 3290 | sdio_claim_host(bus->sdiodev->func[1]); |
3358 | brcmf_sdio_clkctl(bus, CLK_AVAIL, false); | 3291 | brcmf_sdio_clkctl(bus, CLK_AVAIL, false); |
3359 | 3292 | ||
3360 | /* Keep arm in reset */ | 3293 | /* Keep arm in reset */ |
3361 | if (!brcmf_sdio_download_state(bus, true)) { | 3294 | brcmf_sdio_chip_enter_download(bus->sdiodev, bus->ci); |
3362 | brcmf_err("error placing ARM core in reset\n"); | 3295 | |
3296 | fw = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_BIN); | ||
3297 | if (fw == NULL) { | ||
3298 | bcmerror = -ENOENT; | ||
3363 | goto err; | 3299 | goto err; |
3364 | } | 3300 | } |
3365 | 3301 | ||
3366 | if (brcmf_sdio_download_code_file(bus)) { | 3302 | rstvec = get_unaligned_le32(fw->data); |
3303 | brcmf_dbg(SDIO, "firmware rstvec: %x\n", rstvec); | ||
3304 | |||
3305 | bcmerror = brcmf_sdio_download_code_file(bus, fw); | ||
3306 | release_firmware(fw); | ||
3307 | if (bcmerror) { | ||
3367 | brcmf_err("dongle image file download failed\n"); | 3308 | brcmf_err("dongle image file download failed\n"); |
3368 | goto err; | 3309 | goto err; |
3369 | } | 3310 | } |
3370 | 3311 | ||
3371 | if (brcmf_sdio_download_nvram(bus)) { | 3312 | fw = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_NVRAM); |
3313 | if (fw == NULL) { | ||
3314 | bcmerror = -ENOENT; | ||
3315 | goto err; | ||
3316 | } | ||
3317 | |||
3318 | bcmerror = brcmf_sdio_download_nvram(bus, fw); | ||
3319 | release_firmware(fw); | ||
3320 | if (bcmerror) { | ||
3372 | brcmf_err("dongle nvram file download failed\n"); | 3321 | brcmf_err("dongle nvram file download failed\n"); |
3373 | goto err; | 3322 | goto err; |
3374 | } | 3323 | } |
3375 | 3324 | ||
3376 | /* Take arm out of reset */ | 3325 | /* Take arm out of reset */ |
3377 | if (!brcmf_sdio_download_state(bus, false)) { | 3326 | if (!brcmf_sdio_chip_exit_download(bus->sdiodev, bus->ci, rstvec)) { |
3378 | brcmf_err("error getting out of ARM core reset\n"); | 3327 | brcmf_err("error getting out of ARM core reset\n"); |
3379 | goto err; | 3328 | goto err; |
3380 | } | 3329 | } |
3381 | 3330 | ||
3331 | /* Allow HT Clock now that the ARM is running. */ | ||
3332 | brcmf_bus_change_state(bus->sdiodev->bus_if, BRCMF_BUS_LOAD); | ||
3382 | bcmerror = 0; | 3333 | bcmerror = 0; |
3383 | 3334 | ||
3384 | err: | 3335 | err: |
@@ -3567,9 +3518,11 @@ static int brcmf_sdio_bus_init(struct device *dev) | |||
3567 | 3518 | ||
3568 | /* try to download image and nvram to the dongle */ | 3519 | /* try to download image and nvram to the dongle */ |
3569 | if (bus_if->state == BRCMF_BUS_DOWN) { | 3520 | if (bus_if->state == BRCMF_BUS_DOWN) { |
3521 | bus->alp_only = true; | ||
3570 | err = brcmf_sdio_download_firmware(bus); | 3522 | err = brcmf_sdio_download_firmware(bus); |
3571 | if (err) | 3523 | if (err) |
3572 | return err; | 3524 | return err; |
3525 | bus->alp_only = false; | ||
3573 | } | 3526 | } |
3574 | 3527 | ||
3575 | if (!bus->sdiodev->bus_if->drvr) | 3528 | if (!bus->sdiodev->bus_if->drvr) |
@@ -3653,7 +3606,7 @@ void brcmf_sdio_isr(struct brcmf_sdio *bus) | |||
3653 | return; | 3606 | return; |
3654 | } | 3607 | } |
3655 | 3608 | ||
3656 | if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) { | 3609 | if (!brcmf_bus_ready(bus->sdiodev->bus_if)) { |
3657 | brcmf_err("bus is down. we have nothing to do\n"); | 3610 | brcmf_err("bus is down. we have nothing to do\n"); |
3658 | return; | 3611 | return; |
3659 | } | 3612 | } |
@@ -3664,7 +3617,6 @@ void brcmf_sdio_isr(struct brcmf_sdio *bus) | |||
3664 | else | 3617 | else |
3665 | if (brcmf_sdio_intr_rstatus(bus)) { | 3618 | if (brcmf_sdio_intr_rstatus(bus)) { |
3666 | brcmf_err("failed backplane access\n"); | 3619 | brcmf_err("failed backplane access\n"); |
3667 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | ||
3668 | } | 3620 | } |
3669 | 3621 | ||
3670 | /* Disable additional interrupts (is this needed now)? */ | 3622 | /* Disable additional interrupts (is this needed now)? */ |
@@ -3779,8 +3731,6 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus) | |||
3779 | u32 reg_val; | 3731 | u32 reg_val; |
3780 | u32 drivestrength; | 3732 | u32 drivestrength; |
3781 | 3733 | ||
3782 | bus->alp_only = true; | ||
3783 | |||
3784 | sdio_claim_host(bus->sdiodev->func[1]); | 3734 | sdio_claim_host(bus->sdiodev->func[1]); |
3785 | 3735 | ||
3786 | pr_debug("F1 signature read @0x18000000=0x%4x\n", | 3736 | pr_debug("F1 signature read @0x18000000=0x%4x\n", |
@@ -3803,6 +3753,11 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus) | |||
3803 | goto fail; | 3753 | goto fail; |
3804 | } | 3754 | } |
3805 | 3755 | ||
3756 | /* SDIO register access works so moving | ||
3757 | * state from UNKNOWN to DOWN. | ||
3758 | */ | ||
3759 | brcmf_bus_change_state(bus->sdiodev->bus_if, BRCMF_BUS_DOWN); | ||
3760 | |||
3806 | if (brcmf_sdio_chip_attach(bus->sdiodev, &bus->ci)) { | 3761 | if (brcmf_sdio_chip_attach(bus->sdiodev, &bus->ci)) { |
3807 | brcmf_err("brcmf_sdio_chip_attach failed!\n"); | 3762 | brcmf_err("brcmf_sdio_chip_attach failed!\n"); |
3808 | goto fail; | 3763 | goto fail; |
@@ -4026,7 +3981,6 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) | |||
4026 | /* Disable F2 to clear any intermediate frame state on the dongle */ | 3981 | /* Disable F2 to clear any intermediate frame state on the dongle */ |
4027 | sdio_disable_func(bus->sdiodev->func[SDIO_FUNC_2]); | 3982 | sdio_disable_func(bus->sdiodev->func[SDIO_FUNC_2]); |
4028 | 3983 | ||
4029 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | ||
4030 | bus->rxflow = false; | 3984 | bus->rxflow = false; |
4031 | 3985 | ||
4032 | /* Done with backplane-dependent accesses, can drop clock... */ | 3986 | /* Done with backplane-dependent accesses, can drop clock... */ |
@@ -4082,17 +4036,26 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus) | |||
4082 | } | 4036 | } |
4083 | 4037 | ||
4084 | if (bus->ci) { | 4038 | if (bus->ci) { |
4085 | sdio_claim_host(bus->sdiodev->func[1]); | 4039 | if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) { |
4086 | brcmf_sdio_clkctl(bus, CLK_AVAIL, false); | 4040 | sdio_claim_host(bus->sdiodev->func[1]); |
4087 | brcmf_sdio_clkctl(bus, CLK_NONE, false); | 4041 | brcmf_sdio_clkctl(bus, CLK_AVAIL, false); |
4088 | sdio_release_host(bus->sdiodev->func[1]); | 4042 | /* Leave the device in state where it is |
4043 | * 'quiet'. This is done by putting it in | ||
4044 | * download_state which essentially resets | ||
4045 | * all necessary cores. | ||
4046 | */ | ||
4047 | msleep(20); | ||
4048 | brcmf_sdio_chip_enter_download(bus->sdiodev, | ||
4049 | bus->ci); | ||
4050 | brcmf_sdio_clkctl(bus, CLK_NONE, false); | ||
4051 | sdio_release_host(bus->sdiodev->func[1]); | ||
4052 | } | ||
4089 | brcmf_sdio_chip_detach(&bus->ci); | 4053 | brcmf_sdio_chip_detach(&bus->ci); |
4090 | } | 4054 | } |
4091 | 4055 | ||
4092 | brcmu_pkt_buf_free_skb(bus->txglom_sgpad); | 4056 | brcmu_pkt_buf_free_skb(bus->txglom_sgpad); |
4093 | kfree(bus->rxbuf); | 4057 | kfree(bus->rxbuf); |
4094 | kfree(bus->hdrbuf); | 4058 | kfree(bus->hdrbuf); |
4095 | kfree(bus->vars); | ||
4096 | kfree(bus); | 4059 | kfree(bus); |
4097 | } | 4060 | } |
4098 | 4061 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/nvram.c b/drivers/net/wireless/brcm80211/brcmfmac/nvram.c new file mode 100644 index 000000000000..d5ef86db631b --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/nvram.c | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Broadcom Corporation | ||
3 | * | ||
4 | * 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 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/firmware.h> | ||
20 | |||
21 | #include "nvram.h" | ||
22 | |||
23 | /* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a file | ||
24 | * and ending in a NUL. Removes carriage returns, empty lines, comment lines, | ||
25 | * and converts newlines to NULs. Shortens buffer as needed and pads with NULs. | ||
26 | * End of buffer is completed with token identifying length of buffer. | ||
27 | */ | ||
28 | void *brcmf_nvram_strip(const struct firmware *nv, u32 *new_length) | ||
29 | { | ||
30 | u8 *nvram; | ||
31 | u32 i; | ||
32 | u32 len; | ||
33 | u32 column; | ||
34 | u8 val; | ||
35 | bool comment; | ||
36 | u32 token; | ||
37 | __le32 token_le; | ||
38 | |||
39 | /* Alloc for extra 0 byte + roundup by 4 + length field */ | ||
40 | nvram = kmalloc(nv->size + 1 + 3 + sizeof(token_le), GFP_KERNEL); | ||
41 | if (!nvram) | ||
42 | return NULL; | ||
43 | |||
44 | len = 0; | ||
45 | column = 0; | ||
46 | comment = false; | ||
47 | for (i = 0; i < nv->size; i++) { | ||
48 | val = nv->data[i]; | ||
49 | if (val == 0) | ||
50 | break; | ||
51 | if (val == '\r') | ||
52 | continue; | ||
53 | if (comment && (val != '\n')) | ||
54 | continue; | ||
55 | comment = false; | ||
56 | if (val == '#') { | ||
57 | comment = true; | ||
58 | continue; | ||
59 | } | ||
60 | if (val == '\n') { | ||
61 | if (column == 0) | ||
62 | continue; | ||
63 | nvram[len] = 0; | ||
64 | len++; | ||
65 | column = 0; | ||
66 | continue; | ||
67 | } | ||
68 | nvram[len] = val; | ||
69 | len++; | ||
70 | column++; | ||
71 | } | ||
72 | column = len; | ||
73 | *new_length = roundup(len + 1, 4); | ||
74 | while (column != *new_length) { | ||
75 | nvram[column] = 0; | ||
76 | column++; | ||
77 | } | ||
78 | |||
79 | token = *new_length / 4; | ||
80 | token = (~token << 16) | (token & 0x0000FFFF); | ||
81 | token_le = cpu_to_le32(token); | ||
82 | |||
83 | memcpy(&nvram[*new_length], &token_le, sizeof(token_le)); | ||
84 | *new_length += sizeof(token_le); | ||
85 | |||
86 | return nvram; | ||
87 | } | ||
88 | |||
89 | void brcmf_nvram_free(void *nvram) | ||
90 | { | ||
91 | kfree(nvram); | ||
92 | } | ||
93 | |||
94 | |||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/nvram.h b/drivers/net/wireless/brcm80211/brcmfmac/nvram.h new file mode 100644 index 000000000000..d454580928c9 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/nvram.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Broadcom Corporation | ||
3 | * | ||
4 | * 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 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | #ifndef BRCMFMAC_NVRAM_H | ||
17 | #define BRCMFMAC_NVRAM_H | ||
18 | |||
19 | |||
20 | void *brcmf_nvram_strip(const struct firmware *nv, u32 *new_length); | ||
21 | void brcmf_nvram_free(void *nvram); | ||
22 | |||
23 | |||
24 | #endif /* BRCMFMAC_NVRAM_H */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c index 9fd40675f18e..82bf3c5d3cdc 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c | |||
@@ -51,6 +51,9 @@ | |||
51 | #define BCM43143_CORE_ARM_BASE 0x18003000 | 51 | #define BCM43143_CORE_ARM_BASE 0x18003000 |
52 | #define BCM43143_RAMSIZE 0x70000 | 52 | #define BCM43143_RAMSIZE 0x70000 |
53 | 53 | ||
54 | /* All D11 cores, ID 0x812 */ | ||
55 | #define BCM43xx_CORE_D11_BASE 0x18001000 | ||
56 | |||
54 | #define SBCOREREV(sbidh) \ | 57 | #define SBCOREREV(sbidh) \ |
55 | ((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \ | 58 | ((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \ |
56 | ((sbidh) & SSB_IDHIGH_RCLO)) | 59 | ((sbidh) & SSB_IDHIGH_RCLO)) |
@@ -66,6 +69,10 @@ | |||
66 | /* ARM CR4 core specific control flag bits */ | 69 | /* ARM CR4 core specific control flag bits */ |
67 | #define ARMCR4_BCMA_IOCTL_CPUHALT 0x0020 | 70 | #define ARMCR4_BCMA_IOCTL_CPUHALT 0x0020 |
68 | 71 | ||
72 | /* D11 core specific control flag bits */ | ||
73 | #define D11_BCMA_IOCTL_PHYCLOCKEN 0x0004 | ||
74 | #define D11_BCMA_IOCTL_PHYRESET 0x0008 | ||
75 | |||
69 | #define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu)) | 76 | #define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu)) |
70 | /* SDIO Pad drive strength to select value mappings */ | 77 | /* SDIO Pad drive strength to select value mappings */ |
71 | struct sdiod_drive_str { | 78 | struct sdiod_drive_str { |
@@ -111,7 +118,7 @@ static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = { | |||
111 | }; | 118 | }; |
112 | 119 | ||
113 | u8 | 120 | u8 |
114 | brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid) | 121 | brcmf_sdio_chip_getinfidx(struct brcmf_chip *ci, u16 coreid) |
115 | { | 122 | { |
116 | u8 idx; | 123 | u8 idx; |
117 | 124 | ||
@@ -124,7 +131,7 @@ brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid) | |||
124 | 131 | ||
125 | static u32 | 132 | static u32 |
126 | brcmf_sdio_sb_corerev(struct brcmf_sdio_dev *sdiodev, | 133 | brcmf_sdio_sb_corerev(struct brcmf_sdio_dev *sdiodev, |
127 | struct chip_info *ci, u16 coreid) | 134 | struct brcmf_chip *ci, u16 coreid) |
128 | { | 135 | { |
129 | u32 regdata; | 136 | u32 regdata; |
130 | u8 idx; | 137 | u8 idx; |
@@ -139,7 +146,7 @@ brcmf_sdio_sb_corerev(struct brcmf_sdio_dev *sdiodev, | |||
139 | 146 | ||
140 | static u32 | 147 | static u32 |
141 | brcmf_sdio_ai_corerev(struct brcmf_sdio_dev *sdiodev, | 148 | brcmf_sdio_ai_corerev(struct brcmf_sdio_dev *sdiodev, |
142 | struct chip_info *ci, u16 coreid) | 149 | struct brcmf_chip *ci, u16 coreid) |
143 | { | 150 | { |
144 | u8 idx; | 151 | u8 idx; |
145 | 152 | ||
@@ -150,7 +157,7 @@ brcmf_sdio_ai_corerev(struct brcmf_sdio_dev *sdiodev, | |||
150 | 157 | ||
151 | static bool | 158 | static bool |
152 | brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev, | 159 | brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev, |
153 | struct chip_info *ci, u16 coreid) | 160 | struct brcmf_chip *ci, u16 coreid) |
154 | { | 161 | { |
155 | u32 regdata; | 162 | u32 regdata; |
156 | u8 idx; | 163 | u8 idx; |
@@ -169,7 +176,7 @@ brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev, | |||
169 | 176 | ||
170 | static bool | 177 | static bool |
171 | brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev, | 178 | brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev, |
172 | struct chip_info *ci, u16 coreid) | 179 | struct brcmf_chip *ci, u16 coreid) |
173 | { | 180 | { |
174 | u32 regdata; | 181 | u32 regdata; |
175 | u8 idx; | 182 | u8 idx; |
@@ -193,7 +200,8 @@ brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev, | |||
193 | 200 | ||
194 | static void | 201 | static void |
195 | brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev, | 202 | brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev, |
196 | struct chip_info *ci, u16 coreid, u32 core_bits) | 203 | struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits, |
204 | u32 in_resetbits) | ||
197 | { | 205 | { |
198 | u32 regdata, base; | 206 | u32 regdata, base; |
199 | u8 idx; | 207 | u8 idx; |
@@ -279,52 +287,48 @@ brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev, | |||
279 | 287 | ||
280 | static void | 288 | static void |
281 | brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev, | 289 | brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev, |
282 | struct chip_info *ci, u16 coreid, u32 core_bits) | 290 | struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits, |
291 | u32 in_resetbits) | ||
283 | { | 292 | { |
284 | u8 idx; | 293 | u8 idx; |
285 | u32 regdata; | 294 | u32 regdata; |
295 | u32 wrapbase; | ||
286 | 296 | ||
287 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); | 297 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); |
288 | if (idx == BRCMF_MAX_CORENUM) | 298 | if (idx == BRCMF_MAX_CORENUM) |
289 | return; | 299 | return; |
290 | 300 | ||
301 | wrapbase = ci->c_inf[idx].wrapbase; | ||
302 | |||
291 | /* if core is already in reset, just return */ | 303 | /* if core is already in reset, just return */ |
292 | regdata = brcmf_sdiod_regrl(sdiodev, | 304 | regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_RESET_CTL, NULL); |
293 | ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, | ||
294 | NULL); | ||
295 | if ((regdata & BCMA_RESET_CTL_RESET) != 0) | 305 | if ((regdata & BCMA_RESET_CTL_RESET) != 0) |
296 | return; | 306 | return; |
297 | 307 | ||
298 | /* ensure no pending backplane operation | 308 | /* configure reset */ |
299 | * 300uc should be sufficient for backplane ops to be finish | 309 | brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_IOCTL, pre_resetbits | |
300 | * extra 10ms is taken into account for firmware load stage | 310 | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL); |
301 | * after 10300us carry on disabling the core anyway | 311 | regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL); |
302 | */ | ||
303 | SPINWAIT(brcmf_sdiod_regrl(sdiodev, | ||
304 | ci->c_inf[idx].wrapbase+BCMA_RESET_ST, | ||
305 | NULL), 10300); | ||
306 | regdata = brcmf_sdiod_regrl(sdiodev, | ||
307 | ci->c_inf[idx].wrapbase+BCMA_RESET_ST, | ||
308 | NULL); | ||
309 | if (regdata) | ||
310 | brcmf_err("disabling core 0x%x with reset status %x\n", | ||
311 | coreid, regdata); | ||
312 | 312 | ||
313 | brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, | 313 | /* put in reset */ |
314 | brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_RESET_CTL, | ||
314 | BCMA_RESET_CTL_RESET, NULL); | 315 | BCMA_RESET_CTL_RESET, NULL); |
315 | udelay(1); | ||
316 | |||
317 | brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | ||
318 | core_bits, NULL); | ||
319 | regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | ||
320 | NULL); | ||
321 | usleep_range(10, 20); | 316 | usleep_range(10, 20); |
322 | 317 | ||
318 | /* wait till reset is 1 */ | ||
319 | SPINWAIT(brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_RESET_CTL, NULL) != | ||
320 | BCMA_RESET_CTL_RESET, 300); | ||
321 | |||
322 | /* post reset configure */ | ||
323 | brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_IOCTL, pre_resetbits | | ||
324 | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL); | ||
325 | regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL); | ||
323 | } | 326 | } |
324 | 327 | ||
325 | static void | 328 | static void |
326 | brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev, | 329 | brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev, |
327 | struct chip_info *ci, u16 coreid, u32 core_bits) | 330 | struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits, |
331 | u32 in_resetbits, u32 post_resetbits) | ||
328 | { | 332 | { |
329 | u32 regdata; | 333 | u32 regdata; |
330 | u8 idx; | 334 | u8 idx; |
@@ -337,7 +341,8 @@ brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev, | |||
337 | * Must do the disable sequence first to work for | 341 | * Must do the disable sequence first to work for |
338 | * arbitrary current core state. | 342 | * arbitrary current core state. |
339 | */ | 343 | */ |
340 | brcmf_sdio_sb_coredisable(sdiodev, ci, coreid, 0); | 344 | brcmf_sdio_sb_coredisable(sdiodev, ci, coreid, pre_resetbits, |
345 | in_resetbits); | ||
341 | 346 | ||
342 | /* | 347 | /* |
343 | * Now do the initialization sequence. | 348 | * Now do the initialization sequence. |
@@ -390,40 +395,37 @@ brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev, | |||
390 | 395 | ||
391 | static void | 396 | static void |
392 | brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev, | 397 | brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev, |
393 | struct chip_info *ci, u16 coreid, u32 core_bits) | 398 | struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits, |
399 | u32 in_resetbits, u32 post_resetbits) | ||
394 | { | 400 | { |
395 | u8 idx; | 401 | u8 idx; |
396 | u32 regdata; | 402 | u32 regdata; |
403 | u32 wrapbase; | ||
397 | 404 | ||
398 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); | 405 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); |
399 | if (idx == BRCMF_MAX_CORENUM) | 406 | if (idx == BRCMF_MAX_CORENUM) |
400 | return; | 407 | return; |
401 | 408 | ||
409 | wrapbase = ci->c_inf[idx].wrapbase; | ||
410 | |||
402 | /* must disable first to work for arbitrary current core state */ | 411 | /* must disable first to work for arbitrary current core state */ |
403 | brcmf_sdio_ai_coredisable(sdiodev, ci, coreid, core_bits); | 412 | brcmf_sdio_ai_coredisable(sdiodev, ci, coreid, pre_resetbits, |
413 | in_resetbits); | ||
404 | 414 | ||
405 | /* now do initialization sequence */ | 415 | while (brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_RESET_CTL, NULL) & |
406 | brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 416 | BCMA_RESET_CTL_RESET) { |
407 | core_bits | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL); | 417 | brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_RESET_CTL, 0, NULL); |
408 | regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 418 | usleep_range(40, 60); |
409 | NULL); | 419 | } |
410 | brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, | ||
411 | 0, NULL); | ||
412 | regdata = brcmf_sdiod_regrl(sdiodev, | ||
413 | ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, | ||
414 | NULL); | ||
415 | udelay(1); | ||
416 | 420 | ||
417 | brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 421 | brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_IOCTL, post_resetbits | |
418 | core_bits | BCMA_IOCTL_CLK, NULL); | 422 | BCMA_IOCTL_CLK, NULL); |
419 | regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 423 | regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL); |
420 | NULL); | ||
421 | udelay(1); | ||
422 | } | 424 | } |
423 | 425 | ||
424 | #ifdef DEBUG | 426 | #ifdef DEBUG |
425 | /* safety check for chipinfo */ | 427 | /* safety check for chipinfo */ |
426 | static int brcmf_sdio_chip_cichk(struct chip_info *ci) | 428 | static int brcmf_sdio_chip_cichk(struct brcmf_chip *ci) |
427 | { | 429 | { |
428 | u8 core_idx; | 430 | u8 core_idx; |
429 | 431 | ||
@@ -450,189 +452,213 @@ static int brcmf_sdio_chip_cichk(struct chip_info *ci) | |||
450 | return 0; | 452 | return 0; |
451 | } | 453 | } |
452 | #else /* DEBUG */ | 454 | #else /* DEBUG */ |
453 | static inline int brcmf_sdio_chip_cichk(struct chip_info *ci) | 455 | static inline int brcmf_sdio_chip_cichk(struct brcmf_chip *ci) |
454 | { | 456 | { |
455 | return 0; | 457 | return 0; |
456 | } | 458 | } |
457 | #endif | 459 | #endif |
458 | 460 | ||
459 | static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev, | 461 | static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev, |
460 | struct chip_info *ci) | 462 | struct brcmf_chip *ci) |
461 | { | 463 | { |
462 | u32 regdata; | 464 | u32 regdata; |
463 | int ret; | 465 | u32 socitype; |
464 | 466 | ||
465 | /* Get CC core rev | 467 | /* Get CC core rev |
466 | * Chipid is assume to be at offset 0 from regs arg | 468 | * Chipid is assume to be at offset 0 from SI_ENUM_BASE |
467 | * For different chiptypes or old sdio hosts w/o chipcommon, | 469 | * For different chiptypes or old sdio hosts w/o chipcommon, |
468 | * other ways of recognition should be added here. | 470 | * other ways of recognition should be added here. |
469 | */ | 471 | */ |
470 | ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON; | ||
471 | ci->c_inf[0].base = SI_ENUM_BASE; | ||
472 | regdata = brcmf_sdiod_regrl(sdiodev, | 472 | regdata = brcmf_sdiod_regrl(sdiodev, |
473 | CORE_CC_REG(ci->c_inf[0].base, chipid), | 473 | CORE_CC_REG(SI_ENUM_BASE, chipid), |
474 | NULL); | 474 | NULL); |
475 | ci->chip = regdata & CID_ID_MASK; | 475 | ci->chip = regdata & CID_ID_MASK; |
476 | ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; | 476 | ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; |
477 | if (sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 && | 477 | if (sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 && |
478 | ci->chiprev >= 2) | 478 | ci->chiprev >= 2) |
479 | ci->chip = BCM4339_CHIP_ID; | 479 | ci->chip = BCM4339_CHIP_ID; |
480 | ci->socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT; | 480 | socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT; |
481 | 481 | ||
482 | brcmf_dbg(INFO, "chipid=0x%x chiprev=%d\n", ci->chip, ci->chiprev); | 482 | brcmf_dbg(INFO, "found %s chip: id=0x%x, rev=%d\n", |
483 | socitype == SOCI_SB ? "SB" : "AXI", ci->chip, ci->chiprev); | ||
483 | 484 | ||
484 | /* Address of cores for new chips should be added here */ | 485 | if (socitype == SOCI_SB) { |
485 | switch (ci->chip) { | 486 | if (ci->chip != BCM4329_CHIP_ID) { |
486 | case BCM43143_CHIP_ID: | 487 | brcmf_err("SB chip is not supported\n"); |
487 | ci->c_inf[0].wrapbase = ci->c_inf[0].base + 0x00100000; | 488 | return -ENODEV; |
488 | ci->c_inf[0].cib = 0x2b000000; | 489 | } |
489 | ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; | 490 | ci->iscoreup = brcmf_sdio_sb_iscoreup; |
490 | ci->c_inf[1].base = BCM43143_CORE_BUS_BASE; | 491 | ci->corerev = brcmf_sdio_sb_corerev; |
491 | ci->c_inf[1].wrapbase = ci->c_inf[1].base + 0x00100000; | 492 | ci->coredisable = brcmf_sdio_sb_coredisable; |
492 | ci->c_inf[1].cib = 0x18000000; | 493 | ci->resetcore = brcmf_sdio_sb_resetcore; |
493 | ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; | 494 | |
494 | ci->c_inf[2].base = BCM43143_CORE_SOCRAM_BASE; | 495 | ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON; |
495 | ci->c_inf[2].wrapbase = ci->c_inf[2].base + 0x00100000; | 496 | ci->c_inf[0].base = SI_ENUM_BASE; |
496 | ci->c_inf[2].cib = 0x14000000; | ||
497 | ci->c_inf[3].id = BCMA_CORE_ARM_CM3; | ||
498 | ci->c_inf[3].base = BCM43143_CORE_ARM_BASE; | ||
499 | ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000; | ||
500 | ci->c_inf[3].cib = 0x07000000; | ||
501 | ci->ramsize = BCM43143_RAMSIZE; | ||
502 | break; | ||
503 | case BCM43241_CHIP_ID: | ||
504 | ci->c_inf[0].wrapbase = 0x18100000; | ||
505 | ci->c_inf[0].cib = 0x2a084411; | ||
506 | ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; | ||
507 | ci->c_inf[1].base = 0x18002000; | ||
508 | ci->c_inf[1].wrapbase = 0x18102000; | ||
509 | ci->c_inf[1].cib = 0x0e004211; | ||
510 | ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; | ||
511 | ci->c_inf[2].base = 0x18004000; | ||
512 | ci->c_inf[2].wrapbase = 0x18104000; | ||
513 | ci->c_inf[2].cib = 0x14080401; | ||
514 | ci->c_inf[3].id = BCMA_CORE_ARM_CM3; | ||
515 | ci->c_inf[3].base = 0x18003000; | ||
516 | ci->c_inf[3].wrapbase = 0x18103000; | ||
517 | ci->c_inf[3].cib = 0x07004211; | ||
518 | ci->ramsize = 0x90000; | ||
519 | break; | ||
520 | case BCM4329_CHIP_ID: | ||
521 | ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; | 497 | ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; |
522 | ci->c_inf[1].base = BCM4329_CORE_BUS_BASE; | 498 | ci->c_inf[1].base = BCM4329_CORE_BUS_BASE; |
523 | ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; | 499 | ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; |
524 | ci->c_inf[2].base = BCM4329_CORE_SOCRAM_BASE; | 500 | ci->c_inf[2].base = BCM4329_CORE_SOCRAM_BASE; |
525 | ci->c_inf[3].id = BCMA_CORE_ARM_CM3; | 501 | ci->c_inf[3].id = BCMA_CORE_ARM_CM3; |
526 | ci->c_inf[3].base = BCM4329_CORE_ARM_BASE; | 502 | ci->c_inf[3].base = BCM4329_CORE_ARM_BASE; |
503 | ci->c_inf[4].id = BCMA_CORE_80211; | ||
504 | ci->c_inf[4].base = BCM43xx_CORE_D11_BASE; | ||
527 | ci->ramsize = BCM4329_RAMSIZE; | 505 | ci->ramsize = BCM4329_RAMSIZE; |
528 | break; | 506 | } else if (socitype == SOCI_AI) { |
529 | case BCM4330_CHIP_ID: | ||
530 | ci->c_inf[0].wrapbase = 0x18100000; | ||
531 | ci->c_inf[0].cib = 0x27004211; | ||
532 | ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; | ||
533 | ci->c_inf[1].base = 0x18002000; | ||
534 | ci->c_inf[1].wrapbase = 0x18102000; | ||
535 | ci->c_inf[1].cib = 0x07004211; | ||
536 | ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; | ||
537 | ci->c_inf[2].base = 0x18004000; | ||
538 | ci->c_inf[2].wrapbase = 0x18104000; | ||
539 | ci->c_inf[2].cib = 0x0d080401; | ||
540 | ci->c_inf[3].id = BCMA_CORE_ARM_CM3; | ||
541 | ci->c_inf[3].base = 0x18003000; | ||
542 | ci->c_inf[3].wrapbase = 0x18103000; | ||
543 | ci->c_inf[3].cib = 0x03004211; | ||
544 | ci->ramsize = 0x48000; | ||
545 | break; | ||
546 | case BCM4334_CHIP_ID: | ||
547 | ci->c_inf[0].wrapbase = 0x18100000; | ||
548 | ci->c_inf[0].cib = 0x29004211; | ||
549 | ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; | ||
550 | ci->c_inf[1].base = 0x18002000; | ||
551 | ci->c_inf[1].wrapbase = 0x18102000; | ||
552 | ci->c_inf[1].cib = 0x0d004211; | ||
553 | ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; | ||
554 | ci->c_inf[2].base = 0x18004000; | ||
555 | ci->c_inf[2].wrapbase = 0x18104000; | ||
556 | ci->c_inf[2].cib = 0x13080401; | ||
557 | ci->c_inf[3].id = BCMA_CORE_ARM_CM3; | ||
558 | ci->c_inf[3].base = 0x18003000; | ||
559 | ci->c_inf[3].wrapbase = 0x18103000; | ||
560 | ci->c_inf[3].cib = 0x07004211; | ||
561 | ci->ramsize = 0x80000; | ||
562 | break; | ||
563 | case BCM4335_CHIP_ID: | ||
564 | ci->c_inf[0].wrapbase = 0x18100000; | ||
565 | ci->c_inf[0].cib = 0x2b084411; | ||
566 | ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; | ||
567 | ci->c_inf[1].base = 0x18005000; | ||
568 | ci->c_inf[1].wrapbase = 0x18105000; | ||
569 | ci->c_inf[1].cib = 0x0f004211; | ||
570 | ci->c_inf[2].id = BCMA_CORE_ARM_CR4; | ||
571 | ci->c_inf[2].base = 0x18002000; | ||
572 | ci->c_inf[2].wrapbase = 0x18102000; | ||
573 | ci->c_inf[2].cib = 0x01084411; | ||
574 | ci->ramsize = 0xc0000; | ||
575 | ci->rambase = 0x180000; | ||
576 | break; | ||
577 | case BCM4339_CHIP_ID: | ||
578 | ci->c_inf[0].wrapbase = 0x18100000; | ||
579 | ci->c_inf[0].cib = 0x2e084411; | ||
580 | ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; | ||
581 | ci->c_inf[1].base = 0x18005000; | ||
582 | ci->c_inf[1].wrapbase = 0x18105000; | ||
583 | ci->c_inf[1].cib = 0x15004211; | ||
584 | ci->c_inf[2].id = BCMA_CORE_ARM_CR4; | ||
585 | ci->c_inf[2].base = 0x18002000; | ||
586 | ci->c_inf[2].wrapbase = 0x18102000; | ||
587 | ci->c_inf[2].cib = 0x04084411; | ||
588 | ci->ramsize = 0xc0000; | ||
589 | ci->rambase = 0x180000; | ||
590 | break; | ||
591 | case BCM43362_CHIP_ID: | ||
592 | ci->c_inf[0].wrapbase = 0x18100000; | ||
593 | ci->c_inf[0].cib = 0x27004211; | ||
594 | ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; | ||
595 | ci->c_inf[1].base = 0x18002000; | ||
596 | ci->c_inf[1].wrapbase = 0x18102000; | ||
597 | ci->c_inf[1].cib = 0x0a004211; | ||
598 | ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; | ||
599 | ci->c_inf[2].base = 0x18004000; | ||
600 | ci->c_inf[2].wrapbase = 0x18104000; | ||
601 | ci->c_inf[2].cib = 0x08080401; | ||
602 | ci->c_inf[3].id = BCMA_CORE_ARM_CM3; | ||
603 | ci->c_inf[3].base = 0x18003000; | ||
604 | ci->c_inf[3].wrapbase = 0x18103000; | ||
605 | ci->c_inf[3].cib = 0x03004211; | ||
606 | ci->ramsize = 0x3C000; | ||
607 | break; | ||
608 | default: | ||
609 | brcmf_err("chipid 0x%x is not supported\n", ci->chip); | ||
610 | return -ENODEV; | ||
611 | } | ||
612 | |||
613 | ret = brcmf_sdio_chip_cichk(ci); | ||
614 | if (ret) | ||
615 | return ret; | ||
616 | |||
617 | switch (ci->socitype) { | ||
618 | case SOCI_SB: | ||
619 | ci->iscoreup = brcmf_sdio_sb_iscoreup; | ||
620 | ci->corerev = brcmf_sdio_sb_corerev; | ||
621 | ci->coredisable = brcmf_sdio_sb_coredisable; | ||
622 | ci->resetcore = brcmf_sdio_sb_resetcore; | ||
623 | break; | ||
624 | case SOCI_AI: | ||
625 | ci->iscoreup = brcmf_sdio_ai_iscoreup; | 507 | ci->iscoreup = brcmf_sdio_ai_iscoreup; |
626 | ci->corerev = brcmf_sdio_ai_corerev; | 508 | ci->corerev = brcmf_sdio_ai_corerev; |
627 | ci->coredisable = brcmf_sdio_ai_coredisable; | 509 | ci->coredisable = brcmf_sdio_ai_coredisable; |
628 | ci->resetcore = brcmf_sdio_ai_resetcore; | 510 | ci->resetcore = brcmf_sdio_ai_resetcore; |
629 | break; | 511 | |
630 | default: | 512 | ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON; |
631 | brcmf_err("socitype %u not supported\n", ci->socitype); | 513 | ci->c_inf[0].base = SI_ENUM_BASE; |
514 | |||
515 | /* Address of cores for new chips should be added here */ | ||
516 | switch (ci->chip) { | ||
517 | case BCM43143_CHIP_ID: | ||
518 | ci->c_inf[0].wrapbase = ci->c_inf[0].base + 0x00100000; | ||
519 | ci->c_inf[0].cib = 0x2b000000; | ||
520 | ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; | ||
521 | ci->c_inf[1].base = BCM43143_CORE_BUS_BASE; | ||
522 | ci->c_inf[1].wrapbase = ci->c_inf[1].base + 0x00100000; | ||
523 | ci->c_inf[1].cib = 0x18000000; | ||
524 | ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; | ||
525 | ci->c_inf[2].base = BCM43143_CORE_SOCRAM_BASE; | ||
526 | ci->c_inf[2].wrapbase = ci->c_inf[2].base + 0x00100000; | ||
527 | ci->c_inf[2].cib = 0x14000000; | ||
528 | ci->c_inf[3].id = BCMA_CORE_ARM_CM3; | ||
529 | ci->c_inf[3].base = BCM43143_CORE_ARM_BASE; | ||
530 | ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000; | ||
531 | ci->c_inf[3].cib = 0x07000000; | ||
532 | ci->c_inf[4].id = BCMA_CORE_80211; | ||
533 | ci->c_inf[4].base = BCM43xx_CORE_D11_BASE; | ||
534 | ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000; | ||
535 | ci->ramsize = BCM43143_RAMSIZE; | ||
536 | break; | ||
537 | case BCM43241_CHIP_ID: | ||
538 | ci->c_inf[0].wrapbase = 0x18100000; | ||
539 | ci->c_inf[0].cib = 0x2a084411; | ||
540 | ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; | ||
541 | ci->c_inf[1].base = 0x18002000; | ||
542 | ci->c_inf[1].wrapbase = 0x18102000; | ||
543 | ci->c_inf[1].cib = 0x0e004211; | ||
544 | ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; | ||
545 | ci->c_inf[2].base = 0x18004000; | ||
546 | ci->c_inf[2].wrapbase = 0x18104000; | ||
547 | ci->c_inf[2].cib = 0x14080401; | ||
548 | ci->c_inf[3].id = BCMA_CORE_ARM_CM3; | ||
549 | ci->c_inf[3].base = 0x18003000; | ||
550 | ci->c_inf[3].wrapbase = 0x18103000; | ||
551 | ci->c_inf[3].cib = 0x07004211; | ||
552 | ci->c_inf[4].id = BCMA_CORE_80211; | ||
553 | ci->c_inf[4].base = BCM43xx_CORE_D11_BASE; | ||
554 | ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000; | ||
555 | ci->ramsize = 0x90000; | ||
556 | break; | ||
557 | case BCM4330_CHIP_ID: | ||
558 | ci->c_inf[0].wrapbase = 0x18100000; | ||
559 | ci->c_inf[0].cib = 0x27004211; | ||
560 | ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; | ||
561 | ci->c_inf[1].base = 0x18002000; | ||
562 | ci->c_inf[1].wrapbase = 0x18102000; | ||
563 | ci->c_inf[1].cib = 0x07004211; | ||
564 | ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; | ||
565 | ci->c_inf[2].base = 0x18004000; | ||
566 | ci->c_inf[2].wrapbase = 0x18104000; | ||
567 | ci->c_inf[2].cib = 0x0d080401; | ||
568 | ci->c_inf[3].id = BCMA_CORE_ARM_CM3; | ||
569 | ci->c_inf[3].base = 0x18003000; | ||
570 | ci->c_inf[3].wrapbase = 0x18103000; | ||
571 | ci->c_inf[3].cib = 0x03004211; | ||
572 | ci->c_inf[4].id = BCMA_CORE_80211; | ||
573 | ci->c_inf[4].base = BCM43xx_CORE_D11_BASE; | ||
574 | ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000; | ||
575 | ci->ramsize = 0x48000; | ||
576 | break; | ||
577 | case BCM4334_CHIP_ID: | ||
578 | ci->c_inf[0].wrapbase = 0x18100000; | ||
579 | ci->c_inf[0].cib = 0x29004211; | ||
580 | ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; | ||
581 | ci->c_inf[1].base = 0x18002000; | ||
582 | ci->c_inf[1].wrapbase = 0x18102000; | ||
583 | ci->c_inf[1].cib = 0x0d004211; | ||
584 | ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; | ||
585 | ci->c_inf[2].base = 0x18004000; | ||
586 | ci->c_inf[2].wrapbase = 0x18104000; | ||
587 | ci->c_inf[2].cib = 0x13080401; | ||
588 | ci->c_inf[3].id = BCMA_CORE_ARM_CM3; | ||
589 | ci->c_inf[3].base = 0x18003000; | ||
590 | ci->c_inf[3].wrapbase = 0x18103000; | ||
591 | ci->c_inf[3].cib = 0x07004211; | ||
592 | ci->c_inf[4].id = BCMA_CORE_80211; | ||
593 | ci->c_inf[4].base = BCM43xx_CORE_D11_BASE; | ||
594 | ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000; | ||
595 | ci->ramsize = 0x80000; | ||
596 | break; | ||
597 | case BCM4335_CHIP_ID: | ||
598 | ci->c_inf[0].wrapbase = 0x18100000; | ||
599 | ci->c_inf[0].cib = 0x2b084411; | ||
600 | ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; | ||
601 | ci->c_inf[1].base = 0x18005000; | ||
602 | ci->c_inf[1].wrapbase = 0x18105000; | ||
603 | ci->c_inf[1].cib = 0x0f004211; | ||
604 | ci->c_inf[2].id = BCMA_CORE_ARM_CR4; | ||
605 | ci->c_inf[2].base = 0x18002000; | ||
606 | ci->c_inf[2].wrapbase = 0x18102000; | ||
607 | ci->c_inf[2].cib = 0x01084411; | ||
608 | ci->c_inf[3].id = BCMA_CORE_80211; | ||
609 | ci->c_inf[3].base = BCM43xx_CORE_D11_BASE; | ||
610 | ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000; | ||
611 | ci->ramsize = 0xc0000; | ||
612 | ci->rambase = 0x180000; | ||
613 | break; | ||
614 | case BCM43362_CHIP_ID: | ||
615 | ci->c_inf[0].wrapbase = 0x18100000; | ||
616 | ci->c_inf[0].cib = 0x27004211; | ||
617 | ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; | ||
618 | ci->c_inf[1].base = 0x18002000; | ||
619 | ci->c_inf[1].wrapbase = 0x18102000; | ||
620 | ci->c_inf[1].cib = 0x0a004211; | ||
621 | ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; | ||
622 | ci->c_inf[2].base = 0x18004000; | ||
623 | ci->c_inf[2].wrapbase = 0x18104000; | ||
624 | ci->c_inf[2].cib = 0x08080401; | ||
625 | ci->c_inf[3].id = BCMA_CORE_ARM_CM3; | ||
626 | ci->c_inf[3].base = 0x18003000; | ||
627 | ci->c_inf[3].wrapbase = 0x18103000; | ||
628 | ci->c_inf[3].cib = 0x03004211; | ||
629 | ci->c_inf[4].id = BCMA_CORE_80211; | ||
630 | ci->c_inf[4].base = BCM43xx_CORE_D11_BASE; | ||
631 | ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000; | ||
632 | ci->ramsize = 0x3C000; | ||
633 | break; | ||
634 | case BCM4339_CHIP_ID: | ||
635 | ci->c_inf[0].wrapbase = 0x18100000; | ||
636 | ci->c_inf[0].cib = 0x2e084411; | ||
637 | ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; | ||
638 | ci->c_inf[1].base = 0x18005000; | ||
639 | ci->c_inf[1].wrapbase = 0x18105000; | ||
640 | ci->c_inf[1].cib = 0x15004211; | ||
641 | ci->c_inf[2].id = BCMA_CORE_ARM_CR4; | ||
642 | ci->c_inf[2].base = 0x18002000; | ||
643 | ci->c_inf[2].wrapbase = 0x18102000; | ||
644 | ci->c_inf[2].cib = 0x04084411; | ||
645 | ci->c_inf[3].id = BCMA_CORE_80211; | ||
646 | ci->c_inf[3].base = BCM43xx_CORE_D11_BASE; | ||
647 | ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000; | ||
648 | ci->ramsize = 0xc0000; | ||
649 | ci->rambase = 0x180000; | ||
650 | break; | ||
651 | default: | ||
652 | brcmf_err("AXI chip is not supported\n"); | ||
653 | return -ENODEV; | ||
654 | } | ||
655 | } else { | ||
656 | brcmf_err("chip backplane type %u is not supported\n", | ||
657 | socitype); | ||
632 | return -ENODEV; | 658 | return -ENODEV; |
633 | } | 659 | } |
634 | 660 | ||
635 | return 0; | 661 | return brcmf_sdio_chip_cichk(ci); |
636 | } | 662 | } |
637 | 663 | ||
638 | static int | 664 | static int |
@@ -682,7 +708,7 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev) | |||
682 | 708 | ||
683 | static void | 709 | static void |
684 | brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev, | 710 | brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev, |
685 | struct chip_info *ci) | 711 | struct brcmf_chip *ci) |
686 | { | 712 | { |
687 | u32 base = ci->c_inf[0].base; | 713 | u32 base = ci->c_inf[0].base; |
688 | 714 | ||
@@ -713,19 +739,18 @@ brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev, | |||
713 | * Make sure any on-chip ARM is off (in case strapping is wrong), | 739 | * Make sure any on-chip ARM is off (in case strapping is wrong), |
714 | * or downloaded code was already running. | 740 | * or downloaded code was already running. |
715 | */ | 741 | */ |
716 | ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0); | 742 | ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0, 0); |
717 | } | 743 | } |
718 | 744 | ||
719 | int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev, | 745 | int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev, |
720 | struct chip_info **ci_ptr) | 746 | struct brcmf_chip **ci_ptr) |
721 | { | 747 | { |
722 | int ret; | 748 | int ret; |
723 | struct chip_info *ci; | 749 | struct brcmf_chip *ci; |
724 | 750 | ||
725 | brcmf_dbg(TRACE, "Enter\n"); | 751 | brcmf_dbg(TRACE, "Enter\n"); |
726 | 752 | ||
727 | /* alloc chip_info_t */ | 753 | ci = kzalloc(sizeof(*ci), GFP_ATOMIC); |
728 | ci = kzalloc(sizeof(struct chip_info), GFP_ATOMIC); | ||
729 | if (!ci) | 754 | if (!ci) |
730 | return -ENOMEM; | 755 | return -ENOMEM; |
731 | 756 | ||
@@ -753,7 +778,7 @@ err: | |||
753 | } | 778 | } |
754 | 779 | ||
755 | void | 780 | void |
756 | brcmf_sdio_chip_detach(struct chip_info **ci_ptr) | 781 | brcmf_sdio_chip_detach(struct brcmf_chip **ci_ptr) |
757 | { | 782 | { |
758 | brcmf_dbg(TRACE, "Enter\n"); | 783 | brcmf_dbg(TRACE, "Enter\n"); |
759 | 784 | ||
@@ -772,7 +797,7 @@ static char *brcmf_sdio_chip_name(uint chipid, char *buf, uint len) | |||
772 | 797 | ||
773 | void | 798 | void |
774 | brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, | 799 | brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, |
775 | struct chip_info *ci, u32 drivestrength) | 800 | struct brcmf_chip *ci, u32 drivestrength) |
776 | { | 801 | { |
777 | const struct sdiod_drive_str *str_tab = NULL; | 802 | const struct sdiod_drive_str *str_tab = NULL; |
778 | u32 str_mask; | 803 | u32 str_mask; |
@@ -842,107 +867,19 @@ brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, | |||
842 | } | 867 | } |
843 | } | 868 | } |
844 | 869 | ||
845 | #ifdef DEBUG | ||
846 | static bool | ||
847 | brcmf_sdio_chip_verifynvram(struct brcmf_sdio_dev *sdiodev, u32 nvram_addr, | ||
848 | char *nvram_dat, uint nvram_sz) | ||
849 | { | ||
850 | char *nvram_ularray; | ||
851 | int err; | ||
852 | bool ret = true; | ||
853 | |||
854 | /* read back and verify */ | ||
855 | brcmf_dbg(INFO, "Compare NVRAM dl & ul; size=%d\n", nvram_sz); | ||
856 | nvram_ularray = kmalloc(nvram_sz, GFP_KERNEL); | ||
857 | /* do not proceed while no memory but */ | ||
858 | if (!nvram_ularray) | ||
859 | return true; | ||
860 | |||
861 | /* Upload image to verify downloaded contents. */ | ||
862 | memset(nvram_ularray, 0xaa, nvram_sz); | ||
863 | |||
864 | /* Read the vars list to temp buffer for comparison */ | ||
865 | err = brcmf_sdiod_ramrw(sdiodev, false, nvram_addr, nvram_ularray, | ||
866 | nvram_sz); | ||
867 | if (err) { | ||
868 | brcmf_err("error %d on reading %d nvram bytes at 0x%08x\n", | ||
869 | err, nvram_sz, nvram_addr); | ||
870 | } else if (memcmp(nvram_dat, nvram_ularray, nvram_sz)) { | ||
871 | brcmf_err("Downloaded NVRAM image is corrupted\n"); | ||
872 | ret = false; | ||
873 | } | ||
874 | kfree(nvram_ularray); | ||
875 | |||
876 | return ret; | ||
877 | } | ||
878 | #else /* DEBUG */ | ||
879 | static inline bool | ||
880 | brcmf_sdio_chip_verifynvram(struct brcmf_sdio_dev *sdiodev, u32 nvram_addr, | ||
881 | char *nvram_dat, uint nvram_sz) | ||
882 | { | ||
883 | return true; | ||
884 | } | ||
885 | #endif /* DEBUG */ | ||
886 | |||
887 | static bool brcmf_sdio_chip_writenvram(struct brcmf_sdio_dev *sdiodev, | ||
888 | struct chip_info *ci, | ||
889 | char *nvram_dat, uint nvram_sz) | ||
890 | { | ||
891 | int err; | ||
892 | u32 nvram_addr; | ||
893 | u32 token; | ||
894 | __le32 token_le; | ||
895 | |||
896 | nvram_addr = (ci->ramsize - 4) - nvram_sz + ci->rambase; | ||
897 | |||
898 | /* Write the vars list */ | ||
899 | err = brcmf_sdiod_ramrw(sdiodev, true, nvram_addr, nvram_dat, nvram_sz); | ||
900 | if (err) { | ||
901 | brcmf_err("error %d on writing %d nvram bytes at 0x%08x\n", | ||
902 | err, nvram_sz, nvram_addr); | ||
903 | return false; | ||
904 | } | ||
905 | |||
906 | if (!brcmf_sdio_chip_verifynvram(sdiodev, nvram_addr, | ||
907 | nvram_dat, nvram_sz)) | ||
908 | return false; | ||
909 | |||
910 | /* generate token: | ||
911 | * nvram size, converted to words, in lower 16-bits, checksum | ||
912 | * in upper 16-bits. | ||
913 | */ | ||
914 | token = nvram_sz / 4; | ||
915 | token = (~token << 16) | (token & 0x0000FFFF); | ||
916 | token_le = cpu_to_le32(token); | ||
917 | |||
918 | brcmf_dbg(INFO, "RAM size: %d\n", ci->ramsize); | ||
919 | brcmf_dbg(INFO, "nvram is placed at %d, size %d, token=0x%08x\n", | ||
920 | nvram_addr, nvram_sz, token); | ||
921 | |||
922 | /* Write the length token to the last word */ | ||
923 | if (brcmf_sdiod_ramrw(sdiodev, true, (ci->ramsize - 4 + ci->rambase), | ||
924 | (u8 *)&token_le, 4)) | ||
925 | return false; | ||
926 | |||
927 | return true; | ||
928 | } | ||
929 | |||
930 | static void | 870 | static void |
931 | brcmf_sdio_chip_cm3_enterdl(struct brcmf_sdio_dev *sdiodev, | 871 | brcmf_sdio_chip_cm3_enterdl(struct brcmf_sdio_dev *sdiodev, |
932 | struct chip_info *ci) | 872 | struct brcmf_chip *ci) |
933 | { | 873 | { |
934 | u32 zeros = 0; | 874 | ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0, 0); |
935 | 875 | ci->resetcore(sdiodev, ci, BCMA_CORE_80211, | |
936 | ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0); | 876 | D11_BCMA_IOCTL_PHYRESET | D11_BCMA_IOCTL_PHYCLOCKEN, |
937 | ci->resetcore(sdiodev, ci, BCMA_CORE_INTERNAL_MEM, 0); | 877 | D11_BCMA_IOCTL_PHYCLOCKEN, D11_BCMA_IOCTL_PHYCLOCKEN); |
938 | 878 | ci->resetcore(sdiodev, ci, BCMA_CORE_INTERNAL_MEM, 0, 0, 0); | |
939 | /* clear length token */ | ||
940 | brcmf_sdiod_ramrw(sdiodev, true, ci->ramsize - 4, (u8 *)&zeros, 4); | ||
941 | } | 879 | } |
942 | 880 | ||
943 | static bool | 881 | static bool brcmf_sdio_chip_cm3_exitdl(struct brcmf_sdio_dev *sdiodev, |
944 | brcmf_sdio_chip_cm3_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci, | 882 | struct brcmf_chip *ci) |
945 | char *nvram_dat, uint nvram_sz) | ||
946 | { | 883 | { |
947 | u8 core_idx; | 884 | u8 core_idx; |
948 | u32 reg_addr; | 885 | u32 reg_addr; |
@@ -952,38 +889,45 @@ brcmf_sdio_chip_cm3_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci, | |||
952 | return false; | 889 | return false; |
953 | } | 890 | } |
954 | 891 | ||
955 | if (!brcmf_sdio_chip_writenvram(sdiodev, ci, nvram_dat, nvram_sz)) | ||
956 | return false; | ||
957 | |||
958 | /* clear all interrupts */ | 892 | /* clear all interrupts */ |
959 | core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV); | 893 | core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV); |
960 | reg_addr = ci->c_inf[core_idx].base; | 894 | reg_addr = ci->c_inf[core_idx].base; |
961 | reg_addr += offsetof(struct sdpcmd_regs, intstatus); | 895 | reg_addr += offsetof(struct sdpcmd_regs, intstatus); |
962 | brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL); | 896 | brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL); |
963 | 897 | ||
964 | ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CM3, 0); | 898 | ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CM3, 0, 0, 0); |
965 | 899 | ||
966 | return true; | 900 | return true; |
967 | } | 901 | } |
968 | 902 | ||
969 | static inline void | 903 | static inline void |
970 | brcmf_sdio_chip_cr4_enterdl(struct brcmf_sdio_dev *sdiodev, | 904 | brcmf_sdio_chip_cr4_enterdl(struct brcmf_sdio_dev *sdiodev, |
971 | struct chip_info *ci) | 905 | struct brcmf_chip *ci) |
972 | { | 906 | { |
973 | ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, | 907 | u8 idx; |
974 | ARMCR4_BCMA_IOCTL_CPUHALT); | 908 | u32 regdata; |
909 | u32 wrapbase; | ||
910 | idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CR4); | ||
911 | |||
912 | if (idx == BRCMF_MAX_CORENUM) | ||
913 | return; | ||
914 | |||
915 | wrapbase = ci->c_inf[idx].wrapbase; | ||
916 | regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL); | ||
917 | regdata &= ARMCR4_BCMA_IOCTL_CPUHALT; | ||
918 | ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, regdata, | ||
919 | ARMCR4_BCMA_IOCTL_CPUHALT, ARMCR4_BCMA_IOCTL_CPUHALT); | ||
920 | ci->resetcore(sdiodev, ci, BCMA_CORE_80211, | ||
921 | D11_BCMA_IOCTL_PHYRESET | D11_BCMA_IOCTL_PHYCLOCKEN, | ||
922 | D11_BCMA_IOCTL_PHYCLOCKEN, D11_BCMA_IOCTL_PHYCLOCKEN); | ||
975 | } | 923 | } |
976 | 924 | ||
977 | static bool | 925 | static bool brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev, |
978 | brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci, | 926 | struct brcmf_chip *ci, u32 rstvec) |
979 | char *nvram_dat, uint nvram_sz) | ||
980 | { | 927 | { |
981 | u8 core_idx; | 928 | u8 core_idx; |
982 | u32 reg_addr; | 929 | u32 reg_addr; |
983 | 930 | ||
984 | if (!brcmf_sdio_chip_writenvram(sdiodev, ci, nvram_dat, nvram_sz)) | ||
985 | return false; | ||
986 | |||
987 | /* clear all interrupts */ | 931 | /* clear all interrupts */ |
988 | core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV); | 932 | core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV); |
989 | reg_addr = ci->c_inf[core_idx].base; | 933 | reg_addr = ci->c_inf[core_idx].base; |
@@ -991,17 +935,18 @@ brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci, | |||
991 | brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL); | 935 | brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL); |
992 | 936 | ||
993 | /* Write reset vector to address 0 */ | 937 | /* Write reset vector to address 0 */ |
994 | brcmf_sdiod_ramrw(sdiodev, true, 0, (void *)&ci->rst_vec, | 938 | brcmf_sdiod_ramrw(sdiodev, true, 0, (void *)&rstvec, |
995 | sizeof(ci->rst_vec)); | 939 | sizeof(rstvec)); |
996 | 940 | ||
997 | /* restore ARM */ | 941 | /* restore ARM */ |
998 | ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, 0); | 942 | ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, ARMCR4_BCMA_IOCTL_CPUHALT, |
943 | 0, 0); | ||
999 | 944 | ||
1000 | return true; | 945 | return true; |
1001 | } | 946 | } |
1002 | 947 | ||
1003 | void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev, | 948 | void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev, |
1004 | struct chip_info *ci) | 949 | struct brcmf_chip *ci) |
1005 | { | 950 | { |
1006 | u8 arm_core_idx; | 951 | u8 arm_core_idx; |
1007 | 952 | ||
@@ -1015,15 +960,13 @@ void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev, | |||
1015 | } | 960 | } |
1016 | 961 | ||
1017 | bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev, | 962 | bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev, |
1018 | struct chip_info *ci, char *nvram_dat, | 963 | struct brcmf_chip *ci, u32 rstvec) |
1019 | uint nvram_sz) | ||
1020 | { | 964 | { |
1021 | u8 arm_core_idx; | 965 | u8 arm_core_idx; |
1022 | 966 | ||
1023 | arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3); | 967 | arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3); |
1024 | if (BRCMF_MAX_CORENUM != arm_core_idx) | 968 | if (BRCMF_MAX_CORENUM != arm_core_idx) |
1025 | return brcmf_sdio_chip_cm3_exitdl(sdiodev, ci, nvram_dat, | 969 | return brcmf_sdio_chip_cm3_exitdl(sdiodev, ci); |
1026 | nvram_sz); | ||
1027 | 970 | ||
1028 | return brcmf_sdio_chip_cr4_exitdl(sdiodev, ci, nvram_dat, nvram_sz); | 971 | return brcmf_sdio_chip_cr4_exitdl(sdiodev, ci, rstvec); |
1029 | } | 972 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h index 7ea424e20773..fb0614329ede 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h | |||
@@ -54,7 +54,7 @@ | |||
54 | 54 | ||
55 | #define BRCMF_MAX_CORENUM 6 | 55 | #define BRCMF_MAX_CORENUM 6 |
56 | 56 | ||
57 | struct chip_core_info { | 57 | struct brcmf_core { |
58 | u16 id; | 58 | u16 id; |
59 | u16 rev; | 59 | u16 rev; |
60 | u32 base; | 60 | u32 base; |
@@ -63,27 +63,28 @@ struct chip_core_info { | |||
63 | u32 cib; | 63 | u32 cib; |
64 | }; | 64 | }; |
65 | 65 | ||
66 | struct chip_info { | 66 | struct brcmf_chip { |
67 | u32 chip; | 67 | u32 chip; |
68 | u32 chiprev; | 68 | u32 chiprev; |
69 | u32 socitype; | ||
70 | /* core info */ | 69 | /* core info */ |
71 | /* always put chipcommon core at 0, bus core at 1 */ | 70 | /* always put chipcommon core at 0, bus core at 1 */ |
72 | struct chip_core_info c_inf[BRCMF_MAX_CORENUM]; | 71 | struct brcmf_core c_inf[BRCMF_MAX_CORENUM]; |
73 | u32 pmurev; | 72 | u32 pmurev; |
74 | u32 pmucaps; | 73 | u32 pmucaps; |
75 | u32 ramsize; | 74 | u32 ramsize; |
76 | u32 rambase; | 75 | u32 rambase; |
77 | u32 rst_vec; /* reset vertor for ARM CR4 core */ | 76 | u32 rst_vec; /* reset vertor for ARM CR4 core */ |
78 | 77 | ||
79 | bool (*iscoreup)(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci, | 78 | bool (*iscoreup)(struct brcmf_sdio_dev *sdiodev, struct brcmf_chip *ci, |
80 | u16 coreid); | 79 | u16 coreid); |
81 | u32 (*corerev)(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci, | 80 | u32 (*corerev)(struct brcmf_sdio_dev *sdiodev, struct brcmf_chip *ci, |
82 | u16 coreid); | 81 | u16 coreid); |
83 | void (*coredisable)(struct brcmf_sdio_dev *sdiodev, | 82 | void (*coredisable)(struct brcmf_sdio_dev *sdiodev, |
84 | struct chip_info *ci, u16 coreid, u32 core_bits); | 83 | struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits, |
84 | u32 in_resetbits); | ||
85 | void (*resetcore)(struct brcmf_sdio_dev *sdiodev, | 85 | void (*resetcore)(struct brcmf_sdio_dev *sdiodev, |
86 | struct chip_info *ci, u16 coreid, u32 core_bits); | 86 | struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits, |
87 | u32 in_resetbits, u32 post_resetbits); | ||
87 | }; | 88 | }; |
88 | 89 | ||
89 | struct sbconfig { | 90 | struct sbconfig { |
@@ -216,15 +217,15 @@ struct sdpcmd_regs { | |||
216 | }; | 217 | }; |
217 | 218 | ||
218 | int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev, | 219 | int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev, |
219 | struct chip_info **ci_ptr); | 220 | struct brcmf_chip **ci_ptr); |
220 | void brcmf_sdio_chip_detach(struct chip_info **ci_ptr); | 221 | void brcmf_sdio_chip_detach(struct brcmf_chip **ci_ptr); |
221 | void brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, | 222 | void brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, |
222 | struct chip_info *ci, u32 drivestrength); | 223 | struct brcmf_chip *ci, |
223 | u8 brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid); | 224 | u32 drivestrength); |
225 | u8 brcmf_sdio_chip_getinfidx(struct brcmf_chip *ci, u16 coreid); | ||
224 | void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev, | 226 | void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev, |
225 | struct chip_info *ci); | 227 | struct brcmf_chip *ci); |
226 | bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev, | 228 | bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev, |
227 | struct chip_info *ci, char *nvram_dat, | 229 | struct brcmf_chip *ci, u32 rstvec); |
228 | uint nvram_sz); | ||
229 | 230 | ||
230 | #endif /* _BRCMFMAC_SDIO_CHIP_H_ */ | 231 | #endif /* _BRCMFMAC_SDIO_CHIP_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index c345c32eb631..24f65cd53859 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c | |||
@@ -522,10 +522,10 @@ brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state) | |||
522 | /* update state of upper layer */ | 522 | /* update state of upper layer */ |
523 | if (state == BRCMFMAC_USB_STATE_DOWN) { | 523 | if (state == BRCMFMAC_USB_STATE_DOWN) { |
524 | brcmf_dbg(USB, "DBUS is down\n"); | 524 | brcmf_dbg(USB, "DBUS is down\n"); |
525 | bcmf_bus->state = BRCMF_BUS_DOWN; | 525 | brcmf_bus_change_state(bcmf_bus, BRCMF_BUS_DOWN); |
526 | } else if (state == BRCMFMAC_USB_STATE_UP) { | 526 | } else if (state == BRCMFMAC_USB_STATE_UP) { |
527 | brcmf_dbg(USB, "DBUS is up\n"); | 527 | brcmf_dbg(USB, "DBUS is up\n"); |
528 | bcmf_bus->state = BRCMF_BUS_DATA; | 528 | brcmf_bus_change_state(bcmf_bus, BRCMF_BUS_DATA); |
529 | } else { | 529 | } else { |
530 | brcmf_dbg(USB, "DBUS current state=%d\n", state); | 530 | brcmf_dbg(USB, "DBUS current state=%d\n", state); |
531 | } | 531 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index aad83aef7d93..d7718a5fa2f0 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
@@ -2989,6 +2989,7 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp, | |||
2989 | } | 2989 | } |
2990 | 2990 | ||
2991 | set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); | 2991 | set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); |
2992 | cfg->escan_info.run = brcmf_run_escan; | ||
2992 | err = brcmf_do_escan(cfg, wiphy, ifp, request); | 2993 | err = brcmf_do_escan(cfg, wiphy, ifp, request); |
2993 | if (err) { | 2994 | if (err) { |
2994 | clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); | 2995 | clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index e71ce8c842a2..925034b80e9c 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | |||
@@ -1071,7 +1071,6 @@ static int ieee_hw_init(struct ieee80211_hw *hw) | |||
1071 | hw->max_rates = 2; /* Primary rate and 1 fallback rate */ | 1071 | hw->max_rates = 2; /* Primary rate and 1 fallback rate */ |
1072 | 1072 | ||
1073 | /* channel change time is dependent on chip and band */ | 1073 | /* channel change time is dependent on chip and band */ |
1074 | hw->channel_change_time = 7 * 1000; | ||
1075 | hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 1074 | hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
1076 | BIT(NL80211_IFTYPE_AP) | | 1075 | BIT(NL80211_IFTYPE_AP) | |
1077 | BIT(NL80211_IFTYPE_ADHOC); | 1076 | BIT(NL80211_IFTYPE_ADHOC); |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 8138f1cff4e5..9417cb5a2553 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c | |||
@@ -7108,7 +7108,6 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh, | |||
7108 | struct sk_buff *p, | 7108 | struct sk_buff *p, |
7109 | struct ieee80211_rx_status *rx_status) | 7109 | struct ieee80211_rx_status *rx_status) |
7110 | { | 7110 | { |
7111 | int preamble; | ||
7112 | int channel; | 7111 | int channel; |
7113 | u32 rspec; | 7112 | u32 rspec; |
7114 | unsigned char *plcp; | 7113 | unsigned char *plcp; |
@@ -7191,7 +7190,6 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh, | |||
7191 | rx_status->rate_idx -= BRCMS_LEGACY_5G_RATE_OFFSET; | 7190 | rx_status->rate_idx -= BRCMS_LEGACY_5G_RATE_OFFSET; |
7192 | 7191 | ||
7193 | /* Determine short preamble and rate_idx */ | 7192 | /* Determine short preamble and rate_idx */ |
7194 | preamble = 0; | ||
7195 | if (is_cck_rate(rspec)) { | 7193 | if (is_cck_rate(rspec)) { |
7196 | if (rxh->PhyRxStatus_0 & PRXS0_SHORTH) | 7194 | if (rxh->PhyRxStatus_0 & PRXS0_SHORTH) |
7197 | rx_status->flag |= RX_FLAG_SHORTPRE; | 7195 | rx_status->flag |= RX_FLAG_SHORTPRE; |
diff --git a/drivers/net/wireless/cw1200/main.c b/drivers/net/wireless/cw1200/main.c index d1270da4dfea..3e78cc3ccb78 100644 --- a/drivers/net/wireless/cw1200/main.c +++ b/drivers/net/wireless/cw1200/main.c | |||
@@ -301,7 +301,6 @@ static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr, | |||
301 | 301 | ||
302 | hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; | 302 | hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; |
303 | 303 | ||
304 | hw->channel_change_time = 1000; /* TODO: find actual value */ | ||
305 | hw->queues = 4; | 304 | hw->queues = 4; |
306 | 305 | ||
307 | priv->rts_threshold = -1; | 306 | priv->rts_threshold = -1; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 40eb5e691475..c24d1d3d55f6 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -406,9 +406,8 @@ static bool iwl_resume_status_fn(struct iwl_notif_wait_data *notif_wait, | |||
406 | { | 406 | { |
407 | struct iwl_resume_data *resume_data = data; | 407 | struct iwl_resume_data *resume_data = data; |
408 | struct iwl_priv *priv = resume_data->priv; | 408 | struct iwl_priv *priv = resume_data->priv; |
409 | u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
410 | 409 | ||
411 | if (len - 4 != sizeof(*resume_data->cmd)) { | 410 | if (iwl_rx_packet_payload_len(pkt) != sizeof(*resume_data->cmd)) { |
412 | IWL_ERR(priv, "rx wrong size data\n"); | 411 | IWL_ERR(priv, "rx wrong size data\n"); |
413 | return true; | 412 | return true; |
414 | } | 413 | } |
diff --git a/drivers/net/wireless/iwlwifi/dvm/rx.c b/drivers/net/wireless/iwlwifi/dvm/rx.c index b68bb2f4d2c2..7a1bc1c547e1 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rx.c +++ b/drivers/net/wireless/iwlwifi/dvm/rx.c | |||
@@ -205,8 +205,7 @@ static int iwlagn_rx_pm_debug_statistics_notif(struct iwl_priv *priv, | |||
205 | struct iwl_device_cmd *cmd) | 205 | struct iwl_device_cmd *cmd) |
206 | { | 206 | { |
207 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 207 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
208 | u32 __maybe_unused len = | 208 | u32 __maybe_unused len = iwl_rx_packet_len(pkt); |
209 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
210 | IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " | 209 | IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " |
211 | "notification for PM_DEBUG_STATISTIC_NOTIFIC:\n", len); | 210 | "notification for PM_DEBUG_STATISTIC_NOTIFIC:\n", len); |
212 | iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->data, len); | 211 | iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->data, len); |
@@ -457,7 +456,7 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv, | |||
457 | const int reg_recalib_period = 60; | 456 | const int reg_recalib_period = 60; |
458 | int change; | 457 | int change; |
459 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 458 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
460 | u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | 459 | u32 len = iwl_rx_packet_payload_len(pkt); |
461 | __le32 *flag; | 460 | __le32 *flag; |
462 | struct statistics_general_common *common; | 461 | struct statistics_general_common *common; |
463 | struct statistics_rx_non_phy *rx_non_phy; | 462 | struct statistics_rx_non_phy *rx_non_phy; |
@@ -467,8 +466,6 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv, | |||
467 | struct statistics_tx *tx; | 466 | struct statistics_tx *tx; |
468 | struct statistics_bt_activity *bt_activity; | 467 | struct statistics_bt_activity *bt_activity; |
469 | 468 | ||
470 | len -= sizeof(struct iwl_cmd_header); /* skip header */ | ||
471 | |||
472 | IWL_DEBUG_RX(priv, "Statistics notification received (%d bytes).\n", | 469 | IWL_DEBUG_RX(priv, "Statistics notification received (%d bytes).\n", |
473 | len); | 470 | len); |
474 | 471 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c index f59709a9b79d..cf03ef5619d9 100644 --- a/drivers/net/wireless/iwlwifi/dvm/ucode.c +++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c | |||
@@ -388,7 +388,6 @@ static bool iwlagn_wait_calib(struct iwl_notif_wait_data *notif_wait, | |||
388 | { | 388 | { |
389 | struct iwl_priv *priv = data; | 389 | struct iwl_priv *priv = data; |
390 | struct iwl_calib_hdr *hdr; | 390 | struct iwl_calib_hdr *hdr; |
391 | int len; | ||
392 | 391 | ||
393 | if (pkt->hdr.cmd != CALIBRATION_RES_NOTIFICATION) { | 392 | if (pkt->hdr.cmd != CALIBRATION_RES_NOTIFICATION) { |
394 | WARN_ON(pkt->hdr.cmd != CALIBRATION_COMPLETE_NOTIFICATION); | 393 | WARN_ON(pkt->hdr.cmd != CALIBRATION_COMPLETE_NOTIFICATION); |
@@ -396,12 +395,8 @@ static bool iwlagn_wait_calib(struct iwl_notif_wait_data *notif_wait, | |||
396 | } | 395 | } |
397 | 396 | ||
398 | hdr = (struct iwl_calib_hdr *)pkt->data; | 397 | hdr = (struct iwl_calib_hdr *)pkt->data; |
399 | len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
400 | 398 | ||
401 | /* reduce the size by the length field itself */ | 399 | if (iwl_calib_set(priv, hdr, iwl_rx_packet_payload_len(pkt))) |
402 | len -= sizeof(__le32); | ||
403 | |||
404 | if (iwl_calib_set(priv, hdr, len)) | ||
405 | IWL_ERR(priv, "Failed to record calibration data %d\n", | 400 | IWL_ERR(priv, "Failed to record calibration data %d\n", |
406 | hdr->op_code); | 401 | hdr->op_code); |
407 | 402 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index 1b61cb529948..f06f4cbe1317 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | |||
@@ -264,14 +264,13 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, | |||
264 | struct ieee80211_sta_vht_cap *vht_cap) | 264 | struct ieee80211_sta_vht_cap *vht_cap) |
265 | { | 265 | { |
266 | int num_ants = num_of_ant(data->valid_rx_ant); | 266 | int num_ants = num_of_ant(data->valid_rx_ant); |
267 | int bf_sts_cap = num_ants - 1; | ||
268 | 267 | ||
269 | vht_cap->vht_supported = true; | 268 | vht_cap->vht_supported = true; |
270 | 269 | ||
271 | vht_cap->cap = IEEE80211_VHT_CAP_SHORT_GI_80 | | 270 | vht_cap->cap = IEEE80211_VHT_CAP_SHORT_GI_80 | |
272 | IEEE80211_VHT_CAP_RXSTBC_1 | | 271 | IEEE80211_VHT_CAP_RXSTBC_1 | |
273 | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | | 272 | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | |
274 | bf_sts_cap << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT | | 273 | 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT | |
275 | 7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; | 274 | 7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; |
276 | 275 | ||
277 | if (num_ants > 1) | 276 | if (num_ants > 1) |
@@ -290,9 +289,6 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, | |||
290 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | | 289 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | |
291 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 14); | 290 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 14); |
292 | 291 | ||
293 | /* Max rate for Long GI NSS=2 80Mhz is 780Mbps */ | ||
294 | vht_cap->vht_mcs.rx_highest = cpu_to_le16(780); | ||
295 | |||
296 | if (num_ants == 1 || | 292 | if (num_ants == 1 || |
297 | cfg->rx_with_siso_diversity) { | 293 | cfg->rx_with_siso_diversity) { |
298 | vht_cap->cap |= IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | | 294 | vht_cap->cap |= IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | |
@@ -300,12 +296,9 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, | |||
300 | /* this works because NOT_SUPPORTED == 3 */ | 296 | /* this works because NOT_SUPPORTED == 3 */ |
301 | vht_cap->vht_mcs.rx_mcs_map |= | 297 | vht_cap->vht_mcs.rx_mcs_map |= |
302 | cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << 2); | 298 | cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << 2); |
303 | /* Max rate for Long GI NSS=1 80Mhz is 390Mbps */ | ||
304 | vht_cap->vht_mcs.rx_highest = cpu_to_le16(390); | ||
305 | } | 299 | } |
306 | 300 | ||
307 | vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map; | 301 | vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map; |
308 | vht_cap->vht_mcs.tx_highest = vht_cap->vht_mcs.rx_highest; | ||
309 | } | 302 | } |
310 | 303 | ||
311 | static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | 304 | static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index d69b0fb0a434..100bd0d79681 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
@@ -277,4 +277,8 @@ static inline unsigned int SCD_QUEUE_STATUS_BITS(unsigned int chnl) | |||
277 | 277 | ||
278 | /*********************** END TX SCHEDULER *************************************/ | 278 | /*********************** END TX SCHEDULER *************************************/ |
279 | 279 | ||
280 | /* Oscillator clock */ | ||
281 | #define OSC_CLK (0xa04068) | ||
282 | #define OSC_CLK_FORCE_CONTROL (0x8) | ||
283 | |||
280 | #endif /* __iwl_prph_h__ */ | 284 | #endif /* __iwl_prph_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 8d1b5ed3502a..1f065cf4a4ba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -176,6 +176,16 @@ struct iwl_rx_packet { | |||
176 | u8 data[]; | 176 | u8 data[]; |
177 | } __packed; | 177 | } __packed; |
178 | 178 | ||
179 | static inline u32 iwl_rx_packet_len(const struct iwl_rx_packet *pkt) | ||
180 | { | ||
181 | return le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
182 | } | ||
183 | |||
184 | static inline u32 iwl_rx_packet_payload_len(const struct iwl_rx_packet *pkt) | ||
185 | { | ||
186 | return iwl_rx_packet_len(pkt) - sizeof(pkt->hdr); | ||
187 | } | ||
188 | |||
179 | /** | 189 | /** |
180 | * enum CMD_MODE - how to send the host commands ? | 190 | * enum CMD_MODE - how to send the host commands ? |
181 | * | 191 | * |
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index f04d2f4d80cd..f36a7ee0267f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c | |||
@@ -886,8 +886,7 @@ static int iwl_mvm_get_last_nonqos_seq(struct iwl_mvm *mvm, | |||
886 | if (err) | 886 | if (err) |
887 | return err; | 887 | return err; |
888 | 888 | ||
889 | size = le32_to_cpu(cmd.resp_pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | 889 | size = iwl_rx_packet_payload_len(cmd.resp_pkt); |
890 | size -= sizeof(cmd.resp_pkt->hdr); | ||
891 | if (size < sizeof(__le16)) { | 890 | if (size < sizeof(__le16)) { |
892 | err = -EINVAL; | 891 | err = -EINVAL; |
893 | } else { | 892 | } else { |
@@ -1211,9 +1210,8 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
1211 | if (ret) | 1210 | if (ret) |
1212 | goto out; | 1211 | goto out; |
1213 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 1212 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
1214 | len = le32_to_cpu(d3_cfg_cmd.resp_pkt->len_n_flags) & | 1213 | len = iwl_rx_packet_payload_len(d3_cfg_cmd.resp_pkt); |
1215 | FH_RSCSR_FRAME_SIZE_MSK; | 1214 | if (len >= sizeof(u32)) { |
1216 | if (len >= sizeof(u32) * 2) { | ||
1217 | mvm->d3_test_pme_ptr = | 1215 | mvm->d3_test_pme_ptr = |
1218 | le32_to_cpup((__le32 *)d3_cfg_cmd.resp_pkt->data); | 1216 | le32_to_cpup((__le32 *)d3_cfg_cmd.resp_pkt->data); |
1219 | } | 1217 | } |
@@ -1668,8 +1666,8 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
1668 | else | 1666 | else |
1669 | status_size = sizeof(struct iwl_wowlan_status_v4); | 1667 | status_size = sizeof(struct iwl_wowlan_status_v4); |
1670 | 1668 | ||
1671 | len = le32_to_cpu(cmd.resp_pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | 1669 | len = iwl_rx_packet_payload_len(cmd.resp_pkt); |
1672 | if (len - sizeof(struct iwl_cmd_header) < status_size) { | 1670 | if (len < status_size) { |
1673 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); | 1671 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); |
1674 | goto out_free_resp; | 1672 | goto out_free_resp; |
1675 | } | 1673 | } |
@@ -1704,8 +1702,7 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
1704 | status.wake_packet = status_v4->wake_packet; | 1702 | status.wake_packet = status_v4->wake_packet; |
1705 | } | 1703 | } |
1706 | 1704 | ||
1707 | if (len - sizeof(struct iwl_cmd_header) != | 1705 | if (len != status_size + ALIGN(status.wake_packet_bufsize, 4)) { |
1708 | status_size + ALIGN(status.wake_packet_bufsize, 4)) { | ||
1709 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); | 1706 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); |
1710 | goto out_free_resp; | 1707 | goto out_free_resp; |
1711 | } | 1708 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 76cdce9edf55..369d4c90e669 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c | |||
@@ -135,7 +135,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf, | |||
135 | ofs = img->sec[IWL_UCODE_SECTION_DATA].offset; | 135 | ofs = img->sec[IWL_UCODE_SECTION_DATA].offset; |
136 | len = img->sec[IWL_UCODE_SECTION_DATA].len; | 136 | len = img->sec[IWL_UCODE_SECTION_DATA].len; |
137 | 137 | ||
138 | if (!mvm->dbgfs_sram_offset && !mvm->dbgfs_sram_len) { | 138 | if (mvm->dbgfs_sram_len) { |
139 | ofs = mvm->dbgfs_sram_offset; | 139 | ofs = mvm->dbgfs_sram_offset; |
140 | len = mvm->dbgfs_sram_len; | 140 | len = mvm->dbgfs_sram_len; |
141 | } | 141 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h index 6bbbad453a3b..1b60fdff6a56 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h | |||
@@ -97,9 +97,6 @@ enum iwl_sta_flags { | |||
97 | STA_FLG_FLG_ANT_B), | 97 | STA_FLG_FLG_ANT_B), |
98 | 98 | ||
99 | STA_FLG_PS = BIT(8), | 99 | STA_FLG_PS = BIT(8), |
100 | STA_FLG_INVALID = BIT(9), | ||
101 | STA_FLG_DLP_EN = BIT(10), | ||
102 | STA_FLG_SET_ALL_KEYS = BIT(11), | ||
103 | STA_FLG_DRAIN_FLOW = BIT(12), | 100 | STA_FLG_DRAIN_FLOW = BIT(12), |
104 | STA_FLG_PAN = BIT(13), | 101 | STA_FLG_PAN = BIT(13), |
105 | STA_FLG_CLASS_AUTH = BIT(14), | 102 | STA_FLG_CLASS_AUTH = BIT(14), |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index b41177eb4888..c49b5073c251 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -262,9 +262,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
262 | mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; | 262 | mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; |
263 | 263 | ||
264 | /* currently FW API supports only one optional cipher scheme */ | 264 | /* currently FW API supports only one optional cipher scheme */ |
265 | if (mvm->fw->cs->cipher) { | 265 | if (mvm->fw->cs[0].cipher) { |
266 | mvm->hw->n_cipher_schemes = 1; | 266 | mvm->hw->n_cipher_schemes = 1; |
267 | mvm->hw->cipher_schemes = mvm->fw->cs; | 267 | mvm->hw->cipher_schemes = &mvm->fw->cs[0]; |
268 | } | 268 | } |
269 | 269 | ||
270 | #ifdef CONFIG_PM_SLEEP | 270 | #ifdef CONFIG_PM_SLEEP |
@@ -944,6 +944,8 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
944 | IWL_ERR(mvm, "failed to update power mode\n"); | 944 | IWL_ERR(mvm, "failed to update power mode\n"); |
945 | } | 945 | } |
946 | iwl_mvm_bt_coex_vif_change(mvm); | 946 | iwl_mvm_bt_coex_vif_change(mvm); |
947 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_TT, | ||
948 | IEEE80211_SMPS_AUTOMATIC); | ||
947 | } else if (changes & BSS_CHANGED_BEACON_INFO) { | 949 | } else if (changes & BSS_CHANGED_BEACON_INFO) { |
948 | /* | 950 | /* |
949 | * We received a beacon _after_ association so | 951 | * We received a beacon _after_ association so |
@@ -1012,9 +1014,16 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, | |||
1012 | if (ret) | 1014 | if (ret) |
1013 | goto out_unbind; | 1015 | goto out_unbind; |
1014 | 1016 | ||
1017 | /* must be set before quota calculations */ | ||
1018 | mvmvif->ap_ibss_active = true; | ||
1019 | |||
1020 | /* power updated needs to be done before quotas */ | ||
1021 | mvm->bound_vif_cnt++; | ||
1022 | iwl_mvm_power_update_binding(mvm, vif, true); | ||
1023 | |||
1015 | ret = iwl_mvm_update_quotas(mvm, vif); | 1024 | ret = iwl_mvm_update_quotas(mvm, vif); |
1016 | if (ret) | 1025 | if (ret) |
1017 | goto out_rm_bcast; | 1026 | goto out_quota_failed; |
1018 | 1027 | ||
1019 | /* Need to update the P2P Device MAC (only GO, IBSS is single vif) */ | 1028 | /* Need to update the P2P Device MAC (only GO, IBSS is single vif) */ |
1020 | if (vif->p2p && mvm->p2p_device_vif) | 1029 | if (vif->p2p && mvm->p2p_device_vif) |
@@ -1025,7 +1034,10 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, | |||
1025 | mutex_unlock(&mvm->mutex); | 1034 | mutex_unlock(&mvm->mutex); |
1026 | return 0; | 1035 | return 0; |
1027 | 1036 | ||
1028 | out_rm_bcast: | 1037 | out_quota_failed: |
1038 | mvm->bound_vif_cnt--; | ||
1039 | iwl_mvm_power_update_binding(mvm, vif, false); | ||
1040 | mvmvif->ap_ibss_active = false; | ||
1029 | iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta); | 1041 | iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta); |
1030 | out_unbind: | 1042 | out_unbind: |
1031 | iwl_mvm_binding_remove_vif(mvm, vif); | 1043 | iwl_mvm_binding_remove_vif(mvm, vif); |
@@ -1057,6 +1069,10 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw, | |||
1057 | iwl_mvm_update_quotas(mvm, NULL); | 1069 | iwl_mvm_update_quotas(mvm, NULL); |
1058 | iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta); | 1070 | iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta); |
1059 | iwl_mvm_binding_remove_vif(mvm, vif); | 1071 | iwl_mvm_binding_remove_vif(mvm, vif); |
1072 | |||
1073 | mvm->bound_vif_cnt--; | ||
1074 | iwl_mvm_power_update_binding(mvm, vif, false); | ||
1075 | |||
1060 | iwl_mvm_mac_ctxt_remove(mvm, vif); | 1076 | iwl_mvm_mac_ctxt_remove(mvm, vif); |
1061 | 1077 | ||
1062 | mutex_unlock(&mvm->mutex); | 1078 | mutex_unlock(&mvm->mutex); |
@@ -1790,11 +1806,11 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw, | |||
1790 | } | 1806 | } |
1791 | 1807 | ||
1792 | iwl_mvm_binding_remove_vif(mvm, vif); | 1808 | iwl_mvm_binding_remove_vif(mvm, vif); |
1793 | out_unlock: | ||
1794 | mvmvif->phy_ctxt = NULL; | ||
1795 | mvm->bound_vif_cnt--; | 1809 | mvm->bound_vif_cnt--; |
1796 | iwl_mvm_power_update_binding(mvm, vif, false); | 1810 | iwl_mvm_power_update_binding(mvm, vif, false); |
1797 | 1811 | ||
1812 | out_unlock: | ||
1813 | mvmvif->phy_ctxt = NULL; | ||
1798 | mutex_unlock(&mvm->mutex); | 1814 | mutex_unlock(&mvm->mutex); |
1799 | } | 1815 | } |
1800 | 1816 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index c6beb0f842d5..35b71af78d02 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c | |||
@@ -392,17 +392,16 @@ out: | |||
392 | /* Loads the NVM data stored in mvm->nvm_sections into the NIC */ | 392 | /* Loads the NVM data stored in mvm->nvm_sections into the NIC */ |
393 | int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm) | 393 | int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm) |
394 | { | 394 | { |
395 | int i, ret; | 395 | int i, ret = 0; |
396 | u16 section_id; | ||
397 | struct iwl_nvm_section *sections = mvm->nvm_sections; | 396 | struct iwl_nvm_section *sections = mvm->nvm_sections; |
398 | 397 | ||
399 | IWL_DEBUG_EEPROM(mvm->trans->dev, "'Write to NVM\n"); | 398 | IWL_DEBUG_EEPROM(mvm->trans->dev, "'Write to NVM\n"); |
400 | 399 | ||
401 | for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) { | 400 | for (i = 0; i < ARRAY_SIZE(mvm->nvm_sections); i++) { |
402 | section_id = nvm_to_read[i]; | 401 | if (!mvm->nvm_sections[i].data || !mvm->nvm_sections[i].length) |
403 | ret = iwl_nvm_write_section(mvm, section_id, | 402 | continue; |
404 | sections[section_id].data, | 403 | ret = iwl_nvm_write_section(mvm, i, sections[i].data, |
405 | sections[section_id].length); | 404 | sections[i].length); |
406 | if (ret < 0) { | 405 | if (ret < 0) { |
407 | IWL_ERR(mvm, "iwl_mvm_send_cmd failed: %d\n", ret); | 406 | IWL_ERR(mvm, "iwl_mvm_send_cmd failed: %d\n", ret); |
408 | break; | 407 | break; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 552c76a926ed..a3d43de342d7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -309,6 +309,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { | |||
309 | CMD(BT_PROFILE_NOTIFICATION), | 309 | CMD(BT_PROFILE_NOTIFICATION), |
310 | CMD(BT_CONFIG), | 310 | CMD(BT_CONFIG), |
311 | CMD(MCAST_FILTER_CMD), | 311 | CMD(MCAST_FILTER_CMD), |
312 | CMD(REPLY_SF_CFG_CMD), | ||
312 | CMD(REPLY_BEACON_FILTERING_CMD), | 313 | CMD(REPLY_BEACON_FILTERING_CMD), |
313 | CMD(REPLY_THERMAL_MNG_BACKOFF), | 314 | CMD(REPLY_THERMAL_MNG_BACKOFF), |
314 | CMD(MAC_PM_POWER_TABLE), | 315 | CMD(MAC_PM_POWER_TABLE), |
@@ -472,6 +473,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
472 | 473 | ||
473 | out_unregister: | 474 | out_unregister: |
474 | ieee80211_unregister_hw(mvm->hw); | 475 | ieee80211_unregister_hw(mvm->hw); |
476 | iwl_mvm_leds_exit(mvm); | ||
475 | out_free: | 477 | out_free: |
476 | iwl_phy_db_free(mvm->phy_db); | 478 | iwl_phy_db_free(mvm->phy_db); |
477 | kfree(mvm->scan_cmd); | 479 | kfree(mvm->scan_cmd); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index ba078a3322b8..6abf74e1351f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
@@ -356,7 +356,7 @@ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) | |||
356 | return idx; | 356 | return idx; |
357 | } | 357 | } |
358 | 358 | ||
359 | return -1; | 359 | return IWL_RATE_INVALID; |
360 | } | 360 | } |
361 | 361 | ||
362 | static void rs_rate_scale_perform(struct iwl_mvm *mvm, | 362 | static void rs_rate_scale_perform(struct iwl_mvm *mvm, |
@@ -702,10 +702,8 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate, | |||
702 | memset(rate, 0, sizeof(*rate)); | 702 | memset(rate, 0, sizeof(*rate)); |
703 | rate->index = iwl_hwrate_to_plcp_idx(ucode_rate); | 703 | rate->index = iwl_hwrate_to_plcp_idx(ucode_rate); |
704 | 704 | ||
705 | if (rate->index == IWL_RATE_INVALID) { | 705 | if (rate->index == IWL_RATE_INVALID) |
706 | rate->index = -1; | ||
707 | return -EINVAL; | 706 | return -EINVAL; |
708 | } | ||
709 | 707 | ||
710 | rate->ant = (ant_msk >> RATE_MCS_ANT_POS); | 708 | rate->ant = (ant_msk >> RATE_MCS_ANT_POS); |
711 | 709 | ||
@@ -1590,6 +1588,8 @@ static int rs_switch_to_column(struct iwl_mvm *mvm, | |||
1590 | search_tbl->column = col_id; | 1588 | search_tbl->column = col_id; |
1591 | rs_set_expected_tpt_table(lq_sta, search_tbl); | 1589 | rs_set_expected_tpt_table(lq_sta, search_tbl); |
1592 | 1590 | ||
1591 | lq_sta->visited_columns |= BIT(col_id); | ||
1592 | |||
1593 | /* Get the best matching rate if we're changing modes. e.g. | 1593 | /* Get the best matching rate if we're changing modes. e.g. |
1594 | * SISO->MIMO, LEGACY->SISO, MIMO->SISO | 1594 | * SISO->MIMO, LEGACY->SISO, MIMO->SISO |
1595 | */ | 1595 | */ |
@@ -1613,7 +1613,6 @@ static int rs_switch_to_column(struct iwl_mvm *mvm, | |||
1613 | IWL_DEBUG_RATE(mvm, "Switched to column %d: Index %d\n", | 1613 | IWL_DEBUG_RATE(mvm, "Switched to column %d: Index %d\n", |
1614 | col_id, rate->index); | 1614 | col_id, rate->index); |
1615 | 1615 | ||
1616 | lq_sta->visited_columns |= BIT(col_id); | ||
1617 | return 0; | 1616 | return 0; |
1618 | 1617 | ||
1619 | err: | 1618 | err: |
@@ -2560,7 +2559,9 @@ static int rs_pretty_print_rate(char *buf, const u32 rate) | |||
2560 | int index = iwl_hwrate_to_plcp_idx(rate); | 2559 | int index = iwl_hwrate_to_plcp_idx(rate); |
2561 | 2560 | ||
2562 | return sprintf(buf, "Legacy | ANT: %s Rate: %s Mbps\n", | 2561 | return sprintf(buf, "Legacy | ANT: %s Rate: %s Mbps\n", |
2563 | rs_pretty_ant(ant), iwl_rate_mcs[index].mbps); | 2562 | rs_pretty_ant(ant), |
2563 | index == IWL_RATE_INVALID ? "BAD" : | ||
2564 | iwl_rate_mcs[index].mbps); | ||
2564 | } | 2565 | } |
2565 | 2566 | ||
2566 | if (rate & RATE_MCS_VHT_MSK) { | 2567 | if (rate & RATE_MCS_VHT_MSK) { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index 50f3d7f560bc..b4c2abaa297b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c | |||
@@ -249,12 +249,12 @@ static bool iwl_mvm_time_event_response(struct iwl_notif_wait_data *notif_wait, | |||
249 | container_of(notif_wait, struct iwl_mvm, notif_wait); | 249 | container_of(notif_wait, struct iwl_mvm, notif_wait); |
250 | struct iwl_mvm_time_event_data *te_data = data; | 250 | struct iwl_mvm_time_event_data *te_data = data; |
251 | struct iwl_time_event_resp *resp; | 251 | struct iwl_time_event_resp *resp; |
252 | int resp_len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | 252 | int resp_len = iwl_rx_packet_payload_len(pkt); |
253 | 253 | ||
254 | if (WARN_ON(pkt->hdr.cmd != TIME_EVENT_CMD)) | 254 | if (WARN_ON(pkt->hdr.cmd != TIME_EVENT_CMD)) |
255 | return true; | 255 | return true; |
256 | 256 | ||
257 | if (WARN_ON_ONCE(resp_len != sizeof(pkt->hdr) + sizeof(*resp))) { | 257 | if (WARN_ON_ONCE(resp_len != sizeof(*resp))) { |
258 | IWL_ERR(mvm, "Invalid TIME_EVENT_CMD response\n"); | 258 | IWL_ERR(mvm, "Invalid TIME_EVENT_CMD response\n"); |
259 | return true; | 259 | return true; |
260 | } | 260 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 3c575a39987b..90378c217bc7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
@@ -390,7 +390,6 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
390 | seq_number &= IEEE80211_SCTL_SEQ; | 390 | seq_number &= IEEE80211_SCTL_SEQ; |
391 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | 391 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); |
392 | hdr->seq_ctrl |= cpu_to_le16(seq_number); | 392 | hdr->seq_ctrl |= cpu_to_le16(seq_number); |
393 | seq_number += 0x10; | ||
394 | is_data_qos = true; | 393 | is_data_qos = true; |
395 | is_ampdu = info->flags & IEEE80211_TX_CTL_AMPDU; | 394 | is_ampdu = info->flags & IEEE80211_TX_CTL_AMPDU; |
396 | } | 395 | } |
@@ -407,13 +406,13 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
407 | } | 406 | } |
408 | 407 | ||
409 | IWL_DEBUG_TX(mvm, "TX to [%d|%d] Q:%d - seq: 0x%x\n", mvmsta->sta_id, | 408 | IWL_DEBUG_TX(mvm, "TX to [%d|%d] Q:%d - seq: 0x%x\n", mvmsta->sta_id, |
410 | tid, txq_id, seq_number); | 409 | tid, txq_id, IEEE80211_SEQ_TO_SN(seq_number)); |
411 | 410 | ||
412 | if (iwl_trans_tx(mvm->trans, skb, dev_cmd, txq_id)) | 411 | if (iwl_trans_tx(mvm->trans, skb, dev_cmd, txq_id)) |
413 | goto drop_unlock_sta; | 412 | goto drop_unlock_sta; |
414 | 413 | ||
415 | if (is_data_qos && !ieee80211_has_morefrags(fc)) | 414 | if (is_data_qos && !ieee80211_has_morefrags(fc)) |
416 | mvmsta->tid_data[tid].seq_number = seq_number; | 415 | mvmsta->tid_data[tid].seq_number = seq_number + 0x10; |
417 | 416 | ||
418 | spin_unlock(&mvmsta->lock); | 417 | spin_unlock(&mvmsta->lock); |
419 | 418 | ||
@@ -704,7 +703,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
704 | */ | 703 | */ |
705 | spin_lock_bh(&mvmsta->lock); | 704 | spin_lock_bh(&mvmsta->lock); |
706 | sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); | 705 | sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); |
707 | if (IS_ERR_OR_NULL(sta)) { | 706 | if (!sta || PTR_ERR(sta) == -EBUSY) { |
708 | /* | 707 | /* |
709 | * Station disappeared in the meantime: | 708 | * Station disappeared in the meantime: |
710 | * so we are draining. | 709 | * so we are draining. |
@@ -713,7 +712,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
713 | schedule_work(&mvm->sta_drained_wk); | 712 | schedule_work(&mvm->sta_drained_wk); |
714 | } | 713 | } |
715 | spin_unlock_bh(&mvmsta->lock); | 714 | spin_unlock_bh(&mvmsta->lock); |
716 | } else if (!mvmsta) { | 715 | } else if (!mvmsta && PTR_ERR(sta) == -EBUSY) { |
717 | /* Tx response without STA, so we are draining */ | 716 | /* Tx response without STA, so we are draining */ |
718 | set_bit(sta_id, mvm->sta_drained); | 717 | set_bit(sta_id, mvm->sta_drained); |
719 | schedule_work(&mvm->sta_drained_wk); | 718 | schedule_work(&mvm->sta_drained_wk); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index 487d61b25359..a4a5e25623c3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c | |||
@@ -168,8 +168,8 @@ int iwl_mvm_send_cmd_status(struct iwl_mvm *mvm, struct iwl_host_cmd *cmd, | |||
168 | goto out_free_resp; | 168 | goto out_free_resp; |
169 | } | 169 | } |
170 | 170 | ||
171 | resp_len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | 171 | resp_len = iwl_rx_packet_payload_len(pkt); |
172 | if (WARN_ON_ONCE(resp_len != sizeof(pkt->hdr) + sizeof(*resp))) { | 172 | if (WARN_ON_ONCE(resp_len != sizeof(*resp))) { |
173 | ret = -EIO; | 173 | ret = -EIO; |
174 | goto out_free_resp; | 174 | goto out_free_resp; |
175 | } | 175 | } |
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 1890ea29c264..08c23d497a02 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c | |||
@@ -615,7 +615,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, | |||
615 | rxcb._offset, get_cmd_string(trans_pcie, pkt->hdr.cmd), | 615 | rxcb._offset, get_cmd_string(trans_pcie, pkt->hdr.cmd), |
616 | pkt->hdr.cmd); | 616 | pkt->hdr.cmd); |
617 | 617 | ||
618 | len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | 618 | len = iwl_rx_packet_len(pkt); |
619 | len += sizeof(u32); /* account for status word */ | 619 | len += sizeof(u32); /* account for status word */ |
620 | trace_iwlwifi_dev_rx(trans->dev, trans, pkt, len); | 620 | trace_iwlwifi_dev_rx(trans->dev, trans, pkt, len); |
621 | trace_iwlwifi_dev_rx_data(trans->dev, trans, pkt, len); | 621 | trace_iwlwifi_dev_rx_data(trans->dev, trans, pkt, len); |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 16f66c1a23de..f9507807b486 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -178,6 +178,28 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans) | |||
178 | goto out; | 178 | goto out; |
179 | } | 179 | } |
180 | 180 | ||
181 | if (trans->cfg->host_interrupt_operation_mode) { | ||
182 | /* | ||
183 | * This is a bit of an abuse - This is needed for 7260 / 3160 | ||
184 | * only check host_interrupt_operation_mode even if this is | ||
185 | * not related to host_interrupt_operation_mode. | ||
186 | * | ||
187 | * Enable the oscillator to count wake up time for L1 exit. This | ||
188 | * consumes slightly more power (100uA) - but allows to be sure | ||
189 | * that we wake up from L1 on time. | ||
190 | * | ||
191 | * This looks weird: read twice the same register, discard the | ||
192 | * value, set a bit, and yet again, read that same register | ||
193 | * just to discard the value. But that's the way the hardware | ||
194 | * seems to like it. | ||
195 | */ | ||
196 | iwl_read_prph(trans, OSC_CLK); | ||
197 | iwl_read_prph(trans, OSC_CLK); | ||
198 | iwl_set_bits_prph(trans, OSC_CLK, OSC_CLK_FORCE_CONTROL); | ||
199 | iwl_read_prph(trans, OSC_CLK); | ||
200 | iwl_read_prph(trans, OSC_CLK); | ||
201 | } | ||
202 | |||
181 | /* | 203 | /* |
182 | * Enable DMA clock and wait for it to stabilize. | 204 | * Enable DMA clock and wait for it to stabilize. |
183 | * | 205 | * |
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 116f4aba08d6..32f75007a825 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c | |||
@@ -1268,14 +1268,9 @@ static struct cfg80211_scan_request * | |||
1268 | _new_connect_scan_req(struct wiphy *wiphy, struct cfg80211_connect_params *sme) | 1268 | _new_connect_scan_req(struct wiphy *wiphy, struct cfg80211_connect_params *sme) |
1269 | { | 1269 | { |
1270 | struct cfg80211_scan_request *creq = NULL; | 1270 | struct cfg80211_scan_request *creq = NULL; |
1271 | int i, n_channels = 0; | 1271 | int i, n_channels = ieee80211_get_num_supported_channels(wiphy); |
1272 | enum ieee80211_band band; | 1272 | enum ieee80211_band band; |
1273 | 1273 | ||
1274 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
1275 | if (wiphy->bands[band]) | ||
1276 | n_channels += wiphy->bands[band]->n_channels; | ||
1277 | } | ||
1278 | |||
1279 | creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) + | 1274 | creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) + |
1280 | n_channels * sizeof(void *), | 1275 | n_channels * sizeof(void *), |
1281 | GFP_ATOMIC); | 1276 | GFP_ATOMIC); |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index fa41a773b79b..69d4c3179d04 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -163,6 +163,11 @@ static const struct ieee80211_regdomain hwsim_world_regdom_custom_02 = { | |||
163 | } | 163 | } |
164 | }; | 164 | }; |
165 | 165 | ||
166 | static const struct ieee80211_regdomain *hwsim_world_regdom_custom[] = { | ||
167 | &hwsim_world_regdom_custom_01, | ||
168 | &hwsim_world_regdom_custom_02, | ||
169 | }; | ||
170 | |||
166 | struct hwsim_vif_priv { | 171 | struct hwsim_vif_priv { |
167 | u32 magic; | 172 | u32 magic; |
168 | u8 bssid[ETH_ALEN]; | 173 | u8 bssid[ETH_ALEN]; |
@@ -321,8 +326,52 @@ static const struct ieee80211_rate hwsim_rates[] = { | |||
321 | { .bitrate = 540 } | 326 | { .bitrate = 540 } |
322 | }; | 327 | }; |
323 | 328 | ||
329 | static const struct ieee80211_iface_limit hwsim_if_limits[] = { | ||
330 | { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) }, | ||
331 | { .max = 2048, .types = BIT(NL80211_IFTYPE_STATION) | | ||
332 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
333 | #ifdef CONFIG_MAC80211_MESH | ||
334 | BIT(NL80211_IFTYPE_MESH_POINT) | | ||
335 | #endif | ||
336 | BIT(NL80211_IFTYPE_AP) | | ||
337 | BIT(NL80211_IFTYPE_P2P_GO) }, | ||
338 | { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) }, | ||
339 | }; | ||
340 | |||
341 | static const struct ieee80211_iface_limit hwsim_if_dfs_limits[] = { | ||
342 | { .max = 8, .types = BIT(NL80211_IFTYPE_AP) }, | ||
343 | }; | ||
344 | |||
345 | static const struct ieee80211_iface_combination hwsim_if_comb[] = { | ||
346 | { | ||
347 | .limits = hwsim_if_limits, | ||
348 | .n_limits = ARRAY_SIZE(hwsim_if_limits), | ||
349 | .max_interfaces = 2048, | ||
350 | .num_different_channels = 1, | ||
351 | }, | ||
352 | { | ||
353 | .limits = hwsim_if_dfs_limits, | ||
354 | .n_limits = ARRAY_SIZE(hwsim_if_dfs_limits), | ||
355 | .max_interfaces = 8, | ||
356 | .num_different_channels = 1, | ||
357 | .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | | ||
358 | BIT(NL80211_CHAN_WIDTH_20) | | ||
359 | BIT(NL80211_CHAN_WIDTH_40) | | ||
360 | BIT(NL80211_CHAN_WIDTH_80) | | ||
361 | BIT(NL80211_CHAN_WIDTH_160), | ||
362 | } | ||
363 | }; | ||
364 | |||
324 | static spinlock_t hwsim_radio_lock; | 365 | static spinlock_t hwsim_radio_lock; |
325 | static struct list_head hwsim_radios; | 366 | static struct list_head hwsim_radios; |
367 | static int hwsim_radio_idx; | ||
368 | |||
369 | static struct platform_driver mac80211_hwsim_driver = { | ||
370 | .driver = { | ||
371 | .name = "mac80211_hwsim", | ||
372 | .owner = THIS_MODULE, | ||
373 | }, | ||
374 | }; | ||
326 | 375 | ||
327 | struct mac80211_hwsim_data { | 376 | struct mac80211_hwsim_data { |
328 | struct list_head list; | 377 | struct list_head list; |
@@ -332,8 +381,10 @@ struct mac80211_hwsim_data { | |||
332 | struct ieee80211_channel channels_2ghz[ARRAY_SIZE(hwsim_channels_2ghz)]; | 381 | struct ieee80211_channel channels_2ghz[ARRAY_SIZE(hwsim_channels_2ghz)]; |
333 | struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)]; | 382 | struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)]; |
334 | struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; | 383 | struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; |
384 | struct ieee80211_iface_combination if_combination; | ||
335 | 385 | ||
336 | struct mac_address addresses[2]; | 386 | struct mac_address addresses[2]; |
387 | int channels, idx; | ||
337 | 388 | ||
338 | struct ieee80211_channel *tmp_chan; | 389 | struct ieee80211_channel *tmp_chan; |
339 | struct delayed_work roc_done; | 390 | struct delayed_work roc_done; |
@@ -401,21 +452,179 @@ static struct genl_family hwsim_genl_family = { | |||
401 | /* MAC80211_HWSIM netlink policy */ | 452 | /* MAC80211_HWSIM netlink policy */ |
402 | 453 | ||
403 | static struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { | 454 | static struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { |
404 | [HWSIM_ATTR_ADDR_RECEIVER] = { .type = NLA_UNSPEC, | 455 | [HWSIM_ATTR_ADDR_RECEIVER] = { .type = NLA_UNSPEC, .len = ETH_ALEN }, |
405 | .len = 6*sizeof(u8) }, | 456 | [HWSIM_ATTR_ADDR_TRANSMITTER] = { .type = NLA_UNSPEC, .len = ETH_ALEN }, |
406 | [HWSIM_ATTR_ADDR_TRANSMITTER] = { .type = NLA_UNSPEC, | ||
407 | .len = 6*sizeof(u8) }, | ||
408 | [HWSIM_ATTR_FRAME] = { .type = NLA_BINARY, | 457 | [HWSIM_ATTR_FRAME] = { .type = NLA_BINARY, |
409 | .len = IEEE80211_MAX_DATA_LEN }, | 458 | .len = IEEE80211_MAX_DATA_LEN }, |
410 | [HWSIM_ATTR_FLAGS] = { .type = NLA_U32 }, | 459 | [HWSIM_ATTR_FLAGS] = { .type = NLA_U32 }, |
411 | [HWSIM_ATTR_RX_RATE] = { .type = NLA_U32 }, | 460 | [HWSIM_ATTR_RX_RATE] = { .type = NLA_U32 }, |
412 | [HWSIM_ATTR_SIGNAL] = { .type = NLA_U32 }, | 461 | [HWSIM_ATTR_SIGNAL] = { .type = NLA_U32 }, |
413 | [HWSIM_ATTR_TX_INFO] = { .type = NLA_UNSPEC, | 462 | [HWSIM_ATTR_TX_INFO] = { .type = NLA_UNSPEC, |
414 | .len = IEEE80211_TX_MAX_RATES*sizeof( | 463 | .len = IEEE80211_TX_MAX_RATES * |
415 | struct hwsim_tx_rate)}, | 464 | sizeof(struct hwsim_tx_rate)}, |
416 | [HWSIM_ATTR_COOKIE] = { .type = NLA_U64 }, | 465 | [HWSIM_ATTR_COOKIE] = { .type = NLA_U64 }, |
466 | [HWSIM_ATTR_CHANNELS] = { .type = NLA_U32 }, | ||
467 | [HWSIM_ATTR_RADIO_ID] = { .type = NLA_U32 }, | ||
468 | [HWSIM_ATTR_REG_HINT_ALPHA2] = { .type = NLA_STRING, .len = 2 }, | ||
469 | [HWSIM_ATTR_REG_CUSTOM_REG] = { .type = NLA_U32 }, | ||
470 | [HWSIM_ATTR_REG_STRICT_REG] = { .type = NLA_FLAG }, | ||
417 | }; | 471 | }; |
418 | 472 | ||
473 | static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, | ||
474 | struct sk_buff *skb, | ||
475 | struct ieee80211_channel *chan); | ||
476 | |||
477 | /* sysfs attributes */ | ||
478 | static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif) | ||
479 | { | ||
480 | struct mac80211_hwsim_data *data = dat; | ||
481 | struct hwsim_vif_priv *vp = (void *)vif->drv_priv; | ||
482 | struct sk_buff *skb; | ||
483 | struct ieee80211_pspoll *pspoll; | ||
484 | |||
485 | if (!vp->assoc) | ||
486 | return; | ||
487 | |||
488 | wiphy_debug(data->hw->wiphy, | ||
489 | "%s: send PS-Poll to %pM for aid %d\n", | ||
490 | __func__, vp->bssid, vp->aid); | ||
491 | |||
492 | skb = dev_alloc_skb(sizeof(*pspoll)); | ||
493 | if (!skb) | ||
494 | return; | ||
495 | pspoll = (void *) skb_put(skb, sizeof(*pspoll)); | ||
496 | pspoll->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | | ||
497 | IEEE80211_STYPE_PSPOLL | | ||
498 | IEEE80211_FCTL_PM); | ||
499 | pspoll->aid = cpu_to_le16(0xc000 | vp->aid); | ||
500 | memcpy(pspoll->bssid, vp->bssid, ETH_ALEN); | ||
501 | memcpy(pspoll->ta, mac, ETH_ALEN); | ||
502 | |||
503 | rcu_read_lock(); | ||
504 | mac80211_hwsim_tx_frame(data->hw, skb, | ||
505 | rcu_dereference(vif->chanctx_conf)->def.chan); | ||
506 | rcu_read_unlock(); | ||
507 | } | ||
508 | |||
509 | static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac, | ||
510 | struct ieee80211_vif *vif, int ps) | ||
511 | { | ||
512 | struct hwsim_vif_priv *vp = (void *)vif->drv_priv; | ||
513 | struct sk_buff *skb; | ||
514 | struct ieee80211_hdr *hdr; | ||
515 | |||
516 | if (!vp->assoc) | ||
517 | return; | ||
518 | |||
519 | wiphy_debug(data->hw->wiphy, | ||
520 | "%s: send data::nullfunc to %pM ps=%d\n", | ||
521 | __func__, vp->bssid, ps); | ||
522 | |||
523 | skb = dev_alloc_skb(sizeof(*hdr)); | ||
524 | if (!skb) | ||
525 | return; | ||
526 | hdr = (void *) skb_put(skb, sizeof(*hdr) - ETH_ALEN); | ||
527 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | | ||
528 | IEEE80211_STYPE_NULLFUNC | | ||
529 | (ps ? IEEE80211_FCTL_PM : 0)); | ||
530 | hdr->duration_id = cpu_to_le16(0); | ||
531 | memcpy(hdr->addr1, vp->bssid, ETH_ALEN); | ||
532 | memcpy(hdr->addr2, mac, ETH_ALEN); | ||
533 | memcpy(hdr->addr3, vp->bssid, ETH_ALEN); | ||
534 | |||
535 | rcu_read_lock(); | ||
536 | mac80211_hwsim_tx_frame(data->hw, skb, | ||
537 | rcu_dereference(vif->chanctx_conf)->def.chan); | ||
538 | rcu_read_unlock(); | ||
539 | } | ||
540 | |||
541 | |||
542 | static void hwsim_send_nullfunc_ps(void *dat, u8 *mac, | ||
543 | struct ieee80211_vif *vif) | ||
544 | { | ||
545 | struct mac80211_hwsim_data *data = dat; | ||
546 | hwsim_send_nullfunc(data, mac, vif, 1); | ||
547 | } | ||
548 | |||
549 | static void hwsim_send_nullfunc_no_ps(void *dat, u8 *mac, | ||
550 | struct ieee80211_vif *vif) | ||
551 | { | ||
552 | struct mac80211_hwsim_data *data = dat; | ||
553 | hwsim_send_nullfunc(data, mac, vif, 0); | ||
554 | } | ||
555 | |||
556 | static int hwsim_fops_ps_read(void *dat, u64 *val) | ||
557 | { | ||
558 | struct mac80211_hwsim_data *data = dat; | ||
559 | *val = data->ps; | ||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | static int hwsim_fops_ps_write(void *dat, u64 val) | ||
564 | { | ||
565 | struct mac80211_hwsim_data *data = dat; | ||
566 | enum ps_mode old_ps; | ||
567 | |||
568 | if (val != PS_DISABLED && val != PS_ENABLED && val != PS_AUTO_POLL && | ||
569 | val != PS_MANUAL_POLL) | ||
570 | return -EINVAL; | ||
571 | |||
572 | old_ps = data->ps; | ||
573 | data->ps = val; | ||
574 | |||
575 | if (val == PS_MANUAL_POLL) { | ||
576 | ieee80211_iterate_active_interfaces(data->hw, | ||
577 | IEEE80211_IFACE_ITER_NORMAL, | ||
578 | hwsim_send_ps_poll, data); | ||
579 | data->ps_poll_pending = true; | ||
580 | } else if (old_ps == PS_DISABLED && val != PS_DISABLED) { | ||
581 | ieee80211_iterate_active_interfaces(data->hw, | ||
582 | IEEE80211_IFACE_ITER_NORMAL, | ||
583 | hwsim_send_nullfunc_ps, | ||
584 | data); | ||
585 | } else if (old_ps != PS_DISABLED && val == PS_DISABLED) { | ||
586 | ieee80211_iterate_active_interfaces(data->hw, | ||
587 | IEEE80211_IFACE_ITER_NORMAL, | ||
588 | hwsim_send_nullfunc_no_ps, | ||
589 | data); | ||
590 | } | ||
591 | |||
592 | return 0; | ||
593 | } | ||
594 | |||
595 | DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_ps, hwsim_fops_ps_read, hwsim_fops_ps_write, | ||
596 | "%llu\n"); | ||
597 | |||
598 | static int hwsim_write_simulate_radar(void *dat, u64 val) | ||
599 | { | ||
600 | struct mac80211_hwsim_data *data = dat; | ||
601 | |||
602 | ieee80211_radar_detected(data->hw); | ||
603 | |||
604 | return 0; | ||
605 | } | ||
606 | |||
607 | DEFINE_SIMPLE_ATTRIBUTE(hwsim_simulate_radar, NULL, | ||
608 | hwsim_write_simulate_radar, "%llu\n"); | ||
609 | |||
610 | static int hwsim_fops_group_read(void *dat, u64 *val) | ||
611 | { | ||
612 | struct mac80211_hwsim_data *data = dat; | ||
613 | *val = data->group; | ||
614 | return 0; | ||
615 | } | ||
616 | |||
617 | static int hwsim_fops_group_write(void *dat, u64 val) | ||
618 | { | ||
619 | struct mac80211_hwsim_data *data = dat; | ||
620 | data->group = val; | ||
621 | return 0; | ||
622 | } | ||
623 | |||
624 | DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_group, | ||
625 | hwsim_fops_group_read, hwsim_fops_group_write, | ||
626 | "%llx\n"); | ||
627 | |||
419 | static netdev_tx_t hwsim_mon_xmit(struct sk_buff *skb, | 628 | static netdev_tx_t hwsim_mon_xmit(struct sk_buff *skb, |
420 | struct net_device *dev) | 629 | struct net_device *dev) |
421 | { | 630 | { |
@@ -639,7 +848,7 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, | |||
639 | } | 848 | } |
640 | 849 | ||
641 | if (nla_put(skb, HWSIM_ATTR_ADDR_TRANSMITTER, | 850 | if (nla_put(skb, HWSIM_ATTR_ADDR_TRANSMITTER, |
642 | sizeof(struct mac_address), data->addresses[1].addr)) | 851 | ETH_ALEN, data->addresses[1].addr)) |
643 | goto nla_put_failure; | 852 | goto nla_put_failure; |
644 | 853 | ||
645 | /* We get the skb->data */ | 854 | /* We get the skb->data */ |
@@ -878,7 +1087,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, | |||
878 | return; | 1087 | return; |
879 | } | 1088 | } |
880 | 1089 | ||
881 | if (channels == 1) { | 1090 | if (data->channels == 1) { |
882 | channel = data->channel; | 1091 | channel = data->channel; |
883 | } else if (txi->hw_queue == 4) { | 1092 | } else if (txi->hw_queue == 4) { |
884 | channel = data->tmp_chan; | 1093 | channel = data->tmp_chan; |
@@ -906,7 +1115,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, | |||
906 | if (control->sta) | 1115 | if (control->sta) |
907 | hwsim_check_sta_magic(control->sta); | 1116 | hwsim_check_sta_magic(control->sta); |
908 | 1117 | ||
909 | if (rctbl) | 1118 | if (hw->flags & IEEE80211_HW_SUPPORTS_RC_TABLE) |
910 | ieee80211_get_tx_rates(txi->control.vif, control->sta, skb, | 1119 | ieee80211_get_tx_rates(txi->control.vif, control->sta, skb, |
911 | txi->control.rates, | 1120 | txi->control.rates, |
912 | ARRAY_SIZE(txi->control.rates)); | 1121 | ARRAY_SIZE(txi->control.rates)); |
@@ -1013,7 +1222,7 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, | |||
1013 | { | 1222 | { |
1014 | u32 _pid = ACCESS_ONCE(wmediumd_portid); | 1223 | u32 _pid = ACCESS_ONCE(wmediumd_portid); |
1015 | 1224 | ||
1016 | if (rctbl) { | 1225 | if (hw->flags & IEEE80211_HW_SUPPORTS_RC_TABLE) { |
1017 | struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb); | 1226 | struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb); |
1018 | ieee80211_get_tx_rates(txi->control.vif, NULL, skb, | 1227 | ieee80211_get_tx_rates(txi->control.vif, NULL, skb, |
1019 | txi->control.rates, | 1228 | txi->control.rates, |
@@ -1050,7 +1259,7 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, | |||
1050 | if (skb == NULL) | 1259 | if (skb == NULL) |
1051 | return; | 1260 | return; |
1052 | info = IEEE80211_SKB_CB(skb); | 1261 | info = IEEE80211_SKB_CB(skb); |
1053 | if (rctbl) | 1262 | if (hw->flags & IEEE80211_HW_SUPPORTS_RC_TABLE) |
1054 | ieee80211_get_tx_rates(vif, NULL, skb, | 1263 | ieee80211_get_tx_rates(vif, NULL, skb, |
1055 | info->control.rates, | 1264 | info->control.rates, |
1056 | ARRAY_SIZE(info->control.rates)); | 1265 | ARRAY_SIZE(info->control.rates)); |
@@ -1141,7 +1350,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) | |||
1141 | 1350 | ||
1142 | data->channel = conf->chandef.chan; | 1351 | data->channel = conf->chandef.chan; |
1143 | 1352 | ||
1144 | WARN_ON(data->channel && channels > 1); | 1353 | WARN_ON(data->channel && data->channels > 1); |
1145 | 1354 | ||
1146 | data->power_level = conf->power_level; | 1355 | data->power_level = conf->power_level; |
1147 | if (!data->started || !data->beacon_int) | 1356 | if (!data->started || !data->beacon_int) |
@@ -1388,8 +1597,6 @@ static const struct nla_policy hwsim_testmode_policy[HWSIM_TM_ATTR_MAX + 1] = { | |||
1388 | [HWSIM_TM_ATTR_PS] = { .type = NLA_U32 }, | 1597 | [HWSIM_TM_ATTR_PS] = { .type = NLA_U32 }, |
1389 | }; | 1598 | }; |
1390 | 1599 | ||
1391 | static int hwsim_fops_ps_write(void *dat, u64 val); | ||
1392 | |||
1393 | static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw, | 1600 | static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw, |
1394 | struct ieee80211_vif *vif, | 1601 | struct ieee80211_vif *vif, |
1395 | void *data, int len) | 1602 | void *data, int len) |
@@ -1700,8 +1907,7 @@ static void mac80211_hwsim_unassign_vif_chanctx(struct ieee80211_hw *hw, | |||
1700 | hwsim_check_chanctx_magic(ctx); | 1907 | hwsim_check_chanctx_magic(ctx); |
1701 | } | 1908 | } |
1702 | 1909 | ||
1703 | static struct ieee80211_ops mac80211_hwsim_ops = | 1910 | static const struct ieee80211_ops mac80211_hwsim_ops = { |
1704 | { | ||
1705 | .tx = mac80211_hwsim_tx, | 1911 | .tx = mac80211_hwsim_tx, |
1706 | .start = mac80211_hwsim_start, | 1912 | .start = mac80211_hwsim_start, |
1707 | .stop = mac80211_hwsim_stop, | 1913 | .stop = mac80211_hwsim_stop, |
@@ -1726,217 +1932,290 @@ static struct ieee80211_ops mac80211_hwsim_ops = | |||
1726 | .set_tsf = mac80211_hwsim_set_tsf, | 1932 | .set_tsf = mac80211_hwsim_set_tsf, |
1727 | }; | 1933 | }; |
1728 | 1934 | ||
1935 | static struct ieee80211_ops mac80211_hwsim_mchan_ops; | ||
1729 | 1936 | ||
1730 | static void mac80211_hwsim_free(void) | 1937 | static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, |
1938 | const struct ieee80211_regdomain *regd, | ||
1939 | bool reg_strict) | ||
1731 | { | 1940 | { |
1732 | struct list_head tmplist, *i, *tmp; | 1941 | int err; |
1733 | struct mac80211_hwsim_data *data, *tmpdata; | 1942 | u8 addr[ETH_ALEN]; |
1734 | 1943 | struct mac80211_hwsim_data *data; | |
1735 | INIT_LIST_HEAD(&tmplist); | 1944 | struct ieee80211_hw *hw; |
1945 | enum ieee80211_band band; | ||
1946 | const struct ieee80211_ops *ops = &mac80211_hwsim_ops; | ||
1947 | int idx; | ||
1736 | 1948 | ||
1737 | spin_lock_bh(&hwsim_radio_lock); | 1949 | spin_lock_bh(&hwsim_radio_lock); |
1738 | list_for_each_safe(i, tmp, &hwsim_radios) | 1950 | idx = hwsim_radio_idx++; |
1739 | list_move(i, &tmplist); | ||
1740 | spin_unlock_bh(&hwsim_radio_lock); | 1951 | spin_unlock_bh(&hwsim_radio_lock); |
1741 | 1952 | ||
1742 | list_for_each_entry_safe(data, tmpdata, &tmplist, list) { | 1953 | if (channels > 1) |
1743 | debugfs_remove_recursive(data->debugfs); | 1954 | ops = &mac80211_hwsim_mchan_ops; |
1744 | ieee80211_unregister_hw(data->hw); | 1955 | hw = ieee80211_alloc_hw(sizeof(*data), ops); |
1745 | device_release_driver(data->dev); | 1956 | if (!hw) { |
1746 | device_unregister(data->dev); | 1957 | printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw failed\n"); |
1747 | ieee80211_free_hw(data->hw); | 1958 | err = -ENOMEM; |
1959 | goto failed; | ||
1960 | } | ||
1961 | data = hw->priv; | ||
1962 | data->hw = hw; | ||
1963 | |||
1964 | data->dev = device_create(hwsim_class, NULL, 0, hw, "hwsim%d", idx); | ||
1965 | if (IS_ERR(data->dev)) { | ||
1966 | printk(KERN_DEBUG | ||
1967 | "mac80211_hwsim: device_create failed (%ld)\n", | ||
1968 | PTR_ERR(data->dev)); | ||
1969 | err = -ENOMEM; | ||
1970 | goto failed_drvdata; | ||
1971 | } | ||
1972 | data->dev->driver = &mac80211_hwsim_driver.driver; | ||
1973 | err = device_bind_driver(data->dev); | ||
1974 | if (err != 0) { | ||
1975 | printk(KERN_DEBUG "mac80211_hwsim: device_bind_driver failed (%d)\n", | ||
1976 | err); | ||
1977 | goto failed_hw; | ||
1748 | } | 1978 | } |
1749 | class_destroy(hwsim_class); | ||
1750 | } | ||
1751 | |||
1752 | static struct platform_driver mac80211_hwsim_driver = { | ||
1753 | .driver = { | ||
1754 | .name = "mac80211_hwsim", | ||
1755 | .owner = THIS_MODULE, | ||
1756 | }, | ||
1757 | }; | ||
1758 | |||
1759 | static const struct net_device_ops hwsim_netdev_ops = { | ||
1760 | .ndo_start_xmit = hwsim_mon_xmit, | ||
1761 | .ndo_change_mtu = eth_change_mtu, | ||
1762 | .ndo_set_mac_address = eth_mac_addr, | ||
1763 | .ndo_validate_addr = eth_validate_addr, | ||
1764 | }; | ||
1765 | |||
1766 | static void hwsim_mon_setup(struct net_device *dev) | ||
1767 | { | ||
1768 | dev->netdev_ops = &hwsim_netdev_ops; | ||
1769 | dev->destructor = free_netdev; | ||
1770 | ether_setup(dev); | ||
1771 | dev->tx_queue_len = 0; | ||
1772 | dev->type = ARPHRD_IEEE80211_RADIOTAP; | ||
1773 | memset(dev->dev_addr, 0, ETH_ALEN); | ||
1774 | dev->dev_addr[0] = 0x12; | ||
1775 | } | ||
1776 | 1979 | ||
1980 | skb_queue_head_init(&data->pending); | ||
1777 | 1981 | ||
1778 | static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif) | 1982 | SET_IEEE80211_DEV(hw, data->dev); |
1779 | { | 1983 | memset(addr, 0, ETH_ALEN); |
1780 | struct mac80211_hwsim_data *data = dat; | 1984 | addr[0] = 0x02; |
1781 | struct hwsim_vif_priv *vp = (void *)vif->drv_priv; | 1985 | addr[3] = idx >> 8; |
1782 | struct sk_buff *skb; | 1986 | addr[4] = idx; |
1783 | struct ieee80211_pspoll *pspoll; | 1987 | memcpy(data->addresses[0].addr, addr, ETH_ALEN); |
1988 | memcpy(data->addresses[1].addr, addr, ETH_ALEN); | ||
1989 | data->addresses[1].addr[0] |= 0x40; | ||
1990 | hw->wiphy->n_addresses = 2; | ||
1991 | hw->wiphy->addresses = data->addresses; | ||
1992 | |||
1993 | data->channels = channels; | ||
1994 | data->idx = idx; | ||
1995 | |||
1996 | if (data->channels > 1) { | ||
1997 | hw->wiphy->max_scan_ssids = 255; | ||
1998 | hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; | ||
1999 | hw->wiphy->max_remain_on_channel_duration = 1000; | ||
2000 | /* For channels > 1 DFS is not allowed */ | ||
2001 | hw->wiphy->n_iface_combinations = 1; | ||
2002 | hw->wiphy->iface_combinations = &data->if_combination; | ||
2003 | data->if_combination = hwsim_if_comb[0]; | ||
2004 | data->if_combination.num_different_channels = data->channels; | ||
2005 | } else { | ||
2006 | hw->wiphy->iface_combinations = hwsim_if_comb; | ||
2007 | hw->wiphy->n_iface_combinations = ARRAY_SIZE(hwsim_if_comb); | ||
2008 | } | ||
1784 | 2009 | ||
1785 | if (!vp->assoc) | 2010 | INIT_DELAYED_WORK(&data->roc_done, hw_roc_done); |
1786 | return; | 2011 | INIT_DELAYED_WORK(&data->hw_scan, hw_scan_work); |
2012 | |||
2013 | hw->queues = 5; | ||
2014 | hw->offchannel_tx_hw_queue = 4; | ||
2015 | hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | ||
2016 | BIT(NL80211_IFTYPE_AP) | | ||
2017 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
2018 | BIT(NL80211_IFTYPE_P2P_GO) | | ||
2019 | BIT(NL80211_IFTYPE_ADHOC) | | ||
2020 | BIT(NL80211_IFTYPE_MESH_POINT) | | ||
2021 | BIT(NL80211_IFTYPE_P2P_DEVICE); | ||
2022 | |||
2023 | hw->flags = IEEE80211_HW_MFP_CAPABLE | | ||
2024 | IEEE80211_HW_SIGNAL_DBM | | ||
2025 | IEEE80211_HW_SUPPORTS_STATIC_SMPS | | ||
2026 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | ||
2027 | IEEE80211_HW_AMPDU_AGGREGATION | | ||
2028 | IEEE80211_HW_WANT_MONITOR_VIF | | ||
2029 | IEEE80211_HW_QUEUE_CONTROL | | ||
2030 | IEEE80211_HW_SUPPORTS_HT_CCK_RATES; | ||
2031 | if (rctbl) | ||
2032 | hw->flags |= IEEE80211_HW_SUPPORTS_RC_TABLE; | ||
2033 | |||
2034 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | | ||
2035 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | | ||
2036 | WIPHY_FLAG_AP_UAPSD; | ||
2037 | hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; | ||
2038 | |||
2039 | /* ask mac80211 to reserve space for magic */ | ||
2040 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); | ||
2041 | hw->sta_data_size = sizeof(struct hwsim_sta_priv); | ||
2042 | hw->chanctx_data_size = sizeof(struct hwsim_chanctx_priv); | ||
2043 | |||
2044 | memcpy(data->channels_2ghz, hwsim_channels_2ghz, | ||
2045 | sizeof(hwsim_channels_2ghz)); | ||
2046 | memcpy(data->channels_5ghz, hwsim_channels_5ghz, | ||
2047 | sizeof(hwsim_channels_5ghz)); | ||
2048 | memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates)); | ||
2049 | |||
2050 | for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) { | ||
2051 | struct ieee80211_supported_band *sband = &data->bands[band]; | ||
2052 | switch (band) { | ||
2053 | case IEEE80211_BAND_2GHZ: | ||
2054 | sband->channels = data->channels_2ghz; | ||
2055 | sband->n_channels = ARRAY_SIZE(hwsim_channels_2ghz); | ||
2056 | sband->bitrates = data->rates; | ||
2057 | sband->n_bitrates = ARRAY_SIZE(hwsim_rates); | ||
2058 | break; | ||
2059 | case IEEE80211_BAND_5GHZ: | ||
2060 | sband->channels = data->channels_5ghz; | ||
2061 | sband->n_channels = ARRAY_SIZE(hwsim_channels_5ghz); | ||
2062 | sband->bitrates = data->rates + 4; | ||
2063 | sband->n_bitrates = ARRAY_SIZE(hwsim_rates) - 4; | ||
2064 | break; | ||
2065 | default: | ||
2066 | continue; | ||
2067 | } | ||
1787 | 2068 | ||
1788 | wiphy_debug(data->hw->wiphy, | 2069 | sband->ht_cap.ht_supported = true; |
1789 | "%s: send PS-Poll to %pM for aid %d\n", | 2070 | sband->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | |
1790 | __func__, vp->bssid, vp->aid); | 2071 | IEEE80211_HT_CAP_GRN_FLD | |
2072 | IEEE80211_HT_CAP_SGI_40 | | ||
2073 | IEEE80211_HT_CAP_DSSSCCK40; | ||
2074 | sband->ht_cap.ampdu_factor = 0x3; | ||
2075 | sband->ht_cap.ampdu_density = 0x6; | ||
2076 | memset(&sband->ht_cap.mcs, 0, | ||
2077 | sizeof(sband->ht_cap.mcs)); | ||
2078 | sband->ht_cap.mcs.rx_mask[0] = 0xff; | ||
2079 | sband->ht_cap.mcs.rx_mask[1] = 0xff; | ||
2080 | sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | ||
2081 | |||
2082 | hw->wiphy->bands[band] = sband; | ||
2083 | |||
2084 | sband->vht_cap.vht_supported = true; | ||
2085 | sband->vht_cap.cap = | ||
2086 | IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | | ||
2087 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ | | ||
2088 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | | ||
2089 | IEEE80211_VHT_CAP_RXLDPC | | ||
2090 | IEEE80211_VHT_CAP_SHORT_GI_80 | | ||
2091 | IEEE80211_VHT_CAP_SHORT_GI_160 | | ||
2092 | IEEE80211_VHT_CAP_TXSTBC | | ||
2093 | IEEE80211_VHT_CAP_RXSTBC_1 | | ||
2094 | IEEE80211_VHT_CAP_RXSTBC_2 | | ||
2095 | IEEE80211_VHT_CAP_RXSTBC_3 | | ||
2096 | IEEE80211_VHT_CAP_RXSTBC_4 | | ||
2097 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; | ||
2098 | sband->vht_cap.vht_mcs.rx_mcs_map = | ||
2099 | cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_8 << 0 | | ||
2100 | IEEE80211_VHT_MCS_SUPPORT_0_8 << 2 | | ||
2101 | IEEE80211_VHT_MCS_SUPPORT_0_9 << 4 | | ||
2102 | IEEE80211_VHT_MCS_SUPPORT_0_8 << 6 | | ||
2103 | IEEE80211_VHT_MCS_SUPPORT_0_8 << 8 | | ||
2104 | IEEE80211_VHT_MCS_SUPPORT_0_9 << 10 | | ||
2105 | IEEE80211_VHT_MCS_SUPPORT_0_9 << 12 | | ||
2106 | IEEE80211_VHT_MCS_SUPPORT_0_8 << 14); | ||
2107 | sband->vht_cap.vht_mcs.tx_mcs_map = | ||
2108 | sband->vht_cap.vht_mcs.rx_mcs_map; | ||
2109 | } | ||
1791 | 2110 | ||
1792 | skb = dev_alloc_skb(sizeof(*pspoll)); | 2111 | /* By default all radios belong to the first group */ |
1793 | if (!skb) | 2112 | data->group = 1; |
1794 | return; | 2113 | mutex_init(&data->mutex); |
1795 | pspoll = (void *) skb_put(skb, sizeof(*pspoll)); | ||
1796 | pspoll->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | | ||
1797 | IEEE80211_STYPE_PSPOLL | | ||
1798 | IEEE80211_FCTL_PM); | ||
1799 | pspoll->aid = cpu_to_le16(0xc000 | vp->aid); | ||
1800 | memcpy(pspoll->bssid, vp->bssid, ETH_ALEN); | ||
1801 | memcpy(pspoll->ta, mac, ETH_ALEN); | ||
1802 | 2114 | ||
1803 | rcu_read_lock(); | 2115 | /* Enable frame retransmissions for lossy channels */ |
1804 | mac80211_hwsim_tx_frame(data->hw, skb, | 2116 | hw->max_rates = 4; |
1805 | rcu_dereference(vif->chanctx_conf)->def.chan); | 2117 | hw->max_rate_tries = 11; |
1806 | rcu_read_unlock(); | ||
1807 | } | ||
1808 | 2118 | ||
1809 | static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac, | 2119 | if (reg_strict) |
1810 | struct ieee80211_vif *vif, int ps) | 2120 | hw->wiphy->regulatory_flags |= REGULATORY_STRICT_REG; |
1811 | { | 2121 | if (regd) { |
1812 | struct hwsim_vif_priv *vp = (void *)vif->drv_priv; | 2122 | hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; |
1813 | struct sk_buff *skb; | 2123 | wiphy_apply_custom_regulatory(hw->wiphy, regd); |
1814 | struct ieee80211_hdr *hdr; | 2124 | /* give the regulatory workqueue a chance to run */ |
2125 | schedule_timeout_interruptible(1); | ||
2126 | } | ||
1815 | 2127 | ||
1816 | if (!vp->assoc) | 2128 | err = ieee80211_register_hw(hw); |
1817 | return; | 2129 | if (err < 0) { |
2130 | printk(KERN_DEBUG "mac80211_hwsim: ieee80211_register_hw failed (%d)\n", | ||
2131 | err); | ||
2132 | goto failed_hw; | ||
2133 | } | ||
1818 | 2134 | ||
1819 | wiphy_debug(data->hw->wiphy, | 2135 | wiphy_debug(hw->wiphy, "hwaddr %pM registered\n", hw->wiphy->perm_addr); |
1820 | "%s: send data::nullfunc to %pM ps=%d\n", | ||
1821 | __func__, vp->bssid, ps); | ||
1822 | 2136 | ||
1823 | skb = dev_alloc_skb(sizeof(*hdr)); | 2137 | if (reg_alpha2) |
1824 | if (!skb) | 2138 | regulatory_hint(hw->wiphy, reg_alpha2); |
1825 | return; | ||
1826 | hdr = (void *) skb_put(skb, sizeof(*hdr) - ETH_ALEN); | ||
1827 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | | ||
1828 | IEEE80211_STYPE_NULLFUNC | | ||
1829 | (ps ? IEEE80211_FCTL_PM : 0)); | ||
1830 | hdr->duration_id = cpu_to_le16(0); | ||
1831 | memcpy(hdr->addr1, vp->bssid, ETH_ALEN); | ||
1832 | memcpy(hdr->addr2, mac, ETH_ALEN); | ||
1833 | memcpy(hdr->addr3, vp->bssid, ETH_ALEN); | ||
1834 | 2139 | ||
1835 | rcu_read_lock(); | 2140 | data->debugfs = debugfs_create_dir("hwsim", hw->wiphy->debugfsdir); |
1836 | mac80211_hwsim_tx_frame(data->hw, skb, | 2141 | debugfs_create_file("ps", 0666, data->debugfs, data, &hwsim_fops_ps); |
1837 | rcu_dereference(vif->chanctx_conf)->def.chan); | 2142 | debugfs_create_file("group", 0666, data->debugfs, data, |
1838 | rcu_read_unlock(); | 2143 | &hwsim_fops_group); |
1839 | } | 2144 | if (data->channels == 1) |
2145 | debugfs_create_file("dfs_simulate_radar", 0222, | ||
2146 | data->debugfs, | ||
2147 | data, &hwsim_simulate_radar); | ||
1840 | 2148 | ||
2149 | tasklet_hrtimer_init(&data->beacon_timer, | ||
2150 | mac80211_hwsim_beacon, | ||
2151 | CLOCK_MONOTONIC_RAW, HRTIMER_MODE_ABS); | ||
1841 | 2152 | ||
1842 | static void hwsim_send_nullfunc_ps(void *dat, u8 *mac, | 2153 | spin_lock_bh(&hwsim_radio_lock); |
1843 | struct ieee80211_vif *vif) | 2154 | list_add_tail(&data->list, &hwsim_radios); |
1844 | { | 2155 | spin_unlock_bh(&hwsim_radio_lock); |
1845 | struct mac80211_hwsim_data *data = dat; | ||
1846 | hwsim_send_nullfunc(data, mac, vif, 1); | ||
1847 | } | ||
1848 | 2156 | ||
2157 | return idx; | ||
1849 | 2158 | ||
1850 | static void hwsim_send_nullfunc_no_ps(void *dat, u8 *mac, | 2159 | failed_hw: |
1851 | struct ieee80211_vif *vif) | 2160 | device_unregister(data->dev); |
1852 | { | 2161 | failed_drvdata: |
1853 | struct mac80211_hwsim_data *data = dat; | 2162 | ieee80211_free_hw(hw); |
1854 | hwsim_send_nullfunc(data, mac, vif, 0); | 2163 | failed: |
2164 | return err; | ||
1855 | } | 2165 | } |
1856 | 2166 | ||
1857 | 2167 | static void mac80211_hwsim_destroy_radio(struct mac80211_hwsim_data *data) | |
1858 | static int hwsim_fops_ps_read(void *dat, u64 *val) | ||
1859 | { | 2168 | { |
1860 | struct mac80211_hwsim_data *data = dat; | 2169 | debugfs_remove_recursive(data->debugfs); |
1861 | *val = data->ps; | 2170 | ieee80211_unregister_hw(data->hw); |
1862 | return 0; | 2171 | device_release_driver(data->dev); |
2172 | device_unregister(data->dev); | ||
2173 | ieee80211_free_hw(data->hw); | ||
1863 | } | 2174 | } |
1864 | 2175 | ||
1865 | static int hwsim_fops_ps_write(void *dat, u64 val) | 2176 | static void mac80211_hwsim_free(void) |
1866 | { | 2177 | { |
1867 | struct mac80211_hwsim_data *data = dat; | 2178 | struct mac80211_hwsim_data *data; |
1868 | enum ps_mode old_ps; | ||
1869 | |||
1870 | if (val != PS_DISABLED && val != PS_ENABLED && val != PS_AUTO_POLL && | ||
1871 | val != PS_MANUAL_POLL) | ||
1872 | return -EINVAL; | ||
1873 | |||
1874 | old_ps = data->ps; | ||
1875 | data->ps = val; | ||
1876 | 2179 | ||
1877 | if (val == PS_MANUAL_POLL) { | 2180 | spin_lock_bh(&hwsim_radio_lock); |
1878 | ieee80211_iterate_active_interfaces(data->hw, | 2181 | while ((data = list_first_entry_or_null(&hwsim_radios, |
1879 | IEEE80211_IFACE_ITER_NORMAL, | 2182 | struct mac80211_hwsim_data, |
1880 | hwsim_send_ps_poll, data); | 2183 | list))) { |
1881 | data->ps_poll_pending = true; | 2184 | list_del(&data->list); |
1882 | } else if (old_ps == PS_DISABLED && val != PS_DISABLED) { | 2185 | spin_unlock_bh(&hwsim_radio_lock); |
1883 | ieee80211_iterate_active_interfaces(data->hw, | 2186 | mac80211_hwsim_destroy_radio(data); |
1884 | IEEE80211_IFACE_ITER_NORMAL, | 2187 | spin_lock_bh(&hwsim_radio_lock); |
1885 | hwsim_send_nullfunc_ps, | ||
1886 | data); | ||
1887 | } else if (old_ps != PS_DISABLED && val == PS_DISABLED) { | ||
1888 | ieee80211_iterate_active_interfaces(data->hw, | ||
1889 | IEEE80211_IFACE_ITER_NORMAL, | ||
1890 | hwsim_send_nullfunc_no_ps, | ||
1891 | data); | ||
1892 | } | 2188 | } |
1893 | 2189 | spin_unlock_bh(&hwsim_radio_lock); | |
1894 | return 0; | 2190 | class_destroy(hwsim_class); |
1895 | } | ||
1896 | |||
1897 | DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_ps, hwsim_fops_ps_read, hwsim_fops_ps_write, | ||
1898 | "%llu\n"); | ||
1899 | |||
1900 | static int hwsim_write_simulate_radar(void *dat, u64 val) | ||
1901 | { | ||
1902 | struct mac80211_hwsim_data *data = dat; | ||
1903 | |||
1904 | ieee80211_radar_detected(data->hw); | ||
1905 | |||
1906 | return 0; | ||
1907 | } | 2191 | } |
1908 | 2192 | ||
1909 | DEFINE_SIMPLE_ATTRIBUTE(hwsim_simulate_radar, NULL, | 2193 | static const struct net_device_ops hwsim_netdev_ops = { |
1910 | hwsim_write_simulate_radar, "%llu\n"); | 2194 | .ndo_start_xmit = hwsim_mon_xmit, |
1911 | 2195 | .ndo_change_mtu = eth_change_mtu, | |
1912 | static int hwsim_fops_group_read(void *dat, u64 *val) | 2196 | .ndo_set_mac_address = eth_mac_addr, |
1913 | { | 2197 | .ndo_validate_addr = eth_validate_addr, |
1914 | struct mac80211_hwsim_data *data = dat; | 2198 | }; |
1915 | *val = data->group; | ||
1916 | return 0; | ||
1917 | } | ||
1918 | 2199 | ||
1919 | static int hwsim_fops_group_write(void *dat, u64 val) | 2200 | static void hwsim_mon_setup(struct net_device *dev) |
1920 | { | 2201 | { |
1921 | struct mac80211_hwsim_data *data = dat; | 2202 | dev->netdev_ops = &hwsim_netdev_ops; |
1922 | data->group = val; | 2203 | dev->destructor = free_netdev; |
1923 | return 0; | 2204 | ether_setup(dev); |
2205 | dev->tx_queue_len = 0; | ||
2206 | dev->type = ARPHRD_IEEE80211_RADIOTAP; | ||
2207 | memset(dev->dev_addr, 0, ETH_ALEN); | ||
2208 | dev->dev_addr[0] = 0x12; | ||
1924 | } | 2209 | } |
1925 | 2210 | ||
1926 | DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_group, | 2211 | static struct mac80211_hwsim_data *get_hwsim_data_ref_from_addr(const u8 *addr) |
1927 | hwsim_fops_group_read, hwsim_fops_group_write, | ||
1928 | "%llx\n"); | ||
1929 | |||
1930 | static struct mac80211_hwsim_data *get_hwsim_data_ref_from_addr( | ||
1931 | struct mac_address *addr) | ||
1932 | { | 2212 | { |
1933 | struct mac80211_hwsim_data *data; | 2213 | struct mac80211_hwsim_data *data; |
1934 | bool _found = false; | 2214 | bool _found = false; |
1935 | 2215 | ||
1936 | spin_lock_bh(&hwsim_radio_lock); | 2216 | spin_lock_bh(&hwsim_radio_lock); |
1937 | list_for_each_entry(data, &hwsim_radios, list) { | 2217 | list_for_each_entry(data, &hwsim_radios, list) { |
1938 | if (memcmp(data->addresses[1].addr, addr, | 2218 | if (memcmp(data->addresses[1].addr, addr, ETH_ALEN) == 0) { |
1939 | sizeof(struct mac_address)) == 0) { | ||
1940 | _found = true; | 2219 | _found = true; |
1941 | break; | 2220 | break; |
1942 | } | 2221 | } |
@@ -1959,27 +2238,26 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2, | |||
1959 | struct hwsim_tx_rate *tx_attempts; | 2238 | struct hwsim_tx_rate *tx_attempts; |
1960 | unsigned long ret_skb_ptr; | 2239 | unsigned long ret_skb_ptr; |
1961 | struct sk_buff *skb, *tmp; | 2240 | struct sk_buff *skb, *tmp; |
1962 | struct mac_address *src; | 2241 | const u8 *src; |
1963 | unsigned int hwsim_flags; | 2242 | unsigned int hwsim_flags; |
1964 | |||
1965 | int i; | 2243 | int i; |
1966 | bool found = false; | 2244 | bool found = false; |
1967 | 2245 | ||
2246 | if (info->snd_portid != wmediumd_portid) | ||
2247 | return -EINVAL; | ||
2248 | |||
1968 | if (!info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER] || | 2249 | if (!info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER] || |
1969 | !info->attrs[HWSIM_ATTR_FLAGS] || | 2250 | !info->attrs[HWSIM_ATTR_FLAGS] || |
1970 | !info->attrs[HWSIM_ATTR_COOKIE] || | 2251 | !info->attrs[HWSIM_ATTR_COOKIE] || |
1971 | !info->attrs[HWSIM_ATTR_TX_INFO]) | 2252 | !info->attrs[HWSIM_ATTR_TX_INFO]) |
1972 | goto out; | 2253 | goto out; |
1973 | 2254 | ||
1974 | src = (struct mac_address *)nla_data( | 2255 | src = (void *)nla_data(info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER]); |
1975 | info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER]); | ||
1976 | hwsim_flags = nla_get_u32(info->attrs[HWSIM_ATTR_FLAGS]); | 2256 | hwsim_flags = nla_get_u32(info->attrs[HWSIM_ATTR_FLAGS]); |
1977 | |||
1978 | ret_skb_ptr = nla_get_u64(info->attrs[HWSIM_ATTR_COOKIE]); | 2257 | ret_skb_ptr = nla_get_u64(info->attrs[HWSIM_ATTR_COOKIE]); |
1979 | 2258 | ||
1980 | data2 = get_hwsim_data_ref_from_addr(src); | 2259 | data2 = get_hwsim_data_ref_from_addr(src); |
1981 | 2260 | if (!data2) | |
1982 | if (data2 == NULL) | ||
1983 | goto out; | 2261 | goto out; |
1984 | 2262 | ||
1985 | /* look for the skb matching the cookie passed back from user */ | 2263 | /* look for the skb matching the cookie passed back from user */ |
@@ -2036,38 +2314,37 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, | |||
2036 | 2314 | ||
2037 | struct mac80211_hwsim_data *data2; | 2315 | struct mac80211_hwsim_data *data2; |
2038 | struct ieee80211_rx_status rx_status; | 2316 | struct ieee80211_rx_status rx_status; |
2039 | struct mac_address *dst; | 2317 | const u8 *dst; |
2040 | int frame_data_len; | 2318 | int frame_data_len; |
2041 | char *frame_data; | 2319 | void *frame_data; |
2042 | struct sk_buff *skb = NULL; | 2320 | struct sk_buff *skb = NULL; |
2043 | 2321 | ||
2322 | if (info->snd_portid != wmediumd_portid) | ||
2323 | return -EINVAL; | ||
2324 | |||
2044 | if (!info->attrs[HWSIM_ATTR_ADDR_RECEIVER] || | 2325 | if (!info->attrs[HWSIM_ATTR_ADDR_RECEIVER] || |
2045 | !info->attrs[HWSIM_ATTR_FRAME] || | 2326 | !info->attrs[HWSIM_ATTR_FRAME] || |
2046 | !info->attrs[HWSIM_ATTR_RX_RATE] || | 2327 | !info->attrs[HWSIM_ATTR_RX_RATE] || |
2047 | !info->attrs[HWSIM_ATTR_SIGNAL]) | 2328 | !info->attrs[HWSIM_ATTR_SIGNAL]) |
2048 | goto out; | 2329 | goto out; |
2049 | 2330 | ||
2050 | dst = (struct mac_address *)nla_data( | 2331 | dst = (void *)nla_data(info->attrs[HWSIM_ATTR_ADDR_RECEIVER]); |
2051 | info->attrs[HWSIM_ATTR_ADDR_RECEIVER]); | ||
2052 | |||
2053 | frame_data_len = nla_len(info->attrs[HWSIM_ATTR_FRAME]); | 2332 | frame_data_len = nla_len(info->attrs[HWSIM_ATTR_FRAME]); |
2054 | frame_data = (char *)nla_data(info->attrs[HWSIM_ATTR_FRAME]); | 2333 | frame_data = (void *)nla_data(info->attrs[HWSIM_ATTR_FRAME]); |
2055 | 2334 | ||
2056 | /* Allocate new skb here */ | 2335 | /* Allocate new skb here */ |
2057 | skb = alloc_skb(frame_data_len, GFP_KERNEL); | 2336 | skb = alloc_skb(frame_data_len, GFP_KERNEL); |
2058 | if (skb == NULL) | 2337 | if (skb == NULL) |
2059 | goto err; | 2338 | goto err; |
2060 | 2339 | ||
2061 | if (frame_data_len <= IEEE80211_MAX_DATA_LEN) { | 2340 | if (frame_data_len > IEEE80211_MAX_DATA_LEN) |
2062 | /* Copy the data */ | ||
2063 | memcpy(skb_put(skb, frame_data_len), frame_data, | ||
2064 | frame_data_len); | ||
2065 | } else | ||
2066 | goto err; | 2341 | goto err; |
2067 | 2342 | ||
2068 | data2 = get_hwsim_data_ref_from_addr(dst); | 2343 | /* Copy the data */ |
2344 | memcpy(skb_put(skb, frame_data_len), frame_data, frame_data_len); | ||
2069 | 2345 | ||
2070 | if (data2 == NULL) | 2346 | data2 = get_hwsim_data_ref_from_addr(dst); |
2347 | if (!data2) | ||
2071 | goto out; | 2348 | goto out; |
2072 | 2349 | ||
2073 | /* check if radio is configured properly */ | 2350 | /* check if radio is configured properly */ |
@@ -2075,7 +2352,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, | |||
2075 | if (data2->idle || !data2->started) | 2352 | if (data2->idle || !data2->started) |
2076 | goto out; | 2353 | goto out; |
2077 | 2354 | ||
2078 | /*A frame is received from user space*/ | 2355 | /* A frame is received from user space */ |
2079 | memset(&rx_status, 0, sizeof(rx_status)); | 2356 | memset(&rx_status, 0, sizeof(rx_status)); |
2080 | rx_status.freq = data2->channel->center_freq; | 2357 | rx_status.freq = data2->channel->center_freq; |
2081 | rx_status.band = data2->channel->band; | 2358 | rx_status.band = data2->channel->band; |
@@ -2097,8 +2374,24 @@ out: | |||
2097 | static int hwsim_register_received_nl(struct sk_buff *skb_2, | 2374 | static int hwsim_register_received_nl(struct sk_buff *skb_2, |
2098 | struct genl_info *info) | 2375 | struct genl_info *info) |
2099 | { | 2376 | { |
2100 | if (info == NULL) | 2377 | struct mac80211_hwsim_data *data; |
2101 | goto out; | 2378 | int chans = 1; |
2379 | |||
2380 | spin_lock_bh(&hwsim_radio_lock); | ||
2381 | list_for_each_entry(data, &hwsim_radios, list) | ||
2382 | chans = max(chans, data->channels); | ||
2383 | spin_unlock_bh(&hwsim_radio_lock); | ||
2384 | |||
2385 | /* In the future we should revise the userspace API and allow it | ||
2386 | * to set a flag that it does support multi-channel, then we can | ||
2387 | * let this pass conditionally on the flag. | ||
2388 | * For current userspace, prohibit it since it won't work right. | ||
2389 | */ | ||
2390 | if (chans > 1) | ||
2391 | return -EOPNOTSUPP; | ||
2392 | |||
2393 | if (wmediumd_portid) | ||
2394 | return -EBUSY; | ||
2102 | 2395 | ||
2103 | wmediumd_portid = info->snd_portid; | 2396 | wmediumd_portid = info->snd_portid; |
2104 | 2397 | ||
@@ -2106,9 +2399,53 @@ static int hwsim_register_received_nl(struct sk_buff *skb_2, | |||
2106 | "switching to wmediumd mode with pid %d\n", info->snd_portid); | 2399 | "switching to wmediumd mode with pid %d\n", info->snd_portid); |
2107 | 2400 | ||
2108 | return 0; | 2401 | return 0; |
2109 | out: | 2402 | } |
2110 | printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__); | 2403 | |
2111 | return -EINVAL; | 2404 | static int hwsim_create_radio_nl(struct sk_buff *msg, struct genl_info *info) |
2405 | { | ||
2406 | unsigned int chans = channels; | ||
2407 | const char *alpha2 = NULL; | ||
2408 | const struct ieee80211_regdomain *regd = NULL; | ||
2409 | bool reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG]; | ||
2410 | |||
2411 | if (info->attrs[HWSIM_ATTR_CHANNELS]) | ||
2412 | chans = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]); | ||
2413 | |||
2414 | if (info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]) | ||
2415 | alpha2 = nla_data(info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]); | ||
2416 | |||
2417 | if (info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]) { | ||
2418 | u32 idx = nla_get_u32(info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]); | ||
2419 | |||
2420 | if (idx >= ARRAY_SIZE(hwsim_world_regdom_custom)) | ||
2421 | return -EINVAL; | ||
2422 | regd = hwsim_world_regdom_custom[idx]; | ||
2423 | } | ||
2424 | |||
2425 | return mac80211_hwsim_create_radio(chans, alpha2, regd, reg_strict); | ||
2426 | } | ||
2427 | |||
2428 | static int hwsim_destroy_radio_nl(struct sk_buff *msg, struct genl_info *info) | ||
2429 | { | ||
2430 | struct mac80211_hwsim_data *data; | ||
2431 | int idx; | ||
2432 | |||
2433 | if (!info->attrs[HWSIM_ATTR_RADIO_ID]) | ||
2434 | return -EINVAL; | ||
2435 | idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]); | ||
2436 | |||
2437 | spin_lock_bh(&hwsim_radio_lock); | ||
2438 | list_for_each_entry(data, &hwsim_radios, list) { | ||
2439 | if (data->idx != idx) | ||
2440 | continue; | ||
2441 | list_del(&data->list); | ||
2442 | spin_unlock_bh(&hwsim_radio_lock); | ||
2443 | mac80211_hwsim_destroy_radio(data); | ||
2444 | return 0; | ||
2445 | } | ||
2446 | spin_unlock_bh(&hwsim_radio_lock); | ||
2447 | |||
2448 | return -ENODEV; | ||
2112 | } | 2449 | } |
2113 | 2450 | ||
2114 | /* Generic Netlink operations array */ | 2451 | /* Generic Netlink operations array */ |
@@ -2129,6 +2466,18 @@ static const struct genl_ops hwsim_ops[] = { | |||
2129 | .policy = hwsim_genl_policy, | 2466 | .policy = hwsim_genl_policy, |
2130 | .doit = hwsim_tx_info_frame_received_nl, | 2467 | .doit = hwsim_tx_info_frame_received_nl, |
2131 | }, | 2468 | }, |
2469 | { | ||
2470 | .cmd = HWSIM_CMD_CREATE_RADIO, | ||
2471 | .policy = hwsim_genl_policy, | ||
2472 | .doit = hwsim_create_radio_nl, | ||
2473 | .flags = GENL_ADMIN_PERM, | ||
2474 | }, | ||
2475 | { | ||
2476 | .cmd = HWSIM_CMD_DESTROY_RADIO, | ||
2477 | .policy = hwsim_genl_policy, | ||
2478 | .doit = hwsim_destroy_radio_nl, | ||
2479 | .flags = GENL_ADMIN_PERM, | ||
2480 | }, | ||
2132 | }; | 2481 | }; |
2133 | 2482 | ||
2134 | static int mac80211_hwsim_netlink_notify(struct notifier_block *nb, | 2483 | static int mac80211_hwsim_netlink_notify(struct notifier_block *nb, |
@@ -2157,10 +2506,6 @@ static int hwsim_init_netlink(void) | |||
2157 | { | 2506 | { |
2158 | int rc; | 2507 | int rc; |
2159 | 2508 | ||
2160 | /* userspace test API hasn't been adjusted for multi-channel */ | ||
2161 | if (channels > 1) | ||
2162 | return 0; | ||
2163 | |||
2164 | printk(KERN_INFO "mac80211_hwsim: initializing netlink\n"); | 2509 | printk(KERN_INFO "mac80211_hwsim: initializing netlink\n"); |
2165 | 2510 | ||
2166 | rc = genl_register_family_with_ops(&hwsim_genl_family, hwsim_ops); | 2511 | rc = genl_register_family_with_ops(&hwsim_genl_family, hwsim_ops); |
@@ -2180,94 +2525,36 @@ failure: | |||
2180 | 2525 | ||
2181 | static void hwsim_exit_netlink(void) | 2526 | static void hwsim_exit_netlink(void) |
2182 | { | 2527 | { |
2183 | int ret; | ||
2184 | |||
2185 | /* userspace test API hasn't been adjusted for multi-channel */ | ||
2186 | if (channels > 1) | ||
2187 | return; | ||
2188 | |||
2189 | printk(KERN_INFO "mac80211_hwsim: closing netlink\n"); | ||
2190 | /* unregister the notifier */ | 2528 | /* unregister the notifier */ |
2191 | netlink_unregister_notifier(&hwsim_netlink_notifier); | 2529 | netlink_unregister_notifier(&hwsim_netlink_notifier); |
2192 | /* unregister the family */ | 2530 | /* unregister the family */ |
2193 | ret = genl_unregister_family(&hwsim_genl_family); | 2531 | genl_unregister_family(&hwsim_genl_family); |
2194 | if (ret) | ||
2195 | printk(KERN_DEBUG "mac80211_hwsim: " | ||
2196 | "unregister family %i\n", ret); | ||
2197 | } | 2532 | } |
2198 | 2533 | ||
2199 | static const struct ieee80211_iface_limit hwsim_if_limits[] = { | ||
2200 | { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) }, | ||
2201 | { .max = 2048, .types = BIT(NL80211_IFTYPE_STATION) | | ||
2202 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
2203 | #ifdef CONFIG_MAC80211_MESH | ||
2204 | BIT(NL80211_IFTYPE_MESH_POINT) | | ||
2205 | #endif | ||
2206 | BIT(NL80211_IFTYPE_AP) | | ||
2207 | BIT(NL80211_IFTYPE_P2P_GO) }, | ||
2208 | { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) }, | ||
2209 | }; | ||
2210 | |||
2211 | static const struct ieee80211_iface_limit hwsim_if_dfs_limits[] = { | ||
2212 | { .max = 8, .types = BIT(NL80211_IFTYPE_AP) }, | ||
2213 | }; | ||
2214 | |||
2215 | static struct ieee80211_iface_combination hwsim_if_comb[] = { | ||
2216 | { | ||
2217 | .limits = hwsim_if_limits, | ||
2218 | .n_limits = ARRAY_SIZE(hwsim_if_limits), | ||
2219 | .max_interfaces = 2048, | ||
2220 | .num_different_channels = 1, | ||
2221 | }, | ||
2222 | { | ||
2223 | .limits = hwsim_if_dfs_limits, | ||
2224 | .n_limits = ARRAY_SIZE(hwsim_if_dfs_limits), | ||
2225 | .max_interfaces = 8, | ||
2226 | .num_different_channels = 1, | ||
2227 | .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | | ||
2228 | BIT(NL80211_CHAN_WIDTH_20) | | ||
2229 | BIT(NL80211_CHAN_WIDTH_40) | | ||
2230 | BIT(NL80211_CHAN_WIDTH_80) | | ||
2231 | BIT(NL80211_CHAN_WIDTH_160), | ||
2232 | } | ||
2233 | }; | ||
2234 | |||
2235 | static int __init init_mac80211_hwsim(void) | 2534 | static int __init init_mac80211_hwsim(void) |
2236 | { | 2535 | { |
2237 | int i, err = 0; | 2536 | int i, err; |
2238 | u8 addr[ETH_ALEN]; | ||
2239 | struct mac80211_hwsim_data *data; | ||
2240 | struct ieee80211_hw *hw; | ||
2241 | enum ieee80211_band band; | ||
2242 | 2537 | ||
2243 | if (radios < 1 || radios > 100) | 2538 | if (radios < 0 || radios > 100) |
2244 | return -EINVAL; | 2539 | return -EINVAL; |
2245 | 2540 | ||
2246 | if (channels < 1) | 2541 | if (channels < 1) |
2247 | return -EINVAL; | 2542 | return -EINVAL; |
2248 | 2543 | ||
2249 | if (channels > 1) { | 2544 | mac80211_hwsim_mchan_ops = mac80211_hwsim_ops; |
2250 | hwsim_if_comb[0].num_different_channels = channels; | 2545 | mac80211_hwsim_mchan_ops.hw_scan = mac80211_hwsim_hw_scan; |
2251 | mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan; | 2546 | mac80211_hwsim_mchan_ops.cancel_hw_scan = mac80211_hwsim_cancel_hw_scan; |
2252 | mac80211_hwsim_ops.cancel_hw_scan = | 2547 | mac80211_hwsim_mchan_ops.sw_scan_start = NULL; |
2253 | mac80211_hwsim_cancel_hw_scan; | 2548 | mac80211_hwsim_mchan_ops.sw_scan_complete = NULL; |
2254 | mac80211_hwsim_ops.sw_scan_start = NULL; | 2549 | mac80211_hwsim_mchan_ops.remain_on_channel = mac80211_hwsim_roc; |
2255 | mac80211_hwsim_ops.sw_scan_complete = NULL; | 2550 | mac80211_hwsim_mchan_ops.cancel_remain_on_channel = mac80211_hwsim_croc; |
2256 | mac80211_hwsim_ops.remain_on_channel = | 2551 | mac80211_hwsim_mchan_ops.add_chanctx = mac80211_hwsim_add_chanctx; |
2257 | mac80211_hwsim_roc; | 2552 | mac80211_hwsim_mchan_ops.remove_chanctx = mac80211_hwsim_remove_chanctx; |
2258 | mac80211_hwsim_ops.cancel_remain_on_channel = | 2553 | mac80211_hwsim_mchan_ops.change_chanctx = mac80211_hwsim_change_chanctx; |
2259 | mac80211_hwsim_croc; | 2554 | mac80211_hwsim_mchan_ops.assign_vif_chanctx = |
2260 | mac80211_hwsim_ops.add_chanctx = | 2555 | mac80211_hwsim_assign_vif_chanctx; |
2261 | mac80211_hwsim_add_chanctx; | 2556 | mac80211_hwsim_mchan_ops.unassign_vif_chanctx = |
2262 | mac80211_hwsim_ops.remove_chanctx = | 2557 | mac80211_hwsim_unassign_vif_chanctx; |
2263 | mac80211_hwsim_remove_chanctx; | ||
2264 | mac80211_hwsim_ops.change_chanctx = | ||
2265 | mac80211_hwsim_change_chanctx; | ||
2266 | mac80211_hwsim_ops.assign_vif_chanctx = | ||
2267 | mac80211_hwsim_assign_vif_chanctx; | ||
2268 | mac80211_hwsim_ops.unassign_vif_chanctx = | ||
2269 | mac80211_hwsim_unassign_vif_chanctx; | ||
2270 | } | ||
2271 | 2558 | ||
2272 | spin_lock_init(&hwsim_radio_lock); | 2559 | spin_lock_init(&hwsim_radio_lock); |
2273 | INIT_LIST_HEAD(&hwsim_radios); | 2560 | INIT_LIST_HEAD(&hwsim_radios); |
@@ -2279,361 +2566,116 @@ static int __init init_mac80211_hwsim(void) | |||
2279 | hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim"); | 2566 | hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim"); |
2280 | if (IS_ERR(hwsim_class)) { | 2567 | if (IS_ERR(hwsim_class)) { |
2281 | err = PTR_ERR(hwsim_class); | 2568 | err = PTR_ERR(hwsim_class); |
2282 | goto failed_unregister_driver; | 2569 | goto out_unregister_driver; |
2283 | } | 2570 | } |
2284 | 2571 | ||
2285 | memset(addr, 0, ETH_ALEN); | ||
2286 | addr[0] = 0x02; | ||
2287 | |||
2288 | for (i = 0; i < radios; i++) { | 2572 | for (i = 0; i < radios; i++) { |
2289 | printk(KERN_DEBUG "mac80211_hwsim: Initializing radio %d\n", | 2573 | const char *reg_alpha2 = NULL; |
2290 | i); | 2574 | const struct ieee80211_regdomain *regd = NULL; |
2291 | hw = ieee80211_alloc_hw(sizeof(*data), &mac80211_hwsim_ops); | 2575 | bool reg_strict = false; |
2292 | if (!hw) { | ||
2293 | printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw " | ||
2294 | "failed\n"); | ||
2295 | err = -ENOMEM; | ||
2296 | goto failed; | ||
2297 | } | ||
2298 | data = hw->priv; | ||
2299 | data->hw = hw; | ||
2300 | |||
2301 | data->dev = device_create(hwsim_class, NULL, 0, hw, | ||
2302 | "hwsim%d", i); | ||
2303 | if (IS_ERR(data->dev)) { | ||
2304 | printk(KERN_DEBUG | ||
2305 | "mac80211_hwsim: device_create failed (%ld)\n", | ||
2306 | PTR_ERR(data->dev)); | ||
2307 | err = -ENOMEM; | ||
2308 | goto failed_drvdata; | ||
2309 | } | ||
2310 | data->dev->driver = &mac80211_hwsim_driver.driver; | ||
2311 | err = device_bind_driver(data->dev); | ||
2312 | if (err != 0) { | ||
2313 | printk(KERN_DEBUG | ||
2314 | "mac80211_hwsim: device_bind_driver failed (%d)\n", | ||
2315 | err); | ||
2316 | goto failed_hw; | ||
2317 | } | ||
2318 | |||
2319 | skb_queue_head_init(&data->pending); | ||
2320 | |||
2321 | SET_IEEE80211_DEV(hw, data->dev); | ||
2322 | addr[3] = i >> 8; | ||
2323 | addr[4] = i; | ||
2324 | memcpy(data->addresses[0].addr, addr, ETH_ALEN); | ||
2325 | memcpy(data->addresses[1].addr, addr, ETH_ALEN); | ||
2326 | data->addresses[1].addr[0] |= 0x40; | ||
2327 | hw->wiphy->n_addresses = 2; | ||
2328 | hw->wiphy->addresses = data->addresses; | ||
2329 | |||
2330 | hw->wiphy->iface_combinations = hwsim_if_comb; | ||
2331 | hw->wiphy->n_iface_combinations = ARRAY_SIZE(hwsim_if_comb); | ||
2332 | |||
2333 | if (channels > 1) { | ||
2334 | hw->wiphy->max_scan_ssids = 255; | ||
2335 | hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; | ||
2336 | hw->wiphy->max_remain_on_channel_duration = 1000; | ||
2337 | /* For channels > 1 DFS is not allowed */ | ||
2338 | hw->wiphy->n_iface_combinations = 1; | ||
2339 | } | ||
2340 | |||
2341 | INIT_DELAYED_WORK(&data->roc_done, hw_roc_done); | ||
2342 | INIT_DELAYED_WORK(&data->hw_scan, hw_scan_work); | ||
2343 | |||
2344 | hw->channel_change_time = 1; | ||
2345 | hw->queues = 5; | ||
2346 | hw->offchannel_tx_hw_queue = 4; | ||
2347 | hw->wiphy->interface_modes = | ||
2348 | BIT(NL80211_IFTYPE_STATION) | | ||
2349 | BIT(NL80211_IFTYPE_AP) | | ||
2350 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
2351 | BIT(NL80211_IFTYPE_P2P_GO) | | ||
2352 | BIT(NL80211_IFTYPE_ADHOC) | | ||
2353 | BIT(NL80211_IFTYPE_MESH_POINT) | | ||
2354 | BIT(NL80211_IFTYPE_P2P_DEVICE); | ||
2355 | |||
2356 | hw->flags = IEEE80211_HW_MFP_CAPABLE | | ||
2357 | IEEE80211_HW_SIGNAL_DBM | | ||
2358 | IEEE80211_HW_SUPPORTS_STATIC_SMPS | | ||
2359 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | ||
2360 | IEEE80211_HW_AMPDU_AGGREGATION | | ||
2361 | IEEE80211_HW_WANT_MONITOR_VIF | | ||
2362 | IEEE80211_HW_QUEUE_CONTROL | | ||
2363 | IEEE80211_HW_SUPPORTS_HT_CCK_RATES; | ||
2364 | if (rctbl) | ||
2365 | hw->flags |= IEEE80211_HW_SUPPORTS_RC_TABLE; | ||
2366 | |||
2367 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | | ||
2368 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | | ||
2369 | WIPHY_FLAG_AP_UAPSD; | ||
2370 | hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; | ||
2371 | |||
2372 | /* ask mac80211 to reserve space for magic */ | ||
2373 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); | ||
2374 | hw->sta_data_size = sizeof(struct hwsim_sta_priv); | ||
2375 | hw->chanctx_data_size = sizeof(struct hwsim_chanctx_priv); | ||
2376 | |||
2377 | memcpy(data->channels_2ghz, hwsim_channels_2ghz, | ||
2378 | sizeof(hwsim_channels_2ghz)); | ||
2379 | memcpy(data->channels_5ghz, hwsim_channels_5ghz, | ||
2380 | sizeof(hwsim_channels_5ghz)); | ||
2381 | memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates)); | ||
2382 | |||
2383 | for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) { | ||
2384 | struct ieee80211_supported_band *sband = &data->bands[band]; | ||
2385 | switch (band) { | ||
2386 | case IEEE80211_BAND_2GHZ: | ||
2387 | sband->channels = data->channels_2ghz; | ||
2388 | sband->n_channels = | ||
2389 | ARRAY_SIZE(hwsim_channels_2ghz); | ||
2390 | sband->bitrates = data->rates; | ||
2391 | sband->n_bitrates = ARRAY_SIZE(hwsim_rates); | ||
2392 | break; | ||
2393 | case IEEE80211_BAND_5GHZ: | ||
2394 | sband->channels = data->channels_5ghz; | ||
2395 | sband->n_channels = | ||
2396 | ARRAY_SIZE(hwsim_channels_5ghz); | ||
2397 | sband->bitrates = data->rates + 4; | ||
2398 | sband->n_bitrates = ARRAY_SIZE(hwsim_rates) - 4; | ||
2399 | break; | ||
2400 | default: | ||
2401 | continue; | ||
2402 | } | ||
2403 | |||
2404 | sband->ht_cap.ht_supported = true; | ||
2405 | sband->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | | ||
2406 | IEEE80211_HT_CAP_GRN_FLD | | ||
2407 | IEEE80211_HT_CAP_SGI_40 | | ||
2408 | IEEE80211_HT_CAP_DSSSCCK40; | ||
2409 | sband->ht_cap.ampdu_factor = 0x3; | ||
2410 | sband->ht_cap.ampdu_density = 0x6; | ||
2411 | memset(&sband->ht_cap.mcs, 0, | ||
2412 | sizeof(sband->ht_cap.mcs)); | ||
2413 | sband->ht_cap.mcs.rx_mask[0] = 0xff; | ||
2414 | sband->ht_cap.mcs.rx_mask[1] = 0xff; | ||
2415 | sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | ||
2416 | |||
2417 | hw->wiphy->bands[band] = sband; | ||
2418 | |||
2419 | sband->vht_cap.vht_supported = true; | ||
2420 | sband->vht_cap.cap = | ||
2421 | IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | | ||
2422 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ | | ||
2423 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | | ||
2424 | IEEE80211_VHT_CAP_RXLDPC | | ||
2425 | IEEE80211_VHT_CAP_SHORT_GI_80 | | ||
2426 | IEEE80211_VHT_CAP_SHORT_GI_160 | | ||
2427 | IEEE80211_VHT_CAP_TXSTBC | | ||
2428 | IEEE80211_VHT_CAP_RXSTBC_1 | | ||
2429 | IEEE80211_VHT_CAP_RXSTBC_2 | | ||
2430 | IEEE80211_VHT_CAP_RXSTBC_3 | | ||
2431 | IEEE80211_VHT_CAP_RXSTBC_4 | | ||
2432 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; | ||
2433 | sband->vht_cap.vht_mcs.rx_mcs_map = | ||
2434 | cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_8 << 0 | | ||
2435 | IEEE80211_VHT_MCS_SUPPORT_0_8 << 2 | | ||
2436 | IEEE80211_VHT_MCS_SUPPORT_0_9 << 4 | | ||
2437 | IEEE80211_VHT_MCS_SUPPORT_0_8 << 6 | | ||
2438 | IEEE80211_VHT_MCS_SUPPORT_0_8 << 8 | | ||
2439 | IEEE80211_VHT_MCS_SUPPORT_0_9 << 10 | | ||
2440 | IEEE80211_VHT_MCS_SUPPORT_0_9 << 12 | | ||
2441 | IEEE80211_VHT_MCS_SUPPORT_0_8 << 14); | ||
2442 | sband->vht_cap.vht_mcs.tx_mcs_map = | ||
2443 | sband->vht_cap.vht_mcs.rx_mcs_map; | ||
2444 | } | ||
2445 | /* By default all radios are belonging to the first group */ | ||
2446 | data->group = 1; | ||
2447 | mutex_init(&data->mutex); | ||
2448 | |||
2449 | /* Enable frame retransmissions for lossy channels */ | ||
2450 | hw->max_rates = 4; | ||
2451 | hw->max_rate_tries = 11; | ||
2452 | 2576 | ||
2453 | /* Work to be done prior to ieee80211_register_hw() */ | ||
2454 | switch (regtest) { | 2577 | switch (regtest) { |
2455 | case HWSIM_REGTEST_DISABLED: | ||
2456 | case HWSIM_REGTEST_DRIVER_REG_FOLLOW: | ||
2457 | case HWSIM_REGTEST_DRIVER_REG_ALL: | ||
2458 | case HWSIM_REGTEST_DIFF_COUNTRY: | 2578 | case HWSIM_REGTEST_DIFF_COUNTRY: |
2459 | /* | 2579 | if (i < ARRAY_SIZE(hwsim_alpha2s)) |
2460 | * Nothing to be done for driver regulatory domain | 2580 | reg_alpha2 = hwsim_alpha2s[i]; |
2461 | * hints prior to ieee80211_register_hw() | ||
2462 | */ | ||
2463 | break; | ||
2464 | case HWSIM_REGTEST_WORLD_ROAM: | ||
2465 | if (i == 0) { | ||
2466 | hw->wiphy->regulatory_flags |= | ||
2467 | REGULATORY_CUSTOM_REG; | ||
2468 | wiphy_apply_custom_regulatory(hw->wiphy, | ||
2469 | &hwsim_world_regdom_custom_01); | ||
2470 | } | ||
2471 | break; | ||
2472 | case HWSIM_REGTEST_CUSTOM_WORLD: | ||
2473 | hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; | ||
2474 | wiphy_apply_custom_regulatory(hw->wiphy, | ||
2475 | &hwsim_world_regdom_custom_01); | ||
2476 | break; | ||
2477 | case HWSIM_REGTEST_CUSTOM_WORLD_2: | ||
2478 | if (i == 0) { | ||
2479 | hw->wiphy->regulatory_flags |= | ||
2480 | REGULATORY_CUSTOM_REG; | ||
2481 | wiphy_apply_custom_regulatory(hw->wiphy, | ||
2482 | &hwsim_world_regdom_custom_01); | ||
2483 | } else if (i == 1) { | ||
2484 | hw->wiphy->regulatory_flags |= | ||
2485 | REGULATORY_CUSTOM_REG; | ||
2486 | wiphy_apply_custom_regulatory(hw->wiphy, | ||
2487 | &hwsim_world_regdom_custom_02); | ||
2488 | } | ||
2489 | break; | ||
2490 | case HWSIM_REGTEST_STRICT_ALL: | ||
2491 | hw->wiphy->regulatory_flags |= REGULATORY_STRICT_REG; | ||
2492 | break; | ||
2493 | case HWSIM_REGTEST_STRICT_FOLLOW: | ||
2494 | case HWSIM_REGTEST_STRICT_AND_DRIVER_REG: | ||
2495 | if (i == 0) | ||
2496 | hw->wiphy->regulatory_flags |= | ||
2497 | REGULATORY_STRICT_REG; | ||
2498 | break; | ||
2499 | case HWSIM_REGTEST_ALL: | ||
2500 | if (i == 0) { | ||
2501 | hw->wiphy->regulatory_flags |= | ||
2502 | REGULATORY_CUSTOM_REG; | ||
2503 | wiphy_apply_custom_regulatory(hw->wiphy, | ||
2504 | &hwsim_world_regdom_custom_01); | ||
2505 | } else if (i == 1) { | ||
2506 | hw->wiphy->regulatory_flags |= | ||
2507 | REGULATORY_CUSTOM_REG; | ||
2508 | wiphy_apply_custom_regulatory(hw->wiphy, | ||
2509 | &hwsim_world_regdom_custom_02); | ||
2510 | } else if (i == 4) | ||
2511 | hw->wiphy->regulatory_flags |= | ||
2512 | REGULATORY_STRICT_REG; | ||
2513 | break; | ||
2514 | default: | ||
2515 | break; | ||
2516 | } | ||
2517 | |||
2518 | /* give the regulatory workqueue a chance to run */ | ||
2519 | if (regtest) | ||
2520 | schedule_timeout_interruptible(1); | ||
2521 | err = ieee80211_register_hw(hw); | ||
2522 | if (err < 0) { | ||
2523 | printk(KERN_DEBUG "mac80211_hwsim: " | ||
2524 | "ieee80211_register_hw failed (%d)\n", err); | ||
2525 | goto failed_hw; | ||
2526 | } | ||
2527 | |||
2528 | /* Work to be done after to ieee80211_register_hw() */ | ||
2529 | switch (regtest) { | ||
2530 | case HWSIM_REGTEST_WORLD_ROAM: | ||
2531 | case HWSIM_REGTEST_DISABLED: | ||
2532 | break; | 2581 | break; |
2533 | case HWSIM_REGTEST_DRIVER_REG_FOLLOW: | 2582 | case HWSIM_REGTEST_DRIVER_REG_FOLLOW: |
2534 | if (!i) | 2583 | if (!i) |
2535 | regulatory_hint(hw->wiphy, hwsim_alpha2s[0]); | 2584 | reg_alpha2 = hwsim_alpha2s[0]; |
2536 | break; | 2585 | break; |
2537 | case HWSIM_REGTEST_DRIVER_REG_ALL: | ||
2538 | case HWSIM_REGTEST_STRICT_ALL: | 2586 | case HWSIM_REGTEST_STRICT_ALL: |
2539 | regulatory_hint(hw->wiphy, hwsim_alpha2s[0]); | 2587 | reg_strict = true; |
2588 | case HWSIM_REGTEST_DRIVER_REG_ALL: | ||
2589 | reg_alpha2 = hwsim_alpha2s[0]; | ||
2540 | break; | 2590 | break; |
2541 | case HWSIM_REGTEST_DIFF_COUNTRY: | 2591 | case HWSIM_REGTEST_WORLD_ROAM: |
2542 | if (i < ARRAY_SIZE(hwsim_alpha2s)) | 2592 | if (i == 0) |
2543 | regulatory_hint(hw->wiphy, hwsim_alpha2s[i]); | 2593 | regd = &hwsim_world_regdom_custom_01; |
2544 | break; | 2594 | break; |
2545 | case HWSIM_REGTEST_CUSTOM_WORLD: | 2595 | case HWSIM_REGTEST_CUSTOM_WORLD: |
2596 | regd = &hwsim_world_regdom_custom_01; | ||
2597 | break; | ||
2546 | case HWSIM_REGTEST_CUSTOM_WORLD_2: | 2598 | case HWSIM_REGTEST_CUSTOM_WORLD_2: |
2547 | /* | 2599 | if (i == 0) |
2548 | * Nothing to be done for custom world regulatory | 2600 | regd = &hwsim_world_regdom_custom_01; |
2549 | * domains after to ieee80211_register_hw | 2601 | else if (i == 1) |
2550 | */ | 2602 | regd = &hwsim_world_regdom_custom_02; |
2551 | break; | 2603 | break; |
2552 | case HWSIM_REGTEST_STRICT_FOLLOW: | 2604 | case HWSIM_REGTEST_STRICT_FOLLOW: |
2553 | if (i == 0) | 2605 | if (i == 0) { |
2554 | regulatory_hint(hw->wiphy, hwsim_alpha2s[0]); | 2606 | reg_strict = true; |
2607 | reg_alpha2 = hwsim_alpha2s[0]; | ||
2608 | } | ||
2555 | break; | 2609 | break; |
2556 | case HWSIM_REGTEST_STRICT_AND_DRIVER_REG: | 2610 | case HWSIM_REGTEST_STRICT_AND_DRIVER_REG: |
2557 | if (i == 0) | 2611 | if (i == 0) { |
2558 | regulatory_hint(hw->wiphy, hwsim_alpha2s[0]); | 2612 | reg_strict = true; |
2559 | else if (i == 1) | 2613 | reg_alpha2 = hwsim_alpha2s[0]; |
2560 | regulatory_hint(hw->wiphy, hwsim_alpha2s[1]); | 2614 | } else if (i == 1) { |
2615 | reg_alpha2 = hwsim_alpha2s[1]; | ||
2616 | } | ||
2561 | break; | 2617 | break; |
2562 | case HWSIM_REGTEST_ALL: | 2618 | case HWSIM_REGTEST_ALL: |
2563 | if (i == 2) | 2619 | switch (i) { |
2564 | regulatory_hint(hw->wiphy, hwsim_alpha2s[0]); | 2620 | case 0: |
2565 | else if (i == 3) | 2621 | regd = &hwsim_world_regdom_custom_01; |
2566 | regulatory_hint(hw->wiphy, hwsim_alpha2s[1]); | 2622 | break; |
2567 | else if (i == 4) | 2623 | case 1: |
2568 | regulatory_hint(hw->wiphy, hwsim_alpha2s[2]); | 2624 | regd = &hwsim_world_regdom_custom_02; |
2625 | break; | ||
2626 | case 2: | ||
2627 | reg_alpha2 = hwsim_alpha2s[0]; | ||
2628 | break; | ||
2629 | case 3: | ||
2630 | reg_alpha2 = hwsim_alpha2s[1]; | ||
2631 | break; | ||
2632 | case 4: | ||
2633 | reg_strict = true; | ||
2634 | reg_alpha2 = hwsim_alpha2s[2]; | ||
2635 | break; | ||
2636 | } | ||
2569 | break; | 2637 | break; |
2570 | default: | 2638 | default: |
2571 | break; | 2639 | break; |
2572 | } | 2640 | } |
2573 | 2641 | ||
2574 | wiphy_debug(hw->wiphy, "hwaddr %pm registered\n", | 2642 | err = mac80211_hwsim_create_radio(channels, reg_alpha2, |
2575 | hw->wiphy->perm_addr); | 2643 | regd, reg_strict); |
2576 | 2644 | if (err < 0) | |
2577 | data->debugfs = debugfs_create_dir("hwsim", | 2645 | goto out_free_radios; |
2578 | hw->wiphy->debugfsdir); | ||
2579 | debugfs_create_file("ps", 0666, data->debugfs, data, | ||
2580 | &hwsim_fops_ps); | ||
2581 | debugfs_create_file("group", 0666, data->debugfs, data, | ||
2582 | &hwsim_fops_group); | ||
2583 | if (channels == 1) | ||
2584 | debugfs_create_file("dfs_simulate_radar", 0222, | ||
2585 | data->debugfs, | ||
2586 | data, &hwsim_simulate_radar); | ||
2587 | |||
2588 | tasklet_hrtimer_init(&data->beacon_timer, | ||
2589 | mac80211_hwsim_beacon, | ||
2590 | CLOCK_MONOTONIC_RAW, HRTIMER_MODE_ABS); | ||
2591 | |||
2592 | list_add_tail(&data->list, &hwsim_radios); | ||
2593 | } | 2646 | } |
2594 | 2647 | ||
2595 | hwsim_mon = alloc_netdev(0, "hwsim%d", hwsim_mon_setup); | 2648 | hwsim_mon = alloc_netdev(0, "hwsim%d", hwsim_mon_setup); |
2596 | if (hwsim_mon == NULL) { | 2649 | if (hwsim_mon == NULL) { |
2597 | err = -ENOMEM; | 2650 | err = -ENOMEM; |
2598 | goto failed; | 2651 | goto out_free_radios; |
2599 | } | 2652 | } |
2600 | 2653 | ||
2601 | rtnl_lock(); | 2654 | rtnl_lock(); |
2602 | |||
2603 | err = dev_alloc_name(hwsim_mon, hwsim_mon->name); | 2655 | err = dev_alloc_name(hwsim_mon, hwsim_mon->name); |
2604 | if (err < 0) | 2656 | if (err < 0) { |
2605 | goto failed_mon; | 2657 | rtnl_unlock(); |
2606 | 2658 | goto out_free_radios; | |
2659 | } | ||
2607 | 2660 | ||
2608 | err = register_netdevice(hwsim_mon); | 2661 | err = register_netdevice(hwsim_mon); |
2609 | if (err < 0) | 2662 | if (err < 0) { |
2610 | goto failed_mon; | 2663 | rtnl_unlock(); |
2611 | 2664 | goto out_free_mon; | |
2665 | } | ||
2612 | rtnl_unlock(); | 2666 | rtnl_unlock(); |
2613 | 2667 | ||
2614 | err = hwsim_init_netlink(); | 2668 | err = hwsim_init_netlink(); |
2615 | if (err < 0) | 2669 | if (err < 0) |
2616 | goto failed_nl; | 2670 | goto out_free_mon; |
2617 | 2671 | ||
2618 | return 0; | 2672 | return 0; |
2619 | 2673 | ||
2620 | failed_nl: | 2674 | out_free_mon: |
2621 | printk(KERN_DEBUG "mac_80211_hwsim: failed initializing netlink\n"); | ||
2622 | return err; | ||
2623 | |||
2624 | failed_mon: | ||
2625 | rtnl_unlock(); | ||
2626 | free_netdev(hwsim_mon); | 2675 | free_netdev(hwsim_mon); |
2676 | out_free_radios: | ||
2627 | mac80211_hwsim_free(); | 2677 | mac80211_hwsim_free(); |
2628 | return err; | 2678 | out_unregister_driver: |
2629 | |||
2630 | failed_hw: | ||
2631 | device_unregister(data->dev); | ||
2632 | failed_drvdata: | ||
2633 | ieee80211_free_hw(hw); | ||
2634 | failed: | ||
2635 | mac80211_hwsim_free(); | ||
2636 | failed_unregister_driver: | ||
2637 | platform_driver_unregister(&mac80211_hwsim_driver); | 2679 | platform_driver_unregister(&mac80211_hwsim_driver); |
2638 | return err; | 2680 | return err; |
2639 | } | 2681 | } |
diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h index afaad5a443b6..2747cce5a269 100644 --- a/drivers/net/wireless/mac80211_hwsim.h +++ b/drivers/net/wireless/mac80211_hwsim.h | |||
@@ -65,6 +65,9 @@ enum hwsim_tx_control_flags { | |||
65 | * kernel, uses: | 65 | * kernel, uses: |
66 | * %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_FLAGS, | 66 | * %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_FLAGS, |
67 | * %HWSIM_ATTR_TX_INFO, %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE | 67 | * %HWSIM_ATTR_TX_INFO, %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE |
68 | * @HWSIM_CMD_CREATE_RADIO: create a new radio with the given parameters, | ||
69 | * returns the radio ID (>= 0) or negative on errors | ||
70 | * @HWSIM_CMD_DESTROY_RADIO: destroy a radio | ||
68 | * @__HWSIM_CMD_MAX: enum limit | 71 | * @__HWSIM_CMD_MAX: enum limit |
69 | */ | 72 | */ |
70 | enum { | 73 | enum { |
@@ -72,6 +75,8 @@ enum { | |||
72 | HWSIM_CMD_REGISTER, | 75 | HWSIM_CMD_REGISTER, |
73 | HWSIM_CMD_FRAME, | 76 | HWSIM_CMD_FRAME, |
74 | HWSIM_CMD_TX_INFO_FRAME, | 77 | HWSIM_CMD_TX_INFO_FRAME, |
78 | HWSIM_CMD_CREATE_RADIO, | ||
79 | HWSIM_CMD_DESTROY_RADIO, | ||
75 | __HWSIM_CMD_MAX, | 80 | __HWSIM_CMD_MAX, |
76 | }; | 81 | }; |
77 | #define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1) | 82 | #define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1) |
@@ -94,6 +99,14 @@ enum { | |||
94 | space | 99 | space |
95 | * @HWSIM_ATTR_TX_INFO: ieee80211_tx_rate array | 100 | * @HWSIM_ATTR_TX_INFO: ieee80211_tx_rate array |
96 | * @HWSIM_ATTR_COOKIE: sk_buff cookie to identify the frame | 101 | * @HWSIM_ATTR_COOKIE: sk_buff cookie to identify the frame |
102 | * @HWSIM_ATTR_CHANNELS: u32 attribute used with the %HWSIM_CMD_CREATE_RADIO | ||
103 | * command giving the number of channels supported by the new radio | ||
104 | * @HWSIM_ATTR_RADIO_ID: u32 attribute used with %HWSIM_CMD_DESTROY_RADIO | ||
105 | * only to destroy a radio | ||
106 | * @HWSIM_ATTR_REG_HINT_ALPHA2: alpha2 for regulatoro driver hint | ||
107 | * (nla string, length 2) | ||
108 | * @HWSIM_ATTR_REG_CUSTOM_REG: custom regulatory domain index (u32 attribute) | ||
109 | * @HWSIM_ATTR_REG_STRICT_REG: request REGULATORY_STRICT_REG (flag attribute) | ||
97 | * @__HWSIM_ATTR_MAX: enum limit | 110 | * @__HWSIM_ATTR_MAX: enum limit |
98 | */ | 111 | */ |
99 | 112 | ||
@@ -108,6 +121,11 @@ enum { | |||
108 | HWSIM_ATTR_SIGNAL, | 121 | HWSIM_ATTR_SIGNAL, |
109 | HWSIM_ATTR_TX_INFO, | 122 | HWSIM_ATTR_TX_INFO, |
110 | HWSIM_ATTR_COOKIE, | 123 | HWSIM_ATTR_COOKIE, |
124 | HWSIM_ATTR_CHANNELS, | ||
125 | HWSIM_ATTR_RADIO_ID, | ||
126 | HWSIM_ATTR_REG_HINT_ALPHA2, | ||
127 | HWSIM_ATTR_REG_CUSTOM_REG, | ||
128 | HWSIM_ATTR_REG_STRICT_REG, | ||
111 | __HWSIM_ATTR_MAX, | 129 | __HWSIM_ATTR_MAX, |
112 | }; | 130 | }; |
113 | #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) | 131 | #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) |
diff --git a/drivers/net/wireless/mwifiex/Kconfig b/drivers/net/wireless/mwifiex/Kconfig index f7ff4725506a..ecdf34505b54 100644 --- a/drivers/net/wireless/mwifiex/Kconfig +++ b/drivers/net/wireless/mwifiex/Kconfig | |||
@@ -31,12 +31,12 @@ config MWIFIEX_PCIE | |||
31 | mwifiex_pcie. | 31 | mwifiex_pcie. |
32 | 32 | ||
33 | config MWIFIEX_USB | 33 | config MWIFIEX_USB |
34 | tristate "Marvell WiFi-Ex Driver for USB8797" | 34 | tristate "Marvell WiFi-Ex Driver for USB8797/8897" |
35 | depends on MWIFIEX && USB | 35 | depends on MWIFIEX && USB |
36 | select FW_LOADER | 36 | select FW_LOADER |
37 | ---help--- | 37 | ---help--- |
38 | This adds support for wireless adapters based on Marvell | 38 | This adds support for wireless adapters based on Marvell |
39 | Avastar 88W8797 chipset with USB interface. | 39 | 8797/8897 chipset with USB interface. |
40 | 40 | ||
41 | If you choose to build it as a module, it will be called | 41 | If you choose to build it as a module, it will be called |
42 | mwifiex_usb. | 42 | mwifiex_usb. |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index e7c81abf108e..f37b403e83d0 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -2677,6 +2677,7 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) | |||
2677 | struct wiphy *wiphy; | 2677 | struct wiphy *wiphy; |
2678 | struct mwifiex_private *priv = adapter->priv[MWIFIEX_BSS_TYPE_STA]; | 2678 | struct mwifiex_private *priv = adapter->priv[MWIFIEX_BSS_TYPE_STA]; |
2679 | u8 *country_code; | 2679 | u8 *country_code; |
2680 | u32 thr, retry; | ||
2680 | 2681 | ||
2681 | /* create a new wiphy for use with cfg80211 */ | 2682 | /* create a new wiphy for use with cfg80211 */ |
2682 | wiphy = wiphy_new(&mwifiex_cfg80211_ops, | 2683 | wiphy = wiphy_new(&mwifiex_cfg80211_ops, |
@@ -2766,6 +2767,19 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) | |||
2766 | country_code); | 2767 | country_code); |
2767 | } | 2768 | } |
2768 | 2769 | ||
2770 | mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, | ||
2771 | HostCmd_ACT_GEN_GET, FRAG_THRESH_I, &thr); | ||
2772 | wiphy->frag_threshold = thr; | ||
2773 | mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, | ||
2774 | HostCmd_ACT_GEN_GET, RTS_THRESH_I, &thr); | ||
2775 | wiphy->rts_threshold = thr; | ||
2776 | mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, | ||
2777 | HostCmd_ACT_GEN_GET, SHORT_RETRY_LIM_I, &retry); | ||
2778 | wiphy->retry_short = (u8) retry; | ||
2779 | mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, | ||
2780 | HostCmd_ACT_GEN_GET, LONG_RETRY_LIM_I, &retry); | ||
2781 | wiphy->retry_long = (u8) retry; | ||
2782 | |||
2769 | adapter->wiphy = wiphy; | 2783 | adapter->wiphy = wiphy; |
2770 | return ret; | 2784 | return ret; |
2771 | } | 2785 | } |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 4cee6ceb7e9e..5fa932d5f905 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -226,7 +226,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
226 | 226 | ||
227 | /* HW_SPEC fw_cap_info */ | 227 | /* HW_SPEC fw_cap_info */ |
228 | 228 | ||
229 | #define ISSUPP_11ACENABLED(fw_cap_info) (fw_cap_info & (BIT(13)|BIT(14))) | 229 | #define ISSUPP_11ACENABLED(fw_cap_info) (fw_cap_info & (BIT(12)|BIT(13))) |
230 | 230 | ||
231 | #define GET_VHTCAP_CHWDSET(vht_cap_info) ((vht_cap_info >> 2) & 0x3) | 231 | #define GET_VHTCAP_CHWDSET(vht_cap_info) ((vht_cap_info >> 2) & 0x3) |
232 | #define GET_VHTNSSMCS(mcs_mapset, nss) ((mcs_mapset >> (2 * (nss - 1))) & 0x3) | 232 | #define GET_VHTNSSMCS(mcs_mapset, nss) ((mcs_mapset >> (2 * (nss - 1))) & 0x3) |
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 0ed06646f19a..0a8a26e10f01 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -1681,7 +1681,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1681 | const u8 *ie_buf; | 1681 | const u8 *ie_buf; |
1682 | size_t ie_len; | 1682 | size_t ie_len; |
1683 | u16 channel = 0; | 1683 | u16 channel = 0; |
1684 | u64 fw_tsf = 0; | 1684 | __le64 fw_tsf = 0; |
1685 | u16 beacon_size = 0; | 1685 | u16 beacon_size = 0; |
1686 | u32 curr_bcn_bytes; | 1686 | u32 curr_bcn_bytes; |
1687 | u32 freq; | 1687 | u32 freq; |
@@ -1815,7 +1815,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1815 | ie_buf, ie_len, rssi, GFP_KERNEL); | 1815 | ie_buf, ie_len, rssi, GFP_KERNEL); |
1816 | bss_priv = (struct mwifiex_bss_priv *)bss->priv; | 1816 | bss_priv = (struct mwifiex_bss_priv *)bss->priv; |
1817 | bss_priv->band = band; | 1817 | bss_priv->band = band; |
1818 | bss_priv->fw_tsf = fw_tsf; | 1818 | bss_priv->fw_tsf = le64_to_cpu(fw_tsf); |
1819 | if (priv->media_connected && | 1819 | if (priv->media_connected && |
1820 | !memcmp(bssid, | 1820 | !memcmp(bssid, |
1821 | priv->curr_bss_params.bss_descriptor | 1821 | priv->curr_bss_params.bss_descriptor |
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index a9240a2083f2..e8ebbd4bc3cd 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c | |||
@@ -22,15 +22,21 @@ | |||
22 | 22 | ||
23 | #define USB_VERSION "1.0" | 23 | #define USB_VERSION "1.0" |
24 | 24 | ||
25 | static const char usbdriver_name[] = "usb8797"; | 25 | static const char usbdriver_name[] = "usb8xxx"; |
26 | 26 | ||
27 | static struct mwifiex_if_ops usb_ops; | 27 | static struct mwifiex_if_ops usb_ops; |
28 | static struct semaphore add_remove_card_sem; | 28 | static struct semaphore add_remove_card_sem; |
29 | static struct usb_card_rec *usb_card; | 29 | static struct usb_card_rec *usb_card; |
30 | 30 | ||
31 | static struct usb_device_id mwifiex_usb_table[] = { | 31 | static struct usb_device_id mwifiex_usb_table[] = { |
32 | {USB_DEVICE(USB8797_VID, USB8797_PID_1)}, | 32 | /* 8797 */ |
33 | {USB_DEVICE_AND_INTERFACE_INFO(USB8797_VID, USB8797_PID_2, | 33 | {USB_DEVICE(USB8XXX_VID, USB8797_PID_1)}, |
34 | {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8797_PID_2, | ||
35 | USB_CLASS_VENDOR_SPEC, | ||
36 | USB_SUBCLASS_VENDOR_SPEC, 0xff)}, | ||
37 | /* 8897 */ | ||
38 | {USB_DEVICE(USB8XXX_VID, USB8897_PID_1)}, | ||
39 | {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8897_PID_2, | ||
34 | USB_CLASS_VENDOR_SPEC, | 40 | USB_CLASS_VENDOR_SPEC, |
35 | USB_SUBCLASS_VENDOR_SPEC, 0xff)}, | 41 | USB_SUBCLASS_VENDOR_SPEC, 0xff)}, |
36 | { } /* Terminating entry */ | 42 | { } /* Terminating entry */ |
@@ -343,10 +349,20 @@ static int mwifiex_usb_probe(struct usb_interface *intf, | |||
343 | id_vendor, id_product, bcd_device); | 349 | id_vendor, id_product, bcd_device); |
344 | 350 | ||
345 | /* PID_1 is used for firmware downloading only */ | 351 | /* PID_1 is used for firmware downloading only */ |
346 | if (id_product == USB8797_PID_1) | 352 | switch (id_product) { |
347 | card->usb_boot_state = USB8797_FW_DNLD; | 353 | case USB8797_PID_1: |
348 | else | 354 | case USB8897_PID_1: |
349 | card->usb_boot_state = USB8797_FW_READY; | 355 | card->usb_boot_state = USB8XXX_FW_DNLD; |
356 | break; | ||
357 | case USB8797_PID_2: | ||
358 | case USB8897_PID_2: | ||
359 | card->usb_boot_state = USB8XXX_FW_READY; | ||
360 | break; | ||
361 | default: | ||
362 | pr_warning("unknown id_product %#x\n", id_product); | ||
363 | card->usb_boot_state = USB8XXX_FW_DNLD; | ||
364 | break; | ||
365 | } | ||
350 | 366 | ||
351 | card->udev = udev; | 367 | card->udev = udev; |
352 | card->intf = intf; | 368 | card->intf = intf; |
@@ -755,9 +771,20 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) | |||
755 | 771 | ||
756 | card->adapter = adapter; | 772 | card->adapter = adapter; |
757 | adapter->dev = &card->udev->dev; | 773 | adapter->dev = &card->udev->dev; |
758 | strcpy(adapter->fw_name, USB8797_DEFAULT_FW_NAME); | ||
759 | usb_card = card; | 774 | usb_card = card; |
760 | 775 | ||
776 | switch (le16_to_cpu(card->udev->descriptor.idProduct)) { | ||
777 | case USB8897_PID_1: | ||
778 | case USB8897_PID_2: | ||
779 | strcpy(adapter->fw_name, USB8897_DEFAULT_FW_NAME); | ||
780 | break; | ||
781 | case USB8797_PID_1: | ||
782 | case USB8797_PID_2: | ||
783 | default: | ||
784 | strcpy(adapter->fw_name, USB8797_DEFAULT_FW_NAME); | ||
785 | break; | ||
786 | } | ||
787 | |||
761 | return 0; | 788 | return 0; |
762 | } | 789 | } |
763 | 790 | ||
@@ -773,7 +800,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, | |||
773 | { | 800 | { |
774 | int ret = 0; | 801 | int ret = 0; |
775 | u8 *firmware = fw->fw_buf, *recv_buff; | 802 | u8 *firmware = fw->fw_buf, *recv_buff; |
776 | u32 retries = USB8797_FW_MAX_RETRY, dlen; | 803 | u32 retries = USB8XXX_FW_MAX_RETRY, dlen; |
777 | u32 fw_seqnum = 0, tlen = 0, dnld_cmd = 0; | 804 | u32 fw_seqnum = 0, tlen = 0, dnld_cmd = 0; |
778 | struct fw_data *fwdata; | 805 | struct fw_data *fwdata; |
779 | struct fw_sync_header sync_fw; | 806 | struct fw_sync_header sync_fw; |
@@ -875,7 +902,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, | |||
875 | continue; | 902 | continue; |
876 | } | 903 | } |
877 | 904 | ||
878 | retries = USB8797_FW_MAX_RETRY; | 905 | retries = USB8XXX_FW_MAX_RETRY; |
879 | break; | 906 | break; |
880 | } | 907 | } |
881 | fw_seqnum++; | 908 | fw_seqnum++; |
@@ -899,13 +926,13 @@ static int mwifiex_usb_dnld_fw(struct mwifiex_adapter *adapter, | |||
899 | int ret; | 926 | int ret; |
900 | struct usb_card_rec *card = (struct usb_card_rec *)adapter->card; | 927 | struct usb_card_rec *card = (struct usb_card_rec *)adapter->card; |
901 | 928 | ||
902 | if (card->usb_boot_state == USB8797_FW_DNLD) { | 929 | if (card->usb_boot_state == USB8XXX_FW_DNLD) { |
903 | ret = mwifiex_prog_fw_w_helper(adapter, fw); | 930 | ret = mwifiex_prog_fw_w_helper(adapter, fw); |
904 | if (ret) | 931 | if (ret) |
905 | return -1; | 932 | return -1; |
906 | 933 | ||
907 | /* Boot state changes after successful firmware download */ | 934 | /* Boot state changes after successful firmware download */ |
908 | if (card->usb_boot_state == USB8797_FW_DNLD) | 935 | if (card->usb_boot_state == USB8XXX_FW_DNLD) |
909 | return -1; | 936 | return -1; |
910 | } | 937 | } |
911 | 938 | ||
@@ -1039,4 +1066,5 @@ MODULE_AUTHOR("Marvell International Ltd."); | |||
1039 | MODULE_DESCRIPTION("Marvell WiFi-Ex USB Driver version" USB_VERSION); | 1066 | MODULE_DESCRIPTION("Marvell WiFi-Ex USB Driver version" USB_VERSION); |
1040 | MODULE_VERSION(USB_VERSION); | 1067 | MODULE_VERSION(USB_VERSION); |
1041 | MODULE_LICENSE("GPL v2"); | 1068 | MODULE_LICENSE("GPL v2"); |
1042 | MODULE_FIRMWARE("mrvl/usb8797_uapsta.bin"); | 1069 | MODULE_FIRMWARE(USB8797_DEFAULT_FW_NAME); |
1070 | MODULE_FIRMWARE(USB8897_DEFAULT_FW_NAME); | ||
diff --git a/drivers/net/wireless/mwifiex/usb.h b/drivers/net/wireless/mwifiex/usb.h index 98c4316cd1a9..15b73d12e998 100644 --- a/drivers/net/wireless/mwifiex/usb.h +++ b/drivers/net/wireless/mwifiex/usb.h | |||
@@ -22,19 +22,23 @@ | |||
22 | 22 | ||
23 | #include <linux/usb.h> | 23 | #include <linux/usb.h> |
24 | 24 | ||
25 | #define USB8797_VID 0x1286 | 25 | #define USB8XXX_VID 0x1286 |
26 | |||
26 | #define USB8797_PID_1 0x2043 | 27 | #define USB8797_PID_1 0x2043 |
27 | #define USB8797_PID_2 0x2044 | 28 | #define USB8797_PID_2 0x2044 |
29 | #define USB8897_PID_1 0x2045 | ||
30 | #define USB8897_PID_2 0x2046 | ||
28 | 31 | ||
29 | #define USB8797_FW_DNLD 1 | 32 | #define USB8XXX_FW_DNLD 1 |
30 | #define USB8797_FW_READY 2 | 33 | #define USB8XXX_FW_READY 2 |
31 | #define USB8797_FW_MAX_RETRY 3 | 34 | #define USB8XXX_FW_MAX_RETRY 3 |
32 | 35 | ||
33 | #define MWIFIEX_TX_DATA_URB 6 | 36 | #define MWIFIEX_TX_DATA_URB 6 |
34 | #define MWIFIEX_RX_DATA_URB 6 | 37 | #define MWIFIEX_RX_DATA_URB 6 |
35 | #define MWIFIEX_USB_TIMEOUT 100 | 38 | #define MWIFIEX_USB_TIMEOUT 100 |
36 | 39 | ||
37 | #define USB8797_DEFAULT_FW_NAME "mrvl/usb8797_uapsta.bin" | 40 | #define USB8797_DEFAULT_FW_NAME "mrvl/usb8797_uapsta.bin" |
41 | #define USB8897_DEFAULT_FW_NAME "mrvl/usb8897_uapsta.bin" | ||
38 | 42 | ||
39 | #define FW_DNLD_TX_BUF_SIZE 620 | 43 | #define FW_DNLD_TX_BUF_SIZE 620 |
40 | #define FW_DNLD_RX_BUF_SIZE 2048 | 44 | #define FW_DNLD_RX_BUF_SIZE 2048 |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 63dbde5c3713..4987c3f942ce 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -5892,8 +5892,6 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv) | |||
5892 | 5892 | ||
5893 | hw->extra_tx_headroom -= priv->ap_fw ? REDUCED_TX_HEADROOM : 0; | 5893 | hw->extra_tx_headroom -= priv->ap_fw ? REDUCED_TX_HEADROOM : 0; |
5894 | 5894 | ||
5895 | hw->channel_change_time = 10; | ||
5896 | |||
5897 | hw->queues = MWL8K_TX_WMM_QUEUES; | 5895 | hw->queues = MWL8K_TX_WMM_QUEUES; |
5898 | 5896 | ||
5899 | /* Set rssi values to dBm */ | 5897 | /* Set rssi values to dBm */ |
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 80d93cba5150..eede90b63f84 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c | |||
@@ -756,7 +756,6 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) | |||
756 | BIT(NL80211_IFTYPE_AP) | | 756 | BIT(NL80211_IFTYPE_AP) | |
757 | BIT(NL80211_IFTYPE_MESH_POINT); | 757 | BIT(NL80211_IFTYPE_MESH_POINT); |
758 | 758 | ||
759 | dev->channel_change_time = 1000; /* TODO: find actual value */ | ||
760 | priv->beacon_req_id = cpu_to_le32(0); | 759 | priv->beacon_req_id = cpu_to_le32(0); |
761 | priv->tx_stats[P54_QUEUE_BEACON].limit = 1; | 760 | priv->tx_stats[P54_QUEUE_BEACON].limit = 1; |
762 | priv->tx_stats[P54_QUEUE_FWSCAN].limit = 1; | 761 | priv->tx_stats[P54_QUEUE_FWSCAN].limit = 1; |
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 9c96831c0b5c..153c61539ec8 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c | |||
@@ -586,7 +586,7 @@ static void p54_rx_stats(struct p54_common *priv, struct sk_buff *skb) | |||
586 | chan = priv->curchan; | 586 | chan = priv->curchan; |
587 | if (chan) { | 587 | if (chan) { |
588 | struct survey_info *survey = &priv->survey[chan->hw_value]; | 588 | struct survey_info *survey = &priv->survey[chan->hw_value]; |
589 | survey->noise = clamp_t(s8, priv->noise, -128, 127); | 589 | survey->noise = clamp(priv->noise, -128, 127); |
590 | survey->channel_time = priv->survey_raw.active; | 590 | survey->channel_time = priv->survey_raw.active; |
591 | survey->channel_time_tx = priv->survey_raw.tx; | 591 | survey->channel_time_tx = priv->survey_raw.tx; |
592 | survey->channel_time_busy = priv->survey_raw.tx + | 592 | survey->channel_time_busy = priv->survey_raw.tx + |
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index d63a12cc5de8..93bb384eb001 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c | |||
@@ -353,7 +353,6 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw) | |||
353 | 353 | ||
354 | /* TODO: Correct this value for our hw */ | 354 | /* TODO: Correct this value for our hw */ |
355 | /* TODO: define these hard code value */ | 355 | /* TODO: define these hard code value */ |
356 | hw->channel_change_time = 100; | ||
357 | hw->max_listen_interval = 10; | 356 | hw->max_listen_interval = 10; |
358 | hw->max_rate_tries = 4; | 357 | hw->max_rate_tries = 4; |
359 | /* hw->max_rates = 1; */ | 358 | /* hw->max_rates = 1; */ |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 8501954cfb44..c61311084d7e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | |||
@@ -317,6 +317,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { | |||
317 | {RTL_USB_DEVICE(0x0bda, 0x5088, rtl92cu_hal_cfg)}, /*Thinkware-CC&C*/ | 317 | {RTL_USB_DEVICE(0x0bda, 0x5088, rtl92cu_hal_cfg)}, /*Thinkware-CC&C*/ |
318 | {RTL_USB_DEVICE(0x0df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ | 318 | {RTL_USB_DEVICE(0x0df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ |
319 | {RTL_USB_DEVICE(0x0df6, 0x005c, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ | 319 | {RTL_USB_DEVICE(0x0df6, 0x005c, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ |
320 | {RTL_USB_DEVICE(0x0df6, 0x0077, rtl92cu_hal_cfg)}, /*Sitecom-WLA2100V2*/ | ||
320 | {RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/ | 321 | {RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/ |
321 | {RTL_USB_DEVICE(0x4856, 0x0091, rtl92cu_hal_cfg)}, /*NetweeN - Feixun*/ | 322 | {RTL_USB_DEVICE(0x4856, 0x0091, rtl92cu_hal_cfg)}, /*NetweeN - Feixun*/ |
322 | /* HP - Lite-On ,8188CUS Slim Combo */ | 323 | /* HP - Lite-On ,8188CUS Slim Combo */ |
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c index 119c148f7740..757e25784a8a 100644 --- a/drivers/net/wireless/ti/wl1251/main.c +++ b/drivers/net/wireless/ti/wl1251/main.c | |||
@@ -1468,7 +1468,6 @@ int wl1251_init_ieee80211(struct wl1251 *wl) | |||
1468 | 1468 | ||
1469 | /* unit us */ | 1469 | /* unit us */ |
1470 | /* FIXME: find a proper value */ | 1470 | /* FIXME: find a proper value */ |
1471 | wl->hw->channel_change_time = 10000; | ||
1472 | 1471 | ||
1473 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | | 1472 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | |
1474 | IEEE80211_HW_SUPPORTS_PS | | 1473 | IEEE80211_HW_SUPPORTS_PS | |
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index e9da47cead58..b46b3116cc55 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -4457,6 +4457,16 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
4457 | if (ret < 0) | 4457 | if (ret < 0) |
4458 | goto out; | 4458 | goto out; |
4459 | 4459 | ||
4460 | if ((changed & BSS_CHANGED_TXPOWER) && | ||
4461 | bss_conf->txpower != wlvif->power_level) { | ||
4462 | |||
4463 | ret = wl1271_acx_tx_power(wl, wlvif, bss_conf->txpower); | ||
4464 | if (ret < 0) | ||
4465 | goto out; | ||
4466 | |||
4467 | wlvif->power_level = bss_conf->txpower; | ||
4468 | } | ||
4469 | |||
4460 | if (is_ap) | 4470 | if (is_ap) |
4461 | wl1271_bss_info_changed_ap(wl, vif, bss_conf, changed); | 4471 | wl1271_bss_info_changed_ap(wl, vif, bss_conf, changed); |
4462 | else | 4472 | else |
@@ -5710,7 +5720,6 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
5710 | 5720 | ||
5711 | /* unit us */ | 5721 | /* unit us */ |
5712 | /* FIXME: find a proper value */ | 5722 | /* FIXME: find a proper value */ |
5713 | wl->hw->channel_change_time = 10000; | ||
5714 | wl->hw->max_listen_interval = wl->conf.conn.max_listen_interval; | 5723 | wl->hw->max_listen_interval = wl->conf.conn.max_listen_interval; |
5715 | 5724 | ||
5716 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | | 5725 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | |