aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-07-28 20:36:25 -0400
committerDavid S. Miller <davem@davemloft.net>2014-07-28 20:36:25 -0400
commit3fd0202a0dfe07d255c5462d7d0e27673ca10430 (patch)
tree126483df9ff404e0d31cdcad18ad4280df06d89f /drivers/net
parenta67eed571aa505f51a4d02cab765a9d4f6ef80c4 (diff)
parent9a244409d0b0cf3b1e46f1dc331f2c718597fae0 (diff)
Merge tag 'master-2014-07-25' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next
John W. Linville says: ==================== pull request: wireless-next 2014-07-25 Please pull this batch of updates intended for the 3.17 stream! For the mac80211 bits, Johannes says: "We have a lot of TDLS patches, among them a fix that should make hwsim tests happy again. The rest, this time, is mostly small fixes." For the Bluetooth bits, Gustavo says: "Some more patches for 3.17. The most important change here is the move of the 6lowpan code to net/6lowpan. It has been agreed with Davem that this change will go through the bluetooth tree. The rest are mostly clean up and fixes." and, "Here follows some more patches for 3.17. These are mostly fixes to what we've sent to you before for next merge window." For the iwlwifi bits, Emmanuel says: "I have the usual amount of BT Coex stuff. Arik continues to work on TDLS and Ariej contributes a few things for HS2.0. I added a few more things to the firmware debugging infrastructure. Eran fixes a small bug - pretty normal content." And for the Atheros bits, Kalle says: "For ath6kl me and Jessica added support for ar6004 hw3.0, our latest version of ar6004. For ath10k Janusz added a printout so that it's easier to check what ath10k kconfig options are enabled. He also added a debugfs file to configure maximum amsdu and ampdu values. Also we had few fixes as usual." On top of that is the usual large batch of various driver updates -- brcmfmac, mwifiex, the TI drivers, and wil6210 all get some action. RafaƂ has also been very busy with b43 and related updates. Also, I pulled the wireless tree into this in order to resolve a merge conflict... P.S. The change to fs/compat_ioctl.c reflects a name change in a Bluetooth header file... ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.c11
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c12
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h3
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c73
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_tx.c46
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c11
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.h3
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c6
-rw-r--r--drivers/net/wireless/ath/ath6kl/bmi.h3
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c6
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.c16
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h36
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc_pipe.c32
-rw-r--r--drivers/net/wireless/ath/ath6kl/init.c90
-rw-r--r--drivers/net/wireless/ath/ath6kl/main.c17
-rw-r--r--drivers/net/wireless/ath/ath6kl/usb.c7
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.c72
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_mac.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mac.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h10
-rw-r--r--drivers/net/wireless/ath/ath9k/spectral.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c34
-rw-r--r--drivers/net/wireless/ath/wil6210/debugfs.c58
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c42
-rw-r--r--drivers/net/wireless/ath/wil6210/pcie_bus.c22
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.c6
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h26
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c21
-rw-r--r--drivers/net/wireless/b43/main.c149
-rw-r--r--drivers/net/wireless/b43/main.h1
-rw-r--r--drivers/net/wireless/b43/phy_lcn.c35
-rw-r--r--drivers/net/wireless/b43/phy_n.c1113
-rw-r--r--drivers/net/wireless/b43/phy_n.h15
-rw-r--r--drivers/net/wireless/b43/radio_2057.c420
-rw-r--r--drivers/net/wireless/b43/radio_2057.h10
-rw-r--r--drivers/net/wireless/b43/tables_nphy.c176
-rw-r--r--drivers/net/wireless/b43/xmit.c7
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/Makefile1
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c23
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/chip.c28
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd.h5
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c196
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h74
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c13
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c274
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/feature.c136
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/feature.h86
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/firmware.c5
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/firmware.h5
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c100
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h4
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/usb.c49
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c958
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/main.c37
-rw-r--r--drivers/net/wireless/brcm80211/include/brcm_hw_ids.h60
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig25
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-8000.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-config.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h17
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-modparams.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h21
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/coex.c193
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/coex_legacy.c119
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs.c104
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api.h67
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c15
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c383
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h52
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/nvm.c4
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/ops.c14
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sta.c24
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/time-event.c89
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tt.c12
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tx.c10
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c202
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c11
-rw-r--r--drivers/net/wireless/mwifiex/11n.c3
-rw-r--r--drivers/net/wireless/mwifiex/11n_rxreorder.c27
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c8
-rw-r--r--drivers/net/wireless/mwifiex/cmdevt.c40
-rw-r--r--drivers/net/wireless/mwifiex/fw.h2
-rw-r--r--drivers/net/wireless/mwifiex/join.c8
-rw-r--r--drivers/net/wireless/mwifiex/main.c16
-rw-r--r--drivers/net/wireless/mwifiex/pcie.c14
-rw-r--r--drivers/net/wireless/mwifiex/sdio.c15
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmd.c2
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmdresp.c2
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c10
-rw-r--r--drivers/net/wireless/mwifiex/tdls.c22
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c4
-rw-r--r--drivers/net/wireless/ti/wl12xx/main.c2
-rw-r--r--drivers/net/wireless/ti/wl18xx/cmd.c89
-rw-r--r--drivers/net/wireless/ti/wl18xx/cmd.h19
-rw-r--r--drivers/net/wireless/ti/wl18xx/event.c65
-rw-r--r--drivers/net/wireless/ti/wl18xx/event.h2
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c34
-rw-r--r--drivers/net/wireless/ti/wl18xx/tx.c7
-rw-r--r--drivers/net/wireless/ti/wl18xx/wl18xx.h2
-rw-r--r--drivers/net/wireless/ti/wlcore/Makefile2
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.c12
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.h3
-rw-r--r--drivers/net/wireless/ti/wlcore/debugfs.c2
-rw-r--r--drivers/net/wireless/ti/wlcore/hw_ops.h27
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c103
-rw-r--r--drivers/net/wireless/ti/wlcore/tx.c2
-rw-r--r--drivers/net/wireless/ti/wlcore/vendor_cmd.c197
-rw-r--r--drivers/net/wireless/ti/wlcore/vendor_cmd.h45
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore.h8
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore_i.h20
-rw-r--r--drivers/net/wireless/zd1211rw/Kconfig4
115 files changed, 4949 insertions, 1924 deletions
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
index d185dc0cd12b..4333107ecf37 100644
--- a/drivers/net/wireless/ath/ath10k/ce.c
+++ b/drivers/net/wireless/ath/ath10k/ce.c
@@ -603,16 +603,19 @@ static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
603 if (ret) 603 if (ret)
604 return ret; 604 return ret;
605 605
606 src_ring->hw_index = 606 read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
607 ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); 607 if (read_index == 0xffffffff)
608 src_ring->hw_index &= nentries_mask; 608 return -ENODEV;
609
610 read_index &= nentries_mask;
611 src_ring->hw_index = read_index;
609 612
610 ath10k_pci_sleep(ar); 613 ath10k_pci_sleep(ar);
611 } 614 }
612 615
613 read_index = src_ring->hw_index; 616 read_index = src_ring->hw_index;
614 617
615 if ((read_index == sw_index) || (read_index == 0xffffffff)) 618 if (read_index == sw_index)
616 return -EIO; 619 return -EIO;
617 620
618 sbase = src_ring->shadow_base; 621 sbase = src_ring->shadow_base;
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index e6c56c5bb0f6..93adb8c58969 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -802,7 +802,7 @@ int ath10k_core_start(struct ath10k *ar)
802 802
803 INIT_LIST_HEAD(&ar->arvifs); 803 INIT_LIST_HEAD(&ar->arvifs);
804 804
805 if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags)) 805 if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags)) {
806 ath10k_info("%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n", 806 ath10k_info("%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n",
807 ar->hw_params.name, 807 ar->hw_params.name,
808 ar->target_version, 808 ar->target_version,
@@ -811,6 +811,12 @@ int ath10k_core_start(struct ath10k *ar)
811 ar->fw_api, 811 ar->fw_api,
812 ar->htt.target_version_major, 812 ar->htt.target_version_major,
813 ar->htt.target_version_minor); 813 ar->htt.target_version_minor);
814 ath10k_info("debug %d debugfs %d tracing %d dfs %d\n",
815 config_enabled(CONFIG_ATH10K_DEBUG),
816 config_enabled(CONFIG_ATH10K_DEBUGFS),
817 config_enabled(CONFIG_ATH10K_TRACING),
818 config_enabled(CONFIG_ATH10K_DFS_CERTIFIED));
819 }
814 820
815 __set_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags); 821 __set_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags);
816 822
@@ -988,7 +994,9 @@ err_unregister_mac:
988err_release_fw: 994err_release_fw:
989 ath10k_core_free_firmware_files(ar); 995 ath10k_core_free_firmware_files(ar);
990err: 996err:
991 device_release_driver(ar->dev); 997 /* TODO: It's probably a good idea to release device from the driver
998 * but calling device_release_driver() here will cause a deadlock.
999 */
992 return; 1000 return;
993} 1001}
994 1002
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 68ceef61933d..83a5fa91531d 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -290,6 +290,9 @@ struct ath10k_debug {
290 struct ath_dfs_pool_stats dfs_pool_stats; 290 struct ath_dfs_pool_stats dfs_pool_stats;
291 291
292 u32 fw_dbglog_mask; 292 u32 fw_dbglog_mask;
293
294 u8 htt_max_amsdu;
295 u8 htt_max_ampdu;
293}; 296};
294 297
295enum ath10k_state { 298enum ath10k_state {
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 1b7ff4ba122c..3030158c478e 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -671,6 +671,72 @@ static const struct file_operations fops_htt_stats_mask = {
671 .llseek = default_llseek, 671 .llseek = default_llseek,
672}; 672};
673 673
674static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,
675 char __user *user_buf,
676 size_t count, loff_t *ppos)
677{
678 struct ath10k *ar = file->private_data;
679 char buf[64];
680 u8 amsdu = 3, ampdu = 64;
681 unsigned int len;
682
683 mutex_lock(&ar->conf_mutex);
684
685 if (ar->debug.htt_max_amsdu)
686 amsdu = ar->debug.htt_max_amsdu;
687
688 if (ar->debug.htt_max_ampdu)
689 ampdu = ar->debug.htt_max_ampdu;
690
691 mutex_unlock(&ar->conf_mutex);
692
693 len = scnprintf(buf, sizeof(buf), "%u %u\n", amsdu, ampdu);
694
695 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
696}
697
698static ssize_t ath10k_write_htt_max_amsdu_ampdu(struct file *file,
699 const char __user *user_buf,
700 size_t count, loff_t *ppos)
701{
702 struct ath10k *ar = file->private_data;
703 int res;
704 char buf[64];
705 unsigned int amsdu, ampdu;
706
707 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
708
709 /* make sure that buf is null terminated */
710 buf[sizeof(buf) - 1] = 0;
711
712 res = sscanf(buf, "%u %u", &amsdu, &ampdu);
713
714 if (res != 2)
715 return -EINVAL;
716
717 mutex_lock(&ar->conf_mutex);
718
719 res = ath10k_htt_h2t_aggr_cfg_msg(&ar->htt, ampdu, amsdu);
720 if (res)
721 goto out;
722
723 res = count;
724 ar->debug.htt_max_amsdu = amsdu;
725 ar->debug.htt_max_ampdu = ampdu;
726
727out:
728 mutex_unlock(&ar->conf_mutex);
729 return res;
730}
731
732static const struct file_operations fops_htt_max_amsdu_ampdu = {
733 .read = ath10k_read_htt_max_amsdu_ampdu,
734 .write = ath10k_write_htt_max_amsdu_ampdu,
735 .open = simple_open,
736 .owner = THIS_MODULE,
737 .llseek = default_llseek,
738};
739
674static ssize_t ath10k_read_fw_dbglog(struct file *file, 740static ssize_t ath10k_read_fw_dbglog(struct file *file,
675 char __user *user_buf, 741 char __user *user_buf,
676 size_t count, loff_t *ppos) 742 size_t count, loff_t *ppos)
@@ -757,6 +823,9 @@ void ath10k_debug_stop(struct ath10k *ar)
757 * warning from del_timer(). */ 823 * warning from del_timer(). */
758 if (ar->debug.htt_stats_mask != 0) 824 if (ar->debug.htt_stats_mask != 0)
759 cancel_delayed_work(&ar->debug.htt_stats_dwork); 825 cancel_delayed_work(&ar->debug.htt_stats_dwork);
826
827 ar->debug.htt_max_amsdu = 0;
828 ar->debug.htt_max_ampdu = 0;
760} 829}
761 830
762static ssize_t ath10k_write_simulate_radar(struct file *file, 831static ssize_t ath10k_write_simulate_radar(struct file *file,
@@ -867,6 +936,10 @@ int ath10k_debug_create(struct ath10k *ar)
867 debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy, 936 debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy,
868 ar, &fops_htt_stats_mask); 937 ar, &fops_htt_stats_mask);
869 938
939 debugfs_create_file("htt_max_amsdu_ampdu", S_IRUSR | S_IWUSR,
940 ar->debug.debugfs_phy, ar,
941 &fops_htt_max_amsdu_ampdu);
942
870 debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy, 943 debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy,
871 ar, &fops_fw_dbglog); 944 ar, &fops_fw_dbglog);
872 945
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 9a263462c793..6c93f3885ee5 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -240,16 +240,10 @@ struct htt_oob_sync_req {
240 __le16 rsvd0; 240 __le16 rsvd0;
241} __packed; 241} __packed;
242 242
243#define HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_MASK 0x1F
244#define HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_LSB 0
245
246struct htt_aggr_conf { 243struct htt_aggr_conf {
247 u8 max_num_ampdu_subframes; 244 u8 max_num_ampdu_subframes;
248 union { 245 /* amsdu_subframes is limited by 0x1F mask */
249 /* dont use bitfields; undefined behaviour */ 246 u8 max_num_amsdu_subframes;
250 u8 flags; /* see %HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_ */
251 u8 max_num_amsdu_subframes:5;
252 } __packed;
253} __packed; 247} __packed;
254 248
255#define HTT_MGMT_FRM_HDR_DOWNLOAD_LEN 32 249#define HTT_MGMT_FRM_HDR_DOWNLOAD_LEN 32
@@ -1343,6 +1337,9 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb);
1343int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt); 1337int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt);
1344int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie); 1338int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie);
1345int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt); 1339int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt);
1340int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
1341 u8 max_subfrms_ampdu,
1342 u8 max_subfrms_amsdu);
1346 1343
1347void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt); 1344void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt);
1348int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt); 1345int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt);
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 7064354d1f4f..accb6b4f6faf 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -307,6 +307,52 @@ int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt)
307 return 0; 307 return 0;
308} 308}
309 309
310int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
311 u8 max_subfrms_ampdu,
312 u8 max_subfrms_amsdu)
313{
314 struct htt_aggr_conf *aggr_conf;
315 struct sk_buff *skb;
316 struct htt_cmd *cmd;
317 int len;
318 int ret;
319
320 /* Firmware defaults are: amsdu = 3 and ampdu = 64 */
321
322 if (max_subfrms_ampdu == 0 || max_subfrms_ampdu > 64)
323 return -EINVAL;
324
325 if (max_subfrms_amsdu == 0 || max_subfrms_amsdu > 31)
326 return -EINVAL;
327
328 len = sizeof(cmd->hdr);
329 len += sizeof(cmd->aggr_conf);
330
331 skb = ath10k_htc_alloc_skb(len);
332 if (!skb)
333 return -ENOMEM;
334
335 skb_put(skb, len);
336 cmd = (struct htt_cmd *)skb->data;
337 cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_AGGR_CFG;
338
339 aggr_conf = &cmd->aggr_conf;
340 aggr_conf->max_num_ampdu_subframes = max_subfrms_ampdu;
341 aggr_conf->max_num_amsdu_subframes = max_subfrms_amsdu;
342
343 ath10k_dbg(ATH10K_DBG_HTT, "htt h2t aggr cfg msg amsdu %d ampdu %d",
344 aggr_conf->max_num_amsdu_subframes,
345 aggr_conf->max_num_ampdu_subframes);
346
347 ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb);
348 if (ret) {
349 dev_kfree_skb_any(skb);
350 return ret;
351 }
352
353 return 0;
354}
355
310int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) 356int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
311{ 357{
312 struct device *dev = htt->ar->dev; 358 struct device *dev = htt->ar->dev;
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index d0004d59c97e..06840d101c45 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -1362,8 +1362,6 @@ static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar,
1362 ath10k_ce_recv_buf_enqueue(ce_rx, &xfer, resp_paddr); 1362 ath10k_ce_recv_buf_enqueue(ce_rx, &xfer, resp_paddr);
1363 } 1363 }
1364 1364
1365 init_completion(&xfer.done);
1366
1367 ret = ath10k_ce_send(ce_tx, &xfer, req_paddr, req_len, -1, 0); 1365 ret = ath10k_ce_send(ce_tx, &xfer, req_paddr, req_len, -1, 0);
1368 if (ret) 1366 if (ret)
1369 goto err_resp; 1367 goto err_resp;
@@ -1414,10 +1412,7 @@ static void ath10k_pci_bmi_send_done(struct ath10k_ce_pipe *ce_state)
1414 &nbytes, &transfer_id)) 1412 &nbytes, &transfer_id))
1415 return; 1413 return;
1416 1414
1417 if (xfer->wait_for_resp) 1415 xfer->tx_done = true;
1418 return;
1419
1420 complete(&xfer->done);
1421} 1416}
1422 1417
1423static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state) 1418static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state)
@@ -1438,7 +1433,7 @@ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state)
1438 } 1433 }
1439 1434
1440 xfer->resp_len = nbytes; 1435 xfer->resp_len = nbytes;
1441 complete(&xfer->done); 1436 xfer->rx_done = true;
1442} 1437}
1443 1438
1444static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe, 1439static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
@@ -1451,7 +1446,7 @@ static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
1451 ath10k_pci_bmi_send_done(tx_pipe); 1446 ath10k_pci_bmi_send_done(tx_pipe);
1452 ath10k_pci_bmi_recv_data(rx_pipe); 1447 ath10k_pci_bmi_recv_data(rx_pipe);
1453 1448
1454 if (completion_done(&xfer->done)) 1449 if (xfer->tx_done && (xfer->rx_done == xfer->wait_for_resp))
1455 return 0; 1450 return 0;
1456 1451
1457 schedule(); 1452 schedule();
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h
index dfdebb4157aa..940129209990 100644
--- a/drivers/net/wireless/ath/ath10k/pci.h
+++ b/drivers/net/wireless/ath/ath10k/pci.h
@@ -38,7 +38,8 @@
38#define DIAG_TRANSFER_LIMIT 2048 38#define DIAG_TRANSFER_LIMIT 2048
39 39
40struct bmi_xfer { 40struct bmi_xfer {
41 struct completion done; 41 bool tx_done;
42 bool rx_done;
42 bool wait_for_resp; 43 bool wait_for_resp;
43 u32 resp_len; 44 u32 resp_len;
44}; 45};
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 4b7782a529ac..6f83cae57655 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2106,7 +2106,6 @@ static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb)
2106{ 2106{
2107 struct wmi_cmd_hdr *cmd_hdr; 2107 struct wmi_cmd_hdr *cmd_hdr;
2108 enum wmi_event_id id; 2108 enum wmi_event_id id;
2109 u16 len;
2110 2109
2111 cmd_hdr = (struct wmi_cmd_hdr *)skb->data; 2110 cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
2112 id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); 2111 id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
@@ -2114,8 +2113,6 @@ static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb)
2114 if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) 2113 if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
2115 return; 2114 return;
2116 2115
2117 len = skb->len;
2118
2119 trace_ath10k_wmi_event(id, skb->data, skb->len); 2116 trace_ath10k_wmi_event(id, skb->data, skb->len);
2120 2117
2121 switch (id) { 2118 switch (id) {
@@ -2225,7 +2222,6 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
2225{ 2222{
2226 struct wmi_cmd_hdr *cmd_hdr; 2223 struct wmi_cmd_hdr *cmd_hdr;
2227 enum wmi_10x_event_id id; 2224 enum wmi_10x_event_id id;
2228 u16 len;
2229 2225
2230 cmd_hdr = (struct wmi_cmd_hdr *)skb->data; 2226 cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
2231 id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); 2227 id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
@@ -2233,8 +2229,6 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
2233 if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) 2229 if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
2234 return; 2230 return;
2235 2231
2236 len = skb->len;
2237
2238 trace_ath10k_wmi_event(id, skb->data, skb->len); 2232 trace_ath10k_wmi_event(id, skb->data, skb->len);
2239 2233
2240 switch (id) { 2234 switch (id) {
diff --git a/drivers/net/wireless/ath/ath6kl/bmi.h b/drivers/net/wireless/ath/ath6kl/bmi.h
index 18fdd69e1f71..397a52f2628b 100644
--- a/drivers/net/wireless/ath/ath6kl/bmi.h
+++ b/drivers/net/wireless/ath/ath6kl/bmi.h
@@ -242,7 +242,8 @@ struct ath6kl_bmi_target_info {
242 (void) (check_type == val); \ 242 (void) (check_type == val); \
243 addr = ath6kl_get_hi_item_addr(ar, HI_ITEM(item)); \ 243 addr = ath6kl_get_hi_item_addr(ar, HI_ITEM(item)); \
244 ret = ath6kl_bmi_read(ar, addr, (u8 *) &tmp, 4); \ 244 ret = ath6kl_bmi_read(ar, addr, (u8 *) &tmp, 4); \
245 *val = le32_to_cpu(tmp); \ 245 if (!ret) \
246 *val = le32_to_cpu(tmp); \
246 ret; \ 247 ret; \
247 }) 248 })
248 249
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 1c4ce8e3eebe..e535807c3d89 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -2899,7 +2899,8 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
2899 if (info->inactivity_timeout) { 2899 if (info->inactivity_timeout) {
2900 inactivity_timeout = info->inactivity_timeout; 2900 inactivity_timeout = info->inactivity_timeout;
2901 2901
2902 if (ar->hw.flags & ATH6KL_HW_AP_INACTIVITY_MINS) 2902 if (test_bit(ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS,
2903 ar->fw_capabilities))
2903 inactivity_timeout = DIV_ROUND_UP(inactivity_timeout, 2904 inactivity_timeout = DIV_ROUND_UP(inactivity_timeout,
2904 60); 2905 60);
2905 2906
@@ -3782,7 +3783,8 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
3782 ath6kl_band_5ghz.ht_cap.ht_supported = false; 3783 ath6kl_band_5ghz.ht_cap.ht_supported = false;
3783 } 3784 }
3784 3785
3785 if (ar->hw.flags & ATH6KL_HW_64BIT_RATES) { 3786 if (test_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES,
3787 ar->fw_capabilities)) {
3786 ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff; 3788 ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
3787 ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; 3789 ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
3788 ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff; 3790 ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;
diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c
index b0b652042760..0df74b245af4 100644
--- a/drivers/net/wireless/ath/ath6kl/core.c
+++ b/drivers/net/wireless/ath/ath6kl/core.c
@@ -123,6 +123,22 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type)
123 123
124 /* FIXME: we should free all firmwares in the error cases below */ 124 /* FIXME: we should free all firmwares in the error cases below */
125 125
126 /*
127 * Backwards compatibility support for older ar6004 firmware images
128 * which do not set these feature flags.
129 */
130 if (ar->target_type == TARGET_TYPE_AR6004 &&
131 ar->fw_api <= 4) {
132 __set_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES,
133 ar->fw_capabilities);
134 __set_bit(ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS,
135 ar->fw_capabilities);
136
137 if (ar->hw.id == AR6004_HW_1_3_VERSION)
138 __set_bit(ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT,
139 ar->fw_capabilities);
140 }
141
126 /* Indicate that WMI is enabled (although not ready yet) */ 142 /* Indicate that WMI is enabled (although not ready yet) */
127 set_bit(WMI_ENABLED, &ar->flag); 143 set_bit(WMI_ENABLED, &ar->flag);
128 ar->wmi = ath6kl_wmi_init(ar); 144 ar->wmi = ath6kl_wmi_init(ar);
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 26b0f92424e1..2b78c863d030 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -136,6 +136,21 @@ enum ath6kl_fw_capability {
136 */ 136 */
137 ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL, 137 ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL,
138 138
139 /* WMI_SET_TX_SELECT_RATES_CMDID uses 64 bit size rate table */
140 ATH6KL_FW_CAPABILITY_64BIT_RATES,
141
142 /* WMI_AP_CONN_INACT_CMDID uses minutes as units */
143 ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS,
144
145 /* use low priority endpoint for all data */
146 ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT,
147
148 /* ratetable is the 2 stream version (max MCS15) */
149 ATH6KL_FW_CAPABILITY_RATETABLE_MCS15,
150
151 /* firmare doesn't support IP checksumming */
152 ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM,
153
139 /* this needs to be last */ 154 /* this needs to be last */
140 ATH6KL_FW_CAPABILITY_MAX, 155 ATH6KL_FW_CAPABILITY_MAX,
141}; 156};
@@ -149,15 +164,13 @@ struct ath6kl_fw_ie {
149}; 164};
150 165
151enum ath6kl_hw_flags { 166enum ath6kl_hw_flags {
152 ATH6KL_HW_64BIT_RATES = BIT(0),
153 ATH6KL_HW_AP_INACTIVITY_MINS = BIT(1),
154 ATH6KL_HW_MAP_LP_ENDPOINT = BIT(2),
155 ATH6KL_HW_SDIO_CRC_ERROR_WAR = BIT(3), 167 ATH6KL_HW_SDIO_CRC_ERROR_WAR = BIT(3),
156}; 168};
157 169
158#define ATH6KL_FW_API2_FILE "fw-2.bin" 170#define ATH6KL_FW_API2_FILE "fw-2.bin"
159#define ATH6KL_FW_API3_FILE "fw-3.bin" 171#define ATH6KL_FW_API3_FILE "fw-3.bin"
160#define ATH6KL_FW_API4_FILE "fw-4.bin" 172#define ATH6KL_FW_API4_FILE "fw-4.bin"
173#define ATH6KL_FW_API5_FILE "fw-5.bin"
161 174
162/* AR6003 1.0 definitions */ 175/* AR6003 1.0 definitions */
163#define AR6003_HW_1_0_VERSION 0x300002ba 176#define AR6003_HW_1_0_VERSION 0x300002ba
@@ -215,8 +228,21 @@ enum ath6kl_hw_flags {
215#define AR6004_HW_1_3_VERSION 0x31c8088a 228#define AR6004_HW_1_3_VERSION 0x31c8088a
216#define AR6004_HW_1_3_FW_DIR "ath6k/AR6004/hw1.3" 229#define AR6004_HW_1_3_FW_DIR "ath6k/AR6004/hw1.3"
217#define AR6004_HW_1_3_FIRMWARE_FILE "fw.ram.bin" 230#define AR6004_HW_1_3_FIRMWARE_FILE "fw.ram.bin"
218#define AR6004_HW_1_3_BOARD_DATA_FILE "ath6k/AR6004/hw1.3/bdata.bin" 231#define AR6004_HW_1_3_TCMD_FIRMWARE_FILE "utf.bin"
219#define AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE "ath6k/AR6004/hw1.3/bdata.bin" 232#define AR6004_HW_1_3_UTF_FIRMWARE_FILE "utf.bin"
233#define AR6004_HW_1_3_TESTSCRIPT_FILE "nullTestFlow.bin"
234#define AR6004_HW_1_3_BOARD_DATA_FILE AR6004_HW_1_3_FW_DIR "/bdata.bin"
235#define AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE AR6004_HW_1_3_FW_DIR "/bdata.bin"
236
237/* AR6004 3.0 definitions */
238#define AR6004_HW_3_0_VERSION 0x31C809F8
239#define AR6004_HW_3_0_FW_DIR "ath6k/AR6004/hw3.0"
240#define AR6004_HW_3_0_FIRMWARE_FILE "fw.ram.bin"
241#define AR6004_HW_3_0_TCMD_FIRMWARE_FILE "utf.bin"
242#define AR6004_HW_3_0_UTF_FIRMWARE_FILE "utf.bin"
243#define AR6004_HW_3_0_TESTSCRIPT_FILE "nullTestFlow.bin"
244#define AR6004_HW_3_0_BOARD_DATA_FILE AR6004_HW_3_0_FW_DIR "/bdata.bin"
245#define AR6004_HW_3_0_DEFAULT_BOARD_DATA_FILE AR6004_HW_3_0_FW_DIR "/bdata.bin"
220 246
221/* Per STA data, used in AP mode */ 247/* Per STA data, used in AP mode */
222#define STA_PS_AWAKE BIT(0) 248#define STA_PS_AWAKE BIT(0)
diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
index 756fe52a12c8..ca1a18c86c0d 100644
--- a/drivers/net/wireless/ath/ath6kl/htc_pipe.c
+++ b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
@@ -1170,8 +1170,12 @@ static int htc_wait_recv_ctrl_message(struct htc_target *target)
1170static void htc_rxctrl_complete(struct htc_target *context, 1170static void htc_rxctrl_complete(struct htc_target *context,
1171 struct htc_packet *packet) 1171 struct htc_packet *packet)
1172{ 1172{
1173 /* TODO, can't really receive HTC control messages yet.... */ 1173 struct sk_buff *skb = packet->skb;
1174 ath6kl_dbg(ATH6KL_DBG_HTC, "%s: invalid call function\n", __func__); 1174
1175 if (packet->endpoint == ENDPOINT_0 &&
1176 packet->status == -ECANCELED &&
1177 skb != NULL)
1178 dev_kfree_skb(skb);
1175} 1179}
1176 1180
1177/* htc pipe initialization */ 1181/* htc pipe initialization */
@@ -1678,7 +1682,29 @@ static void ath6kl_htc_pipe_activity_changed(struct htc_target *target,
1678 1682
1679static void ath6kl_htc_pipe_flush_rx_buf(struct htc_target *target) 1683static void ath6kl_htc_pipe_flush_rx_buf(struct htc_target *target)
1680{ 1684{
1681 /* TODO */ 1685 struct htc_endpoint *endpoint;
1686 struct htc_packet *packet, *tmp_pkt;
1687 int i;
1688
1689 for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
1690 endpoint = &target->endpoint[i];
1691
1692 spin_lock_bh(&target->rx_lock);
1693
1694 list_for_each_entry_safe(packet, tmp_pkt,
1695 &endpoint->rx_bufq, list) {
1696 list_del(&packet->list);
1697 spin_unlock_bh(&target->rx_lock);
1698 ath6kl_dbg(ATH6KL_DBG_HTC,
1699 "htc rx flush pkt 0x%p len %d ep %d\n",
1700 packet, packet->buf_len,
1701 packet->endpoint);
1702 dev_kfree_skb(packet->pkt_cntxt);
1703 spin_lock_bh(&target->rx_lock);
1704 }
1705
1706 spin_unlock_bh(&target->rx_lock);
1707 }
1682} 1708}
1683 1709
1684static int ath6kl_htc_pipe_credit_setup(struct htc_target *target, 1710static int ath6kl_htc_pipe_credit_setup(struct htc_target *target,
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index 8ee7097f0b25..fffd52355123 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -93,8 +93,7 @@ static const struct ath6kl_hw hw_list[] = {
93 .board_addr = 0x433900, 93 .board_addr = 0x433900,
94 .refclk_hz = 26000000, 94 .refclk_hz = 26000000,
95 .uarttx_pin = 11, 95 .uarttx_pin = 11,
96 .flags = ATH6KL_HW_64BIT_RATES | 96 .flags = 0,
97 ATH6KL_HW_AP_INACTIVITY_MINS,
98 97
99 .fw = { 98 .fw = {
100 .dir = AR6004_HW_1_0_FW_DIR, 99 .dir = AR6004_HW_1_0_FW_DIR,
@@ -114,8 +113,7 @@ static const struct ath6kl_hw hw_list[] = {
114 .board_addr = 0x43d400, 113 .board_addr = 0x43d400,
115 .refclk_hz = 40000000, 114 .refclk_hz = 40000000,
116 .uarttx_pin = 11, 115 .uarttx_pin = 11,
117 .flags = ATH6KL_HW_64BIT_RATES | 116 .flags = 0,
118 ATH6KL_HW_AP_INACTIVITY_MINS,
119 .fw = { 117 .fw = {
120 .dir = AR6004_HW_1_1_FW_DIR, 118 .dir = AR6004_HW_1_1_FW_DIR,
121 .fw = AR6004_HW_1_1_FIRMWARE_FILE, 119 .fw = AR6004_HW_1_1_FIRMWARE_FILE,
@@ -134,8 +132,7 @@ static const struct ath6kl_hw hw_list[] = {
134 .board_addr = 0x435c00, 132 .board_addr = 0x435c00,
135 .refclk_hz = 40000000, 133 .refclk_hz = 40000000,
136 .uarttx_pin = 11, 134 .uarttx_pin = 11,
137 .flags = ATH6KL_HW_64BIT_RATES | 135 .flags = 0,
138 ATH6KL_HW_AP_INACTIVITY_MINS,
139 136
140 .fw = { 137 .fw = {
141 .dir = AR6004_HW_1_2_FW_DIR, 138 .dir = AR6004_HW_1_2_FW_DIR,
@@ -152,20 +149,43 @@ static const struct ath6kl_hw hw_list[] = {
152 .board_ext_data_addr = 0x437000, 149 .board_ext_data_addr = 0x437000,
153 .reserved_ram_size = 7168, 150 .reserved_ram_size = 7168,
154 .board_addr = 0x436400, 151 .board_addr = 0x436400,
155 .refclk_hz = 40000000, 152 .refclk_hz = 0,
156 .uarttx_pin = 11, 153 .uarttx_pin = 11,
157 .flags = ATH6KL_HW_64BIT_RATES | 154 .flags = 0,
158 ATH6KL_HW_AP_INACTIVITY_MINS |
159 ATH6KL_HW_MAP_LP_ENDPOINT,
160 155
161 .fw = { 156 .fw = {
162 .dir = AR6004_HW_1_3_FW_DIR, 157 .dir = AR6004_HW_1_3_FW_DIR,
163 .fw = AR6004_HW_1_3_FIRMWARE_FILE, 158 .fw = AR6004_HW_1_3_FIRMWARE_FILE,
159 .tcmd = AR6004_HW_1_3_TCMD_FIRMWARE_FILE,
160 .utf = AR6004_HW_1_3_UTF_FIRMWARE_FILE,
161 .testscript = AR6004_HW_1_3_TESTSCRIPT_FILE,
164 }, 162 },
165 163
166 .fw_board = AR6004_HW_1_3_BOARD_DATA_FILE, 164 .fw_board = AR6004_HW_1_3_BOARD_DATA_FILE,
167 .fw_default_board = AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE, 165 .fw_default_board = AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE,
168 }, 166 },
167 {
168 .id = AR6004_HW_3_0_VERSION,
169 .name = "ar6004 hw 3.0",
170 .dataset_patch_addr = 0,
171 .app_load_addr = 0x1234,
172 .board_ext_data_addr = 0,
173 .reserved_ram_size = 7168,
174 .board_addr = 0x436400,
175 .testscript_addr = 0,
176 .flags = 0,
177
178 .fw = {
179 .dir = AR6004_HW_3_0_FW_DIR,
180 .fw = AR6004_HW_3_0_FIRMWARE_FILE,
181 .tcmd = AR6004_HW_3_0_TCMD_FIRMWARE_FILE,
182 .utf = AR6004_HW_3_0_UTF_FIRMWARE_FILE,
183 .testscript = AR6004_HW_3_0_TESTSCRIPT_FILE,
184 },
185
186 .fw_board = AR6004_HW_3_0_BOARD_DATA_FILE,
187 .fw_default_board = AR6004_HW_3_0_DEFAULT_BOARD_DATA_FILE,
188 },
169}; 189};
170 190
171/* 191/*
@@ -601,7 +621,9 @@ int ath6kl_configure_target(struct ath6kl *ar)
601 * but possible in theory. 621 * but possible in theory.
602 */ 622 */
603 623
604 if (ar->target_type == TARGET_TYPE_AR6003) { 624 if ((ar->target_type == TARGET_TYPE_AR6003) ||
625 (ar->version.target_ver == AR6004_HW_1_3_VERSION) ||
626 (ar->version.target_ver == AR6004_HW_3_0_VERSION)) {
605 param = ar->hw.board_ext_data_addr; 627 param = ar->hw.board_ext_data_addr;
606 ram_reserved_size = ar->hw.reserved_ram_size; 628 ram_reserved_size = ar->hw.reserved_ram_size;
607 629
@@ -629,9 +651,12 @@ int ath6kl_configure_target(struct ath6kl *ar)
629 return status; 651 return status;
630 652
631 /* Configure target refclk_hz */ 653 /* Configure target refclk_hz */
632 status = ath6kl_bmi_write_hi32(ar, hi_refclk_hz, ar->hw.refclk_hz); 654 if (ar->hw.refclk_hz != 0) {
633 if (status) 655 status = ath6kl_bmi_write_hi32(ar, hi_refclk_hz,
634 return status; 656 ar->hw.refclk_hz);
657 if (status)
658 return status;
659 }
635 660
636 return 0; 661 return 0;
637} 662}
@@ -1112,6 +1137,12 @@ int ath6kl_init_fetch_firmwares(struct ath6kl *ar)
1112 if (ret) 1137 if (ret)
1113 return ret; 1138 return ret;
1114 1139
1140 ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API5_FILE);
1141 if (ret == 0) {
1142 ar->fw_api = 5;
1143 goto out;
1144 }
1145
1115 ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API4_FILE); 1146 ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API4_FILE);
1116 if (ret == 0) { 1147 if (ret == 0) {
1117 ar->fw_api = 4; 1148 ar->fw_api = 4;
@@ -1161,11 +1192,19 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
1161 ath6kl_bmi_write_hi32(ar, hi_board_data, 1192 ath6kl_bmi_write_hi32(ar, hi_board_data,
1162 board_address); 1193 board_address);
1163 } else { 1194 } else {
1164 ath6kl_bmi_read_hi32(ar, hi_board_data, &board_address); 1195 ret = ath6kl_bmi_read_hi32(ar, hi_board_data, &board_address);
1196 if (ret) {
1197 ath6kl_err("Failed to get board file target address.\n");
1198 return ret;
1199 }
1165 } 1200 }
1166 1201
1167 /* determine where in target ram to write extended board data */ 1202 /* determine where in target ram to write extended board data */
1168 ath6kl_bmi_read_hi32(ar, hi_board_ext_data, &board_ext_address); 1203 ret = ath6kl_bmi_read_hi32(ar, hi_board_ext_data, &board_ext_address);
1204 if (ret) {
1205 ath6kl_err("Failed to get extended board file target address.\n");
1206 return ret;
1207 }
1169 1208
1170 if (ar->target_type == TARGET_TYPE_AR6003 && 1209 if (ar->target_type == TARGET_TYPE_AR6003 &&
1171 board_ext_address == 0) { 1210 board_ext_address == 0) {
@@ -1229,7 +1268,13 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
1229 } 1268 }
1230 1269
1231 /* record the fact that Board Data IS initialized */ 1270 /* record the fact that Board Data IS initialized */
1232 ath6kl_bmi_write_hi32(ar, hi_board_data_initialized, 1); 1271 if ((ar->version.target_ver == AR6004_HW_1_3_VERSION) ||
1272 (ar->version.target_ver == AR6004_HW_3_0_VERSION))
1273 param = board_data_size;
1274 else
1275 param = 1;
1276
1277 ath6kl_bmi_write_hi32(ar, hi_board_data_initialized, param);
1233 1278
1234 return ret; 1279 return ret;
1235} 1280}
@@ -1360,7 +1405,11 @@ static int ath6kl_upload_testscript(struct ath6kl *ar)
1360 } 1405 }
1361 1406
1362 ath6kl_bmi_write_hi32(ar, hi_ota_testscript, address); 1407 ath6kl_bmi_write_hi32(ar, hi_ota_testscript, address);
1363 ath6kl_bmi_write_hi32(ar, hi_end_ram_reserve_sz, 4096); 1408
1409 if ((ar->version.target_ver != AR6004_HW_1_3_VERSION) &&
1410 (ar->version.target_ver != AR6004_HW_3_0_VERSION))
1411 ath6kl_bmi_write_hi32(ar, hi_end_ram_reserve_sz, 4096);
1412
1364 ath6kl_bmi_write_hi32(ar, hi_test_apps_related, 1); 1413 ath6kl_bmi_write_hi32(ar, hi_test_apps_related, 1);
1365 1414
1366 return 0; 1415 return 0;
@@ -1566,6 +1615,11 @@ static const struct fw_capa_str_map {
1566 { ATH6KL_FW_CAPABILITY_REGDOMAIN, "regdomain" }, 1615 { ATH6KL_FW_CAPABILITY_REGDOMAIN, "regdomain" },
1567 { ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2, "sched-scan-v2" }, 1616 { ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2, "sched-scan-v2" },
1568 { ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL, "hb-poll" }, 1617 { ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL, "hb-poll" },
1618 { ATH6KL_FW_CAPABILITY_64BIT_RATES, "64bit-rates" },
1619 { ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS, "ap-inactivity-mins" },
1620 { ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT, "map-lp-endpoint" },
1621 { ATH6KL_FW_CAPABILITY_RATETABLE_MCS15, "ratetable-mcs15" },
1622 { ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM, "no-ip-checksum" },
1569}; 1623};
1570 1624
1571static const char *ath6kl_init_get_fw_capa_name(unsigned int id) 1625static const char *ath6kl_init_get_fw_capa_name(unsigned int id)
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index d56554674da4..21516bc65785 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -702,6 +702,7 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len)
702 struct ath6kl *ar = vif->ar; 702 struct ath6kl *ar = vif->ar;
703 struct target_stats *stats = &vif->target_stats; 703 struct target_stats *stats = &vif->target_stats;
704 struct tkip_ccmp_stats *ccmp_stats; 704 struct tkip_ccmp_stats *ccmp_stats;
705 s32 rate;
705 u8 ac; 706 u8 ac;
706 707
707 if (len < sizeof(*tgt_stats)) 708 if (len < sizeof(*tgt_stats))
@@ -731,8 +732,9 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len)
731 le32_to_cpu(tgt_stats->stats.tx.mult_retry_cnt); 732 le32_to_cpu(tgt_stats->stats.tx.mult_retry_cnt);
732 stats->tx_rts_fail_cnt += 733 stats->tx_rts_fail_cnt +=
733 le32_to_cpu(tgt_stats->stats.tx.rts_fail_cnt); 734 le32_to_cpu(tgt_stats->stats.tx.rts_fail_cnt);
734 stats->tx_ucast_rate = 735
735 ath6kl_wmi_get_rate(a_sle32_to_cpu(tgt_stats->stats.tx.ucast_rate)); 736 rate = a_sle32_to_cpu(tgt_stats->stats.tx.ucast_rate);
737 stats->tx_ucast_rate = ath6kl_wmi_get_rate(ar->wmi, rate);
736 738
737 stats->rx_pkt += le32_to_cpu(tgt_stats->stats.rx.pkt); 739 stats->rx_pkt += le32_to_cpu(tgt_stats->stats.rx.pkt);
738 stats->rx_byte += le32_to_cpu(tgt_stats->stats.rx.byte); 740 stats->rx_byte += le32_to_cpu(tgt_stats->stats.rx.byte);
@@ -749,8 +751,9 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len)
749 le32_to_cpu(tgt_stats->stats.rx.key_cache_miss); 751 le32_to_cpu(tgt_stats->stats.rx.key_cache_miss);
750 stats->rx_decrypt_err += le32_to_cpu(tgt_stats->stats.rx.decrypt_err); 752 stats->rx_decrypt_err += le32_to_cpu(tgt_stats->stats.rx.decrypt_err);
751 stats->rx_dupl_frame += le32_to_cpu(tgt_stats->stats.rx.dupl_frame); 753 stats->rx_dupl_frame += le32_to_cpu(tgt_stats->stats.rx.dupl_frame);
752 stats->rx_ucast_rate = 754
753 ath6kl_wmi_get_rate(a_sle32_to_cpu(tgt_stats->stats.rx.ucast_rate)); 755 rate = a_sle32_to_cpu(tgt_stats->stats.rx.ucast_rate);
756 stats->rx_ucast_rate = ath6kl_wmi_get_rate(ar->wmi, rate);
754 757
755 ccmp_stats = &tgt_stats->stats.tkip_ccmp_stats; 758 ccmp_stats = &tgt_stats->stats.tkip_ccmp_stats;
756 759
@@ -1290,6 +1293,8 @@ static const struct net_device_ops ath6kl_netdev_ops = {
1290 1293
1291void init_netdev(struct net_device *dev) 1294void init_netdev(struct net_device *dev)
1292{ 1295{
1296 struct ath6kl *ar = ath6kl_priv(dev);
1297
1293 dev->netdev_ops = &ath6kl_netdev_ops; 1298 dev->netdev_ops = &ath6kl_netdev_ops;
1294 dev->destructor = free_netdev; 1299 dev->destructor = free_netdev;
1295 dev->watchdog_timeo = ATH6KL_TX_TIMEOUT; 1300 dev->watchdog_timeo = ATH6KL_TX_TIMEOUT;
@@ -1301,7 +1306,9 @@ void init_netdev(struct net_device *dev)
1301 WMI_MAX_TX_META_SZ + 1306 WMI_MAX_TX_META_SZ +
1302 ATH6KL_HTC_ALIGN_BYTES, 4); 1307 ATH6KL_HTC_ALIGN_BYTES, 4);
1303 1308
1304 dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; 1309 if (!test_bit(ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM,
1310 ar->fw_capabilities))
1311 dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
1305 1312
1306 return; 1313 return;
1307} 1314}
diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c
index 3afc5a463d06..c44325856b81 100644
--- a/drivers/net/wireless/ath/ath6kl/usb.c
+++ b/drivers/net/wireless/ath/ath6kl/usb.c
@@ -802,7 +802,8 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id,
802 break; 802 break;
803 case WMI_DATA_VI_SVC: 803 case WMI_DATA_VI_SVC:
804 804
805 if (ar->hw.flags & ATH6KL_HW_MAP_LP_ENDPOINT) 805 if (test_bit(ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT,
806 ar->fw_capabilities))
806 *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP; 807 *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP;
807 else 808 else
808 *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP; 809 *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP;
@@ -814,7 +815,8 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id,
814 break; 815 break;
815 case WMI_DATA_VO_SVC: 816 case WMI_DATA_VO_SVC:
816 817
817 if (ar->hw.flags & ATH6KL_HW_MAP_LP_ENDPOINT) 818 if (test_bit(ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT,
819 ar->fw_capabilities))
818 *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP; 820 *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP;
819 else 821 else
820 *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP; 822 *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP;
@@ -1208,6 +1210,7 @@ static int ath6kl_usb_pm_reset_resume(struct usb_interface *intf)
1208 1210
1209/* table of devices that work with this driver */ 1211/* table of devices that work with this driver */
1210static struct usb_device_id ath6kl_usb_ids[] = { 1212static struct usb_device_id ath6kl_usb_ids[] = {
1213 {USB_DEVICE(0x0cf3, 0x9375)},
1211 {USB_DEVICE(0x0cf3, 0x9374)}, 1214 {USB_DEVICE(0x0cf3, 0x9374)},
1212 { /* Terminating entry */ }, 1215 { /* Terminating entry */ },
1213}; 1216};
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index 4d7f9e4712e9..94df345d08c2 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -59,6 +59,55 @@ static const s32 wmi_rate_tbl[][2] = {
59 {0, 0} 59 {0, 0}
60}; 60};
61 61
62static const s32 wmi_rate_tbl_mcs15[][2] = {
63 /* {W/O SGI, with SGI} */
64 {1000, 1000},
65 {2000, 2000},
66 {5500, 5500},
67 {11000, 11000},
68 {6000, 6000},
69 {9000, 9000},
70 {12000, 12000},
71 {18000, 18000},
72 {24000, 24000},
73 {36000, 36000},
74 {48000, 48000},
75 {54000, 54000},
76 {6500, 7200}, /* HT 20, MCS 0 */
77 {13000, 14400},
78 {19500, 21700},
79 {26000, 28900},
80 {39000, 43300},
81 {52000, 57800},
82 {58500, 65000},
83 {65000, 72200},
84 {13000, 14400}, /* HT 20, MCS 8 */
85 {26000, 28900},
86 {39000, 43300},
87 {52000, 57800},
88 {78000, 86700},
89 {104000, 115600},
90 {117000, 130000},
91 {130000, 144400}, /* HT 20, MCS 15 */
92 {13500, 15000}, /*HT 40, MCS 0 */
93 {27000, 30000},
94 {40500, 45000},
95 {54000, 60000},
96 {81000, 90000},
97 {108000, 120000},
98 {121500, 135000},
99 {135000, 150000},
100 {27000, 30000}, /*HT 40, MCS 8 */
101 {54000, 60000},
102 {81000, 90000},
103 {108000, 120000},
104 {162000, 180000},
105 {216000, 240000},
106 {243000, 270000},
107 {270000, 300000}, /*HT 40, MCS 15 */
108 {0, 0}
109};
110
62/* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */ 111/* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */
63static const u8 up_to_ac[] = { 112static const u8 up_to_ac[] = {
64 WMM_AC_BE, 113 WMM_AC_BE,
@@ -2838,7 +2887,8 @@ int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
2838{ 2887{
2839 struct ath6kl *ar = wmi->parent_dev; 2888 struct ath6kl *ar = wmi->parent_dev;
2840 2889
2841 if (ar->hw.flags & ATH6KL_HW_64BIT_RATES) 2890 if (test_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES,
2891 ar->fw_capabilities))
2842 return ath6kl_set_bitrate_mask64(wmi, if_idx, mask); 2892 return ath6kl_set_bitrate_mask64(wmi, if_idx, mask);
2843 else 2893 else
2844 return ath6kl_set_bitrate_mask32(wmi, if_idx, mask); 2894 return ath6kl_set_bitrate_mask32(wmi, if_idx, mask);
@@ -3279,9 +3329,11 @@ int ath6kl_wmi_set_regdomain_cmd(struct wmi *wmi, const char *alpha2)
3279 NO_SYNC_WMIFLAG); 3329 NO_SYNC_WMIFLAG);
3280} 3330}
3281 3331
3282s32 ath6kl_wmi_get_rate(s8 rate_index) 3332s32 ath6kl_wmi_get_rate(struct wmi *wmi, s8 rate_index)
3283{ 3333{
3334 struct ath6kl *ar = wmi->parent_dev;
3284 u8 sgi = 0; 3335 u8 sgi = 0;
3336 s32 ret;
3285 3337
3286 if (rate_index == RATE_AUTO) 3338 if (rate_index == RATE_AUTO)
3287 return 0; 3339 return 0;
@@ -3292,10 +3344,20 @@ s32 ath6kl_wmi_get_rate(s8 rate_index)
3292 sgi = 1; 3344 sgi = 1;
3293 } 3345 }
3294 3346
3295 if (WARN_ON(rate_index > RATE_MCS_7_40)) 3347 if (test_bit(ATH6KL_FW_CAPABILITY_RATETABLE_MCS15,
3296 rate_index = RATE_MCS_7_40; 3348 ar->fw_capabilities)) {
3349 if (WARN_ON(rate_index >= ARRAY_SIZE(wmi_rate_tbl_mcs15)))
3350 return 0;
3351
3352 ret = wmi_rate_tbl_mcs15[(u32) rate_index][sgi];
3353 } else {
3354 if (WARN_ON(rate_index >= ARRAY_SIZE(wmi_rate_tbl)))
3355 return 0;
3297 3356
3298 return wmi_rate_tbl[(u32) rate_index][sgi]; 3357 ret = wmi_rate_tbl[(u32) rate_index][sgi];
3358 }
3359
3360 return ret;
3299} 3361}
3300 3362
3301static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap, 3363static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap,
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index bb23fc00111d..19f88b4a24fb 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -2632,7 +2632,7 @@ int ath6kl_wmi_set_htcap_cmd(struct wmi *wmi, u8 if_idx,
2632 struct ath6kl_htcap *htcap); 2632 struct ath6kl_htcap *htcap);
2633int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len); 2633int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len);
2634 2634
2635s32 ath6kl_wmi_get_rate(s8 rate_index); 2635s32 ath6kl_wmi_get_rate(struct wmi *wmi, s8 rate_index);
2636 2636
2637int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx, 2637int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx,
2638 __be32 ips0, __be32 ips1); 2638 __be32 ips0, __be32 ips1);
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
index 741b38ddcb37..59af9f9712da 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
@@ -281,7 +281,7 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
281 281
282 ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen) 282 ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen)
283 | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) 283 | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
284 | SM(i->txpower, AR_XmitPower) 284 | SM(i->txpower, AR_XmitPower0)
285 | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) 285 | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
286 | (i->flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) 286 | (i->flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
287 | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) 287 | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
@@ -306,6 +306,10 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
306 | set11nRateFlags(i->rates, 2) 306 | set11nRateFlags(i->rates, 2)
307 | set11nRateFlags(i->rates, 3) 307 | set11nRateFlags(i->rates, 3)
308 | SM(i->rtscts_rate, AR_RTSCTSRate); 308 | SM(i->rtscts_rate, AR_RTSCTSRate);
309
310 ACCESS_ONCE(ads->ds_ctl9) = SM(i->txpower, AR_XmitPower1);
311 ACCESS_ONCE(ads->ds_ctl10) = SM(i->txpower, AR_XmitPower2);
312 ACCESS_ONCE(ads->ds_ctl11) = SM(i->txpower, AR_XmitPower3);
309} 313}
310 314
311static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, 315static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index 729ffbf07343..71e38e85aa99 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -101,7 +101,7 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
101 101
102 ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen) 102 ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen)
103 | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) 103 | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
104 | SM(i->txpower, AR_XmitPower) 104 | SM(i->txpower, AR_XmitPower0)
105 | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) 105 | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
106 | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) 106 | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
107 | (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0) 107 | (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0)
@@ -151,6 +151,10 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
151 | SM(i->rtscts_rate, AR_RTSCTSRate); 151 | SM(i->rtscts_rate, AR_RTSCTSRate);
152 152
153 ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding; 153 ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding;
154
155 ACCESS_ONCE(ads->ctl20) = SM(i->txpower, AR_XmitPower1);
156 ACCESS_ONCE(ads->ctl21) = SM(i->txpower, AR_XmitPower2);
157 ACCESS_ONCE(ads->ctl22) = SM(i->txpower, AR_XmitPower3);
154} 158}
155 159
156static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads) 160static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads)
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 11b5e4dd6294..7fc13a8da675 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -182,7 +182,8 @@ struct ath_atx_ac {
182 182
183struct ath_frame_info { 183struct ath_frame_info {
184 struct ath_buf *bf; 184 struct ath_buf *bf;
185 int framelen; 185 u16 framelen;
186 s8 txq;
186 enum ath9k_key_type keytype; 187 enum ath9k_key_type keytype;
187 u8 keyix; 188 u8 keyix;
188 u8 rtscts_rate; 189 u8 rtscts_rate;
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index ce073e995dfe..d2279365be6f 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -202,7 +202,7 @@ static ssize_t write_file_ani(struct file *file,
202 if (kstrtoul(buf, 0, &ani)) 202 if (kstrtoul(buf, 0, &ani))
203 return -EINVAL; 203 return -EINVAL;
204 204
205 if (ani < 0 || ani > 1) 205 if (ani > 1)
206 return -EINVAL; 206 return -EINVAL;
207 207
208 common->disable_ani = !ani; 208 common->disable_ani = !ani;
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index da7686757535..6c56cafa5ca4 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -346,8 +346,14 @@ struct ar5416_desc {
346#define AR_FrameLen 0x00000fff 346#define AR_FrameLen 0x00000fff
347#define AR_VirtMoreFrag 0x00001000 347#define AR_VirtMoreFrag 0x00001000
348#define AR_TxCtlRsvd00 0x0000e000 348#define AR_TxCtlRsvd00 0x0000e000
349#define AR_XmitPower 0x003f0000 349#define AR_XmitPower0 0x003f0000
350#define AR_XmitPower_S 16 350#define AR_XmitPower0_S 16
351#define AR_XmitPower1 0x3f000000
352#define AR_XmitPower1_S 24
353#define AR_XmitPower2 0x3f000000
354#define AR_XmitPower2_S 24
355#define AR_XmitPower3 0x3f000000
356#define AR_XmitPower3_S 24
351#define AR_RTSEnable 0x00400000 357#define AR_RTSEnable 0x00400000
352#define AR_VEOL 0x00800000 358#define AR_VEOL 0x00800000
353#define AR_ClrDestMask 0x01000000 359#define AR_ClrDestMask 0x01000000
diff --git a/drivers/net/wireless/ath/ath9k/spectral.c b/drivers/net/wireless/ath/ath9k/spectral.c
index 99f4de95c264..5fe29b9f8fa2 100644
--- a/drivers/net/wireless/ath/ath9k/spectral.c
+++ b/drivers/net/wireless/ath/ath9k/spectral.c
@@ -313,7 +313,7 @@ static ssize_t write_file_spectral_short_repeat(struct file *file,
313 if (kstrtoul(buf, 0, &val)) 313 if (kstrtoul(buf, 0, &val))
314 return -EINVAL; 314 return -EINVAL;
315 315
316 if (val < 0 || val > 1) 316 if (val > 1)
317 return -EINVAL; 317 return -EINVAL;
318 318
319 sc->spec_config.short_repeat = val; 319 sc->spec_config.short_repeat = val;
@@ -361,7 +361,7 @@ static ssize_t write_file_spectral_count(struct file *file,
361 if (kstrtoul(buf, 0, &val)) 361 if (kstrtoul(buf, 0, &val))
362 return -EINVAL; 362 return -EINVAL;
363 363
364 if (val < 0 || val > 255) 364 if (val > 255)
365 return -EINVAL; 365 return -EINVAL;
366 366
367 sc->spec_config.count = val; 367 sc->spec_config.count = val;
@@ -409,7 +409,7 @@ static ssize_t write_file_spectral_period(struct file *file,
409 if (kstrtoul(buf, 0, &val)) 409 if (kstrtoul(buf, 0, &val))
410 return -EINVAL; 410 return -EINVAL;
411 411
412 if (val < 0 || val > 255) 412 if (val > 255)
413 return -EINVAL; 413 return -EINVAL;
414 414
415 sc->spec_config.period = val; 415 sc->spec_config.period = val;
@@ -457,7 +457,7 @@ static ssize_t write_file_spectral_fft_period(struct file *file,
457 if (kstrtoul(buf, 0, &val)) 457 if (kstrtoul(buf, 0, &val))
458 return -EINVAL; 458 return -EINVAL;
459 459
460 if (val < 0 || val > 15) 460 if (val > 15)
461 return -EINVAL; 461 return -EINVAL;
462 462
463 sc->spec_config.fft_period = val; 463 sc->spec_config.fft_period = val;
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index d4927c9a6bae..704fcbcbe20b 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -157,15 +157,14 @@ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
157 struct sk_buff *skb) 157 struct sk_buff *skb)
158{ 158{
159 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 159 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
160 int q, hw_queue; 160 struct ath_frame_info *fi = get_frame_info(skb);
161 161 int hw_queue;
162 q = skb_get_queue_mapping(skb); 162 int q = fi->txq;
163 if (txq == sc->tx.uapsdq)
164 txq = sc->tx.txq_map[q];
165 163
166 if (txq != sc->tx.txq_map[q]) 164 if (q < 0)
167 return; 165 return;
168 166
167 txq = sc->tx.txq_map[q];
169 if (WARN_ON(--txq->pending_frames < 0)) 168 if (WARN_ON(--txq->pending_frames < 0))
170 txq->pending_frames = 0; 169 txq->pending_frames = 0;
171 170
@@ -898,6 +897,15 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
898 897
899 tx_info = IEEE80211_SKB_CB(skb); 898 tx_info = IEEE80211_SKB_CB(skb);
900 tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT; 899 tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT;
900
901 /*
902 * No aggregation session is running, but there may be frames
903 * from a previous session or a failed attempt in the queue.
904 * Send them out as normal data frames
905 */
906 if (!tid->active)
907 tx_info->flags &= ~IEEE80211_TX_CTL_AMPDU;
908
901 if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) { 909 if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) {
902 bf->bf_state.bf_type = 0; 910 bf->bf_state.bf_type = 0;
903 return bf; 911 return bf;
@@ -2036,6 +2044,7 @@ static void setup_frame_info(struct ieee80211_hw *hw,
2036 an = (struct ath_node *) sta->drv_priv; 2044 an = (struct ath_node *) sta->drv_priv;
2037 2045
2038 memset(fi, 0, sizeof(*fi)); 2046 memset(fi, 0, sizeof(*fi));
2047 fi->txq = -1;
2039 if (hw_key) 2048 if (hw_key)
2040 fi->keyix = hw_key->hw_key_idx; 2049 fi->keyix = hw_key->hw_key_idx;
2041 else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0) 2050 else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0)
@@ -2187,6 +2196,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
2187 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 2196 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
2188 struct ieee80211_sta *sta = txctl->sta; 2197 struct ieee80211_sta *sta = txctl->sta;
2189 struct ieee80211_vif *vif = info->control.vif; 2198 struct ieee80211_vif *vif = info->control.vif;
2199 struct ath_frame_info *fi = get_frame_info(skb);
2190 struct ath_vif *avp = NULL; 2200 struct ath_vif *avp = NULL;
2191 struct ath_softc *sc = hw->priv; 2201 struct ath_softc *sc = hw->priv;
2192 struct ath_txq *txq = txctl->txq; 2202 struct ath_txq *txq = txctl->txq;
@@ -2216,11 +2226,13 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
2216 hw_queue = (info->hw_queue >= sc->hw->queues - 2) ? q : info->hw_queue; 2226 hw_queue = (info->hw_queue >= sc->hw->queues - 2) ? q : info->hw_queue;
2217 2227
2218 ath_txq_lock(sc, txq); 2228 ath_txq_lock(sc, txq);
2219 if (txq == sc->tx.txq_map[q] && 2229 if (txq == sc->tx.txq_map[q]) {
2220 ++txq->pending_frames > sc->tx.txq_max_pending[q] && 2230 fi->txq = q;
2221 !txq->stopped) { 2231 if (++txq->pending_frames > sc->tx.txq_max_pending[q] &&
2222 ieee80211_stop_queue(sc->hw, hw_queue); 2232 !txq->stopped) {
2223 txq->stopped = true; 2233 ieee80211_stop_queue(sc->hw, hw_queue);
2234 txq->stopped = true;
2235 }
2224 } 2236 }
2225 2237
2226 queue = ieee80211_is_data_present(hdr->frame_control); 2238 queue = ieee80211_is_data_present(hdr->frame_control);
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index a868c5eebe37..8f66186adb8c 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -448,8 +448,10 @@ static ssize_t wil_write_file_rxon(struct file *file, const char __user *buf,
448 char *kbuf = kmalloc(len + 1, GFP_KERNEL); 448 char *kbuf = kmalloc(len + 1, GFP_KERNEL);
449 if (!kbuf) 449 if (!kbuf)
450 return -ENOMEM; 450 return -ENOMEM;
451 if (copy_from_user(kbuf, buf, len)) 451 if (copy_from_user(kbuf, buf, len)) {
452 kfree(kbuf);
452 return -EIO; 453 return -EIO;
454 }
453 455
454 kbuf[len] = '\0'; 456 kbuf[len] = '\0';
455 rc = kstrtol(kbuf, 0, &channel); 457 rc = kstrtol(kbuf, 0, &channel);
@@ -963,6 +965,26 @@ static const struct file_operations fops_sta = {
963}; 965};
964 966
965/*----------------*/ 967/*----------------*/
968static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil,
969 struct dentry *dbg)
970{
971 int i;
972 char name[32];
973
974 for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) {
975 struct debugfs_blob_wrapper *blob = &wil->blobs[i];
976 const struct fw_map *map = &fw_mapping[i];
977
978 if (!map->name)
979 continue;
980
981 blob->data = (void * __force)wil->csr + HOSTADDR(map->host);
982 blob->size = map->to - map->from;
983 snprintf(name, sizeof(name), "blob_%s", map->name);
984 wil_debugfs_create_ioblob(name, S_IRUGO, dbg, blob);
985 }
986}
987
966int wil6210_debugfs_init(struct wil6210_priv *wil) 988int wil6210_debugfs_init(struct wil6210_priv *wil)
967{ 989{
968 struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME, 990 struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME,
@@ -986,6 +1008,8 @@ int wil6210_debugfs_init(struct wil6210_priv *wil)
986 &wil->secure_pcp); 1008 &wil->secure_pcp);
987 wil_debugfs_create_ulong("status", S_IRUGO | S_IWUSR, dbg, 1009 wil_debugfs_create_ulong("status", S_IRUGO | S_IWUSR, dbg,
988 &wil->status); 1010 &wil->status);
1011 debugfs_create_u32("fw_version", S_IRUGO, dbg, &wil->fw_version);
1012 debugfs_create_x32("hw_version", S_IRUGO, dbg, &wil->hw_version);
989 1013
990 wil6210_debugfs_create_ISR(wil, "USER_ICR", dbg, 1014 wil6210_debugfs_create_ISR(wil, "USER_ICR", dbg,
991 HOSTADDR(RGF_USER_USER_ICR)); 1015 HOSTADDR(RGF_USER_USER_ICR));
@@ -998,6 +1022,9 @@ int wil6210_debugfs_init(struct wil6210_priv *wil)
998 wil6210_debugfs_create_pseudo_ISR(wil, dbg); 1022 wil6210_debugfs_create_pseudo_ISR(wil, dbg);
999 wil6210_debugfs_create_ITR_CNT(wil, dbg); 1023 wil6210_debugfs_create_ITR_CNT(wil, dbg);
1000 1024
1025 wil_debugfs_create_iomem_x32("RGF_USER_USAGE_1", S_IRUGO, dbg,
1026 wil->csr +
1027 HOSTADDR(RGF_USER_USAGE_1));
1001 debugfs_create_u32("mem_addr", S_IRUGO | S_IWUSR, dbg, &mem_addr); 1028 debugfs_create_u32("mem_addr", S_IRUGO | S_IWUSR, dbg, &mem_addr);
1002 debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread); 1029 debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread);
1003 1030
@@ -1010,34 +1037,7 @@ int wil6210_debugfs_init(struct wil6210_priv *wil)
1010 debugfs_create_file("link", S_IRUGO, dbg, wil, &fops_link); 1037 debugfs_create_file("link", S_IRUGO, dbg, wil, &fops_link);
1011 debugfs_create_file("info", S_IRUGO, dbg, wil, &fops_info); 1038 debugfs_create_file("info", S_IRUGO, dbg, wil, &fops_info);
1012 1039
1013 wil->rgf_blob.data = (void * __force)wil->csr + 0; 1040 wil6210_debugfs_init_blobs(wil, dbg);
1014 wil->rgf_blob.size = 0xa000;
1015 wil_debugfs_create_ioblob("blob_rgf", S_IRUGO, dbg, &wil->rgf_blob);
1016
1017 wil->fw_code_blob.data = (void * __force)wil->csr + 0x40000;
1018 wil->fw_code_blob.size = 0x40000;
1019 wil_debugfs_create_ioblob("blob_fw_code", S_IRUGO, dbg,
1020 &wil->fw_code_blob);
1021
1022 wil->fw_data_blob.data = (void * __force)wil->csr + 0x80000;
1023 wil->fw_data_blob.size = 0x8000;
1024 wil_debugfs_create_ioblob("blob_fw_data", S_IRUGO, dbg,
1025 &wil->fw_data_blob);
1026
1027 wil->fw_peri_blob.data = (void * __force)wil->csr + 0x88000;
1028 wil->fw_peri_blob.size = 0x18000;
1029 wil_debugfs_create_ioblob("blob_fw_peri", S_IRUGO, dbg,
1030 &wil->fw_peri_blob);
1031
1032 wil->uc_code_blob.data = (void * __force)wil->csr + 0xa0000;
1033 wil->uc_code_blob.size = 0x10000;
1034 wil_debugfs_create_ioblob("blob_uc_code", S_IRUGO, dbg,
1035 &wil->uc_code_blob);
1036
1037 wil->uc_data_blob.data = (void * __force)wil->csr + 0xb0000;
1038 wil->uc_data_blob.size = 0x4000;
1039 wil_debugfs_create_ioblob("blob_uc_data", S_IRUGO, dbg,
1040 &wil->uc_data_blob);
1041 1041
1042 return 0; 1042 return 0;
1043} 1043}
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 53a689ed7c7d..3704d2a434f3 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -314,8 +314,9 @@ static void wil_target_reset(struct wil6210_priv *wil)
314 int delay = 0; 314 int delay = 0;
315 u32 hw_state; 315 u32 hw_state;
316 u32 rev_id; 316 u32 rev_id;
317 bool is_sparrow = (wil->board->board == WIL_BOARD_SPARROW);
317 318
318 wil_dbg_misc(wil, "Resetting...\n"); 319 wil_dbg_misc(wil, "Resetting \"%s\"...\n", wil->board->name);
319 320
320 /* register read */ 321 /* register read */
321#define R(a) ioread32(wil->csr + HOSTADDR(a)) 322#define R(a) ioread32(wil->csr + HOSTADDR(a))
@@ -328,35 +329,59 @@ static void wil_target_reset(struct wil6210_priv *wil)
328 329
329 wil->hw_version = R(RGF_USER_FW_REV_ID); 330 wil->hw_version = R(RGF_USER_FW_REV_ID);
330 rev_id = wil->hw_version & 0xff; 331 rev_id = wil->hw_version & 0xff;
332
333 /* Clear MAC link up */
334 S(RGF_HP_CTRL, BIT(15));
331 /* hpal_perst_from_pad_src_n_mask */ 335 /* hpal_perst_from_pad_src_n_mask */
332 S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(6)); 336 S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(6));
333 /* car_perst_rst_src_n_mask */ 337 /* car_perst_rst_src_n_mask */
334 S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(7)); 338 S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(7));
335 wmb(); /* order is important here */ 339 wmb(); /* order is important here */
336 340
341 if (is_sparrow) {
342 W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x3ff81f);
343 wmb(); /* order is important here */
344 }
345
337 W(RGF_USER_MAC_CPU_0, BIT(1)); /* mac_cpu_man_rst */ 346 W(RGF_USER_MAC_CPU_0, BIT(1)); /* mac_cpu_man_rst */
338 W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */ 347 W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */
339 wmb(); /* order is important here */ 348 wmb(); /* order is important here */
340 349
341 W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000); 350 W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000);
342 W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F); 351 W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F);
343 W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000170); 352 W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, is_sparrow ? 0x000000B0 : 0x00000170);
344 W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00); 353 W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00);
345 wmb(); /* order is important here */ 354 wmb(); /* order is important here */
346 355
356 if (is_sparrow) {
357 W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x0);
358 wmb(); /* order is important here */
359 }
360
347 W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0); 361 W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0);
348 W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0); 362 W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0);
349 W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0); 363 W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0);
350 W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); 364 W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
351 wmb(); /* order is important here */ 365 wmb(); /* order is important here */
352 366
353 W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001); 367 if (is_sparrow) {
354 if (rev_id == 1) { 368 W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000003);
355 W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080); 369 /* reset A2 PCIE AHB */
356 } else {
357 W(RGF_PCIE_LOS_COUNTER_CTL, BIT(6) | BIT(8));
358 W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000); 370 W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000);
371
372 } else {
373 W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001);
374 if (rev_id == 1) {
375 /* reset A1 BOTH PCIE AHB & PCIE RGF */
376 W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080);
377 } else {
378 W(RGF_PCIE_LOS_COUNTER_CTL, BIT(6) | BIT(8));
379 W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000);
380 }
381
359 } 382 }
383
384 /* TODO: check order here!!! Erez code is different */
360 W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); 385 W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
361 wmb(); /* order is important here */ 386 wmb(); /* order is important here */
362 387
@@ -371,7 +396,8 @@ static void wil_target_reset(struct wil6210_priv *wil)
371 } 396 }
372 } while (hw_state != HW_MACHINE_BOOT_DONE); 397 } while (hw_state != HW_MACHINE_BOOT_DONE);
373 398
374 if (rev_id == 2) 399 /* TODO: Erez check rev_id != 1 */
400 if (!is_sparrow && (rev_id != 1))
375 W(RGF_PCIE_LOS_COUNTER_CTL, BIT(8)); 401 W(RGF_PCIE_LOS_COUNTER_CTL, BIT(8));
376 402
377 C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD); 403 C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c
index 77b6272d93fb..d3fbfa28db62 100644
--- a/drivers/net/wireless/ath/wil6210/pcie_bus.c
+++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c
@@ -122,10 +122,12 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
122 struct wil6210_priv *wil; 122 struct wil6210_priv *wil;
123 struct device *dev = &pdev->dev; 123 struct device *dev = &pdev->dev;
124 void __iomem *csr; 124 void __iomem *csr;
125 struct wil_board *board = (struct wil_board *)id->driver_data;
125 int rc; 126 int rc;
126 127
127 /* check HW */ 128 /* check HW */
128 dev_info(&pdev->dev, WIL_NAME " device found [%04x:%04x] (rev %x)\n", 129 dev_info(&pdev->dev, WIL_NAME
130 " \"%s\" device found [%04x:%04x] (rev %x)\n", board->name,
129 (int)pdev->vendor, (int)pdev->device, (int)pdev->revision); 131 (int)pdev->vendor, (int)pdev->device, (int)pdev->revision);
130 132
131 if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) { 133 if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) {
@@ -175,6 +177,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
175 177
176 pci_set_drvdata(pdev, wil); 178 pci_set_drvdata(pdev, wil);
177 wil->pdev = pdev; 179 wil->pdev = pdev;
180 wil->board = board;
178 181
179 wil6210_clear_irq(wil); 182 wil6210_clear_irq(wil);
180 /* FW should raise IRQ when ready */ 183 /* FW should raise IRQ when ready */
@@ -225,8 +228,21 @@ static void wil_pcie_remove(struct pci_dev *pdev)
225 pci_disable_device(pdev); 228 pci_disable_device(pdev);
226} 229}
227 230
228static DEFINE_PCI_DEVICE_TABLE(wil6210_pcie_ids) = { 231static const struct wil_board wil_board_marlon = {
229 { PCI_DEVICE(0x1ae9, 0x0301) }, 232 .board = WIL_BOARD_MARLON,
233 .name = "marlon",
234};
235
236static const struct wil_board wil_board_sparrow = {
237 .board = WIL_BOARD_SPARROW,
238 .name = "sparrow",
239};
240
241static const struct pci_device_id wil6210_pcie_ids[] = {
242 { PCI_DEVICE(0x1ae9, 0x0301),
243 .driver_data = (kernel_ulong_t)&wil_board_marlon },
244 { PCI_DEVICE(0x1ae9, 0x0310),
245 .driver_data = (kernel_ulong_t)&wil_board_sparrow },
230 { /* end: all zeroes */ }, 246 { /* end: all zeroes */ },
231}; 247};
232MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids); 248MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids);
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index af4b93e4beb5..d3467943d39d 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -1108,8 +1108,10 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
1108 while (vring->swtail != new_swtail) { 1108 while (vring->swtail != new_swtail) {
1109 struct vring_tx_desc dd, *d = &dd; 1109 struct vring_tx_desc dd, *d = &dd;
1110 u16 dmalen; 1110 u16 dmalen;
1111 struct wil_ctx *ctx = &vring->ctx[vring->swtail]; 1111 struct sk_buff *skb;
1112 struct sk_buff *skb = ctx->skb; 1112
1113 ctx = &vring->ctx[vring->swtail];
1114 skb = ctx->skb;
1113 _d = &vring->va[vring->swtail].tx; 1115 _d = &vring->va[vring->swtail].tx;
1114 1116
1115 *d = *_d; 1117 *d = *_d;
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 424906635f05..67e9624f7111 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -24,6 +24,13 @@
24 24
25#define WIL_NAME "wil6210" 25#define WIL_NAME "wil6210"
26 26
27struct wil_board {
28 int board;
29#define WIL_BOARD_MARLON (1)
30#define WIL_BOARD_SPARROW (2)
31 const char * const name;
32};
33
27/** 34/**
28 * extract bits [@b0:@b1] (inclusive) from the value @x 35 * extract bits [@b0:@b1] (inclusive) from the value @x
29 * it should be @b0 <= @b1, or result is incorrect 36 * it should be @b0 <= @b1, or result is incorrect
@@ -78,6 +85,7 @@ struct RGF_ICR {
78} __packed; 85} __packed;
79 86
80/* registers - FW addresses */ 87/* registers - FW addresses */
88#define RGF_USER_USAGE_1 (0x880004)
81#define RGF_USER_HW_MACHINE_STATE (0x8801dc) 89#define RGF_USER_HW_MACHINE_STATE (0x8801dc)
82 #define HW_MACHINE_BOOT_DONE (0x3fffffd) 90 #define HW_MACHINE_BOOT_DONE (0x3fffffd)
83#define RGF_USER_USER_CPU_0 (0x8801e0) 91#define RGF_USER_USER_CPU_0 (0x8801e0)
@@ -93,6 +101,7 @@ struct RGF_ICR {
93#define RGF_USER_CLKS_CTL_SW_RST_MASK_0 (0x880b14) 101#define RGF_USER_CLKS_CTL_SW_RST_MASK_0 (0x880b14)
94#define RGF_USER_USER_ICR (0x880b4c) /* struct RGF_ICR */ 102#define RGF_USER_USER_ICR (0x880b4c) /* struct RGF_ICR */
95 #define BIT_USER_USER_ICR_SW_INT_2 BIT(18) 103 #define BIT_USER_USER_ICR_SW_INT_2 BIT(18)
104#define RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0 (0x880c18)
96 105
97#define RGF_DMA_EP_TX_ICR (0x881bb4) /* struct RGF_ICR */ 106#define RGF_DMA_EP_TX_ICR (0x881bb4) /* struct RGF_ICR */
98 #define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0) 107 #define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0)
@@ -121,6 +130,7 @@ struct RGF_ICR {
121 #define BIT_DMA_PSEUDO_CAUSE_TX BIT(1) 130 #define BIT_DMA_PSEUDO_CAUSE_TX BIT(1)
122 #define BIT_DMA_PSEUDO_CAUSE_MISC BIT(2) 131 #define BIT_DMA_PSEUDO_CAUSE_MISC BIT(2)
123 132
133#define RGF_HP_CTRL (0x88265c)
124#define RGF_PCIE_LOS_COUNTER_CTL (0x882dc4) 134#define RGF_PCIE_LOS_COUNTER_CTL (0x882dc4)
125 135
126/* popular locations */ 136/* popular locations */
@@ -135,6 +145,14 @@ struct RGF_ICR {
135#define ISR_MISC_FW_ERROR BIT_DMA_EP_MISC_ICR_FW_INT(3) 145#define ISR_MISC_FW_ERROR BIT_DMA_EP_MISC_ICR_FW_INT(3)
136 146
137/* Hardware definitions end */ 147/* Hardware definitions end */
148struct fw_map {
149 u32 from; /* linker address - from, inclusive */
150 u32 to; /* linker address - to, exclusive */
151 u32 host; /* PCI/Host address - BAR0 + 0x880000 */
152 const char *name; /* for debugfs */
153};
154/* array size should be in sync with actual definition in the wmi.c */
155extern const struct fw_map fw_mapping[7];
138 156
139/** 157/**
140 * mk_cidxtid - construct @cidxtid field 158 * mk_cidxtid - construct @cidxtid field
@@ -365,6 +383,7 @@ struct wil6210_priv {
365 ulong status; 383 ulong status;
366 u32 fw_version; 384 u32 fw_version;
367 u32 hw_version; 385 u32 hw_version;
386 struct wil_board *board;
368 u8 n_mids; /* number of additional MIDs as reported by FW */ 387 u8 n_mids; /* number of additional MIDs as reported by FW */
369 int recovery_count; /* num of FW recovery attempts in a short time */ 388 int recovery_count; /* num of FW recovery attempts in a short time */
370 unsigned long last_fw_recovery; /* jiffies of last fw recovery */ 389 unsigned long last_fw_recovery; /* jiffies of last fw recovery */
@@ -415,12 +434,7 @@ struct wil6210_priv {
415 atomic_t isr_count_rx, isr_count_tx; 434 atomic_t isr_count_rx, isr_count_tx;
416 /* debugfs */ 435 /* debugfs */
417 struct dentry *debug; 436 struct dentry *debug;
418 struct debugfs_blob_wrapper fw_code_blob; 437 struct debugfs_blob_wrapper blobs[ARRAY_SIZE(fw_mapping)];
419 struct debugfs_blob_wrapper fw_data_blob;
420 struct debugfs_blob_wrapper fw_peri_blob;
421 struct debugfs_blob_wrapper uc_code_blob;
422 struct debugfs_blob_wrapper uc_data_blob;
423 struct debugfs_blob_wrapper rgf_blob;
424}; 438};
425 439
426#define wil_to_wiphy(i) (i->wdev->wiphy) 440#define wil_to_wiphy(i) (i->wdev->wiphy)
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index a136dab560e2..1d1d0afdd2e1 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -65,18 +65,17 @@
65 65
66/** 66/**
67 * @fw_mapping provides memory remapping table 67 * @fw_mapping provides memory remapping table
68 *
69 * array size should be in sync with the declaration in the wil6210.h
68 */ 70 */
69static const struct { 71const struct fw_map fw_mapping[] = {
70 u32 from; /* linker address - from, inclusive */ 72 {0x000000, 0x040000, 0x8c0000, "fw_code"}, /* FW code RAM 256k */
71 u32 to; /* linker address - to, exclusive */ 73 {0x800000, 0x808000, 0x900000, "fw_data"}, /* FW data RAM 32k */
72 u32 host; /* PCI/Host address - BAR0 + 0x880000 */ 74 {0x840000, 0x860000, 0x908000, "fw_peri"}, /* periph. data RAM 128k */
73} fw_mapping[] = { 75 {0x880000, 0x88a000, 0x880000, "rgf"}, /* various RGF 40k */
74 {0x000000, 0x040000, 0x8c0000}, /* FW code RAM 256k */ 76 {0x88a000, 0x88b000, 0x88a000, "AGC_tbl"}, /* AGC table 4k */
75 {0x800000, 0x808000, 0x900000}, /* FW data RAM 32k */ 77 {0x88b000, 0x88c000, 0x88b000, "rgf_ext"}, /* Pcie_ext_rgf 4k */
76 {0x840000, 0x860000, 0x908000}, /* peripheral data RAM 128k/96k used */ 78 {0x8c0000, 0x949000, 0x8c0000, "upper"}, /* upper area 548k */
77 {0x880000, 0x88a000, 0x880000}, /* various RGF */
78 {0x88b000, 0x88c000, 0x88b000}, /* Pcie_ext_rgf */
79 {0x8c0000, 0x949000, 0x8c0000}, /* trivial mapping for upper area */
80 /* 79 /*
81 * 920000..930000 ucode code RAM 80 * 920000..930000 ucode code RAM
82 * 930000..932000 ucode data RAM 81 * 930000..932000 ucode data RAM
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 15aaeb132a32..d7055febe119 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -210,6 +210,9 @@ static struct ieee80211_channel b43_2ghz_chantable[] = {
210 CHAN2G(13, 2472, 0), 210 CHAN2G(13, 2472, 0),
211 CHAN2G(14, 2484, 0), 211 CHAN2G(14, 2484, 0),
212}; 212};
213
214/* No support for the last 3 channels (12, 13, 14) */
215#define b43_2ghz_chantable_limited_size 11
213#undef CHAN2G 216#undef CHAN2G
214 217
215#define CHAN4G(_channel, _flags) { \ 218#define CHAN4G(_channel, _flags) { \
@@ -287,6 +290,14 @@ static struct ieee80211_channel b43_5ghz_nphy_chantable[] = {
287 CHAN5G(182, 0), 290 CHAN5G(182, 0),
288}; 291};
289 292
293static struct ieee80211_channel b43_5ghz_nphy_chantable_limited[] = {
294 CHAN5G(36, 0), CHAN5G(40, 0),
295 CHAN5G(44, 0), CHAN5G(48, 0),
296 CHAN5G(149, 0), CHAN5G(153, 0),
297 CHAN5G(157, 0), CHAN5G(161, 0),
298 CHAN5G(165, 0),
299};
300
290static struct ieee80211_channel b43_5ghz_aphy_chantable[] = { 301static struct ieee80211_channel b43_5ghz_aphy_chantable[] = {
291 CHAN5G(34, 0), CHAN5G(36, 0), 302 CHAN5G(34, 0), CHAN5G(36, 0),
292 CHAN5G(38, 0), CHAN5G(40, 0), 303 CHAN5G(38, 0), CHAN5G(40, 0),
@@ -319,6 +330,14 @@ static struct ieee80211_supported_band b43_band_5GHz_nphy = {
319 .n_bitrates = b43_a_ratetable_size, 330 .n_bitrates = b43_a_ratetable_size,
320}; 331};
321 332
333static struct ieee80211_supported_band b43_band_5GHz_nphy_limited = {
334 .band = IEEE80211_BAND_5GHZ,
335 .channels = b43_5ghz_nphy_chantable_limited,
336 .n_channels = ARRAY_SIZE(b43_5ghz_nphy_chantable_limited),
337 .bitrates = b43_a_ratetable,
338 .n_bitrates = b43_a_ratetable_size,
339};
340
322static struct ieee80211_supported_band b43_band_5GHz_aphy = { 341static struct ieee80211_supported_band b43_band_5GHz_aphy = {
323 .band = IEEE80211_BAND_5GHZ, 342 .band = IEEE80211_BAND_5GHZ,
324 .channels = b43_5ghz_aphy_chantable, 343 .channels = b43_5ghz_aphy_chantable,
@@ -335,6 +354,14 @@ static struct ieee80211_supported_band b43_band_2GHz = {
335 .n_bitrates = b43_g_ratetable_size, 354 .n_bitrates = b43_g_ratetable_size,
336}; 355};
337 356
357static struct ieee80211_supported_band b43_band_2ghz_limited = {
358 .band = IEEE80211_BAND_2GHZ,
359 .channels = b43_2ghz_chantable,
360 .n_channels = b43_2ghz_chantable_limited_size,
361 .bitrates = b43_g_ratetable,
362 .n_bitrates = b43_g_ratetable_size,
363};
364
338static void b43_wireless_core_exit(struct b43_wldev *dev); 365static void b43_wireless_core_exit(struct b43_wldev *dev);
339static int b43_wireless_core_init(struct b43_wldev *dev); 366static int b43_wireless_core_init(struct b43_wldev *dev);
340static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev); 367static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev);
@@ -2953,6 +2980,45 @@ void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on)
2953 } 2980 }
2954} 2981}
2955 2982
2983/* brcms_b_switch_macfreq */
2984void b43_mac_switch_freq(struct b43_wldev *dev, u8 spurmode)
2985{
2986 u16 chip_id = dev->dev->chip_id;
2987
2988 if (chip_id == BCMA_CHIP_ID_BCM43217 ||
2989 chip_id == BCMA_CHIP_ID_BCM43222 ||
2990 chip_id == BCMA_CHIP_ID_BCM43224 ||
2991 chip_id == BCMA_CHIP_ID_BCM43225 ||
2992 chip_id == BCMA_CHIP_ID_BCM43227 ||
2993 chip_id == BCMA_CHIP_ID_BCM43228) {
2994 switch (spurmode) {
2995 case 2: /* 126 Mhz */
2996 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x2082);
2997 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
2998 break;
2999 case 1: /* 123 Mhz */
3000 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x5341);
3001 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
3002 break;
3003 default: /* 120 Mhz */
3004 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x8889);
3005 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
3006 break;
3007 }
3008 } else if (dev->phy.type == B43_PHYTYPE_LCN) {
3009 switch (spurmode) {
3010 case 1: /* 82 Mhz */
3011 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x7CE0);
3012 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
3013 break;
3014 default: /* 80 Mhz */
3015 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0xCCCD);
3016 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
3017 break;
3018 }
3019 }
3020}
3021
2956static void b43_adjust_opmode(struct b43_wldev *dev) 3022static void b43_adjust_opmode(struct b43_wldev *dev)
2957{ 3023{
2958 struct b43_wl *wl = dev->wl; 3024 struct b43_wl *wl = dev->wl;
@@ -4335,8 +4401,9 @@ static int b43_phy_versioning(struct b43_wldev *dev)
4335 u8 phy_type; 4401 u8 phy_type;
4336 u8 phy_rev; 4402 u8 phy_rev;
4337 u16 radio_manuf; 4403 u16 radio_manuf;
4338 u16 radio_ver; 4404 u16 radio_id;
4339 u16 radio_rev; 4405 u16 radio_rev;
4406 u8 radio_ver;
4340 int unsupported = 0; 4407 int unsupported = 0;
4341 4408
4342 /* Get PHY versioning */ 4409 /* Get PHY versioning */
@@ -4360,7 +4427,7 @@ static int b43_phy_versioning(struct b43_wldev *dev)
4360#endif 4427#endif
4361#ifdef CONFIG_B43_PHY_N 4428#ifdef CONFIG_B43_PHY_N
4362 case B43_PHYTYPE_N: 4429 case B43_PHYTYPE_N:
4363 if (phy_rev > 9) 4430 if (phy_rev >= 19)
4364 unsupported = 1; 4431 unsupported = 1;
4365 break; 4432 break;
4366#endif 4433#endif
@@ -4402,7 +4469,9 @@ static int b43_phy_versioning(struct b43_wldev *dev)
4402 radio_rev = b43_read16(dev, B43_MMIO_RADIO24_DATA); 4469 radio_rev = b43_read16(dev, B43_MMIO_RADIO24_DATA);
4403 4470
4404 b43_write16(dev, B43_MMIO_RADIO24_CONTROL, 1); 4471 b43_write16(dev, B43_MMIO_RADIO24_CONTROL, 1);
4405 radio_ver = b43_read16(dev, B43_MMIO_RADIO24_DATA); 4472 radio_id = b43_read16(dev, B43_MMIO_RADIO24_DATA);
4473
4474 radio_ver = 0; /* Is there version somewhere? */
4406 } else if (core_rev >= 24) { 4475 } else if (core_rev >= 24) {
4407 u16 radio24[3]; 4476 u16 radio24[3];
4408 4477
@@ -4411,12 +4480,10 @@ static int b43_phy_versioning(struct b43_wldev *dev)
4411 radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA); 4480 radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA);
4412 } 4481 }
4413 4482
4414 /* Broadcom uses "id" for our "ver" and has separated "ver" */
4415 /* radio_ver = (radio24[0] & 0xF0) >> 4; */
4416
4417 radio_manuf = 0x17F; 4483 radio_manuf = 0x17F;
4418 radio_ver = (radio24[2] << 8) | radio24[1]; 4484 radio_id = (radio24[2] << 8) | radio24[1];
4419 radio_rev = (radio24[0] & 0xF); 4485 radio_rev = (radio24[0] & 0xF);
4486 radio_ver = (radio24[0] & 0xF0) >> 4;
4420 } else { 4487 } else {
4421 if (dev->dev->chip_id == 0x4317) { 4488 if (dev->dev->chip_id == 0x4317) {
4422 if (dev->dev->chip_rev == 0) 4489 if (dev->dev->chip_rev == 0)
@@ -4435,15 +4502,16 @@ static int b43_phy_versioning(struct b43_wldev *dev)
4435 << 16; 4502 << 16;
4436 } 4503 }
4437 radio_manuf = (tmp & 0x00000FFF); 4504 radio_manuf = (tmp & 0x00000FFF);
4438 radio_ver = (tmp & 0x0FFFF000) >> 12; 4505 radio_id = (tmp & 0x0FFFF000) >> 12;
4439 radio_rev = (tmp & 0xF0000000) >> 28; 4506 radio_rev = (tmp & 0xF0000000) >> 28;
4507 radio_ver = 0; /* Probably not available on old hw */
4440 } 4508 }
4441 4509
4442 if (radio_manuf != 0x17F /* Broadcom */) 4510 if (radio_manuf != 0x17F /* Broadcom */)
4443 unsupported = 1; 4511 unsupported = 1;
4444 switch (phy_type) { 4512 switch (phy_type) {
4445 case B43_PHYTYPE_A: 4513 case B43_PHYTYPE_A:
4446 if (radio_ver != 0x2060) 4514 if (radio_id != 0x2060)
4447 unsupported = 1; 4515 unsupported = 1;
4448 if (radio_rev != 1) 4516 if (radio_rev != 1)
4449 unsupported = 1; 4517 unsupported = 1;
@@ -4451,43 +4519,49 @@ static int b43_phy_versioning(struct b43_wldev *dev)
4451 unsupported = 1; 4519 unsupported = 1;
4452 break; 4520 break;
4453 case B43_PHYTYPE_B: 4521 case B43_PHYTYPE_B:
4454 if ((radio_ver & 0xFFF0) != 0x2050) 4522 if ((radio_id & 0xFFF0) != 0x2050)
4455 unsupported = 1; 4523 unsupported = 1;
4456 break; 4524 break;
4457 case B43_PHYTYPE_G: 4525 case B43_PHYTYPE_G:
4458 if (radio_ver != 0x2050) 4526 if (radio_id != 0x2050)
4459 unsupported = 1; 4527 unsupported = 1;
4460 break; 4528 break;
4461 case B43_PHYTYPE_N: 4529 case B43_PHYTYPE_N:
4462 if (radio_ver != 0x2055 && radio_ver != 0x2056) 4530 if (radio_id != 0x2055 && radio_id != 0x2056 &&
4531 radio_id != 0x2057)
4532 unsupported = 1;
4533 if (radio_id == 0x2057 &&
4534 !(radio_rev == 9 || radio_rev == 14))
4463 unsupported = 1; 4535 unsupported = 1;
4464 break; 4536 break;
4465 case B43_PHYTYPE_LP: 4537 case B43_PHYTYPE_LP:
4466 if (radio_ver != 0x2062 && radio_ver != 0x2063) 4538 if (radio_id != 0x2062 && radio_id != 0x2063)
4467 unsupported = 1; 4539 unsupported = 1;
4468 break; 4540 break;
4469 case B43_PHYTYPE_HT: 4541 case B43_PHYTYPE_HT:
4470 if (radio_ver != 0x2059) 4542 if (radio_id != 0x2059)
4471 unsupported = 1; 4543 unsupported = 1;
4472 break; 4544 break;
4473 case B43_PHYTYPE_LCN: 4545 case B43_PHYTYPE_LCN:
4474 if (radio_ver != 0x2064) 4546 if (radio_id != 0x2064)
4475 unsupported = 1; 4547 unsupported = 1;
4476 break; 4548 break;
4477 default: 4549 default:
4478 B43_WARN_ON(1); 4550 B43_WARN_ON(1);
4479 } 4551 }
4480 if (unsupported) { 4552 if (unsupported) {
4481 b43err(dev->wl, "FOUND UNSUPPORTED RADIO " 4553 b43err(dev->wl,
4482 "(Manuf 0x%X, Version 0x%X, Revision %u)\n", 4554 "FOUND UNSUPPORTED RADIO (Manuf 0x%X, ID 0x%X, Revision %u, Version %u)\n",
4483 radio_manuf, radio_ver, radio_rev); 4555 radio_manuf, radio_id, radio_rev, radio_ver);
4484 return -EOPNOTSUPP; 4556 return -EOPNOTSUPP;
4485 } 4557 }
4486 b43dbg(dev->wl, "Found Radio: Manuf 0x%X, Version 0x%X, Revision %u\n", 4558 b43info(dev->wl,
4487 radio_manuf, radio_ver, radio_rev); 4559 "Found Radio: Manuf 0x%X, ID 0x%X, Revision %u, Version %u\n",
4560 radio_manuf, radio_id, radio_rev, radio_ver);
4488 4561
4562 /* FIXME: b43 treats "id" as "ver" and ignores the real "ver" */
4489 phy->radio_manuf = radio_manuf; 4563 phy->radio_manuf = radio_manuf;
4490 phy->radio_ver = radio_ver; 4564 phy->radio_ver = radio_id;
4491 phy->radio_rev = radio_rev; 4565 phy->radio_rev = radio_rev;
4492 4566
4493 phy->analog = analog_type; 4567 phy->analog = analog_type;
@@ -5095,12 +5169,24 @@ static int b43_setup_bands(struct b43_wldev *dev,
5095 bool have_2ghz_phy, bool have_5ghz_phy) 5169 bool have_2ghz_phy, bool have_5ghz_phy)
5096{ 5170{
5097 struct ieee80211_hw *hw = dev->wl->hw; 5171 struct ieee80211_hw *hw = dev->wl->hw;
5172 struct b43_phy *phy = &dev->phy;
5173 bool limited_2g;
5174 bool limited_5g;
5175
5176 /* We don't support all 2 GHz channels on some devices */
5177 limited_2g = phy->radio_ver == 0x2057 &&
5178 (phy->radio_rev == 9 || phy->radio_rev == 14);
5179 limited_5g = phy->radio_ver == 0x2057 &&
5180 phy->radio_rev == 9;
5098 5181
5099 if (have_2ghz_phy) 5182 if (have_2ghz_phy)
5100 hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &b43_band_2GHz; 5183 hw->wiphy->bands[IEEE80211_BAND_2GHZ] = limited_2g ?
5184 &b43_band_2ghz_limited : &b43_band_2GHz;
5101 if (dev->phy.type == B43_PHYTYPE_N) { 5185 if (dev->phy.type == B43_PHYTYPE_N) {
5102 if (have_5ghz_phy) 5186 if (have_5ghz_phy)
5103 hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_nphy; 5187 hw->wiphy->bands[IEEE80211_BAND_5GHZ] = limited_5g ?
5188 &b43_band_5GHz_nphy_limited :
5189 &b43_band_5GHz_nphy;
5104 } else { 5190 } else {
5105 if (have_5ghz_phy) 5191 if (have_5ghz_phy)
5106 hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_aphy; 5192 hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_aphy;
@@ -5248,14 +5334,15 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
5248 b43_supported_bands(dev, &have_2ghz_phy, &have_5ghz_phy); 5334 b43_supported_bands(dev, &have_2ghz_phy, &have_5ghz_phy);
5249 5335
5250 /* We don't support 5 GHz on some PHYs yet */ 5336 /* We don't support 5 GHz on some PHYs yet */
5251 switch (dev->phy.type) { 5337 if (have_5ghz_phy) {
5252 case B43_PHYTYPE_A: 5338 switch (dev->phy.type) {
5253 case B43_PHYTYPE_G: 5339 case B43_PHYTYPE_A:
5254 case B43_PHYTYPE_N: 5340 case B43_PHYTYPE_G:
5255 case B43_PHYTYPE_LP: 5341 case B43_PHYTYPE_LP:
5256 case B43_PHYTYPE_HT: 5342 case B43_PHYTYPE_HT:
5257 b43warn(wl, "5 GHz band is unsupported on this PHY\n"); 5343 b43warn(wl, "5 GHz band is unsupported on this PHY\n");
5258 have_5ghz_phy = false; 5344 have_5ghz_phy = false;
5345 }
5259 } 5346 }
5260 5347
5261 if (!have_2ghz_phy && !have_5ghz_phy) { 5348 if (!have_2ghz_phy && !have_5ghz_phy) {
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
index f476fc337d64..9f22e4b4c132 100644
--- a/drivers/net/wireless/b43/main.h
+++ b/drivers/net/wireless/b43/main.h
@@ -99,6 +99,7 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags);
99void b43_mac_suspend(struct b43_wldev *dev); 99void b43_mac_suspend(struct b43_wldev *dev);
100void b43_mac_enable(struct b43_wldev *dev); 100void b43_mac_enable(struct b43_wldev *dev);
101void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on); 101void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on);
102void b43_mac_switch_freq(struct b43_wldev *dev, u8 spurmode);
102 103
103 104
104struct b43_request_fw_context; 105struct b43_request_fw_context;
diff --git a/drivers/net/wireless/b43/phy_lcn.c b/drivers/net/wireless/b43/phy_lcn.c
index 0bafa3b17035..e76bbdf3247e 100644
--- a/drivers/net/wireless/b43/phy_lcn.c
+++ b/drivers/net/wireless/b43/phy_lcn.c
@@ -54,39 +54,6 @@ enum lcn_sense_type {
54 B43_SENSE_VBAT, 54 B43_SENSE_VBAT,
55}; 55};
56 56
57/* In theory it's PHY common function, move if needed */
58/* brcms_b_switch_macfreq */
59static void b43_phy_switch_macfreq(struct b43_wldev *dev, u8 spurmode)
60{
61 if (dev->dev->chip_id == 43224 || dev->dev->chip_id == 43225) {
62 switch (spurmode) {
63 case 2: /* 126 Mhz */
64 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x2082);
65 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
66 break;
67 case 1: /* 123 Mhz */
68 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x5341);
69 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
70 break;
71 default: /* 120 Mhz */
72 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x8889);
73 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
74 break;
75 }
76 } else if (dev->phy.type == B43_PHYTYPE_LCN) {
77 switch (spurmode) {
78 case 1: /* 82 Mhz */
79 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x7CE0);
80 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
81 break;
82 default: /* 80 Mhz */
83 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0xCCCD);
84 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
85 break;
86 }
87 }
88}
89
90/************************************************** 57/**************************************************
91 * Radio 2064. 58 * Radio 2064.
92 **************************************************/ 59 **************************************************/
@@ -609,7 +576,7 @@ static void b43_phy_lcn_txrx_spur_avoidance_mode(struct b43_wldev *dev,
609 b43_phy_write(dev, 0x93b, ((0 << 13) + 23)); 576 b43_phy_write(dev, 0x93b, ((0 << 13) + 23));
610 b43_phy_write(dev, 0x93c, ((0 << 13) + 1989)); 577 b43_phy_write(dev, 0x93c, ((0 << 13) + 1989));
611 } 578 }
612 b43_phy_switch_macfreq(dev, enable); 579 b43_mac_switch_freq(dev, enable);
613} 580}
614 581
615/************************************************** 582/**************************************************
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index 50ca6f87d5e8..d269fbb27b9e 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -36,6 +36,7 @@
36#include "main.h" 36#include "main.h"
37 37
38struct nphy_txgains { 38struct nphy_txgains {
39 u16 tx_lpf[2];
39 u16 txgm[2]; 40 u16 txgm[2];
40 u16 pga[2]; 41 u16 pga[2];
41 u16 pad[2]; 42 u16 pad[2];
@@ -43,6 +44,7 @@ struct nphy_txgains {
43}; 44};
44 45
45struct nphy_iqcal_params { 46struct nphy_iqcal_params {
47 u16 tx_lpf;
46 u16 txgm; 48 u16 txgm;
47 u16 pga; 49 u16 pga;
48 u16 pad; 50 u16 pad;
@@ -69,6 +71,14 @@ enum b43_nphy_rf_sequence {
69 B43_RFSEQ_UPDATE_GAINU, 71 B43_RFSEQ_UPDATE_GAINU,
70}; 72};
71 73
74enum n_rf_ctl_over_cmd {
75 N_RF_CTL_OVER_CMD_RXRF_PU = 0,
76 N_RF_CTL_OVER_CMD_RX_PU = 1,
77 N_RF_CTL_OVER_CMD_TX_PU = 2,
78 N_RF_CTL_OVER_CMD_RX_GAIN = 3,
79 N_RF_CTL_OVER_CMD_TX_GAIN = 4,
80};
81
72enum n_intc_override { 82enum n_intc_override {
73 N_INTC_OVERRIDE_OFF = 0, 83 N_INTC_OVERRIDE_OFF = 0,
74 N_INTC_OVERRIDE_TRSW = 1, 84 N_INTC_OVERRIDE_TRSW = 1,
@@ -140,11 +150,19 @@ ok:
140 b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode); 150 b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
141} 151}
142 152
153static void b43_nphy_rf_ctl_override_rev19(struct b43_wldev *dev, u16 field,
154 u16 value, u8 core, bool off,
155 u8 override_id)
156{
157 /* TODO */
158}
159
143/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverrideRev7 */ 160/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverrideRev7 */
144static void b43_nphy_rf_ctl_override_rev7(struct b43_wldev *dev, u16 field, 161static void b43_nphy_rf_ctl_override_rev7(struct b43_wldev *dev, u16 field,
145 u16 value, u8 core, bool off, 162 u16 value, u8 core, bool off,
146 u8 override) 163 u8 override)
147{ 164{
165 struct b43_phy *phy = &dev->phy;
148 const struct nphy_rf_control_override_rev7 *e; 166 const struct nphy_rf_control_override_rev7 *e;
149 u16 en_addrs[3][2] = { 167 u16 en_addrs[3][2] = {
150 { 0x0E7, 0x0EC }, { 0x342, 0x343 }, { 0x346, 0x347 } 168 { 0x0E7, 0x0EC }, { 0x342, 0x343 }, { 0x346, 0x347 }
@@ -154,6 +172,11 @@ static void b43_nphy_rf_ctl_override_rev7(struct b43_wldev *dev, u16 field,
154 u16 val_addr; 172 u16 val_addr;
155 u8 i; 173 u8 i;
156 174
175 if (phy->rev >= 19 || phy->rev < 3) {
176 B43_WARN_ON(1);
177 return;
178 }
179
157 /* Remember: we can get NULL! */ 180 /* Remember: we can get NULL! */
158 e = b43_nphy_get_rf_ctl_over_rev7(dev, field, override); 181 e = b43_nphy_get_rf_ctl_over_rev7(dev, field, override);
159 182
@@ -181,6 +204,50 @@ static void b43_nphy_rf_ctl_override_rev7(struct b43_wldev *dev, u16 field,
181 } 204 }
182} 205}
183 206
207/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverideOneToMany */
208static void b43_nphy_rf_ctl_override_one_to_many(struct b43_wldev *dev,
209 enum n_rf_ctl_over_cmd cmd,
210 u16 value, u8 core, bool off)
211{
212 struct b43_phy *phy = &dev->phy;
213 u16 tmp;
214
215 B43_WARN_ON(phy->rev < 7);
216
217 switch (cmd) {
218 case N_RF_CTL_OVER_CMD_RXRF_PU:
219 b43_nphy_rf_ctl_override_rev7(dev, 0x20, value, core, off, 1);
220 b43_nphy_rf_ctl_override_rev7(dev, 0x10, value, core, off, 1);
221 b43_nphy_rf_ctl_override_rev7(dev, 0x08, value, core, off, 1);
222 break;
223 case N_RF_CTL_OVER_CMD_RX_PU:
224 b43_nphy_rf_ctl_override_rev7(dev, 0x4, value, core, off, 1);
225 b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 1);
226 b43_nphy_rf_ctl_override_rev7(dev, 0x1, value, core, off, 1);
227 b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 2);
228 b43_nphy_rf_ctl_override_rev7(dev, 0x0800, 0, core, off, 1);
229 break;
230 case N_RF_CTL_OVER_CMD_TX_PU:
231 b43_nphy_rf_ctl_override_rev7(dev, 0x4, value, core, off, 0);
232 b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 1);
233 b43_nphy_rf_ctl_override_rev7(dev, 0x1, value, core, off, 2);
234 b43_nphy_rf_ctl_override_rev7(dev, 0x0800, 1, core, off, 1);
235 break;
236 case N_RF_CTL_OVER_CMD_RX_GAIN:
237 tmp = value & 0xFF;
238 b43_nphy_rf_ctl_override_rev7(dev, 0x0800, tmp, core, off, 0);
239 tmp = value >> 8;
240 b43_nphy_rf_ctl_override_rev7(dev, 0x6000, tmp, core, off, 0);
241 break;
242 case N_RF_CTL_OVER_CMD_TX_GAIN:
243 tmp = value & 0x7FFF;
244 b43_nphy_rf_ctl_override_rev7(dev, 0x1000, tmp, core, off, 0);
245 tmp = value >> 14;
246 b43_nphy_rf_ctl_override_rev7(dev, 0x4000, tmp, core, off, 0);
247 break;
248 }
249}
250
184/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */ 251/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */
185static void b43_nphy_rf_ctl_override(struct b43_wldev *dev, u16 field, 252static void b43_nphy_rf_ctl_override(struct b43_wldev *dev, u16 field,
186 u16 value, u8 core, bool off) 253 u16 value, u8 core, bool off)
@@ -264,6 +331,8 @@ static void b43_nphy_rf_ctl_intc_override_rev7(struct b43_wldev *dev,
264 u16 reg, tmp, tmp2, val; 331 u16 reg, tmp, tmp2, val;
265 int core; 332 int core;
266 333
334 /* TODO: What about rev19+? Revs 3+ and 7+ are a bit similar */
335
267 for (core = 0; core < 2; core++) { 336 for (core = 0; core < 2; core++) {
268 if ((core_sel == 1 && core != 0) || 337 if ((core_sel == 1 && core != 0) ||
269 (core_sel == 2 && core != 1)) 338 (core_sel == 2 && core != 1))
@@ -274,6 +343,7 @@ static void b43_nphy_rf_ctl_intc_override_rev7(struct b43_wldev *dev,
274 switch (intc_override) { 343 switch (intc_override) {
275 case N_INTC_OVERRIDE_OFF: 344 case N_INTC_OVERRIDE_OFF:
276 b43_phy_write(dev, reg, 0); 345 b43_phy_write(dev, reg, 0);
346 b43_phy_mask(dev, 0x2ff, ~0x2000);
277 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); 347 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
278 break; 348 break;
279 case N_INTC_OVERRIDE_TRSW: 349 case N_INTC_OVERRIDE_TRSW:
@@ -505,6 +575,14 @@ static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable)
505 } 575 }
506} 576}
507 577
578/* http://bcm-v4.sipsolutions.net/PHY/N/Read_Lpf_Bw_Ctl */
579static u16 b43_nphy_read_lpf_ctl(struct b43_wldev *dev, u16 offset)
580{
581 if (!offset)
582 offset = b43_is_40mhz(dev) ? 0x159 : 0x154;
583 return b43_ntab_read(dev, B43_NTAB16(7, offset)) & 0x7;
584}
585
508/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */ 586/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */
509static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev) 587static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
510{ 588{
@@ -669,10 +747,63 @@ static void b43_radio_2057_setup(struct b43_wldev *dev,
669 b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x8); 747 b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x8);
670 } 748 }
671 break; 749 break;
672 /* TODO */ 750 case 9: /* e.g. PHY rev 16 */
751 b43_radio_write(dev, R2057_LOGEN_PTAT_RESETS, 0x20);
752 b43_radio_write(dev, R2057_VCOBUF_IDACS, 0x18);
753 if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
754 b43_radio_write(dev, R2057_LOGEN_PTAT_RESETS, 0x38);
755 b43_radio_write(dev, R2057_VCOBUF_IDACS, 0x0f);
756
757 if (b43_is_40mhz(dev)) {
758 /* TODO */
759 } else {
760 b43_radio_write(dev,
761 R2057_PAD_BIAS_FILTER_BWS_CORE0,
762 0x3c);
763 b43_radio_write(dev,
764 R2057_PAD_BIAS_FILTER_BWS_CORE1,
765 0x3c);
766 }
767 }
768 break;
769 case 14: /* 2 GHz only */
770 b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x1b);
771 b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f);
772 b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x1f);
773 b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x1f);
774 break;
673 } 775 }
674 776
675 /* TODO */ 777 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
778 u16 txmix2g_tune_boost_pu = 0;
779 u16 pad2g_tune_pus = 0;
780
781 if (b43_nphy_ipa(dev)) {
782 switch (phy->radio_rev) {
783 case 9:
784 txmix2g_tune_boost_pu = 0x0041;
785 /* TODO */
786 break;
787 case 14:
788 txmix2g_tune_boost_pu = 0x21;
789 pad2g_tune_pus = 0x23;
790 break;
791 }
792 }
793
794 if (txmix2g_tune_boost_pu)
795 b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0,
796 txmix2g_tune_boost_pu);
797 if (pad2g_tune_pus)
798 b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0,
799 pad2g_tune_pus);
800 if (txmix2g_tune_boost_pu)
801 b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1,
802 txmix2g_tune_boost_pu);
803 if (pad2g_tune_pus)
804 b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1,
805 pad2g_tune_pus);
806 }
676 807
677 usleep_range(50, 100); 808 usleep_range(50, 100);
678 809
@@ -690,13 +821,62 @@ static void b43_radio_2057_setup(struct b43_wldev *dev,
690static u8 b43_radio_2057_rcal(struct b43_wldev *dev) 821static u8 b43_radio_2057_rcal(struct b43_wldev *dev)
691{ 822{
692 struct b43_phy *phy = &dev->phy; 823 struct b43_phy *phy = &dev->phy;
824 u16 saved_regs_phy[12];
825 u16 saved_regs_phy_rf[6];
826 u16 saved_regs_radio[2] = { };
827 static const u16 phy_to_store[] = {
828 B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2,
829 B43_NPHY_RFCTL_LUT_TRSW_LO1, B43_NPHY_RFCTL_LUT_TRSW_LO2,
830 B43_NPHY_RFCTL_RXG1, B43_NPHY_RFCTL_RXG2,
831 B43_NPHY_RFCTL_TXG1, B43_NPHY_RFCTL_TXG2,
832 B43_NPHY_REV7_RF_CTL_MISC_REG3, B43_NPHY_REV7_RF_CTL_MISC_REG4,
833 B43_NPHY_REV7_RF_CTL_MISC_REG5, B43_NPHY_REV7_RF_CTL_MISC_REG6,
834 };
835 static const u16 phy_to_store_rf[] = {
836 B43_NPHY_REV3_RFCTL_OVER0, B43_NPHY_REV3_RFCTL_OVER1,
837 B43_NPHY_REV7_RF_CTL_OVER3, B43_NPHY_REV7_RF_CTL_OVER4,
838 B43_NPHY_REV7_RF_CTL_OVER5, B43_NPHY_REV7_RF_CTL_OVER6,
839 };
693 u16 tmp; 840 u16 tmp;
841 int i;
694 842
695 if (phy->radio_rev == 5) { 843 /* Save */
696 b43_phy_mask(dev, 0x342, ~0x2); 844 for (i = 0; i < ARRAY_SIZE(phy_to_store); i++)
845 saved_regs_phy[i] = b43_phy_read(dev, phy_to_store[i]);
846 for (i = 0; i < ARRAY_SIZE(phy_to_store_rf); i++)
847 saved_regs_phy_rf[i] = b43_phy_read(dev, phy_to_store_rf[i]);
848
849 /* Set */
850 for (i = 0; i < ARRAY_SIZE(phy_to_store); i++)
851 b43_phy_write(dev, phy_to_store[i], 0);
852 b43_phy_write(dev, B43_NPHY_REV3_RFCTL_OVER0, 0x07ff);
853 b43_phy_write(dev, B43_NPHY_REV3_RFCTL_OVER1, 0x07ff);
854 b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x07ff);
855 b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER4, 0x07ff);
856 b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER5, 0x007f);
857 b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER6, 0x007f);
858
859 switch (phy->radio_rev) {
860 case 5:
861 b43_phy_mask(dev, B43_NPHY_REV7_RF_CTL_OVER3, ~0x2);
697 udelay(10); 862 udelay(10);
698 b43_radio_set(dev, R2057_IQTEST_SEL_PU, 0x1); 863 b43_radio_set(dev, R2057_IQTEST_SEL_PU, 0x1);
699 b43_radio_maskset(dev, 0x1ca, ~0x2, 0x1); 864 b43_radio_maskset(dev, R2057v7_IQTEST_SEL_PU2, ~0x2, 0x1);
865 break;
866 case 9:
867 b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x2);
868 b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_MISC_REG3, 0x2);
869 saved_regs_radio[0] = b43_radio_read(dev, R2057_IQTEST_SEL_PU);
870 b43_radio_write(dev, R2057_IQTEST_SEL_PU, 0x11);
871 break;
872 case 14:
873 saved_regs_radio[0] = b43_radio_read(dev, R2057_IQTEST_SEL_PU);
874 saved_regs_radio[1] = b43_radio_read(dev, R2057v7_IQTEST_SEL_PU2);
875 b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_MISC_REG3, 0x2);
876 b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x2);
877 b43_radio_write(dev, R2057v7_IQTEST_SEL_PU2, 0x2);
878 b43_radio_write(dev, R2057_IQTEST_SEL_PU, 0x1);
879 break;
700 } 880 }
701 881
702 /* Enable */ 882 /* Enable */
@@ -720,14 +900,30 @@ static u8 b43_radio_2057_rcal(struct b43_wldev *dev)
720 /* Disable */ 900 /* Disable */
721 b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x1); 901 b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x1);
722 902
723 if (phy->radio_rev == 5) { 903 /* Restore */
724 b43_radio_mask(dev, R2057_IPA2G_CASCONV_CORE0, ~0x1); 904 for (i = 0; i < ARRAY_SIZE(phy_to_store_rf); i++)
725 b43_radio_mask(dev, 0x1ca, ~0x2); 905 b43_phy_write(dev, phy_to_store_rf[i], saved_regs_phy_rf[i]);
726 } 906 for (i = 0; i < ARRAY_SIZE(phy_to_store); i++)
727 if (phy->radio_rev <= 4 || phy->radio_rev == 6) { 907 b43_phy_write(dev, phy_to_store[i], saved_regs_phy[i]);
908
909 switch (phy->radio_rev) {
910 case 0 ... 4:
911 case 6:
728 b43_radio_maskset(dev, R2057_TEMPSENSE_CONFIG, ~0x3C, tmp); 912 b43_radio_maskset(dev, R2057_TEMPSENSE_CONFIG, ~0x3C, tmp);
729 b43_radio_maskset(dev, R2057_BANDGAP_RCAL_TRIM, ~0xF0, 913 b43_radio_maskset(dev, R2057_BANDGAP_RCAL_TRIM, ~0xF0,
730 tmp << 2); 914 tmp << 2);
915 break;
916 case 5:
917 b43_radio_mask(dev, R2057_IPA2G_CASCONV_CORE0, ~0x1);
918 b43_radio_mask(dev, R2057v7_IQTEST_SEL_PU2, ~0x2);
919 break;
920 case 9:
921 b43_radio_write(dev, R2057_IQTEST_SEL_PU, saved_regs_radio[0]);
922 break;
923 case 14:
924 b43_radio_write(dev, R2057_IQTEST_SEL_PU, saved_regs_radio[0]);
925 b43_radio_write(dev, R2057v7_IQTEST_SEL_PU2, saved_regs_radio[1]);
926 break;
731 } 927 }
732 928
733 return tmp & 0x3e; 929 return tmp & 0x3e;
@@ -749,7 +945,7 @@ static u16 b43_radio_2057_rccal(struct b43_wldev *dev)
749 b43_radio_write(dev, R2057_RCCAL_TRC0, 0xC0); 945 b43_radio_write(dev, R2057_RCCAL_TRC0, 0xC0);
750 } else { 946 } else {
751 b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x61); 947 b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x61);
752 b43_radio_write(dev, R2057_RCCAL_TRC0, 0xE1); 948 b43_radio_write(dev, R2057_RCCAL_TRC0, 0xE9);
753 } 949 }
754 b43_radio_write(dev, R2057_RCCAL_X1, 0x6E); 950 b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
755 951
@@ -829,6 +1025,9 @@ static void b43_radio_2057_init_post(struct b43_wldev *dev)
829{ 1025{
830 b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x1); 1026 b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x1);
831 1027
1028 if (0) /* FIXME: Is this BCM43217 specific? */
1029 b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x2);
1030
832 b43_radio_set(dev, R2057_RFPLL_MISC_CAL_RESETN, 0x78); 1031 b43_radio_set(dev, R2057_RFPLL_MISC_CAL_RESETN, 0x78);
833 b43_radio_set(dev, R2057_XTAL_CONFIG2, 0x80); 1032 b43_radio_set(dev, R2057_XTAL_CONFIG2, 0x80);
834 mdelay(2); 1033 mdelay(2);
@@ -1386,6 +1585,7 @@ static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
1386 u16 wait, bool iqmode, bool dac_test, 1585 u16 wait, bool iqmode, bool dac_test,
1387 bool modify_bbmult) 1586 bool modify_bbmult)
1388{ 1587{
1588 struct b43_phy *phy = &dev->phy;
1389 struct b43_phy_n *nphy = dev->phy.n; 1589 struct b43_phy_n *nphy = dev->phy.n;
1390 int i; 1590 int i;
1391 u16 seq_mode; 1591 u16 seq_mode;
@@ -1393,6 +1593,26 @@ static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
1393 1593
1394 b43_nphy_stay_in_carrier_search(dev, true); 1594 b43_nphy_stay_in_carrier_search(dev, true);
1395 1595
1596 if (phy->rev >= 7) {
1597 bool lpf_bw3, lpf_bw4;
1598
1599 lpf_bw3 = b43_phy_read(dev, B43_NPHY_REV7_RF_CTL_OVER3) & 0x80;
1600 lpf_bw4 = b43_phy_read(dev, B43_NPHY_REV7_RF_CTL_OVER4) & 0x80;
1601
1602 if (lpf_bw3 || lpf_bw4) {
1603 /* TODO */
1604 } else {
1605 u16 value = b43_nphy_read_lpf_ctl(dev, 0);
1606 if (phy->rev >= 19)
1607 b43_nphy_rf_ctl_override_rev19(dev, 0x80, value,
1608 0, false, 1);
1609 else
1610 b43_nphy_rf_ctl_override_rev7(dev, 0x80, value,
1611 0, false, 1);
1612 nphy->lpf_bw_overrode_for_sample_play = true;
1613 }
1614 }
1615
1396 if ((nphy->bb_mult_save & 0x80000000) == 0) { 1616 if ((nphy->bb_mult_save & 0x80000000) == 0) {
1397 tmp = b43_ntab_read(dev, B43_NTAB16(15, 87)); 1617 tmp = b43_ntab_read(dev, B43_NTAB16(15, 87));
1398 nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000; 1618 nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000;
@@ -1520,6 +1740,12 @@ static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale,
1520 } 1740 }
1521} 1741}
1522 1742
1743static void b43_nphy_rssi_select_rev19(struct b43_wldev *dev, u8 code,
1744 enum n_rssi_type rssi_type)
1745{
1746 /* TODO */
1747}
1748
1523static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, 1749static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code,
1524 enum n_rssi_type rssi_type) 1750 enum n_rssi_type rssi_type)
1525{ 1751{
@@ -1589,13 +1815,15 @@ static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code,
1589 enum ieee80211_band band = 1815 enum ieee80211_band band =
1590 b43_current_band(dev->wl); 1816 b43_current_band(dev->wl);
1591 1817
1592 if (b43_nphy_ipa(dev)) 1818 if (dev->phy.rev < 7) {
1593 val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE; 1819 if (b43_nphy_ipa(dev))
1594 else 1820 val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE;
1595 val = 0x11; 1821 else
1596 reg = (i == 0) ? 0x2000 : 0x3000; 1822 val = 0x11;
1597 reg |= B2055_PADDRV; 1823 reg = (i == 0) ? B2056_TX0 : B2056_TX1;
1598 b43_radio_write(dev, reg, val); 1824 reg |= B2056_TX_TX_SSI_MUX;
1825 b43_radio_write(dev, reg, val);
1826 }
1599 1827
1600 reg = (i == 0) ? 1828 reg = (i == 0) ?
1601 B43_NPHY_AFECTL_OVER1 : 1829 B43_NPHY_AFECTL_OVER1 :
@@ -1682,7 +1910,9 @@ static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code,
1682static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, 1910static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code,
1683 enum n_rssi_type type) 1911 enum n_rssi_type type)
1684{ 1912{
1685 if (dev->phy.rev >= 3) 1913 if (dev->phy.rev >= 19)
1914 b43_nphy_rssi_select_rev19(dev, code, type);
1915 else if (dev->phy.rev >= 3)
1686 b43_nphy_rev3_rssi_select(dev, code, type); 1916 b43_nphy_rev3_rssi_select(dev, code, type);
1687 else 1917 else
1688 b43_nphy_rev2_rssi_select(dev, code, type); 1918 b43_nphy_rev2_rssi_select(dev, code, type);
@@ -1726,6 +1956,8 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, enum n_rssi_type rssi_type,
1726 u16 save_regs_phy[9]; 1956 u16 save_regs_phy[9];
1727 u16 s[2]; 1957 u16 s[2];
1728 1958
1959 /* TODO: rev7+ is treated like rev3+, what about rev19+? */
1960
1729 if (dev->phy.rev >= 3) { 1961 if (dev->phy.rev >= 3) {
1730 save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); 1962 save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
1731 save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); 1963 save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
@@ -1825,12 +2057,14 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
1825 B43_NPHY_AFECTL_OVER1, B43_NPHY_AFECTL_OVER, 2057 B43_NPHY_AFECTL_OVER1, B43_NPHY_AFECTL_OVER,
1826 B43_NPHY_AFECTL_C1, B43_NPHY_AFECTL_C2, 2058 B43_NPHY_AFECTL_C1, B43_NPHY_AFECTL_C2,
1827 B43_NPHY_TXF_40CO_B1S1, B43_NPHY_RFCTL_OVER, 2059 B43_NPHY_TXF_40CO_B1S1, B43_NPHY_RFCTL_OVER,
1828 0x342, 0x343, 0x346, 0x347, 2060 B43_NPHY_REV7_RF_CTL_OVER3, B43_NPHY_REV7_RF_CTL_OVER4,
2061 B43_NPHY_REV7_RF_CTL_OVER5, B43_NPHY_REV7_RF_CTL_OVER6,
1829 0x2ff, 2062 0x2ff,
1830 B43_NPHY_TXF_40CO_B1S0, B43_NPHY_TXF_40CO_B32S1, 2063 B43_NPHY_TXF_40CO_B1S0, B43_NPHY_TXF_40CO_B32S1,
1831 B43_NPHY_RFCTL_CMD, 2064 B43_NPHY_RFCTL_CMD,
1832 B43_NPHY_RFCTL_LUT_TRSW_UP1, B43_NPHY_RFCTL_LUT_TRSW_UP2, 2065 B43_NPHY_RFCTL_LUT_TRSW_UP1, B43_NPHY_RFCTL_LUT_TRSW_UP2,
1833 0x340, 0x341, 0x344, 0x345, 2066 B43_NPHY_REV7_RF_CTL_MISC_REG3, B43_NPHY_REV7_RF_CTL_MISC_REG4,
2067 B43_NPHY_REV7_RF_CTL_MISC_REG5, B43_NPHY_REV7_RF_CTL_MISC_REG6,
1834 B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2 2068 B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2
1835 }; 2069 };
1836 u16 *regs_to_store; 2070 u16 *regs_to_store;
@@ -1877,9 +2111,24 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
1877 b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 1, 7); 2111 b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 1, 7);
1878 2112
1879 if (dev->phy.rev >= 7) { 2113 if (dev->phy.rev >= 7) {
1880 /* TODO */ 2114 b43_nphy_rf_ctl_override_one_to_many(dev,
2115 N_RF_CTL_OVER_CMD_RXRF_PU,
2116 0, 0, false);
2117 b43_nphy_rf_ctl_override_one_to_many(dev,
2118 N_RF_CTL_OVER_CMD_RX_PU,
2119 1, 0, false);
2120 b43_nphy_rf_ctl_override_rev7(dev, 0x80, 1, 0, false, 0);
2121 b43_nphy_rf_ctl_override_rev7(dev, 0x40, 1, 0, false, 0);
1881 if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { 2122 if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
2123 b43_nphy_rf_ctl_override_rev7(dev, 0x20, 0, 0, false,
2124 0);
2125 b43_nphy_rf_ctl_override_rev7(dev, 0x10, 1, 0, false,
2126 0);
1882 } else { 2127 } else {
2128 b43_nphy_rf_ctl_override_rev7(dev, 0x10, 0, 0, false,
2129 0);
2130 b43_nphy_rf_ctl_override_rev7(dev, 0x20, 1, 0, false,
2131 0);
1883 } 2132 }
1884 } else { 2133 } else {
1885 b43_nphy_rf_ctl_override(dev, 0x1, 0, 0, false); 2134 b43_nphy_rf_ctl_override(dev, 0x1, 0, 0, false);
@@ -1908,7 +2157,10 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
1908 /* Grab RSSI results for every possible VCM */ 2157 /* Grab RSSI results for every possible VCM */
1909 for (vcm = 0; vcm < 8; vcm++) { 2158 for (vcm = 0; vcm < 8; vcm++) {
1910 if (dev->phy.rev >= 7) 2159 if (dev->phy.rev >= 7)
1911 ; 2160 b43_radio_maskset(dev,
2161 core ? R2057_NB_MASTER_CORE1 :
2162 R2057_NB_MASTER_CORE0,
2163 ~R2057_VCM_MASK, vcm);
1912 else 2164 else
1913 b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC, 2165 b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC,
1914 0xE3, vcm << 2); 2166 0xE3, vcm << 2);
@@ -1939,7 +2191,10 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
1939 2191
1940 /* Select the best VCM */ 2192 /* Select the best VCM */
1941 if (dev->phy.rev >= 7) 2193 if (dev->phy.rev >= 7)
1942 ; 2194 b43_radio_maskset(dev,
2195 core ? R2057_NB_MASTER_CORE1 :
2196 R2057_NB_MASTER_CORE0,
2197 ~R2057_VCM_MASK, vcm);
1943 else 2198 else
1944 b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC, 2199 b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC,
1945 0xE3, vcm_final << 2); 2200 0xE3, vcm_final << 2);
@@ -2009,6 +2264,10 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
2009 rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; 2264 rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
2010 } 2265 }
2011 if (dev->phy.rev >= 7) { 2266 if (dev->phy.rev >= 7) {
2267 rssical_radio_regs[0] = b43_radio_read(dev,
2268 R2057_NB_MASTER_CORE0);
2269 rssical_radio_regs[1] = b43_radio_read(dev,
2270 R2057_NB_MASTER_CORE1);
2012 } else { 2271 } else {
2013 rssical_radio_regs[0] = b43_radio_read(dev, B2056_RX0 | 2272 rssical_radio_regs[0] = b43_radio_read(dev, B2056_RX0 |
2014 B2056_RX_RSSI_MISC); 2273 B2056_RX_RSSI_MISC);
@@ -2209,7 +2468,9 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, enum n_rssi_type type)
2209 */ 2468 */
2210static void b43_nphy_rssi_cal(struct b43_wldev *dev) 2469static void b43_nphy_rssi_cal(struct b43_wldev *dev)
2211{ 2470{
2212 if (dev->phy.rev >= 3) { 2471 if (dev->phy.rev >= 19) {
2472 /* TODO */
2473 } else if (dev->phy.rev >= 3) {
2213 b43_nphy_rev3_rssi_cal(dev); 2474 b43_nphy_rev3_rssi_cal(dev);
2214 } else { 2475 } else {
2215 b43_nphy_rev2_rssi_cal(dev, N_RSSI_NB); 2476 b43_nphy_rev2_rssi_cal(dev, N_RSSI_NB);
@@ -2222,7 +2483,21 @@ static void b43_nphy_rssi_cal(struct b43_wldev *dev)
2222 * Workarounds 2483 * Workarounds
2223 **************************************************/ 2484 **************************************************/
2224 2485
2225static void b43_nphy_gain_ctl_workarounds_rev3plus(struct b43_wldev *dev) 2486static void b43_nphy_gain_ctl_workarounds_rev19(struct b43_wldev *dev)
2487{
2488 /* TODO */
2489}
2490
2491static void b43_nphy_gain_ctl_workarounds_rev7(struct b43_wldev *dev)
2492{
2493 struct b43_phy *phy = &dev->phy;
2494
2495 switch (phy->rev) {
2496 /* TODO */
2497 }
2498}
2499
2500static void b43_nphy_gain_ctl_workarounds_rev3(struct b43_wldev *dev)
2226{ 2501{
2227 struct ssb_sprom *sprom = dev->dev->bus_sprom; 2502 struct ssb_sprom *sprom = dev->dev->bus_sprom;
2228 2503
@@ -2419,46 +2694,54 @@ static void b43_nphy_gain_ctl_workarounds_rev1_2(struct b43_wldev *dev)
2419/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */ 2694/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */
2420static void b43_nphy_gain_ctl_workarounds(struct b43_wldev *dev) 2695static void b43_nphy_gain_ctl_workarounds(struct b43_wldev *dev)
2421{ 2696{
2422 if (dev->phy.rev >= 7) 2697 if (dev->phy.rev >= 19)
2423 ; /* TODO */ 2698 b43_nphy_gain_ctl_workarounds_rev19(dev);
2699 else if (dev->phy.rev >= 7)
2700 b43_nphy_gain_ctl_workarounds_rev7(dev);
2424 else if (dev->phy.rev >= 3) 2701 else if (dev->phy.rev >= 3)
2425 b43_nphy_gain_ctl_workarounds_rev3plus(dev); 2702 b43_nphy_gain_ctl_workarounds_rev3(dev);
2426 else 2703 else
2427 b43_nphy_gain_ctl_workarounds_rev1_2(dev); 2704 b43_nphy_gain_ctl_workarounds_rev1_2(dev);
2428} 2705}
2429 2706
2430/* http://bcm-v4.sipsolutions.net/PHY/N/Read_Lpf_Bw_Ctl */
2431static u16 b43_nphy_read_lpf_ctl(struct b43_wldev *dev, u16 offset)
2432{
2433 if (!offset)
2434 offset = b43_is_40mhz(dev) ? 0x159 : 0x154;
2435 return b43_ntab_read(dev, B43_NTAB16(7, offset)) & 0x7;
2436}
2437
2438static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) 2707static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
2439{ 2708{
2440 struct ssb_sprom *sprom = dev->dev->bus_sprom; 2709 struct ssb_sprom *sprom = dev->dev->bus_sprom;
2441 struct b43_phy *phy = &dev->phy; 2710 struct b43_phy *phy = &dev->phy;
2442 2711
2712 /* TX to RX */
2713 u8 tx2rx_events[7] = { 4, 3, 5, 2, 1, 8, 31, };
2714 u8 tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1, };
2715 /* RX to TX */
2443 u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3, 2716 u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
2444 0x1F }; 2717 0x1F };
2445 u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; 2718 u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
2446 2719
2447 u16 ntab7_15e_16e[] = { 0x10f, 0x10f }; 2720 static const u16 ntab7_15e_16e[] = { 0, 0x10f, 0x10f };
2448 u8 ntab7_138_146[] = { 0x11, 0x11 }; 2721 u8 ntab7_138_146[] = { 0x11, 0x11 };
2449 u8 ntab7_133[] = { 0x77, 0x11, 0x11 }; 2722 u8 ntab7_133[] = { 0x77, 0x11, 0x11 };
2450 2723
2451 u16 lpf_20, lpf_40, lpf_11b; 2724 u16 lpf_ofdm_20mhz[2], lpf_ofdm_40mhz[2], lpf_11b[2];
2452 u16 bcap_val, bcap_val_11b, bcap_val_11n_20, bcap_val_11n_40; 2725 u16 bcap_val;
2453 u16 scap_val, scap_val_11b, scap_val_11n_20, scap_val_11n_40; 2726 s16 bcap_val_11b[2], bcap_val_11n_20[2], bcap_val_11n_40[2];
2727 u16 scap_val;
2728 s16 scap_val_11b[2], scap_val_11n_20[2], scap_val_11n_40[2];
2454 bool rccal_ovrd = false; 2729 bool rccal_ovrd = false;
2455 2730
2456 u16 rx2tx_lut_20_11b, rx2tx_lut_20_11n, rx2tx_lut_40_11n;
2457 u16 bias, conv, filt; 2731 u16 bias, conv, filt;
2458 2732
2733 u32 noise_tbl[2];
2734
2459 u32 tmp32; 2735 u32 tmp32;
2460 u8 core; 2736 u8 core;
2461 2737
2738 b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
2739 b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01b3);
2740 b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
2741 b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016e);
2742 b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00cd);
2743 b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
2744
2462 if (phy->rev == 7) { 2745 if (phy->rev == 7) {
2463 b43_phy_set(dev, B43_NPHY_FINERX2_CGC, 0x10); 2746 b43_phy_set(dev, B43_NPHY_FINERX2_CGC, 0x10);
2464 b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0xFF80, 0x0020); 2747 b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0xFF80, 0x0020);
@@ -2478,11 +2761,18 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
2478 b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0xFF80, 0x0040); 2761 b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0xFF80, 0x0040);
2479 b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0x80FF, 0x4000); 2762 b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0x80FF, 0x4000);
2480 } 2763 }
2481 if (phy->rev <= 8) { 2764
2765 if (phy->rev >= 16) {
2766 b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x7ff);
2767 b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x7ff);
2768 } else if (phy->rev <= 8) {
2482 b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1B0); 2769 b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1B0);
2483 b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1B0); 2770 b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1B0);
2484 } 2771 }
2485 if (phy->rev >= 8) 2772
2773 if (phy->rev >= 16)
2774 b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0xa0);
2775 else if (phy->rev >= 8)
2486 b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0x72); 2776 b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0x72);
2487 2777
2488 b43_ntab_write(dev, B43_NTAB16(8, 0x00), 2); 2778 b43_ntab_write(dev, B43_NTAB16(8, 0x00), 2);
@@ -2490,9 +2780,11 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
2490 tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0)); 2780 tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
2491 tmp32 &= 0xffffff; 2781 tmp32 &= 0xffffff;
2492 b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32); 2782 b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
2493 b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15e), 2, ntab7_15e_16e); 2783 b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15d), 3, ntab7_15e_16e);
2494 b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16e), 2, ntab7_15e_16e); 2784 b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16d), 3, ntab7_15e_16e);
2495 2785
2786 b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays,
2787 ARRAY_SIZE(tx2rx_events));
2496 if (b43_nphy_ipa(dev)) 2788 if (b43_nphy_ipa(dev))
2497 b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa, 2789 b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa,
2498 rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa)); 2790 rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa));
@@ -2500,84 +2792,176 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
2500 b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_0, 0x3FFF, 0x4000); 2792 b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_0, 0x3FFF, 0x4000);
2501 b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_1, 0x3FFF, 0x4000); 2793 b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_1, 0x3FFF, 0x4000);
2502 2794
2503 lpf_20 = b43_nphy_read_lpf_ctl(dev, 0x154); 2795 for (core = 0; core < 2; core++) {
2504 lpf_40 = b43_nphy_read_lpf_ctl(dev, 0x159); 2796 lpf_ofdm_20mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x154 + core * 0x10);
2505 lpf_11b = b43_nphy_read_lpf_ctl(dev, 0x152); 2797 lpf_ofdm_40mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x159 + core * 0x10);
2798 lpf_11b[core] = b43_nphy_read_lpf_ctl(dev, 0x152 + core * 0x10);
2799 }
2800
2801 bcap_val = b43_radio_read(dev, R2057_RCCAL_BCAP_VAL);
2802 scap_val = b43_radio_read(dev, R2057_RCCAL_SCAP_VAL);
2803
2506 if (b43_nphy_ipa(dev)) { 2804 if (b43_nphy_ipa(dev)) {
2507 if ((phy->radio_rev == 5 && b43_is_40mhz(dev)) || 2805 bool ghz2 = b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ;
2508 phy->radio_rev == 7 || phy->radio_rev == 8) { 2806
2509 bcap_val = b43_radio_read(dev, 0x16b); 2807 switch (phy->radio_rev) {
2510 scap_val = b43_radio_read(dev, 0x16a); 2808 case 5:
2511 scap_val_11b = scap_val; 2809 /* Check radio version (to be 0) by PHY rev for now */
2512 bcap_val_11b = bcap_val; 2810 if (phy->rev == 8 && b43_is_40mhz(dev)) {
2513 if (phy->radio_rev == 5 && b43_is_40mhz(dev)) { 2811 for (core = 0; core < 2; core++) {
2514 scap_val_11n_20 = scap_val; 2812 scap_val_11b[core] = scap_val;
2515 bcap_val_11n_20 = bcap_val; 2813 bcap_val_11b[core] = bcap_val;
2516 scap_val_11n_40 = bcap_val_11n_40 = 0xc; 2814 scap_val_11n_20[core] = scap_val;
2815 bcap_val_11n_20[core] = bcap_val;
2816 scap_val_11n_40[core] = 0xc;
2817 bcap_val_11n_40[core] = 0xc;
2818 }
2819
2517 rccal_ovrd = true; 2820 rccal_ovrd = true;
2518 } else { /* Rev 7/8 */ 2821 }
2519 lpf_20 = 4; 2822 if (phy->rev == 9) {
2520 lpf_11b = 1; 2823 /* TODO: Radio version 1 (e.g. BCM5357B0) */
2824 }
2825 break;
2826 case 7:
2827 case 8:
2828 for (core = 0; core < 2; core++) {
2829 scap_val_11b[core] = scap_val;
2830 bcap_val_11b[core] = bcap_val;
2831 lpf_ofdm_20mhz[core] = 4;
2832 lpf_11b[core] = 1;
2521 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 2833 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
2522 scap_val_11n_20 = 0xc; 2834 scap_val_11n_20[core] = 0xc;
2523 bcap_val_11n_20 = 0xc; 2835 bcap_val_11n_20[core] = 0xc;
2524 scap_val_11n_40 = 0xa; 2836 scap_val_11n_40[core] = 0xa;
2525 bcap_val_11n_40 = 0xa; 2837 bcap_val_11n_40[core] = 0xa;
2526 } else { 2838 } else {
2527 scap_val_11n_20 = 0x14; 2839 scap_val_11n_20[core] = 0x14;
2528 bcap_val_11n_20 = 0x14; 2840 bcap_val_11n_20[core] = 0x14;
2529 scap_val_11n_40 = 0xf; 2841 scap_val_11n_40[core] = 0xf;
2530 bcap_val_11n_40 = 0xf; 2842 bcap_val_11n_40[core] = 0xf;
2531 } 2843 }
2532 rccal_ovrd = true;
2533 } 2844 }
2845
2846 rccal_ovrd = true;
2847 break;
2848 case 9:
2849 for (core = 0; core < 2; core++) {
2850 bcap_val_11b[core] = bcap_val;
2851 scap_val_11b[core] = scap_val;
2852 lpf_11b[core] = 1;
2853
2854 if (ghz2) {
2855 bcap_val_11n_20[core] = bcap_val + 13;
2856 scap_val_11n_20[core] = scap_val + 15;
2857 } else {
2858 bcap_val_11n_20[core] = bcap_val + 14;
2859 scap_val_11n_20[core] = scap_val + 15;
2860 }
2861 lpf_ofdm_20mhz[core] = 4;
2862
2863 if (ghz2) {
2864 bcap_val_11n_40[core] = bcap_val - 7;
2865 scap_val_11n_40[core] = scap_val - 5;
2866 } else {
2867 bcap_val_11n_40[core] = bcap_val + 2;
2868 scap_val_11n_40[core] = scap_val + 4;
2869 }
2870 lpf_ofdm_40mhz[core] = 4;
2871 }
2872
2873 rccal_ovrd = true;
2874 break;
2875 case 14:
2876 for (core = 0; core < 2; core++) {
2877 bcap_val_11b[core] = bcap_val;
2878 scap_val_11b[core] = scap_val;
2879 lpf_11b[core] = 1;
2880 }
2881
2882 bcap_val_11n_20[0] = bcap_val + 20;
2883 scap_val_11n_20[0] = scap_val + 20;
2884 lpf_ofdm_20mhz[0] = 3;
2885
2886 bcap_val_11n_20[1] = bcap_val + 16;
2887 scap_val_11n_20[1] = scap_val + 16;
2888 lpf_ofdm_20mhz[1] = 3;
2889
2890 bcap_val_11n_40[0] = bcap_val + 20;
2891 scap_val_11n_40[0] = scap_val + 20;
2892 lpf_ofdm_40mhz[0] = 4;
2893
2894 bcap_val_11n_40[1] = bcap_val + 10;
2895 scap_val_11n_40[1] = scap_val + 10;
2896 lpf_ofdm_40mhz[1] = 4;
2897
2898 rccal_ovrd = true;
2899 break;
2534 } 2900 }
2535 } else { 2901 } else {
2536 if (phy->radio_rev == 5) { 2902 if (phy->radio_rev == 5) {
2537 lpf_20 = 1; 2903 for (core = 0; core < 2; core++) {
2538 lpf_40 = 3; 2904 lpf_ofdm_20mhz[core] = 1;
2539 bcap_val = b43_radio_read(dev, 0x16b); 2905 lpf_ofdm_40mhz[core] = 3;
2540 scap_val = b43_radio_read(dev, 0x16a); 2906 scap_val_11b[core] = scap_val;
2541 scap_val_11b = scap_val; 2907 bcap_val_11b[core] = bcap_val;
2542 bcap_val_11b = bcap_val; 2908 scap_val_11n_20[core] = 0x11;
2543 scap_val_11n_20 = 0x11; 2909 scap_val_11n_40[core] = 0x11;
2544 scap_val_11n_40 = 0x11; 2910 bcap_val_11n_20[core] = 0x13;
2545 bcap_val_11n_20 = 0x13; 2911 bcap_val_11n_40[core] = 0x13;
2546 bcap_val_11n_40 = 0x13; 2912 }
2913
2547 rccal_ovrd = true; 2914 rccal_ovrd = true;
2548 } 2915 }
2549 } 2916 }
2550 if (rccal_ovrd) { 2917 if (rccal_ovrd) {
2551 rx2tx_lut_20_11b = (bcap_val_11b << 8) | 2918 u16 rx2tx_lut_20_11b[2], rx2tx_lut_20_11n[2], rx2tx_lut_40_11n[2];
2552 (scap_val_11b << 3) | 2919 u8 rx2tx_lut_extra = 1;
2553 lpf_11b; 2920
2554 rx2tx_lut_20_11n = (bcap_val_11n_20 << 8) | 2921 for (core = 0; core < 2; core++) {
2555 (scap_val_11n_20 << 3) | 2922 bcap_val_11b[core] = clamp_val(bcap_val_11b[core], 0, 0x1f);
2556 lpf_20; 2923 scap_val_11b[core] = clamp_val(scap_val_11b[core], 0, 0x1f);
2557 rx2tx_lut_40_11n = (bcap_val_11n_40 << 8) | 2924 bcap_val_11n_20[core] = clamp_val(bcap_val_11n_20[core], 0, 0x1f);
2558 (scap_val_11n_40 << 3) | 2925 scap_val_11n_20[core] = clamp_val(scap_val_11n_20[core], 0, 0x1f);
2559 lpf_40; 2926 bcap_val_11n_40[core] = clamp_val(bcap_val_11n_40[core], 0, 0x1f);
2927 scap_val_11n_40[core] = clamp_val(scap_val_11n_40[core], 0, 0x1f);
2928
2929 rx2tx_lut_20_11b[core] = (rx2tx_lut_extra << 13) |
2930 (bcap_val_11b[core] << 8) |
2931 (scap_val_11b[core] << 3) |
2932 lpf_11b[core];
2933 rx2tx_lut_20_11n[core] = (rx2tx_lut_extra << 13) |
2934 (bcap_val_11n_20[core] << 8) |
2935 (scap_val_11n_20[core] << 3) |
2936 lpf_ofdm_20mhz[core];
2937 rx2tx_lut_40_11n[core] = (rx2tx_lut_extra << 13) |
2938 (bcap_val_11n_40[core] << 8) |
2939 (scap_val_11n_40[core] << 3) |
2940 lpf_ofdm_40mhz[core];
2941 }
2942
2560 for (core = 0; core < 2; core++) { 2943 for (core = 0; core < 2; core++) {
2561 b43_ntab_write(dev, B43_NTAB16(7, 0x152 + core * 16), 2944 b43_ntab_write(dev, B43_NTAB16(7, 0x152 + core * 16),
2562 rx2tx_lut_20_11b); 2945 rx2tx_lut_20_11b[core]);
2563 b43_ntab_write(dev, B43_NTAB16(7, 0x153 + core * 16), 2946 b43_ntab_write(dev, B43_NTAB16(7, 0x153 + core * 16),
2564 rx2tx_lut_20_11n); 2947 rx2tx_lut_20_11n[core]);
2565 b43_ntab_write(dev, B43_NTAB16(7, 0x154 + core * 16), 2948 b43_ntab_write(dev, B43_NTAB16(7, 0x154 + core * 16),
2566 rx2tx_lut_20_11n); 2949 rx2tx_lut_20_11n[core]);
2567 b43_ntab_write(dev, B43_NTAB16(7, 0x155 + core * 16), 2950 b43_ntab_write(dev, B43_NTAB16(7, 0x155 + core * 16),
2568 rx2tx_lut_40_11n); 2951 rx2tx_lut_40_11n[core]);
2569 b43_ntab_write(dev, B43_NTAB16(7, 0x156 + core * 16), 2952 b43_ntab_write(dev, B43_NTAB16(7, 0x156 + core * 16),
2570 rx2tx_lut_40_11n); 2953 rx2tx_lut_40_11n[core]);
2571 b43_ntab_write(dev, B43_NTAB16(7, 0x157 + core * 16), 2954 b43_ntab_write(dev, B43_NTAB16(7, 0x157 + core * 16),
2572 rx2tx_lut_40_11n); 2955 rx2tx_lut_40_11n[core]);
2573 b43_ntab_write(dev, B43_NTAB16(7, 0x158 + core * 16), 2956 b43_ntab_write(dev, B43_NTAB16(7, 0x158 + core * 16),
2574 rx2tx_lut_40_11n); 2957 rx2tx_lut_40_11n[core]);
2575 b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16), 2958 b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16),
2576 rx2tx_lut_40_11n); 2959 rx2tx_lut_40_11n[core]);
2577 } 2960 }
2578 b43_nphy_rf_ctl_override_rev7(dev, 16, 1, 3, false, 2);
2579 } 2961 }
2962
2580 b43_phy_write(dev, 0x32F, 0x3); 2963 b43_phy_write(dev, 0x32F, 0x3);
2964
2581 if (phy->radio_rev == 4 || phy->radio_rev == 6) 2965 if (phy->radio_rev == 4 || phy->radio_rev == 6)
2582 b43_nphy_rf_ctl_override_rev7(dev, 4, 1, 3, false, 0); 2966 b43_nphy_rf_ctl_override_rev7(dev, 4, 1, 3, false, 0);
2583 2967
@@ -2625,7 +3009,8 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
2625 0x7f); 3009 0x7f);
2626 } 3010 }
2627 } 3011 }
2628 if (phy->radio_rev == 3) { 3012 switch (phy->radio_rev) {
3013 case 3:
2629 for (core = 0; core < 2; core++) { 3014 for (core = 0; core < 2; core++) {
2630 if (core == 0) { 3015 if (core == 0) {
2631 b43_radio_write(dev, 0x64, 3016 b43_radio_write(dev, 0x64,
@@ -2651,7 +3036,9 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
2651 0x3E); 3036 0x3E);
2652 } 3037 }
2653 } 3038 }
2654 } else if (phy->radio_rev == 7 || phy->radio_rev == 8) { 3039 break;
3040 case 7:
3041 case 8:
2655 if (!b43_is_40mhz(dev)) { 3042 if (!b43_is_40mhz(dev)) {
2656 b43_radio_write(dev, 0x5F, 0x14); 3043 b43_radio_write(dev, 0x5F, 0x14);
2657 b43_radio_write(dev, 0xE8, 0x12); 3044 b43_radio_write(dev, 0xE8, 0x12);
@@ -2659,6 +3046,21 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
2659 b43_radio_write(dev, 0x5F, 0x16); 3046 b43_radio_write(dev, 0x5F, 0x16);
2660 b43_radio_write(dev, 0xE8, 0x16); 3047 b43_radio_write(dev, 0xE8, 0x16);
2661 } 3048 }
3049 break;
3050 case 14:
3051 for (core = 0; core < 2; core++) {
3052 int o = core ? 0x85 : 0;
3053
3054 b43_radio_write(dev, o + R2057_IPA2G_CASCONV_CORE0, 0x13);
3055 b43_radio_write(dev, o + R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, 0x21);
3056 b43_radio_write(dev, o + R2057_IPA2G_BIAS_FILTER_CORE0, 0xff);
3057 b43_radio_write(dev, o + R2057_PAD2G_IDACS_CORE0, 0x88);
3058 b43_radio_write(dev, o + R2057_PAD2G_TUNE_PUS_CORE0, 0x23);
3059 b43_radio_write(dev, o + R2057_IPA2G_IMAIN_CORE0, 0x16);
3060 b43_radio_write(dev, o + R2057_PAD_BIAS_FILTER_BWS_CORE0, 0x3e);
3061 b43_radio_write(dev, o + R2057_BACKUP1_CORE0, 0x10);
3062 }
3063 break;
2662 } 3064 }
2663 } else { 3065 } else {
2664 u16 freq = phy->chandef->chan->center_freq; 3066 u16 freq = phy->chandef->chan->center_freq;
@@ -2706,8 +3108,8 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
2706 b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x1); 3108 b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x1);
2707 b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x1); 3109 b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x1);
2708 b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x1); 3110 b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x1);
2709 b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0x20); 3111 b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0);
2710 b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0x20); 3112 b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0);
2711 3113
2712 b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x4); 3114 b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x4);
2713 b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x4); 3115 b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x4);
@@ -2718,20 +3120,20 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
2718 b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, 0x2); 3120 b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, 0x2);
2719 3121
2720 b43_ntab_write(dev, B43_NTAB32(16, 0x100), 20); 3122 b43_ntab_write(dev, B43_NTAB32(16, 0x100), 20);
2721 b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x138), 2, ntab7_138_146); 3123 b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x138), 2, ntab7_138_146);
2722 b43_ntab_write(dev, B43_NTAB16(7, 0x141), 0x77); 3124 b43_ntab_write(dev, B43_NTAB16(7, 0x141), 0x77);
2723 b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x133), 3, ntab7_133); 3125 b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x133), 3, ntab7_133);
2724 b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x146), 2, ntab7_138_146); 3126 b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x146), 2, ntab7_138_146);
2725 b43_ntab_write(dev, B43_NTAB16(7, 0x123), 0x77); 3127 b43_ntab_write(dev, B43_NTAB16(7, 0x123), 0x77);
2726 b43_ntab_write(dev, B43_NTAB16(7, 0x12A), 0x77); 3128 b43_ntab_write(dev, B43_NTAB16(7, 0x12A), 0x77);
2727 3129
2728 if (!b43_is_40mhz(dev)) { 3130 b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x02), 1, noise_tbl);
2729 b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x18D); 3131 noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D;
2730 b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x18D); 3132 b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x02), 2, noise_tbl);
2731 } else { 3133
2732 b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x14D); 3134 b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x7E), 1, noise_tbl);
2733 b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x14D); 3135 noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D;
2734 } 3136 b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x7E), 2, noise_tbl);
2735 3137
2736 b43_nphy_gain_ctl_workarounds(dev); 3138 b43_nphy_gain_ctl_workarounds(dev);
2737 3139
@@ -3059,6 +3461,7 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)
3059 b43_phy_set(dev, B43_NPHY_IQFLIP, 3461 b43_phy_set(dev, B43_NPHY_IQFLIP,
3060 B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2); 3462 B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
3061 3463
3464 /* TODO: rev19+ */
3062 if (dev->phy.rev >= 7) 3465 if (dev->phy.rev >= 7)
3063 b43_nphy_workarounds_rev7plus(dev); 3466 b43_nphy_workarounds_rev7plus(dev);
3064 else if (dev->phy.rev >= 3) 3467 else if (dev->phy.rev >= 3)
@@ -3120,6 +3523,7 @@ static void b43_nphy_update_txrx_chain(struct b43_wldev *dev)
3120/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */ 3523/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */
3121static void b43_nphy_stop_playback(struct b43_wldev *dev) 3524static void b43_nphy_stop_playback(struct b43_wldev *dev)
3122{ 3525{
3526 struct b43_phy *phy = &dev->phy;
3123 struct b43_phy_n *nphy = dev->phy.n; 3527 struct b43_phy_n *nphy = dev->phy.n;
3124 u16 tmp; 3528 u16 tmp;
3125 3529
@@ -3140,6 +3544,15 @@ static void b43_nphy_stop_playback(struct b43_wldev *dev)
3140 nphy->bb_mult_save = 0; 3544 nphy->bb_mult_save = 0;
3141 } 3545 }
3142 3546
3547 if (phy->rev >= 7 && nphy->lpf_bw_overrode_for_sample_play) {
3548 if (phy->rev >= 19)
3549 b43_nphy_rf_ctl_override_rev19(dev, 0x80, 0, 0, true,
3550 1);
3551 else
3552 b43_nphy_rf_ctl_override_rev7(dev, 0x80, 0, 0, true, 1);
3553 nphy->lpf_bw_overrode_for_sample_play = false;
3554 }
3555
3143 if (nphy->hang_avoid) 3556 if (nphy->hang_avoid)
3144 b43_nphy_stay_in_carrier_search(dev, 0); 3557 b43_nphy_stay_in_carrier_search(dev, 0);
3145} 3558}
@@ -3149,16 +3562,23 @@ static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core,
3149 struct nphy_txgains target, 3562 struct nphy_txgains target,
3150 struct nphy_iqcal_params *params) 3563 struct nphy_iqcal_params *params)
3151{ 3564{
3565 struct b43_phy *phy = &dev->phy;
3152 int i, j, indx; 3566 int i, j, indx;
3153 u16 gain; 3567 u16 gain;
3154 3568
3155 if (dev->phy.rev >= 3) { 3569 if (dev->phy.rev >= 3) {
3570 params->tx_lpf = target.tx_lpf[core]; /* Rev 7+ */
3156 params->txgm = target.txgm[core]; 3571 params->txgm = target.txgm[core];
3157 params->pga = target.pga[core]; 3572 params->pga = target.pga[core];
3158 params->pad = target.pad[core]; 3573 params->pad = target.pad[core];
3159 params->ipa = target.ipa[core]; 3574 params->ipa = target.ipa[core];
3160 params->cal_gain = (params->txgm << 12) | (params->pga << 8) | 3575 if (phy->rev >= 19) {
3161 (params->pad << 4) | (params->ipa); 3576 /* TODO */
3577 } else if (phy->rev >= 7) {
3578 params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 3) | (params->ipa) | (params->tx_lpf << 15);
3579 } else {
3580 params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 4) | (params->ipa);
3581 }
3162 for (j = 0; j < 5; j++) 3582 for (j = 0; j < 5; j++)
3163 params->ncorr[j] = 0x79; 3583 params->ncorr[j] = 0x79;
3164 } else { 3584 } else {
@@ -3199,6 +3619,7 @@ static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev,
3199/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */ 3619/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */
3200static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable) 3620static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
3201{ 3621{
3622 struct b43_phy *phy = &dev->phy;
3202 struct b43_phy_n *nphy = dev->phy.n; 3623 struct b43_phy_n *nphy = dev->phy.n;
3203 u8 i; 3624 u8 i;
3204 u16 bmask, val, tmp; 3625 u16 bmask, val, tmp;
@@ -3268,12 +3689,25 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
3268 b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, ~(bmask), val); 3689 b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, ~(bmask), val);
3269 3690
3270 if (band == IEEE80211_BAND_5GHZ) { 3691 if (band == IEEE80211_BAND_5GHZ) {
3271 b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, 3692 if (phy->rev >= 19) {
3272 ~B43_NPHY_TXPCTL_CMD_INIT, 0x64); 3693 /* TODO */
3273 if (dev->phy.rev > 1) 3694 } else if (phy->rev >= 7) {
3695 b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
3696 ~B43_NPHY_TXPCTL_CMD_INIT,
3697 0x32);
3274 b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT, 3698 b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
3275 ~B43_NPHY_TXPCTL_INIT_PIDXI1, 3699 ~B43_NPHY_TXPCTL_INIT_PIDXI1,
3700 0x32);
3701 } else {
3702 b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
3703 ~B43_NPHY_TXPCTL_CMD_INIT,
3276 0x64); 3704 0x64);
3705 if (phy->rev > 1)
3706 b43_phy_maskset(dev,
3707 B43_NPHY_TXPCTL_INIT,
3708 ~B43_NPHY_TXPCTL_INIT_PIDXI1,
3709 0x64);
3710 }
3277 } 3711 }
3278 3712
3279 if (dev->phy.rev >= 3) { 3713 if (dev->phy.rev >= 3) {
@@ -3290,6 +3724,10 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
3290 } 3724 }
3291 } 3725 }
3292 3726
3727 if (phy->rev >= 7) {
3728 /* TODO */
3729 }
3730
3293 if (dev->phy.rev >= 3) { 3731 if (dev->phy.rev >= 3) {
3294 b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x100); 3732 b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x100);
3295 b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x100); 3733 b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x100);
@@ -3331,6 +3769,7 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
3331 if (nphy->hang_avoid) 3769 if (nphy->hang_avoid)
3332 b43_nphy_stay_in_carrier_search(dev, 1); 3770 b43_nphy_stay_in_carrier_search(dev, 1);
3333 3771
3772 /* TODO: rev19+ */
3334 if (dev->phy.rev >= 7) { 3773 if (dev->phy.rev >= 7) {
3335 txpi[0] = txpi[1] = 30; 3774 txpi[0] = txpi[1] = 30;
3336 } else if (dev->phy.rev >= 3) { 3775 } else if (dev->phy.rev >= 3) {
@@ -3433,7 +3872,9 @@ static void b43_nphy_ipa_internal_tssi_setup(struct b43_wldev *dev)
3433 u8 core; 3872 u8 core;
3434 u16 r; /* routing */ 3873 u16 r; /* routing */
3435 3874
3436 if (phy->rev >= 7) { 3875 if (phy->rev >= 19) {
3876 /* TODO */
3877 } else if (phy->rev >= 7) {
3437 for (core = 0; core < 2; core++) { 3878 for (core = 0; core < 2; core++) {
3438 r = core ? 0x190 : 0x170; 3879 r = core ? 0x190 : 0x170;
3439 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 3880 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
@@ -3516,13 +3957,16 @@ static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
3516 u32 tmp; 3957 u32 tmp;
3517 s32 rssi[4] = { }; 3958 s32 rssi[4] = { };
3518 3959
3519 /* TODO: check if we can transmit */ 3960 if (phy->chandef->chan->flags & IEEE80211_CHAN_NO_IR)
3961 return;
3520 3962
3521 if (b43_nphy_ipa(dev)) 3963 if (b43_nphy_ipa(dev))
3522 b43_nphy_ipa_internal_tssi_setup(dev); 3964 b43_nphy_ipa_internal_tssi_setup(dev);
3523 3965
3524 if (phy->rev >= 7) 3966 if (phy->rev >= 19)
3525 b43_nphy_rf_ctl_override_rev7(dev, 0x2000, 0, 3, false, 0); 3967 b43_nphy_rf_ctl_override_rev19(dev, 0x1000, 0, 3, false, 0);
3968 else if (phy->rev >= 7)
3969 b43_nphy_rf_ctl_override_rev7(dev, 0x1000, 0, 3, false, 0);
3526 else if (phy->rev >= 3) 3970 else if (phy->rev >= 3)
3527 b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, false); 3971 b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, false);
3528 3972
@@ -3531,14 +3975,20 @@ static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
3531 udelay(20); 3975 udelay(20);
3532 tmp = b43_nphy_poll_rssi(dev, N_RSSI_TSSI_2G, rssi, 1); 3976 tmp = b43_nphy_poll_rssi(dev, N_RSSI_TSSI_2G, rssi, 1);
3533 b43_nphy_stop_playback(dev); 3977 b43_nphy_stop_playback(dev);
3978
3534 b43_nphy_rssi_select(dev, 0, N_RSSI_W1); 3979 b43_nphy_rssi_select(dev, 0, N_RSSI_W1);
3535 3980
3536 if (phy->rev >= 7) 3981 if (phy->rev >= 19)
3537 b43_nphy_rf_ctl_override_rev7(dev, 0x2000, 0, 3, true, 0); 3982 b43_nphy_rf_ctl_override_rev19(dev, 0x1000, 0, 3, true, 0);
3983 else if (phy->rev >= 7)
3984 b43_nphy_rf_ctl_override_rev7(dev, 0x1000, 0, 3, true, 0);
3538 else if (phy->rev >= 3) 3985 else if (phy->rev >= 3)
3539 b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, true); 3986 b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, true);
3540 3987
3541 if (phy->rev >= 3) { 3988 if (phy->rev >= 19) {
3989 /* TODO */
3990 return;
3991 } else if (phy->rev >= 3) {
3542 nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 24) & 0xFF; 3992 nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 24) & 0xFF;
3543 nphy->pwr_ctl_info[1].idle_tssi_5g = (tmp >> 8) & 0xFF; 3993 nphy->pwr_ctl_info[1].idle_tssi_5g = (tmp >> 8) & 0xFF;
3544 } else { 3994 } else {
@@ -3730,7 +4180,9 @@ static void b43_nphy_tx_power_ctl_setup(struct b43_wldev *dev)
3730 udelay(1); 4180 udelay(1);
3731 } 4181 }
3732 4182
3733 if (dev->phy.rev >= 7) { 4183 if (phy->rev >= 19) {
4184 /* TODO */
4185 } else if (phy->rev >= 7) {
3734 b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, 4186 b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
3735 ~B43_NPHY_TXPCTL_CMD_INIT, 0x19); 4187 ~B43_NPHY_TXPCTL_CMD_INIT, 0x19);
3736 b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT, 4188 b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
@@ -3793,24 +4245,30 @@ static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev)
3793 b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table); 4245 b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table);
3794 b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table); 4246 b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table);
3795 4247
3796 if (phy->rev >= 3) { 4248 if (phy->rev < 3)
4249 return;
4250
3797#if 0 4251#if 0
3798 nphy->gmval = (table[0] >> 16) & 0x7000; 4252 nphy->gmval = (table[0] >> 16) & 0x7000;
3799#endif 4253#endif
3800 4254
3801 for (i = 0; i < 128; i++) { 4255 for (i = 0; i < 128; i++) {
4256 if (phy->rev >= 19) {
4257 /* TODO */
4258 return;
4259 } else if (phy->rev >= 7) {
4260 /* TODO */
4261 return;
4262 } else {
3802 pga_gain = (table[i] >> 24) & 0xF; 4263 pga_gain = (table[i] >> 24) & 0xF;
3803 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) 4264 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
3804 rfpwr_offset = 4265 rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain];
3805 b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain];
3806 else 4266 else
3807 rfpwr_offset = 4267 rfpwr_offset = 0; /* FIXME */
3808 0; /* FIXME */
3809 b43_ntab_write(dev, B43_NTAB32(26, 576 + i),
3810 rfpwr_offset);
3811 b43_ntab_write(dev, B43_NTAB32(27, 576 + i),
3812 rfpwr_offset);
3813 } 4268 }
4269
4270 b43_ntab_write(dev, B43_NTAB32(26, 576 + i), rfpwr_offset);
4271 b43_ntab_write(dev, B43_NTAB32(27, 576 + i), rfpwr_offset);
3814 } 4272 }
3815} 4273}
3816 4274
@@ -3827,7 +4285,9 @@ static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable)
3827 nphy->rfctrl_intc2_save = b43_phy_read(dev, 4285 nphy->rfctrl_intc2_save = b43_phy_read(dev,
3828 B43_NPHY_RFCTL_INTC2); 4286 B43_NPHY_RFCTL_INTC2);
3829 band = b43_current_band(dev->wl); 4287 band = b43_current_band(dev->wl);
3830 if (dev->phy.rev >= 3) { 4288 if (dev->phy.rev >= 7) {
4289 tmp = 0x1480;
4290 } else if (dev->phy.rev >= 3) {
3831 if (band == IEEE80211_BAND_5GHZ) 4291 if (band == IEEE80211_BAND_5GHZ)
3832 tmp = 0x600; 4292 tmp = 0x600;
3833 else 4293 else
@@ -4274,7 +4734,13 @@ static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)
4274 rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; 4734 rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
4275 } 4735 }
4276 4736
4277 if (dev->phy.rev >= 7) { 4737 if (dev->phy.rev >= 19) {
4738 /* TODO */
4739 } else if (dev->phy.rev >= 7) {
4740 b43_radio_maskset(dev, R2057_NB_MASTER_CORE0, ~R2057_VCM_MASK,
4741 rssical_radio_regs[0]);
4742 b43_radio_maskset(dev, R2057_NB_MASTER_CORE1, ~R2057_VCM_MASK,
4743 rssical_radio_regs[1]);
4278 } else { 4744 } else {
4279 b43_radio_maskset(dev, B2056_RX0 | B2056_RX_RSSI_MISC, 0xE3, 4745 b43_radio_maskset(dev, B2056_RX0 | B2056_RX_RSSI_MISC, 0xE3,
4280 rssical_radio_regs[0]); 4746 rssical_radio_regs[0]);
@@ -4298,15 +4764,78 @@ static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)
4298 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]); 4764 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]);
4299} 4765}
4300 4766
4767static void b43_nphy_tx_cal_radio_setup_rev19(struct b43_wldev *dev)
4768{
4769 /* TODO */
4770}
4771
4772static void b43_nphy_tx_cal_radio_setup_rev7(struct b43_wldev *dev)
4773{
4774 struct b43_phy *phy = &dev->phy;
4775 struct b43_phy_n *nphy = dev->phy.n;
4776 u16 *save = nphy->tx_rx_cal_radio_saveregs;
4777 int core, off;
4778 u16 r, tmp;
4779
4780 for (core = 0; core < 2; core++) {
4781 r = core ? 0x20 : 0;
4782 off = core * 11;
4783
4784 save[off + 0] = b43_radio_read(dev, r + R2057_TX0_TX_SSI_MASTER);
4785 save[off + 1] = b43_radio_read(dev, r + R2057_TX0_IQCAL_VCM_HG);
4786 save[off + 2] = b43_radio_read(dev, r + R2057_TX0_IQCAL_IDAC);
4787 save[off + 3] = b43_radio_read(dev, r + R2057_TX0_TSSI_VCM);
4788 save[off + 4] = 0;
4789 save[off + 5] = b43_radio_read(dev, r + R2057_TX0_TX_SSI_MUX);
4790 if (phy->radio_rev != 5)
4791 save[off + 6] = b43_radio_read(dev, r + R2057_TX0_TSSIA);
4792 save[off + 7] = b43_radio_read(dev, r + R2057_TX0_TSSIG);
4793 save[off + 8] = b43_radio_read(dev, r + R2057_TX0_TSSI_MISC1);
4794
4795 if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
4796 b43_radio_write(dev, r + R2057_TX0_TX_SSI_MASTER, 0xA);
4797 b43_radio_write(dev, r + R2057_TX0_IQCAL_VCM_HG, 0x43);
4798 b43_radio_write(dev, r + R2057_TX0_IQCAL_IDAC, 0x55);
4799 b43_radio_write(dev, r + R2057_TX0_TSSI_VCM, 0);
4800 b43_radio_write(dev, r + R2057_TX0_TSSIG, 0);
4801 if (nphy->use_int_tx_iq_lo_cal) {
4802 b43_radio_write(dev, r + R2057_TX0_TX_SSI_MUX, 0x4);
4803 tmp = true ? 0x31 : 0x21; /* TODO */
4804 b43_radio_write(dev, r + R2057_TX0_TSSIA, tmp);
4805 }
4806 b43_radio_write(dev, r + R2057_TX0_TSSI_MISC1, 0x00);
4807 } else {
4808 b43_radio_write(dev, r + R2057_TX0_TX_SSI_MASTER, 0x6);
4809 b43_radio_write(dev, r + R2057_TX0_IQCAL_VCM_HG, 0x43);
4810 b43_radio_write(dev, r + R2057_TX0_IQCAL_IDAC, 0x55);
4811 b43_radio_write(dev, r + R2057_TX0_TSSI_VCM, 0);
4812
4813 if (phy->radio_rev != 5)
4814 b43_radio_write(dev, r + R2057_TX0_TSSIA, 0);
4815 if (nphy->use_int_tx_iq_lo_cal) {
4816 b43_radio_write(dev, r + R2057_TX0_TX_SSI_MUX, 0x6);
4817 tmp = true ? 0x31 : 0x21; /* TODO */
4818 b43_radio_write(dev, r + R2057_TX0_TSSIG, tmp);
4819 }
4820 b43_radio_write(dev, r + R2057_TX0_TSSI_MISC1, 0);
4821 }
4822 }
4823}
4824
4301/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */ 4825/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */
4302static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev) 4826static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev)
4303{ 4827{
4828 struct b43_phy *phy = &dev->phy;
4304 struct b43_phy_n *nphy = dev->phy.n; 4829 struct b43_phy_n *nphy = dev->phy.n;
4305 u16 *save = nphy->tx_rx_cal_radio_saveregs; 4830 u16 *save = nphy->tx_rx_cal_radio_saveregs;
4306 u16 tmp; 4831 u16 tmp;
4307 u8 offset, i; 4832 u8 offset, i;
4308 4833
4309 if (dev->phy.rev >= 3) { 4834 if (phy->rev >= 19) {
4835 b43_nphy_tx_cal_radio_setup_rev19(dev);
4836 } else if (phy->rev >= 7) {
4837 b43_nphy_tx_cal_radio_setup_rev7(dev);
4838 } else if (phy->rev >= 3) {
4310 for (i = 0; i < 2; i++) { 4839 for (i = 0; i < 2; i++) {
4311 tmp = (i == 0) ? 0x2000 : 0x3000; 4840 tmp = (i == 0) ? 0x2000 : 0x3000;
4312 offset = i * 11; 4841 offset = i * 11;
@@ -4415,41 +4944,61 @@ static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core)
4415 } 4944 }
4416} 4945}
4417 4946
4947static void b43_nphy_pa_set_tx_dig_filter(struct b43_wldev *dev, u16 offset,
4948 const s16 *filter)
4949{
4950 int i;
4951
4952 offset = B43_PHY_N(offset);
4953
4954 for (i = 0; i < 15; i++, offset++)
4955 b43_phy_write(dev, offset, filter[i]);
4956}
4957
4418/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */ 4958/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */
4419static void b43_nphy_ext_pa_set_tx_dig_filters(struct b43_wldev *dev) 4959static void b43_nphy_ext_pa_set_tx_dig_filters(struct b43_wldev *dev)
4420{ 4960{
4421 int i; 4961 b43_nphy_pa_set_tx_dig_filter(dev, 0x2C5,
4422 for (i = 0; i < 15; i++) 4962 tbl_tx_filter_coef_rev4[2]);
4423 b43_phy_write(dev, B43_PHY_N(0x2C5 + i),
4424 tbl_tx_filter_coef_rev4[2][i]);
4425} 4963}
4426 4964
4427/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */ 4965/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */
4428static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev) 4966static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev)
4429{ 4967{
4430 int i, j;
4431 /* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */ 4968 /* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */
4432 static const u16 offset[] = { 0x186, 0x195, 0x2C5 }; 4969 static const u16 offset[] = { 0x186, 0x195, 0x2C5 };
4970 static const s16 dig_filter_phy_rev16[] = {
4971 -375, 136, -407, 208, -1527,
4972 956, 93, 186, 93, 230,
4973 -44, 230, 201, -191, 201,
4974 };
4975 int i;
4433 4976
4434 for (i = 0; i < 3; i++) 4977 for (i = 0; i < 3; i++)
4435 for (j = 0; j < 15; j++) 4978 b43_nphy_pa_set_tx_dig_filter(dev, offset[i],
4436 b43_phy_write(dev, B43_PHY_N(offset[i] + j), 4979 tbl_tx_filter_coef_rev4[i]);
4437 tbl_tx_filter_coef_rev4[i][j]); 4980
4981 /* Verified with BCM43227 and BCM43228 */
4982 if (dev->phy.rev == 16)
4983 b43_nphy_pa_set_tx_dig_filter(dev, 0x186, dig_filter_phy_rev16);
4984
4985 if (dev->dev->chip_id == BCMA_CHIP_ID_BCM43217) {
4986 b43_nphy_pa_set_tx_dig_filter(dev, 0x186, dig_filter_phy_rev16);
4987 b43_nphy_pa_set_tx_dig_filter(dev, 0x195,
4988 tbl_tx_filter_coef_rev4[1]);
4989 }
4438 4990
4439 if (b43_is_40mhz(dev)) { 4991 if (b43_is_40mhz(dev)) {
4440 for (j = 0; j < 15; j++) 4992 b43_nphy_pa_set_tx_dig_filter(dev, 0x186,
4441 b43_phy_write(dev, B43_PHY_N(offset[0] + j), 4993 tbl_tx_filter_coef_rev4[3]);
4442 tbl_tx_filter_coef_rev4[3][j]); 4994 } else {
4443 } else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { 4995 if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
4444 for (j = 0; j < 15; j++) 4996 b43_nphy_pa_set_tx_dig_filter(dev, 0x186,
4445 b43_phy_write(dev, B43_PHY_N(offset[0] + j), 4997 tbl_tx_filter_coef_rev4[5]);
4446 tbl_tx_filter_coef_rev4[5][j]); 4998 if (dev->phy.channel == 14)
4447 } 4999 b43_nphy_pa_set_tx_dig_filter(dev, 0x186,
4448 5000 tbl_tx_filter_coef_rev4[6]);
4449 if (dev->phy.channel == 14) 5001 }
4450 for (j = 0; j < 15; j++)
4451 b43_phy_write(dev, B43_PHY_N(offset[0] + j),
4452 tbl_tx_filter_coef_rev4[6][j]);
4453} 5002}
4454 5003
4455/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */ 5004/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */
@@ -4471,7 +5020,13 @@ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev)
4471 b43_nphy_stay_in_carrier_search(dev, false); 5020 b43_nphy_stay_in_carrier_search(dev, false);
4472 5021
4473 for (i = 0; i < 2; ++i) { 5022 for (i = 0; i < 2; ++i) {
4474 if (dev->phy.rev >= 3) { 5023 if (dev->phy.rev >= 7) {
5024 target.ipa[i] = curr_gain[i] & 0x0007;
5025 target.pad[i] = (curr_gain[i] & 0x00F8) >> 3;
5026 target.pga[i] = (curr_gain[i] & 0x0F00) >> 8;
5027 target.txgm[i] = (curr_gain[i] & 0x7000) >> 12;
5028 target.tx_lpf[i] = (curr_gain[i] & 0x8000) >> 15;
5029 } else if (dev->phy.rev >= 3) {
4475 target.ipa[i] = curr_gain[i] & 0x000F; 5030 target.ipa[i] = curr_gain[i] & 0x000F;
4476 target.pad[i] = (curr_gain[i] & 0x00F0) >> 4; 5031 target.pad[i] = (curr_gain[i] & 0x00F0) >> 4;
4477 target.pga[i] = (curr_gain[i] & 0x0F00) >> 8; 5032 target.pga[i] = (curr_gain[i] & 0x0F00) >> 8;
@@ -4498,7 +5053,13 @@ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev)
4498 if (!table) 5053 if (!table)
4499 break; 5054 break;
4500 5055
4501 if (dev->phy.rev >= 3) { 5056 if (dev->phy.rev >= 7) {
5057 target.ipa[i] = (table[index[i]] >> 16) & 0x7;
5058 target.pad[i] = (table[index[i]] >> 19) & 0x1F;
5059 target.pga[i] = (table[index[i]] >> 24) & 0xF;
5060 target.txgm[i] = (table[index[i]] >> 28) & 0x7;
5061 target.tx_lpf[i] = (table[index[i]] >> 31) & 0x1;
5062 } else if (dev->phy.rev >= 3) {
4502 target.ipa[i] = (table[index[i]] >> 16) & 0xF; 5063 target.ipa[i] = (table[index[i]] >> 16) & 0xF;
4503 target.pad[i] = (table[index[i]] >> 20) & 0xF; 5064 target.pad[i] = (table[index[i]] >> 20) & 0xF;
4504 target.pga[i] = (table[index[i]] >> 24) & 0xF; 5065 target.pga[i] = (table[index[i]] >> 24) & 0xF;
@@ -4547,6 +5108,8 @@ static void b43_nphy_tx_cal_phy_cleanup(struct b43_wldev *dev)
4547/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */ 5108/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */
4548static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev) 5109static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)
4549{ 5110{
5111 struct b43_phy *phy = &dev->phy;
5112 struct b43_phy_n *nphy = dev->phy.n;
4550 u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs; 5113 u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
4551 u16 tmp; 5114 u16 tmp;
4552 5115
@@ -4578,7 +5141,12 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)
4578 regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); 5141 regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
4579 regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); 5142 regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
4580 5143
4581 b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA, 1, 3); 5144 if (!nphy->use_int_tx_iq_lo_cal)
5145 b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA,
5146 1, 3);
5147 else
5148 b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA,
5149 0, 3);
4582 b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 2, 1); 5150 b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 2, 1);
4583 b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 8, 2); 5151 b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 8, 2);
4584 5152
@@ -4586,6 +5154,33 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)
4586 regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1); 5154 regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
4587 b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001); 5155 b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
4588 b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001); 5156 b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
5157
5158 tmp = b43_nphy_read_lpf_ctl(dev, 0);
5159 if (phy->rev >= 19)
5160 b43_nphy_rf_ctl_override_rev19(dev, 0x80, tmp, 0, false,
5161 1);
5162 else if (phy->rev >= 7)
5163 b43_nphy_rf_ctl_override_rev7(dev, 0x80, tmp, 0, false,
5164 1);
5165
5166 if (nphy->use_int_tx_iq_lo_cal && true /* FIXME */) {
5167 if (phy->rev >= 19) {
5168 b43_nphy_rf_ctl_override_rev19(dev, 0x8, 0, 0x3,
5169 false, 0);
5170 } else if (phy->rev >= 8) {
5171 b43_nphy_rf_ctl_override_rev7(dev, 0x8, 0, 0x3,
5172 false, 0);
5173 } else if (phy->rev == 7) {
5174 b43_radio_maskset(dev, R2057_OVR_REG0, 1 << 4, 1 << 4);
5175 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
5176 b43_radio_maskset(dev, R2057_PAD2G_TUNE_PUS_CORE0, ~1, 0);
5177 b43_radio_maskset(dev, R2057_PAD2G_TUNE_PUS_CORE1, ~1, 0);
5178 } else {
5179 b43_radio_maskset(dev, R2057_IPA5G_CASCOFFV_PU_CORE0, ~1, 0);
5180 b43_radio_maskset(dev, R2057_IPA5G_CASCOFFV_PU_CORE1, ~1, 0);
5181 }
5182 }
5183 }
4589 } else { 5184 } else {
4590 b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, 0xA000); 5185 b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, 0xA000);
4591 b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, 0xA000); 5186 b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, 0xA000);
@@ -4614,6 +5209,7 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)
4614/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */ 5209/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */
4615static void b43_nphy_save_cal(struct b43_wldev *dev) 5210static void b43_nphy_save_cal(struct b43_wldev *dev)
4616{ 5211{
5212 struct b43_phy *phy = &dev->phy;
4617 struct b43_phy_n *nphy = dev->phy.n; 5213 struct b43_phy_n *nphy = dev->phy.n;
4618 5214
4619 struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; 5215 struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
@@ -4638,7 +5234,26 @@ static void b43_nphy_save_cal(struct b43_wldev *dev)
4638 5234
4639 b43_nphy_rx_iq_coeffs(dev, false, rxcal_coeffs); 5235 b43_nphy_rx_iq_coeffs(dev, false, rxcal_coeffs);
4640 /* TODO use some definitions */ 5236 /* TODO use some definitions */
4641 if (dev->phy.rev >= 3) { 5237 if (phy->rev >= 19) {
5238 /* TODO */
5239 } else if (phy->rev >= 7) {
5240 txcal_radio_regs[0] = b43_radio_read(dev,
5241 R2057_TX0_LOFT_FINE_I);
5242 txcal_radio_regs[1] = b43_radio_read(dev,
5243 R2057_TX0_LOFT_FINE_Q);
5244 txcal_radio_regs[4] = b43_radio_read(dev,
5245 R2057_TX0_LOFT_COARSE_I);
5246 txcal_radio_regs[5] = b43_radio_read(dev,
5247 R2057_TX0_LOFT_COARSE_Q);
5248 txcal_radio_regs[2] = b43_radio_read(dev,
5249 R2057_TX1_LOFT_FINE_I);
5250 txcal_radio_regs[3] = b43_radio_read(dev,
5251 R2057_TX1_LOFT_FINE_Q);
5252 txcal_radio_regs[6] = b43_radio_read(dev,
5253 R2057_TX1_LOFT_COARSE_I);
5254 txcal_radio_regs[7] = b43_radio_read(dev,
5255 R2057_TX1_LOFT_COARSE_Q);
5256 } else if (phy->rev >= 3) {
4642 txcal_radio_regs[0] = b43_radio_read(dev, 0x2021); 5257 txcal_radio_regs[0] = b43_radio_read(dev, 0x2021);
4643 txcal_radio_regs[1] = b43_radio_read(dev, 0x2022); 5258 txcal_radio_regs[1] = b43_radio_read(dev, 0x2022);
4644 txcal_radio_regs[2] = b43_radio_read(dev, 0x3021); 5259 txcal_radio_regs[2] = b43_radio_read(dev, 0x3021);
@@ -4665,6 +5280,7 @@ static void b43_nphy_save_cal(struct b43_wldev *dev)
4665/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */ 5280/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */
4666static void b43_nphy_restore_cal(struct b43_wldev *dev) 5281static void b43_nphy_restore_cal(struct b43_wldev *dev)
4667{ 5282{
5283 struct b43_phy *phy = &dev->phy;
4668 struct b43_phy_n *nphy = dev->phy.n; 5284 struct b43_phy_n *nphy = dev->phy.n;
4669 5285
4670 u16 coef[4]; 5286 u16 coef[4];
@@ -4712,7 +5328,26 @@ static void b43_nphy_restore_cal(struct b43_wldev *dev)
4712 } 5328 }
4713 5329
4714 /* TODO use some definitions */ 5330 /* TODO use some definitions */
4715 if (dev->phy.rev >= 3) { 5331 if (phy->rev >= 19) {
5332 /* TODO */
5333 } else if (phy->rev >= 7) {
5334 b43_radio_write(dev, R2057_TX0_LOFT_FINE_I,
5335 txcal_radio_regs[0]);
5336 b43_radio_write(dev, R2057_TX0_LOFT_FINE_Q,
5337 txcal_radio_regs[1]);
5338 b43_radio_write(dev, R2057_TX0_LOFT_COARSE_I,
5339 txcal_radio_regs[4]);
5340 b43_radio_write(dev, R2057_TX0_LOFT_COARSE_Q,
5341 txcal_radio_regs[5]);
5342 b43_radio_write(dev, R2057_TX1_LOFT_FINE_I,
5343 txcal_radio_regs[2]);
5344 b43_radio_write(dev, R2057_TX1_LOFT_FINE_Q,
5345 txcal_radio_regs[3]);
5346 b43_radio_write(dev, R2057_TX1_LOFT_COARSE_I,
5347 txcal_radio_regs[6]);
5348 b43_radio_write(dev, R2057_TX1_LOFT_COARSE_Q,
5349 txcal_radio_regs[7]);
5350 } else if (phy->rev >= 3) {
4716 b43_radio_write(dev, 0x2021, txcal_radio_regs[0]); 5351 b43_radio_write(dev, 0x2021, txcal_radio_regs[0]);
4717 b43_radio_write(dev, 0x2022, txcal_radio_regs[1]); 5352 b43_radio_write(dev, 0x2022, txcal_radio_regs[1]);
4718 b43_radio_write(dev, 0x3021, txcal_radio_regs[2]); 5353 b43_radio_write(dev, 0x3021, txcal_radio_regs[2]);
@@ -4789,7 +5424,13 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
4789 } 5424 }
4790 } 5425 }
4791 5426
4792 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9); 5427 if (phy->rev >= 19) {
5428 /* TODO */
5429 } else if (phy->rev >= 7) {
5430 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AD9);
5431 } else {
5432 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9);
5433 }
4793 5434
4794 if (!b43_is_40mhz(dev)) 5435 if (!b43_is_40mhz(dev))
4795 freq = 2500; 5436 freq = 2500;
@@ -5183,6 +5824,9 @@ static int b43_nphy_rev3_cal_rx_iq(struct b43_wldev *dev,
5183static int b43_nphy_cal_rx_iq(struct b43_wldev *dev, 5824static int b43_nphy_cal_rx_iq(struct b43_wldev *dev,
5184 struct nphy_txgains target, u8 type, bool debug) 5825 struct nphy_txgains target, u8 type, bool debug)
5185{ 5826{
5827 if (dev->phy.rev >= 7)
5828 type = 0;
5829
5186 if (dev->phy.rev >= 3) 5830 if (dev->phy.rev >= 3)
5187 return b43_nphy_rev3_cal_rx_iq(dev, target, type, debug); 5831 return b43_nphy_rev3_cal_rx_iq(dev, target, type, debug);
5188 else 5832 else
@@ -5269,6 +5913,9 @@ static void b43_nphy_bphy_init(struct b43_wldev *dev)
5269/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */ 5913/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */
5270static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init) 5914static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)
5271{ 5915{
5916 if (dev->phy.rev >= 7)
5917 return;
5918
5272 if (dev->phy.rev >= 3) { 5919 if (dev->phy.rev >= 3) {
5273 if (!init) 5920 if (!init)
5274 return; 5921 return;
@@ -5344,6 +5991,10 @@ static int b43_phy_initn(struct b43_wldev *dev)
5344#endif 5991#endif
5345 } 5992 }
5346 } 5993 }
5994 nphy->use_int_tx_iq_lo_cal = b43_nphy_ipa(dev) ||
5995 phy->rev >= 7 ||
5996 (phy->rev >= 5 &&
5997 sprom->boardflags2_hi & B43_BFH2_INTERNDET_TXIQCAL);
5347 nphy->deaf_count = 0; 5998 nphy->deaf_count = 0;
5348 b43_nphy_tables_init(dev); 5999 b43_nphy_tables_init(dev);
5349 nphy->crsminpwr_adjusted = false; 6000 nphy->crsminpwr_adjusted = false;
@@ -5353,6 +6004,16 @@ static int b43_phy_initn(struct b43_wldev *dev)
5353 if (dev->phy.rev >= 3) { 6004 if (dev->phy.rev >= 3) {
5354 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, 0); 6005 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, 0);
5355 b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0); 6006 b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
6007 if (phy->rev >= 7) {
6008 b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0);
6009 b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER4, 0);
6010 b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER5, 0);
6011 b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER6, 0);
6012 }
6013 if (phy->rev >= 19) {
6014 /* TODO */
6015 }
6016
5356 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, 0); 6017 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, 0);
5357 b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, 0); 6018 b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, 0);
5358 } else { 6019 } else {
@@ -5390,7 +6051,9 @@ static int b43_phy_initn(struct b43_wldev *dev)
5390 b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50); 6051 b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50);
5391 b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30); 6052 b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30);
5392 6053
5393 b43_nphy_update_mimo_config(dev, nphy->preamble_override); 6054 if (phy->rev < 8)
6055 b43_nphy_update_mimo_config(dev, nphy->preamble_override);
6056
5394 b43_nphy_update_txrx_chain(dev); 6057 b43_nphy_update_txrx_chain(dev);
5395 6058
5396 if (phy->rev < 2) { 6059 if (phy->rev < 2) {
@@ -5422,10 +6085,12 @@ static int b43_phy_initn(struct b43_wldev *dev)
5422 6085
5423 b43_mac_phy_clock_set(dev, true); 6086 b43_mac_phy_clock_set(dev, true);
5424 6087
5425 b43_nphy_pa_override(dev, false); 6088 if (phy->rev < 7) {
5426 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); 6089 b43_nphy_pa_override(dev, false);
5427 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); 6090 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
5428 b43_nphy_pa_override(dev, true); 6091 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
6092 b43_nphy_pa_override(dev, true);
6093 }
5429 6094
5430 b43_nphy_classifier(dev, 0, 0); 6095 b43_nphy_classifier(dev, 0, 0);
5431 b43_nphy_read_clip_detection(dev, clip); 6096 b43_nphy_read_clip_detection(dev, clip);
@@ -5548,23 +6213,23 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev,
5548 struct b43_phy *phy = &dev->phy; 6213 struct b43_phy *phy = &dev->phy;
5549 struct b43_phy_n *nphy = dev->phy.n; 6214 struct b43_phy_n *nphy = dev->phy.n;
5550 int ch = new_channel->hw_value; 6215 int ch = new_channel->hw_value;
5551
5552 u16 old_band_5ghz;
5553 u16 tmp16; 6216 u16 tmp16;
5554 6217
5555 old_band_5ghz = 6218 if (new_channel->band == IEEE80211_BAND_5GHZ) {
5556 b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ;
5557 if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) {
5558 tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR); 6219 tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR);
5559 b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4); 6220 b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4);
5560 b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000); 6221 /* Put BPHY in the reset */
6222 b43_phy_set(dev, B43_PHY_B_BBCFG,
6223 B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX);
5561 b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16); 6224 b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16);
5562 b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ); 6225 b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ);
5563 } else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) { 6226 } else if (new_channel->band == IEEE80211_BAND_2GHZ) {
5564 b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); 6227 b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
5565 tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR); 6228 tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR);
5566 b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4); 6229 b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4);
5567 b43_phy_mask(dev, B43_PHY_B_BBCFG, 0x3FFF); 6230 /* Take BPHY out of the reset */
6231 b43_phy_mask(dev, B43_PHY_B_BBCFG,
6232 (u16)~(B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX));
5568 b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16); 6233 b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16);
5569 } 6234 }
5570 6235
@@ -5589,31 +6254,45 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev,
5589 6254
5590 if (dev->phy.rev >= 3 && 6255 if (dev->phy.rev >= 3 &&
5591 dev->phy.n->spur_avoid != B43_SPUR_AVOID_DISABLE) { 6256 dev->phy.n->spur_avoid != B43_SPUR_AVOID_DISABLE) {
5592 bool avoid = false; 6257 u8 spuravoid = 0;
6258
5593 if (dev->phy.n->spur_avoid == B43_SPUR_AVOID_FORCE) { 6259 if (dev->phy.n->spur_avoid == B43_SPUR_AVOID_FORCE) {
5594 avoid = true; 6260 spuravoid = 1;
5595 } else if (!b43_is_40mhz(dev)) { 6261 } else if (phy->rev >= 19) {
5596 if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14) 6262 /* TODO */
5597 avoid = true; 6263 } else if (phy->rev >= 18) {
5598 } else { /* 40MHz */ 6264 /* TODO */
5599 if (nphy->aband_spurwar_en && 6265 } else if (phy->rev >= 17) {
5600 (ch == 38 || ch == 102 || ch == 118)) 6266 /* TODO: Off for channels 1-11, but check 12-14! */
5601 avoid = dev->dev->chip_id == 0x4716; 6267 } else if (phy->rev >= 16) {
6268 /* TODO: Off for 2 GHz, but check 5 GHz! */
6269 } else if (phy->rev >= 7) {
6270 if (!b43_is_40mhz(dev)) { /* 20MHz */
6271 if (ch == 13 || ch == 14 || ch == 153)
6272 spuravoid = 1;
6273 } else { /* 40 MHz */
6274 if (ch == 54)
6275 spuravoid = 1;
6276 }
6277 } else {
6278 if (!b43_is_40mhz(dev)) { /* 20MHz */
6279 if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14)
6280 spuravoid = 1;
6281 } else { /* 40MHz */
6282 if (nphy->aband_spurwar_en &&
6283 (ch == 38 || ch == 102 || ch == 118))
6284 spuravoid = dev->dev->chip_id == 0x4716;
6285 }
5602 } 6286 }
5603 6287
5604 b43_nphy_pmu_spur_avoid(dev, avoid); 6288 b43_nphy_pmu_spur_avoid(dev, spuravoid);
5605 6289
5606 if (dev->dev->chip_id == 43222 || dev->dev->chip_id == 43224 || 6290 b43_mac_switch_freq(dev, spuravoid);
5607 dev->dev->chip_id == 43225) {
5608 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW,
5609 avoid ? 0x5341 : 0x8889);
5610 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
5611 }
5612 6291
5613 if (dev->phy.rev == 3 || dev->phy.rev == 4) 6292 if (dev->phy.rev == 3 || dev->phy.rev == 4)
5614 ; /* TODO: reset PLL */ 6293 ; /* TODO: reset PLL */
5615 6294
5616 if (avoid) 6295 if (spuravoid)
5617 b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTRX); 6296 b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTRX);
5618 else 6297 else
5619 b43_phy_mask(dev, B43_NPHY_BBCFG, 6298 b43_phy_mask(dev, B43_NPHY_BBCFG,
@@ -5644,7 +6323,10 @@ static int b43_nphy_set_channel(struct b43_wldev *dev,
5644 6323
5645 u8 tmp; 6324 u8 tmp;
5646 6325
5647 if (phy->rev >= 7) { 6326 if (phy->rev >= 19) {
6327 return -ESRCH;
6328 /* TODO */
6329 } else if (phy->rev >= 7) {
5648 r2057_get_chantabent_rev7(dev, channel->center_freq, 6330 r2057_get_chantabent_rev7(dev, channel->center_freq,
5649 &tabent_r7, &tabent_r7_2g); 6331 &tabent_r7, &tabent_r7_2g);
5650 if (!tabent_r7 && !tabent_r7_2g) 6332 if (!tabent_r7 && !tabent_r7_2g)
@@ -5681,7 +6363,9 @@ static int b43_nphy_set_channel(struct b43_wldev *dev,
5681 b43_phy_mask(dev, 0x310, (u16)~0x8000); 6363 b43_phy_mask(dev, 0x310, (u16)~0x8000);
5682 } 6364 }
5683 6365
5684 if (phy->rev >= 7) { 6366 if (phy->rev >= 19) {
6367 /* TODO */
6368 } else if (phy->rev >= 7) {
5685 const struct b43_phy_n_sfo_cfg *phy_regs = tabent_r7 ? 6369 const struct b43_phy_n_sfo_cfg *phy_regs = tabent_r7 ?
5686 &(tabent_r7->phy_regs) : &(tabent_r7_2g->phy_regs); 6370 &(tabent_r7->phy_regs) : &(tabent_r7_2g->phy_regs);
5687 6371
@@ -5834,7 +6518,7 @@ static void b43_nphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
5834static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg) 6518static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg)
5835{ 6519{
5836 /* Register 1 is a 32-bit register. */ 6520 /* Register 1 is a 32-bit register. */
5837 B43_WARN_ON(reg == 1); 6521 B43_WARN_ON(dev->phy.rev < 7 && reg == 1);
5838 6522
5839 if (dev->phy.rev >= 7) 6523 if (dev->phy.rev >= 7)
5840 reg |= 0x200; /* Radio 0x2057 */ 6524 reg |= 0x200; /* Radio 0x2057 */
@@ -5848,7 +6532,7 @@ static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg)
5848static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) 6532static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
5849{ 6533{
5850 /* Register 1 is a 32-bit register. */ 6534 /* Register 1 is a 32-bit register. */
5851 B43_WARN_ON(reg == 1); 6535 B43_WARN_ON(dev->phy.rev < 7 && reg == 1);
5852 6536
5853 b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); 6537 b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
5854 b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); 6538 b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
@@ -5858,15 +6542,23 @@ static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
5858static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, 6542static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
5859 bool blocked) 6543 bool blocked)
5860{ 6544{
6545 struct b43_phy *phy = &dev->phy;
6546
5861 if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED) 6547 if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
5862 b43err(dev->wl, "MAC not suspended\n"); 6548 b43err(dev->wl, "MAC not suspended\n");
5863 6549
5864 if (blocked) { 6550 if (blocked) {
5865 b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, 6551 if (phy->rev >= 19) {
5866 ~B43_NPHY_RFCTL_CMD_CHIP0PU);
5867 if (dev->phy.rev >= 7) {
5868 /* TODO */ 6552 /* TODO */
5869 } else if (dev->phy.rev >= 3) { 6553 } else if (phy->rev >= 8) {
6554 b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
6555 ~B43_NPHY_RFCTL_CMD_CHIP0PU);
6556 } else if (phy->rev >= 7) {
6557 /* Nothing needed */
6558 } else if (phy->rev >= 3) {
6559 b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
6560 ~B43_NPHY_RFCTL_CMD_CHIP0PU);
6561
5870 b43_radio_mask(dev, 0x09, ~0x2); 6562 b43_radio_mask(dev, 0x09, ~0x2);
5871 6563
5872 b43_radio_write(dev, 0x204D, 0); 6564 b43_radio_write(dev, 0x204D, 0);
@@ -5884,11 +6576,13 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
5884 b43_radio_write(dev, 0x3064, 0); 6576 b43_radio_write(dev, 0x3064, 0);
5885 } 6577 }
5886 } else { 6578 } else {
5887 if (dev->phy.rev >= 7) { 6579 if (phy->rev >= 19) {
6580 /* TODO */
6581 } else if (phy->rev >= 7) {
5888 if (!dev->phy.radio_on) 6582 if (!dev->phy.radio_on)
5889 b43_radio_2057_init(dev); 6583 b43_radio_2057_init(dev);
5890 b43_switch_channel(dev, dev->phy.channel); 6584 b43_switch_channel(dev, dev->phy.channel);
5891 } else if (dev->phy.rev >= 3) { 6585 } else if (phy->rev >= 3) {
5892 if (!dev->phy.radio_on) 6586 if (!dev->phy.radio_on)
5893 b43_radio_init2056(dev); 6587 b43_radio_init2056(dev);
5894 b43_switch_channel(dev, dev->phy.channel); 6588 b43_switch_channel(dev, dev->phy.channel);
@@ -5901,10 +6595,13 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
5901/* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */ 6595/* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */
5902static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on) 6596static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
5903{ 6597{
6598 struct b43_phy *phy = &dev->phy;
5904 u16 override = on ? 0x0 : 0x7FFF; 6599 u16 override = on ? 0x0 : 0x7FFF;
5905 u16 core = on ? 0xD : 0x00FD; 6600 u16 core = on ? 0xD : 0x00FD;
5906 6601
5907 if (dev->phy.rev >= 3) { 6602 if (phy->rev >= 19) {
6603 /* TODO */
6604 } else if (phy->rev >= 3) {
5908 if (on) { 6605 if (on) {
5909 b43_phy_write(dev, B43_NPHY_AFECTL_C1, core); 6606 b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
5910 b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override); 6607 b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h
index ecfbf66dbc3b..30bec815b969 100644
--- a/drivers/net/wireless/b43/phy_n.h
+++ b/drivers/net/wireless/b43/phy_n.h
@@ -366,11 +366,13 @@
366#define B43_NPHY_TXF_40CO_B1S0 B43_PHY_N(0x0E5) /* TX filter 40 coeff B1 stage 0 */ 366#define B43_NPHY_TXF_40CO_B1S0 B43_PHY_N(0x0E5) /* TX filter 40 coeff B1 stage 0 */
367#define B43_NPHY_TXF_40CO_B32S1 B43_PHY_N(0x0E6) /* TX filter 40 coeff B32 stage 1 */ 367#define B43_NPHY_TXF_40CO_B32S1 B43_PHY_N(0x0E6) /* TX filter 40 coeff B32 stage 1 */
368#define B43_NPHY_TXF_40CO_B1S1 B43_PHY_N(0x0E7) /* TX filter 40 coeff B1 stage 1 */ 368#define B43_NPHY_TXF_40CO_B1S1 B43_PHY_N(0x0E7) /* TX filter 40 coeff B1 stage 1 */
369#define B43_NPHY_REV3_RFCTL_OVER0 B43_PHY_N(0x0E7)
369#define B43_NPHY_TXF_40CO_B32S2 B43_PHY_N(0x0E8) /* TX filter 40 coeff B32 stage 2 */ 370#define B43_NPHY_TXF_40CO_B32S2 B43_PHY_N(0x0E8) /* TX filter 40 coeff B32 stage 2 */
370#define B43_NPHY_TXF_40CO_B1S2 B43_PHY_N(0x0E9) /* TX filter 40 coeff B1 stage 2 */ 371#define B43_NPHY_TXF_40CO_B1S2 B43_PHY_N(0x0E9) /* TX filter 40 coeff B1 stage 2 */
371#define B43_NPHY_BIST_STAT2 B43_PHY_N(0x0EA) /* BIST status 2 */ 372#define B43_NPHY_BIST_STAT2 B43_PHY_N(0x0EA) /* BIST status 2 */
372#define B43_NPHY_BIST_STAT3 B43_PHY_N(0x0EB) /* BIST status 3 */ 373#define B43_NPHY_BIST_STAT3 B43_PHY_N(0x0EB) /* BIST status 3 */
373#define B43_NPHY_RFCTL_OVER B43_PHY_N(0x0EC) /* RF control override */ 374#define B43_NPHY_RFCTL_OVER B43_PHY_N(0x0EC) /* RF control override */
375#define B43_NPHY_REV3_RFCTL_OVER1 B43_PHY_N(0x0EC)
374#define B43_NPHY_MIMOCFG B43_PHY_N(0x0ED) /* MIMO config */ 376#define B43_NPHY_MIMOCFG B43_PHY_N(0x0ED) /* MIMO config */
375#define B43_NPHY_MIMOCFG_GFMIX 0x0004 /* Greenfield or mixed mode */ 377#define B43_NPHY_MIMOCFG_GFMIX 0x0004 /* Greenfield or mixed mode */
376#define B43_NPHY_MIMOCFG_AUTO 0x0100 /* Greenfield/mixed mode auto */ 378#define B43_NPHY_MIMOCFG_AUTO 0x0100 /* Greenfield/mixed mode auto */
@@ -857,7 +859,18 @@
857#define B43_NPHY_REV3_C2_CLIP2_GAIN_A B43_PHY_N(0x2AF) 859#define B43_NPHY_REV3_C2_CLIP2_GAIN_A B43_PHY_N(0x2AF)
858#define B43_NPHY_REV3_C2_CLIP2_GAIN_B B43_PHY_N(0x2B0) 860#define B43_NPHY_REV3_C2_CLIP2_GAIN_B B43_PHY_N(0x2B0)
859 861
862#define B43_NPHY_REV7_RF_CTL_MISC_REG3 B43_PHY_N(0x340)
863#define B43_NPHY_REV7_RF_CTL_MISC_REG4 B43_PHY_N(0x341)
864#define B43_NPHY_REV7_RF_CTL_OVER3 B43_PHY_N(0x342)
865#define B43_NPHY_REV7_RF_CTL_OVER4 B43_PHY_N(0x343)
866#define B43_NPHY_REV7_RF_CTL_MISC_REG5 B43_PHY_N(0x344)
867#define B43_NPHY_REV7_RF_CTL_MISC_REG6 B43_PHY_N(0x345)
868#define B43_NPHY_REV7_RF_CTL_OVER5 B43_PHY_N(0x346)
869#define B43_NPHY_REV7_RF_CTL_OVER6 B43_PHY_N(0x347)
870
860#define B43_PHY_B_BBCFG B43_PHY_N_BMODE(0x001) /* BB config */ 871#define B43_PHY_B_BBCFG B43_PHY_N_BMODE(0x001) /* BB config */
872#define B43_PHY_B_BBCFG_RSTCCA 0x4000 /* Reset CCA */
873#define B43_PHY_B_BBCFG_RSTRX 0x8000 /* Reset RX */
861#define B43_PHY_B_TEST B43_PHY_N_BMODE(0x00A) 874#define B43_PHY_B_TEST B43_PHY_N_BMODE(0x00A)
862 875
863struct b43_wldev; 876struct b43_wldev;
@@ -935,6 +948,8 @@ struct b43_phy_n {
935 bool gain_boost; 948 bool gain_boost;
936 bool elna_gain_config; 949 bool elna_gain_config;
937 bool band5g_pwrgain; 950 bool band5g_pwrgain;
951 bool use_int_tx_iq_lo_cal;
952 bool lpf_bw_overrode_for_sample_play;
938 953
939 u8 mphase_cal_phase_id; 954 u8 mphase_cal_phase_id;
940 u16 mphase_txcal_cmdidx; 955 u16 mphase_txcal_cmdidx;
diff --git a/drivers/net/wireless/b43/radio_2057.c b/drivers/net/wireless/b43/radio_2057.c
index df3574545819..ff1e026a61a1 100644
--- a/drivers/net/wireless/b43/radio_2057.c
+++ b/drivers/net/wireless/b43/radio_2057.c
@@ -105,6 +105,27 @@ static u16 r2057_rev8_init[][2] = {
105}; 105};
106*/ 106*/
107 107
108/* Extracted from MMIO dump of 6.30.223.141 */
109static u16 r2057_rev9_init[][2] = {
110 { 0x27, 0x1f }, { 0x28, 0x0a }, { 0x29, 0x2f }, { 0x42, 0x1f },
111 { 0x48, 0x3f }, { 0x5c, 0x41 }, { 0x63, 0x14 }, { 0x64, 0x12 },
112 { 0x66, 0xff }, { 0x74, 0xa3 }, { 0x7b, 0x14 }, { 0x7c, 0x14 },
113 { 0x7d, 0xee }, { 0x86, 0xc0 }, { 0xc4, 0x10 }, { 0xc9, 0x01 },
114 { 0xe1, 0x41 }, { 0xe8, 0x14 }, { 0xe9, 0x12 }, { 0xeb, 0xff },
115 { 0xf5, 0x0a }, { 0xf8, 0x09 }, { 0xf9, 0xa3 }, { 0x100, 0x14 },
116 { 0x101, 0x10 }, { 0x102, 0xee }, { 0x10b, 0xc0 }, { 0x149, 0x10 },
117 { 0x14e, 0x01 }, { 0x1b7, 0x05 }, { 0x1c2, 0xa0 },
118};
119
120/* Extracted from MMIO dump of 6.30.223.248 */
121static u16 r2057_rev14_init[][2] = {
122 { 0x011, 0xfc }, { 0x030, 0x24 }, { 0x040, 0x1c }, { 0x082, 0x08 },
123 { 0x0b4, 0x44 }, { 0x0c8, 0x01 }, { 0x0c9, 0x01 }, { 0x107, 0x08 },
124 { 0x14d, 0x01 }, { 0x14e, 0x01 }, { 0x1af, 0x40 }, { 0x1b0, 0x40 },
125 { 0x1cc, 0x01 }, { 0x1cf, 0x10 }, { 0x1d0, 0x0f }, { 0x1d3, 0x10 },
126 { 0x1d4, 0x0f },
127};
128
108#define RADIOREGS7(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \ 129#define RADIOREGS7(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
109 r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \ 130 r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
110 r20, r21, r22, r23, r24, r25, r26, r27) \ 131 r20, r21, r22, r23, r24, r25, r26, r27) \
@@ -137,6 +158,27 @@ static u16 r2057_rev8_init[][2] = {
137 .radio_lna2g_tune_core1 = r26, \ 158 .radio_lna2g_tune_core1 = r26, \
138 .radio_lna5g_tune_core1 = r27 159 .radio_lna5g_tune_core1 = r27
139 160
161#define RADIOREGS7_2G(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
162 r10, r11, r12, r13, r14, r15, r16, r17) \
163 .radio_vcocal_countval0 = r00, \
164 .radio_vcocal_countval1 = r01, \
165 .radio_rfpll_refmaster_sparextalsize = r02, \
166 .radio_rfpll_loopfilter_r1 = r03, \
167 .radio_rfpll_loopfilter_c2 = r04, \
168 .radio_rfpll_loopfilter_c1 = r05, \
169 .radio_cp_kpd_idac = r06, \
170 .radio_rfpll_mmd0 = r07, \
171 .radio_rfpll_mmd1 = r08, \
172 .radio_vcobuf_tune = r09, \
173 .radio_logen_mx2g_tune = r10, \
174 .radio_logen_indbuf2g_tune = r11, \
175 .radio_txmix2g_tune_boost_pu_core0 = r12, \
176 .radio_pad2g_tune_pus_core0 = r13, \
177 .radio_lna2g_tune_core0 = r14, \
178 .radio_txmix2g_tune_boost_pu_core1 = r15, \
179 .radio_pad2g_tune_pus_core1 = r16, \
180 .radio_lna2g_tune_core1 = r17
181
140#define PHYREGS(r0, r1, r2, r3, r4, r5) \ 182#define PHYREGS(r0, r1, r2, r3, r4, r5) \
141 .phy_regs.phy_bw1a = r0, \ 183 .phy_regs.phy_bw1a = r0, \
142 .phy_regs.phy_bw2 = r1, \ 184 .phy_regs.phy_bw2 = r1, \
@@ -145,6 +187,353 @@ static u16 r2057_rev8_init[][2] = {
145 .phy_regs.phy_bw5 = r4, \ 187 .phy_regs.phy_bw5 = r4, \
146 .phy_regs.phy_bw6 = r5 188 .phy_regs.phy_bw6 = r5
147 189
190/* Copied from brcmsmac (5.75.11): chan_info_nphyrev8_2057_rev5 */
191static const struct b43_nphy_chantabent_rev7_2g b43_nphy_chantab_phy_rev8_radio_rev5[] = {
192 {
193 .freq = 2412,
194 RADIOREGS7_2G(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
195 0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61,
196 0x03, 0xff),
197 PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
198 },
199 {
200 .freq = 2417,
201 RADIOREGS7_2G(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
202 0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61,
203 0x03, 0xff),
204 PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
205 },
206 {
207 .freq = 2422,
208 RADIOREGS7_2G(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
209 0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61,
210 0x03, 0xef),
211 PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
212 },
213 {
214 .freq = 2427,
215 RADIOREGS7_2G(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
216 0x09, 0x0c, 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61,
217 0x03, 0xdf),
218 PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
219 },
220 {
221 .freq = 2432,
222 RADIOREGS7_2G(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
223 0x09, 0x0c, 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61,
224 0x03, 0xcf),
225 PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
226 },
227 {
228 .freq = 2437,
229 RADIOREGS7_2G(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
230 0x09, 0x0c, 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61,
231 0x03, 0xbf),
232 PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
233 },
234 {
235 .freq = 2442,
236 RADIOREGS7_2G(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
237 0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61,
238 0x03, 0xaf),
239 PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
240 },
241 {
242 .freq = 2447,
243 RADIOREGS7_2G(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
244 0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61,
245 0x03, 0x9f),
246 PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
247 },
248 {
249 .freq = 2452,
250 RADIOREGS7_2G(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
251 0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61,
252 0x03, 0x8f),
253 PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
254 },
255 {
256 .freq = 2457,
257 RADIOREGS7_2G(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
258 0x09, 0x0b, 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61,
259 0x03, 0x7f),
260 PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
261 },
262 {
263 .freq = 2462,
264 RADIOREGS7_2G(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
265 0x09, 0x0b, 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61,
266 0x03, 0x6f),
267 PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
268 },
269 {
270 .freq = 2467,
271 RADIOREGS7_2G(0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3,
272 0x09, 0x0b, 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61,
273 0x03, 0x5f),
274 PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
275 },
276 {
277 .freq = 2472,
278 RADIOREGS7_2G(0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8,
279 0x09, 0x0a, 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61,
280 0x03, 0x4f),
281 PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
282 },
283 {
284 .freq = 2484,
285 RADIOREGS7_2G(0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4,
286 0x09, 0x0a, 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61,
287 0x03, 0x3f),
288 PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424),
289 }
290};
291
292/* Extracted from MMIO dump of 6.30.223.248 */
293static const struct b43_nphy_chantabent_rev7_2g b43_nphy_chantab_phy_rev17_radio_rev14[] = {
294 {
295 .freq = 2412,
296 RADIOREGS7_2G(0x48, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x6c,
297 0x09, 0x0d, 0x09, 0x03, 0x21, 0x53, 0xff, 0x21,
298 0x53, 0xff),
299 PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
300 },
301 {
302 .freq = 2417,
303 RADIOREGS7_2G(0x4b, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x71,
304 0x09, 0x0d, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
305 0x53, 0xff),
306 PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
307 },
308 {
309 .freq = 2422,
310 RADIOREGS7_2G(0x4e, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x76,
311 0x09, 0x0d, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
312 0x53, 0xff),
313 PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
314 },
315 {
316 .freq = 2427,
317 RADIOREGS7_2G(0x52, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x7b,
318 0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
319 0x53, 0xff),
320 PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
321 },
322 {
323 .freq = 2432,
324 RADIOREGS7_2G(0x55, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x80,
325 0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
326 0x53, 0xff),
327 PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
328 },
329 {
330 .freq = 2437,
331 RADIOREGS7_2G(0x58, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x85,
332 0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
333 0x53, 0xff),
334 PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
335 },
336 {
337 .freq = 2442,
338 RADIOREGS7_2G(0x5c, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x8a,
339 0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21,
340 0x43, 0xff),
341 PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
342 },
343 {
344 .freq = 2447,
345 RADIOREGS7_2G(0x5f, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x8f,
346 0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21,
347 0x43, 0xff),
348 PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
349 },
350 {
351 .freq = 2452,
352 RADIOREGS7_2G(0x62, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x94,
353 0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21,
354 0x43, 0xff),
355 PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
356 },
357 {
358 .freq = 2457,
359 RADIOREGS7_2G(0x66, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x99,
360 0x09, 0x0b, 0x07, 0x03, 0x21, 0x43, 0xff, 0x21,
361 0x43, 0xff),
362 PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
363 },
364 {
365 .freq = 2462,
366 RADIOREGS7_2G(0x69, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x9e,
367 0x09, 0x0b, 0x07, 0x03, 0x01, 0x43, 0xff, 0x01,
368 0x43, 0xff),
369 PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
370 },
371};
372
373/* Extracted from MMIO dump of 6.30.223.141 */
374static const struct b43_nphy_chantabent_rev7 b43_nphy_chantab_phy_rev16_radio_rev9[] = {
375 {
376 .freq = 2412,
377 RADIOREGS7(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
378 0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x41, 0x63,
379 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
380 0x00, 0x00, 0xf0, 0x00),
381 PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
382 },
383 {
384 .freq = 2417,
385 RADIOREGS7(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
386 0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x41, 0x63,
387 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
388 0x00, 0x00, 0xf0, 0x00),
389 PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
390 },
391 {
392 .freq = 2422,
393 RADIOREGS7(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
394 0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x41, 0x63,
395 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
396 0x00, 0x00, 0xf0, 0x00),
397 PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
398 },
399 {
400 .freq = 2427,
401 RADIOREGS7(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
402 0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x41, 0x63,
403 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
404 0x00, 0x00, 0xf0, 0x00),
405 PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
406 },
407 {
408 .freq = 2432,
409 RADIOREGS7(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
410 0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x41, 0x63,
411 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
412 0x00, 0x00, 0xf0, 0x00),
413 PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
414 },
415 {
416 .freq = 2437,
417 RADIOREGS7(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
418 0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x41, 0x63,
419 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
420 0x00, 0x00, 0xf0, 0x00),
421 PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
422 },
423 {
424 .freq = 2442,
425 RADIOREGS7(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
426 0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63,
427 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
428 0x00, 0x00, 0xf0, 0x00),
429 PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
430 },
431 {
432 .freq = 2447,
433 RADIOREGS7(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
434 0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63,
435 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
436 0x00, 0x00, 0xf0, 0x00),
437 PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
438 },
439 {
440 .freq = 2452,
441 RADIOREGS7(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
442 0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63,
443 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
444 0x00, 0x00, 0xf0, 0x00),
445 PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
446 },
447 {
448 .freq = 2457,
449 RADIOREGS7(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
450 0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x41, 0x63,
451 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
452 0x00, 0x00, 0xf0, 0x00),
453 PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
454 },
455 {
456 .freq = 2462,
457 RADIOREGS7(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
458 0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x41, 0x63,
459 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
460 0x00, 0x00, 0xf0, 0x00),
461 PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
462 },
463 {
464 .freq = 5180,
465 RADIOREGS7(0xbe, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x06,
466 0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00,
467 0x9f, 0x2f, 0xa3, 0x00, 0xfc, 0x00, 0x00, 0x4f,
468 0x3a, 0x83, 0x00, 0xfc),
469 PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
470 },
471 {
472 .freq = 5200,
473 RADIOREGS7(0xc5, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x08,
474 0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00,
475 0x7f, 0x2f, 0x83, 0x00, 0xf8, 0x00, 0x00, 0x4c,
476 0x4a, 0x83, 0x00, 0xf8),
477 PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
478 },
479 {
480 .freq = 5220,
481 RADIOREGS7(0xcc, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x0a,
482 0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00,
483 0x6d, 0x3d, 0x83, 0x00, 0xf8, 0x00, 0x00, 0x2d,
484 0x2a, 0x73, 0x00, 0xf8),
485 PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
486 },
487 {
488 .freq = 5240,
489 RADIOREGS7(0xd2, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x0c,
490 0x02, 0x0d, 0x00, 0x0d, 0x00, 0x8d, 0x00, 0x00,
491 0x4d, 0x1c, 0x73, 0x00, 0xf8, 0x00, 0x00, 0x4d,
492 0x2b, 0x73, 0x00, 0xf8),
493 PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
494 },
495 {
496 .freq = 5745,
497 RADIOREGS7(0x7b, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x7d,
498 0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00,
499 0x08, 0x03, 0x03, 0x00, 0x30, 0x00, 0x00, 0x06,
500 0x02, 0x03, 0x00, 0x30),
501 PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
502 },
503 {
504 .freq = 5765,
505 RADIOREGS7(0x81, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x81,
506 0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00,
507 0x06, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05,
508 0x02, 0x03, 0x00, 0x00),
509 PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
510 },
511 {
512 .freq = 5785,
513 RADIOREGS7(0x88, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x85,
514 0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00,
515 0x08, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05,
516 0x21, 0x03, 0x00, 0x00),
517 PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
518 },
519 {
520 .freq = 5805,
521 RADIOREGS7(0x8f, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x89,
522 0x04, 0x07, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00,
523 0x06, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03,
524 0x00, 0x03, 0x00, 0x00),
525 PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
526 },
527 {
528 .freq = 5825,
529 RADIOREGS7(0x95, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x8d,
530 0x04, 0x07, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00,
531 0x05, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03,
532 0x00, 0x03, 0x00, 0x00),
533 PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
534 },
535};
536
148void r2057_upload_inittabs(struct b43_wldev *dev) 537void r2057_upload_inittabs(struct b43_wldev *dev)
149{ 538{
150 struct b43_phy *phy = &dev->phy; 539 struct b43_phy *phy = &dev->phy;
@@ -171,6 +560,18 @@ void r2057_upload_inittabs(struct b43_wldev *dev)
171 size = ARRAY_SIZE(r2057_rev5a_init); 560 size = ARRAY_SIZE(r2057_rev5a_init);
172 } 561 }
173 break; 562 break;
563 case 16:
564 if (phy->radio_rev == 9) {
565 table = r2057_rev9_init[0];
566 size = ARRAY_SIZE(r2057_rev9_init);
567 }
568 break;
569 case 17:
570 if (phy->radio_rev == 14) {
571 table = r2057_rev14_init[0];
572 size = ARRAY_SIZE(r2057_rev14_init);
573 }
574 break;
174 } 575 }
175 576
176 B43_WARN_ON(!table); 577 B43_WARN_ON(!table);
@@ -193,8 +594,25 @@ void r2057_get_chantabent_rev7(struct b43_wldev *dev, u16 freq,
193 *tabent_r7 = NULL; 594 *tabent_r7 = NULL;
194 *tabent_r7_2g = NULL; 595 *tabent_r7_2g = NULL;
195 596
196 /* TODO */
197 switch (phy->rev) { 597 switch (phy->rev) {
598 case 8:
599 if (phy->radio_rev == 5) {
600 e_r7_2g = b43_nphy_chantab_phy_rev8_radio_rev5;
601 len = ARRAY_SIZE(b43_nphy_chantab_phy_rev8_radio_rev5);
602 }
603 break;
604 case 16:
605 if (phy->radio_rev == 9) {
606 e_r7 = b43_nphy_chantab_phy_rev16_radio_rev9;
607 len = ARRAY_SIZE(b43_nphy_chantab_phy_rev16_radio_rev9);
608 }
609 break;
610 case 17:
611 if (phy->radio_rev == 14) {
612 e_r7_2g = b43_nphy_chantab_phy_rev17_radio_rev14;
613 len = ARRAY_SIZE(b43_nphy_chantab_phy_rev17_radio_rev14);
614 }
615 break;
198 default: 616 default:
199 break; 617 break;
200 } 618 }
diff --git a/drivers/net/wireless/b43/radio_2057.h b/drivers/net/wireless/b43/radio_2057.h
index 675d1bb64429..220d080238ff 100644
--- a/drivers/net/wireless/b43/radio_2057.h
+++ b/drivers/net/wireless/b43/radio_2057.h
@@ -84,6 +84,8 @@
84#define R2057_CMOSBUF_RX_RCCR 0x04c 84#define R2057_CMOSBUF_RX_RCCR 0x04c
85#define R2057_LOGEN_SEL_PKDET 0x04d 85#define R2057_LOGEN_SEL_PKDET 0x04d
86#define R2057_CMOSBUF_SHAREIQ_PTAT 0x04e 86#define R2057_CMOSBUF_SHAREIQ_PTAT 0x04e
87
88/* MISC core 0 */
87#define R2057_RXTXBIAS_CONFIG_CORE0 0x04f 89#define R2057_RXTXBIAS_CONFIG_CORE0 0x04f
88#define R2057_TXGM_TXRF_PUS_CORE0 0x050 90#define R2057_TXGM_TXRF_PUS_CORE0 0x050
89#define R2057_TXGM_IDAC_BLEED_CORE0 0x051 91#define R2057_TXGM_IDAC_BLEED_CORE0 0x051
@@ -204,6 +206,8 @@
204#define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE0 0x0d1 206#define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE0 0x0d1
205#define R2057_LPF_GAIN_CORE0 0x0d2 207#define R2057_LPF_GAIN_CORE0 0x0d2
206#define R2057_DACBUF_IDACS_BW_CORE0 0x0d3 208#define R2057_DACBUF_IDACS_BW_CORE0 0x0d3
209
210/* MISC core 1 */
207#define R2057_RXTXBIAS_CONFIG_CORE1 0x0d4 211#define R2057_RXTXBIAS_CONFIG_CORE1 0x0d4
208#define R2057_TXGM_TXRF_PUS_CORE1 0x0d5 212#define R2057_TXGM_TXRF_PUS_CORE1 0x0d5
209#define R2057_TXGM_IDAC_BLEED_CORE1 0x0d6 213#define R2057_TXGM_IDAC_BLEED_CORE1 0x0d6
@@ -324,6 +328,7 @@
324#define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE1 0x156 328#define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE1 0x156
325#define R2057_LPF_GAIN_CORE1 0x157 329#define R2057_LPF_GAIN_CORE1 0x157
326#define R2057_DACBUF_IDACS_BW_CORE1 0x158 330#define R2057_DACBUF_IDACS_BW_CORE1 0x158
331
327#define R2057_DACBUF_VINCM_CORE1 0x159 332#define R2057_DACBUF_VINCM_CORE1 0x159
328#define R2057_RCCAL_START_R1_Q1_P1 0x15a 333#define R2057_RCCAL_START_R1_Q1_P1 0x15a
329#define R2057_RCCAL_X1 0x15b 334#define R2057_RCCAL_X1 0x15b
@@ -345,6 +350,8 @@
345#define R2057_RCCAL_BCAP_VAL 0x16b 350#define R2057_RCCAL_BCAP_VAL 0x16b
346#define R2057_RCCAL_HPC_VAL 0x16c 351#define R2057_RCCAL_HPC_VAL 0x16c
347#define R2057_RCCAL_OVERRIDES 0x16d 352#define R2057_RCCAL_OVERRIDES 0x16d
353
354/* TX core 0 */
348#define R2057_TX0_IQCAL_GAIN_BW 0x170 355#define R2057_TX0_IQCAL_GAIN_BW 0x170
349#define R2057_TX0_LOFT_FINE_I 0x171 356#define R2057_TX0_LOFT_FINE_I 0x171
350#define R2057_TX0_LOFT_FINE_Q 0x172 357#define R2057_TX0_LOFT_FINE_Q 0x172
@@ -362,6 +369,8 @@
362#define R2057_TX0_TXRXCOUPLE_2G_PWRUP 0x17e 369#define R2057_TX0_TXRXCOUPLE_2G_PWRUP 0x17e
363#define R2057_TX0_TXRXCOUPLE_5G_ATTEN 0x17f 370#define R2057_TX0_TXRXCOUPLE_5G_ATTEN 0x17f
364#define R2057_TX0_TXRXCOUPLE_5G_PWRUP 0x180 371#define R2057_TX0_TXRXCOUPLE_5G_PWRUP 0x180
372
373/* TX core 1 */
365#define R2057_TX1_IQCAL_GAIN_BW 0x190 374#define R2057_TX1_IQCAL_GAIN_BW 0x190
366#define R2057_TX1_LOFT_FINE_I 0x191 375#define R2057_TX1_LOFT_FINE_I 0x191
367#define R2057_TX1_LOFT_FINE_Q 0x192 376#define R2057_TX1_LOFT_FINE_Q 0x192
@@ -379,6 +388,7 @@
379#define R2057_TX1_TXRXCOUPLE_2G_PWRUP 0x19e 388#define R2057_TX1_TXRXCOUPLE_2G_PWRUP 0x19e
380#define R2057_TX1_TXRXCOUPLE_5G_ATTEN 0x19f 389#define R2057_TX1_TXRXCOUPLE_5G_ATTEN 0x19f
381#define R2057_TX1_TXRXCOUPLE_5G_PWRUP 0x1a0 390#define R2057_TX1_TXRXCOUPLE_5G_PWRUP 0x1a0
391
382#define R2057_AFE_VCM_CAL_MASTER_CORE0 0x1a1 392#define R2057_AFE_VCM_CAL_MASTER_CORE0 0x1a1
383#define R2057_AFE_SET_VCM_I_CORE0 0x1a2 393#define R2057_AFE_SET_VCM_I_CORE0 0x1a2
384#define R2057_AFE_SET_VCM_Q_CORE0 0x1a3 394#define R2057_AFE_SET_VCM_Q_CORE0 0x1a3
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c
index b28dce950e1f..4b5885077b01 100644
--- a/drivers/net/wireless/b43/tables_nphy.c
+++ b/drivers/net/wireless/b43/tables_nphy.c
@@ -2408,6 +2408,41 @@ static const u32 b43_ntab_tx_gain_epa_rev3_2g[] = {
2408 0x1041003c, 0x1041003b, 0x10410039, 0x10410037, 2408 0x1041003c, 0x1041003b, 0x10410039, 0x10410037,
2409}; 2409};
2410 2410
2411static const u32 b43_ntab_tx_gain_epa_rev3_hi_pwr_2g[] = {
2412 0x0f410044, 0x0f410042, 0x0f410040, 0x0f41003e,
2413 0x0f41003c, 0x0f41003b, 0x0f410039, 0x0f410037,
2414 0x0e410044, 0x0e410042, 0x0e410040, 0x0e41003e,
2415 0x0e41003c, 0x0e41003b, 0x0e410039, 0x0e410037,
2416 0x0d410044, 0x0d410042, 0x0d410040, 0x0d41003e,
2417 0x0d41003c, 0x0d41003b, 0x0d410039, 0x0d410037,
2418 0x0c410044, 0x0c410042, 0x0c410040, 0x0c41003e,
2419 0x0c41003c, 0x0c41003b, 0x0c410039, 0x0c410037,
2420 0x0b410044, 0x0b410042, 0x0b410040, 0x0b41003e,
2421 0x0b41003c, 0x0b41003b, 0x0b410039, 0x0b410037,
2422 0x0a410044, 0x0a410042, 0x0a410040, 0x0a41003e,
2423 0x0a41003c, 0x0a41003b, 0x0a410039, 0x0a410037,
2424 0x09410044, 0x09410042, 0x09410040, 0x0941003e,
2425 0x0941003c, 0x0941003b, 0x09410039, 0x09410037,
2426 0x08410044, 0x08410042, 0x08410040, 0x0841003e,
2427 0x0841003c, 0x0841003b, 0x08410039, 0x08410037,
2428 0x07410044, 0x07410042, 0x07410040, 0x0741003e,
2429 0x0741003c, 0x0741003b, 0x07410039, 0x07410037,
2430 0x06410044, 0x06410042, 0x06410040, 0x0641003e,
2431 0x0641003c, 0x0641003b, 0x06410039, 0x06410037,
2432 0x05410044, 0x05410042, 0x05410040, 0x0541003e,
2433 0x0541003c, 0x0541003b, 0x05410039, 0x05410037,
2434 0x04410044, 0x04410042, 0x04410040, 0x0441003e,
2435 0x0441003c, 0x0441003b, 0x04410039, 0x04410037,
2436 0x03410044, 0x03410042, 0x03410040, 0x0341003e,
2437 0x0341003c, 0x0341003b, 0x03410039, 0x03410037,
2438 0x02410044, 0x02410042, 0x02410040, 0x0241003e,
2439 0x0241003c, 0x0241003b, 0x02410039, 0x02410037,
2440 0x01410044, 0x01410042, 0x01410040, 0x0141003e,
2441 0x0141003c, 0x0141003b, 0x01410039, 0x01410037,
2442 0x00410044, 0x00410042, 0x00410040, 0x0041003e,
2443 0x0041003c, 0x0041003b, 0x00410039, 0x00410037
2444};
2445
2411/* EPA 5 GHz */ 2446/* EPA 5 GHz */
2412 2447
2413static const u32 b43_ntab_tx_gain_epa_rev3_5g[] = { 2448static const u32 b43_ntab_tx_gain_epa_rev3_5g[] = {
@@ -2480,6 +2515,41 @@ static const u32 b43_ntab_tx_gain_epa_rev4_5g[] = {
2480 0x20d2003a, 0x20d20038, 0x20d20036, 0x20d20034, 2515 0x20d2003a, 0x20d20038, 0x20d20036, 0x20d20034,
2481}; 2516};
2482 2517
2518static const u32 b43_ntab_tx_gain_epa_rev4_hi_pwr_5g[] = {
2519 0x2ff10044, 0x2ff10042, 0x2ff10040, 0x2ff1003e,
2520 0x2ff1003c, 0x2ff1003b, 0x2ff10039, 0x2ff10037,
2521 0x2ef10044, 0x2ef10042, 0x2ef10040, 0x2ef1003e,
2522 0x2ef1003c, 0x2ef1003b, 0x2ef10039, 0x2ef10037,
2523 0x2df10044, 0x2df10042, 0x2df10040, 0x2df1003e,
2524 0x2df1003c, 0x2df1003b, 0x2df10039, 0x2df10037,
2525 0x2cf10044, 0x2cf10042, 0x2cf10040, 0x2cf1003e,
2526 0x2cf1003c, 0x2cf1003b, 0x2cf10039, 0x2cf10037,
2527 0x2bf10044, 0x2bf10042, 0x2bf10040, 0x2bf1003e,
2528 0x2bf1003c, 0x2bf1003b, 0x2bf10039, 0x2bf10037,
2529 0x2af10044, 0x2af10042, 0x2af10040, 0x2af1003e,
2530 0x2af1003c, 0x2af1003b, 0x2af10039, 0x2af10037,
2531 0x29f10044, 0x29f10042, 0x29f10040, 0x29f1003e,
2532 0x29f1003c, 0x29f1003b, 0x29f10039, 0x29f10037,
2533 0x28f10044, 0x28f10042, 0x28f10040, 0x28f1003e,
2534 0x28f1003c, 0x28f1003b, 0x28f10039, 0x28f10037,
2535 0x27f10044, 0x27f10042, 0x27f10040, 0x27f1003e,
2536 0x27f1003c, 0x27f1003b, 0x27f10039, 0x27f10037,
2537 0x26f10044, 0x26f10042, 0x26f10040, 0x26f1003e,
2538 0x26f1003c, 0x26f1003b, 0x26f10039, 0x26f10037,
2539 0x25f10044, 0x25f10042, 0x25f10040, 0x25f1003e,
2540 0x25f1003c, 0x25f1003b, 0x25f10039, 0x25f10037,
2541 0x24f10044, 0x24f10042, 0x24f10040, 0x24f1003e,
2542 0x24f1003c, 0x24f1003b, 0x24f10039, 0x24f10038,
2543 0x23f10041, 0x23f10040, 0x23f1003f, 0x23f1003e,
2544 0x23f1003c, 0x23f1003b, 0x23f10039, 0x23f10037,
2545 0x22f10044, 0x22f10042, 0x22f10040, 0x22f1003e,
2546 0x22f1003c, 0x22f1003b, 0x22f10039, 0x22f10037,
2547 0x21f10044, 0x21f10042, 0x21f10040, 0x21f1003e,
2548 0x21f1003c, 0x21f1003b, 0x21f10039, 0x21f10037,
2549 0x20d10043, 0x20d10041, 0x20d1003e, 0x20d1003c,
2550 0x20d1003a, 0x20d10038, 0x20d10036, 0x20d10034
2551};
2552
2483static const u32 b43_ntab_tx_gain_epa_rev5_5g[] = { 2553static const u32 b43_ntab_tx_gain_epa_rev5_5g[] = {
2484 0x0f62004a, 0x0f620048, 0x0f620046, 0x0f620044, 2554 0x0f62004a, 0x0f620048, 0x0f620046, 0x0f620044,
2485 0x0f620042, 0x0f620040, 0x0f62003e, 0x0f62003c, 2555 0x0f620042, 0x0f620040, 0x0f62003e, 0x0f62003c,
@@ -2622,6 +2692,42 @@ static const u32 b43_ntab_tx_gain_ipa_rev6_2g[] = {
2622 0x00f70028, 0x00f70027, 0x00f70026, 0x00f70025, 2692 0x00f70028, 0x00f70027, 0x00f70026, 0x00f70025,
2623}; 2693};
2624 2694
2695/* Copied from brcmsmac (5.75.11): nphy_tpc_txgain_ipa_2g_2057rev5 */
2696static const u32 b43_ntab_tx_gain_ipa_2057_rev5_2g[] = {
2697 0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e,
2698 0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033,
2699 0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e,
2700 0x3067002e, 0x305f002f, 0x30570030, 0x3057002d,
2701 0x304f002e, 0x30470031, 0x3047002e, 0x3047002c,
2702 0x30470029, 0x303f002c, 0x303f0029, 0x3037002d,
2703 0x3037002a, 0x30370028, 0x302f002c, 0x302f002a,
2704 0x302f0028, 0x302f0026, 0x3027002c, 0x30270029,
2705 0x30270027, 0x30270025, 0x30270023, 0x301f002c,
2706 0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024,
2707 0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b,
2708 0x30170028, 0x30170026, 0x30170024, 0x30170022,
2709 0x30170020, 0x3017001e, 0x3017001d, 0x3017001b,
2710 0x3017001a, 0x30170018, 0x30170017, 0x30170015,
2711 0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024,
2712 0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d,
2713 0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017,
2714 0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215,
2715 0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615,
2716 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
2717 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
2718 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
2719 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
2720 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
2721 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
2722 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
2723 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
2724 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
2725 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
2726 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
2727 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
2728 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
2729};
2730
2625/* Extracted from MMIO dump of 6.30.223.141 */ 2731/* Extracted from MMIO dump of 6.30.223.141 */
2626static const u32 b43_ntab_tx_gain_ipa_2057_rev9_2g[] = { 2732static const u32 b43_ntab_tx_gain_ipa_2057_rev9_2g[] = {
2627 0x60ff0031, 0x60e7002c, 0x60cf002a, 0x60c70029, 2733 0x60ff0031, 0x60e7002c, 0x60cf002a, 0x60c70029,
@@ -2658,6 +2764,42 @@ static const u32 b43_ntab_tx_gain_ipa_2057_rev9_2g[] = {
2658 0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715, 2764 0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
2659}; 2765};
2660 2766
2767/* Extracted from MMIO dump of 6.30.223.248 */
2768static const u32 b43_ntab_tx_gain_ipa_2057_rev14_2g[] = {
2769 0x50df002e, 0x50cf002d, 0x50bf002c, 0x50b7002b,
2770 0x50af002a, 0x50a70029, 0x509f0029, 0x50970028,
2771 0x508f0027, 0x50870027, 0x507f0027, 0x50770027,
2772 0x506f0027, 0x50670027, 0x505f0028, 0x50570029,
2773 0x504f002b, 0x5047002e, 0x5047002b, 0x50470029,
2774 0x503f002c, 0x503f0029, 0x5037002c, 0x5037002a,
2775 0x50370028, 0x502f002d, 0x502f002b, 0x502f0028,
2776 0x502f0026, 0x5027002d, 0x5027002a, 0x50270028,
2777 0x50270026, 0x50270024, 0x501f002e, 0x501f002b,
2778 0x501f0029, 0x501f0027, 0x501f0024, 0x501f0022,
2779 0x501f0020, 0x501f001f, 0x5017002c, 0x50170029,
2780 0x50170027, 0x50170024, 0x50170022, 0x50170021,
2781 0x5017001f, 0x5017001d, 0x5017001b, 0x5017001a,
2782 0x50170018, 0x50170017, 0x50170015, 0x500f002c,
2783 0x500f002a, 0x500f0027, 0x500f0025, 0x500f0023,
2784 0x500f0022, 0x500f001f, 0x500f001e, 0x500f001c,
2785 0x500f001a, 0x500f0019, 0x500f0018, 0x500f0016,
2786 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
2787 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
2788 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
2789 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
2790 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
2791 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
2792 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
2793 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
2794 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
2795 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
2796 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
2797 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
2798 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
2799 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
2800 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
2801};
2802
2661/* IPA 2 5Hz */ 2803/* IPA 2 5Hz */
2662 2804
2663static const u32 b43_ntab_tx_gain_ipa_rev3_5g[] = { 2805static const u32 b43_ntab_tx_gain_ipa_rev3_5g[] = {
@@ -2967,11 +3109,11 @@ static const struct nphy_rf_control_override_rev7
2967 { 0x0010, 0x07A, 0x07D, 0x0010, 4 }, 3109 { 0x0010, 0x07A, 0x07D, 0x0010, 4 },
2968 { 0x0020, 0x07A, 0x07D, 0x0020, 5 }, 3110 { 0x0020, 0x07A, 0x07D, 0x0020, 5 },
2969 { 0x0040, 0x07A, 0x07D, 0x0040, 6 }, 3111 { 0x0040, 0x07A, 0x07D, 0x0040, 6 },
2970 { 0x0080, 0x0F8, 0x0FA, 0x0080, 7 }, 3112 { 0x0080, 0x07A, 0x07D, 0x0080, 7 },
2971 { 0x0400, 0x0F8, 0x0FA, 0x0070, 4 }, 3113 { 0x0400, 0x0F8, 0x0FA, 0x0070, 4 },
2972 { 0x0800, 0x07B, 0x07E, 0xFFFF, 0 }, 3114 { 0x0800, 0x07B, 0x07E, 0xFFFF, 0 },
2973 { 0x1000, 0x07C, 0x07F, 0xFFFF, 0 }, 3115 { 0x1000, 0x07C, 0x07F, 0xFFFF, 0 },
2974 { 0x6000, 0x348, 0x349, 0xFFFF, 0 }, 3116 { 0x6000, 0x348, 0x349, 0x00FF, 0 },
2975 { 0x2000, 0x348, 0x349, 0x000F, 0 }, 3117 { 0x2000, 0x348, 0x349, 0x000F, 0 },
2976}; 3118};
2977 3119
@@ -3477,9 +3619,18 @@ static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev)
3477 3619
3478 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 3620 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
3479 switch (phy->rev) { 3621 switch (phy->rev) {
3622 case 17:
3623 if (phy->radio_rev == 14)
3624 return b43_ntab_tx_gain_ipa_2057_rev14_2g;
3625 break;
3480 case 16: 3626 case 16:
3481 if (phy->radio_rev == 9) 3627 if (phy->radio_rev == 9)
3482 return b43_ntab_tx_gain_ipa_2057_rev9_2g; 3628 return b43_ntab_tx_gain_ipa_2057_rev9_2g;
3629 break;
3630 case 8:
3631 if (phy->radio_rev == 5)
3632 return b43_ntab_tx_gain_ipa_2057_rev5_2g;
3633 break;
3483 case 6: 3634 case 6:
3484 if (dev->dev->chip_id == BCMA_CHIP_ID_BCM47162) 3635 if (dev->dev->chip_id == BCMA_CHIP_ID_BCM47162)
3485 return b43_ntab_tx_gain_ipa_rev5_2g; 3636 return b43_ntab_tx_gain_ipa_rev5_2g;
@@ -3489,23 +3640,24 @@ static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev)
3489 case 4: 3640 case 4:
3490 case 3: 3641 case 3:
3491 return b43_ntab_tx_gain_ipa_rev3_2g; 3642 return b43_ntab_tx_gain_ipa_rev3_2g;
3492 default:
3493 b43err(dev->wl,
3494 "No 2GHz IPA gain table available for this device\n");
3495 return NULL;
3496 } 3643 }
3644
3645 b43err(dev->wl,
3646 "No 2GHz IPA gain table available for this device\n");
3647 return NULL;
3497 } else { 3648 } else {
3498 switch (phy->rev) { 3649 switch (phy->rev) {
3499 case 16: 3650 case 16:
3500 if (phy->radio_rev == 9) 3651 if (phy->radio_rev == 9)
3501 return b43_ntab_tx_gain_ipa_2057_rev9_5g; 3652 return b43_ntab_tx_gain_ipa_2057_rev9_5g;
3653 break;
3502 case 3 ... 6: 3654 case 3 ... 6:
3503 return b43_ntab_tx_gain_ipa_rev3_5g; 3655 return b43_ntab_tx_gain_ipa_rev3_5g;
3504 default:
3505 b43err(dev->wl,
3506 "No 5GHz IPA gain table available for this device\n");
3507 return NULL;
3508 } 3656 }
3657
3658 b43err(dev->wl,
3659 "No 5GHz IPA gain table available for this device\n");
3660 return NULL;
3509 } 3661 }
3510} 3662}
3511 3663
@@ -3530,7 +3682,7 @@ const u32 *b43_nphy_get_tx_gain_table(struct b43_wldev *dev)
3530 case 4: 3682 case 4:
3531 return sprom->fem.ghz5.extpa_gain == 3 ? 3683 return sprom->fem.ghz5.extpa_gain == 3 ?
3532 b43_ntab_tx_gain_epa_rev4_5g : 3684 b43_ntab_tx_gain_epa_rev4_5g :
3533 b43_ntab_tx_gain_epa_rev4_5g; /* FIXME */ 3685 b43_ntab_tx_gain_epa_rev4_hi_pwr_5g;
3534 case 3: 3686 case 3:
3535 return b43_ntab_tx_gain_epa_rev3_5g; 3687 return b43_ntab_tx_gain_epa_rev3_5g;
3536 default: 3688 default:
@@ -3543,7 +3695,7 @@ const u32 *b43_nphy_get_tx_gain_table(struct b43_wldev *dev)
3543 case 6: 3695 case 6:
3544 case 5: 3696 case 5:
3545 if (sprom->fem.ghz5.extpa_gain == 3) 3697 if (sprom->fem.ghz5.extpa_gain == 3)
3546 return b43_ntab_tx_gain_epa_rev3_2g; /* FIXME */ 3698 return b43_ntab_tx_gain_epa_rev3_hi_pwr_2g;
3547 /* fall through */ 3699 /* fall through */
3548 case 4: 3700 case 4:
3549 case 3: 3701 case 3:
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 6e6ef3fc2247..426dc13c44cd 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -80,9 +80,10 @@ static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp)
80} 80}
81 81
82/* Extract the bitrate index out of an OFDM PLCP header. */ 82/* Extract the bitrate index out of an OFDM PLCP header. */
83static int b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy) 83static int b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool ghz5)
84{ 84{
85 int base = aphy ? 0 : 4; 85 /* For 2 GHz band first OFDM rate is at index 4, see main.c */
86 int base = ghz5 ? 0 : 4;
86 87
87 switch (plcp->raw[0] & 0xF) { 88 switch (plcp->raw[0] & 0xF) {
88 case 0xB: 89 case 0xB:
@@ -767,7 +768,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
767 768
768 if (phystat0 & B43_RX_PHYST0_OFDM) 769 if (phystat0 & B43_RX_PHYST0_OFDM)
769 rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp, 770 rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,
770 phytype == B43_PHYTYPE_A); 771 !!(chanstat & B43_RX_CHAN_5GHZ));
771 else 772 else
772 rate_idx = b43_plcp_get_bitrate_idx_cck(plcp); 773 rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);
773 if (unlikely(rate_idx == -1)) { 774 if (unlikely(rate_idx == -1)) {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
index 4cffb2ee3673..de0cff3df389 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
@@ -34,6 +34,7 @@ brcmfmac-objs += \
34 dhd_common.o \ 34 dhd_common.o \
35 dhd_linux.o \ 35 dhd_linux.o \
36 firmware.o \ 36 firmware.o \
37 feature.o \
37 btcoex.o \ 38 btcoex.o \
38 vendor.o 39 vendor.o
39brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \ 40brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index a16e644e7c08..f467cafe3e8f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -25,7 +25,6 @@
25#include <linux/mmc/sdio.h> 25#include <linux/mmc/sdio.h>
26#include <linux/mmc/core.h> 26#include <linux/mmc/core.h>
27#include <linux/mmc/sdio_func.h> 27#include <linux/mmc/sdio_func.h>
28#include <linux/mmc/sdio_ids.h>
29#include <linux/mmc/card.h> 28#include <linux/mmc/card.h>
30#include <linux/mmc/host.h> 29#include <linux/mmc/host.h>
31#include <linux/platform_device.h> 30#include <linux/platform_device.h>
@@ -979,18 +978,20 @@ out:
979 return ret; 978 return ret;
980} 979}
981 980
981#define BRCMF_SDIO_DEVICE(dev_id) \
982 {SDIO_DEVICE(BRCM_SDIO_VENDOR_ID_BROADCOM, dev_id)}
983
982/* devices we support, null terminated */ 984/* devices we support, null terminated */
983static const struct sdio_device_id brcmf_sdmmc_ids[] = { 985static const struct sdio_device_id brcmf_sdmmc_ids[] = {
984 {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43143)}, 986 BRCMF_SDIO_DEVICE(BRCM_SDIO_43143_DEVICE_ID),
985 {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43241)}, 987 BRCMF_SDIO_DEVICE(BRCM_SDIO_43241_DEVICE_ID),
986 {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, 988 BRCMF_SDIO_DEVICE(BRCM_SDIO_4329_DEVICE_ID),
987 {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)}, 989 BRCMF_SDIO_DEVICE(BRCM_SDIO_4330_DEVICE_ID),
988 {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)}, 990 BRCMF_SDIO_DEVICE(BRCM_SDIO_4334_DEVICE_ID),
989 {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43362)}, 991 BRCMF_SDIO_DEVICE(BRCM_SDIO_43362_DEVICE_ID),
990 {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, 992 BRCMF_SDIO_DEVICE(BRCM_SDIO_4335_4339_DEVICE_ID),
991 SDIO_DEVICE_ID_BROADCOM_4335_4339)}, 993 BRCMF_SDIO_DEVICE(BRCM_SDIO_4354_DEVICE_ID),
992 {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4354)}, 994 { /* end: all zeroes */ }
993 { /* end: all zeroes */ },
994}; 995};
995MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); 996MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
996 997
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
index c7c9f15c0fe0..96800db0536b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
@@ -482,30 +482,30 @@ static inline int brcmf_chip_cores_check(struct brcmf_chip_priv *ci)
482static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci) 482static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci)
483{ 483{
484 switch (ci->pub.chip) { 484 switch (ci->pub.chip) {
485 case BCM4329_CHIP_ID: 485 case BRCM_CC_4329_CHIP_ID:
486 ci->pub.ramsize = BCM4329_RAMSIZE; 486 ci->pub.ramsize = BCM4329_RAMSIZE;
487 break; 487 break;
488 case BCM43143_CHIP_ID: 488 case BRCM_CC_43143_CHIP_ID:
489 ci->pub.ramsize = BCM43143_RAMSIZE; 489 ci->pub.ramsize = BCM43143_RAMSIZE;
490 break; 490 break;
491 case BCM43241_CHIP_ID: 491 case BRCM_CC_43241_CHIP_ID:
492 ci->pub.ramsize = 0x90000; 492 ci->pub.ramsize = 0x90000;
493 break; 493 break;
494 case BCM4330_CHIP_ID: 494 case BRCM_CC_4330_CHIP_ID:
495 ci->pub.ramsize = 0x48000; 495 ci->pub.ramsize = 0x48000;
496 break; 496 break;
497 case BCM4334_CHIP_ID: 497 case BRCM_CC_4334_CHIP_ID:
498 ci->pub.ramsize = 0x80000; 498 ci->pub.ramsize = 0x80000;
499 break; 499 break;
500 case BCM4335_CHIP_ID: 500 case BRCM_CC_4335_CHIP_ID:
501 ci->pub.ramsize = 0xc0000; 501 ci->pub.ramsize = 0xc0000;
502 ci->pub.rambase = 0x180000; 502 ci->pub.rambase = 0x180000;
503 break; 503 break;
504 case BCM43362_CHIP_ID: 504 case BRCM_CC_43362_CHIP_ID:
505 ci->pub.ramsize = 0x3c000; 505 ci->pub.ramsize = 0x3c000;
506 break; 506 break;
507 case BCM4339_CHIP_ID: 507 case BRCM_CC_4339_CHIP_ID:
508 case BCM4354_CHIP_ID: 508 case BRCM_CC_4354_CHIP_ID:
509 ci->pub.ramsize = 0xc0000; 509 ci->pub.ramsize = 0xc0000;
510 ci->pub.rambase = 0x180000; 510 ci->pub.rambase = 0x180000;
511 break; 511 break;
@@ -682,7 +682,7 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
682 ci->pub.chiprev); 682 ci->pub.chiprev);
683 683
684 if (socitype == SOCI_SB) { 684 if (socitype == SOCI_SB) {
685 if (ci->pub.chip != BCM4329_CHIP_ID) { 685 if (ci->pub.chip != BRCM_CC_4329_CHIP_ID) {
686 brcmf_err("SB chip is not supported\n"); 686 brcmf_err("SB chip is not supported\n");
687 return -ENODEV; 687 return -ENODEV;
688 } 688 }
@@ -1008,13 +1008,13 @@ bool brcmf_chip_sr_capable(struct brcmf_chip *pub)
1008 chip = container_of(pub, struct brcmf_chip_priv, pub); 1008 chip = container_of(pub, struct brcmf_chip_priv, pub);
1009 1009
1010 switch (pub->chip) { 1010 switch (pub->chip) {
1011 case BCM4354_CHIP_ID: 1011 case BRCM_CC_4354_CHIP_ID:
1012 /* explicitly check SR engine enable bit */ 1012 /* explicitly check SR engine enable bit */
1013 pmu_cc3_mask = BIT(2); 1013 pmu_cc3_mask = BIT(2);
1014 /* fall-through */ 1014 /* fall-through */
1015 case BCM43241_CHIP_ID: 1015 case BRCM_CC_43241_CHIP_ID:
1016 case BCM4335_CHIP_ID: 1016 case BRCM_CC_4335_CHIP_ID:
1017 case BCM4339_CHIP_ID: 1017 case BRCM_CC_4339_CHIP_ID:
1018 /* read PMU chipcontrol register 3 */ 1018 /* read PMU chipcontrol register 3 */
1019 addr = CORE_CC_REG(base, chipcontrol_addr); 1019 addr = CORE_CC_REG(base, chipcontrol_addr);
1020 chip->ops->write32(chip->ctx, addr, 3); 1020 chip->ops->write32(chip->ctx, addr, 3);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
index a8998eb60d22..7da6441bcfa8 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
@@ -103,6 +103,10 @@ struct brcmf_pub {
103 103
104 struct brcmf_ampdu_rx_reorder 104 struct brcmf_ampdu_rx_reorder
105 *reorder_flows[BRCMF_AMPDU_RX_REORDER_MAXFLOWS]; 105 *reorder_flows[BRCMF_AMPDU_RX_REORDER_MAXFLOWS];
106
107 u32 feat_flags;
108 u32 chip_quirks;
109
106#ifdef DEBUG 110#ifdef DEBUG
107 struct dentry *dbgfs_dir; 111 struct dentry *dbgfs_dir;
108#endif 112#endif
@@ -175,7 +179,6 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
175void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx); 179void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx);
176void brcmf_txflowblock_if(struct brcmf_if *ifp, 180void brcmf_txflowblock_if(struct brcmf_if *ifp,
177 enum brcmf_netif_stop_reason reason, bool state); 181 enum brcmf_netif_stop_reason reason, bool state);
178u32 brcmf_get_chip_info(struct brcmf_if *ifp);
179void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx, 182void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
180 bool success); 183 bool success);
181 184
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
index 03fe8aca4d32..be9f4f829192 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
@@ -41,37 +41,12 @@ void brcmf_debugfs_exit(void)
41 root_folder = NULL; 41 root_folder = NULL;
42} 42}
43 43
44static 44static int brcmf_debugfs_chipinfo_read(struct seq_file *seq, void *data)
45ssize_t brcmf_debugfs_chipinfo_read(struct file *f, char __user *data,
46 size_t count, loff_t *ppos)
47{ 45{
48 struct brcmf_pub *drvr = f->private_data; 46 struct brcmf_bus *bus = dev_get_drvdata(seq->private);
49 struct brcmf_bus *bus = drvr->bus_if;
50 char buf[40];
51 int res;
52
53 /* only allow read from start */
54 if (*ppos > 0)
55 return 0;
56
57 res = scnprintf(buf, sizeof(buf), "chip: %x(%u) rev %u\n",
58 bus->chip, bus->chip, bus->chiprev);
59 return simple_read_from_buffer(data, count, ppos, buf, res);
60}
61
62static const struct file_operations brcmf_debugfs_chipinfo_ops = {
63 .owner = THIS_MODULE,
64 .open = simple_open,
65 .read = brcmf_debugfs_chipinfo_read
66};
67
68static int brcmf_debugfs_create_chipinfo(struct brcmf_pub *drvr)
69{
70 struct dentry *dentry = drvr->dbgfs_dir;
71 47
72 if (!IS_ERR_OR_NULL(dentry)) 48 seq_printf(seq, "chip: %x(%u) rev %u\n",
73 debugfs_create_file("chipinfo", S_IRUGO, dentry, drvr, 49 bus->chip, bus->chip, bus->chiprev);
74 &brcmf_debugfs_chipinfo_ops);
75 return 0; 50 return 0;
76} 51}
77 52
@@ -83,7 +58,8 @@ int brcmf_debugfs_attach(struct brcmf_pub *drvr)
83 return -ENODEV; 58 return -ENODEV;
84 59
85 drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder); 60 drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder);
86 brcmf_debugfs_create_chipinfo(drvr); 61 brcmf_debugfs_add_entry(drvr, "chipinfo", brcmf_debugfs_chipinfo_read);
62
87 return PTR_ERR_OR_ZERO(drvr->dbgfs_dir); 63 return PTR_ERR_OR_ZERO(drvr->dbgfs_dir);
88} 64}
89 65
@@ -98,148 +74,44 @@ struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr)
98 return drvr->dbgfs_dir; 74 return drvr->dbgfs_dir;
99} 75}
100 76
101static 77struct brcmf_debugfs_entry {
102ssize_t brcmf_debugfs_sdio_counter_read(struct file *f, char __user *data, 78 int (*read)(struct seq_file *seq, void *data);
103 size_t count, loff_t *ppos) 79 struct brcmf_pub *drvr;
104{
105 struct brcmf_sdio_count *sdcnt = f->private_data;
106 char buf[750];
107 int res;
108
109 /* only allow read from start */
110 if (*ppos > 0)
111 return 0;
112
113 res = scnprintf(buf, sizeof(buf),
114 "intrcount: %u\nlastintrs: %u\n"
115 "pollcnt: %u\nregfails: %u\n"
116 "tx_sderrs: %u\nfcqueued: %u\n"
117 "rxrtx: %u\nrx_toolong: %u\n"
118 "rxc_errors: %u\nrx_hdrfail: %u\n"
119 "rx_badhdr: %u\nrx_badseq: %u\n"
120 "fc_rcvd: %u\nfc_xoff: %u\n"
121 "fc_xon: %u\nrxglomfail: %u\n"
122 "rxglomframes: %u\nrxglompkts: %u\n"
123 "f2rxhdrs: %u\nf2rxdata: %u\n"
124 "f2txdata: %u\nf1regdata: %u\n"
125 "tickcnt: %u\ntx_ctlerrs: %lu\n"
126 "tx_ctlpkts: %lu\nrx_ctlerrs: %lu\n"
127 "rx_ctlpkts: %lu\nrx_readahead: %lu\n",
128 sdcnt->intrcount, sdcnt->lastintrs,
129 sdcnt->pollcnt, sdcnt->regfails,
130 sdcnt->tx_sderrs, sdcnt->fcqueued,
131 sdcnt->rxrtx, sdcnt->rx_toolong,
132 sdcnt->rxc_errors, sdcnt->rx_hdrfail,
133 sdcnt->rx_badhdr, sdcnt->rx_badseq,
134 sdcnt->fc_rcvd, sdcnt->fc_xoff,
135 sdcnt->fc_xon, sdcnt->rxglomfail,
136 sdcnt->rxglomframes, sdcnt->rxglompkts,
137 sdcnt->f2rxhdrs, sdcnt->f2rxdata,
138 sdcnt->f2txdata, sdcnt->f1regdata,
139 sdcnt->tickcnt, sdcnt->tx_ctlerrs,
140 sdcnt->tx_ctlpkts, sdcnt->rx_ctlerrs,
141 sdcnt->rx_ctlpkts, sdcnt->rx_readahead_cnt);
142
143 return simple_read_from_buffer(data, count, ppos, buf, res);
144}
145
146static const struct file_operations brcmf_debugfs_sdio_counter_ops = {
147 .owner = THIS_MODULE,
148 .open = simple_open,
149 .read = brcmf_debugfs_sdio_counter_read
150}; 80};
151 81
152void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr, 82static int brcmf_debugfs_entry_open(struct inode *inode, struct file *f)
153 struct brcmf_sdio_count *sdcnt)
154{ 83{
155 struct dentry *dentry = drvr->dbgfs_dir; 84 struct brcmf_debugfs_entry *entry = inode->i_private;
156 85
157 if (!IS_ERR_OR_NULL(dentry)) 86 return single_open(f, entry->read, entry->drvr->bus_if->dev);
158 debugfs_create_file("counters", S_IRUGO, dentry,
159 sdcnt, &brcmf_debugfs_sdio_counter_ops);
160}
161
162static
163ssize_t brcmf_debugfs_fws_stats_read(struct file *f, char __user *data,
164 size_t count, loff_t *ppos)
165{
166 struct brcmf_fws_stats *fwstats = f->private_data;
167 char buf[650];
168 int res;
169
170 /* only allow read from start */
171 if (*ppos > 0)
172 return 0;
173
174 res = scnprintf(buf, sizeof(buf),
175 "header_pulls: %u\n"
176 "header_only_pkt: %u\n"
177 "tlv_parse_failed: %u\n"
178 "tlv_invalid_type: %u\n"
179 "mac_update_fails: %u\n"
180 "ps_update_fails: %u\n"
181 "if_update_fails: %u\n"
182 "pkt2bus: %u\n"
183 "generic_error: %u\n"
184 "rollback_success: %u\n"
185 "rollback_failed: %u\n"
186 "delayq_full: %u\n"
187 "supprq_full: %u\n"
188 "txs_indicate: %u\n"
189 "txs_discard: %u\n"
190 "txs_suppr_core: %u\n"
191 "txs_suppr_ps: %u\n"
192 "txs_tossed: %u\n"
193 "txs_host_tossed: %u\n"
194 "bus_flow_block: %u\n"
195 "fws_flow_block: %u\n"
196 "send_pkts: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n"
197 "requested_sent: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n",
198 fwstats->header_pulls,
199 fwstats->header_only_pkt,
200 fwstats->tlv_parse_failed,
201 fwstats->tlv_invalid_type,
202 fwstats->mac_update_failed,
203 fwstats->mac_ps_update_failed,
204 fwstats->if_update_failed,
205 fwstats->pkt2bus,
206 fwstats->generic_error,
207 fwstats->rollback_success,
208 fwstats->rollback_failed,
209 fwstats->delayq_full_error,
210 fwstats->supprq_full_error,
211 fwstats->txs_indicate,
212 fwstats->txs_discard,
213 fwstats->txs_supp_core,
214 fwstats->txs_supp_ps,
215 fwstats->txs_tossed,
216 fwstats->txs_host_tossed,
217 fwstats->bus_flow_block,
218 fwstats->fws_flow_block,
219 fwstats->send_pkts[0], fwstats->send_pkts[1],
220 fwstats->send_pkts[2], fwstats->send_pkts[3],
221 fwstats->send_pkts[4],
222 fwstats->requested_sent[0],
223 fwstats->requested_sent[1],
224 fwstats->requested_sent[2],
225 fwstats->requested_sent[3],
226 fwstats->requested_sent[4]);
227
228 return simple_read_from_buffer(data, count, ppos, buf, res);
229} 87}
230 88
231static const struct file_operations brcmf_debugfs_fws_stats_ops = { 89static const struct file_operations brcmf_debugfs_def_ops = {
232 .owner = THIS_MODULE, 90 .owner = THIS_MODULE,
233 .open = simple_open, 91 .open = brcmf_debugfs_entry_open,
234 .read = brcmf_debugfs_fws_stats_read 92 .release = single_release,
93 .read = seq_read,
94 .llseek = seq_lseek
235}; 95};
236 96
237void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr, 97int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
238 struct brcmf_fws_stats *stats) 98 int (*read_fn)(struct seq_file *seq, void *data))
239{ 99{
240 struct dentry *dentry = drvr->dbgfs_dir; 100 struct dentry *dentry = drvr->dbgfs_dir;
101 struct brcmf_debugfs_entry *entry;
102
103 if (IS_ERR_OR_NULL(dentry))
104 return -ENOENT;
105
106 entry = devm_kzalloc(drvr->bus_if->dev, sizeof(*entry), GFP_KERNEL);
107 if (!entry)
108 return -ENOMEM;
109
110 entry->read = read_fn;
111 entry->drvr = drvr;
112
113 dentry = debugfs_create_file(fn, S_IRUGO, dentry, entry,
114 &brcmf_debugfs_def_ops);
241 115
242 if (!IS_ERR_OR_NULL(dentry)) 116 return PTR_ERR_OR_ZERO(dentry);
243 debugfs_create_file("fws_stats", S_IRUGO, dentry,
244 stats, &brcmf_debugfs_fws_stats_ops);
245} 117}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
index ef52ed7abc69..6eade7c60c63 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
@@ -100,68 +100,6 @@ do { \
100 100
101extern int brcmf_msg_level; 101extern int brcmf_msg_level;
102 102
103/*
104 * hold counter variables used in brcmfmac sdio driver.
105 */
106struct brcmf_sdio_count {
107 uint intrcount; /* Count of device interrupt callbacks */
108 uint lastintrs; /* Count as of last watchdog timer */
109 uint pollcnt; /* Count of active polls */
110 uint regfails; /* Count of R_REG failures */
111 uint tx_sderrs; /* Count of tx attempts with sd errors */
112 uint fcqueued; /* Tx packets that got queued */
113 uint rxrtx; /* Count of rtx requests (NAK to dongle) */
114 uint rx_toolong; /* Receive frames too long to receive */
115 uint rxc_errors; /* SDIO errors when reading control frames */
116 uint rx_hdrfail; /* SDIO errors on header reads */
117 uint rx_badhdr; /* Bad received headers (roosync?) */
118 uint rx_badseq; /* Mismatched rx sequence number */
119 uint fc_rcvd; /* Number of flow-control events received */
120 uint fc_xoff; /* Number which turned on flow-control */
121 uint fc_xon; /* Number which turned off flow-control */
122 uint rxglomfail; /* Failed deglom attempts */
123 uint rxglomframes; /* Number of glom frames (superframes) */
124 uint rxglompkts; /* Number of packets from glom frames */
125 uint f2rxhdrs; /* Number of header reads */
126 uint f2rxdata; /* Number of frame data reads */
127 uint f2txdata; /* Number of f2 frame writes */
128 uint f1regdata; /* Number of f1 register accesses */
129 uint tickcnt; /* Number of watchdog been schedule */
130 ulong tx_ctlerrs; /* Err of sending ctrl frames */
131 ulong tx_ctlpkts; /* Ctrl frames sent to dongle */
132 ulong rx_ctlerrs; /* Err of processing rx ctrl frames */
133 ulong rx_ctlpkts; /* Ctrl frames processed from dongle */
134 ulong rx_readahead_cnt; /* packets where header read-ahead was used */
135};
136
137struct brcmf_fws_stats {
138 u32 tlv_parse_failed;
139 u32 tlv_invalid_type;
140 u32 header_only_pkt;
141 u32 header_pulls;
142 u32 pkt2bus;
143 u32 send_pkts[5];
144 u32 requested_sent[5];
145 u32 generic_error;
146 u32 mac_update_failed;
147 u32 mac_ps_update_failed;
148 u32 if_update_failed;
149 u32 packet_request_failed;
150 u32 credit_request_failed;
151 u32 rollback_success;
152 u32 rollback_failed;
153 u32 delayq_full_error;
154 u32 supprq_full_error;
155 u32 txs_indicate;
156 u32 txs_discard;
157 u32 txs_supp_core;
158 u32 txs_supp_ps;
159 u32 txs_tossed;
160 u32 txs_host_tossed;
161 u32 bus_flow_block;
162 u32 fws_flow_block;
163};
164
165struct brcmf_pub; 103struct brcmf_pub;
166#ifdef DEBUG 104#ifdef DEBUG
167void brcmf_debugfs_init(void); 105void brcmf_debugfs_init(void);
@@ -169,10 +107,8 @@ void brcmf_debugfs_exit(void);
169int brcmf_debugfs_attach(struct brcmf_pub *drvr); 107int brcmf_debugfs_attach(struct brcmf_pub *drvr);
170void brcmf_debugfs_detach(struct brcmf_pub *drvr); 108void brcmf_debugfs_detach(struct brcmf_pub *drvr);
171struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr); 109struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr);
172void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr, 110int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
173 struct brcmf_sdio_count *sdcnt); 111 int (*read_fn)(struct seq_file *seq, void *data));
174void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr,
175 struct brcmf_fws_stats *stats);
176#else 112#else
177static inline void brcmf_debugfs_init(void) 113static inline void brcmf_debugfs_init(void)
178{ 114{
@@ -187,9 +123,11 @@ static inline int brcmf_debugfs_attach(struct brcmf_pub *drvr)
187static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr) 123static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr)
188{ 124{
189} 125}
190static inline void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr, 126static inline
191 struct brcmf_fws_stats *stats) 127int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
128 int (*read_fn)(struct seq_file *seq, void *data))
192{ 129{
130 return 0;
193} 131}
194#endif 132#endif
195 133
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index 2699441d4f41..347b4260f45b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -30,6 +30,7 @@
30#include "wl_cfg80211.h" 30#include "wl_cfg80211.h"
31#include "fwil.h" 31#include "fwil.h"
32#include "fwsignal.h" 32#include "fwsignal.h"
33#include "feature.h"
33#include "proto.h" 34#include "proto.h"
34 35
35MODULE_AUTHOR("Broadcom Corporation"); 36MODULE_AUTHOR("Broadcom Corporation");
@@ -937,6 +938,8 @@ int brcmf_bus_start(struct device *dev)
937 if (ret < 0) 938 if (ret < 0)
938 goto fail; 939 goto fail;
939 940
941 brcmf_feat_attach(drvr);
942
940 ret = brcmf_fws_init(drvr); 943 ret = brcmf_fws_init(drvr);
941 if (ret < 0) 944 if (ret < 0)
942 goto fail; 945 goto fail;
@@ -1074,16 +1077,6 @@ int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
1074 return !err; 1077 return !err;
1075} 1078}
1076 1079
1077/*
1078 * return chip id and rev of the device encoded in u32.
1079 */
1080u32 brcmf_get_chip_info(struct brcmf_if *ifp)
1081{
1082 struct brcmf_bus *bus = ifp->drvr->bus_if;
1083
1084 return bus->chip << 4 | bus->chiprev;
1085}
1086
1087static void brcmf_driver_register(struct work_struct *work) 1080static void brcmf_driver_register(struct work_struct *work)
1088{ 1081{
1089#ifdef CONFIG_BRCMFMAC_SDIO 1082#ifdef CONFIG_BRCMFMAC_SDIO
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 8fa0dbbbda72..67d91d5cc13d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -391,6 +391,40 @@ struct brcmf_sdio_hdrinfo {
391 u16 tail_pad; 391 u16 tail_pad;
392}; 392};
393 393
394/*
395 * hold counter variables
396 */
397struct brcmf_sdio_count {
398 uint intrcount; /* Count of device interrupt callbacks */
399 uint lastintrs; /* Count as of last watchdog timer */
400 uint pollcnt; /* Count of active polls */
401 uint regfails; /* Count of R_REG failures */
402 uint tx_sderrs; /* Count of tx attempts with sd errors */
403 uint fcqueued; /* Tx packets that got queued */
404 uint rxrtx; /* Count of rtx requests (NAK to dongle) */
405 uint rx_toolong; /* Receive frames too long to receive */
406 uint rxc_errors; /* SDIO errors when reading control frames */
407 uint rx_hdrfail; /* SDIO errors on header reads */
408 uint rx_badhdr; /* Bad received headers (roosync?) */
409 uint rx_badseq; /* Mismatched rx sequence number */
410 uint fc_rcvd; /* Number of flow-control events received */
411 uint fc_xoff; /* Number which turned on flow-control */
412 uint fc_xon; /* Number which turned off flow-control */
413 uint rxglomfail; /* Failed deglom attempts */
414 uint rxglomframes; /* Number of glom frames (superframes) */
415 uint rxglompkts; /* Number of packets from glom frames */
416 uint f2rxhdrs; /* Number of header reads */
417 uint f2rxdata; /* Number of frame data reads */
418 uint f2txdata; /* Number of f2 frame writes */
419 uint f1regdata; /* Number of f1 register accesses */
420 uint tickcnt; /* Number of watchdog been schedule */
421 ulong tx_ctlerrs; /* Err of sending ctrl frames */
422 ulong tx_ctlpkts; /* Ctrl frames sent to dongle */
423 ulong rx_ctlerrs; /* Err of processing rx ctrl frames */
424 ulong rx_ctlpkts; /* Ctrl frames processed from dongle */
425 ulong rx_readahead_cnt; /* packets where header read-ahead was used */
426};
427
394/* misc chip info needed by some of the routines */ 428/* misc chip info needed by some of the routines */
395/* Private data for SDIO bus interaction */ 429/* Private data for SDIO bus interaction */
396struct brcmf_sdio { 430struct brcmf_sdio {
@@ -620,40 +654,46 @@ enum brcmf_firmware_type {
620 name ## _FIRMWARE_NAME, name ## _NVRAM_NAME 654 name ## _FIRMWARE_NAME, name ## _NVRAM_NAME
621 655
622static const struct brcmf_firmware_names brcmf_fwname_data[] = { 656static const struct brcmf_firmware_names brcmf_fwname_data[] = {
623 { BCM43143_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43143) }, 657 { BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43143) },
624 { BCM43241_CHIP_ID, 0x0000001F, BRCMF_FIRMWARE_NVRAM(BCM43241B0) }, 658 { BRCM_CC_43241_CHIP_ID, 0x0000001F, BRCMF_FIRMWARE_NVRAM(BCM43241B0) },
625 { BCM43241_CHIP_ID, 0xFFFFFFE0, BRCMF_FIRMWARE_NVRAM(BCM43241B4) }, 659 { BRCM_CC_43241_CHIP_ID, 0xFFFFFFE0, BRCMF_FIRMWARE_NVRAM(BCM43241B4) },
626 { BCM4329_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4329) }, 660 { BRCM_CC_4329_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4329) },
627 { BCM4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) }, 661 { BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) },
628 { BCM4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) }, 662 { BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) },
629 { BCM4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) }, 663 { BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) },
630 { BCM43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) }, 664 { BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) },
631 { BCM4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) }, 665 { BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) },
632 { BCM4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) } 666 { BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) }
633}; 667};
634 668
635static const char *brcmf_sdio_get_fwname(struct brcmf_chip *ci, 669static int brcmf_sdio_get_fwnames(struct brcmf_chip *ci,
636 enum brcmf_firmware_type type) 670 struct brcmf_sdio_dev *sdiodev)
637{ 671{
638 int i; 672 int i;
639 673
640 for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) { 674 for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) {
641 if (brcmf_fwname_data[i].chipid == ci->chip && 675 if (brcmf_fwname_data[i].chipid == ci->chip &&
642 brcmf_fwname_data[i].revmsk & BIT(ci->chiprev)) { 676 brcmf_fwname_data[i].revmsk & BIT(ci->chiprev))
643 switch (type) { 677 break;
644 case BRCMF_FIRMWARE_BIN:
645 return brcmf_fwname_data[i].bin;
646 case BRCMF_FIRMWARE_NVRAM:
647 return brcmf_fwname_data[i].nv;
648 default:
649 brcmf_err("invalid firmware type (%d)\n", type);
650 return NULL;
651 }
652 }
653 } 678 }
654 brcmf_err("Unknown chipid %d [%d]\n", 679
655 ci->chip, ci->chiprev); 680 if (i == ARRAY_SIZE(brcmf_fwname_data)) {
656 return NULL; 681 brcmf_err("Unknown chipid %d [%d]\n", ci->chip, ci->chiprev);
682 return -ENODEV;
683 }
684
685 /* check if firmware path is provided by module parameter */
686 if (brcmf_firmware_path[0] != '\0') {
687 if (brcmf_firmware_path[strlen(brcmf_firmware_path) - 1] != '/')
688 strcat(brcmf_firmware_path, "/");
689
690 strcpy(sdiodev->fw_name, brcmf_firmware_path);
691 strcpy(sdiodev->nvram_name, brcmf_firmware_path);
692 }
693 strcat(sdiodev->fw_name, brcmf_fwname_data[i].bin);
694 strcat(sdiodev->nvram_name, brcmf_fwname_data[i].nv);
695
696 return 0;
657} 697}
658 698
659static void pkt_align(struct sk_buff *p, int len, int align) 699static void pkt_align(struct sk_buff *p, int len, int align)
@@ -2898,16 +2938,13 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
2898} 2938}
2899 2939
2900#ifdef DEBUG 2940#ifdef DEBUG
2901static int brcmf_sdio_dump_console(struct brcmf_sdio *bus, 2941static int brcmf_sdio_dump_console(struct seq_file *seq, struct brcmf_sdio *bus,
2902 struct sdpcm_shared *sh, char __user *data, 2942 struct sdpcm_shared *sh)
2903 size_t count)
2904{ 2943{
2905 u32 addr, console_ptr, console_size, console_index; 2944 u32 addr, console_ptr, console_size, console_index;
2906 char *conbuf = NULL; 2945 char *conbuf = NULL;
2907 __le32 sh_val; 2946 __le32 sh_val;
2908 int rv; 2947 int rv;
2909 loff_t pos = 0;
2910 int nbytes = 0;
2911 2948
2912 /* obtain console information from device memory */ 2949 /* obtain console information from device memory */
2913 addr = sh->console_addr + offsetof(struct rte_console, log_le); 2950 addr = sh->console_addr + offsetof(struct rte_console, log_le);
@@ -2945,33 +2982,24 @@ static int brcmf_sdio_dump_console(struct brcmf_sdio *bus,
2945 if (rv < 0) 2982 if (rv < 0)
2946 goto done; 2983 goto done;
2947 2984
2948 rv = simple_read_from_buffer(data, count, &pos, 2985 rv = seq_write(seq, conbuf + console_index,
2949 conbuf + console_index, 2986 console_size - console_index);
2950 console_size - console_index);
2951 if (rv < 0) 2987 if (rv < 0)
2952 goto done; 2988 goto done;
2953 2989
2954 nbytes = rv; 2990 if (console_index > 0)
2955 if (console_index > 0) { 2991 rv = seq_write(seq, conbuf, console_index - 1);
2956 pos = 0; 2992
2957 rv = simple_read_from_buffer(data+nbytes, count, &pos,
2958 conbuf, console_index - 1);
2959 if (rv < 0)
2960 goto done;
2961 rv += nbytes;
2962 }
2963done: 2993done:
2964 vfree(conbuf); 2994 vfree(conbuf);
2965 return rv; 2995 return rv;
2966} 2996}
2967 2997
2968static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh, 2998static int brcmf_sdio_trap_info(struct seq_file *seq, struct brcmf_sdio *bus,
2969 char __user *data, size_t count) 2999 struct sdpcm_shared *sh)
2970{ 3000{
2971 int error, res; 3001 int error;
2972 char buf[350];
2973 struct brcmf_trap_info tr; 3002 struct brcmf_trap_info tr;
2974 loff_t pos = 0;
2975 3003
2976 if ((sh->flags & SDPCM_SHARED_TRAP) == 0) { 3004 if ((sh->flags & SDPCM_SHARED_TRAP) == 0) {
2977 brcmf_dbg(INFO, "no trap in firmware\n"); 3005 brcmf_dbg(INFO, "no trap in firmware\n");
@@ -2983,34 +3011,30 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
2983 if (error < 0) 3011 if (error < 0)
2984 return error; 3012 return error;
2985 3013
2986 res = scnprintf(buf, sizeof(buf), 3014 seq_printf(seq,
2987 "dongle trap info: type 0x%x @ epc 0x%08x\n" 3015 "dongle trap info: type 0x%x @ epc 0x%08x\n"
2988 " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n" 3016 " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n"
2989 " lr 0x%08x pc 0x%08x offset 0x%x\n" 3017 " lr 0x%08x pc 0x%08x offset 0x%x\n"
2990 " r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n" 3018 " r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n"
2991 " r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n", 3019 " r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n",
2992 le32_to_cpu(tr.type), le32_to_cpu(tr.epc), 3020 le32_to_cpu(tr.type), le32_to_cpu(tr.epc),
2993 le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr), 3021 le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr),
2994 le32_to_cpu(tr.r13), le32_to_cpu(tr.r14), 3022 le32_to_cpu(tr.r13), le32_to_cpu(tr.r14),
2995 le32_to_cpu(tr.pc), sh->trap_addr, 3023 le32_to_cpu(tr.pc), sh->trap_addr,
2996 le32_to_cpu(tr.r0), le32_to_cpu(tr.r1), 3024 le32_to_cpu(tr.r0), le32_to_cpu(tr.r1),
2997 le32_to_cpu(tr.r2), le32_to_cpu(tr.r3), 3025 le32_to_cpu(tr.r2), le32_to_cpu(tr.r3),
2998 le32_to_cpu(tr.r4), le32_to_cpu(tr.r5), 3026 le32_to_cpu(tr.r4), le32_to_cpu(tr.r5),
2999 le32_to_cpu(tr.r6), le32_to_cpu(tr.r7)); 3027 le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
3000 3028
3001 return simple_read_from_buffer(data, count, &pos, buf, res); 3029 return 0;
3002} 3030}
3003 3031
3004static int brcmf_sdio_assert_info(struct brcmf_sdio *bus, 3032static int brcmf_sdio_assert_info(struct seq_file *seq, struct brcmf_sdio *bus,
3005 struct sdpcm_shared *sh, char __user *data, 3033 struct sdpcm_shared *sh)
3006 size_t count)
3007{ 3034{
3008 int error = 0; 3035 int error = 0;
3009 char buf[200];
3010 char file[80] = "?"; 3036 char file[80] = "?";
3011 char expr[80] = "<???>"; 3037 char expr[80] = "<???>";
3012 int res;
3013 loff_t pos = 0;
3014 3038
3015 if ((sh->flags & SDPCM_SHARED_ASSERT_BUILT) == 0) { 3039 if ((sh->flags & SDPCM_SHARED_ASSERT_BUILT) == 0) {
3016 brcmf_dbg(INFO, "firmware not built with -assert\n"); 3040 brcmf_dbg(INFO, "firmware not built with -assert\n");
@@ -3035,10 +3059,9 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
3035 } 3059 }
3036 sdio_release_host(bus->sdiodev->func[1]); 3060 sdio_release_host(bus->sdiodev->func[1]);
3037 3061
3038 res = scnprintf(buf, sizeof(buf), 3062 seq_printf(seq, "dongle assert: %s:%d: assert(%s)\n",
3039 "dongle assert: %s:%d: assert(%s)\n", 3063 file, sh->assert_line, expr);
3040 file, sh->assert_line, expr); 3064 return 0;
3041 return simple_read_from_buffer(data, count, &pos, buf, res);
3042} 3065}
3043 3066
3044static int brcmf_sdio_checkdied(struct brcmf_sdio *bus) 3067static int brcmf_sdio_checkdied(struct brcmf_sdio *bus)
@@ -3062,59 +3085,75 @@ static int brcmf_sdio_checkdied(struct brcmf_sdio *bus)
3062 return 0; 3085 return 0;
3063} 3086}
3064 3087
3065static int brcmf_sdio_died_dump(struct brcmf_sdio *bus, char __user *data, 3088static int brcmf_sdio_died_dump(struct seq_file *seq, struct brcmf_sdio *bus)
3066 size_t count, loff_t *ppos)
3067{ 3089{
3068 int error = 0; 3090 int error = 0;
3069 struct sdpcm_shared sh; 3091 struct sdpcm_shared sh;
3070 int nbytes = 0;
3071 loff_t pos = *ppos;
3072
3073 if (pos != 0)
3074 return 0;
3075 3092
3076 error = brcmf_sdio_readshared(bus, &sh); 3093 error = brcmf_sdio_readshared(bus, &sh);
3077 if (error < 0) 3094 if (error < 0)
3078 goto done; 3095 goto done;
3079 3096
3080 error = brcmf_sdio_assert_info(bus, &sh, data, count); 3097 error = brcmf_sdio_assert_info(seq, bus, &sh);
3081 if (error < 0) 3098 if (error < 0)
3082 goto done; 3099 goto done;
3083 nbytes = error;
3084 3100
3085 error = brcmf_sdio_trap_info(bus, &sh, data+nbytes, count); 3101 error = brcmf_sdio_trap_info(seq, bus, &sh);
3086 if (error < 0) 3102 if (error < 0)
3087 goto done; 3103 goto done;
3088 nbytes += error;
3089 3104
3090 error = brcmf_sdio_dump_console(bus, &sh, data+nbytes, count); 3105 error = brcmf_sdio_dump_console(seq, bus, &sh);
3091 if (error < 0)
3092 goto done;
3093 nbytes += error;
3094 3106
3095 error = nbytes;
3096 *ppos += nbytes;
3097done: 3107done:
3098 return error; 3108 return error;
3099} 3109}
3100 3110
3101static ssize_t brcmf_sdio_forensic_read(struct file *f, char __user *data, 3111static int brcmf_sdio_forensic_read(struct seq_file *seq, void *data)
3102 size_t count, loff_t *ppos)
3103{ 3112{
3104 struct brcmf_sdio *bus = f->private_data; 3113 struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
3105 int res; 3114 struct brcmf_sdio *bus = bus_if->bus_priv.sdio->bus;
3106 3115
3107 res = brcmf_sdio_died_dump(bus, data, count, ppos); 3116 return brcmf_sdio_died_dump(seq, bus);
3108 if (res > 0)
3109 *ppos += res;
3110 return (ssize_t)res;
3111} 3117}
3112 3118
3113static const struct file_operations brcmf_sdio_forensic_ops = { 3119static int brcmf_debugfs_sdio_count_read(struct seq_file *seq, void *data)
3114 .owner = THIS_MODULE, 3120{
3115 .open = simple_open, 3121 struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
3116 .read = brcmf_sdio_forensic_read 3122 struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
3117}; 3123 struct brcmf_sdio_count *sdcnt = &sdiodev->bus->sdcnt;
3124
3125 seq_printf(seq,
3126 "intrcount: %u\nlastintrs: %u\n"
3127 "pollcnt: %u\nregfails: %u\n"
3128 "tx_sderrs: %u\nfcqueued: %u\n"
3129 "rxrtx: %u\nrx_toolong: %u\n"
3130 "rxc_errors: %u\nrx_hdrfail: %u\n"
3131 "rx_badhdr: %u\nrx_badseq: %u\n"
3132 "fc_rcvd: %u\nfc_xoff: %u\n"
3133 "fc_xon: %u\nrxglomfail: %u\n"
3134 "rxglomframes: %u\nrxglompkts: %u\n"
3135 "f2rxhdrs: %u\nf2rxdata: %u\n"
3136 "f2txdata: %u\nf1regdata: %u\n"
3137 "tickcnt: %u\ntx_ctlerrs: %lu\n"
3138 "tx_ctlpkts: %lu\nrx_ctlerrs: %lu\n"
3139 "rx_ctlpkts: %lu\nrx_readahead: %lu\n",
3140 sdcnt->intrcount, sdcnt->lastintrs,
3141 sdcnt->pollcnt, sdcnt->regfails,
3142 sdcnt->tx_sderrs, sdcnt->fcqueued,
3143 sdcnt->rxrtx, sdcnt->rx_toolong,
3144 sdcnt->rxc_errors, sdcnt->rx_hdrfail,
3145 sdcnt->rx_badhdr, sdcnt->rx_badseq,
3146 sdcnt->fc_rcvd, sdcnt->fc_xoff,
3147 sdcnt->fc_xon, sdcnt->rxglomfail,
3148 sdcnt->rxglomframes, sdcnt->rxglompkts,
3149 sdcnt->f2rxhdrs, sdcnt->f2rxdata,
3150 sdcnt->f2txdata, sdcnt->f1regdata,
3151 sdcnt->tickcnt, sdcnt->tx_ctlerrs,
3152 sdcnt->tx_ctlpkts, sdcnt->rx_ctlerrs,
3153 sdcnt->rx_ctlpkts, sdcnt->rx_readahead_cnt);
3154
3155 return 0;
3156}
3118 3157
3119static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus) 3158static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus)
3120{ 3159{
@@ -3124,9 +3163,9 @@ static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus)
3124 if (IS_ERR_OR_NULL(dentry)) 3163 if (IS_ERR_OR_NULL(dentry))
3125 return; 3164 return;
3126 3165
3127 debugfs_create_file("forensics", S_IRUGO, dentry, bus, 3166 brcmf_debugfs_add_entry(drvr, "forensics", brcmf_sdio_forensic_read);
3128 &brcmf_sdio_forensic_ops); 3167 brcmf_debugfs_add_entry(drvr, "counters",
3129 brcmf_debugfs_create_sdio_count(drvr, &bus->sdcnt); 3168 brcmf_debugfs_sdio_count_read);
3130 debugfs_create_u32("console_interval", 0644, dentry, 3169 debugfs_create_u32("console_interval", 0644, dentry,
3131 &bus->console_interval); 3170 &bus->console_interval);
3132} 3171}
@@ -3598,17 +3637,17 @@ brcmf_sdio_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
3598 return; 3637 return;
3599 3638
3600 switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) { 3639 switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
3601 case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12): 3640 case SDIOD_DRVSTR_KEY(BRCM_CC_4330_CHIP_ID, 12):
3602 str_tab = sdiod_drvstr_tab1_1v8; 3641 str_tab = sdiod_drvstr_tab1_1v8;
3603 str_mask = 0x00003800; 3642 str_mask = 0x00003800;
3604 str_shift = 11; 3643 str_shift = 11;
3605 break; 3644 break;
3606 case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17): 3645 case SDIOD_DRVSTR_KEY(BRCM_CC_4334_CHIP_ID, 17):
3607 str_tab = sdiod_drvstr_tab6_1v8; 3646 str_tab = sdiod_drvstr_tab6_1v8;
3608 str_mask = 0x00001800; 3647 str_mask = 0x00001800;
3609 str_shift = 11; 3648 str_shift = 11;
3610 break; 3649 break;
3611 case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17): 3650 case SDIOD_DRVSTR_KEY(BRCM_CC_43143_CHIP_ID, 17):
3612 /* note: 43143 does not support tristate */ 3651 /* note: 43143 does not support tristate */
3613 i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1; 3652 i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1;
3614 if (drivestrength >= sdiod_drvstr_tab2_3v3[i].strength) { 3653 if (drivestrength >= sdiod_drvstr_tab2_3v3[i].strength) {
@@ -3619,7 +3658,7 @@ brcmf_sdio_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
3619 brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n", 3658 brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n",
3620 ci->name, drivestrength); 3659 ci->name, drivestrength);
3621 break; 3660 break;
3622 case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13): 3661 case SDIOD_DRVSTR_KEY(BRCM_CC_43362_CHIP_ID, 13):
3623 str_tab = sdiod_drive_strength_tab5_1v8; 3662 str_tab = sdiod_drive_strength_tab5_1v8;
3624 str_mask = 0x00003800; 3663 str_mask = 0x00003800;
3625 str_shift = 11; 3664 str_shift = 11;
@@ -3720,12 +3759,12 @@ static u32 brcmf_sdio_buscore_read32(void *ctx, u32 addr)
3720 u32 val, rev; 3759 u32 val, rev;
3721 3760
3722 val = brcmf_sdiod_regrl(sdiodev, addr, NULL); 3761 val = brcmf_sdiod_regrl(sdiodev, addr, NULL);
3723 if (sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 && 3762 if (sdiodev->func[0]->device == BRCM_SDIO_4335_4339_DEVICE_ID &&
3724 addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) { 3763 addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) {
3725 rev = (val & CID_REV_MASK) >> CID_REV_SHIFT; 3764 rev = (val & CID_REV_MASK) >> CID_REV_SHIFT;
3726 if (rev >= 2) { 3765 if (rev >= 2) {
3727 val &= ~CID_ID_MASK; 3766 val &= ~CID_ID_MASK;
3728 val |= BCM4339_CHIP_ID; 3767 val |= BRCM_CC_4339_CHIP_ID;
3729 } 3768 }
3730 } 3769 }
3731 return val; 3770 return val;
@@ -4127,11 +4166,12 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
4127 brcmf_sdio_debugfs_create(bus); 4166 brcmf_sdio_debugfs_create(bus);
4128 brcmf_dbg(INFO, "completed!!\n"); 4167 brcmf_dbg(INFO, "completed!!\n");
4129 4168
4169 ret = brcmf_sdio_get_fwnames(bus->ci, sdiodev);
4170 if (ret)
4171 goto fail;
4172
4130 ret = brcmf_fw_get_firmwares(sdiodev->dev, BRCMF_FW_REQUEST_NVRAM, 4173 ret = brcmf_fw_get_firmwares(sdiodev->dev, BRCMF_FW_REQUEST_NVRAM,
4131 brcmf_sdio_get_fwname(bus->ci, 4174 sdiodev->fw_name, sdiodev->nvram_name,
4132 BRCMF_FIRMWARE_BIN),
4133 brcmf_sdio_get_fwname(bus->ci,
4134 BRCMF_FIRMWARE_NVRAM),
4135 brcmf_sdio_firmware_callback); 4175 brcmf_sdio_firmware_callback);
4136 if (ret != 0) { 4176 if (ret != 0) {
4137 brcmf_err("async firmware request failed: %d\n", ret); 4177 brcmf_err("async firmware request failed: %d\n", ret);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/brcm80211/brcmfmac/feature.c
new file mode 100644
index 000000000000..50877e3c5d2f
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c
@@ -0,0 +1,136 @@
1/*
2 * Copyright (c) 2014 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/netdevice.h>
18
19#include <brcm_hw_ids.h>
20#include "dhd.h"
21#include "dhd_bus.h"
22#include "dhd_dbg.h"
23#include "fwil.h"
24#include "feature.h"
25
26/*
27 * firmware error code received if iovar is unsupported.
28 */
29#define EBRCMF_FEAT_UNSUPPORTED 23
30
31/*
32 * expand feature list to array of feature strings.
33 */
34#define BRCMF_FEAT_DEF(_f) \
35 #_f,
36static const char *brcmf_feat_names[] = {
37 BRCMF_FEAT_LIST
38};
39#undef BRCMF_FEAT_DEF
40
41#ifdef DEBUG
42/*
43 * expand quirk list to array of quirk strings.
44 */
45#define BRCMF_QUIRK_DEF(_q) \
46 #_q,
47static const char * const brcmf_quirk_names[] = {
48 BRCMF_QUIRK_LIST
49};
50#undef BRCMF_QUIRK_DEF
51
52/**
53 * brcmf_feat_debugfs_read() - expose feature info to debugfs.
54 *
55 * @seq: sequence for debugfs entry.
56 * @data: raw data pointer.
57 */
58static int brcmf_feat_debugfs_read(struct seq_file *seq, void *data)
59{
60 struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
61 u32 feats = bus_if->drvr->feat_flags;
62 u32 quirks = bus_if->drvr->chip_quirks;
63 int id;
64
65 seq_printf(seq, "Features: %08x\n", feats);
66 for (id = 0; id < BRCMF_FEAT_LAST; id++)
67 if (feats & BIT(id))
68 seq_printf(seq, "\t%s\n", brcmf_feat_names[id]);
69 seq_printf(seq, "\nQuirks: %08x\n", quirks);
70 for (id = 0; id < BRCMF_FEAT_QUIRK_LAST; id++)
71 if (quirks & BIT(id))
72 seq_printf(seq, "\t%s\n", brcmf_quirk_names[id]);
73 return 0;
74}
75#else
76static int brcmf_feat_debugfs_read(struct seq_file *seq, void *data)
77{
78 return 0;
79}
80#endif /* DEBUG */
81
82/**
83 * brcmf_feat_iovar_int_get() - determine feature through iovar query.
84 *
85 * @ifp: interface to query.
86 * @id: feature id.
87 * @name: iovar name.
88 */
89static void brcmf_feat_iovar_int_get(struct brcmf_if *ifp,
90 enum brcmf_feat_id id, char *name)
91{
92 u32 data;
93 int err;
94
95 err = brcmf_fil_iovar_int_get(ifp, name, &data);
96 if (err == 0) {
97 brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
98 ifp->drvr->feat_flags |= BIT(id);
99 } else {
100 brcmf_dbg(TRACE, "%s feature check failed: %d\n",
101 brcmf_feat_names[id], err);
102 }
103}
104
105void brcmf_feat_attach(struct brcmf_pub *drvr)
106{
107 struct brcmf_if *ifp = drvr->iflist[0];
108
109 brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan");
110
111 /* set chip related quirks */
112 switch (drvr->bus_if->chip) {
113 case BRCM_CC_43236_CHIP_ID:
114 drvr->chip_quirks |= BIT(BRCMF_FEAT_QUIRK_AUTO_AUTH);
115 break;
116 case BRCM_CC_4329_CHIP_ID:
117 drvr->chip_quirks |= BIT(BRCMF_FEAT_QUIRK_NEED_MPC);
118 break;
119 default:
120 /* no quirks */
121 break;
122 }
123
124 brcmf_debugfs_add_entry(drvr, "features", brcmf_feat_debugfs_read);
125}
126
127bool brcmf_feat_is_enabled(struct brcmf_if *ifp, enum brcmf_feat_id id)
128{
129 return (ifp->drvr->feat_flags & BIT(id));
130}
131
132bool brcmf_feat_is_quirk_enabled(struct brcmf_if *ifp,
133 enum brcmf_feat_quirk quirk)
134{
135 return (ifp->drvr->chip_quirks & BIT(quirk));
136}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/brcm80211/brcmfmac/feature.h
new file mode 100644
index 000000000000..961d175f8afb
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.h
@@ -0,0 +1,86 @@
1/*
2 * Copyright (c) 2014 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 _BRCMF_FEATURE_H
17#define _BRCMF_FEATURE_H
18
19/*
20 * Features:
21 *
22 * MCHAN: multi-channel for concurrent P2P.
23 */
24#define BRCMF_FEAT_LIST \
25 BRCMF_FEAT_DEF(MCHAN)
26/*
27 * Quirks:
28 *
29 * AUTO_AUTH: workaround needed for automatic authentication type.
30 * NEED_MPC: driver needs to disable MPC during scanning operation.
31 */
32#define BRCMF_QUIRK_LIST \
33 BRCMF_QUIRK_DEF(AUTO_AUTH) \
34 BRCMF_QUIRK_DEF(NEED_MPC)
35
36#define BRCMF_FEAT_DEF(_f) \
37 BRCMF_FEAT_ ## _f,
38/*
39 * expand feature list to enumeration.
40 */
41enum brcmf_feat_id {
42 BRCMF_FEAT_LIST
43 BRCMF_FEAT_LAST
44};
45#undef BRCMF_FEAT_DEF
46
47#define BRCMF_QUIRK_DEF(_q) \
48 BRCMF_FEAT_QUIRK_ ## _q,
49/*
50 * expand quirk list to enumeration.
51 */
52enum brcmf_feat_quirk {
53 BRCMF_QUIRK_LIST
54 BRCMF_FEAT_QUIRK_LAST
55};
56#undef BRCMF_QUIRK_DEF
57
58/**
59 * brcmf_feat_attach() - determine features and quirks.
60 *
61 * @drvr: driver instance.
62 */
63void brcmf_feat_attach(struct brcmf_pub *drvr);
64
65/**
66 * brcmf_feat_is_enabled() - query feature.
67 *
68 * @ifp: interface instance.
69 * @id: feature id to check.
70 *
71 * Return: true is feature is enabled; otherwise false.
72 */
73bool brcmf_feat_is_enabled(struct brcmf_if *ifp, enum brcmf_feat_id id);
74
75/**
76 * brcmf_feat_is_quirk_enabled() - query chip quirk.
77 *
78 * @ifp: interface instance.
79 * @quirk: quirk id to check.
80 *
81 * Return: true is quirk is enabled; otherwise false.
82 */
83bool brcmf_feat_is_quirk_enabled(struct brcmf_if *ifp,
84 enum brcmf_feat_quirk quirk);
85
86#endif /* _BRCMF_FEATURE_H */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
index 7b7d237c1ddb..8ea9f283d2b8 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
@@ -18,10 +18,15 @@
18#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/device.h> 19#include <linux/device.h>
20#include <linux/firmware.h> 20#include <linux/firmware.h>
21#include <linux/module.h>
21 22
22#include "dhd_dbg.h" 23#include "dhd_dbg.h"
23#include "firmware.h" 24#include "firmware.h"
24 25
26char brcmf_firmware_path[BRCMF_FW_PATH_LEN];
27module_param_string(firmware_path, brcmf_firmware_path,
28 BRCMF_FW_PATH_LEN, 0440);
29
25enum nvram_parser_state { 30enum nvram_parser_state {
26 IDLE, 31 IDLE,
27 KEY, 32 KEY,
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.h b/drivers/net/wireless/brcm80211/brcmfmac/firmware.h
index 6431bfd7afff..4d3482356b77 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.h
@@ -21,6 +21,11 @@
21#define BRCMF_FW_REQ_FLAGS 0x00F0 21#define BRCMF_FW_REQ_FLAGS 0x00F0
22#define BRCMF_FW_REQ_NV_OPTIONAL 0x0010 22#define BRCMF_FW_REQ_NV_OPTIONAL 0x0010
23 23
24#define BRCMF_FW_PATH_LEN 256
25#define BRCMF_FW_NAME_LEN 32
26
27extern char brcmf_firmware_path[];
28
24void brcmf_fw_nvram_free(void *nvram); 29void brcmf_fw_nvram_free(void *nvram);
25/* 30/*
26 * Request firmware(s) asynchronously. When the asynchronous request 31 * Request firmware(s) asynchronously. When the asynchronous request
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index 699908de314a..d42f7d04b65f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -454,6 +454,34 @@ struct brcmf_fws_macdesc_table {
454 struct brcmf_fws_mac_descriptor other; 454 struct brcmf_fws_mac_descriptor other;
455}; 455};
456 456
457struct brcmf_fws_stats {
458 u32 tlv_parse_failed;
459 u32 tlv_invalid_type;
460 u32 header_only_pkt;
461 u32 header_pulls;
462 u32 pkt2bus;
463 u32 send_pkts[5];
464 u32 requested_sent[5];
465 u32 generic_error;
466 u32 mac_update_failed;
467 u32 mac_ps_update_failed;
468 u32 if_update_failed;
469 u32 packet_request_failed;
470 u32 credit_request_failed;
471 u32 rollback_success;
472 u32 rollback_failed;
473 u32 delayq_full_error;
474 u32 supprq_full_error;
475 u32 txs_indicate;
476 u32 txs_discard;
477 u32 txs_supp_core;
478 u32 txs_supp_ps;
479 u32 txs_tossed;
480 u32 txs_host_tossed;
481 u32 bus_flow_block;
482 u32 fws_flow_block;
483};
484
457struct brcmf_fws_info { 485struct brcmf_fws_info {
458 struct brcmf_pub *drvr; 486 struct brcmf_pub *drvr;
459 spinlock_t spinlock; 487 spinlock_t spinlock;
@@ -2017,6 +2045,75 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
2017 brcmf_fws_unlock(fws); 2045 brcmf_fws_unlock(fws);
2018} 2046}
2019 2047
2048#ifdef DEBUG
2049static int brcmf_debugfs_fws_stats_read(struct seq_file *seq, void *data)
2050{
2051 struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
2052 struct brcmf_fws_stats *fwstats = &bus_if->drvr->fws->stats;
2053
2054 seq_printf(seq,
2055 "header_pulls: %u\n"
2056 "header_only_pkt: %u\n"
2057 "tlv_parse_failed: %u\n"
2058 "tlv_invalid_type: %u\n"
2059 "mac_update_fails: %u\n"
2060 "ps_update_fails: %u\n"
2061 "if_update_fails: %u\n"
2062 "pkt2bus: %u\n"
2063 "generic_error: %u\n"
2064 "rollback_success: %u\n"
2065 "rollback_failed: %u\n"
2066 "delayq_full: %u\n"
2067 "supprq_full: %u\n"
2068 "txs_indicate: %u\n"
2069 "txs_discard: %u\n"
2070 "txs_suppr_core: %u\n"
2071 "txs_suppr_ps: %u\n"
2072 "txs_tossed: %u\n"
2073 "txs_host_tossed: %u\n"
2074 "bus_flow_block: %u\n"
2075 "fws_flow_block: %u\n"
2076 "send_pkts: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n"
2077 "requested_sent: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n",
2078 fwstats->header_pulls,
2079 fwstats->header_only_pkt,
2080 fwstats->tlv_parse_failed,
2081 fwstats->tlv_invalid_type,
2082 fwstats->mac_update_failed,
2083 fwstats->mac_ps_update_failed,
2084 fwstats->if_update_failed,
2085 fwstats->pkt2bus,
2086 fwstats->generic_error,
2087 fwstats->rollback_success,
2088 fwstats->rollback_failed,
2089 fwstats->delayq_full_error,
2090 fwstats->supprq_full_error,
2091 fwstats->txs_indicate,
2092 fwstats->txs_discard,
2093 fwstats->txs_supp_core,
2094 fwstats->txs_supp_ps,
2095 fwstats->txs_tossed,
2096 fwstats->txs_host_tossed,
2097 fwstats->bus_flow_block,
2098 fwstats->fws_flow_block,
2099 fwstats->send_pkts[0], fwstats->send_pkts[1],
2100 fwstats->send_pkts[2], fwstats->send_pkts[3],
2101 fwstats->send_pkts[4],
2102 fwstats->requested_sent[0],
2103 fwstats->requested_sent[1],
2104 fwstats->requested_sent[2],
2105 fwstats->requested_sent[3],
2106 fwstats->requested_sent[4]);
2107
2108 return 0;
2109}
2110#else
2111static int brcmf_debugfs_fws_stats_read(struct seq_file *seq, void *data)
2112{
2113 return 0;
2114}
2115#endif
2116
2020int brcmf_fws_init(struct brcmf_pub *drvr) 2117int brcmf_fws_init(struct brcmf_pub *drvr)
2021{ 2118{
2022 struct brcmf_fws_info *fws; 2119 struct brcmf_fws_info *fws;
@@ -2107,7 +2204,8 @@ int brcmf_fws_init(struct brcmf_pub *drvr)
2107 BRCMF_FWS_PSQ_LEN); 2204 BRCMF_FWS_PSQ_LEN);
2108 2205
2109 /* create debugfs file for statistics */ 2206 /* create debugfs file for statistics */
2110 brcmf_debugfs_create_fws_stats(drvr, &fws->stats); 2207 brcmf_debugfs_add_entry(drvr, "fws_stats",
2208 brcmf_debugfs_fws_stats_read);
2111 2209
2112 brcmf_dbg(INFO, "%s bdcv2 tlv signaling [%x]\n", 2210 brcmf_dbg(INFO, "%s bdcv2 tlv signaling [%x]\n",
2113 fws->fw_signals ? "enabled" : "disabled", tlv); 2211 fws->fw_signals ? "enabled" : "disabled", tlv);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
index 3deab7959a0d..6c5e585ccda9 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
@@ -18,6 +18,8 @@
18#define _BRCM_SDH_H_ 18#define _BRCM_SDH_H_
19 19
20#include <linux/skbuff.h> 20#include <linux/skbuff.h>
21#include <linux/firmware.h>
22#include "firmware.h"
21 23
22#define SDIO_FUNC_0 0 24#define SDIO_FUNC_0 0
23#define SDIO_FUNC_1 1 25#define SDIO_FUNC_1 1
@@ -182,6 +184,8 @@ struct brcmf_sdio_dev {
182 uint max_segment_size; 184 uint max_segment_size;
183 uint txglomsz; 185 uint txglomsz;
184 struct sg_table sgtable; 186 struct sg_table sgtable;
187 char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
188 char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
185}; 189};
186 190
187/* sdio core registers */ 191/* sdio core registers */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index b732a99e402c..dc135915470d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -21,6 +21,7 @@
21#include <linux/vmalloc.h> 21#include <linux/vmalloc.h>
22 22
23#include <brcmu_utils.h> 23#include <brcmu_utils.h>
24#include <brcm_hw_ids.h>
24#include <brcmu_wifi.h> 25#include <brcmu_wifi.h>
25#include <dhd_bus.h> 26#include <dhd_bus.h>
26#include <dhd_dbg.h> 27#include <dhd_dbg.h>
@@ -913,16 +914,16 @@ static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo)
913static bool brcmf_usb_chip_support(int chipid, int chiprev) 914static bool brcmf_usb_chip_support(int chipid, int chiprev)
914{ 915{
915 switch(chipid) { 916 switch(chipid) {
916 case 43143: 917 case BRCM_CC_43143_CHIP_ID:
917 return true; 918 return true;
918 case 43235: 919 case BRCM_CC_43235_CHIP_ID:
919 case 43236: 920 case BRCM_CC_43236_CHIP_ID:
920 case 43238: 921 case BRCM_CC_43238_CHIP_ID:
921 return (chiprev == 3); 922 return (chiprev == 3);
922 case 43242: 923 case BRCM_CC_43242_CHIP_ID:
923 return true; 924 return true;
924 case 43566: 925 case BRCM_CC_43566_CHIP_ID:
925 case 43569: 926 case BRCM_CC_43569_CHIP_ID:
926 return true; 927 return true;
927 default: 928 default:
928 break; 929 break;
@@ -1016,16 +1017,16 @@ static int check_file(const u8 *headers)
1016static const char *brcmf_usb_get_fwname(struct brcmf_usbdev_info *devinfo) 1017static const char *brcmf_usb_get_fwname(struct brcmf_usbdev_info *devinfo)
1017{ 1018{
1018 switch (devinfo->bus_pub.devid) { 1019 switch (devinfo->bus_pub.devid) {
1019 case 43143: 1020 case BRCM_CC_43143_CHIP_ID:
1020 return BRCMF_USB_43143_FW_NAME; 1021 return BRCMF_USB_43143_FW_NAME;
1021 case 43235: 1022 case BRCM_CC_43235_CHIP_ID:
1022 case 43236: 1023 case BRCM_CC_43236_CHIP_ID:
1023 case 43238: 1024 case BRCM_CC_43238_CHIP_ID:
1024 return BRCMF_USB_43236_FW_NAME; 1025 return BRCMF_USB_43236_FW_NAME;
1025 case 43242: 1026 case BRCM_CC_43242_CHIP_ID:
1026 return BRCMF_USB_43242_FW_NAME; 1027 return BRCMF_USB_43242_FW_NAME;
1027 case 43566: 1028 case BRCM_CC_43566_CHIP_ID:
1028 case 43569: 1029 case BRCM_CC_43569_CHIP_ID:
1029 return BRCMF_USB_43569_FW_NAME; 1030 return BRCMF_USB_43569_FW_NAME;
1030 default: 1031 default:
1031 return NULL; 1032 return NULL;
@@ -1366,21 +1367,17 @@ static int brcmf_usb_reset_resume(struct usb_interface *intf)
1366 brcmf_usb_probe_phase2); 1367 brcmf_usb_probe_phase2);
1367} 1368}
1368 1369
1369#define BRCMF_USB_VENDOR_ID_BROADCOM 0x0a5c 1370#define BRCMF_USB_DEVICE(dev_id) \
1370#define BRCMF_USB_DEVICE_ID_43143 0xbd1e 1371 { USB_DEVICE(BRCM_USB_VENDOR_ID_BROADCOM, dev_id) }
1371#define BRCMF_USB_DEVICE_ID_43236 0xbd17
1372#define BRCMF_USB_DEVICE_ID_43242 0xbd1f
1373#define BRCMF_USB_DEVICE_ID_43569 0xbd27
1374#define BRCMF_USB_DEVICE_ID_BCMFW 0x0bdc
1375 1372
1376static struct usb_device_id brcmf_usb_devid_table[] = { 1373static struct usb_device_id brcmf_usb_devid_table[] = {
1377 { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43143) }, 1374 BRCMF_USB_DEVICE(BRCM_USB_43143_DEVICE_ID),
1378 { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43236) }, 1375 BRCMF_USB_DEVICE(BRCM_USB_43236_DEVICE_ID),
1379 { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43242) }, 1376 BRCMF_USB_DEVICE(BRCM_USB_43242_DEVICE_ID),
1380 { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43569) }, 1377 BRCMF_USB_DEVICE(BRCM_USB_43569_DEVICE_ID),
1381 /* special entry for device with firmware loaded and running */ 1378 /* special entry for device with firmware loaded and running */
1382 { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_BCMFW) }, 1379 BRCMF_USB_DEVICE(BRCM_USB_BCMFW_DEVICE_ID),
1383 { } 1380 { /* end: all zeroes */ }
1384}; 1381};
1385 1382
1386MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table); 1383MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index 9682cf213ec4..48078a321716 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -33,6 +33,7 @@
33#include "p2p.h" 33#include "p2p.h"
34#include "btcoex.h" 34#include "btcoex.h"
35#include "wl_cfg80211.h" 35#include "wl_cfg80211.h"
36#include "feature.h"
36#include "fwil.h" 37#include "fwil.h"
37#include "vendor.h" 38#include "vendor.h"
38 39
@@ -102,24 +103,6 @@ static bool check_vif_up(struct brcmf_cfg80211_vif *vif)
102 return true; 103 return true;
103} 104}
104 105
105#define CHAN2G(_channel, _freq, _flags) { \
106 .band = IEEE80211_BAND_2GHZ, \
107 .center_freq = (_freq), \
108 .hw_value = (_channel), \
109 .flags = (_flags), \
110 .max_antenna_gain = 0, \
111 .max_power = 30, \
112}
113
114#define CHAN5G(_channel, _flags) { \
115 .band = IEEE80211_BAND_5GHZ, \
116 .center_freq = 5000 + (5 * (_channel)), \
117 .hw_value = (_channel), \
118 .flags = (_flags), \
119 .max_antenna_gain = 0, \
120 .max_power = 30, \
121}
122
123#define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2) 106#define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
124#define RATETAB_ENT(_rateid, _flags) \ 107#define RATETAB_ENT(_rateid, _flags) \
125 { \ 108 { \
@@ -148,58 +131,17 @@ static struct ieee80211_rate __wl_rates[] = {
148#define wl_g_rates (__wl_rates + 0) 131#define wl_g_rates (__wl_rates + 0)
149#define wl_g_rates_size 12 132#define wl_g_rates_size 12
150 133
151static struct ieee80211_channel __wl_2ghz_channels[] = { 134/* Band templates duplicated per wiphy. The channel info
152 CHAN2G(1, 2412, 0), 135 * is filled in after querying the device.
153 CHAN2G(2, 2417, 0), 136 */
154 CHAN2G(3, 2422, 0), 137static const struct ieee80211_supported_band __wl_band_2ghz = {
155 CHAN2G(4, 2427, 0),
156 CHAN2G(5, 2432, 0),
157 CHAN2G(6, 2437, 0),
158 CHAN2G(7, 2442, 0),
159 CHAN2G(8, 2447, 0),
160 CHAN2G(9, 2452, 0),
161 CHAN2G(10, 2457, 0),
162 CHAN2G(11, 2462, 0),
163 CHAN2G(12, 2467, 0),
164 CHAN2G(13, 2472, 0),
165 CHAN2G(14, 2484, 0),
166};
167
168static struct ieee80211_channel __wl_5ghz_a_channels[] = {
169 CHAN5G(34, 0), CHAN5G(36, 0),
170 CHAN5G(38, 0), CHAN5G(40, 0),
171 CHAN5G(42, 0), CHAN5G(44, 0),
172 CHAN5G(46, 0), CHAN5G(48, 0),
173 CHAN5G(52, 0), CHAN5G(56, 0),
174 CHAN5G(60, 0), CHAN5G(64, 0),
175 CHAN5G(100, 0), CHAN5G(104, 0),
176 CHAN5G(108, 0), CHAN5G(112, 0),
177 CHAN5G(116, 0), CHAN5G(120, 0),
178 CHAN5G(124, 0), CHAN5G(128, 0),
179 CHAN5G(132, 0), CHAN5G(136, 0),
180 CHAN5G(140, 0), CHAN5G(149, 0),
181 CHAN5G(153, 0), CHAN5G(157, 0),
182 CHAN5G(161, 0), CHAN5G(165, 0),
183 CHAN5G(184, 0), CHAN5G(188, 0),
184 CHAN5G(192, 0), CHAN5G(196, 0),
185 CHAN5G(200, 0), CHAN5G(204, 0),
186 CHAN5G(208, 0), CHAN5G(212, 0),
187 CHAN5G(216, 0),
188};
189
190static struct ieee80211_supported_band __wl_band_2ghz = {
191 .band = IEEE80211_BAND_2GHZ, 138 .band = IEEE80211_BAND_2GHZ,
192 .channels = __wl_2ghz_channels,
193 .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
194 .bitrates = wl_g_rates, 139 .bitrates = wl_g_rates,
195 .n_bitrates = wl_g_rates_size, 140 .n_bitrates = wl_g_rates_size,
196 .ht_cap = {IEEE80211_HT_CAP_SUP_WIDTH_20_40, true},
197}; 141};
198 142
199static struct ieee80211_supported_band __wl_band_5ghz_a = { 143static const struct ieee80211_supported_band __wl_band_5ghz_a = {
200 .band = IEEE80211_BAND_5GHZ, 144 .band = IEEE80211_BAND_5GHZ,
201 .channels = __wl_5ghz_a_channels,
202 .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
203 .bitrates = wl_a_rates, 145 .bitrates = wl_a_rates,
204 .n_bitrates = wl_a_rates_size, 146 .n_bitrates = wl_a_rates_size,
205}; 147};
@@ -592,7 +534,7 @@ static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy,
592 534
593static void brcmf_scan_config_mpc(struct brcmf_if *ifp, int mpc) 535static void brcmf_scan_config_mpc(struct brcmf_if *ifp, int mpc)
594{ 536{
595 if ((brcmf_get_chip_info(ifp) >> 4) == 0x4329) 537 if (brcmf_feat_is_quirk_enabled(ifp, BRCMF_FEAT_QUIRK_NEED_MPC))
596 brcmf_set_mpc(ifp, mpc); 538 brcmf_set_mpc(ifp, mpc);
597} 539}
598 540
@@ -1619,17 +1561,10 @@ static
1619enum nl80211_auth_type brcmf_war_auth_type(struct brcmf_if *ifp, 1561enum nl80211_auth_type brcmf_war_auth_type(struct brcmf_if *ifp,
1620 enum nl80211_auth_type type) 1562 enum nl80211_auth_type type)
1621{ 1563{
1622 u32 ci; 1564 if (type == NL80211_AUTHTYPE_AUTOMATIC &&
1623 if (type == NL80211_AUTHTYPE_AUTOMATIC) { 1565 brcmf_feat_is_quirk_enabled(ifp, BRCMF_FEAT_QUIRK_AUTO_AUTH)) {
1624 /* shift to ignore chip revision */ 1566 brcmf_dbg(CONN, "WAR: use OPEN instead of AUTO\n");
1625 ci = brcmf_get_chip_info(ifp) >> 4; 1567 type = NL80211_AUTHTYPE_OPEN_SYSTEM;
1626 switch (ci) {
1627 case 43236:
1628 brcmf_dbg(CONN, "43236 WAR: use OPEN instead of AUTO\n");
1629 return NL80211_AUTHTYPE_OPEN_SYSTEM;
1630 default:
1631 break;
1632 }
1633 } 1568 }
1634 return type; 1569 return type;
1635} 1570}
@@ -4284,122 +4219,6 @@ static struct cfg80211_ops wl_cfg80211_ops = {
4284 .tdls_oper = brcmf_cfg80211_tdls_oper, 4219 .tdls_oper = brcmf_cfg80211_tdls_oper,
4285}; 4220};
4286 4221
4287static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
4288{
4289 /* scheduled scan settings */
4290 wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
4291 wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
4292 wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
4293 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
4294}
4295
4296static const struct ieee80211_iface_limit brcmf_iface_limits[] = {
4297 {
4298 .max = 2,
4299 .types = BIT(NL80211_IFTYPE_STATION) |
4300 BIT(NL80211_IFTYPE_ADHOC) |
4301 BIT(NL80211_IFTYPE_AP)
4302 },
4303 {
4304 .max = 1,
4305 .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
4306 BIT(NL80211_IFTYPE_P2P_GO)
4307 },
4308 {
4309 .max = 1,
4310 .types = BIT(NL80211_IFTYPE_P2P_DEVICE)
4311 }
4312};
4313static const struct ieee80211_iface_combination brcmf_iface_combos[] = {
4314 {
4315 .max_interfaces = BRCMF_IFACE_MAX_CNT,
4316 .num_different_channels = 2,
4317 .n_limits = ARRAY_SIZE(brcmf_iface_limits),
4318 .limits = brcmf_iface_limits
4319 }
4320};
4321
4322static const struct ieee80211_txrx_stypes
4323brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
4324 [NL80211_IFTYPE_STATION] = {
4325 .tx = 0xffff,
4326 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
4327 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
4328 },
4329 [NL80211_IFTYPE_P2P_CLIENT] = {
4330 .tx = 0xffff,
4331 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
4332 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
4333 },
4334 [NL80211_IFTYPE_P2P_GO] = {
4335 .tx = 0xffff,
4336 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
4337 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
4338 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
4339 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
4340 BIT(IEEE80211_STYPE_AUTH >> 4) |
4341 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
4342 BIT(IEEE80211_STYPE_ACTION >> 4)
4343 },
4344 [NL80211_IFTYPE_P2P_DEVICE] = {
4345 .tx = 0xffff,
4346 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
4347 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
4348 }
4349};
4350
4351static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
4352{
4353 struct wiphy *wiphy;
4354 s32 err = 0;
4355
4356 wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info));
4357 if (!wiphy) {
4358 brcmf_err("Could not allocate wiphy device\n");
4359 return ERR_PTR(-ENOMEM);
4360 }
4361 set_wiphy_dev(wiphy, phydev);
4362 wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
4363 wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
4364 wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
4365 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
4366 BIT(NL80211_IFTYPE_ADHOC) |
4367 BIT(NL80211_IFTYPE_AP) |
4368 BIT(NL80211_IFTYPE_P2P_CLIENT) |
4369 BIT(NL80211_IFTYPE_P2P_GO) |
4370 BIT(NL80211_IFTYPE_P2P_DEVICE);
4371 wiphy->iface_combinations = brcmf_iface_combos;
4372 wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
4373 wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
4374 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
4375 wiphy->cipher_suites = __wl_cipher_suites;
4376 wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
4377 wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT |
4378 WIPHY_FLAG_OFFCHAN_TX |
4379 WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
4380 WIPHY_FLAG_SUPPORTS_TDLS;
4381 if (!brcmf_roamoff)
4382 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
4383 wiphy->mgmt_stypes = brcmf_txrx_stypes;
4384 wiphy->max_remain_on_channel_duration = 5000;
4385 brcmf_wiphy_pno_params(wiphy);
4386 brcmf_dbg(INFO, "Registering custom regulatory\n");
4387 wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
4388 wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
4389
4390 /* vendor commands/events support */
4391 wiphy->vendor_commands = brcmf_vendor_cmds;
4392 wiphy->n_vendor_commands = BRCMF_VNDR_CMDS_LAST - 1;
4393
4394 err = wiphy_register(wiphy);
4395 if (err < 0) {
4396 brcmf_err("Could not register wiphy device (%d)\n", err);
4397 wiphy_free(wiphy);
4398 return ERR_PTR(err);
4399 }
4400 return wiphy;
4401}
4402
4403struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, 4222struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
4404 enum nl80211_iftype type, 4223 enum nl80211_iftype type,
4405 bool pm_block) 4224 bool pm_block)
@@ -4943,138 +4762,6 @@ static void init_vif_event(struct brcmf_cfg80211_vif_event *event)
4943 mutex_init(&event->vif_event_lock); 4762 mutex_init(&event->vif_event_lock);
4944} 4763}
4945 4764
4946static int brcmf_enable_bw40_2g(struct brcmf_if *ifp)
4947{
4948 struct brcmf_fil_bwcap_le band_bwcap;
4949 u32 val;
4950 int err;
4951
4952 /* verify support for bw_cap command */
4953 val = WLC_BAND_5G;
4954 err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &val);
4955
4956 if (!err) {
4957 /* only set 2G bandwidth using bw_cap command */
4958 band_bwcap.band = cpu_to_le32(WLC_BAND_2G);
4959 band_bwcap.bw_cap = cpu_to_le32(WLC_BW_CAP_40MHZ);
4960 err = brcmf_fil_iovar_data_set(ifp, "bw_cap", &band_bwcap,
4961 sizeof(band_bwcap));
4962 } else {
4963 brcmf_dbg(INFO, "fallback to mimo_bw_cap\n");
4964 val = WLC_N_BW_40ALL;
4965 err = brcmf_fil_iovar_int_set(ifp, "mimo_bw_cap", val);
4966 }
4967 return err;
4968}
4969
4970struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
4971 struct device *busdev)
4972{
4973 struct net_device *ndev = drvr->iflist[0]->ndev;
4974 struct brcmf_cfg80211_info *cfg;
4975 struct wiphy *wiphy;
4976 struct brcmf_cfg80211_vif *vif;
4977 struct brcmf_if *ifp;
4978 s32 err = 0;
4979 s32 io_type;
4980
4981 if (!ndev) {
4982 brcmf_err("ndev is invalid\n");
4983 return NULL;
4984 }
4985
4986 ifp = netdev_priv(ndev);
4987 wiphy = brcmf_setup_wiphy(busdev);
4988 if (IS_ERR(wiphy))
4989 return NULL;
4990
4991 cfg = wiphy_priv(wiphy);
4992 cfg->wiphy = wiphy;
4993 cfg->pub = drvr;
4994 init_vif_event(&cfg->vif_event);
4995 INIT_LIST_HEAD(&cfg->vif_list);
4996
4997 vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_STATION, false);
4998 if (IS_ERR(vif)) {
4999 wiphy_free(wiphy);
5000 return NULL;
5001 }
5002
5003 vif->ifp = ifp;
5004 vif->wdev.netdev = ndev;
5005 ndev->ieee80211_ptr = &vif->wdev;
5006 SET_NETDEV_DEV(ndev, wiphy_dev(cfg->wiphy));
5007
5008 err = wl_init_priv(cfg);
5009 if (err) {
5010 brcmf_err("Failed to init iwm_priv (%d)\n", err);
5011 goto cfg80211_attach_out;
5012 }
5013 ifp->vif = vif;
5014
5015 err = brcmf_p2p_attach(cfg);
5016 if (err) {
5017 brcmf_err("P2P initilisation failed (%d)\n", err);
5018 goto cfg80211_p2p_attach_out;
5019 }
5020 err = brcmf_btcoex_attach(cfg);
5021 if (err) {
5022 brcmf_err("BT-coex initialisation failed (%d)\n", err);
5023 brcmf_p2p_detach(&cfg->p2p);
5024 goto cfg80211_p2p_attach_out;
5025 }
5026
5027 /* If cfg80211 didn't disable 40MHz HT CAP in wiphy_register(),
5028 * setup 40MHz in 2GHz band and enable OBSS scanning.
5029 */
5030 if (wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.cap &
5031 IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
5032 err = brcmf_enable_bw40_2g(ifp);
5033 if (!err)
5034 err = brcmf_fil_iovar_int_set(ifp, "obss_coex",
5035 BRCMF_OBSS_COEX_AUTO);
5036 }
5037 /* clear for now and rely on update later */
5038 wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.ht_supported = false;
5039 wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.cap = 0;
5040
5041 err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1);
5042 if (err) {
5043 brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err);
5044 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS;
5045 }
5046
5047 err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION,
5048 &io_type);
5049 if (err) {
5050 brcmf_err("Failed to get D11 version (%d)\n", err);
5051 goto cfg80211_p2p_attach_out;
5052 }
5053 cfg->d11inf.io_type = (u8)io_type;
5054 brcmu_d11_attach(&cfg->d11inf);
5055
5056 return cfg;
5057
5058cfg80211_p2p_attach_out:
5059 wl_deinit_priv(cfg);
5060
5061cfg80211_attach_out:
5062 brcmf_free_vif(vif);
5063 return NULL;
5064}
5065
5066void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
5067{
5068 if (!cfg)
5069 return;
5070
5071 WARN_ON(!list_empty(&cfg->vif_list));
5072 wiphy_unregister(cfg->wiphy);
5073 brcmf_btcoex_detach(cfg);
5074 wl_deinit_priv(cfg);
5075 wiphy_free(cfg->wiphy);
5076}
5077
5078static s32 4765static s32
5079brcmf_dongle_roam(struct brcmf_if *ifp, u32 bcn_timeout) 4766brcmf_dongle_roam(struct brcmf_if *ifp, u32 bcn_timeout)
5080{ 4767{
@@ -5167,25 +4854,77 @@ dongle_scantime_out:
5167 return err; 4854 return err;
5168} 4855}
5169 4856
4857/* Filter the list of channels received from firmware counting only
4858 * the 20MHz channels. The wiphy band data only needs those which get
4859 * flagged to indicate if they can take part in higher bandwidth.
4860 */
4861static void brcmf_count_20mhz_channels(struct brcmf_cfg80211_info *cfg,
4862 struct brcmf_chanspec_list *chlist,
4863 u32 chcnt[])
4864{
4865 u32 total = le32_to_cpu(chlist->count);
4866 struct brcmu_chan ch;
4867 int i;
4868
4869 for (i = 0; i <= total; i++) {
4870 ch.chspec = (u16)le32_to_cpu(chlist->element[i]);
4871 cfg->d11inf.decchspec(&ch);
4872
4873 /* Firmware gives a ordered list. We skip non-20MHz
4874 * channels is 2G. For 5G we can abort upon reaching
4875 * a non-20MHz channel in the list.
4876 */
4877 if (ch.bw != BRCMU_CHAN_BW_20) {
4878 if (ch.band == BRCMU_CHAN_BAND_5G)
4879 break;
4880 else
4881 continue;
4882 }
4883
4884 if (ch.band == BRCMU_CHAN_BAND_2G)
4885 chcnt[0] += 1;
4886 else if (ch.band == BRCMU_CHAN_BAND_5G)
4887 chcnt[1] += 1;
4888 }
4889}
4890
4891static void brcmf_update_bw40_channel_flag(struct ieee80211_channel *channel,
4892 struct brcmu_chan *ch)
4893{
4894 u32 ht40_flag;
5170 4895
5171static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, 4896 ht40_flag = channel->flags & IEEE80211_CHAN_NO_HT40;
5172 u32 bw_cap[]) 4897 if (ch->sb == BRCMU_CHAN_SB_U) {
4898 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
4899 channel->flags &= ~IEEE80211_CHAN_NO_HT40;
4900 channel->flags |= IEEE80211_CHAN_NO_HT40PLUS;
4901 } else {
4902 /* It should be one of
4903 * IEEE80211_CHAN_NO_HT40 or
4904 * IEEE80211_CHAN_NO_HT40PLUS
4905 */
4906 channel->flags &= ~IEEE80211_CHAN_NO_HT40;
4907 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
4908 channel->flags |= IEEE80211_CHAN_NO_HT40MINUS;
4909 }
4910}
4911
4912static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
4913 u32 bw_cap[])
5173{ 4914{
5174 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); 4915 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
5175 struct ieee80211_channel *band_chan_arr; 4916 struct ieee80211_supported_band *band;
4917 struct ieee80211_channel *channel;
4918 struct wiphy *wiphy;
5176 struct brcmf_chanspec_list *list; 4919 struct brcmf_chanspec_list *list;
5177 struct brcmu_chan ch; 4920 struct brcmu_chan ch;
5178 s32 err; 4921 int err;
5179 u8 *pbuf; 4922 u8 *pbuf;
5180 u32 i, j; 4923 u32 i, j;
5181 u32 total; 4924 u32 total;
5182 enum ieee80211_band band; 4925 u32 chaninfo;
5183 u32 channel; 4926 u32 chcnt[2] = { 0, 0 };
5184 u32 *n_cnt;
5185 u32 index; 4927 u32 index;
5186 u32 ht40_flag;
5187 bool update;
5188 u32 array_size;
5189 4928
5190 pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL); 4929 pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
5191 4930
@@ -5198,11 +4937,45 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg,
5198 BRCMF_DCMD_MEDLEN); 4937 BRCMF_DCMD_MEDLEN);
5199 if (err) { 4938 if (err) {
5200 brcmf_err("get chanspecs error (%d)\n", err); 4939 brcmf_err("get chanspecs error (%d)\n", err);
5201 goto exit; 4940 goto fail_pbuf;
5202 } 4941 }
5203 4942
5204 __wl_band_2ghz.n_channels = 0; 4943 brcmf_count_20mhz_channels(cfg, list, chcnt);
5205 __wl_band_5ghz_a.n_channels = 0; 4944 wiphy = cfg_to_wiphy(cfg);
4945 if (chcnt[0]) {
4946 band = kmemdup(&__wl_band_2ghz, sizeof(__wl_band_2ghz),
4947 GFP_KERNEL);
4948 if (band == NULL) {
4949 err = -ENOMEM;
4950 goto fail_pbuf;
4951 }
4952 band->channels = kcalloc(chcnt[0], sizeof(*channel),
4953 GFP_KERNEL);
4954 if (band->channels == NULL) {
4955 kfree(band);
4956 err = -ENOMEM;
4957 goto fail_pbuf;
4958 }
4959 band->n_channels = 0;
4960 wiphy->bands[IEEE80211_BAND_2GHZ] = band;
4961 }
4962 if (chcnt[1]) {
4963 band = kmemdup(&__wl_band_5ghz_a, sizeof(__wl_band_5ghz_a),
4964 GFP_KERNEL);
4965 if (band == NULL) {
4966 err = -ENOMEM;
4967 goto fail_band2g;
4968 }
4969 band->channels = kcalloc(chcnt[1], sizeof(*channel),
4970 GFP_KERNEL);
4971 if (band->channels == NULL) {
4972 kfree(band);
4973 err = -ENOMEM;
4974 goto fail_band2g;
4975 }
4976 band->n_channels = 0;
4977 wiphy->bands[IEEE80211_BAND_5GHZ] = band;
4978 }
5206 4979
5207 total = le32_to_cpu(list->count); 4980 total = le32_to_cpu(list->count);
5208 for (i = 0; i < total; i++) { 4981 for (i = 0; i < total; i++) {
@@ -5210,100 +4983,151 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg,
5210 cfg->d11inf.decchspec(&ch); 4983 cfg->d11inf.decchspec(&ch);
5211 4984
5212 if (ch.band == BRCMU_CHAN_BAND_2G) { 4985 if (ch.band == BRCMU_CHAN_BAND_2G) {
5213 band_chan_arr = __wl_2ghz_channels; 4986 band = wiphy->bands[IEEE80211_BAND_2GHZ];
5214 array_size = ARRAY_SIZE(__wl_2ghz_channels);
5215 n_cnt = &__wl_band_2ghz.n_channels;
5216 band = IEEE80211_BAND_2GHZ;
5217 } else if (ch.band == BRCMU_CHAN_BAND_5G) { 4987 } else if (ch.band == BRCMU_CHAN_BAND_5G) {
5218 band_chan_arr = __wl_5ghz_a_channels; 4988 band = wiphy->bands[IEEE80211_BAND_5GHZ];
5219 array_size = ARRAY_SIZE(__wl_5ghz_a_channels);
5220 n_cnt = &__wl_band_5ghz_a.n_channels;
5221 band = IEEE80211_BAND_5GHZ;
5222 } else { 4989 } else {
5223 brcmf_err("Invalid channel Spec. 0x%x.\n", ch.chspec); 4990 brcmf_err("Invalid channel Spec. 0x%x.\n", ch.chspec);
5224 continue; 4991 continue;
5225 } 4992 }
5226 if (!(bw_cap[band] & WLC_BW_40MHZ_BIT) && 4993 if (!(bw_cap[band->band] & WLC_BW_40MHZ_BIT) &&
5227 ch.bw == BRCMU_CHAN_BW_40) 4994 ch.bw == BRCMU_CHAN_BW_40)
5228 continue; 4995 continue;
5229 if (!(bw_cap[band] & WLC_BW_80MHZ_BIT) && 4996 if (!(bw_cap[band->band] & WLC_BW_80MHZ_BIT) &&
5230 ch.bw == BRCMU_CHAN_BW_80) 4997 ch.bw == BRCMU_CHAN_BW_80)
5231 continue; 4998 continue;
5232 update = false; 4999
5233 for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) { 5000 channel = band->channels;
5234 if (band_chan_arr[j].hw_value == ch.chnum) { 5001 index = band->n_channels;
5235 update = true; 5002 for (j = 0; j < band->n_channels; j++) {
5003 if (channel[j].hw_value == ch.chnum) {
5004 index = j;
5236 break; 5005 break;
5237 } 5006 }
5238 } 5007 }
5239 if (update) 5008 channel[index].center_freq =
5240 index = j; 5009 ieee80211_channel_to_frequency(ch.chnum, band->band);
5241 else 5010 channel[index].hw_value = ch.chnum;
5242 index = *n_cnt; 5011
5243 if (index < array_size) { 5012 /* assuming the chanspecs order is HT20,
5244 band_chan_arr[index].center_freq = 5013 * HT40 upper, HT40 lower, and VHT80.
5245 ieee80211_channel_to_frequency(ch.chnum, band); 5014 */
5246 band_chan_arr[index].hw_value = ch.chnum; 5015 if (ch.bw == BRCMU_CHAN_BW_80) {
5247 5016 channel[index].flags &= ~IEEE80211_CHAN_NO_80MHZ;
5248 /* assuming the chanspecs order is HT20, 5017 } else if (ch.bw == BRCMU_CHAN_BW_40) {
5249 * HT40 upper, HT40 lower, and VHT80. 5018 brcmf_update_bw40_channel_flag(&channel[index], &ch);
5019 } else {
5020 /* disable other bandwidths for now as mentioned
5021 * order assure they are enabled for subsequent
5022 * chanspecs.
5250 */ 5023 */
5251 if (ch.bw == BRCMU_CHAN_BW_80) { 5024 channel[index].flags = IEEE80211_CHAN_NO_HT40 |
5252 band_chan_arr[index].flags &= 5025 IEEE80211_CHAN_NO_80MHZ;
5253 ~IEEE80211_CHAN_NO_80MHZ; 5026 ch.bw = BRCMU_CHAN_BW_20;
5254 } else if (ch.bw == BRCMU_CHAN_BW_40) { 5027 cfg->d11inf.encchspec(&ch);
5255 ht40_flag = band_chan_arr[index].flags & 5028 chaninfo = ch.chspec;
5256 IEEE80211_CHAN_NO_HT40; 5029 err = brcmf_fil_bsscfg_int_get(ifp, "per_chan_info",
5257 if (ch.sb == BRCMU_CHAN_SB_U) { 5030 &chaninfo);
5258 if (ht40_flag == IEEE80211_CHAN_NO_HT40) 5031 if (!err) {
5259 band_chan_arr[index].flags &= 5032 if (chaninfo & WL_CHAN_RADAR)
5260 ~IEEE80211_CHAN_NO_HT40; 5033 channel[index].flags |=
5261 band_chan_arr[index].flags |= 5034 (IEEE80211_CHAN_RADAR |
5262 IEEE80211_CHAN_NO_HT40PLUS; 5035 IEEE80211_CHAN_NO_IR);
5263 } else { 5036 if (chaninfo & WL_CHAN_PASSIVE)
5264 /* It should be one of 5037 channel[index].flags |=
5265 * IEEE80211_CHAN_NO_HT40 or 5038 IEEE80211_CHAN_NO_IR;
5266 * IEEE80211_CHAN_NO_HT40PLUS
5267 */
5268 band_chan_arr[index].flags &=
5269 ~IEEE80211_CHAN_NO_HT40;
5270 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
5271 band_chan_arr[index].flags |=
5272 IEEE80211_CHAN_NO_HT40MINUS;
5273 }
5274 } else {
5275 /* disable other bandwidths for now as mentioned
5276 * order assure they are enabled for subsequent
5277 * chanspecs.
5278 */
5279 band_chan_arr[index].flags =
5280 IEEE80211_CHAN_NO_HT40 |
5281 IEEE80211_CHAN_NO_80MHZ;
5282 ch.bw = BRCMU_CHAN_BW_20;
5283 cfg->d11inf.encchspec(&ch);
5284 channel = ch.chspec;
5285 err = brcmf_fil_bsscfg_int_get(ifp,
5286 "per_chan_info",
5287 &channel);
5288 if (!err) {
5289 if (channel & WL_CHAN_RADAR)
5290 band_chan_arr[index].flags |=
5291 (IEEE80211_CHAN_RADAR |
5292 IEEE80211_CHAN_NO_IR);
5293 if (channel & WL_CHAN_PASSIVE)
5294 band_chan_arr[index].flags |=
5295 IEEE80211_CHAN_NO_IR;
5296 }
5297 } 5039 }
5298 if (!update)
5299 (*n_cnt)++;
5300 } 5040 }
5041 if (index == band->n_channels)
5042 band->n_channels++;
5301 } 5043 }
5302exit: 5044 kfree(pbuf);
5045 return 0;
5046
5047fail_band2g:
5048 kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
5049 kfree(wiphy->bands[IEEE80211_BAND_2GHZ]);
5050 wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
5051fail_pbuf:
5303 kfree(pbuf); 5052 kfree(pbuf);
5304 return err; 5053 return err;
5305} 5054}
5306 5055
5056static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg)
5057{
5058 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
5059 struct ieee80211_supported_band *band;
5060 struct brcmf_fil_bwcap_le band_bwcap;
5061 struct brcmf_chanspec_list *list;
5062 u8 *pbuf;
5063 u32 val;
5064 int err;
5065 struct brcmu_chan ch;
5066 u32 num_chan;
5067 int i, j;
5068
5069 /* verify support for bw_cap command */
5070 val = WLC_BAND_5G;
5071 err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &val);
5072
5073 if (!err) {
5074 /* only set 2G bandwidth using bw_cap command */
5075 band_bwcap.band = cpu_to_le32(WLC_BAND_2G);
5076 band_bwcap.bw_cap = cpu_to_le32(WLC_BW_CAP_40MHZ);
5077 err = brcmf_fil_iovar_data_set(ifp, "bw_cap", &band_bwcap,
5078 sizeof(band_bwcap));
5079 } else {
5080 brcmf_dbg(INFO, "fallback to mimo_bw_cap\n");
5081 val = WLC_N_BW_40ALL;
5082 err = brcmf_fil_iovar_int_set(ifp, "mimo_bw_cap", val);
5083 }
5084
5085 if (!err) {
5086 /* update channel info in 2G band */
5087 pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
5088
5089 if (pbuf == NULL)
5090 return -ENOMEM;
5091
5092 ch.band = BRCMU_CHAN_BAND_2G;
5093 ch.bw = BRCMU_CHAN_BW_40;
5094 ch.chnum = 0;
5095 cfg->d11inf.encchspec(&ch);
5096
5097 /* pass encoded chanspec in query */
5098 *(__le16 *)pbuf = cpu_to_le16(ch.chspec);
5099
5100 err = brcmf_fil_iovar_data_get(ifp, "chanspecs", pbuf,
5101 BRCMF_DCMD_MEDLEN);
5102 if (err) {
5103 brcmf_err("get chanspecs error (%d)\n", err);
5104 kfree(pbuf);
5105 return err;
5106 }
5107
5108 band = cfg_to_wiphy(cfg)->bands[IEEE80211_BAND_2GHZ];
5109 list = (struct brcmf_chanspec_list *)pbuf;
5110 num_chan = le32_to_cpu(list->count);
5111 for (i = 0; i < num_chan; i++) {
5112 ch.chspec = (u16)le32_to_cpu(list->element[i]);
5113 cfg->d11inf.decchspec(&ch);
5114 if (WARN_ON(ch.band != BRCMU_CHAN_BAND_2G))
5115 continue;
5116 if (WARN_ON(ch.bw != BRCMU_CHAN_BW_40))
5117 continue;
5118 for (j = 0; j < band->n_channels; j++) {
5119 if (band->channels[j].hw_value == ch.chnum)
5120 break;
5121 }
5122 if (WARN_ON(j == band->n_channels))
5123 continue;
5124
5125 brcmf_update_bw40_channel_flag(&band->channels[j], &ch);
5126 }
5127 }
5128 return err;
5129}
5130
5307static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[]) 5131static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[])
5308{ 5132{
5309 u32 band, mimo_bwcap; 5133 u32 band, mimo_bwcap;
@@ -5394,44 +5218,19 @@ static void brcmf_update_vht_cap(struct ieee80211_supported_band *band,
5394 band->vht_cap.vht_mcs.tx_mcs_map = mcs_map; 5218 band->vht_cap.vht_mcs.tx_mcs_map = mcs_map;
5395} 5219}
5396 5220
5397static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg) 5221static int brcmf_setup_wiphybands(struct wiphy *wiphy)
5398{ 5222{
5223 struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
5399 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); 5224 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
5400 struct wiphy *wiphy;
5401 s32 phy_list;
5402 u32 band_list[3];
5403 u32 nmode = 0; 5225 u32 nmode = 0;
5404 u32 vhtmode = 0; 5226 u32 vhtmode = 0;
5405 u32 bw_cap[2] = { 0, 0 }; 5227 u32 bw_cap[2] = { WLC_BW_20MHZ_BIT, WLC_BW_20MHZ_BIT };
5406 u32 rxchain; 5228 u32 rxchain;
5407 u32 nchain; 5229 u32 nchain;
5408 s8 phy; 5230 int err;
5409 s32 err;
5410 u32 nband;
5411 s32 i; 5231 s32 i;
5412 struct ieee80211_supported_band *bands[2] = { NULL, NULL };
5413 struct ieee80211_supported_band *band; 5232 struct ieee80211_supported_band *band;
5414 5233
5415 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_PHYLIST,
5416 &phy_list, sizeof(phy_list));
5417 if (err) {
5418 brcmf_err("BRCMF_C_GET_PHYLIST error (%d)\n", err);
5419 return err;
5420 }
5421
5422 phy = ((char *)&phy_list)[0];
5423 brcmf_dbg(INFO, "BRCMF_C_GET_PHYLIST reported: %c phy\n", phy);
5424
5425
5426 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BANDLIST,
5427 &band_list, sizeof(band_list));
5428 if (err) {
5429 brcmf_err("BRCMF_C_GET_BANDLIST error (%d)\n", err);
5430 return err;
5431 }
5432 brcmf_dbg(INFO, "BRCMF_C_GET_BANDLIST reported: 0x%08x 0x%08x 0x%08x phy\n",
5433 band_list[0], band_list[1], band_list[2]);
5434
5435 (void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode); 5234 (void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode);
5436 err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode); 5235 err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode);
5437 if (err) { 5236 if (err) {
@@ -5453,44 +5252,129 @@ static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg)
5453 } 5252 }
5454 brcmf_dbg(INFO, "nchain=%d\n", nchain); 5253 brcmf_dbg(INFO, "nchain=%d\n", nchain);
5455 5254
5456 err = brcmf_construct_reginfo(cfg, bw_cap); 5255 err = brcmf_construct_chaninfo(cfg, bw_cap);
5457 if (err) { 5256 if (err) {
5458 brcmf_err("brcmf_construct_reginfo failed (%d)\n", err); 5257 brcmf_err("brcmf_construct_chaninfo failed (%d)\n", err);
5459 return err; 5258 return err;
5460 } 5259 }
5461 5260
5462 nband = band_list[0]; 5261 wiphy = cfg_to_wiphy(cfg);
5463 5262 for (i = 0; i < ARRAY_SIZE(wiphy->bands); i++) {
5464 for (i = 1; i <= nband && i < ARRAY_SIZE(band_list); i++) { 5263 band = wiphy->bands[i];
5465 band = NULL; 5264 if (band == NULL)
5466 if ((band_list[i] == WLC_BAND_5G) &&
5467 (__wl_band_5ghz_a.n_channels > 0))
5468 band = &__wl_band_5ghz_a;
5469 else if ((band_list[i] == WLC_BAND_2G) &&
5470 (__wl_band_2ghz.n_channels > 0))
5471 band = &__wl_band_2ghz;
5472 else
5473 continue; 5265 continue;
5474 5266
5475 if (nmode) 5267 if (nmode)
5476 brcmf_update_ht_cap(band, bw_cap, nchain); 5268 brcmf_update_ht_cap(band, bw_cap, nchain);
5477 if (vhtmode) 5269 if (vhtmode)
5478 brcmf_update_vht_cap(band, bw_cap, nchain); 5270 brcmf_update_vht_cap(band, bw_cap, nchain);
5479 bands[band->band] = band;
5480 } 5271 }
5481 5272
5482 wiphy = cfg_to_wiphy(cfg); 5273 return 0;
5483 wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ];
5484 wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ];
5485 wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
5486
5487 return err;
5488} 5274}
5489 5275
5276static const struct ieee80211_iface_limit brcmf_iface_limits[] = {
5277 {
5278 .max = 2,
5279 .types = BIT(NL80211_IFTYPE_STATION) |
5280 BIT(NL80211_IFTYPE_ADHOC) |
5281 BIT(NL80211_IFTYPE_AP)
5282 },
5283 {
5284 .max = 1,
5285 .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
5286 BIT(NL80211_IFTYPE_P2P_GO)
5287 },
5288 {
5289 .max = 1,
5290 .types = BIT(NL80211_IFTYPE_P2P_DEVICE)
5291 }
5292};
5293static struct ieee80211_iface_combination brcmf_iface_combos[] = {
5294 {
5295 .max_interfaces = BRCMF_IFACE_MAX_CNT,
5296 .num_different_channels = 1,
5297 .n_limits = ARRAY_SIZE(brcmf_iface_limits),
5298 .limits = brcmf_iface_limits
5299 }
5300};
5301
5302static const struct ieee80211_txrx_stypes
5303brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
5304 [NL80211_IFTYPE_STATION] = {
5305 .tx = 0xffff,
5306 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
5307 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
5308 },
5309 [NL80211_IFTYPE_P2P_CLIENT] = {
5310 .tx = 0xffff,
5311 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
5312 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
5313 },
5314 [NL80211_IFTYPE_P2P_GO] = {
5315 .tx = 0xffff,
5316 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
5317 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
5318 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
5319 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
5320 BIT(IEEE80211_STYPE_AUTH >> 4) |
5321 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
5322 BIT(IEEE80211_STYPE_ACTION >> 4)
5323 },
5324 [NL80211_IFTYPE_P2P_DEVICE] = {
5325 .tx = 0xffff,
5326 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
5327 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
5328 }
5329};
5490 5330
5491static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_info *cfg) 5331static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
5492{ 5332{
5493 return brcmf_update_wiphybands(cfg); 5333 /* scheduled scan settings */
5334 wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
5335 wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
5336 wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
5337 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
5338}
5339
5340static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
5341{
5342 struct ieee80211_iface_combination ifc_combo;
5343 wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
5344 wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
5345 wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
5346 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
5347 BIT(NL80211_IFTYPE_ADHOC) |
5348 BIT(NL80211_IFTYPE_AP) |
5349 BIT(NL80211_IFTYPE_P2P_CLIENT) |
5350 BIT(NL80211_IFTYPE_P2P_GO) |
5351 BIT(NL80211_IFTYPE_P2P_DEVICE);
5352 /* need VSDB firmware feature for concurrent channels */
5353 ifc_combo = brcmf_iface_combos[0];
5354 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
5355 ifc_combo.num_different_channels = 2;
5356 wiphy->iface_combinations = kmemdup(&ifc_combo,
5357 sizeof(ifc_combo),
5358 GFP_KERNEL);
5359 wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
5360 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
5361 wiphy->cipher_suites = __wl_cipher_suites;
5362 wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
5363 wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT |
5364 WIPHY_FLAG_OFFCHAN_TX |
5365 WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
5366 WIPHY_FLAG_SUPPORTS_TDLS;
5367 if (!brcmf_roamoff)
5368 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
5369 wiphy->mgmt_stypes = brcmf_txrx_stypes;
5370 wiphy->max_remain_on_channel_duration = 5000;
5371 brcmf_wiphy_pno_params(wiphy);
5372
5373 /* vendor commands/events support */
5374 wiphy->vendor_commands = brcmf_vendor_cmds;
5375 wiphy->n_vendor_commands = BRCMF_VNDR_CMDS_LAST - 1;
5376
5377 return brcmf_setup_wiphybands(wiphy);
5494} 5378}
5495 5379
5496static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) 5380static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
@@ -5528,9 +5412,6 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
5528 NULL, NULL); 5412 NULL, NULL);
5529 if (err) 5413 if (err)
5530 goto default_conf_out; 5414 goto default_conf_out;
5531 err = brcmf_dongle_probecap(cfg);
5532 if (err)
5533 goto default_conf_out;
5534 5415
5535 brcmf_configure_arp_offload(ifp, true); 5416 brcmf_configure_arp_offload(ifp, true);
5536 5417
@@ -5658,3 +5539,150 @@ int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg,
5658 vif_event_equals(event, action), timeout); 5539 vif_event_equals(event, action), timeout);
5659} 5540}
5660 5541
5542static void brcmf_free_wiphy(struct wiphy *wiphy)
5543{
5544 kfree(wiphy->iface_combinations);
5545 if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
5546 kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
5547 kfree(wiphy->bands[IEEE80211_BAND_2GHZ]);
5548 }
5549 if (wiphy->bands[IEEE80211_BAND_5GHZ]) {
5550 kfree(wiphy->bands[IEEE80211_BAND_5GHZ]->channels);
5551 kfree(wiphy->bands[IEEE80211_BAND_5GHZ]);
5552 }
5553 wiphy_free(wiphy);
5554}
5555
5556struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
5557 struct device *busdev)
5558{
5559 struct net_device *ndev = drvr->iflist[0]->ndev;
5560 struct brcmf_cfg80211_info *cfg;
5561 struct wiphy *wiphy;
5562 struct brcmf_cfg80211_vif *vif;
5563 struct brcmf_if *ifp;
5564 s32 err = 0;
5565 s32 io_type;
5566 u16 *cap = NULL;
5567
5568 if (!ndev) {
5569 brcmf_err("ndev is invalid\n");
5570 return NULL;
5571 }
5572
5573 ifp = netdev_priv(ndev);
5574 wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info));
5575 if (!wiphy) {
5576 brcmf_err("Could not allocate wiphy device\n");
5577 return NULL;
5578 }
5579 set_wiphy_dev(wiphy, busdev);
5580
5581 cfg = wiphy_priv(wiphy);
5582 cfg->wiphy = wiphy;
5583 cfg->pub = drvr;
5584 init_vif_event(&cfg->vif_event);
5585 INIT_LIST_HEAD(&cfg->vif_list);
5586
5587 vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_STATION, false);
5588 if (IS_ERR(vif))
5589 goto wiphy_out;
5590
5591 vif->ifp = ifp;
5592 vif->wdev.netdev = ndev;
5593 ndev->ieee80211_ptr = &vif->wdev;
5594 SET_NETDEV_DEV(ndev, wiphy_dev(cfg->wiphy));
5595
5596 err = wl_init_priv(cfg);
5597 if (err) {
5598 brcmf_err("Failed to init iwm_priv (%d)\n", err);
5599 brcmf_free_vif(vif);
5600 goto wiphy_out;
5601 }
5602 ifp->vif = vif;
5603
5604 /* determine d11 io type before wiphy setup */
5605 err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION, &io_type);
5606 if (err) {
5607 brcmf_err("Failed to get D11 version (%d)\n", err);
5608 goto priv_out;
5609 }
5610 cfg->d11inf.io_type = (u8)io_type;
5611 brcmu_d11_attach(&cfg->d11inf);
5612
5613 err = brcmf_setup_wiphy(wiphy, ifp);
5614 if (err < 0)
5615 goto priv_out;
5616
5617 brcmf_dbg(INFO, "Registering custom regulatory\n");
5618 wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
5619 wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
5620
5621 /* firmware defaults to 40MHz disabled in 2G band. We signal
5622 * cfg80211 here that we do and have it decide we can enable
5623 * it. But first check if device does support 2G operation.
5624 */
5625 if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
5626 cap = &wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.cap;
5627 *cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
5628 }
5629 err = wiphy_register(wiphy);
5630 if (err < 0) {
5631 brcmf_err("Could not register wiphy device (%d)\n", err);
5632 goto priv_out;
5633 }
5634
5635 /* If cfg80211 didn't disable 40MHz HT CAP in wiphy_register(),
5636 * setup 40MHz in 2GHz band and enable OBSS scanning.
5637 */
5638 if (cap && (*cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) {
5639 err = brcmf_enable_bw40_2g(cfg);
5640 if (!err)
5641 err = brcmf_fil_iovar_int_set(ifp, "obss_coex",
5642 BRCMF_OBSS_COEX_AUTO);
5643 else
5644 *cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
5645 }
5646
5647 err = brcmf_p2p_attach(cfg);
5648 if (err) {
5649 brcmf_err("P2P initilisation failed (%d)\n", err);
5650 goto wiphy_unreg_out;
5651 }
5652 err = brcmf_btcoex_attach(cfg);
5653 if (err) {
5654 brcmf_err("BT-coex initialisation failed (%d)\n", err);
5655 brcmf_p2p_detach(&cfg->p2p);
5656 goto wiphy_unreg_out;
5657 }
5658
5659 err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1);
5660 if (err) {
5661 brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err);
5662 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS;
5663 }
5664
5665 return cfg;
5666
5667wiphy_unreg_out:
5668 wiphy_unregister(cfg->wiphy);
5669priv_out:
5670 wl_deinit_priv(cfg);
5671 brcmf_free_vif(vif);
5672wiphy_out:
5673 brcmf_free_wiphy(wiphy);
5674 return NULL;
5675}
5676
5677void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
5678{
5679 if (!cfg)
5680 return;
5681
5682 WARN_ON(!list_empty(&cfg->vif_list));
5683 wiphy_unregister(cfg->wiphy);
5684 brcmf_btcoex_detach(cfg);
5685 brcmf_p2p_detach(&cfg->p2p);
5686 wl_deinit_priv(cfg);
5687 brcmf_free_wiphy(cfg->wiphy);
5688}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index af8ba64ace39..1b474828d5b8 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -4707,41 +4707,6 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
4707 return err; 4707 return err;
4708} 4708}
4709 4709
4710static void brcms_c_attach_antgain_init(struct brcms_c_info *wlc)
4711{
4712 uint unit;
4713 unit = wlc->pub->unit;
4714
4715 if ((wlc->band->antgain == -1) && (wlc->pub->sromrev == 1)) {
4716 /* default antenna gain for srom rev 1 is 2 dBm (8 qdbm) */
4717 wlc->band->antgain = 8;
4718 } else if (wlc->band->antgain == -1) {
4719 wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in"
4720 " srom, using 2dB\n", unit, __func__);
4721 wlc->band->antgain = 8;
4722 } else {
4723 s8 gain, fract;
4724 /* Older sroms specified gain in whole dbm only. In order
4725 * be able to specify qdbm granularity and remain backward
4726 * compatible the whole dbms are now encoded in only
4727 * low 6 bits and remaining qdbms are encoded in the hi 2 bits.
4728 * 6 bit signed number ranges from -32 - 31.
4729 *
4730 * Examples:
4731 * 0x1 = 1 db,
4732 * 0xc1 = 1.75 db (1 + 3 quarters),
4733 * 0x3f = -1 (-1 + 0 quarters),
4734 * 0x7f = -.75 (-1 + 1 quarters) = -3 qdbm.
4735 * 0xbf = -.50 (-1 + 2 quarters) = -2 qdbm.
4736 */
4737 gain = wlc->band->antgain & 0x3f;
4738 gain <<= 2; /* Sign extend */
4739 gain >>= 2;
4740 fract = (wlc->band->antgain & 0xc0) >> 6;
4741 wlc->band->antgain = 4 * gain + fract;
4742 }
4743}
4744
4745static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc) 4710static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc)
4746{ 4711{
4747 int aa; 4712 int aa;
@@ -4780,8 +4745,6 @@ static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc)
4780 else 4745 else
4781 wlc->band->antgain = sprom->antenna_gain.a0; 4746 wlc->band->antgain = sprom->antenna_gain.a0;
4782 4747
4783 brcms_c_attach_antgain_init(wlc);
4784
4785 return true; 4748 return true;
4786} 4749}
4787 4750
diff --git a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
index d816270db3be..64d1a7ba040c 100644
--- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
+++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
@@ -17,32 +17,56 @@
17#ifndef _BRCM_HW_IDS_H_ 17#ifndef _BRCM_HW_IDS_H_
18#define _BRCM_HW_IDS_H_ 18#define _BRCM_HW_IDS_H_
19 19
20#define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */ 20#include <linux/pci_ids.h>
21#include <linux/mmc/sdio_ids.h>
22
23#define BRCM_USB_VENDOR_ID_BROADCOM 0x0a5c
24#define BRCM_PCIE_VENDOR_ID_BROADCOM PCI_VENDOR_ID_BROADCOM
25#define BRCM_SDIO_VENDOR_ID_BROADCOM SDIO_VENDOR_ID_BROADCOM
26
27/* Chipcommon Core Chip IDs */
28#define BRCM_CC_43143_CHIP_ID 43143
29#define BRCM_CC_43235_CHIP_ID 43235
30#define BRCM_CC_43236_CHIP_ID 43236
31#define BRCM_CC_43238_CHIP_ID 43238
32#define BRCM_CC_43241_CHIP_ID 0x4324
33#define BRCM_CC_43242_CHIP_ID 43242
34#define BRCM_CC_4329_CHIP_ID 0x4329
35#define BRCM_CC_4330_CHIP_ID 0x4330
36#define BRCM_CC_4334_CHIP_ID 0x4334
37#define BRCM_CC_43362_CHIP_ID 43362
38#define BRCM_CC_4335_CHIP_ID 0x4335
39#define BRCM_CC_4339_CHIP_ID 0x4339
40#define BRCM_CC_4354_CHIP_ID 0x4354
41#define BRCM_CC_43566_CHIP_ID 43566
42#define BRCM_CC_43569_CHIP_ID 43569
43
44/* SDIO Device IDs */
45#define BRCM_SDIO_43143_DEVICE_ID BRCM_CC_43143_CHIP_ID
46#define BRCM_SDIO_43241_DEVICE_ID BRCM_CC_43241_CHIP_ID
47#define BRCM_SDIO_4329_DEVICE_ID BRCM_CC_4329_CHIP_ID
48#define BRCM_SDIO_4330_DEVICE_ID BRCM_CC_4330_CHIP_ID
49#define BRCM_SDIO_4334_DEVICE_ID BRCM_CC_4334_CHIP_ID
50#define BRCM_SDIO_43362_DEVICE_ID BRCM_CC_43362_CHIP_ID
51#define BRCM_SDIO_4335_4339_DEVICE_ID BRCM_CC_4335_CHIP_ID
52#define BRCM_SDIO_4354_DEVICE_ID BRCM_CC_4354_CHIP_ID
21 53
54/* USB Device IDs */
55#define BRCM_USB_43143_DEVICE_ID 0xbd1e
56#define BRCM_USB_43236_DEVICE_ID 0xbd17
57#define BRCM_USB_43242_DEVICE_ID 0xbd1f
58#define BRCM_USB_43569_DEVICE_ID 0xbd27
59#define BRCM_USB_BCMFW_DEVICE_ID 0x0bdc
60
61/* brcmsmac IDs */
62#define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */
22#define BCM43224_D11N_ID 0x4353 /* 43224 802.11n dualband device */ 63#define BCM43224_D11N_ID 0x4353 /* 43224 802.11n dualband device */
23#define BCM43224_D11N_ID_VEN1 0x0576 /* Vendor specific 43224 802.11n db */ 64#define BCM43224_D11N_ID_VEN1 0x0576 /* Vendor specific 43224 802.11n db */
24
25#define BCM43225_D11N2G_ID 0x4357 /* 43225 802.11n 2.4GHz device */ 65#define BCM43225_D11N2G_ID 0x4357 /* 43225 802.11n 2.4GHz device */
26
27#define BCM43236_D11N_ID 0x4346 /* 43236 802.11n dualband device */ 66#define BCM43236_D11N_ID 0x4346 /* 43236 802.11n dualband device */
28#define BCM43236_D11N2G_ID 0x4347 /* 43236 802.11n 2.4GHz device */ 67#define BCM43236_D11N2G_ID 0x4347 /* 43236 802.11n 2.4GHz device */
29 68
30/* Chipcommon Core Chip IDs */
31#define BCM4313_CHIP_ID 0x4313 69#define BCM4313_CHIP_ID 0x4313
32#define BCM43143_CHIP_ID 43143
33#define BCM43224_CHIP_ID 43224 70#define BCM43224_CHIP_ID 43224
34#define BCM43225_CHIP_ID 43225
35#define BCM43235_CHIP_ID 43235
36#define BCM43236_CHIP_ID 43236
37#define BCM43238_CHIP_ID 43238
38#define BCM43241_CHIP_ID 0x4324
39#define BCM4329_CHIP_ID 0x4329
40#define BCM4330_CHIP_ID 0x4330
41#define BCM4331_CHIP_ID 0x4331
42#define BCM4334_CHIP_ID 0x4334
43#define BCM4335_CHIP_ID 0x4335
44#define BCM43362_CHIP_ID 43362
45#define BCM4339_CHIP_ID 0x4339
46#define BCM4354_CHIP_ID 0x4354
47 71
48#endif /* _BRCM_HW_IDS_H_ */ 72#endif /* _BRCM_HW_IDS_H_ */
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 7fd50428b934..6451d2b6abcf 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -20,16 +20,17 @@ config IWLWIFI
20 Intel 2000 Series Wi-Fi Adapters 20 Intel 2000 Series Wi-Fi Adapters
21 Intel 7260 Wi-Fi Adapter 21 Intel 7260 Wi-Fi Adapter
22 Intel 3160 Wi-Fi Adapter 22 Intel 3160 Wi-Fi Adapter
23 Intel 7265 Wi-Fi Adapter
23 24
24 25
25 This driver uses the kernel's mac80211 subsystem. 26 This driver uses the kernel's mac80211 subsystem.
26 27
27 In order to use this driver, you will need a microcode (uCode) 28 In order to use this driver, you will need a firmware
28 image for it. You can obtain the microcode from: 29 image for it. You can obtain the microcode from:
29 30
30 <http://intellinuxwireless.org/>. 31 <http://wireless.kernel.org/en/users/Drivers/iwlwifi>.
31 32
32 The microcode is typically installed in /lib/firmware. You can 33 The firmware is typically installed in /lib/firmware. You can
33 look in the hotplug script /etc/hotplug/firmware.agent to 34 look in the hotplug script /etc/hotplug/firmware.agent to
34 determine which directory FIRMWARE_DIR is set to when the script 35 determine which directory FIRMWARE_DIR is set to when the script
35 runs. 36 runs.
@@ -39,9 +40,10 @@ config IWLWIFI
39 say M here and read <file:Documentation/kbuild/modules.txt>. The 40 say M here and read <file:Documentation/kbuild/modules.txt>. The
40 module will be called iwlwifi. 41 module will be called iwlwifi.
41 42
43if IWLWIFI
44
42config IWLWIFI_LEDS 45config IWLWIFI_LEDS
43 bool 46 bool
44 depends on IWLWIFI
45 depends on LEDS_CLASS=y || LEDS_CLASS=IWLWIFI 47 depends on LEDS_CLASS=y || LEDS_CLASS=IWLWIFI
46 select LEDS_TRIGGERS 48 select LEDS_TRIGGERS
47 select MAC80211_LEDS 49 select MAC80211_LEDS
@@ -49,7 +51,7 @@ config IWLWIFI_LEDS
49 51
50config IWLDVM 52config IWLDVM
51 tristate "Intel Wireless WiFi DVM Firmware support" 53 tristate "Intel Wireless WiFi DVM Firmware support"
52 depends on IWLWIFI 54 depends on m
53 default IWLWIFI 55 default IWLWIFI
54 help 56 help
55 This is the driver that supports the DVM firmware which is 57 This is the driver that supports the DVM firmware which is
@@ -58,7 +60,7 @@ config IWLDVM
58 60
59config IWLMVM 61config IWLMVM
60 tristate "Intel Wireless WiFi MVM Firmware support" 62 tristate "Intel Wireless WiFi MVM Firmware support"
61 depends on IWLWIFI 63 depends on m
62 help 64 help
63 This is the driver that supports the MVM firmware which is 65 This is the driver that supports the MVM firmware which is
64 currently only available for 7260 and 3160 devices. 66 currently only available for 7260 and 3160 devices.
@@ -70,7 +72,7 @@ config IWLWIFI_OPMODE_MODULAR
70 default y if IWLMVM=m 72 default y if IWLMVM=m
71 73
72comment "WARNING: iwlwifi is useless without IWLDVM or IWLMVM" 74comment "WARNING: iwlwifi is useless without IWLDVM or IWLMVM"
73 depends on IWLWIFI && IWLDVM=n && IWLMVM=n 75 depends on IWLDVM=n && IWLMVM=n
74 76
75config IWLWIFI_BCAST_FILTERING 77config IWLWIFI_BCAST_FILTERING
76 bool "Enable broadcast filtering" 78 bool "Enable broadcast filtering"
@@ -86,11 +88,9 @@ config IWLWIFI_BCAST_FILTERING
86 expect incoming broadcasts for their normal operations. 88 expect incoming broadcasts for their normal operations.
87 89
88menu "Debugging Options" 90menu "Debugging Options"
89 depends on IWLWIFI
90 91
91config IWLWIFI_DEBUG 92config IWLWIFI_DEBUG
92 bool "Enable full debugging output in the iwlwifi driver" 93 bool "Enable full debugging output in the iwlwifi driver"
93 depends on IWLWIFI
94 ---help--- 94 ---help---
95 This option will enable debug tracing output for the iwlwifi drivers 95 This option will enable debug tracing output for the iwlwifi drivers
96 96
@@ -115,7 +115,7 @@ config IWLWIFI_DEBUG
115 115
116config IWLWIFI_DEBUGFS 116config IWLWIFI_DEBUGFS
117 bool "iwlwifi debugfs support" 117 bool "iwlwifi debugfs support"
118 depends on IWLWIFI && MAC80211_DEBUGFS 118 depends on MAC80211_DEBUGFS
119 ---help--- 119 ---help---
120 Enable creation of debugfs files for the iwlwifi drivers. This 120 Enable creation of debugfs files for the iwlwifi drivers. This
121 is a low-impact option that allows getting insight into the 121 is a low-impact option that allows getting insight into the
@@ -123,13 +123,12 @@ config IWLWIFI_DEBUGFS
123 123
124config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE 124config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
125 bool "Experimental uCode support" 125 bool "Experimental uCode support"
126 depends on IWLWIFI && IWLWIFI_DEBUG 126 depends on IWLWIFI_DEBUG
127 ---help--- 127 ---help---
128 Enable use of experimental ucode for testing and debugging. 128 Enable use of experimental ucode for testing and debugging.
129 129
130config IWLWIFI_DEVICE_TRACING 130config IWLWIFI_DEVICE_TRACING
131 bool "iwlwifi device access tracing" 131 bool "iwlwifi device access tracing"
132 depends on IWLWIFI
133 depends on EVENT_TRACING 132 depends on EVENT_TRACING
134 help 133 help
135 Say Y here to trace all commands, including TX frames and IO 134 Say Y here to trace all commands, including TX frames and IO
@@ -145,3 +144,5 @@ config IWLWIFI_DEVICE_TRACING
145 If unsure, say Y so we can help you better when problems 144 If unsure, say Y so we can help you better when problems
146 occur. 145 occur.
147endmenu 146endmenu
147
148endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-8000.c b/drivers/net/wireless/iwlwifi/iwl-8000.c
index 51486cc9d943..44b19e015102 100644
--- a/drivers/net/wireless/iwlwifi/iwl-8000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-8000.c
@@ -85,6 +85,9 @@
85#define NVM_HW_SECTION_NUM_FAMILY_8000 10 85#define NVM_HW_SECTION_NUM_FAMILY_8000 10
86#define DEFAULT_NVM_FILE_FAMILY_8000 "iwl_nvm_8000.bin" 86#define DEFAULT_NVM_FILE_FAMILY_8000 "iwl_nvm_8000.bin"
87 87
88/* Max SDIO RX aggregation size of the ADDBA request/response */
89#define MAX_RX_AGG_SIZE_8260_SDIO 28
90
88static const struct iwl_base_params iwl8000_base_params = { 91static const struct iwl_base_params iwl8000_base_params = {
89 .eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_8000, 92 .eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_8000,
90 .num_of_queues = IWLAGN_NUM_QUEUES, 93 .num_of_queues = IWLAGN_NUM_QUEUES,
@@ -129,6 +132,7 @@ const struct iwl_cfg iwl8260_2ac_sdio_cfg = {
129 .nvm_ver = IWL8000_NVM_VERSION, 132 .nvm_ver = IWL8000_NVM_VERSION,
130 .nvm_calib_ver = IWL8000_TX_POWER_VERSION, 133 .nvm_calib_ver = IWL8000_TX_POWER_VERSION,
131 .default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000, 134 .default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000,
135 .max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
132}; 136};
133 137
134MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK)); 138MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h
index 034c2fc4b69f..8da596db9abe 100644
--- a/drivers/net/wireless/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/iwlwifi/iwl-config.h
@@ -240,6 +240,7 @@ struct iwl_pwr_tx_backoff {
240 * @d0i3: device uses d0i3 instead of d3 240 * @d0i3: device uses d0i3 instead of d3
241 * @nvm_hw_section_num: the ID of the HW NVM section 241 * @nvm_hw_section_num: the ID of the HW NVM section
242 * @pwr_tx_backoffs: translation table between power limits and backoffs 242 * @pwr_tx_backoffs: translation table between power limits and backoffs
243 * @max_rx_agg_size: max RX aggregation size of the ADDBA request/response
243 * 244 *
244 * We enable the driver to be backward compatible wrt. hardware features. 245 * We enable the driver to be backward compatible wrt. hardware features.
245 * API differences in uCode shouldn't be handled here but through TLVs 246 * API differences in uCode shouldn't be handled here but through TLVs
@@ -276,6 +277,7 @@ struct iwl_cfg {
276 const struct iwl_pwr_tx_backoff *pwr_tx_backoffs; 277 const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
277 bool no_power_up_nic_in_init; 278 bool no_power_up_nic_in_init;
278 const char *default_nvm_file; 279 const char *default_nvm_file;
280 unsigned int max_rx_agg_size;
279}; 281};
280 282
281/* 283/*
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
index c39a0b899e83..de5994a776c7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
@@ -70,21 +70,24 @@
70/** 70/**
71 * enum iwl_fw_error_dump_type - types of data in the dump file 71 * enum iwl_fw_error_dump_type - types of data in the dump file
72 * @IWL_FW_ERROR_DUMP_SRAM: 72 * @IWL_FW_ERROR_DUMP_SRAM:
73 * @IWL_FW_ERROR_DUMP_REG: 73 * @IWL_FW_ERROR_DUMP_CSR: Control Status Registers - from offset 0
74 * @IWL_FW_ERROR_DUMP_RXF: 74 * @IWL_FW_ERROR_DUMP_RXF:
75 * @IWL_FW_ERROR_DUMP_TXCMD: last TX command data, structured as 75 * @IWL_FW_ERROR_DUMP_TXCMD: last TX command data, structured as
76 * &struct iwl_fw_error_dump_txcmd packets 76 * &struct iwl_fw_error_dump_txcmd packets
77 * @IWL_FW_ERROR_DUMP_DEV_FW_INFO: struct %iwl_fw_error_dump_info 77 * @IWL_FW_ERROR_DUMP_DEV_FW_INFO: struct %iwl_fw_error_dump_info
78 * info on the device / firmware. 78 * info on the device / firmware.
79 * @IWL_FW_ERROR_DUMP_FW_MONITOR: firmware monitor 79 * @IWL_FW_ERROR_DUMP_FW_MONITOR: firmware monitor
80 * @IWL_FW_ERROR_DUMP_PRPH: range of periphery registers - there can be several
81 * sections like this in a single file.
80 */ 82 */
81enum iwl_fw_error_dump_type { 83enum iwl_fw_error_dump_type {
82 IWL_FW_ERROR_DUMP_SRAM = 0, 84 IWL_FW_ERROR_DUMP_SRAM = 0,
83 IWL_FW_ERROR_DUMP_REG = 1, 85 IWL_FW_ERROR_DUMP_CSR = 1,
84 IWL_FW_ERROR_DUMP_RXF = 2, 86 IWL_FW_ERROR_DUMP_RXF = 2,
85 IWL_FW_ERROR_DUMP_TXCMD = 3, 87 IWL_FW_ERROR_DUMP_TXCMD = 3,
86 IWL_FW_ERROR_DUMP_DEV_FW_INFO = 4, 88 IWL_FW_ERROR_DUMP_DEV_FW_INFO = 4,
87 IWL_FW_ERROR_DUMP_FW_MONITOR = 5, 89 IWL_FW_ERROR_DUMP_FW_MONITOR = 5,
90 IWL_FW_ERROR_DUMP_PRPH = 6,
88 91
89 IWL_FW_ERROR_DUMP_MAX, 92 IWL_FW_ERROR_DUMP_MAX,
90}; 93};
@@ -163,6 +166,16 @@ struct iwl_fw_error_dump_fw_mon {
163} __packed; 166} __packed;
164 167
165/** 168/**
169 * struct iwl_fw_error_dump_prph - periphery registers data
170 * @prph_start: address of the first register in this chunk
171 * @data: the content of the registers
172 */
173struct iwl_fw_error_dump_prph {
174 __le32 prph_start;
175 __le32 data[];
176};
177
178/**
166 * iwl_fw_error_next_data - advance fw error dump data pointer 179 * iwl_fw_error_next_data - advance fw error dump data pointer
167 * @data: previous data block 180 * @data: previous data block
168 * Returns: next data block 181 * Returns: next data block
diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h
index f2d39cb011fc..71507cf490e6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-modparams.h
+++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h
@@ -99,7 +99,7 @@ enum iwl_disable_11n {
99 * @wd_disable: disable stuck queue check, default = 1 99 * @wd_disable: disable stuck queue check, default = 1
100 * @bt_coex_active: enable bt coex, default = true 100 * @bt_coex_active: enable bt coex, default = true
101 * @led_mode: system default, default = 0 101 * @led_mode: system default, default = 0
102 * @power_save: disable power save, default = false 102 * @power_save: enable power save, default = false
103 * @power_level: power level, default = 1 103 * @power_level: power level, default = 1
104 * @debug_level: levels are IWL_DL_* 104 * @debug_level: levels are IWL_DL_*
105 * @ant_coupling: antenna coupling in dB, default = 0 105 * @ant_coupling: antenna coupling in dB, default = 0
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 34d49e171fb4..656371a668da 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -394,6 +394,11 @@ struct iwl_trans_config {
394 const char *const *command_names; 394 const char *const *command_names;
395}; 395};
396 396
397struct iwl_trans_dump_data {
398 u32 len;
399 u8 data[];
400};
401
397struct iwl_trans; 402struct iwl_trans;
398 403
399/** 404/**
@@ -461,10 +466,8 @@ struct iwl_trans;
461 * @unref: release a reference previously taken with @ref. Note that 466 * @unref: release a reference previously taken with @ref. Note that
462 * initially the reference count is 1, making an initial @unref 467 * initially the reference count is 1, making an initial @unref
463 * necessary to allow low power states. 468 * necessary to allow low power states.
464 * @dump_data: fill a data dump with debug data, maybe containing last 469 * @dump_data: return a vmalloc'ed buffer with debug data, maybe containing last
465 * TX'ed commands and similar. When called with a NULL buffer and 470 * TX'ed commands and similar. The buffer will be vfree'd by the caller.
466 * zero buffer length, provide only the (estimated) required buffer
467 * length. Return the used buffer length.
468 * Note that the transport must fill in the proper file headers. 471 * Note that the transport must fill in the proper file headers.
469 */ 472 */
470struct iwl_trans_ops { 473struct iwl_trans_ops {
@@ -518,7 +521,7 @@ struct iwl_trans_ops {
518 void (*unref)(struct iwl_trans *trans); 521 void (*unref)(struct iwl_trans *trans);
519 522
520#ifdef CONFIG_IWLWIFI_DEBUGFS 523#ifdef CONFIG_IWLWIFI_DEBUGFS
521 u32 (*dump_data)(struct iwl_trans *trans, void *buf, u32 buflen); 524 struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans);
522#endif 525#endif
523}; 526};
524 527
@@ -685,12 +688,12 @@ static inline void iwl_trans_unref(struct iwl_trans *trans)
685} 688}
686 689
687#ifdef CONFIG_IWLWIFI_DEBUGFS 690#ifdef CONFIG_IWLWIFI_DEBUGFS
688static inline u32 iwl_trans_dump_data(struct iwl_trans *trans, 691static inline struct iwl_trans_dump_data *
689 void *buf, u32 buflen) 692iwl_trans_dump_data(struct iwl_trans *trans)
690{ 693{
691 if (!trans->ops->dump_data) 694 if (!trans->ops->dump_data)
692 return 0; 695 return NULL;
693 return trans->ops->dump_data(trans, buf, buflen); 696 return trans->ops->dump_data(trans);
694} 697}
695#endif 698#endif
696 699
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c
index 8110fe00bf55..2291bbcaaeab 100644
--- a/drivers/net/wireless/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/iwlwifi/mvm/coex.c
@@ -72,16 +72,56 @@
72 72
73#define BT_ANTENNA_COUPLING_THRESHOLD (30) 73#define BT_ANTENNA_COUPLING_THRESHOLD (30)
74 74
75const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = { 75const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX] = {
76 [BT_KILL_MSK_DEFAULT] = 0xffff0000, 76 [BT_KILL_MSK_DEFAULT] = 0xfffffc00,
77 [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff, 77 [BT_KILL_MSK_NEVER] = 0xffffffff,
78 [BT_KILL_MSK_REDUCED_TXPOW] = 0, 78 [BT_KILL_MSK_ALWAYS] = 0,
79}; 79};
80 80
81const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = { 81const u8 iwl_bt_cts_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT] = {
82 [BT_KILL_MSK_DEFAULT] = 0xffff0000, 82 {
83 [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff, 83 BT_KILL_MSK_ALWAYS,
84 [BT_KILL_MSK_REDUCED_TXPOW] = 0, 84 BT_KILL_MSK_ALWAYS,
85 BT_KILL_MSK_ALWAYS,
86 },
87 {
88 BT_KILL_MSK_NEVER,
89 BT_KILL_MSK_NEVER,
90 BT_KILL_MSK_NEVER,
91 },
92 {
93 BT_KILL_MSK_NEVER,
94 BT_KILL_MSK_NEVER,
95 BT_KILL_MSK_NEVER,
96 },
97 {
98 BT_KILL_MSK_DEFAULT,
99 BT_KILL_MSK_NEVER,
100 BT_KILL_MSK_DEFAULT,
101 },
102};
103
104const u8 iwl_bt_ack_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT] = {
105 {
106 BT_KILL_MSK_ALWAYS,
107 BT_KILL_MSK_ALWAYS,
108 BT_KILL_MSK_ALWAYS,
109 },
110 {
111 BT_KILL_MSK_ALWAYS,
112 BT_KILL_MSK_ALWAYS,
113 BT_KILL_MSK_ALWAYS,
114 },
115 {
116 BT_KILL_MSK_ALWAYS,
117 BT_KILL_MSK_ALWAYS,
118 BT_KILL_MSK_ALWAYS,
119 },
120 {
121 BT_KILL_MSK_DEFAULT,
122 BT_KILL_MSK_ALWAYS,
123 BT_KILL_MSK_DEFAULT,
124 },
85}; 125};
86 126
87static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = { 127static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = {
@@ -611,54 +651,43 @@ send_cmd:
611 return ret; 651 return ret;
612} 652}
613 653
614static int iwl_mvm_bt_udpate_sw_boost(struct iwl_mvm *mvm, 654static int iwl_mvm_bt_udpate_sw_boost(struct iwl_mvm *mvm)
615 bool reduced_tx_power)
616{ 655{
617 enum iwl_bt_kill_msk bt_kill_msk;
618 struct iwl_bt_coex_sw_boost_update_cmd cmd = {};
619 struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif; 656 struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
657 u32 primary_lut = le32_to_cpu(notif->primary_ch_lut);
658 u32 secondary_lut = le32_to_cpu(notif->secondary_ch_lut);
659 u32 ag = le32_to_cpu(notif->bt_activity_grading);
660 struct iwl_bt_coex_sw_boost_update_cmd cmd = {};
661 u8 ack_kill_msk[NUM_PHY_CTX] = {};
662 u8 cts_kill_msk[NUM_PHY_CTX] = {};
663 int i;
620 664
621 lockdep_assert_held(&mvm->mutex); 665 lockdep_assert_held(&mvm->mutex);
622 666
623 if (reduced_tx_power) { 667 ack_kill_msk[0] = iwl_bt_ack_kill_msk[ag][primary_lut];
624 /* Reduced Tx power has precedence on the type of the profile */ 668 cts_kill_msk[0] = iwl_bt_cts_kill_msk[ag][primary_lut];
625 bt_kill_msk = BT_KILL_MSK_REDUCED_TXPOW;
626 } else {
627 /* Low latency BT profile is active: give higher prio to BT */
628 if (BT_MBOX_MSG(notif, 3, SCO_STATE) ||
629 BT_MBOX_MSG(notif, 3, A2DP_STATE) ||
630 BT_MBOX_MSG(notif, 3, SNIFF_STATE))
631 bt_kill_msk = BT_KILL_MSK_SCO_HID_A2DP;
632 else
633 bt_kill_msk = BT_KILL_MSK_DEFAULT;
634 }
635 669
636 IWL_DEBUG_COEX(mvm, 670 ack_kill_msk[1] = iwl_bt_ack_kill_msk[ag][secondary_lut];
637 "Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive\n", 671 cts_kill_msk[1] = iwl_bt_cts_kill_msk[ag][secondary_lut];
638 bt_kill_msk,
639 BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in",
640 BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in",
641 BT_MBOX_MSG(notif, 3, SNIFF_STATE) ? "" : "in");
642 672
643 /* Don't send HCMD if there is no update */ 673 /* Don't send HCMD if there is no update */
644 if (bt_kill_msk == mvm->bt_kill_msk) 674 if (!memcmp(ack_kill_msk, mvm->bt_ack_kill_msk, sizeof(ack_kill_msk)) ||
675 !memcmp(cts_kill_msk, mvm->bt_cts_kill_msk, sizeof(cts_kill_msk)))
645 return 0; 676 return 0;
646 677
647 mvm->bt_kill_msk = bt_kill_msk; 678 memcpy(mvm->bt_ack_kill_msk, ack_kill_msk,
679 sizeof(mvm->bt_ack_kill_msk));
680 memcpy(mvm->bt_cts_kill_msk, cts_kill_msk,
681 sizeof(mvm->bt_cts_kill_msk));
648 682
649 cmd.boost_values[0].kill_ack_msk = 683 BUILD_BUG_ON(ARRAY_SIZE(ack_kill_msk) < ARRAY_SIZE(cmd.boost_values));
650 cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]);
651 cmd.boost_values[0].kill_cts_msk =
652 cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]);
653 684
654 cmd.boost_values[1].kill_ack_msk = cmd.boost_values[0].kill_ack_msk; 685 for (i = 0; i < ARRAY_SIZE(cmd.boost_values); i++) {
655 cmd.boost_values[2].kill_cts_msk = cmd.boost_values[0].kill_cts_msk; 686 cmd.boost_values[i].kill_ack_msk =
656 cmd.boost_values[1].kill_ack_msk = cmd.boost_values[0].kill_ack_msk; 687 cpu_to_le32(iwl_bt_ctl_kill_msk[ack_kill_msk[i]]);
657 cmd.boost_values[2].kill_cts_msk = cmd.boost_values[0].kill_cts_msk; 688 cmd.boost_values[i].kill_cts_msk =
658 689 cpu_to_le32(iwl_bt_ctl_kill_msk[cts_kill_msk[i]]);
659 IWL_DEBUG_COEX(mvm, "ACK Kill msk = 0x%08x, CTS Kill msk = 0x%08x\n", 690 }
660 iwl_bt_ack_kill_msk[bt_kill_msk],
661 iwl_bt_cts_kill_msk[bt_kill_msk]);
662 691
663 return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_SW_BOOST, 0, 692 return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_SW_BOOST, 0,
664 sizeof(cmd), &cmd); 693 sizeof(cmd), &cmd);
@@ -700,8 +729,6 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
700struct iwl_bt_iterator_data { 729struct iwl_bt_iterator_data {
701 struct iwl_bt_coex_profile_notif *notif; 730 struct iwl_bt_coex_profile_notif *notif;
702 struct iwl_mvm *mvm; 731 struct iwl_mvm *mvm;
703 u32 num_bss_ifaces;
704 bool reduced_tx_power;
705 struct ieee80211_chanctx_conf *primary; 732 struct ieee80211_chanctx_conf *primary;
706 struct ieee80211_chanctx_conf *secondary; 733 struct ieee80211_chanctx_conf *secondary;
707 bool primary_ll; 734 bool primary_ll;
@@ -737,22 +764,12 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
737 764
738 switch (vif->type) { 765 switch (vif->type) {
739 case NL80211_IFTYPE_STATION: 766 case NL80211_IFTYPE_STATION:
740 /* Count BSSes vifs */
741 data->num_bss_ifaces++;
742 /* default smps_mode for BSS / P2P client is AUTOMATIC */ 767 /* default smps_mode for BSS / P2P client is AUTOMATIC */
743 smps_mode = IEEE80211_SMPS_AUTOMATIC; 768 smps_mode = IEEE80211_SMPS_AUTOMATIC;
744 break; 769 break;
745 case NL80211_IFTYPE_AP: 770 case NL80211_IFTYPE_AP:
746 /* default smps_mode for AP / GO is OFF */ 771 if (!mvmvif->ap_ibss_active)
747 smps_mode = IEEE80211_SMPS_OFF;
748 if (!mvmvif->ap_ibss_active) {
749 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
750 smps_mode);
751 return; 772 return;
752 }
753
754 /* the Ack / Cts kill mask must be default if AP / GO */
755 data->reduced_tx_power = false;
756 break; 773 break;
757 default: 774 default:
758 return; 775 return;
@@ -763,11 +780,10 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
763 /* If channel context is invalid or not on 2.4GHz .. */ 780 /* If channel context is invalid or not on 2.4GHz .. */
764 if ((!chanctx_conf || 781 if ((!chanctx_conf ||
765 chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) { 782 chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) {
766 /* ... relax constraints and disable rssi events */
767 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
768 smps_mode);
769 data->reduced_tx_power = false;
770 if (vif->type == NL80211_IFTYPE_STATION) { 783 if (vif->type == NL80211_IFTYPE_STATION) {
784 /* ... relax constraints and disable rssi events */
785 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
786 smps_mode);
771 iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, 787 iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
772 false); 788 false);
773 iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); 789 iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
@@ -779,9 +795,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
779 if (bt_activity_grading >= BT_HIGH_TRAFFIC) 795 if (bt_activity_grading >= BT_HIGH_TRAFFIC)
780 smps_mode = IEEE80211_SMPS_STATIC; 796 smps_mode = IEEE80211_SMPS_STATIC;
781 else if (bt_activity_grading >= BT_LOW_TRAFFIC) 797 else if (bt_activity_grading >= BT_LOW_TRAFFIC)
782 smps_mode = vif->type == NL80211_IFTYPE_AP ? 798 smps_mode = IEEE80211_SMPS_DYNAMIC;
783 IEEE80211_SMPS_OFF :
784 IEEE80211_SMPS_DYNAMIC;
785 799
786 /* relax SMPS contraints for next association */ 800 /* relax SMPS contraints for next association */
787 if (!vif->bss_conf.assoc) 801 if (!vif->bss_conf.assoc)
@@ -795,7 +809,9 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
795 "mac %d: bt_activity_grading %d smps_req %d\n", 809 "mac %d: bt_activity_grading %d smps_req %d\n",
796 mvmvif->id, bt_activity_grading, smps_mode); 810 mvmvif->id, bt_activity_grading, smps_mode);
797 811
798 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode); 812 if (vif->type == NL80211_IFTYPE_STATION)
813 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
814 smps_mode);
799 815
800 /* low latency is always primary */ 816 /* low latency is always primary */
801 if (iwl_mvm_vif_low_latency(mvmvif)) { 817 if (iwl_mvm_vif_low_latency(mvmvif)) {
@@ -846,7 +862,6 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
846 if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT || 862 if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
847 mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc || 863 mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc ||
848 le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF) { 864 le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF) {
849 data->reduced_tx_power = false;
850 iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false); 865 iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false);
851 iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); 866 iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
852 return; 867 return;
@@ -861,23 +876,9 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
861 if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) { 876 if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) {
862 if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true)) 877 if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true))
863 IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); 878 IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
864
865 /*
866 * bt_kill_msk can be BT_KILL_MSK_REDUCED_TXPOW only if all the
867 * BSS / P2P clients have rssi above threshold.
868 * We set the bt_kill_msk to BT_KILL_MSK_REDUCED_TXPOW before
869 * the iteration, if one interface's rssi isn't good enough,
870 * bt_kill_msk will be set to default values.
871 */
872 } else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) { 879 } else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) {
873 if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false)) 880 if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
874 IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); 881 IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
875
876 /*
877 * One interface hasn't rssi above threshold, bt_kill_msk must
878 * be set to default values.
879 */
880 data->reduced_tx_power = false;
881 } 882 }
882 883
883 /* Begin to monitor the RSSI: it may influence the reduced Tx power */ 884 /* Begin to monitor the RSSI: it may influence the reduced Tx power */
@@ -889,7 +890,6 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
889 struct iwl_bt_iterator_data data = { 890 struct iwl_bt_iterator_data data = {
890 .mvm = mvm, 891 .mvm = mvm,
891 .notif = &mvm->last_bt_notif, 892 .notif = &mvm->last_bt_notif,
892 .reduced_tx_power = true,
893 }; 893 };
894 struct iwl_bt_coex_ci_cmd cmd = {}; 894 struct iwl_bt_coex_ci_cmd cmd = {};
895 u8 ci_bw_idx; 895 u8 ci_bw_idx;
@@ -959,14 +959,7 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
959 memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd)); 959 memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd));
960 } 960 }
961 961
962 /* 962 if (iwl_mvm_bt_udpate_sw_boost(mvm))
963 * If there are no BSS / P2P client interfaces, reduced Tx Power is
964 * irrelevant since it is based on the RSSI coming from the beacon.
965 * Use BT_KILL_MSK_DEFAULT in that case.
966 */
967 data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
968
969 if (iwl_mvm_bt_udpate_sw_boost(mvm, data.reduced_tx_power))
970 IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); 963 IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
971} 964}
972 965
@@ -1035,16 +1028,6 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
1035 return; 1028 return;
1036 1029
1037 mvmsta = iwl_mvm_sta_from_mac80211(sta); 1030 mvmsta = iwl_mvm_sta_from_mac80211(sta);
1038
1039 data->num_bss_ifaces++;
1040
1041 /*
1042 * This interface doesn't support reduced Tx power (because of low
1043 * RSSI probably), then set bt_kill_msk to default values.
1044 */
1045 if (!mvmsta->bt_reduced_txpower)
1046 data->reduced_tx_power = false;
1047 /* else - possibly leave it to BT_KILL_MSK_REDUCED_TXPOW */
1048} 1031}
1049 1032
1050void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 1033void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@@ -1053,7 +1036,6 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
1053 struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv; 1036 struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
1054 struct iwl_bt_iterator_data data = { 1037 struct iwl_bt_iterator_data data = {
1055 .mvm = mvm, 1038 .mvm = mvm,
1056 .reduced_tx_power = true,
1057 }; 1039 };
1058 int ret; 1040 int ret;
1059 1041
@@ -1100,14 +1082,7 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
1100 mvm->hw, IEEE80211_IFACE_ITER_NORMAL, 1082 mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
1101 iwl_mvm_bt_rssi_iterator, &data); 1083 iwl_mvm_bt_rssi_iterator, &data);
1102 1084
1103 /* 1085 if (iwl_mvm_bt_udpate_sw_boost(mvm))
1104 * If there are no BSS / P2P client interfaces, reduced Tx Power is
1105 * irrelevant since it is based on the RSSI coming from the beacon.
1106 * Use BT_KILL_MSK_DEFAULT in that case.
1107 */
1108 data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
1109
1110 if (iwl_mvm_bt_udpate_sw_boost(mvm, data.reduced_tx_power))
1111 IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); 1086 IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
1112} 1087}
1113 1088
@@ -1150,7 +1125,7 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
1150 enum iwl_bt_coex_lut_type lut_type; 1125 enum iwl_bt_coex_lut_type lut_type;
1151 1126
1152 if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT)) 1127 if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
1153 return iwl_mvm_coex_agg_time_limit_old(mvm, sta); 1128 return iwl_mvm_bt_coex_is_mimo_allowed_old(mvm, sta);
1154 1129
1155 if (IWL_COEX_IS_TTC_ON(mvm->last_bt_notif.ttc_rrc_status, phy_ctxt->id)) 1130 if (IWL_COEX_IS_TTC_ON(mvm->last_bt_notif.ttc_rrc_status, phy_ctxt->id))
1156 return true; 1131 return true;
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
index ce50363d314b..a3be33359927 100644
--- a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
+++ b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
@@ -649,10 +649,6 @@ int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm)
649 sizeof(iwl_bt_prio_boost)); 649 sizeof(iwl_bt_prio_boost));
650 memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut, 650 memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut,
651 sizeof(iwl_bt_mprio_lut)); 651 sizeof(iwl_bt_mprio_lut));
652 bt_cmd->kill_ack_msk =
653 cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]);
654 bt_cmd->kill_cts_msk =
655 cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]);
656 652
657send_cmd: 653send_cmd:
658 memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old)); 654 memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old));
@@ -664,12 +660,13 @@ send_cmd:
664 return ret; 660 return ret;
665} 661}
666 662
667static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm, 663static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm)
668 bool reduced_tx_power)
669{ 664{
670 enum iwl_bt_kill_msk bt_kill_msk;
671 struct iwl_bt_coex_cmd_old *bt_cmd;
672 struct iwl_bt_coex_profile_notif_old *notif = &mvm->last_bt_notif_old; 665 struct iwl_bt_coex_profile_notif_old *notif = &mvm->last_bt_notif_old;
666 u32 primary_lut = le32_to_cpu(notif->primary_ch_lut);
667 u32 ag = le32_to_cpu(notif->bt_activity_grading);
668 struct iwl_bt_coex_cmd_old *bt_cmd;
669 u8 ack_kill_msk, cts_kill_msk;
673 struct iwl_host_cmd cmd = { 670 struct iwl_host_cmd cmd = {
674 .id = BT_CONFIG, 671 .id = BT_CONFIG,
675 .data[0] = &bt_cmd, 672 .data[0] = &bt_cmd,
@@ -680,31 +677,15 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
680 677
681 lockdep_assert_held(&mvm->mutex); 678 lockdep_assert_held(&mvm->mutex);
682 679
683 if (reduced_tx_power) { 680 ack_kill_msk = iwl_bt_ack_kill_msk[ag][primary_lut];
684 /* Reduced Tx power has precedence on the type of the profile */ 681 cts_kill_msk = iwl_bt_cts_kill_msk[ag][primary_lut];
685 bt_kill_msk = BT_KILL_MSK_REDUCED_TXPOW;
686 } else {
687 /* Low latency BT profile is active: give higher prio to BT */
688 if (BT_MBOX_MSG(notif, 3, SCO_STATE) ||
689 BT_MBOX_MSG(notif, 3, A2DP_STATE) ||
690 BT_MBOX_MSG(notif, 3, SNIFF_STATE))
691 bt_kill_msk = BT_KILL_MSK_SCO_HID_A2DP;
692 else
693 bt_kill_msk = BT_KILL_MSK_DEFAULT;
694 }
695
696 IWL_DEBUG_COEX(mvm,
697 "Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive\n",
698 bt_kill_msk,
699 BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in",
700 BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in",
701 BT_MBOX_MSG(notif, 3, SNIFF_STATE) ? "" : "in");
702 682
703 /* Don't send HCMD if there is no update */ 683 if (mvm->bt_ack_kill_msk[0] == ack_kill_msk &&
704 if (bt_kill_msk == mvm->bt_kill_msk) 684 mvm->bt_cts_kill_msk[0] == cts_kill_msk)
705 return 0; 685 return 0;
706 686
707 mvm->bt_kill_msk = bt_kill_msk; 687 mvm->bt_ack_kill_msk[0] = ack_kill_msk;
688 mvm->bt_cts_kill_msk[0] = cts_kill_msk;
708 689
709 bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL); 690 bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
710 if (!bt_cmd) 691 if (!bt_cmd)
@@ -712,16 +693,12 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
712 cmd.data[0] = bt_cmd; 693 cmd.data[0] = bt_cmd;
713 bt_cmd->flags = cpu_to_le32(BT_COEX_NW_OLD); 694 bt_cmd->flags = cpu_to_le32(BT_COEX_NW_OLD);
714 695
715 bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]); 696 bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ctl_kill_msk[ack_kill_msk]);
716 bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]); 697 bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_ctl_kill_msk[cts_kill_msk]);
717 bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE | 698 bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE |
718 BT_VALID_KILL_ACK | 699 BT_VALID_KILL_ACK |
719 BT_VALID_KILL_CTS); 700 BT_VALID_KILL_CTS);
720 701
721 IWL_DEBUG_COEX(mvm, "ACK Kill msk = 0x%08x, CTS Kill msk = 0x%08x\n",
722 iwl_bt_ack_kill_msk[bt_kill_msk],
723 iwl_bt_cts_kill_msk[bt_kill_msk]);
724
725 ret = iwl_mvm_send_cmd(mvm, &cmd); 702 ret = iwl_mvm_send_cmd(mvm, &cmd);
726 703
727 kfree(bt_cmd); 704 kfree(bt_cmd);
@@ -777,8 +754,6 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
777struct iwl_bt_iterator_data { 754struct iwl_bt_iterator_data {
778 struct iwl_bt_coex_profile_notif_old *notif; 755 struct iwl_bt_coex_profile_notif_old *notif;
779 struct iwl_mvm *mvm; 756 struct iwl_mvm *mvm;
780 u32 num_bss_ifaces;
781 bool reduced_tx_power;
782 struct ieee80211_chanctx_conf *primary; 757 struct ieee80211_chanctx_conf *primary;
783 struct ieee80211_chanctx_conf *secondary; 758 struct ieee80211_chanctx_conf *secondary;
784 bool primary_ll; 759 bool primary_ll;
@@ -814,22 +789,12 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
814 789
815 switch (vif->type) { 790 switch (vif->type) {
816 case NL80211_IFTYPE_STATION: 791 case NL80211_IFTYPE_STATION:
817 /* Count BSSes vifs */
818 data->num_bss_ifaces++;
819 /* default smps_mode for BSS / P2P client is AUTOMATIC */ 792 /* default smps_mode for BSS / P2P client is AUTOMATIC */
820 smps_mode = IEEE80211_SMPS_AUTOMATIC; 793 smps_mode = IEEE80211_SMPS_AUTOMATIC;
821 break; 794 break;
822 case NL80211_IFTYPE_AP: 795 case NL80211_IFTYPE_AP:
823 /* default smps_mode for AP / GO is OFF */ 796 if (!mvmvif->ap_ibss_active)
824 smps_mode = IEEE80211_SMPS_OFF;
825 if (!mvmvif->ap_ibss_active) {
826 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
827 smps_mode);
828 return; 797 return;
829 }
830
831 /* the Ack / Cts kill mask must be default if AP / GO */
832 data->reduced_tx_power = false;
833 break; 798 break;
834 default: 799 default:
835 return; 800 return;
@@ -840,11 +805,10 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
840 /* If channel context is invalid or not on 2.4GHz .. */ 805 /* If channel context is invalid or not on 2.4GHz .. */
841 if ((!chanctx_conf || 806 if ((!chanctx_conf ||
842 chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) { 807 chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) {
843 /* ... relax constraints and disable rssi events */
844 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
845 smps_mode);
846 data->reduced_tx_power = false;
847 if (vif->type == NL80211_IFTYPE_STATION) { 808 if (vif->type == NL80211_IFTYPE_STATION) {
809 /* ... relax constraints and disable rssi events */
810 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
811 smps_mode);
848 iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, 812 iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
849 false); 813 false);
850 iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); 814 iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
@@ -869,7 +833,9 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
869 mvmvif->id, data->notif->bt_status, bt_activity_grading, 833 mvmvif->id, data->notif->bt_status, bt_activity_grading,
870 smps_mode); 834 smps_mode);
871 835
872 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode); 836 if (vif->type == NL80211_IFTYPE_STATION)
837 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
838 smps_mode);
873 839
874 /* low latency is always primary */ 840 /* low latency is always primary */
875 if (iwl_mvm_vif_low_latency(mvmvif)) { 841 if (iwl_mvm_vif_low_latency(mvmvif)) {
@@ -920,7 +886,6 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
920 if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT || 886 if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
921 mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc || 887 mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc ||
922 !data->notif->bt_status) { 888 !data->notif->bt_status) {
923 data->reduced_tx_power = false;
924 iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false); 889 iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false);
925 iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); 890 iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
926 return; 891 return;
@@ -935,23 +900,9 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
935 if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) { 900 if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) {
936 if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true)) 901 if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true))
937 IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); 902 IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
938
939 /*
940 * bt_kill_msk can be BT_KILL_MSK_REDUCED_TXPOW only if all the
941 * BSS / P2P clients have rssi above threshold.
942 * We set the bt_kill_msk to BT_KILL_MSK_REDUCED_TXPOW before
943 * the iteration, if one interface's rssi isn't good enough,
944 * bt_kill_msk will be set to default values.
945 */
946 } else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) { 903 } else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) {
947 if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false)) 904 if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
948 IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); 905 IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
949
950 /*
951 * One interface hasn't rssi above threshold, bt_kill_msk must
952 * be set to default values.
953 */
954 data->reduced_tx_power = false;
955 } 906 }
956 907
957 /* Begin to monitor the RSSI: it may influence the reduced Tx power */ 908 /* Begin to monitor the RSSI: it may influence the reduced Tx power */
@@ -963,7 +914,6 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
963 struct iwl_bt_iterator_data data = { 914 struct iwl_bt_iterator_data data = {
964 .mvm = mvm, 915 .mvm = mvm,
965 .notif = &mvm->last_bt_notif_old, 916 .notif = &mvm->last_bt_notif_old,
966 .reduced_tx_power = true,
967 }; 917 };
968 struct iwl_bt_coex_ci_cmd_old cmd = {}; 918 struct iwl_bt_coex_ci_cmd_old cmd = {};
969 u8 ci_bw_idx; 919 u8 ci_bw_idx;
@@ -1037,14 +987,7 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
1037 memcpy(&mvm->last_bt_ci_cmd_old, &cmd, sizeof(cmd)); 987 memcpy(&mvm->last_bt_ci_cmd_old, &cmd, sizeof(cmd));
1038 } 988 }
1039 989
1040 /* 990 if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm))
1041 * If there are no BSS / P2P client interfaces, reduced Tx Power is
1042 * irrelevant since it is based on the RSSI coming from the beacon.
1043 * Use BT_KILL_MSK_DEFAULT in that case.
1044 */
1045 data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
1046
1047 if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power))
1048 IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); 991 IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
1049} 992}
1050 993
@@ -1115,16 +1058,6 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
1115 return; 1058 return;
1116 1059
1117 mvmsta = iwl_mvm_sta_from_mac80211(sta); 1060 mvmsta = iwl_mvm_sta_from_mac80211(sta);
1118
1119 data->num_bss_ifaces++;
1120
1121 /*
1122 * This interface doesn't support reduced Tx power (because of low
1123 * RSSI probably), then set bt_kill_msk to default values.
1124 */
1125 if (!mvmsta->bt_reduced_txpower)
1126 data->reduced_tx_power = false;
1127 /* else - possibly leave it to BT_KILL_MSK_REDUCED_TXPOW */
1128} 1061}
1129 1062
1130void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 1063void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@@ -1133,7 +1066,6 @@ void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
1133 struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv; 1066 struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
1134 struct iwl_bt_iterator_data data = { 1067 struct iwl_bt_iterator_data data = {
1135 .mvm = mvm, 1068 .mvm = mvm,
1136 .reduced_tx_power = true,
1137 }; 1069 };
1138 int ret; 1070 int ret;
1139 1071
@@ -1175,14 +1107,7 @@ void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
1175 mvm->hw, IEEE80211_IFACE_ITER_NORMAL, 1107 mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
1176 iwl_mvm_bt_rssi_iterator, &data); 1108 iwl_mvm_bt_rssi_iterator, &data);
1177 1109
1178 /* 1110 if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm))
1179 * If there are no BSS / P2P client interfaces, reduced Tx Power is
1180 * irrelevant since it is based on the RSSI coming from the beacon.
1181 * Use BT_KILL_MSK_DEFAULT in that case.
1182 */
1183 data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
1184
1185 if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power))
1186 IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); 1111 IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
1187} 1112}
1188 1113
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index f131ef0ec5b3..7d18f466fbb3 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -146,17 +146,47 @@ static ssize_t iwl_dbgfs_fw_error_dump_read(struct file *file,
146 char __user *user_buf, 146 char __user *user_buf,
147 size_t count, loff_t *ppos) 147 size_t count, loff_t *ppos)
148{ 148{
149 struct iwl_fw_error_dump_file *dump_file = file->private_data; 149 struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data;
150 ssize_t bytes_read = 0;
151 ssize_t bytes_read_trans = 0;
152
153 if (*ppos < dump_ptrs->op_mode_len)
154 bytes_read +=
155 simple_read_from_buffer(user_buf, count, ppos,
156 dump_ptrs->op_mode_ptr,
157 dump_ptrs->op_mode_len);
158
159 if (bytes_read < 0 || *ppos < dump_ptrs->op_mode_len)
160 return bytes_read;
161
162 if (dump_ptrs->trans_ptr) {
163 *ppos -= dump_ptrs->op_mode_len;
164 bytes_read_trans =
165 simple_read_from_buffer(user_buf + bytes_read,
166 count - bytes_read, ppos,
167 dump_ptrs->trans_ptr->data,
168 dump_ptrs->trans_ptr->len);
169 *ppos += dump_ptrs->op_mode_len;
170
171 if (bytes_read_trans >= 0)
172 bytes_read += bytes_read_trans;
173 else if (!bytes_read)
174 /* propagate the failure */
175 return bytes_read_trans;
176 }
177
178 return bytes_read;
150 179
151 return simple_read_from_buffer(user_buf, count, ppos,
152 dump_file,
153 le32_to_cpu(dump_file->file_len));
154} 180}
155 181
156static int iwl_dbgfs_fw_error_dump_release(struct inode *inode, 182static int iwl_dbgfs_fw_error_dump_release(struct inode *inode,
157 struct file *file) 183 struct file *file)
158{ 184{
159 vfree(file->private_data); 185 struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data;
186
187 vfree(dump_ptrs->op_mode_ptr);
188 vfree(dump_ptrs->trans_ptr);
189 kfree(dump_ptrs);
160 190
161 return 0; 191 return 0;
162} 192}
@@ -514,9 +544,9 @@ static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
514 544
515 pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n"); 545 pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n");
516 pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill Mask 0x%08x\n", 546 pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill Mask 0x%08x\n",
517 iwl_bt_ack_kill_msk[mvm->bt_kill_msk]); 547 iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[0]]);
518 pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill Mask 0x%08x\n", 548 pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill Mask 0x%08x\n",
519 iwl_bt_cts_kill_msk[mvm->bt_kill_msk]); 549 iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[0]]);
520 550
521 } else { 551 } else {
522 struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd; 552 struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd;
@@ -531,10 +561,19 @@ static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
531 le64_to_cpu(cmd->bt_secondary_ci)); 561 le64_to_cpu(cmd->bt_secondary_ci));
532 562
533 pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n"); 563 pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n");
534 pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill Mask 0x%08x\n", 564 pos += scnprintf(buf+pos, bufsz-pos,
535 iwl_bt_ack_kill_msk[mvm->bt_kill_msk]); 565 "\tPrimary: ACK Kill Mask 0x%08x\n",
536 pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill Mask 0x%08x\n", 566 iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[0]]);
537 iwl_bt_cts_kill_msk[mvm->bt_kill_msk]); 567 pos += scnprintf(buf+pos, bufsz-pos,
568 "\tPrimary: CTS Kill Mask 0x%08x\n",
569 iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[0]]);
570 pos += scnprintf(buf+pos, bufsz-pos,
571 "\tSecondary: ACK Kill Mask 0x%08x\n",
572 iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[1]]);
573 pos += scnprintf(buf+pos, bufsz-pos,
574 "\tSecondary: CTS Kill Mask 0x%08x\n",
575 iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[1]]);
576
538 } 577 }
539 578
540 mutex_unlock(&mvm->mutex); 579 mutex_unlock(&mvm->mutex);
@@ -830,8 +869,14 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
830static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf, 869static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
831 size_t count, loff_t *ppos) 870 size_t count, loff_t *ppos)
832{ 871{
872 int ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_NMI);
873 if (ret)
874 return ret;
875
833 iwl_force_nmi(mvm->trans); 876 iwl_force_nmi(mvm->trans);
834 877
878 iwl_mvm_unref(mvm, IWL_MVM_REF_NMI);
879
835 return count; 880 return count;
836} 881}
837 882
@@ -1115,11 +1160,11 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf,
1115} 1160}
1116#endif 1161#endif
1117 1162
1118#define PRINT_MVM_REF(ref) do { \ 1163#define PRINT_MVM_REF(ref) do { \
1119 if (test_bit(ref, mvm->ref_bitmap)) \ 1164 if (mvm->refs[ref]) \
1120 pos += scnprintf(buf + pos, bufsz - pos, \ 1165 pos += scnprintf(buf + pos, bufsz - pos, \
1121 "\t(0x%lx) %s\n", \ 1166 "\t(0x%lx): %d %s\n", \
1122 BIT(ref), #ref); \ 1167 BIT(ref), mvm->refs[ref], #ref); \
1123} while (0) 1168} while (0)
1124 1169
1125static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file, 1170static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
@@ -1127,12 +1172,17 @@ static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
1127 size_t count, loff_t *ppos) 1172 size_t count, loff_t *ppos)
1128{ 1173{
1129 struct iwl_mvm *mvm = file->private_data; 1174 struct iwl_mvm *mvm = file->private_data;
1130 int pos = 0; 1175 int i, pos = 0;
1131 char buf[256]; 1176 char buf[256];
1132 const size_t bufsz = sizeof(buf); 1177 const size_t bufsz = sizeof(buf);
1178 u32 refs = 0;
1133 1179
1134 pos += scnprintf(buf + pos, bufsz - pos, "taken mvm refs: 0x%lx\n", 1180 for (i = 0; i < IWL_MVM_REF_COUNT; i++)
1135 mvm->ref_bitmap[0]); 1181 if (mvm->refs[i])
1182 refs |= BIT(i);
1183
1184 pos += scnprintf(buf + pos, bufsz - pos, "taken mvm refs: 0x%x\n",
1185 refs);
1136 1186
1137 PRINT_MVM_REF(IWL_MVM_REF_UCODE_DOWN); 1187 PRINT_MVM_REF(IWL_MVM_REF_UCODE_DOWN);
1138 PRINT_MVM_REF(IWL_MVM_REF_SCAN); 1188 PRINT_MVM_REF(IWL_MVM_REF_SCAN);
@@ -1158,7 +1208,7 @@ static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf,
1158 1208
1159 mutex_lock(&mvm->mutex); 1209 mutex_lock(&mvm->mutex);
1160 1210
1161 taken = test_bit(IWL_MVM_REF_USER, mvm->ref_bitmap); 1211 taken = mvm->refs[IWL_MVM_REF_USER];
1162 if (value == 1 && !taken) 1212 if (value == 1 && !taken)
1163 iwl_mvm_ref(mvm, IWL_MVM_REF_USER); 1213 iwl_mvm_ref(mvm, IWL_MVM_REF_USER);
1164 else if (value == 0 && taken) 1214 else if (value == 0 && taken)
@@ -1194,14 +1244,21 @@ iwl_dbgfs_prph_reg_read(struct file *file,
1194 int pos = 0; 1244 int pos = 0;
1195 char buf[32]; 1245 char buf[32];
1196 const size_t bufsz = sizeof(buf); 1246 const size_t bufsz = sizeof(buf);
1247 int ret;
1197 1248
1198 if (!mvm->dbgfs_prph_reg_addr) 1249 if (!mvm->dbgfs_prph_reg_addr)
1199 return -EINVAL; 1250 return -EINVAL;
1200 1251
1252 ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_READ);
1253 if (ret)
1254 return ret;
1255
1201 pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n", 1256 pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n",
1202 mvm->dbgfs_prph_reg_addr, 1257 mvm->dbgfs_prph_reg_addr,
1203 iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr)); 1258 iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr));
1204 1259
1260 iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_READ);
1261
1205 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1262 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1206} 1263}
1207 1264
@@ -1211,6 +1268,7 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
1211{ 1268{
1212 u8 args; 1269 u8 args;
1213 u32 value; 1270 u32 value;
1271 int ret;
1214 1272
1215 args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value); 1273 args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value);
1216 /* if we only want to set the reg address - nothing more to do */ 1274 /* if we only want to set the reg address - nothing more to do */
@@ -1221,7 +1279,13 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
1221 if (args != 2) 1279 if (args != 2)
1222 return -EINVAL; 1280 return -EINVAL;
1223 1281
1282 ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE);
1283 if (ret)
1284 return ret;
1285
1224 iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value); 1286 iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value);
1287
1288 iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE);
1225out: 1289out:
1226 return count; 1290 return count;
1227} 1291}
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
index ab12aaa43034..69875716dcdb 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
@@ -385,6 +385,8 @@ enum iwl_bt_activity_grading {
385 BT_ON_NO_CONNECTION = 1, 385 BT_ON_NO_CONNECTION = 1,
386 BT_LOW_TRAFFIC = 2, 386 BT_LOW_TRAFFIC = 2,
387 BT_HIGH_TRAFFIC = 3, 387 BT_HIGH_TRAFFIC = 3,
388
389 BT_MAX_AG,
388}; /* BT_COEX_BT_ACTIVITY_GRADING_API_E_VER_1 */ 390}; /* BT_COEX_BT_ACTIVITY_GRADING_API_E_VER_1 */
389 391
390enum iwl_bt_ci_compliance { 392enum iwl_bt_ci_compliance {
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index b8e4e78d601b..95f5b3274efb 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -133,6 +133,7 @@ enum {
133 /* Scan offload */ 133 /* Scan offload */
134 SCAN_OFFLOAD_REQUEST_CMD = 0x51, 134 SCAN_OFFLOAD_REQUEST_CMD = 0x51,
135 SCAN_OFFLOAD_ABORT_CMD = 0x52, 135 SCAN_OFFLOAD_ABORT_CMD = 0x52,
136 HOT_SPOT_CMD = 0x53,
136 SCAN_OFFLOAD_COMPLETE = 0x6D, 137 SCAN_OFFLOAD_COMPLETE = 0x6D,
137 SCAN_OFFLOAD_UPDATE_PROFILES_CMD = 0x6E, 138 SCAN_OFFLOAD_UPDATE_PROFILES_CMD = 0x6E,
138 SCAN_OFFLOAD_CONFIG_CMD = 0x6f, 139 SCAN_OFFLOAD_CONFIG_CMD = 0x6f,
@@ -910,6 +911,72 @@ struct iwl_phy_context_cmd {
910 __le32 dsp_cfg_flags; 911 __le32 dsp_cfg_flags;
911} __packed; /* PHY_CONTEXT_CMD_API_VER_1 */ 912} __packed; /* PHY_CONTEXT_CMD_API_VER_1 */
912 913
914/*
915 * Aux ROC command
916 *
917 * Command requests the firmware to create a time event for a certain duration
918 * and remain on the given channel. This is done by using the Aux framework in
919 * the FW.
920 * The command was first used for Hot Spot issues - but can be used regardless
921 * to Hot Spot.
922 *
923 * ( HOT_SPOT_CMD 0x53 )
924 *
925 * @id_and_color: ID and color of the MAC
926 * @action: action to perform, one of FW_CTXT_ACTION_*
927 * @event_unique_id: If the action FW_CTXT_ACTION_REMOVE then the
928 * event_unique_id should be the id of the time event assigned by ucode.
929 * Otherwise ignore the event_unique_id.
930 * @sta_id_and_color: station id and color, resumed during "Remain On Channel"
931 * activity.
932 * @channel_info: channel info
933 * @node_addr: Our MAC Address
934 * @reserved: reserved for alignment
935 * @apply_time: GP2 value to start (should always be the current GP2 value)
936 * @apply_time_max_delay: Maximum apply time delay value in TU. Defines max
937 * time by which start of the event is allowed to be postponed.
938 * @duration: event duration in TU To calculate event duration:
939 * timeEventDuration = min(duration, remainingQuota)
940 */
941struct iwl_hs20_roc_req {
942 /* COMMON_INDEX_HDR_API_S_VER_1 hdr */
943 __le32 id_and_color;
944 __le32 action;
945 __le32 event_unique_id;
946 __le32 sta_id_and_color;
947 struct iwl_fw_channel_info channel_info;
948 u8 node_addr[ETH_ALEN];
949 __le16 reserved;
950 __le32 apply_time;
951 __le32 apply_time_max_delay;
952 __le32 duration;
953} __packed; /* HOT_SPOT_CMD_API_S_VER_1 */
954
955/*
956 * values for AUX ROC result values
957 */
958enum iwl_mvm_hot_spot {
959 HOT_SPOT_RSP_STATUS_OK,
960 HOT_SPOT_RSP_STATUS_TOO_MANY_EVENTS,
961 HOT_SPOT_MAX_NUM_OF_SESSIONS,
962};
963
964/*
965 * Aux ROC command response
966 *
967 * In response to iwl_hs20_roc_req the FW sends this command to notify the
968 * driver the uid of the timevent.
969 *
970 * ( HOT_SPOT_CMD 0x53 )
971 *
972 * @event_unique_id: Unique ID of time event assigned by ucode
973 * @status: Return status 0 is success, all the rest used for specific errors
974 */
975struct iwl_hs20_roc_res {
976 __le32 event_unique_id;
977 __le32 status;
978} __packed; /* HOT_SPOT_RSP_API_S_VER_1 */
979
913#define IWL_RX_INFO_PHY_CNT 8 980#define IWL_RX_INFO_PHY_CNT 8
914#define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1 981#define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1
915#define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff 982#define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
index 96b9cf8137e7..0e523e28cabf 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -1074,8 +1074,12 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
1074 /* Fill the common data for all mac context types */ 1074 /* Fill the common data for all mac context types */
1075 iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); 1075 iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
1076 1076
1077 /* Also enable probe requests to pass */ 1077 /*
1078 cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); 1078 * pass probe requests and beacons from other APs (needed
1079 * for ht protection)
1080 */
1081 cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST |
1082 MAC_FILTER_IN_BEACON);
1079 1083
1080 /* Fill the data specific for ap mode */ 1084 /* Fill the data specific for ap mode */
1081 iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap, 1085 iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap,
@@ -1096,6 +1100,13 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
1096 /* Fill the common data for all mac context types */ 1100 /* Fill the common data for all mac context types */
1097 iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); 1101 iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
1098 1102
1103 /*
1104 * pass probe requests and beacons from other APs (needed
1105 * for ht protection)
1106 */
1107 cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST |
1108 MAC_FILTER_IN_BEACON);
1109
1099 /* Fill the data specific for GO mode */ 1110 /* Fill the data specific for GO mode */
1100 iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap, 1111 iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap,
1101 action == FW_CTXT_ACTION_ADD); 1112 action == FW_CTXT_ACTION_ADD);
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 2eb6ebee4467..0d6a8b768a68 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -211,7 +211,9 @@ void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
211 return; 211 return;
212 212
213 IWL_DEBUG_RPM(mvm, "Take mvm reference - type %d\n", ref_type); 213 IWL_DEBUG_RPM(mvm, "Take mvm reference - type %d\n", ref_type);
214 WARN_ON(test_and_set_bit(ref_type, mvm->ref_bitmap)); 214 spin_lock_bh(&mvm->refs_lock);
215 mvm->refs[ref_type]++;
216 spin_unlock_bh(&mvm->refs_lock);
215 iwl_trans_ref(mvm->trans); 217 iwl_trans_ref(mvm->trans);
216} 218}
217 219
@@ -221,29 +223,35 @@ void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
221 return; 223 return;
222 224
223 IWL_DEBUG_RPM(mvm, "Leave mvm reference - type %d\n", ref_type); 225 IWL_DEBUG_RPM(mvm, "Leave mvm reference - type %d\n", ref_type);
224 WARN_ON(!test_and_clear_bit(ref_type, mvm->ref_bitmap)); 226 spin_lock_bh(&mvm->refs_lock);
227 WARN_ON(!mvm->refs[ref_type]--);
228 spin_unlock_bh(&mvm->refs_lock);
225 iwl_trans_unref(mvm->trans); 229 iwl_trans_unref(mvm->trans);
226} 230}
227 231
228static void 232static void iwl_mvm_unref_all_except(struct iwl_mvm *mvm,
229iwl_mvm_unref_all_except(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref) 233 enum iwl_mvm_ref_type except_ref)
230{ 234{
231 int i; 235 int i, j;
232 236
233 if (!iwl_mvm_is_d0i3_supported(mvm)) 237 if (!iwl_mvm_is_d0i3_supported(mvm))
234 return; 238 return;
235 239
236 for_each_set_bit(i, mvm->ref_bitmap, IWL_MVM_REF_COUNT) { 240 spin_lock_bh(&mvm->refs_lock);
237 if (ref == i) 241 for (i = 0; i < IWL_MVM_REF_COUNT; i++) {
242 if (except_ref == i || !mvm->refs[i])
238 continue; 243 continue;
239 244
240 IWL_DEBUG_RPM(mvm, "Cleanup: remove mvm ref type %d\n", i); 245 IWL_DEBUG_RPM(mvm, "Cleanup: remove mvm ref type %d (%d)\n",
241 clear_bit(i, mvm->ref_bitmap); 246 i, mvm->refs[i]);
242 iwl_trans_unref(mvm->trans); 247 for (j = 0; j < mvm->refs[i]; j++)
248 iwl_trans_unref(mvm->trans);
249 mvm->refs[i] = 0;
243 } 250 }
251 spin_unlock_bh(&mvm->refs_lock);
244} 252}
245 253
246static int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type) 254int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
247{ 255{
248 iwl_mvm_ref(mvm, ref_type); 256 iwl_mvm_ref(mvm, ref_type);
249 257
@@ -321,13 +329,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
321 hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; 329 hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
322 } 330 }
323 331
324 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT &&
325 !iwlwifi_mod_params.uapsd_disable) {
326 hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD;
327 hw->uapsd_queues = IWL_UAPSD_AC_INFO;
328 hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
329 }
330
331 if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) 332 if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
332 hw->flags |= IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS; 333 hw->flags |= IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS;
333 334
@@ -660,6 +661,7 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
660 spin_unlock_bh(&mvm->time_event_lock); 661 spin_unlock_bh(&mvm->time_event_lock);
661 662
662 mvmvif->phy_ctxt = NULL; 663 mvmvif->phy_ctxt = NULL;
664 memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data));
663} 665}
664 666
665#ifdef CONFIG_IWLWIFI_DEBUGFS 667#ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -668,11 +670,11 @@ static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
668 struct iwl_fw_error_dump_file *dump_file; 670 struct iwl_fw_error_dump_file *dump_file;
669 struct iwl_fw_error_dump_data *dump_data; 671 struct iwl_fw_error_dump_data *dump_data;
670 struct iwl_fw_error_dump_info *dump_info; 672 struct iwl_fw_error_dump_info *dump_info;
673 struct iwl_mvm_dump_ptrs *fw_error_dump;
671 const struct fw_img *img; 674 const struct fw_img *img;
672 u32 sram_len, sram_ofs; 675 u32 sram_len, sram_ofs;
673 u32 file_len, rxf_len; 676 u32 file_len, rxf_len;
674 unsigned long flags; 677 unsigned long flags;
675 u32 trans_len;
676 int reg_val; 678 int reg_val;
677 679
678 lockdep_assert_held(&mvm->mutex); 680 lockdep_assert_held(&mvm->mutex);
@@ -680,6 +682,10 @@ static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
680 if (mvm->fw_error_dump) 682 if (mvm->fw_error_dump)
681 return; 683 return;
682 684
685 fw_error_dump = kzalloc(sizeof(*mvm->fw_error_dump), GFP_KERNEL);
686 if (!fw_error_dump)
687 return;
688
683 img = &mvm->fw->img[mvm->cur_ucode]; 689 img = &mvm->fw->img[mvm->cur_ucode];
684 sram_ofs = img->sec[IWL_UCODE_SECTION_DATA].offset; 690 sram_ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
685 sram_len = img->sec[IWL_UCODE_SECTION_DATA].len; 691 sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
@@ -697,18 +703,15 @@ static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
697 rxf_len + 703 rxf_len +
698 sizeof(*dump_info); 704 sizeof(*dump_info);
699 705
700 trans_len = iwl_trans_dump_data(mvm->trans, NULL, 0);
701 if (trans_len)
702 file_len += trans_len;
703
704 dump_file = vzalloc(file_len); 706 dump_file = vzalloc(file_len);
705 if (!dump_file) 707 if (!dump_file) {
708 kfree(fw_error_dump);
706 return; 709 return;
710 }
707 711
708 mvm->fw_error_dump = dump_file; 712 fw_error_dump->op_mode_ptr = dump_file;
709 713
710 dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER); 714 dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER);
711 dump_file->file_len = cpu_to_le32(file_len);
712 dump_data = (void *)dump_file->data; 715 dump_data = (void *)dump_file->data;
713 716
714 dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO); 717 dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO);
@@ -749,14 +752,12 @@ static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
749 iwl_trans_read_mem_bytes(mvm->trans, sram_ofs, dump_data->data, 752 iwl_trans_read_mem_bytes(mvm->trans, sram_ofs, dump_data->data,
750 sram_len); 753 sram_len);
751 754
752 if (trans_len) { 755 fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans);
753 void *buf = iwl_fw_error_next_data(dump_data); 756 fw_error_dump->op_mode_len = file_len;
754 u32 real_trans_len = iwl_trans_dump_data(mvm->trans, buf, 757 if (fw_error_dump->trans_ptr)
755 trans_len); 758 file_len += fw_error_dump->trans_ptr->len;
756 dump_data = (void *)((u8 *)buf + real_trans_len); 759 dump_file->file_len = cpu_to_le32(file_len);
757 dump_file->file_len = 760 mvm->fw_error_dump = fw_error_dump;
758 cpu_to_le32(file_len - trans_len + real_trans_len);
759 }
760} 761}
761#endif 762#endif
762 763
@@ -788,6 +789,12 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
788 iwl_mvm_reset_phy_ctxts(mvm); 789 iwl_mvm_reset_phy_ctxts(mvm);
789 memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); 790 memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
790 memset(mvm->sta_drained, 0, sizeof(mvm->sta_drained)); 791 memset(mvm->sta_drained, 0, sizeof(mvm->sta_drained));
792 memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
793 memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old));
794 memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd));
795 memset(&mvm->last_bt_ci_cmd_old, 0, sizeof(mvm->last_bt_ci_cmd_old));
796 memset(&mvm->bt_ack_kill_msk, 0, sizeof(mvm->bt_ack_kill_msk));
797 memset(&mvm->bt_cts_kill_msk, 0, sizeof(mvm->bt_cts_kill_msk));
791 798
792 ieee80211_wake_queues(mvm->hw); 799 ieee80211_wake_queues(mvm->hw);
793 800
@@ -1399,6 +1406,28 @@ static inline int iwl_mvm_configure_bcast_filter(struct iwl_mvm *mvm,
1399} 1406}
1400#endif 1407#endif
1401 1408
1409static void iwl_mvm_teardown_tdls_peers(struct iwl_mvm *mvm)
1410{
1411 struct ieee80211_sta *sta;
1412 struct iwl_mvm_sta *mvmsta;
1413 int i;
1414
1415 lockdep_assert_held(&mvm->mutex);
1416
1417 for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
1418 sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
1419 lockdep_is_held(&mvm->mutex));
1420 if (!sta || IS_ERR(sta) || !sta->tdls)
1421 continue;
1422
1423 mvmsta = iwl_mvm_sta_from_mac80211(sta);
1424 ieee80211_tdls_oper_request(mvmsta->vif, sta->addr,
1425 NL80211_TDLS_TEARDOWN,
1426 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED,
1427 GFP_KERNEL);
1428 }
1429}
1430
1402static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, 1431static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
1403 struct ieee80211_vif *vif, 1432 struct ieee80211_vif *vif,
1404 struct ieee80211_bss_conf *bss_conf, 1433 struct ieee80211_bss_conf *bss_conf,
@@ -1494,14 +1523,18 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
1494 */ 1523 */
1495 iwl_mvm_remove_time_event(mvm, mvmvif, 1524 iwl_mvm_remove_time_event(mvm, mvmvif,
1496 &mvmvif->time_event_data); 1525 &mvmvif->time_event_data);
1497 iwl_mvm_sf_update(mvm, vif, false);
1498 WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
1499 } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | 1526 } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS |
1500 BSS_CHANGED_QOS)) { 1527 BSS_CHANGED_QOS)) {
1501 ret = iwl_mvm_power_update_mac(mvm); 1528 ret = iwl_mvm_power_update_mac(mvm);
1502 if (ret) 1529 if (ret)
1503 IWL_ERR(mvm, "failed to update power mode\n"); 1530 IWL_ERR(mvm, "failed to update power mode\n");
1504 } 1531 }
1532
1533 if (changes & BSS_CHANGED_BEACON_INFO) {
1534 iwl_mvm_sf_update(mvm, vif, false);
1535 WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
1536 }
1537
1505 if (changes & BSS_CHANGED_TXPOWER) { 1538 if (changes & BSS_CHANGED_TXPOWER) {
1506 IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d\n", 1539 IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d\n",
1507 bss_conf->txpower); 1540 bss_conf->txpower);
@@ -1533,6 +1566,14 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
1533 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 1566 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1534 int ret; 1567 int ret;
1535 1568
1569 /*
1570 * iwl_mvm_mac_ctxt_add() might read directly from the device
1571 * (the system time), so make sure it is available.
1572 */
1573 ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_START_AP);
1574 if (ret)
1575 return ret;
1576
1536 mutex_lock(&mvm->mutex); 1577 mutex_lock(&mvm->mutex);
1537 1578
1538 /* Send the beacon template */ 1579 /* Send the beacon template */
@@ -1581,6 +1622,10 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
1581 1622
1582 iwl_mvm_bt_coex_vif_change(mvm); 1623 iwl_mvm_bt_coex_vif_change(mvm);
1583 1624
1625 /* we don't support TDLS during DCM */
1626 if (iwl_mvm_phy_ctx_count(mvm) > 1)
1627 iwl_mvm_teardown_tdls_peers(mvm);
1628
1584 mutex_unlock(&mvm->mutex); 1629 mutex_unlock(&mvm->mutex);
1585 return 0; 1630 return 0;
1586 1631
@@ -1594,6 +1639,7 @@ out_remove:
1594 iwl_mvm_mac_ctxt_remove(mvm, vif); 1639 iwl_mvm_mac_ctxt_remove(mvm, vif);
1595out_unlock: 1640out_unlock:
1596 mutex_unlock(&mvm->mutex); 1641 mutex_unlock(&mvm->mutex);
1642 iwl_mvm_unref(mvm, IWL_MVM_REF_START_AP);
1597 return ret; 1643 return ret;
1598} 1644}
1599 1645
@@ -1671,6 +1717,14 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
1671{ 1717{
1672 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 1718 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1673 1719
1720 /*
1721 * iwl_mvm_bss_info_changed_station() might call
1722 * iwl_mvm_protect_session(), which reads directly from
1723 * the device (the system time), so make sure it is available.
1724 */
1725 if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_BSS_CHANGED))
1726 return;
1727
1674 mutex_lock(&mvm->mutex); 1728 mutex_lock(&mvm->mutex);
1675 1729
1676 if (changes & BSS_CHANGED_IDLE && !bss_conf->idle) 1730 if (changes & BSS_CHANGED_IDLE && !bss_conf->idle)
@@ -1690,8 +1744,50 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
1690 } 1744 }
1691 1745
1692 mutex_unlock(&mvm->mutex); 1746 mutex_unlock(&mvm->mutex);
1747 iwl_mvm_unref(mvm, IWL_MVM_REF_BSS_CHANGED);
1693} 1748}
1694 1749
1750static int iwl_mvm_cancel_scan_wait_notif(struct iwl_mvm *mvm,
1751 enum iwl_scan_status scan_type)
1752{
1753 int ret;
1754 bool wait_for_handlers = false;
1755
1756 mutex_lock(&mvm->mutex);
1757
1758 if (mvm->scan_status != scan_type) {
1759 ret = 0;
1760 /* make sure there are no pending notifications */
1761 wait_for_handlers = true;
1762 goto out;
1763 }
1764
1765 switch (scan_type) {
1766 case IWL_MVM_SCAN_SCHED:
1767 ret = iwl_mvm_scan_offload_stop(mvm, true);
1768 break;
1769 case IWL_MVM_SCAN_OS:
1770 ret = iwl_mvm_cancel_scan(mvm);
1771 break;
1772 case IWL_MVM_SCAN_NONE:
1773 default:
1774 WARN_ON_ONCE(1);
1775 ret = -EINVAL;
1776 break;
1777 }
1778 if (ret)
1779 goto out;
1780
1781 wait_for_handlers = true;
1782out:
1783 mutex_unlock(&mvm->mutex);
1784
1785 /* make sure we consume the completion notification */
1786 if (wait_for_handlers)
1787 iwl_mvm_wait_for_async_handlers(mvm);
1788
1789 return ret;
1790}
1695static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, 1791static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
1696 struct ieee80211_vif *vif, 1792 struct ieee80211_vif *vif,
1697 struct ieee80211_scan_request *hw_req) 1793 struct ieee80211_scan_request *hw_req)
@@ -1704,19 +1800,13 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
1704 req->n_channels > mvm->fw->ucode_capa.n_scan_channels) 1800 req->n_channels > mvm->fw->ucode_capa.n_scan_channels)
1705 return -EINVAL; 1801 return -EINVAL;
1706 1802
1803 ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_SCHED);
1804 if (ret)
1805 return ret;
1806
1707 mutex_lock(&mvm->mutex); 1807 mutex_lock(&mvm->mutex);
1708 1808
1709 switch (mvm->scan_status) { 1809 if (mvm->scan_status != IWL_MVM_SCAN_NONE) {
1710 case IWL_MVM_SCAN_SCHED:
1711 ret = iwl_mvm_scan_offload_stop(mvm, true);
1712 if (ret) {
1713 ret = -EBUSY;
1714 goto out;
1715 }
1716 break;
1717 case IWL_MVM_SCAN_NONE:
1718 break;
1719 default:
1720 ret = -EBUSY; 1810 ret = -EBUSY;
1721 goto out; 1811 goto out;
1722 } 1812 }
@@ -1732,8 +1822,6 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
1732 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); 1822 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
1733out: 1823out:
1734 mutex_unlock(&mvm->mutex); 1824 mutex_unlock(&mvm->mutex);
1735 /* make sure to flush the Rx handler before the next scan arrives */
1736 iwl_mvm_wait_for_async_handlers(mvm);
1737 return ret; 1825 return ret;
1738} 1826}
1739 1827
@@ -1885,28 +1973,6 @@ static void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm,
1885 iwl_mvm_power_update_mac(mvm); 1973 iwl_mvm_power_update_mac(mvm);
1886} 1974}
1887 1975
1888static void iwl_mvm_teardown_tdls_peers(struct iwl_mvm *mvm)
1889{
1890 struct ieee80211_sta *sta;
1891 struct iwl_mvm_sta *mvmsta;
1892 int i;
1893
1894 lockdep_assert_held(&mvm->mutex);
1895
1896 for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
1897 sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
1898 lockdep_is_held(&mvm->mutex));
1899 if (!sta || IS_ERR(sta) || !sta->tdls)
1900 continue;
1901
1902 mvmsta = iwl_mvm_sta_from_mac80211(sta);
1903 ieee80211_tdls_oper_request(mvmsta->vif, sta->addr,
1904 NL80211_TDLS_TEARDOWN,
1905 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED,
1906 GFP_KERNEL);
1907 }
1908}
1909
1910static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, 1976static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
1911 struct ieee80211_vif *vif, 1977 struct ieee80211_vif *vif,
1912 struct ieee80211_sta *sta, 1978 struct ieee80211_sta *sta,
@@ -2065,10 +2131,19 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
2065 if (WARN_ON_ONCE(vif->bss_conf.assoc)) 2131 if (WARN_ON_ONCE(vif->bss_conf.assoc))
2066 return; 2132 return;
2067 2133
2134 /*
2135 * iwl_mvm_protect_session() reads directly from the device
2136 * (the system time), so make sure it is available.
2137 */
2138 if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PREPARE_TX))
2139 return;
2140
2068 mutex_lock(&mvm->mutex); 2141 mutex_lock(&mvm->mutex);
2069 /* Try really hard to protect the session and hear a beacon */ 2142 /* Try really hard to protect the session and hear a beacon */
2070 iwl_mvm_protect_session(mvm, vif, duration, min_duration, 500); 2143 iwl_mvm_protect_session(mvm, vif, duration, min_duration, 500);
2071 mutex_unlock(&mvm->mutex); 2144 mutex_unlock(&mvm->mutex);
2145
2146 iwl_mvm_unref(mvm, IWL_MVM_REF_PREPARE_TX);
2072} 2147}
2073 2148
2074static void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw, 2149static void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
@@ -2077,10 +2152,19 @@ static void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
2077 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 2152 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
2078 u32 duration = 2 * vif->bss_conf.dtim_period * vif->bss_conf.beacon_int; 2153 u32 duration = 2 * vif->bss_conf.dtim_period * vif->bss_conf.beacon_int;
2079 2154
2155 /*
2156 * iwl_mvm_protect_session() reads directly from the device
2157 * (the system time), so make sure it is available.
2158 */
2159 if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_TDLS))
2160 return;
2161
2080 mutex_lock(&mvm->mutex); 2162 mutex_lock(&mvm->mutex);
2081 /* Protect the session to hear the TDLS setup response on the channel */ 2163 /* Protect the session to hear the TDLS setup response on the channel */
2082 iwl_mvm_protect_session(mvm, vif, duration, duration, 100); 2164 iwl_mvm_protect_session(mvm, vif, duration, duration, 100);
2083 mutex_unlock(&mvm->mutex); 2165 mutex_unlock(&mvm->mutex);
2166
2167 iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_TDLS);
2084} 2168}
2085 2169
2086static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw, 2170static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
@@ -2091,6 +2175,10 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
2091 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 2175 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
2092 int ret; 2176 int ret;
2093 2177
2178 ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_OS);
2179 if (ret)
2180 return ret;
2181
2094 mutex_lock(&mvm->mutex); 2182 mutex_lock(&mvm->mutex);
2095 2183
2096 if (!iwl_mvm_is_idle(mvm)) { 2184 if (!iwl_mvm_is_idle(mvm)) {
@@ -2098,26 +2186,7 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
2098 goto out; 2186 goto out;
2099 } 2187 }
2100 2188
2101 switch (mvm->scan_status) { 2189 if (mvm->scan_status != IWL_MVM_SCAN_NONE) {
2102 case IWL_MVM_SCAN_OS:
2103 IWL_DEBUG_SCAN(mvm, "Stopping previous scan for sched_scan\n");
2104 ret = iwl_mvm_cancel_scan(mvm);
2105 if (ret) {
2106 ret = -EBUSY;
2107 goto out;
2108 }
2109
2110 /*
2111 * iwl_mvm_rx_scan_complete() will be called soon but will
2112 * not reset the scan status as it won't be IWL_MVM_SCAN_OS
2113 * any more since we queue the next scan immediately (below).
2114 * We make sure it is called before the next scan starts by
2115 * flushing the async-handlers work.
2116 */
2117 break;
2118 case IWL_MVM_SCAN_NONE:
2119 break;
2120 default:
2121 ret = -EBUSY; 2190 ret = -EBUSY;
2122 goto out; 2191 goto out;
2123 } 2192 }
@@ -2145,8 +2214,6 @@ err:
2145 mvm->scan_status = IWL_MVM_SCAN_NONE; 2214 mvm->scan_status = IWL_MVM_SCAN_NONE;
2146out: 2215out:
2147 mutex_unlock(&mvm->mutex); 2216 mutex_unlock(&mvm->mutex);
2148 /* make sure to flush the Rx handler before the next scan arrives */
2149 iwl_mvm_wait_for_async_handlers(mvm);
2150 return ret; 2217 return ret;
2151} 2218}
2152 2219
@@ -2266,6 +2333,119 @@ static void iwl_mvm_mac_update_tkip_key(struct ieee80211_hw *hw,
2266} 2333}
2267 2334
2268 2335
2336static bool iwl_mvm_rx_aux_roc(struct iwl_notif_wait_data *notif_wait,
2337 struct iwl_rx_packet *pkt, void *data)
2338{
2339 struct iwl_mvm *mvm =
2340 container_of(notif_wait, struct iwl_mvm, notif_wait);
2341 struct iwl_hs20_roc_res *resp;
2342 int resp_len = iwl_rx_packet_payload_len(pkt);
2343 struct iwl_mvm_time_event_data *te_data = data;
2344
2345 if (WARN_ON(pkt->hdr.cmd != HOT_SPOT_CMD))
2346 return true;
2347
2348 if (WARN_ON_ONCE(resp_len != sizeof(*resp))) {
2349 IWL_ERR(mvm, "Invalid HOT_SPOT_CMD response\n");
2350 return true;
2351 }
2352
2353 resp = (void *)pkt->data;
2354
2355 IWL_DEBUG_TE(mvm,
2356 "Aux ROC: Recieved response from ucode: status=%d uid=%d\n",
2357 resp->status, resp->event_unique_id);
2358
2359 te_data->uid = le32_to_cpu(resp->event_unique_id);
2360 IWL_DEBUG_TE(mvm, "TIME_EVENT_CMD response - UID = 0x%x\n",
2361 te_data->uid);
2362
2363 spin_lock_bh(&mvm->time_event_lock);
2364 list_add_tail(&te_data->list, &mvm->aux_roc_te_list);
2365 spin_unlock_bh(&mvm->time_event_lock);
2366
2367 return true;
2368}
2369
2370#define AUX_ROC_MAX_DELAY_ON_CHANNEL 5000
2371static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
2372 struct ieee80211_channel *channel,
2373 struct ieee80211_vif *vif,
2374 int duration)
2375{
2376 int res, time_reg = DEVICE_SYSTEM_TIME_REG;
2377 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
2378 struct iwl_mvm_time_event_data *te_data = &mvmvif->hs_time_event_data;
2379 static const u8 time_event_response[] = { HOT_SPOT_CMD };
2380 struct iwl_notification_wait wait_time_event;
2381 struct iwl_hs20_roc_req aux_roc_req = {
2382 .action = cpu_to_le32(FW_CTXT_ACTION_ADD),
2383 .id_and_color =
2384 cpu_to_le32(FW_CMD_ID_AND_COLOR(MAC_INDEX_AUX, 0)),
2385 .sta_id_and_color = cpu_to_le32(mvm->aux_sta.sta_id),
2386 /* Set the channel info data */
2387 .channel_info.band = (channel->band == IEEE80211_BAND_2GHZ) ?
2388 PHY_BAND_24 : PHY_BAND_5,
2389 .channel_info.channel = channel->hw_value,
2390 .channel_info.width = PHY_VHT_CHANNEL_MODE20,
2391 /* Set the time and duration */
2392 .apply_time = cpu_to_le32(iwl_read_prph(mvm->trans, time_reg)),
2393 .apply_time_max_delay =
2394 cpu_to_le32(MSEC_TO_TU(AUX_ROC_MAX_DELAY_ON_CHANNEL)),
2395 .duration = cpu_to_le32(MSEC_TO_TU(duration)),
2396 };
2397
2398 /* Set the node address */
2399 memcpy(aux_roc_req.node_addr, vif->addr, ETH_ALEN);
2400
2401 te_data->vif = vif;
2402 te_data->duration = duration;
2403 te_data->id = HOT_SPOT_CMD;
2404
2405 lockdep_assert_held(&mvm->mutex);
2406
2407 spin_lock_bh(&mvm->time_event_lock);
2408 list_add_tail(&te_data->list, &mvm->time_event_list);
2409 spin_unlock_bh(&mvm->time_event_lock);
2410
2411 /*
2412 * Use a notification wait, which really just processes the
2413 * command response and doesn't wait for anything, in order
2414 * to be able to process the response and get the UID inside
2415 * the RX path. Using CMD_WANT_SKB doesn't work because it
2416 * stores the buffer and then wakes up this thread, by which
2417 * time another notification (that the time event started)
2418 * might already be processed unsuccessfully.
2419 */
2420 iwl_init_notification_wait(&mvm->notif_wait, &wait_time_event,
2421 time_event_response,
2422 ARRAY_SIZE(time_event_response),
2423 iwl_mvm_rx_aux_roc, te_data);
2424
2425 res = iwl_mvm_send_cmd_pdu(mvm, HOT_SPOT_CMD, 0, sizeof(aux_roc_req),
2426 &aux_roc_req);
2427
2428 if (res) {
2429 IWL_ERR(mvm, "Couldn't send HOT_SPOT_CMD: %d\n", res);
2430 iwl_remove_notification(&mvm->notif_wait, &wait_time_event);
2431 goto out_clear_te;
2432 }
2433
2434 /* No need to wait for anything, so just pass 1 (0 isn't valid) */
2435 res = iwl_wait_notification(&mvm->notif_wait, &wait_time_event, 1);
2436 /* should never fail */
2437 WARN_ON_ONCE(res);
2438
2439 if (res) {
2440 out_clear_te:
2441 spin_lock_bh(&mvm->time_event_lock);
2442 iwl_mvm_te_clear_data(mvm, te_data);
2443 spin_unlock_bh(&mvm->time_event_lock);
2444 }
2445
2446 return res;
2447}
2448
2269static int iwl_mvm_roc(struct ieee80211_hw *hw, 2449static int iwl_mvm_roc(struct ieee80211_hw *hw,
2270 struct ieee80211_vif *vif, 2450 struct ieee80211_vif *vif,
2271 struct ieee80211_channel *channel, 2451 struct ieee80211_channel *channel,
@@ -2281,8 +2461,17 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
2281 IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value, 2461 IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value,
2282 duration, type); 2462 duration, type);
2283 2463
2284 if (vif->type != NL80211_IFTYPE_P2P_DEVICE) { 2464 switch (vif->type) {
2285 IWL_ERR(mvm, "vif isn't a P2P_DEVICE: %d\n", vif->type); 2465 case NL80211_IFTYPE_STATION:
2466 /* Use aux roc framework (HS20) */
2467 ret = iwl_mvm_send_aux_roc_cmd(mvm, channel,
2468 vif, duration);
2469 return ret;
2470 case NL80211_IFTYPE_P2P_DEVICE:
2471 /* handle below */
2472 break;
2473 default:
2474 IWL_ERR(mvm, "vif isn't P2P_DEVICE: %d\n", vif->type);
2286 return -EINVAL; 2475 return -EINVAL;
2287 } 2476 }
2288 2477
@@ -2661,6 +2850,10 @@ static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,
2661 goto out_remove; 2850 goto out_remove;
2662 } 2851 }
2663 2852
2853 /* we don't support TDLS during DCM - can be caused by channel switch */
2854 if (iwl_mvm_phy_ctx_count(mvm) > 1)
2855 iwl_mvm_teardown_tdls_peers(mvm);
2856
2664 goto out; 2857 goto out;
2665 2858
2666out_remove: 2859out_remove:
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 785e5232c757..2e73d3bd7757 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -82,6 +82,8 @@
82/* RSSI offset for WkP */ 82/* RSSI offset for WkP */
83#define IWL_RSSI_OFFSET 50 83#define IWL_RSSI_OFFSET 50
84#define IWL_MVM_MISSED_BEACONS_THRESHOLD 8 84#define IWL_MVM_MISSED_BEACONS_THRESHOLD 8
85/* A TimeUnit is 1024 microsecond */
86#define MSEC_TO_TU(_msec) (_msec*1000/1024)
85 87
86/* 88/*
87 * The CSA NoA is scheduled IWL_MVM_CHANNEL_SWITCH_TIME TUs before "beacon 0" 89 * The CSA NoA is scheduled IWL_MVM_CHANNEL_SWITCH_TIME TUs before "beacon 0"
@@ -126,6 +128,21 @@ struct iwl_mvm_mod_params {
126}; 128};
127extern struct iwl_mvm_mod_params iwlmvm_mod_params; 129extern struct iwl_mvm_mod_params iwlmvm_mod_params;
128 130
131/**
132 * struct iwl_mvm_dump_ptrs - set of pointers needed for the fw-error-dump
133 *
134 * @op_mode_ptr: pointer to the buffer coming from the mvm op_mode
135 * @trans_ptr: pointer to struct %iwl_trans_dump_data which contains the
136 * transport's data.
137 * @trans_len: length of the valid data in trans_ptr
138 * @op_mode_len: length of the valid data in op_mode_ptr
139 */
140struct iwl_mvm_dump_ptrs {
141 struct iwl_trans_dump_data *trans_ptr;
142 void *op_mode_ptr;
143 u32 op_mode_len;
144};
145
129struct iwl_mvm_phy_ctxt { 146struct iwl_mvm_phy_ctxt {
130 u16 id; 147 u16 id;
131 u16 color; 148 u16 color;
@@ -249,6 +266,15 @@ enum iwl_mvm_ref_type {
249 IWL_MVM_REF_TX, 266 IWL_MVM_REF_TX,
250 IWL_MVM_REF_TX_AGG, 267 IWL_MVM_REF_TX_AGG,
251 IWL_MVM_REF_ADD_IF, 268 IWL_MVM_REF_ADD_IF,
269 IWL_MVM_REF_START_AP,
270 IWL_MVM_REF_BSS_CHANGED,
271 IWL_MVM_REF_PREPARE_TX,
272 IWL_MVM_REF_PROTECT_TDLS,
273 IWL_MVM_REF_CHECK_CTKILL,
274 IWL_MVM_REF_PRPH_READ,
275 IWL_MVM_REF_PRPH_WRITE,
276 IWL_MVM_REF_NMI,
277 IWL_MVM_REF_TM_CMD,
252 IWL_MVM_REF_EXIT_WORK, 278 IWL_MVM_REF_EXIT_WORK,
253 279
254 IWL_MVM_REF_COUNT, 280 IWL_MVM_REF_COUNT,
@@ -327,6 +353,7 @@ struct iwl_mvm_vif {
327 */ 353 */
328 struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS]; 354 struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
329 struct iwl_mvm_time_event_data time_event_data; 355 struct iwl_mvm_time_event_data time_event_data;
356 struct iwl_mvm_time_event_data hs_time_event_data;
330 357
331 struct iwl_mvm_int_sta bcast_sta; 358 struct iwl_mvm_int_sta bcast_sta;
332 359
@@ -606,14 +633,15 @@ struct iwl_mvm {
606 */ 633 */
607 unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)]; 634 unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)];
608 635
609 /* A bitmap of reference types taken by the driver. */ 636 /* references taken by the driver and spinlock protecting them */
610 unsigned long ref_bitmap[BITS_TO_LONGS(IWL_MVM_REF_COUNT)]; 637 spinlock_t refs_lock;
638 u8 refs[IWL_MVM_REF_COUNT];
611 639
612 u8 vif_count; 640 u8 vif_count;
613 641
614 /* -1 for always, 0 for never, >0 for that many times */ 642 /* -1 for always, 0 for never, >0 for that many times */
615 s8 restart_fw; 643 s8 restart_fw;
616 void *fw_error_dump; 644 struct iwl_mvm_dump_ptrs *fw_error_dump;
617 645
618#ifdef CONFIG_IWLWIFI_LEDS 646#ifdef CONFIG_IWLWIFI_LEDS
619 struct led_classdev led; 647 struct led_classdev led;
@@ -647,7 +675,8 @@ struct iwl_mvm {
647 wait_queue_head_t d0i3_exit_waitq; 675 wait_queue_head_t d0i3_exit_waitq;
648 676
649 /* BT-Coex */ 677 /* BT-Coex */
650 u8 bt_kill_msk; 678 u8 bt_ack_kill_msk[NUM_PHY_CTX];
679 u8 bt_cts_kill_msk[NUM_PHY_CTX];
651 680
652 struct iwl_bt_coex_profile_notif_old last_bt_notif_old; 681 struct iwl_bt_coex_profile_notif_old last_bt_notif_old;
653 struct iwl_bt_coex_ci_cmd_old last_bt_ci_cmd_old; 682 struct iwl_bt_coex_ci_cmd_old last_bt_ci_cmd_old;
@@ -659,6 +688,9 @@ struct iwl_mvm {
659 u8 bt_tx_prio; 688 u8 bt_tx_prio;
660 enum iwl_bt_force_ant_mode bt_force_ant_mode; 689 enum iwl_bt_force_ant_mode bt_force_ant_mode;
661 690
691 /* Aux ROC */
692 struct list_head aux_roc_te_list;
693
662 /* Thermal Throttling and CTkill */ 694 /* Thermal Throttling and CTkill */
663 struct iwl_mvm_tt_mgmt thermal_throttle; 695 struct iwl_mvm_tt_mgmt thermal_throttle;
664 s32 temperature; /* Celsius */ 696 s32 temperature; /* Celsius */
@@ -697,6 +729,7 @@ enum iwl_mvm_status {
697 IWL_MVM_STATUS_ROC_RUNNING, 729 IWL_MVM_STATUS_ROC_RUNNING,
698 IWL_MVM_STATUS_IN_HW_RESTART, 730 IWL_MVM_STATUS_IN_HW_RESTART,
699 IWL_MVM_STATUS_IN_D0I3, 731 IWL_MVM_STATUS_IN_D0I3,
732 IWL_MVM_STATUS_ROC_AUX_RUNNING,
700}; 733};
701 734
702static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm) 735static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm)
@@ -988,6 +1021,7 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
988/* D0i3 */ 1021/* D0i3 */
989void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type); 1022void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
990void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type); 1023void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
1024int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
991void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq); 1025void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq);
992int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm); 1026int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm);
993 1027
@@ -1029,12 +1063,14 @@ int iwl_mvm_rx_ant_coupling_notif_old(struct iwl_mvm *mvm,
1029 1063
1030enum iwl_bt_kill_msk { 1064enum iwl_bt_kill_msk {
1031 BT_KILL_MSK_DEFAULT, 1065 BT_KILL_MSK_DEFAULT,
1032 BT_KILL_MSK_SCO_HID_A2DP, 1066 BT_KILL_MSK_NEVER,
1033 BT_KILL_MSK_REDUCED_TXPOW, 1067 BT_KILL_MSK_ALWAYS,
1034 BT_KILL_MSK_MAX, 1068 BT_KILL_MSK_MAX,
1035}; 1069};
1036extern const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX]; 1070
1037extern const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX]; 1071extern const u8 iwl_bt_ack_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT];
1072extern const u8 iwl_bt_cts_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT];
1073extern const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX];
1038 1074
1039/* beacon filtering */ 1075/* beacon filtering */
1040#ifdef CONFIG_IWLWIFI_DEBUGFS 1076#ifdef CONFIG_IWLWIFI_DEBUGFS
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c
index b04805ccb443..cfdd314fdd5d 100644
--- a/drivers/net/wireless/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c
@@ -265,7 +265,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
265 if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) { 265 if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
266 if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data || 266 if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
267 !mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) { 267 !mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) {
268 IWL_ERR(mvm, "Can't parse empty NVM sections\n"); 268 IWL_ERR(mvm, "Can't parse empty OTP/NVM sections\n");
269 return NULL; 269 return NULL;
270 } 270 }
271 } else { 271 } else {
@@ -273,7 +273,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
273 if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data || 273 if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
274 !mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) { 274 !mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) {
275 IWL_ERR(mvm, 275 IWL_ERR(mvm,
276 "Can't parse empty family 8000 NVM sections\n"); 276 "Can't parse empty family 8000 OTP/NVM sections\n");
277 return NULL; 277 return NULL;
278 } 278 }
279 /* MAC_OVERRIDE or at least HW section must exist */ 279 /* MAC_OVERRIDE or at least HW section must exist */
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index 7d7b2fbe7cd1..610dbcb0dc27 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -289,6 +289,7 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
289 CMD(MATCH_FOUND_NOTIFICATION), 289 CMD(MATCH_FOUND_NOTIFICATION),
290 CMD(SCAN_OFFLOAD_REQUEST_CMD), 290 CMD(SCAN_OFFLOAD_REQUEST_CMD),
291 CMD(SCAN_OFFLOAD_ABORT_CMD), 291 CMD(SCAN_OFFLOAD_ABORT_CMD),
292 CMD(HOT_SPOT_CMD),
292 CMD(SCAN_OFFLOAD_COMPLETE), 293 CMD(SCAN_OFFLOAD_COMPLETE),
293 CMD(SCAN_OFFLOAD_UPDATE_PROFILES_CMD), 294 CMD(SCAN_OFFLOAD_UPDATE_PROFILES_CMD),
294 CMD(SCAN_ITERATION_COMPLETE), 295 CMD(SCAN_ITERATION_COMPLETE),
@@ -391,6 +392,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
391 if (!hw) 392 if (!hw)
392 return NULL; 393 return NULL;
393 394
395 if (cfg->max_rx_agg_size)
396 hw->max_rx_aggregation_subframes = cfg->max_rx_agg_size;
397
394 op_mode = hw->priv; 398 op_mode = hw->priv;
395 op_mode->ops = &iwl_mvm_ops; 399 op_mode->ops = &iwl_mvm_ops;
396 400
@@ -416,6 +420,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
416 mutex_init(&mvm->d0i3_suspend_mutex); 420 mutex_init(&mvm->d0i3_suspend_mutex);
417 spin_lock_init(&mvm->async_handlers_lock); 421 spin_lock_init(&mvm->async_handlers_lock);
418 INIT_LIST_HEAD(&mvm->time_event_list); 422 INIT_LIST_HEAD(&mvm->time_event_list);
423 INIT_LIST_HEAD(&mvm->aux_roc_te_list);
419 INIT_LIST_HEAD(&mvm->async_handlers_list); 424 INIT_LIST_HEAD(&mvm->async_handlers_list);
420 spin_lock_init(&mvm->time_event_lock); 425 spin_lock_init(&mvm->time_event_lock);
421 426
@@ -425,6 +430,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
425 INIT_WORK(&mvm->d0i3_exit_work, iwl_mvm_d0i3_exit_work); 430 INIT_WORK(&mvm->d0i3_exit_work, iwl_mvm_d0i3_exit_work);
426 431
427 spin_lock_init(&mvm->d0i3_tx_lock); 432 spin_lock_init(&mvm->d0i3_tx_lock);
433 spin_lock_init(&mvm->refs_lock);
428 skb_queue_head_init(&mvm->d0i3_tx); 434 skb_queue_head_init(&mvm->d0i3_tx);
429 init_waitqueue_head(&mvm->d0i3_exit_waitq); 435 init_waitqueue_head(&mvm->d0i3_exit_waitq);
430 436
@@ -539,7 +545,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
539 memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx)); 545 memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx));
540 546
541 /* rpm starts with a taken ref. only set the appropriate bit here. */ 547 /* rpm starts with a taken ref. only set the appropriate bit here. */
542 set_bit(IWL_MVM_REF_UCODE_DOWN, mvm->ref_bitmap); 548 mvm->refs[IWL_MVM_REF_UCODE_DOWN] = 1;
543 549
544 return op_mode; 550 return op_mode;
545 551
@@ -567,7 +573,11 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
567 ieee80211_unregister_hw(mvm->hw); 573 ieee80211_unregister_hw(mvm->hw);
568 574
569 kfree(mvm->scan_cmd); 575 kfree(mvm->scan_cmd);
570 vfree(mvm->fw_error_dump); 576 if (mvm->fw_error_dump) {
577 vfree(mvm->fw_error_dump->op_mode_ptr);
578 vfree(mvm->fw_error_dump->trans_ptr);
579 kfree(mvm->fw_error_dump);
580 }
571 kfree(mvm->mcast_filter_cmd); 581 kfree(mvm->mcast_filter_cmd);
572 mvm->mcast_filter_cmd = NULL; 582 mvm->mcast_filter_cmd = NULL;
573 583
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index 812813964847..763548880399 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.c
@@ -98,23 +98,21 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
98 bool update) 98 bool update)
99{ 99{
100 struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; 100 struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
101 struct iwl_mvm_add_sta_cmd add_sta_cmd; 101 struct iwl_mvm_add_sta_cmd add_sta_cmd = {
102 .sta_id = mvm_sta->sta_id,
103 .mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color),
104 .add_modify = update ? 1 : 0,
105 .station_flags_msk = cpu_to_le32(STA_FLG_FAT_EN_MSK |
106 STA_FLG_MIMO_EN_MSK),
107 };
102 int ret; 108 int ret;
103 u32 status; 109 u32 status;
104 u32 agg_size = 0, mpdu_dens = 0; 110 u32 agg_size = 0, mpdu_dens = 0;
105 111
106 memset(&add_sta_cmd, 0, sizeof(add_sta_cmd));
107
108 add_sta_cmd.sta_id = mvm_sta->sta_id;
109 add_sta_cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
110 if (!update) { 112 if (!update) {
111 add_sta_cmd.tfd_queue_msk = cpu_to_le32(mvm_sta->tfd_queue_msk); 113 add_sta_cmd.tfd_queue_msk = cpu_to_le32(mvm_sta->tfd_queue_msk);
112 memcpy(&add_sta_cmd.addr, sta->addr, ETH_ALEN); 114 memcpy(&add_sta_cmd.addr, sta->addr, ETH_ALEN);
113 } 115 }
114 add_sta_cmd.add_modify = update ? 1 : 0;
115
116 add_sta_cmd.station_flags_msk |= cpu_to_le32(STA_FLG_FAT_EN_MSK |
117 STA_FLG_MIMO_EN_MSK);
118 116
119 switch (sta->bandwidth) { 117 switch (sta->bandwidth) {
120 case IEEE80211_STA_RX_BW_160: 118 case IEEE80211_STA_RX_BW_160:
@@ -528,8 +526,12 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
528 526
529 lockdep_assert_held(&mvm->mutex); 527 lockdep_assert_held(&mvm->mutex);
530 528
531 /* Add the aux station, but without any queues */ 529 /* Map Aux queue to fifo - needs to happen before adding Aux station */
532 ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, 0, 530 iwl_trans_ac_txq_enable(mvm->trans, mvm->aux_queue,
531 IWL_MVM_TX_FIFO_MCAST);
532
533 /* Allocate aux station and assign to it the aux queue */
534 ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, BIT(mvm->aux_queue),
533 NL80211_IFTYPE_UNSPECIFIED); 535 NL80211_IFTYPE_UNSPECIFIED);
534 if (ret) 536 if (ret)
535 return ret; 537 return ret;
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c
index ae52613b97f2..33e5041f1efc 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c
@@ -72,9 +72,6 @@
72#include "iwl-io.h" 72#include "iwl-io.h"
73#include "iwl-prph.h" 73#include "iwl-prph.h"
74 74
75/* A TimeUnit is 1024 microsecond */
76#define MSEC_TO_TU(_msec) (_msec*1000/1024)
77
78/* 75/*
79 * For the high priority TE use a time event type that has similar priority to 76 * For the high priority TE use a time event type that has similar priority to
80 * the FW's action scan priority. 77 * the FW's action scan priority.
@@ -100,6 +97,21 @@ void iwl_mvm_te_clear_data(struct iwl_mvm *mvm,
100void iwl_mvm_roc_done_wk(struct work_struct *wk) 97void iwl_mvm_roc_done_wk(struct work_struct *wk)
101{ 98{
102 struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, roc_done_wk); 99 struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, roc_done_wk);
100 u32 queues = 0;
101
102 /*
103 * Clear the ROC_RUNNING /ROC_AUX_RUNNING status bit.
104 * This will cause the TX path to drop offchannel transmissions.
105 * That would also be done by mac80211, but it is racy, in particular
106 * in the case that the time event actually completed in the firmware
107 * (which is handled in iwl_mvm_te_handle_notif).
108 */
109 if (test_and_clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status))
110 queues |= BIT(IWL_MVM_OFFCHANNEL_QUEUE);
111 if (test_and_clear_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status))
112 queues |= BIT(mvm->aux_queue);
113
114 iwl_mvm_unref(mvm, IWL_MVM_REF_ROC);
103 115
104 synchronize_net(); 116 synchronize_net();
105 117
@@ -113,22 +125,12 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
113 * issue as it will have to complete before the next command is 125 * issue as it will have to complete before the next command is
114 * executed, and a new time event means a new command. 126 * executed, and a new time event means a new command.
115 */ 127 */
116 iwl_mvm_flush_tx_path(mvm, BIT(IWL_MVM_OFFCHANNEL_QUEUE), false); 128 iwl_mvm_flush_tx_path(mvm, queues, false);
117} 129}
118 130
119static void iwl_mvm_roc_finished(struct iwl_mvm *mvm) 131static void iwl_mvm_roc_finished(struct iwl_mvm *mvm)
120{ 132{
121 /* 133 /*
122 * First, clear the ROC_RUNNING status bit. This will cause the TX
123 * path to drop offchannel transmissions. That would also be done
124 * by mac80211, but it is racy, in particular in the case that the
125 * time event actually completed in the firmware (which is handled
126 * in iwl_mvm_te_handle_notif).
127 */
128 clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
129 iwl_mvm_unref(mvm, IWL_MVM_REF_ROC);
130
131 /*
132 * Of course, our status bit is just as racy as mac80211, so in 134 * Of course, our status bit is just as racy as mac80211, so in
133 * addition, fire off the work struct which will drop all frames 135 * addition, fire off the work struct which will drop all frames
134 * from the hardware queues that made it through the race. First 136 * from the hardware queues that made it through the race. First
@@ -263,6 +265,60 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
263} 265}
264 266
265/* 267/*
268 * Handle A Aux ROC time event
269 */
270static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm,
271 struct iwl_time_event_notif *notif)
272{
273 struct iwl_mvm_time_event_data *te_data, *tmp;
274 bool aux_roc_te = false;
275
276 list_for_each_entry_safe(te_data, tmp, &mvm->aux_roc_te_list, list) {
277 if (le32_to_cpu(notif->unique_id) == te_data->uid) {
278 aux_roc_te = true;
279 break;
280 }
281 }
282 if (!aux_roc_te) /* Not a Aux ROC time event */
283 return -EINVAL;
284
285 if (!le32_to_cpu(notif->status)) {
286 IWL_DEBUG_TE(mvm,
287 "ERROR: Aux ROC Time Event %s notification failure\n",
288 (le32_to_cpu(notif->action) &
289 TE_V2_NOTIF_HOST_EVENT_START) ? "start" : "end");
290 return -EINVAL;
291 }
292
293 IWL_DEBUG_TE(mvm,
294 "Aux ROC time event notification - UID = 0x%x action %d\n",
295 le32_to_cpu(notif->unique_id),
296 le32_to_cpu(notif->action));
297
298 if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_END) {
299 /* End TE, notify mac80211 */
300 ieee80211_remain_on_channel_expired(mvm->hw);
301 iwl_mvm_roc_finished(mvm); /* flush aux queue */
302 list_del(&te_data->list); /* remove from list */
303 te_data->running = false;
304 te_data->vif = NULL;
305 te_data->uid = 0;
306 } else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) {
307 set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
308 set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status);
309 te_data->running = true;
310 ieee80211_ready_on_channel(mvm->hw); /* Start TE */
311 } else {
312 IWL_DEBUG_TE(mvm,
313 "ERROR: Unknown Aux ROC Time Event (action = %d)\n",
314 le32_to_cpu(notif->action));
315 return -EINVAL;
316 }
317
318 return 0;
319}
320
321/*
266 * The Rx handler for time event notifications 322 * The Rx handler for time event notifications
267 */ 323 */
268int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm, 324int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm,
@@ -278,10 +334,15 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm,
278 le32_to_cpu(notif->action)); 334 le32_to_cpu(notif->action));
279 335
280 spin_lock_bh(&mvm->time_event_lock); 336 spin_lock_bh(&mvm->time_event_lock);
337 /* This time event is triggered for Aux ROC request */
338 if (!iwl_mvm_aux_roc_te_handle_notif(mvm, notif))
339 goto unlock;
340
281 list_for_each_entry_safe(te_data, tmp, &mvm->time_event_list, list) { 341 list_for_each_entry_safe(te_data, tmp, &mvm->time_event_list, list) {
282 if (le32_to_cpu(notif->unique_id) == te_data->uid) 342 if (le32_to_cpu(notif->unique_id) == te_data->uid)
283 iwl_mvm_te_handle_notif(mvm, te_data, notif); 343 iwl_mvm_te_handle_notif(mvm, te_data, notif);
284 } 344 }
345unlock:
285 spin_unlock_bh(&mvm->time_event_lock); 346 spin_unlock_bh(&mvm->time_event_lock);
286 347
287 return 0; 348 return 0;
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c
index 868561512783..0464599c111e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tt.c
@@ -140,9 +140,9 @@ static u16 iwl_mvm_dts_get_ptat_deviation_offset(struct iwl_mvm *mvm)
140 140
141 /* TODO: move parsing to NVM code */ 141 /* TODO: move parsing to NVM code */
142 calib = mvm->nvm_sections[NVM_SECTION_TYPE_CALIBRATION].data; 142 calib = mvm->nvm_sections[NVM_SECTION_TYPE_CALIBRATION].data;
143 ptat = calib[OTP_DTS_DIODE_DEVIATION]; 143 ptat = calib[OTP_DTS_DIODE_DEVIATION * 2];
144 pa1 = calib[OTP_DTS_DIODE_DEVIATION + 1]; 144 pa1 = calib[OTP_DTS_DIODE_DEVIATION * 2 + 1];
145 pa2 = calib[OTP_DTS_DIODE_DEVIATION + 2]; 145 pa2 = calib[OTP_DTS_DIODE_DEVIATION * 2 + 2];
146 146
147 /* get the median: */ 147 /* get the median: */
148 if (ptat > pa1) { 148 if (ptat > pa1) {
@@ -338,10 +338,16 @@ static void check_exit_ctkill(struct work_struct *work)
338 338
339 duration = tt->params->ct_kill_duration; 339 duration = tt->params->ct_kill_duration;
340 340
341 /* make sure the device is available for direct read/writes */
342 if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_CHECK_CTKILL))
343 goto reschedule;
344
341 iwl_trans_start_hw(mvm->trans); 345 iwl_trans_start_hw(mvm->trans);
342 temp = check_nic_temperature(mvm); 346 temp = check_nic_temperature(mvm);
343 iwl_trans_stop_device(mvm->trans); 347 iwl_trans_stop_device(mvm->trans);
344 348
349 iwl_mvm_unref(mvm, IWL_MVM_REF_CHECK_CTKILL);
350
345 if (temp < MIN_TEMPERATURE || temp > MAX_TEMPERATURE) { 351 if (temp < MIN_TEMPERATURE || temp > MAX_TEMPERATURE) {
346 IWL_DEBUG_TEMP(mvm, "Failed to measure NIC temperature\n"); 352 IWL_DEBUG_TEMP(mvm, "Failed to measure NIC temperature\n");
347 goto reschedule; 353 goto reschedule;
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index e9ff38635c21..dbc870713882 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -311,6 +311,16 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
311 return -1; 311 return -1;
312 312
313 /* 313 /*
314 * IWL_MVM_OFFCHANNEL_QUEUE is used for ROC packets that can be used
315 * in 2 different types of vifs, P2P & STATION. P2P uses the offchannel
316 * queue. STATION (HS2.0) uses the auxiliary context of the FW,
317 * and hence needs to be sent on the aux queue
318 */
319 if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE &&
320 info->control.vif->type == NL80211_IFTYPE_STATION)
321 IEEE80211_SKB_CB(skb)->hw_queue = mvm->aux_queue;
322
323 /*
314 * If the interface on which frame is sent is the P2P_DEVICE 324 * If the interface on which frame is sent is the P2P_DEVICE
315 * or an AP/GO interface use the broadcast station associated 325 * or an AP/GO interface use the broadcast station associated
316 * with it; otherwise use the AUX station. 326 * with it; otherwise use the AUX station.
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index 5b5b0d8c6f60..06e04aaf61ee 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -67,6 +67,7 @@
67#include <linux/sched.h> 67#include <linux/sched.h>
68#include <linux/bitops.h> 68#include <linux/bitops.h>
69#include <linux/gfp.h> 69#include <linux/gfp.h>
70#include <linux/vmalloc.h>
70 71
71#include "iwl-drv.h" 72#include "iwl-drv.h"
72#include "iwl-trans.h" 73#include "iwl-trans.h"
@@ -1773,28 +1774,207 @@ static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd)
1773 return cmdlen; 1774 return cmdlen;
1774} 1775}
1775 1776
1776static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans, 1777static const struct {
1777 void *buf, u32 buflen) 1778 u32 start, end;
1779} iwl_prph_dump_addr[] = {
1780 { .start = 0x00a00000, .end = 0x00a00000 },
1781 { .start = 0x00a0000c, .end = 0x00a00024 },
1782 { .start = 0x00a0002c, .end = 0x00a0003c },
1783 { .start = 0x00a00410, .end = 0x00a00418 },
1784 { .start = 0x00a00420, .end = 0x00a00420 },
1785 { .start = 0x00a00428, .end = 0x00a00428 },
1786 { .start = 0x00a00430, .end = 0x00a0043c },
1787 { .start = 0x00a00444, .end = 0x00a00444 },
1788 { .start = 0x00a004c0, .end = 0x00a004cc },
1789 { .start = 0x00a004d8, .end = 0x00a004d8 },
1790 { .start = 0x00a004e0, .end = 0x00a004f0 },
1791 { .start = 0x00a00840, .end = 0x00a00840 },
1792 { .start = 0x00a00850, .end = 0x00a00858 },
1793 { .start = 0x00a01004, .end = 0x00a01008 },
1794 { .start = 0x00a01010, .end = 0x00a01010 },
1795 { .start = 0x00a01018, .end = 0x00a01018 },
1796 { .start = 0x00a01024, .end = 0x00a01024 },
1797 { .start = 0x00a0102c, .end = 0x00a01034 },
1798 { .start = 0x00a0103c, .end = 0x00a01040 },
1799 { .start = 0x00a01048, .end = 0x00a01094 },
1800 { .start = 0x00a01c00, .end = 0x00a01c20 },
1801 { .start = 0x00a01c58, .end = 0x00a01c58 },
1802 { .start = 0x00a01c7c, .end = 0x00a01c7c },
1803 { .start = 0x00a01c28, .end = 0x00a01c54 },
1804 { .start = 0x00a01c5c, .end = 0x00a01c5c },
1805 { .start = 0x00a01c84, .end = 0x00a01c84 },
1806 { .start = 0x00a01ce0, .end = 0x00a01d0c },
1807 { .start = 0x00a01d18, .end = 0x00a01d20 },
1808 { .start = 0x00a01d2c, .end = 0x00a01d30 },
1809 { .start = 0x00a01d40, .end = 0x00a01d5c },
1810 { .start = 0x00a01d80, .end = 0x00a01d80 },
1811 { .start = 0x00a01d98, .end = 0x00a01d98 },
1812 { .start = 0x00a01dc0, .end = 0x00a01dfc },
1813 { .start = 0x00a01e00, .end = 0x00a01e2c },
1814 { .start = 0x00a01e40, .end = 0x00a01e60 },
1815 { .start = 0x00a01e84, .end = 0x00a01e90 },
1816 { .start = 0x00a01e9c, .end = 0x00a01ec4 },
1817 { .start = 0x00a01ed0, .end = 0x00a01ed0 },
1818 { .start = 0x00a01f00, .end = 0x00a01f14 },
1819 { .start = 0x00a01f44, .end = 0x00a01f58 },
1820 { .start = 0x00a01f80, .end = 0x00a01fa8 },
1821 { .start = 0x00a01fb0, .end = 0x00a01fbc },
1822 { .start = 0x00a01ff8, .end = 0x00a01ffc },
1823 { .start = 0x00a02000, .end = 0x00a02048 },
1824 { .start = 0x00a02068, .end = 0x00a020f0 },
1825 { .start = 0x00a02100, .end = 0x00a02118 },
1826 { .start = 0x00a02140, .end = 0x00a0214c },
1827 { .start = 0x00a02168, .end = 0x00a0218c },
1828 { .start = 0x00a021c0, .end = 0x00a021c0 },
1829 { .start = 0x00a02400, .end = 0x00a02410 },
1830 { .start = 0x00a02418, .end = 0x00a02420 },
1831 { .start = 0x00a02428, .end = 0x00a0242c },
1832 { .start = 0x00a02434, .end = 0x00a02434 },
1833 { .start = 0x00a02440, .end = 0x00a02460 },
1834 { .start = 0x00a02468, .end = 0x00a024b0 },
1835 { .start = 0x00a024c8, .end = 0x00a024cc },
1836 { .start = 0x00a02500, .end = 0x00a02504 },
1837 { .start = 0x00a0250c, .end = 0x00a02510 },
1838 { .start = 0x00a02540, .end = 0x00a02554 },
1839 { .start = 0x00a02580, .end = 0x00a025f4 },
1840 { .start = 0x00a02600, .end = 0x00a0260c },
1841 { .start = 0x00a02648, .end = 0x00a02650 },
1842 { .start = 0x00a02680, .end = 0x00a02680 },
1843 { .start = 0x00a026c0, .end = 0x00a026d0 },
1844 { .start = 0x00a02700, .end = 0x00a0270c },
1845 { .start = 0x00a02804, .end = 0x00a02804 },
1846 { .start = 0x00a02818, .end = 0x00a0281c },
1847 { .start = 0x00a02c00, .end = 0x00a02db4 },
1848 { .start = 0x00a02df4, .end = 0x00a02fb0 },
1849 { .start = 0x00a03000, .end = 0x00a03014 },
1850 { .start = 0x00a0301c, .end = 0x00a0302c },
1851 { .start = 0x00a03034, .end = 0x00a03038 },
1852 { .start = 0x00a03040, .end = 0x00a03048 },
1853 { .start = 0x00a03060, .end = 0x00a03068 },
1854 { .start = 0x00a03070, .end = 0x00a03074 },
1855 { .start = 0x00a0307c, .end = 0x00a0307c },
1856 { .start = 0x00a03080, .end = 0x00a03084 },
1857 { .start = 0x00a0308c, .end = 0x00a03090 },
1858 { .start = 0x00a03098, .end = 0x00a03098 },
1859 { .start = 0x00a030a0, .end = 0x00a030a0 },
1860 { .start = 0x00a030a8, .end = 0x00a030b4 },
1861 { .start = 0x00a030bc, .end = 0x00a030bc },
1862 { .start = 0x00a030c0, .end = 0x00a0312c },
1863 { .start = 0x00a03c00, .end = 0x00a03c5c },
1864 { .start = 0x00a04400, .end = 0x00a04454 },
1865 { .start = 0x00a04460, .end = 0x00a04474 },
1866 { .start = 0x00a044c0, .end = 0x00a044ec },
1867 { .start = 0x00a04500, .end = 0x00a04504 },
1868 { .start = 0x00a04510, .end = 0x00a04538 },
1869 { .start = 0x00a04540, .end = 0x00a04548 },
1870 { .start = 0x00a04560, .end = 0x00a0457c },
1871 { .start = 0x00a04590, .end = 0x00a04598 },
1872 { .start = 0x00a045c0, .end = 0x00a045f4 },
1873};
1874
1875static u32 iwl_trans_pcie_dump_prph(struct iwl_trans *trans,
1876 struct iwl_fw_error_dump_data **data)
1877{
1878 struct iwl_fw_error_dump_prph *prph;
1879 unsigned long flags;
1880 u32 prph_len = 0, i;
1881
1882 if (!iwl_trans_grab_nic_access(trans, false, &flags))
1883 return 0;
1884
1885 for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr); i++) {
1886 /* The range includes both boundaries */
1887 int num_bytes_in_chunk = iwl_prph_dump_addr[i].end -
1888 iwl_prph_dump_addr[i].start + 4;
1889 int reg;
1890 __le32 *val;
1891
1892 prph_len += sizeof(*data) + sizeof(*prph) +
1893 num_bytes_in_chunk;
1894
1895 (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH);
1896 (*data)->len = cpu_to_le32(sizeof(*prph) +
1897 num_bytes_in_chunk);
1898 prph = (void *)(*data)->data;
1899 prph->prph_start = cpu_to_le32(iwl_prph_dump_addr[i].start);
1900 val = (void *)prph->data;
1901
1902 for (reg = iwl_prph_dump_addr[i].start;
1903 reg <= iwl_prph_dump_addr[i].end;
1904 reg += 4)
1905 *val++ = cpu_to_le32(iwl_trans_pcie_read_prph(trans,
1906 reg));
1907 *data = iwl_fw_error_next_data(*data);
1908 }
1909
1910 iwl_trans_release_nic_access(trans, &flags);
1911
1912 return prph_len;
1913}
1914
1915#define IWL_CSR_TO_DUMP (0x250)
1916
1917static u32 iwl_trans_pcie_dump_csr(struct iwl_trans *trans,
1918 struct iwl_fw_error_dump_data **data)
1919{
1920 u32 csr_len = sizeof(**data) + IWL_CSR_TO_DUMP;
1921 __le32 *val;
1922 int i;
1923
1924 (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_CSR);
1925 (*data)->len = cpu_to_le32(IWL_CSR_TO_DUMP);
1926 val = (void *)(*data)->data;
1927
1928 for (i = 0; i < IWL_CSR_TO_DUMP; i += 4)
1929 *val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i));
1930
1931 *data = iwl_fw_error_next_data(*data);
1932
1933 return csr_len;
1934}
1935
1936static
1937struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans)
1778{ 1938{
1779 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1939 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
1780 struct iwl_fw_error_dump_data *data; 1940 struct iwl_fw_error_dump_data *data;
1781 struct iwl_txq *cmdq = &trans_pcie->txq[trans_pcie->cmd_queue]; 1941 struct iwl_txq *cmdq = &trans_pcie->txq[trans_pcie->cmd_queue];
1782 struct iwl_fw_error_dump_txcmd *txcmd; 1942 struct iwl_fw_error_dump_txcmd *txcmd;
1943 struct iwl_trans_dump_data *dump_data;
1783 u32 len; 1944 u32 len;
1784 int i, ptr; 1945 int i, ptr;
1785 1946
1786 len = sizeof(*data) + 1947 /* transport dump header */
1948 len = sizeof(*dump_data);
1949
1950 /* host commands */
1951 len += sizeof(*data) +
1787 cmdq->q.n_window * (sizeof(*txcmd) + TFD_MAX_PAYLOAD_SIZE); 1952 cmdq->q.n_window * (sizeof(*txcmd) + TFD_MAX_PAYLOAD_SIZE);
1788 1953
1954 /* CSR registers */
1955 len += sizeof(*data) + IWL_CSR_TO_DUMP;
1956
1957 /* PRPH registers */
1958 for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr); i++) {
1959 /* The range includes both boundaries */
1960 int num_bytes_in_chunk = iwl_prph_dump_addr[i].end -
1961 iwl_prph_dump_addr[i].start + 4;
1962
1963 len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_prph) +
1964 num_bytes_in_chunk;
1965 }
1966
1967 /* FW monitor */
1789 if (trans_pcie->fw_mon_page) 1968 if (trans_pcie->fw_mon_page)
1790 len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_fw_mon) + 1969 len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_fw_mon) +
1791 trans_pcie->fw_mon_size; 1970 trans_pcie->fw_mon_size;
1792 1971
1793 if (!buf) 1972 dump_data = vzalloc(len);
1794 return len; 1973 if (!dump_data)
1974 return NULL;
1795 1975
1796 len = 0; 1976 len = 0;
1797 data = buf; 1977 data = (void *)dump_data->data;
1798 data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD); 1978 data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD);
1799 txcmd = (void *)data->data; 1979 txcmd = (void *)data->data;
1800 spin_lock_bh(&cmdq->lock); 1980 spin_lock_bh(&cmdq->lock);
@@ -1820,11 +2000,15 @@ static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans,
1820 2000
1821 data->len = cpu_to_le32(len); 2001 data->len = cpu_to_le32(len);
1822 len += sizeof(*data); 2002 len += sizeof(*data);
2003 data = iwl_fw_error_next_data(data);
2004
2005 len += iwl_trans_pcie_dump_prph(trans, &data);
2006 len += iwl_trans_pcie_dump_csr(trans, &data);
2007 /* data is already pointing to the next section */
1823 2008
1824 if (trans_pcie->fw_mon_page) { 2009 if (trans_pcie->fw_mon_page) {
1825 struct iwl_fw_error_dump_fw_mon *fw_mon_data; 2010 struct iwl_fw_error_dump_fw_mon *fw_mon_data;
1826 2011
1827 data = iwl_fw_error_next_data(data);
1828 data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FW_MONITOR); 2012 data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FW_MONITOR);
1829 data->len = cpu_to_le32(trans_pcie->fw_mon_size + 2013 data->len = cpu_to_le32(trans_pcie->fw_mon_size +
1830 sizeof(*fw_mon_data)); 2014 sizeof(*fw_mon_data));
@@ -1852,7 +2036,9 @@ static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans,
1852 trans_pcie->fw_mon_size; 2036 trans_pcie->fw_mon_size;
1853 } 2037 }
1854 2038
1855 return len; 2039 dump_data->len = len;
2040
2041 return dump_data;
1856} 2042}
1857#else 2043#else
1858static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, 2044static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 5ea65fce0b83..1326f6121835 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -685,11 +685,16 @@ static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw,
685 struct mac80211_hwsim_data *data = hw->priv; 685 struct mac80211_hwsim_data *data = hw->priv;
686 u64 now = mac80211_hwsim_get_tsf(hw, vif); 686 u64 now = mac80211_hwsim_get_tsf(hw, vif);
687 u32 bcn_int = data->beacon_int; 687 u32 bcn_int = data->beacon_int;
688 s64 delta = tsf - now; 688 u64 delta = abs64(tsf - now);
689 689
690 data->tsf_offset += delta;
691 /* adjust after beaconing with new timestamp at old TBTT */ 690 /* adjust after beaconing with new timestamp at old TBTT */
692 data->bcn_delta = do_div(delta, bcn_int); 691 if (tsf > now) {
692 data->tsf_offset += delta;
693 data->bcn_delta = do_div(delta, bcn_int);
694 } else {
695 data->tsf_offset -= delta;
696 data->bcn_delta = -do_div(delta, bcn_int);
697 }
693} 698}
694 699
695static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw, 700static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c
index 9d6d8d9f01e3..62f5dbe602d3 100644
--- a/drivers/net/wireless/mwifiex/11n.c
+++ b/drivers/net/wireless/mwifiex/11n.c
@@ -541,7 +541,6 @@ void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid,
541int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac) 541int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac)
542{ 542{
543 struct host_cmd_ds_11n_addba_req add_ba_req; 543 struct host_cmd_ds_11n_addba_req add_ba_req;
544 struct mwifiex_sta_node *sta_ptr;
545 u32 tx_win_size = priv->add_ba_param.tx_win_size; 544 u32 tx_win_size = priv->add_ba_param.tx_win_size;
546 static u8 dialog_tok; 545 static u8 dialog_tok;
547 int ret; 546 int ret;
@@ -553,6 +552,8 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac)
553 ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && 552 ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
554 priv->adapter->is_hw_11ac_capable && 553 priv->adapter->is_hw_11ac_capable &&
555 memcmp(priv->cfg_bssid, peer_mac, ETH_ALEN)) { 554 memcmp(priv->cfg_bssid, peer_mac, ETH_ALEN)) {
555 struct mwifiex_sta_node *sta_ptr;
556
556 sta_ptr = mwifiex_get_sta_entry(priv, peer_mac); 557 sta_ptr = mwifiex_get_sta_entry(priv, peer_mac);
557 if (!sta_ptr) { 558 if (!sta_ptr) {
558 dev_warn(priv->adapter->dev, 559 dev_warn(priv->adapter->dev,
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index b22bae3d1205..06a2c215ef5e 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -249,13 +249,22 @@ void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta)
249 * buffered in Rx reordering table. 249 * buffered in Rx reordering table.
250 */ 250 */
251static int 251static int
252mwifiex_11n_find_last_seq_num(struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr) 252mwifiex_11n_find_last_seq_num(struct reorder_tmr_cnxt *ctx)
253{ 253{
254 struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr = ctx->ptr;
255 struct mwifiex_private *priv = ctx->priv;
256 unsigned long flags;
254 int i; 257 int i;
255 258
256 for (i = (rx_reorder_tbl_ptr->win_size - 1); i >= 0; --i) 259 spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
257 if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) 260 for (i = rx_reorder_tbl_ptr->win_size - 1; i >= 0; --i) {
261 if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) {
262 spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
263 flags);
258 return i; 264 return i;
265 }
266 }
267 spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
259 268
260 return -1; 269 return -1;
261} 270}
@@ -274,7 +283,7 @@ mwifiex_flush_data(unsigned long context)
274 (struct reorder_tmr_cnxt *) context; 283 (struct reorder_tmr_cnxt *) context;
275 int start_win, seq_num; 284 int start_win, seq_num;
276 285
277 seq_num = mwifiex_11n_find_last_seq_num(ctx->ptr); 286 seq_num = mwifiex_11n_find_last_seq_num(ctx);
278 287
279 if (seq_num < 0) 288 if (seq_num < 0)
280 return; 289 return;
@@ -729,9 +738,9 @@ void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv)
729 mwifiex_del_rx_reorder_entry(priv, del_tbl_ptr); 738 mwifiex_del_rx_reorder_entry(priv, del_tbl_ptr);
730 spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); 739 spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
731 } 740 }
741 INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
732 spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); 742 spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
733 743
734 INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
735 mwifiex_reset_11n_rx_seq_num(priv); 744 mwifiex_reset_11n_rx_seq_num(priv);
736} 745}
737 746
@@ -749,10 +758,14 @@ void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags)
749 priv = adapter->priv[i]; 758 priv = adapter->priv[i];
750 if (!priv) 759 if (!priv)
751 continue; 760 continue;
752 if (list_empty(&priv->rx_reorder_tbl_ptr))
753 continue;
754 761
755 spin_lock_irqsave(&priv->rx_reorder_tbl_lock, lock_flags); 762 spin_lock_irqsave(&priv->rx_reorder_tbl_lock, lock_flags);
763 if (list_empty(&priv->rx_reorder_tbl_ptr)) {
764 spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
765 lock_flags);
766 continue;
767 }
768
756 list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list) 769 list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list)
757 tbl->flags = flags; 770 tbl->flags = flags;
758 spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, lock_flags); 771 spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, lock_flags);
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index ca87f923c61e..e2e6bf13c2d8 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1604,9 +1604,6 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len,
1604 return -EINVAL; 1604 return -EINVAL;
1605 } 1605 }
1606 1606
1607 /* disconnect before try to associate */
1608 mwifiex_deauthenticate(priv, NULL);
1609
1610 /* As this is new association, clear locally stored 1607 /* As this is new association, clear locally stored
1611 * keys and security related flags */ 1608 * keys and security related flags */
1612 priv->sec_info.wpa_enabled = false; 1609 priv->sec_info.wpa_enabled = false;
@@ -1744,6 +1741,11 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
1744 return -EINVAL; 1741 return -EINVAL;
1745 } 1742 }
1746 1743
1744 if (priv->wdev && priv->wdev->current_bss) {
1745 wiphy_warn(wiphy, "%s: already connected\n", dev->name);
1746 return -EALREADY;
1747 }
1748
1747 wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n", 1749 wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n",
1748 (char *) sme->ssid, sme->bssid); 1750 (char *) sme->ssid, sme->bssid);
1749 1751
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index 5899eee87fb1..baf0aab63c04 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -137,7 +137,6 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
137 struct host_cmd_ds_command *host_cmd; 137 struct host_cmd_ds_command *host_cmd;
138 uint16_t cmd_code; 138 uint16_t cmd_code;
139 uint16_t cmd_size; 139 uint16_t cmd_size;
140 struct timeval tstamp;
141 unsigned long flags; 140 unsigned long flags;
142 __le32 tmp; 141 __le32 tmp;
143 142
@@ -198,10 +197,8 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
198 */ 197 */
199 skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len); 198 skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len);
200 199
201 do_gettimeofday(&tstamp); 200 dev_dbg(adapter->dev,
202 dev_dbg(adapter->dev, "cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d," 201 "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n", cmd_code,
203 " seqno %#x\n",
204 tstamp.tv_sec, tstamp.tv_usec, cmd_code,
205 le16_to_cpu(*(__le16 *) ((u8 *) host_cmd + S_DS_GEN)), cmd_size, 202 le16_to_cpu(*(__le16 *) ((u8 *) host_cmd + S_DS_GEN)), cmd_size,
206 le16_to_cpu(host_cmd->seq_num)); 203 le16_to_cpu(host_cmd->seq_num));
207 204
@@ -273,7 +270,6 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter)
273 (struct mwifiex_opt_sleep_confirm *) 270 (struct mwifiex_opt_sleep_confirm *)
274 adapter->sleep_cfm->data; 271 adapter->sleep_cfm->data;
275 struct sk_buff *sleep_cfm_tmp; 272 struct sk_buff *sleep_cfm_tmp;
276 struct timeval ts;
277 __le32 tmp; 273 __le32 tmp;
278 274
279 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); 275 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
@@ -284,10 +280,9 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter)
284 (adapter->seq_num, priv->bss_num, 280 (adapter->seq_num, priv->bss_num,
285 priv->bss_type))); 281 priv->bss_type)));
286 282
287 do_gettimeofday(&ts);
288 dev_dbg(adapter->dev, 283 dev_dbg(adapter->dev,
289 "cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d, seqno %#x\n", 284 "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n",
290 ts.tv_sec, ts.tv_usec, le16_to_cpu(sleep_cfm_buf->command), 285 le16_to_cpu(sleep_cfm_buf->command),
291 le16_to_cpu(sleep_cfm_buf->action), 286 le16_to_cpu(sleep_cfm_buf->action),
292 le16_to_cpu(sleep_cfm_buf->size), 287 le16_to_cpu(sleep_cfm_buf->size),
293 le16_to_cpu(sleep_cfm_buf->seq_num)); 288 le16_to_cpu(sleep_cfm_buf->seq_num));
@@ -442,7 +437,6 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter)
442 mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); 437 mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
443 struct sk_buff *skb = adapter->event_skb; 438 struct sk_buff *skb = adapter->event_skb;
444 u32 eventcause = adapter->event_cause; 439 u32 eventcause = adapter->event_cause;
445 struct timeval tstamp;
446 struct mwifiex_rxinfo *rx_info; 440 struct mwifiex_rxinfo *rx_info;
447 441
448 /* Save the last event to debug log */ 442 /* Save the last event to debug log */
@@ -467,9 +461,7 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter)
467 rx_info->bss_type = priv->bss_type; 461 rx_info->bss_type = priv->bss_type;
468 } 462 }
469 463
470 do_gettimeofday(&tstamp); 464 dev_dbg(adapter->dev, "EVENT: cause: %#x\n", eventcause);
471 dev_dbg(adapter->dev, "EVENT: %lu.%lu: cause: %#x\n",
472 tstamp.tv_sec, tstamp.tv_usec, eventcause);
473 if (eventcause == EVENT_PS_SLEEP || eventcause == EVENT_PS_AWAKE) { 465 if (eventcause == EVENT_PS_SLEEP || eventcause == EVENT_PS_AWAKE) {
474 /* Handle PS_SLEEP/AWAKE events on STA */ 466 /* Handle PS_SLEEP/AWAKE events on STA */
475 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); 467 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
@@ -781,7 +773,6 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
781 uint16_t orig_cmdresp_no; 773 uint16_t orig_cmdresp_no;
782 uint16_t cmdresp_no; 774 uint16_t cmdresp_no;
783 uint16_t cmdresp_result; 775 uint16_t cmdresp_result;
784 struct timeval tstamp;
785 unsigned long flags; 776 unsigned long flags;
786 777
787 /* Now we got response from FW, cancel the command timer */ 778 /* Now we got response from FW, cancel the command timer */
@@ -839,11 +830,10 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
839 adapter->dbg.last_cmd_resp_id[adapter->dbg.last_cmd_resp_index] = 830 adapter->dbg.last_cmd_resp_id[adapter->dbg.last_cmd_resp_index] =
840 orig_cmdresp_no; 831 orig_cmdresp_no;
841 832
842 do_gettimeofday(&tstamp); 833 dev_dbg(adapter->dev,
843 dev_dbg(adapter->dev, "cmd: CMD_RESP: (%lu.%lu): 0x%x, result %d," 834 "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n",
844 " len %d, seqno 0x%x\n", 835 orig_cmdresp_no, cmdresp_result,
845 tstamp.tv_sec, tstamp.tv_usec, orig_cmdresp_no, cmdresp_result, 836 le16_to_cpu(resp->size), le16_to_cpu(resp->seq_num));
846 le16_to_cpu(resp->size), le16_to_cpu(resp->seq_num));
847 837
848 if (!(orig_cmdresp_no & HostCmd_RET_BIT)) { 838 if (!(orig_cmdresp_no & HostCmd_RET_BIT)) {
849 dev_err(adapter->dev, "CMD_RESP: invalid cmd resp\n"); 839 dev_err(adapter->dev, "CMD_RESP: invalid cmd resp\n");
@@ -903,7 +893,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
903 struct mwifiex_adapter *adapter = 893 struct mwifiex_adapter *adapter =
904 (struct mwifiex_adapter *) function_context; 894 (struct mwifiex_adapter *) function_context;
905 struct cmd_ctrl_node *cmd_node; 895 struct cmd_ctrl_node *cmd_node;
906 struct timeval tstamp;
907 896
908 adapter->is_cmd_timedout = 1; 897 adapter->is_cmd_timedout = 1;
909 if (!adapter->curr_cmd) { 898 if (!adapter->curr_cmd) {
@@ -916,10 +905,8 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
916 adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index]; 905 adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index];
917 adapter->dbg.timeout_cmd_act = 906 adapter->dbg.timeout_cmd_act =
918 adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index]; 907 adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index];
919 do_gettimeofday(&tstamp);
920 dev_err(adapter->dev, 908 dev_err(adapter->dev,
921 "%s: Timeout cmd id (%lu.%lu) = %#x, act = %#x\n", 909 "%s: Timeout cmd id = %#x, act = %#x\n", __func__,
922 __func__, tstamp.tv_sec, tstamp.tv_usec,
923 adapter->dbg.timeout_cmd_id, 910 adapter->dbg.timeout_cmd_id,
924 adapter->dbg.timeout_cmd_act); 911 adapter->dbg.timeout_cmd_act);
925 912
@@ -1237,18 +1224,15 @@ mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *adapter,
1237 uint16_t result = le16_to_cpu(cmd->result); 1224 uint16_t result = le16_to_cpu(cmd->result);
1238 uint16_t command = le16_to_cpu(cmd->command); 1225 uint16_t command = le16_to_cpu(cmd->command);
1239 uint16_t seq_num = le16_to_cpu(cmd->seq_num); 1226 uint16_t seq_num = le16_to_cpu(cmd->seq_num);
1240 struct timeval ts;
1241 1227
1242 if (!upld_len) { 1228 if (!upld_len) {
1243 dev_err(adapter->dev, "%s: cmd size is 0\n", __func__); 1229 dev_err(adapter->dev, "%s: cmd size is 0\n", __func__);
1244 return; 1230 return;
1245 } 1231 }
1246 1232
1247 do_gettimeofday(&ts);
1248 dev_dbg(adapter->dev, 1233 dev_dbg(adapter->dev,
1249 "cmd: CMD_RESP: (%lu.%lu): 0x%x, result %d, len %d, seqno 0x%x\n", 1234 "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n",
1250 ts.tv_sec, ts.tv_usec, command, result, le16_to_cpu(cmd->size), 1235 command, result, le16_to_cpu(cmd->size), seq_num);
1251 seq_num);
1252 1236
1253 /* Get BSS number and corresponding priv */ 1237 /* Get BSS number and corresponding priv */
1254 priv = mwifiex_get_priv_by_id(adapter, HostCmd_GET_BSS_NO(seq_num), 1238 priv = mwifiex_get_priv_by_id(adapter, HostCmd_GET_BSS_NO(seq_num),
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 5561573452bb..49da2d53d294 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -713,7 +713,7 @@ struct mwifiex_ie_types_vendor_param_set {
713 u8 ie[MWIFIEX_MAX_VSIE_LEN]; 713 u8 ie[MWIFIEX_MAX_VSIE_LEN];
714}; 714};
715 715
716#define MWIFIEX_TDLS_IDLE_TIMEOUT 60 716#define MWIFIEX_TDLS_IDLE_TIMEOUT_IN_SEC 60
717 717
718struct mwifiex_ie_types_tdls_idle_timeout { 718struct mwifiex_ie_types_tdls_idle_timeout {
719 struct mwifiex_ie_types_header header; 719 struct mwifiex_ie_types_header header;
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
index fc135649b85f..8d6c25908b6d 100644
--- a/drivers/net/wireless/mwifiex/join.c
+++ b/drivers/net/wireless/mwifiex/join.c
@@ -949,7 +949,7 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
949 chan_tlv->chan_scan_param[0].radio_type |= 949 chan_tlv->chan_scan_param[0].radio_type |=
950 (IEEE80211_HT_PARAM_CHA_SEC_ABOVE << 4); 950 (IEEE80211_HT_PARAM_CHA_SEC_ABOVE << 4);
951 else if (adapter->sec_chan_offset == 951 else if (adapter->sec_chan_offset ==
952 IEEE80211_HT_PARAM_CHA_SEC_ABOVE) 952 IEEE80211_HT_PARAM_CHA_SEC_BELOW)
953 chan_tlv->chan_scan_param[0].radio_type |= 953 chan_tlv->chan_scan_param[0].radio_type |=
954 (IEEE80211_HT_PARAM_CHA_SEC_BELOW << 4); 954 (IEEE80211_HT_PARAM_CHA_SEC_BELOW << 4);
955 } 955 }
@@ -1288,8 +1288,6 @@ done:
1288int mwifiex_associate(struct mwifiex_private *priv, 1288int mwifiex_associate(struct mwifiex_private *priv,
1289 struct mwifiex_bssdescriptor *bss_desc) 1289 struct mwifiex_bssdescriptor *bss_desc)
1290{ 1290{
1291 u8 current_bssid[ETH_ALEN];
1292
1293 /* Return error if the adapter is not STA role or table entry 1291 /* Return error if the adapter is not STA role or table entry
1294 * is not marked as infra. 1292 * is not marked as infra.
1295 */ 1293 */
@@ -1304,10 +1302,6 @@ int mwifiex_associate(struct mwifiex_private *priv,
1304 else 1302 else
1305 mwifiex_set_ba_params(priv); 1303 mwifiex_set_ba_params(priv);
1306 1304
1307 memcpy(&current_bssid,
1308 &priv->curr_bss_params.bss_descriptor.mac_address,
1309 sizeof(current_bssid));
1310
1311 /* Clear any past association response stored for application 1305 /* Clear any past association response stored for application
1312 retrieval */ 1306 retrieval */
1313 priv->assoc_rsp_size = 0; 1307 priv->assoc_rsp_size = 0;
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 3e5194fb0b0f..dfa37eadc4db 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -33,6 +33,7 @@ static void scan_delay_timer_fn(unsigned long data)
33 struct mwifiex_private *priv = (struct mwifiex_private *)data; 33 struct mwifiex_private *priv = (struct mwifiex_private *)data;
34 struct mwifiex_adapter *adapter = priv->adapter; 34 struct mwifiex_adapter *adapter = priv->adapter;
35 struct cmd_ctrl_node *cmd_node, *tmp_node; 35 struct cmd_ctrl_node *cmd_node, *tmp_node;
36 spinlock_t *scan_q_lock = &adapter->scan_pending_q_lock;
36 unsigned long flags; 37 unsigned long flags;
37 38
38 if (adapter->surprise_removed) 39 if (adapter->surprise_removed)
@@ -44,13 +45,13 @@ static void scan_delay_timer_fn(unsigned long data)
44 * Abort scan operation by cancelling all pending scan 45 * Abort scan operation by cancelling all pending scan
45 * commands 46 * commands
46 */ 47 */
47 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); 48 spin_lock_irqsave(scan_q_lock, flags);
48 list_for_each_entry_safe(cmd_node, tmp_node, 49 list_for_each_entry_safe(cmd_node, tmp_node,
49 &adapter->scan_pending_q, list) { 50 &adapter->scan_pending_q, list) {
50 list_del(&cmd_node->list); 51 list_del(&cmd_node->list);
51 mwifiex_insert_cmd_to_free_q(adapter, cmd_node); 52 mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
52 } 53 }
53 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); 54 spin_unlock_irqrestore(scan_q_lock, flags);
54 55
55 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); 56 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
56 adapter->scan_processing = false; 57 adapter->scan_processing = false;
@@ -79,12 +80,17 @@ static void scan_delay_timer_fn(unsigned long data)
79 */ 80 */
80 adapter->scan_delay_cnt = 0; 81 adapter->scan_delay_cnt = 0;
81 adapter->empty_tx_q_cnt = 0; 82 adapter->empty_tx_q_cnt = 0;
82 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); 83 spin_lock_irqsave(scan_q_lock, flags);
84
85 if (list_empty(&adapter->scan_pending_q)) {
86 spin_unlock_irqrestore(scan_q_lock, flags);
87 goto done;
88 }
89
83 cmd_node = list_first_entry(&adapter->scan_pending_q, 90 cmd_node = list_first_entry(&adapter->scan_pending_q,
84 struct cmd_ctrl_node, list); 91 struct cmd_ctrl_node, list);
85 list_del(&cmd_node->list); 92 list_del(&cmd_node->list);
86 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, 93 spin_unlock_irqrestore(scan_q_lock, flags);
87 flags);
88 94
89 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, 95 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
90 true); 96 true);
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index 5f7afffdd34e..c16dd2cc8198 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -2238,7 +2238,6 @@ static void mwifiex_pcie_fw_dump_work(struct mwifiex_adapter *adapter)
2238 struct pcie_service_card *card = adapter->card; 2238 struct pcie_service_card *card = adapter->card;
2239 const struct mwifiex_pcie_card_reg *creg = card->pcie.reg; 2239 const struct mwifiex_pcie_card_reg *creg = card->pcie.reg;
2240 unsigned int reg, reg_start, reg_end; 2240 unsigned int reg, reg_start, reg_end;
2241 struct timeval t;
2242 u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0; 2241 u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0;
2243 enum rdwr_status stat; 2242 enum rdwr_status stat;
2244 u32 memory_size; 2243 u32 memory_size;
@@ -2257,9 +2256,7 @@ static void mwifiex_pcie_fw_dump_work(struct mwifiex_adapter *adapter)
2257 entry->mem_size = 0; 2256 entry->mem_size = 0;
2258 } 2257 }
2259 2258
2260 do_gettimeofday(&t); 2259 dev_info(adapter->dev, "== mwifiex firmware dump start ==\n");
2261 dev_info(adapter->dev, "== mwifiex firmware dump start: %u.%06u ==\n",
2262 (u32)t.tv_sec, (u32)t.tv_usec);
2263 2260
2264 /* Read the number of the memories which will dump */ 2261 /* Read the number of the memories which will dump */
2265 stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag); 2262 stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
@@ -2303,9 +2300,8 @@ static void mwifiex_pcie_fw_dump_work(struct mwifiex_adapter *adapter)
2303 end_ptr = dbg_ptr + memory_size; 2300 end_ptr = dbg_ptr + memory_size;
2304 2301
2305 doneflag = entry->done_flag; 2302 doneflag = entry->done_flag;
2306 do_gettimeofday(&t); 2303 dev_info(adapter->dev, "Start %s output, please wait...\n",
2307 dev_info(adapter->dev, "Start %s output %u.%06u, please wait...\n", 2304 entry->mem_name);
2308 entry->mem_name, (u32)t.tv_sec, (u32)t.tv_usec);
2309 2305
2310 do { 2306 do {
2311 stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag); 2307 stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
@@ -2331,9 +2327,7 @@ static void mwifiex_pcie_fw_dump_work(struct mwifiex_adapter *adapter)
2331 break; 2327 break;
2332 } while (true); 2328 } while (true);
2333 } 2329 }
2334 do_gettimeofday(&t); 2330 dev_info(adapter->dev, "== mwifiex firmware dump end ==\n");
2335 dev_info(adapter->dev, "== mwifiex firmware dump end: %u.%06u ==\n",
2336 (u32)t.tv_sec, (u32)t.tv_usec);
2337 2331
2338 kobject_uevent_env(&adapter->wiphy->dev.kobj, KOBJ_CHANGE, env); 2332 kobject_uevent_env(&adapter->wiphy->dev.kobj, KOBJ_CHANGE, env);
2339 2333
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index 1da04a086bd9..1770fa3fc1e6 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -1954,6 +1954,7 @@ static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter)
1954 mmc_remove_host(target); 1954 mmc_remove_host(target);
1955 /* 20ms delay is based on experiment with sdhci controller */ 1955 /* 20ms delay is based on experiment with sdhci controller */
1956 mdelay(20); 1956 mdelay(20);
1957 target->rescan_entered = 0; /* rescan non-removable cards */
1957 mmc_add_host(target); 1958 mmc_add_host(target);
1958} 1959}
1959 1960
@@ -2012,7 +2013,6 @@ static void mwifiex_sdio_fw_dump_work(struct work_struct *work)
2012 int ret = 0; 2013 int ret = 0;
2013 unsigned int reg, reg_start, reg_end; 2014 unsigned int reg, reg_start, reg_end;
2014 u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0; 2015 u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0;
2015 struct timeval t;
2016 enum rdwr_status stat; 2016 enum rdwr_status stat;
2017 u32 memory_size; 2017 u32 memory_size;
2018 static char *env[] = { "DRIVER=mwifiex_sdio", "EVENT=fw_dump", NULL }; 2018 static char *env[] = { "DRIVER=mwifiex_sdio", "EVENT=fw_dump", NULL };
@@ -2033,9 +2033,7 @@ static void mwifiex_sdio_fw_dump_work(struct work_struct *work)
2033 mwifiex_pm_wakeup_card(adapter); 2033 mwifiex_pm_wakeup_card(adapter);
2034 sdio_claim_host(card->func); 2034 sdio_claim_host(card->func);
2035 2035
2036 do_gettimeofday(&t); 2036 dev_info(adapter->dev, "== mwifiex firmware dump start ==\n");
2037 dev_info(adapter->dev, "== mwifiex firmware dump start: %u.%06u ==\n",
2038 (u32)t.tv_sec, (u32)t.tv_usec);
2039 2037
2040 stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag); 2038 stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag);
2041 if (stat == RDWR_STATUS_FAILURE) 2039 if (stat == RDWR_STATUS_FAILURE)
@@ -2087,9 +2085,8 @@ static void mwifiex_sdio_fw_dump_work(struct work_struct *work)
2087 end_ptr = dbg_ptr + memory_size; 2085 end_ptr = dbg_ptr + memory_size;
2088 2086
2089 doneflag = entry->done_flag; 2087 doneflag = entry->done_flag;
2090 do_gettimeofday(&t); 2088 dev_info(adapter->dev, "Start %s output, please wait...\n",
2091 dev_info(adapter->dev, "Start %s output %u.%06u, please wait...\n", 2089 entry->mem_name);
2092 entry->mem_name, (u32)t.tv_sec, (u32)t.tv_usec);
2093 2090
2094 do { 2091 do {
2095 stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag); 2092 stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag);
@@ -2120,9 +2117,7 @@ static void mwifiex_sdio_fw_dump_work(struct work_struct *work)
2120 break; 2117 break;
2121 } while (1); 2118 } while (1);
2122 } 2119 }
2123 do_gettimeofday(&t); 2120 dev_info(adapter->dev, "== mwifiex firmware dump end ==\n");
2124 dev_info(adapter->dev, "== mwifiex firmware dump end: %u.%06u ==\n",
2125 (u32)t.tv_sec, (u32)t.tv_usec);
2126 2121
2127 kobject_uevent_env(&adapter->wiphy->dev.kobj, KOBJ_CHANGE, env); 2122 kobject_uevent_env(&adapter->wiphy->dev.kobj, KOBJ_CHANGE, env);
2128 2123
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index 0f077aaadab6..733de92a4c61 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -1647,7 +1647,7 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv,
1647 timeout = (void *)(pos + config_len); 1647 timeout = (void *)(pos + config_len);
1648 timeout->header.type = cpu_to_le16(TLV_TYPE_TDLS_IDLE_TIMEOUT); 1648 timeout->header.type = cpu_to_le16(TLV_TYPE_TDLS_IDLE_TIMEOUT);
1649 timeout->header.len = cpu_to_le16(sizeof(timeout->value)); 1649 timeout->header.len = cpu_to_le16(sizeof(timeout->value));
1650 timeout->value = cpu_to_le16(MWIFIEX_TDLS_IDLE_TIMEOUT); 1650 timeout->value = cpu_to_le16(MWIFIEX_TDLS_IDLE_TIMEOUT_IN_SEC);
1651 config_len += sizeof(struct mwifiex_ie_types_tdls_idle_timeout); 1651 config_len += sizeof(struct mwifiex_ie_types_tdls_idle_timeout);
1652 1652
1653 break; 1653 break;
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index 822357b7b0bb..08b78baeb846 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -908,7 +908,7 @@ static int mwifiex_ret_tdls_oper(struct mwifiex_private *priv,
908 break; 908 break;
909 default: 909 default:
910 dev_err(priv->adapter->dev, 910 dev_err(priv->adapter->dev,
911 "Unknown TDLS command action respnse %d", action); 911 "Unknown TDLS command action response %d", action);
912 return -1; 912 return -1;
913 } 913 }
914 914
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 1a03d4d8b418..caae9738100a 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -283,10 +283,6 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
283 priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) { 283 priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) {
284 u8 config_bands; 284 u8 config_bands;
285 285
286 ret = mwifiex_deauthenticate(priv, NULL);
287 if (ret)
288 goto done;
289
290 if (!bss_desc) 286 if (!bss_desc)
291 return -1; 287 return -1;
292 288
@@ -345,12 +341,6 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
345 goto done; 341 goto done;
346 } 342 }
347 343
348 /* Exit Adhoc mode first */
349 dev_dbg(adapter->dev, "info: Sending Adhoc Stop\n");
350 ret = mwifiex_deauthenticate(priv, NULL);
351 if (ret)
352 goto done;
353
354 priv->adhoc_is_link_sensed = false; 344 priv->adhoc_is_link_sensed = false;
355 345
356 ret = mwifiex_check_network_compatibility(priv, bss_desc); 346 ret = mwifiex_check_network_compatibility(priv, bss_desc);
diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c
index a414161c6064..4c5fd953893d 100644
--- a/drivers/net/wireless/mwifiex/tdls.c
+++ b/drivers/net/wireless/mwifiex/tdls.c
@@ -781,6 +781,7 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
781 struct mwifiex_sta_node *sta_ptr; 781 struct mwifiex_sta_node *sta_ptr;
782 u8 *peer, *pos, *end; 782 u8 *peer, *pos, *end;
783 u8 i, action, basic; 783 u8 i, action, basic;
784 __le16 cap = 0;
784 int ie_len = 0; 785 int ie_len = 0;
785 786
786 if (len < (sizeof(struct ethhdr) + 3)) 787 if (len < (sizeof(struct ethhdr) + 3))
@@ -792,18 +793,9 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
792 793
793 peer = buf + ETH_ALEN; 794 peer = buf + ETH_ALEN;
794 action = *(buf + sizeof(struct ethhdr) + 2); 795 action = *(buf + sizeof(struct ethhdr) + 2);
795
796 /* just handle TDLS setup request/response/confirm */
797 if (action > WLAN_TDLS_SETUP_CONFIRM)
798 return;
799
800 dev_dbg(priv->adapter->dev, 796 dev_dbg(priv->adapter->dev,
801 "rx:tdls action: peer=%pM, action=%d\n", peer, action); 797 "rx:tdls action: peer=%pM, action=%d\n", peer, action);
802 798
803 sta_ptr = mwifiex_add_sta_entry(priv, peer);
804 if (!sta_ptr)
805 return;
806
807 switch (action) { 799 switch (action) {
808 case WLAN_TDLS_SETUP_REQUEST: 800 case WLAN_TDLS_SETUP_REQUEST:
809 if (len < (sizeof(struct ethhdr) + TDLS_REQ_FIX_LEN)) 801 if (len < (sizeof(struct ethhdr) + TDLS_REQ_FIX_LEN))
@@ -811,7 +803,7 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
811 803
812 pos = buf + sizeof(struct ethhdr) + 4; 804 pos = buf + sizeof(struct ethhdr) + 4;
813 /* payload 1+ category 1 + action 1 + dialog 1 */ 805 /* payload 1+ category 1 + action 1 + dialog 1 */
814 sta_ptr->tdls_cap.capab = cpu_to_le16(*(u16 *)pos); 806 cap = cpu_to_le16(*(u16 *)pos);
815 ie_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN; 807 ie_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN;
816 pos += 2; 808 pos += 2;
817 break; 809 break;
@@ -821,7 +813,7 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
821 return; 813 return;
822 /* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/ 814 /* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/
823 pos = buf + sizeof(struct ethhdr) + 6; 815 pos = buf + sizeof(struct ethhdr) + 6;
824 sta_ptr->tdls_cap.capab = cpu_to_le16(*(u16 *)pos); 816 cap = cpu_to_le16(*(u16 *)pos);
825 ie_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN; 817 ie_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN;
826 pos += 2; 818 pos += 2;
827 break; 819 break;
@@ -833,10 +825,16 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
833 ie_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN; 825 ie_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN;
834 break; 826 break;
835 default: 827 default:
836 dev_warn(priv->adapter->dev, "Unknown TDLS frame type.\n"); 828 dev_dbg(priv->adapter->dev, "Unknown TDLS frame type.\n");
837 return; 829 return;
838 } 830 }
839 831
832 sta_ptr = mwifiex_add_sta_entry(priv, peer);
833 if (!sta_ptr)
834 return;
835
836 sta_ptr->tdls_cap.capab = cap;
837
840 for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) { 838 for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) {
841 if (pos + 2 + pos[1] > end) 839 if (pos + 2 + pos[1] > end)
842 break; 840 break;
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 832006b5aab1..573897b8e878 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -1284,6 +1284,8 @@ static struct usb_device_id rt2800usb_device_table[] = {
1284 /* Arcadyan */ 1284 /* Arcadyan */
1285 { USB_DEVICE(0x043e, 0x7a12) }, 1285 { USB_DEVICE(0x043e, 0x7a12) },
1286 { USB_DEVICE(0x043e, 0x7a32) }, 1286 { USB_DEVICE(0x043e, 0x7a32) },
1287 /* ASUS */
1288 { USB_DEVICE(0x0b05, 0x17e8) },
1287 /* Azurewave */ 1289 /* Azurewave */
1288 { USB_DEVICE(0x13d3, 0x3329) }, 1290 { USB_DEVICE(0x13d3, 0x3329) },
1289 { USB_DEVICE(0x13d3, 0x3365) }, 1291 { USB_DEVICE(0x13d3, 0x3365) },
@@ -1320,6 +1322,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
1320 { USB_DEVICE(0x057c, 0x8501) }, 1322 { USB_DEVICE(0x057c, 0x8501) },
1321 /* Buffalo */ 1323 /* Buffalo */
1322 { USB_DEVICE(0x0411, 0x0241) }, 1324 { USB_DEVICE(0x0411, 0x0241) },
1325 { USB_DEVICE(0x0411, 0x0253) },
1323 /* D-Link */ 1326 /* D-Link */
1324 { USB_DEVICE(0x2001, 0x3c1a) }, 1327 { USB_DEVICE(0x2001, 0x3c1a) },
1325 { USB_DEVICE(0x2001, 0x3c21) }, 1328 { USB_DEVICE(0x2001, 0x3c21) },
@@ -1410,6 +1413,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
1410 { USB_DEVICE(0x0df6, 0x0053) }, 1413 { USB_DEVICE(0x0df6, 0x0053) },
1411 { USB_DEVICE(0x0df6, 0x0069) }, 1414 { USB_DEVICE(0x0df6, 0x0069) },
1412 { USB_DEVICE(0x0df6, 0x006f) }, 1415 { USB_DEVICE(0x0df6, 0x006f) },
1416 { USB_DEVICE(0x0df6, 0x0078) },
1413 /* SMC */ 1417 /* SMC */
1414 { USB_DEVICE(0x083a, 0xa512) }, 1418 { USB_DEVICE(0x083a, 0xa512) },
1415 { USB_DEVICE(0x083a, 0xc522) }, 1419 { USB_DEVICE(0x083a, 0xc522) },
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index d50dfac91631..0bccf123831e 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1668,7 +1668,7 @@ static bool wl12xx_lnk_high_prio(struct wl1271 *wl, u8 hlid,
1668{ 1668{
1669 u8 thold; 1669 u8 thold;
1670 1670
1671 if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map)) 1671 if (test_bit(hlid, &wl->fw_fast_lnk_map))
1672 thold = wl->conf.tx.fast_link_thold; 1672 thold = wl->conf.tx.fast_link_thold;
1673 else 1673 else
1674 thold = wl->conf.tx.slow_link_thold; 1674 thold = wl->conf.tx.slow_link_thold;
diff --git a/drivers/net/wireless/ti/wl18xx/cmd.c b/drivers/net/wireless/ti/wl18xx/cmd.c
index 7649c75cd68d..44f0b205b065 100644
--- a/drivers/net/wireless/ti/wl18xx/cmd.c
+++ b/drivers/net/wireless/ti/wl18xx/cmd.c
@@ -78,3 +78,92 @@ out_free:
78out: 78out:
79 return ret; 79 return ret;
80} 80}
81
82int wl18xx_cmd_smart_config_start(struct wl1271 *wl, u32 group_bitmap)
83{
84 struct wl18xx_cmd_smart_config_start *cmd;
85 int ret = 0;
86
87 wl1271_debug(DEBUG_CMD, "cmd smart config start group_bitmap=0x%x",
88 group_bitmap);
89
90 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
91 if (!cmd) {
92 ret = -ENOMEM;
93 goto out;
94 }
95
96 cmd->group_id_bitmask = cpu_to_le32(group_bitmap);
97
98 ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_START, cmd, sizeof(*cmd), 0);
99 if (ret < 0) {
100 wl1271_error("failed to send smart config start command");
101 goto out_free;
102 }
103
104out_free:
105 kfree(cmd);
106out:
107 return ret;
108}
109
110int wl18xx_cmd_smart_config_stop(struct wl1271 *wl)
111{
112 struct wl1271_cmd_header *cmd;
113 int ret = 0;
114
115 wl1271_debug(DEBUG_CMD, "cmd smart config stop");
116
117 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
118 if (!cmd) {
119 ret = -ENOMEM;
120 goto out;
121 }
122
123 ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_STOP, cmd, sizeof(*cmd), 0);
124 if (ret < 0) {
125 wl1271_error("failed to send smart config stop command");
126 goto out_free;
127 }
128
129out_free:
130 kfree(cmd);
131out:
132 return ret;
133}
134
135int wl18xx_cmd_smart_config_set_group_key(struct wl1271 *wl, u16 group_id,
136 u8 key_len, u8 *key)
137{
138 struct wl18xx_cmd_smart_config_set_group_key *cmd;
139 int ret = 0;
140
141 wl1271_debug(DEBUG_CMD, "cmd smart config set group key id=0x%x",
142 group_id);
143
144 if (key_len != sizeof(cmd->key)) {
145 wl1271_error("invalid group key size: %d", key_len);
146 return -E2BIG;
147 }
148
149 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
150 if (!cmd) {
151 ret = -ENOMEM;
152 goto out;
153 }
154
155 cmd->group_id = cpu_to_le32(group_id);
156 memcpy(cmd->key, key, key_len);
157
158 ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_SET_GROUP_KEY, cmd,
159 sizeof(*cmd), 0);
160 if (ret < 0) {
161 wl1271_error("failed to send smart config set group key cmd");
162 goto out_free;
163 }
164
165out_free:
166 kfree(cmd);
167out:
168 return ret;
169}
diff --git a/drivers/net/wireless/ti/wl18xx/cmd.h b/drivers/net/wireless/ti/wl18xx/cmd.h
index 6687d10899ac..92499e2dfa83 100644
--- a/drivers/net/wireless/ti/wl18xx/cmd.h
+++ b/drivers/net/wireless/ti/wl18xx/cmd.h
@@ -45,8 +45,25 @@ struct wl18xx_cmd_channel_switch {
45 u8 padding[2]; 45 u8 padding[2];
46} __packed; 46} __packed;
47 47
48struct wl18xx_cmd_smart_config_start {
49 struct wl1271_cmd_header header;
50
51 __le32 group_id_bitmask;
52} __packed;
53
54struct wl18xx_cmd_smart_config_set_group_key {
55 struct wl1271_cmd_header header;
56
57 __le32 group_id;
58
59 u8 key[16];
60} __packed;
61
48int wl18xx_cmd_channel_switch(struct wl1271 *wl, 62int wl18xx_cmd_channel_switch(struct wl1271 *wl,
49 struct wl12xx_vif *wlvif, 63 struct wl12xx_vif *wlvif,
50 struct ieee80211_channel_switch *ch_switch); 64 struct ieee80211_channel_switch *ch_switch);
51 65int wl18xx_cmd_smart_config_start(struct wl1271 *wl, u32 group_bitmap);
66int wl18xx_cmd_smart_config_stop(struct wl1271 *wl);
67int wl18xx_cmd_smart_config_set_group_key(struct wl1271 *wl, u16 group_id,
68 u8 key_len, u8 *key);
52#endif 69#endif
diff --git a/drivers/net/wireless/ti/wl18xx/event.c b/drivers/net/wireless/ti/wl18xx/event.c
index c9199d7804c6..eb1848e08424 100644
--- a/drivers/net/wireless/ti/wl18xx/event.c
+++ b/drivers/net/wireless/ti/wl18xx/event.c
@@ -19,10 +19,12 @@
19 * 19 *
20 */ 20 */
21 21
22#include <net/genetlink.h>
22#include "event.h" 23#include "event.h"
23#include "scan.h" 24#include "scan.h"
24#include "../wlcore/cmd.h" 25#include "../wlcore/cmd.h"
25#include "../wlcore/debug.h" 26#include "../wlcore/debug.h"
27#include "../wlcore/vendor_cmd.h"
26 28
27int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event, 29int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event,
28 bool *timeout) 30 bool *timeout)
@@ -45,6 +47,58 @@ int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event,
45 return wlcore_cmd_wait_for_event_or_timeout(wl, local_event, timeout); 47 return wlcore_cmd_wait_for_event_or_timeout(wl, local_event, timeout);
46} 48}
47 49
50static int wlcore_smart_config_sync_event(struct wl1271 *wl, u8 sync_channel,
51 u8 sync_band)
52{
53 struct sk_buff *skb;
54 enum ieee80211_band band;
55 int freq;
56
57 if (sync_band == WLCORE_BAND_5GHZ)
58 band = IEEE80211_BAND_5GHZ;
59 else
60 band = IEEE80211_BAND_2GHZ;
61
62 freq = ieee80211_channel_to_frequency(sync_channel, band);
63
64 wl1271_debug(DEBUG_EVENT,
65 "SMART_CONFIG_SYNC_EVENT_ID, freq: %d (chan: %d band %d)",
66 freq, sync_channel, sync_band);
67 skb = cfg80211_vendor_event_alloc(wl->hw->wiphy, 20,
68 WLCORE_VENDOR_EVENT_SC_SYNC,
69 GFP_KERNEL);
70
71 if (nla_put_u32(skb, WLCORE_VENDOR_ATTR_FREQ, freq)) {
72 kfree_skb(skb);
73 return -EMSGSIZE;
74 }
75 cfg80211_vendor_event(skb, GFP_KERNEL);
76 return 0;
77}
78
79static int wlcore_smart_config_decode_event(struct wl1271 *wl,
80 u8 ssid_len, u8 *ssid,
81 u8 pwd_len, u8 *pwd)
82{
83 struct sk_buff *skb;
84
85 wl1271_debug(DEBUG_EVENT, "SMART_CONFIG_DECODE_EVENT_ID");
86 wl1271_dump_ascii(DEBUG_EVENT, "SSID:", ssid, ssid_len);
87
88 skb = cfg80211_vendor_event_alloc(wl->hw->wiphy,
89 ssid_len + pwd_len + 20,
90 WLCORE_VENDOR_EVENT_SC_DECODE,
91 GFP_KERNEL);
92
93 if (nla_put(skb, WLCORE_VENDOR_ATTR_SSID, ssid_len, ssid) ||
94 nla_put(skb, WLCORE_VENDOR_ATTR_PSK, pwd_len, pwd)) {
95 kfree_skb(skb);
96 return -EMSGSIZE;
97 }
98 cfg80211_vendor_event(skb, GFP_KERNEL);
99 return 0;
100}
101
48int wl18xx_process_mailbox_events(struct wl1271 *wl) 102int wl18xx_process_mailbox_events(struct wl1271 *wl)
49{ 103{
50 struct wl18xx_event_mailbox *mbox = wl->mbox; 104 struct wl18xx_event_mailbox *mbox = wl->mbox;
@@ -107,5 +161,16 @@ int wl18xx_process_mailbox_events(struct wl1271 *wl)
107 if (vector & REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID) 161 if (vector & REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID)
108 wlcore_event_roc_complete(wl); 162 wlcore_event_roc_complete(wl);
109 163
164 if (vector & SMART_CONFIG_SYNC_EVENT_ID)
165 wlcore_smart_config_sync_event(wl, mbox->sc_sync_channel,
166 mbox->sc_sync_band);
167
168 if (vector & SMART_CONFIG_DECODE_EVENT_ID)
169 wlcore_smart_config_decode_event(wl,
170 mbox->sc_ssid_len,
171 mbox->sc_ssid,
172 mbox->sc_pwd_len,
173 mbox->sc_pwd);
174
110 return 0; 175 return 0;
111} 176}
diff --git a/drivers/net/wireless/ti/wl18xx/event.h b/drivers/net/wireless/ti/wl18xx/event.h
index a76e98eb8372..0680312d4943 100644
--- a/drivers/net/wireless/ti/wl18xx/event.h
+++ b/drivers/net/wireless/ti/wl18xx/event.h
@@ -38,6 +38,8 @@ enum {
38 REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID = BIT(18), 38 REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID = BIT(18),
39 DFS_CHANNELS_CONFIG_COMPLETE_EVENT = BIT(19), 39 DFS_CHANNELS_CONFIG_COMPLETE_EVENT = BIT(19),
40 PERIODIC_SCAN_REPORT_EVENT_ID = BIT(20), 40 PERIODIC_SCAN_REPORT_EVENT_ID = BIT(20),
41 SMART_CONFIG_SYNC_EVENT_ID = BIT(22),
42 SMART_CONFIG_DECODE_EVENT_ID = BIT(23),
41}; 43};
42 44
43struct wl18xx_event_mailbox { 45struct wl18xx_event_mailbox {
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index de5b4fa5d166..7af1936719eb 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -992,7 +992,10 @@ static int wl18xx_boot(struct wl1271 *wl)
992 REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | 992 REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
993 INACTIVE_STA_EVENT_ID | 993 INACTIVE_STA_EVENT_ID |
994 CHANNEL_SWITCH_COMPLETE_EVENT_ID | 994 CHANNEL_SWITCH_COMPLETE_EVENT_ID |
995 DFS_CHANNELS_CONFIG_COMPLETE_EVENT; 995 DFS_CHANNELS_CONFIG_COMPLETE_EVENT |
996 SMART_CONFIG_SYNC_EVENT_ID |
997 SMART_CONFIG_DECODE_EVENT_ID;
998;
996 999
997 wl->ap_event_mask = MAX_TX_FAILURE_EVENT_ID; 1000 wl->ap_event_mask = MAX_TX_FAILURE_EVENT_ID;
998 1001
@@ -1606,15 +1609,20 @@ static bool wl18xx_lnk_high_prio(struct wl1271 *wl, u8 hlid,
1606 u8 thold; 1609 u8 thold;
1607 struct wl18xx_fw_status_priv *status_priv = 1610 struct wl18xx_fw_status_priv *status_priv =
1608 (struct wl18xx_fw_status_priv *)wl->fw_status->priv; 1611 (struct wl18xx_fw_status_priv *)wl->fw_status->priv;
1609 u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap); 1612 unsigned long suspend_bitmap;
1613
1614 /* if we don't have the link map yet, assume they all low prio */
1615 if (!status_priv)
1616 return false;
1610 1617
1611 /* suspended links are never high priority */ 1618 /* suspended links are never high priority */
1612 if (test_bit(hlid, (unsigned long *)&suspend_bitmap)) 1619 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
1620 if (test_bit(hlid, &suspend_bitmap))
1613 return false; 1621 return false;
1614 1622
1615 /* the priority thresholds are taken from FW */ 1623 /* the priority thresholds are taken from FW */
1616 if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map) && 1624 if (test_bit(hlid, &wl->fw_fast_lnk_map) &&
1617 !test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map)) 1625 !test_bit(hlid, &wl->ap_fw_ps_map))
1618 thold = status_priv->tx_fast_link_prio_threshold; 1626 thold = status_priv->tx_fast_link_prio_threshold;
1619 else 1627 else
1620 thold = status_priv->tx_slow_link_prio_threshold; 1628 thold = status_priv->tx_slow_link_prio_threshold;
@@ -1628,12 +1636,17 @@ static bool wl18xx_lnk_low_prio(struct wl1271 *wl, u8 hlid,
1628 u8 thold; 1636 u8 thold;
1629 struct wl18xx_fw_status_priv *status_priv = 1637 struct wl18xx_fw_status_priv *status_priv =
1630 (struct wl18xx_fw_status_priv *)wl->fw_status->priv; 1638 (struct wl18xx_fw_status_priv *)wl->fw_status->priv;
1631 u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap); 1639 unsigned long suspend_bitmap;
1640
1641 /* if we don't have the link map yet, assume they all low prio */
1642 if (!status_priv)
1643 return true;
1632 1644
1633 if (test_bit(hlid, (unsigned long *)&suspend_bitmap)) 1645 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
1646 if (test_bit(hlid, &suspend_bitmap))
1634 thold = status_priv->tx_suspend_threshold; 1647 thold = status_priv->tx_suspend_threshold;
1635 else if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map) && 1648 else if (test_bit(hlid, &wl->fw_fast_lnk_map) &&
1636 !test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map)) 1649 !test_bit(hlid, &wl->ap_fw_ps_map))
1637 thold = status_priv->tx_fast_stop_threshold; 1650 thold = status_priv->tx_fast_stop_threshold;
1638 else 1651 else
1639 thold = status_priv->tx_slow_stop_threshold; 1652 thold = status_priv->tx_slow_stop_threshold;
@@ -1687,6 +1700,9 @@ static struct wlcore_ops wl18xx_ops = {
1687 .convert_hwaddr = wl18xx_convert_hwaddr, 1700 .convert_hwaddr = wl18xx_convert_hwaddr,
1688 .lnk_high_prio = wl18xx_lnk_high_prio, 1701 .lnk_high_prio = wl18xx_lnk_high_prio,
1689 .lnk_low_prio = wl18xx_lnk_low_prio, 1702 .lnk_low_prio = wl18xx_lnk_low_prio,
1703 .smart_config_start = wl18xx_cmd_smart_config_start,
1704 .smart_config_stop = wl18xx_cmd_smart_config_stop,
1705 .smart_config_set_group_key = wl18xx_cmd_smart_config_set_group_key,
1690}; 1706};
1691 1707
1692/* HT cap appropriate for wide channels in 2Ghz */ 1708/* HT cap appropriate for wide channels in 2Ghz */
diff --git a/drivers/net/wireless/ti/wl18xx/tx.c b/drivers/net/wireless/ti/wl18xx/tx.c
index be1ebd55ac88..3406ffb53325 100644
--- a/drivers/net/wireless/ti/wl18xx/tx.c
+++ b/drivers/net/wireless/ti/wl18xx/tx.c
@@ -30,7 +30,7 @@
30 30
31static 31static
32void wl18xx_get_last_tx_rate(struct wl1271 *wl, struct ieee80211_vif *vif, 32void wl18xx_get_last_tx_rate(struct wl1271 *wl, struct ieee80211_vif *vif,
33 struct ieee80211_tx_rate *rate) 33 u8 band, struct ieee80211_tx_rate *rate)
34{ 34{
35 u8 fw_rate = wl->fw_status->counters.tx_last_rate; 35 u8 fw_rate = wl->fw_status->counters.tx_last_rate;
36 36
@@ -43,6 +43,8 @@ void wl18xx_get_last_tx_rate(struct wl1271 *wl, struct ieee80211_vif *vif,
43 43
44 if (fw_rate <= CONF_HW_RATE_INDEX_54MBPS) { 44 if (fw_rate <= CONF_HW_RATE_INDEX_54MBPS) {
45 rate->idx = fw_rate; 45 rate->idx = fw_rate;
46 if (band == IEEE80211_BAND_5GHZ)
47 rate->idx -= CONF_HW_RATE_INDEX_6MBPS;
46 rate->flags = 0; 48 rate->flags = 0;
47 } else { 49 } else {
48 rate->flags = IEEE80211_TX_RC_MCS; 50 rate->flags = IEEE80211_TX_RC_MCS;
@@ -102,7 +104,8 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte)
102 * first pass info->control.vif while it's valid, and then fill out 104 * first pass info->control.vif while it's valid, and then fill out
103 * the info->status structures 105 * the info->status structures
104 */ 106 */
105 wl18xx_get_last_tx_rate(wl, info->control.vif, &info->status.rates[0]); 107 wl18xx_get_last_tx_rate(wl, info->control.vif,
108 info->band, &info->status.rates[0]);
106 109
107 info->status.rates[0].count = 1; /* no data about retries */ 110 info->status.rates[0].count = 1; /* no data about retries */
108 info->status.ack_signal = -1; 111 info->status.ack_signal = -1;
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h
index eb7cfe817010..6a2b88030c1d 100644
--- a/drivers/net/wireless/ti/wl18xx/wl18xx.h
+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h
@@ -38,7 +38,7 @@
38#define WL18XX_NUM_TX_DESCRIPTORS 32 38#define WL18XX_NUM_TX_DESCRIPTORS 32
39#define WL18XX_NUM_RX_DESCRIPTORS 32 39#define WL18XX_NUM_RX_DESCRIPTORS 32
40 40
41#define WL18XX_NUM_MAC_ADDRESSES 3 41#define WL18XX_NUM_MAC_ADDRESSES 2
42 42
43#define WL18XX_RX_BA_MAX_SESSIONS 13 43#define WL18XX_RX_BA_MAX_SESSIONS 13
44 44
diff --git a/drivers/net/wireless/ti/wlcore/Makefile b/drivers/net/wireless/ti/wlcore/Makefile
index 4f23931d7bd5..0a69c1373643 100644
--- a/drivers/net/wireless/ti/wlcore/Makefile
+++ b/drivers/net/wireless/ti/wlcore/Makefile
@@ -1,5 +1,5 @@
1wlcore-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \ 1wlcore-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \
2 boot.o init.o debugfs.o scan.o sysfs.o 2 boot.o init.o debugfs.o scan.o sysfs.o vendor_cmd.o
3 3
4wlcore_spi-objs = spi.o 4wlcore_spi-objs = spi.o
5wlcore_sdio-objs = sdio.o 5wlcore_sdio-objs = sdio.o
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index e269c0a57017..05604ee31224 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -372,9 +372,9 @@ void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
372 wl1271_tx_reset_link_queues(wl, *hlid); 372 wl1271_tx_reset_link_queues(wl, *hlid);
373 wl->links[*hlid].wlvif = NULL; 373 wl->links[*hlid].wlvif = NULL;
374 374
375 if (wlvif->bss_type == BSS_TYPE_STA_BSS || 375 if (wlvif->bss_type == BSS_TYPE_AP_BSS &&
376 (wlvif->bss_type == BSS_TYPE_AP_BSS && 376 *hlid == wlvif->ap.bcast_hlid) {
377 *hlid == wlvif->ap.bcast_hlid)) { 377 u32 sqn_padding = WL1271_TX_SQN_POST_RECOVERY_PADDING;
378 /* 378 /*
379 * save the total freed packets in the wlvif, in case this is 379 * save the total freed packets in the wlvif, in case this is
380 * recovery or suspend 380 * recovery or suspend
@@ -385,9 +385,11 @@ void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
385 * increment the initial seq number on recovery to account for 385 * increment the initial seq number on recovery to account for
386 * transmitted packets that we haven't yet got in the FW status 386 * transmitted packets that we haven't yet got in the FW status
387 */ 387 */
388 if (wlvif->encryption_type == KEY_GEM)
389 sqn_padding = WL1271_TX_SQN_POST_RECOVERY_PADDING_GEM;
390
388 if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) 391 if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
389 wlvif->total_freed_pkts += 392 wlvif->total_freed_pkts += sqn_padding;
390 WL1271_TX_SQN_POST_RECOVERY_PADDING;
391 } 393 }
392 394
393 wl->links[*hlid].total_freed_pkts = 0; 395 wl->links[*hlid].total_freed_pkts = 0;
diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h
index 6788d7356ca5..ca6a28b03f8f 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.h
+++ b/drivers/net/wireless/ti/wlcore/cmd.h
@@ -170,6 +170,9 @@ enum wl1271_commands {
170 170
171 /* start of 18xx specific commands */ 171 /* start of 18xx specific commands */
172 CMD_DFS_CHANNEL_CONFIG = 60, 172 CMD_DFS_CHANNEL_CONFIG = 60,
173 CMD_SMART_CONFIG_START = 61,
174 CMD_SMART_CONFIG_STOP = 62,
175 CMD_SMART_CONFIG_SET_GROUP_KEY = 63,
173 176
174 MAX_COMMAND_ID = 0xFFFF, 177 MAX_COMMAND_ID = 0xFFFF,
175}; 178};
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c
index 89893c717025..0be21f62fcb0 100644
--- a/drivers/net/wireless/ti/wlcore/debugfs.c
+++ b/drivers/net/wireless/ti/wlcore/debugfs.c
@@ -496,7 +496,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
496 DRIVER_STATE_PRINT_INT(sg_enabled); 496 DRIVER_STATE_PRINT_INT(sg_enabled);
497 DRIVER_STATE_PRINT_INT(enable_11a); 497 DRIVER_STATE_PRINT_INT(enable_11a);
498 DRIVER_STATE_PRINT_INT(noise); 498 DRIVER_STATE_PRINT_INT(noise);
499 DRIVER_STATE_PRINT_HEX(ap_fw_ps_map); 499 DRIVER_STATE_PRINT_LHEX(ap_fw_ps_map);
500 DRIVER_STATE_PRINT_LHEX(ap_ps_map); 500 DRIVER_STATE_PRINT_LHEX(ap_ps_map);
501 DRIVER_STATE_PRINT_HEX(quirks); 501 DRIVER_STATE_PRINT_HEX(quirks);
502 DRIVER_STATE_PRINT_HEX(irq); 502 DRIVER_STATE_PRINT_HEX(irq);
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h
index 1555ff970050..aa9f82c72296 100644
--- a/drivers/net/wireless/ti/wlcore/hw_ops.h
+++ b/drivers/net/wireless/ti/wlcore/hw_ops.h
@@ -260,4 +260,31 @@ wlcore_hw_lnk_low_prio(struct wl1271 *wl, u8 hlid,
260 return wl->ops->lnk_low_prio(wl, hlid, lnk); 260 return wl->ops->lnk_low_prio(wl, hlid, lnk);
261} 261}
262 262
263static inline int
264wlcore_smart_config_start(struct wl1271 *wl, u32 group_bitmap)
265{
266 if (!wl->ops->smart_config_start)
267 return -EINVAL;
268
269 return wl->ops->smart_config_start(wl, group_bitmap);
270}
271
272static inline int
273wlcore_smart_config_stop(struct wl1271 *wl)
274{
275 if (!wl->ops->smart_config_stop)
276 return -EINVAL;
277
278 return wl->ops->smart_config_stop(wl);
279}
280
281static inline int
282wlcore_smart_config_set_group_key(struct wl1271 *wl, u16 group_id,
283 u8 key_len, u8 *key)
284{
285 if (!wl->ops->smart_config_set_group_key)
286 return -EINVAL;
287
288 return wl->ops->smart_config_set_group_key(wl, group_id, key_len, key);
289}
263#endif 290#endif
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 48f83868f9cb..575c8f6d4009 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -37,6 +37,7 @@
37#include "init.h" 37#include "init.h"
38#include "debugfs.h" 38#include "debugfs.h"
39#include "testmode.h" 39#include "testmode.h"
40#include "vendor_cmd.h"
40#include "scan.h" 41#include "scan.h"
41#include "hw_ops.h" 42#include "hw_ops.h"
42#include "sysfs.h" 43#include "sysfs.h"
@@ -332,7 +333,7 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl,
332{ 333{
333 bool fw_ps; 334 bool fw_ps;
334 335
335 fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); 336 fw_ps = test_bit(hlid, &wl->ap_fw_ps_map);
336 337
337 /* 338 /*
338 * Wake up from high level PS if the STA is asleep with too little 339 * Wake up from high level PS if the STA is asleep with too little
@@ -359,13 +360,13 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl,
359 struct wl12xx_vif *wlvif, 360 struct wl12xx_vif *wlvif,
360 struct wl_fw_status *status) 361 struct wl_fw_status *status)
361{ 362{
362 u32 cur_fw_ps_map; 363 unsigned long cur_fw_ps_map;
363 u8 hlid; 364 u8 hlid;
364 365
365 cur_fw_ps_map = status->link_ps_bitmap; 366 cur_fw_ps_map = status->link_ps_bitmap;
366 if (wl->ap_fw_ps_map != cur_fw_ps_map) { 367 if (wl->ap_fw_ps_map != cur_fw_ps_map) {
367 wl1271_debug(DEBUG_PSM, 368 wl1271_debug(DEBUG_PSM,
368 "link ps prev 0x%x cur 0x%x changed 0x%x", 369 "link ps prev 0x%lx cur 0x%lx changed 0x%lx",
369 wl->ap_fw_ps_map, cur_fw_ps_map, 370 wl->ap_fw_ps_map, cur_fw_ps_map,
370 wl->ap_fw_ps_map ^ cur_fw_ps_map); 371 wl->ap_fw_ps_map ^ cur_fw_ps_map);
371 372
@@ -898,6 +899,44 @@ out:
898 wlcore_set_partition(wl, &old_part); 899 wlcore_set_partition(wl, &old_part);
899} 900}
900 901
902static void wlcore_save_freed_pkts(struct wl1271 *wl, struct wl12xx_vif *wlvif,
903 u8 hlid, struct ieee80211_sta *sta)
904{
905 struct wl1271_station *wl_sta;
906 u32 sqn_recovery_padding = WL1271_TX_SQN_POST_RECOVERY_PADDING;
907
908 wl_sta = (void *)sta->drv_priv;
909 wl_sta->total_freed_pkts = wl->links[hlid].total_freed_pkts;
910
911 /*
912 * increment the initial seq number on recovery to account for
913 * transmitted packets that we haven't yet got in the FW status
914 */
915 if (wlvif->encryption_type == KEY_GEM)
916 sqn_recovery_padding = WL1271_TX_SQN_POST_RECOVERY_PADDING_GEM;
917
918 if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
919 wl_sta->total_freed_pkts += sqn_recovery_padding;
920}
921
922static void wlcore_save_freed_pkts_addr(struct wl1271 *wl,
923 struct wl12xx_vif *wlvif,
924 u8 hlid, const u8 *addr)
925{
926 struct ieee80211_sta *sta;
927 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
928
929 if (WARN_ON(hlid == WL12XX_INVALID_LINK_ID ||
930 is_zero_ether_addr(addr)))
931 return;
932
933 rcu_read_lock();
934 sta = ieee80211_find_sta(vif, addr);
935 if (sta)
936 wlcore_save_freed_pkts(wl, wlvif, hlid, sta);
937 rcu_read_unlock();
938}
939
901static void wlcore_print_recovery(struct wl1271 *wl) 940static void wlcore_print_recovery(struct wl1271 *wl)
902{ 941{
903 u32 pc = 0; 942 u32 pc = 0;
@@ -961,6 +1000,13 @@ static void wl1271_recovery_work(struct work_struct *work)
961 wlvif = list_first_entry(&wl->wlvif_list, 1000 wlvif = list_first_entry(&wl->wlvif_list,
962 struct wl12xx_vif, list); 1001 struct wl12xx_vif, list);
963 vif = wl12xx_wlvif_to_vif(wlvif); 1002 vif = wl12xx_wlvif_to_vif(wlvif);
1003
1004 if (wlvif->bss_type == BSS_TYPE_STA_BSS &&
1005 test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) {
1006 wlcore_save_freed_pkts_addr(wl, wlvif, wlvif->sta.hlid,
1007 vif->bss_conf.bssid);
1008 }
1009
964 __wl1271_op_remove_interface(wl, vif, false); 1010 __wl1271_op_remove_interface(wl, vif, false);
965 } 1011 }
966 1012
@@ -4703,36 +4749,18 @@ static int wl1271_allocate_sta(struct wl1271 *wl,
4703 4749
4704void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid) 4750void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid)
4705{ 4751{
4706 struct wl1271_station *wl_sta;
4707 struct ieee80211_sta *sta;
4708 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
4709
4710 if (!test_bit(hlid, wlvif->ap.sta_hlid_map)) 4752 if (!test_bit(hlid, wlvif->ap.sta_hlid_map))
4711 return; 4753 return;
4712 4754
4713 clear_bit(hlid, wlvif->ap.sta_hlid_map); 4755 clear_bit(hlid, wlvif->ap.sta_hlid_map);
4714 __clear_bit(hlid, &wl->ap_ps_map); 4756 __clear_bit(hlid, &wl->ap_ps_map);
4715 __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); 4757 __clear_bit(hlid, &wl->ap_fw_ps_map);
4716 4758
4717 /* 4759 /*
4718 * save the last used PN in the private part of iee80211_sta, 4760 * save the last used PN in the private part of iee80211_sta,
4719 * in case of recovery/suspend 4761 * in case of recovery/suspend
4720 */ 4762 */
4721 rcu_read_lock(); 4763 wlcore_save_freed_pkts_addr(wl, wlvif, hlid, wl->links[hlid].addr);
4722 sta = ieee80211_find_sta(vif, wl->links[hlid].addr);
4723 if (sta) {
4724 wl_sta = (void *)sta->drv_priv;
4725 wl_sta->total_freed_pkts = wl->links[hlid].total_freed_pkts;
4726
4727 /*
4728 * increment the initial seq number on recovery to account for
4729 * transmitted packets that we haven't yet got in the FW status
4730 */
4731 if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
4732 wl_sta->total_freed_pkts +=
4733 WL1271_TX_SQN_POST_RECOVERY_PADDING;
4734 }
4735 rcu_read_unlock();
4736 4764
4737 wl12xx_free_link(wl, wlvif, &hlid); 4765 wl12xx_free_link(wl, wlvif, &hlid);
4738 wl->active_sta_count--; 4766 wl->active_sta_count--;
@@ -4915,6 +4943,21 @@ static int wl12xx_update_sta_state(struct wl1271 *wl,
4915 clear_bit(WLVIF_FLAG_STA_STATE_SENT, &wlvif->flags); 4943 clear_bit(WLVIF_FLAG_STA_STATE_SENT, &wlvif->flags);
4916 } 4944 }
4917 4945
4946 /* save seq number on disassoc (suspend) */
4947 if (is_sta &&
4948 old_state == IEEE80211_STA_ASSOC &&
4949 new_state == IEEE80211_STA_AUTH) {
4950 wlcore_save_freed_pkts(wl, wlvif, wlvif->sta.hlid, sta);
4951 wlvif->total_freed_pkts = 0;
4952 }
4953
4954 /* restore seq number on assoc (resume) */
4955 if (is_sta &&
4956 old_state == IEEE80211_STA_AUTH &&
4957 new_state == IEEE80211_STA_ASSOC) {
4958 wlvif->total_freed_pkts = wl_sta->total_freed_pkts;
4959 }
4960
4918 /* clear ROCs on failure or authorization */ 4961 /* clear ROCs on failure or authorization */
4919 if (is_sta && 4962 if (is_sta &&
4920 (new_state == IEEE80211_STA_AUTHORIZED || 4963 (new_state == IEEE80211_STA_AUTHORIZED ||
@@ -5149,6 +5192,10 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
5149 if (unlikely(wl->state == WLCORE_STATE_OFF)) { 5192 if (unlikely(wl->state == WLCORE_STATE_OFF)) {
5150 wl12xx_for_each_wlvif_sta(wl, wlvif) { 5193 wl12xx_for_each_wlvif_sta(wl, wlvif) {
5151 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); 5194 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
5195
5196 if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
5197 continue;
5198
5152 ieee80211_chswitch_done(vif, false); 5199 ieee80211_chswitch_done(vif, false);
5153 } 5200 }
5154 goto out; 5201 goto out;
@@ -5164,6 +5211,9 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
5164 wl12xx_for_each_wlvif_sta(wl, wlvif) { 5211 wl12xx_for_each_wlvif_sta(wl, wlvif) {
5165 unsigned long delay_usec; 5212 unsigned long delay_usec;
5166 5213
5214 if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
5215 continue;
5216
5167 ret = wl->ops->channel_switch(wl, wlvif, ch_switch); 5217 ret = wl->ops->channel_switch(wl, wlvif, ch_switch);
5168 if (ret) 5218 if (ret)
5169 goto out_sleep; 5219 goto out_sleep;
@@ -5619,7 +5669,7 @@ static void wl12xx_derive_mac_addresses(struct wl1271 *wl, u32 oui, u32 nic)
5619 memcpy(&wl->addresses[idx], &wl->addresses[0], 5669 memcpy(&wl->addresses[idx], &wl->addresses[0],
5620 sizeof(wl->addresses[0])); 5670 sizeof(wl->addresses[0]));
5621 /* LAA bit */ 5671 /* LAA bit */
5622 wl->addresses[idx].addr[2] |= BIT(1); 5672 wl->addresses[idx].addr[0] |= BIT(1);
5623 } 5673 }
5624 5674
5625 wl->hw->wiphy->n_addresses = WLCORE_NUM_MAC_ADDRESSES; 5675 wl->hw->wiphy->n_addresses = WLCORE_NUM_MAC_ADDRESSES;
@@ -5764,7 +5814,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
5764 wl->hw->wiphy->max_sched_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - 5814 wl->hw->wiphy->max_sched_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE -
5765 sizeof(struct ieee80211_header); 5815 sizeof(struct ieee80211_header);
5766 5816
5767 wl->hw->wiphy->max_remain_on_channel_duration = 5000; 5817 wl->hw->wiphy->max_remain_on_channel_duration = 30000;
5768 5818
5769 wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD | 5819 wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD |
5770 WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | 5820 WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
@@ -5833,6 +5883,9 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
5833 wl->hw->wiphy->iface_combinations = wl->iface_combinations; 5883 wl->hw->wiphy->iface_combinations = wl->iface_combinations;
5834 wl->hw->wiphy->n_iface_combinations = wl->n_iface_combinations; 5884 wl->hw->wiphy->n_iface_combinations = wl->n_iface_combinations;
5835 5885
5886 /* register vendor commands */
5887 wlcore_set_vendor_commands(wl->hw->wiphy);
5888
5836 SET_IEEE80211_DEV(wl->hw, wl->dev); 5889 SET_IEEE80211_DEV(wl->hw, wl->dev);
5837 5890
5838 wl->hw->sta_data_size = sizeof(struct wl1271_station); 5891 wl->hw->sta_data_size = sizeof(struct wl1271_station);
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
index 40b43115f835..f0ac36139bcc 100644
--- a/drivers/net/wireless/ti/wlcore/tx.c
+++ b/drivers/net/wireless/ti/wlcore/tx.c
@@ -126,7 +126,7 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl,
126 if (WARN_ON(!test_bit(hlid, wlvif->links_map))) 126 if (WARN_ON(!test_bit(hlid, wlvif->links_map)))
127 return; 127 return;
128 128
129 fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); 129 fw_ps = test_bit(hlid, &wl->ap_fw_ps_map);
130 tx_pkts = wl->links[hlid].allocated_pkts; 130 tx_pkts = wl->links[hlid].allocated_pkts;
131 131
132 /* 132 /*
diff --git a/drivers/net/wireless/ti/wlcore/vendor_cmd.c b/drivers/net/wireless/ti/wlcore/vendor_cmd.c
new file mode 100644
index 000000000000..ad86a48dcfcb
--- /dev/null
+++ b/drivers/net/wireless/ti/wlcore/vendor_cmd.c
@@ -0,0 +1,197 @@
1/*
2 * This file is part of wlcore
3 *
4 * Copyright (C) 2014 Texas Instruments. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 */
10
11#include <net/mac80211.h>
12#include <net/netlink.h>
13
14#include "wlcore.h"
15#include "debug.h"
16#include "ps.h"
17#include "hw_ops.h"
18#include "vendor_cmd.h"
19
20static const
21struct nla_policy wlcore_vendor_attr_policy[NUM_WLCORE_VENDOR_ATTR] = {
22 [WLCORE_VENDOR_ATTR_FREQ] = { .type = NLA_U32 },
23 [WLCORE_VENDOR_ATTR_GROUP_ID] = { .type = NLA_U32 },
24 [WLCORE_VENDOR_ATTR_GROUP_KEY] = { .type = NLA_U32,
25 .len = WLAN_MAX_KEY_LEN },
26};
27
28static int
29wlcore_vendor_cmd_smart_config_start(struct wiphy *wiphy,
30 struct wireless_dev *wdev,
31 const void *data, int data_len)
32{
33 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
34 struct wl1271 *wl = hw->priv;
35 struct nlattr *tb[NUM_WLCORE_VENDOR_ATTR];
36 int ret;
37
38 wl1271_debug(DEBUG_CMD, "vendor cmd smart config start");
39
40 if (!data)
41 return -EINVAL;
42
43 ret = nla_parse(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len,
44 wlcore_vendor_attr_policy);
45 if (ret)
46 return ret;
47
48 if (!tb[WLCORE_VENDOR_ATTR_GROUP_ID])
49 return -EINVAL;
50
51 mutex_lock(&wl->mutex);
52
53 if (unlikely(wl->state != WLCORE_STATE_ON)) {
54 ret = -EINVAL;
55 goto out;
56 }
57
58 ret = wl1271_ps_elp_wakeup(wl);
59 if (ret < 0)
60 goto out;
61
62 ret = wlcore_smart_config_start(wl,
63 nla_get_u32(tb[WLCORE_VENDOR_ATTR_GROUP_ID]));
64
65 wl1271_ps_elp_sleep(wl);
66out:
67 mutex_unlock(&wl->mutex);
68
69 return 0;
70}
71
72static int
73wlcore_vendor_cmd_smart_config_stop(struct wiphy *wiphy,
74 struct wireless_dev *wdev,
75 const void *data, int data_len)
76{
77 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
78 struct wl1271 *wl = hw->priv;
79 int ret;
80
81 wl1271_debug(DEBUG_CMD, "testmode cmd smart config stop");
82
83 mutex_lock(&wl->mutex);
84
85 if (unlikely(wl->state != WLCORE_STATE_ON)) {
86 ret = -EINVAL;
87 goto out;
88 }
89
90 ret = wl1271_ps_elp_wakeup(wl);
91 if (ret < 0)
92 goto out;
93
94 ret = wlcore_smart_config_stop(wl);
95
96 wl1271_ps_elp_sleep(wl);
97out:
98 mutex_unlock(&wl->mutex);
99
100 return ret;
101}
102
103static int
104wlcore_vendor_cmd_smart_config_set_group_key(struct wiphy *wiphy,
105 struct wireless_dev *wdev,
106 const void *data, int data_len)
107{
108 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
109 struct wl1271 *wl = hw->priv;
110 struct nlattr *tb[NUM_WLCORE_VENDOR_ATTR];
111 int ret;
112
113 wl1271_debug(DEBUG_CMD, "testmode cmd smart config set group key");
114
115 if (!data)
116 return -EINVAL;
117
118 ret = nla_parse(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len,
119 wlcore_vendor_attr_policy);
120 if (ret)
121 return ret;
122
123 if (!tb[WLCORE_VENDOR_ATTR_GROUP_ID] ||
124 !tb[WLCORE_VENDOR_ATTR_GROUP_KEY])
125 return -EINVAL;
126
127 mutex_lock(&wl->mutex);
128
129 if (unlikely(wl->state != WLCORE_STATE_ON)) {
130 ret = -EINVAL;
131 goto out;
132 }
133
134 ret = wl1271_ps_elp_wakeup(wl);
135 if (ret < 0)
136 goto out;
137
138 ret = wlcore_smart_config_set_group_key(wl,
139 nla_get_u32(tb[WLCORE_VENDOR_ATTR_GROUP_ID]),
140 nla_len(tb[WLCORE_VENDOR_ATTR_GROUP_KEY]),
141 nla_data(tb[WLCORE_VENDOR_ATTR_GROUP_KEY]));
142
143 wl1271_ps_elp_sleep(wl);
144out:
145 mutex_unlock(&wl->mutex);
146
147 return ret;
148}
149
150static const struct wiphy_vendor_command wlcore_vendor_commands[] = {
151 {
152 .info = {
153 .vendor_id = TI_OUI,
154 .subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_START,
155 },
156 .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
157 WIPHY_VENDOR_CMD_NEED_RUNNING,
158 .doit = wlcore_vendor_cmd_smart_config_start,
159 },
160 {
161 .info = {
162 .vendor_id = TI_OUI,
163 .subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_STOP,
164 },
165 .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
166 WIPHY_VENDOR_CMD_NEED_RUNNING,
167 .doit = wlcore_vendor_cmd_smart_config_stop,
168 },
169 {
170 .info = {
171 .vendor_id = TI_OUI,
172 .subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_SET_GROUP_KEY,
173 },
174 .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
175 WIPHY_VENDOR_CMD_NEED_RUNNING,
176 .doit = wlcore_vendor_cmd_smart_config_set_group_key,
177 },
178};
179
180static const struct nl80211_vendor_cmd_info wlcore_vendor_events[] = {
181 {
182 .vendor_id = TI_OUI,
183 .subcmd = WLCORE_VENDOR_EVENT_SC_SYNC,
184 },
185 {
186 .vendor_id = TI_OUI,
187 .subcmd = WLCORE_VENDOR_EVENT_SC_DECODE,
188 },
189};
190
191void wlcore_set_vendor_commands(struct wiphy *wiphy)
192{
193 wiphy->vendor_commands = wlcore_vendor_commands;
194 wiphy->n_vendor_commands = ARRAY_SIZE(wlcore_vendor_commands);
195 wiphy->vendor_events = wlcore_vendor_events;
196 wiphy->n_vendor_events = ARRAY_SIZE(wlcore_vendor_events);
197}
diff --git a/drivers/net/wireless/ti/wlcore/vendor_cmd.h b/drivers/net/wireless/ti/wlcore/vendor_cmd.h
new file mode 100644
index 000000000000..6e0c15e30f03
--- /dev/null
+++ b/drivers/net/wireless/ti/wlcore/vendor_cmd.h
@@ -0,0 +1,45 @@
1/*
2 * This file is part of wlcore
3 *
4 * Copyright (C) 2014 Texas Instruments. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 */
10
11#ifndef __WLCORE_VENDOR_H__
12#define __WLCORE_VENDOR_H__
13
14#ifdef __KERNEL__
15void wlcore_set_vendor_commands(struct wiphy *wiphy);
16#endif
17
18#define TI_OUI 0x080028
19
20enum wlcore_vendor_commands {
21 WLCORE_VENDOR_CMD_SMART_CONFIG_START,
22 WLCORE_VENDOR_CMD_SMART_CONFIG_STOP,
23 WLCORE_VENDOR_CMD_SMART_CONFIG_SET_GROUP_KEY,
24
25 NUM_WLCORE_VENDOR_CMD,
26 MAX_WLCORE_VENDOR_CMD = NUM_WLCORE_VENDOR_CMD - 1
27};
28
29enum wlcore_vendor_attributes {
30 WLCORE_VENDOR_ATTR_FREQ,
31 WLCORE_VENDOR_ATTR_PSK,
32 WLCORE_VENDOR_ATTR_SSID,
33 WLCORE_VENDOR_ATTR_GROUP_ID,
34 WLCORE_VENDOR_ATTR_GROUP_KEY,
35
36 NUM_WLCORE_VENDOR_ATTR,
37 MAX_WLCORE_VENDOR_ATTR = NUM_WLCORE_VENDOR_ATTR - 1
38};
39
40enum wlcore_vendor_events {
41 WLCORE_VENDOR_EVENT_SC_SYNC,
42 WLCORE_VENDOR_EVENT_SC_DECODE,
43};
44
45#endif /* __WLCORE_VENDOR_H__ */
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 71320509b56d..df78cf12ef15 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -117,6 +117,10 @@ struct wlcore_ops {
117 struct wl1271_link *lnk); 117 struct wl1271_link *lnk);
118 bool (*lnk_low_prio)(struct wl1271 *wl, u8 hlid, 118 bool (*lnk_low_prio)(struct wl1271 *wl, u8 hlid,
119 struct wl1271_link *lnk); 119 struct wl1271_link *lnk);
120 int (*smart_config_start)(struct wl1271 *wl, u32 group_bitmap);
121 int (*smart_config_stop)(struct wl1271 *wl);
122 int (*smart_config_set_group_key)(struct wl1271 *wl, u16 group_id,
123 u8 key_len, u8 *key);
120}; 124};
121 125
122enum wlcore_partitions { 126enum wlcore_partitions {
@@ -384,10 +388,10 @@ struct wl1271 {
384 int active_link_count; 388 int active_link_count;
385 389
386 /* Fast/slow links bitmap according to FW */ 390 /* Fast/slow links bitmap according to FW */
387 u32 fw_fast_lnk_map; 391 unsigned long fw_fast_lnk_map;
388 392
389 /* AP-mode - a bitmap of links currently in PS mode according to FW */ 393 /* AP-mode - a bitmap of links currently in PS mode according to FW */
390 u32 ap_fw_ps_map; 394 unsigned long ap_fw_ps_map;
391 395
392 /* AP-mode - a bitmap of links currently in PS mode in mac80211 */ 396 /* AP-mode - a bitmap of links currently in PS mode in mac80211 */
393 unsigned long ap_ps_map; 397 unsigned long ap_ps_map;
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index c2c34a84ff3d..0e52556044d9 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -45,6 +45,9 @@
45#define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff)) 45#define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
46#define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff)) 46#define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
47#define WL1271_TX_SQN_POST_RECOVERY_PADDING 0xff 47#define WL1271_TX_SQN_POST_RECOVERY_PADDING 0xff
48/* Use smaller padding for GEM, as some APs have issues when it's too big */
49#define WL1271_TX_SQN_POST_RECOVERY_PADDING_GEM 0x20
50
48 51
49#define WL1271_CIPHER_SUITE_GEM 0x00147201 52#define WL1271_CIPHER_SUITE_GEM 0x00147201
50 53
@@ -324,6 +327,7 @@ struct wl1271_station {
324 * total freed FW packets on the link to the STA - used for tracking the 327 * total freed FW packets on the link to the STA - used for tracking the
325 * AES/TKIP PN across recoveries. Re-initialized each time from the 328 * AES/TKIP PN across recoveries. Re-initialized each time from the
326 * wl1271_station structure. 329 * wl1271_station structure.
330 * Used in both AP and STA mode.
327 */ 331 */
328 u64 total_freed_pkts; 332 u64 total_freed_pkts;
329}; 333};
@@ -460,21 +464,19 @@ struct wl12xx_vif {
460 struct delayed_work pending_auth_complete_work; 464 struct delayed_work pending_auth_complete_work;
461 465
462 /* 466 /*
467 * total freed FW packets on the link.
468 * For STA this holds the PN of the link to the AP.
469 * For AP this holds the PN of the broadcast link.
470 */
471 u64 total_freed_pkts;
472
473 /*
463 * This struct must be last! 474 * This struct must be last!
464 * data that has to be saved acrossed reconfigs (e.g. recovery) 475 * data that has to be saved acrossed reconfigs (e.g. recovery)
465 * should be declared in this struct. 476 * should be declared in this struct.
466 */ 477 */
467 struct { 478 struct {
468 u8 persistent[0]; 479 u8 persistent[0];
469
470 /*
471 * total freed FW packets on the link - used for
472 * storing the AES/TKIP PN during recovery, as this
473 * structure is not zeroed out.
474 * For STA this holds the PN of the link to the AP.
475 * For AP this holds the PN of the broadcast link.
476 */
477 u64 total_freed_pkts;
478 }; 480 };
479}; 481};
480 482
diff --git a/drivers/net/wireless/zd1211rw/Kconfig b/drivers/net/wireless/zd1211rw/Kconfig
index 96c8e1de0879..95920581860a 100644
--- a/drivers/net/wireless/zd1211rw/Kconfig
+++ b/drivers/net/wireless/zd1211rw/Kconfig
@@ -3,11 +3,11 @@ config ZD1211RW
3 depends on USB && MAC80211 3 depends on USB && MAC80211
4 select FW_LOADER 4 select FW_LOADER
5 ---help--- 5 ---help---
6 This is an experimental driver for the ZyDAS ZD1211/ZD1211B wireless 6 This is a driver for the ZyDAS ZD1211/ZD1211B wireless
7 chip, present in many USB-wireless adapters. 7 chip, present in many USB-wireless adapters.
8 8
9 Device firmware is required alongside this driver. You can download 9 Device firmware is required alongside this driver. You can download
10 the firmware distribution from http://zd1211.ath.cx/get-firmware 10 the firmware distribution from http://sf.net/projects/zd1211/files/
11 11
12config ZD1211RW_DEBUG 12config ZD1211RW_DEBUG
13 bool "ZyDAS ZD1211 debugging" 13 bool "ZyDAS ZD1211 debugging"