summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/ath10k/Kconfig3
-rw-r--r--drivers/net/wireless/ath/ath10k/ahb.c9
-rw-r--r--drivers/net/wireless/ath/ath10k/bmi.c23
-rw-r--r--drivers/net/wireless/ath/ath10k/bmi.h36
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.c18
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.h11
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c737
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h64
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c144
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.h9
-rw-r--r--drivers/net/wireless/ath/ath10k/debugfs_sta.c130
-rw-r--r--drivers/net/wireless/ath/ath10k/htc.c82
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.h52
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c296
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_tx.c155
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.c191
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.h32
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c114
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.h1
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c76
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.h3
-rw-r--r--drivers/net/wireless/ath/ath10k/rx_desc.h15
-rw-r--r--drivers/net/wireless/ath/ath10k/sdio.c8
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.c22
-rw-r--r--drivers/net/wireless/ath/ath10k/targaddrs.h4
-rw-r--r--drivers/net/wireless/ath/ath10k/txrx.c3
-rw-r--r--drivers/net/wireless/ath/ath10k/usb.c7
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.c11
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c78
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h43
-rw-r--r--drivers/net/wireless/ath/ath10k/wow.c2
-rw-r--r--drivers/net/wireless/ath/ath6kl/init.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/common-debug.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/common-debug.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/common-spectral.c83
-rw-r--r--drivers/net/wireless/ath/ath9k/common-spectral.h17
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c13
-rw-r--r--drivers/net/wireless/ath/ath9k/debug_sta.c18
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/tx99.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c2
-rw-r--r--drivers/net/wireless/ath/wil6210/pm.c3
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h2
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c2
-rw-r--r--drivers/net/wireless/broadcom/b43/main.c2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c26
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/22000.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/9000.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h81
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/rx.h8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/scan.h5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dbg.c411
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dbg.h45
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/debugfs.c64
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/error-dump.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/file.h7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/img.h41
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/runtime.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.c77
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-trans.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c13
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c42
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/nvm.c25
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c39
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rx.c29
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c373
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/time-event.c11
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tx.c15
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/utils.c16
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/rx.c32
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/tx.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/Kconfig43
-rw-r--r--drivers/net/wireless/mediatek/mt76/Makefile27
-rw-r--r--drivers/net/wireless/mediatek/mt76/debugfs.c31
-rw-r--r--drivers/net/wireless/mediatek/mt76/mac80211.c6
-rw-r--r--drivers/net/wireless/mediatek/mt76/mmio.c27
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76.h37
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig20
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/Makefile6
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/debugfs.c85
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c568
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h132
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/init.c237
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h406
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/mac.c82
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/mac.h20
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/main.c117
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/mcu.h9
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h157
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/pci.c127
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c146
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/phy.c274
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/trace.h1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/tx.c115
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/usb.c308
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c176
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02.h208
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_dfs.h (renamed from drivers/net/wireless/mediatek/mt76/mt76x2_dfs.h)40
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_dma.h17
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c156
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h (renamed from drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.h)147
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_mac.c257
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_mac.h35
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c13
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h13
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c260
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_phy.c183
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_phy.h30
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_trace.c (renamed from drivers/net/wireless/mediatek/mt76/mt76x2_trace.c)2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_trace.h (renamed from drivers/net/wireless/mediatek/mt76/mt76x2_trace.h)31
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c203
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_usb.h9
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c59
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_util.c80
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_util.h54
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2.h250
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig20
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/Makefile16
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/debugfs.c (renamed from drivers/net/wireless/mediatek/mt76/mt76x2_debugfs.c)35
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/dfs.h26
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c (renamed from drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.c)356
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.h73
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/init.c (renamed from drivers/net/wireless/mediatek/mt76/mt76x2_init_common.c)36
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/mac.c54
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/mac.h (renamed from drivers/net/wireless/mediatek/mt76/mt76x2_common.c)37
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c (renamed from drivers/net/wireless/mediatek/mt76/mt76x2_mcu_common.c)20
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/mcu.h (renamed from drivers/net/wireless/mediatek/mt76/mt76x2_mcu.h)13
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h107
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h (renamed from drivers/net/wireless/mediatek/mt76/mt76x2u.h)44
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/pci.c (renamed from drivers/net/wireless/mediatek/mt76/mt76x2_pci.c)8
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/pci_dfs.c (renamed from drivers/net/wireless/mediatek/mt76/mt76x2_dfs.c)145
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c (renamed from drivers/net/wireless/mediatek/mt76/mt76x2_init.c)141
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/pci_mac.c (renamed from drivers/net/wireless/mediatek/mt76/mt76x2_mac.c)108
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c (renamed from drivers/net/wireless/mediatek/mt76/mt76x2_main.c)39
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c (renamed from drivers/net/wireless/mediatek/mt76/mt76x2_mcu.c)14
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c (renamed from drivers/net/wireless/mediatek/mt76/mt76x2_phy.c)43
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/pci_tx.c (renamed from drivers/net/wireless/mediatek/mt76/mt76x2_tx.c)43
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/phy.c (renamed from drivers/net/wireless/mediatek/mt76/mt76x2_phy_common.c)145
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/usb.c (renamed from drivers/net/wireless/mediatek/mt76/mt76x2_usb.c)10
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c (renamed from drivers/net/wireless/mediatek/mt76/mt76x2u_init.c)63
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c (renamed from drivers/net/wireless/mediatek/mt76/mt76x2u_mac.c)40
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c (renamed from drivers/net/wireless/mediatek/mt76/mt76x2u_main.c)25
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c (renamed from drivers/net/wireless/mediatek/mt76/mt76x2u_mcu.c)21
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c (renamed from drivers/net/wireless/mediatek/mt76/mt76x2u_phy.c)54
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_core.c88
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_dma.c124
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_mac.h64
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_mac_common.c239
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_tx_common.c118
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2u_core.c53
-rw-r--r--drivers/net/wireless/mediatek/mt76/tx.c36
-rw-r--r--drivers/net/wireless/mediatek/mt76/usb.c17
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/cfg80211.c193
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/commands.c535
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/core.c39
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/core.h8
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/event.c18
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c5
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/qlink.h5
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/qlink_util.h8
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c13
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/wifi.h4
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c48
-rw-r--r--drivers/net/wireless/ti/wlcore/sdio.c17
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore.h2
-rw-r--r--drivers/net/wireless/zydas/zd1211rw/zd_mac.c2
-rw-r--r--drivers/ssb/driver_chipcommon.c2
177 files changed, 6916 insertions, 5633 deletions
diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig
index 54ff5930126c..6572a43590a8 100644
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -42,7 +42,8 @@ config ATH10K_USB
config ATH10K_SNOC
tristate "Qualcomm ath10k SNOC support (EXPERIMENTAL)"
- depends on ATH10K && ARCH_QCOM
+ depends on ATH10K
+ depends on ARCH_QCOM || COMPILE_TEST
---help---
This module adds support for integrated WCN3990 chip connected
to system NOC(SNOC). Currently work in progress and will not
diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c
index be90c9e9e5bc..4cd69aca75e2 100644
--- a/drivers/net/wireless/ath/ath10k/ahb.c
+++ b/drivers/net/wireless/ath/ath10k/ahb.c
@@ -750,7 +750,7 @@ static int ath10k_ahb_probe(struct platform_device *pdev)
enum ath10k_hw_rev hw_rev;
size_t size;
int ret;
- u32 chip_id;
+ struct ath10k_bus_params bus_params;
of_id = of_match_device(ath10k_ahb_of_match, &pdev->dev);
if (!of_id) {
@@ -806,14 +806,15 @@ static int ath10k_ahb_probe(struct platform_device *pdev)
ath10k_pci_ce_deinit(ar);
- chip_id = ath10k_ahb_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
- if (chip_id == 0xffffffff) {
+ bus_params.dev_type = ATH10K_DEV_TYPE_LL;
+ bus_params.chip_id = ath10k_ahb_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
+ if (bus_params.chip_id == 0xffffffff) {
ath10k_err(ar, "failed to get chip id\n");
ret = -ENODEV;
goto err_halt_device;
}
- ret = ath10k_core_register(ar, chip_id);
+ ret = ath10k_core_register(ar, &bus_params);
if (ret) {
ath10k_err(ar, "failed to register driver core: %d\n", ret);
goto err_halt_device;
diff --git a/drivers/net/wireless/ath/ath10k/bmi.c b/drivers/net/wireless/ath/ath10k/bmi.c
index af4978d6a14b..1750b182209b 100644
--- a/drivers/net/wireless/ath/ath10k/bmi.c
+++ b/drivers/net/wireless/ath/ath10k/bmi.c
@@ -459,3 +459,26 @@ int ath10k_bmi_fast_download(struct ath10k *ar,
return ret;
}
+
+int ath10k_bmi_set_start(struct ath10k *ar, u32 address)
+{
+ struct bmi_cmd cmd;
+ u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.set_app_start);
+ int ret;
+
+ if (ar->bmi.done_sent) {
+ ath10k_warn(ar, "bmi set start command disallowed\n");
+ return -EBUSY;
+ }
+
+ cmd.id = __cpu_to_le32(BMI_SET_APP_START);
+ cmd.set_app_start.addr = __cpu_to_le32(address);
+
+ ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, NULL, NULL);
+ if (ret) {
+ ath10k_warn(ar, "unable to set start to the device:%d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/wireless/ath/ath10k/bmi.h b/drivers/net/wireless/ath/ath10k/bmi.h
index 9a396817aa55..725c9afc63f2 100644
--- a/drivers/net/wireless/ath/ath10k/bmi.h
+++ b/drivers/net/wireless/ath/ath10k/bmi.h
@@ -86,6 +86,10 @@ enum bmi_cmd_id {
#define BMI_PARAM_GET_FLASH_BOARD_ID 0x8000
#define BMI_PARAM_FLASH_SECTION_ALL 0x10000
+/* Dual-band Extended Board ID */
+#define BMI_PARAM_GET_EXT_BOARD_ID 0x40000
+#define ATH10K_BMI_EXT_BOARD_ID_SUPPORT 0x40000
+
#define ATH10K_BMI_BOARD_ID_FROM_OTP_MASK 0x7c00
#define ATH10K_BMI_BOARD_ID_FROM_OTP_LSB 10
@@ -93,6 +97,7 @@ enum bmi_cmd_id {
#define ATH10K_BMI_CHIP_ID_FROM_OTP_LSB 15
#define ATH10K_BMI_BOARD_ID_STATUS_MASK 0xff
+#define ATH10K_BMI_EBOARD_ID_STATUS_MASK 0xff
struct bmi_cmd {
__le32 id; /* enum bmi_cmd_id */
@@ -190,6 +195,35 @@ struct bmi_target_info {
u32 type;
};
+struct bmi_segmented_file_header {
+ __le32 magic_num;
+ __le32 file_flags;
+ u8 data[];
+};
+
+struct bmi_segmented_metadata {
+ __le32 addr;
+ __le32 length;
+ u8 data[];
+};
+
+#define BMI_SGMTFILE_MAGIC_NUM 0x544d4753 /* "SGMT" */
+#define BMI_SGMTFILE_FLAG_COMPRESS 1
+
+/* Special values for bmi_segmented_metadata.length (all have high bit set) */
+
+/* end of segmented data */
+#define BMI_SGMTFILE_DONE 0xffffffff
+
+/* Board Data segment */
+#define BMI_SGMTFILE_BDDATA 0xfffffffe
+
+/* set beginning address */
+#define BMI_SGMTFILE_BEGINADDR 0xfffffffd
+
+/* immediate function execution */
+#define BMI_SGMTFILE_EXEC 0xfffffffc
+
/* in jiffies */
#define BMI_COMMUNICATION_TIMEOUT_HZ (3 * HZ)
@@ -239,4 +273,6 @@ int ath10k_bmi_fast_download(struct ath10k *ar, u32 address,
const void *buffer, u32 length);
int ath10k_bmi_read_soc_reg(struct ath10k *ar, u32 address, u32 *reg_val);
int ath10k_bmi_write_soc_reg(struct ath10k *ar, u32 address, u32 reg_val);
+int ath10k_bmi_set_start(struct ath10k *ar, u32 address);
+
#endif /* _BMI_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
index d0381aaad01c..f6d3ecbdd3a3 100644
--- a/drivers/net/wireless/ath/ath10k/ce.c
+++ b/drivers/net/wireless/ath/ath10k/ce.c
@@ -1280,10 +1280,17 @@ static void ath10k_ce_per_engine_handler_adjust(struct ath10k_ce_pipe *ce_state)
int ath10k_ce_disable_interrupts(struct ath10k *ar)
{
+ struct ath10k_ce *ce = ath10k_ce_priv(ar);
+ struct ath10k_ce_pipe *ce_state;
+ u32 ctrl_addr;
int ce_id;
for (ce_id = 0; ce_id < CE_COUNT; ce_id++) {
- u32 ctrl_addr = ath10k_ce_base_address(ar, ce_id);
+ ce_state = &ce->ce_states[ce_id];
+ if (ce_state->attr_flags & CE_ATTR_POLL)
+ continue;
+
+ ctrl_addr = ath10k_ce_base_address(ar, ce_id);
ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr);
ath10k_ce_error_intr_disable(ar, ctrl_addr);
@@ -1300,11 +1307,14 @@ void ath10k_ce_enable_interrupts(struct ath10k *ar)
int ce_id;
struct ath10k_ce_pipe *ce_state;
- /* Skip the last copy engine, CE7 the diagnostic window, as that
- * uses polling and isn't initialized for interrupts.
+ /* Enable interrupts for copy engine that
+ * are not using polling mode.
*/
- for (ce_id = 0; ce_id < CE_COUNT - 1; ce_id++) {
+ for (ce_id = 0; ce_id < CE_COUNT; ce_id++) {
ce_state = &ce->ce_states[ce_id];
+ if (ce_state->attr_flags & CE_ATTR_POLL)
+ continue;
+
ath10k_ce_per_engine_handler_adjust(ce_state);
}
}
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h
index b8fb5382dede..ead9987c3259 100644
--- a/drivers/net/wireless/ath/ath10k/ce.h
+++ b/drivers/net/wireless/ath/ath10k/ce.h
@@ -275,16 +275,19 @@ void ath10k_ce_free_rri(struct ath10k *ar);
/* ce_attr.flags values */
/* Use NonSnooping PCIe accesses? */
-#define CE_ATTR_NO_SNOOP 1
+#define CE_ATTR_NO_SNOOP BIT(0)
/* Byte swap data words */
-#define CE_ATTR_BYTE_SWAP_DATA 2
+#define CE_ATTR_BYTE_SWAP_DATA BIT(1)
/* Swizzle descriptors? */
-#define CE_ATTR_SWIZZLE_DESCRIPTORS 4
+#define CE_ATTR_SWIZZLE_DESCRIPTORS BIT(2)
/* no interrupt on copy completion */
-#define CE_ATTR_DIS_INTR 8
+#define CE_ATTR_DIS_INTR BIT(3)
+
+/* no interrupt, only polling */
+#define CE_ATTR_POLL BIT(4)
/* Attributes of an instance of a Copy Engine */
struct ce_attr {
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index ebc213884a9a..203f30992c26 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/of.h>
+#include <linux/property.h>
#include <linux/dmi.h>
#include <linux/ctype.h>
#include <asm/byteorder.h>
@@ -63,6 +64,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
{
.id = QCA988X_HW_2_0_VERSION,
.dev_id = QCA988X_2_0_DEVICE_ID,
+ .bus = ATH10K_BUS_PCI,
.name = "qca988x hw2.0",
.patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,
.uart_pin = 7,
@@ -84,7 +86,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
.n_cipher_suites = 8,
- .num_peers = TARGET_TLV_NUM_PEERS,
.ast_skid_limit = 0x10,
.num_wds_entries = 0x20,
.target_64bit = false,
@@ -92,6 +93,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.shadow_reg_support = false,
.rri_on_ddr = false,
.hw_filter_reset_required = true,
+ .fw_diag_ce_download = false,
},
{
.id = QCA988X_HW_2_0_VERSION,
@@ -117,7 +119,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
.n_cipher_suites = 8,
- .num_peers = TARGET_TLV_NUM_PEERS,
.ast_skid_limit = 0x10,
.num_wds_entries = 0x20,
.target_64bit = false,
@@ -126,10 +127,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.shadow_reg_support = false,
.rri_on_ddr = false,
.hw_filter_reset_required = true,
+ .fw_diag_ce_download = false,
},
{
.id = QCA9887_HW_1_0_VERSION,
.dev_id = QCA9887_1_0_DEVICE_ID,
+ .bus = ATH10K_BUS_PCI,
.name = "qca9887 hw1.0",
.patch_load_addr = QCA9887_HW_1_0_PATCH_LOAD_ADDR,
.uart_pin = 7,
@@ -151,7 +154,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
.n_cipher_suites = 8,
- .num_peers = TARGET_TLV_NUM_PEERS,
.ast_skid_limit = 0x10,
.num_wds_entries = 0x20,
.target_64bit = false,
@@ -160,10 +162,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.shadow_reg_support = false,
.rri_on_ddr = false,
.hw_filter_reset_required = true,
+ .fw_diag_ce_download = false,
},
{
.id = QCA6174_HW_2_1_VERSION,
.dev_id = QCA6164_2_1_DEVICE_ID,
+ .bus = ATH10K_BUS_PCI,
.name = "qca6164 hw2.1",
.patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR,
.uart_pin = 6,
@@ -184,7 +188,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
.n_cipher_suites = 8,
- .num_peers = TARGET_TLV_NUM_PEERS,
.ast_skid_limit = 0x10,
.num_wds_entries = 0x20,
.target_64bit = false,
@@ -193,10 +196,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.shadow_reg_support = false,
.rri_on_ddr = false,
.hw_filter_reset_required = true,
+ .fw_diag_ce_download = false,
},
{
.id = QCA6174_HW_2_1_VERSION,
.dev_id = QCA6174_2_1_DEVICE_ID,
+ .bus = ATH10K_BUS_PCI,
.name = "qca6174 hw2.1",
.patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR,
.uart_pin = 6,
@@ -217,7 +222,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
.n_cipher_suites = 8,
- .num_peers = TARGET_TLV_NUM_PEERS,
.ast_skid_limit = 0x10,
.num_wds_entries = 0x20,
.target_64bit = false,
@@ -226,10 +230,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.shadow_reg_support = false,
.rri_on_ddr = false,
.hw_filter_reset_required = true,
+ .fw_diag_ce_download = false,
},
{
.id = QCA6174_HW_3_0_VERSION,
.dev_id = QCA6174_2_1_DEVICE_ID,
+ .bus = ATH10K_BUS_PCI,
.name = "qca6174 hw3.0",
.patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR,
.uart_pin = 6,
@@ -250,7 +256,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
.n_cipher_suites = 8,
- .num_peers = TARGET_TLV_NUM_PEERS,
.ast_skid_limit = 0x10,
.num_wds_entries = 0x20,
.target_64bit = false,
@@ -259,10 +264,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.shadow_reg_support = false,
.rri_on_ddr = false,
.hw_filter_reset_required = true,
+ .fw_diag_ce_download = false,
},
{
.id = QCA6174_HW_3_2_VERSION,
.dev_id = QCA6174_2_1_DEVICE_ID,
+ .bus = ATH10K_BUS_PCI,
.name = "qca6174 hw3.2",
.patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR,
.uart_pin = 6,
@@ -286,7 +293,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
.n_cipher_suites = 8,
- .num_peers = TARGET_TLV_NUM_PEERS,
.ast_skid_limit = 0x10,
.num_wds_entries = 0x20,
.target_64bit = false,
@@ -295,10 +301,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.shadow_reg_support = false,
.rri_on_ddr = false,
.hw_filter_reset_required = true,
+ .fw_diag_ce_download = true,
},
{
.id = QCA99X0_HW_2_0_DEV_VERSION,
.dev_id = QCA99X0_2_0_DEVICE_ID,
+ .bus = ATH10K_BUS_PCI,
.name = "qca99x0 hw2.0",
.patch_load_addr = QCA99X0_HW_2_0_PATCH_LOAD_ADDR,
.uart_pin = 7,
@@ -325,7 +333,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
.n_cipher_suites = 11,
- .num_peers = TARGET_TLV_NUM_PEERS,
.ast_skid_limit = 0x10,
.num_wds_entries = 0x20,
.target_64bit = false,
@@ -334,10 +341,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.shadow_reg_support = false,
.rri_on_ddr = false,
.hw_filter_reset_required = true,
+ .fw_diag_ce_download = false,
},
{
.id = QCA9984_HW_1_0_DEV_VERSION,
.dev_id = QCA9984_1_0_DEVICE_ID,
+ .bus = ATH10K_BUS_PCI,
.name = "qca9984/qca9994 hw1.0",
.patch_load_addr = QCA9984_HW_1_0_PATCH_LOAD_ADDR,
.uart_pin = 7,
@@ -354,8 +363,10 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.fw = {
.dir = QCA9984_HW_1_0_FW_DIR,
.board = QCA9984_HW_1_0_BOARD_DATA_FILE,
+ .eboard = QCA9984_HW_1_0_EBOARD_DATA_FILE,
.board_size = QCA99X0_BOARD_DATA_SZ,
.board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
+ .ext_board_size = QCA99X0_EXT_BOARD_DATA_SZ,
},
.sw_decrypt_mcast_mgmt = true,
.hw_ops = &qca99x0_ops,
@@ -369,7 +380,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.vht160_mcs_rx_highest = 1560,
.vht160_mcs_tx_highest = 1560,
.n_cipher_suites = 11,
- .num_peers = TARGET_TLV_NUM_PEERS,
.ast_skid_limit = 0x10,
.num_wds_entries = 0x20,
.target_64bit = false,
@@ -378,10 +388,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.shadow_reg_support = false,
.rri_on_ddr = false,
.hw_filter_reset_required = true,
+ .fw_diag_ce_download = false,
},
{
.id = QCA9888_HW_2_0_DEV_VERSION,
.dev_id = QCA9888_2_0_DEVICE_ID,
+ .bus = ATH10K_BUS_PCI,
.name = "qca9888 hw2.0",
.patch_load_addr = QCA9888_HW_2_0_PATCH_LOAD_ADDR,
.uart_pin = 7,
@@ -412,7 +424,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.vht160_mcs_rx_highest = 780,
.vht160_mcs_tx_highest = 780,
.n_cipher_suites = 11,
- .num_peers = TARGET_TLV_NUM_PEERS,
.ast_skid_limit = 0x10,
.num_wds_entries = 0x20,
.target_64bit = false,
@@ -421,10 +432,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.shadow_reg_support = false,
.rri_on_ddr = false,
.hw_filter_reset_required = true,
+ .fw_diag_ce_download = false,
},
{
.id = QCA9377_HW_1_0_DEV_VERSION,
.dev_id = QCA9377_1_0_DEVICE_ID,
+ .bus = ATH10K_BUS_PCI,
.name = "qca9377 hw1.0",
.patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR,
.uart_pin = 6,
@@ -445,7 +458,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
.n_cipher_suites = 8,
- .num_peers = TARGET_TLV_NUM_PEERS,
.ast_skid_limit = 0x10,
.num_wds_entries = 0x20,
.target_64bit = false,
@@ -454,10 +466,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.shadow_reg_support = false,
.rri_on_ddr = false,
.hw_filter_reset_required = true,
+ .fw_diag_ce_download = false,
},
{
.id = QCA9377_HW_1_1_DEV_VERSION,
.dev_id = QCA9377_1_0_DEVICE_ID,
+ .bus = ATH10K_BUS_PCI,
.name = "qca9377 hw1.1",
.patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR,
.uart_pin = 6,
@@ -480,7 +494,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
.n_cipher_suites = 8,
- .num_peers = TARGET_TLV_NUM_PEERS,
.ast_skid_limit = 0x10,
.num_wds_entries = 0x20,
.target_64bit = false,
@@ -489,10 +502,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.shadow_reg_support = false,
.rri_on_ddr = false,
.hw_filter_reset_required = true,
+ .fw_diag_ce_download = true,
},
{
.id = QCA4019_HW_1_0_DEV_VERSION,
.dev_id = 0,
+ .bus = ATH10K_BUS_AHB,
.name = "qca4019 hw1.0",
.patch_load_addr = QCA4019_HW_1_0_PATCH_LOAD_ADDR,
.uart_pin = 7,
@@ -520,7 +535,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
.n_cipher_suites = 11,
- .num_peers = TARGET_TLV_NUM_PEERS,
.ast_skid_limit = 0x10,
.num_wds_entries = 0x20,
.target_64bit = false,
@@ -529,10 +543,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.shadow_reg_support = false,
.rri_on_ddr = false,
.hw_filter_reset_required = true,
+ .fw_diag_ce_download = false,
},
{
.id = WCN3990_HW_1_0_DEV_VERSION,
.dev_id = 0,
+ .bus = ATH10K_BUS_PCI,
.name = "wcn3990 hw1.0",
.continuous_frag_desc = true,
.tx_chain_mask = 0x7,
@@ -553,6 +569,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.shadow_reg_support = true,
.rri_on_ddr = true,
.hw_filter_reset_required = false,
+ .fw_diag_ce_download = false,
},
};
@@ -776,153 +793,11 @@ static int ath10k_push_board_ext_data(struct ath10k *ar, const void *data,
return 0;
}
-static int ath10k_download_board_data(struct ath10k *ar, const void *data,
- size_t data_len)
-{
- u32 board_data_size = ar->hw_params.fw.board_size;
- u32 address;
- int ret;
-
- ret = ath10k_push_board_ext_data(ar, data, data_len);
- if (ret) {
- ath10k_err(ar, "could not push board ext data (%d)\n", ret);
- goto exit;
- }
-
- ret = ath10k_bmi_read32(ar, hi_board_data, &address);
- if (ret) {
- ath10k_err(ar, "could not read board data addr (%d)\n", ret);
- goto exit;
- }
-
- ret = ath10k_bmi_write_memory(ar, address, data,
- min_t(u32, board_data_size,
- data_len));
- if (ret) {
- ath10k_err(ar, "could not write board data (%d)\n", ret);
- goto exit;
- }
-
- ret = ath10k_bmi_write32(ar, hi_board_data_initialized, 1);
- if (ret) {
- ath10k_err(ar, "could not write board data bit (%d)\n", ret);
- goto exit;
- }
-
-exit:
- return ret;
-}
-
-static int ath10k_download_cal_file(struct ath10k *ar,
- const struct firmware *file)
-{
- int ret;
-
- if (!file)
- return -ENOENT;
-
- if (IS_ERR(file))
- return PTR_ERR(file);
-
- ret = ath10k_download_board_data(ar, file->data, file->size);
- if (ret) {
- ath10k_err(ar, "failed to download cal_file data: %d\n", ret);
- return ret;
- }
-
- ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cal file downloaded\n");
-
- return 0;
-}
-
-static int ath10k_download_cal_dt(struct ath10k *ar, const char *dt_name)
-{
- struct device_node *node;
- int data_len;
- void *data;
- int ret;
-
- node = ar->dev->of_node;
- if (!node)
- /* Device Tree is optional, don't print any warnings if
- * there's no node for ath10k.
- */
- return -ENOENT;
-
- if (!of_get_property(node, dt_name, &data_len)) {
- /* The calibration data node is optional */
- return -ENOENT;
- }
-
- if (data_len != ar->hw_params.cal_data_len) {
- ath10k_warn(ar, "invalid calibration data length in DT: %d\n",
- data_len);
- ret = -EMSGSIZE;
- goto out;
- }
-
- data = kmalloc(data_len, GFP_KERNEL);
- if (!data) {
- ret = -ENOMEM;
- goto out;
- }
-
- ret = of_property_read_u8_array(node, dt_name, data, data_len);
- if (ret) {
- ath10k_warn(ar, "failed to read calibration data from DT: %d\n",
- ret);
- goto out_free;
- }
-
- ret = ath10k_download_board_data(ar, data, data_len);
- if (ret) {
- ath10k_warn(ar, "failed to download calibration data from Device Tree: %d\n",
- ret);
- goto out_free;
- }
-
- ret = 0;
-
-out_free:
- kfree(data);
-
-out:
- return ret;
-}
-
-static int ath10k_download_cal_eeprom(struct ath10k *ar)
-{
- size_t data_len;
- void *data = NULL;
- int ret;
-
- ret = ath10k_hif_fetch_cal_eeprom(ar, &data, &data_len);
- if (ret) {
- if (ret != -EOPNOTSUPP)
- ath10k_warn(ar, "failed to read calibration data from EEPROM: %d\n",
- ret);
- goto out_free;
- }
-
- ret = ath10k_download_board_data(ar, data, data_len);
- if (ret) {
- ath10k_warn(ar, "failed to download calibration data from EEPROM: %d\n",
- ret);
- goto out_free;
- }
-
- ret = 0;
-
-out_free:
- kfree(data);
-
- return ret;
-}
-
static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
{
u32 result, address;
u8 board_id, chip_id;
+ bool ext_bid_support;
int ret, bmi_board_id_param;
address = ar->hw_params.patch_load_addr;
@@ -962,10 +837,13 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
board_id = MS(result, ATH10K_BMI_BOARD_ID_FROM_OTP);
chip_id = MS(result, ATH10K_BMI_CHIP_ID_FROM_OTP);
+ ext_bid_support = (result & ATH10K_BMI_EXT_BOARD_ID_SUPPORT);
ath10k_dbg(ar, ATH10K_DBG_BOOT,
- "boot get otp board id result 0x%08x board_id %d chip_id %d\n",
- result, board_id, chip_id);
+ "boot get otp board id result 0x%08x board_id %d chip_id %d ext_bid_support %d\n",
+ result, board_id, chip_id, ext_bid_support);
+
+ ar->id.ext_bid_supported = ext_bid_support;
if ((result & ATH10K_BMI_BOARD_ID_STATUS_MASK) != 0 ||
(board_id == 0)) {
@@ -1069,64 +947,6 @@ static int ath10k_core_check_dt(struct ath10k *ar)
return 0;
}
-static int ath10k_download_and_run_otp(struct ath10k *ar)
-{
- u32 result, address = ar->hw_params.patch_load_addr;
- u32 bmi_otp_exe_param = ar->hw_params.otp_exe_param;
- int ret;
-
- ret = ath10k_download_board_data(ar,
- ar->running_fw->board_data,
- ar->running_fw->board_len);
- if (ret) {
- ath10k_err(ar, "failed to download board data: %d\n", ret);
- return ret;
- }
-
- /* OTP is optional */
-
- if (!ar->running_fw->fw_file.otp_data ||
- !ar->running_fw->fw_file.otp_len) {
- ath10k_warn(ar, "Not running otp, calibration will be incorrect (otp-data %pK otp_len %zd)!\n",
- ar->running_fw->fw_file.otp_data,
- ar->running_fw->fw_file.otp_len);
- return 0;
- }
-
- ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot upload otp to 0x%x len %zd\n",
- address, ar->running_fw->fw_file.otp_len);
-
- ret = ath10k_bmi_fast_download(ar, address,
- ar->running_fw->fw_file.otp_data,
- ar->running_fw->fw_file.otp_len);
- if (ret) {
- ath10k_err(ar, "could not write otp (%d)\n", ret);
- return ret;
- }
-
- /* As of now pre-cal is valid for 10_4 variants */
- if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT ||
- ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE)
- bmi_otp_exe_param = BMI_PARAM_FLASH_SECTION_ALL;
-
- ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, &result);
- if (ret) {
- ath10k_err(ar, "could not execute otp (%d)\n", ret);
- return ret;
- }
-
- ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result);
-
- if (!(skip_otp || test_bit(ATH10K_FW_FEATURE_IGNORE_OTP_RESULT,
- ar->running_fw->fw_file.fw_features)) &&
- result != 0) {
- ath10k_err(ar, "otp calibration failed: %d", result);
- return -EINVAL;
- }
-
- return 0;
-}
-
static int ath10k_download_fw(struct ath10k *ar)
{
u32 address, data_len;
@@ -1149,14 +969,24 @@ static int ath10k_download_fw(struct ath10k *ar)
"boot uploading firmware image %pK len %d\n",
data, data_len);
- ret = ath10k_bmi_fast_download(ar, address, data, data_len);
- if (ret) {
- ath10k_err(ar, "failed to download firmware: %d\n",
- ret);
- return ret;
+ /* Check if device supports to download firmware via
+ * diag copy engine. Downloading firmware via diag CE
+ * greatly reduces the time to download firmware.
+ */
+ if (ar->hw_params.fw_diag_ce_download) {
+ ret = ath10k_hw_diag_fast_download(ar, address,
+ data, data_len);
+ if (ret == 0)
+ /* firmware upload via diag ce was successful */
+ return 0;
+
+ ath10k_warn(ar,
+ "failed to upload firmware via diag ce, trying BMI: %d",
+ ret);
}
- return ret;
+ return ath10k_bmi_fast_download(ar, address,
+ data, data_len);
}
static void ath10k_core_free_board_files(struct ath10k *ar)
@@ -1164,9 +994,15 @@ static void ath10k_core_free_board_files(struct ath10k *ar)
if (!IS_ERR(ar->normal_mode_fw.board))
release_firmware(ar->normal_mode_fw.board);
+ if (!IS_ERR(ar->normal_mode_fw.ext_board))
+ release_firmware(ar->normal_mode_fw.ext_board);
+
ar->normal_mode_fw.board = NULL;
ar->normal_mode_fw.board_data = NULL;
ar->normal_mode_fw.board_len = 0;
+ ar->normal_mode_fw.ext_board = NULL;
+ ar->normal_mode_fw.ext_board_data = NULL;
+ ar->normal_mode_fw.ext_board_len = 0;
}
static void ath10k_core_free_firmware_files(struct ath10k *ar)
@@ -1220,28 +1056,47 @@ success:
return 0;
}
-static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar)
+static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar, int bd_ie_type)
{
- if (!ar->hw_params.fw.board) {
- ath10k_err(ar, "failed to find board file fw entry\n");
- return -EINVAL;
- }
+ const struct firmware *fw;
- ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar,
- ar->hw_params.fw.dir,
- ar->hw_params.fw.board);
- if (IS_ERR(ar->normal_mode_fw.board))
- return PTR_ERR(ar->normal_mode_fw.board);
+ if (bd_ie_type == ATH10K_BD_IE_BOARD) {
+ if (!ar->hw_params.fw.board) {
+ ath10k_err(ar, "failed to find board file fw entry\n");
+ return -EINVAL;
+ }
- ar->normal_mode_fw.board_data = ar->normal_mode_fw.board->data;
- ar->normal_mode_fw.board_len = ar->normal_mode_fw.board->size;
+ ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar,
+ ar->hw_params.fw.dir,
+ ar->hw_params.fw.board);
+ if (IS_ERR(ar->normal_mode_fw.board))
+ return PTR_ERR(ar->normal_mode_fw.board);
+
+ ar->normal_mode_fw.board_data = ar->normal_mode_fw.board->data;
+ ar->normal_mode_fw.board_len = ar->normal_mode_fw.board->size;
+ } else if (bd_ie_type == ATH10K_BD_IE_BOARD_EXT) {
+ if (!ar->hw_params.fw.eboard) {
+ ath10k_err(ar, "failed to find eboard file fw entry\n");
+ return -EINVAL;
+ }
+
+ fw = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir,
+ ar->hw_params.fw.eboard);
+ ar->normal_mode_fw.ext_board = fw;
+ if (IS_ERR(ar->normal_mode_fw.ext_board))
+ return PTR_ERR(ar->normal_mode_fw.ext_board);
+
+ ar->normal_mode_fw.ext_board_data = ar->normal_mode_fw.ext_board->data;
+ ar->normal_mode_fw.ext_board_len = ar->normal_mode_fw.ext_board->size;
+ }
return 0;
}
static int ath10k_core_parse_bd_ie_board(struct ath10k *ar,
const void *buf, size_t buf_len,
- const char *boardname)
+ const char *boardname,
+ int bd_ie_type)
{
const struct ath10k_fw_ie *hdr;
bool name_match_found;
@@ -1290,12 +1145,21 @@ static int ath10k_core_parse_bd_ie_board(struct ath10k *ar,
/* no match found */
break;
- ath10k_dbg(ar, ATH10K_DBG_BOOT,
- "boot found board data for '%s'",
- boardname);
+ if (bd_ie_type == ATH10K_BD_IE_BOARD) {
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "boot found board data for '%s'",
+ boardname);
- ar->normal_mode_fw.board_data = board_ie_data;
- ar->normal_mode_fw.board_len = board_ie_len;
+ ar->normal_mode_fw.board_data = board_ie_data;
+ ar->normal_mode_fw.board_len = board_ie_len;
+ } else if (bd_ie_type == ATH10K_BD_IE_BOARD_EXT) {
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "boot found eboard data for '%s'",
+ boardname);
+
+ ar->normal_mode_fw.ext_board_data = board_ie_data;
+ ar->normal_mode_fw.ext_board_len = board_ie_len;
+ }
ret = 0;
goto out;
@@ -1345,7 +1209,18 @@ static int ath10k_core_search_bd(struct ath10k *ar,
switch (ie_id) {
case ATH10K_BD_IE_BOARD:
ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len,
- boardname);
+ boardname,
+ ATH10K_BD_IE_BOARD);
+ if (ret == -ENOENT)
+ /* no match found, continue */
+ break;
+
+ /* either found or error, so stop searching */
+ goto out;
+ case ATH10K_BD_IE_BOARD_EXT:
+ ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len,
+ boardname,
+ ATH10K_BD_IE_BOARD_EXT);
if (ret == -ENOENT)
/* no match found, continue */
break;
@@ -1375,9 +1250,11 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar,
const u8 *data;
int ret;
- ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar,
- ar->hw_params.fw.dir,
- filename);
+ /* Skip if already fetched during board data download */
+ if (!ar->normal_mode_fw.board)
+ ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar,
+ ar->hw_params.fw.dir,
+ filename);
if (IS_ERR(ar->normal_mode_fw.board))
return PTR_ERR(ar->normal_mode_fw.board);
@@ -1465,23 +1342,49 @@ out:
return 0;
}
-static int ath10k_core_fetch_board_file(struct ath10k *ar)
+static int ath10k_core_create_eboard_name(struct ath10k *ar, char *name,
+ size_t name_len)
+{
+ if (ar->id.bmi_ids_valid) {
+ scnprintf(name, name_len,
+ "bus=%s,bmi-chip-id=%d,bmi-eboard-id=%d",
+ ath10k_bus_str(ar->hif.bus),
+ ar->id.bmi_chip_id,
+ ar->id.bmi_eboard_id);
+
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using eboard name '%s'\n", name);
+ return 0;
+ }
+ /* Fallback if returned board id is zero */
+ return -1;
+}
+
+static int ath10k_core_fetch_board_file(struct ath10k *ar, int bd_ie_type)
{
char boardname[100], fallback_boardname[100];
int ret;
- ret = ath10k_core_create_board_name(ar, boardname,
- sizeof(boardname), true);
- if (ret) {
- ath10k_err(ar, "failed to create board name: %d", ret);
- return ret;
- }
+ if (bd_ie_type == ATH10K_BD_IE_BOARD) {
+ ret = ath10k_core_create_board_name(ar, boardname,
+ sizeof(boardname), true);
+ if (ret) {
+ ath10k_err(ar, "failed to create board name: %d", ret);
+ return ret;
+ }
- ret = ath10k_core_create_board_name(ar, fallback_boardname,
- sizeof(boardname), false);
- if (ret) {
- ath10k_err(ar, "failed to create fallback board name: %d", ret);
- return ret;
+ ret = ath10k_core_create_board_name(ar, fallback_boardname,
+ sizeof(boardname), false);
+ if (ret) {
+ ath10k_err(ar, "failed to create fallback board name: %d", ret);
+ return ret;
+ }
+ } else if (bd_ie_type == ATH10K_BD_IE_BOARD_EXT) {
+ ret = ath10k_core_create_eboard_name(ar, boardname,
+ sizeof(boardname));
+ if (ret) {
+ ath10k_err(ar, "fallback to eboard.bin since board id 0");
+ goto fallback;
+ }
}
ar->bd_api = 2;
@@ -1491,8 +1394,9 @@ static int ath10k_core_fetch_board_file(struct ath10k *ar)
if (!ret)
goto success;
+fallback:
ar->bd_api = 1;
- ret = ath10k_core_fetch_board_data_api_1(ar);
+ ret = ath10k_core_fetch_board_data_api_1(ar, bd_ie_type);
if (ret) {
ath10k_err(ar, "failed to fetch board-2.bin or board.bin from %s\n",
ar->hw_params.fw.dir);
@@ -1504,6 +1408,291 @@ success:
return 0;
}
+static int ath10k_core_get_ext_board_id_from_otp(struct ath10k *ar)
+{
+ u32 result, address;
+ u8 ext_board_id;
+ int ret;
+
+ address = ar->hw_params.patch_load_addr;
+
+ if (!ar->normal_mode_fw.fw_file.otp_data ||
+ !ar->normal_mode_fw.fw_file.otp_len) {
+ ath10k_warn(ar,
+ "failed to retrieve extended board id due to otp binary missing\n");
+ return -ENODATA;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "boot upload otp to 0x%x len %zd for ext board id\n",
+ address, ar->normal_mode_fw.fw_file.otp_len);
+
+ ret = ath10k_bmi_fast_download(ar, address,
+ ar->normal_mode_fw.fw_file.otp_data,
+ ar->normal_mode_fw.fw_file.otp_len);
+ if (ret) {
+ ath10k_err(ar, "could not write otp for ext board id check: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = ath10k_bmi_execute(ar, address, BMI_PARAM_GET_EXT_BOARD_ID, &result);
+ if (ret) {
+ ath10k_err(ar, "could not execute otp for ext board id check: %d\n",
+ ret);
+ return ret;
+ }
+
+ if (!result) {
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "ext board id does not exist in otp, ignore it\n");
+ return -EOPNOTSUPP;
+ }
+
+ ext_board_id = result & ATH10K_BMI_EBOARD_ID_STATUS_MASK;
+
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "boot get otp ext board id result 0x%08x ext_board_id %d\n",
+ result, ext_board_id);
+
+ ar->id.bmi_eboard_id = ext_board_id;
+
+ return 0;
+}
+
+static int ath10k_download_board_data(struct ath10k *ar, const void *data,
+ size_t data_len)
+{
+ u32 board_data_size = ar->hw_params.fw.board_size;
+ u32 eboard_data_size = ar->hw_params.fw.ext_board_size;
+ u32 board_address;
+ u32 ext_board_address;
+ int ret;
+
+ ret = ath10k_push_board_ext_data(ar, data, data_len);
+ if (ret) {
+ ath10k_err(ar, "could not push board ext data (%d)\n", ret);
+ goto exit;
+ }
+
+ ret = ath10k_bmi_read32(ar, hi_board_data, &board_address);
+ if (ret) {
+ ath10k_err(ar, "could not read board data addr (%d)\n", ret);
+ goto exit;
+ }
+
+ ret = ath10k_bmi_write_memory(ar, board_address, data,
+ min_t(u32, board_data_size,
+ data_len));
+ if (ret) {
+ ath10k_err(ar, "could not write board data (%d)\n", ret);
+ goto exit;
+ }
+
+ ret = ath10k_bmi_write32(ar, hi_board_data_initialized, 1);
+ if (ret) {
+ ath10k_err(ar, "could not write board data bit (%d)\n", ret);
+ goto exit;
+ }
+
+ if (!ar->id.ext_bid_supported)
+ goto exit;
+
+ /* Extended board data download */
+ ret = ath10k_core_get_ext_board_id_from_otp(ar);
+ if (ret == -EOPNOTSUPP) {
+ /* Not fetching ext_board_data if ext board id is 0 */
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "otp returned ext board id 0\n");
+ return 0;
+ } else if (ret) {
+ ath10k_err(ar, "failed to get extended board id: %d\n", ret);
+ goto exit;
+ }
+
+ ret = ath10k_core_fetch_board_file(ar, ATH10K_BD_IE_BOARD_EXT);
+ if (ret)
+ goto exit;
+
+ if (ar->normal_mode_fw.ext_board_data) {
+ ext_board_address = board_address + EXT_BOARD_ADDRESS_OFFSET;
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "boot writing ext board data to addr 0x%x",
+ ext_board_address);
+ ret = ath10k_bmi_write_memory(ar, ext_board_address,
+ ar->normal_mode_fw.ext_board_data,
+ min_t(u32, eboard_data_size, data_len));
+ if (ret)
+ ath10k_err(ar, "failed to write ext board data: %d\n", ret);
+ }
+
+exit:
+ return ret;
+}
+
+static int ath10k_download_and_run_otp(struct ath10k *ar)
+{
+ u32 result, address = ar->hw_params.patch_load_addr;
+ u32 bmi_otp_exe_param = ar->hw_params.otp_exe_param;
+ int ret;
+
+ ret = ath10k_download_board_data(ar,
+ ar->running_fw->board_data,
+ ar->running_fw->board_len);
+ if (ret) {
+ ath10k_err(ar, "failed to download board data: %d\n", ret);
+ return ret;
+ }
+
+ /* OTP is optional */
+
+ if (!ar->running_fw->fw_file.otp_data ||
+ !ar->running_fw->fw_file.otp_len) {
+ ath10k_warn(ar, "Not running otp, calibration will be incorrect (otp-data %pK otp_len %zd)!\n",
+ ar->running_fw->fw_file.otp_data,
+ ar->running_fw->fw_file.otp_len);
+ return 0;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot upload otp to 0x%x len %zd\n",
+ address, ar->running_fw->fw_file.otp_len);
+
+ ret = ath10k_bmi_fast_download(ar, address,
+ ar->running_fw->fw_file.otp_data,
+ ar->running_fw->fw_file.otp_len);
+ if (ret) {
+ ath10k_err(ar, "could not write otp (%d)\n", ret);
+ return ret;
+ }
+
+ /* As of now pre-cal is valid for 10_4 variants */
+ if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT ||
+ ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE)
+ bmi_otp_exe_param = BMI_PARAM_FLASH_SECTION_ALL;
+
+ ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, &result);
+ if (ret) {
+ ath10k_err(ar, "could not execute otp (%d)\n", ret);
+ return ret;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result);
+
+ if (!(skip_otp || test_bit(ATH10K_FW_FEATURE_IGNORE_OTP_RESULT,
+ ar->running_fw->fw_file.fw_features)) &&
+ result != 0) {
+ ath10k_err(ar, "otp calibration failed: %d", result);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ath10k_download_cal_file(struct ath10k *ar,
+ const struct firmware *file)
+{
+ int ret;
+
+ if (!file)
+ return -ENOENT;
+
+ if (IS_ERR(file))
+ return PTR_ERR(file);
+
+ ret = ath10k_download_board_data(ar, file->data, file->size);
+ if (ret) {
+ ath10k_err(ar, "failed to download cal_file data: %d\n", ret);
+ return ret;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cal file downloaded\n");
+
+ return 0;
+}
+
+static int ath10k_download_cal_dt(struct ath10k *ar, const char *dt_name)
+{
+ struct device_node *node;
+ int data_len;
+ void *data;
+ int ret;
+
+ node = ar->dev->of_node;
+ if (!node)
+ /* Device Tree is optional, don't print any warnings if
+ * there's no node for ath10k.
+ */
+ return -ENOENT;
+
+ if (!of_get_property(node, dt_name, &data_len)) {
+ /* The calibration data node is optional */
+ return -ENOENT;
+ }
+
+ if (data_len != ar->hw_params.cal_data_len) {
+ ath10k_warn(ar, "invalid calibration data length in DT: %d\n",
+ data_len);
+ ret = -EMSGSIZE;
+ goto out;
+ }
+
+ data = kmalloc(data_len, GFP_KERNEL);
+ if (!data) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = of_property_read_u8_array(node, dt_name, data, data_len);
+ if (ret) {
+ ath10k_warn(ar, "failed to read calibration data from DT: %d\n",
+ ret);
+ goto out_free;
+ }
+
+ ret = ath10k_download_board_data(ar, data, data_len);
+ if (ret) {
+ ath10k_warn(ar, "failed to download calibration data from Device Tree: %d\n",
+ ret);
+ goto out_free;
+ }
+
+ ret = 0;
+
+out_free:
+ kfree(data);
+
+out:
+ return ret;
+}
+
+static int ath10k_download_cal_eeprom(struct ath10k *ar)
+{
+ size_t data_len;
+ void *data = NULL;
+ int ret;
+
+ ret = ath10k_hif_fetch_cal_eeprom(ar, &data, &data_len);
+ if (ret) {
+ if (ret != -EOPNOTSUPP)
+ ath10k_warn(ar, "failed to read calibration data from EEPROM: %d\n",
+ ret);
+ goto out_free;
+ }
+
+ ret = ath10k_download_board_data(ar, data, data_len);
+ if (ret) {
+ ath10k_warn(ar, "failed to download calibration data from EEPROM: %d\n",
+ ret);
+ goto out_free;
+ }
+
+ ret = 0;
+
+out_free:
+ kfree(data);
+
+ return ret;
+}
+
int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name,
struct ath10k_fw_file *fw_file)
{
@@ -1896,7 +2085,8 @@ static int ath10k_init_hw_params(struct ath10k *ar)
for (i = 0; i < ARRAY_SIZE(ath10k_hw_params_list); i++) {
hw_params = &ath10k_hw_params_list[i];
- if (hw_params->id == ar->target_version &&
+ if (hw_params->bus == ar->hif.bus &&
+ hw_params->id == ar->target_version &&
hw_params->dev_id == ar->dev_id)
break;
}
@@ -1997,6 +2187,7 @@ static void ath10k_core_set_coverage_class_work(struct work_struct *work)
static int ath10k_core_init_firmware_features(struct ath10k *ar)
{
struct ath10k_fw_file *fw_file = &ar->normal_mode_fw.fw_file;
+ int max_num_peers;
if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, fw_file->fw_features) &&
!test_bit(ATH10K_FW_FEATURE_WMI_10X, fw_file->fw_features)) {
@@ -2076,7 +2267,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
switch (fw_file->wmi_op_version) {
case ATH10K_FW_WMI_OP_VERSION_MAIN:
- ar->max_num_peers = TARGET_NUM_PEERS;
+ max_num_peers = TARGET_NUM_PEERS;
ar->max_num_stations = TARGET_NUM_STATIONS;
ar->max_num_vdevs = TARGET_NUM_VDEVS;
ar->htt.max_num_pending_tx = TARGET_NUM_MSDU_DESC;
@@ -2088,10 +2279,10 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
case ATH10K_FW_WMI_OP_VERSION_10_2:
case ATH10K_FW_WMI_OP_VERSION_10_2_4:
if (ath10k_peer_stats_enabled(ar)) {
- ar->max_num_peers = TARGET_10X_TX_STATS_NUM_PEERS;
+ max_num_peers = TARGET_10X_TX_STATS_NUM_PEERS;
ar->max_num_stations = TARGET_10X_TX_STATS_NUM_STATIONS;
} else {
- ar->max_num_peers = TARGET_10X_NUM_PEERS;
+ max_num_peers = TARGET_10X_NUM_PEERS;
ar->max_num_stations = TARGET_10X_NUM_STATIONS;
}
ar->max_num_vdevs = TARGET_10X_NUM_VDEVS;
@@ -2100,7 +2291,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
break;
case ATH10K_FW_WMI_OP_VERSION_TLV:
- ar->max_num_peers = TARGET_TLV_NUM_PEERS;
+ max_num_peers = TARGET_TLV_NUM_PEERS;
ar->max_num_stations = TARGET_TLV_NUM_STATIONS;
ar->max_num_vdevs = TARGET_TLV_NUM_VDEVS;
ar->max_num_tdls_vdevs = TARGET_TLV_NUM_TDLS_VDEVS;
@@ -2112,7 +2303,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
ar->wmi.mgmt_max_num_pending_tx = TARGET_TLV_MGMT_NUM_MSDU_DESC;
break;
case ATH10K_FW_WMI_OP_VERSION_10_4:
- ar->max_num_peers = TARGET_10_4_NUM_PEERS;
+ max_num_peers = TARGET_10_4_NUM_PEERS;
ar->max_num_stations = TARGET_10_4_NUM_STATIONS;
ar->num_active_peers = TARGET_10_4_ACTIVE_PEERS;
ar->max_num_vdevs = TARGET_10_4_NUM_VDEVS;
@@ -2131,10 +2322,16 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
break;
case ATH10K_FW_WMI_OP_VERSION_UNSET:
case ATH10K_FW_WMI_OP_VERSION_MAX:
+ default:
WARN_ON(1);
return -EINVAL;
}
+ if (ar->hw_params.num_peers)
+ ar->max_num_peers = ar->hw_params.num_peers;
+ else
+ ar->max_num_peers = max_num_peers;
+
/* Backwards compatibility for firmwares without
* ATH10K_FW_IE_HTT_OP_VERSION.
*/
@@ -2384,6 +2581,10 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
ar->wmi.svc_map))
val |= WMI_10_4_TDLS_UAPSD_BUFFER_STA;
+ if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI,
+ ar->wmi.svc_map))
+ val |= WMI_10_4_TX_DATA_ACK_RSSI;
+
status = ath10k_mac_ext_resource_config(ar, val);
if (status) {
ath10k_err(ar,
@@ -2608,7 +2809,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
if (ret)
ath10k_dbg(ar, ATH10K_DBG_BOOT, "DT bdf variant name not set.\n");
- ret = ath10k_core_fetch_board_file(ar);
+ ret = ath10k_core_fetch_board_file(ar, ATH10K_BD_IE_BOARD);
if (ret) {
ath10k_err(ar, "failed to fetch board file: %d\n", ret);
goto err_free_firmware_files;
@@ -2617,6 +2818,8 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
ath10k_debug_print_board_info(ar);
}
+ device_get_mac_address(ar->dev, ar->mac_addr, sizeof(ar->mac_addr));
+
ret = ath10k_core_init_firmware_features(ar);
if (ret) {
ath10k_err(ar, "fatal problem with firmware features: %d\n",
@@ -2729,9 +2932,11 @@ err:
return;
}
-int ath10k_core_register(struct ath10k *ar, u32 chip_id)
+int ath10k_core_register(struct ath10k *ar,
+ const struct ath10k_bus_params *bus_params)
{
- ar->chip_id = chip_id;
+ ar->chip_id = bus_params->chip_id;
+ ar->dev_type = bus_params->dev_type;
queue_work(ar->workqueue, &ar->register_work);
return 0;
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 9feea02e7d37..c76af343db3d 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -92,14 +92,6 @@
struct ath10k;
-enum ath10k_bus {
- ATH10K_BUS_PCI,
- ATH10K_BUS_AHB,
- ATH10K_BUS_SDIO,
- ATH10K_BUS_USB,
- ATH10K_BUS_SNOC,
-};
-
static inline const char *ath10k_bus_str(enum ath10k_bus bus)
{
switch (bus) {
@@ -461,6 +453,36 @@ struct ath10k_sta_tid_stats {
unsigned long int rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_MAX];
};
+enum ath10k_counter_type {
+ ATH10K_COUNTER_TYPE_BYTES,
+ ATH10K_COUNTER_TYPE_PKTS,
+ ATH10K_COUNTER_TYPE_MAX,
+};
+
+enum ath10k_stats_type {
+ ATH10K_STATS_TYPE_SUCC,
+ ATH10K_STATS_TYPE_FAIL,
+ ATH10K_STATS_TYPE_RETRY,
+ ATH10K_STATS_TYPE_AMPDU,
+ ATH10K_STATS_TYPE_MAX,
+};
+
+struct ath10k_htt_data_stats {
+ u64 legacy[ATH10K_COUNTER_TYPE_MAX][ATH10K_LEGACY_NUM];
+ u64 ht[ATH10K_COUNTER_TYPE_MAX][ATH10K_HT_MCS_NUM];
+ u64 vht[ATH10K_COUNTER_TYPE_MAX][ATH10K_VHT_MCS_NUM];
+ u64 bw[ATH10K_COUNTER_TYPE_MAX][ATH10K_BW_NUM];
+ u64 nss[ATH10K_COUNTER_TYPE_MAX][ATH10K_NSS_NUM];
+ u64 gi[ATH10K_COUNTER_TYPE_MAX][ATH10K_GI_NUM];
+};
+
+struct ath10k_htt_tx_stats {
+ struct ath10k_htt_data_stats stats[ATH10K_STATS_TYPE_MAX];
+ u64 tx_duration;
+ u64 ba_fails;
+ u64 ack_fails;
+};
+
struct ath10k_sta {
struct ath10k_vif *arvif;
@@ -474,6 +496,7 @@ struct ath10k_sta {
struct work_struct update_wk;
u64 rx_duration;
+ struct ath10k_htt_tx_stats *tx_stats;
#ifdef CONFIG_MAC80211_DEBUGFS
/* protected by conf_mutex */
@@ -482,6 +505,8 @@ struct ath10k_sta {
/* Protected with ar->data_lock */
struct ath10k_sta_tid_stats tid_stats[IEEE80211_NUM_TIDS + 1];
#endif
+ /* Protected with ar->data_lock */
+ u32 peer_ps_state;
};
#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5 * HZ)
@@ -607,6 +632,7 @@ struct ath10k_debug {
u32 reg_addr;
u32 nf_cal_period;
void *cal_data;
+ u32 enable_extd_tx_stats;
};
enum ath10k_state {
@@ -861,6 +887,9 @@ struct ath10k_fw_components {
const struct firmware *board;
const void *board_data;
size_t board_len;
+ const struct firmware *ext_board;
+ const void *ext_board_data;
+ size_t ext_board_len;
struct ath10k_fw_file fw_file;
};
@@ -880,6 +909,16 @@ struct ath10k_per_peer_tx_stats {
u32 reserved2;
};
+enum ath10k_dev_type {
+ ATH10K_DEV_TYPE_LL,
+ ATH10K_DEV_TYPE_HL,
+};
+
+struct ath10k_bus_params {
+ u32 chip_id;
+ enum ath10k_dev_type dev_type;
+};
+
struct ath10k {
struct ath_common ath_common;
struct ieee80211_hw *hw;
@@ -890,6 +929,7 @@ struct ath10k {
enum ath10k_hw_rev hw_rev;
u16 dev_id;
u32 chip_id;
+ enum ath10k_dev_type dev_type;
u32 target_version;
u8 fw_version_major;
u32 fw_version_minor;
@@ -908,6 +948,8 @@ struct ath10k {
u32 low_5ghz_chan;
u32 high_5ghz_chan;
bool ani_enabled;
+ /* protected by conf_mutex */
+ u8 ps_state_enable;
bool p2p;
@@ -947,7 +989,9 @@ struct ath10k {
bool bmi_ids_valid;
u8 bmi_board_id;
+ u8 bmi_eboard_id;
u8 bmi_chip_id;
+ bool ext_bid_supported;
char bdf_ext[ATH10K_SMBIOS_BDF_EXT_STR_LENGTH];
} id;
@@ -1003,6 +1047,7 @@ struct ath10k {
struct completion install_key_done;
+ int last_wmi_vdev_start_status;
struct completion vdev_setup_done;
struct workqueue_struct *workqueue;
@@ -1167,7 +1212,8 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
const struct ath10k_fw_components *fw_components);
int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt);
void ath10k_core_stop(struct ath10k *ar);
-int ath10k_core_register(struct ath10k *ar, u32 chip_id);
+int ath10k_core_register(struct ath10k *ar,
+ const struct ath10k_bus_params *bus_params);
void ath10k_core_unregister(struct ath10k *ar);
#endif /* _CORE_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 0baaad90b8d1..2c0cb6757fc6 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -2042,6 +2042,61 @@ static const struct file_operations fops_btcoex = {
.open = simple_open
};
+static ssize_t ath10k_write_enable_extd_tx_stats(struct file *file,
+ const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct ath10k *ar = file->private_data;
+ u32 filter;
+ int ret;
+
+ if (kstrtouint_from_user(ubuf, count, 0, &filter))
+ return -EINVAL;
+
+ mutex_lock(&ar->conf_mutex);
+
+ if (ar->state != ATH10K_STATE_ON) {
+ ar->debug.enable_extd_tx_stats = filter;
+ ret = count;
+ goto out;
+ }
+
+ if (filter == ar->debug.enable_extd_tx_stats) {
+ ret = count;
+ goto out;
+ }
+
+ ar->debug.enable_extd_tx_stats = filter;
+ ret = count;
+
+out:
+ mutex_unlock(&ar->conf_mutex);
+ return ret;
+}
+
+static ssize_t ath10k_read_enable_extd_tx_stats(struct file *file,
+ char __user *ubuf,
+ size_t count, loff_t *ppos)
+
+{
+ char buf[32];
+ struct ath10k *ar = file->private_data;
+ int len = 0;
+
+ mutex_lock(&ar->conf_mutex);
+ len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
+ ar->debug.enable_extd_tx_stats);
+ mutex_unlock(&ar->conf_mutex);
+
+ return simple_read_from_buffer(ubuf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_enable_extd_tx_stats = {
+ .read = ath10k_read_enable_extd_tx_stats,
+ .write = ath10k_write_enable_extd_tx_stats,
+ .open = simple_open
+};
+
static ssize_t ath10k_write_peer_stats(struct file *file,
const char __user *ubuf,
size_t count, loff_t *ppos)
@@ -2343,6 +2398,85 @@ static const struct file_operations fops_warm_hw_reset = {
.llseek = default_llseek,
};
+static void ath10k_peer_ps_state_disable(void *data,
+ struct ieee80211_sta *sta)
+{
+ struct ath10k *ar = data;
+ struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
+
+ spin_lock_bh(&ar->data_lock);
+ arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED;
+ spin_unlock_bh(&ar->data_lock);
+}
+
+static ssize_t ath10k_write_ps_state_enable(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath10k *ar = file->private_data;
+ int ret;
+ u32 param;
+ u8 ps_state_enable;
+
+ if (kstrtou8_from_user(user_buf, count, 0, &ps_state_enable))
+ return -EINVAL;
+
+ if (ps_state_enable > 1 || ps_state_enable < 0)
+ return -EINVAL;
+
+ mutex_lock(&ar->conf_mutex);
+
+ if (ar->ps_state_enable == ps_state_enable) {
+ ret = count;
+ goto exit;
+ }
+
+ param = ar->wmi.pdev_param->peer_sta_ps_statechg_enable;
+ ret = ath10k_wmi_pdev_set_param(ar, param, ps_state_enable);
+ if (ret) {
+ ath10k_warn(ar, "failed to enable ps_state_enable: %d\n",
+ ret);
+ goto exit;
+ }
+ ar->ps_state_enable = ps_state_enable;
+
+ if (!ar->ps_state_enable)
+ ieee80211_iterate_stations_atomic(ar->hw,
+ ath10k_peer_ps_state_disable,
+ ar);
+
+ ret = count;
+
+exit:
+ mutex_unlock(&ar->conf_mutex);
+
+ return ret;
+}
+
+static ssize_t ath10k_read_ps_state_enable(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath10k *ar = file->private_data;
+ int len = 0;
+ char buf[32];
+
+ mutex_lock(&ar->conf_mutex);
+ len = scnprintf(buf, sizeof(buf) - len, "%d\n",
+ ar->ps_state_enable);
+ mutex_unlock(&ar->conf_mutex);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_ps_state_enable = {
+ .read = ath10k_read_ps_state_enable,
+ .write = ath10k_write_ps_state_enable,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
int ath10k_debug_create(struct ath10k *ar)
{
ar->debug.cal_data = vzalloc(ATH10K_DEBUG_CAL_DATA_LEN);
@@ -2454,10 +2588,15 @@ int ath10k_debug_register(struct ath10k *ar)
debugfs_create_file("btcoex", 0644, ar->debug.debugfs_phy, ar,
&fops_btcoex);
- if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map))
+ if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) {
debugfs_create_file("peer_stats", 0644, ar->debug.debugfs_phy, ar,
&fops_peer_stats);
+ debugfs_create_file("enable_extd_tx_stats", 0644,
+ ar->debug.debugfs_phy, ar,
+ &fops_enable_extd_tx_stats);
+ }
+
debugfs_create_file("fw_checksums", 0400, ar->debug.debugfs_phy, ar,
&fops_fw_checksums);
@@ -2474,6 +2613,9 @@ int ath10k_debug_register(struct ath10k *ar)
debugfs_create_file("warm_hw_reset", 0600, ar->debug.debugfs_phy, ar,
&fops_warm_hw_reset);
+ debugfs_create_file("ps_state_enable", 0600, ar->debug.debugfs_phy, ar,
+ &fops_ps_state_enable);
+
return 0;
}
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index 0afca5c106b6..3a6191cff2f9 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -128,6 +128,10 @@ static inline u32 ath10k_debug_get_fw_dbglog_level(struct ath10k *ar)
return ar->debug.fw_dbglog_level;
}
+static inline int ath10k_debug_is_extd_tx_stats_enabled(struct ath10k *ar)
+{
+ return ar->debug.enable_extd_tx_stats;
+}
#else
static inline int ath10k_debug_start(struct ath10k *ar)
@@ -190,6 +194,11 @@ static inline u32 ath10k_debug_get_fw_dbglog_level(struct ath10k *ar)
return 0;
}
+static inline int ath10k_debug_is_extd_tx_stats_enabled(struct ath10k *ar)
+{
+ return 0;
+}
+
#define ATH10K_DFS_STAT_INC(ar, c) do { } while (0)
#define ath10k_debug_get_et_strings NULL
diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
index a63c97e2c50c..b09cdc699c69 100644
--- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c
+++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
@@ -460,6 +460,33 @@ static const struct file_operations fops_peer_debug_trigger = {
.llseek = default_llseek,
};
+static ssize_t ath10k_dbg_sta_read_peer_ps_state(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_sta *sta = file->private_data;
+ struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
+ struct ath10k *ar = arsta->arvif->ar;
+ char buf[20];
+ int len = 0;
+
+ spin_lock_bh(&ar->data_lock);
+
+ len = scnprintf(buf, sizeof(buf) - len, "%d\n",
+ arsta->peer_ps_state);
+
+ spin_unlock_bh(&ar->data_lock);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_peer_ps_state = {
+ .open = simple_open,
+ .read = ath10k_dbg_sta_read_peer_ps_state,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
static char *get_err_str(enum ath10k_pkt_rx_err i)
{
switch (i) {
@@ -626,9 +653,105 @@ static const struct file_operations fops_tid_stats_dump = {
.llseek = default_llseek,
};
+static ssize_t ath10k_dbg_sta_dump_tx_stats(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_sta *sta = file->private_data;
+ struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
+ struct ath10k *ar = arsta->arvif->ar;
+ struct ath10k_htt_data_stats *stats;
+ const char *str_name[ATH10K_STATS_TYPE_MAX] = {"succ", "fail",
+ "retry", "ampdu"};
+ const char *str[ATH10K_COUNTER_TYPE_MAX] = {"bytes", "packets"};
+ int len = 0, i, j, k, retval = 0;
+ const int size = 2 * 4096;
+ char *buf;
+
+ buf = kzalloc(size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ mutex_lock(&ar->conf_mutex);
+
+ spin_lock_bh(&ar->data_lock);
+ for (k = 0; k < ATH10K_STATS_TYPE_MAX; k++) {
+ for (j = 0; j < ATH10K_COUNTER_TYPE_MAX; j++) {
+ stats = &arsta->tx_stats->stats[k];
+ len += scnprintf(buf + len, size - len, "%s_%s\n",
+ str_name[k],
+ str[j]);
+ len += scnprintf(buf + len, size - len,
+ " VHT MCS %s\n",
+ str[j]);
+ for (i = 0; i < ATH10K_VHT_MCS_NUM; i++)
+ len += scnprintf(buf + len, size - len,
+ " %llu ",
+ stats->vht[j][i]);
+ len += scnprintf(buf + len, size - len, "\n");
+ len += scnprintf(buf + len, size - len, " HT MCS %s\n",
+ str[j]);
+ for (i = 0; i < ATH10K_HT_MCS_NUM; i++)
+ len += scnprintf(buf + len, size - len,
+ " %llu ", stats->ht[j][i]);
+ len += scnprintf(buf + len, size - len, "\n");
+ len += scnprintf(buf + len, size - len,
+ " BW %s (20,40,80,160 MHz)\n", str[j]);
+ len += scnprintf(buf + len, size - len,
+ " %llu %llu %llu %llu\n",
+ stats->bw[j][0], stats->bw[j][1],
+ stats->bw[j][2], stats->bw[j][3]);
+ len += scnprintf(buf + len, size - len,
+ " NSS %s (1x1,2x2,3x3,4x4)\n", str[j]);
+ len += scnprintf(buf + len, size - len,
+ " %llu %llu %llu %llu\n",
+ stats->nss[j][0], stats->nss[j][1],
+ stats->nss[j][2], stats->nss[j][3]);
+ len += scnprintf(buf + len, size - len,
+ " GI %s (LGI,SGI)\n",
+ str[j]);
+ len += scnprintf(buf + len, size - len, " %llu %llu\n",
+ stats->gi[j][0], stats->gi[j][1]);
+ len += scnprintf(buf + len, size - len,
+ " legacy rate %s (1,2 ... Mbps)\n ",
+ str[j]);
+ for (i = 0; i < ATH10K_LEGACY_NUM; i++)
+ len += scnprintf(buf + len, size - len, "%llu ",
+ stats->legacy[j][i]);
+ len += scnprintf(buf + len, size - len, "\n");
+ }
+ }
+
+ len += scnprintf(buf + len, size - len,
+ "\nTX duration\n %llu usecs\n",
+ arsta->tx_stats->tx_duration);
+ len += scnprintf(buf + len, size - len,
+ "BA fails\n %llu\n", arsta->tx_stats->ba_fails);
+ len += scnprintf(buf + len, size - len,
+ "ack fails\n %llu\n", arsta->tx_stats->ack_fails);
+ spin_unlock_bh(&ar->data_lock);
+
+ if (len > size)
+ len = size;
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+
+ mutex_unlock(&ar->conf_mutex);
+ return retval;
+}
+
+static const struct file_operations fops_tx_stats = {
+ .read = ath10k_dbg_sta_dump_tx_stats,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct dentry *dir)
{
+ struct ath10k *ar = hw->priv;
+
debugfs_create_file("aggr_mode", 0644, dir, sta, &fops_aggr_mode);
debugfs_create_file("addba", 0200, dir, sta, &fops_addba);
debugfs_create_file("addba_resp", 0200, dir, sta, &fops_addba_resp);
@@ -637,4 +760,11 @@ void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
&fops_peer_debug_trigger);
debugfs_create_file("dump_tid_stats", 0400, dir, sta,
&fops_tid_stats_dump);
+
+ if (ath10k_peer_stats_enabled(ar) &&
+ ath10k_debug_is_extd_tx_stats_enabled(ar))
+ debugfs_create_file("tx_stats", 0400, dir, sta,
+ &fops_tx_stats);
+ debugfs_create_file("peer_ps_state", 0400, dir, sta,
+ &fops_peer_ps_state);
}
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index 331b8d558791..28daed5981a1 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -53,7 +53,8 @@ static inline void ath10k_htc_restore_tx_skb(struct ath10k_htc *htc,
{
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
- dma_unmap_single(htc->ar->dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
+ if (htc->ar->dev_type != ATH10K_DEV_TYPE_HL)
+ dma_unmap_single(htc->ar->dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
skb_pull(skb, sizeof(struct ath10k_htc_hdr));
}
@@ -137,11 +138,14 @@ int ath10k_htc_send(struct ath10k_htc *htc,
ath10k_htc_prepare_tx_skb(ep, skb);
skb_cb->eid = eid;
- skb_cb->paddr = dma_map_single(dev, skb->data, skb->len, DMA_TO_DEVICE);
- ret = dma_mapping_error(dev, skb_cb->paddr);
- if (ret) {
- ret = -EIO;
- goto err_credits;
+ if (ar->dev_type != ATH10K_DEV_TYPE_HL) {
+ skb_cb->paddr = dma_map_single(dev, skb->data, skb->len,
+ DMA_TO_DEVICE);
+ ret = dma_mapping_error(dev, skb_cb->paddr);
+ if (ret) {
+ ret = -EIO;
+ goto err_credits;
+ }
}
sg_item.transfer_id = ep->eid;
@@ -157,7 +161,8 @@ int ath10k_htc_send(struct ath10k_htc *htc,
return 0;
err_unmap:
- dma_unmap_single(dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
+ if (ar->dev_type != ATH10K_DEV_TYPE_HL)
+ dma_unmap_single(dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
err_credits:
if (ep->tx_credit_flow_enabled) {
spin_lock_bh(&htc->tx_lock);
@@ -803,8 +808,11 @@ setup:
ep->service_id,
&ep->ul_pipe_id,
&ep->dl_pipe_id);
- if (status)
+ if (status) {
+ ath10k_warn(ar, "unsupported HTC service id: %d\n",
+ ep->service_id);
return status;
+ }
ath10k_dbg(ar, ATH10K_DBG_BOOT,
"boot htc service '%s' ul pipe %d dl pipe %d eid %d ready\n",
@@ -838,6 +846,56 @@ struct sk_buff *ath10k_htc_alloc_skb(struct ath10k *ar, int size)
return skb;
}
+static void ath10k_htc_pktlog_process_rx(struct ath10k *ar, struct sk_buff *skb)
+{
+ trace_ath10k_htt_pktlog(ar, skb->data, skb->len);
+ dev_kfree_skb_any(skb);
+}
+
+static int ath10k_htc_pktlog_connect(struct ath10k *ar)
+{
+ struct ath10k_htc_svc_conn_resp conn_resp;
+ struct ath10k_htc_svc_conn_req conn_req;
+ int status;
+
+ memset(&conn_req, 0, sizeof(conn_req));
+ memset(&conn_resp, 0, sizeof(conn_resp));
+
+ conn_req.ep_ops.ep_tx_complete = NULL;
+ conn_req.ep_ops.ep_rx_complete = ath10k_htc_pktlog_process_rx;
+ conn_req.ep_ops.ep_tx_credits = NULL;
+
+ /* connect to control service */
+ conn_req.service_id = ATH10K_HTC_SVC_ID_HTT_LOG_MSG;
+ status = ath10k_htc_connect_service(&ar->htc, &conn_req, &conn_resp);
+ if (status) {
+ ath10k_warn(ar, "failed to connect to PKTLOG service: %d\n",
+ status);
+ return status;
+ }
+
+ return 0;
+}
+
+static bool ath10k_htc_pktlog_svc_supported(struct ath10k *ar)
+{
+ u8 ul_pipe_id;
+ u8 dl_pipe_id;
+ int status;
+
+ status = ath10k_hif_map_service_to_pipe(ar, ATH10K_HTC_SVC_ID_HTT_LOG_MSG,
+ &ul_pipe_id,
+ &dl_pipe_id);
+ if (status) {
+ ath10k_warn(ar, "unsupported HTC service id: %d\n",
+ ATH10K_HTC_SVC_ID_HTT_LOG_MSG);
+
+ return false;
+ }
+
+ return true;
+}
+
int ath10k_htc_start(struct ath10k_htc *htc)
{
struct ath10k *ar = htc->ar;
@@ -871,6 +929,14 @@ int ath10k_htc_start(struct ath10k_htc *htc)
return status;
}
+ if (ath10k_htc_pktlog_svc_supported(ar)) {
+ status = ath10k_htc_pktlog_connect(ar);
+ if (status) {
+ ath10k_err(ar, "failed to connect to pktlog: %d\n", status);
+ return status;
+ }
+ }
+
return 0;
}
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 5d3ff80f3a1f..a76f7c9e2199 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -29,7 +29,6 @@
#include "htc.h"
#include "hw.h"
#include "rx_desc.h"
-#include "hw.h"
enum htt_dbg_stats_type {
HTT_DBG_STATS_WAL_PDEV_TXRX = 1 << 0,
@@ -577,6 +576,8 @@ struct htt_mgmt_tx_completion {
#define HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES_MASK 0xFF000000
#define HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES_LSB 24
+#define HTT_TX_CMPL_FLAG_DATA_RSSI BIT(0)
+
struct htt_rx_indication_hdr {
u8 info0; /* %HTT_RX_INDICATION_INFO0_ */
__le16 peer_id;
@@ -719,6 +720,15 @@ struct htt_rx_indication {
struct htt_rx_indication_mpdu_range mpdu_ranges[0];
} __packed;
+/* High latency version of the RX indication */
+struct htt_rx_indication_hl {
+ struct htt_rx_indication_hdr hdr;
+ struct htt_rx_indication_ppdu ppdu;
+ struct htt_rx_indication_prefix prefix;
+ struct fw_rx_desc_hl fw_desc;
+ struct htt_rx_indication_mpdu_range mpdu_ranges[0];
+} __packed;
+
static inline struct htt_rx_indication_mpdu_range *
htt_rx_ind_get_mpdu_ranges(struct htt_rx_indication *rx_ind)
{
@@ -731,6 +741,18 @@ static inline struct htt_rx_indication_mpdu_range *
return ptr;
}
+static inline struct htt_rx_indication_mpdu_range *
+ htt_rx_ind_get_mpdu_ranges_hl(struct htt_rx_indication_hl *rx_ind)
+{
+ void *ptr = rx_ind;
+
+ ptr += sizeof(rx_ind->hdr)
+ + sizeof(rx_ind->ppdu)
+ + sizeof(rx_ind->prefix)
+ + sizeof(rx_ind->fw_desc);
+ return ptr;
+}
+
enum htt_rx_flush_mpdu_status {
HTT_RX_FLUSH_MPDU_DISCARD = 0,
HTT_RX_FLUSH_MPDU_REORDER = 1,
@@ -840,7 +862,7 @@ struct htt_data_tx_completion {
} __packed;
} __packed;
u8 num_msdus;
- u8 rsvd0;
+ u8 flags2; /* HTT_TX_CMPL_FLAG_DATA_RSSI */
__le16 msdus[0]; /* variable length based on %num_msdus */
} __packed;
@@ -1641,6 +1663,7 @@ struct htt_resp {
struct htt_mgmt_tx_completion mgmt_tx_completion;
struct htt_data_tx_completion data_tx_completion;
struct htt_rx_indication rx_ind;
+ struct htt_rx_indication_hl rx_ind_hl;
struct htt_rx_fragment_indication rx_frag_ind;
struct htt_rx_peer_map peer_map;
struct htt_rx_peer_unmap peer_unmap;
@@ -1994,6 +2017,31 @@ struct htt_rx_desc {
u8 msdu_payload[0];
};
+#define HTT_RX_DESC_HL_INFO_SEQ_NUM_MASK 0x00000fff
+#define HTT_RX_DESC_HL_INFO_SEQ_NUM_LSB 0
+#define HTT_RX_DESC_HL_INFO_ENCRYPTED_MASK 0x00001000
+#define HTT_RX_DESC_HL_INFO_ENCRYPTED_LSB 12
+#define HTT_RX_DESC_HL_INFO_CHAN_INFO_PRESENT_MASK 0x00002000
+#define HTT_RX_DESC_HL_INFO_CHAN_INFO_PRESENT_LSB 13
+#define HTT_RX_DESC_HL_INFO_MCAST_BCAST_MASK 0x00008000
+#define HTT_RX_DESC_HL_INFO_MCAST_BCAST_LSB 15
+#define HTT_RX_DESC_HL_INFO_FRAGMENT_MASK 0x00010000
+#define HTT_RX_DESC_HL_INFO_FRAGMENT_LSB 16
+#define HTT_RX_DESC_HL_INFO_KEY_ID_OCT_MASK 0x01fe0000
+#define HTT_RX_DESC_HL_INFO_KEY_ID_OCT_LSB 17
+
+struct htt_rx_desc_base_hl {
+ __le32 info; /* HTT_RX_DESC_HL_INFO_ */
+};
+
+struct htt_rx_chan_info {
+ __le16 primary_chan_center_freq_mhz;
+ __le16 contig_chan1_center_freq_mhz;
+ __le16 contig_chan2_center_freq_mhz;
+ u8 phy_mode;
+ u8 reserved;
+} __packed;
+
#define HTT_RX_DESC_ALIGN 8
#define HTT_MAC_ADDR_LEN 6
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 1455007f3eb8..f2405258a6d3 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -265,6 +265,9 @@ int ath10k_htt_rx_ring_refill(struct ath10k *ar)
struct ath10k_htt *htt = &ar->htt;
int ret;
+ if (ar->dev_type == ATH10K_DEV_TYPE_HL)
+ return 0;
+
spin_lock_bh(&htt->rx_ring.lock);
ret = ath10k_htt_rx_ring_fill_n(htt, (htt->rx_ring.fill_level -
htt->rx_ring.fill_cnt));
@@ -279,6 +282,9 @@ int ath10k_htt_rx_ring_refill(struct ath10k *ar)
void ath10k_htt_rx_free(struct ath10k_htt *htt)
{
+ if (htt->ar->dev_type == ATH10K_DEV_TYPE_HL)
+ return;
+
del_timer_sync(&htt->rx_ring.refill_retry_timer);
skb_queue_purge(&htt->rx_msdus_q);
@@ -570,6 +576,9 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
size_t size;
struct timer_list *timer = &htt->rx_ring.refill_retry_timer;
+ if (ar->dev_type == ATH10K_DEV_TYPE_HL)
+ return 0;
+
htt->rx_confused = false;
/* XXX: The fill level could be changed during runtime in response to
@@ -1846,8 +1855,116 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt)
return 0;
}
-static void ath10k_htt_rx_proc_rx_ind(struct ath10k_htt *htt,
- struct htt_rx_indication *rx)
+static bool ath10k_htt_rx_proc_rx_ind_hl(struct ath10k_htt *htt,
+ struct htt_rx_indication_hl *rx,
+ struct sk_buff *skb)
+{
+ struct ath10k *ar = htt->ar;
+ struct ath10k_peer *peer;
+ struct htt_rx_indication_mpdu_range *mpdu_ranges;
+ struct fw_rx_desc_hl *fw_desc;
+ struct ieee80211_hdr *hdr;
+ struct ieee80211_rx_status *rx_status;
+ u16 peer_id;
+ u8 rx_desc_len;
+ int num_mpdu_ranges;
+ size_t tot_hdr_len;
+ struct ieee80211_channel *ch;
+
+ peer_id = __le16_to_cpu(rx->hdr.peer_id);
+
+ spin_lock_bh(&ar->data_lock);
+ peer = ath10k_peer_find_by_id(ar, peer_id);
+ spin_unlock_bh(&ar->data_lock);
+ if (!peer)
+ ath10k_warn(ar, "Got RX ind from invalid peer: %u\n", peer_id);
+
+ num_mpdu_ranges = MS(__le32_to_cpu(rx->hdr.info1),
+ HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES);
+ mpdu_ranges = htt_rx_ind_get_mpdu_ranges_hl(rx);
+ fw_desc = &rx->fw_desc;
+ rx_desc_len = fw_desc->len;
+
+ /* I have not yet seen any case where num_mpdu_ranges > 1.
+ * qcacld does not seem handle that case either, so we introduce the
+ * same limitiation here as well.
+ */
+ if (num_mpdu_ranges > 1)
+ ath10k_warn(ar,
+ "Unsupported number of MPDU ranges: %d, ignoring all but the first\n",
+ num_mpdu_ranges);
+
+ if (mpdu_ranges->mpdu_range_status !=
+ HTT_RX_IND_MPDU_STATUS_OK) {
+ ath10k_warn(ar, "MPDU range status: %d\n",
+ mpdu_ranges->mpdu_range_status);
+ goto err;
+ }
+
+ /* Strip off all headers before the MAC header before delivery to
+ * mac80211
+ */
+ tot_hdr_len = sizeof(struct htt_resp_hdr) + sizeof(rx->hdr) +
+ sizeof(rx->ppdu) + sizeof(rx->prefix) +
+ sizeof(rx->fw_desc) +
+ sizeof(*mpdu_ranges) * num_mpdu_ranges + rx_desc_len;
+ skb_pull(skb, tot_hdr_len);
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+ rx_status = IEEE80211_SKB_RXCB(skb);
+ rx_status->chains |= BIT(0);
+ rx_status->signal = ATH10K_DEFAULT_NOISE_FLOOR +
+ rx->ppdu.combined_rssi;
+ rx_status->flag &= ~RX_FLAG_NO_SIGNAL_VAL;
+
+ spin_lock_bh(&ar->data_lock);
+ ch = ar->scan_channel;
+ if (!ch)
+ ch = ar->rx_channel;
+ if (!ch)
+ ch = ath10k_htt_rx_h_any_channel(ar);
+ if (!ch)
+ ch = ar->tgt_oper_chan;
+ spin_unlock_bh(&ar->data_lock);
+
+ if (ch) {
+ rx_status->band = ch->band;
+ rx_status->freq = ch->center_freq;
+ }
+ if (rx->fw_desc.flags & FW_RX_DESC_FLAGS_LAST_MSDU)
+ rx_status->flag &= ~RX_FLAG_AMSDU_MORE;
+ else
+ rx_status->flag |= RX_FLAG_AMSDU_MORE;
+
+ /* Not entirely sure about this, but all frames from the chipset has
+ * the protected flag set even though they have already been decrypted.
+ * Unmasking this flag is necessary in order for mac80211 not to drop
+ * the frame.
+ * TODO: Verify this is always the case or find out a way to check
+ * if there has been hw decryption.
+ */
+ if (ieee80211_has_protected(hdr->frame_control)) {
+ hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+ rx_status->flag |= RX_FLAG_DECRYPTED |
+ RX_FLAG_IV_STRIPPED |
+ RX_FLAG_MMIC_STRIPPED;
+ }
+
+ ieee80211_rx_ni(ar->hw, skb);
+
+ /* We have delivered the skb to the upper layers (mac80211) so we
+ * must not free it.
+ */
+ return false;
+err:
+ /* Tell the caller that it must free the skb since we have not
+ * consumed it
+ */
+ return true;
+}
+
+static void ath10k_htt_rx_proc_rx_ind_ll(struct ath10k_htt *htt,
+ struct htt_rx_indication *rx)
{
struct ath10k *ar = htt->ar;
struct htt_rx_indication_mpdu_range *mpdu_ranges;
@@ -1884,7 +2001,9 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
struct htt_resp *resp = (struct htt_resp *)skb->data;
struct htt_tx_done tx_done = {};
int status = MS(resp->data_tx_completion.flags, HTT_DATA_TX_STATUS);
- __le16 msdu_id;
+ __le16 msdu_id, *msdus;
+ bool rssi_enabled = false;
+ u8 msdu_count = 0;
int i;
switch (status) {
@@ -1908,10 +2027,30 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx completion num_msdus %d\n",
resp->data_tx_completion.num_msdus);
- for (i = 0; i < resp->data_tx_completion.num_msdus; i++) {
- msdu_id = resp->data_tx_completion.msdus[i];
+ msdu_count = resp->data_tx_completion.num_msdus;
+
+ if (resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_DATA_RSSI)
+ rssi_enabled = true;
+
+ for (i = 0; i < msdu_count; i++) {
+ msdus = resp->data_tx_completion.msdus;
+ msdu_id = msdus[i];
tx_done.msdu_id = __le16_to_cpu(msdu_id);
+ if (rssi_enabled) {
+ /* Total no of MSDUs should be even,
+ * if odd MSDUs are sent firmware fills
+ * last msdu id with 0xffff
+ */
+ if (msdu_count & 0x01) {
+ msdu_id = msdus[msdu_count + i + 1];
+ tx_done.ack_rssi = __le16_to_cpu(msdu_id);
+ } else {
+ msdu_id = msdus[msdu_count + i];
+ tx_done.ack_rssi = __le16_to_cpu(msdu_id);
+ }
+ }
+
/* kfifo_put: In practice firmware shouldn't fire off per-CE
* interrupt and main interrupt (MSI/-X range case) for the same
* HTC service so it should be safe to use kfifo_put w/o lock.
@@ -2488,7 +2627,7 @@ void ath10k_htt_htc_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
dev_kfree_skb_any(skb);
}
-static inline bool is_valid_legacy_rate(u8 rate)
+static inline int ath10k_get_legacy_rate_idx(struct ath10k *ar, u8 rate)
{
static const u8 legacy_rates[] = {1, 2, 5, 11, 6, 9, 12,
18, 24, 36, 48, 54};
@@ -2496,10 +2635,116 @@ static inline bool is_valid_legacy_rate(u8 rate)
for (i = 0; i < ARRAY_SIZE(legacy_rates); i++) {
if (rate == legacy_rates[i])
- return true;
+ return i;
}
- return false;
+ ath10k_warn(ar, "Invalid legacy rate %hhd peer stats", rate);
+ return -EINVAL;
+}
+
+static void
+ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar,
+ struct ath10k_sta *arsta,
+ struct ath10k_per_peer_tx_stats *pstats,
+ u8 legacy_rate_idx)
+{
+ struct rate_info *txrate = &arsta->txrate;
+ struct ath10k_htt_tx_stats *tx_stats;
+ int ht_idx, gi, mcs, bw, nss;
+
+ if (!arsta->tx_stats)
+ return;
+
+ tx_stats = arsta->tx_stats;
+ gi = (arsta->txrate.flags & RATE_INFO_FLAGS_SHORT_GI);
+ ht_idx = txrate->mcs + txrate->nss * 8;
+ mcs = txrate->mcs;
+ bw = txrate->bw;
+ nss = txrate->nss;
+
+#define STATS_OP_FMT(name) tx_stats->stats[ATH10K_STATS_TYPE_##name]
+
+ if (txrate->flags == RATE_INFO_FLAGS_VHT_MCS) {
+ STATS_OP_FMT(SUCC).vht[0][mcs] += pstats->succ_bytes;
+ STATS_OP_FMT(SUCC).vht[1][mcs] += pstats->succ_pkts;
+ STATS_OP_FMT(FAIL).vht[0][mcs] += pstats->failed_bytes;
+ STATS_OP_FMT(FAIL).vht[1][mcs] += pstats->failed_pkts;
+ STATS_OP_FMT(RETRY).vht[0][mcs] += pstats->retry_bytes;
+ STATS_OP_FMT(RETRY).vht[1][mcs] += pstats->retry_pkts;
+ } else if (txrate->flags == RATE_INFO_FLAGS_MCS) {
+ STATS_OP_FMT(SUCC).ht[0][ht_idx] += pstats->succ_bytes;
+ STATS_OP_FMT(SUCC).ht[1][ht_idx] += pstats->succ_pkts;
+ STATS_OP_FMT(FAIL).ht[0][ht_idx] += pstats->failed_bytes;
+ STATS_OP_FMT(FAIL).ht[1][ht_idx] += pstats->failed_pkts;
+ STATS_OP_FMT(RETRY).ht[0][ht_idx] += pstats->retry_bytes;
+ STATS_OP_FMT(RETRY).ht[1][ht_idx] += pstats->retry_pkts;
+ } else {
+ mcs = legacy_rate_idx;
+ if (mcs < 0)
+ return;
+
+ STATS_OP_FMT(SUCC).legacy[0][mcs] += pstats->succ_bytes;
+ STATS_OP_FMT(SUCC).legacy[1][mcs] += pstats->succ_pkts;
+ STATS_OP_FMT(FAIL).legacy[0][mcs] += pstats->failed_bytes;
+ STATS_OP_FMT(FAIL).legacy[1][mcs] += pstats->failed_pkts;
+ STATS_OP_FMT(RETRY).legacy[0][mcs] += pstats->retry_bytes;
+ STATS_OP_FMT(RETRY).legacy[1][mcs] += pstats->retry_pkts;
+ }
+
+ if (ATH10K_HW_AMPDU(pstats->flags)) {
+ tx_stats->ba_fails += ATH10K_HW_BA_FAIL(pstats->flags);
+
+ if (txrate->flags == RATE_INFO_FLAGS_MCS) {
+ STATS_OP_FMT(AMPDU).ht[0][ht_idx] +=
+ pstats->succ_bytes + pstats->retry_bytes;
+ STATS_OP_FMT(AMPDU).ht[1][ht_idx] +=
+ pstats->succ_pkts + pstats->retry_pkts;
+ } else {
+ STATS_OP_FMT(AMPDU).vht[0][mcs] +=
+ pstats->succ_bytes + pstats->retry_bytes;
+ STATS_OP_FMT(AMPDU).vht[1][mcs] +=
+ pstats->succ_pkts + pstats->retry_pkts;
+ }
+ STATS_OP_FMT(AMPDU).bw[0][bw] +=
+ pstats->succ_bytes + pstats->retry_bytes;
+ STATS_OP_FMT(AMPDU).nss[0][nss] +=
+ pstats->succ_bytes + pstats->retry_bytes;
+ STATS_OP_FMT(AMPDU).gi[0][gi] +=
+ pstats->succ_bytes + pstats->retry_bytes;
+ STATS_OP_FMT(AMPDU).bw[1][bw] +=
+ pstats->succ_pkts + pstats->retry_pkts;
+ STATS_OP_FMT(AMPDU).nss[1][nss] +=
+ pstats->succ_pkts + pstats->retry_pkts;
+ STATS_OP_FMT(AMPDU).gi[1][gi] +=
+ pstats->succ_pkts + pstats->retry_pkts;
+ } else {
+ tx_stats->ack_fails +=
+ ATH10K_HW_BA_FAIL(pstats->flags);
+ }
+
+ STATS_OP_FMT(SUCC).bw[0][bw] += pstats->succ_bytes;
+ STATS_OP_FMT(SUCC).nss[0][nss] += pstats->succ_bytes;
+ STATS_OP_FMT(SUCC).gi[0][gi] += pstats->succ_bytes;
+
+ STATS_OP_FMT(SUCC).bw[1][bw] += pstats->succ_pkts;
+ STATS_OP_FMT(SUCC).nss[1][nss] += pstats->succ_pkts;
+ STATS_OP_FMT(SUCC).gi[1][gi] += pstats->succ_pkts;
+
+ STATS_OP_FMT(FAIL).bw[0][bw] += pstats->failed_bytes;
+ STATS_OP_FMT(FAIL).nss[0][nss] += pstats->failed_bytes;
+ STATS_OP_FMT(FAIL).gi[0][gi] += pstats->failed_bytes;
+
+ STATS_OP_FMT(FAIL).bw[1][bw] += pstats->failed_pkts;
+ STATS_OP_FMT(FAIL).nss[1][nss] += pstats->failed_pkts;
+ STATS_OP_FMT(FAIL).gi[1][gi] += pstats->failed_pkts;
+
+ STATS_OP_FMT(RETRY).bw[0][bw] += pstats->retry_bytes;
+ STATS_OP_FMT(RETRY).nss[0][nss] += pstats->retry_bytes;
+ STATS_OP_FMT(RETRY).gi[0][gi] += pstats->retry_bytes;
+
+ STATS_OP_FMT(RETRY).bw[1][bw] += pstats->retry_pkts;
+ STATS_OP_FMT(RETRY).nss[1][nss] += pstats->retry_pkts;
+ STATS_OP_FMT(RETRY).gi[1][gi] += pstats->retry_pkts;
}
static void
@@ -2508,7 +2753,7 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar,
struct ath10k_per_peer_tx_stats *peer_stats)
{
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
- u8 rate = 0, sgi;
+ u8 rate = 0, rate_idx = 0, sgi;
struct rate_info txrate;
lockdep_assert_held(&ar->data_lock);
@@ -2536,17 +2781,12 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar,
if (txrate.flags == WMI_RATE_PREAMBLE_CCK ||
txrate.flags == WMI_RATE_PREAMBLE_OFDM) {
rate = ATH10K_HW_LEGACY_RATE(peer_stats->ratecode);
-
- if (!is_valid_legacy_rate(rate)) {
- ath10k_warn(ar, "Invalid legacy rate %hhd peer stats",
- rate);
- return;
- }
-
/* This is hacky, FW sends CCK rate 5.5Mbps as 6 */
- rate *= 10;
- if (rate == 60 && txrate.flags == WMI_RATE_PREAMBLE_CCK)
- rate = rate - 5;
+ if (rate == 6 && txrate.flags == WMI_RATE_PREAMBLE_CCK)
+ rate = 5;
+ rate_idx = ath10k_get_legacy_rate_idx(ar, rate);
+ if (rate_idx < 0)
+ return;
arsta->txrate.legacy = rate;
} else if (txrate.flags == WMI_RATE_PREAMBLE_HT) {
arsta->txrate.flags = RATE_INFO_FLAGS_MCS;
@@ -2561,6 +2801,10 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar,
arsta->txrate.nss = txrate.nss;
arsta->txrate.bw = ath10k_bw_to_mac80211_bw(txrate.bw);
+
+ if (ath10k_debug_is_extd_tx_stats_enabled(ar))
+ ath10k_accumulate_per_peer_tx_stats(ar, arsta, peer_stats,
+ rate_idx);
}
static void ath10k_htt_fetch_peer_stats(struct ath10k *ar,
@@ -2702,7 +2946,12 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
break;
}
case HTT_T2H_MSG_TYPE_RX_IND:
- ath10k_htt_rx_proc_rx_ind(htt, &resp->rx_ind);
+ if (ar->dev_type == ATH10K_DEV_TYPE_HL)
+ return ath10k_htt_rx_proc_rx_ind_hl(htt,
+ &resp->rx_ind_hl,
+ skb);
+ else
+ ath10k_htt_rx_proc_rx_ind_ll(htt, &resp->rx_ind);
break;
case HTT_T2H_MSG_TYPE_PEER_MAP: {
struct htt_peer_map_event ev = {
@@ -2986,11 +3235,16 @@ static const struct ath10k_htt_rx_ops htt_rx_ops_64 = {
.htt_reset_paddrs_ring = ath10k_htt_reset_paddrs_ring_64,
};
+static const struct ath10k_htt_rx_ops htt_rx_ops_hl = {
+};
+
void ath10k_htt_set_rx_ops(struct ath10k_htt *htt)
{
struct ath10k *ar = htt->ar;
- if (ar->hw_params.target_64bit)
+ if (ar->dev_type == ATH10K_DEV_TYPE_HL)
+ htt->rx_ops = &htt_rx_ops_hl;
+ else if (ar->hw_params.target_64bit)
htt->rx_ops = &htt_rx_ops_64;
else
htt->rx_ops = &htt_rx_ops_32;
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 7cff0d52338f..ad05ab714c9b 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -495,6 +495,9 @@ int ath10k_htt_tx_start(struct ath10k_htt *htt)
if (htt->tx_mem_allocated)
return 0;
+ if (ar->dev_type == ATH10K_DEV_TYPE_HL)
+ return 0;
+
ret = ath10k_htt_tx_alloc_buf(htt);
if (ret)
goto free_idr_pending_tx;
@@ -934,6 +937,57 @@ static int ath10k_htt_send_rx_ring_cfg_64(struct ath10k_htt *htt)
return 0;
}
+static int ath10k_htt_send_rx_ring_cfg_hl(struct ath10k_htt *htt)
+{
+ struct ath10k *ar = htt->ar;
+ struct sk_buff *skb;
+ struct htt_cmd *cmd;
+ struct htt_rx_ring_setup_ring32 *ring;
+ const int num_rx_ring = 1;
+ u16 flags;
+ int len;
+ int ret;
+
+ /*
+ * the HW expects the buffer to be an integral number of 4-byte
+ * "words"
+ */
+ BUILD_BUG_ON(!IS_ALIGNED(HTT_RX_BUF_SIZE, 4));
+ BUILD_BUG_ON((HTT_RX_BUF_SIZE & HTT_MAX_CACHE_LINE_SIZE_MASK) != 0);
+
+ len = sizeof(cmd->hdr) + sizeof(cmd->rx_setup_32.hdr)
+ + (sizeof(*ring) * num_rx_ring);
+ skb = ath10k_htc_alloc_skb(ar, len);
+ if (!skb)
+ return -ENOMEM;
+
+ skb_put(skb, len);
+
+ cmd = (struct htt_cmd *)skb->data;
+ ring = &cmd->rx_setup_32.rings[0];
+
+ cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_RX_RING_CFG;
+ cmd->rx_setup_32.hdr.num_rings = 1;
+
+ flags = 0;
+ flags |= HTT_RX_RING_FLAGS_MSDU_PAYLOAD;
+ flags |= HTT_RX_RING_FLAGS_UNICAST_RX;
+ flags |= HTT_RX_RING_FLAGS_MULTICAST_RX;
+
+ memset(ring, 0, sizeof(*ring));
+ ring->rx_ring_len = __cpu_to_le16(HTT_RX_RING_SIZE_MIN);
+ ring->rx_ring_bufsize = __cpu_to_le16(HTT_RX_BUF_SIZE);
+ ring->flags = __cpu_to_le16(flags);
+
+ ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb);
+ if (ret) {
+ dev_kfree_skb_any(skb);
+ return ret;
+ }
+
+ return 0;
+}
+
int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
u8 max_subfrms_ampdu,
u8 max_subfrms_amsdu)
@@ -1123,7 +1177,8 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
return 0;
err_unmap_msdu:
- dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
+ if (ar->dev_type != ATH10K_DEV_TYPE_HL)
+ dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
err_free_txdesc:
dev_kfree_skb_any(txdesc);
err_free_msdu_id:
@@ -1134,6 +1189,94 @@ err:
return res;
}
+#define HTT_TX_HL_NEEDED_HEADROOM \
+ (unsigned int)(sizeof(struct htt_cmd_hdr) + \
+ sizeof(struct htt_data_tx_desc) + \
+ sizeof(struct ath10k_htc_hdr))
+
+static int ath10k_htt_tx_hl(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode,
+ struct sk_buff *msdu)
+{
+ struct ath10k *ar = htt->ar;
+ int res, data_len;
+ struct htt_cmd_hdr *cmd_hdr;
+ struct htt_data_tx_desc *tx_desc;
+ struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
+ struct sk_buff *tmp_skb;
+ bool is_eth = (txmode == ATH10K_HW_TXRX_ETHERNET);
+ u8 vdev_id = ath10k_htt_tx_get_vdev_id(ar, msdu);
+ u8 tid = ath10k_htt_tx_get_tid(msdu, is_eth);
+ u8 flags0 = 0;
+ u16 flags1 = 0;
+
+ data_len = msdu->len;
+
+ switch (txmode) {
+ case ATH10K_HW_TXRX_RAW:
+ case ATH10K_HW_TXRX_NATIVE_WIFI:
+ flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT;
+ /* fall through */
+ case ATH10K_HW_TXRX_ETHERNET:
+ flags0 |= SM(txmode, HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
+ break;
+ case ATH10K_HW_TXRX_MGMT:
+ flags0 |= SM(ATH10K_HW_TXRX_MGMT,
+ HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
+ flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT;
+ break;
+ }
+
+ if (skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT)
+ flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT;
+
+ flags1 |= SM((u16)vdev_id, HTT_DATA_TX_DESC_FLAGS1_VDEV_ID);
+ flags1 |= SM((u16)tid, HTT_DATA_TX_DESC_FLAGS1_EXT_TID);
+ if (msdu->ip_summed == CHECKSUM_PARTIAL &&
+ !test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
+ flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD;
+ flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD;
+ }
+
+ /* Prepend the HTT header and TX desc struct to the data message
+ * and realloc the skb if it does not have enough headroom.
+ */
+ if (skb_headroom(msdu) < HTT_TX_HL_NEEDED_HEADROOM) {
+ tmp_skb = msdu;
+
+ ath10k_dbg(htt->ar, ATH10K_DBG_HTT,
+ "Not enough headroom in skb. Current headroom: %u, needed: %u. Reallocating...\n",
+ skb_headroom(msdu), HTT_TX_HL_NEEDED_HEADROOM);
+ msdu = skb_realloc_headroom(msdu, HTT_TX_HL_NEEDED_HEADROOM);
+ kfree_skb(tmp_skb);
+ if (!msdu) {
+ ath10k_warn(htt->ar, "htt hl tx: Unable to realloc skb!\n");
+ res = -ENOMEM;
+ goto out;
+ }
+ }
+
+ skb_push(msdu, sizeof(*cmd_hdr));
+ skb_push(msdu, sizeof(*tx_desc));
+ cmd_hdr = (struct htt_cmd_hdr *)msdu->data;
+ tx_desc = (struct htt_data_tx_desc *)(msdu->data + sizeof(*cmd_hdr));
+
+ cmd_hdr->msg_type = HTT_H2T_MSG_TYPE_TX_FRM;
+ tx_desc->flags0 = flags0;
+ tx_desc->flags1 = __cpu_to_le16(flags1);
+ tx_desc->len = __cpu_to_le16(data_len);
+ tx_desc->id = 0;
+ tx_desc->frags_paddr = 0; /* always zero */
+ /* Initialize peer_id to INVALID_PEER because this is NOT
+ * Reinjection path
+ */
+ tx_desc->peerid = __cpu_to_le32(HTT_INVALID_PEERID);
+
+ res = ath10k_htc_send(&htt->ar->htc, htt->eid, msdu);
+
+out:
+ return res;
+}
+
static int ath10k_htt_tx_32(struct ath10k_htt *htt,
enum ath10k_hw_txrx_mode txmode,
struct sk_buff *msdu)
@@ -1561,11 +1704,19 @@ static const struct ath10k_htt_tx_ops htt_tx_ops_64 = {
.htt_free_txbuff = ath10k_htt_tx_free_cont_txbuf_64,
};
+static const struct ath10k_htt_tx_ops htt_tx_ops_hl = {
+ .htt_send_rx_ring_cfg = ath10k_htt_send_rx_ring_cfg_hl,
+ .htt_send_frag_desc_bank_cfg = ath10k_htt_send_frag_desc_bank_cfg_32,
+ .htt_tx = ath10k_htt_tx_hl,
+};
+
void ath10k_htt_set_tx_ops(struct ath10k_htt *htt)
{
struct ath10k *ar = htt->ar;
- if (ar->hw_params.target_64bit)
+ if (ar->dev_type == ATH10K_DEV_TYPE_HL)
+ htt->tx_ops = &htt_tx_ops_hl;
+ else if (ar->hw_params.target_64bit)
htt->tx_ops = &htt_tx_ops_64;
else
htt->tx_ops = &htt_tx_ops_32;
diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c
index 677535b3d207..af8ae8117c62 100644
--- a/drivers/net/wireless/ath/ath10k/hw.c
+++ b/drivers/net/wireless/ath/ath10k/hw.c
@@ -16,6 +16,7 @@
#include <linux/types.h>
#include <linux/bitops.h>
+#include <linux/bitfield.h>
#include "core.h"
#include "hw.h"
#include "hif.h"
@@ -918,6 +919,196 @@ static int ath10k_hw_qca6174_enable_pll_clock(struct ath10k *ar)
return 0;
}
+/* Program CPU_ADDR_MSB to allow different memory
+ * region access.
+ */
+static void ath10k_hw_map_target_mem(struct ath10k *ar, u32 msb)
+{
+ u32 address = SOC_CORE_BASE_ADDRESS + FW_RAM_CONFIG_ADDRESS;
+
+ ath10k_hif_write32(ar, address, msb);
+}
+
+/* 1. Write to memory region of target, such as IRAM adn DRAM.
+ * 2. Target address( 0 ~ 00100000 & 0x00400000~0x00500000)
+ * can be written directly. See ath10k_pci_targ_cpu_to_ce_addr() too.
+ * 3. In order to access the region other than the above,
+ * we need to set the value of register CPU_ADDR_MSB.
+ * 4. Target memory access space is limited to 1M size. If the size is larger
+ * than 1M, need to split it and program CPU_ADDR_MSB accordingly.
+ */
+static int ath10k_hw_diag_segment_msb_download(struct ath10k *ar,
+ const void *buffer,
+ u32 address,
+ u32 length)
+{
+ u32 addr = address & REGION_ACCESS_SIZE_MASK;
+ int ret, remain_size, size;
+ const u8 *buf;
+
+ ath10k_hw_map_target_mem(ar, CPU_ADDR_MSB_REGION_VAL(address));
+
+ if (addr + length > REGION_ACCESS_SIZE_LIMIT) {
+ size = REGION_ACCESS_SIZE_LIMIT - addr;
+ remain_size = length - size;
+
+ ret = ath10k_hif_diag_write(ar, address, buffer, size);
+ if (ret) {
+ ath10k_warn(ar,
+ "failed to download the first %d bytes segment to address:0x%x: %d\n",
+ size, address, ret);
+ goto done;
+ }
+
+ /* Change msb to the next memory region*/
+ ath10k_hw_map_target_mem(ar,
+ CPU_ADDR_MSB_REGION_VAL(address) + 1);
+ buf = buffer + size;
+ ret = ath10k_hif_diag_write(ar,
+ address & ~REGION_ACCESS_SIZE_MASK,
+ buf, remain_size);
+ if (ret) {
+ ath10k_warn(ar,
+ "failed to download the second %d bytes segment to address:0x%x: %d\n",
+ remain_size,
+ address & ~REGION_ACCESS_SIZE_MASK,
+ ret);
+ goto done;
+ }
+ } else {
+ ret = ath10k_hif_diag_write(ar, address, buffer, length);
+ if (ret) {
+ ath10k_warn(ar,
+ "failed to download the only %d bytes segment to address:0x%x: %d\n",
+ length, address, ret);
+ goto done;
+ }
+ }
+
+done:
+ /* Change msb to DRAM */
+ ath10k_hw_map_target_mem(ar,
+ CPU_ADDR_MSB_REGION_VAL(DRAM_BASE_ADDRESS));
+ return ret;
+}
+
+static int ath10k_hw_diag_segment_download(struct ath10k *ar,
+ const void *buffer,
+ u32 address,
+ u32 length)
+{
+ if (address >= DRAM_BASE_ADDRESS + REGION_ACCESS_SIZE_LIMIT)
+ /* Needs to change MSB for memory write */
+ return ath10k_hw_diag_segment_msb_download(ar, buffer,
+ address, length);
+ else
+ return ath10k_hif_diag_write(ar, address, buffer, length);
+}
+
+int ath10k_hw_diag_fast_download(struct ath10k *ar,
+ u32 address,
+ const void *buffer,
+ u32 length)
+{
+ const u8 *buf = buffer;
+ bool sgmt_end = false;
+ u32 base_addr = 0;
+ u32 base_len = 0;
+ u32 left = 0;
+ struct bmi_segmented_file_header *hdr;
+ struct bmi_segmented_metadata *metadata;
+ int ret = 0;
+
+ if (length < sizeof(*hdr))
+ return -EINVAL;
+
+ /* check firmware header. If it has no correct magic number
+ * or it's compressed, returns error.
+ */
+ hdr = (struct bmi_segmented_file_header *)buf;
+ if (__le32_to_cpu(hdr->magic_num) != BMI_SGMTFILE_MAGIC_NUM) {
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "Not a supported firmware, magic_num:0x%x\n",
+ hdr->magic_num);
+ return -EINVAL;
+ }
+
+ if (hdr->file_flags != 0) {
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "Not a supported firmware, file_flags:0x%x\n",
+ hdr->file_flags);
+ return -EINVAL;
+ }
+
+ metadata = (struct bmi_segmented_metadata *)hdr->data;
+ left = length - sizeof(*hdr);
+
+ while (left > 0) {
+ if (left < sizeof(*metadata)) {
+ ath10k_warn(ar, "firmware segment is truncated: %d\n",
+ left);
+ ret = -EINVAL;
+ break;
+ }
+ base_addr = __le32_to_cpu(metadata->addr);
+ base_len = __le32_to_cpu(metadata->length);
+ buf = metadata->data;
+ left -= sizeof(*metadata);
+
+ switch (base_len) {
+ case BMI_SGMTFILE_BEGINADDR:
+ /* base_addr is the start address to run */
+ ret = ath10k_bmi_set_start(ar, base_addr);
+ base_len = 0;
+ break;
+ case BMI_SGMTFILE_DONE:
+ /* no more segment */
+ base_len = 0;
+ sgmt_end = true;
+ ret = 0;
+ break;
+ case BMI_SGMTFILE_BDDATA:
+ case BMI_SGMTFILE_EXEC:
+ ath10k_warn(ar,
+ "firmware has unsupported segment:%d\n",
+ base_len);
+ ret = -EINVAL;
+ break;
+ default:
+ if (base_len > left) {
+ /* sanity check */
+ ath10k_warn(ar,
+ "firmware has invalid segment length, %d > %d\n",
+ base_len, left);
+ ret = -EINVAL;
+ break;
+ }
+
+ ret = ath10k_hw_diag_segment_download(ar,
+ buf,
+ base_addr,
+ base_len);
+
+ if (ret)
+ ath10k_warn(ar,
+ "failed to download firmware via diag interface:%d\n",
+ ret);
+ break;
+ }
+
+ if (ret || sgmt_end)
+ break;
+
+ metadata = (struct bmi_segmented_metadata *)(buf + base_len);
+ left -= base_len;
+ }
+
+ if (ret == 0)
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "boot firmware fast diag download successfully.\n");
+ return ret;
+}
+
const struct ath10k_hw_ops qca988x_ops = {
.set_coverage_class = ath10k_hw_qca988x_set_coverage_class,
};
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index fac58c3c576a..1b5da272d18c 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -21,6 +21,14 @@
#include "targaddrs.h"
+enum ath10k_bus {
+ ATH10K_BUS_PCI,
+ ATH10K_BUS_AHB,
+ ATH10K_BUS_SDIO,
+ ATH10K_BUS_USB,
+ ATH10K_BUS_SNOC,
+};
+
#define ATH10K_FW_DIR "ath10k"
#define QCA988X_2_0_DEVICE_ID_UBNT (0x11ac)
@@ -109,6 +117,7 @@ enum qca9377_chip_id_rev {
#define QCA9984_HW_1_0_CHIP_ID_REV 0x0
#define QCA9984_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA9984/hw1.0"
#define QCA9984_HW_1_0_BOARD_DATA_FILE "board.bin"
+#define QCA9984_HW_1_0_EBOARD_DATA_FILE "eboard.bin"
#define QCA9984_HW_1_0_PATCH_LOAD_ADDR 0x1234
/* QCA9888 2.0 defines */
@@ -221,6 +230,7 @@ enum ath10k_fw_htt_op_version {
enum ath10k_bd_ie_type {
/* contains sub IEs of enum ath10k_bd_ie_board_type */
ATH10K_BD_IE_BOARD = 0,
+ ATH10K_BD_IE_BOARD_EXT = 1,
};
enum ath10k_bd_ie_board_type {
@@ -389,6 +399,11 @@ extern const struct ath10k_hw_ce_regs qcax_ce_regs;
void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev);
+int ath10k_hw_diag_fast_download(struct ath10k *ar,
+ u32 address,
+ const void *buffer,
+ u32 length);
+
#define QCA_REV_988X(ar) ((ar)->hw_rev == ATH10K_HW_QCA988X)
#define QCA_REV_9887(ar) ((ar)->hw_rev == ATH10K_HW_QCA9887)
#define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174)
@@ -501,6 +516,7 @@ struct ath10k_hw_clk_params {
struct ath10k_hw_params {
u32 id;
u16 dev_id;
+ enum ath10k_bus bus;
const char *name;
u32 patch_load_addr;
int uart_pin;
@@ -539,6 +555,8 @@ struct ath10k_hw_params {
const char *dir;
const char *board;
size_t board_size;
+ const char *eboard;
+ size_t ext_board_size;
size_t board_ext_size;
} fw;
@@ -594,6 +612,9 @@ struct ath10k_hw_params {
* to avoid it sending spurious acks.
*/
bool hw_filter_reset_required;
+
+ /* target supporting fw download via diag ce */
+ bool fw_diag_ce_download;
};
struct htt_rx_desc;
@@ -1129,4 +1150,15 @@ ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw,
#define RTC_SYNC_STATUS_PLL_CHANGING_MASK 0x00000020
/* qca6174 PLL offset/mask end */
+/* CPU_ADDR_MSB is a register, bit[3:0] is to specify which memory
+ * region is accessed. The memory region size is 1M.
+ * If host wants to access 0xX12345 at target, then CPU_ADDR_MSB[3:0]
+ * is 0xX.
+ * The following MACROs are defined to get the 0xX and the size limit.
+ */
+#define CPU_ADDR_MSB_REGION_MASK GENMASK(23, 20)
+#define CPU_ADDR_MSB_REGION_VAL(X) FIELD_GET(CPU_ADDR_MSB_REGION_MASK, X)
+#define REGION_ACCESS_SIZE_LIMIT 0x100000
+#define REGION_ACCESS_SIZE_MASK (REGION_ACCESS_SIZE_LIMIT - 1)
+
#endif /* _HW_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 496772d95d11..3933dd96da55 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -30,7 +30,6 @@
#include "htt.h"
#include "txrx.h"
#include "testmode.h"
-#include "wmi.h"
#include "wmi-tlv.h"
#include "wmi-ops.h"
#include "wow.h"
@@ -157,6 +156,22 @@ u8 ath10k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
return 0;
}
+static int ath10k_mac_get_rate_hw_value(int bitrate)
+{
+ int i;
+ u8 hw_value_prefix = 0;
+
+ if (ath10k_mac_bitrate_is_cck(bitrate))
+ hw_value_prefix = WMI_RATE_PREAMBLE_CCK << 6;
+
+ for (i = 0; i < sizeof(ath10k_rates); i++) {
+ if (ath10k_rates[i].bitrate == bitrate)
+ return hw_value_prefix | ath10k_rates[i].hw_value;
+ }
+
+ return -EINVAL;
+}
+
static int ath10k_mac_get_max_vht_mcs_map(u16 mcs_map, int nss)
{
switch ((mcs_map >> (2 * nss)) & 0x3) {
@@ -968,7 +983,7 @@ static inline int ath10k_vdev_setup_sync(struct ath10k *ar)
if (time_left == 0)
return -ETIMEDOUT;
- return 0;
+ return ar->last_wmi_vdev_start_status;
}
static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
@@ -5452,9 +5467,10 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
struct cfg80211_chan_def def;
u32 vdev_param, pdev_param, slottime, preamble;
u16 bitrate, hw_value;
- u8 rate;
- int rateidx, ret = 0;
+ u8 rate, basic_rate_idx;
+ int rateidx, ret = 0, hw_rate_code;
enum nl80211_band band;
+ const struct ieee80211_supported_band *sband;
mutex_lock(&ar->conf_mutex);
@@ -5660,6 +5676,30 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
arvif->vdev_id, ret);
}
+ if (changed & BSS_CHANGED_BASIC_RATES) {
+ if (WARN_ON(ath10k_mac_vif_chan(vif, &def))) {
+ mutex_unlock(&ar->conf_mutex);
+ return;
+ }
+
+ sband = ar->hw->wiphy->bands[def.chan->band];
+ basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1;
+ bitrate = sband->bitrates[basic_rate_idx].bitrate;
+
+ hw_rate_code = ath10k_mac_get_rate_hw_value(bitrate);
+ if (hw_rate_code < 0) {
+ ath10k_warn(ar, "bitrate not supported %d\n", bitrate);
+ mutex_unlock(&ar->conf_mutex);
+ return;
+ }
+
+ vdev_param = ar->wmi.vdev_param->mgmt_rate;
+ ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
+ hw_rate_code);
+ if (ret)
+ ath10k_warn(ar, "failed to set mgmt tx rate %d\n", ret);
+ }
+
mutex_unlock(&ar->conf_mutex);
}
@@ -6216,6 +6256,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
new_state == IEEE80211_STA_NONE) {
memset(arsta, 0, sizeof(*arsta));
arsta->arvif = arvif;
+ arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED;
INIT_WORK(&arsta->update_wk, ath10k_sta_rc_update_wk);
for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
@@ -6244,6 +6285,13 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
ar->num_stations + 1, ar->max_num_stations,
ar->num_peers + 1, ar->max_num_peers);
+ if (ath10k_debug_is_extd_tx_stats_enabled(ar)) {
+ arsta->tx_stats = kzalloc(sizeof(*arsta->tx_stats),
+ GFP_KERNEL);
+ if (!arsta->tx_stats)
+ goto exit;
+ }
+
num_tdls_stations = ath10k_mac_tdls_vif_stations_count(hw, vif);
num_tdls_vifs = ath10k_mac_tdls_vifs_count(hw);
@@ -6329,6 +6377,9 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
"mac vdev %d peer delete %pM sta %pK (sta gone)\n",
arvif->vdev_id, sta->addr, sta);
+ if (ath10k_debug_is_extd_tx_stats_enabled(ar))
+ kfree(arsta->tx_stats);
+
if (sta->tdls) {
ret = ath10k_mac_tdls_peer_update(ar, arvif->vdev_id,
sta,
@@ -6769,23 +6820,17 @@ static int ath10k_mac_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
return -EOPNOTSUPP;
}
-static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- u32 queues, bool drop)
+void ath10k_mac_wait_tx_complete(struct ath10k *ar)
{
- struct ath10k *ar = hw->priv;
bool skip;
long time_left;
/* mac80211 doesn't care if we really xmit queued frames or not
* we'll collect those frames either way if we stop/delete vdevs
*/
- if (drop)
- return;
-
- mutex_lock(&ar->conf_mutex);
if (ar->state == ATH10K_STATE_WEDGED)
- goto skip;
+ return;
time_left = wait_event_timeout(ar->htt.empty_tx_wq, ({
bool empty;
@@ -6804,8 +6849,18 @@ static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
if (time_left == 0 || skip)
ath10k_warn(ar, "failed to flush transmit queue (skip %i ar-state %i): %ld\n",
skip, ar->state, time_left);
+}
-skip:
+static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ u32 queues, bool drop)
+{
+ struct ath10k *ar = hw->priv;
+
+ if (drop)
+ return;
+
+ mutex_lock(&ar->conf_mutex);
+ ath10k_mac_wait_tx_complete(ar);
mutex_unlock(&ar->conf_mutex);
}
@@ -8149,6 +8204,24 @@ static const struct ieee80211_iface_combination ath10k_10_4_if_comb[] = {
},
};
+static const struct
+ieee80211_iface_combination ath10k_10_4_bcn_int_if_comb[] = {
+ {
+ .limits = ath10k_10_4_if_limits,
+ .n_limits = ARRAY_SIZE(ath10k_10_4_if_limits),
+ .max_interfaces = 16,
+ .num_different_channels = 1,
+ .beacon_int_infra_match = true,
+ .beacon_int_min_gcd = 100,
+#ifdef CONFIG_ATH10K_DFS_CERTIFIED
+ .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
+ BIT(NL80211_CHAN_WIDTH_20) |
+ BIT(NL80211_CHAN_WIDTH_40) |
+ BIT(NL80211_CHAN_WIDTH_80),
+#endif
+ },
+};
+
static void ath10k_get_arvif_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
@@ -8311,6 +8384,10 @@ int ath10k_mac_register(struct ath10k *ar)
void *channels;
int ret;
+ if (!is_valid_ether_addr(ar->mac_addr)) {
+ ath10k_warn(ar, "invalid MAC address; choosing random\n");
+ eth_random_addr(ar->mac_addr);
+ }
SET_IEEE80211_PERM_ADDR(ar->hw, ar->mac_addr);
SET_IEEE80211_DEV(ar->hw, ar->dev);
@@ -8465,6 +8542,10 @@ int ath10k_mac_register(struct ath10k *ar)
wiphy_ext_feature_set(ar->hw->wiphy,
NL80211_EXT_FEATURE_SET_SCAN_DWELL);
+ if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT);
+
/*
* on LL hardware queues are managed entirely by the FW
* so we only advertise to mac we can do the queues thing
@@ -8508,6 +8589,13 @@ int ath10k_mac_register(struct ath10k *ar)
ar->hw->wiphy->iface_combinations = ath10k_10_4_if_comb;
ar->hw->wiphy->n_iface_combinations =
ARRAY_SIZE(ath10k_10_4_if_comb);
+ if (test_bit(WMI_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT,
+ ar->wmi.svc_map)) {
+ ar->hw->wiphy->iface_combinations =
+ ath10k_10_4_bcn_int_if_comb;
+ ar->hw->wiphy->n_iface_combinations =
+ ARRAY_SIZE(ath10k_10_4_bcn_int_if_comb);
+ }
break;
case ATH10K_FW_WMI_OP_VERSION_UNSET:
case ATH10K_FW_WMI_OP_VERSION_MAX:
diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h
index 81f8d6c0af35..570493d2d648 100644
--- a/drivers/net/wireless/ath/ath10k/mac.h
+++ b/drivers/net/wireless/ath/ath10k/mac.h
@@ -82,6 +82,7 @@ struct ieee80211_txq *ath10k_mac_txq_lookup(struct ath10k *ar,
u16 peer_id,
u8 tid);
int ath10k_mac_ext_resource_config(struct ath10k *ar, u32 val);
+void ath10k_mac_wait_tx_complete(struct ath10k *ar);
static inline void ath10k_tx_h_seq_no(struct ieee80211_vif *vif,
struct sk_buff *skb)
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 97fa5c74f2fe..873dbb65439f 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -192,7 +192,7 @@ static struct ce_attr host_ce_config_wlan[] = {
/* CE7: ce_diag, the Diagnostic Window */
{
- .flags = CE_ATTR_FLAGS,
+ .flags = CE_ATTR_FLAGS | CE_ATTR_POLL,
.src_nentries = 2,
.src_sz_max = DIAG_TRANSFER_LIMIT,
.dest_nentries = 2,
@@ -870,6 +870,21 @@ static u32 ath10k_pci_qca988x_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)
return val;
}
+/* Refactor from ath10k_pci_qca988x_targ_cpu_to_ce_addr.
+ * Support to access target space below 1M for qca6174 and qca9377.
+ * If target space is below 1M, the bit[20] of converted CE addr is 0.
+ * Otherwise bit[20] of converted CE addr is 1.
+ */
+static u32 ath10k_pci_qca6174_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)
+{
+ u32 val = 0, region = addr & 0xfffff;
+
+ val = (ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS)
+ & 0x7ff) << 21;
+ val |= ((addr >= 0x100000) ? 0x100000 : 0) | region;
+ return val;
+}
+
static u32 ath10k_pci_qca99x0_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)
{
u32 val = 0, region = addr & 0xfffff;
@@ -931,6 +946,15 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
goto done;
}
+ /* The address supplied by the caller is in the
+ * Target CPU virtual address space.
+ *
+ * In order to use this address with the diagnostic CE,
+ * convert it from Target CPU virtual address space
+ * to CE address space
+ */
+ address = ath10k_pci_targ_cpu_to_ce_addr(ar, address);
+
remaining_bytes = nbytes;
ce_data = ce_data_base;
while (remaining_bytes) {
@@ -942,16 +966,6 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
goto done;
/* Request CE to send from Target(!) address to Host buffer */
- /*
- * The address supplied by the caller is in the
- * Target CPU virtual address space.
- *
- * In order to use this address with the diagnostic CE,
- * convert it from Target CPU virtual address space
- * to CE address space
- */
- address = ath10k_pci_targ_cpu_to_ce_addr(ar, address);
-
ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)address, nbytes, 0,
0);
if (ret)
@@ -960,8 +974,10 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
i = 0;
while (ath10k_ce_completed_send_next_nolock(ce_diag,
NULL) != 0) {
- mdelay(1);
- if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
+ udelay(DIAG_ACCESS_CE_WAIT_US);
+ i += DIAG_ACCESS_CE_WAIT_US;
+
+ if (i > DIAG_ACCESS_CE_TIMEOUT_US) {
ret = -EBUSY;
goto done;
}
@@ -972,9 +988,10 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
(void **)&buf,
&completed_nbytes)
!= 0) {
- mdelay(1);
+ udelay(DIAG_ACCESS_CE_WAIT_US);
+ i += DIAG_ACCESS_CE_WAIT_US;
- if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
+ if (i > DIAG_ACCESS_CE_TIMEOUT_US) {
ret = -EBUSY;
goto done;
}
@@ -1119,9 +1136,10 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
i = 0;
while (ath10k_ce_completed_send_next_nolock(ce_diag,
NULL) != 0) {
- mdelay(1);
+ udelay(DIAG_ACCESS_CE_WAIT_US);
+ i += DIAG_ACCESS_CE_WAIT_US;
- if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
+ if (i > DIAG_ACCESS_CE_TIMEOUT_US) {
ret = -EBUSY;
goto done;
}
@@ -1132,9 +1150,10 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
(void **)&buf,
&completed_nbytes)
!= 0) {
- mdelay(1);
+ udelay(DIAG_ACCESS_CE_WAIT_US);
+ i += DIAG_ACCESS_CE_WAIT_US;
- if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
+ if (i > DIAG_ACCESS_CE_TIMEOUT_US) {
ret = -EBUSY;
goto done;
}
@@ -1839,7 +1858,7 @@ int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id,
}
}
- if (WARN_ON(!ul_set || !dl_set))
+ if (!ul_set || !dl_set)
return -ENOENT;
return 0;
@@ -3482,7 +3501,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
struct ath10k *ar;
struct ath10k_pci *ar_pci;
enum ath10k_hw_rev hw_rev;
- u32 chip_id;
+ struct ath10k_bus_params bus_params;
bool pci_ps;
int (*pci_soft_reset)(struct ath10k *ar);
int (*pci_hard_reset)(struct ath10k *ar);
@@ -3510,7 +3529,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
pci_ps = true;
pci_soft_reset = ath10k_pci_warm_reset;
pci_hard_reset = ath10k_pci_qca6174_chip_reset;
- targ_cpu_to_ce_addr = ath10k_pci_qca988x_targ_cpu_to_ce_addr;
+ targ_cpu_to_ce_addr = ath10k_pci_qca6174_targ_cpu_to_ce_addr;
break;
case QCA99X0_2_0_DEVICE_ID:
hw_rev = ATH10K_HW_QCA99X0;
@@ -3538,7 +3557,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
pci_ps = true;
pci_soft_reset = NULL;
pci_hard_reset = ath10k_pci_qca6174_chip_reset;
- targ_cpu_to_ce_addr = ath10k_pci_qca988x_targ_cpu_to_ce_addr;
+ targ_cpu_to_ce_addr = ath10k_pci_qca6174_targ_cpu_to_ce_addr;
break;
default:
WARN_ON(1);
@@ -3618,19 +3637,20 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
goto err_free_irq;
}
- chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
- if (chip_id == 0xffffffff) {
+ bus_params.dev_type = ATH10K_DEV_TYPE_LL;
+ bus_params.chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
+ if (bus_params.chip_id == 0xffffffff) {
ath10k_err(ar, "failed to get chip id\n");
goto err_free_irq;
}
- if (!ath10k_pci_chip_is_supported(pdev->device, chip_id)) {
+ if (!ath10k_pci_chip_is_supported(pdev->device, bus_params.chip_id)) {
ath10k_err(ar, "device %04x with chip_id %08x isn't supported\n",
- pdev->device, chip_id);
+ pdev->device, bus_params.chip_id);
goto err_free_irq;
}
- ret = ath10k_core_register(ar, chip_id);
+ ret = ath10k_core_register(ar, &bus_params);
if (ret) {
ath10k_err(ar, "failed to register driver core: %d\n", ret);
goto err_free_irq;
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h
index 0ed436657108..e8d86331c539 100644
--- a/drivers/net/wireless/ath/ath10k/pci.h
+++ b/drivers/net/wireless/ath/ath10k/pci.h
@@ -207,7 +207,8 @@ static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar)
#define CDC_WAR_DATA_CE 4
/* Wait up to this many Ms for a Diagnostic Access CE operation to complete */
-#define DIAG_ACCESS_CE_TIMEOUT_MS 10
+#define DIAG_ACCESS_CE_TIMEOUT_US 10000 /* 10 ms */
+#define DIAG_ACCESS_CE_WAIT_US 50
void ath10k_pci_write32(struct ath10k *ar, u32 offset, u32 value);
void ath10k_pci_soc_write32(struct ath10k *ar, u32 addr, u32 val);
diff --git a/drivers/net/wireless/ath/ath10k/rx_desc.h b/drivers/net/wireless/ath/ath10k/rx_desc.h
index ea4075d456fa..310674de3cb8 100644
--- a/drivers/net/wireless/ath/ath10k/rx_desc.h
+++ b/drivers/net/wireless/ath/ath10k/rx_desc.h
@@ -1277,4 +1277,19 @@ struct fw_rx_desc_base {
u8 info0;
} __packed;
+#define FW_RX_DESC_FLAGS_FIRST_MSDU (1 << 0)
+#define FW_RX_DESC_FLAGS_LAST_MSDU (1 << 1)
+#define FW_RX_DESC_C3_FAILED (1 << 2)
+#define FW_RX_DESC_C4_FAILED (1 << 3)
+#define FW_RX_DESC_IPV6 (1 << 4)
+#define FW_RX_DESC_TCP (1 << 5)
+#define FW_RX_DESC_UDP (1 << 6)
+
+struct fw_rx_desc_hl {
+ u8 info0;
+ u8 version;
+ u8 len;
+ u8 flags;
+} __packed;
+
#endif /* _RX_DESC_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
index 7f61591ce0de..983ecfef1d28 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -1941,7 +1941,8 @@ static int ath10k_sdio_probe(struct sdio_func *func,
struct ath10k_sdio *ar_sdio;
struct ath10k *ar;
enum ath10k_hw_rev hw_rev;
- u32 chip_id, dev_id_base;
+ u32 dev_id_base;
+ struct ath10k_bus_params bus_params;
int ret, i;
/* Assumption: All SDIO based chipsets (so far) are QCA6174 based.
@@ -2035,9 +2036,10 @@ static int ath10k_sdio_probe(struct sdio_func *func,
goto err_free_wq;
}
+ bus_params.dev_type = ATH10K_DEV_TYPE_HL;
/* TODO: don't know yet how to get chip_id with SDIO */
- chip_id = 0;
- ret = ath10k_core_register(ar, chip_id);
+ bus_params.chip_id = 0;
+ ret = ath10k_core_register(ar, &bus_params);
if (ret) {
ath10k_err(ar, "failed to register driver core: %d\n", ret);
goto err_free_wq;
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index fa1843a7e0fd..f7b5b855aab2 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -62,6 +62,7 @@ static void ath10k_snoc_htt_tx_cb(struct ath10k_ce_pipe *ce_state);
static void ath10k_snoc_htc_rx_cb(struct ath10k_ce_pipe *ce_state);
static void ath10k_snoc_htt_rx_cb(struct ath10k_ce_pipe *ce_state);
static void ath10k_snoc_htt_htc_rx_cb(struct ath10k_ce_pipe *ce_state);
+static void ath10k_snoc_pktlog_rx_cb(struct ath10k_ce_pipe *ce_state);
static const struct ath10k_snoc_drv_priv drv_priv = {
.hw_rev = ATH10K_HW_WCN3990,
@@ -171,7 +172,7 @@ static struct ce_attr host_ce_config_wlan[] = {
.src_nentries = 0,
.src_sz_max = 2048,
.dest_nentries = 512,
- .recv_cb = ath10k_snoc_htt_htc_rx_cb,
+ .recv_cb = ath10k_snoc_pktlog_rx_cb,
},
};
@@ -436,6 +437,14 @@ static void ath10k_snoc_htt_htc_rx_cb(struct ath10k_ce_pipe *ce_state)
ath10k_snoc_process_rx_cb(ce_state, ath10k_htc_rx_completion_handler);
}
+/* Called by lower (CE) layer when data is received from the Target.
+ * WCN3990 firmware uses separate CE(CE11) to transfer pktlog data.
+ */
+static void ath10k_snoc_pktlog_rx_cb(struct ath10k_ce_pipe *ce_state)
+{
+ ath10k_snoc_process_rx_cb(ce_state, ath10k_htc_rx_completion_handler);
+}
+
static void ath10k_snoc_htt_rx_deliver(struct ath10k *ar, struct sk_buff *skb)
{
skb_pull(skb, sizeof(struct ath10k_htc_hdr));
@@ -616,7 +625,7 @@ static int ath10k_snoc_hif_map_service_to_pipe(struct ath10k *ar,
}
}
- if (WARN_ON(!ul_set || !dl_set))
+ if (!ul_set || !dl_set)
return -ENOENT;
return 0;
@@ -722,14 +731,15 @@ static void ath10k_snoc_buffer_cleanup(struct ath10k *ar)
static void ath10k_snoc_hif_stop(struct ath10k *ar)
{
ath10k_snoc_irq_disable(ar);
- ath10k_snoc_buffer_cleanup(ar);
napi_synchronize(&ar->napi);
napi_disable(&ar->napi);
+ ath10k_snoc_buffer_cleanup(ar);
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif stop\n");
}
static int ath10k_snoc_hif_start(struct ath10k *ar)
{
+ napi_enable(&ar->napi);
ath10k_snoc_irq_enable(ar);
ath10k_snoc_rx_post(ar);
@@ -792,7 +802,6 @@ static int ath10k_snoc_hif_power_up(struct ath10k *ar)
goto err_wlan_enable;
}
- napi_enable(&ar->napi);
return 0;
err_wlan_enable:
@@ -1274,6 +1283,7 @@ static int ath10k_snoc_probe(struct platform_device *pdev)
struct ath10k *ar;
int ret;
u32 i;
+ struct ath10k_bus_params bus_params;
of_id = of_match_device(ath10k_snoc_dt_match, &pdev->dev);
if (!of_id) {
@@ -1341,7 +1351,9 @@ static int ath10k_snoc_probe(struct platform_device *pdev)
goto err_free_irq;
}
- ret = ath10k_core_register(ar, drv_data->hw_rev);
+ bus_params.dev_type = ATH10K_DEV_TYPE_LL;
+ bus_params.chip_id = drv_data->hw_rev;
+ ret = ath10k_core_register(ar, &bus_params);
if (ret) {
ath10k_err(ar, "failed to register driver core: %d\n", ret);
goto err_hw_power_off;
diff --git a/drivers/net/wireless/ath/ath10k/targaddrs.h b/drivers/net/wireless/ath/ath10k/targaddrs.h
index c2b5bad0459b..b11a1c3d87b4 100644
--- a/drivers/net/wireless/ath/ath10k/targaddrs.h
+++ b/drivers/net/wireless/ath/ath10k/targaddrs.h
@@ -484,6 +484,10 @@ struct host_interest {
#define QCA99X0_BOARD_DATA_SZ 12288
#define QCA99X0_BOARD_EXT_DATA_SZ 0
+/* Dual band extended board data */
+#define QCA99X0_EXT_BOARD_DATA_SZ 2048
+#define EXT_BOARD_ADDRESS_OFFSET 0x3000
+
#define QCA4019_BOARD_DATA_SZ 12064
#define QCA4019_BOARD_EXT_DATA_SZ 0
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
index cda164f6e9f6..23606b6972d0 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -95,7 +95,8 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
wake_up(&htt->empty_tx_wq);
spin_unlock_bh(&htt->tx_lock);
- dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
+ if (ar->dev_type != ATH10K_DEV_TYPE_HL)
+ dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
ath10k_report_offchan_tx(htt->ar, msdu);
diff --git a/drivers/net/wireless/ath/ath10k/usb.c b/drivers/net/wireless/ath/ath10k/usb.c
index d4803ff5a78a..f731d35ee76d 100644
--- a/drivers/net/wireless/ath/ath10k/usb.c
+++ b/drivers/net/wireless/ath/ath10k/usb.c
@@ -983,7 +983,7 @@ static int ath10k_usb_probe(struct usb_interface *interface,
struct usb_device *dev = interface_to_usbdev(interface);
int ret, vendor_id, product_id;
enum ath10k_hw_rev hw_rev;
- u32 chip_id;
+ struct ath10k_bus_params bus_params;
/* Assumption: All USB based chipsets (so far) are QCA9377 based.
* If there will be newer chipsets that does not use the hw reg
@@ -1016,9 +1016,10 @@ static int ath10k_usb_probe(struct usb_interface *interface,
ar->id.vendor = vendor_id;
ar->id.device = product_id;
+ bus_params.dev_type = ATH10K_DEV_TYPE_HL;
/* TODO: don't know yet how to get chip_id with USB */
- chip_id = 0;
- ret = ath10k_core_register(ar, chip_id);
+ bus_params.chip_id = 0;
+ ret = ath10k_core_register(ar, &bus_params);
if (ret) {
ath10k_warn(ar, "failed to register driver core: %d\n", ret);
goto err;
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index cdc1e64d52ad..731ceaed4d5a 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -19,7 +19,6 @@
#include "debug.h"
#include "mac.h"
#include "hw.h"
-#include "mac.h"
#include "wmi.h"
#include "wmi-ops.h"
#include "wmi-tlv.h"
@@ -1569,7 +1568,10 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
cfg->num_vdevs = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
- cfg->num_peers = __cpu_to_le32(ar->hw_params.num_peers);
+ if (ar->hw_params.num_peers)
+ cfg->num_peers = __cpu_to_le32(ar->hw_params.num_peers);
+ else
+ cfg->num_peers = __cpu_to_le32(TARGET_TLV_NUM_PEERS);
cfg->ast_skid_limit = __cpu_to_le32(ar->hw_params.ast_skid_limit);
cfg->num_wds_entries = __cpu_to_le32(ar->hw_params.num_wds_entries);
@@ -1582,7 +1584,10 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
}
cfg->num_peer_keys = __cpu_to_le32(2);
- cfg->num_tids = __cpu_to_le32(TARGET_TLV_NUM_TIDS);
+ if (ar->hw_params.num_peers)
+ cfg->num_tids = __cpu_to_le32(ar->hw_params.num_peers * 2);
+ else
+ cfg->num_tids = __cpu_to_le32(TARGET_TLV_NUM_TIDS);
cfg->tx_chain_mask = __cpu_to_le32(0x7);
cfg->rx_chain_mask = __cpu_to_le32(0x7);
cfg->rx_timeout_pri[0] = __cpu_to_le32(0x64);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 40ce0e4006bc..25e8fa789e8d 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1307,7 +1307,8 @@ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
.set_mcast2ucast_mode = WMI_PDEV_PARAM_UNSUPPORTED,
.set_mcast2ucast_buffer = WMI_PDEV_PARAM_UNSUPPORTED,
.remove_mcast2ucast_buffer = WMI_PDEV_PARAM_UNSUPPORTED,
- .peer_sta_ps_statechg_enable = WMI_PDEV_PARAM_UNSUPPORTED,
+ .peer_sta_ps_statechg_enable =
+ WMI_10X_PDEV_PARAM_PEER_STA_PS_STATECHG_ENABLE,
.igmpmld_ac_override = WMI_PDEV_PARAM_UNSUPPORTED,
.block_interbss = WMI_PDEV_PARAM_UNSUPPORTED,
.set_disable_reset_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
@@ -2342,7 +2343,12 @@ static int wmi_process_mgmt_tx_comp(struct ath10k *ar, u32 desc_id,
dma_unmap_single(ar->dev, pkt_addr->paddr,
msdu->len, DMA_FROM_DEVICE);
info = IEEE80211_SKB_CB(msdu);
- info->flags |= status;
+
+ if (status)
+ info->flags &= ~IEEE80211_TX_STAT_ACK;
+ else
+ info->flags |= IEEE80211_TX_STAT_ACK;
+
ieee80211_tx_status_irqsafe(ar->hw, msdu);
ret = 0;
@@ -2482,7 +2488,8 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
status->freq, status->band, status->signal,
status->rate_idx);
- ieee80211_rx(ar->hw, skb);
+ ieee80211_rx_ni(ar->hw, skb);
+
return 0;
}
@@ -3242,18 +3249,31 @@ void ath10k_wmi_event_vdev_start_resp(struct ath10k *ar, struct sk_buff *skb)
{
struct wmi_vdev_start_ev_arg arg = {};
int ret;
+ u32 status;
ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_START_RESP_EVENTID\n");
+ ar->last_wmi_vdev_start_status = 0;
+
ret = ath10k_wmi_pull_vdev_start(ar, skb, &arg);
if (ret) {
ath10k_warn(ar, "failed to parse vdev start event: %d\n", ret);
- return;
+ ar->last_wmi_vdev_start_status = ret;
+ goto out;
}
- if (WARN_ON(__le32_to_cpu(arg.status)))
- return;
+ status = __le32_to_cpu(arg.status);
+ if (WARN_ON_ONCE(status)) {
+ ath10k_warn(ar, "vdev-start-response reports status error: %d (%s)\n",
+ status, (status == WMI_VDEV_START_CHAN_INVALID) ?
+ "chan-invalid" : "unknown");
+ /* Setup is done one way or another though, so we should still
+ * do the completion, so don't return here.
+ */
+ ar->last_wmi_vdev_start_status = -EINVAL;
+ }
+out:
complete(&ar->vdev_setup_done);
}
@@ -4780,6 +4800,13 @@ ath10k_wmi_tpc_final_get_rate(struct ath10k *ar,
}
}
+ if (pream == -1) {
+ ath10k_warn(ar, "unknown wmi tpc final index and frequency: %u, %u\n",
+ pream_idx, __le32_to_cpu(ev->chan_freq));
+ tpc = 0;
+ goto out;
+ }
+
if (pream == 4)
tpc = min_t(u8, ev->rates_array[rate_idx],
ev->max_reg_allow_pow[ch]);
@@ -5022,6 +5049,36 @@ ath10k_wmi_handle_tdls_peer_event(struct ath10k *ar, struct sk_buff *skb)
}
}
+static void
+ath10k_wmi_event_peer_sta_ps_state_chg(struct ath10k *ar, struct sk_buff *skb)
+{
+ struct wmi_peer_sta_ps_state_chg_event *ev;
+ struct ieee80211_sta *sta;
+ struct ath10k_sta *arsta;
+ u8 peer_addr[ETH_ALEN];
+
+ lockdep_assert_held(&ar->data_lock);
+
+ ev = (struct wmi_peer_sta_ps_state_chg_event *)skb->data;
+ ether_addr_copy(peer_addr, ev->peer_macaddr.addr);
+
+ rcu_read_lock();
+
+ sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer_addr, NULL);
+
+ if (!sta) {
+ ath10k_warn(ar, "failed to find station entry %pM\n",
+ peer_addr);
+ goto exit;
+ }
+
+ arsta = (struct ath10k_sta *)sta->drv_priv;
+ arsta->peer_ps_state = __le32_to_cpu(ev->peer_ps_state);
+
+exit:
+ rcu_read_unlock();
+}
+
void ath10k_wmi_event_pdev_ftm_intg(struct ath10k *ar, struct sk_buff *skb)
{
ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PDEV_FTM_INTG_EVENTID\n");
@@ -5455,7 +5512,8 @@ int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb)
arg.mac_addr,
__le32_to_cpu(arg.status));
- ether_addr_copy(ar->mac_addr, arg.mac_addr);
+ if (is_zero_ether_addr(ar->mac_addr))
+ ether_addr_copy(ar->mac_addr, arg.mac_addr);
complete(&ar->wmi.unified_ready);
return 0;
}
@@ -5951,6 +6009,9 @@ static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb)
ath10k_dbg(ar, ATH10K_DBG_WMI,
"received event id %d not implemented\n", id);
break;
+ case WMI_10_2_PEER_STA_PS_STATECHG_EVENTID:
+ ath10k_wmi_event_peer_sta_ps_state_chg(ar, skb);
+ break;
default:
ath10k_warn(ar, "Unknown eventid: %d\n", id);
break;
@@ -6068,6 +6129,9 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
case WMI_10_4_DFS_STATUS_CHECK_EVENTID:
ath10k_wmi_event_dfs_status_check(ar, skb);
break;
+ case WMI_10_4_PEER_STA_PS_STATECHG_EVENTID:
+ ath10k_wmi_event_peer_sta_ps_state_chg(ar, skb);
+ break;
default:
ath10k_warn(ar, "Unknown eventid: %d\n", id);
break;
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 36220258e3c7..f67c52757ea6 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -203,6 +203,8 @@ enum wmi_service {
WMI_SERVICE_TPC_STATS_FINAL,
WMI_SERVICE_RESET_CHIP,
WMI_SERVICE_SPOOF_MAC_SUPPORT,
+ WMI_SERVICE_TX_DATA_ACK_RSSI,
+ WMI_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT,
/* keep last */
WMI_SERVICE_MAX,
@@ -350,6 +352,13 @@ enum wmi_10_4_service {
WMI_10_4_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS,
WMI_10_4_SERVICE_HOST_DFS_CHECK_SUPPORT,
WMI_10_4_SERVICE_TPC_STATS_FINAL,
+ WMI_10_4_SERVICE_CFR_CAPTURE_SUPPORT,
+ WMI_10_4_SERVICE_TX_DATA_ACK_RSSI,
+ WMI_10_4_SERVICE_CFR_CAPTURE_IND_MSG_TYPE_LEGACY,
+ WMI_10_4_SERVICE_PER_PACKET_SW_ENCRYPT,
+ WMI_10_4_SERVICE_PEER_TID_CONFIGS_SUPPORT,
+ WMI_10_4_SERVICE_VDEV_BCN_RATE_CONTROL,
+ WMI_10_4_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT,
};
static inline char *wmi_service_name(int service_id)
@@ -463,6 +472,8 @@ static inline char *wmi_service_name(int service_id)
SVCSTR(WMI_SERVICE_HOST_DFS_CHECK_SUPPORT);
SVCSTR(WMI_SERVICE_TPC_STATS_FINAL);
SVCSTR(WMI_SERVICE_RESET_CHIP);
+ SVCSTR(WMI_SERVICE_TX_DATA_ACK_RSSI);
+ SVCSTR(WMI_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT);
default:
return NULL;
}
@@ -771,6 +782,10 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out,
WMI_SERVICE_HOST_DFS_CHECK_SUPPORT, len);
SVCMAP(WMI_10_4_SERVICE_TPC_STATS_FINAL,
WMI_SERVICE_TPC_STATS_FINAL, len);
+ SVCMAP(WMI_10_4_SERVICE_TX_DATA_ACK_RSSI,
+ WMI_SERVICE_TX_DATA_ACK_RSSI, len);
+ SVCMAP(WMI_10_4_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT,
+ WMI_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT, len);
}
#undef SVCMAP
@@ -2924,6 +2939,7 @@ enum wmi_coex_version {
* @WMI_10_4_TDLS_CONN_TRACKER_IN_HOST_MODE: TDLS connection tracker in host
* enable/disable
* @WMI_10_4_TDLS_EXPLICIT_MODE_ONLY:Explicit TDLS mode enable/disable
+ * @WMI_10_4_TX_DATA_ACK_RSSI: Enable DATA ACK RSSI if firmware is capable
*/
enum wmi_10_4_feature_mask {
WMI_10_4_LTEU_SUPPORT = BIT(0),
@@ -2939,6 +2955,7 @@ enum wmi_10_4_feature_mask {
WMI_10_4_TDLS_UAPSD_SLEEP_STA = BIT(10),
WMI_10_4_TDLS_CONN_TRACKER_IN_HOST_MODE = BIT(11),
WMI_10_4_TDLS_EXPLICIT_MODE_ONLY = BIT(12),
+ WMI_10_4_TX_DATA_ACK_RSSI = BIT(16),
};
@@ -4153,6 +4170,13 @@ enum wmi_tpc_pream_5ghz {
WMI_TPC_PREAM_5GHZ_HTCUP,
};
+#define WMI_PEER_PS_STATE_DISABLED 2
+
+struct wmi_peer_sta_ps_state_chg_event {
+ struct wmi_mac_addr peer_macaddr;
+ __le32 peer_ps_state;
+} __packed;
+
struct wmi_pdev_chanlist_update_event {
/* number of channels */
__le32 num_chan;
@@ -4958,10 +4982,15 @@ enum wmi_rate_preamble {
#define ATH10K_HW_GI(flags) (((flags) >> 5) & 0x1)
#define ATH10K_HW_RATECODE(rate, nss, preamble) \
(((preamble) << 6) | ((nss) << 4) | (rate))
+#define ATH10K_HW_AMPDU(flags) ((flags) & 0x1)
+#define ATH10K_HW_BA_FAIL(flags) (((flags) >> 1) & 0x3)
-#define VHT_MCS_NUM 10
-#define VHT_BW_NUM 4
-#define VHT_NSS_NUM 4
+#define ATH10K_VHT_MCS_NUM 10
+#define ATH10K_BW_NUM 4
+#define ATH10K_NSS_NUM 4
+#define ATH10K_LEGACY_NUM 12
+#define ATH10K_GI_NUM 2
+#define ATH10K_HT_MCS_NUM 32
/* Value to disable fixed rate setting */
#define WMI_FIXED_RATE_NONE (0xff)
@@ -6642,11 +6671,17 @@ struct wmi_ch_info_ev_arg {
__le32 rx_frame_count;
};
+/* From 10.4 firmware, not sure all have the same values. */
+enum wmi_vdev_start_status {
+ WMI_VDEV_START_OK = 0,
+ WMI_VDEV_START_CHAN_INVALID,
+};
+
struct wmi_vdev_start_ev_arg {
__le32 vdev_id;
__le32 req_id;
__le32 resp_type; /* %WMI_VDEV_RESP_ */
- __le32 status;
+ __le32 status; /* See wmi_vdev_start_status enum above */
};
struct wmi_peer_kick_ev_arg {
diff --git a/drivers/net/wireless/ath/ath10k/wow.c b/drivers/net/wireless/ath/ath10k/wow.c
index a6b179f88d36..af444dfecae9 100644
--- a/drivers/net/wireless/ath/ath10k/wow.c
+++ b/drivers/net/wireless/ath/ath10k/wow.c
@@ -374,6 +374,8 @@ int ath10k_wow_op_suspend(struct ieee80211_hw *hw,
goto cleanup;
}
+ ath10k_mac_wait_tx_complete(ar);
+
ret = ath10k_wow_enable(ar);
if (ret) {
ath10k_warn(ar, "failed to start wow: %d\n", ret);
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index 58fb227a849f..54132af70094 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -710,8 +710,8 @@ static bool check_device_tree(struct ath6kl *ar)
for_each_compatible_node(node, NULL, "atheros,ath6kl") {
board_id = of_get_property(node, board_id_prop, NULL);
if (board_id == NULL) {
- ath6kl_warn("No \"%s\" property on %s node.\n",
- board_id_prop, node->name);
+ ath6kl_warn("No \"%s\" property on %pOFn node.\n",
+ board_id_prop, node);
continue;
}
snprintf(board_filename, sizeof(board_filename),
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 003e9fb456ac..21ba20981a80 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -1074,6 +1074,7 @@ struct ath_softc {
struct ath_spec_scan_priv spec_priv;
+ struct ieee80211_vif *tx99_vif;
struct sk_buff *tx99_skb;
bool tx99_state;
s16 tx99_power;
diff --git a/drivers/net/wireless/ath/ath9k/common-debug.c b/drivers/net/wireless/ath/ath9k/common-debug.c
index 239429f10378..53ca4b063eb9 100644
--- a/drivers/net/wireless/ath/ath9k/common-debug.c
+++ b/drivers/net/wireless/ath/ath9k/common-debug.c
@@ -144,6 +144,8 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
RXS_ERR("BEACONS", rx_beacons);
RXS_ERR("FRAGS", rx_frags);
RXS_ERR("SPECTRAL", rx_spectral);
+ RXS_ERR("SPECTRAL SMPL GOOD", rx_spectral_sample_good);
+ RXS_ERR("SPECTRAL SMPL ERR", rx_spectral_sample_err);
RXS_ERR("CRC ERR", crc_err);
RXS_ERR("DECRYPT CRC ERR", decrypt_crc_err);
diff --git a/drivers/net/wireless/ath/ath9k/common-debug.h b/drivers/net/wireless/ath/ath9k/common-debug.h
index 3376990d3a24..2938b5b96b07 100644
--- a/drivers/net/wireless/ath/ath9k/common-debug.h
+++ b/drivers/net/wireless/ath/ath9k/common-debug.h
@@ -39,6 +39,8 @@
* @rx_beacons: No. of beacons received.
* @rx_frags: No. of rx-fragements received.
* @rx_spectral: No of spectral packets received.
+ * @rx_spectral_sample_good: No. of good spectral samples
+ * @rx_spectral_sample_err: No. of good spectral samples
*/
struct ath_rx_stats {
u32 rx_pkts_all;
@@ -58,6 +60,8 @@ struct ath_rx_stats {
u32 rx_beacons;
u32 rx_frags;
u32 rx_spectral;
+ u32 rx_spectral_sample_good;
+ u32 rx_spectral_sample_err;
};
#ifdef CONFIG_ATH9K_COMMON_DEBUG
diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c
index 440e16e641e4..6a43d26276e5 100644
--- a/drivers/net/wireless/ath/ath9k/common-spectral.c
+++ b/drivers/net/wireless/ath/ath9k/common-spectral.c
@@ -59,8 +59,7 @@ ath_cmn_max_idx_verify_ht20_fft(u8 *sample_end, int bytes_read)
sample = sample_end - SPECTRAL_HT20_SAMPLE_LEN + 1;
- max_index = spectral_max_index(mag_info->all_bins,
- SPECTRAL_HT20_NUM_BINS);
+ max_index = spectral_max_index_ht20(mag_info->all_bins);
max_magnitude = spectral_max_magnitude(mag_info->all_bins);
max_exp = mag_info->max_exp & 0xf;
@@ -72,7 +71,7 @@ ath_cmn_max_idx_verify_ht20_fft(u8 *sample_end, int bytes_read)
if (bytes_read < SPECTRAL_HT20_SAMPLE_LEN && max_index < 1)
return -1;
- if (sample[max_index] != (max_magnitude >> max_exp))
+ if ((sample[max_index] & 0xf8) != ((max_magnitude >> max_exp) & 0xf8))
return -1;
else
return 0;
@@ -100,12 +99,10 @@ ath_cmn_max_idx_verify_ht20_40_fft(u8 *sample_end, int bytes_read)
sample = sample_end - SPECTRAL_HT20_40_SAMPLE_LEN + 1;
lower_mag = spectral_max_magnitude(mag_info->lower_bins);
- lower_max_index = spectral_max_index(mag_info->lower_bins,
- SPECTRAL_HT20_40_NUM_BINS);
+ lower_max_index = spectral_max_index_ht40(mag_info->lower_bins);
upper_mag = spectral_max_magnitude(mag_info->upper_bins);
- upper_max_index = spectral_max_index(mag_info->upper_bins,
- SPECTRAL_HT20_40_NUM_BINS);
+ upper_max_index = spectral_max_index_ht40(mag_info->upper_bins);
max_exp = mag_info->max_exp & 0xf;
@@ -117,19 +114,10 @@ ath_cmn_max_idx_verify_ht20_40_fft(u8 *sample_end, int bytes_read)
((upper_max_index < 1) || (lower_max_index < 1)))
return -1;
- /* Some time hardware messes up the index and adds
- * the index of the middle point (dc_pos). Try to fix it.
- */
- if ((upper_max_index - dc_pos > 0) &&
- (sample[upper_max_index] == (upper_mag >> max_exp)))
- upper_max_index -= dc_pos;
-
- if ((lower_max_index - dc_pos > 0) &&
- (sample[lower_max_index - dc_pos] == (lower_mag >> max_exp)))
- lower_max_index -= dc_pos;
-
- if ((sample[upper_max_index + dc_pos] != (upper_mag >> max_exp)) ||
- (sample[lower_max_index] != (lower_mag >> max_exp)))
+ if (((sample[upper_max_index + dc_pos] & 0xf8) !=
+ ((upper_mag >> max_exp) & 0xf8)) ||
+ ((sample[lower_max_index] & 0xf8) !=
+ ((lower_mag >> max_exp) & 0xf8)))
return -1;
else
return 0;
@@ -169,8 +157,7 @@ ath_cmn_process_ht20_fft(struct ath_rx_status *rs,
magnitude = spectral_max_magnitude(mag_info->all_bins);
fft_sample_20.max_magnitude = __cpu_to_be16(magnitude);
- max_index = spectral_max_index(mag_info->all_bins,
- SPECTRAL_HT20_NUM_BINS);
+ max_index = spectral_max_index_ht20(mag_info->all_bins);
fft_sample_20.max_index = max_index;
bitmap_w = spectral_bitmap_weight(mag_info->all_bins);
@@ -188,7 +175,8 @@ ath_cmn_process_ht20_fft(struct ath_rx_status *rs,
magnitude >> max_exp,
max_index);
- if (fft_sample_20.data[max_index] != (magnitude >> max_exp)) {
+ if ((fft_sample_20.data[max_index] & 0xf8) !=
+ ((magnitude >> max_exp) & 0xf8)) {
ath_dbg(common, SPECTRAL_SCAN, "Magnitude mismatch !\n");
ret = -1;
}
@@ -302,12 +290,10 @@ ath_cmn_process_ht20_40_fft(struct ath_rx_status *rs,
upper_mag = spectral_max_magnitude(mag_info->upper_bins);
fft_sample_40.upper_max_magnitude = __cpu_to_be16(upper_mag);
- lower_max_index = spectral_max_index(mag_info->lower_bins,
- SPECTRAL_HT20_40_NUM_BINS);
+ lower_max_index = spectral_max_index_ht40(mag_info->lower_bins);
fft_sample_40.lower_max_index = lower_max_index;
- upper_max_index = spectral_max_index(mag_info->upper_bins,
- SPECTRAL_HT20_40_NUM_BINS);
+ upper_max_index = spectral_max_index_ht40(mag_info->upper_bins);
fft_sample_40.upper_max_index = upper_max_index;
lower_bitmap_w = spectral_bitmap_weight(mag_info->lower_bins);
@@ -331,29 +317,13 @@ ath_cmn_process_ht20_40_fft(struct ath_rx_status *rs,
upper_mag >> max_exp,
upper_max_index);
- /* Some time hardware messes up the index and adds
- * the index of the middle point (dc_pos). Try to fix it.
- */
- if ((upper_max_index - dc_pos > 0) &&
- (fft_sample_40.data[upper_max_index] == (upper_mag >> max_exp))) {
- upper_max_index -= dc_pos;
- fft_sample_40.upper_max_index = upper_max_index;
- }
-
- if ((lower_max_index - dc_pos > 0) &&
- (fft_sample_40.data[lower_max_index - dc_pos] ==
- (lower_mag >> max_exp))) {
- lower_max_index -= dc_pos;
- fft_sample_40.lower_max_index = lower_max_index;
- }
-
/* Check if we got the expected magnitude values at
* the expected bins
*/
- if ((fft_sample_40.data[upper_max_index + dc_pos]
- != (upper_mag >> max_exp)) ||
- (fft_sample_40.data[lower_max_index]
- != (lower_mag >> max_exp))) {
+ if (((fft_sample_40.data[upper_max_index + dc_pos] & 0xf8)
+ != ((upper_mag >> max_exp) & 0xf8)) ||
+ ((fft_sample_40.data[lower_max_index] & 0xf8)
+ != ((lower_mag >> max_exp) & 0xf8))) {
ath_dbg(common, SPECTRAL_SCAN, "Magnitude mismatch !\n");
ret = -1;
}
@@ -411,7 +381,7 @@ ath_cmn_process_ht20_40_fft(struct ath_rx_status *rs,
ath_dbg(common, SPECTRAL_SCAN,
"Calculated new upper max 0x%X at %i\n",
- tmp_mag, i);
+ tmp_mag, fft_sample_40.upper_max_index);
} else
for (i = dc_pos; i < SPECTRAL_HT20_40_NUM_BINS; i++) {
if (fft_sample_40.data[i] == (upper_mag >> max_exp))
@@ -501,6 +471,7 @@ int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_h
u8 sample_buf[SPECTRAL_SAMPLE_MAX_LEN] = {0};
struct ath_hw *ah = spec_priv->ah;
struct ath_common *common = ath9k_hw_common(spec_priv->ah);
+ struct ath_softc *sc = (struct ath_softc *)common->priv;
u8 num_bins, *vdata = (u8 *)hdr;
struct ath_radar_info *radar_info;
int len = rs->rs_datalen;
@@ -649,8 +620,13 @@ int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_h
sample_buf, sample_len,
sample_bytes);
- fft_handler(rs, spec_priv, sample_buf,
- tsf, freq, chan_type);
+ ret = fft_handler(rs, spec_priv, sample_buf,
+ tsf, freq, chan_type);
+
+ if (ret == 0)
+ RX_STAT_INC(rx_spectral_sample_good);
+ else
+ RX_STAT_INC(rx_spectral_sample_err);
memset(sample_buf, 0, SPECTRAL_SAMPLE_MAX_LEN);
@@ -665,6 +641,11 @@ int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_h
ret = fft_handler(rs, spec_priv, sample_start,
tsf, freq, chan_type);
+ if (ret == 0)
+ RX_STAT_INC(rx_spectral_sample_good);
+ else
+ RX_STAT_INC(rx_spectral_sample_err);
+
/* Mix the received bins to the /dev/random
* pool
*/
@@ -675,7 +656,7 @@ int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_h
* loop.
*/
if (len <= fft_len + 2)
- break;
+ return 1;
sample_start = &vdata[i + 1];
diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.h b/drivers/net/wireless/ath/ath9k/common-spectral.h
index 303ab470ce34..011d8ab8b974 100644
--- a/drivers/net/wireless/ath/ath9k/common-spectral.h
+++ b/drivers/net/wireless/ath/ath9k/common-spectral.h
@@ -145,6 +145,23 @@ static inline u8 spectral_max_index(u8 *bins, int num_bins)
return m;
}
+static inline u8 spectral_max_index_ht40(u8 *bins)
+{
+ u8 idx;
+
+ idx = spectral_max_index(bins, SPECTRAL_HT20_40_NUM_BINS);
+
+ /* positive values and zero are starting at the beginning
+ * of the data field.
+ */
+ return idx % (SPECTRAL_HT20_40_NUM_BINS / 2);
+}
+
+static inline u8 spectral_max_index_ht20(u8 *bins)
+{
+ return spectral_max_index(bins, SPECTRAL_HT20_NUM_BINS);
+}
+
/* return the bitmap weight from the all/upper/lower bins */
static inline u8 spectral_bitmap_weight(u8 *bins)
{
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 0a6eb8a8c1ed..c871b7ec5011 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -990,19 +990,6 @@ static int read_file_dump_nfcal(struct seq_file *file, void *data)
return 0;
}
-static int open_file_dump_nfcal(struct inode *inode, struct file *f)
-{
- return single_open(f, read_file_dump_nfcal, inode->i_private);
-}
-
-static const struct file_operations fops_dump_nfcal = {
- .read = seq_read,
- .open = open_file_dump_nfcal,
- .owner = THIS_MODULE,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
static ssize_t read_file_btcoex(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
diff --git a/drivers/net/wireless/ath/ath9k/debug_sta.c b/drivers/net/wireless/ath/ath9k/debug_sta.c
index ed8b77a74630..e8fcd3e1c470 100644
--- a/drivers/net/wireless/ath/ath9k/debug_sta.c
+++ b/drivers/net/wireless/ath/ath9k/debug_sta.c
@@ -286,9 +286,25 @@ static ssize_t read_airtime(struct file *file, char __user *user_buf,
return retval;
}
+static ssize_t
+write_airtime_reset_stub(struct file *file, const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_node *an = file->private_data;
+ struct ath_airtime_stats *astats;
+ int i;
+
+ astats = &an->airtime_stats;
+ astats->rx_airtime = 0;
+ astats->tx_airtime = 0;
+ for (i = 0; i < 4; i++)
+ an->airtime_deficit[i] = ATH_AIRTIME_QUANTUM;
+ return count;
+}
static const struct file_operations fops_airtime = {
.read = read_airtime,
+ .write = write_airtime_reset_stub,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
@@ -304,5 +320,5 @@ void ath9k_sta_add_debugfs(struct ieee80211_hw *hw,
debugfs_create_file("node_aggr", 0444, dir, an, &fops_node_aggr);
debugfs_create_file("node_recv", 0444, dir, an, &fops_node_recv);
- debugfs_create_file("airtime", 0444, dir, an, &fops_airtime);
+ debugfs_create_file("airtime", 0644, dir, an, &fops_airtime);
}
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 6ce4b9f1dcb4..c85f613e8ceb 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1251,8 +1251,13 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
struct ath_vif *avp = (void *)vif->drv_priv;
struct ath_node *an = &avp->mcast_node;
- if (IS_ENABLED(CONFIG_ATH9K_TX99))
- return -EOPNOTSUPP;
+ if (IS_ENABLED(CONFIG_ATH9K_TX99)) {
+ if (sc->cur_chan->nvifs >= 1) {
+ mutex_unlock(&sc->mutex);
+ return -EOPNOTSUPP;
+ }
+ sc->tx99_vif = vif;
+ }
mutex_lock(&sc->mutex);
@@ -1337,6 +1342,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
ath9k_p2p_remove_vif(sc, vif);
sc->cur_chan->nvifs--;
+ sc->tx99_vif = NULL;
if (!ath9k_is_chanctx_enabled())
list_del(&avp->list);
diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c
index 9b05ffb68c34..95544ce05acf 100644
--- a/drivers/net/wireless/ath/ath9k/tx99.c
+++ b/drivers/net/wireless/ath/ath9k/tx99.c
@@ -54,6 +54,7 @@ static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc)
struct ieee80211_hdr *hdr;
struct ieee80211_tx_info *tx_info;
struct sk_buff *skb;
+ struct ath_vif *avp;
skb = alloc_skb(len, GFP_KERNEL);
if (!skb)
@@ -71,11 +72,17 @@ static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc)
memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN);
memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
+ if (sc->tx99_vif) {
+ avp = (struct ath_vif *) sc->tx99_vif->drv_priv;
+ hdr->seq_ctrl |= cpu_to_le16(avp->seq_no);
+ }
+
tx_info = IEEE80211_SKB_CB(skb);
memset(tx_info, 0, sizeof(*tx_info));
rate = &tx_info->control.rates[0];
tx_info->band = sc->cur_chan->chandef.chan->band;
tx_info->flags = IEEE80211_TX_CTL_NO_ACK;
+ tx_info->control.vif = sc->tx99_vif;
rate->count = 1;
if (ah->curchan && IS_CHAN_HT(ah->curchan)) {
rate->flags |= IEEE80211_TX_RC_MCS;
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 66b6a8872c06..43b6c8508e49 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -2973,7 +2973,7 @@ int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb,
return -EINVAL;
}
- ath_set_rates(NULL, NULL, bf);
+ ath_set_rates(sc->tx99_vif, NULL, bf);
ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, bf->bf_daddr);
ath9k_hw_tx99_start(sc->sc_ah, txctl->txq->axq_qnum);
diff --git a/drivers/net/wireless/ath/wil6210/pm.c b/drivers/net/wireless/ath/wil6210/pm.c
index 3a4194779ddf..75fe9323547c 100644
--- a/drivers/net/wireless/ath/wil6210/pm.c
+++ b/drivers/net/wireless/ath/wil6210/pm.c
@@ -190,7 +190,7 @@ out:
static int wil_suspend_keep_radio_on(struct wil6210_priv *wil)
{
int rc = 0;
- unsigned long start, data_comp_to;
+ unsigned long data_comp_to;
wil_dbg_pm(wil, "suspend keep radio on\n");
@@ -232,7 +232,6 @@ static int wil_suspend_keep_radio_on(struct wil6210_priv *wil)
}
/* Wait for completion of the pending RX packets */
- start = jiffies;
data_comp_to = jiffies + msecs_to_jiffies(WIL_DATA_COMPLETION_TO_MS);
if (test_bit(wil_status_napi_en, wil->status)) {
while (!wil->txrx_ops.is_rx_idle(wil)) {
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index cf6a69198b5d..abb82018d3b4 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -455,7 +455,7 @@ static inline void parse_cidxtid(u8 cidxtid, u8 *cid, u8 *tid)
*/
static inline bool wil_cid_valid(u8 cid)
{
- return (cid >= 0 && cid < WIL6210_MAX_CID);
+ return cid < WIL6210_MAX_CID;
}
struct wil6210_mbox_ring {
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index c3ad8e4df3ec..4859f0e43658 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -1177,7 +1177,7 @@ static void wmi_evt_ring_en(struct wil6210_vif *vif, int id, void *d, int len)
u8 vri = evt->ring_index;
struct wireless_dev *wdev = vif_to_wdev(vif);
struct wil_sta_info *sta;
- int cid;
+ u8 cid;
struct key_params params;
wil_dbg_wmi(wil, "Enable vring %d MID %d\n", vri, vif->mid);
diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c
index 4daa1ce8cba3..74be3c809225 100644
--- a/drivers/net/wireless/broadcom/b43/main.c
+++ b/drivers/net/wireless/broadcom/b43/main.c
@@ -5493,13 +5493,11 @@ err_powerdown:
static void b43_one_core_detach(struct b43_bus_dev *dev)
{
struct b43_wldev *wldev;
- struct b43_wl *wl;
/* Do not cancel ieee80211-workqueue based work here.
* See comment in b43_remove(). */
wldev = b43_bus_get_wldev(dev);
- wl = wldev->wl;
b43_debugfs_remove_device(wldev);
b43_wireless_core_detach(wldev);
list_del(&wldev->list);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
index 3e9c4f2f5dd1..456a1bf008b3 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
@@ -74,7 +74,7 @@
#define P2P_AF_MAX_WAIT_TIME msecs_to_jiffies(2000)
#define P2P_INVALID_CHANNEL -1
#define P2P_CHANNEL_SYNC_RETRY 5
-#define P2P_AF_FRM_SCAN_MAX_WAIT msecs_to_jiffies(1500)
+#define P2P_AF_FRM_SCAN_MAX_WAIT msecs_to_jiffies(450)
#define P2P_DEFAULT_SLEEP_TIME_VSDB 200
/* WiFi P2P Public Action Frame OUI Subtypes */
@@ -1134,7 +1134,6 @@ static s32 brcmf_p2p_af_searching_channel(struct brcmf_p2p_info *p2p)
{
struct afx_hdl *afx_hdl = &p2p->afx_hdl;
struct brcmf_cfg80211_vif *pri_vif;
- unsigned long duration;
s32 retry;
brcmf_dbg(TRACE, "Enter\n");
@@ -1150,7 +1149,6 @@ static s32 brcmf_p2p_af_searching_channel(struct brcmf_p2p_info *p2p)
* pending action frame tx is cancelled.
*/
retry = 0;
- duration = msecs_to_jiffies(P2P_AF_FRM_SCAN_MAX_WAIT);
while ((retry < P2P_CHANNEL_SYNC_RETRY) &&
(afx_hdl->peer_chan == P2P_INVALID_CHANNEL)) {
afx_hdl->is_listen = false;
@@ -1158,7 +1156,8 @@ static s32 brcmf_p2p_af_searching_channel(struct brcmf_p2p_info *p2p)
retry);
/* search peer on peer's listen channel */
schedule_work(&afx_hdl->afx_work);
- wait_for_completion_timeout(&afx_hdl->act_frm_scan, duration);
+ wait_for_completion_timeout(&afx_hdl->act_frm_scan,
+ P2P_AF_FRM_SCAN_MAX_WAIT);
if ((afx_hdl->peer_chan != P2P_INVALID_CHANNEL) ||
(!test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL,
&p2p->status)))
@@ -1171,7 +1170,7 @@ static s32 brcmf_p2p_af_searching_channel(struct brcmf_p2p_info *p2p)
afx_hdl->is_listen = true;
schedule_work(&afx_hdl->afx_work);
wait_for_completion_timeout(&afx_hdl->act_frm_scan,
- duration);
+ P2P_AF_FRM_SCAN_MAX_WAIT);
}
if ((afx_hdl->peer_chan != P2P_INVALID_CHANNEL) ||
(!test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL,
@@ -1458,10 +1457,12 @@ int brcmf_p2p_notify_action_tx_complete(struct brcmf_if *ifp,
return 0;
if (e->event_code == BRCMF_E_ACTION_FRAME_COMPLETE) {
- if (e->status == BRCMF_E_STATUS_SUCCESS)
+ if (e->status == BRCMF_E_STATUS_SUCCESS) {
set_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED,
&p2p->status);
- else {
+ if (!p2p->wait_for_offchan_complete)
+ complete(&p2p->send_af_done);
+ } else {
set_bit(BRCMF_P2P_STATUS_ACTION_TX_NOACK, &p2p->status);
/* If there is no ack, we don't need to wait for
* WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE event
@@ -1512,6 +1513,17 @@ static s32 brcmf_p2p_tx_action_frame(struct brcmf_p2p_info *p2p,
p2p->af_sent_channel = le32_to_cpu(af_params->channel);
p2p->af_tx_sent_jiffies = jiffies;
+ if (test_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, &p2p->status) &&
+ p2p->af_sent_channel ==
+ ieee80211_frequency_to_channel(p2p->remain_on_channel.center_freq))
+ p2p->wait_for_offchan_complete = false;
+ else
+ p2p->wait_for_offchan_complete = true;
+
+ brcmf_dbg(TRACE, "Waiting for %s tx completion event\n",
+ (p2p->wait_for_offchan_complete) ?
+ "off-channel" : "on-channel");
+
timeout = wait_for_completion_timeout(&p2p->send_af_done,
P2P_AF_MAX_WAIT_TIME);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h
index 0e8b34d2d85c..39f0d0218088 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h
@@ -124,6 +124,7 @@ struct afx_hdl {
* @gon_req_action: about to send go negotiation requets frame.
* @block_gon_req_tx: drop tx go negotiation requets frame.
* @p2pdev_dynamically: is p2p device if created by module param or supplicant.
+ * @wait_for_offchan_complete: wait for off-channel tx completion event.
*/
struct brcmf_p2p_info {
struct brcmf_cfg80211_info *cfg;
@@ -144,6 +145,7 @@ struct brcmf_p2p_info {
bool gon_req_action;
bool block_gon_req_tx;
bool p2pdev_dynamically;
+ bool wait_for_offchan_complete;
};
s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced);
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
index a8acc755a02c..da5d5f9b2573 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
@@ -56,7 +56,7 @@
#include "iwl-config.h"
/* Highest firmware API version supported */
-#define IWL_22000_UCODE_API_MAX 38
+#define IWL_22000_UCODE_API_MAX 41
/* Lowest firmware API version supported */
#define IWL_22000_UCODE_API_MIN 39
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
index 37deaf4fd7b3..d55fd23cafe6 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
@@ -57,7 +57,7 @@
#include "fw/file.h"
/* Highest firmware API version supported */
-#define IWL9000_UCODE_API_MAX 38
+#define IWL9000_UCODE_API_MAX 41
/* Lowest firmware API version supported */
#define IWL9000_UCODE_API_MIN 30
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
index 6c5338364794..93b392f0c6a4 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
@@ -165,7 +165,7 @@ struct iwl_nvm_access_resp {
*/
struct iwl_nvm_get_info {
__le32 reserved;
-} __packed; /* GRP_REGULATORY_NVM_GET_INFO_CMD_S_VER_1 */
+} __packed; /* REGULATORY_NVM_GET_INFO_CMD_API_S_VER_1 */
/**
* enum iwl_nvm_info_general_flags - flags in NVM_GET_INFO resp
@@ -180,14 +180,14 @@ enum iwl_nvm_info_general_flags {
* @flags: bit 0: 1 - empty, 0 - non-empty
* @nvm_version: nvm version
* @board_type: board type
- * @reserved: reserved
+ * @n_hw_addrs: number of reserved MAC addresses
*/
struct iwl_nvm_get_info_general {
__le32 flags;
__le16 nvm_version;
u8 board_type;
- u8 reserved;
-} __packed; /* GRP_REGULATORY_NVM_GET_INFO_GENERAL_S_VER_1 */
+ u8 n_hw_addrs;
+} __packed; /* REGULATORY_NVM_GET_INFO_GENERAL_S_VER_2 */
/**
* enum iwl_nvm_mac_sku_flags - flags in &iwl_nvm_get_info_sku
@@ -231,7 +231,7 @@ struct iwl_nvm_get_info_sku {
struct iwl_nvm_get_info_phy {
__le32 tx_chains;
__le32 rx_chains;
-} __packed; /* GRP_REGULATORY_NVM_GET_INFO_PHY_SKU_SECTION_S_VER_1 */
+} __packed; /* REGULATORY_NVM_GET_INFO_PHY_SKU_SECTION_S_VER_1 */
#define IWL_NUM_CHANNELS (51)
@@ -245,7 +245,7 @@ struct iwl_nvm_get_info_regulatory {
__le32 lar_enabled;
__le16 channel_profile[IWL_NUM_CHANNELS];
__le16 reserved;
-} __packed; /* GRP_REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_1 */
+} __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_1 */
/**
* struct iwl_nvm_get_info_rsp - response to get NVM data
@@ -259,7 +259,7 @@ struct iwl_nvm_get_info_rsp {
struct iwl_nvm_get_info_sku mac_sku;
struct iwl_nvm_get_info_phy phy_sku;
struct iwl_nvm_get_info_regulatory regulatory;
-} __packed; /* GRP_REGULATORY_NVM_GET_INFO_CMD_RSP_S_VER_2 */
+} __packed; /* REGULATORY_NVM_GET_INFO_RSP_API_S_VER_3 */
/**
* struct iwl_nvm_access_complete_cmd - NVM_ACCESS commands are completed
@@ -270,22 +270,6 @@ struct iwl_nvm_access_complete_cmd {
} __packed; /* NVM_ACCESS_COMPLETE_CMD_API_S_VER_1 */
/**
- * struct iwl_mcc_update_cmd_v1 - Request the device to update geographic
- * regulatory profile according to the given MCC (Mobile Country Code).
- * The MCC is two letter-code, ascii upper case[A-Z] or '00' for world domain.
- * 'ZZ' MCC will be used to switch to NVM default profile; in this case, the
- * MCC in the cmd response will be the relevant MCC in the NVM.
- * @mcc: given mobile country code
- * @source_id: the source from where we got the MCC, see iwl_mcc_source
- * @reserved: reserved for alignment
- */
-struct iwl_mcc_update_cmd_v1 {
- __le16 mcc;
- u8 source_id;
- u8 reserved;
-} __packed; /* LAR_UPDATE_MCC_CMD_API_S_VER_1 */
-
-/**
* struct iwl_mcc_update_cmd - Request the device to update geographic
* regulatory profile according to the given MCC (Mobile Country Code).
* The MCC is two letter-code, ascii upper case[A-Z] or '00' for world domain.
@@ -306,7 +290,18 @@ struct iwl_mcc_update_cmd {
} __packed; /* LAR_UPDATE_MCC_CMD_API_S_VER_2 */
/**
- * struct iwl_mcc_update_resp_v1 - response to MCC_UPDATE_CMD.
+ * enum iwl_geo_information - geographic information.
+ * @GEO_NO_INFO: no special info for this geo profile.
+ * @GEO_WMM_ETSI_5GHZ_INFO: this geo profile limits the WMM params
+ * for the 5 GHz band.
+ */
+enum iwl_geo_information {
+ GEO_NO_INFO = 0,
+ GEO_WMM_ETSI_5GHZ_INFO = BIT(0),
+};
+
+/**
+ * struct iwl_mcc_update_resp_v3 - response to MCC_UPDATE_CMD.
* Contains the new channel control profile map, if changed, and the new MCC
* (mobile country code).
* The new MCC may be different than what was requested in MCC_UPDATE_CMD.
@@ -314,30 +309,23 @@ struct iwl_mcc_update_cmd {
* @mcc: the new applied MCC
* @cap: capabilities for all channels which matches the MCC
* @source_id: the MCC source, see iwl_mcc_source
- * @n_channels: number of channels in @channels_data (may be 14, 39, 50 or 51
- * channels, depending on platform)
+ * @time: time elapsed from the MCC test start (in units of 30 seconds)
+ * @geo_info: geographic specific profile information
+ * see &enum iwl_geo_information.
+ * @n_channels: number of channels in @channels_data.
* @channels: channel control data map, DWORD for each channel. Only the first
* 16bits are used.
*/
-struct iwl_mcc_update_resp_v1 {
+struct iwl_mcc_update_resp_v3 {
__le32 status;
__le16 mcc;
u8 cap;
u8 source_id;
+ __le16 time;
+ __le16 geo_info;
__le32 n_channels;
__le32 channels[0];
-} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_1 */
-
-/**
- * enum iwl_geo_information - geographic information.
- * @GEO_NO_INFO: no special info for this geo profile.
- * @GEO_WMM_ETSI_5GHZ_INFO: this geo profile limits the WMM params
- * for the 5 GHz band.
- */
-enum iwl_geo_information {
- GEO_NO_INFO = 0,
- GEO_WMM_ETSI_5GHZ_INFO = BIT(0),
-};
+} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_3 */
/**
* struct iwl_mcc_update_resp - response to MCC_UPDATE_CMD.
@@ -347,25 +335,26 @@ enum iwl_geo_information {
* @status: see &enum iwl_mcc_update_status
* @mcc: the new applied MCC
* @cap: capabilities for all channels which matches the MCC
- * @source_id: the MCC source, see iwl_mcc_source
- * @time: time elapsed from the MCC test start (in 30 seconds TU)
+ * @time: time elapsed from the MCC test start (in units of 30 seconds)
* @geo_info: geographic specific profile information
* see &enum iwl_geo_information.
- * @n_channels: number of channels in @channels_data (may be 14, 39, 50 or 51
- * channels, depending on platform)
+ * @source_id: the MCC source, see iwl_mcc_source
+ * @reserved: for four bytes alignment.
+ * @n_channels: number of channels in @channels_data.
* @channels: channel control data map, DWORD for each channel. Only the first
* 16bits are used.
*/
struct iwl_mcc_update_resp {
__le32 status;
__le16 mcc;
- u8 cap;
- u8 source_id;
+ __le16 cap;
__le16 time;
__le16 geo_info;
+ u8 source_id;
+ u8 reserved[3];
__le32 n_channels;
__le32 channels[0];
-} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_3 */
+} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_4 */
/**
* struct iwl_mcc_chub_notif - chub notifies of mcc change
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
index 415b8842b426..0537496b6eb1 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
@@ -368,10 +368,10 @@ enum iwl_rx_he_phy {
/* trigger encoded */
IWL_RX_HE_PHY_RU_ALLOC_MASK = 0xfe0000000000ULL,
IWL_RX_HE_PHY_INFO_TYPE_MASK = 0xf000000000000000ULL,
- IWL_RX_HE_PHY_INFO_TYPE_SU = 0x0,
- IWL_RX_HE_PHY_INFO_TYPE_MU = 0x1,
- IWL_RX_HE_PHY_INFO_TYPE_MU_EXT_INFO = 0x2,
- IWL_RX_HE_PHY_INFO_TYPE_TB_EXT_INFO = 0x3,
+ IWL_RX_HE_PHY_INFO_TYPE_SU = 0x0, /* TSF low valid (first DW) */
+ IWL_RX_HE_PHY_INFO_TYPE_MU = 0x1, /* TSF low/high valid (both DWs) */
+ IWL_RX_HE_PHY_INFO_TYPE_MU_EXT_INFO = 0x2, /* same + SIGB-common0/1/2 valid */
+ IWL_RX_HE_PHY_INFO_TYPE_TB = 0x3, /* TSF low/high valid (both DWs) */
/* second dword - MU data */
IWL_RX_HE_PHY_MU_SIGB_COMPRESSION = BIT_ULL(32 + 0),
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
index 310b01e3cce1..18741889ec30 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
@@ -596,9 +596,12 @@ enum iwl_umac_scan_general_flags {
* enum iwl_umac_scan_general_flags2 - UMAC scan general flags #2
* @IWL_UMAC_SCAN_GEN_FLAGS2_NOTIF_PER_CHNL: Whether to send a complete
* notification per channel or not.
+ * @IWL_UMAC_SCAN_GEN_FLAGS2_ALLOW_CHNL_REORDER: Whether to allow channel
+ * reorder optimization or not.
*/
enum iwl_umac_scan_general_flags2 {
- IWL_UMAC_SCAN_GEN_FLAGS2_NOTIF_PER_CHNL = BIT(0),
+ IWL_UMAC_SCAN_GEN_FLAGS2_NOTIF_PER_CHNL = BIT(0),
+ IWL_UMAC_SCAN_GEN_FLAGS2_ALLOW_CHNL_REORDER = BIT(1),
};
/**
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index 0dcf1a673478..f44c716b1130 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -240,7 +240,7 @@ static void iwl_fw_dump_fifos(struct iwl_fw_runtime *fwrt,
if (!iwl_trans_grab_nic_access(fwrt->trans, &flags))
return;
- if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_RXF)) {
+ if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_RXF)) {
/* Pull RXF1 */
iwl_fwrt_dump_rxf(fwrt, dump_data,
cfg->lmac[0].rxfifo1_size, 0, 0);
@@ -254,7 +254,7 @@ static void iwl_fw_dump_fifos(struct iwl_fw_runtime *fwrt,
LMAC2_PRPH_OFFSET, 2);
}
- if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_TXF)) {
+ if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_TXF)) {
/* Pull TXF data from LMAC1 */
for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries; i++) {
/* Mark the number of TXF we're pulling now */
@@ -279,7 +279,7 @@ static void iwl_fw_dump_fifos(struct iwl_fw_runtime *fwrt,
}
}
- if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_INTERNAL_TXF) &&
+ if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_INTERNAL_TXF) &&
fw_has_capa(&fwrt->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) {
/* Pull UMAC internal TXF data from all TXFs */
@@ -573,103 +573,95 @@ static int iwl_fw_get_prph_len(struct iwl_fw_runtime *fwrt)
static void iwl_fw_dump_mem(struct iwl_fw_runtime *fwrt,
struct iwl_fw_error_dump_data **dump_data,
- u32 sram_len, u32 sram_ofs, u32 smem_len,
- u32 sram2_len)
+ u32 len, u32 ofs, u32 type)
{
- const struct iwl_fw_dbg_mem_seg_tlv *fw_dbg_mem = fwrt->fw->dbg_mem_tlv;
struct iwl_fw_error_dump_mem *dump_mem;
+
+ if (!len)
+ return;
+
+ (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
+ (*dump_data)->len = cpu_to_le32(len + sizeof(*dump_mem));
+ dump_mem = (void *)(*dump_data)->data;
+ dump_mem->type = cpu_to_le32(type);
+ dump_mem->offset = cpu_to_le32(ofs);
+ iwl_trans_read_mem_bytes(fwrt->trans, ofs, dump_mem->data, len);
+ *dump_data = iwl_fw_error_next_data(*dump_data);
+
+ IWL_DEBUG_INFO(fwrt, "WRT memory dump. Type=%u\n", dump_mem->type);
+}
+
+#define ADD_LEN(len, item_len, const_len) \
+ do {size_t item = item_len; len += (!!item) * const_len + item; } \
+ while (0)
+
+static int iwl_fw_fifo_len(struct iwl_fw_runtime *fwrt,
+ struct iwl_fwrt_shared_mem_cfg *mem_cfg)
+{
+ size_t hdr_len = sizeof(struct iwl_fw_error_dump_data) +
+ sizeof(struct iwl_fw_error_dump_fifo);
+ u32 fifo_len = 0;
int i;
- if (!fwrt->fw->n_dbg_mem_tlv) {
- (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
- (*dump_data)->len = cpu_to_le32(sram_len + sizeof(*dump_mem));
- dump_mem = (void *)(*dump_data)->data;
- dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_SRAM);
- dump_mem->offset = cpu_to_le32(sram_ofs);
- iwl_trans_read_mem_bytes(fwrt->trans, sram_ofs, dump_mem->data,
- sram_len);
- *dump_data = iwl_fw_error_next_data(*dump_data);
- }
+ if (!(fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_RXF)))
+ goto dump_txf;
- for (i = 0; i < fwrt->fw->n_dbg_mem_tlv; i++) {
- u32 len = le32_to_cpu(fw_dbg_mem[i].len);
- u32 ofs = le32_to_cpu(fw_dbg_mem[i].ofs);
+ /* Count RXF2 size */
+ ADD_LEN(fifo_len, mem_cfg->rxfifo2_size, hdr_len);
- (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
- (*dump_data)->len = cpu_to_le32(len + sizeof(*dump_mem));
- dump_mem = (void *)(*dump_data)->data;
- dump_mem->type = fw_dbg_mem[i].data_type;
- dump_mem->offset = cpu_to_le32(ofs);
+ /* Count RXF1 sizes */
+ for (i = 0; i < mem_cfg->num_lmacs; i++)
+ ADD_LEN(fifo_len, mem_cfg->lmac[i].rxfifo1_size, hdr_len);
- IWL_DEBUG_INFO(fwrt, "WRT memory dump. Type=%u\n",
- dump_mem->type);
+dump_txf:
+ if (!(fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_TXF)))
+ goto dump_internal_txf;
- iwl_trans_read_mem_bytes(fwrt->trans, ofs, dump_mem->data, len);
- *dump_data = iwl_fw_error_next_data(*dump_data);
- }
+ /* Count TXF sizes */
+ for (i = 0; i < mem_cfg->num_lmacs; i++) {
+ int j;
- if (smem_len) {
- IWL_DEBUG_INFO(fwrt, "WRT SMEM dump\n");
- (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
- (*dump_data)->len = cpu_to_le32(smem_len + sizeof(*dump_mem));
- dump_mem = (void *)(*dump_data)->data;
- dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_SMEM);
- dump_mem->offset = cpu_to_le32(fwrt->trans->cfg->smem_offset);
- iwl_trans_read_mem_bytes(fwrt->trans,
- fwrt->trans->cfg->smem_offset,
- dump_mem->data, smem_len);
- *dump_data = iwl_fw_error_next_data(*dump_data);
+ for (j = 0; j < mem_cfg->num_txfifo_entries; j++)
+ ADD_LEN(fifo_len, mem_cfg->lmac[i].txfifo_size[j],
+ hdr_len);
}
- if (sram2_len) {
- IWL_DEBUG_INFO(fwrt, "WRT SRAM dump\n");
- (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
- (*dump_data)->len = cpu_to_le32(sram2_len + sizeof(*dump_mem));
- dump_mem = (void *)(*dump_data)->data;
- dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_SRAM);
- dump_mem->offset = cpu_to_le32(fwrt->trans->cfg->dccm2_offset);
- iwl_trans_read_mem_bytes(fwrt->trans,
- fwrt->trans->cfg->dccm2_offset,
- dump_mem->data, sram2_len);
- *dump_data = iwl_fw_error_next_data(*dump_data);
- }
+dump_internal_txf:
+ if (!((fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_INTERNAL_TXF)) &&
+ fw_has_capa(&fwrt->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)))
+ goto out;
+
+ for (i = 0; i < ARRAY_SIZE(mem_cfg->internal_txfifo_size); i++)
+ ADD_LEN(fifo_len, mem_cfg->internal_txfifo_size[i], hdr_len);
+
+out:
+ return fifo_len;
}
-void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
+static struct iwl_fw_error_dump_file *
+_iwl_fw_error_dump(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_dump_ptrs *fw_error_dump)
{
struct iwl_fw_error_dump_file *dump_file;
struct iwl_fw_error_dump_data *dump_data;
struct iwl_fw_error_dump_info *dump_info;
struct iwl_fw_error_dump_smem_cfg *dump_smem_cfg;
struct iwl_fw_error_dump_trigger_desc *dump_trig;
- struct iwl_fw_dump_ptrs *fw_error_dump;
- struct scatterlist *sg_dump_data;
u32 sram_len, sram_ofs;
- const struct iwl_fw_dbg_mem_seg_tlv *fw_dbg_mem = fwrt->fw->dbg_mem_tlv;
+ const struct iwl_fw_dbg_mem_seg_tlv *fw_mem = fwrt->fw->dbg.mem_tlv;
struct iwl_fwrt_shared_mem_cfg *mem_cfg = &fwrt->smem_cfg;
- u32 file_len, fifo_data_len = 0, prph_len = 0, radio_len = 0;
- u32 smem_len = fwrt->fw->n_dbg_mem_tlv ? 0 : fwrt->trans->cfg->smem_len;
- u32 sram2_len = fwrt->fw->n_dbg_mem_tlv ?
+ u32 file_len, fifo_len = 0, prph_len = 0, radio_len = 0;
+ u32 smem_len = fwrt->fw->dbg.n_mem_tlv ? 0 : fwrt->trans->cfg->smem_len;
+ u32 sram2_len = fwrt->fw->dbg.n_mem_tlv ?
0 : fwrt->trans->cfg->dccm2_len;
bool monitor_dump_only = false;
int i;
- IWL_DEBUG_INFO(fwrt, "WRT dump start\n");
-
- /* there's no point in fw dump if the bus is dead */
- if (test_bit(STATUS_TRANS_DEAD, &fwrt->trans->status)) {
- IWL_ERR(fwrt, "Skip fw error dump since bus is dead\n");
- goto out;
- }
-
if (fwrt->dump.trig &&
fwrt->dump.trig->mode & IWL_FW_DBG_TRIGGER_MONITOR_ONLY)
monitor_dump_only = true;
- fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL);
- if (!fw_error_dump)
- goto out;
-
/* SRAM - include stack CCM if driver knows the values for it */
if (!fwrt->trans->cfg->dccm_offset || !fwrt->trans->cfg->dccm_len) {
const struct fw_img *img;
@@ -684,112 +676,43 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
/* reading RXF/TXF sizes */
if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status)) {
- fifo_data_len = 0;
-
- if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_RXF)) {
-
- /* Count RXF2 size */
- if (mem_cfg->rxfifo2_size) {
- /* Add header info */
- fifo_data_len +=
- mem_cfg->rxfifo2_size +
- sizeof(*dump_data) +
- sizeof(struct iwl_fw_error_dump_fifo);
- }
-
- /* Count RXF1 sizes */
- for (i = 0; i < mem_cfg->num_lmacs; i++) {
- if (!mem_cfg->lmac[i].rxfifo1_size)
- continue;
-
- /* Add header info */
- fifo_data_len +=
- mem_cfg->lmac[i].rxfifo1_size +
- sizeof(*dump_data) +
- sizeof(struct iwl_fw_error_dump_fifo);
- }
- }
-
- if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_TXF)) {
- size_t fifo_const_len = sizeof(*dump_data) +
- sizeof(struct iwl_fw_error_dump_fifo);
-
- /* Count TXF sizes */
- for (i = 0; i < mem_cfg->num_lmacs; i++) {
- int j;
-
- for (j = 0; j < mem_cfg->num_txfifo_entries;
- j++) {
- if (!mem_cfg->lmac[i].txfifo_size[j])
- continue;
-
- /* Add header info */
- fifo_data_len +=
- fifo_const_len +
- mem_cfg->lmac[i].txfifo_size[j];
- }
- }
- }
-
- if ((fwrt->fw->dbg_dump_mask &
- BIT(IWL_FW_ERROR_DUMP_INTERNAL_TXF)) &&
- fw_has_capa(&fwrt->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) {
- for (i = 0;
- i < ARRAY_SIZE(mem_cfg->internal_txfifo_size);
- i++) {
- if (!mem_cfg->internal_txfifo_size[i])
- continue;
-
- /* Add header info */
- fifo_data_len +=
- mem_cfg->internal_txfifo_size[i] +
- sizeof(*dump_data) +
- sizeof(struct iwl_fw_error_dump_fifo);
- }
- }
+ fifo_len = iwl_fw_fifo_len(fwrt, mem_cfg);
/* Make room for PRPH registers */
if (!fwrt->trans->cfg->gen2 &&
- fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_PRPH))
+ fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_PRPH))
prph_len += iwl_fw_get_prph_len(fwrt);
if (fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_7000 &&
- fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_RADIO_REG))
+ fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_RADIO_REG))
radio_len = sizeof(*dump_data) + RADIO_REG_MAX_READ;
}
- file_len = sizeof(*dump_file) +
- fifo_data_len +
- prph_len +
- radio_len;
+ file_len = sizeof(*dump_file) + fifo_len + prph_len + radio_len;
- if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_DEV_FW_INFO))
+ if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_DEV_FW_INFO))
file_len += sizeof(*dump_data) + sizeof(*dump_info);
- if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM_CFG))
+ if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM_CFG))
file_len += sizeof(*dump_data) + sizeof(*dump_smem_cfg);
- if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM)) {
- /* Make room for the SMEM, if it exists */
- if (smem_len)
- file_len += sizeof(*dump_data) + smem_len +
- sizeof(struct iwl_fw_error_dump_mem);
-
- /* Make room for the secondary SRAM, if it exists */
- if (sram2_len)
- file_len += sizeof(*dump_data) + sram2_len +
- sizeof(struct iwl_fw_error_dump_mem);
-
- /* Make room for MEM segments */
- for (i = 0; i < fwrt->fw->n_dbg_mem_tlv; i++) {
- file_len += sizeof(*dump_data) +
- le32_to_cpu(fw_dbg_mem[i].len) +
- sizeof(struct iwl_fw_error_dump_mem);
- }
+ if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM)) {
+ size_t hdr_len = sizeof(*dump_data) +
+ sizeof(struct iwl_fw_error_dump_mem);
+
+ /* Dump SRAM only if no mem_tlvs */
+ if (!fwrt->fw->dbg.n_mem_tlv)
+ ADD_LEN(file_len, sram_len, hdr_len);
+
+ /* Make room for all mem types that exist */
+ ADD_LEN(file_len, smem_len, hdr_len);
+ ADD_LEN(file_len, sram2_len, hdr_len);
+
+ for (i = 0; i < fwrt->fw->dbg.n_mem_tlv; i++)
+ ADD_LEN(file_len, le32_to_cpu(fw_mem[i].len), hdr_len);
}
/* Make room for fw's virtual image pages, if it exists */
- if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING) &&
+ if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING) &&
!fwrt->trans->cfg->gen2 &&
fwrt->fw->img[fwrt->cur_fw_img].paging_mem_size &&
fwrt->fw_paging_db[0].fw_paging_block)
@@ -809,28 +732,21 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
sizeof(*dump_info) + sizeof(*dump_smem_cfg);
}
- if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_ERROR_INFO) &&
+ if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_ERROR_INFO) &&
fwrt->dump.desc)
file_len += sizeof(*dump_data) + sizeof(*dump_trig) +
fwrt->dump.desc->len;
- if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM) &&
- !fwrt->fw->n_dbg_mem_tlv)
- file_len += sizeof(*dump_data) + sram_len +
- sizeof(struct iwl_fw_error_dump_mem);
-
dump_file = vzalloc(file_len);
- if (!dump_file) {
- kfree(fw_error_dump);
- goto out;
- }
+ if (!dump_file)
+ return NULL;
fw_error_dump->fwrt_ptr = dump_file;
dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER);
dump_data = (void *)dump_file->data;
- if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_DEV_FW_INFO)) {
+ if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_DEV_FW_INFO)) {
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO);
dump_data->len = cpu_to_le32(sizeof(*dump_info));
dump_info = (void *)dump_data->data;
@@ -851,7 +767,7 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
dump_data = iwl_fw_error_next_data(dump_data);
}
- if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM_CFG)) {
+ if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM_CFG)) {
/* Dump shared memory configuration */
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_CFG);
dump_data->len = cpu_to_le32(sizeof(*dump_smem_cfg));
@@ -882,13 +798,13 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
}
/* We only dump the FIFOs if the FW is in error state */
- if (fifo_data_len) {
+ if (fifo_len) {
iwl_fw_dump_fifos(fwrt, &dump_data);
if (radio_len)
iwl_read_radio_regs(fwrt, &dump_data);
}
- if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_ERROR_INFO) &&
+ if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_ERROR_INFO) &&
fwrt->dump.desc) {
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_ERROR_INFO);
dump_data->len = cpu_to_le32(sizeof(*dump_trig) +
@@ -902,12 +818,32 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
/* In case we only want monitor dump, skip to dump trasport data */
if (monitor_dump_only)
- goto dump_trans_data;
+ goto out;
- if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM))
- iwl_fw_dump_mem(fwrt, &dump_data, sram_len, sram_ofs, smem_len,
- sram2_len);
+ if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM)) {
+ const struct iwl_fw_dbg_mem_seg_tlv *fw_dbg_mem =
+ fwrt->fw->dbg.mem_tlv;
+ if (!fwrt->fw->dbg.n_mem_tlv)
+ iwl_fw_dump_mem(fwrt, &dump_data, sram_len, sram_ofs,
+ IWL_FW_ERROR_DUMP_MEM_SRAM);
+
+ for (i = 0; i < fwrt->fw->dbg.n_mem_tlv; i++) {
+ u32 len = le32_to_cpu(fw_dbg_mem[i].len);
+ u32 ofs = le32_to_cpu(fw_dbg_mem[i].ofs);
+
+ iwl_fw_dump_mem(fwrt, &dump_data, len, ofs,
+ le32_to_cpu(fw_dbg_mem[i].data_type));
+ }
+
+ iwl_fw_dump_mem(fwrt, &dump_data, smem_len,
+ fwrt->trans->cfg->smem_offset,
+ IWL_FW_ERROR_DUMP_MEM_SMEM);
+
+ iwl_fw_dump_mem(fwrt, &dump_data, sram2_len,
+ fwrt->trans->cfg->dccm2_offset,
+ IWL_FW_ERROR_DUMP_MEM_SRAM);
+ }
if (iwl_fw_dbg_is_d3_debug_enabled(fwrt) && fwrt->dump.d3_debug_data) {
u32 addr = fwrt->trans->cfg->d3_debug_data_base_addr;
@@ -929,7 +865,7 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
}
/* Dump fw's virtual image */
- if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING) &&
+ if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING) &&
!fwrt->trans->cfg->gen2 &&
fwrt->fw->img[fwrt->cur_fw_img].paging_mem_size &&
fwrt->fw_paging_db[0].fw_paging_block) {
@@ -965,13 +901,44 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
ARRAY_SIZE(iwl_prph_dump_addr_9000));
}
-dump_trans_data:
+out:
+ dump_file->file_len = cpu_to_le32(file_len);
+ return dump_file;
+}
+
+void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
+{
+ struct iwl_fw_dump_ptrs *fw_error_dump;
+ struct iwl_fw_error_dump_file *dump_file;
+ struct scatterlist *sg_dump_data;
+ u32 file_len;
+
+ IWL_DEBUG_INFO(fwrt, "WRT dump start\n");
+
+ /* there's no point in fw dump if the bus is dead */
+ if (test_bit(STATUS_TRANS_DEAD, &fwrt->trans->status)) {
+ IWL_ERR(fwrt, "Skip fw error dump since bus is dead\n");
+ goto out;
+ }
+
+ fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL);
+ if (!fw_error_dump)
+ goto out;
+
+ dump_file = _iwl_fw_error_dump(fwrt, fw_error_dump);
+ if (!dump_file) {
+ kfree(fw_error_dump);
+ goto out;
+ }
+
fw_error_dump->trans_ptr = iwl_trans_dump_data(fwrt->trans,
fwrt->dump.trig);
+ file_len = le32_to_cpu(dump_file->file_len);
fw_error_dump->fwrt_len = file_len;
- if (fw_error_dump->trans_ptr)
+ if (fw_error_dump->trans_ptr) {
file_len += fw_error_dump->trans_ptr->len;
- dump_file->file_len = cpu_to_le32(file_len);
+ dump_file->file_len = cpu_to_le32(file_len);
+ }
sg_dump_data = alloc_sgtable(file_len);
if (sg_dump_data) {
@@ -1006,15 +973,34 @@ const struct iwl_fw_dump_desc iwl_dump_desc_assert = {
};
IWL_EXPORT_SYMBOL(iwl_dump_desc_assert);
-int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
- const struct iwl_fw_dump_desc *desc,
- const struct iwl_fw_dbg_trigger_tlv *trigger)
+void iwl_fw_alive_error_dump(struct iwl_fw_runtime *fwrt)
{
- unsigned int delay = 0;
+ struct iwl_fw_dump_desc *iwl_dump_desc_no_alive =
+ kmalloc(sizeof(*iwl_dump_desc_no_alive), GFP_KERNEL);
- if (trigger)
- delay = msecs_to_jiffies(le32_to_cpu(trigger->stop_delay));
+ if (!iwl_dump_desc_no_alive)
+ return;
+
+ iwl_dump_desc_no_alive->trig_desc.type =
+ cpu_to_le32(FW_DBG_TRIGGER_NO_ALIVE);
+ iwl_dump_desc_no_alive->len = 0;
+
+ if (WARN_ON(fwrt->dump.desc))
+ iwl_fw_free_dump_desc(fwrt);
+
+ IWL_WARN(fwrt, "Collecting data: trigger %d fired.\n",
+ FW_DBG_TRIGGER_NO_ALIVE);
+ fwrt->dump.desc = iwl_dump_desc_no_alive;
+ iwl_fw_error_dump(fwrt);
+ clear_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &fwrt->status);
+}
+IWL_EXPORT_SYMBOL(iwl_fw_alive_error_dump);
+
+int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
+ const struct iwl_fw_dump_desc *desc, void *trigger,
+ unsigned int delay)
+{
/*
* If the loading of the FW completed successfully, the next step is to
* get the SMEM config data. Thus, if fwrt->smem_cfg.num_lmacs is non
@@ -1031,7 +1017,8 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
fwrt->smem_cfg.num_lmacs)
return -EIO;
- if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status))
+ if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status) ||
+ test_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &fwrt->status))
return -EBUSY;
if (WARN_ON(fwrt->dump.desc))
@@ -1052,25 +1039,38 @@ IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect_desc);
int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
enum iwl_fw_dbg_trigger trig,
const char *str, size_t len,
- const struct iwl_fw_dbg_trigger_tlv *trigger)
+ struct iwl_fw_dbg_trigger_tlv *trigger)
{
struct iwl_fw_dump_desc *desc;
+ unsigned int delay = 0;
- if (trigger && trigger->flags & IWL_FW_DBG_FORCE_RESTART) {
- IWL_WARN(fwrt, "Force restart: trigger %d fired.\n", trig);
- iwl_force_nmi(fwrt->trans);
- return 0;
+ if (trigger) {
+ u16 occurrences = le16_to_cpu(trigger->occurrences) - 1;
+
+ if (!le16_to_cpu(trigger->occurrences))
+ return 0;
+
+ if (trigger->flags & IWL_FW_DBG_FORCE_RESTART) {
+ IWL_WARN(fwrt, "Force restart: trigger %d fired.\n",
+ trig);
+ iwl_force_nmi(fwrt->trans);
+ return 0;
+ }
+
+ trigger->occurrences = cpu_to_le16(occurrences);
+ delay = le16_to_cpu(trigger->trig_dis_ms);
}
desc = kzalloc(sizeof(*desc) + len, GFP_ATOMIC);
if (!desc)
return -ENOMEM;
+
desc->len = len;
desc->trig_desc.type = cpu_to_le32(trig);
memcpy(desc->trig_desc.data, str, len);
- return iwl_fw_dbg_collect_desc(fwrt, desc, trigger);
+ return iwl_fw_dbg_collect_desc(fwrt, desc, trigger, delay);
}
IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect);
@@ -1078,13 +1078,9 @@ int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dbg_trigger_tlv *trigger,
const char *fmt, ...)
{
- u16 occurrences = le16_to_cpu(trigger->occurrences);
int ret, len = 0;
char buf[64];
- if (!occurrences)
- return 0;
-
if (fmt) {
va_list ap;
@@ -1107,7 +1103,6 @@ int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt,
if (ret)
return ret;
- trigger->occurrences = cpu_to_le16(occurrences - 1);
return 0;
}
IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect_trig);
@@ -1118,17 +1113,17 @@ int iwl_fw_start_dbg_conf(struct iwl_fw_runtime *fwrt, u8 conf_id)
int ret;
int i;
- if (WARN_ONCE(conf_id >= ARRAY_SIZE(fwrt->fw->dbg_conf_tlv),
+ if (WARN_ONCE(conf_id >= ARRAY_SIZE(fwrt->fw->dbg.conf_tlv),
"Invalid configuration %d\n", conf_id))
return -EINVAL;
/* EARLY START - firmware's configuration is hard coded */
- if ((!fwrt->fw->dbg_conf_tlv[conf_id] ||
- !fwrt->fw->dbg_conf_tlv[conf_id]->num_of_hcmds) &&
+ if ((!fwrt->fw->dbg.conf_tlv[conf_id] ||
+ !fwrt->fw->dbg.conf_tlv[conf_id]->num_of_hcmds) &&
conf_id == FW_DBG_START_FROM_ALIVE)
return 0;
- if (!fwrt->fw->dbg_conf_tlv[conf_id])
+ if (!fwrt->fw->dbg.conf_tlv[conf_id])
return -EINVAL;
if (fwrt->dump.conf != FW_DBG_INVALID)
@@ -1136,8 +1131,8 @@ int iwl_fw_start_dbg_conf(struct iwl_fw_runtime *fwrt, u8 conf_id)
fwrt->dump.conf);
/* Send all HCMDs for configuring the FW debug */
- ptr = (void *)&fwrt->fw->dbg_conf_tlv[conf_id]->hcmd;
- for (i = 0; i < fwrt->fw->dbg_conf_tlv[conf_id]->num_of_hcmds; i++) {
+ ptr = (void *)&fwrt->fw->dbg.conf_tlv[conf_id]->hcmd;
+ for (i = 0; i < fwrt->fw->dbg.conf_tlv[conf_id]->num_of_hcmds; i++) {
struct iwl_fw_dbg_conf_hcmd *cmd = (void *)ptr;
struct iwl_host_cmd hcmd = {
.id = cmd->id,
@@ -1183,7 +1178,7 @@ void iwl_fw_error_dump_wk(struct work_struct *work)
/* start recording again if the firmware is not crashed */
if (!test_bit(STATUS_FW_ERROR, &fwrt->trans->status) &&
- fwrt->fw->dbg_dest_tlv) {
+ fwrt->fw->dbg.dest_tlv) {
/* wait before we collect the data till the DBGC stop */
udelay(500);
iwl_fw_dbg_restart_recording(fwrt, &params);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
index 3c89230fae6a..d9578dcec24c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
@@ -107,25 +107,25 @@ static inline void iwl_fw_free_dump_desc(struct iwl_fw_runtime *fwrt)
void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt);
int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
const struct iwl_fw_dump_desc *desc,
- const struct iwl_fw_dbg_trigger_tlv *trigger);
+ void *trigger, unsigned int delay);
int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
enum iwl_fw_dbg_trigger trig,
const char *str, size_t len,
- const struct iwl_fw_dbg_trigger_tlv *trigger);
+ struct iwl_fw_dbg_trigger_tlv *trigger);
int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dbg_trigger_tlv *trigger,
const char *fmt, ...) __printf(3, 4);
int iwl_fw_start_dbg_conf(struct iwl_fw_runtime *fwrt, u8 id);
#define iwl_fw_dbg_trigger_enabled(fw, id) ({ \
- void *__dbg_trigger = (fw)->dbg_trigger_tlv[(id)]; \
+ void *__dbg_trigger = (fw)->dbg.trigger_tlv[(id)]; \
unlikely(__dbg_trigger); \
})
static inline struct iwl_fw_dbg_trigger_tlv*
_iwl_fw_dbg_get_trigger(const struct iwl_fw *fw, enum iwl_fw_dbg_trigger id)
{
- return fw->dbg_trigger_tlv[id];
+ return fw->dbg.trigger_tlv[id];
}
#define iwl_fw_dbg_get_trigger(fw, id) ({ \
@@ -154,12 +154,9 @@ iwl_fw_dbg_trigger_stop_conf_match(struct iwl_fw_runtime *fwrt,
}
static inline bool
-iwl_fw_dbg_no_trig_window(struct iwl_fw_runtime *fwrt,
- struct iwl_fw_dbg_trigger_tlv *trig)
+iwl_fw_dbg_no_trig_window(struct iwl_fw_runtime *fwrt, u32 id, u32 dis_ms)
{
- unsigned long wind_jiff =
- msecs_to_jiffies(le16_to_cpu(trig->trig_dis_ms));
- u32 id = le32_to_cpu(trig->id);
+ unsigned long wind_jiff = msecs_to_jiffies(dis_ms);
/* If this is the first event checked, jump to update start ts */
if (fwrt->dump.non_collect_ts_start[id] &&
@@ -179,7 +176,8 @@ iwl_fw_dbg_trigger_check_stop(struct iwl_fw_runtime *fwrt,
if (wdev && !iwl_fw_dbg_trigger_vif_match(trig, wdev))
return false;
- if (iwl_fw_dbg_no_trig_window(fwrt, trig)) {
+ if (iwl_fw_dbg_no_trig_window(fwrt, le32_to_cpu(trig->id),
+ le16_to_cpu(trig->trig_dis_ms))) {
IWL_WARN(fwrt, "Trigger %d occurred while no-collect window.\n",
trig->id);
return false;
@@ -188,6 +186,30 @@ iwl_fw_dbg_trigger_check_stop(struct iwl_fw_runtime *fwrt,
return iwl_fw_dbg_trigger_stop_conf_match(fwrt, trig);
}
+static inline struct iwl_fw_dbg_trigger_tlv*
+_iwl_fw_dbg_trigger_on(struct iwl_fw_runtime *fwrt,
+ struct wireless_dev *wdev,
+ const enum iwl_fw_dbg_trigger id)
+{
+ struct iwl_fw_dbg_trigger_tlv *trig;
+
+ if (!iwl_fw_dbg_trigger_enabled(fwrt->fw, id))
+ return NULL;
+
+ trig = _iwl_fw_dbg_get_trigger(fwrt->fw, id);
+
+ if (!iwl_fw_dbg_trigger_check_stop(fwrt, wdev, trig))
+ return NULL;
+
+ return trig;
+}
+
+#define iwl_fw_dbg_trigger_on(fwrt, wdev, id) ({ \
+ BUILD_BUG_ON(!__builtin_constant_p(id)); \
+ BUILD_BUG_ON((id) >= FW_DBG_TRIGGER_MAX); \
+ _iwl_fw_dbg_trigger_on((fwrt), (wdev), (id)); \
+})
+
static inline void
_iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt,
struct wireless_dev *wdev,
@@ -293,7 +315,7 @@ static inline bool iwl_fw_dbg_is_d3_debug_enabled(struct iwl_fw_runtime *fwrt)
return fw_has_capa(&fwrt->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_D3_DEBUG) &&
fwrt->trans->cfg->d3_debug_data_length &&
- fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_D3_DEBUG_DATA);
+ fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_D3_DEBUG_DATA);
}
void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt);
@@ -344,4 +366,5 @@ static inline void iwl_fw_resume_timestamp(struct iwl_fw_runtime *fwrt) {}
#endif /* CONFIG_IWLWIFI_DEBUGFS */
+void iwl_fw_alive_error_dump(struct iwl_fw_runtime *fwrt);
#endif /* __iwl_fw_dbg_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c
index 1049bdfe1e69..3e120dd47305 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c
@@ -258,11 +258,75 @@ static ssize_t iwl_dbgfs_timestamp_marker_read(struct iwl_fw_runtime *fwrt,
FWRT_DEBUGFS_READ_WRITE_FILE_OPS(timestamp_marker, 16);
+struct hcmd_write_data {
+ __be32 cmd_id;
+ __be32 flags;
+ __be16 length;
+ u8 data[0];
+} __packed;
+
+static ssize_t iwl_dbgfs_send_hcmd_write(struct iwl_fw_runtime *fwrt, char *buf,
+ size_t count)
+{
+ size_t header_size = (sizeof(u32) * 2 + sizeof(u16)) * 2;
+ size_t data_size = (count - 1) / 2;
+ int ret;
+ struct hcmd_write_data *data;
+ struct iwl_host_cmd hcmd = {
+ .len = { 0, },
+ .data = { NULL, },
+ };
+
+ if (fwrt->ops && fwrt->ops->fw_running &&
+ !fwrt->ops->fw_running(fwrt->ops_ctx))
+ return -EIO;
+
+ if (count < header_size + 1 || count > 1024 * 4)
+ return -EINVAL;
+
+ data = kmalloc(data_size, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ ret = hex2bin((u8 *)data, buf, data_size);
+ if (ret)
+ goto out;
+
+ hcmd.id = be32_to_cpu(data->cmd_id);
+ hcmd.flags = be32_to_cpu(data->flags);
+ hcmd.len[0] = be16_to_cpu(data->length);
+ hcmd.data[0] = data->data;
+
+ if (count != header_size + hcmd.len[0] * 2 + 1) {
+ IWL_ERR(fwrt,
+ "host command data size does not match header length\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (fwrt->ops && fwrt->ops->send_hcmd)
+ ret = fwrt->ops->send_hcmd(fwrt->ops_ctx, &hcmd);
+ else
+ ret = -EPERM;
+
+ if (ret < 0)
+ goto out;
+
+ if (hcmd.flags & CMD_WANT_SKB)
+ iwl_free_resp(&hcmd);
+out:
+ kfree(data);
+ return ret ?: count;
+}
+
+FWRT_DEBUGFS_WRITE_FILE_OPS(send_hcmd, 512);
+
int iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt,
struct dentry *dbgfs_dir)
{
INIT_DELAYED_WORK(&fwrt->timestamp.wk, iwl_fw_timestamp_marker_wk);
FWRT_DEBUGFS_ADD_FILE(timestamp_marker, dbgfs_dir, 0200);
+ FWRT_DEBUGFS_ADD_FILE(send_hcmd, dbgfs_dir, 0200);
return 0;
err:
IWL_ERR(fwrt, "Can't create the fwrt debugfs directory\n");
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
index 6d3ef331b7d5..6fede174c664 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
@@ -328,6 +328,7 @@ iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data)
* @FW_DBG_TDLS: trigger log collection upon TDLS related events.
* @FW_DBG_TRIGGER_TX_STATUS: trigger log collection upon tx status when
* the firmware sends a tx reply.
+ * @FW_DBG_TRIGGER_NO_ALIVE: trigger log collection if alive flow fails
*/
enum iwl_fw_dbg_trigger {
FW_DBG_TRIGGER_INVALID = 0,
@@ -345,6 +346,7 @@ enum iwl_fw_dbg_trigger {
FW_DBG_TRIGGER_TX_LATENCY,
FW_DBG_TRIGGER_TDLS,
FW_DBG_TRIGGER_TX_STATUS,
+ FW_DBG_TRIGGER_NO_ALIVE,
/* must be last */
FW_DBG_TRIGGER_MAX,
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h
index 63e277b07b8a..6005a41c53d1 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/file.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h
@@ -337,7 +337,7 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
* antenna the beacon should be transmitted
* @IWL_UCODE_TLV_CAPA_BEACON_STORING: firmware will store the latest beacon
* from AP and will send it upon d0i3 exit.
- * @IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V2: support LAR API V2
+ * @IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V3: support LAR API V3
* @IWL_UCODE_TLV_CAPA_CT_KILL_BY_FW: firmware responsible for CT-kill
* @IWL_UCODE_TLV_CAPA_TEMP_THS_REPORT_SUPPORT: supports temperature
* thresholds reporting
@@ -352,6 +352,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
* power reduction.
* @IWL_UCODE_TLV_CAPA_MLME_OFFLOAD: supports MLME offload
* @IWL_UCODE_TLV_CAPA_D3_DEBUG: supports debug recording during D3
+ * @IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT: MCC response support 11ax
+ * capability.
*
* @NUM_IWL_UCODE_TLV_CAPA: number of bits used
*/
@@ -392,7 +394,7 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_CSA_AND_TBTT_OFFLOAD = (__force iwl_ucode_tlv_capa_t)70,
IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION = (__force iwl_ucode_tlv_capa_t)71,
IWL_UCODE_TLV_CAPA_BEACON_STORING = (__force iwl_ucode_tlv_capa_t)72,
- IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V2 = (__force iwl_ucode_tlv_capa_t)73,
+ IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V3 = (__force iwl_ucode_tlv_capa_t)73,
IWL_UCODE_TLV_CAPA_CT_KILL_BY_FW = (__force iwl_ucode_tlv_capa_t)74,
IWL_UCODE_TLV_CAPA_TEMP_THS_REPORT_SUPPORT = (__force iwl_ucode_tlv_capa_t)75,
IWL_UCODE_TLV_CAPA_CTDP_SUPPORT = (__force iwl_ucode_tlv_capa_t)76,
@@ -402,6 +404,7 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_TX_POWER_ACK = (__force iwl_ucode_tlv_capa_t)84,
IWL_UCODE_TLV_CAPA_D3_DEBUG = (__force iwl_ucode_tlv_capa_t)87,
IWL_UCODE_TLV_CAPA_LED_CMD_SUPPORT = (__force iwl_ucode_tlv_capa_t)88,
+ IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT = (__force iwl_ucode_tlv_capa_t)89,
IWL_UCODE_TLV_CAPA_MLME_OFFLOAD = (__force iwl_ucode_tlv_capa_t)96,
NUM_IWL_UCODE_TLV_CAPA
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.h b/drivers/net/wireless/intel/iwlwifi/fw/img.h
index 9cc8fe8908ac..54dbbd998abf 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/img.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/img.h
@@ -198,6 +198,29 @@ enum iwl_fw_type {
};
/**
+ * struct iwl_fw_dbg - debug data
+ *
+ * @dest_tlv: points to debug destination TLV (typically SRAM or DRAM)
+ * @n_dest_reg: num of reg_ops in dest_tlv
+ * @conf_tlv: array of pointers to configuration HCMDs
+ * @trigger_tlv: array of pointers to triggers TLVs
+ * @trigger_tlv_len: lengths of the @dbg_trigger_tlv entries
+ * @mem_tlv: Runtime addresses to dump
+ * @n_mem_tlv: number of runtime addresses
+ * @dump_mask: bitmask of dump regions
+*/
+struct iwl_fw_dbg {
+ struct iwl_fw_dbg_dest_tlv_v1 *dest_tlv;
+ u8 n_dest_reg;
+ struct iwl_fw_dbg_conf_tlv *conf_tlv[FW_DBG_CONF_MAX];
+ struct iwl_fw_dbg_trigger_tlv *trigger_tlv[FW_DBG_TRIGGER_MAX];
+ size_t trigger_tlv_len[FW_DBG_TRIGGER_MAX];
+ struct iwl_fw_dbg_mem_seg_tlv *mem_tlv;
+ size_t n_mem_tlv;
+ u32 dump_mask;
+};
+
+/**
* struct iwl_fw - variables associated with the firmware
*
* @ucode_ver: ucode version from the ucode file
@@ -217,12 +240,6 @@ enum iwl_fw_type {
* @cipher_scheme: optional external cipher scheme.
* @human_readable: human readable version
* we get the ALIVE from the uCode
- * @dbg_dest_tlv: points to the destination TLV for debug
- * @dbg_conf_tlv: array of pointers to configuration TLVs for debug
- * @dbg_conf_tlv_len: lengths of the @dbg_conf_tlv entries
- * @dbg_trigger_tlv: array of pointers to triggers TLVs
- * @dbg_trigger_tlv_len: lengths of the @dbg_trigger_tlv entries
- * @dbg_dest_reg_num: num of reg_ops in %dbg_dest_tlv
*/
struct iwl_fw {
u32 ucode_ver;
@@ -250,15 +267,7 @@ struct iwl_fw {
struct iwl_fw_cipher_scheme cs[IWL_UCODE_MAX_CS];
u8 human_readable[FW_VER_HUMAN_READABLE_SZ];
- struct iwl_fw_dbg_dest_tlv_v1 *dbg_dest_tlv;
- struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX];
- size_t dbg_conf_tlv_len[FW_DBG_CONF_MAX];
- struct iwl_fw_dbg_trigger_tlv *dbg_trigger_tlv[FW_DBG_TRIGGER_MAX];
- struct iwl_fw_dbg_mem_seg_tlv *dbg_mem_tlv;
- size_t n_dbg_mem_tlv;
- size_t dbg_trigger_tlv_len[FW_DBG_TRIGGER_MAX];
- u8 dbg_dest_reg_num;
- u32 dbg_dump_mask;
+ struct iwl_fw_dbg dbg;
};
static inline const char *get_fw_dbg_mode_string(int mode)
@@ -280,7 +289,7 @@ static inline const char *get_fw_dbg_mode_string(int mode)
static inline bool
iwl_fw_dbg_conf_usniffer(const struct iwl_fw *fw, u8 id)
{
- const struct iwl_fw_dbg_conf_tlv *conf_tlv = fw->dbg_conf_tlv[id];
+ const struct iwl_fw_dbg_conf_tlv *conf_tlv = fw->dbg.conf_tlv[id];
if (!conf_tlv)
return false;
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
index 9ed5819defaf..6b95d0e75889 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
@@ -71,6 +71,7 @@ struct iwl_fw_runtime_ops {
int (*dump_start)(void *ctx);
void (*dump_end)(void *ctx);
bool (*fw_running)(void *ctx);
+ int (*send_hcmd)(void *ctx, struct iwl_host_cmd *host_cmd);
};
#define MAX_NUM_LMAC 2
@@ -88,6 +89,7 @@ struct iwl_fwrt_shared_mem_cfg {
enum iwl_fw_runtime_status {
IWL_FWRT_STATUS_DUMPING = 0,
+ IWL_FWRT_STATUS_WAIT_ALIVE,
};
/**
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index d3a60d1aacb5..ba41d23b4211 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -168,12 +168,12 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv)
{
int i;
- kfree(drv->fw.dbg_dest_tlv);
- for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_conf_tlv); i++)
- kfree(drv->fw.dbg_conf_tlv[i]);
- for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_trigger_tlv); i++)
- kfree(drv->fw.dbg_trigger_tlv[i]);
- kfree(drv->fw.dbg_mem_tlv);
+ kfree(drv->fw.dbg.dest_tlv);
+ for (i = 0; i < ARRAY_SIZE(drv->fw.dbg.conf_tlv); i++)
+ kfree(drv->fw.dbg.conf_tlv[i]);
+ for (i = 0; i < ARRAY_SIZE(drv->fw.dbg.trigger_tlv); i++)
+ kfree(drv->fw.dbg.trigger_tlv[i]);
+ kfree(drv->fw.dbg.mem_tlv);
kfree(drv->fw.iml);
for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
@@ -303,7 +303,7 @@ struct iwl_firmware_pieces {
struct iwl_fw_dbg_trigger_tlv *dbg_trigger_tlv[FW_DBG_TRIGGER_MAX];
size_t dbg_trigger_tlv_len[FW_DBG_TRIGGER_MAX];
struct iwl_fw_dbg_mem_seg_tlv *dbg_mem_tlv;
- size_t n_dbg_mem_tlv;
+ size_t n_mem_tlv;
};
/*
@@ -936,7 +936,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
IWL_INFO(drv, "Found debug destination: %s\n",
get_fw_dbg_mode_string(mon_mode));
- drv->fw.dbg_dest_reg_num = (dest_v1) ?
+ drv->fw.dbg.n_dest_reg = (dest_v1) ?
tlv_len -
offsetof(struct iwl_fw_dbg_dest_tlv_v1,
reg_ops) :
@@ -944,8 +944,8 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
offsetof(struct iwl_fw_dbg_dest_tlv,
reg_ops);
- drv->fw.dbg_dest_reg_num /=
- sizeof(drv->fw.dbg_dest_tlv->reg_ops[0]);
+ drv->fw.dbg.n_dest_reg /=
+ sizeof(drv->fw.dbg.dest_tlv->reg_ops[0]);
break;
}
@@ -959,7 +959,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
break;
}
- if (conf->id >= ARRAY_SIZE(drv->fw.dbg_conf_tlv)) {
+ if (conf->id >= ARRAY_SIZE(drv->fw.dbg.conf_tlv)) {
IWL_ERR(drv,
"Skip unknown configuration: %d\n",
conf->id);
@@ -988,7 +988,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
(void *)tlv_data;
u32 trigger_id = le32_to_cpu(trigger->id);
- if (trigger_id >= ARRAY_SIZE(drv->fw.dbg_trigger_tlv)) {
+ if (trigger_id >= ARRAY_SIZE(drv->fw.dbg.trigger_tlv)) {
IWL_ERR(drv,
"Skip unknown trigger: %u\n",
trigger->id);
@@ -1015,7 +1015,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
break;
}
- drv->fw.dbg_dump_mask =
+ drv->fw.dbg.dump_mask =
le32_to_cpup((__le32 *)tlv_data);
break;
}
@@ -1070,13 +1070,13 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
dbg_mem->data_type);
size = sizeof(*pieces->dbg_mem_tlv) *
- (pieces->n_dbg_mem_tlv + 1);
+ (pieces->n_mem_tlv + 1);
n = krealloc(pieces->dbg_mem_tlv, size, GFP_KERNEL);
if (!n)
return -ENOMEM;
pieces->dbg_mem_tlv = n;
- pieces->dbg_mem_tlv[pieces->n_dbg_mem_tlv] = *dbg_mem;
- pieces->n_dbg_mem_tlv++;
+ pieces->dbg_mem_tlv[pieces->n_mem_tlv] = *dbg_mem;
+ pieces->n_mem_tlv++;
break;
}
case IWL_UCODE_TLV_IML: {
@@ -1256,7 +1256,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
fw->ucode_capa.n_scan_channels = IWL_DEFAULT_SCAN_CHANNELS;
/* dump all fw memory areas by default except d3 debug data */
- fw->dbg_dump_mask = 0xfffdffff;
+ fw->dbg.dump_mask = 0xfffdffff;
pieces = kzalloc(sizeof(*pieces), GFP_KERNEL);
if (!pieces)
@@ -1323,21 +1323,21 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
goto out_free_fw;
if (pieces->dbg_dest_tlv_init) {
- size_t dbg_dest_size = sizeof(*drv->fw.dbg_dest_tlv) +
- sizeof(drv->fw.dbg_dest_tlv->reg_ops[0]) *
- drv->fw.dbg_dest_reg_num;
+ size_t dbg_dest_size = sizeof(*drv->fw.dbg.dest_tlv) +
+ sizeof(drv->fw.dbg.dest_tlv->reg_ops[0]) *
+ drv->fw.dbg.n_dest_reg;
- drv->fw.dbg_dest_tlv = kmalloc(dbg_dest_size, GFP_KERNEL);
+ drv->fw.dbg.dest_tlv = kmalloc(dbg_dest_size, GFP_KERNEL);
- if (!drv->fw.dbg_dest_tlv)
+ if (!drv->fw.dbg.dest_tlv)
goto out_free_fw;
if (*pieces->dbg_dest_ver == 0) {
- memcpy(drv->fw.dbg_dest_tlv, pieces->dbg_dest_tlv_v1,
+ memcpy(drv->fw.dbg.dest_tlv, pieces->dbg_dest_tlv_v1,
dbg_dest_size);
} else {
struct iwl_fw_dbg_dest_tlv_v1 *dest_tlv =
- drv->fw.dbg_dest_tlv;
+ drv->fw.dbg.dest_tlv;
dest_tlv->version = pieces->dbg_dest_tlv->version;
dest_tlv->monitor_mode =
@@ -1352,8 +1352,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
pieces->dbg_dest_tlv->base_shift;
memcpy(dest_tlv->reg_ops,
pieces->dbg_dest_tlv->reg_ops,
- sizeof(drv->fw.dbg_dest_tlv->reg_ops[0]) *
- drv->fw.dbg_dest_reg_num);
+ sizeof(drv->fw.dbg.dest_tlv->reg_ops[0]) *
+ drv->fw.dbg.n_dest_reg);
/* In version 1 of the destination tlv, which is
* relevant for internal buffer exclusively,
@@ -1369,15 +1369,13 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
}
}
- for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_conf_tlv); i++) {
+ for (i = 0; i < ARRAY_SIZE(drv->fw.dbg.conf_tlv); i++) {
if (pieces->dbg_conf_tlv[i]) {
- drv->fw.dbg_conf_tlv_len[i] =
- pieces->dbg_conf_tlv_len[i];
- drv->fw.dbg_conf_tlv[i] =
+ drv->fw.dbg.conf_tlv[i] =
kmemdup(pieces->dbg_conf_tlv[i],
- drv->fw.dbg_conf_tlv_len[i],
+ pieces->dbg_conf_tlv_len[i],
GFP_KERNEL);
- if (!drv->fw.dbg_conf_tlv[i])
+ if (!pieces->dbg_conf_tlv_len[i])
goto out_free_fw;
}
}
@@ -1404,7 +1402,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
trigger_tlv_sz[FW_DBG_TRIGGER_TDLS] =
sizeof(struct iwl_fw_dbg_trigger_tdls);
- for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_trigger_tlv); i++) {
+ for (i = 0; i < ARRAY_SIZE(drv->fw.dbg.trigger_tlv); i++) {
if (pieces->dbg_trigger_tlv[i]) {
/*
* If the trigger isn't long enough, WARN and exit.
@@ -1417,22 +1415,22 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
(trigger_tlv_sz[i] +
sizeof(struct iwl_fw_dbg_trigger_tlv))))
goto out_free_fw;
- drv->fw.dbg_trigger_tlv_len[i] =
+ drv->fw.dbg.trigger_tlv_len[i] =
pieces->dbg_trigger_tlv_len[i];
- drv->fw.dbg_trigger_tlv[i] =
+ drv->fw.dbg.trigger_tlv[i] =
kmemdup(pieces->dbg_trigger_tlv[i],
- drv->fw.dbg_trigger_tlv_len[i],
+ drv->fw.dbg.trigger_tlv_len[i],
GFP_KERNEL);
- if (!drv->fw.dbg_trigger_tlv[i])
+ if (!drv->fw.dbg.trigger_tlv[i])
goto out_free_fw;
}
}
/* Now that we can no longer fail, copy information */
- drv->fw.dbg_mem_tlv = pieces->dbg_mem_tlv;
+ drv->fw.dbg.mem_tlv = pieces->dbg_mem_tlv;
pieces->dbg_mem_tlv = NULL;
- drv->fw.n_dbg_mem_tlv = pieces->n_dbg_mem_tlv;
+ drv->fw.dbg.n_mem_tlv = pieces->n_mem_tlv;
/*
* The (size - 16) / 12 formula is based on the information recorded
@@ -1473,6 +1471,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
break;
default:
WARN(1, "Invalid fw type %d\n", fw->type);
+ /* fall through */
case IWL_FW_MVM:
op = &iwlwifi_opmode_table[MVM_OP_MODE];
break;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
index ec300d388694..96e101d79662 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
@@ -1335,6 +1335,7 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
bool lar_fw_supported = !iwlwifi_mod_params.lar_disable &&
fw_has_capa(&fw->ucode_capa,
IWL_UCODE_TLV_CAPA_LAR_SUPPORT);
+ bool empty_otp;
u32 mac_flags;
u32 sbands_flags = 0;
@@ -1350,7 +1351,9 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
}
rsp = (void *)hcmd.resp_pkt->data;
- if (le32_to_cpu(rsp->general.flags) & NVM_GENERAL_FLAGS_EMPTY_OTP)
+ empty_otp = !!(le32_to_cpu(rsp->general.flags) &
+ NVM_GENERAL_FLAGS_EMPTY_OTP);
+ if (empty_otp)
IWL_INFO(trans, "OTP is empty\n");
nvm = kzalloc(sizeof(*nvm) +
@@ -1374,6 +1377,11 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
/* Initialize general data */
nvm->nvm_version = le16_to_cpu(rsp->general.nvm_version);
+ nvm->n_hw_addrs = rsp->general.n_hw_addrs;
+ if (nvm->n_hw_addrs == 0)
+ IWL_WARN(trans,
+ "Firmware declares no reserved mac addresses. OTP is empty: %d\n",
+ empty_otp);
/* Initialize MAC sku data */
mac_flags = le32_to_cpu(rsp->mac_sku.mac_sku_flags);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
index 6c636b2a6b43..26b3c73051ca 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
@@ -725,7 +725,7 @@ struct iwl_dram_data {
* @dbg_dest_tlv: points to the destination TLV for debug
* @dbg_conf_tlv: array of pointers to configuration TLVs for debug
* @dbg_trigger_tlv: array of pointers to triggers TLVs for debug
- * @dbg_dest_reg_num: num of reg_ops in %dbg_dest_tlv
+ * @dbg_n_dest_reg: num of reg_ops in %dbg_dest_tlv
* @num_blocks: number of blocks in fw_mon
* @fw_mon: address of the buffers for firmware monitor
* @system_pm_mode: the system-wide power management mode in use.
@@ -778,7 +778,7 @@ struct iwl_trans {
const struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX];
struct iwl_fw_dbg_trigger_tlv * const *dbg_trigger_tlv;
u32 dbg_dump_mask;
- u8 dbg_dest_reg_num;
+ u8 dbg_n_dest_reg;
int num_blocks;
struct iwl_dram_data fw_mon[IWL_MAX_DEBUG_ALLOCATIONS];
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index de40752aa67e..3b6b3d8fb961 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -666,16 +666,11 @@ iwl_dbgfs_bt_force_ant_write(struct iwl_mvm *mvm, char *buf,
};
int ret, bt_force_ant_mode;
- for (bt_force_ant_mode = 0;
- bt_force_ant_mode < ARRAY_SIZE(modes_str);
- bt_force_ant_mode++) {
- if (!strcmp(buf, modes_str[bt_force_ant_mode]))
- break;
- }
-
- if (bt_force_ant_mode >= ARRAY_SIZE(modes_str))
- return -EINVAL;
+ ret = match_string(modes_str, ARRAY_SIZE(modes_str), buf);
+ if (ret < 0)
+ return ret;
+ bt_force_ant_mode = ret;
ret = 0;
mutex_lock(&mvm->mutex);
if (mvm->bt_force_ant_mode == bt_force_ant_mode)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 96d26b749952..c5df73231ba3 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -299,6 +299,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
enum iwl_ucode_type old_type = mvm->fwrt.cur_fw_img;
static const u16 alive_cmd[] = { MVM_ALIVE };
+ set_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &mvm->fwrt.status);
if (ucode_type == IWL_UCODE_REGULAR &&
iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_START_FROM_ALIVE) &&
!(fw_has_capa(&mvm->fw->ucode_capa,
@@ -369,6 +370,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
atomic_set(&mvm->mac80211_queue_stop_count[i], 0);
set_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
+ clear_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &mvm->fwrt.status);
return 0;
}
@@ -699,8 +701,12 @@ static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm)
enabled = !!(wifi_pkg->package.elements[1].integer.value);
n_profiles = wifi_pkg->package.elements[2].integer.value;
- /* in case of BIOS bug */
- if (n_profiles <= 0) {
+ /*
+ * Check the validity of n_profiles. The EWRD profiles start
+ * from index 1, so the maximum value allowed here is
+ * ACPI_SAR_PROFILES_NUM - 1.
+ */
+ if (n_profiles <= 0 || n_profiles >= ACPI_SAR_PROFILE_NUM) {
ret = -EINVAL;
goto out_free;
}
@@ -1022,7 +1028,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
mvm->fwrt.dump.conf = FW_DBG_INVALID;
/* if we have a destination, assume EARLY START */
- if (mvm->fw->dbg_dest_tlv)
+ if (mvm->fw->dbg.dest_tlv)
mvm->fwrt.dump.conf = FW_DBG_START_FROM_ALIVE;
iwl_fw_start_dbg_conf(&mvm->fwrt, FW_DBG_START_FROM_ALIVE);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index 781f30356720..6486cfb33f40 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -1487,12 +1487,11 @@ static void iwl_mvm_beacon_loss_iterator(void *_data, u8 *mac,
IWL_MVM_MISSED_BEACONS_THRESHOLD)
ieee80211_beacon_loss(vif);
- if (!iwl_fw_dbg_trigger_enabled(mvm->fw,
- FW_DBG_TRIGGER_MISSED_BEACONS))
+ trigger = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif),
+ FW_DBG_TRIGGER_MISSED_BEACONS);
+ if (!trigger)
return;
- trigger = iwl_fw_dbg_get_trigger(mvm->fw,
- FW_DBG_TRIGGER_MISSED_BEACONS);
bcon_trig = (void *)trigger->data;
stop_trig_missed_bcon = le32_to_cpu(bcon_trig->stop_consec_missed_bcon);
stop_trig_missed_bcon_since_rx =
@@ -1500,11 +1499,6 @@ static void iwl_mvm_beacon_loss_iterator(void *_data, u8 *mac,
/* TODO: implement start trigger */
- if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt,
- ieee80211_vif_to_wdev(vif),
- trigger))
- return;
-
if (rx_missed_bcon_since_rx >= stop_trig_missed_bcon_since_rx ||
rx_missed_bcon >= stop_trig_missed_bcon)
iwl_fw_dbg_collect_trig(&mvm->fwrt, trigger, NULL);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index c78d017749d3..505b0385d800 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -857,16 +857,13 @@ iwl_mvm_ampdu_check_trigger(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_fw_dbg_trigger_tlv *trig;
struct iwl_fw_dbg_trigger_ba *ba_trig;
- if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_BA))
+ trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif),
+ FW_DBG_TRIGGER_BA);
+ if (!trig)
return;
- trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_BA);
ba_trig = (void *)trig->data;
- if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt,
- ieee80211_vif_to_wdev(vif), trig))
- return;
-
switch (action) {
case IEEE80211_AMPDU_TX_OPERATIONAL: {
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
@@ -1231,12 +1228,15 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm)
iwl_mvm_del_aux_sta(mvm);
/*
- * Clear IN_HW_RESTART flag when stopping the hw (as restart_complete()
- * won't be called in this case).
+ * Clear IN_HW_RESTART and HW_RESTART_REQUESTED flag when stopping the
+ * hw (as restart_complete() won't be called in this case) and mac80211
+ * won't execute the restart.
* But make sure to cleanup interfaces that have gone down before/during
* HW restart was requested.
*/
- if (test_and_clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
+ if (test_and_clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) ||
+ test_and_clear_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
+ &mvm->status))
ieee80211_iterate_interfaces(mvm->hw, 0,
iwl_mvm_cleanup_iterator, mvm);
@@ -2802,14 +2802,12 @@ iwl_mvm_tdls_check_trigger(struct iwl_mvm *mvm,
struct iwl_fw_dbg_trigger_tlv *trig;
struct iwl_fw_dbg_trigger_tdls *tdls_trig;
- if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TDLS))
+ trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif),
+ FW_DBG_TRIGGER_TDLS);
+ if (!trig)
return;
- trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_TDLS);
tdls_trig = (void *)trig->data;
- if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt,
- ieee80211_vif_to_wdev(vif), trig))
- return;
if (!(tdls_trig->action_bitmap & BIT(action)))
return;
@@ -4491,14 +4489,12 @@ static void iwl_mvm_event_mlme_callback(struct iwl_mvm *mvm,
struct iwl_fw_dbg_trigger_tlv *trig;
struct iwl_fw_dbg_trigger_mlme *trig_mlme;
- if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_MLME))
+ trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif),
+ FW_DBG_TRIGGER_MLME);
+ if (!trig)
return;
- trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_MLME);
trig_mlme = (void *)trig->data;
- if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt,
- ieee80211_vif_to_wdev(vif), trig))
- return;
if (event->u.mlme.data == ASSOC_EVENT) {
if (event->u.mlme.status == MLME_DENIED)
@@ -4533,14 +4529,12 @@ static void iwl_mvm_event_bar_rx_callback(struct iwl_mvm *mvm,
struct iwl_fw_dbg_trigger_tlv *trig;
struct iwl_fw_dbg_trigger_ba *ba_trig;
- if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_BA))
+ trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif),
+ FW_DBG_TRIGGER_BA);
+ if (!trig)
return;
- trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_BA);
ba_trig = (void *)trig->data;
- if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt,
- ieee80211_vif_to_wdev(vif), trig))
- return;
if (!(le16_to_cpu(ba_trig->rx_bar) & BIT(event->u.ba.tid)))
return;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
index fff98fed35ed..3633f27d048a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
@@ -477,15 +477,11 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
u32 status;
int resp_len, n_channels;
u16 mcc;
- bool resp_v2 = fw_has_capa(&mvm->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V2);
if (WARN_ON_ONCE(!iwl_mvm_is_lar_supported(mvm)))
return ERR_PTR(-EOPNOTSUPP);
cmd.len[0] = sizeof(struct iwl_mcc_update_cmd);
- if (!resp_v2)
- cmd.len[0] = sizeof(struct iwl_mcc_update_cmd_v1);
IWL_DEBUG_LAR(mvm, "send MCC update to FW with '%c%c' src = %d\n",
alpha2[0], alpha2[1], src_id);
@@ -497,7 +493,8 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
pkt = cmd.resp_pkt;
/* Extract MCC response */
- if (resp_v2) {
+ if (fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT)) {
struct iwl_mcc_update_resp *mcc_resp = (void *)pkt->data;
n_channels = __le32_to_cpu(mcc_resp->n_channels);
@@ -509,9 +506,9 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
goto exit;
}
} else {
- struct iwl_mcc_update_resp_v1 *mcc_resp_v1 = (void *)pkt->data;
+ struct iwl_mcc_update_resp_v3 *mcc_resp_v3 = (void *)pkt->data;
- n_channels = __le32_to_cpu(mcc_resp_v1->n_channels);
+ n_channels = __le32_to_cpu(mcc_resp_v3->n_channels);
resp_len = sizeof(struct iwl_mcc_update_resp) +
n_channels * sizeof(__le32);
resp_cp = kzalloc(resp_len, GFP_KERNEL);
@@ -520,12 +517,14 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
goto exit;
}
- resp_cp->status = mcc_resp_v1->status;
- resp_cp->mcc = mcc_resp_v1->mcc;
- resp_cp->cap = mcc_resp_v1->cap;
- resp_cp->source_id = mcc_resp_v1->source_id;
- resp_cp->n_channels = mcc_resp_v1->n_channels;
- memcpy(resp_cp->channels, mcc_resp_v1->channels,
+ resp_cp->status = mcc_resp_v3->status;
+ resp_cp->mcc = mcc_resp_v3->mcc;
+ resp_cp->cap = cpu_to_le16(mcc_resp_v3->cap);
+ resp_cp->source_id = mcc_resp_v3->source_id;
+ resp_cp->time = mcc_resp_v3->time;
+ resp_cp->geo_info = mcc_resp_v3->geo_info;
+ resp_cp->n_channels = mcc_resp_v3->n_channels;
+ memcpy(resp_cp->channels, mcc_resp_v3->channels,
n_channels * sizeof(__le32));
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 0599d323cbeb..0e2092526fae 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -565,10 +565,23 @@ static bool iwl_mvm_fwrt_fw_running(void *ctx)
return iwl_mvm_firmware_running(ctx);
}
+static int iwl_mvm_fwrt_send_hcmd(void *ctx, struct iwl_host_cmd *host_cmd)
+{
+ struct iwl_mvm *mvm = (struct iwl_mvm *)ctx;
+ int ret;
+
+ mutex_lock(&mvm->mutex);
+ ret = iwl_mvm_send_cmd(mvm, host_cmd);
+ mutex_unlock(&mvm->mutex);
+
+ return ret;
+}
+
static const struct iwl_fw_runtime_ops iwl_mvm_fwrt_ops = {
.dump_start = iwl_mvm_fwrt_dump_start,
.dump_end = iwl_mvm_fwrt_dump_end,
.fw_running = iwl_mvm_fwrt_fw_running,
+ .send_hcmd = iwl_mvm_fwrt_send_hcmd,
};
static struct iwl_op_mode *
@@ -604,9 +617,13 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
if (cfg->max_rx_agg_size)
hw->max_rx_aggregation_subframes = cfg->max_rx_agg_size;
+ else
+ hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
if (cfg->max_tx_agg_size)
hw->max_tx_aggregation_subframes = cfg->max_tx_agg_size;
+ else
+ hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
op_mode = hw->priv;
@@ -748,12 +765,12 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
iwl_trans_configure(mvm->trans, &trans_cfg);
trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
- trans->dbg_dest_tlv = mvm->fw->dbg_dest_tlv;
- trans->dbg_dest_reg_num = mvm->fw->dbg_dest_reg_num;
- memcpy(trans->dbg_conf_tlv, mvm->fw->dbg_conf_tlv,
+ trans->dbg_dest_tlv = mvm->fw->dbg.dest_tlv;
+ trans->dbg_n_dest_reg = mvm->fw->dbg.n_dest_reg;
+ memcpy(trans->dbg_conf_tlv, mvm->fw->dbg.conf_tlv,
sizeof(trans->dbg_conf_tlv));
- trans->dbg_trigger_tlv = mvm->fw->dbg_trigger_tlv;
- trans->dbg_dump_mask = mvm->fw->dbg_dump_mask;
+ trans->dbg_trigger_tlv = mvm->fw->dbg.trigger_tlv;
+ trans->dbg_dump_mask = mvm->fw->dbg.dump_mask;
trans->iml = mvm->fw->iml;
trans->iml_len = mvm->fw->iml_len;
@@ -784,6 +801,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mutex_lock(&mvm->mutex);
iwl_mvm_ref(mvm, IWL_MVM_REF_INIT_UCODE);
err = iwl_run_init_mvm_ucode(mvm, true);
+ if (test_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &mvm->fwrt.status))
+ iwl_fw_alive_error_dump(&mvm->fwrt);
if (!iwlmvm_mod_params.init_dbg || !err)
iwl_mvm_stop_device(mvm);
iwl_mvm_unref(mvm, IWL_MVM_REF_INIT_UCODE);
@@ -953,15 +972,13 @@ static inline void iwl_mvm_rx_check_trigger(struct iwl_mvm *mvm,
struct iwl_fw_dbg_trigger_cmd *cmds_trig;
int i;
- if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_FW_NOTIF))
+ trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, NULL,
+ FW_DBG_TRIGGER_FW_NOTIF);
+ if (!trig)
return;
- trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_FW_NOTIF);
cmds_trig = (void *)trig->data;
- if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, NULL, trig))
- return;
-
for (i = 0; i < ARRAY_SIZE(cmds_trig->cmds); i++) {
/* don't collect on CMD 0 */
if (!cmds_trig->cmds[i].cmd_id)
@@ -1223,7 +1240,7 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
*/
if (!mvm->fw_restart && fw_error) {
iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert,
- NULL);
+ NULL, 0);
} else if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
struct iwl_mvm_reprobe *reprobe;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index a050220da678..ef624833cf1b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -433,13 +433,14 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct ieee80211_vif *tx_blocked_vif =
rcu_dereference(mvm->csa_tx_blocked_vif);
+ struct iwl_fw_dbg_trigger_tlv *trig;
+ struct ieee80211_vif *vif = mvmsta->vif;
/* We have tx blocked stations (with CS bit). If we heard
* frames from a blocked station on a new channel we can
* TX to it again.
*/
- if (unlikely(tx_blocked_vif) &&
- mvmsta->vif == tx_blocked_vif) {
+ if (unlikely(tx_blocked_vif) && vif == tx_blocked_vif) {
struct iwl_mvm_vif *mvmvif =
iwl_mvm_vif_from_mac80211(tx_blocked_vif);
@@ -450,23 +451,18 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
rs_update_last_rssi(mvm, mvmsta, rx_status);
- if (iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_RSSI) &&
- ieee80211_is_beacon(hdr->frame_control)) {
- struct iwl_fw_dbg_trigger_tlv *trig;
+ trig = iwl_fw_dbg_trigger_on(&mvm->fwrt,
+ ieee80211_vif_to_wdev(vif),
+ FW_DBG_TRIGGER_RSSI);
+
+ if (trig && ieee80211_is_beacon(hdr->frame_control)) {
struct iwl_fw_dbg_trigger_low_rssi *rssi_trig;
- bool trig_check;
s32 rssi;
- trig = iwl_fw_dbg_get_trigger(mvm->fw,
- FW_DBG_TRIGGER_RSSI);
rssi_trig = (void *)trig->data;
rssi = le32_to_cpu(rssi_trig->rssi);
- trig_check =
- iwl_fw_dbg_trigger_check_stop(&mvm->fwrt,
- ieee80211_vif_to_wdev(mvmsta->vif),
- trig);
- if (trig_check && rx_status->signal < rssi)
+ if (rx_status->signal < rssi)
iwl_fw_dbg_collect_trig(&mvm->fwrt, trig,
NULL);
}
@@ -693,15 +689,12 @@ iwl_mvm_rx_stats_check_trigger(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt)
struct iwl_fw_dbg_trigger_stats *trig_stats;
u32 trig_offset, trig_thold;
- if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_STATS))
+ trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, NULL, FW_DBG_TRIGGER_STATS);
+ if (!trig)
return;
- trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_STATS);
trig_stats = (void *)trig->data;
- if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, NULL, trig))
- return;
-
trig_offset = le32_to_cpu(trig_stats->stop_offset);
trig_thold = le32_to_cpu(trig_stats->stop_threshold);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
index 894dd6379b9a..26ac9402568d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
@@ -923,6 +923,185 @@ static void iwl_mvm_decode_he_sigb(struct iwl_mvm *mvm,
}
}
+static void
+iwl_mvm_decode_he_phy_ru_alloc(u64 he_phy_data, u32 rate_n_flags,
+ struct ieee80211_radiotap_he *he,
+ struct ieee80211_radiotap_he_mu *he_mu,
+ struct ieee80211_rx_status *rx_status)
+{
+ /*
+ * Unfortunately, we have to leave the mac80211 data
+ * incorrect for the case that we receive an HE-MU
+ * transmission and *don't* have the HE phy data (due
+ * to the bits being used for TSF). This shouldn't
+ * happen though as management frames where we need
+ * the TSF/timers are not be transmitted in HE-MU.
+ */
+ u8 ru = FIELD_GET(IWL_RX_HE_PHY_RU_ALLOC_MASK, he_phy_data);
+ u8 offs = 0;
+
+ rx_status->bw = RATE_INFO_BW_HE_RU;
+
+ he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN);
+
+ switch (ru) {
+ case 0 ... 36:
+ rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26;
+ offs = ru;
+ break;
+ case 37 ... 52:
+ rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52;
+ offs = ru - 37;
+ break;
+ case 53 ... 60:
+ rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
+ offs = ru - 53;
+ break;
+ case 61 ... 64:
+ rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242;
+ offs = ru - 61;
+ break;
+ case 65 ... 66:
+ rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484;
+ offs = ru - 65;
+ break;
+ case 67:
+ rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996;
+ break;
+ case 68:
+ rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
+ break;
+ }
+ he->data2 |= le16_encode_bits(offs,
+ IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET);
+ he->data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN |
+ IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET_KNOWN);
+ if (he_phy_data & IWL_RX_HE_PHY_RU_ALLOC_SEC80)
+ he->data2 |=
+ cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC);
+
+ if (he_mu) {
+#define CHECK_BW(bw) \
+ BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_ ## bw ## MHZ != \
+ RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS)
+ CHECK_BW(20);
+ CHECK_BW(40);
+ CHECK_BW(80);
+ CHECK_BW(160);
+ he_mu->flags2 |=
+ le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK,
+ rate_n_flags),
+ IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW);
+ }
+}
+
+static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm,
+ struct iwl_rx_mpdu_desc *desc,
+ struct ieee80211_radiotap_he *he,
+ struct ieee80211_radiotap_he_mu *he_mu,
+ struct ieee80211_rx_status *rx_status,
+ u64 he_phy_data, u32 rate_n_flags,
+ int queue)
+{
+ u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
+ bool sigb_data;
+ u16 d1known = IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN |
+ IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN |
+ IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN |
+ IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN |
+ IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN;
+ u16 d2known = IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN |
+ IEEE80211_RADIOTAP_HE_DATA2_PE_DISAMBIG_KNOWN |
+ IEEE80211_RADIOTAP_HE_DATA2_TXOP_KNOWN;
+
+ he->data1 |= cpu_to_le16(d1known);
+ he->data2 |= cpu_to_le16(d2known);
+ he->data3 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_BSS_COLOR_MASK,
+ he_phy_data),
+ IEEE80211_RADIOTAP_HE_DATA3_BSS_COLOR);
+ he->data3 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_UPLINK,
+ he_phy_data),
+ IEEE80211_RADIOTAP_HE_DATA3_UL_DL);
+ he->data3 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_LDPC_EXT_SYM,
+ he_phy_data),
+ IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG);
+ he->data4 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_SPATIAL_REUSE_MASK,
+ he_phy_data),
+ IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE);
+ he->data5 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_PRE_FEC_PAD_MASK,
+ he_phy_data),
+ IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD);
+ he->data5 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_PE_DISAMBIG,
+ he_phy_data),
+ IEEE80211_RADIOTAP_HE_DATA5_PE_DISAMBIG);
+ he->data6 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_TXOP_DUR_MASK,
+ he_phy_data),
+ IEEE80211_RADIOTAP_HE_DATA6_TXOP);
+ he->data6 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_DOPPLER,
+ he_phy_data),
+ IEEE80211_RADIOTAP_HE_DATA6_DOPPLER);
+
+ switch (he_type) {
+ case RATE_MCS_HE_TYPE_MU:
+ he_mu->flags1 |=
+ le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_SIGB_DCM,
+ he_phy_data),
+ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM);
+ he_mu->flags1 |=
+ le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_SIGB_MCS_MASK,
+ he_phy_data),
+ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS);
+ he_mu->flags2 |=
+ le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_SIBG_SYM_OR_USER_NUM_MASK,
+ he_phy_data),
+ IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS);
+ he_mu->flags2 |=
+ le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_SIGB_COMPRESSION,
+ he_phy_data),
+ IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP);
+ he_mu->flags2 |=
+ le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_PREAMBLE_PUNC_TYPE_MASK,
+ he_phy_data),
+ IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW);
+
+ sigb_data = FIELD_GET(IWL_RX_HE_PHY_INFO_TYPE_MASK,
+ he_phy_data) ==
+ IWL_RX_HE_PHY_INFO_TYPE_MU_EXT_INFO;
+ if (sigb_data)
+ iwl_mvm_decode_he_sigb(mvm, desc, rate_n_flags, he_mu);
+ /* fall through */
+ case RATE_MCS_HE_TYPE_TRIG:
+ he->data2 |=
+ cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN);
+ he->data5 |=
+ le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_HE_LTF_NUM_MASK,
+ he_phy_data),
+ IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS);
+ break;
+ case RATE_MCS_HE_TYPE_SU:
+ case RATE_MCS_HE_TYPE_EXT_SU:
+ he->data1 |=
+ cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BEAM_CHANGE_KNOWN);
+ he->data3 |=
+ le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_BEAM_CHNG,
+ he_phy_data),
+ IEEE80211_RADIOTAP_HE_DATA3_BEAM_CHANGE);
+ break;
+ }
+
+ switch (FIELD_GET(IWL_RX_HE_PHY_INFO_TYPE_MASK, he_phy_data)) {
+ case IWL_RX_HE_PHY_INFO_TYPE_MU:
+ case IWL_RX_HE_PHY_INFO_TYPE_MU_EXT_INFO:
+ case IWL_RX_HE_PHY_INFO_TYPE_TB:
+ iwl_mvm_decode_he_phy_ru_alloc(he_phy_data, rate_n_flags,
+ he, he_mu, rx_status);
+ break;
+ default:
+ /* nothing */
+ break;
+ }
+}
+
static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
struct iwl_rx_mpdu_desc *desc,
u32 rate_n_flags, u16 phy_info, int queue)
@@ -933,9 +1112,8 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
u64 he_phy_data = HE_PHY_DATA_INVAL;
struct ieee80211_radiotap_he *he = NULL;
struct ieee80211_radiotap_he_mu *he_mu = NULL;
- u32 he_type = 0xffffffff;
+ u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
u8 stbc, ltf;
-
static const struct ieee80211_radiotap_he known = {
.data1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN |
IEEE80211_RADIOTAP_HE_DATA1_DATA_DCM_KNOWN |
@@ -953,25 +1131,19 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),
};
unsigned int radiotap_len = 0;
- bool overload = phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD;
- bool sigb_data = false;
he = skb_put_data(skb, &known, sizeof(known));
radiotap_len += sizeof(known);
rx_status->flag |= RX_FLAG_RADIOTAP_HE;
- he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
-
if (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD) {
- if (mvm->trans->cfg->device_family >=
- IWL_DEVICE_FAMILY_22560)
+ if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
he_phy_data = le64_to_cpu(desc->v3.he_phy_data);
else
he_phy_data = le64_to_cpu(desc->v1.he_phy_data);
if (he_type == RATE_MCS_HE_TYPE_MU) {
- he_mu = skb_put_data(skb, &mu_known,
- sizeof(mu_known));
+ he_mu = skb_put_data(skb, &mu_known, sizeof(mu_known));
radiotap_len += sizeof(mu_known);
rx_status->flag |= RX_FLAG_RADIOTAP_HE_MU;
}
@@ -980,60 +1152,21 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
/* temporarily hide the radiotap data */
__skb_pull(skb, radiotap_len);
- if (overload && he_type == RATE_MCS_HE_TYPE_SU) {
- he->data1 |=
- cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN);
- if (FIELD_GET(IWL_RX_HE_PHY_UPLINK, he_phy_data))
- he->data3 |=
- cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA3_UL_DL);
-
+ if (he_phy_data != HE_PHY_DATA_INVAL &&
+ he_type == RATE_MCS_HE_TYPE_SU) {
+ /* report the AMPDU-EOF bit on single frames */
if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
if (FIELD_GET(IWL_RX_HE_PHY_DELIM_EOF, he_phy_data))
rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
}
- } else if (overload && he_mu && he_phy_data != HE_PHY_DATA_INVAL) {
- he_mu->flags1 |=
- le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_SIBG_SYM_OR_USER_NUM_MASK,
- he_phy_data),
- IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS);
- he_mu->flags1 |=
- le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_SIGB_DCM,
- he_phy_data),
- IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM);
- he_mu->flags1 |=
- le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_SIGB_MCS_MASK,
- he_phy_data),
- IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS);
- he_mu->flags2 |=
- le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_SIGB_COMPRESSION,
- he_phy_data),
- IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP);
- he_mu->flags2 |=
- le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_PREAMBLE_PUNC_TYPE_MASK,
- he_phy_data),
- IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW);
-
- sigb_data = FIELD_GET(IWL_RX_HE_PHY_INFO_TYPE_MASK,
- he_phy_data) ==
- IWL_RX_HE_PHY_INFO_TYPE_MU_EXT_INFO;
- if (sigb_data)
- iwl_mvm_decode_he_sigb(mvm, desc, rate_n_flags, he_mu);
- }
- if (he_phy_data != HE_PHY_DATA_INVAL &&
- (he_type == RATE_MCS_HE_TYPE_SU ||
- he_type == RATE_MCS_HE_TYPE_MU)) {
- u8 bss_color = FIELD_GET(IWL_RX_HE_PHY_BSS_COLOR_MASK,
- he_phy_data);
-
- if (bss_color) {
- he->data1 |=
- cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN);
- he->data3 |= cpu_to_le16(bss_color);
- }
}
+ if (he_phy_data != HE_PHY_DATA_INVAL)
+ iwl_mvm_decode_he_phy_data(mvm, desc, he, he_mu, rx_status,
+ he_phy_data, rate_n_flags, queue);
+
/* update aggregation data for monitor sake on default queue */
if (!queue && (phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
bool toggle_bit = phy_info & IWL_RX_MPDU_PHY_AMPDU_TOGGLE;
@@ -1056,84 +1189,12 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
}
- if (he_phy_data != HE_PHY_DATA_INVAL &&
- (FIELD_GET(IWL_RX_HE_PHY_INFO_TYPE_MASK, he_phy_data) ==
- IWL_RX_HE_PHY_INFO_TYPE_MU_EXT_INFO ||
- FIELD_GET(IWL_RX_HE_PHY_INFO_TYPE_MASK, he_phy_data) ==
- IWL_RX_HE_PHY_INFO_TYPE_TB_EXT_INFO)) {
- /*
- * Unfortunately, we have to leave the mac80211 data
- * incorrect for the case that we receive an HE-MU
- * transmission and *don't* have the HE phy data (due
- * to the bits being used for TSF). This shouldn't
- * happen though as management frames where we need
- * the TSF/timers are not be transmitted in HE-MU.
- */
- u8 ru = FIELD_GET(IWL_RX_HE_PHY_RU_ALLOC_MASK, he_phy_data);
- u8 offs = 0;
-
- rx_status->bw = RATE_INFO_BW_HE_RU;
-
+ /* actually data is filled in mac80211 */
+ if (he_type == RATE_MCS_HE_TYPE_SU ||
+ he_type == RATE_MCS_HE_TYPE_EXT_SU)
he->data1 |=
cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN);
- switch (ru) {
- case 0 ... 36:
- rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26;
- offs = ru;
- break;
- case 37 ... 52:
- rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52;
- offs = ru - 37;
- break;
- case 53 ... 60:
- rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
- offs = ru - 53;
- break;
- case 61 ... 64:
- rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242;
- offs = ru - 61;
- break;
- case 65 ... 66:
- rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484;
- offs = ru - 65;
- break;
- case 67:
- rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996;
- break;
- case 68:
- rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
- break;
- }
- he->data2 |=
- le16_encode_bits(offs,
- IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET);
- he->data2 |=
- cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN |
- IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET_KNOWN);
- if (he_phy_data & IWL_RX_HE_PHY_RU_ALLOC_SEC80)
- he->data2 |=
- cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC);
-
- if (he_mu) {
-#define CHECK_BW(bw) \
- BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_ ## bw ## MHZ != \
- RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS)
- CHECK_BW(20);
- CHECK_BW(40);
- CHECK_BW(80);
- CHECK_BW(160);
- he->data2 |=
- le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK,
- rate_n_flags),
- IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW);
- }
- } else if (he_type == RATE_MCS_HE_TYPE_SU ||
- he_type == RATE_MCS_HE_TYPE_EXT_SU) {
- he->data1 |=
- cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN);
- }
-
stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >> RATE_MCS_STBC_POS;
rx_status->nss =
((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>
@@ -1202,9 +1263,8 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
he->data5 |= le16_encode_bits(ltf, IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE);
- switch (he_type) {
- case RATE_MCS_HE_TYPE_SU:
- case RATE_MCS_HE_TYPE_EXT_SU: {
+ if (he_type == RATE_MCS_HE_TYPE_SU ||
+ he_type == RATE_MCS_HE_TYPE_EXT_SU) {
u16 val;
/* LTF syms correspond to streams */
@@ -1234,31 +1294,10 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
rx_status->nss);
val = 0;
}
+
he->data5 |=
le16_encode_bits(val,
IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS);
- }
- break;
- case RATE_MCS_HE_TYPE_MU: {
- u16 val;
-
- if (he_phy_data == HE_PHY_DATA_INVAL)
- break;
-
- val = FIELD_GET(IWL_RX_HE_PHY_HE_LTF_NUM_MASK,
- he_phy_data);
-
- he->data2 |=
- cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN);
- he->data5 |=
- cpu_to_le16(FIELD_PREP(
- IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS,
- val));
- }
- break;
- case RATE_MCS_HE_TYPE_TRIG:
- /* not supported */
- break;
}
}
@@ -1424,6 +1463,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
u8 baid = (u8)((le32_to_cpu(desc->reorder_data) &
IWL_RX_MPDU_REORDER_BAID_MASK) >>
IWL_RX_MPDU_REORDER_BAID_SHIFT);
+ struct iwl_fw_dbg_trigger_tlv *trig;
+ struct ieee80211_vif *vif = mvmsta->vif;
if (!mvm->tcm.paused && len >= sizeof(*hdr) &&
!is_multicast_ether_addr(hdr->addr1) &&
@@ -1436,8 +1477,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
* frames from a blocked station on a new channel we can
* TX to it again.
*/
- if (unlikely(tx_blocked_vif) &&
- tx_blocked_vif == mvmsta->vif) {
+ if (unlikely(tx_blocked_vif) && tx_blocked_vif == vif) {
struct iwl_mvm_vif *mvmvif =
iwl_mvm_vif_from_mac80211(tx_blocked_vif);
@@ -1448,23 +1488,18 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
rs_update_last_rssi(mvm, mvmsta, rx_status);
- if (iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_RSSI) &&
- ieee80211_is_beacon(hdr->frame_control)) {
- struct iwl_fw_dbg_trigger_tlv *trig;
+ trig = iwl_fw_dbg_trigger_on(&mvm->fwrt,
+ ieee80211_vif_to_wdev(vif),
+ FW_DBG_TRIGGER_RSSI);
+
+ if (trig && ieee80211_is_beacon(hdr->frame_control)) {
struct iwl_fw_dbg_trigger_low_rssi *rssi_trig;
- bool trig_check;
s32 rssi;
- trig = iwl_fw_dbg_get_trigger(mvm->fw,
- FW_DBG_TRIGGER_RSSI);
rssi_trig = (void *)trig->data;
rssi = le32_to_cpu(rssi_trig->rssi);
- trig_check =
- iwl_fw_dbg_trigger_check_stop(&mvm->fwrt,
- ieee80211_vif_to_wdev(mvmsta->vif),
- trig);
- if (trig_check && rx_status->signal < rssi)
+ if (rx_status->signal < rssi)
iwl_fw_dbg_collect_trig(&mvm->fwrt, trig,
NULL);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index e9048a98e793..ffcd0ca86041 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -1448,6 +1448,9 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_LMAC2_FRAGMENTED)
cmd->v8.num_of_fragments[SCAN_HB_LMAC_IDX] =
IWL_SCAN_NUM_OF_FRAGS;
+
+ cmd->v8.general_flags2 =
+ IWL_UMAC_SCAN_GEN_FLAGS2_ALLOW_CHNL_REORDER;
}
cmd->scan_start_mac_id = scan_vif->id;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
index cd91bc44259c..e1a6f4e22253 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
@@ -254,17 +254,14 @@ static void iwl_mvm_te_check_trigger(struct iwl_mvm *mvm,
struct iwl_fw_dbg_trigger_time_event *te_trig;
int i;
- if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TIME_EVENT))
+ trig = iwl_fw_dbg_trigger_on(&mvm->fwrt,
+ ieee80211_vif_to_wdev(te_data->vif),
+ FW_DBG_TRIGGER_TIME_EVENT);
+ if (!trig)
return;
- trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_TIME_EVENT);
te_trig = (void *)trig->data;
- if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt,
- ieee80211_vif_to_wdev(te_data->vif),
- trig))
- return;
-
for (i = 0; i < ARRAY_SIZE(te_trig->time_events); i++) {
u32 trig_te_id = le32_to_cpu(te_trig->time_events[i].id);
u32 trig_action_bitmap =
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index a6877b3f8037..99c64ea2619b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -79,15 +79,12 @@ iwl_mvm_bar_check_trigger(struct iwl_mvm *mvm, const u8 *addr,
struct iwl_fw_dbg_trigger_tlv *trig;
struct iwl_fw_dbg_trigger_ba *ba_trig;
- if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_BA))
+ trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, NULL, FW_DBG_TRIGGER_BA);
+ if (!trig)
return;
- trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_BA);
ba_trig = (void *)trig->data;
- if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, NULL, trig))
- return;
-
if (!(le16_to_cpu(ba_trig->tx_bar) & BIT(tid)))
return;
@@ -1414,15 +1411,13 @@ static void iwl_mvm_tx_status_check_trigger(struct iwl_mvm *mvm,
struct iwl_fw_dbg_trigger_tx_status *status_trig;
int i;
- if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TX_STATUS))
+ trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, NULL,
+ FW_DBG_TRIGGER_TX_STATUS);
+ if (!trig)
return;
- trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_TX_STATUS);
status_trig = (void *)trig->data;
- if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, NULL, trig))
- return;
-
for (i = 0; i < ARRAY_SIZE(status_trig->statuses); i++) {
/* don't collect on status 0 */
if (!status_trig->statuses[i].status)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
index dcacc4d11abc..6c14d3413bdc 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
@@ -1238,14 +1238,12 @@ void iwl_mvm_connection_loss(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_fw_dbg_trigger_tlv *trig;
struct iwl_fw_dbg_trigger_mlme *trig_mlme;
- if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_MLME))
+ trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif),
+ FW_DBG_TRIGGER_MLME);
+ if (!trig)
goto out;
- trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_MLME);
trig_mlme = (void *)trig->data;
- if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt,
- ieee80211_vif_to_wdev(vif), trig))
- goto out;
if (trig_mlme->stop_connection_loss &&
--trig_mlme->stop_connection_loss)
@@ -1430,14 +1428,12 @@ void iwl_mvm_event_frame_timeout_callback(struct iwl_mvm *mvm,
struct iwl_fw_dbg_trigger_tlv *trig;
struct iwl_fw_dbg_trigger_ba *ba_trig;
- if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_BA))
+ trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif),
+ FW_DBG_TRIGGER_BA);
+ if (!trig)
return;
- trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_BA);
ba_trig = (void *)trig->data;
- if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt,
- ieee80211_vif_to_wdev(vif), trig))
- return;
if (!(le16_to_cpu(ba_trig->frame_timeout) & BIT(tid)))
return;
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
index d519e7ebdbe8..e965cc588850 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
@@ -1144,6 +1144,14 @@ void iwl_pcie_rx_free(struct iwl_trans *trans)
kfree(trans_pcie->rxq);
}
+static void iwl_pcie_rx_move_to_allocator(struct iwl_rxq *rxq,
+ struct iwl_rb_allocator *rba)
+{
+ spin_lock(&rba->lock);
+ list_splice_tail_init(&rxq->rx_used, &rba->rbd_empty);
+ spin_unlock(&rba->lock);
+}
+
/*
* iwl_pcie_rx_reuse_rbd - Recycle used RBDs
*
@@ -1175,9 +1183,7 @@ static void iwl_pcie_rx_reuse_rbd(struct iwl_trans *trans,
if ((rxq->used_count % RX_CLAIM_REQ_ALLOC) == RX_POST_REQ_ALLOC) {
/* Move the 2 RBDs to the allocator ownership.
Allocator has another 6 from pool for the request completion*/
- spin_lock(&rba->lock);
- list_splice_tail_init(&rxq->rx_used, &rba->rbd_empty);
- spin_unlock(&rba->lock);
+ iwl_pcie_rx_move_to_allocator(rxq, rba);
atomic_inc(&rba->req_pending);
queue_work(rba->alloc_wq, &rba->rx_alloc);
@@ -1400,10 +1406,18 @@ restart:
IWL_DEBUG_RX(trans, "Q %d: HW = SW = %d\n", rxq->id, r);
while (i != r) {
+ struct iwl_rb_allocator *rba = &trans_pcie->rba;
struct iwl_rx_mem_buffer *rxb;
-
- if (unlikely(rxq->used_count == rxq->queue_size / 2))
+ /* number of RBDs still waiting for page allocation */
+ u32 rb_pending_alloc =
+ atomic_read(&trans_pcie->rba.req_pending) *
+ RX_CLAIM_REQ_ALLOC;
+
+ if (unlikely(rb_pending_alloc >= rxq->queue_size / 2 &&
+ !emergency)) {
+ iwl_pcie_rx_move_to_allocator(rxq, rba);
emergency = true;
+ }
rxb = iwl_pcie_get_rxb(trans, rxq, i);
if (!rxb)
@@ -1425,17 +1439,13 @@ restart:
iwl_pcie_rx_allocator_get(trans, rxq);
if (rxq->used_count % RX_CLAIM_REQ_ALLOC == 0 && !emergency) {
- struct iwl_rb_allocator *rba = &trans_pcie->rba;
-
/* Add the remaining empty RBDs for allocator use */
- spin_lock(&rba->lock);
- list_splice_tail_init(&rxq->rx_used, &rba->rbd_empty);
- spin_unlock(&rba->lock);
+ iwl_pcie_rx_move_to_allocator(rxq, rba);
} else if (emergency) {
count++;
if (count == 8) {
count = 0;
- if (rxq->used_count < rxq->queue_size / 3)
+ if (rb_pending_alloc < rxq->queue_size / 3)
emergency = false;
rxq->read = i;
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index bc6682a11fa4..5bafb3f46eb8 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -931,7 +931,7 @@ void iwl_pcie_apply_destination(struct iwl_trans *trans)
else
IWL_WARN(trans, "PCI should have external buffer debug\n");
- for (i = 0; i < trans->dbg_dest_reg_num; i++) {
+ for (i = 0; i < trans->dbg_n_dest_reg; i++) {
u32 addr = le32_to_cpu(dest->reg_ops[i].addr);
u32 val = le32_to_cpu(dest->reg_ops[i].val);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
index ba9d37bed4c2..b71cf55480fc 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
@@ -438,6 +438,8 @@ static int iwl_pcie_gen2_tx_add_frags(struct iwl_trans *trans,
return -ENOMEM;
tb_idx = iwl_pcie_gen2_set_tb(trans, tfd, tb_phys,
skb_frag_size(frag));
+ if (tb_idx < 0)
+ return tb_idx;
out_meta->tbs |= BIT(tb_idx);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
index 67820bfaba64..f227b91098c9 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
@@ -2013,6 +2013,8 @@ static int iwl_fill_data_tbs(struct iwl_trans *trans, struct sk_buff *skb,
return -EINVAL;
tb_idx = iwl_pcie_txq_build_tfd(trans, txq, tb_phys,
skb_frag_size(frag), false);
+ if (tb_idx < 0)
+ return tb_idx;
out_meta->tbs |= BIT(tb_idx);
}
diff --git a/drivers/net/wireless/mediatek/mt76/Kconfig b/drivers/net/wireless/mediatek/mt76/Kconfig
index 7f24aad94efd..0ccbcd7e887d 100644
--- a/drivers/net/wireless/mediatek/mt76/Kconfig
+++ b/drivers/net/wireless/mediatek/mt76/Kconfig
@@ -13,44 +13,5 @@ config MT76x02_USB
tristate
select MT76_USB
-config MT76x0_COMMON
- tristate
- select MT76x02_LIB
-
-config MT76x2_COMMON
- tristate
- select MT76x02_LIB
-
-config MT76x0U
- tristate "MediaTek MT76x0U (USB) support"
- select MT76x0_COMMON
- select MT76x02_USB
- depends on MAC80211
- depends on USB
- help
- This adds support for MT7610U-based wireless USB dongles.
-
-config MT76x0E
- tristate "MediaTek MT76x0E (PCIe) support"
- select MT76x0_COMMON
- depends on MAC80211
- depends on PCI
- help
- This adds support for MT7610/MT7630-based wireless PCIe devices.
-
-config MT76x2E
- tristate "MediaTek MT76x2E (PCIe) support"
- select MT76x2_COMMON
- depends on MAC80211
- depends on PCI
- ---help---
- This adds support for MT7612/MT7602/MT7662-based wireless PCIe devices.
-
-config MT76x2U
- tristate "MediaTek MT76x2U (USB) support"
- select MT76x2_COMMON
- select MT76x02_USB
- depends on MAC80211
- depends on USB
- help
- This adds support for MT7612U-based wireless USB dongles.
+source "drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig"
+source "drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig"
diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile
index 4d25b5c3b70b..9b8d7488c545 100644
--- a/drivers/net/wireless/mediatek/mt76/Makefile
+++ b/drivers/net/wireless/mediatek/mt76/Makefile
@@ -1,11 +1,7 @@
obj-$(CONFIG_MT76_CORE) += mt76.o
obj-$(CONFIG_MT76_USB) += mt76-usb.o
-obj-$(CONFIG_MT76x0_COMMON) += mt76x0/
obj-$(CONFIG_MT76x02_LIB) += mt76x02-lib.o
obj-$(CONFIG_MT76x02_USB) += mt76x02-usb.o
-obj-$(CONFIG_MT76x2_COMMON) += mt76x2-common.o
-obj-$(CONFIG_MT76x2E) += mt76x2e.o
-obj-$(CONFIG_MT76x2U) += mt76x2u.o
mt76-y := \
mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o tx.o agg-rx.o
@@ -14,24 +10,13 @@ mt76-usb-y := usb.o usb_trace.o usb_mcu.o
CFLAGS_trace.o := -I$(src)
CFLAGS_usb_trace.o := -I$(src)
+CFLAGS_mt76x02_trace.o := -I$(src)
-mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o mt76x02_mcu.o
+mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o mt76x02_mcu.o \
+ mt76x02_eeprom.o mt76x02_phy.o mt76x02_mmio.o \
+ mt76x02_txrx.o mt76x02_trace.o
mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o
-mt76x2-common-y := \
- mt76x2_eeprom.o mt76x2_tx_common.o mt76x2_mac_common.o \
- mt76x2_init_common.o mt76x2_common.o mt76x2_phy_common.o \
- mt76x2_debugfs.o mt76x2_mcu_common.o
-
-mt76x2e-y := \
- mt76x2_pci.o mt76x2_dma.o \
- mt76x2_main.o mt76x2_init.o mt76x2_tx.o \
- mt76x2_core.o mt76x2_mac.o mt76x2_mcu.o mt76x2_phy.o \
- mt76x2_dfs.o mt76x2_trace.o
-
-mt76x2u-y := \
- mt76x2_usb.o mt76x2u_init.o mt76x2u_main.o mt76x2u_mac.o \
- mt76x2u_mcu.o mt76x2u_phy.o mt76x2u_core.o
-
-CFLAGS_mt76x2_trace.o := -I$(src)
+obj-$(CONFIG_MT76x0_COMMON) += mt76x0/
+obj-$(CONFIG_MT76x2_COMMON) += mt76x2/
diff --git a/drivers/net/wireless/mediatek/mt76/debugfs.c b/drivers/net/wireless/mediatek/mt76/debugfs.c
index a38d05dea599..a5adf22c3ffa 100644
--- a/drivers/net/wireless/mediatek/mt76/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/debugfs.c
@@ -56,6 +56,35 @@ mt76_queues_read(struct seq_file *s, void *data)
return 0;
}
+void mt76_seq_puts_array(struct seq_file *file, const char *str,
+ s8 *val, int len)
+{
+ int i;
+
+ seq_printf(file, "%10s:", str);
+ for (i = 0; i < len; i++)
+ seq_printf(file, " %2d", val[i]);
+ seq_puts(file, "\n");
+}
+EXPORT_SYMBOL_GPL(mt76_seq_puts_array);
+
+static int mt76_read_rate_txpower(struct seq_file *s, void *data)
+{
+ struct mt76_dev *dev = dev_get_drvdata(s->private);
+
+ mt76_seq_puts_array(s, "CCK", dev->rate_power.cck,
+ ARRAY_SIZE(dev->rate_power.cck));
+ mt76_seq_puts_array(s, "OFDM", dev->rate_power.ofdm,
+ ARRAY_SIZE(dev->rate_power.ofdm));
+ mt76_seq_puts_array(s, "STBC", dev->rate_power.stbc,
+ ARRAY_SIZE(dev->rate_power.stbc));
+ mt76_seq_puts_array(s, "HT", dev->rate_power.ht,
+ ARRAY_SIZE(dev->rate_power.ht));
+ mt76_seq_puts_array(s, "VHT", dev->rate_power.vht,
+ ARRAY_SIZE(dev->rate_power.vht));
+ return 0;
+}
+
struct dentry *mt76_register_debugfs(struct mt76_dev *dev)
{
struct dentry *dir;
@@ -72,6 +101,8 @@ struct dentry *mt76_register_debugfs(struct mt76_dev *dev)
if (dev->otp.data)
debugfs_create_blob("otp", 0400, dir, &dev->otp);
debugfs_create_devm_seqfile(dev->dev, "queues", dir, mt76_queues_read);
+ debugfs_create_devm_seqfile(dev->dev, "rate_txpower", dir,
+ mt76_read_rate_txpower);
return dir;
}
diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
index 639cbafc1d50..2a699e8b79bf 100644
--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
+++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
@@ -550,6 +550,12 @@ mt76_check_ps(struct mt76_dev *dev, struct sk_buff *skb)
struct mt76_wcid *wcid = status->wcid;
bool ps;
+ if (ieee80211_is_pspoll(hdr->frame_control) && !wcid) {
+ sta = ieee80211_find_sta_by_ifaddr(dev->hw, hdr->addr2, NULL);
+ if (sta)
+ wcid = status->wcid = (struct mt76_wcid *) sta->drv_priv;
+ }
+
if (!wcid || !wcid->sta)
return;
diff --git a/drivers/net/wireless/mediatek/mt76/mmio.c b/drivers/net/wireless/mediatek/mt76/mmio.c
index 2f09f451a9b6..30a5d928e655 100644
--- a/drivers/net/wireless/mediatek/mt76/mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mmio.c
@@ -46,6 +46,30 @@ static void mt76_mmio_copy(struct mt76_dev *dev, u32 offset, const void *data,
__iowrite32_copy(dev->mmio.regs + offset, data, len >> 2);
}
+static int mt76_mmio_wr_rp(struct mt76_dev *dev, u32 base,
+ const struct mt76_reg_pair *data, int len)
+{
+ while (len > 0) {
+ mt76_mmio_wr(dev, data->reg, data->value);
+ data++;
+ len--;
+ }
+
+ return 0;
+}
+
+static int mt76_mmio_rd_rp(struct mt76_dev *dev, u32 base,
+ struct mt76_reg_pair *data, int len)
+{
+ while (len > 0) {
+ data->value = mt76_mmio_rr(dev, data->reg);
+ data++;
+ len--;
+ }
+
+ return 0;
+}
+
void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs)
{
static const struct mt76_bus_ops mt76_mmio_ops = {
@@ -53,6 +77,8 @@ void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs)
.rmw = mt76_mmio_rmw,
.wr = mt76_mmio_wr,
.copy = mt76_mmio_copy,
+ .wr_rp = mt76_mmio_wr_rp,
+ .rd_rp = mt76_mmio_rd_rp,
};
dev->bus = &mt76_mmio_ops;
@@ -60,6 +86,7 @@ void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs)
skb_queue_head_init(&dev->mmio.mcu.res_q);
init_waitqueue_head(&dev->mmio.mcu.wait);
+ spin_lock_init(&dev->mmio.irq_lock);
mutex_init(&dev->mmio.mcu.mutex);
}
EXPORT_SYMBOL_GPL(mt76_mmio_init);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index dbda49243a10..f723a07cab29 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -122,6 +122,7 @@ struct mt76_queue {
dma_addr_t desc_dma;
struct sk_buff *rx_head;
struct page_frag_cache rx_page;
+ spinlock_t rx_page_lock;
};
struct mt76_mcu_ops {
@@ -261,8 +262,6 @@ struct mt76_driver_ops {
void (*sta_ps)(struct mt76_dev *dev, struct ieee80211_sta *sta,
bool ps);
- s8 (*get_max_txpwr_adj)(struct mt76_dev *dev,
- const struct ieee80211_tx_rate *rate);
};
struct mt76_channel_state {
@@ -275,6 +274,19 @@ struct mt76_sband {
struct mt76_channel_state *chan;
};
+struct mt76_rate_power {
+ union {
+ struct {
+ s8 cck[4];
+ s8 ofdm[8];
+ s8 stbc[10];
+ s8 ht[16];
+ s8 vht[10];
+ };
+ s8 all[48];
+ };
+};
+
/* addr req mask */
#define MT_VEND_TYPE_EEPROM BIT(31)
#define MT_VEND_TYPE_CFG BIT(30)
@@ -349,6 +361,8 @@ struct mt76_mmio {
u32 msg_seq;
} mcu;
void __iomem *regs;
+ spinlock_t irq_lock;
+ u32 irqmask;
};
struct mt76_dev {
@@ -388,6 +402,7 @@ struct mt76_dev {
unsigned long state;
u8 antenna_mask;
+ u16 chainmask;
struct mt76_sband sband_2g;
struct mt76_sband sband_5g;
@@ -395,6 +410,10 @@ struct mt76_dev {
struct debugfs_blob_wrapper otp;
struct mt76_hw_cap cap;
+ struct mt76_rate_power rate_power;
+ int txpower_conf;
+ int txpower_cur;
+
u32 debugfs_reg;
struct led_classdev led_cdev;
@@ -418,18 +437,6 @@ enum mt76_phy_type {
MT_PHY_TYPE_VHT,
};
-struct mt76_rate_power {
- union {
- struct {
- s8 cck[4];
- s8 ofdm[8];
- s8 ht[16];
- s8 vht[10];
- };
- s8 all[38];
- };
-};
-
struct mt76_rx_status {
struct mt76_wcid *wcid;
@@ -539,6 +546,8 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
void mt76_unregister_device(struct mt76_dev *dev);
struct dentry *mt76_register_debugfs(struct mt76_dev *dev);
+void mt76_seq_puts_array(struct seq_file *file, const char *str,
+ s8 *val, int len);
int mt76_eeprom_init(struct mt76_dev *dev, int len);
void mt76_eeprom_override(struct mt76_dev *dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig b/drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig
new file mode 100644
index 000000000000..9a6157db3893
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig
@@ -0,0 +1,20 @@
+config MT76x0_COMMON
+ tristate
+ select MT76x02_LIB
+
+config MT76x0U
+ tristate "MediaTek MT76x0U (USB) support"
+ select MT76x0_COMMON
+ select MT76x02_USB
+ depends on MAC80211
+ depends on USB
+ help
+ This adds support for MT7610U-based wireless USB dongles.
+
+config MT76x0E
+ tristate "MediaTek MT76x0E (PCIe) support"
+ select MT76x0_COMMON
+ depends on MAC80211
+ depends on PCI
+ help
+ This adds support for MT7610/MT7630-based wireless PCIe devices.
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/Makefile b/drivers/net/wireless/mediatek/mt76/mt76x0/Makefile
index 48f7979e36ef..20672978dceb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/Makefile
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/Makefile
@@ -4,9 +4,9 @@ obj-$(CONFIG_MT76x0_COMMON) += mt76x0-common.o
mt76x0-common-y := \
init.o main.o trace.o eeprom.o phy.o \
- mac.o debugfs.o tx.o
-mt76x0u-y := usb.o
-mt76x0e-y := pci.o
+ mac.o debugfs.o
+mt76x0u-y := usb.o usb_mcu.o
+mt76x0e-y := pci.o pci_mcu.o
# ccflags-y := -DDEBUG
CFLAGS_trace.o := -I$(src)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt76x0/debugfs.c
index e7a77a886068..3224e5b1a1e5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/debugfs.c
@@ -19,29 +19,9 @@
#include "eeprom.h"
static int
-mt76_reg_set(void *data, u64 val)
-{
- struct mt76x0_dev *dev = data;
-
- mt76_wr(dev, dev->debugfs_reg, val);
- return 0;
-}
-
-static int
-mt76_reg_get(void *data, u64 *val)
-{
- struct mt76x0_dev *dev = data;
-
- *val = mt76_rr(dev, dev->debugfs_reg);
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(fops_regval, mt76_reg_get, mt76_reg_set, "0x%08llx\n");
-
-static int
mt76x0_ampdu_stat_read(struct seq_file *file, void *data)
{
- struct mt76x0_dev *dev = file->private;
+ struct mt76x02_dev *dev = file->private;
int i, j;
#define stat_printf(grp, off, name) \
@@ -95,72 +75,13 @@ static const struct file_operations fops_ampdu_stat = {
.release = single_release,
};
-static int
-mt76x0_eeprom_param_read(struct seq_file *file, void *data)
-{
- struct mt76x0_dev *dev = file->private;
- int i;
-
- seq_printf(file, "RF freq offset: %hhx\n", dev->ee->rf_freq_off);
- seq_printf(file, "RSSI offset 2GHz: %hhx %hhx\n",
- dev->ee->rssi_offset_2ghz[0], dev->ee->rssi_offset_2ghz[1]);
- seq_printf(file, "RSSI offset 5GHz: %hhx %hhx %hhx\n",
- dev->ee->rssi_offset_5ghz[0], dev->ee->rssi_offset_5ghz[1],
- dev->ee->rssi_offset_5ghz[2]);
- seq_printf(file, "Temperature offset: %hhx\n", dev->ee->temp_off);
- seq_printf(file, "LNA gain 2Ghz: %hhx\n", dev->ee->lna_gain_2ghz);
- seq_printf(file, "LNA gain 5Ghz: %hhx %hhx %hhx\n",
- dev->ee->lna_gain_5ghz[0], dev->ee->lna_gain_5ghz[1],
- dev->ee->lna_gain_5ghz[2]);
- seq_printf(file, "Power Amplifier type %hhx\n", dev->ee->pa_type);
- seq_printf(file, "Reg channels: %hhu-%hhu\n", dev->ee->reg.start,
- dev->ee->reg.start + dev->ee->reg.num - 1);
-
- seq_puts(file, "Per channel power:\n");
- for (i = 0; i < 58; i++)
- seq_printf(file, "\t%d chan:%d pwr:%d\n", i, i,
- dev->ee->tx_pwr_per_chan[i]);
-
- seq_puts(file, "Per rate power 2GHz:\n");
- for (i = 0; i < 5; i++)
- seq_printf(file, "\t %d bw20:%d bw40:%d\n",
- i, dev->ee->tx_pwr_cfg_2g[i][0],
- dev->ee->tx_pwr_cfg_5g[i][1]);
-
- seq_puts(file, "Per rate power 5GHz:\n");
- for (i = 0; i < 5; i++)
- seq_printf(file, "\t %d bw20:%d bw40:%d\n",
- i, dev->ee->tx_pwr_cfg_5g[i][0],
- dev->ee->tx_pwr_cfg_5g[i][1]);
-
- return 0;
-}
-
-static int
-mt76x0_eeprom_param_open(struct inode *inode, struct file *f)
-{
- return single_open(f, mt76x0_eeprom_param_read, inode->i_private);
-}
-
-static const struct file_operations fops_eeprom_param = {
- .open = mt76x0_eeprom_param_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-void mt76x0_init_debugfs(struct mt76x0_dev *dev)
+void mt76x0_init_debugfs(struct mt76x02_dev *dev)
{
struct dentry *dir;
- dir = debugfs_create_dir("mt76x0", dev->mt76.hw->wiphy->debugfsdir);
+ dir = mt76_register_debugfs(&dev->mt76);
if (!dir)
return;
- debugfs_create_u32("regidx", S_IRUSR | S_IWUSR, dir, &dev->debugfs_reg);
- debugfs_create_file("regval", S_IRUSR | S_IWUSR, dir, dev,
- &fops_regval);
debugfs_create_file("ampdu_stat", S_IRUSR, dir, dev, &fops_ampdu_stat);
- debugfs_create_file("eeprom_param", S_IRUSR, dir, dev,
- &fops_eeprom_param);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
index 79856bde1632..5735038c0e2d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
@@ -13,6 +13,7 @@
* GNU General Public License for more details.
*/
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
@@ -20,81 +21,20 @@
#include <asm/unaligned.h>
#include "mt76x0.h"
#include "eeprom.h"
-
-static bool
-field_valid(u8 val)
-{
- return val != 0xff;
-}
-
-static s8
-field_validate(u8 val)
-{
- if (!field_valid(val))
- return 0;
-
- return val;
-}
-
-static inline int
-sign_extend(u32 val, unsigned int size)
-{
- bool sign = val & BIT(size - 1);
-
- val &= BIT(size - 1) - 1;
-
- return sign ? val : -val;
-}
-
-static int
-mt76x0_efuse_read(struct mt76x0_dev *dev, u16 addr, u8 *data,
- enum mt76x0_eeprom_access_modes mode)
-{
- u32 val;
- int i;
-
- val = mt76_rr(dev, MT_EFUSE_CTRL);
- val &= ~(MT_EFUSE_CTRL_AIN |
- MT_EFUSE_CTRL_MODE);
- val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf) |
- FIELD_PREP(MT_EFUSE_CTRL_MODE, mode) |
- MT_EFUSE_CTRL_KICK;
- mt76_wr(dev, MT_EFUSE_CTRL, val);
-
- if (!mt76_poll(dev, MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000))
- return -ETIMEDOUT;
-
- val = mt76_rr(dev, MT_EFUSE_CTRL);
- if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT) {
- /* Parts of eeprom not in the usage map (0x80-0xc0,0xf0)
- * will not return valid data but it's ok.
- */
- memset(data, 0xff, 16);
- return 0;
- }
-
- for (i = 0; i < 4; i++) {
- val = mt76_rr(dev, MT_EFUSE_DATA(i));
- put_unaligned_le32(val, data + 4 * i);
- }
-
- return 0;
-}
+#include "../mt76x02_phy.h"
#define MT_MAP_READS DIV_ROUND_UP(MT_EFUSE_USAGE_MAP_SIZE, 16)
static int
-mt76x0_efuse_physical_size_check(struct mt76x0_dev *dev)
+mt76x0_efuse_physical_size_check(struct mt76x02_dev *dev)
{
u8 data[MT_MAP_READS * 16];
int ret, i;
u32 start = 0, end = 0, cnt_free;
- for (i = 0; i < MT_MAP_READS; i++) {
- ret = mt76x0_efuse_read(dev, MT_EE_USAGE_MAP_START + i * 16,
- data + i * 16, MT_EE_PHYSICAL_READ);
- if (ret)
- return ret;
- }
+ ret = mt76x02_get_efuse_data(&dev->mt76, MT_EE_USAGE_MAP_START,
+ data, sizeof(data), MT_EE_PHYSICAL_READ);
+ if (ret)
+ return ret;
for (i = 0; i < MT_EFUSE_USAGE_MAP_SIZE; i++)
if (!data[i]) {
@@ -105,345 +45,307 @@ mt76x0_efuse_physical_size_check(struct mt76x0_dev *dev)
cnt_free = end - start + 1;
if (MT_EFUSE_USAGE_MAP_SIZE - cnt_free < 5) {
- dev_err(dev->mt76.dev, "Error: your device needs default EEPROM file and this driver doesn't support it!\n");
+ dev_err(dev->mt76.dev,
+ "driver does not support default EEPROM\n");
return -EINVAL;
}
return 0;
}
-static void
-mt76x0_set_chip_cap(struct mt76x0_dev *dev, u8 *eeprom)
+static void mt76x0_set_chip_cap(struct mt76x02_dev *dev)
{
- enum mt76x2_board_type { BOARD_TYPE_2GHZ = 1, BOARD_TYPE_5GHZ = 2 };
- u16 nic_conf0 = get_unaligned_le16(eeprom + MT_EE_NIC_CONF_0);
- u16 nic_conf1 = get_unaligned_le16(eeprom + MT_EE_NIC_CONF_1);
-
- dev_dbg(dev->mt76.dev, "NIC_CONF0: %04x NIC_CONF1: %04x\n", nic_conf0, nic_conf1);
-
- switch (FIELD_GET(MT_EE_NIC_CONF_0_BOARD_TYPE, nic_conf0)) {
- case BOARD_TYPE_5GHZ:
- dev->mt76.cap.has_5ghz = true;
- break;
- case BOARD_TYPE_2GHZ:
- dev->mt76.cap.has_2ghz = true;
- break;
- default:
- dev->mt76.cap.has_2ghz = true;
- dev->mt76.cap.has_5ghz = true;
- break;
- }
+ u16 nic_conf0 = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_0);
+ u16 nic_conf1 = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_1);
- dev_dbg(dev->mt76.dev, "Has 2GHZ %d 5GHZ %d\n",
+ mt76x02_eeprom_parse_hw_cap(&dev->mt76);
+ dev_dbg(dev->mt76.dev, "2GHz %d 5GHz %d\n",
dev->mt76.cap.has_2ghz, dev->mt76.cap.has_5ghz);
- if (!field_valid(nic_conf1 & 0xff))
+ if (dev->no_2ghz) {
+ dev->mt76.cap.has_2ghz = false;
+ dev_dbg(dev->mt76.dev, "mask out 2GHz support\n");
+ }
+
+ if (!mt76x02_field_valid(nic_conf1 & 0xff))
nic_conf1 &= 0xff00;
if (nic_conf1 & MT_EE_NIC_CONF_1_HW_RF_CTRL)
dev_err(dev->mt76.dev,
- "Error: this driver does not support HW RF ctrl\n");
+ "driver does not support HW RF ctrl\n");
- if (!field_valid(nic_conf0 >> 8))
+ if (!mt76x02_field_valid(nic_conf0 >> 8))
return;
if (FIELD_GET(MT_EE_NIC_CONF_0_RX_PATH, nic_conf0) > 1 ||
FIELD_GET(MT_EE_NIC_CONF_0_TX_PATH, nic_conf0) > 1)
- dev_err(dev->mt76.dev,
- "Error: device has more than 1 RX/TX stream!\n");
-
- dev->ee->pa_type = FIELD_GET(MT_EE_NIC_CONF_0_PA_TYPE, nic_conf0);
- dev_dbg(dev->mt76.dev, "PA Type %d\n", dev->ee->pa_type);
+ dev_err(dev->mt76.dev, "invalid tx-rx stream\n");
}
-static int
-mt76x0_set_macaddr(struct mt76x0_dev *dev, const u8 *eeprom)
+static void mt76x0_set_temp_offset(struct mt76x02_dev *dev)
{
- const void *src = eeprom + MT_EE_MAC_ADDR;
- u8 *dst = dev->mt76.macaddr;
-
- ether_addr_copy(dev->mt76.macaddr, src);
+ u8 val;
- if (!is_valid_ether_addr(dst)) {
- eth_random_addr(dst);
- dev_info(dev->mt76.dev,
- "Invalid MAC address, using random address %pM\n",
- dst);
- }
-
- mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(dst));
- mt76_wr(dev, MT_MAC_ADDR_DW1, get_unaligned_le16(dst + 4) |
- FIELD_PREP(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff));
-
- return 0;
-}
-
-static void
-mt76x0_set_temp_offset(struct mt76x0_dev *dev, u8 *eeprom)
-{
- u8 temp = eeprom[MT_EE_TEMP_OFFSET];
-
- if (field_valid(temp))
- dev->ee->temp_off = sign_extend(temp, 8);
+ val = mt76x02_eeprom_get(&dev->mt76, MT_EE_2G_TARGET_POWER) >> 8;
+ if (mt76x02_field_valid(val))
+ dev->cal.rx.temp_offset = mt76x02_sign_extend(val, 8);
else
- dev->ee->temp_off = -10;
+ dev->cal.rx.temp_offset = -10;
}
-static void
-mt76x0_set_country_reg(struct mt76x0_dev *dev, u8 *eeprom)
+static void mt76x0_set_freq_offset(struct mt76x02_dev *dev)
{
- /* Note: - region 31 is not valid for mt76x0 (see rtmp_init.c)
- * - comments in rtmp_def.h are incorrect (see rt_channel.c)
- */
- static const struct reg_channel_bounds chan_bounds[] = {
- /* EEPROM country regions 0 - 7 */
- { 1, 11 }, { 1, 13 }, { 10, 2 }, { 10, 4 },
- { 14, 1 }, { 1, 14 }, { 3, 7 }, { 5, 9 },
- /* EEPROM country regions 32 - 33 */
- { 1, 11 }, { 1, 14 }
- };
- u8 val = eeprom[MT_EE_COUNTRY_REGION_2GHZ];
- int idx = -1;
-
- dev_dbg(dev->mt76.dev, "REG 2GHZ %u REG 5GHZ %u\n", val, eeprom[MT_EE_COUNTRY_REGION_5GHZ]);
- if (val < 8)
- idx = val;
- if (val > 31 && val < 33)
- idx = val - 32 + 8;
-
- if (idx != -1)
- dev_info(dev->mt76.dev,
- "EEPROM country region %02hhx (channels %hhd-%hhd)\n",
- val, chan_bounds[idx].start,
- chan_bounds[idx].start + chan_bounds[idx].num - 1);
- else
- idx = 5; /* channels 1 - 14 */
-
- dev->ee->reg = chan_bounds[idx];
-
- /* TODO: country region 33 is special - phy should be set to B-mode
- * before entering channel 14 (see sta/connect.c)
- */
-}
+ struct mt76x02_rx_freq_cal *caldata = &dev->cal.rx;
+ u8 val;
-static void
-mt76x0_set_rf_freq_off(struct mt76x0_dev *dev, u8 *eeprom)
-{
- u8 comp;
+ val = mt76x02_eeprom_get(&dev->mt76, MT_EE_FREQ_OFFSET);
+ if (!mt76x02_field_valid(val))
+ val = 0;
+ caldata->freq_offset = val;
- dev->ee->rf_freq_off = field_validate(eeprom[MT_EE_FREQ_OFFSET]);
- comp = field_validate(eeprom[MT_EE_FREQ_OFFSET_COMPENSATION]);
+ val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TSSI_BOUND4) >> 8;
+ if (!mt76x02_field_valid(val))
+ val = 0;
- if (comp & BIT(7))
- dev->ee->rf_freq_off -= comp & 0x7f;
- else
- dev->ee->rf_freq_off += comp;
+ caldata->freq_offset -= mt76x02_sign_extend(val, 8);
}
-static void
-mt76x0_set_lna_gain(struct mt76x0_dev *dev, u8 *eeprom)
+void mt76x0_read_rx_gain(struct mt76x02_dev *dev)
{
- u8 gain;
+ struct ieee80211_channel *chan = dev->mt76.chandef.chan;
+ struct mt76x02_rx_freq_cal *caldata = &dev->cal.rx;
+ s8 val, lna_5g[3], lna_2g;
+ u16 rssi_offset;
+ int i;
- dev->ee->lna_gain_2ghz = eeprom[MT_EE_LNA_GAIN_2GHZ];
- dev->ee->lna_gain_5ghz[0] = eeprom[MT_EE_LNA_GAIN_5GHZ_0];
+ mt76x02_get_rx_gain(&dev->mt76, chan->band, &rssi_offset,
+ &lna_2g, lna_5g);
+ caldata->lna_gain = mt76x02_get_lna_gain(&dev->mt76, &lna_2g,
+ lna_5g, chan);
- gain = eeprom[MT_EE_LNA_GAIN_5GHZ_1];
- if (gain == 0xff || gain == 0)
- dev->ee->lna_gain_5ghz[1] = dev->ee->lna_gain_5ghz[0];
- else
- dev->ee->lna_gain_5ghz[1] = gain;
+ for (i = 0; i < ARRAY_SIZE(caldata->rssi_offset); i++) {
+ val = rssi_offset >> (8 * i);
+ if (val < -10 || val > 10)
+ val = 0;
- gain = eeprom[MT_EE_LNA_GAIN_5GHZ_2];
- if (gain == 0xff || gain == 0)
- dev->ee->lna_gain_5ghz[2] = dev->ee->lna_gain_5ghz[0];
- else
- dev->ee->lna_gain_5ghz[2] = gain;
+ caldata->rssi_offset[i] = val;
+ }
}
-static void
-mt76x0_set_rssi_offset(struct mt76x0_dev *dev, u8 *eeprom)
+static s8 mt76x0_get_delta(struct mt76_dev *dev)
{
- int i;
- s8 *rssi_offset = dev->ee->rssi_offset_2ghz;
+ struct cfg80211_chan_def *chandef = &dev->chandef;
+ u8 val;
- for (i = 0; i < 2; i++) {
- rssi_offset[i] = eeprom[MT_EE_RSSI_OFFSET + i];
-
- if (rssi_offset[i] < -10 || rssi_offset[i] > 10) {
- dev_warn(dev->mt76.dev,
- "Warning: EEPROM RSSI is invalid %02hhx\n",
- rssi_offset[i]);
- rssi_offset[i] = 0;
- }
- }
-
- rssi_offset = dev->ee->rssi_offset_5ghz;
+ if (mt76x02_tssi_enabled(dev))
+ return 0;
- for (i = 0; i < 3; i++) {
- rssi_offset[i] = eeprom[MT_EE_RSSI_OFFSET_5GHZ + i];
+ if (chandef->width == NL80211_CHAN_WIDTH_80) {
+ val = mt76x02_eeprom_get(dev, MT_EE_5G_TARGET_POWER) >> 8;
+ } else if (chandef->width == NL80211_CHAN_WIDTH_40) {
+ u16 data;
- if (rssi_offset[i] < -10 || rssi_offset[i] > 10) {
- dev_warn(dev->mt76.dev,
- "Warning: EEPROM RSSI is invalid %02hhx\n",
- rssi_offset[i]);
- rssi_offset[i] = 0;
- }
+ data = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_DELTA_BW40);
+ if (chandef->chan->band == NL80211_BAND_5GHZ)
+ val = data >> 8;
+ else
+ val = data;
+ } else {
+ return 0;
}
+
+ return mt76x02_rate_power_val(val);
}
-static u32
-calc_bw40_power_rate(u32 value, int delta)
+void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev)
{
- u32 ret = 0;
- int i, tmp;
-
- for (i = 0; i < 4; i++) {
- tmp = s6_to_int((value >> i*8) & 0xff) + delta;
- ret |= (u32)(int_to_s6(tmp)) << i*8;
- }
-
- return ret;
+ struct ieee80211_channel *chan = dev->mt76.chandef.chan;
+ bool is_2ghz = chan->band == NL80211_BAND_2GHZ;
+ struct mt76_rate_power *t = &dev->mt76.rate_power;
+ s8 delta = mt76x0_get_delta(&dev->mt76);
+ u16 val, addr;
+
+ memset(t, 0, sizeof(*t));
+
+ /* cck 1M, 2M, 5.5M, 11M */
+ val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_BYRATE_BASE);
+ t->cck[0] = t->cck[1] = s6_to_s8(val);
+ t->cck[2] = t->cck[3] = s6_to_s8(val >> 8);
+
+ /* ofdm 6M, 9M, 12M, 18M */
+ addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 2 : 0x120;
+ val = mt76x02_eeprom_get(&dev->mt76, addr);
+ t->ofdm[0] = t->ofdm[1] = s6_to_s8(val);
+ t->ofdm[2] = t->ofdm[3] = s6_to_s8(val >> 8);
+
+ /* ofdm 24M, 36M, 48M, 54M */
+ addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 4 : 0x122;
+ val = mt76x02_eeprom_get(&dev->mt76, addr);
+ t->ofdm[4] = t->ofdm[5] = s6_to_s8(val);
+ t->ofdm[6] = t->ofdm[7] = s6_to_s8(val >> 8);
+
+ /* ht-vht mcs 1ss 0, 1, 2, 3 */
+ addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 6 : 0x124;
+ val = mt76x02_eeprom_get(&dev->mt76, addr);
+ t->ht[0] = t->ht[1] = t->vht[0] = t->vht[1] = s6_to_s8(val);
+ t->ht[2] = t->ht[3] = t->vht[2] = t->vht[3] = s6_to_s8(val >> 8);
+
+ /* ht-vht mcs 1ss 4, 5, 6 */
+ addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 8 : 0x126;
+ val = mt76x02_eeprom_get(&dev->mt76, addr);
+ t->ht[4] = t->ht[5] = t->vht[4] = t->vht[5] = s6_to_s8(val);
+ t->ht[6] = t->vht[6] = s6_to_s8(val >> 8);
+
+ /* ht-vht mcs 1ss 0, 1, 2, 3 stbc */
+ addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 14 : 0xec;
+ val = mt76x02_eeprom_get(&dev->mt76, addr);
+ t->stbc[0] = t->stbc[1] = s6_to_s8(val);
+ t->stbc[2] = t->stbc[3] = s6_to_s8(val >> 8);
+
+ /* ht-vht mcs 1ss 4, 5, 6 stbc */
+ addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 16 : 0xee;
+ val = mt76x02_eeprom_get(&dev->mt76, addr);
+ t->stbc[4] = t->stbc[5] = s6_to_s8(val);
+ t->stbc[6] = t->stbc[7] = s6_to_s8(val >> 8);
+
+ /* vht mcs 8, 9 5GHz */
+ val = mt76x02_eeprom_get(&dev->mt76, 0x132);
+ t->vht[7] = s6_to_s8(val);
+ t->vht[8] = s6_to_s8(val >> 8);
+
+ mt76x02_add_rate_power_offset(t, delta);
}
-static s8
-get_delta(u8 val)
+void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info)
{
- s8 ret;
+ struct mt76x0_chan_map {
+ u8 chan;
+ u8 offset;
+ } chan_map[] = {
+ { 2, 0 }, { 4, 1 }, { 6, 2 }, { 8, 3 },
+ { 10, 4 }, { 12, 5 }, { 14, 6 }, { 38, 0 },
+ { 44, 1 }, { 48, 2 }, { 54, 3 }, { 60, 4 },
+ { 64, 5 }, { 102, 6 }, { 108, 7 }, { 112, 8 },
+ { 118, 9 }, { 124, 10 }, { 128, 11 }, { 134, 12 },
+ { 140, 13 }, { 151, 14 }, { 157, 15 }, { 161, 16 },
+ { 167, 17 }, { 171, 18 }, { 173, 19 },
+ };
+ struct ieee80211_channel *chan = dev->mt76.chandef.chan;
+ u8 offset, addr;
+ u16 data;
+ int i;
- if (!field_valid(val) || !(val & BIT(7)))
- return 0;
+ for (i = 0; i < ARRAY_SIZE(chan_map); i++) {
+ if (chan_map[i].chan <= chan->hw_value) {
+ offset = chan_map[i].offset;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(chan_map))
+ offset = chan_map[0].offset;
+
+ if (chan->band == NL80211_BAND_2GHZ) {
+ addr = MT_EE_TX_POWER_DELTA_BW80 + offset;
+ } else {
+ switch (chan->hw_value) {
+ case 58:
+ offset = 8;
+ break;
+ case 106:
+ offset = 14;
+ break;
+ case 112:
+ offset = 20;
+ break;
+ case 155:
+ offset = 30;
+ break;
+ default:
+ break;
+ }
+ addr = MT_EE_TX_POWER_0_GRP4_TSSI_SLOPE + 2 + offset;
+ }
+
+ data = mt76x02_eeprom_get(&dev->mt76, addr);
- ret = val & 0x1f;
- if (ret > 8)
- ret = 8;
- if (val & BIT(6))
- ret = -ret;
+ info[0] = data;
+ if (!info[0] || info[0] > 0x3f)
+ info[0] = 5;
- return ret;
+ info[1] = data >> 8;
+ if (!info[1] || info[1] > 0x3f)
+ info[1] = 5;
}
-static void
-mt76x0_set_tx_power_per_rate(struct mt76x0_dev *dev, u8 *eeprom)
+static int mt76x0_check_eeprom(struct mt76x02_dev *dev)
{
- s8 bw40_delta_2g, bw40_delta_5g;
- u32 val;
- int i;
-
- bw40_delta_2g = get_delta(eeprom[MT_EE_TX_POWER_DELTA_BW40]);
- bw40_delta_5g = get_delta(eeprom[MT_EE_TX_POWER_DELTA_BW40 + 1]);
+ u16 val;
- for (i = 0; i < 5; i++) {
- val = get_unaligned_le32(eeprom + MT_EE_TX_POWER_BYRATE(i));
+ val = get_unaligned_le16(dev->mt76.eeprom.data);
+ if (!val)
+ val = get_unaligned_le16(dev->mt76.eeprom.data +
+ MT_EE_PCI_ID);
- /* Skip last 16 bits. */
- if (i == 4)
- val &= 0x0000ffff;
-
- dev->ee->tx_pwr_cfg_2g[i][0] = val;
- dev->ee->tx_pwr_cfg_2g[i][1] = calc_bw40_power_rate(val, bw40_delta_2g);
+ switch (val) {
+ case 0x7650:
+ case 0x7610:
+ return 0;
+ default:
+ dev_err(dev->mt76.dev, "EEPROM data check failed: %04x\n",
+ val);
+ return -EINVAL;
}
-
- /* Reading per rate tx power for 5 GHz band is a bit more complex. Note
- * we mix 16 bit and 32 bit reads and sometimes do shifts.
- */
- val = get_unaligned_le16(eeprom + 0x120);
- val <<= 16;
- dev->ee->tx_pwr_cfg_5g[0][0] = val;
- dev->ee->tx_pwr_cfg_5g[0][1] = calc_bw40_power_rate(val, bw40_delta_5g);
-
- val = get_unaligned_le32(eeprom + 0x122);
- dev->ee->tx_pwr_cfg_5g[1][0] = val;
- dev->ee->tx_pwr_cfg_5g[1][1] = calc_bw40_power_rate(val, bw40_delta_5g);
-
- val = get_unaligned_le16(eeprom + 0x126);
- dev->ee->tx_pwr_cfg_5g[2][0] = val;
- dev->ee->tx_pwr_cfg_5g[2][1] = calc_bw40_power_rate(val, bw40_delta_5g);
-
- val = get_unaligned_le16(eeprom + 0xec);
- val <<= 16;
- dev->ee->tx_pwr_cfg_5g[3][0] = val;
- dev->ee->tx_pwr_cfg_5g[3][1] = calc_bw40_power_rate(val, bw40_delta_5g);
-
- val = get_unaligned_le16(eeprom + 0xee);
- dev->ee->tx_pwr_cfg_5g[4][0] = val;
- dev->ee->tx_pwr_cfg_5g[4][1] = calc_bw40_power_rate(val, bw40_delta_5g);
}
-static void
-mt76x0_set_tx_power_per_chan(struct mt76x0_dev *dev, u8 *eeprom)
+static int mt76x0_load_eeprom(struct mt76x02_dev *dev)
{
- int i;
- u8 tx_pwr;
+ int found;
- for (i = 0; i < 14; i++) {
- tx_pwr = eeprom[MT_EE_TX_POWER_OFFSET_2GHZ + i];
- if (tx_pwr <= 0x3f && tx_pwr > 0)
- dev->ee->tx_pwr_per_chan[i] = tx_pwr;
- else
- dev->ee->tx_pwr_per_chan[i] = 5;
- }
+ found = mt76_eeprom_init(&dev->mt76, MT76X0_EEPROM_SIZE);
+ if (found < 0)
+ return found;
- for (i = 0; i < 40; i++) {
- tx_pwr = eeprom[MT_EE_TX_POWER_OFFSET_5GHZ + i];
- if (tx_pwr <= 0x3f && tx_pwr > 0)
- dev->ee->tx_pwr_per_chan[14 + i] = tx_pwr;
- else
- dev->ee->tx_pwr_per_chan[14 + i] = 5;
- }
+ if (found && !mt76x0_check_eeprom(dev))
+ return 0;
+
+ found = mt76x0_efuse_physical_size_check(dev);
+ if (found < 0)
+ return found;
- dev->ee->tx_pwr_per_chan[54] = dev->ee->tx_pwr_per_chan[22];
- dev->ee->tx_pwr_per_chan[55] = dev->ee->tx_pwr_per_chan[28];
- dev->ee->tx_pwr_per_chan[56] = dev->ee->tx_pwr_per_chan[34];
- dev->ee->tx_pwr_per_chan[57] = dev->ee->tx_pwr_per_chan[44];
+ return mt76x02_get_efuse_data(&dev->mt76, 0, dev->mt76.eeprom.data,
+ MT76X0_EEPROM_SIZE, MT_EE_READ);
}
-int
-mt76x0_eeprom_init(struct mt76x0_dev *dev)
+int mt76x0_eeprom_init(struct mt76x02_dev *dev)
{
- u8 *eeprom;
- int i, ret;
-
- ret = mt76x0_efuse_physical_size_check(dev);
- if (ret)
- return ret;
+ u8 version, fae;
+ u16 data;
+ int err;
- dev->ee = devm_kzalloc(dev->mt76.dev, sizeof(*dev->ee), GFP_KERNEL);
- if (!dev->ee)
- return -ENOMEM;
+ err = mt76x0_load_eeprom(dev);
+ if (err < 0)
+ return err;
- eeprom = kmalloc(MT76X0_EEPROM_SIZE, GFP_KERNEL);
- if (!eeprom)
- return -ENOMEM;
+ data = mt76x02_eeprom_get(&dev->mt76, MT_EE_VERSION);
+ version = data >> 8;
+ fae = data;
- for (i = 0; i + 16 <= MT76X0_EEPROM_SIZE; i += 16) {
- ret = mt76x0_efuse_read(dev, i, eeprom + i, MT_EE_READ);
- if (ret)
- goto out;
- }
-
- if (eeprom[MT_EE_VERSION_EE] > MT76X0U_EE_MAX_VER)
+ if (version > MT76X0U_EE_MAX_VER)
dev_warn(dev->mt76.dev,
"Warning: unsupported EEPROM version %02hhx\n",
- eeprom[MT_EE_VERSION_EE]);
+ version);
dev_info(dev->mt76.dev, "EEPROM ver:%02hhx fae:%02hhx\n",
- eeprom[MT_EE_VERSION_EE], eeprom[MT_EE_VERSION_FAE]);
-
- mt76x0_set_macaddr(dev, eeprom);
- mt76x0_set_chip_cap(dev, eeprom);
- mt76x0_set_country_reg(dev, eeprom);
- mt76x0_set_rf_freq_off(dev, eeprom);
- mt76x0_set_temp_offset(dev, eeprom);
- mt76x0_set_lna_gain(dev, eeprom);
- mt76x0_set_rssi_offset(dev, eeprom);
- dev->chainmask = 0x0101;
-
- mt76x0_set_tx_power_per_rate(dev, eeprom);
- mt76x0_set_tx_power_per_chan(dev, eeprom);
-
-out:
- kfree(eeprom);
- return ret;
+ version, fae);
+
+ mt76x02_mac_setaddr(&dev->mt76,
+ dev->mt76.eeprom.data + MT_EE_MAC_ADDR);
+ mt76x0_set_chip_cap(dev);
+ mt76x0_set_freq_offset(dev);
+ mt76x0_set_temp_offset(dev);
+
+ dev->mt76.chainmask = 0x0101;
+
+ return 0;
}
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h
index cd0f14361405..40fd4e61769b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h
@@ -16,131 +16,25 @@
#ifndef __MT76X0U_EEPROM_H
#define __MT76X0U_EEPROM_H
-struct mt76x0_dev;
+#include "../mt76x02_eeprom.h"
-#define MT76X0U_EE_MAX_VER 0x0c
-#define MT76X0_EEPROM_SIZE 512
+struct mt76x02_dev;
-#define MT76X0U_DEFAULT_TX_POWER 6
+#define MT76X0U_EE_MAX_VER 0x0c
+#define MT76X0_EEPROM_SIZE 512
-enum mt76_eeprom_field {
- MT_EE_CHIP_ID = 0x00,
- MT_EE_VERSION_FAE = 0x02,
- MT_EE_VERSION_EE = 0x03,
- MT_EE_MAC_ADDR = 0x04,
- MT_EE_NIC_CONF_0 = 0x34,
- MT_EE_NIC_CONF_1 = 0x36,
- MT_EE_COUNTRY_REGION_5GHZ = 0x38,
- MT_EE_COUNTRY_REGION_2GHZ = 0x39,
- MT_EE_FREQ_OFFSET = 0x3a,
- MT_EE_NIC_CONF_2 = 0x42,
+int mt76x0_eeprom_init(struct mt76x02_dev *dev);
+void mt76x0_read_rx_gain(struct mt76x02_dev *dev);
+void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev);
+void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info);
- MT_EE_LNA_GAIN_2GHZ = 0x44,
- MT_EE_LNA_GAIN_5GHZ_0 = 0x45,
- MT_EE_RSSI_OFFSET = 0x46,
- MT_EE_RSSI_OFFSET_5GHZ = 0x4a,
- MT_EE_LNA_GAIN_5GHZ_1 = 0x49,
- MT_EE_LNA_GAIN_5GHZ_2 = 0x4d,
-
- MT_EE_TX_POWER_DELTA_BW40 = 0x50,
-
- MT_EE_TX_POWER_OFFSET_2GHZ = 0x52,
-
- MT_EE_TX_TSSI_SLOPE = 0x6e,
- MT_EE_TX_TSSI_OFFSET_GROUP = 0x6f,
- MT_EE_TX_TSSI_OFFSET = 0x76,
-
- MT_EE_TX_POWER_OFFSET_5GHZ = 0x78,
-
- MT_EE_TEMP_OFFSET = 0xd1,
- MT_EE_FREQ_OFFSET_COMPENSATION = 0xdb,
- MT_EE_TX_POWER_BYRATE_BASE = 0xde,
-
- MT_EE_TX_POWER_BYRATE_BASE_5GHZ = 0x120,
-
- MT_EE_USAGE_MAP_START = 0x1e0,
- MT_EE_USAGE_MAP_END = 0x1fc,
-};
-
-#define MT_EE_NIC_CONF_0_RX_PATH GENMASK(3, 0)
-#define MT_EE_NIC_CONF_0_TX_PATH GENMASK(7, 4)
-#define MT_EE_NIC_CONF_0_PA_TYPE GENMASK(9, 8)
-#define MT_EE_NIC_CONF_0_BOARD_TYPE GENMASK(13, 12)
-
-#define MT_EE_NIC_CONF_1_HW_RF_CTRL BIT(0)
-#define MT_EE_NIC_CONF_1_TEMP_TX_ALC BIT(1)
-#define MT_EE_NIC_CONF_1_LNA_EXT_2G BIT(2)
-#define MT_EE_NIC_CONF_1_LNA_EXT_5G BIT(3)
-#define MT_EE_NIC_CONF_1_TX_ALC_EN BIT(13)
-
-#define MT_EE_NIC_CONF_2_RX_STREAM GENMASK(3, 0)
-#define MT_EE_NIC_CONF_2_TX_STREAM GENMASK(7, 4)
-#define MT_EE_NIC_CONF_2_HW_ANTDIV BIT(8)
-#define MT_EE_NIC_CONF_2_XTAL_OPTION GENMASK(10, 9)
-#define MT_EE_NIC_CONF_2_TEMP_DISABLE BIT(11)
-#define MT_EE_NIC_CONF_2_COEX_METHOD GENMASK(15, 13)
-
-#define MT_EE_TX_POWER_BYRATE(i) (MT_EE_TX_POWER_BYRATE_BASE + \
- (i) * 4)
-
-#define MT_EFUSE_USAGE_MAP_SIZE (MT_EE_USAGE_MAP_END - \
- MT_EE_USAGE_MAP_START + 1)
-
-enum mt76x0_eeprom_access_modes {
- MT_EE_READ = 0,
- MT_EE_PHYSICAL_READ = 1,
-};
-
-struct reg_channel_bounds {
- u8 start;
- u8 num;
-};
-
-struct mt76x0_eeprom_params {
- u8 rf_freq_off;
- s16 temp_off;
- s8 rssi_offset_2ghz[2];
- s8 rssi_offset_5ghz[3];
- s8 lna_gain_2ghz;
- s8 lna_gain_5ghz[3];
- u8 pa_type;
-
- /* TX_PWR_CFG_* values from EEPROM for 20 and 40 Mhz bandwidths. */
- u32 tx_pwr_cfg_2g[5][2];
- u32 tx_pwr_cfg_5g[5][2];
-
- u8 tx_pwr_per_chan[58];
-
- struct reg_channel_bounds reg;
-};
-
-int mt76x0_eeprom_init(struct mt76x0_dev *dev);
-
-static inline u32 s6_validate(u32 reg)
-{
- WARN_ON(reg & ~GENMASK(5, 0));
- return reg & GENMASK(5, 0);
-}
-
-static inline int s6_to_int(u32 reg)
-{
- int s6;
-
- s6 = s6_validate(reg);
- if (s6 & BIT(5))
- s6 -= BIT(6);
-
- return s6;
-}
-
-static inline u32 int_to_s6(int val)
+static inline s8 s6_to_s8(u32 val)
{
- if (val < -0x20)
- return 0x20;
- if (val > 0x1f)
- return 0x1f;
+ s8 ret = val & GENMASK(5, 0);
- return val & 0x3f;
+ if (ret & BIT(5))
+ ret -= BIT(6);
+ return ret;
}
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
index 3a88be267daf..ee2b8e885608 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
@@ -18,8 +18,6 @@
#include "eeprom.h"
#include "trace.h"
#include "mcu.h"
-#include "../mt76x02_util.h"
-
#include "initvals.h"
static void mt76x0_vht_cap_mask(struct ieee80211_supported_band *sband)
@@ -41,9 +39,9 @@ static void mt76x0_vht_cap_mask(struct ieee80211_supported_band *sband)
}
static void
-mt76x0_set_wlan_state(struct mt76x0_dev *dev, u32 val, bool enable)
+mt76x0_set_wlan_state(struct mt76x02_dev *dev, u32 val, bool enable)
{
- int i;
+ u32 mask = MT_CMB_CTRL_XTAL_RDY | MT_CMB_CTRL_PLL_LD;
/* Note: we don't turn off WLAN_CLK because that makes the device
* not respond properly on the probe path.
@@ -60,32 +58,18 @@ mt76x0_set_wlan_state(struct mt76x0_dev *dev, u32 val, bool enable)
mt76_wr(dev, MT_WLAN_FUN_CTRL, val);
udelay(20);
- if (!enable)
- return;
-
- for (i = 200; i; i--) {
- val = mt76_rr(dev, MT_CMB_CTRL);
-
- if (val & MT_CMB_CTRL_XTAL_RDY && val & MT_CMB_CTRL_PLL_LD)
- break;
-
- udelay(20);
- }
-
/* Note: vendor driver tries to disable/enable wlan here and retry
* but the code which does it is so buggy it must have never
* triggered, so don't bother.
*/
- if (!i)
- dev_err(dev->mt76.dev, "Error: PLL and XTAL check failed!\n");
+ if (enable && !mt76_poll(dev, MT_CMB_CTRL, mask, mask, 2000))
+ dev_err(dev->mt76.dev, "PLL and XTAL check failed\n");
}
-void mt76x0_chip_onoff(struct mt76x0_dev *dev, bool enable, bool reset)
+void mt76x0_chip_onoff(struct mt76x02_dev *dev, bool enable, bool reset)
{
u32 val;
- mutex_lock(&dev->hw_atomic_mutex);
-
val = mt76_rr(dev, MT_WLAN_FUN_CTRL);
if (reset) {
@@ -107,57 +91,25 @@ void mt76x0_chip_onoff(struct mt76x0_dev *dev, bool enable, bool reset)
udelay(20);
mt76x0_set_wlan_state(dev, val, enable);
-
- mutex_unlock(&dev->hw_atomic_mutex);
}
EXPORT_SYMBOL_GPL(mt76x0_chip_onoff);
-static void mt76x0_reset_csr_bbp(struct mt76x0_dev *dev)
+static void mt76x0_reset_csr_bbp(struct mt76x02_dev *dev)
{
- u32 val;
-
- val = mt76_rr(dev, MT_PBF_SYS_CTRL);
- val &= ~0x2000;
- mt76_wr(dev, MT_PBF_SYS_CTRL, val);
-
- mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR |
- MT_MAC_SYS_CTRL_RESET_BBP);
-
+ mt76_wr(dev, MT_MAC_SYS_CTRL,
+ MT_MAC_SYS_CTRL_RESET_CSR |
+ MT_MAC_SYS_CTRL_RESET_BBP);
msleep(200);
-}
-
-static void mt76x0_init_usb_dma(struct mt76x0_dev *dev)
-{
- u32 val;
-
- val = mt76_rr(dev, MT_USB_DMA_CFG);
-
- val |= MT_USB_DMA_CFG_RX_BULK_EN |
- MT_USB_DMA_CFG_TX_BULK_EN;
-
- /* disable AGGR_BULK_RX in order to receive one
- * frame in each rx urb and avoid copies
- */
- val &= ~MT_USB_DMA_CFG_RX_BULK_AGG_EN;
- mt76_wr(dev, MT_USB_DMA_CFG, val);
-
- val = mt76_rr(dev, MT_COM_REG0);
- if (val & 1)
- dev_dbg(dev->mt76.dev, "MCU not ready\n");
-
- val = mt76_rr(dev, MT_USB_DMA_CFG);
-
- val |= MT_USB_DMA_CFG_RX_DROP_OR_PAD;
- mt76_wr(dev, MT_USB_DMA_CFG, val);
- val &= ~MT_USB_DMA_CFG_RX_DROP_OR_PAD;
- mt76_wr(dev, MT_USB_DMA_CFG, val);
+ mt76_clear(dev, MT_MAC_SYS_CTRL,
+ MT_MAC_SYS_CTRL_RESET_CSR |
+ MT_MAC_SYS_CTRL_RESET_BBP);
}
#define RANDOM_WRITE(dev, tab) \
mt76_wr_rp(dev, MT_MCU_MEMMAP_WLAN, \
tab, ARRAY_SIZE(tab))
-static int mt76x0_init_bbp(struct mt76x0_dev *dev)
+static int mt76x0_init_bbp(struct mt76x02_dev *dev)
{
int ret, i;
@@ -180,30 +132,13 @@ static int mt76x0_init_bbp(struct mt76x0_dev *dev)
return 0;
}
-static void
-mt76_init_beacon_offsets(struct mt76x0_dev *dev)
-{
- u16 base = MT_BEACON_BASE;
- u32 regs[4] = {};
- int i;
-
- for (i = 0; i < 16; i++) {
- u16 addr = dev->beacon_offsets[i];
-
- regs[i / 4] |= ((addr - base) / 64) << (8 * (i % 4));
- }
-
- for (i = 0; i < 4; i++)
- mt76_wr(dev, MT_BCN_OFFSET(i), regs[i]);
-}
-
-static void mt76x0_init_mac_registers(struct mt76x0_dev *dev)
+static void mt76x0_init_mac_registers(struct mt76x02_dev *dev)
{
u32 reg;
RANDOM_WRITE(dev, common_mac_reg_table);
- mt76_init_beacon_offsets(dev);
+ mt76x02_set_beacon_offsets(&dev->mt76);
/* Enable PBF and MAC clock SYS_CTRL[11:10] = 0x3 */
RANDOM_WRITE(dev, mt76x0_mac_reg_table);
@@ -213,13 +148,6 @@ static void mt76x0_init_mac_registers(struct mt76x0_dev *dev)
reg &= ~0x3;
mt76_wr(dev, MT_MAC_SYS_CTRL, reg);
- if (is_mt7610e(dev)) {
- /* Disable COEX_EN */
- reg = mt76_rr(dev, MT_COEXCFG0);
- reg &= 0xFFFFFFFE;
- mt76_wr(dev, MT_COEXCFG0, reg);
- }
-
/* Set 0x141C[15:12]=0xF */
reg = mt76_rr(dev, MT_EXT_CCA_CFG);
reg |= 0x0000F000;
@@ -237,15 +165,9 @@ static void mt76x0_init_mac_registers(struct mt76x0_dev *dev)
reg &= ~0x000003FF;
reg |= 0x00000201;
mt76_wr(dev, MT_WMM_CTRL, reg);
-
- /* TODO: Probably not needed */
- mt76_wr(dev, 0x7028, 0);
- mt76_wr(dev, 0x7010, 0);
- mt76_wr(dev, 0x7024, 0);
- msleep(10);
}
-static int mt76x0_init_wcid_mem(struct mt76x0_dev *dev)
+static int mt76x0_init_wcid_mem(struct mt76x02_dev *dev)
{
u32 *vals;
int i;
@@ -264,14 +186,14 @@ static int mt76x0_init_wcid_mem(struct mt76x0_dev *dev)
return 0;
}
-static void mt76x0_init_key_mem(struct mt76x0_dev *dev)
+static void mt76x0_init_key_mem(struct mt76x02_dev *dev)
{
u32 vals[4] = {};
mt76_wr_copy(dev, MT_SKEY_MODE_BASE_0, vals, ARRAY_SIZE(vals));
}
-static int mt76x0_init_wcid_attr_mem(struct mt76x0_dev *dev)
+static int mt76x0_init_wcid_attr_mem(struct mt76x02_dev *dev)
{
u32 *vals;
int i;
@@ -288,7 +210,7 @@ static int mt76x0_init_wcid_attr_mem(struct mt76x0_dev *dev)
return 0;
}
-static void mt76x0_reset_counters(struct mt76x0_dev *dev)
+static void mt76x0_reset_counters(struct mt76x02_dev *dev)
{
mt76_rr(dev, MT_RX_STAT_0);
mt76_rr(dev, MT_RX_STAT_1);
@@ -298,49 +220,26 @@ static void mt76x0_reset_counters(struct mt76x0_dev *dev)
mt76_rr(dev, MT_TX_STA_2);
}
-int mt76x0_mac_start(struct mt76x0_dev *dev)
+int mt76x0_mac_start(struct mt76x02_dev *dev)
{
mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX);
- if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
- MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 200000))
+ if (!mt76x02_wait_for_wpdma(&dev->mt76, 200000))
return -ETIMEDOUT;
- dev->mt76.rxfilter = MT_RX_FILTR_CFG_CRC_ERR |
- MT_RX_FILTR_CFG_PHY_ERR | MT_RX_FILTR_CFG_PROMISC |
- MT_RX_FILTR_CFG_VER_ERR | MT_RX_FILTR_CFG_DUP |
- MT_RX_FILTR_CFG_CFACK | MT_RX_FILTR_CFG_CFEND |
- MT_RX_FILTR_CFG_ACK | MT_RX_FILTR_CFG_CTS |
- MT_RX_FILTR_CFG_RTS | MT_RX_FILTR_CFG_PSPOLL |
- MT_RX_FILTR_CFG_BA | MT_RX_FILTR_CFG_CTRL_RSV;
mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter);
-
mt76_wr(dev, MT_MAC_SYS_CTRL,
- MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
-
- if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
- MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 50))
- return -ETIMEDOUT;
+ MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
- return 0;
+ return !mt76x02_wait_for_wpdma(&dev->mt76, 50) ? -ETIMEDOUT : 0;
}
+EXPORT_SYMBOL_GPL(mt76x0_mac_start);
-static void mt76x0_mac_stop_hw(struct mt76x0_dev *dev)
+void mt76x0_mac_stop(struct mt76x02_dev *dev)
{
- int i, ok;
-
- if (test_bit(MT76_REMOVED, &dev->mt76.state))
- return;
-
- mt76_clear(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_TIMER_EN |
- MT_BEACON_TIME_CFG_SYNC_MODE | MT_BEACON_TIME_CFG_TBTT_EN |
- MT_BEACON_TIME_CFG_BEACON_TX);
-
- if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_TX_BUSY, 0, 1000))
- dev_warn(dev->mt76.dev, "Warning: TX DMA did not stop!\n");
+ int i = 200, ok = 0;
/* Page count on TxQ */
- i = 200;
while (i-- && ((mt76_rr(dev, 0x0438) & 0xffffffff) ||
(mt76_rr(dev, 0x0a30) & 0x000000ff) ||
(mt76_rr(dev, 0x0a34) & 0x00ff00ff)))
@@ -353,9 +252,7 @@ static void mt76x0_mac_stop_hw(struct mt76x0_dev *dev)
MT_MAC_SYS_CTRL_ENABLE_TX);
/* Page count on RxQ */
- ok = 0;
- i = 200;
- while (i--) {
+ for (i = 0; i < 200; i++) {
if (!(mt76_rr(dev, MT_RXQ_STA) & 0x00ff0000) &&
!mt76_rr(dev, 0x0a30) &&
!mt76_rr(dev, 0x0a34)) {
@@ -368,36 +265,14 @@ static void mt76x0_mac_stop_hw(struct mt76x0_dev *dev)
if (!mt76_poll(dev, MT_MAC_STATUS, MT_MAC_STATUS_RX, 0, 1000))
dev_warn(dev->mt76.dev, "Warning: MAC RX did not stop!\n");
-
- if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_RX_BUSY, 0, 1000))
- dev_warn(dev->mt76.dev, "Warning: RX DMA did not stop!\n");
-}
-
-void mt76x0_mac_stop(struct mt76x0_dev *dev)
-{
- cancel_delayed_work_sync(&dev->cal_work);
- cancel_delayed_work_sync(&dev->mac_work);
- mt76u_stop_stat_wk(&dev->mt76);
- mt76x0_mac_stop_hw(dev);
}
EXPORT_SYMBOL_GPL(mt76x0_mac_stop);
-int mt76x0_init_hardware(struct mt76x0_dev *dev)
+int mt76x0_init_hardware(struct mt76x02_dev *dev)
{
- static const u16 beacon_offsets[16] = {
- /* 512 byte per beacon */
- 0xc000, 0xc200, 0xc400, 0xc600,
- 0xc800, 0xca00, 0xcc00, 0xce00,
- 0xd000, 0xd200, 0xd400, 0xd600,
- 0xd800, 0xda00, 0xdc00, 0xde00
- };
int ret;
- dev->beacon_offsets = beacon_offsets;
-
- if (!mt76_poll_msec(dev, MT_WPDMA_GLO_CFG,
- MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
- MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 100))
+ if (!mt76x02_wait_for_wpdma(&dev->mt76, 1000))
return -EIO;
/* Wait for ASIC ready after FW load. */
@@ -405,25 +280,21 @@ int mt76x0_init_hardware(struct mt76x0_dev *dev)
return -ETIMEDOUT;
mt76x0_reset_csr_bbp(dev);
- mt76x0_init_usb_dma(dev);
-
- mt76_wr(dev, MT_HEADER_TRANS_CTRL_REG, 0x0);
- mt76_wr(dev, MT_TSO_CTRL, 0x0);
-
ret = mt76x02_mcu_function_select(&dev->mt76, Q_SELECT, 1, false);
if (ret)
return ret;
mt76x0_init_mac_registers(dev);
- if (!mt76_poll_msec(dev, MT_MAC_STATUS,
- MT_MAC_STATUS_TX | MT_MAC_STATUS_RX, 0, 1000))
+ if (!mt76x02_wait_for_txrx_idle(&dev->mt76))
return -EIO;
ret = mt76x0_init_bbp(dev);
if (ret)
return ret;
+ dev->mt76.rxfilter = mt76_rr(dev, MT_RX_FILTR_CFG);
+
ret = mt76x0_init_wcid_mem(dev);
if (ret)
return ret;
@@ -441,12 +312,6 @@ int mt76x0_init_hardware(struct mt76x0_dev *dev)
mt76x0_reset_counters(dev);
- mt76_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e);
-
- mt76_wr(dev, MT_TXOP_CTRL_CFG,
- FIELD_PREP(MT_TXOP_TRUN_EN, 0x3f) |
- FIELD_PREP(MT_TXOP_EXT_CCA_DLY, 0x58));
-
ret = mt76x0_eeprom_init(dev);
if (ret)
return ret;
@@ -457,50 +322,36 @@ int mt76x0_init_hardware(struct mt76x0_dev *dev)
}
EXPORT_SYMBOL_GPL(mt76x0_init_hardware);
-void mt76x0_cleanup(struct mt76x0_dev *dev)
+struct mt76x02_dev *
+mt76x0_alloc_device(struct device *pdev,
+ const struct mt76_driver_ops *drv_ops,
+ const struct ieee80211_ops *ops)
{
- clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);
- mt76x0_chip_onoff(dev, false, false);
- mt76u_queues_deinit(&dev->mt76);
- mt76u_mcu_deinit(&dev->mt76);
-}
-EXPORT_SYMBOL_GPL(mt76x0_cleanup);
-
-struct mt76x0_dev *
-mt76x0_alloc_device(struct device *pdev, const struct mt76_driver_ops *drv_ops)
-{
- struct mt76x0_dev *dev;
+ struct mt76x02_dev *dev;
struct mt76_dev *mdev;
- mdev = mt76_alloc_device(sizeof(*dev), &mt76x0_ops);
+ mdev = mt76_alloc_device(sizeof(*dev), ops);
if (!mdev)
return NULL;
mdev->dev = pdev;
mdev->drv = drv_ops;
- dev = container_of(mdev, struct mt76x0_dev, mt76);
- mutex_init(&dev->reg_atomic_mutex);
- mutex_init(&dev->hw_atomic_mutex);
- spin_lock_init(&dev->mac_lock);
- spin_lock_init(&dev->con_mon_lock);
+ dev = container_of(mdev, struct mt76x02_dev, mt76);
+ mutex_init(&dev->phy_mutex);
atomic_set(&dev->avg_ampdu_len, 1);
return dev;
}
EXPORT_SYMBOL_GPL(mt76x0_alloc_device);
-int mt76x0_register_device(struct mt76x0_dev *dev)
+int mt76x0_register_device(struct mt76x02_dev *dev)
{
struct mt76_dev *mdev = &dev->mt76;
struct ieee80211_hw *hw = mdev->hw;
struct wiphy *wiphy = hw->wiphy;
int ret;
- ret = mt76x0_init_hardware(dev);
- if (ret)
- return ret;
-
/* Reserve WCID 0 for mcast - thanks to this APs WCID will go to
* entry no. 1 like it does in the vendor driver.
*/
@@ -535,12 +386,6 @@ int mt76x0_register_device(struct mt76x0_dev *dev)
if (mdev->cap.has_5ghz)
mt76x0_vht_cap_mask(&dev->mt76.sband_5g.sband);
- /* check hw sg support in order to enable AMSDU */
- if (mt76u_check_sg(mdev))
- hw->max_tx_fragments = MT_SG_MAX_SIZE;
- else
- hw->max_tx_fragments = 1;
-
mt76x0_init_debugfs(dev);
return 0;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h b/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h
index 24afcfd94b4e..236dce6860b4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h
@@ -2,6 +2,7 @@
* (c) Copyright 2002-2010, Ralink Technology, Inc.
* Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
* Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
+ * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
@@ -19,264 +20,215 @@
#include "phy.h"
static const struct mt76_reg_pair common_mac_reg_table[] = {
-#if 1
- {MT_BCN_OFFSET(0), 0xf8f0e8e0}, /* 0x3800(e0), 0x3A00(e8), 0x3C00(f0), 0x3E00(f8), 512B for each beacon */
- {MT_BCN_OFFSET(1), 0x6f77d0c8}, /* 0x3200(c8), 0x3400(d0), 0x1DC0(77), 0x1BC0(6f), 512B for each beacon */
-#endif
-
- {MT_LEGACY_BASIC_RATE, 0x0000013f}, /* Basic rate set bitmap*/
- {MT_HT_BASIC_RATE, 0x00008003}, /* Basic HT rate set , 20M, MCS=3, MM. Format is the same as in TXWI.*/
- {MT_MAC_SYS_CTRL, 0x00}, /* 0x1004, , default Disable RX*/
- {MT_RX_FILTR_CFG, 0x17f97}, /*0x1400 , RX filter control, */
- {MT_BKOFF_SLOT_CFG, 0x209}, /* default set short slot time, CC_DELAY_TIME should be 2 */
- /*{TX_SW_CFG0, 0x40a06}, Gary,2006-08-23 */
- {MT_TX_SW_CFG0, 0x0}, /* Gary,2008-05-21 for CWC test */
- {MT_TX_SW_CFG1, 0x80606}, /* Gary,2006-08-23 */
- {MT_TX_LINK_CFG, 0x1020}, /* Gary,2006-08-23 */
- /*{TX_TIMEOUT_CFG, 0x00182090}, CCK has some problem. So increase timieout value. 2006-10-09 MArvek RT*/
- {MT_TX_TIMEOUT_CFG, 0x000a2090}, /* CCK has some problem. So increase timieout value. 2006-10-09 MArvek RT , Modify for 2860E ,2007-08-01*/
- {MT_MAX_LEN_CFG, 0xa0fff | 0x00001000}, /* 0x3018, MAX frame length. Max PSDU = 16kbytes.*/
- {MT_LED_CFG, 0x7f031e46}, /* Gary, 2006-08-23*/
-
- {MT_PBF_TX_MAX_PCNT, 0x1fbf1f1f /*0xbfbf3f1f*/},
- {MT_PBF_RX_MAX_PCNT, 0x9f},
-
- /*{TX_RTY_CFG, 0x6bb80408}, Jan, 2006/11/16*/
-/* WMM_ACM_SUPPORT */
-/* {TX_RTY_CFG, 0x6bb80101}, sample*/
- {MT_TX_RETRY_CFG, 0x47d01f0f}, /* Jan, 2006/11/16, Set TxWI->ACK =0 in Probe Rsp Modify for 2860E ,2007-08-03*/
-
- {MT_AUTO_RSP_CFG, 0x00000013}, /* Initial Auto_Responder, because QA will turn off Auto-Responder*/
- {MT_CCK_PROT_CFG, 0x05740003 /*0x01740003*/}, /* Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled. */
- {MT_OFDM_PROT_CFG, 0x05740003 /*0x01740003*/}, /* Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled. */
- {MT_PBF_CFG, 0xf40006}, /* Only enable Queue 2*/
- {MT_MM40_PROT_CFG, 0x3F44084}, /* Initial Auto_Responder, because QA will turn off Auto-Responder*/
- {MT_WPDMA_GLO_CFG, 0x00000030},
- {MT_GF20_PROT_CFG, 0x01744004}, /* set 19:18 --> Short NAV for MIMO PS*/
- {MT_GF40_PROT_CFG, 0x03F44084},
- {MT_MM20_PROT_CFG, 0x01744004},
- {MT_TXOP_CTRL_CFG, 0x0000583f, /*0x0000243f*/ /*0x000024bf*/}, /*Extension channel backoff.*/
- {MT_TX_RTS_CFG, 0x00092b20},
-
- {MT_EXP_ACK_TIME, 0x002400ca}, /* default value */
- {MT_TXOP_HLDR_ET, 0x00000002},
-
- /* Jerry comments 2008/01/16: we use SIFS = 10us in CCK defaultly, but it seems that 10us
- is too small for INTEL 2200bg card, so in MBSS mode, the delta time between beacon0
- and beacon1 is SIFS (10us), so if INTEL 2200bg card connects to BSS0, the ping
- will always lost. So we change the SIFS of CCK from 10us to 16us. */
- {MT_XIFS_TIME_CFG, 0x33a41010},
- {MT_PWR_PIN_CFG, 0x00000000},
+ { MT_BCN_OFFSET(0), 0xf8f0e8e0 },
+ { MT_BCN_OFFSET(1), 0x6f77d0c8 },
+ { MT_LEGACY_BASIC_RATE, 0x0000013f },
+ { MT_HT_BASIC_RATE, 0x00008003 },
+ { MT_MAC_SYS_CTRL, 0x00000000 },
+ { MT_RX_FILTR_CFG, 0x00017f97 },
+ { MT_BKOFF_SLOT_CFG, 0x00000209 },
+ { MT_TX_SW_CFG0, 0x00000000 },
+ { MT_TX_SW_CFG1, 0x00080606 },
+ { MT_TX_LINK_CFG, 0x00001020 },
+ { MT_TX_TIMEOUT_CFG, 0x000a2090 },
+ { MT_MAX_LEN_CFG, 0xa0fff | 0x00001000 },
+ { MT_LED_CFG, 0x7f031e46 },
+ { MT_PBF_TX_MAX_PCNT, 0x1fbf1f1f },
+ { MT_PBF_RX_MAX_PCNT, 0x0000fe9f },
+ { MT_TX_RETRY_CFG, 0x47d01f0f },
+ { MT_AUTO_RSP_CFG, 0x00000013 },
+ { MT_CCK_PROT_CFG, 0x05740003 },
+ { MT_OFDM_PROT_CFG, 0x05740003 },
+ { MT_PBF_CFG, 0x00f40006 },
+ { MT_WPDMA_GLO_CFG, 0x00000030 },
+ { MT_GF20_PROT_CFG, 0x01744004 },
+ { MT_GF40_PROT_CFG, 0x03f44084 },
+ { MT_MM20_PROT_CFG, 0x01744004 },
+ { MT_MM40_PROT_CFG, 0x03f54084 },
+ { MT_TXOP_CTRL_CFG, 0x0000583f },
+ { MT_TX_RTS_CFG, 0x00092b20 },
+ { MT_EXP_ACK_TIME, 0x002400ca },
+ { MT_TXOP_HLDR_ET, 0x00000002 },
+ { MT_XIFS_TIME_CFG, 0x33a41010 },
+ { MT_PWR_PIN_CFG, 0x00000000 },
};
static const struct mt76_reg_pair mt76x0_mac_reg_table[] = {
- /* {MT_IOCFG_6, 0xA0040080 }, */
- {MT_PBF_SYS_CTRL, 0x00080c00 },
- {MT_PBF_CFG, 0x77723c1f },
- {MT_FCE_PSE_CTRL, 0x00000001 },
-
- {MT_AMPDU_MAX_LEN_20M1S, 0xBAA99887 },
-
- /* Delay bb_tx_pe for proper tx_mcs_pwr update */
- {MT_TX_SW_CFG0, 0x00000601 },
-
- /* Set rf_tx_pe deassert time to 1us by Chee's comment @MT7650_CR_setting_1018.xlsx */
- {MT_TX_SW_CFG1, 0x00040000 },
- {MT_TX_SW_CFG2, 0x00000000 },
-
- /* disable Tx info report */
- {0xa44, 0x0000000 },
-
- {MT_HEADER_TRANS_CTRL_REG, 0x0},
- {MT_TSO_CTRL, 0x0},
-
- /* BB_PA_MODE_CFG0(0x1214) Keep default value @20120903 */
- {MT_BB_PA_MODE_CFG1, 0x00500055},
-
- /* RF_PA_MODE_CFG0(0x121C) Keep default value @20120903 */
- {MT_RF_PA_MODE_CFG1, 0x00500055},
-
- {MT_TX_ALC_CFG_0, 0x2F2F000C},
- {MT_TX0_BB_GAIN_ATTEN, 0x00000000}, /* set BBP atten gain = 0 */
-
- {MT_TX_PWR_CFG_0, 0x3A3A3A3A},
- {MT_TX_PWR_CFG_1, 0x3A3A3A3A},
- {MT_TX_PWR_CFG_2, 0x3A3A3A3A},
- {MT_TX_PWR_CFG_3, 0x3A3A3A3A},
- {MT_TX_PWR_CFG_4, 0x3A3A3A3A},
- {MT_TX_PWR_CFG_7, 0x3A3A3A3A},
- {MT_TX_PWR_CFG_8, 0x3A},
- {MT_TX_PWR_CFG_9, 0x3A},
- /* Enable Tx length > 4095 byte */
- {0x150C, 0x00000002},
-
- /* Disable bt_abort_tx_en(0x1238[21] = 0) which is not used at MT7650 */
- {0x1238, 0x001700C8},
- /* PMU_OCLEVEL<5:1> from default <5'b10010> to <5'b11011> for normal driver */
- /* {MT_LDO_CTRL_0, 0x00A647B6}, */
-
- /* Default LDO_DIG supply 1.26V, change to 1.2V */
- {MT_LDO_CTRL_1, 0x6B006464 },
-/*
- {MT_HT_BASIC_RATE, 0x00004003 },
- {MT_HT_CTRL_CFG, 0x000001FF },
-*/
+ { MT_IOCFG_6, 0xa0040080 },
+ { MT_PBF_SYS_CTRL, 0x00080c00 },
+ { MT_PBF_CFG, 0x77723c1f },
+ { MT_FCE_PSE_CTRL, 0x00000001 },
+ { MT_AMPDU_MAX_LEN_20M1S, 0xAAA99887 },
+ { MT_TX_SW_CFG0, 0x00000601 },
+ { MT_TX_SW_CFG1, 0x00040000 },
+ { MT_TX_SW_CFG2, 0x00000000 },
+ { 0xa44, 0x00000000 },
+ { MT_HEADER_TRANS_CTRL_REG, 0x00000000 },
+ { MT_TSO_CTRL, 0x00000000 },
+ { MT_BB_PA_MODE_CFG1, 0x00500055 },
+ { MT_RF_PA_MODE_CFG1, 0x00500055 },
+ { MT_TX_ALC_CFG_0, 0x2F2F000C },
+ { MT_TX0_BB_GAIN_ATTEN, 0x00000000 },
+ { MT_TX_PWR_CFG_0, 0x3A3A3A3A },
+ { MT_TX_PWR_CFG_1, 0x3A3A3A3A },
+ { MT_TX_PWR_CFG_2, 0x3A3A3A3A },
+ { MT_TX_PWR_CFG_3, 0x3A3A3A3A },
+ { MT_TX_PWR_CFG_4, 0x3A3A3A3A },
+ { MT_TX_PWR_CFG_7, 0x3A3A3A3A },
+ { MT_TX_PWR_CFG_8, 0x0000003A },
+ { MT_TX_PWR_CFG_9, 0x0000003A },
+ { 0x150C, 0x00000002 },
+ { 0x1238, 0x001700C8 },
+ { MT_LDO_CTRL_0, 0x00A647B6 },
+ { MT_LDO_CTRL_1, 0x6B006464 },
+ { MT_HT_BASIC_RATE, 0x00004003 },
+ { MT_HT_CTRL_CFG, 0x000001FF },
+ { MT_TXOP_HLDR_ET, 0x00000000 },
+ { MT_PN_PAD_MODE, 0x00000003 },
};
-
static const struct mt76_reg_pair mt76x0_bbp_init_tab[] = {
- {MT_BBP(CORE, 1), 0x00000002},
- {MT_BBP(CORE, 4), 0x00000000},
- {MT_BBP(CORE, 24), 0x00000000},
- {MT_BBP(CORE, 32), 0x4003000a},
- {MT_BBP(CORE, 42), 0x00000000},
- {MT_BBP(CORE, 44), 0x00000000},
-
- {MT_BBP(IBI, 11), 0x00000080},
-
- /*
- 0x2300[5] Default Antenna:
- 0 for WIFI main antenna
- 1 for WIFI aux antenna
-
- */
- {MT_BBP(AGC, 0), 0x00021400},
- {MT_BBP(AGC, 1), 0x00000003},
- {MT_BBP(AGC, 2), 0x003A6464},
- {MT_BBP(AGC, 15), 0x88A28CB8},
- {MT_BBP(AGC, 22), 0x00001E21},
- {MT_BBP(AGC, 23), 0x0000272C},
- {MT_BBP(AGC, 24), 0x00002F3A},
- {MT_BBP(AGC, 25), 0x8000005A},
- {MT_BBP(AGC, 26), 0x007C2005},
- {MT_BBP(AGC, 34), 0x000A0C0C},
- {MT_BBP(AGC, 37), 0x2121262C},
- {MT_BBP(AGC, 41), 0x38383E45},
- {MT_BBP(AGC, 57), 0x00001010},
- {MT_BBP(AGC, 59), 0xBAA20E96},
- {MT_BBP(AGC, 63), 0x00000001},
-
- {MT_BBP(TXC, 0), 0x00280403},
- {MT_BBP(TXC, 1), 0x00000000},
-
- {MT_BBP(RXC, 1), 0x00000012},
- {MT_BBP(RXC, 2), 0x00000011},
- {MT_BBP(RXC, 3), 0x00000005},
- {MT_BBP(RXC, 4), 0x00000000},
- {MT_BBP(RXC, 5), 0xF977C4EC},
- {MT_BBP(RXC, 7), 0x00000090},
-
- {MT_BBP(TXO, 8), 0x00000000},
-
- {MT_BBP(TXBE, 0), 0x00000000},
- {MT_BBP(TXBE, 4), 0x00000004},
- {MT_BBP(TXBE, 6), 0x00000000},
- {MT_BBP(TXBE, 8), 0x00000014},
- {MT_BBP(TXBE, 9), 0x20000000},
- {MT_BBP(TXBE, 10), 0x00000000},
- {MT_BBP(TXBE, 12), 0x00000000},
- {MT_BBP(TXBE, 13), 0x00000000},
- {MT_BBP(TXBE, 14), 0x00000000},
- {MT_BBP(TXBE, 15), 0x00000000},
- {MT_BBP(TXBE, 16), 0x00000000},
- {MT_BBP(TXBE, 17), 0x00000000},
-
- {MT_BBP(RXFE, 1), 0x00008800}, /* Add for E3 */
- {MT_BBP(RXFE, 3), 0x00000000},
- {MT_BBP(RXFE, 4), 0x00000000},
-
- {MT_BBP(RXO, 13), 0x00000092},
- {MT_BBP(RXO, 14), 0x00060612},
- {MT_BBP(RXO, 15), 0xC8321B18},
- {MT_BBP(RXO, 16), 0x0000001E},
- {MT_BBP(RXO, 17), 0x00000000},
- {MT_BBP(RXO, 18), 0xCC00A993},
- {MT_BBP(RXO, 19), 0xB9CB9CB9},
- {MT_BBP(RXO, 20), 0x26c00057},
- {MT_BBP(RXO, 21), 0x00000001},
- {MT_BBP(RXO, 24), 0x00000006},
+ { MT_BBP(CORE, 1), 0x00000002 },
+ { MT_BBP(CORE, 4), 0x00000000 },
+ { MT_BBP(CORE, 24), 0x00000000 },
+ { MT_BBP(CORE, 32), 0x4003000a },
+ { MT_BBP(CORE, 42), 0x00000000 },
+ { MT_BBP(CORE, 44), 0x00000000 },
+ { MT_BBP(IBI, 11), 0x0FDE8081 },
+ { MT_BBP(AGC, 0), 0x00021400 },
+ { MT_BBP(AGC, 1), 0x00000003 },
+ { MT_BBP(AGC, 2), 0x003A6464 },
+ { MT_BBP(AGC, 15), 0x88A28CB8 },
+ { MT_BBP(AGC, 22), 0x00001E21 },
+ { MT_BBP(AGC, 23), 0x0000272C },
+ { MT_BBP(AGC, 24), 0x00002F3A },
+ { MT_BBP(AGC, 25), 0x8000005A },
+ { MT_BBP(AGC, 26), 0x007C2005 },
+ { MT_BBP(AGC, 33), 0x00003238 },
+ { MT_BBP(AGC, 34), 0x000A0C0C },
+ { MT_BBP(AGC, 37), 0x2121262C },
+ { MT_BBP(AGC, 41), 0x38383E45 },
+ { MT_BBP(AGC, 57), 0x00001010 },
+ { MT_BBP(AGC, 59), 0xBAA20E96 },
+ { MT_BBP(AGC, 63), 0x00000001 },
+ { MT_BBP(TXC, 0), 0x00280403 },
+ { MT_BBP(TXC, 1), 0x00000000 },
+ { MT_BBP(RXC, 1), 0x00000012 },
+ { MT_BBP(RXC, 2), 0x00000011 },
+ { MT_BBP(RXC, 3), 0x00000005 },
+ { MT_BBP(RXC, 4), 0x00000000 },
+ { MT_BBP(RXC, 5), 0xF977C4EC },
+ { MT_BBP(RXC, 7), 0x00000090 },
+ { MT_BBP(TXO, 8), 0x00000000 },
+ { MT_BBP(TXBE, 0), 0x00000000 },
+ { MT_BBP(TXBE, 4), 0x00000004 },
+ { MT_BBP(TXBE, 6), 0x00000000 },
+ { MT_BBP(TXBE, 8), 0x00000014 },
+ { MT_BBP(TXBE, 9), 0x20000000 },
+ { MT_BBP(TXBE, 10), 0x00000000 },
+ { MT_BBP(TXBE, 12), 0x00000000 },
+ { MT_BBP(TXBE, 13), 0x00000000 },
+ { MT_BBP(TXBE, 14), 0x00000000 },
+ { MT_BBP(TXBE, 15), 0x00000000 },
+ { MT_BBP(TXBE, 16), 0x00000000 },
+ { MT_BBP(TXBE, 17), 0x00000000 },
+ { MT_BBP(RXFE, 1), 0x00008800 },
+ { MT_BBP(RXFE, 3), 0x00000000 },
+ { MT_BBP(RXFE, 4), 0x00000000 },
+ { MT_BBP(RXO, 13), 0x00000192 },
+ { MT_BBP(RXO, 14), 0x00060612 },
+ { MT_BBP(RXO, 15), 0xC8321B18 },
+ { MT_BBP(RXO, 16), 0x0000001E },
+ { MT_BBP(RXO, 17), 0x00000000 },
+ { MT_BBP(RXO, 18), 0xCC00A993 },
+ { MT_BBP(RXO, 19), 0xB9CB9CB9 },
+ { MT_BBP(RXO, 20), 0x26c00057 },
+ { MT_BBP(RXO, 21), 0x00000001 },
+ { MT_BBP(RXO, 24), 0x00000006 },
+ { MT_BBP(RXO, 28), 0x0000003F },
};
static const struct mt76x0_bbp_switch_item mt76x0_bbp_switch_tab[] = {
- {RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 8), 0x0E344EF0}},
- {RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 8), 0x122C54F2}},
+ { RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 4), 0x1FEDA049 } },
+ { RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 4), 0x1FECA054 } },
+
+ { RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 6), 0x00000045 } },
+ { RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 6), 0x0000000A } },
- {RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 14), 0x310F2E39}},
- {RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 14), 0x310F2A3F}},
+ { RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 8), 0x16344EF0 } },
+ { RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 8), 0x122C54F2 } },
- {RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 32), 0x00003230}},
- {RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 32), 0x0000181C}},
+ { RF_G_BAND | RF_BW_20, { MT_BBP(AGC, 12), 0x05052879 } },
+ { RF_G_BAND | RF_BW_40, { MT_BBP(AGC, 12), 0x050528F9 } },
+ { RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 12), 0x050528F9 } },
- {RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 33), 0x00003240}},
- {RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 33), 0x00003218}},
+ { RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 13), 0x35050004 } },
+ { RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 13), 0x2C3A0406 } },
- {RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 35), 0x11112016}},
- {RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 35), 0x11112016}},
+ { RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 14), 0x310F2E3C } },
+ { RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 14), 0x310F2A3F } },
- {RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(RXO, 28), 0x0000008A}},
- {RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(RXO, 28), 0x0000008A}},
+ { RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 26), 0x007C2005 } },
+ { RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 26), 0x007C2005 } },
- {RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 4), 0x1FEDA049}},
- {RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 4), 0x1FECA054}},
+ { RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 27), 0x000000E1 } },
+ { RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 27), 0x000000EC } },
- {RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 6), 0x00000045}},
- {RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 6), 0x0000000A}},
+ { RF_G_BAND | RF_BW_20, { MT_BBP(AGC, 28), 0x00060806 } },
+ { RF_G_BAND | RF_BW_40, { MT_BBP(AGC, 28), 0x00050806 } },
+ { RF_A_BAND | RF_BW_40, { MT_BBP(AGC, 28), 0x00060801 } },
+ { RF_A_BAND | RF_BW_20 | RF_BW_80, { MT_BBP(AGC, 28), 0x00060806 } },
- {RF_G_BAND | RF_BW_20, {MT_BBP(AGC, 12), 0x05052879}},
- {RF_G_BAND | RF_BW_40, {MT_BBP(AGC, 12), 0x050528F9}},
- {RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 12), 0x050528F9}},
+ { RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(RXO, 28), 0x0000008A } },
- {RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 13), 0x35050004}},
- {RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 13), 0x2C3A0406}},
+ { RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 31), 0x00000E23 } },
+ { RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 31), 0x00000E13 } },
- {RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 27), 0x000000E1}},
- {RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 27), 0x000000EC}},
+ { RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 32), 0x00003218 } },
+ { RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 32), 0x0000181C } },
- {RF_G_BAND | RF_BW_20, {MT_BBP(AGC, 28), 0x00060806}},
- {RF_G_BAND | RF_BW_40, {MT_BBP(AGC, 28), 0x00050806}},
- {RF_A_BAND | RF_BW_40, {MT_BBP(AGC, 28), 0x00060801}},
- {RF_A_BAND | RF_BW_20 | RF_BW_80, {MT_BBP(AGC, 28), 0x00060806}},
+ { RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 33), 0x00003240 } },
+ { RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 33), 0x00003218 } },
- {RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 31), 0x00000F23}},
- {RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 31), 0x00000F13}},
+ { RF_G_BAND | RF_BW_20, { MT_BBP(AGC, 35), 0x11111616 } },
+ { RF_G_BAND | RF_BW_40, { MT_BBP(AGC, 35), 0x11111516 } },
+ { RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 35), 0x11111111 } },
- {RF_G_BAND | RF_BW_20, {MT_BBP(AGC, 39), 0x2A2A3036}},
- {RF_G_BAND | RF_BW_40, {MT_BBP(AGC, 39), 0x2A2A2C36}},
- {RF_A_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 39), 0x2A2A3036}},
- {RF_A_BAND | RF_BW_80, {MT_BBP(AGC, 39), 0x2A2A2A36}},
+ { RF_G_BAND | RF_BW_20, { MT_BBP(AGC, 39), 0x2A2A3036 } },
+ { RF_G_BAND | RF_BW_40, { MT_BBP(AGC, 39), 0x2A2A2C36 } },
+ { RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 39), 0x2A2A2A2A } },
- {RF_G_BAND | RF_BW_20, {MT_BBP(AGC, 43), 0x27273438}},
- {RF_G_BAND | RF_BW_40, {MT_BBP(AGC, 43), 0x27272D38}},
- {RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 43), 0x27272B30}},
+ { RF_G_BAND | RF_BW_20, { MT_BBP(AGC, 43), 0x27273438 } },
+ { RF_G_BAND | RF_BW_40, { MT_BBP(AGC, 43), 0x27272D38 } },
+ { RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 43), 0x27271A1A } },
- {RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 51), 0x17171C1C}},
- {RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 51), 0xFFFFFFFF}},
+ { RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 51), 0x17171C1C } },
+ { RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 51), 0xFFFFFFFF } },
- {RF_G_BAND | RF_BW_20, {MT_BBP(AGC, 53), 0x26262A2F}},
- {RF_G_BAND | RF_BW_40, {MT_BBP(AGC, 53), 0x2626322F}},
- {RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 53), 0xFFFFFFFF}},
+ { RF_G_BAND | RF_BW_20, { MT_BBP(AGC, 53), 0x26262A2F } },
+ { RF_G_BAND | RF_BW_40, { MT_BBP(AGC, 53), 0x2626322F } },
+ { RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 53), 0xFFFFFFFF } },
- {RF_G_BAND | RF_BW_20, {MT_BBP(AGC, 55), 0x40404E58}},
- {RF_G_BAND | RF_BW_40, {MT_BBP(AGC, 55), 0x40405858}},
- {RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 55), 0xFFFFFFFF}},
+ { RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 55), 0x40404040 } },
+ { RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 55), 0xFFFFFFFF } },
- {RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 58), 0x00001010}},
- {RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 58), 0x00000000}},
+ { RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 58), 0x00001010 } },
+ { RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 58), 0x00000000 } },
- {RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(RXFE, 0), 0x3D5000E0}},
- {RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(RXFE, 0), 0x895000E0}},
+ { RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(RXFE, 0), 0x3D5000E0 } },
+ { RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(RXFE, 0), 0x895000E0 } },
};
static const struct mt76_reg_pair mt76x0_dcoc_tab[] = {
- {MT_BBP(CAL, 47), 0x000010F0 },
- {MT_BBP(CAL, 48), 0x00008080 },
- {MT_BBP(CAL, 49), 0x00000F07 },
- {MT_BBP(CAL, 50), 0x00000040 },
- {MT_BBP(CAL, 51), 0x00000404 },
- {MT_BBP(CAL, 52), 0x00080803 },
- {MT_BBP(CAL, 53), 0x00000704 },
- {MT_BBP(CAL, 54), 0x00002828 },
- {MT_BBP(CAL, 55), 0x00005050 },
+ { MT_BBP(CAL, 47), 0x000010F0 },
+ { MT_BBP(CAL, 48), 0x00008080 },
+ { MT_BBP(CAL, 49), 0x00000F07 },
+ { MT_BBP(CAL, 50), 0x00000040 },
+ { MT_BBP(CAL, 51), 0x00000404 },
+ { MT_BBP(CAL, 52), 0x00080803 },
+ { MT_BBP(CAL, 53), 0x00000704 },
+ { MT_BBP(CAL, 54), 0x00002828 },
+ { MT_BBP(CAL, 55), 0x00005050 },
};
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mac.c b/drivers/net/wireless/mediatek/mt76/mt76x0/mac.c
index f55734a922aa..7a422c590211 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mac.c
@@ -13,13 +13,13 @@
* GNU General Public License for more details.
*/
+#include <linux/etherdevice.h>
+
#include "mt76x0.h"
#include "trace.h"
-#include "../mt76x02_util.h"
-#include <linux/etherdevice.h>
-void mt76x0_mac_set_protection(struct mt76x0_dev *dev, bool legacy_prot,
- int ht_mode)
+void mt76x0_mac_set_protection(struct mt76x02_dev *dev, bool legacy_prot,
+ int ht_mode)
{
int mode = ht_mode & IEEE80211_HT_OP_MODE_PROTECTION;
bool non_gf = !!(ht_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
@@ -77,7 +77,7 @@ void mt76x0_mac_set_protection(struct mt76x0_dev *dev, bool legacy_prot,
mt76_wr(dev, MT_CCK_PROT_CFG + i * 4, prot[i]);
}
-void mt76x0_mac_set_short_preamble(struct mt76x0_dev *dev, bool short_preamb)
+void mt76x0_mac_set_short_preamble(struct mt76x02_dev *dev, bool short_preamb)
{
if (short_preamb)
mt76_set(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_PREAMB_SHORT);
@@ -85,7 +85,7 @@ void mt76x0_mac_set_short_preamble(struct mt76x0_dev *dev, bool short_preamb)
mt76_clear(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_PREAMB_SHORT);
}
-void mt76x0_mac_config_tsf(struct mt76x0_dev *dev, bool enable, int interval)
+void mt76x0_mac_config_tsf(struct mt76x02_dev *dev, bool enable, int interval)
{
u32 val = mt76_rr(dev, MT_BEACON_TIME_CFG);
@@ -105,7 +105,7 @@ void mt76x0_mac_config_tsf(struct mt76x0_dev *dev, bool enable, int interval)
MT_BEACON_TIME_CFG_TBTT_EN;
}
-static void mt76x0_check_mac_err(struct mt76x0_dev *dev)
+static void mt76x0_check_mac_err(struct mt76x02_dev *dev)
{
u32 val = mt76_rr(dev, 0x10f4);
@@ -120,7 +120,7 @@ static void mt76x0_check_mac_err(struct mt76x0_dev *dev)
}
void mt76x0_mac_work(struct work_struct *work)
{
- struct mt76x0_dev *dev = container_of(work, struct mt76x0_dev,
+ struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev,
mac_work.work);
struct {
u32 addr_base;
@@ -171,7 +171,7 @@ void mt76x0_mac_work(struct work_struct *work)
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work, 10 * HZ);
}
-void mt76x0_mac_set_ampdu_factor(struct mt76x0_dev *dev)
+void mt76x0_mac_set_ampdu_factor(struct mt76x02_dev *dev)
{
struct ieee80211_sta *sta;
struct mt76_wcid *wcid;
@@ -195,67 +195,3 @@ void mt76x0_mac_set_ampdu_factor(struct mt76x0_dev *dev)
mt76_wr(dev, MT_MAX_LEN_CFG, 0xa0fff |
FIELD_PREP(MT_MAX_LEN_CFG_AMPDU, min_factor));
}
-
-static void
-mt76x0_rx_monitor_beacon(struct mt76x0_dev *dev, struct mt76x02_rxwi *rxwi,
- u16 rate, int rssi)
-{
- dev->bcn_phy_mode = FIELD_GET(MT_RXWI_RATE_PHY, rate);
- dev->avg_rssi = ((dev->avg_rssi * 15) / 16 + (rssi << 8)) / 256;
-}
-
-static int
-mt76x0_rx_is_our_beacon(struct mt76x0_dev *dev, u8 *data)
-{
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)data;
-
- return ieee80211_is_beacon(hdr->frame_control) &&
- ether_addr_equal(hdr->addr2, dev->ap_bssid);
-}
-
-u32 mt76x0_mac_process_rx(struct mt76x0_dev *dev, struct sk_buff *skb,
- void *rxi)
-{
- struct mt76_rx_status *status = (struct mt76_rx_status *) skb->cb;
- struct mt76x02_rxwi *rxwi = rxi;
- u32 len, ctl = le32_to_cpu(rxwi->ctl);
- u16 rate = le16_to_cpu(rxwi->rate);
- int rssi, pad_len = 0;
-
- len = FIELD_GET(MT_RXWI_CTL_MPDU_LEN, ctl);
- if (WARN_ON(len < 10))
- return 0;
-
- if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_DECRYPT)) {
- status->flag |= RX_FLAG_DECRYPTED;
- status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
- }
-
- if (rxwi->rxinfo & MT_RXINFO_L2PAD)
- pad_len += 2;
-
- mt76x02_remove_hdr_pad(skb, pad_len);
-
- pskb_trim(skb, len);
- status->chains = BIT(0);
- rssi = mt76x0_phy_get_rssi(dev, rxwi);
- status->chain_signal[0] = status->signal = rssi;
- status->freq = dev->mt76.chandef.chan->center_freq;
- status->band = dev->mt76.chandef.chan->band;
-
- mt76x02_mac_process_rate(status, rate);
-
- spin_lock_bh(&dev->con_mon_lock);
- if (mt76x0_rx_is_our_beacon(dev, skb->data)) {
- mt76x0_rx_monitor_beacon(dev, rxwi, rate, rssi);
- } else if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_UNICAST)) {
- if (dev->avg_rssi == 0)
- dev->avg_rssi = rssi;
- else
- dev->avg_rssi = (dev->avg_rssi * 15) / 16 + rssi / 16;
-
- }
- spin_unlock_bh(&dev->con_mon_lock);
-
- return len;
-}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mac.h b/drivers/net/wireless/mediatek/mt76/mt76x0/mac.h
deleted file mode 100644
index b887693a56b6..000000000000
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/mac.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
- * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef __MT76_MAC_H
-#define __MT76_MAC_H
-
-u32 mt76x0_mac_process_rx(struct mt76x0_dev *dev, struct sk_buff *skb,
- void *rxi);
-#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
index c84e00abfac9..c9cd0254a979 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
@@ -13,49 +13,12 @@
* GNU General Public License for more details.
*/
-#include "mt76x0.h"
-#include "mac.h"
-#include "../mt76x02_util.h"
#include <linux/etherdevice.h>
+#include "mt76x0.h"
-static int mt76x0_start(struct ieee80211_hw *hw)
-{
- struct mt76x0_dev *dev = hw->priv;
- int ret;
-
- mutex_lock(&dev->mt76.mutex);
-
- ret = mt76x0_mac_start(dev);
- if (ret)
- goto out;
-
- ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work,
- MT_CALIBRATE_INTERVAL);
- ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
- MT_CALIBRATE_INTERVAL);
-
- set_bit(MT76_STATE_RUNNING, &dev->mt76.state);
-
-out:
- mutex_unlock(&dev->mt76.mutex);
- return ret;
-}
-
-static void mt76x0_stop(struct ieee80211_hw *hw)
-{
- struct mt76x0_dev *dev = hw->priv;
-
- mutex_lock(&dev->mt76.mutex);
-
- clear_bit(MT76_STATE_RUNNING, &dev->mt76.state);
- mt76x0_mac_stop(dev);
-
- mutex_unlock(&dev->mt76.mutex);
-}
-
-static int mt76x0_config(struct ieee80211_hw *hw, u32 changed)
+int mt76x0_config(struct ieee80211_hw *hw, u32 changed)
{
- struct mt76x0_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
int ret = 0;
mutex_lock(&dev->mt76.mutex);
@@ -66,29 +29,43 @@ static int mt76x0_config(struct ieee80211_hw *hw, u32 changed)
ieee80211_wake_queues(hw);
}
+ if (changed & IEEE80211_CONF_CHANGE_POWER) {
+ dev->mt76.txpower_conf = hw->conf.power_level * 2;
+
+ if (test_bit(MT76_STATE_RUNNING, &dev->mt76.state))
+ mt76x0_phy_set_txpower(dev);
+ }
+
+ if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
+ if (!(hw->conf.flags & IEEE80211_CONF_MONITOR))
+ dev->mt76.rxfilter |= MT_RX_FILTR_CFG_PROMISC;
+ else
+ dev->mt76.rxfilter &= ~MT_RX_FILTR_CFG_PROMISC;
+
+ mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter);
+ }
+
mutex_unlock(&dev->mt76.mutex);
return ret;
}
+EXPORT_SYMBOL_GPL(mt76x0_config);
static void
-mt76x0_addr_wr(struct mt76x0_dev *dev, const u32 offset, const u8 *addr)
+mt76x0_addr_wr(struct mt76x02_dev *dev, const u32 offset, const u8 *addr)
{
mt76_wr(dev, offset, get_unaligned_le32(addr));
mt76_wr(dev, offset + 4, addr[4] | addr[5] << 8);
}
-static void
-mt76x0_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *info, u32 changed)
+void mt76x0_bss_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *info, u32 changed)
{
- struct mt76x0_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
mutex_lock(&dev->mt76.mutex);
- if (changed & BSS_CHANGED_ASSOC)
- mt76x0_phy_con_cal_onoff(dev, info);
-
if (changed & BSS_CHANGED_BSSID) {
mt76x0_addr_wr(dev, MT_MAC_BSSID_DW0, info->bssid);
@@ -130,24 +107,23 @@ mt76x0_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
mutex_unlock(&dev->mt76.mutex);
}
+EXPORT_SYMBOL_GPL(mt76x0_bss_info_changed);
-static void
-mt76x0_sw_scan(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *mac_addr)
+void mt76x0_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ const u8 *mac_addr)
{
- struct mt76x0_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
cancel_delayed_work_sync(&dev->cal_work);
mt76x0_agc_save(dev);
set_bit(MT76_SCANNING, &dev->mt76.state);
}
+EXPORT_SYMBOL_GPL(mt76x0_sw_scan);
-static void
-mt76x0_sw_scan_complete(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+void mt76x0_sw_scan_complete(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
- struct mt76x0_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
mt76x0_agc_restore(dev);
clear_bit(MT76_SCANNING, &dev->mt76.state);
@@ -155,33 +131,14 @@ mt76x0_sw_scan_complete(struct ieee80211_hw *hw,
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
MT_CALIBRATE_INTERVAL);
}
+EXPORT_SYMBOL_GPL(mt76x0_sw_scan_complete);
-static int mt76x0_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
+int mt76x0_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
{
- struct mt76x0_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
mt76_rmw_field(dev, MT_TX_RTS_CFG, MT_TX_RTS_CFG_THRESH, value);
return 0;
}
-
-const struct ieee80211_ops mt76x0_ops = {
- .tx = mt76x0_tx,
- .start = mt76x0_start,
- .stop = mt76x0_stop,
- .add_interface = mt76x02_add_interface,
- .remove_interface = mt76x02_remove_interface,
- .config = mt76x0_config,
- .configure_filter = mt76x02_configure_filter,
- .bss_info_changed = mt76x0_bss_info_changed,
- .sta_add = mt76x02_sta_add,
- .sta_remove = mt76x02_sta_remove,
- .set_key = mt76x02_set_key,
- .conf_tx = mt76x02_conf_tx,
- .sw_scan_start = mt76x0_sw_scan,
- .sw_scan_complete = mt76x0_sw_scan_complete,
- .ampdu_action = mt76x02_ampdu_action,
- .sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
- .set_rts_threshold = mt76x0_set_rts_threshold,
- .wake_tx_queue = mt76_wake_tx_queue,
-};
+EXPORT_SYMBOL_GPL(mt76x0_set_rts_threshold);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.h b/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.h
index f2a87d283e09..b66e70f6cd89 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.h
@@ -17,7 +17,7 @@
#include "../mt76x02_mcu.h"
-struct mt76x0_dev;
+struct mt76x02_dev;
#define MT_MCU_IVB_SIZE 0x40
#define MT_MCU_DLM_OFFSET 0x80000
@@ -41,4 +41,11 @@ enum mcu_calibrate {
MCU_CAL_TX_GROUP_DELAY,
};
+int mt76x0e_mcu_init(struct mt76x02_dev *dev);
+int mt76x0u_mcu_init(struct mt76x02_dev *dev);
+static inline int mt76x0_firmware_running(struct mt76x02_dev *dev)
+{
+ return mt76_rr(dev, MT_MCU_COM_REG0) == 1;
+}
+
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
index 6aaa9a5b51db..1bff2be45a13 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
@@ -25,147 +25,60 @@
#include <net/mac80211.h>
#include <linux/debugfs.h>
-#include "../mt76.h"
-#include "../mt76x02_regs.h"
-#include "../mt76x02_mac.h"
+#include "../mt76x02.h"
+#include "eeprom.h"
#define MT_CALIBRATE_INTERVAL (4 * HZ)
-#define MT_FREQ_CAL_INIT_DELAY (30 * HZ)
-#define MT_FREQ_CAL_CHECK_INTERVAL (10 * HZ)
-#define MT_FREQ_CAL_ADJ_INTERVAL (HZ / 2)
-
-#define MT_BBP_REG_VERSION 0x00
-
#define MT_USB_AGGR_SIZE_LIMIT 21 /* * 1024B */
#define MT_USB_AGGR_TIMEOUT 0x80 /* * 33ns */
-struct mac_stats {
- u64 rx_stat[6];
- u64 tx_stat[6];
- u64 aggr_stat[2];
- u64 aggr_n[32];
- u64 zero_len_del[2];
-};
-
-struct mt76x0_eeprom_params;
-
-#define MT_EE_TEMPERATURE_SLOPE 39
-#define MT_FREQ_OFFSET_INVALID -128
-
-/* addr req mask */
-#define MT_VEND_TYPE_EEPROM BIT(31)
-#define MT_VEND_TYPE_CFG BIT(30)
-#define MT_VEND_TYPE_MASK (MT_VEND_TYPE_EEPROM | MT_VEND_TYPE_CFG)
-
-#define MT_VEND_ADDR(type, n) (MT_VEND_TYPE_##type | (n))
-
-enum mt_bw {
- MT_BW_20,
- MT_BW_40,
-};
-
-/**
- * struct mt76x0_dev - adapter structure
- * @lock: protects @wcid->tx_rate.
- * @mac_lock: locks out mac80211's tx status and rx paths.
- * @con_mon_lock: protects @ap_bssid, @bcn_*, @avg_rssi.
- * @mutex: ensures exclusive access from mac80211 callbacks.
- * @reg_atomic_mutex: ensures atomicity of indirect register accesses
- * (accesses to RF and BBP).
- * @hw_atomic_mutex: ensures exclusive access to HW during critical
- * operations (power management, channel switch).
- */
-struct mt76x0_dev {
- struct mt76_dev mt76; /* must be first */
-
- u8 data[32];
-
- struct delayed_work cal_work;
- struct delayed_work mac_work;
-
- spinlock_t mac_lock;
-
- const u16 *beacon_offsets;
-
- struct mt76x0_eeprom_params *ee;
-
- struct mutex reg_atomic_mutex;
- struct mutex hw_atomic_mutex;
-
- u32 debugfs_reg;
-
- atomic_t avg_ampdu_len;
-
- /* Connection monitoring things */
- spinlock_t con_mon_lock;
- u8 ap_bssid[ETH_ALEN];
-
- s8 bcn_freq_off;
- u8 bcn_phy_mode;
-
- int avg_rssi; /* starts at 0 and converges */
-
- u8 agc_save;
- u16 chainmask;
-
- struct mac_stats stats;
-};
-
-extern const struct ieee80211_ops mt76x0_ops;
-
-static inline bool is_mt7610e(struct mt76x0_dev *dev)
+static inline bool is_mt7610e(struct mt76x02_dev *dev)
{
/* TODO */
return false;
}
-void mt76x0_init_debugfs(struct mt76x0_dev *dev);
-
-/* Compatibility with mt76 */
-#define mt76_rmw_field(_dev, _reg, _field, _val) \
- mt76_rmw(_dev, _reg, _field, FIELD_PREP(_field, _val))
+void mt76x0_init_debugfs(struct mt76x02_dev *dev);
/* Init */
-struct mt76x0_dev *
-mt76x0_alloc_device(struct device *pdev, const struct mt76_driver_ops *drv_ops);
-int mt76x0_init_hardware(struct mt76x0_dev *dev);
-int mt76x0_register_device(struct mt76x0_dev *dev);
-void mt76x0_cleanup(struct mt76x0_dev *dev);
-void mt76x0_chip_onoff(struct mt76x0_dev *dev, bool enable, bool reset);
-
-int mt76x0_mac_start(struct mt76x0_dev *dev);
-void mt76x0_mac_stop(struct mt76x0_dev *dev);
+struct mt76x02_dev *
+mt76x0_alloc_device(struct device *pdev,
+ const struct mt76_driver_ops *drv_ops,
+ const struct ieee80211_ops *ops);
+int mt76x0_init_hardware(struct mt76x02_dev *dev);
+int mt76x0_register_device(struct mt76x02_dev *dev);
+void mt76x0_chip_onoff(struct mt76x02_dev *dev, bool enable, bool reset);
+
+int mt76x0_mac_start(struct mt76x02_dev *dev);
+void mt76x0_mac_stop(struct mt76x02_dev *dev);
+
+int mt76x0_config(struct ieee80211_hw *hw, u32 changed);
+void mt76x0_bss_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *info, u32 changed);
+void mt76x0_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ const u8 *mac_addr);
+void mt76x0_sw_scan_complete(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+int mt76x0_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
/* PHY */
-void mt76x0_phy_init(struct mt76x0_dev *dev);
-int mt76x0_wait_bbp_ready(struct mt76x0_dev *dev);
-void mt76x0_agc_save(struct mt76x0_dev *dev);
-void mt76x0_agc_restore(struct mt76x0_dev *dev);
-int mt76x0_phy_set_channel(struct mt76x0_dev *dev,
+void mt76x0_phy_init(struct mt76x02_dev *dev);
+int mt76x0_wait_bbp_ready(struct mt76x02_dev *dev);
+void mt76x0_agc_save(struct mt76x02_dev *dev);
+void mt76x0_agc_restore(struct mt76x02_dev *dev);
+int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
struct cfg80211_chan_def *chandef);
-void mt76x0_phy_recalibrate_after_assoc(struct mt76x0_dev *dev);
-int mt76x0_phy_get_rssi(struct mt76x0_dev *dev, struct mt76x02_rxwi *rxwi);
-void mt76x0_phy_con_cal_onoff(struct mt76x0_dev *dev,
- struct ieee80211_bss_conf *info);
+void mt76x0_phy_recalibrate_after_assoc(struct mt76x02_dev *dev);
+void mt76x0_phy_set_txpower(struct mt76x02_dev *dev);
/* MAC */
void mt76x0_mac_work(struct work_struct *work);
-void mt76x0_mac_set_protection(struct mt76x0_dev *dev, bool legacy_prot,
+void mt76x0_mac_set_protection(struct mt76x02_dev *dev, bool legacy_prot,
int ht_mode);
-void mt76x0_mac_set_short_preamble(struct mt76x0_dev *dev, bool short_preamb);
-void mt76x0_mac_config_tsf(struct mt76x0_dev *dev, bool enable, int interval);
-void mt76x0_mac_set_ampdu_factor(struct mt76x0_dev *dev);
-
-/* TX */
-void mt76x0_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
- struct sk_buff *skb);
-
-void mt76x0_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
- struct sk_buff *skb);
+void mt76x0_mac_set_short_preamble(struct mt76x02_dev *dev, bool short_preamb);
+void mt76x0_mac_config_tsf(struct mt76x02_dev *dev, bool enable, int interval);
+void mt76x0_mac_set_ampdu_factor(struct mt76x02_dev *dev);
-int mt76x0_tx_prepare_skb(struct mt76_dev *mdev, void *data,
- struct sk_buff *skb, struct mt76_queue *q,
- struct mt76_wcid *wcid, struct ieee80211_sta *sta,
- u32 *tx_info);
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
index eb383f96ec9a..87997cddf0d6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
@@ -19,12 +19,113 @@
#include <linux/pci.h>
#include "mt76x0.h"
+#include "mcu.h"
+
+static int mt76x0e_start(struct ieee80211_hw *hw)
+{
+ struct mt76x02_dev *dev = hw->priv;
+
+ mutex_lock(&dev->mt76.mutex);
+
+ mt76x02_mac_start(dev);
+ ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work,
+ MT_CALIBRATE_INTERVAL);
+ ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
+ MT_CALIBRATE_INTERVAL);
+ set_bit(MT76_STATE_RUNNING, &dev->mt76.state);
+
+ mutex_unlock(&dev->mt76.mutex);
+
+ return 0;
+}
+
+static void mt76x0e_stop_hw(struct mt76x02_dev *dev)
+{
+ cancel_delayed_work_sync(&dev->cal_work);
+ cancel_delayed_work_sync(&dev->mac_work);
+
+ if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY,
+ 0, 1000))
+ dev_warn(dev->mt76.dev, "TX DMA did not stop\n");
+ mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_EN);
+
+ mt76x0_mac_stop(dev);
+
+ if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_RX_DMA_BUSY,
+ 0, 1000))
+ dev_warn(dev->mt76.dev, "TX DMA did not stop\n");
+ mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_RX_DMA_EN);
+}
+
+static void mt76x0e_stop(struct ieee80211_hw *hw)
+{
+ struct mt76x02_dev *dev = hw->priv;
+
+ mutex_lock(&dev->mt76.mutex);
+ clear_bit(MT76_STATE_RUNNING, &dev->mt76.state);
+ mt76x0e_stop_hw(dev);
+ mutex_unlock(&dev->mt76.mutex);
+}
+
+static const struct ieee80211_ops mt76x0e_ops = {
+ .tx = mt76x02_tx,
+ .start = mt76x0e_start,
+ .stop = mt76x0e_stop,
+ .config = mt76x0_config,
+ .add_interface = mt76x02_add_interface,
+ .remove_interface = mt76x02_remove_interface,
+ .configure_filter = mt76x02_configure_filter,
+};
+
+static int mt76x0e_register_device(struct mt76x02_dev *dev)
+{
+ int err;
+
+ mt76x0_chip_onoff(dev, true, false);
+ if (!mt76x02_wait_for_mac(&dev->mt76))
+ return -ETIMEDOUT;
+
+ mt76x02_dma_disable(dev);
+ err = mt76x0e_mcu_init(dev);
+ if (err < 0)
+ return err;
+
+ err = mt76x02_dma_init(dev);
+ if (err < 0)
+ return err;
+
+ err = mt76x0_init_hardware(dev);
+ if (err < 0)
+ return err;
+
+ if (mt76_chip(&dev->mt76) == 0x7610) {
+ u16 val;
+
+ mt76_clear(dev, MT_COEXCFG0, BIT(0));
+ val = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_0);
+ if (val & MT_EE_NIC_CONF_0_PA_IO_CURRENT) {
+ u32 data;
+
+ /* set external external PA I/O
+ * current to 16mA
+ */
+ data = mt76_rr(dev, 0x11c);
+ val |= 0xc03;
+ mt76_wr(dev, 0x11c, val);
+ }
+ }
+
+ mt76_clear(dev, 0x110, BIT(9));
+ mt76_set(dev, MT_MAX_LEN_CFG, BIT(13));
+
+ return 0;
+}
static int
mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
- struct mt76x0_dev *dev;
- int ret = -ENODEV;
+ struct mt76x02_dev *dev;
+ int ret;
ret = pcim_enable_device(pdev);
if (ret)
@@ -40,7 +141,7 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret)
return ret;
- dev = mt76x0_alloc_device(&pdev->dev, NULL);
+ dev = mt76x0_alloc_device(&pdev->dev, NULL, &mt76x0e_ops);
if (!dev)
return -ENOMEM;
@@ -49,22 +150,40 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dev->mt76.rev = mt76_rr(dev, MT_ASIC_VERSION);
dev_info(dev->mt76.dev, "ASIC revision: %08x\n", dev->mt76.rev);
-/* error: */
+ ret = mt76x0e_register_device(dev);
+ if (ret < 0)
+ goto error;
+
+ return 0;
+
+error:
ieee80211_free_hw(mt76_hw(dev));
return ret;
}
+static void mt76x0e_cleanup(struct mt76x02_dev *dev)
+{
+ clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);
+ mt76x0_chip_onoff(dev, false, false);
+ mt76x0e_stop_hw(dev);
+ mt76x02_dma_cleanup(dev);
+ mt76x02_mcu_cleanup(&dev->mt76);
+}
+
static void
mt76x0e_remove(struct pci_dev *pdev)
{
struct mt76_dev *mdev = pci_get_drvdata(pdev);
+ struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
mt76_unregister_device(mdev);
+ mt76x0e_cleanup(dev);
ieee80211_free_hw(mdev->hw);
}
static const struct pci_device_id mt76x0e_device_table[] = {
{ PCI_DEVICE(0x14c3, 0x7630) },
+ { PCI_DEVICE(0x14c3, 0x7650) },
{ },
};
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c
new file mode 100644
index 000000000000..6c66656c21f4
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/kernel.h>
+#include <linux/firmware.h>
+
+#include "mt76x0.h"
+#include "mcu.h"
+
+#define MT7610E_FIRMWARE "mediatek/mt7610e.bin"
+#define MT7650E_FIRMWARE "mediatek/mt7650e.bin"
+
+#define MT_MCU_IVB_ADDR (MT_MCU_ILM_ADDR + 0x54000 - MT_MCU_IVB_SIZE)
+
+static int mt76x0e_load_firmware(struct mt76x02_dev *dev)
+{
+ bool is_combo_chip = mt76_chip(&dev->mt76) != 0x7610;
+ u32 val, ilm_len, dlm_len, offset = 0;
+ const struct mt76x02_fw_header *hdr;
+ const struct firmware *fw;
+ const char *firmware;
+ const u8 *fw_payload;
+ int len, err;
+
+ if (is_combo_chip)
+ firmware = MT7650E_FIRMWARE;
+ else
+ firmware = MT7610E_FIRMWARE;
+
+ err = request_firmware(&fw, firmware, dev->mt76.dev);
+ if (err)
+ return err;
+
+ if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
+ err = -EIO;
+ goto out;
+ }
+
+ hdr = (const struct mt76x02_fw_header *)fw->data;
+
+ len = sizeof(*hdr);
+ len += le32_to_cpu(hdr->ilm_len);
+ len += le32_to_cpu(hdr->dlm_len);
+
+ if (fw->size != len) {
+ err = -EIO;
+ goto out;
+ }
+
+ fw_payload = fw->data + sizeof(*hdr);
+
+ val = le16_to_cpu(hdr->fw_ver);
+ dev_info(dev->mt76.dev, "Firmware Version: %d.%d.%02d\n",
+ (val >> 12) & 0xf, (val >> 8) & 0xf, val & 0xf);
+
+ val = le16_to_cpu(hdr->fw_ver);
+ dev_dbg(dev->mt76.dev,
+ "Firmware Version: %d.%d.%02d Build: %x Build time: %.16s\n",
+ (val >> 12) & 0xf, (val >> 8) & 0xf, val & 0xf,
+ le16_to_cpu(hdr->build_ver), hdr->build_time);
+
+ if (is_combo_chip && !mt76_poll(dev, MT_MCU_SEMAPHORE_00, 1, 1, 600)) {
+ dev_err(dev->mt76.dev,
+ "Could not get hardware semaphore for loading fw\n");
+ err = -ETIMEDOUT;
+ goto out;
+ }
+
+ /* upload ILM. */
+ mt76_wr(dev, MT_MCU_PCIE_REMAP_BASE4, 0);
+ ilm_len = le32_to_cpu(hdr->ilm_len);
+ if (is_combo_chip) {
+ ilm_len -= MT_MCU_IVB_SIZE;
+ offset = MT_MCU_IVB_SIZE;
+ }
+ dev_dbg(dev->mt76.dev, "loading FW - ILM %u\n", ilm_len);
+ mt76_wr_copy(dev, MT_MCU_ILM_ADDR + offset, fw_payload + offset,
+ ilm_len);
+
+ /* upload IVB. */
+ if (is_combo_chip) {
+ dev_dbg(dev->mt76.dev, "loading FW - IVB %u\n",
+ MT_MCU_IVB_SIZE);
+ mt76_wr_copy(dev, MT_MCU_IVB_ADDR, fw_payload, MT_MCU_IVB_SIZE);
+ }
+
+ /* upload DLM. */
+ mt76_wr(dev, MT_MCU_PCIE_REMAP_BASE4, MT_MCU_DLM_OFFSET);
+ dlm_len = le32_to_cpu(hdr->dlm_len);
+ dev_dbg(dev->mt76.dev, "loading FW - DLM %u\n", dlm_len);
+ mt76_wr_copy(dev, MT_MCU_ILM_ADDR,
+ fw_payload + le32_to_cpu(hdr->ilm_len), dlm_len);
+
+ /* trigger firmware */
+ mt76_wr(dev, MT_MCU_PCIE_REMAP_BASE4, 0);
+ if (is_combo_chip)
+ mt76_wr(dev, MT_MCU_INT_LEVEL, 0x3);
+ else
+ mt76_wr(dev, MT_MCU_RESET_CTL, 0x300);
+
+ if (!mt76_poll_msec(dev, MT_MCU_COM_REG0, 1, 1, 1000)) {
+ dev_err(dev->mt76.dev, "Firmware failed to start\n");
+ err = -ETIMEDOUT;
+ goto out;
+ }
+
+ dev_dbg(dev->mt76.dev, "Firmware running!\n");
+
+out:
+ if (is_combo_chip)
+ mt76_wr(dev, MT_MCU_SEMAPHORE_00, 0x1);
+ release_firmware(fw);
+
+ return err;
+}
+
+int mt76x0e_mcu_init(struct mt76x02_dev *dev)
+{
+ static const struct mt76_mcu_ops mt76x0e_mcu_ops = {
+ .mcu_msg_alloc = mt76x02_mcu_msg_alloc,
+ .mcu_send_msg = mt76x02_mcu_msg_send,
+ };
+ int err;
+
+ dev->mt76.mcu_ops = &mt76x0e_mcu_ops;
+
+ err = mt76x0e_load_firmware(dev);
+ if (err < 0)
+ return err;
+
+ set_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state);
+
+ return 0;
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
index 2b6d928aab89..4850a2db18d7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
@@ -21,11 +21,12 @@
#include "phy.h"
#include "initvals.h"
#include "initvals_phy.h"
+#include "../mt76x02_phy.h"
#include <linux/etherdevice.h>
static int
-mt76x0_rf_csr_wr(struct mt76x0_dev *dev, u32 offset, u8 value)
+mt76x0_rf_csr_wr(struct mt76x02_dev *dev, u32 offset, u8 value)
{
int ret = 0;
u8 bank, reg;
@@ -39,7 +40,7 @@ mt76x0_rf_csr_wr(struct mt76x0_dev *dev, u32 offset, u8 value)
if (WARN_ON_ONCE(reg > 64) || WARN_ON_ONCE(bank) > 8)
return -EINVAL;
- mutex_lock(&dev->reg_atomic_mutex);
+ mutex_lock(&dev->phy_mutex);
if (!mt76_poll(dev, MT_RF_CSR_CFG, MT_RF_CSR_CFG_KICK, 0, 100)) {
ret = -ETIMEDOUT;
@@ -54,7 +55,7 @@ mt76x0_rf_csr_wr(struct mt76x0_dev *dev, u32 offset, u8 value)
MT_RF_CSR_CFG_KICK);
trace_mt76x0_rf_write(&dev->mt76, bank, offset, value);
out:
- mutex_unlock(&dev->reg_atomic_mutex);
+ mutex_unlock(&dev->phy_mutex);
if (ret < 0)
dev_err(dev->mt76.dev, "Error: RF write %d:%d failed:%d!!\n",
@@ -63,8 +64,7 @@ out:
return ret;
}
-static int
-mt76x0_rf_csr_rr(struct mt76x0_dev *dev, u32 offset)
+static int mt76x0_rf_csr_rr(struct mt76x02_dev *dev, u32 offset)
{
int ret = -ETIMEDOUT;
u32 val;
@@ -79,7 +79,7 @@ mt76x0_rf_csr_rr(struct mt76x0_dev *dev, u32 offset)
if (WARN_ON_ONCE(reg > 64) || WARN_ON_ONCE(bank) > 8)
return -EINVAL;
- mutex_lock(&dev->reg_atomic_mutex);
+ mutex_lock(&dev->phy_mutex);
if (!mt76_poll(dev, MT_RF_CSR_CFG, MT_RF_CSR_CFG_KICK, 0, 100))
goto out;
@@ -99,7 +99,7 @@ mt76x0_rf_csr_rr(struct mt76x0_dev *dev, u32 offset)
trace_mt76x0_rf_read(&dev->mt76, bank, offset, ret);
}
out:
- mutex_unlock(&dev->reg_atomic_mutex);
+ mutex_unlock(&dev->phy_mutex);
if (ret < 0)
dev_err(dev->mt76.dev, "Error: RF read %d:%d failed:%d!!\n",
@@ -109,7 +109,7 @@ out:
}
static int
-rf_wr(struct mt76x0_dev *dev, u32 offset, u8 val)
+rf_wr(struct mt76x02_dev *dev, u32 offset, u8 val)
{
if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state)) {
struct mt76_reg_pair pair = {
@@ -125,7 +125,7 @@ rf_wr(struct mt76x0_dev *dev, u32 offset, u8 val)
}
static int
-rf_rr(struct mt76x0_dev *dev, u32 offset)
+rf_rr(struct mt76x02_dev *dev, u32 offset)
{
int ret;
u32 val;
@@ -146,7 +146,7 @@ rf_rr(struct mt76x0_dev *dev, u32 offset)
}
static int
-rf_rmw(struct mt76x0_dev *dev, u32 offset, u8 mask, u8 val)
+rf_rmw(struct mt76x02_dev *dev, u32 offset, u8 mask, u8 val)
{
int ret;
@@ -162,14 +162,14 @@ rf_rmw(struct mt76x0_dev *dev, u32 offset, u8 mask, u8 val)
}
static int
-rf_set(struct mt76x0_dev *dev, u32 offset, u8 val)
+rf_set(struct mt76x02_dev *dev, u32 offset, u8 val)
{
return rf_rmw(dev, offset, 0, val);
}
#if 0
static int
-rf_clear(struct mt76x0_dev *dev, u32 offset, u8 mask)
+rf_clear(struct mt76x02_dev *dev, u32 offset, u8 mask)
{
return rf_rmw(dev, offset, mask, 0);
}
@@ -179,7 +179,7 @@ rf_clear(struct mt76x0_dev *dev, u32 offset, u8 mask)
mt76_wr_rp(dev, MT_MCU_MEMMAP_RF, \
tab, ARRAY_SIZE(tab))
-int mt76x0_wait_bbp_ready(struct mt76x0_dev *dev)
+int mt76x0_wait_bbp_ready(struct mt76x02_dev *dev)
{
int i = 20;
u32 val;
@@ -200,7 +200,7 @@ int mt76x0_wait_bbp_ready(struct mt76x0_dev *dev)
}
static void
-mt76x0_bbp_set_ctrlch(struct mt76x0_dev *dev, enum nl80211_chan_width width,
+mt76x0_bbp_set_ctrlch(struct mt76x02_dev *dev, enum nl80211_chan_width width,
u8 ctrl)
{
int core_val, agc_val;
@@ -226,25 +226,7 @@ mt76x0_bbp_set_ctrlch(struct mt76x0_dev *dev, enum nl80211_chan_width width,
mt76_rmw_field(dev, MT_BBP(TXBE, 0), MT_BBP_TXBE_R0_CTRL_CHAN, ctrl);
}
-int mt76x0_phy_get_rssi(struct mt76x0_dev *dev, struct mt76x02_rxwi *rxwi)
-{
- s8 lna_gain, rssi_offset;
- int val;
-
- if (dev->mt76.chandef.chan->band == NL80211_BAND_2GHZ) {
- lna_gain = dev->ee->lna_gain_2ghz;
- rssi_offset = dev->ee->rssi_offset_2ghz[0];
- } else {
- lna_gain = dev->ee->lna_gain_5ghz[0];
- rssi_offset = dev->ee->rssi_offset_5ghz[0];
- }
-
- val = rxwi->rssi[0] + rssi_offset - lna_gain;
-
- return val;
-}
-
-static void mt76x0_vco_cal(struct mt76x0_dev *dev, u8 channel)
+static void mt76x0_vco_cal(struct mt76x02_dev *dev, u8 channel)
{
u8 val;
@@ -301,14 +283,14 @@ static void mt76x0_vco_cal(struct mt76x0_dev *dev, u8 channel)
}
static void
-mt76x0_mac_set_ctrlch(struct mt76x0_dev *dev, bool primary_upper)
+mt76x0_mac_set_ctrlch(struct mt76x02_dev *dev, bool primary_upper)
{
mt76_rmw_field(dev, MT_TX_BAND_CFG, MT_TX_BAND_CFG_UPPER_40M,
primary_upper);
}
static void
-mt76x0_phy_set_band(struct mt76x0_dev *dev, enum nl80211_band band)
+mt76x0_phy_set_band(struct mt76x02_dev *dev, enum nl80211_band band)
{
switch (band) {
case NL80211_BAND_2GHZ:
@@ -340,16 +322,12 @@ mt76x0_phy_set_band(struct mt76x0_dev *dev, enum nl80211_band band)
}
}
-#define EXT_PA_2G_5G 0x0
-#define EXT_PA_5G_ONLY 0x1
-#define EXT_PA_2G_ONLY 0x2
-#define INT_PA_2G_5G 0x3
-
static void
-mt76x0_phy_set_chan_rf_params(struct mt76x0_dev *dev, u8 channel, u16 rf_bw_band)
+mt76x0_phy_set_chan_rf_params(struct mt76x02_dev *dev, u8 channel, u16 rf_bw_band)
{
u16 rf_band = rf_bw_band & 0xff00;
u16 rf_bw = rf_bw_band & 0x00ff;
+ enum nl80211_band band;
u32 mac_reg;
u8 rf_val;
int i;
@@ -496,11 +474,8 @@ mt76x0_phy_set_chan_rf_params(struct mt76x0_dev *dev, u8 channel, u16 rf_bw_band
mac_reg &= ~0xC; /* Clear 0x518[3:2] */
mt76_wr(dev, MT_RF_MISC, mac_reg);
- if (dev->ee->pa_type == INT_PA_2G_5G ||
- (dev->ee->pa_type == EXT_PA_5G_ONLY && (rf_band & RF_G_BAND)) ||
- (dev->ee->pa_type == EXT_PA_2G_ONLY && (rf_band & RF_A_BAND))) {
- ; /* Internal PA - nothing to do. */
- } else {
+ band = (rf_band & RF_G_BAND) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
+ if (mt76x02_ext_pa_enabled(&dev->mt76, band)) {
/*
MT_RF_MISC (offset: 0x0518)
[2]1'b1: enable external A band PA, 1'b0: disable external A band PA
@@ -539,7 +514,7 @@ mt76x0_phy_set_chan_rf_params(struct mt76x0_dev *dev, u8 channel, u16 rf_bw_band
}
static void
-mt76x0_phy_set_chan_bbp_params(struct mt76x0_dev *dev, u8 channel, u16 rf_bw_band)
+mt76x0_phy_set_chan_bbp_params(struct mt76x02_dev *dev, u8 channel, u16 rf_bw_band)
{
int i;
@@ -552,20 +527,10 @@ mt76x0_phy_set_chan_bbp_params(struct mt76x0_dev *dev, u8 channel, u16 rf_bw_ban
if (pair->reg == MT_BBP(AGC, 8)) {
u32 val = pair->value;
- u8 gain = FIELD_GET(MT_BBP_AGC_GAIN, val);
-
- if (channel > 14) {
- if (channel < 100)
- gain -= dev->ee->lna_gain_5ghz[0]*2;
- else if (channel < 137)
- gain -= dev->ee->lna_gain_5ghz[1]*2;
- else
- gain -= dev->ee->lna_gain_5ghz[2]*2;
-
- } else {
- gain -= dev->ee->lna_gain_2ghz*2;
- }
+ u8 gain;
+ gain = FIELD_GET(MT_BBP_AGC_GAIN, val);
+ gain -= dev->cal.rx.lna_gain * 2;
val &= ~MT_BBP_AGC_GAIN;
val |= FIELD_PREP(MT_BBP_AGC_GAIN, gain);
mt76_wr(dev, pair->reg, val);
@@ -575,46 +540,27 @@ mt76x0_phy_set_chan_bbp_params(struct mt76x0_dev *dev, u8 channel, u16 rf_bw_ban
}
}
-#if 0
-static void
-mt76x0_extra_power_over_mac(struct mt76x0_dev *dev)
-{
- u32 val;
-
- val = ((mt76_rr(dev, MT_TX_PWR_CFG_1) & 0x00003f00) >> 8);
- val |= ((mt76_rr(dev, MT_TX_PWR_CFG_2) & 0x00003f00) << 8);
- mt76_wr(dev, MT_TX_PWR_CFG_7, val);
-
- /* TODO: fix VHT */
- val = ((mt76_rr(dev, MT_TX_PWR_CFG_3) & 0x0000ff00) >> 8);
- mt76_wr(dev, MT_TX_PWR_CFG_8, val);
-
- val = ((mt76_rr(dev, MT_TX_PWR_CFG_4) & 0x0000ff00) >> 8);
- mt76_wr(dev, MT_TX_PWR_CFG_9, val);
-}
-
-static void
-mt76x0_phy_set_tx_power(struct mt76x0_dev *dev, u8 channel, u8 rf_bw_band)
+static void mt76x0_ant_select(struct mt76x02_dev *dev)
{
- u32 val;
- int i;
- int bw = (rf_bw_band & RF_BW_20) ? 0 : 1;
-
- for (i = 0; i < 4; i++) {
- if (channel <= 14)
- val = dev->ee->tx_pwr_cfg_2g[i][bw];
- else
- val = dev->ee->tx_pwr_cfg_5g[i][bw];
+ struct ieee80211_channel *chan = dev->mt76.chandef.chan;
- mt76_wr(dev, MT_TX_PWR_CFG_0 + 4*i, val);
+ /* single antenna mode */
+ if (chan->band == NL80211_BAND_2GHZ) {
+ mt76_rmw(dev, MT_COEXCFG3,
+ BIT(5) | BIT(4) | BIT(3) | BIT(2), BIT(1));
+ mt76_rmw(dev, MT_WLAN_FUN_CTRL, BIT(5), BIT(6));
+ } else {
+ mt76_rmw(dev, MT_COEXCFG3, BIT(5) | BIT(2),
+ BIT(4) | BIT(3));
+ mt76_clear(dev, MT_WLAN_FUN_CTRL,
+ BIT(6) | BIT(5));
}
-
- mt76x0_extra_power_over_mac(dev);
+ mt76_clear(dev, MT_CMB_CTRL, BIT(14) | BIT(12));
+ mt76_clear(dev, MT_COEXCFG0, BIT(2));
}
-#endif
static void
-mt76x0_bbp_set_bw(struct mt76x0_dev *dev, enum nl80211_chan_width width)
+mt76x0_bbp_set_bw(struct mt76x02_dev *dev, enum nl80211_chan_width width)
{
enum { BW_20 = 0, BW_40 = 1, BW_80 = 2, BW_10 = 4};
int bw;
@@ -644,36 +590,24 @@ mt76x0_bbp_set_bw(struct mt76x0_dev *dev, enum nl80211_chan_width width)
mt76x02_mcu_function_select(&dev->mt76, BW_SETTING, bw, false);
}
-static void
-mt76x0_phy_set_chan_pwr(struct mt76x0_dev *dev, u8 channel)
+void mt76x0_phy_set_txpower(struct mt76x02_dev *dev)
{
- static const int mt76x0_tx_pwr_ch_list[] = {
- 1,2,3,4,5,6,7,8,9,10,11,12,13,14,
- 36,38,40,44,46,48,52,54,56,60,62,64,
- 100,102,104,108,110,112,116,118,120,124,126,128,132,134,136,140,
- 149,151,153,157,159,161,165,167,169,171,173,
- 42,58,106,122,155
- };
- int i;
- u32 val;
+ struct mt76_rate_power *t = &dev->mt76.rate_power;
+ u8 info[2];
- for (i = 0; i < ARRAY_SIZE(mt76x0_tx_pwr_ch_list); i++)
- if (mt76x0_tx_pwr_ch_list[i] == channel)
- break;
+ mt76x0_get_power_info(dev, info);
+ mt76x0_get_tx_power_per_rate(dev);
- if (WARN_ON(i == ARRAY_SIZE(mt76x0_tx_pwr_ch_list)))
- return;
+ mt76x02_add_rate_power_offset(t, info[0]);
+ mt76x02_limit_rate_power(t, dev->mt76.txpower_conf);
+ dev->mt76.txpower_cur = mt76x02_get_max_rate_power(t);
+ mt76x02_add_rate_power_offset(t, -info[0]);
- val = mt76_rr(dev, MT_TX_ALC_CFG_0);
- val &= ~0x3f3f;
- val |= dev->ee->tx_pwr_per_chan[i];
- val |= 0x2f2f << 16;
- mt76_wr(dev, MT_TX_ALC_CFG_0, val);
+ mt76x02_phy_set_txpower(&dev->mt76, info[0], info[1]);
}
-static int
-__mt76x0_phy_set_channel(struct mt76x0_dev *dev,
- struct cfg80211_chan_def *chandef)
+int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
+ struct cfg80211_chan_def *chandef)
{
u32 ext_cca_chan[4] = {
[0] = FIELD_PREP(MT_EXT_CCA_CFG_CCA0, 0) |
@@ -707,6 +641,7 @@ __mt76x0_phy_set_channel(struct mt76x0_dev *dev,
freq1 = chandef->center_freq1;
channel = chandef->chan->hw_value;
rf_bw_band = (channel <= 14) ? RF_G_BAND : RF_A_BAND;
+ dev->mt76.chandef = *chandef;
switch (chandef->width) {
case NL80211_CHAN_WIDTH_40:
@@ -733,6 +668,7 @@ __mt76x0_phy_set_channel(struct mt76x0_dev *dev,
mt76x0_bbp_set_bw(dev, chandef->width);
mt76x0_bbp_set_ctrlch(dev, chandef->width, ch_group_index);
mt76x0_mac_set_ctrlch(dev, ch_group_index & 1);
+ mt76x0_ant_select(dev);
mt76_rmw(dev, MT_EXT_CCA_CFG,
(MT_EXT_CCA_CFG_CCA0 |
@@ -744,6 +680,7 @@ __mt76x0_phy_set_channel(struct mt76x0_dev *dev,
mt76x0_phy_set_band(dev, chandef->chan->band);
mt76x0_phy_set_chan_rf_params(dev, channel, rf_bw_band);
+ mt76x0_read_rx_gain(dev);
/* set Japan Tx filter at channel 14 */
val = mt76_rr(dev, MT_BBP(CORE, 1));
@@ -762,25 +699,12 @@ __mt76x0_phy_set_channel(struct mt76x0_dev *dev,
if (scan)
mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_RXDCOC, 1, false);
- mt76x0_phy_set_chan_pwr(dev, channel);
+ mt76x0_phy_set_txpower(dev);
- dev->mt76.chandef = *chandef;
return 0;
}
-int mt76x0_phy_set_channel(struct mt76x0_dev *dev,
- struct cfg80211_chan_def *chandef)
-{
- int ret;
-
- mutex_lock(&dev->hw_atomic_mutex);
- ret = __mt76x0_phy_set_channel(dev, chandef);
- mutex_unlock(&dev->hw_atomic_mutex);
-
- return ret;
-}
-
-void mt76x0_phy_recalibrate_after_assoc(struct mt76x0_dev *dev)
+void mt76x0_phy_recalibrate_after_assoc(struct mt76x02_dev *dev)
{
u32 tx_alc, reg_val;
u8 channel = dev->mt76.chandef.chan->hw_value;
@@ -816,18 +740,18 @@ void mt76x0_phy_recalibrate_after_assoc(struct mt76x0_dev *dev)
mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_RXDCOC, 1, false);
}
-void mt76x0_agc_save(struct mt76x0_dev *dev)
+void mt76x0_agc_save(struct mt76x02_dev *dev)
{
/* Only one RX path */
dev->agc_save = FIELD_GET(MT_BBP_AGC_GAIN, mt76_rr(dev, MT_BBP(AGC, 8)));
}
-void mt76x0_agc_restore(struct mt76x0_dev *dev)
+void mt76x0_agc_restore(struct mt76x02_dev *dev)
{
mt76_rmw_field(dev, MT_BBP(AGC, 8), MT_BBP_AGC_GAIN, dev->agc_save);
}
-static void mt76x0_temp_sensor(struct mt76x0_dev *dev)
+static void mt76x0_temp_sensor(struct mt76x02_dev *dev)
{
u8 rf_b7_73, rf_b0_66, rf_b0_67;
int cycle, temp;
@@ -863,7 +787,7 @@ static void mt76x0_temp_sensor(struct mt76x0_dev *dev)
else
sval |= 0xffffff00; /* Negative */
- temp = (35 * (sval - dev->ee->temp_off))/ 10 + 25;
+ temp = (35 * (sval - dev->cal.rx.temp_offset)) / 10 + 25;
done:
rf_wr(dev, MT_RF(7, 73), rf_b7_73);
@@ -871,14 +795,17 @@ done:
rf_wr(dev, MT_RF(0, 73), rf_b0_67);
}
-static void mt76x0_dynamic_vga_tuning(struct mt76x0_dev *dev)
+static void mt76x0_dynamic_vga_tuning(struct mt76x02_dev *dev)
{
+ struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
u32 val, init_vga;
+ int avg_rssi;
- init_vga = (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ) ? 0x54 : 0x4E;
- if (dev->avg_rssi > -60)
+ init_vga = chandef->chan->band == NL80211_BAND_5GHZ ? 0x54 : 0x4E;
+ avg_rssi = mt76x02_phy_get_min_avg_rssi(&dev->mt76);
+ if (avg_rssi > -60)
init_vga -= 0x20;
- else if (dev->avg_rssi > -70)
+ else if (avg_rssi > -70)
init_vga -= 0x10;
val = mt76_rr(dev, MT_BBP(AGC, 8));
@@ -889,8 +816,8 @@ static void mt76x0_dynamic_vga_tuning(struct mt76x0_dev *dev)
static void mt76x0_phy_calibrate(struct work_struct *work)
{
- struct mt76x0_dev *dev = container_of(work, struct mt76x0_dev,
- cal_work.work);
+ struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev,
+ cal_work.work);
mt76x0_dynamic_vga_tuning(dev);
mt76x0_temp_sensor(dev);
@@ -899,45 +826,7 @@ static void mt76x0_phy_calibrate(struct work_struct *work)
MT_CALIBRATE_INTERVAL);
}
-void mt76x0_phy_con_cal_onoff(struct mt76x0_dev *dev,
- struct ieee80211_bss_conf *info)
-{
- /* Start/stop collecting beacon data */
- spin_lock_bh(&dev->con_mon_lock);
- ether_addr_copy(dev->ap_bssid, info->bssid);
- dev->avg_rssi = 0;
- dev->bcn_freq_off = MT_FREQ_OFFSET_INVALID;
- spin_unlock_bh(&dev->con_mon_lock);
-}
-
-static void
-mt76x0_set_rx_chains(struct mt76x0_dev *dev)
-{
- u32 val;
-
- val = mt76_rr(dev, MT_BBP(AGC, 0));
- val &= ~(BIT(3) | BIT(4));
-
- if (dev->chainmask & BIT(1))
- val |= BIT(3);
-
- mt76_wr(dev, MT_BBP(AGC, 0), val);
-
- mb();
- val = mt76_rr(dev, MT_BBP(AGC, 0));
-}
-
-static void
-mt76x0_set_tx_dac(struct mt76x0_dev *dev)
-{
- if (dev->chainmask & BIT(1))
- mt76_set(dev, MT_BBP(TXBE, 5), 3);
- else
- mt76_clear(dev, MT_BBP(TXBE, 5), 3);
-}
-
-static void
-mt76x0_rf_init(struct mt76x0_dev *dev)
+static void mt76x0_rf_init(struct mt76x02_dev *dev)
{
int i;
u8 val;
@@ -969,7 +858,8 @@ mt76x0_rf_init(struct mt76x0_dev *dev)
E1: B0.R22<6:0>: xo_cxo<6:0>
E2: B0.R21<0>: xo_cxo<0>, B0.R22<7:0>: xo_cxo<8:1>
*/
- rf_wr(dev, MT_RF(0, 22), min_t(u8, dev->ee->rf_freq_off, 0xBF));
+ rf_wr(dev, MT_RF(0, 22),
+ min_t(u8, dev->cal.rx.freq_offset, 0xbf));
val = rf_rr(dev, MT_RF(0, 22));
/*
@@ -989,23 +879,11 @@ mt76x0_rf_init(struct mt76x0_dev *dev)
rf_set(dev, MT_RF(0, 4), 0x80);
}
-static void mt76x0_ant_select(struct mt76x0_dev *dev)
-{
- /* Single antenna mode. */
- mt76_rmw(dev, MT_WLAN_FUN_CTRL, BIT(5), BIT(6));
- mt76_clear(dev, MT_CMB_CTRL, BIT(14) | BIT(12));
- mt76_clear(dev, MT_COEXCFG0, BIT(2));
- mt76_rmw(dev, MT_COEXCFG3, BIT(5) | BIT(4) | BIT(3) | BIT(2), BIT(1));
-}
-
-void mt76x0_phy_init(struct mt76x0_dev *dev)
+void mt76x0_phy_init(struct mt76x02_dev *dev)
{
INIT_DELAYED_WORK(&dev->cal_work, mt76x0_phy_calibrate);
- mt76x0_ant_select(dev);
-
mt76x0_rf_init(dev);
-
- mt76x0_set_rx_chains(dev);
- mt76x0_set_tx_dac(dev);
+ mt76x02_phy_set_rxpath(&dev->mt76);
+ mt76x02_phy_set_txdac(&dev->mt76);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/trace.h b/drivers/net/wireless/mediatek/mt76/mt76x0/trace.h
index 36bbdd585163..75d1d6738c34 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/trace.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/trace.h
@@ -17,7 +17,6 @@
#include <linux/tracepoint.h>
#include "mt76x0.h"
-#include "mac.h"
#undef TRACE_SYSTEM
#define TRACE_SYSTEM mt76x0
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/tx.c b/drivers/net/wireless/mediatek/mt76/mt76x0/tx.c
deleted file mode 100644
index c6d8ba01feb1..000000000000
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/tx.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
- * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include "mt76x0.h"
-#include "trace.h"
-#include "../mt76x02_util.h"
-#include "../mt76x02_usb.h"
-
-static struct mt76x02_txwi *
-mt76x0_push_txwi(struct mt76x0_dev *dev, struct sk_buff *skb,
- struct ieee80211_sta *sta, struct mt76_wcid *wcid,
- int pkt_len)
-{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_tx_rate *rate = &info->control.rates[0];
- struct mt76x02_txwi *txwi;
- unsigned long flags;
- u16 rate_ctl;
- u8 nss;
-
- txwi = (struct mt76x02_txwi *)skb_push(skb, sizeof(struct mt76x02_txwi));
- memset(txwi, 0, sizeof(*txwi));
-
- if (!wcid->tx_rate_set)
- ieee80211_get_tx_rates(info->control.vif, sta, skb,
- info->control.rates, 1);
-
- spin_lock_irqsave(&dev->mt76.lock, flags);
- if (rate->idx < 0 || !rate->count) {
- rate_ctl = wcid->tx_rate;
- nss = wcid->tx_rate_nss;
- } else {
- rate_ctl = mt76x02_mac_tx_rate_val(&dev->mt76, rate, &nss);
- }
- spin_unlock_irqrestore(&dev->mt76.lock, flags);
-
- txwi->wcid = wcid->idx;
- txwi->rate = cpu_to_le16(rate_ctl);
- txwi->pktid = (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) ? 1 : 0;
-
- mt76x02_mac_fill_txwi(txwi, skb, sta, pkt_len, nss);
-
- return txwi;
-}
-
-void mt76x0_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
- struct sk_buff *skb)
-{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct mt76x0_dev *dev = hw->priv;
- struct ieee80211_vif *vif = info->control.vif;
- struct mt76_wcid *wcid = &dev->mt76.global_wcid;
-
- if (control->sta) {
- struct mt76x02_sta *msta;
-
- msta = (struct mt76x02_sta *)control->sta->drv_priv;
- wcid = &msta->wcid;
- /* sw encrypted frames */
- if (!info->control.hw_key && wcid->hw_key_idx != 0xff)
- control->sta = NULL;
- }
-
- if (vif && !control->sta) {
- struct mt76x02_vif *mvif;
-
- mvif = (struct mt76x02_vif *)vif->drv_priv;
- wcid = &mvif->group_wcid;
- }
-
- mt76_tx(&dev->mt76, control->sta, wcid, skb);
-}
-
-int mt76x0_tx_prepare_skb(struct mt76_dev *mdev, void *data,
- struct sk_buff *skb, struct mt76_queue *q,
- struct mt76_wcid *wcid, struct ieee80211_sta *sta,
- u32 *tx_info)
-{
- struct mt76x0_dev *dev = container_of(mdev, struct mt76x0_dev, mt76);
- struct mt76x02_txwi *txwi;
- int len = skb->len;
-
- mt76x02_insert_hdr_pad(skb);
- txwi = mt76x0_push_txwi(dev, skb, sta, wcid, len);
-
- return mt76x02u_set_txinfo(skb, wcid, q2ep(q->hw_idx));
-}
-EXPORT_SYMBOL_GPL(mt76x0_tx_prepare_skb);
-
-void mt76x0_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
- struct sk_buff *skb)
-{
- struct mt76x0_dev *dev = container_of(mdev, struct mt76x0_dev, mt76);
- void *rxwi = skb->data;
-
- skb_pull(skb, sizeof(struct mt76x02_rxwi));
- if (!mt76x0_mac_process_rx(dev, skb, rxwi)) {
- dev_kfree_skb(skb);
- return;
- }
-
- mt76_rx(&dev->mt76, q, skb);
-}
-EXPORT_SYMBOL_GPL(mt76x0_queue_rx_skb);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
index bb8c0cd3d48a..a7fd36c2f633 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
@@ -13,17 +13,13 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/firmware.h>
#include <linux/usb.h>
#include "mt76x0.h"
#include "mcu.h"
#include "trace.h"
-#include "../mt76x02_util.h"
#include "../mt76x02_usb.h"
-#define MT7610U_FIRMWARE "mediatek/mt7610u.bin"
-
static struct usb_device_id mt76x0_device_table[] = {
{ USB_DEVICE(0x148F, 0x7610) }, /* MT7610U */
{ USB_DEVICE(0x13B1, 0x003E) }, /* Linksys AE6000 */
@@ -45,187 +41,198 @@ static struct usb_device_id mt76x0_device_table[] = {
{ USB_DEVICE(0x20f4, 0x806b) }, /* TRENDnet TEW-806UBH */
{ USB_DEVICE(0x7392, 0xc711) }, /* Devolo Wifi ac Stick */
{ USB_DEVICE(0x0df6, 0x0079) }, /* Sitecom Europe B.V. ac Stick */
- { USB_DEVICE(0x2357, 0x0105) }, /* TP-LINK Archer T1U */
+ { USB_DEVICE(0x2357, 0x0105),
+ .driver_info = 1, }, /* TP-LINK Archer T1U */
{ USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7630, 0xff, 0x2, 0xff)}, /* MT7630U */
{ USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7650, 0xff, 0x2, 0xff)}, /* MT7650U */
{ 0, }
};
-#define MCU_FW_URB_MAX_PAYLOAD 0x38f8
-#define MCU_FW_URB_SIZE (MCU_FW_URB_MAX_PAYLOAD + 12)
-
-static inline int mt76x0_firmware_running(struct mt76x0_dev *dev)
-{
- return mt76_rr(dev, MT_MCU_COM_REG0) == 1;
-}
-
-static int
-mt76x0u_upload_firmware(struct mt76x0_dev *dev,
- const struct mt76x02_fw_header *hdr)
+static void mt76x0_init_usb_dma(struct mt76x02_dev *dev)
{
- u8 *fw_payload = (u8 *)(hdr + 1);
- u32 ilm_len, dlm_len;
- void *ivb;
- int err;
+ u32 val;
- ivb = kmemdup(fw_payload, MT_MCU_IVB_SIZE, GFP_KERNEL);
- if (!ivb)
- return -ENOMEM;
+ val = mt76_rr(dev, MT_USB_DMA_CFG);
- ilm_len = le32_to_cpu(hdr->ilm_len) - MT_MCU_IVB_SIZE;
- dev_dbg(dev->mt76.dev, "loading FW - ILM %u + IVB %u\n",
- ilm_len, MT_MCU_IVB_SIZE);
- err = mt76x02u_mcu_fw_send_data(&dev->mt76,
- fw_payload + MT_MCU_IVB_SIZE,
- ilm_len, MCU_FW_URB_MAX_PAYLOAD,
- MT_MCU_IVB_SIZE);
- if (err)
- goto out;
+ val |= MT_USB_DMA_CFG_RX_BULK_EN |
+ MT_USB_DMA_CFG_TX_BULK_EN;
- dlm_len = le32_to_cpu(hdr->dlm_len);
- dev_dbg(dev->mt76.dev, "loading FW - DLM %u\n", dlm_len);
- err = mt76x02u_mcu_fw_send_data(&dev->mt76,
- fw_payload + le32_to_cpu(hdr->ilm_len),
- dlm_len, MCU_FW_URB_MAX_PAYLOAD,
- MT_MCU_DLM_OFFSET);
- if (err)
- goto out;
-
- err = mt76u_vendor_request(&dev->mt76, MT_VEND_DEV_MODE,
- USB_DIR_OUT | USB_TYPE_VENDOR,
- 0x12, 0, ivb, MT_MCU_IVB_SIZE);
- if (err < 0)
- goto out;
+ /* disable AGGR_BULK_RX in order to receive one
+ * frame in each rx urb and avoid copies
+ */
+ val &= ~MT_USB_DMA_CFG_RX_BULK_AGG_EN;
+ mt76_wr(dev, MT_USB_DMA_CFG, val);
- if (!mt76_poll_msec(dev, MT_MCU_COM_REG0, 1, 1, 1000)) {
- dev_err(dev->mt76.dev, "Firmware failed to start\n");
- err = -ETIMEDOUT;
- goto out;
- }
+ val = mt76_rr(dev, MT_COM_REG0);
+ if (val & 1)
+ dev_dbg(dev->mt76.dev, "MCU not ready\n");
- dev_dbg(dev->mt76.dev, "Firmware running!\n");
+ val = mt76_rr(dev, MT_USB_DMA_CFG);
-out:
- kfree(ivb);
+ val |= MT_USB_DMA_CFG_RX_DROP_OR_PAD;
+ mt76_wr(dev, MT_USB_DMA_CFG, val);
+ val &= ~MT_USB_DMA_CFG_RX_DROP_OR_PAD;
+ mt76_wr(dev, MT_USB_DMA_CFG, val);
+}
- return err;
+static void mt76x0u_cleanup(struct mt76x02_dev *dev)
+{
+ clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);
+ mt76x0_chip_onoff(dev, false, false);
+ mt76u_queues_deinit(&dev->mt76);
+ mt76u_mcu_deinit(&dev->mt76);
}
-static int mt76x0u_load_firmware(struct mt76x0_dev *dev)
+static void mt76x0u_mac_stop(struct mt76x02_dev *dev)
{
- const struct firmware *fw;
- const struct mt76x02_fw_header *hdr;
- int len, ret;
- u32 val;
+ clear_bit(MT76_STATE_RUNNING, &dev->mt76.state);
+ cancel_delayed_work_sync(&dev->cal_work);
+ cancel_delayed_work_sync(&dev->mac_work);
+ mt76u_stop_stat_wk(&dev->mt76);
- mt76_wr(dev, MT_USB_DMA_CFG, (MT_USB_DMA_CFG_RX_BULK_EN |
- MT_USB_DMA_CFG_TX_BULK_EN));
+ if (test_bit(MT76_REMOVED, &dev->mt76.state))
+ return;
- if (mt76x0_firmware_running(dev))
- return 0;
+ mt76_clear(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_TIMER_EN |
+ MT_BEACON_TIME_CFG_SYNC_MODE | MT_BEACON_TIME_CFG_TBTT_EN |
+ MT_BEACON_TIME_CFG_BEACON_TX);
- ret = request_firmware(&fw, MT7610U_FIRMWARE, dev->mt76.dev);
- if (ret)
- return ret;
+ if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_TX_BUSY, 0, 1000))
+ dev_warn(dev->mt76.dev, "TX DMA did not stop\n");
- if (!fw || !fw->data || fw->size < sizeof(*hdr))
- goto err_inv_fw;
+ mt76x0_mac_stop(dev);
- hdr = (const struct mt76x02_fw_header *)fw->data;
+ if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_RX_BUSY, 0, 1000))
+ dev_warn(dev->mt76.dev, "RX DMA did not stop\n");
+}
- if (le32_to_cpu(hdr->ilm_len) <= MT_MCU_IVB_SIZE)
- goto err_inv_fw;
+static int mt76x0u_start(struct ieee80211_hw *hw)
+{
+ struct mt76x02_dev *dev = hw->priv;
+ int ret;
- len = sizeof(*hdr);
- len += le32_to_cpu(hdr->ilm_len);
- len += le32_to_cpu(hdr->dlm_len);
+ mutex_lock(&dev->mt76.mutex);
- if (fw->size != len)
- goto err_inv_fw;
+ ret = mt76x0_mac_start(dev);
+ if (ret)
+ goto out;
- val = le16_to_cpu(hdr->fw_ver);
- dev_dbg(dev->mt76.dev,
- "Firmware Version: %d.%d.%02d Build: %x Build time: %.16s\n",
- (val >> 12) & 0xf, (val >> 8) & 0xf, val & 0xf,
- le16_to_cpu(hdr->build_ver), hdr->build_time);
+ ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work,
+ MT_CALIBRATE_INTERVAL);
+ ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
+ MT_CALIBRATE_INTERVAL);
+ set_bit(MT76_STATE_RUNNING, &dev->mt76.state);
- len = le32_to_cpu(hdr->ilm_len);
+out:
+ mutex_unlock(&dev->mt76.mutex);
+ return ret;
+}
- mt76_wr(dev, 0x1004, 0x2c);
+static void mt76x0u_stop(struct ieee80211_hw *hw)
+{
+ struct mt76x02_dev *dev = hw->priv;
- mt76_set(dev, MT_USB_DMA_CFG, (MT_USB_DMA_CFG_RX_BULK_EN |
- MT_USB_DMA_CFG_TX_BULK_EN) |
- FIELD_PREP(MT_USB_DMA_CFG_RX_BULK_AGG_TOUT, 0x20));
- mt76x02u_mcu_fw_reset(&dev->mt76);
- msleep(5);
-/*
- mt76x0_rmw(dev, MT_PBF_CFG, 0, (MT_PBF_CFG_TX0Q_EN |
- MT_PBF_CFG_TX1Q_EN |
- MT_PBF_CFG_TX2Q_EN |
- MT_PBF_CFG_TX3Q_EN));
-*/
-
- mt76_wr(dev, MT_FCE_PSE_CTRL, 1);
-
- /* FCE tx_fs_base_ptr */
- mt76_wr(dev, MT_TX_CPU_FROM_FCE_BASE_PTR, 0x400230);
- /* FCE tx_fs_max_cnt */
- mt76_wr(dev, MT_TX_CPU_FROM_FCE_MAX_COUNT, 1);
- /* FCE pdma enable */
- mt76_wr(dev, MT_FCE_PDMA_GLOBAL_CONF, 0x44);
- /* FCE skip_fs_en */
- mt76_wr(dev, MT_FCE_SKIP_FS, 3);
+ mutex_lock(&dev->mt76.mutex);
+ mt76x0u_mac_stop(dev);
+ mutex_unlock(&dev->mt76.mutex);
+}
- val = mt76_rr(dev, MT_USB_DMA_CFG);
- val |= MT_USB_DMA_CFG_UDMA_TX_WL_DROP;
- mt76_wr(dev, MT_USB_DMA_CFG, val);
- val &= ~MT_USB_DMA_CFG_UDMA_TX_WL_DROP;
- mt76_wr(dev, MT_USB_DMA_CFG, val);
+static const struct ieee80211_ops mt76x0u_ops = {
+ .tx = mt76x02_tx,
+ .start = mt76x0u_start,
+ .stop = mt76x0u_stop,
+ .add_interface = mt76x02_add_interface,
+ .remove_interface = mt76x02_remove_interface,
+ .config = mt76x0_config,
+ .configure_filter = mt76x02_configure_filter,
+ .bss_info_changed = mt76x0_bss_info_changed,
+ .sta_add = mt76x02_sta_add,
+ .sta_remove = mt76x02_sta_remove,
+ .set_key = mt76x02_set_key,
+ .conf_tx = mt76x02_conf_tx,
+ .sw_scan_start = mt76x0_sw_scan,
+ .sw_scan_complete = mt76x0_sw_scan_complete,
+ .ampdu_action = mt76x02_ampdu_action,
+ .sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
+ .set_rts_threshold = mt76x0_set_rts_threshold,
+ .wake_tx_queue = mt76_wake_tx_queue,
+};
- ret = mt76x0u_upload_firmware(dev, hdr);
- release_firmware(fw);
+static int mt76x0u_register_device(struct mt76x02_dev *dev)
+{
+ struct ieee80211_hw *hw = dev->mt76.hw;
+ int err;
- mt76_wr(dev, MT_FCE_PSE_CTRL, 1);
+ err = mt76u_alloc_queues(&dev->mt76);
+ if (err < 0)
+ goto out_err;
- return ret;
+ err = mt76u_mcu_init_rx(&dev->mt76);
+ if (err < 0)
+ goto out_err;
-err_inv_fw:
- dev_err(dev->mt76.dev, "Invalid firmware image\n");
- release_firmware(fw);
- return -ENOENT;
-}
+ mt76x0_chip_onoff(dev, true, true);
+ if (!mt76x02_wait_for_mac(&dev->mt76)) {
+ err = -ETIMEDOUT;
+ goto out_err;
+ }
-static int mt76x0u_mcu_init(struct mt76x0_dev *dev)
-{
- int ret;
+ err = mt76x0u_mcu_init(dev);
+ if (err < 0)
+ goto out_err;
- ret = mt76x0u_load_firmware(dev);
- if (ret < 0)
- return ret;
+ mt76x0_init_usb_dma(dev);
+ err = mt76x0_init_hardware(dev);
+ if (err < 0)
+ goto out_err;
- set_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state);
+ mt76_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e);
+ mt76_wr(dev, MT_TXOP_CTRL_CFG,
+ FIELD_PREP(MT_TXOP_TRUN_EN, 0x3f) |
+ FIELD_PREP(MT_TXOP_EXT_CCA_DLY, 0x58));
+
+ err = mt76x0_register_device(dev);
+ if (err < 0)
+ goto out_err;
+
+ /* check hw sg support in order to enable AMSDU */
+ if (mt76u_check_sg(&dev->mt76))
+ hw->max_tx_fragments = MT_SG_MAX_SIZE;
+ else
+ hw->max_tx_fragments = 1;
+
+ set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);
return 0;
+
+out_err:
+ mt76x0u_cleanup(dev);
+ return err;
}
static int mt76x0u_probe(struct usb_interface *usb_intf,
const struct usb_device_id *id)
{
static const struct mt76_driver_ops drv_ops = {
- .tx_prepare_skb = mt76x0_tx_prepare_skb,
- .tx_complete_skb = mt76x02_tx_complete_skb,
+ .tx_prepare_skb = mt76x02u_tx_prepare_skb,
+ .tx_complete_skb = mt76x02u_tx_complete_skb,
.tx_status_data = mt76x02_tx_status_data,
- .rx_skb = mt76x0_queue_rx_skb,
+ .rx_skb = mt76x02_queue_rx_skb,
};
struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
- struct mt76x0_dev *dev;
+ struct mt76x02_dev *dev;
u32 asic_rev, mac_rev;
int ret;
- dev = mt76x0_alloc_device(&usb_intf->dev, &drv_ops);
+ dev = mt76x0_alloc_device(&usb_intf->dev, &drv_ops,
+ &mt76x0u_ops);
if (!dev)
return -ENOMEM;
+ /* Quirk for Archer T1U */
+ if (id->driver_info)
+ dev->no_2ghz = true;
+
usb_dev = usb_get_dev(usb_dev);
usb_reset_device(usb_dev);
@@ -253,32 +260,12 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
if (!(mt76_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL))
dev_warn(dev->mt76.dev, "Warning: eFUSE not present\n");
- ret = mt76u_mcu_init_rx(&dev->mt76);
+ ret = mt76x0u_register_device(dev);
if (ret < 0)
goto err;
- ret = mt76u_alloc_queues(&dev->mt76);
- if (ret < 0)
- goto err;
-
- mt76x0_chip_onoff(dev, true, true);
-
- if (!mt76x02_wait_for_mac(&dev->mt76))
- return -ETIMEDOUT;
-
- ret = mt76x0u_mcu_init(dev);
- if (ret)
- goto err_hw;
-
- ret = mt76x0_register_device(dev);
- if (ret)
- goto err_hw;
-
- set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);
-
return 0;
-err_hw:
- mt76x0_cleanup(dev);
+
err:
usb_set_intfdata(usb_intf, NULL);
usb_put_dev(interface_to_usbdev(usb_intf));
@@ -289,14 +276,14 @@ err:
static void mt76x0_disconnect(struct usb_interface *usb_intf)
{
- struct mt76x0_dev *dev = usb_get_intfdata(usb_intf);
+ struct mt76x02_dev *dev = usb_get_intfdata(usb_intf);
bool initalized = test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);
if (!initalized)
return;
ieee80211_unregister_hw(dev->mt76.hw);
- mt76x0_cleanup(dev);
+ mt76x0u_cleanup(dev);
usb_set_intfdata(usb_intf, NULL);
usb_put_dev(interface_to_usbdev(usb_intf));
@@ -307,11 +294,11 @@ static void mt76x0_disconnect(struct usb_interface *usb_intf)
static int __maybe_unused mt76x0_suspend(struct usb_interface *usb_intf,
pm_message_t state)
{
- struct mt76x0_dev *dev = usb_get_intfdata(usb_intf);
+ struct mt76x02_dev *dev = usb_get_intfdata(usb_intf);
struct mt76_usb *usb = &dev->mt76.usb;
mt76u_stop_queues(&dev->mt76);
- mt76x0_mac_stop(dev);
+ mt76x0u_mac_stop(dev);
usb_kill_urb(usb->mcu.res.urb);
return 0;
@@ -319,7 +306,7 @@ static int __maybe_unused mt76x0_suspend(struct usb_interface *usb_intf,
static int __maybe_unused mt76x0_resume(struct usb_interface *usb_intf)
{
- struct mt76x0_dev *dev = usb_get_intfdata(usb_intf);
+ struct mt76x02_dev *dev = usb_get_intfdata(usb_intf);
struct mt76_usb *usb = &dev->mt76.usb;
int ret;
@@ -345,12 +332,11 @@ static int __maybe_unused mt76x0_resume(struct usb_interface *usb_intf)
return 0;
err:
- mt76x0_cleanup(dev);
+ mt76x0u_cleanup(dev);
return ret;
}
MODULE_DEVICE_TABLE(usb, mt76x0_device_table);
-MODULE_FIRMWARE(MT7610U_FIRMWARE);
MODULE_LICENSE("GPL");
static struct usb_driver mt76x0_driver = {
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c
new file mode 100644
index 000000000000..fb6fa1fa5548
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/kernel.h>
+#include <linux/firmware.h>
+
+#include "mt76x0.h"
+#include "mcu.h"
+#include "../mt76x02_usb.h"
+
+#define MCU_FW_URB_MAX_PAYLOAD 0x38f8
+#define MCU_FW_URB_SIZE (MCU_FW_URB_MAX_PAYLOAD + 12)
+#define MT7610U_FIRMWARE "mediatek/mt7610u.bin"
+
+static int
+mt76x0u_upload_firmware(struct mt76x02_dev *dev,
+ const struct mt76x02_fw_header *hdr)
+{
+ u8 *fw_payload = (u8 *)(hdr + 1);
+ u32 ilm_len, dlm_len;
+ void *ivb;
+ int err;
+
+ ivb = kmemdup(fw_payload, MT_MCU_IVB_SIZE, GFP_KERNEL);
+ if (!ivb)
+ return -ENOMEM;
+
+ ilm_len = le32_to_cpu(hdr->ilm_len) - MT_MCU_IVB_SIZE;
+ dev_dbg(dev->mt76.dev, "loading FW - ILM %u + IVB %u\n",
+ ilm_len, MT_MCU_IVB_SIZE);
+ err = mt76x02u_mcu_fw_send_data(&dev->mt76,
+ fw_payload + MT_MCU_IVB_SIZE,
+ ilm_len, MCU_FW_URB_MAX_PAYLOAD,
+ MT_MCU_IVB_SIZE);
+ if (err)
+ goto out;
+
+ dlm_len = le32_to_cpu(hdr->dlm_len);
+ dev_dbg(dev->mt76.dev, "loading FW - DLM %u\n", dlm_len);
+ err = mt76x02u_mcu_fw_send_data(&dev->mt76,
+ fw_payload + le32_to_cpu(hdr->ilm_len),
+ dlm_len, MCU_FW_URB_MAX_PAYLOAD,
+ MT_MCU_DLM_OFFSET);
+ if (err)
+ goto out;
+
+ err = mt76u_vendor_request(&dev->mt76, MT_VEND_DEV_MODE,
+ USB_DIR_OUT | USB_TYPE_VENDOR,
+ 0x12, 0, ivb, MT_MCU_IVB_SIZE);
+ if (err < 0)
+ goto out;
+
+ if (!mt76_poll_msec(dev, MT_MCU_COM_REG0, 1, 1, 1000)) {
+ dev_err(dev->mt76.dev, "Firmware failed to start\n");
+ err = -ETIMEDOUT;
+ goto out;
+ }
+
+ dev_dbg(dev->mt76.dev, "Firmware running!\n");
+
+out:
+ kfree(ivb);
+
+ return err;
+}
+
+static int mt76x0u_load_firmware(struct mt76x02_dev *dev)
+{
+ const struct firmware *fw;
+ const struct mt76x02_fw_header *hdr;
+ int len, ret;
+ u32 val;
+
+ mt76_wr(dev, MT_USB_DMA_CFG, (MT_USB_DMA_CFG_RX_BULK_EN |
+ MT_USB_DMA_CFG_TX_BULK_EN));
+
+ if (mt76x0_firmware_running(dev))
+ return 0;
+
+ ret = request_firmware(&fw, MT7610U_FIRMWARE, dev->mt76.dev);
+ if (ret)
+ return ret;
+
+ if (!fw || !fw->data || fw->size < sizeof(*hdr))
+ goto err_inv_fw;
+
+ hdr = (const struct mt76x02_fw_header *)fw->data;
+
+ if (le32_to_cpu(hdr->ilm_len) <= MT_MCU_IVB_SIZE)
+ goto err_inv_fw;
+
+ len = sizeof(*hdr);
+ len += le32_to_cpu(hdr->ilm_len);
+ len += le32_to_cpu(hdr->dlm_len);
+
+ if (fw->size != len)
+ goto err_inv_fw;
+
+ val = le16_to_cpu(hdr->fw_ver);
+ dev_dbg(dev->mt76.dev,
+ "Firmware Version: %d.%d.%02d Build: %x Build time: %.16s\n",
+ (val >> 12) & 0xf, (val >> 8) & 0xf, val & 0xf,
+ le16_to_cpu(hdr->build_ver), hdr->build_time);
+
+ len = le32_to_cpu(hdr->ilm_len);
+
+ mt76_wr(dev, 0x1004, 0x2c);
+
+ mt76_set(dev, MT_USB_DMA_CFG,
+ (MT_USB_DMA_CFG_RX_BULK_EN | MT_USB_DMA_CFG_TX_BULK_EN) |
+ FIELD_PREP(MT_USB_DMA_CFG_RX_BULK_AGG_TOUT, 0x20));
+ mt76x02u_mcu_fw_reset(&dev->mt76);
+ usleep_range(5000, 6000);
+/*
+ mt76x0_rmw(dev, MT_PBF_CFG, 0, (MT_PBF_CFG_TX0Q_EN |
+ MT_PBF_CFG_TX1Q_EN |
+ MT_PBF_CFG_TX2Q_EN |
+ MT_PBF_CFG_TX3Q_EN));
+*/
+
+ mt76_wr(dev, MT_FCE_PSE_CTRL, 1);
+
+ /* FCE tx_fs_base_ptr */
+ mt76_wr(dev, MT_TX_CPU_FROM_FCE_BASE_PTR, 0x400230);
+ /* FCE tx_fs_max_cnt */
+ mt76_wr(dev, MT_TX_CPU_FROM_FCE_MAX_COUNT, 1);
+ /* FCE pdma enable */
+ mt76_wr(dev, MT_FCE_PDMA_GLOBAL_CONF, 0x44);
+ /* FCE skip_fs_en */
+ mt76_wr(dev, MT_FCE_SKIP_FS, 3);
+
+ val = mt76_rr(dev, MT_USB_DMA_CFG);
+ val |= MT_USB_DMA_CFG_UDMA_TX_WL_DROP;
+ mt76_wr(dev, MT_USB_DMA_CFG, val);
+ val &= ~MT_USB_DMA_CFG_UDMA_TX_WL_DROP;
+ mt76_wr(dev, MT_USB_DMA_CFG, val);
+
+ ret = mt76x0u_upload_firmware(dev, hdr);
+ release_firmware(fw);
+
+ mt76_wr(dev, MT_FCE_PSE_CTRL, 1);
+
+ return ret;
+
+err_inv_fw:
+ dev_err(dev->mt76.dev, "Invalid firmware image\n");
+ release_firmware(fw);
+ return -ENOENT;
+}
+
+int mt76x0u_mcu_init(struct mt76x02_dev *dev)
+{
+ int ret;
+
+ ret = mt76x0u_load_firmware(dev);
+ if (ret < 0)
+ return ret;
+
+ set_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state);
+
+ return 0;
+}
+
+MODULE_FIRMWARE(MT7610U_FIRMWARE);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h
new file mode 100644
index 000000000000..65174817ebc4
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
+ * Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __MT76X02_UTIL_H
+#define __MT76X02_UTIL_H
+
+#include <linux/kfifo.h>
+
+#include "mt76.h"
+#include "mt76x02_regs.h"
+#include "mt76x02_mac.h"
+#include "mt76x02_dfs.h"
+#include "mt76x02_dma.h"
+
+struct mt76x02_mac_stats {
+ u64 rx_stat[6];
+ u64 tx_stat[6];
+ u64 aggr_stat[2];
+ u64 aggr_n[32];
+ u64 zero_len_del[2];
+};
+
+#define MT_MAX_CHAINS 2
+struct mt76x02_rx_freq_cal {
+ s8 high_gain[MT_MAX_CHAINS];
+ s8 rssi_offset[MT_MAX_CHAINS];
+ s8 lna_gain;
+ u32 mcu_gain;
+ s16 temp_offset;
+ u8 freq_offset;
+};
+
+struct mt76x02_calibration {
+ struct mt76x02_rx_freq_cal rx;
+
+ u8 agc_gain_init[MT_MAX_CHAINS];
+ u8 agc_gain_cur[MT_MAX_CHAINS];
+
+ u16 false_cca;
+ s8 avg_rssi_all;
+ s8 agc_gain_adjust;
+ s8 low_gain;
+
+ u8 temp;
+
+ bool init_cal_done;
+ bool tssi_cal_done;
+ bool tssi_comp_pending;
+ bool dpd_cal_done;
+ bool channel_cal_done;
+};
+
+struct mt76x02_dev {
+ struct mt76_dev mt76; /* must be first */
+
+ struct mac_address macaddr_list[8];
+
+ struct mutex phy_mutex;
+ struct mutex mutex;
+
+ u8 txdone_seq;
+ DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x02_tx_status);
+
+ struct sk_buff *rx_head;
+
+ struct tasklet_struct tx_tasklet;
+ struct tasklet_struct pre_tbtt_tasklet;
+ struct delayed_work cal_work;
+ struct delayed_work mac_work;
+
+ struct mt76x02_mac_stats stats;
+ atomic_t avg_ampdu_len;
+ u32 aggr_stats[32];
+
+ struct sk_buff *beacons[8];
+ u8 beacon_mask;
+ u8 beacon_data_mask;
+
+ u8 tbtt_count;
+ u16 beacon_int;
+
+ struct mt76x02_calibration cal;
+
+ s8 target_power;
+ s8 target_power_delta[2];
+ bool enable_tpc;
+
+ bool no_2ghz;
+
+ u8 agc_save;
+
+ u8 coverage_class;
+ u8 slottime;
+
+ struct mt76x02_dfs_pattern_detector dfs_pd;
+};
+
+extern struct ieee80211_rate mt76x02_rates[12];
+
+void mt76x02_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed_flags,
+ unsigned int *total_flags, u64 multicast);
+int mt76x02_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+int mt76x02_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+
+void mt76x02_vif_init(struct mt76_dev *dev, struct ieee80211_vif *vif,
+ unsigned int idx);
+int mt76x02_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+void mt76x02_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+
+int mt76x02_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_ampdu_params *params);
+int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key);
+int mt76x02_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ u16 queue, const struct ieee80211_tx_queue_params *params);
+void mt76x02_sta_rate_tbl_update(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+s8 mt76x02_tx_get_max_txpwr_adj(struct mt76_dev *dev,
+ const struct ieee80211_tx_rate *rate);
+s8 mt76x02_tx_get_txpwr_adj(struct mt76_dev *mdev, s8 txpwr, s8 max_txpwr_adj);
+void mt76x02_tx_set_txpwr_auto(struct mt76x02_dev *dev, s8 txpwr);
+int mt76x02_insert_hdr_pad(struct sk_buff *skb);
+void mt76x02_remove_hdr_pad(struct sk_buff *skb, int len);
+void mt76x02_tx_complete(struct mt76_dev *dev, struct sk_buff *skb);
+bool mt76x02_tx_status_data(struct mt76_dev *dev, u8 *update);
+void mt76x02_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+ struct sk_buff *skb);
+void mt76x02_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q);
+irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance);
+void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
+ struct sk_buff *skb);
+int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi,
+ struct sk_buff *skb, struct mt76_queue *q,
+ struct mt76_wcid *wcid, struct ieee80211_sta *sta,
+ u32 *tx_info);
+
+extern const u16 mt76x02_beacon_offsets[16];
+void mt76x02_set_beacon_offsets(struct mt76_dev *dev);
+void mt76x02_set_irq_mask(struct mt76x02_dev *dev, u32 clear, u32 set);
+void mt76x02_mac_start(struct mt76x02_dev *dev);
+
+static inline void mt76x02_irq_enable(struct mt76x02_dev *dev, u32 mask)
+{
+ mt76x02_set_irq_mask(dev, 0, mask);
+}
+
+static inline void mt76x02_irq_disable(struct mt76x02_dev *dev, u32 mask)
+{
+ mt76x02_set_irq_mask(dev, mask, 0);
+}
+
+static inline bool
+mt76x02_wait_for_txrx_idle(struct mt76_dev *dev)
+{
+ return __mt76_poll_msec(dev, MT_MAC_STATUS,
+ MT_MAC_STATUS_TX | MT_MAC_STATUS_RX,
+ 0, 100);
+}
+
+static inline struct mt76x02_sta *
+mt76x02_rx_get_sta(struct mt76_dev *dev, u8 idx)
+{
+ struct mt76_wcid *wcid;
+
+ if (idx >= ARRAY_SIZE(dev->wcid))
+ return NULL;
+
+ wcid = rcu_dereference(dev->wcid[idx]);
+ if (!wcid)
+ return NULL;
+
+ return container_of(wcid, struct mt76x02_sta, wcid);
+}
+
+static inline struct mt76_wcid *
+mt76x02_rx_get_sta_wcid(struct mt76x02_sta *sta, bool unicast)
+{
+ if (!sta)
+ return NULL;
+
+ if (unicast)
+ return &sta->wcid;
+ else
+ return &sta->vif->group_wcid;
+}
+
+#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.h b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.h
index 693f421bf096..7e177c934592 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.h
@@ -14,8 +14,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#ifndef __MT76x2_DFS_H
-#define __MT76x2_DFS_H
+#ifndef __MT76x02_DFS_H
+#define __MT76x02_DFS_H
#include <linux/types.h>
#include <linux/nl80211.h>
@@ -49,7 +49,7 @@
#define MT_DFS_ETSI_MAX_PRI (133333 + 125000 + 117647 + 1000)
#define MT_DFS_ETSI_MIN_PRI (4500 - 20)
-struct mt76x2_radar_specs {
+struct mt76x02_radar_specs {
u8 mode;
u16 avg_len;
u16 e_low;
@@ -70,7 +70,7 @@ struct mt76x2_radar_specs {
#define MT_DFS_EVENT_ENGINE(x) (((x) & BIT(31)) ? 2 : 0)
#define MT_DFS_EVENT_TIMESTAMP(x) ((x) & GENMASK(21, 0))
#define MT_DFS_EVENT_WIDTH(x) ((x) & GENMASK(11, 0))
-struct mt76x2_dfs_event {
+struct mt76x02_dfs_event {
unsigned long fetch_ts;
u32 ts;
u16 width;
@@ -78,12 +78,12 @@ struct mt76x2_dfs_event {
};
#define MT_DFS_EVENT_BUFLEN 256
-struct mt76x2_dfs_event_rb {
- struct mt76x2_dfs_event data[MT_DFS_EVENT_BUFLEN];
+struct mt76x02_dfs_event_rb {
+ struct mt76x02_dfs_event data[MT_DFS_EVENT_BUFLEN];
int h_rb, t_rb;
};
-struct mt76x2_dfs_sequence {
+struct mt76x02_dfs_sequence {
struct list_head head;
u32 first_ts;
u32 last_ts;
@@ -92,7 +92,7 @@ struct mt76x2_dfs_sequence {
u8 engine;
};
-struct mt76x2_dfs_hw_pulse {
+struct mt76x02_dfs_hw_pulse {
u8 engine;
u32 period;
u32 w1;
@@ -100,47 +100,41 @@ struct mt76x2_dfs_hw_pulse {
u32 burst;
};
-struct mt76x2_dfs_sw_detector_params {
+struct mt76x02_dfs_sw_detector_params {
u32 min_pri;
u32 max_pri;
u32 pri_margin;
};
-struct mt76x2_dfs_engine_stats {
+struct mt76x02_dfs_engine_stats {
u32 hw_pattern;
u32 hw_pulse_discarded;
u32 sw_pattern;
};
-struct mt76x2_dfs_seq_stats {
+struct mt76x02_dfs_seq_stats {
u32 seq_pool_len;
u32 seq_len;
};
-struct mt76x2_dfs_pattern_detector {
+struct mt76x02_dfs_pattern_detector {
enum nl80211_dfs_regions region;
u8 chirp_pulse_cnt;
u32 chirp_pulse_ts;
- struct mt76x2_dfs_sw_detector_params sw_dpd_params;
- struct mt76x2_dfs_event_rb event_rb[2];
+ struct mt76x02_dfs_sw_detector_params sw_dpd_params;
+ struct mt76x02_dfs_event_rb event_rb[2];
struct list_head sequences;
struct list_head seq_pool;
- struct mt76x2_dfs_seq_stats seq_stats;
+ struct mt76x02_dfs_seq_stats seq_stats;
unsigned long last_sw_check;
u32 last_event_ts;
- struct mt76x2_dfs_engine_stats stats[MT_DFS_NUM_ENGINES];
+ struct mt76x02_dfs_engine_stats stats[MT_DFS_NUM_ENGINES];
struct tasklet_struct dfs_tasklet;
};
-void mt76x2_dfs_init_params(struct mt76x2_dev *dev);
-void mt76x2_dfs_init_detector(struct mt76x2_dev *dev);
-void mt76x2_dfs_adjust_agc(struct mt76x2_dev *dev);
-void mt76x2_dfs_set_domain(struct mt76x2_dev *dev,
- enum nl80211_dfs_regions region);
-
-#endif /* __MT76x2_DFS_H */
+#endif /* __MT76x02_DFS_H */
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dma.h b/drivers/net/wireless/mediatek/mt76/mt76x02_dma.h
index 32a323ebc6a7..6394010a565f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_dma.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dma.h
@@ -17,6 +17,7 @@
#ifndef __MT76x02_DMA_H
#define __MT76x02_DMA_H
+#include "mt76x02.h"
#include "dma.h"
#define MT_TXD_INFO_LEN GENMASK(15, 0)
@@ -47,6 +48,9 @@
#define MT_MCU_MSG_TYPE GENMASK(31, 30)
#define MT_MCU_MSG_TYPE_CMD BIT(30)
+#define MT_RX_HEADROOM 32
+#define MT76X02_RX_RING_SIZE 256
+
enum dma_msg_port {
WLAN_PORT,
CPU_RX_PORT,
@@ -57,4 +61,17 @@ enum dma_msg_port {
DISCARD,
};
+static inline bool
+mt76x02_wait_for_wpdma(struct mt76_dev *dev, int timeout)
+{
+ return __mt76_poll(dev, MT_WPDMA_GLO_CFG,
+ MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
+ MT_WPDMA_GLO_CFG_RX_DMA_BUSY,
+ 0, timeout);
+}
+
+int mt76x02_dma_init(struct mt76x02_dev *dev);
+void mt76x02_dma_disable(struct mt76x02_dev *dev);
+void mt76x02_dma_cleanup(struct mt76x02_dev *dev);
+
#endif /* __MT76x02_DMA_H */
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c
new file mode 100644
index 000000000000..d3efeb8a72b7
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
+ * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <asm/unaligned.h>
+
+#include "mt76.h"
+#include "mt76x02_eeprom.h"
+#include "mt76x02_regs.h"
+
+static int
+mt76x02_efuse_read(struct mt76_dev *dev, u16 addr, u8 *data,
+ enum mt76x02_eeprom_modes mode)
+{
+ u32 val;
+ int i;
+
+ val = __mt76_rr(dev, MT_EFUSE_CTRL);
+ val &= ~(MT_EFUSE_CTRL_AIN |
+ MT_EFUSE_CTRL_MODE);
+ val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf);
+ val |= FIELD_PREP(MT_EFUSE_CTRL_MODE, mode);
+ val |= MT_EFUSE_CTRL_KICK;
+ __mt76_wr(dev, MT_EFUSE_CTRL, val);
+
+ if (!__mt76_poll_msec(dev, MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK,
+ 0, 1000))
+ return -ETIMEDOUT;
+
+ udelay(2);
+
+ val = __mt76_rr(dev, MT_EFUSE_CTRL);
+ if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT) {
+ memset(data, 0xff, 16);
+ return 0;
+ }
+
+ for (i = 0; i < 4; i++) {
+ val = __mt76_rr(dev, MT_EFUSE_DATA(i));
+ put_unaligned_le32(val, data + 4 * i);
+ }
+
+ return 0;
+}
+
+int mt76x02_get_efuse_data(struct mt76_dev *dev, u16 base, void *buf,
+ int len, enum mt76x02_eeprom_modes mode)
+{
+ int ret, i;
+
+ for (i = 0; i + 16 <= len; i += 16) {
+ ret = mt76x02_efuse_read(dev, base + i, buf + i, mode);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mt76x02_get_efuse_data);
+
+void mt76x02_eeprom_parse_hw_cap(struct mt76_dev *dev)
+{
+ u16 val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0);
+
+ switch (FIELD_GET(MT_EE_NIC_CONF_0_BOARD_TYPE, val)) {
+ case BOARD_TYPE_5GHZ:
+ dev->cap.has_5ghz = true;
+ break;
+ case BOARD_TYPE_2GHZ:
+ dev->cap.has_2ghz = true;
+ break;
+ default:
+ dev->cap.has_2ghz = true;
+ dev->cap.has_5ghz = true;
+ break;
+ }
+}
+EXPORT_SYMBOL_GPL(mt76x02_eeprom_parse_hw_cap);
+
+bool mt76x02_ext_pa_enabled(struct mt76_dev *dev, enum nl80211_band band)
+{
+ u16 conf0 = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0);
+
+ if (band == NL80211_BAND_5GHZ)
+ return !(conf0 & MT_EE_NIC_CONF_0_PA_INT_5G);
+ else
+ return !(conf0 & MT_EE_NIC_CONF_0_PA_INT_2G);
+}
+EXPORT_SYMBOL_GPL(mt76x02_ext_pa_enabled);
+
+void mt76x02_get_rx_gain(struct mt76_dev *dev, enum nl80211_band band,
+ u16 *rssi_offset, s8 *lna_2g, s8 *lna_5g)
+{
+ u16 val;
+
+ val = mt76x02_eeprom_get(dev, MT_EE_LNA_GAIN);
+ *lna_2g = val & 0xff;
+ lna_5g[0] = val >> 8;
+
+ val = mt76x02_eeprom_get(dev, MT_EE_RSSI_OFFSET_2G_1);
+ lna_5g[1] = val >> 8;
+
+ val = mt76x02_eeprom_get(dev, MT_EE_RSSI_OFFSET_5G_1);
+ lna_5g[2] = val >> 8;
+
+ if (!mt76x02_field_valid(lna_5g[1]))
+ lna_5g[1] = lna_5g[0];
+
+ if (!mt76x02_field_valid(lna_5g[2]))
+ lna_5g[2] = lna_5g[0];
+
+ if (band == NL80211_BAND_2GHZ)
+ *rssi_offset = mt76x02_eeprom_get(dev, MT_EE_RSSI_OFFSET_2G_0);
+ else
+ *rssi_offset = mt76x02_eeprom_get(dev, MT_EE_RSSI_OFFSET_5G_0);
+}
+EXPORT_SYMBOL_GPL(mt76x02_get_rx_gain);
+
+u8 mt76x02_get_lna_gain(struct mt76_dev *dev,
+ s8 *lna_2g, s8 *lna_5g,
+ struct ieee80211_channel *chan)
+{
+ u16 val;
+ u8 lna;
+
+ val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1);
+ if (val & MT_EE_NIC_CONF_1_LNA_EXT_2G)
+ *lna_2g = 0;
+ if (val & MT_EE_NIC_CONF_1_LNA_EXT_5G)
+ memset(lna_5g, 0, sizeof(s8) * 3);
+
+ if (chan->band == NL80211_BAND_2GHZ)
+ lna = *lna_2g;
+ else if (chan->hw_value <= 64)
+ lna = lna_5g[0];
+ else if (chan->hw_value <= 128)
+ lna = lna_5g[1];
+ else
+ lna = lna_5g[2];
+
+ return lna != 0xff ? lna : 0;
+}
+EXPORT_SYMBOL_GPL(mt76x02_get_lna_gain);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.h b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h
index 0f3e4d2f4fee..bcd05f7c5f45 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
+ * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -14,18 +15,19 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#ifndef __MT76x2_EEPROM_H
-#define __MT76x2_EEPROM_H
+#ifndef __MT76x02_EEPROM_H
+#define __MT76x02_EEPROM_H
-#include "mt76x2.h"
-
-enum mt76x2_eeprom_field {
+enum mt76x02_eeprom_field {
MT_EE_CHIP_ID = 0x000,
MT_EE_VERSION = 0x002,
MT_EE_MAC_ADDR = 0x004,
MT_EE_PCI_ID = 0x00A,
MT_EE_NIC_CONF_0 = 0x034,
MT_EE_NIC_CONF_1 = 0x036,
+ MT_EE_COUNTRY_REGION_5GHZ = 0x038,
+ MT_EE_COUNTRY_REGION_2GHZ = 0x039,
+ MT_EE_FREQ_OFFSET = 0x03a,
MT_EE_NIC_CONF_2 = 0x042,
MT_EE_XTAL_TRIM_1 = 0x03a,
@@ -34,8 +36,10 @@ enum mt76x2_eeprom_field {
MT_EE_LNA_GAIN = 0x044,
MT_EE_RSSI_OFFSET_2G_0 = 0x046,
MT_EE_RSSI_OFFSET_2G_1 = 0x048,
+ MT_EE_LNA_GAIN_5GHZ_1 = 0x049,
MT_EE_RSSI_OFFSET_5G_0 = 0x04a,
MT_EE_RSSI_OFFSET_5G_1 = 0x04c,
+ MT_EE_LNA_GAIN_5GHZ_2 = 0x04d,
MT_EE_TX_POWER_DELTA_BW40 = 0x050,
MT_EE_TX_POWER_DELTA_BW80 = 0x052,
@@ -68,6 +72,17 @@ enum mt76x2_eeprom_field {
MT_EE_TX_POWER_VHT_MCS4 = 0x0bc,
MT_EE_TX_POWER_VHT_MCS8 = 0x0be,
+ MT_EE_2G_TARGET_POWER = 0x0d0,
+ MT_EE_TEMP_OFFSET = 0x0d1,
+ MT_EE_5G_TARGET_POWER = 0x0d2,
+ MT_EE_TSSI_BOUND1 = 0x0d4,
+ MT_EE_TSSI_BOUND2 = 0x0d6,
+ MT_EE_TSSI_BOUND3 = 0x0d8,
+ MT_EE_TSSI_BOUND4 = 0x0da,
+ MT_EE_FREQ_OFFSET_COMPENSATION = 0x0db,
+ MT_EE_TSSI_BOUND5 = 0x0dc,
+ MT_EE_TX_POWER_BYRATE_BASE = 0x0de,
+
MT_EE_RF_TEMP_COMP_SLOPE_5G = 0x0f2,
MT_EE_RF_TEMP_COMP_SLOPE_2G = 0x0f4,
@@ -81,13 +96,21 @@ enum mt76x2_eeprom_field {
MT_EE_BT_VCDL_CALIBRATION = 0x13c,
MT_EE_BT_PMUCFG = 0x13e,
+ MT_EE_USAGE_MAP_START = 0x1e0,
+ MT_EE_USAGE_MAP_END = 0x1fc,
+
__MT_EE_MAX
};
+#define MT_EE_NIC_CONF_0_RX_PATH GENMASK(3, 0)
+#define MT_EE_NIC_CONF_0_TX_PATH GENMASK(7, 4)
+#define MT_EE_NIC_CONF_0_PA_TYPE GENMASK(9, 8)
#define MT_EE_NIC_CONF_0_PA_INT_2G BIT(8)
#define MT_EE_NIC_CONF_0_PA_INT_5G BIT(9)
+#define MT_EE_NIC_CONF_0_PA_IO_CURRENT BIT(10)
#define MT_EE_NIC_CONF_0_BOARD_TYPE GENMASK(13, 12)
+#define MT_EE_NIC_CONF_1_HW_RF_CTRL BIT(0)
#define MT_EE_NIC_CONF_1_TEMP_TX_ALC BIT(1)
#define MT_EE_NIC_CONF_1_LNA_EXT_2G BIT(2)
#define MT_EE_NIC_CONF_1_LNA_EXT_5G BIT(3)
@@ -100,93 +123,89 @@ enum mt76x2_eeprom_field {
#define MT_EE_NIC_CONF_2_TEMP_DISABLE BIT(11)
#define MT_EE_NIC_CONF_2_COEX_METHOD GENMASK(15, 13)
-enum mt76x2_board_type {
+#define MT_EFUSE_USAGE_MAP_SIZE (MT_EE_USAGE_MAP_END - \
+ MT_EE_USAGE_MAP_START + 1)
+
+enum mt76x02_eeprom_modes {
+ MT_EE_READ,
+ MT_EE_PHYSICAL_READ,
+};
+
+enum mt76x02_board_type {
BOARD_TYPE_2GHZ = 1,
BOARD_TYPE_5GHZ = 2,
};
-enum mt76x2_cal_channel_group {
- MT_CH_5G_JAPAN,
- MT_CH_5G_UNII_1,
- MT_CH_5G_UNII_2,
- MT_CH_5G_UNII_2E_1,
- MT_CH_5G_UNII_2E_2,
- MT_CH_5G_UNII_3,
- __MT_CH_MAX
-};
+static inline bool mt76x02_field_valid(u8 val)
+{
+ return val != 0 && val != 0xff;
+}
-struct mt76x2_tx_power_info {
- u8 target_power;
+static inline int
+mt76x02_sign_extend(u32 val, unsigned int size)
+{
+ bool sign = val & BIT(size - 1);
- s8 delta_bw40;
- s8 delta_bw80;
+ val &= BIT(size - 1) - 1;
- struct {
- s8 tssi_slope;
- s8 tssi_offset;
- s8 target_power;
- s8 delta;
- } chain[MT_MAX_CHAINS];
-};
+ return sign ? val : -val;
+}
-struct mt76x2_temp_comp {
- u8 temp_25_ref;
- int lower_bound; /* J */
- int upper_bound; /* J */
- unsigned int high_slope; /* J / dB */
- unsigned int low_slope; /* J / dB */
-};
+static inline int
+mt76x02_sign_extend_optional(u32 val, unsigned int size)
+{
+ bool enable = val & BIT(size);
+
+ return enable ? mt76x02_sign_extend(val, size) : 0;
+}
+
+static inline s8 mt76x02_rate_power_val(u8 val)
+{
+ if (!mt76x02_field_valid(val))
+ return 0;
+
+ return mt76x02_sign_extend_optional(val, 7);
+}
static inline int
-mt76x2_eeprom_get(struct mt76x2_dev *dev, enum mt76x2_eeprom_field field)
+mt76x02_eeprom_get(struct mt76_dev *dev,
+ enum mt76x02_eeprom_field field)
{
if ((field & 1) || field >= __MT_EE_MAX)
return -1;
- return get_unaligned_le16(dev->mt76.eeprom.data + field);
+ return get_unaligned_le16(dev->eeprom.data + field);
}
-void mt76x2_get_rate_power(struct mt76x2_dev *dev, struct mt76_rate_power *t,
- struct ieee80211_channel *chan);
-int mt76x2_get_max_rate_power(struct mt76_rate_power *r);
-void mt76x2_get_power_info(struct mt76x2_dev *dev,
- struct mt76x2_tx_power_info *t,
- struct ieee80211_channel *chan);
-int mt76x2_get_temp_comp(struct mt76x2_dev *dev, struct mt76x2_temp_comp *t);
-bool mt76x2_ext_pa_enabled(struct mt76x2_dev *dev, enum nl80211_band band);
-void mt76x2_read_rx_gain(struct mt76x2_dev *dev);
-void mt76x2_eeprom_parse_hw_cap(struct mt76x2_dev *dev);
-
static inline bool
-mt76x2_temp_tx_alc_enabled(struct mt76x2_dev *dev)
+mt76x02_temp_tx_alc_enabled(struct mt76_dev *dev)
{
u16 val;
- val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_EXT_PA_5G);
+ val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_EXT_PA_5G);
if (!(val & BIT(15)))
return false;
- return mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_1) &
+ return mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1) &
MT_EE_NIC_CONF_1_TEMP_TX_ALC;
}
static inline bool
-mt76x2_tssi_enabled(struct mt76x2_dev *dev)
+mt76x02_tssi_enabled(struct mt76_dev *dev)
{
- return !mt76x2_temp_tx_alc_enabled(dev) &&
- (mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_1) &
+ return !mt76x02_temp_tx_alc_enabled(dev) &&
+ (mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1) &
MT_EE_NIC_CONF_1_TX_ALC_EN);
}
-static inline bool
-mt76x2_has_ext_lna(struct mt76x2_dev *dev)
-{
- u32 val = mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_1);
-
- if (dev->mt76.chandef.chan->band == NL80211_BAND_2GHZ)
- return val & MT_EE_NIC_CONF_1_LNA_EXT_2G;
- else
- return val & MT_EE_NIC_CONF_1_LNA_EXT_5G;
-}
-
-#endif
+bool mt76x02_ext_pa_enabled(struct mt76_dev *dev, enum nl80211_band band);
+int mt76x02_get_efuse_data(struct mt76_dev *dev, u16 base, void *buf,
+ int len, enum mt76x02_eeprom_modes mode);
+void mt76x02_get_rx_gain(struct mt76_dev *dev, enum nl80211_band band,
+ u16 *rssi_offset, s8 *lna_2g, s8 *lna_5g);
+u8 mt76x02_get_lna_gain(struct mt76_dev *dev,
+ s8 *lna_2g, s8 *lna_5g,
+ struct ieee80211_channel *chan);
+void mt76x02_eeprom_parse_hw_cap(struct mt76_dev *dev);
+
+#endif /* __MT76x02_EEPROM_H */
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
index 0b12299c7a41..244245418ebb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
@@ -15,9 +15,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include "mt76.h"
-#include "mt76x02_regs.h"
-#include "mt76x02_mac.h"
+#include "mt76x02.h"
+#include "mt76x02_trace.h"
enum mt76x02_cipher_type
mt76x02_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data)
@@ -156,8 +155,9 @@ void mt76x02_txq_init(struct mt76_dev *dev, struct ieee80211_txq *txq)
}
EXPORT_SYMBOL_GPL(mt76x02_txq_init);
-void mt76x02_mac_fill_txwi(struct mt76x02_txwi *txwi, struct sk_buff *skb,
- struct ieee80211_sta *sta, int len, u8 nss)
+static void
+mt76x02_mac_fill_txwi(struct mt76x02_txwi *txwi, struct sk_buff *skb,
+ struct ieee80211_sta *sta, int len, u8 nss)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
@@ -196,9 +196,8 @@ void mt76x02_mac_fill_txwi(struct mt76x02_txwi *txwi, struct sk_buff *skb,
txwi->flags |= cpu_to_le16(txwi_flags);
txwi->len_ctl = cpu_to_le16(len);
}
-EXPORT_SYMBOL_GPL(mt76x02_mac_fill_txwi);
-__le16
+static __le16
mt76x02_mac_tx_rate_val(struct mt76_dev *dev,
const struct ieee80211_tx_rate *rate, u8 *nss_val)
{
@@ -248,7 +247,6 @@ mt76x02_mac_tx_rate_val(struct mt76_dev *dev,
*nss_val = nss;
return cpu_to_le16(rateval);
}
-EXPORT_SYMBOL_GPL(mt76x02_mac_tx_rate_val);
void mt76x02_mac_wcid_set_rate(struct mt76_dev *dev, struct mt76_wcid *wcid,
const struct ieee80211_tx_rate *rate)
@@ -341,6 +339,66 @@ mt76x02_mac_process_tx_rate(struct ieee80211_tx_rate *txrate, u16 rate,
return 0;
}
+void mt76x02_mac_write_txwi(struct mt76_dev *dev, struct mt76x02_txwi *txwi,
+ struct sk_buff *skb, struct mt76_wcid *wcid,
+ struct ieee80211_sta *sta, int len)
+{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_tx_rate *rate = &info->control.rates[0];
+ struct ieee80211_key_conf *key = info->control.hw_key;
+ u16 rate_ht_mask = FIELD_PREP(MT_RXWI_RATE_PHY, BIT(1) | BIT(2));
+ u8 nss;
+ s8 txpwr_adj, max_txpwr_adj;
+ u8 ccmp_pn[8], nstreams = dev->chainmask & 0xf;
+
+ memset(txwi, 0, sizeof(*txwi));
+
+ if (wcid)
+ txwi->wcid = wcid->idx;
+ else
+ txwi->wcid = 0xff;
+
+ txwi->pktid = 1;
+
+ if (wcid && wcid->sw_iv && key) {
+ u64 pn = atomic64_inc_return(&key->tx_pn);
+ ccmp_pn[0] = pn;
+ ccmp_pn[1] = pn >> 8;
+ ccmp_pn[2] = 0;
+ ccmp_pn[3] = 0x20 | (key->keyidx << 6);
+ ccmp_pn[4] = pn >> 16;
+ ccmp_pn[5] = pn >> 24;
+ ccmp_pn[6] = pn >> 32;
+ ccmp_pn[7] = pn >> 40;
+ txwi->iv = *((__le32 *)&ccmp_pn[0]);
+ txwi->eiv = *((__le32 *)&ccmp_pn[1]);
+ }
+
+ spin_lock_bh(&dev->lock);
+ if (wcid && (rate->idx < 0 || !rate->count)) {
+ txwi->rate = wcid->tx_rate;
+ max_txpwr_adj = wcid->max_txpwr_adj;
+ nss = wcid->tx_rate_nss;
+ } else {
+ txwi->rate = mt76x02_mac_tx_rate_val(dev, rate, &nss);
+ max_txpwr_adj = mt76x02_tx_get_max_txpwr_adj(dev, rate);
+ }
+ spin_unlock_bh(&dev->lock);
+
+ txpwr_adj = mt76x02_tx_get_txpwr_adj(dev, dev->txpower_conf,
+ max_txpwr_adj);
+ txwi->ctl2 = FIELD_PREP(MT_TX_PWR_ADJ, txpwr_adj);
+
+ if (nstreams > 1 && mt76_rev(dev) >= MT76XX_REV_E4)
+ txwi->txstream = 0x13;
+ else if (nstreams > 1 && mt76_rev(dev) >= MT76XX_REV_E3 &&
+ !(txwi->rate & cpu_to_le16(rate_ht_mask)))
+ txwi->txstream = 0x93;
+
+ mt76x02_mac_fill_txwi(txwi, skb, sta, len, nss);
+}
+EXPORT_SYMBOL_GPL(mt76x02_mac_write_txwi);
+
static void
mt76x02_mac_fill_tx_status(struct mt76_dev *dev,
struct ieee80211_tx_info *info,
@@ -502,3 +560,186 @@ mt76x02_mac_process_rate(struct mt76_rx_status *status, u16 rate)
return 0;
}
EXPORT_SYMBOL_GPL(mt76x02_mac_process_rate);
+
+void mt76x02_mac_setaddr(struct mt76_dev *dev, u8 *addr)
+{
+ ether_addr_copy(dev->macaddr, addr);
+
+ if (!is_valid_ether_addr(dev->macaddr)) {
+ eth_random_addr(dev->macaddr);
+ dev_info(dev->dev,
+ "Invalid MAC address, using random address %pM\n",
+ dev->macaddr);
+ }
+
+ __mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(dev->macaddr));
+ __mt76_wr(dev, MT_MAC_ADDR_DW1,
+ get_unaligned_le16(dev->macaddr + 4) |
+ FIELD_PREP(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff));
+}
+EXPORT_SYMBOL_GPL(mt76x02_mac_setaddr);
+
+static int
+mt76x02_mac_get_rssi(struct mt76x02_dev *dev, s8 rssi, int chain)
+{
+ struct mt76x02_rx_freq_cal *cal = &dev->cal.rx;
+
+ rssi += cal->rssi_offset[chain];
+ rssi -= cal->lna_gain;
+
+ return rssi;
+}
+
+int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
+ void *rxi)
+{
+ struct mt76_rx_status *status = (struct mt76_rx_status *) skb->cb;
+ struct mt76x02_rxwi *rxwi = rxi;
+ struct mt76x02_sta *sta;
+ u32 rxinfo = le32_to_cpu(rxwi->rxinfo);
+ u32 ctl = le32_to_cpu(rxwi->ctl);
+ u16 rate = le16_to_cpu(rxwi->rate);
+ u16 tid_sn = le16_to_cpu(rxwi->tid_sn);
+ bool unicast = rxwi->rxinfo & cpu_to_le32(MT_RXINFO_UNICAST);
+ int i, pad_len = 0, nstreams = dev->mt76.chainmask & 0xf;
+ s8 signal;
+ u8 pn_len;
+ u8 wcid;
+ int len;
+
+ if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state))
+ return -EINVAL;
+
+ if (rxinfo & MT_RXINFO_L2PAD)
+ pad_len += 2;
+
+ if (rxinfo & MT_RXINFO_DECRYPT) {
+ status->flag |= RX_FLAG_DECRYPTED;
+ status->flag |= RX_FLAG_MMIC_STRIPPED;
+ status->flag |= RX_FLAG_MIC_STRIPPED;
+ status->flag |= RX_FLAG_IV_STRIPPED;
+ }
+
+ wcid = FIELD_GET(MT_RXWI_CTL_WCID, ctl);
+ sta = mt76x02_rx_get_sta(&dev->mt76, wcid);
+ status->wcid = mt76x02_rx_get_sta_wcid(sta, unicast);
+
+ len = FIELD_GET(MT_RXWI_CTL_MPDU_LEN, ctl);
+ pn_len = FIELD_GET(MT_RXINFO_PN_LEN, rxinfo);
+ if (pn_len) {
+ int offset = ieee80211_get_hdrlen_from_skb(skb) + pad_len;
+ u8 *data = skb->data + offset;
+
+ status->iv[0] = data[7];
+ status->iv[1] = data[6];
+ status->iv[2] = data[5];
+ status->iv[3] = data[4];
+ status->iv[4] = data[1];
+ status->iv[5] = data[0];
+
+ /*
+ * Driver CCMP validation can't deal with fragments.
+ * Let mac80211 take care of it.
+ */
+ if (rxinfo & MT_RXINFO_FRAG) {
+ status->flag &= ~RX_FLAG_IV_STRIPPED;
+ } else {
+ pad_len += pn_len << 2;
+ len -= pn_len << 2;
+ }
+ }
+
+ mt76x02_remove_hdr_pad(skb, pad_len);
+
+ if ((rxinfo & MT_RXINFO_BA) && !(rxinfo & MT_RXINFO_NULL))
+ status->aggr = true;
+
+ if (WARN_ON_ONCE(len > skb->len))
+ return -EINVAL;
+
+ pskb_trim(skb, len);
+
+ status->chains = BIT(0);
+ signal = mt76x02_mac_get_rssi(dev, rxwi->rssi[0], 0);
+ for (i = 1; i < nstreams; i++) {
+ status->chains |= BIT(i);
+ status->chain_signal[i] = mt76x02_mac_get_rssi(dev,
+ rxwi->rssi[i],
+ i);
+ signal = max_t(s8, signal, status->chain_signal[i]);
+ }
+ status->signal = signal;
+ status->freq = dev->mt76.chandef.chan->center_freq;
+ status->band = dev->mt76.chandef.chan->band;
+
+ status->tid = FIELD_GET(MT_RXWI_TID, tid_sn);
+ status->seqno = FIELD_GET(MT_RXWI_SN, tid_sn);
+
+ if (sta) {
+ ewma_signal_add(&sta->rssi, status->signal);
+ sta->inactive_count = 0;
+ }
+
+ return mt76x02_mac_process_rate(status, rate);
+}
+
+void mt76x02_mac_poll_tx_status(struct mt76x02_dev *dev, bool irq)
+{
+ struct mt76x02_tx_status stat = {};
+ unsigned long flags;
+ u8 update = 1;
+ bool ret;
+
+ if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state))
+ return;
+
+ trace_mac_txstat_poll(dev);
+
+ while (!irq || !kfifo_is_full(&dev->txstatus_fifo)) {
+ spin_lock_irqsave(&dev->mt76.mmio.irq_lock, flags);
+ ret = mt76x02_mac_load_tx_status(&dev->mt76, &stat);
+ spin_unlock_irqrestore(&dev->mt76.mmio.irq_lock, flags);
+
+ if (!ret)
+ break;
+
+ trace_mac_txstat_fetch(dev, &stat);
+
+ if (!irq) {
+ mt76x02_send_tx_status(&dev->mt76, &stat, &update);
+ continue;
+ }
+
+ kfifo_put(&dev->txstatus_fifo, stat);
+ }
+}
+EXPORT_SYMBOL_GPL(mt76x02_mac_poll_tx_status);
+
+static void
+mt76x02_mac_queue_txdone(struct mt76x02_dev *dev, struct sk_buff *skb,
+ void *txwi_ptr)
+{
+ struct mt76x02_tx_info *txi = mt76x02_skb_tx_info(skb);
+ struct mt76x02_txwi *txwi = txwi_ptr;
+
+ mt76x02_mac_poll_tx_status(dev, false);
+
+ txi->tries = 0;
+ txi->jiffies = jiffies;
+ txi->wcid = txwi->wcid;
+ txi->pktid = txwi->pktid;
+ trace_mac_txdone_add(dev, txwi->wcid, txwi->pktid);
+ mt76x02_tx_complete(&dev->mt76, skb);
+}
+
+void mt76x02_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
+ struct mt76_queue_entry *e, bool flush)
+{
+ struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
+
+ if (e->txwi)
+ mt76x02_mac_queue_txdone(dev, e->skb, &e->txwi->txwi);
+ else
+ dev_kfree_skb_any(e->skb);
+}
+EXPORT_SYMBOL_GPL(mt76x02_tx_complete_skb);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h
index 1a5da35702e6..4f7ee4620ab5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h
@@ -20,6 +20,8 @@
#include <linux/average.h>
+struct mt76x02_dev;
+
struct mt76x02_tx_status {
u8 valid:1;
u8 success:1;
@@ -40,6 +42,15 @@ struct mt76x02_vif {
struct mt76_wcid group_wcid;
};
+struct mt76x02_tx_info {
+ unsigned long jiffies;
+ u8 tries;
+
+ u8 wcid;
+ u8 pktid;
+ u8 retry;
+};
+
DECLARE_EWMA(signal, 10, 8);
struct mt76x02_sta {
@@ -165,7 +176,7 @@ static inline bool mt76x02_wait_for_mac(struct mt76_dev *dev)
for (i = 0; i < 500; i++) {
if (test_bit(MT76_REMOVED, &dev->state))
- return -EIO;
+ return false;
switch (dev->bus->rr(dev, MAC_CSR0)) {
case 0:
@@ -179,9 +190,15 @@ static inline bool mt76x02_wait_for_mac(struct mt76_dev *dev)
return false;
}
+static inline struct mt76x02_tx_info *
+mt76x02_skb_tx_info(struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+ return (void *)info->status.status_driver_data;
+}
+
void mt76x02_txq_init(struct mt76_dev *dev, struct ieee80211_txq *txq);
-void mt76x02_mac_fill_txwi(struct mt76x02_txwi *txwi, struct sk_buff *skb,
- struct ieee80211_sta *sta, int len, u8 nss);
enum mt76x02_cipher_type
mt76x02_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data);
@@ -193,13 +210,19 @@ void mt76x02_mac_wcid_setup(struct mt76_dev *dev, u8 idx, u8 vif_idx, u8 *mac);
void mt76x02_mac_wcid_set_drop(struct mt76_dev *dev, u8 idx, bool drop);
void mt76x02_mac_wcid_set_rate(struct mt76_dev *dev, struct mt76_wcid *wcid,
const struct ieee80211_tx_rate *rate);
-__le16
-mt76x02_mac_tx_rate_val(struct mt76_dev *dev,
- const struct ieee80211_tx_rate *rate, u8 *nss_val);
bool mt76x02_mac_load_tx_status(struct mt76_dev *dev,
struct mt76x02_tx_status *stat);
void mt76x02_send_tx_status(struct mt76_dev *dev,
struct mt76x02_tx_status *stat, u8 *update);
+int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
+ void *rxi);
int
mt76x02_mac_process_rate(struct mt76_rx_status *status, u16 rate);
+void mt76x02_mac_setaddr(struct mt76_dev *dev, u8 *addr);
+void mt76x02_mac_write_txwi(struct mt76_dev *dev, struct mt76x02_txwi *txwi,
+ struct sk_buff *skb, struct mt76_wcid *wcid,
+ struct ieee80211_sta *sta, int len);
+void mt76x02_mac_poll_tx_status(struct mt76x02_dev *dev, bool irq);
+void mt76x02_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
+ struct mt76_queue_entry *e, bool flush);
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c
index 5a2fba3462fd..6d565133b7af 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c
@@ -211,3 +211,16 @@ int mt76x02_mcu_cleanup(struct mt76_dev *dev)
return 0;
}
EXPORT_SYMBOL_GPL(mt76x02_mcu_cleanup);
+
+void mt76x02_set_ethtool_fwver(struct mt76_dev *dev,
+ const struct mt76x02_fw_header *h)
+{
+ u16 bld = le16_to_cpu(h->build_ver);
+ u16 ver = le16_to_cpu(h->fw_ver);
+
+ snprintf(dev->hw->wiphy->fw_version,
+ sizeof(dev->hw->wiphy->fw_version),
+ "%d.%d.%02d-b%x",
+ (ver >> 12) & 0xf, (ver >> 8) & 0xf, ver & 0xf, bld);
+}
+EXPORT_SYMBOL_GPL(mt76x02_set_ethtool_fwver);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h
index 2f5af3dad2bb..ce664f8b1c94 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h
@@ -15,7 +15,7 @@
*/
#ifndef __MT76x02_MCU_H
-#define __MT76x0x_MCU_H
+#define __MT76x02_MCU_H
#define MT_MCU_RESET_CTL 0x070C
#define MT_MCU_INT_LEVEL 0x0718
@@ -27,6 +27,15 @@
#define MT_INBAND_PACKET_MAX_LEN 192
#define MT_MCU_MEMMAP_WLAN 0x410000
+#define MT_MCU_PCIE_REMAP_BASE4 0x074C
+
+#define MT_MCU_SEMAPHORE_00 0x07B0
+#define MT_MCU_SEMAPHORE_01 0x07B4
+#define MT_MCU_SEMAPHORE_02 0x07B8
+#define MT_MCU_SEMAPHORE_03 0x07BC
+
+#define MT_MCU_ILM_ADDR 0x80000
+
enum mcu_cmd {
CMD_FUN_SET_OP = 1,
CMD_LOAD_CR = 2,
@@ -96,5 +105,7 @@ int mt76x02_mcu_function_select(struct mt76_dev *dev,
u32 val, bool wait_resp);
int mt76x02_mcu_set_radio_state(struct mt76_dev *dev, bool on,
bool wait_resp);
+void mt76x02_set_ethtool_fwver(struct mt76_dev *dev,
+ const struct mt76x02_fw_header *h);
#endif /* __MT76x02_MCU_H */
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
new file mode 100644
index 000000000000..1b945079c802
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
+ * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/irq.h>
+
+#include "mt76x02.h"
+#include "mt76x02_trace.h"
+
+static int
+mt76x02_init_tx_queue(struct mt76x02_dev *dev, struct mt76_queue *q,
+ int idx, int n_desc)
+{
+ int ret;
+
+ q->regs = dev->mt76.mmio.regs + MT_TX_RING_BASE + idx * MT_RING_SIZE;
+ q->ndesc = n_desc;
+ q->hw_idx = idx;
+
+ ret = mt76_queue_alloc(dev, q);
+ if (ret)
+ return ret;
+
+ mt76x02_irq_enable(dev, MT_INT_TX_DONE(idx));
+
+ return 0;
+}
+
+static int
+mt76x02_init_rx_queue(struct mt76x02_dev *dev, struct mt76_queue *q,
+ int idx, int n_desc, int bufsize)
+{
+ int ret;
+
+ q->regs = dev->mt76.mmio.regs + MT_RX_RING_BASE + idx * MT_RING_SIZE;
+ q->ndesc = n_desc;
+ q->buf_size = bufsize;
+
+ ret = mt76_queue_alloc(dev, q);
+ if (ret)
+ return ret;
+
+ mt76x02_irq_enable(dev, MT_INT_RX_DONE(idx));
+
+ return 0;
+}
+
+static void mt76x02_process_tx_status_fifo(struct mt76x02_dev *dev)
+{
+ struct mt76x02_tx_status stat;
+ u8 update = 1;
+
+ while (kfifo_get(&dev->txstatus_fifo, &stat))
+ mt76x02_send_tx_status(&dev->mt76, &stat, &update);
+}
+
+static void mt76x02_tx_tasklet(unsigned long data)
+{
+ struct mt76x02_dev *dev = (struct mt76x02_dev *)data;
+ int i;
+
+ mt76x02_process_tx_status_fifo(dev);
+
+ for (i = MT_TXQ_MCU; i >= 0; i--)
+ mt76_queue_tx_cleanup(dev, i, false);
+
+ mt76x02_mac_poll_tx_status(dev, false);
+ mt76x02_irq_enable(dev, MT_INT_TX_DONE_ALL);
+}
+
+int mt76x02_dma_init(struct mt76x02_dev *dev)
+{
+ struct mt76_txwi_cache __maybe_unused *t;
+ int i, ret, fifo_size;
+ struct mt76_queue *q;
+ void *status_fifo;
+
+ BUILD_BUG_ON(sizeof(t->txwi) < sizeof(struct mt76x02_txwi));
+ BUILD_BUG_ON(sizeof(struct mt76x02_rxwi) > MT_RX_HEADROOM);
+
+ fifo_size = roundup_pow_of_two(32 * sizeof(struct mt76x02_tx_status));
+ status_fifo = devm_kzalloc(dev->mt76.dev, fifo_size, GFP_KERNEL);
+ if (!status_fifo)
+ return -ENOMEM;
+
+ tasklet_init(&dev->tx_tasklet, mt76x02_tx_tasklet, (unsigned long) dev);
+ kfifo_init(&dev->txstatus_fifo, status_fifo, fifo_size);
+
+ mt76_dma_attach(&dev->mt76);
+
+ mt76_wr(dev, MT_WPDMA_RST_IDX, ~0);
+
+ for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+ ret = mt76x02_init_tx_queue(dev, &dev->mt76.q_tx[i],
+ mt76_ac_to_hwq(i),
+ MT_TX_RING_SIZE);
+ if (ret)
+ return ret;
+ }
+
+ ret = mt76x02_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_PSD],
+ MT_TX_HW_QUEUE_MGMT, MT_TX_RING_SIZE);
+ if (ret)
+ return ret;
+
+ ret = mt76x02_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU],
+ MT_TX_HW_QUEUE_MCU, MT_MCU_RING_SIZE);
+ if (ret)
+ return ret;
+
+ ret = mt76x02_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MCU], 1,
+ MT_MCU_RING_SIZE, MT_RX_BUF_SIZE);
+ if (ret)
+ return ret;
+
+ q = &dev->mt76.q_rx[MT_RXQ_MAIN];
+ q->buf_offset = MT_RX_HEADROOM - sizeof(struct mt76x02_rxwi);
+ ret = mt76x02_init_rx_queue(dev, q, 0, MT76X02_RX_RING_SIZE,
+ MT_RX_BUF_SIZE);
+ if (ret)
+ return ret;
+
+ return mt76_init_queues(dev);
+}
+EXPORT_SYMBOL_GPL(mt76x02_dma_init);
+
+void mt76x02_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
+{
+ struct mt76x02_dev *dev;
+
+ dev = container_of(mdev, struct mt76x02_dev, mt76);
+ mt76x02_irq_enable(dev, MT_INT_RX_DONE(q));
+}
+EXPORT_SYMBOL_GPL(mt76x02_rx_poll_complete);
+
+irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance)
+{
+ struct mt76x02_dev *dev = dev_instance;
+ u32 intr;
+
+ intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
+ mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
+
+ if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state))
+ return IRQ_NONE;
+
+ trace_dev_irq(dev, intr, dev->mt76.mmio.irqmask);
+
+ intr &= dev->mt76.mmio.irqmask;
+
+ if (intr & MT_INT_TX_DONE_ALL) {
+ mt76x02_irq_disable(dev, MT_INT_TX_DONE_ALL);
+ tasklet_schedule(&dev->tx_tasklet);
+ }
+
+ if (intr & MT_INT_RX_DONE(0)) {
+ mt76x02_irq_disable(dev, MT_INT_RX_DONE(0));
+ napi_schedule(&dev->mt76.napi[0]);
+ }
+
+ if (intr & MT_INT_RX_DONE(1)) {
+ mt76x02_irq_disable(dev, MT_INT_RX_DONE(1));
+ napi_schedule(&dev->mt76.napi[1]);
+ }
+
+ if (intr & MT_INT_PRE_TBTT)
+ tasklet_schedule(&dev->pre_tbtt_tasklet);
+
+ /* send buffered multicast frames now */
+ if (intr & MT_INT_TBTT)
+ mt76_queue_kick(dev, &dev->mt76.q_tx[MT_TXQ_PSD]);
+
+ if (intr & MT_INT_TX_STAT) {
+ mt76x02_mac_poll_tx_status(dev, true);
+ tasklet_schedule(&dev->tx_tasklet);
+ }
+
+ if (intr & MT_INT_GPTIMER) {
+ mt76x02_irq_disable(dev, MT_INT_GPTIMER);
+ tasklet_schedule(&dev->dfs_pd.dfs_tasklet);
+ }
+
+ return IRQ_HANDLED;
+}
+EXPORT_SYMBOL_GPL(mt76x02_irq_handler);
+
+void mt76x02_set_irq_mask(struct mt76x02_dev *dev, u32 clear, u32 set)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->mt76.mmio.irq_lock, flags);
+ dev->mt76.mmio.irqmask &= ~clear;
+ dev->mt76.mmio.irqmask |= set;
+ mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask);
+ spin_unlock_irqrestore(&dev->mt76.mmio.irq_lock, flags);
+}
+EXPORT_SYMBOL_GPL(mt76x02_set_irq_mask);
+
+static void mt76x02_dma_enable(struct mt76x02_dev *dev)
+{
+ u32 val;
+
+ mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX);
+ mt76x02_wait_for_wpdma(&dev->mt76, 1000);
+ usleep_range(50, 100);
+
+ val = FIELD_PREP(MT_WPDMA_GLO_CFG_DMA_BURST_SIZE, 3) |
+ MT_WPDMA_GLO_CFG_TX_DMA_EN |
+ MT_WPDMA_GLO_CFG_RX_DMA_EN;
+ mt76_set(dev, MT_WPDMA_GLO_CFG, val);
+ mt76_clear(dev, MT_WPDMA_GLO_CFG,
+ MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);
+}
+EXPORT_SYMBOL_GPL(mt76x02_dma_enable);
+
+void mt76x02_dma_cleanup(struct mt76x02_dev *dev)
+{
+ tasklet_kill(&dev->tx_tasklet);
+ mt76_dma_cleanup(&dev->mt76);
+}
+EXPORT_SYMBOL_GPL(mt76x02_dma_cleanup);
+
+void mt76x02_dma_disable(struct mt76x02_dev *dev)
+{
+ u32 val = mt76_rr(dev, MT_WPDMA_GLO_CFG);
+
+ val &= MT_WPDMA_GLO_CFG_DMA_BURST_SIZE |
+ MT_WPDMA_GLO_CFG_BIG_ENDIAN |
+ MT_WPDMA_GLO_CFG_HDR_SEG_LEN;
+ val |= MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE;
+ mt76_wr(dev, MT_WPDMA_GLO_CFG, val);
+}
+EXPORT_SYMBOL_GPL(mt76x02_dma_disable);
+
+void mt76x02_mac_start(struct mt76x02_dev *dev)
+{
+ mt76x02_dma_enable(dev);
+ mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter);
+ mt76_wr(dev, MT_MAC_SYS_CTRL,
+ MT_MAC_SYS_CTRL_ENABLE_TX |
+ MT_MAC_SYS_CTRL_ENABLE_RX);
+ mt76x02_irq_enable(dev,
+ MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
+ MT_INT_TX_STAT);
+}
+EXPORT_SYMBOL_GPL(mt76x02_mac_start);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c
new file mode 100644
index 000000000000..d31ce1d7b689
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
+ * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+
+#include "mt76.h"
+#include "mt76x02_phy.h"
+#include "mt76x02_mac.h"
+
+void mt76x02_phy_set_rxpath(struct mt76_dev *dev)
+{
+ u32 val;
+
+ val = __mt76_rr(dev, MT_BBP(AGC, 0));
+ val &= ~BIT(4);
+
+ switch (dev->chainmask & 0xf) {
+ case 2:
+ val |= BIT(3);
+ break;
+ default:
+ val &= ~BIT(3);
+ break;
+ }
+
+ __mt76_wr(dev, MT_BBP(AGC, 0), val);
+ mb();
+ val = __mt76_rr(dev, MT_BBP(AGC, 0));
+}
+EXPORT_SYMBOL_GPL(mt76x02_phy_set_rxpath);
+
+void mt76x02_phy_set_txdac(struct mt76_dev *dev)
+{
+ int txpath;
+
+ txpath = (dev->chainmask >> 8) & 0xf;
+ switch (txpath) {
+ case 2:
+ __mt76_set(dev, MT_BBP(TXBE, 5), 0x3);
+ break;
+ default:
+ __mt76_clear(dev, MT_BBP(TXBE, 5), 0x3);
+ break;
+ }
+}
+EXPORT_SYMBOL_GPL(mt76x02_phy_set_txdac);
+
+static u32
+mt76x02_tx_power_mask(u8 v1, u8 v2, u8 v3, u8 v4)
+{
+ u32 val = 0;
+
+ val |= (v1 & (BIT(6) - 1)) << 0;
+ val |= (v2 & (BIT(6) - 1)) << 8;
+ val |= (v3 & (BIT(6) - 1)) << 16;
+ val |= (v4 & (BIT(6) - 1)) << 24;
+ return val;
+}
+
+int mt76x02_get_max_rate_power(struct mt76_rate_power *r)
+{
+ s8 ret = 0;
+ int i;
+
+ for (i = 0; i < sizeof(r->all); i++)
+ ret = max(ret, r->all[i]);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(mt76x02_get_max_rate_power);
+
+void mt76x02_limit_rate_power(struct mt76_rate_power *r, int limit)
+{
+ int i;
+
+ for (i = 0; i < sizeof(r->all); i++)
+ if (r->all[i] > limit)
+ r->all[i] = limit;
+}
+EXPORT_SYMBOL_GPL(mt76x02_limit_rate_power);
+
+void mt76x02_add_rate_power_offset(struct mt76_rate_power *r, int offset)
+{
+ int i;
+
+ for (i = 0; i < sizeof(r->all); i++)
+ r->all[i] += offset;
+}
+EXPORT_SYMBOL_GPL(mt76x02_add_rate_power_offset);
+
+void mt76x02_phy_set_txpower(struct mt76_dev *dev, int txp_0, int txp_1)
+{
+ struct mt76_rate_power *t = &dev->rate_power;
+
+ __mt76_rmw_field(dev, MT_TX_ALC_CFG_0, MT_TX_ALC_CFG_0_CH_INIT_0,
+ txp_0);
+ __mt76_rmw_field(dev, MT_TX_ALC_CFG_0, MT_TX_ALC_CFG_0_CH_INIT_1,
+ txp_1);
+
+ __mt76_wr(dev, MT_TX_PWR_CFG_0,
+ mt76x02_tx_power_mask(t->cck[0], t->cck[2], t->ofdm[0],
+ t->ofdm[2]));
+ __mt76_wr(dev, MT_TX_PWR_CFG_1,
+ mt76x02_tx_power_mask(t->ofdm[4], t->ofdm[6], t->ht[0],
+ t->ht[2]));
+ __mt76_wr(dev, MT_TX_PWR_CFG_2,
+ mt76x02_tx_power_mask(t->ht[4], t->ht[6], t->ht[8],
+ t->ht[10]));
+ __mt76_wr(dev, MT_TX_PWR_CFG_3,
+ mt76x02_tx_power_mask(t->ht[12], t->ht[14], t->stbc[0],
+ t->stbc[2]));
+ __mt76_wr(dev, MT_TX_PWR_CFG_4,
+ mt76x02_tx_power_mask(t->stbc[4], t->stbc[6], 0, 0));
+ __mt76_wr(dev, MT_TX_PWR_CFG_7,
+ mt76x02_tx_power_mask(t->ofdm[7], t->vht[8], t->ht[7],
+ t->vht[9]));
+ __mt76_wr(dev, MT_TX_PWR_CFG_8,
+ mt76x02_tx_power_mask(t->ht[14], 0, t->vht[8], t->vht[9]));
+ __mt76_wr(dev, MT_TX_PWR_CFG_9,
+ mt76x02_tx_power_mask(t->ht[7], 0, t->stbc[8], t->stbc[9]));
+}
+EXPORT_SYMBOL_GPL(mt76x02_phy_set_txpower);
+
+int mt76x02_phy_get_min_avg_rssi(struct mt76_dev *dev)
+{
+ struct mt76x02_sta *sta;
+ struct mt76_wcid *wcid;
+ int i, j, min_rssi = 0;
+ s8 cur_rssi;
+
+ local_bh_disable();
+ rcu_read_lock();
+
+ for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) {
+ unsigned long mask = dev->wcid_mask[i];
+
+ if (!mask)
+ continue;
+
+ for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1) {
+ if (!(mask & 1))
+ continue;
+
+ wcid = rcu_dereference(dev->wcid[j]);
+ if (!wcid)
+ continue;
+
+ sta = container_of(wcid, struct mt76x02_sta, wcid);
+ spin_lock(&dev->rx_lock);
+ if (sta->inactive_count++ < 5)
+ cur_rssi = ewma_signal_read(&sta->rssi);
+ else
+ cur_rssi = 0;
+ spin_unlock(&dev->rx_lock);
+
+ if (cur_rssi < min_rssi)
+ min_rssi = cur_rssi;
+ }
+ }
+
+ rcu_read_unlock();
+ local_bh_enable();
+
+ if (!min_rssi)
+ return -75;
+
+ return min_rssi;
+}
+EXPORT_SYMBOL_GPL(mt76x02_phy_get_min_avg_rssi);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h
new file mode 100644
index 000000000000..e70ea6eeb077
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __MT76x02_PHY_H
+#define __MT76x02_PHY_H
+
+#include "mt76x02_regs.h"
+
+void mt76x02_add_rate_power_offset(struct mt76_rate_power *r, int offset);
+void mt76x02_phy_set_txpower(struct mt76_dev *dev, int txp_0, int txp_2);
+void mt76x02_limit_rate_power(struct mt76_rate_power *r, int limit);
+int mt76x02_get_max_rate_power(struct mt76_rate_power *r);
+void mt76x02_phy_set_rxpath(struct mt76_dev *dev);
+void mt76x02_phy_set_txdac(struct mt76_dev *dev);
+int mt76x02_phy_get_min_avg_rssi(struct mt76_dev *dev);
+
+#endif /* __MT76x02_PHY_H */
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_trace.c b/drivers/net/wireless/mediatek/mt76/mt76x02_trace.c
index a09f117848d6..5b42d2c87937 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_trace.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_trace.c
@@ -18,6 +18,6 @@
#ifndef __CHECKER__
#define CREATE_TRACE_POINTS
-#include "mt76x2_trace.h"
+#include "mt76x02_trace.h"
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_trace.h b/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h
index eb5afeaefa44..713f12d3c8de 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_trace.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h
@@ -14,14 +14,14 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#if !defined(__MT76x2_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
-#define __MT76x2_TRACE_H
+#if !defined(__MT76x02_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __MT76x02_TRACE_H
#include <linux/tracepoint.h>
-#include "mt76x2.h"
+#include "mt76x02.h"
#undef TRACE_SYSTEM
-#define TRACE_SYSTEM mt76x2
+#define TRACE_SYSTEM mt76x02
#define MAXNAME 32
#define DEV_ENTRY __array(char, wiphy_name, 32)
@@ -35,7 +35,7 @@
#define TXID_PR_ARG __entry->wcid, __entry->pktid
DECLARE_EVENT_CLASS(dev_evt,
- TP_PROTO(struct mt76x2_dev *dev),
+ TP_PROTO(struct mt76x02_dev *dev),
TP_ARGS(dev),
TP_STRUCT__entry(
DEV_ENTRY
@@ -47,7 +47,7 @@ DECLARE_EVENT_CLASS(dev_evt,
);
DECLARE_EVENT_CLASS(dev_txid_evt,
- TP_PROTO(struct mt76x2_dev *dev, u8 wcid, u8 pktid),
+ TP_PROTO(struct mt76x02_dev *dev, u8 wcid, u8 pktid),
TP_ARGS(dev, wcid, pktid),
TP_STRUCT__entry(
DEV_ENTRY
@@ -63,18 +63,18 @@ DECLARE_EVENT_CLASS(dev_txid_evt,
)
);
-DEFINE_EVENT(dev_evt, mac_txstat_poll,
- TP_PROTO(struct mt76x2_dev *dev),
- TP_ARGS(dev)
-);
-
DEFINE_EVENT(dev_txid_evt, mac_txdone_add,
- TP_PROTO(struct mt76x2_dev *dev, u8 wcid, u8 pktid),
+ TP_PROTO(struct mt76x02_dev *dev, u8 wcid, u8 pktid),
TP_ARGS(dev, wcid, pktid)
);
+DEFINE_EVENT(dev_evt, mac_txstat_poll,
+ TP_PROTO(struct mt76x02_dev *dev),
+ TP_ARGS(dev)
+);
+
TRACE_EVENT(mac_txstat_fetch,
- TP_PROTO(struct mt76x2_dev *dev,
+ TP_PROTO(struct mt76x02_dev *dev,
struct mt76x02_tx_status *stat),
TP_ARGS(dev, stat),
@@ -110,9 +110,8 @@ TRACE_EVENT(mac_txstat_fetch,
)
);
-
TRACE_EVENT(dev_irq,
- TP_PROTO(struct mt76x2_dev *dev, u32 val, u32 mask),
+ TP_PROTO(struct mt76x02_dev *dev, u32 val, u32 mask),
TP_ARGS(dev, val, mask),
@@ -139,6 +138,6 @@ TRACE_EVENT(dev_irq,
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH .
#undef TRACE_INCLUDE_FILE
-#define TRACE_INCLUDE_FILE mt76x2_trace
+#define TRACE_INCLUDE_FILE mt76x02_trace
#include <trace/define_trace.h>
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
new file mode 100644
index 000000000000..830377221739
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
+ * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+
+#include "mt76x02.h"
+
+void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
+ struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct mt76x02_dev *dev = hw->priv;
+ struct ieee80211_vif *vif = info->control.vif;
+ struct mt76_wcid *wcid = &dev->mt76.global_wcid;
+
+ if (control->sta) {
+ struct mt76x02_sta *msta;
+
+ msta = (struct mt76x02_sta *)control->sta->drv_priv;
+ wcid = &msta->wcid;
+ /* sw encrypted frames */
+ if (!info->control.hw_key && wcid->hw_key_idx != 0xff)
+ control->sta = NULL;
+ }
+
+ if (vif && !control->sta) {
+ struct mt76x02_vif *mvif;
+
+ mvif = (struct mt76x02_vif *)vif->drv_priv;
+ wcid = &mvif->group_wcid;
+ }
+
+ mt76_tx(&dev->mt76, control->sta, wcid, skb);
+}
+EXPORT_SYMBOL_GPL(mt76x02_tx);
+
+void mt76x02_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+ struct sk_buff *skb)
+{
+ struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
+ void *rxwi = skb->data;
+
+ if (q == MT_RXQ_MCU) {
+ /* this is used just by mmio code */
+ skb_queue_tail(&mdev->mmio.mcu.res_q, skb);
+ wake_up(&mdev->mmio.mcu.wait);
+ return;
+ }
+
+ skb_pull(skb, sizeof(struct mt76x02_rxwi));
+ if (mt76x02_mac_process_rx(dev, skb, rxwi)) {
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ mt76_rx(mdev, q, skb);
+}
+EXPORT_SYMBOL_GPL(mt76x02_queue_rx_skb);
+
+s8 mt76x02_tx_get_max_txpwr_adj(struct mt76_dev *dev,
+ const struct ieee80211_tx_rate *rate)
+{
+ s8 max_txpwr;
+
+ if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
+ u8 mcs = ieee80211_rate_get_vht_mcs(rate);
+
+ if (mcs == 8 || mcs == 9) {
+ max_txpwr = dev->rate_power.vht[8];
+ } else {
+ u8 nss, idx;
+
+ nss = ieee80211_rate_get_vht_nss(rate);
+ idx = ((nss - 1) << 3) + mcs;
+ max_txpwr = dev->rate_power.ht[idx & 0xf];
+ }
+ } else if (rate->flags & IEEE80211_TX_RC_MCS) {
+ max_txpwr = dev->rate_power.ht[rate->idx & 0xf];
+ } else {
+ enum nl80211_band band = dev->chandef.chan->band;
+
+ if (band == NL80211_BAND_2GHZ) {
+ const struct ieee80211_rate *r;
+ struct wiphy *wiphy = dev->hw->wiphy;
+ struct mt76_rate_power *rp = &dev->rate_power;
+
+ r = &wiphy->bands[band]->bitrates[rate->idx];
+ if (r->flags & IEEE80211_RATE_SHORT_PREAMBLE)
+ max_txpwr = rp->cck[r->hw_value & 0x3];
+ else
+ max_txpwr = rp->ofdm[r->hw_value & 0x7];
+ } else {
+ max_txpwr = dev->rate_power.ofdm[rate->idx & 0x7];
+ }
+ }
+
+ return max_txpwr;
+}
+EXPORT_SYMBOL_GPL(mt76x02_tx_get_max_txpwr_adj);
+
+s8 mt76x02_tx_get_txpwr_adj(struct mt76_dev *mdev, s8 txpwr, s8 max_txpwr_adj)
+{
+ struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
+
+ txpwr = min_t(s8, txpwr, dev->mt76.txpower_conf);
+ txpwr -= (dev->target_power + dev->target_power_delta[0]);
+ txpwr = min_t(s8, txpwr, max_txpwr_adj);
+
+ if (!dev->enable_tpc)
+ return 0;
+ else if (txpwr >= 0)
+ return min_t(s8, txpwr, 7);
+ else
+ return (txpwr < -16) ? 8 : (txpwr + 32) / 2;
+}
+EXPORT_SYMBOL_GPL(mt76x02_tx_get_txpwr_adj);
+
+void mt76x02_tx_set_txpwr_auto(struct mt76x02_dev *dev, s8 txpwr)
+{
+ s8 txpwr_adj;
+
+ txpwr_adj = mt76x02_tx_get_txpwr_adj(&dev->mt76, txpwr,
+ dev->mt76.rate_power.ofdm[4]);
+ mt76_rmw_field(dev, MT_PROT_AUTO_TX_CFG,
+ MT_PROT_AUTO_TX_CFG_PROT_PADJ, txpwr_adj);
+ mt76_rmw_field(dev, MT_PROT_AUTO_TX_CFG,
+ MT_PROT_AUTO_TX_CFG_AUTO_PADJ, txpwr_adj);
+}
+EXPORT_SYMBOL_GPL(mt76x02_tx_set_txpwr_auto);
+
+void mt76x02_tx_complete(struct mt76_dev *dev, struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+ if (info->flags & IEEE80211_TX_CTL_AMPDU) {
+ ieee80211_free_txskb(dev->hw, skb);
+ } else {
+ ieee80211_tx_info_clear_status(info);
+ info->status.rates[0].idx = -1;
+ info->flags |= IEEE80211_TX_STAT_ACK;
+ ieee80211_tx_status(dev->hw, skb);
+ }
+}
+EXPORT_SYMBOL_GPL(mt76x02_tx_complete);
+
+bool mt76x02_tx_status_data(struct mt76_dev *dev, u8 *update)
+{
+ struct mt76x02_tx_status stat;
+
+ if (!mt76x02_mac_load_tx_status(dev, &stat))
+ return false;
+
+ mt76x02_send_tx_status(dev, &stat, update);
+
+ return true;
+}
+EXPORT_SYMBOL_GPL(mt76x02_tx_status_data);
+
+int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi,
+ struct sk_buff *skb, struct mt76_queue *q,
+ struct mt76_wcid *wcid, struct ieee80211_sta *sta,
+ u32 *tx_info)
+{
+ struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ int qsel = MT_QSEL_EDCA;
+ int ret;
+
+ if (q == &dev->mt76.q_tx[MT_TXQ_PSD] && wcid && wcid->idx < 128)
+ mt76x02_mac_wcid_set_drop(&dev->mt76, wcid->idx, false);
+
+ mt76x02_mac_write_txwi(mdev, txwi, skb, wcid, sta, skb->len);
+
+ ret = mt76x02_insert_hdr_pad(skb);
+ if (ret < 0)
+ return ret;
+
+ if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
+ qsel = MT_QSEL_MGMT;
+
+ *tx_info = FIELD_PREP(MT_TXD_INFO_QSEL, qsel) |
+ MT_TXD_INFO_80211;
+
+ if (!wcid || wcid->hw_key_idx == 0xff || wcid->sw_iv)
+ *tx_info |= MT_TXD_INFO_WIV;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mt76x02_tx_prepare_skb);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h b/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h
index 2482f9761fcd..6b2138328eb2 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h
@@ -15,7 +15,7 @@
*/
#ifndef __MT76x02_USB_H
-#define __MT76x0x_USB_H
+#define __MT76x02_USB_H
#include "mt76.h"
@@ -25,5 +25,10 @@ int mt76x02u_mcu_fw_send_data(struct mt76_dev *dev, const void *data,
int data_len, u32 max_payload, u32 offset);
int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags);
-int mt76x02u_set_txinfo(struct sk_buff *skb, struct mt76_wcid *wcid, u8 ep);
+int mt76x02u_tx_prepare_skb(struct mt76_dev *dev, void *data,
+ struct sk_buff *skb, struct mt76_queue *q,
+ struct mt76_wcid *wcid, struct ieee80211_sta *sta,
+ u32 *tx_info);
+void mt76x02u_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
+ struct mt76_queue_entry *e, bool flush);
#endif /* __MT76x02_USB_H */
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
index 235b1bc5a367..7c6c973af386 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
@@ -14,8 +14,36 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include "mt76.h"
-#include "mt76x02_dma.h"
+#include "mt76x02.h"
+
+static void mt76x02u_remove_dma_hdr(struct sk_buff *skb)
+{
+ int hdr_len;
+
+ skb_pull(skb, sizeof(struct mt76x02_txwi) + MT_DMA_HDR_LEN);
+ hdr_len = ieee80211_get_hdrlen_from_skb(skb);
+ if (hdr_len % 4)
+ mt76x02_remove_hdr_pad(skb, 2);
+}
+
+void mt76x02u_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
+ struct mt76_queue_entry *e, bool flush)
+{
+ mt76x02u_remove_dma_hdr(e->skb);
+ mt76x02_tx_complete(mdev, e->skb);
+}
+EXPORT_SYMBOL_GPL(mt76x02u_tx_complete_skb);
+
+static int mt76x02u_check_skb_rooms(struct sk_buff *skb)
+{
+ int hdr_len = ieee80211_get_hdrlen_from_skb(skb);
+ u32 need_head;
+
+ need_head = sizeof(struct mt76x02_txwi) + MT_DMA_HDR_LEN;
+ if (hdr_len % 4)
+ need_head += 2;
+ return skb_cow(skb, need_head);
+}
int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags)
{
@@ -43,14 +71,15 @@ int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags)
}
if (unlikely(pad)) {
- if (__skb_pad(last, pad, true))
+ if (skb_pad(last, pad))
return -ENOMEM;
__skb_put(last, pad);
}
return 0;
}
-int mt76x02u_set_txinfo(struct sk_buff *skb, struct mt76_wcid *wcid, u8 ep)
+static int
+mt76x02u_set_txinfo(struct sk_buff *skb, struct mt76_wcid *wcid, u8 ep)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
enum mt76_qsel qsel;
@@ -69,4 +98,24 @@ int mt76x02u_set_txinfo(struct sk_buff *skb, struct mt76_wcid *wcid, u8 ep)
return mt76x02u_skb_dma_info(skb, WLAN_PORT, flags);
}
-EXPORT_SYMBOL_GPL(mt76x02u_set_txinfo);
+
+int mt76x02u_tx_prepare_skb(struct mt76_dev *dev, void *data,
+ struct sk_buff *skb, struct mt76_queue *q,
+ struct mt76_wcid *wcid, struct ieee80211_sta *sta,
+ u32 *tx_info)
+{
+ struct mt76x02_txwi *txwi;
+ int err, len = skb->len;
+
+ err = mt76x02u_check_skb_rooms(skb);
+ if (err < 0)
+ return -ENOMEM;
+
+ mt76x02_insert_hdr_pad(skb);
+
+ txwi = skb_push(skb, sizeof(struct mt76x02_txwi));
+ mt76x02_mac_write_txwi(dev, txwi, skb, wcid, sta, len);
+
+ return mt76x02u_set_txinfo(skb, wcid, q2ep(q->hw_idx));
+}
+EXPORT_SYMBOL_GPL(mt76x02u_tx_prepare_skb);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c
index b39a4d7d71cc..cb5f073f08af 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/module.h>
#include <linux/firmware.h>
#include "mt76.h"
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
index 4ecfb75f3f7d..5851ab6b7e26 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -15,10 +15,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include "mt76.h"
-#include "mt76x02_dma.h"
-#include "mt76x02_regs.h"
-#include "mt76x02_mac.h"
+#include <linux/module.h>
+#include "mt76x02.h"
#define CCK_RATE(_idx, _rate) { \
.bitrate = _rate, \
@@ -372,9 +370,7 @@ void mt76x02_sta_rate_tbl_update(struct ieee80211_hw *hw,
rate.idx = rates->rate[0].idx;
rate.flags = rates->rate[0].flags;
mt76x02_mac_wcid_set_rate(dev, &msta->wcid, &rate);
-
- if (dev->drv && dev->drv->get_max_txpwr_adj)
- msta->wcid.max_txpwr_adj = dev->drv->get_max_txpwr_adj(dev, &rate);
+ msta->wcid.max_txpwr_adj = mt76x02_tx_get_max_txpwr_adj(dev, &rate);
}
EXPORT_SYMBOL_GPL(mt76x02_sta_rate_tbl_update);
@@ -407,50 +403,42 @@ void mt76x02_remove_hdr_pad(struct sk_buff *skb, int len)
}
EXPORT_SYMBOL_GPL(mt76x02_remove_hdr_pad);
-static void mt76x02_remove_dma_hdr(struct sk_buff *skb)
-{
- int hdr_len;
-
- skb_pull(skb, sizeof(struct mt76x02_txwi) + MT_DMA_HDR_LEN);
- hdr_len = ieee80211_get_hdrlen_from_skb(skb);
- if (hdr_len % 4)
- mt76x02_remove_hdr_pad(skb, 2);
-}
+const u16 mt76x02_beacon_offsets[16] = {
+ /* 1024 byte per beacon */
+ 0xc000,
+ 0xc400,
+ 0xc800,
+ 0xcc00,
+ 0xd000,
+ 0xd400,
+ 0xd800,
+ 0xdc00,
+ /* BSS idx 8-15 not used for beacons */
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+};
+EXPORT_SYMBOL_GPL(mt76x02_beacon_offsets);
-void mt76x02_tx_complete(struct mt76_dev *dev, struct sk_buff *skb)
+void mt76x02_set_beacon_offsets(struct mt76_dev *dev)
{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ u16 val, base = MT_BEACON_BASE;
+ u32 regs[4] = {};
+ int i;
- if (info->flags & IEEE80211_TX_CTL_AMPDU) {
- ieee80211_free_txskb(dev->hw, skb);
- } else {
- ieee80211_tx_info_clear_status(info);
- info->status.rates[0].idx = -1;
- info->flags |= IEEE80211_TX_STAT_ACK;
- ieee80211_tx_status(dev->hw, skb);
+ for (i = 0; i < 16; i++) {
+ val = mt76x02_beacon_offsets[i] - base;
+ regs[i / 4] |= (val / 64) << (8 * (i % 4));
}
-}
-EXPORT_SYMBOL_GPL(mt76x02_tx_complete);
-
-void mt76x02_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
- struct mt76_queue_entry *e, bool flush)
-{
- mt76x02_remove_dma_hdr(e->skb);
- mt76x02_tx_complete(mdev, e->skb);
-}
-EXPORT_SYMBOL_GPL(mt76x02_tx_complete_skb);
-
-bool mt76x02_tx_status_data(struct mt76_dev *dev, u8 *update)
-{
- struct mt76x02_tx_status stat;
-
- if (!mt76x02_mac_load_tx_status(dev, &stat))
- return false;
-
- mt76x02_send_tx_status(dev, &stat, update);
- return true;
+ for (i = 0; i < 4; i++)
+ __mt76_wr(dev, MT_BCN_OFFSET(i), regs[i]);
}
-EXPORT_SYMBOL_GPL(mt76x02_tx_status_data);
+EXPORT_SYMBOL_GPL(mt76x02_set_beacon_offsets);
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.h b/drivers/net/wireless/mediatek/mt76/mt76x02_util.h
deleted file mode 100644
index 2ea9e68bfa3f..000000000000
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
- * Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef __MT76X02_UTIL_H
-#define __MT76X02_UTIL_H
-
-extern struct ieee80211_rate mt76x02_rates[12];
-
-void mt76x02_configure_filter(struct ieee80211_hw *hw,
- unsigned int changed_flags,
- unsigned int *total_flags, u64 multicast);
-int mt76x02_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
-int mt76x02_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
-
-void mt76x02_vif_init(struct mt76_dev *dev, struct ieee80211_vif *vif,
- unsigned int idx);
-int mt76x02_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
-void mt76x02_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
-
-int mt76x02_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_ampdu_params *params);
-int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
- struct ieee80211_vif *vif, struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key);
-int mt76x02_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- u16 queue, const struct ieee80211_tx_queue_params *params);
-void mt76x02_sta_rate_tbl_update(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
-int mt76x02_insert_hdr_pad(struct sk_buff *skb);
-void mt76x02_remove_hdr_pad(struct sk_buff *skb, int len);
-void mt76x02_tx_complete(struct mt76_dev *dev, struct sk_buff *skb);
-void mt76x02_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
- struct mt76_queue_entry *e, bool flush);
-bool mt76x02_tx_status_data(struct mt76_dev *dev, u8 *update);
-#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2.h b/drivers/net/wireless/mediatek/mt76/mt76x2.h
deleted file mode 100644
index 784962913d9a..000000000000
--- a/drivers/net/wireless/mediatek/mt76/mt76x2.h
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef __MT76x2_H
-#define __MT76x2_H
-
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/spinlock.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/bitops.h>
-#include <linux/kfifo.h>
-
-#define MT7662_FIRMWARE "mt7662.bin"
-#define MT7662_ROM_PATCH "mt7662_rom_patch.bin"
-#define MT7662_EEPROM_SIZE 512
-
-#define MT7662U_FIRMWARE "mediatek/mt7662u.bin"
-#define MT7662U_ROM_PATCH "mediatek/mt7662u_rom_patch.bin"
-
-#define MT76x2_RX_RING_SIZE 256
-#define MT_RX_HEADROOM 32
-
-#define MT_MAX_CHAINS 2
-
-#define MT_CALIBRATE_INTERVAL HZ
-
-#include "mt76.h"
-#include "mt76x02_regs.h"
-#include "mt76x2_mac.h"
-#include "mt76x2_dfs.h"
-
-struct mt76x2_rx_freq_cal {
- s8 high_gain[MT_MAX_CHAINS];
- s8 rssi_offset[MT_MAX_CHAINS];
- s8 lna_gain;
- u32 mcu_gain;
-};
-
-struct mt76x2_calibration {
- struct mt76x2_rx_freq_cal rx;
-
- u8 agc_gain_init[MT_MAX_CHAINS];
- u8 agc_gain_cur[MT_MAX_CHAINS];
-
- u16 false_cca;
- s8 avg_rssi_all;
- s8 agc_gain_adjust;
- s8 low_gain;
-
- u8 temp;
-
- bool init_cal_done;
- bool tssi_cal_done;
- bool tssi_comp_pending;
- bool dpd_cal_done;
- bool channel_cal_done;
-};
-
-struct mt76x2_dev {
- struct mt76_dev mt76; /* must be first */
-
- struct mac_address macaddr_list[8];
-
- struct mutex mutex;
-
- const u16 *beacon_offsets;
- int txpower_conf;
- int txpower_cur;
-
- u8 txdone_seq;
- DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x02_tx_status);
-
- struct sk_buff *rx_head;
-
- struct tasklet_struct tx_tasklet;
- struct tasklet_struct pre_tbtt_tasklet;
- struct delayed_work cal_work;
- struct delayed_work mac_work;
-
- u32 aggr_stats[32];
-
- spinlock_t irq_lock;
- u32 irqmask;
-
- struct sk_buff *beacons[8];
- u8 beacon_mask;
- u8 beacon_data_mask;
-
- u8 tbtt_count;
- u16 beacon_int;
-
- u16 chainmask;
-
- struct mt76x2_calibration cal;
-
- s8 target_power;
- s8 target_power_delta[2];
- struct mt76_rate_power rate_power;
- bool enable_tpc;
-
- u8 coverage_class;
- u8 slottime;
-
- struct mt76x2_dfs_pattern_detector dfs_pd;
-};
-
-static inline bool is_mt7612(struct mt76x2_dev *dev)
-{
- return mt76_chip(&dev->mt76) == 0x7612;
-}
-
-void mt76x2_set_irq_mask(struct mt76x2_dev *dev, u32 clear, u32 set);
-
-static inline bool mt76x2_channel_silent(struct mt76x2_dev *dev)
-{
- struct ieee80211_channel *chan = dev->mt76.chandef.chan;
-
- return ((chan->flags & IEEE80211_CHAN_RADAR) &&
- chan->dfs_state != NL80211_DFS_AVAILABLE);
-}
-
-static inline void mt76x2_irq_enable(struct mt76x2_dev *dev, u32 mask)
-{
- mt76x2_set_irq_mask(dev, 0, mask);
-}
-
-static inline void mt76x2_irq_disable(struct mt76x2_dev *dev, u32 mask)
-{
- mt76x2_set_irq_mask(dev, mask, 0);
-}
-
-static inline bool mt76x2_wait_for_bbp(struct mt76x2_dev *dev)
-{
- return mt76_poll_msec(dev, MT_MAC_STATUS,
- MT_MAC_STATUS_TX | MT_MAC_STATUS_RX,
- 0, 100);
-}
-
-static inline bool wait_for_wpdma(struct mt76x2_dev *dev)
-{
- return mt76_poll(dev, MT_WPDMA_GLO_CFG,
- MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
- MT_WPDMA_GLO_CFG_RX_DMA_BUSY,
- 0, 1000);
-}
-
-extern const struct ieee80211_ops mt76x2_ops;
-
-struct mt76x2_dev *mt76x2_alloc_device(struct device *pdev);
-int mt76x2_register_device(struct mt76x2_dev *dev);
-void mt76x2_init_debugfs(struct mt76x2_dev *dev);
-void mt76x2_init_device(struct mt76x2_dev *dev);
-
-irqreturn_t mt76x2_irq_handler(int irq, void *dev_instance);
-void mt76x2_phy_power_on(struct mt76x2_dev *dev);
-int mt76x2_init_hardware(struct mt76x2_dev *dev);
-void mt76x2_stop_hardware(struct mt76x2_dev *dev);
-int mt76x2_eeprom_init(struct mt76x2_dev *dev);
-int mt76x2_apply_calibration_data(struct mt76x2_dev *dev, int channel);
-void mt76x2_set_tx_ackto(struct mt76x2_dev *dev);
-
-void mt76x2_phy_set_antenna(struct mt76x2_dev *dev);
-int mt76x2_phy_start(struct mt76x2_dev *dev);
-int mt76x2_phy_set_channel(struct mt76x2_dev *dev,
- struct cfg80211_chan_def *chandef);
-int mt76x2_mac_get_rssi(struct mt76x2_dev *dev, s8 rssi, int chain);
-void mt76x2_phy_calibrate(struct work_struct *work);
-void mt76x2_phy_set_txpower(struct mt76x2_dev *dev);
-
-int mt76x2_mcu_init(struct mt76x2_dev *dev);
-int mt76x2_mcu_set_channel(struct mt76x2_dev *dev, u8 channel, u8 bw,
- u8 bw_index, bool scan);
-int mt76x2_mcu_load_cr(struct mt76x2_dev *dev, u8 type, u8 temp_level,
- u8 channel);
-
-int mt76x2_dma_init(struct mt76x2_dev *dev);
-void mt76x2_dma_cleanup(struct mt76x2_dev *dev);
-
-void mt76x2_cleanup(struct mt76x2_dev *dev);
-
-void mt76x2_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
- struct sk_buff *skb);
-int mt76x2_tx_prepare_skb(struct mt76_dev *mdev, void *txwi,
- struct sk_buff *skb, struct mt76_queue *q,
- struct mt76_wcid *wcid, struct ieee80211_sta *sta,
- u32 *tx_info);
-void mt76x2_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
- struct mt76_queue_entry *e, bool flush);
-void mt76x2_mac_set_tx_protection(struct mt76x2_dev *dev, u32 val);
-
-void mt76x2_pre_tbtt_tasklet(unsigned long arg);
-
-void mt76x2_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q);
-void mt76x2_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
- struct sk_buff *skb);
-
-void mt76x2_sta_ps(struct mt76_dev *dev, struct ieee80211_sta *sta, bool ps);
-
-void mt76x2_update_channel(struct mt76_dev *mdev);
-
-s8 mt76x2_tx_get_max_txpwr_adj(struct mt76_dev *dev,
- const struct ieee80211_tx_rate *rate);
-s8 mt76x2_tx_get_txpwr_adj(struct mt76x2_dev *dev, s8 txpwr, s8 max_txpwr_adj);
-void mt76x2_tx_set_txpwr_auto(struct mt76x2_dev *dev, s8 txpwr);
-
-
-void mt76x2_reset_wlan(struct mt76x2_dev *dev, bool enable);
-void mt76x2_init_txpower(struct mt76x2_dev *dev,
- struct ieee80211_supported_band *sband);
-void mt76_write_mac_initvals(struct mt76x2_dev *dev);
-
-int mt76x2_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
-int mt76x2_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
-void mt76x2_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
-int mt76x2_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- u16 queue, const struct ieee80211_tx_queue_params *params);
-void mt76x2_txq_init(struct mt76x2_dev *dev, struct ieee80211_txq *txq);
-
-void mt76x2_phy_tssi_compensate(struct mt76x2_dev *dev, bool wait);
-void mt76x2_phy_set_txpower_regs(struct mt76x2_dev *dev,
- enum nl80211_band band);
-void mt76x2_configure_tx_delay(struct mt76x2_dev *dev,
- enum nl80211_band band, u8 bw);
-void mt76x2_phy_set_bw(struct mt76x2_dev *dev, int width, u8 ctrl);
-void mt76x2_phy_set_band(struct mt76x2_dev *dev, int band, bool primary_upper);
-int mt76x2_phy_get_min_avg_rssi(struct mt76x2_dev *dev);
-void mt76x2_apply_gain_adj(struct mt76x2_dev *dev);
-
-#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig b/drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig
new file mode 100644
index 000000000000..2b414a0e9088
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig
@@ -0,0 +1,20 @@
+config MT76x2_COMMON
+ tristate
+ select MT76x02_LIB
+
+config MT76x2E
+ tristate "MediaTek MT76x2E (PCIe) support"
+ select MT76x2_COMMON
+ depends on MAC80211
+ depends on PCI
+ ---help---
+ This adds support for MT7612/MT7602/MT7662-based wireless PCIe devices.
+
+config MT76x2U
+ tristate "MediaTek MT76x2U (USB) support"
+ select MT76x2_COMMON
+ select MT76x02_USB
+ depends on MAC80211
+ depends on USB
+ help
+ This adds support for MT7612U-based wireless USB dongles.
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/Makefile b/drivers/net/wireless/mediatek/mt76/mt76x2/Makefile
new file mode 100644
index 000000000000..b71bb1049170
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/Makefile
@@ -0,0 +1,16 @@
+obj-$(CONFIG_MT76x2_COMMON) += mt76x2-common.o
+obj-$(CONFIG_MT76x2E) += mt76x2e.o
+obj-$(CONFIG_MT76x2U) += mt76x2u.o
+
+mt76x2-common-y := \
+ eeprom.o mac.o init.o phy.o debugfs.o mcu.o
+
+mt76x2e-y := \
+ pci.o pci_main.o pci_init.o pci_tx.o \
+ pci_mac.o pci_mcu.o pci_phy.o pci_dfs.o
+
+mt76x2u-y := \
+ usb.o usb_init.o usb_main.o usb_mac.o usb_mcu.o \
+ usb_phy.o
+
+CFLAGS_pci_trace.o := -I$(src)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_debugfs.c b/drivers/net/wireless/mediatek/mt76/mt76x2/debugfs.c
index 77b5ff1be05f..e8f8ccc0a5ed 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/debugfs.c
@@ -20,7 +20,7 @@
static int
mt76x2_ampdu_stat_read(struct seq_file *file, void *data)
{
- struct mt76x2_dev *dev = file->private;
+ struct mt76x02_dev *dev = file->private;
int i, j;
for (i = 0; i < 4; i++) {
@@ -47,33 +47,14 @@ mt76x2_ampdu_stat_open(struct inode *inode, struct file *f)
return single_open(f, mt76x2_ampdu_stat_read, inode->i_private);
}
-static void
-seq_puts_array(struct seq_file *file, const char *str, s8 *val, int len)
-{
- int i;
-
- seq_printf(file, "%10s:", str);
- for (i = 0; i < len; i++)
- seq_printf(file, " %2d", val[i]);
- seq_puts(file, "\n");
-}
-
static int read_txpower(struct seq_file *file, void *data)
{
- struct mt76x2_dev *dev = dev_get_drvdata(file->private);
+ struct mt76x02_dev *dev = dev_get_drvdata(file->private);
seq_printf(file, "Target power: %d\n", dev->target_power);
- seq_puts_array(file, "Delta", dev->target_power_delta,
- ARRAY_SIZE(dev->target_power_delta));
- seq_puts_array(file, "CCK", dev->rate_power.cck,
- ARRAY_SIZE(dev->rate_power.cck));
- seq_puts_array(file, "OFDM", dev->rate_power.ofdm,
- ARRAY_SIZE(dev->rate_power.ofdm));
- seq_puts_array(file, "HT", dev->rate_power.ht,
- ARRAY_SIZE(dev->rate_power.ht));
- seq_puts_array(file, "VHT", dev->rate_power.vht,
- ARRAY_SIZE(dev->rate_power.vht));
+ mt76_seq_puts_array(file, "Delta", dev->target_power_delta,
+ ARRAY_SIZE(dev->target_power_delta));
return 0;
}
@@ -87,9 +68,9 @@ static const struct file_operations fops_ampdu_stat = {
static int
mt76x2_dfs_stat_read(struct seq_file *file, void *data)
{
+ struct mt76x02_dev *dev = file->private;
+ struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
int i;
- struct mt76x2_dev *dev = file->private;
- struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
seq_printf(file, "allocated sequences:\t%d\n",
dfs_pd->seq_stats.seq_pool_len);
@@ -125,7 +106,7 @@ static const struct file_operations fops_dfs_stat = {
static int read_agc(struct seq_file *file, void *data)
{
- struct mt76x2_dev *dev = dev_get_drvdata(file->private);
+ struct mt76x02_dev *dev = dev_get_drvdata(file->private);
seq_printf(file, "avg_rssi: %d\n", dev->cal.avg_rssi_all);
seq_printf(file, "low_gain: %d\n", dev->cal.low_gain);
@@ -135,7 +116,7 @@ static int read_agc(struct seq_file *file, void *data)
return 0;
}
-void mt76x2_init_debugfs(struct mt76x2_dev *dev)
+void mt76x2_init_debugfs(struct mt76x02_dev *dev)
{
struct dentry *dir;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/dfs.h b/drivers/net/wireless/mediatek/mt76/mt76x2/dfs.h
new file mode 100644
index 000000000000..3cb9d1864286
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/dfs.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2016 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __DFS_H
+#define __DFS_H
+
+void mt76x2_dfs_init_params(struct mt76x02_dev *dev);
+void mt76x2_dfs_init_detector(struct mt76x02_dev *dev);
+void mt76x2_dfs_adjust_agc(struct mt76x02_dev *dev);
+void mt76x2_dfs_set_domain(struct mt76x02_dev *dev,
+ enum nl80211_dfs_regions region);
+
+#endif /* __DFS_H */
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c
index 1753bcb36356..bbab021b5f1a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c
@@ -14,14 +14,15 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/module.h>
#include <asm/unaligned.h>
#include "mt76x2.h"
-#include "mt76x2_eeprom.h"
+#include "eeprom.h"
#define EE_FIELD(_name, _value) [MT_EE_##_name] = (_value) | 1
static int
-mt76x2_eeprom_copy(struct mt76x2_dev *dev, enum mt76x2_eeprom_field field,
+mt76x2_eeprom_copy(struct mt76x02_dev *dev, enum mt76x02_eeprom_field field,
void *dest, int len)
{
if (field + len > dev->mt76.eeprom.size)
@@ -32,7 +33,7 @@ mt76x2_eeprom_copy(struct mt76x2_dev *dev, enum mt76x2_eeprom_field field,
}
static int
-mt76x2_eeprom_get_macaddr(struct mt76x2_dev *dev)
+mt76x2_eeprom_get_macaddr(struct mt76x02_dev *dev)
{
void *src = dev->mt76.eeprom.data + MT_EE_MAC_ADDR;
@@ -40,73 +41,8 @@ mt76x2_eeprom_get_macaddr(struct mt76x2_dev *dev)
return 0;
}
-void mt76x2_eeprom_parse_hw_cap(struct mt76x2_dev *dev)
-{
- u16 val = mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_0);
-
- switch (FIELD_GET(MT_EE_NIC_CONF_0_BOARD_TYPE, val)) {
- case BOARD_TYPE_5GHZ:
- dev->mt76.cap.has_5ghz = true;
- break;
- case BOARD_TYPE_2GHZ:
- dev->mt76.cap.has_2ghz = true;
- break;
- default:
- dev->mt76.cap.has_2ghz = true;
- dev->mt76.cap.has_5ghz = true;
- break;
- }
-}
-EXPORT_SYMBOL_GPL(mt76x2_eeprom_parse_hw_cap);
-
-static int
-mt76x2_efuse_read(struct mt76x2_dev *dev, u16 addr, u8 *data)
-{
- u32 val;
- int i;
-
- val = mt76_rr(dev, MT_EFUSE_CTRL);
- val &= ~(MT_EFUSE_CTRL_AIN |
- MT_EFUSE_CTRL_MODE);
- val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf);
- val |= MT_EFUSE_CTRL_KICK;
- mt76_wr(dev, MT_EFUSE_CTRL, val);
-
- if (!mt76_poll(dev, MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000))
- return -ETIMEDOUT;
-
- udelay(2);
-
- val = mt76_rr(dev, MT_EFUSE_CTRL);
- if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT) {
- memset(data, 0xff, 16);
- return 0;
- }
-
- for (i = 0; i < 4; i++) {
- val = mt76_rr(dev, MT_EFUSE_DATA(i));
- put_unaligned_le32(val, data + 4 * i);
- }
-
- return 0;
-}
-
-static int
-mt76x2_get_efuse_data(struct mt76x2_dev *dev, void *buf, int len)
-{
- int ret, i;
-
- for (i = 0; i + 16 <= len; i += 16) {
- ret = mt76x2_efuse_read(dev, i, buf + i);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
static bool
-mt76x2_has_cal_free_data(struct mt76x2_dev *dev, u8 *efuse)
+mt76x2_has_cal_free_data(struct mt76x02_dev *dev, u8 *efuse)
{
u16 *efuse_w = (u16 *) efuse;
@@ -132,7 +68,7 @@ mt76x2_has_cal_free_data(struct mt76x2_dev *dev, u8 *efuse)
}
static void
-mt76x2_apply_cal_free_data(struct mt76x2_dev *dev, u8 *efuse)
+mt76x2_apply_cal_free_data(struct mt76x02_dev *dev, u8 *efuse)
{
#define GROUP_5G(_id) \
MT_EE_TX_POWER_0_START_5G + MT_TX_POWER_GROUP_SIZE_5G * (_id), \
@@ -201,7 +137,7 @@ mt76x2_apply_cal_free_data(struct mt76x2_dev *dev, u8 *efuse)
eeprom[MT_EE_BT_PMUCFG] = val & 0xff;
}
-static int mt76x2_check_eeprom(struct mt76x2_dev *dev)
+static int mt76x2_check_eeprom(struct mt76x02_dev *dev)
{
u16 val = get_unaligned_le16(dev->mt76.eeprom.data);
@@ -219,7 +155,7 @@ static int mt76x2_check_eeprom(struct mt76x2_dev *dev)
}
static int
-mt76x2_eeprom_load(struct mt76x2_dev *dev)
+mt76x2_eeprom_load(struct mt76x02_dev *dev)
{
void *efuse;
bool found;
@@ -241,7 +177,8 @@ mt76x2_eeprom_load(struct mt76x2_dev *dev)
efuse = dev->mt76.otp.data;
- if (mt76x2_get_efuse_data(dev, efuse, MT7662_EEPROM_SIZE))
+ if (mt76x02_get_efuse_data(&dev->mt76, 0, efuse,
+ MT7662_EEPROM_SIZE, MT_EE_READ))
goto out;
if (found) {
@@ -259,56 +196,32 @@ out:
return 0;
}
-static inline int
-mt76x2_sign_extend(u32 val, unsigned int size)
-{
- bool sign = val & BIT(size - 1);
-
- val &= BIT(size - 1) - 1;
-
- return sign ? val : -val;
-}
-
-static inline int
-mt76x2_sign_extend_optional(u32 val, unsigned int size)
-{
- bool enable = val & BIT(size);
-
- return enable ? mt76x2_sign_extend(val, size) : 0;
-}
-
-static bool
-field_valid(u8 val)
-{
- return val != 0 && val != 0xff;
-}
-
static void
-mt76x2_set_rx_gain_group(struct mt76x2_dev *dev, u8 val)
+mt76x2_set_rx_gain_group(struct mt76x02_dev *dev, u8 val)
{
s8 *dest = dev->cal.rx.high_gain;
- if (!field_valid(val)) {
+ if (!mt76x02_field_valid(val)) {
dest[0] = 0;
dest[1] = 0;
return;
}
- dest[0] = mt76x2_sign_extend(val, 4);
- dest[1] = mt76x2_sign_extend(val >> 4, 4);
+ dest[0] = mt76x02_sign_extend(val, 4);
+ dest[1] = mt76x02_sign_extend(val >> 4, 4);
}
static void
-mt76x2_set_rssi_offset(struct mt76x2_dev *dev, int chain, u8 val)
+mt76x2_set_rssi_offset(struct mt76x02_dev *dev, int chain, u8 val)
{
s8 *dest = dev->cal.rx.rssi_offset;
- if (!field_valid(val)) {
+ if (!mt76x02_field_valid(val)) {
dest[chain] = 0;
return;
}
- dest[chain] = mt76x2_sign_extend_optional(val, 7);
+ dest[chain] = mt76x02_sign_extend_optional(val, 7);
}
static enum mt76x2_cal_channel_group
@@ -328,28 +241,34 @@ mt76x2_get_cal_channel_group(int channel)
}
static u8
-mt76x2_get_5g_rx_gain(struct mt76x2_dev *dev, u8 channel)
+mt76x2_get_5g_rx_gain(struct mt76x02_dev *dev, u8 channel)
{
enum mt76x2_cal_channel_group group;
group = mt76x2_get_cal_channel_group(channel);
switch (group) {
case MT_CH_5G_JAPAN:
- return mt76x2_eeprom_get(dev, MT_EE_RF_5G_GRP0_1_RX_HIGH_GAIN);
+ return mt76x02_eeprom_get(&dev->mt76,
+ MT_EE_RF_5G_GRP0_1_RX_HIGH_GAIN);
case MT_CH_5G_UNII_1:
- return mt76x2_eeprom_get(dev, MT_EE_RF_5G_GRP0_1_RX_HIGH_GAIN) >> 8;
+ return mt76x02_eeprom_get(&dev->mt76,
+ MT_EE_RF_5G_GRP0_1_RX_HIGH_GAIN) >> 8;
case MT_CH_5G_UNII_2:
- return mt76x2_eeprom_get(dev, MT_EE_RF_5G_GRP2_3_RX_HIGH_GAIN);
+ return mt76x02_eeprom_get(&dev->mt76,
+ MT_EE_RF_5G_GRP2_3_RX_HIGH_GAIN);
case MT_CH_5G_UNII_2E_1:
- return mt76x2_eeprom_get(dev, MT_EE_RF_5G_GRP2_3_RX_HIGH_GAIN) >> 8;
+ return mt76x02_eeprom_get(&dev->mt76,
+ MT_EE_RF_5G_GRP2_3_RX_HIGH_GAIN) >> 8;
case MT_CH_5G_UNII_2E_2:
- return mt76x2_eeprom_get(dev, MT_EE_RF_5G_GRP4_5_RX_HIGH_GAIN);
+ return mt76x02_eeprom_get(&dev->mt76,
+ MT_EE_RF_5G_GRP4_5_RX_HIGH_GAIN);
default:
- return mt76x2_eeprom_get(dev, MT_EE_RF_5G_GRP4_5_RX_HIGH_GAIN) >> 8;
+ return mt76x02_eeprom_get(&dev->mt76,
+ MT_EE_RF_5G_GRP4_5_RX_HIGH_GAIN) >> 8;
}
}
-void mt76x2_read_rx_gain(struct mt76x2_dev *dev)
+void mt76x2_read_rx_gain(struct mt76x02_dev *dev)
{
struct ieee80211_channel *chan = dev->mt76.chandef.chan;
int channel = chan->hw_value;
@@ -358,75 +277,28 @@ void mt76x2_read_rx_gain(struct mt76x2_dev *dev)
u16 val;
if (chan->band == NL80211_BAND_2GHZ)
- val = mt76x2_eeprom_get(dev, MT_EE_RF_2G_RX_HIGH_GAIN) >> 8;
+ val = mt76x02_eeprom_get(&dev->mt76,
+ MT_EE_RF_2G_RX_HIGH_GAIN) >> 8;
else
val = mt76x2_get_5g_rx_gain(dev, channel);
mt76x2_set_rx_gain_group(dev, val);
- if (chan->band == NL80211_BAND_2GHZ) {
- val = mt76x2_eeprom_get(dev, MT_EE_RSSI_OFFSET_2G_0);
- mt76x2_set_rssi_offset(dev, 0, val);
- mt76x2_set_rssi_offset(dev, 1, val >> 8);
- } else {
- val = mt76x2_eeprom_get(dev, MT_EE_RSSI_OFFSET_5G_0);
- mt76x2_set_rssi_offset(dev, 0, val);
- mt76x2_set_rssi_offset(dev, 1, val >> 8);
- }
-
- val = mt76x2_eeprom_get(dev, MT_EE_LNA_GAIN);
- lna_2g = val & 0xff;
- lna_5g[0] = val >> 8;
-
- val = mt76x2_eeprom_get(dev, MT_EE_RSSI_OFFSET_2G_1);
- lna_5g[1] = val >> 8;
-
- val = mt76x2_eeprom_get(dev, MT_EE_RSSI_OFFSET_5G_1);
- lna_5g[2] = val >> 8;
-
- if (!field_valid(lna_5g[1]))
- lna_5g[1] = lna_5g[0];
-
- if (!field_valid(lna_5g[2]))
- lna_5g[2] = lna_5g[0];
+ mt76x02_get_rx_gain(&dev->mt76, chan->band, &val, &lna_2g, lna_5g);
+ mt76x2_set_rssi_offset(dev, 0, val);
+ mt76x2_set_rssi_offset(dev, 1, val >> 8);
dev->cal.rx.mcu_gain = (lna_2g & 0xff);
dev->cal.rx.mcu_gain |= (lna_5g[0] & 0xff) << 8;
dev->cal.rx.mcu_gain |= (lna_5g[1] & 0xff) << 16;
dev->cal.rx.mcu_gain |= (lna_5g[2] & 0xff) << 24;
- val = mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_1);
- if (val & MT_EE_NIC_CONF_1_LNA_EXT_2G)
- lna_2g = 0;
- if (val & MT_EE_NIC_CONF_1_LNA_EXT_5G)
- memset(lna_5g, 0, sizeof(lna_5g));
-
- if (chan->band == NL80211_BAND_2GHZ)
- lna = lna_2g;
- else if (channel <= 64)
- lna = lna_5g[0];
- else if (channel <= 128)
- lna = lna_5g[1];
- else
- lna = lna_5g[2];
-
- if (lna == 0xff)
- lna = 0;
-
- dev->cal.rx.lna_gain = mt76x2_sign_extend(lna, 8);
+ lna = mt76x02_get_lna_gain(&dev->mt76, &lna_2g, lna_5g, chan);
+ dev->cal.rx.lna_gain = mt76x02_sign_extend(lna, 8);
}
EXPORT_SYMBOL_GPL(mt76x2_read_rx_gain);
-static s8
-mt76x2_rate_power_val(u8 val)
-{
- if (!field_valid(val))
- return 0;
-
- return mt76x2_sign_extend_optional(val, 7);
-}
-
-void mt76x2_get_rate_power(struct mt76x2_dev *dev, struct mt76_rate_power *t,
+void mt76x2_get_rate_power(struct mt76x02_dev *dev, struct mt76_rate_power *t,
struct ieee80211_channel *chan)
{
bool is_5ghz;
@@ -436,70 +308,68 @@ void mt76x2_get_rate_power(struct mt76x2_dev *dev, struct mt76_rate_power *t,
memset(t, 0, sizeof(*t));
- val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_CCK);
- t->cck[0] = t->cck[1] = mt76x2_rate_power_val(val);
- t->cck[2] = t->cck[3] = mt76x2_rate_power_val(val >> 8);
+ val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_CCK);
+ t->cck[0] = t->cck[1] = mt76x02_rate_power_val(val);
+ t->cck[2] = t->cck[3] = mt76x02_rate_power_val(val >> 8);
if (is_5ghz)
- val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_OFDM_5G_6M);
+ val = mt76x02_eeprom_get(&dev->mt76,
+ MT_EE_TX_POWER_OFDM_5G_6M);
else
- val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_OFDM_2G_6M);
- t->ofdm[0] = t->ofdm[1] = mt76x2_rate_power_val(val);
- t->ofdm[2] = t->ofdm[3] = mt76x2_rate_power_val(val >> 8);
+ val = mt76x02_eeprom_get(&dev->mt76,
+ MT_EE_TX_POWER_OFDM_2G_6M);
+ t->ofdm[0] = t->ofdm[1] = mt76x02_rate_power_val(val);
+ t->ofdm[2] = t->ofdm[3] = mt76x02_rate_power_val(val >> 8);
if (is_5ghz)
- val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_OFDM_5G_24M);
+ val = mt76x02_eeprom_get(&dev->mt76,
+ MT_EE_TX_POWER_OFDM_5G_24M);
else
- val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_OFDM_2G_24M);
- t->ofdm[4] = t->ofdm[5] = mt76x2_rate_power_val(val);
- t->ofdm[6] = t->ofdm[7] = mt76x2_rate_power_val(val >> 8);
+ val = mt76x02_eeprom_get(&dev->mt76,
+ MT_EE_TX_POWER_OFDM_2G_24M);
+ t->ofdm[4] = t->ofdm[5] = mt76x02_rate_power_val(val);
+ t->ofdm[6] = t->ofdm[7] = mt76x02_rate_power_val(val >> 8);
- val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_HT_MCS0);
- t->ht[0] = t->ht[1] = mt76x2_rate_power_val(val);
- t->ht[2] = t->ht[3] = mt76x2_rate_power_val(val >> 8);
+ val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_HT_MCS0);
+ t->ht[0] = t->ht[1] = mt76x02_rate_power_val(val);
+ t->ht[2] = t->ht[3] = mt76x02_rate_power_val(val >> 8);
- val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_HT_MCS4);
- t->ht[4] = t->ht[5] = mt76x2_rate_power_val(val);
- t->ht[6] = t->ht[7] = mt76x2_rate_power_val(val >> 8);
+ val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_HT_MCS4);
+ t->ht[4] = t->ht[5] = mt76x02_rate_power_val(val);
+ t->ht[6] = t->ht[7] = mt76x02_rate_power_val(val >> 8);
- val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_HT_MCS8);
- t->ht[8] = t->ht[9] = mt76x2_rate_power_val(val);
- t->ht[10] = t->ht[11] = mt76x2_rate_power_val(val >> 8);
+ val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_HT_MCS8);
+ t->ht[8] = t->ht[9] = mt76x02_rate_power_val(val);
+ t->ht[10] = t->ht[11] = mt76x02_rate_power_val(val >> 8);
- val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_HT_MCS12);
- t->ht[12] = t->ht[13] = mt76x2_rate_power_val(val);
- t->ht[14] = t->ht[15] = mt76x2_rate_power_val(val >> 8);
+ val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_HT_MCS12);
+ t->ht[12] = t->ht[13] = mt76x02_rate_power_val(val);
+ t->ht[14] = t->ht[15] = mt76x02_rate_power_val(val >> 8);
- val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_VHT_MCS0);
- t->vht[0] = t->vht[1] = mt76x2_rate_power_val(val);
- t->vht[2] = t->vht[3] = mt76x2_rate_power_val(val >> 8);
+ val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_VHT_MCS0);
+ t->vht[0] = t->vht[1] = mt76x02_rate_power_val(val);
+ t->vht[2] = t->vht[3] = mt76x02_rate_power_val(val >> 8);
- val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_VHT_MCS4);
- t->vht[4] = t->vht[5] = mt76x2_rate_power_val(val);
- t->vht[6] = t->vht[7] = mt76x2_rate_power_val(val >> 8);
+ val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_VHT_MCS4);
+ t->vht[4] = t->vht[5] = mt76x02_rate_power_val(val);
+ t->vht[6] = t->vht[7] = mt76x02_rate_power_val(val >> 8);
- val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_VHT_MCS8);
+ val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_VHT_MCS8);
if (!is_5ghz)
val >>= 8;
- t->vht[8] = t->vht[9] = mt76x2_rate_power_val(val >> 8);
-}
-EXPORT_SYMBOL_GPL(mt76x2_get_rate_power);
+ t->vht[8] = t->vht[9] = mt76x02_rate_power_val(val >> 8);
-int mt76x2_get_max_rate_power(struct mt76_rate_power *r)
-{
- int i;
- s8 ret = 0;
-
- for (i = 0; i < sizeof(r->all); i++)
- ret = max(ret, r->all[i]);
-
- return ret;
+ memcpy(t->stbc, t->ht, sizeof(t->stbc[0]) * 8);
+ t->stbc[8] = t->vht[8];
+ t->stbc[9] = t->vht[9];
}
-EXPORT_SYMBOL_GPL(mt76x2_get_max_rate_power);
+EXPORT_SYMBOL_GPL(mt76x2_get_rate_power);
static void
-mt76x2_get_power_info_2g(struct mt76x2_dev *dev, struct mt76x2_tx_power_info *t,
- struct ieee80211_channel *chan, int chain, int offset)
+mt76x2_get_power_info_2g(struct mt76x02_dev *dev,
+ struct mt76x2_tx_power_info *t,
+ struct ieee80211_channel *chan,
+ int chain, int offset)
{
int channel = chan->hw_value;
int delta_idx;
@@ -518,15 +388,17 @@ mt76x2_get_power_info_2g(struct mt76x2_dev *dev, struct mt76x2_tx_power_info *t,
t->chain[chain].tssi_slope = data[0];
t->chain[chain].tssi_offset = data[1];
t->chain[chain].target_power = data[2];
- t->chain[chain].delta = mt76x2_sign_extend_optional(data[delta_idx], 7);
+ t->chain[chain].delta = mt76x02_sign_extend_optional(data[delta_idx], 7);
- val = mt76x2_eeprom_get(dev, MT_EE_RF_2G_TSSI_OFF_TXPOWER);
+ val = mt76x02_eeprom_get(&dev->mt76, MT_EE_RF_2G_TSSI_OFF_TXPOWER);
t->target_power = val >> 8;
}
static void
-mt76x2_get_power_info_5g(struct mt76x2_dev *dev, struct mt76x2_tx_power_info *t,
- struct ieee80211_channel *chan, int chain, int offset)
+mt76x2_get_power_info_5g(struct mt76x02_dev *dev,
+ struct mt76x2_tx_power_info *t,
+ struct ieee80211_channel *chan,
+ int chain, int offset)
{
int channel = chan->hw_value;
enum mt76x2_cal_channel_group group;
@@ -567,13 +439,13 @@ mt76x2_get_power_info_5g(struct mt76x2_dev *dev, struct mt76x2_tx_power_info *t,
t->chain[chain].tssi_slope = data[0];
t->chain[chain].tssi_offset = data[1];
t->chain[chain].target_power = data[2];
- t->chain[chain].delta = mt76x2_sign_extend_optional(data[delta_idx], 7);
+ t->chain[chain].delta = mt76x02_sign_extend_optional(data[delta_idx], 7);
- val = mt76x2_eeprom_get(dev, MT_EE_RF_2G_RX_HIGH_GAIN);
+ val = mt76x02_eeprom_get(&dev->mt76, MT_EE_RF_2G_RX_HIGH_GAIN);
t->target_power = val & 0xff;
}
-void mt76x2_get_power_info(struct mt76x2_dev *dev,
+void mt76x2_get_power_info(struct mt76x02_dev *dev,
struct mt76x2_tx_power_info *t,
struct ieee80211_channel *chan)
{
@@ -581,8 +453,8 @@ void mt76x2_get_power_info(struct mt76x2_dev *dev,
memset(t, 0, sizeof(*t));
- bw40 = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_DELTA_BW40);
- bw80 = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_DELTA_BW80);
+ bw40 = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_DELTA_BW40);
+ bw80 = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_DELTA_BW80);
if (chan->band == NL80211_BAND_5GHZ) {
bw40 >>= 8;
@@ -597,15 +469,16 @@ void mt76x2_get_power_info(struct mt76x2_dev *dev,
MT_EE_TX_POWER_1_START_2G);
}
- if (mt76x2_tssi_enabled(dev) || !field_valid(t->target_power))
+ if (mt76x02_tssi_enabled(&dev->mt76) ||
+ !mt76x02_field_valid(t->target_power))
t->target_power = t->chain[0].target_power;
- t->delta_bw40 = mt76x2_rate_power_val(bw40);
- t->delta_bw80 = mt76x2_rate_power_val(bw80);
+ t->delta_bw40 = mt76x02_rate_power_val(bw40);
+ t->delta_bw80 = mt76x02_rate_power_val(bw80);
}
EXPORT_SYMBOL_GPL(mt76x2_get_power_info);
-int mt76x2_get_temp_comp(struct mt76x2_dev *dev, struct mt76x2_temp_comp *t)
+int mt76x2_get_temp_comp(struct mt76x02_dev *dev, struct mt76x2_temp_comp *t)
{
enum nl80211_band band = dev->mt76.chandef.chan->band;
u16 val, slope;
@@ -613,20 +486,24 @@ int mt76x2_get_temp_comp(struct mt76x2_dev *dev, struct mt76x2_temp_comp *t)
memset(t, 0, sizeof(*t));
- if (!mt76x2_temp_tx_alc_enabled(dev))
+ if (!mt76x02_temp_tx_alc_enabled(&dev->mt76))
return -EINVAL;
- if (!mt76x2_ext_pa_enabled(dev, band))
+ if (!mt76x02_ext_pa_enabled(&dev->mt76, band))
return -EINVAL;
- val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_EXT_PA_5G) >> 8;
+ val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_EXT_PA_5G) >> 8;
t->temp_25_ref = val & 0x7f;
if (band == NL80211_BAND_5GHZ) {
- slope = mt76x2_eeprom_get(dev, MT_EE_RF_TEMP_COMP_SLOPE_5G);
- bounds = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_EXT_PA_5G);
+ slope = mt76x02_eeprom_get(&dev->mt76,
+ MT_EE_RF_TEMP_COMP_SLOPE_5G);
+ bounds = mt76x02_eeprom_get(&dev->mt76,
+ MT_EE_TX_POWER_EXT_PA_5G);
} else {
- slope = mt76x2_eeprom_get(dev, MT_EE_RF_TEMP_COMP_SLOPE_2G);
- bounds = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_DELTA_BW80) >> 8;
+ slope = mt76x02_eeprom_get(&dev->mt76,
+ MT_EE_RF_TEMP_COMP_SLOPE_2G);
+ bounds = mt76x02_eeprom_get(&dev->mt76,
+ MT_EE_TX_POWER_DELTA_BW80) >> 8;
}
t->high_slope = slope & 0xff;
@@ -638,18 +515,7 @@ int mt76x2_get_temp_comp(struct mt76x2_dev *dev, struct mt76x2_temp_comp *t)
}
EXPORT_SYMBOL_GPL(mt76x2_get_temp_comp);
-bool mt76x2_ext_pa_enabled(struct mt76x2_dev *dev, enum nl80211_band band)
-{
- u16 conf0 = mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_0);
-
- if (band == NL80211_BAND_5GHZ)
- return !(conf0 & MT_EE_NIC_CONF_0_PA_INT_5G);
- else
- return !(conf0 & MT_EE_NIC_CONF_0_PA_INT_2G);
-}
-EXPORT_SYMBOL_GPL(mt76x2_ext_pa_enabled);
-
-int mt76x2_eeprom_init(struct mt76x2_dev *dev)
+int mt76x2_eeprom_init(struct mt76x02_dev *dev)
{
int ret;
@@ -657,7 +523,7 @@ int mt76x2_eeprom_init(struct mt76x2_dev *dev)
if (ret)
return ret;
- mt76x2_eeprom_parse_hw_cap(dev);
+ mt76x02_eeprom_parse_hw_cap(&dev->mt76);
mt76x2_eeprom_get_macaddr(dev);
mt76_eeprom_override(&dev->mt76);
dev->mt76.macaddr[0] &= ~BIT(1);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.h
new file mode 100644
index 000000000000..c97b31c77d83
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __MT76x2_EEPROM_H
+#define __MT76x2_EEPROM_H
+
+#include "../mt76x02_eeprom.h"
+
+enum mt76x2_cal_channel_group {
+ MT_CH_5G_JAPAN,
+ MT_CH_5G_UNII_1,
+ MT_CH_5G_UNII_2,
+ MT_CH_5G_UNII_2E_1,
+ MT_CH_5G_UNII_2E_2,
+ MT_CH_5G_UNII_3,
+ __MT_CH_MAX
+};
+
+struct mt76x2_tx_power_info {
+ u8 target_power;
+
+ s8 delta_bw40;
+ s8 delta_bw80;
+
+ struct {
+ s8 tssi_slope;
+ s8 tssi_offset;
+ s8 target_power;
+ s8 delta;
+ } chain[MT_MAX_CHAINS];
+};
+
+struct mt76x2_temp_comp {
+ u8 temp_25_ref;
+ int lower_bound; /* J */
+ int upper_bound; /* J */
+ unsigned int high_slope; /* J / dB */
+ unsigned int low_slope; /* J / dB */
+};
+
+void mt76x2_get_rate_power(struct mt76x02_dev *dev, struct mt76_rate_power *t,
+ struct ieee80211_channel *chan);
+void mt76x2_get_power_info(struct mt76x02_dev *dev,
+ struct mt76x2_tx_power_info *t,
+ struct ieee80211_channel *chan);
+int mt76x2_get_temp_comp(struct mt76x02_dev *dev, struct mt76x2_temp_comp *t);
+void mt76x2_read_rx_gain(struct mt76x02_dev *dev);
+
+static inline bool
+mt76x2_has_ext_lna(struct mt76x02_dev *dev)
+{
+ u32 val = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_1);
+
+ if (dev->mt76.chandef.chan->band == NL80211_BAND_2GHZ)
+ return val & MT_EE_NIC_CONF_1_LNA_EXT_2G;
+ else
+ return val & MT_EE_NIC_CONF_1_LNA_EXT_5G;
+}
+
+#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_init_common.c b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c
index 31de3365cdb8..ccd9bc9d3e1e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_init_common.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c
@@ -16,10 +16,11 @@
*/
#include "mt76x2.h"
-#include "mt76x2_eeprom.h"
+#include "eeprom.h"
+#include "../mt76x02_phy.h"
static void
-mt76x2_set_wlan_state(struct mt76x2_dev *dev, bool enable)
+mt76x2_set_wlan_state(struct mt76x02_dev *dev, bool enable)
{
u32 val = mt76_rr(dev, MT_WLAN_FUN_CTRL);
@@ -34,10 +35,13 @@ mt76x2_set_wlan_state(struct mt76x2_dev *dev, bool enable)
udelay(20);
}
-void mt76x2_reset_wlan(struct mt76x2_dev *dev, bool enable)
+void mt76x2_reset_wlan(struct mt76x02_dev *dev, bool enable)
{
u32 val;
+ if (!enable)
+ goto out;
+
val = mt76_rr(dev, MT_WLAN_FUN_CTRL);
val &= ~MT_WLAN_FUN_CTRL_FRC_WL_ANT_SEL;
@@ -53,22 +57,12 @@ void mt76x2_reset_wlan(struct mt76x2_dev *dev, bool enable)
mt76_wr(dev, MT_WLAN_FUN_CTRL, val);
udelay(20);
+out:
mt76x2_set_wlan_state(dev, enable);
}
EXPORT_SYMBOL_GPL(mt76x2_reset_wlan);
-static void
-mt76x2_write_reg_pairs(struct mt76x2_dev *dev,
- const struct mt76_reg_pair *data, int len)
-{
- while (len > 0) {
- mt76_wr(dev, data->reg, data->value);
- len--;
- data++;
- }
-}
-
-void mt76_write_mac_initvals(struct mt76x2_dev *dev)
+void mt76_write_mac_initvals(struct mt76x02_dev *dev)
{
#define DEFAULT_PROT_CFG_CCK \
(FIELD_PREP(MT_PROT_CFG_RATE, 0x3) | \
@@ -159,12 +153,12 @@ void mt76_write_mac_initvals(struct mt76x2_dev *dev)
{ MT_GF40_PROT_CFG, DEFAULT_PROT_CFG_40 },
};
- mt76x2_write_reg_pairs(dev, vals, ARRAY_SIZE(vals));
- mt76x2_write_reg_pairs(dev, prot_vals, ARRAY_SIZE(prot_vals));
+ mt76_wr_rp(dev, 0, vals, ARRAY_SIZE(vals));
+ mt76_wr_rp(dev, 0, prot_vals, ARRAY_SIZE(prot_vals));
}
EXPORT_SYMBOL_GPL(mt76_write_mac_initvals);
-void mt76x2_init_device(struct mt76x2_dev *dev)
+void mt76x2_init_device(struct mt76x02_dev *dev)
{
struct ieee80211_hw *hw = mt76_hw(dev);
@@ -183,7 +177,7 @@ void mt76x2_init_device(struct mt76x2_dev *dev)
dev->mt76.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
dev->mt76.sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
- dev->chainmask = 0x202;
+ dev->mt76.chainmask = 0x202;
dev->mt76.global_wcid.idx = 255;
dev->mt76.global_wcid.hw_key_idx = -1;
dev->slottime = 9;
@@ -193,7 +187,7 @@ void mt76x2_init_device(struct mt76x2_dev *dev)
}
EXPORT_SYMBOL_GPL(mt76x2_init_device);
-void mt76x2_init_txpower(struct mt76x2_dev *dev,
+void mt76x2_init_txpower(struct mt76x02_dev *dev,
struct ieee80211_supported_band *sband)
{
struct ieee80211_channel *chan;
@@ -214,7 +208,7 @@ void mt76x2_init_txpower(struct mt76x2_dev *dev,
mt76x2_get_rate_power(dev, &t, chan);
- chan->max_power = mt76x2_get_max_rate_power(&t) +
+ chan->max_power = mt76x02_get_max_rate_power(&t) +
target_power;
chan->max_power /= 2;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mac.c b/drivers/net/wireless/mediatek/mt76/mt76x2/mac.c
new file mode 100644
index 000000000000..e25905c91ee2
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mac.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
+ * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "mt76x2.h"
+
+void mt76x2_mac_stop(struct mt76x02_dev *dev, bool force)
+{
+ bool stopped = false;
+ u32 rts_cfg;
+ int i;
+
+ mt76_wr(dev, MT_MAC_SYS_CTRL, 0);
+
+ rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG);
+ mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg & ~MT_TX_RTS_CFG_RETRY_LIMIT);
+
+ /* Wait for MAC to become idle */
+ for (i = 0; i < 300; i++) {
+ if ((mt76_rr(dev, MT_MAC_STATUS) &
+ (MT_MAC_STATUS_RX | MT_MAC_STATUS_TX)) ||
+ mt76_rr(dev, MT_BBP(IBI, 12))) {
+ udelay(1);
+ continue;
+ }
+
+ stopped = true;
+ break;
+ }
+
+ if (force && !stopped) {
+ mt76_set(dev, MT_BBP(CORE, 4), BIT(1));
+ mt76_clear(dev, MT_BBP(CORE, 4), BIT(1));
+
+ mt76_set(dev, MT_BBP(CORE, 4), BIT(0));
+ mt76_clear(dev, MT_BBP(CORE, 4), BIT(0));
+ }
+
+ mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg);
+}
+EXPORT_SYMBOL_GPL(mt76x2_mac_stop);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_common.c b/drivers/net/wireless/mediatek/mt76/mt76x2/mac.h
index 3e667d8c0ee7..a31bd49ae6cb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_common.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mac.h
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
- * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -15,28 +14,24 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#ifndef __MT76x2_MAC_H
+#define __MT76x2_MAC_H
+
#include "mt76x2.h"
-#include "mt76x02_mac.h"
-void mt76x2_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
- struct sk_buff *skb)
-{
- struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76);
- void *rxwi = skb->data;
+struct mt76x02_dev;
+struct mt76x2_sta;
+struct mt76x02_vif;
+
+int mt76x2_mac_start(struct mt76x02_dev *dev);
+void mt76x2_mac_stop(struct mt76x02_dev *dev, bool force);
+void mt76x2_mac_resume(struct mt76x02_dev *dev);
+void mt76x2_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr);
- if (q == MT_RXQ_MCU) {
- /* this is used just by mmio code */
- skb_queue_tail(&mdev->mmio.mcu.res_q, skb);
- wake_up(&mdev->mmio.mcu.wait);
- return;
- }
+int mt76x2_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx,
+ struct sk_buff *skb);
+void mt76x2_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx, bool val);
- skb_pull(skb, sizeof(struct mt76x02_rxwi));
- if (mt76x2_mac_process_rx(dev, skb, rxwi)) {
- dev_kfree_skb(skb);
- return;
- }
+void mt76x2_mac_work(struct work_struct *work);
- mt76_rx(&dev->mt76, q, skb);
-}
-EXPORT_SYMBOL_GPL(mt76x2_queue_rx_skb);
+#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_mcu_common.c b/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c
index 72f6bfb7a258..134037a227d7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_mcu_common.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c
@@ -20,11 +20,10 @@
#include <linux/delay.h>
#include "mt76x2.h"
-#include "mt76x2_mcu.h"
-#include "mt76x2_eeprom.h"
-#include "mt76x02_dma.h"
+#include "mcu.h"
+#include "eeprom.h"
-int mt76x2_mcu_set_channel(struct mt76x2_dev *dev, u8 channel, u8 bw,
+int mt76x2_mcu_set_channel(struct mt76x02_dev *dev, u8 channel, u8 bw,
u8 bw_index, bool scan)
{
struct sk_buff *skb;
@@ -42,7 +41,7 @@ int mt76x2_mcu_set_channel(struct mt76x2_dev *dev, u8 channel, u8 bw,
.idx = channel,
.scan = scan,
.bw = bw,
- .chainmask = cpu_to_le16(dev->chainmask),
+ .chainmask = cpu_to_le16(dev->mt76.chainmask),
};
/* first set the channel without the extension channel info */
@@ -57,9 +56,10 @@ int mt76x2_mcu_set_channel(struct mt76x2_dev *dev, u8 channel, u8 bw,
}
EXPORT_SYMBOL_GPL(mt76x2_mcu_set_channel);
-int mt76x2_mcu_load_cr(struct mt76x2_dev *dev, u8 type, u8 temp_level,
+int mt76x2_mcu_load_cr(struct mt76x02_dev *dev, u8 type, u8 temp_level,
u8 channel)
{
+ struct mt76_dev *mdev = &dev->mt76;
struct sk_buff *skb;
struct {
u8 cr_mode;
@@ -76,8 +76,8 @@ int mt76x2_mcu_load_cr(struct mt76x2_dev *dev, u8 type, u8 temp_level,
u32 val;
val = BIT(31);
- val |= (mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_0) >> 8) & 0x00ff;
- val |= (mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_1) << 8) & 0xff00;
+ val |= (mt76x02_eeprom_get(mdev, MT_EE_NIC_CONF_0) >> 8) & 0x00ff;
+ val |= (mt76x02_eeprom_get(mdev, MT_EE_NIC_CONF_1) << 8) & 0xff00;
msg.cfg = cpu_to_le32(val);
/* first set the channel without the extension channel info */
@@ -86,7 +86,7 @@ int mt76x2_mcu_load_cr(struct mt76x2_dev *dev, u8 type, u8 temp_level,
}
EXPORT_SYMBOL_GPL(mt76x2_mcu_load_cr);
-int mt76x2_mcu_init_gain(struct mt76x2_dev *dev, u8 channel, u32 gain,
+int mt76x2_mcu_init_gain(struct mt76x02_dev *dev, u8 channel, u32 gain,
bool force)
{
struct sk_buff *skb;
@@ -106,7 +106,7 @@ int mt76x2_mcu_init_gain(struct mt76x2_dev *dev, u8 channel, u32 gain,
}
EXPORT_SYMBOL_GPL(mt76x2_mcu_init_gain);
-int mt76x2_mcu_tssi_comp(struct mt76x2_dev *dev,
+int mt76x2_mcu_tssi_comp(struct mt76x02_dev *dev,
struct mt76x2_tssi_comp *tssi_data)
{
struct sk_buff *skb;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.h
index 3de062d0b644..acfa2b570c7c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.h
@@ -17,7 +17,7 @@
#ifndef __MT76x2_MCU_H
#define __MT76x2_MCU_H
-#include "mt76x02_mcu.h"
+#include "../mt76x02_mcu.h"
/* Register definitions */
#define MT_MCU_CPU_CTL 0x0704
@@ -25,7 +25,6 @@
#define MT_MCU_PCIE_REMAP_BASE1 0x0740
#define MT_MCU_PCIE_REMAP_BASE2 0x0744
#define MT_MCU_PCIE_REMAP_BASE3 0x0748
-#define MT_MCU_PCIE_REMAP_BASE4 0x074C
#define MT_LED_CTRL 0x0770
#define MT_LED_CTRL_REPLAY(_n) BIT(0 + (8 * (_n)))
@@ -50,16 +49,10 @@
#define MT_LED_STATUS_DURATION(_v) (((_v) << __ffs(MT_LED_STATUS_DURATION_MASK)) & \
MT_LED_STATUS_DURATION_MASK)
-#define MT_MCU_SEMAPHORE_00 0x07B0
-#define MT_MCU_SEMAPHORE_01 0x07B4
-#define MT_MCU_SEMAPHORE_02 0x07B8
-#define MT_MCU_SEMAPHORE_03 0x07BC
-
#define MT_MCU_ROM_PATCH_OFFSET 0x80000
#define MT_MCU_ROM_PATCH_ADDR 0x90000
#define MT_MCU_ILM_OFFSET 0x80000
-#define MT_MCU_ILM_ADDR 0x80000
#define MT_MCU_DLM_OFFSET 0x100000
#define MT_MCU_DLM_ADDR 0x90000
@@ -101,8 +94,8 @@ struct mt76x2_tssi_comp {
u8 offset1;
} __packed __aligned(4);
-int mt76x2_mcu_tssi_comp(struct mt76x2_dev *dev, struct mt76x2_tssi_comp *tssi_data);
-int mt76x2_mcu_init_gain(struct mt76x2_dev *dev, u8 channel, u32 gain,
+int mt76x2_mcu_tssi_comp(struct mt76x02_dev *dev, struct mt76x2_tssi_comp *tssi_data);
+int mt76x2_mcu_init_gain(struct mt76x02_dev *dev, u8 channel, u32 gain,
bool force);
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h
new file mode 100644
index 000000000000..cbec8c6f1b2d
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __MT76x2_H
+#define __MT76x2_H
+
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/spinlock.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/bitops.h>
+
+#define MT7662_FIRMWARE "mt7662.bin"
+#define MT7662_ROM_PATCH "mt7662_rom_patch.bin"
+#define MT7662_EEPROM_SIZE 512
+
+#define MT7662U_FIRMWARE "mediatek/mt7662u.bin"
+#define MT7662U_ROM_PATCH "mediatek/mt7662u_rom_patch.bin"
+
+#define MT_CALIBRATE_INTERVAL HZ
+
+#include "../mt76x02.h"
+#include "mac.h"
+#include "dfs.h"
+
+static inline bool is_mt7612(struct mt76x02_dev *dev)
+{
+ return mt76_chip(&dev->mt76) == 0x7612;
+}
+
+static inline bool mt76x2_channel_silent(struct mt76x02_dev *dev)
+{
+ struct ieee80211_channel *chan = dev->mt76.chandef.chan;
+
+ return ((chan->flags & IEEE80211_CHAN_RADAR) &&
+ chan->dfs_state != NL80211_DFS_AVAILABLE);
+}
+
+extern const struct ieee80211_ops mt76x2_ops;
+
+struct mt76x02_dev *mt76x2_alloc_device(struct device *pdev);
+int mt76x2_register_device(struct mt76x02_dev *dev);
+void mt76x2_init_debugfs(struct mt76x02_dev *dev);
+void mt76x2_init_device(struct mt76x02_dev *dev);
+
+void mt76x2_phy_power_on(struct mt76x02_dev *dev);
+int mt76x2_init_hardware(struct mt76x02_dev *dev);
+void mt76x2_stop_hardware(struct mt76x02_dev *dev);
+int mt76x2_eeprom_init(struct mt76x02_dev *dev);
+int mt76x2_apply_calibration_data(struct mt76x02_dev *dev, int channel);
+void mt76x2_set_tx_ackto(struct mt76x02_dev *dev);
+
+void mt76x2_phy_set_antenna(struct mt76x02_dev *dev);
+int mt76x2_phy_start(struct mt76x02_dev *dev);
+int mt76x2_phy_set_channel(struct mt76x02_dev *dev,
+ struct cfg80211_chan_def *chandef);
+void mt76x2_phy_calibrate(struct work_struct *work);
+void mt76x2_phy_set_txpower(struct mt76x02_dev *dev);
+
+int mt76x2_mcu_init(struct mt76x02_dev *dev);
+int mt76x2_mcu_set_channel(struct mt76x02_dev *dev, u8 channel, u8 bw,
+ u8 bw_index, bool scan);
+int mt76x2_mcu_load_cr(struct mt76x02_dev *dev, u8 type, u8 temp_level,
+ u8 channel);
+
+void mt76x2_cleanup(struct mt76x02_dev *dev);
+
+void mt76x2_mac_set_tx_protection(struct mt76x02_dev *dev, u32 val);
+
+void mt76x2_pre_tbtt_tasklet(unsigned long arg);
+
+void mt76x2_sta_ps(struct mt76_dev *dev, struct ieee80211_sta *sta, bool ps);
+
+void mt76x2_update_channel(struct mt76_dev *mdev);
+
+void mt76x2_reset_wlan(struct mt76x02_dev *dev, bool enable);
+void mt76x2_init_txpower(struct mt76x02_dev *dev,
+ struct ieee80211_supported_band *sband);
+void mt76_write_mac_initvals(struct mt76x02_dev *dev);
+
+void mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev, bool wait);
+void mt76x2_phy_set_txpower_regs(struct mt76x02_dev *dev,
+ enum nl80211_band band);
+void mt76x2_configure_tx_delay(struct mt76x02_dev *dev,
+ enum nl80211_band band, u8 bw);
+void mt76x2_phy_set_bw(struct mt76x02_dev *dev, int width, u8 ctrl);
+void mt76x2_phy_set_band(struct mt76x02_dev *dev, int band, bool primary_upper);
+void mt76x2_apply_gain_adj(struct mt76x02_dev *dev);
+
+#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2u.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h
index a0ff6472de1f..6e932b5010ef 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2u.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h
@@ -20,8 +20,7 @@
#include <linux/device.h>
#include "mt76x2.h"
-#include "mt76x2_mcu.h"
-#include "mt76x02_dma.h"
+#include "mcu.h"
#define MT7612U_EEPROM_SIZE 512
@@ -30,38 +29,31 @@
extern const struct ieee80211_ops mt76x2u_ops;
-struct mt76x2_dev *mt76x2u_alloc_device(struct device *pdev);
-int mt76x2u_register_device(struct mt76x2_dev *dev);
-int mt76x2u_init_hardware(struct mt76x2_dev *dev);
-void mt76x2u_cleanup(struct mt76x2_dev *dev);
-void mt76x2u_stop_hw(struct mt76x2_dev *dev);
+struct mt76x02_dev *mt76x2u_alloc_device(struct device *pdev);
+int mt76x2u_register_device(struct mt76x02_dev *dev);
+int mt76x2u_init_hardware(struct mt76x02_dev *dev);
+void mt76x2u_cleanup(struct mt76x02_dev *dev);
+void mt76x2u_stop_hw(struct mt76x02_dev *dev);
-void mt76x2u_mac_setaddr(struct mt76x2_dev *dev, u8 *addr);
-int mt76x2u_mac_reset(struct mt76x2_dev *dev);
-void mt76x2u_mac_resume(struct mt76x2_dev *dev);
-int mt76x2u_mac_start(struct mt76x2_dev *dev);
-int mt76x2u_mac_stop(struct mt76x2_dev *dev);
+int mt76x2u_mac_reset(struct mt76x02_dev *dev);
+void mt76x2u_mac_resume(struct mt76x02_dev *dev);
+int mt76x2u_mac_start(struct mt76x02_dev *dev);
+int mt76x2u_mac_stop(struct mt76x02_dev *dev);
-int mt76x2u_phy_set_channel(struct mt76x2_dev *dev,
+int mt76x2u_phy_set_channel(struct mt76x02_dev *dev,
struct cfg80211_chan_def *chandef);
void mt76x2u_phy_calibrate(struct work_struct *work);
-void mt76x2u_phy_channel_calibrate(struct mt76x2_dev *dev);
-void mt76x2u_phy_set_txdac(struct mt76x2_dev *dev);
-void mt76x2u_phy_set_rxpath(struct mt76x2_dev *dev);
+void mt76x2u_phy_channel_calibrate(struct mt76x02_dev *dev);
void mt76x2u_mcu_complete_urb(struct urb *urb);
-int mt76x2u_mcu_set_dynamic_vga(struct mt76x2_dev *dev, u8 channel, bool ap,
+int mt76x2u_mcu_set_dynamic_vga(struct mt76x02_dev *dev, u8 channel, bool ap,
bool ext, int rssi, u32 false_cca);
-int mt76x2u_mcu_init(struct mt76x2_dev *dev);
-int mt76x2u_mcu_fw_init(struct mt76x2_dev *dev);
+int mt76x2u_mcu_init(struct mt76x02_dev *dev);
+int mt76x2u_mcu_fw_init(struct mt76x02_dev *dev);
-int mt76x2u_alloc_queues(struct mt76x2_dev *dev);
-void mt76x2u_queues_deinit(struct mt76x2_dev *dev);
-void mt76x2u_stop_queues(struct mt76x2_dev *dev);
-int mt76x2u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
- struct sk_buff *skb, struct mt76_queue *q,
- struct mt76_wcid *wcid, struct ieee80211_sta *sta,
- u32 *tx_info);
+int mt76x2u_alloc_queues(struct mt76x02_dev *dev);
+void mt76x2u_queues_deinit(struct mt76x02_dev *dev);
+void mt76x2u_stop_queues(struct mt76x02_dev *dev);
int mt76x2u_skb_dma_info(struct sk_buff *skb, enum dma_msg_port port,
u32 flags);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_pci.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
index e66f047ea448..92432fe97312 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
@@ -19,7 +19,6 @@
#include <linux/pci.h>
#include "mt76x2.h"
-#include "mt76x2_trace.h"
static const struct pci_device_id mt76pci_device_table[] = {
{ PCI_DEVICE(0x14c3, 0x7662) },
@@ -31,7 +30,7 @@ static const struct pci_device_id mt76pci_device_table[] = {
static int
mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
- struct mt76x2_dev *dev;
+ struct mt76x02_dev *dev;
int ret;
ret = pcim_enable_device(pdev);
@@ -53,11 +52,12 @@ mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return -ENOMEM;
mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
+ mt76x2_reset_wlan(dev, false);
dev->mt76.rev = mt76_rr(dev, MT_ASIC_VERSION);
dev_info(dev->mt76.dev, "ASIC revision: %08x\n", dev->mt76.rev);
- ret = devm_request_irq(dev->mt76.dev, pdev->irq, mt76x2_irq_handler,
+ ret = devm_request_irq(dev->mt76.dev, pdev->irq, mt76x02_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (ret)
goto error;
@@ -88,7 +88,7 @@ static void
mt76pci_remove(struct pci_dev *pdev)
{
struct mt76_dev *mdev = pci_get_drvdata(pdev);
- struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76);
+ struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
mt76_unregister_device(mdev);
mt76x2_cleanup(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_dfs.c
index 374cc655c11d..b56febae8945 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_dfs.c
@@ -36,7 +36,7 @@
.pwr_jmp = power_jmp \
}
-static const struct mt76x2_radar_specs etsi_radar_specs[] = {
+static const struct mt76x02_radar_specs etsi_radar_specs[] = {
/* 20MHz */
RADAR_SPEC(0, 8, 2, 15, 106, 150, 10, 4900, 100096, 10, 0,
0x7fffffff, 0x155cc0, 0x19cc),
@@ -66,7 +66,7 @@ static const struct mt76x2_radar_specs etsi_radar_specs[] = {
0x7fffffff, 0x2191c0, 0x15cc)
};
-static const struct mt76x2_radar_specs fcc_radar_specs[] = {
+static const struct mt76x02_radar_specs fcc_radar_specs[] = {
/* 20MHz */
RADAR_SPEC(0, 8, 2, 12, 106, 150, 5, 2900, 80100, 5, 0,
0x7fffffff, 0xfe808, 0x13dc),
@@ -96,7 +96,7 @@ static const struct mt76x2_radar_specs fcc_radar_specs[] = {
0x3938700, 0x57bcf00, 0x1289)
};
-static const struct mt76x2_radar_specs jp_w56_radar_specs[] = {
+static const struct mt76x02_radar_specs jp_w56_radar_specs[] = {
/* 20MHz */
RADAR_SPEC(0, 8, 2, 7, 106, 150, 5, 2900, 80100, 5, 0,
0x7fffffff, 0x14c080, 0x13dc),
@@ -126,7 +126,7 @@ static const struct mt76x2_radar_specs jp_w56_radar_specs[] = {
0x3938700, 0X57bcf00, 0x1289)
};
-static const struct mt76x2_radar_specs jp_w53_radar_specs[] = {
+static const struct mt76x02_radar_specs jp_w53_radar_specs[] = {
/* 20MHz */
RADAR_SPEC(0, 8, 2, 9, 106, 150, 20, 28400, 77000, 20, 0,
0x7fffffff, 0x14c080, 0x16cc),
@@ -150,8 +150,9 @@ static const struct mt76x2_radar_specs jp_w53_radar_specs[] = {
{ 0 }
};
-static void mt76x2_dfs_set_capture_mode_ctrl(struct mt76x2_dev *dev,
- u8 enable)
+static void
+mt76x2_dfs_set_capture_mode_ctrl(struct mt76x02_dev *dev,
+ u8 enable)
{
u32 data;
@@ -159,10 +160,10 @@ static void mt76x2_dfs_set_capture_mode_ctrl(struct mt76x2_dev *dev,
mt76_wr(dev, MT_BBP(DFS, 36), data);
}
-static void mt76x2_dfs_seq_pool_put(struct mt76x2_dev *dev,
- struct mt76x2_dfs_sequence *seq)
+static void mt76x2_dfs_seq_pool_put(struct mt76x02_dev *dev,
+ struct mt76x02_dfs_sequence *seq)
{
- struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
+ struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
list_add(&seq->head, &dfs_pd->seq_pool);
@@ -170,17 +171,17 @@ static void mt76x2_dfs_seq_pool_put(struct mt76x2_dev *dev,
dfs_pd->seq_stats.seq_len--;
}
-static
-struct mt76x2_dfs_sequence *mt76x2_dfs_seq_pool_get(struct mt76x2_dev *dev)
+static struct mt76x02_dfs_sequence *
+mt76x2_dfs_seq_pool_get(struct mt76x02_dev *dev)
{
- struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
- struct mt76x2_dfs_sequence *seq;
+ struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
+ struct mt76x02_dfs_sequence *seq;
if (list_empty(&dfs_pd->seq_pool)) {
seq = devm_kzalloc(dev->mt76.dev, sizeof(*seq), GFP_ATOMIC);
} else {
seq = list_first_entry(&dfs_pd->seq_pool,
- struct mt76x2_dfs_sequence,
+ struct mt76x02_dfs_sequence,
head);
list_del(&seq->head);
dfs_pd->seq_stats.seq_pool_len--;
@@ -213,10 +214,10 @@ static int mt76x2_dfs_get_multiple(int val, int frac, int margin)
return factor;
}
-static void mt76x2_dfs_detector_reset(struct mt76x2_dev *dev)
+static void mt76x2_dfs_detector_reset(struct mt76x02_dev *dev)
{
- struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
- struct mt76x2_dfs_sequence *seq, *tmp_seq;
+ struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
+ struct mt76x02_dfs_sequence *seq, *tmp_seq;
int i;
/* reset hw detector */
@@ -234,11 +235,11 @@ static void mt76x2_dfs_detector_reset(struct mt76x2_dev *dev)
}
}
-static bool mt76x2_dfs_check_chirp(struct mt76x2_dev *dev)
+static bool mt76x2_dfs_check_chirp(struct mt76x02_dev *dev)
{
bool ret = false;
u32 current_ts, delta_ts;
- struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
+ struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
current_ts = mt76_rr(dev, MT_PBF_LIFE_TIMER);
delta_ts = current_ts - dfs_pd->chirp_pulse_ts;
@@ -255,8 +256,8 @@ static bool mt76x2_dfs_check_chirp(struct mt76x2_dev *dev)
return ret;
}
-static void mt76x2_dfs_get_hw_pulse(struct mt76x2_dev *dev,
- struct mt76x2_dfs_hw_pulse *pulse)
+static void mt76x2_dfs_get_hw_pulse(struct mt76x02_dev *dev,
+ struct mt76x02_dfs_hw_pulse *pulse)
{
u32 data;
@@ -275,8 +276,8 @@ static void mt76x2_dfs_get_hw_pulse(struct mt76x2_dev *dev,
pulse->burst = mt76_rr(dev, MT_BBP(DFS, 22));
}
-static bool mt76x2_dfs_check_hw_pulse(struct mt76x2_dev *dev,
- struct mt76x2_dfs_hw_pulse *pulse)
+static bool mt76x2_dfs_check_hw_pulse(struct mt76x02_dev *dev,
+ struct mt76x02_dfs_hw_pulse *pulse)
{
bool ret = false;
@@ -370,8 +371,8 @@ static bool mt76x2_dfs_check_hw_pulse(struct mt76x2_dev *dev,
return ret;
}
-static bool mt76x2_dfs_fetch_event(struct mt76x2_dev *dev,
- struct mt76x2_dfs_event *event)
+static bool mt76x2_dfs_fetch_event(struct mt76x02_dev *dev,
+ struct mt76x02_dfs_event *event)
{
u32 data;
@@ -397,12 +398,12 @@ static bool mt76x2_dfs_fetch_event(struct mt76x2_dev *dev,
return true;
}
-static bool mt76x2_dfs_check_event(struct mt76x2_dev *dev,
- struct mt76x2_dfs_event *event)
+static bool mt76x2_dfs_check_event(struct mt76x02_dev *dev,
+ struct mt76x02_dfs_event *event)
{
if (event->engine == 2) {
- struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
- struct mt76x2_dfs_event_rb *event_buff = &dfs_pd->event_rb[1];
+ struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
+ struct mt76x02_dfs_event_rb *event_buff = &dfs_pd->event_rb[1];
u16 last_event_idx;
u32 delta_ts;
@@ -416,11 +417,11 @@ static bool mt76x2_dfs_check_event(struct mt76x2_dev *dev,
return true;
}
-static void mt76x2_dfs_queue_event(struct mt76x2_dev *dev,
- struct mt76x2_dfs_event *event)
+static void mt76x2_dfs_queue_event(struct mt76x02_dev *dev,
+ struct mt76x02_dfs_event *event)
{
- struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
- struct mt76x2_dfs_event_rb *event_buff;
+ struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
+ struct mt76x02_dfs_event_rb *event_buff;
/* add radar event to ring buffer */
event_buff = event->engine == 2 ? &dfs_pd->event_rb[1]
@@ -434,16 +435,16 @@ static void mt76x2_dfs_queue_event(struct mt76x2_dev *dev,
MT_DFS_EVENT_BUFLEN);
}
-static int mt76x2_dfs_create_sequence(struct mt76x2_dev *dev,
- struct mt76x2_dfs_event *event,
+static int mt76x2_dfs_create_sequence(struct mt76x02_dev *dev,
+ struct mt76x02_dfs_event *event,
u16 cur_len)
{
- struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
- struct mt76x2_dfs_sw_detector_params *sw_params;
+ struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
+ struct mt76x02_dfs_sw_detector_params *sw_params;
u32 width_delta, with_sum, factor, cur_pri;
- struct mt76x2_dfs_sequence seq, *seq_p;
- struct mt76x2_dfs_event_rb *event_rb;
- struct mt76x2_dfs_event *cur_event;
+ struct mt76x02_dfs_sequence seq, *seq_p;
+ struct mt76x02_dfs_event_rb *event_rb;
+ struct mt76x02_dfs_event *cur_event;
int i, j, end, pri;
event_rb = event->engine == 2 ? &dfs_pd->event_rb[1]
@@ -521,12 +522,12 @@ next:
return 0;
}
-static u16 mt76x2_dfs_add_event_to_sequence(struct mt76x2_dev *dev,
- struct mt76x2_dfs_event *event)
+static u16 mt76x2_dfs_add_event_to_sequence(struct mt76x02_dev *dev,
+ struct mt76x02_dfs_event *event)
{
- struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
- struct mt76x2_dfs_sw_detector_params *sw_params;
- struct mt76x2_dfs_sequence *seq, *tmp_seq;
+ struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
+ struct mt76x02_dfs_sw_detector_params *sw_params;
+ struct mt76x02_dfs_sequence *seq, *tmp_seq;
u16 max_seq_len = 0;
u32 factor, pri;
@@ -553,10 +554,10 @@ static u16 mt76x2_dfs_add_event_to_sequence(struct mt76x2_dev *dev,
return max_seq_len;
}
-static bool mt76x2_dfs_check_detection(struct mt76x2_dev *dev)
+static bool mt76x2_dfs_check_detection(struct mt76x02_dev *dev)
{
- struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
- struct mt76x2_dfs_sequence *seq;
+ struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
+ struct mt76x02_dfs_sequence *seq;
if (list_empty(&dfs_pd->sequences))
return false;
@@ -570,10 +571,10 @@ static bool mt76x2_dfs_check_detection(struct mt76x2_dev *dev)
return false;
}
-static void mt76x2_dfs_add_events(struct mt76x2_dev *dev)
+static void mt76x2_dfs_add_events(struct mt76x02_dev *dev)
{
- struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
- struct mt76x2_dfs_event event;
+ struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
+ struct mt76x02_dfs_event event;
int i, seq_len;
/* disable debug mode */
@@ -597,11 +598,11 @@ static void mt76x2_dfs_add_events(struct mt76x2_dev *dev)
mt76x2_dfs_set_capture_mode_ctrl(dev, true);
}
-static void mt76x2_dfs_check_event_window(struct mt76x2_dev *dev)
+static void mt76x2_dfs_check_event_window(struct mt76x02_dev *dev)
{
- struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
- struct mt76x2_dfs_event_rb *event_buff;
- struct mt76x2_dfs_event *event;
+ struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
+ struct mt76x02_dfs_event_rb *event_buff;
+ struct mt76x02_dfs_event *event;
int i;
for (i = 0; i < ARRAY_SIZE(dfs_pd->event_rb); i++) {
@@ -622,8 +623,8 @@ static void mt76x2_dfs_check_event_window(struct mt76x2_dev *dev)
static void mt76x2_dfs_tasklet(unsigned long arg)
{
- struct mt76x2_dev *dev = (struct mt76x2_dev *)arg;
- struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
+ struct mt76x02_dev *dev = (struct mt76x02_dev *)arg;
+ struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
u32 engine_mask;
int i;
@@ -653,7 +654,7 @@ static void mt76x2_dfs_tasklet(unsigned long arg)
goto out;
for (i = 0; i < MT_DFS_NUM_ENGINES; i++) {
- struct mt76x2_dfs_hw_pulse pulse;
+ struct mt76x02_dfs_hw_pulse pulse;
if (!(engine_mask & (1 << i)))
continue;
@@ -678,12 +679,12 @@ static void mt76x2_dfs_tasklet(unsigned long arg)
mt76_wr(dev, MT_BBP(DFS, 1), 0xf);
out:
- mt76x2_irq_enable(dev, MT_INT_GPTIMER);
+ mt76x02_irq_enable(dev, MT_INT_GPTIMER);
}
-static void mt76x2_dfs_init_sw_detector(struct mt76x2_dev *dev)
+static void mt76x2_dfs_init_sw_detector(struct mt76x02_dev *dev)
{
- struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
+ struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
switch (dev->dfs_pd.region) {
case NL80211_DFS_FCC:
@@ -707,11 +708,11 @@ static void mt76x2_dfs_init_sw_detector(struct mt76x2_dev *dev)
}
}
-static void mt76x2_dfs_set_bbp_params(struct mt76x2_dev *dev)
+static void mt76x2_dfs_set_bbp_params(struct mt76x02_dev *dev)
{
- u32 data;
+ const struct mt76x02_radar_specs *radar_specs;
u8 i, shift;
- const struct mt76x2_radar_specs *radar_specs;
+ u32 data;
switch (dev->mt76.chandef.width) {
case NL80211_CHAN_WIDTH_40:
@@ -802,7 +803,7 @@ static void mt76x2_dfs_set_bbp_params(struct mt76x2_dev *dev)
mt76_wr(dev, 0x212c, 0x0c350001);
}
-void mt76x2_dfs_adjust_agc(struct mt76x2_dev *dev)
+void mt76x2_dfs_adjust_agc(struct mt76x02_dev *dev)
{
u32 agc_r8, agc_r4, val_r8, val_r4, dfs_r31;
@@ -823,7 +824,7 @@ void mt76x2_dfs_adjust_agc(struct mt76x2_dev *dev)
mt76_wr(dev, MT_BBP(DFS, 32), 0x00040071);
}
-void mt76x2_dfs_init_params(struct mt76x2_dev *dev)
+void mt76x2_dfs_init_params(struct mt76x02_dev *dev)
{
struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
@@ -834,7 +835,7 @@ void mt76x2_dfs_init_params(struct mt76x2_dev *dev)
/* enable debug mode */
mt76x2_dfs_set_capture_mode_ctrl(dev, true);
- mt76x2_irq_enable(dev, MT_INT_GPTIMER);
+ mt76x02_irq_enable(dev, MT_INT_GPTIMER);
mt76_rmw_field(dev, MT_INT_TIMER_EN,
MT_INT_TIMER_EN_GP_TIMER_EN, 1);
} else {
@@ -844,15 +845,15 @@ void mt76x2_dfs_init_params(struct mt76x2_dev *dev)
mt76_wr(dev, MT_BBP(DFS, 1), 0xf);
mt76_wr(dev, 0x212c, 0);
- mt76x2_irq_disable(dev, MT_INT_GPTIMER);
+ mt76x02_irq_disable(dev, MT_INT_GPTIMER);
mt76_rmw_field(dev, MT_INT_TIMER_EN,
MT_INT_TIMER_EN_GP_TIMER_EN, 0);
}
}
-void mt76x2_dfs_init_detector(struct mt76x2_dev *dev)
+void mt76x2_dfs_init_detector(struct mt76x02_dev *dev)
{
- struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
+ struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
INIT_LIST_HEAD(&dfs_pd->sequences);
INIT_LIST_HEAD(&dfs_pd->seq_pool);
@@ -862,10 +863,10 @@ void mt76x2_dfs_init_detector(struct mt76x2_dev *dev)
(unsigned long)dev);
}
-void mt76x2_dfs_set_domain(struct mt76x2_dev *dev,
+void mt76x2_dfs_set_domain(struct mt76x02_dev *dev,
enum nl80211_dfs_regions region)
{
- struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
+ struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
if (dfs_pd->region != region) {
tasklet_disable(&dfs_pd->dfs_tasklet);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c
index 33f7fabf45c0..f229c6eb65dc 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c
@@ -16,12 +16,11 @@
#include <linux/delay.h>
#include "mt76x2.h"
-#include "mt76x2_eeprom.h"
-#include "mt76x2_mcu.h"
-#include "mt76x02_util.h"
+#include "eeprom.h"
+#include "mcu.h"
static void
-mt76x2_mac_pbf_init(struct mt76x2_dev *dev)
+mt76x2_mac_pbf_init(struct mt76x02_dev *dev)
{
u32 val;
@@ -39,12 +38,12 @@ mt76x2_mac_pbf_init(struct mt76x2_dev *dev)
}
static void
-mt76x2_fixup_xtal(struct mt76x2_dev *dev)
+mt76x2_fixup_xtal(struct mt76x02_dev *dev)
{
u16 eep_val;
s8 offset = 0;
- eep_val = mt76x2_eeprom_get(dev, MT_EE_XTAL_TRIM_2);
+ eep_val = mt76x02_eeprom_get(&dev->mt76, MT_EE_XTAL_TRIM_2);
offset = eep_val & 0x7f;
if ((eep_val & 0xff) == 0xff)
@@ -54,7 +53,7 @@ mt76x2_fixup_xtal(struct mt76x2_dev *dev)
eep_val >>= 8;
if (eep_val == 0x00 || eep_val == 0xff) {
- eep_val = mt76x2_eeprom_get(dev, MT_EE_XTAL_TRIM_1);
+ eep_val = mt76x02_eeprom_get(&dev->mt76, MT_EE_XTAL_TRIM_1);
eep_val &= 0xff;
if (eep_val == 0x00 || eep_val == 0xff)
@@ -65,7 +64,7 @@ mt76x2_fixup_xtal(struct mt76x2_dev *dev)
mt76_rmw_field(dev, MT_XO_CTRL5, MT_XO_CTRL5_C2_VAL, eep_val + offset);
mt76_set(dev, MT_XO_CTRL6, MT_XO_CTRL6_C2_CTRL);
- eep_val = mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_2);
+ eep_val = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_2);
switch (FIELD_GET(MT_EE_NIC_CONF_2_XTAL_OPTION, eep_val)) {
case 0:
mt76_wr(dev, MT_XO_CTRL7, 0x5c1fee80);
@@ -78,24 +77,7 @@ mt76x2_fixup_xtal(struct mt76x2_dev *dev)
}
}
-static void
-mt76x2_init_beacon_offsets(struct mt76x2_dev *dev)
-{
- u16 base = MT_BEACON_BASE;
- u32 regs[4] = {};
- int i;
-
- for (i = 0; i < 16; i++) {
- u16 addr = dev->beacon_offsets[i];
-
- regs[i / 4] |= ((addr - base) / 64) << (8 * (i % 4));
- }
-
- for (i = 0; i < 4; i++)
- mt76_wr(dev, MT_BCN_OFFSET(i), regs[i]);
-}
-
-static int mt76x2_mac_reset(struct mt76x2_dev *dev, bool hard)
+static int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard)
{
static const u8 null_addr[ETH_ALEN] = {};
const u8 *macaddr = dev->mt76.macaddr;
@@ -186,14 +168,14 @@ static int mt76x2_mac_reset(struct mt76x2_dev *dev, bool hard)
MT_CH_TIME_CFG_EIFS_AS_BUSY |
FIELD_PREP(MT_CH_TIME_CFG_CH_TIMER_CLR, 1));
- mt76x2_init_beacon_offsets(dev);
+ mt76x02_set_beacon_offsets(&dev->mt76);
mt76x2_set_tx_ackto(dev);
return 0;
}
-int mt76x2_mac_start(struct mt76x2_dev *dev)
+int mt76x2_mac_start(struct mt76x02_dev *dev)
{
int i;
@@ -204,30 +186,12 @@ int mt76x2_mac_start(struct mt76x2_dev *dev)
mt76_rr(dev, MT_TX_STAT_FIFO);
memset(dev->aggr_stats, 0, sizeof(dev->aggr_stats));
-
- mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX);
- wait_for_wpdma(dev);
- usleep_range(50, 100);
-
- mt76_set(dev, MT_WPDMA_GLO_CFG,
- MT_WPDMA_GLO_CFG_TX_DMA_EN |
- MT_WPDMA_GLO_CFG_RX_DMA_EN);
-
- mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);
-
- mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter);
-
- mt76_wr(dev, MT_MAC_SYS_CTRL,
- MT_MAC_SYS_CTRL_ENABLE_TX |
- MT_MAC_SYS_CTRL_ENABLE_RX);
-
- mt76x2_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
- MT_INT_TX_STAT);
+ mt76x02_mac_start(dev);
return 0;
}
-void mt76x2_mac_resume(struct mt76x2_dev *dev)
+void mt76x2_mac_resume(struct mt76x02_dev *dev)
{
mt76_wr(dev, MT_MAC_SYS_CTRL,
MT_MAC_SYS_CTRL_ENABLE_TX |
@@ -235,7 +199,7 @@ void mt76x2_mac_resume(struct mt76x2_dev *dev)
}
static void
-mt76x2_power_on_rf_patch(struct mt76x2_dev *dev)
+mt76x2_power_on_rf_patch(struct mt76x02_dev *dev)
{
mt76_set(dev, 0x10130, BIT(0) | BIT(16));
udelay(1);
@@ -256,7 +220,7 @@ mt76x2_power_on_rf_patch(struct mt76x2_dev *dev)
}
static void
-mt76x2_power_on_rf(struct mt76x2_dev *dev, int unit)
+mt76x2_power_on_rf(struct mt76x02_dev *dev, int unit)
{
int shift = unit ? 8 : 0;
@@ -278,7 +242,7 @@ mt76x2_power_on_rf(struct mt76x2_dev *dev, int unit)
}
static void
-mt76x2_power_on(struct mt76x2_dev *dev)
+mt76x2_power_on(struct mt76x02_dev *dev)
{
u32 val;
@@ -313,7 +277,7 @@ mt76x2_power_on(struct mt76x2_dev *dev)
mt76x2_power_on_rf(dev, 1);
}
-void mt76x2_set_tx_ackto(struct mt76x2_dev *dev)
+void mt76x2_set_tx_ackto(struct mt76x02_dev *dev)
{
u8 ackto, sifs, slottime = dev->slottime;
@@ -330,43 +294,14 @@ void mt76x2_set_tx_ackto(struct mt76x2_dev *dev)
MT_TX_TIMEOUT_CFG_ACKTO, ackto);
}
-int mt76x2_init_hardware(struct mt76x2_dev *dev)
+int mt76x2_init_hardware(struct mt76x02_dev *dev)
{
- static const u16 beacon_offsets[16] = {
- /* 1024 byte per beacon */
- 0xc000,
- 0xc400,
- 0xc800,
- 0xcc00,
- 0xd000,
- 0xd400,
- 0xd800,
- 0xdc00,
-
- /* BSS idx 8-15 not used for beacons */
- 0xc000,
- 0xc000,
- 0xc000,
- 0xc000,
- 0xc000,
- 0xc000,
- 0xc000,
- 0xc000,
- };
- u32 val;
int ret;
- dev->beacon_offsets = beacon_offsets;
tasklet_init(&dev->pre_tbtt_tasklet, mt76x2_pre_tbtt_tasklet,
(unsigned long) dev);
- val = mt76_rr(dev, MT_WPDMA_GLO_CFG);
- val &= MT_WPDMA_GLO_CFG_DMA_BURST_SIZE |
- MT_WPDMA_GLO_CFG_BIG_ENDIAN |
- MT_WPDMA_GLO_CFG_HDR_SEG_LEN;
- val |= MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE;
- mt76_wr(dev, MT_WPDMA_GLO_CFG, val);
-
+ mt76x02_dma_disable(dev);
mt76x2_reset_wlan(dev, true);
mt76x2_power_on(dev);
@@ -380,7 +315,7 @@ int mt76x2_init_hardware(struct mt76x2_dev *dev)
dev->mt76.rxfilter = mt76_rr(dev, MT_RX_FILTR_CFG);
- ret = mt76x2_dma_init(dev);
+ ret = mt76x02_dma_init(dev);
if (ret)
return ret;
@@ -398,7 +333,7 @@ int mt76x2_init_hardware(struct mt76x2_dev *dev)
return 0;
}
-void mt76x2_stop_hardware(struct mt76x2_dev *dev)
+void mt76x2_stop_hardware(struct mt76x02_dev *dev)
{
cancel_delayed_work_sync(&dev->cal_work);
cancel_delayed_work_sync(&dev->mac_work);
@@ -406,38 +341,36 @@ void mt76x2_stop_hardware(struct mt76x2_dev *dev)
mt76x2_mac_stop(dev, false);
}
-void mt76x2_cleanup(struct mt76x2_dev *dev)
+void mt76x2_cleanup(struct mt76x02_dev *dev)
{
tasklet_disable(&dev->dfs_pd.dfs_tasklet);
tasklet_disable(&dev->pre_tbtt_tasklet);
mt76x2_stop_hardware(dev);
- mt76x2_dma_cleanup(dev);
+ mt76x02_dma_cleanup(dev);
mt76x02_mcu_cleanup(&dev->mt76);
}
-struct mt76x2_dev *mt76x2_alloc_device(struct device *pdev)
+struct mt76x02_dev *mt76x2_alloc_device(struct device *pdev)
{
static const struct mt76_driver_ops drv_ops = {
.txwi_size = sizeof(struct mt76x02_txwi),
.update_survey = mt76x2_update_channel,
- .tx_prepare_skb = mt76x2_tx_prepare_skb,
- .tx_complete_skb = mt76x2_tx_complete_skb,
- .rx_skb = mt76x2_queue_rx_skb,
- .rx_poll_complete = mt76x2_rx_poll_complete,
+ .tx_prepare_skb = mt76x02_tx_prepare_skb,
+ .tx_complete_skb = mt76x02_tx_complete_skb,
+ .rx_skb = mt76x02_queue_rx_skb,
+ .rx_poll_complete = mt76x02_rx_poll_complete,
.sta_ps = mt76x2_sta_ps,
- .get_max_txpwr_adj = mt76x2_tx_get_max_txpwr_adj,
};
- struct mt76x2_dev *dev;
+ struct mt76x02_dev *dev;
struct mt76_dev *mdev;
mdev = mt76_alloc_device(sizeof(*dev), &mt76x2_ops);
if (!mdev)
return NULL;
- dev = container_of(mdev, struct mt76x2_dev, mt76);
+ dev = container_of(mdev, struct mt76x02_dev, mt76);
mdev->dev = pdev;
mdev->drv = &drv_ops;
- spin_lock_init(&dev->irq_lock);
return dev;
}
@@ -446,7 +379,7 @@ static void mt76x2_regd_notifier(struct wiphy *wiphy,
struct regulatory_request *request)
{
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
- struct mt76x2_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
mt76x2_dfs_set_domain(dev, request->dfs_region);
}
@@ -482,8 +415,8 @@ static const struct ieee80211_iface_combination if_comb[] = {
static void mt76x2_led_set_config(struct mt76_dev *mt76, u8 delay_on,
u8 delay_off)
{
- struct mt76x2_dev *dev = container_of(mt76, struct mt76x2_dev,
- mt76);
+ struct mt76x02_dev *dev = container_of(mt76, struct mt76x02_dev,
+ mt76);
u32 val;
val = MT_LED_STATUS_DURATION(0xff) |
@@ -527,20 +460,12 @@ static void mt76x2_led_set_brightness(struct led_classdev *led_cdev,
mt76x2_led_set_config(mt76, 0xff, 0);
}
-int mt76x2_register_device(struct mt76x2_dev *dev)
+int mt76x2_register_device(struct mt76x02_dev *dev)
{
struct ieee80211_hw *hw = mt76_hw(dev);
struct wiphy *wiphy = hw->wiphy;
- void *status_fifo;
- int fifo_size;
int i, ret;
- fifo_size = roundup_pow_of_two(32 * sizeof(struct mt76x02_tx_status));
- status_fifo = devm_kzalloc(dev->mt76.dev, fifo_size, GFP_KERNEL);
- if (!status_fifo)
- return -ENOMEM;
-
- kfifo_init(&dev->txstatus_fifo, status_fifo, fifo_size);
INIT_DELAYED_WORK(&dev->cal_work, mt76x2_phy_calibrate);
INIT_DELAYED_WORK(&dev->mac_work, mt76x2_mac_work);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mac.c
index 241ede98e6d3..08366c5988ea 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mac.c
@@ -16,12 +16,10 @@
#include <linux/delay.h>
#include "mt76x2.h"
-#include "mt76x2_mcu.h"
-#include "mt76x2_eeprom.h"
-#include "mt76x2_trace.h"
-#include "mt76x02_util.h"
+#include "mcu.h"
+#include "eeprom.h"
-void mt76x2_mac_set_bssid(struct mt76x2_dev *dev, u8 idx, const u8 *addr)
+void mt76x2_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr)
{
idx &= 7;
mt76_wr(dev, MT_MAC_APC_BSSID_L(idx), get_unaligned_le32(addr));
@@ -29,84 +27,16 @@ void mt76x2_mac_set_bssid(struct mt76x2_dev *dev, u8 idx, const u8 *addr)
get_unaligned_le16(addr + 4));
}
-void mt76x2_mac_poll_tx_status(struct mt76x2_dev *dev, bool irq)
-{
- struct mt76x02_tx_status stat = {};
- unsigned long flags;
- u8 update = 1;
- bool ret;
-
- if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state))
- return;
-
- trace_mac_txstat_poll(dev);
-
- while (!irq || !kfifo_is_full(&dev->txstatus_fifo)) {
- spin_lock_irqsave(&dev->irq_lock, flags);
- ret = mt76x02_mac_load_tx_status(&dev->mt76, &stat);
- spin_unlock_irqrestore(&dev->irq_lock, flags);
-
- if (!ret)
- break;
-
- trace_mac_txstat_fetch(dev, &stat);
-
- if (!irq) {
- mt76x02_send_tx_status(&dev->mt76, &stat, &update);
- continue;
- }
-
- kfifo_put(&dev->txstatus_fifo, stat);
- }
-}
-
-static void
-mt76x2_mac_queue_txdone(struct mt76x2_dev *dev, struct sk_buff *skb,
- void *txwi_ptr)
-{
- struct mt76x2_tx_info *txi = mt76x2_skb_tx_info(skb);
- struct mt76x02_txwi *txwi = txwi_ptr;
-
- mt76x2_mac_poll_tx_status(dev, false);
-
- txi->tries = 0;
- txi->jiffies = jiffies;
- txi->wcid = txwi->wcid;
- txi->pktid = txwi->pktid;
- trace_mac_txdone_add(dev, txwi->wcid, txwi->pktid);
- mt76x02_tx_complete(&dev->mt76, skb);
-}
-
-void mt76x2_mac_process_tx_status_fifo(struct mt76x2_dev *dev)
-{
- struct mt76x02_tx_status stat;
- u8 update = 1;
-
- while (kfifo_get(&dev->txstatus_fifo, &stat))
- mt76x02_send_tx_status(&dev->mt76, &stat, &update);
-}
-
-void mt76x2_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
- struct mt76_queue_entry *e, bool flush)
-{
- struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76);
-
- if (e->txwi)
- mt76x2_mac_queue_txdone(dev, e->skb, &e->txwi->txwi);
- else
- dev_kfree_skb_any(e->skb);
-}
-
static int
-mt76_write_beacon(struct mt76x2_dev *dev, int offset, struct sk_buff *skb)
+mt76_write_beacon(struct mt76x02_dev *dev, int offset, struct sk_buff *skb)
{
- int beacon_len = dev->beacon_offsets[1] - dev->beacon_offsets[0];
+ int beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0];
struct mt76x02_txwi txwi;
if (WARN_ON_ONCE(beacon_len < skb->len + sizeof(struct mt76x02_txwi)))
return -ENOSPC;
- mt76x2_mac_write_txwi(dev, &txwi, skb, NULL, NULL, skb->len);
+ mt76x02_mac_write_txwi(&dev->mt76, &txwi, skb, NULL, NULL, skb->len);
mt76_wr_copy(dev, offset, &txwi, sizeof(txwi));
offset += sizeof(txwi);
@@ -116,10 +46,10 @@ mt76_write_beacon(struct mt76x2_dev *dev, int offset, struct sk_buff *skb)
}
static int
-__mt76x2_mac_set_beacon(struct mt76x2_dev *dev, u8 bcn_idx, struct sk_buff *skb)
+__mt76x2_mac_set_beacon(struct mt76x02_dev *dev, u8 bcn_idx, struct sk_buff *skb)
{
- int beacon_len = dev->beacon_offsets[1] - dev->beacon_offsets[0];
- int beacon_addr = dev->beacon_offsets[bcn_idx];
+ int beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0];
+ int beacon_addr = mt76x02_beacon_offsets[bcn_idx];
int ret = 0;
int i;
@@ -129,8 +59,7 @@ __mt76x2_mac_set_beacon(struct mt76x2_dev *dev, u8 bcn_idx, struct sk_buff *skb)
if (skb) {
ret = mt76_write_beacon(dev, beacon_addr, skb);
if (!ret)
- dev->beacon_data_mask |= BIT(bcn_idx) &
- dev->beacon_mask;
+ dev->beacon_data_mask |= BIT(bcn_idx);
} else {
dev->beacon_data_mask &= ~BIT(bcn_idx);
for (i = 0; i < beacon_len; i += 4)
@@ -142,7 +71,7 @@ __mt76x2_mac_set_beacon(struct mt76x2_dev *dev, u8 bcn_idx, struct sk_buff *skb)
return ret;
}
-int mt76x2_mac_set_beacon(struct mt76x2_dev *dev, u8 vif_idx,
+int mt76x2_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx,
struct sk_buff *skb)
{
bool force_update = false;
@@ -177,7 +106,8 @@ int mt76x2_mac_set_beacon(struct mt76x2_dev *dev, u8 vif_idx,
return 0;
}
-void mt76x2_mac_set_beacon_enable(struct mt76x2_dev *dev, u8 vif_idx, bool val)
+void mt76x2_mac_set_beacon_enable(struct mt76x02_dev *dev,
+ u8 vif_idx, bool val)
{
u8 old_mask = dev->beacon_mask;
bool en;
@@ -202,14 +132,14 @@ void mt76x2_mac_set_beacon_enable(struct mt76x2_dev *dev, u8 vif_idx, bool val)
mt76_rmw(dev, MT_BEACON_TIME_CFG, reg, reg * en);
if (en)
- mt76x2_irq_enable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT);
+ mt76x02_irq_enable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT);
else
- mt76x2_irq_disable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT);
+ mt76x02_irq_disable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT);
}
void mt76x2_update_channel(struct mt76_dev *mdev)
{
- struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76);
+ struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
struct mt76_channel_state *state;
u32 active, busy;
@@ -226,8 +156,8 @@ void mt76x2_update_channel(struct mt76_dev *mdev)
void mt76x2_mac_work(struct work_struct *work)
{
- struct mt76x2_dev *dev = container_of(work, struct mt76x2_dev,
- mac_work.work);
+ struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev,
+ mac_work.work);
int i, idx;
mt76x2_update_channel(&dev->mt76);
@@ -242,7 +172,7 @@ void mt76x2_mac_work(struct work_struct *work)
MT_CALIBRATE_INTERVAL);
}
-void mt76x2_mac_set_tx_protection(struct mt76x2_dev *dev, u32 val)
+void mt76x2_mac_set_tx_protection(struct mt76x02_dev *dev, u32 val)
{
u32 data = 0;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
index 7f0a89be154c..65fef082e7cc 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
@@ -15,12 +15,11 @@
*/
#include "mt76x2.h"
-#include "mt76x02_util.h"
static int
mt76x2_start(struct ieee80211_hw *hw)
{
- struct mt76x2_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
int ret;
mutex_lock(&dev->mt76.mutex);
@@ -46,7 +45,7 @@ out:
static void
mt76x2_stop(struct ieee80211_hw *hw)
{
- struct mt76x2_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
mutex_lock(&dev->mt76.mutex);
clear_bit(MT76_STATE_RUNNING, &dev->mt76.state);
@@ -55,7 +54,7 @@ mt76x2_stop(struct ieee80211_hw *hw)
}
static int
-mt76x2_set_channel(struct mt76x2_dev *dev, struct cfg80211_chan_def *chandef)
+mt76x2_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef)
{
int ret;
@@ -91,7 +90,7 @@ mt76x2_set_channel(struct mt76x2_dev *dev, struct cfg80211_chan_def *chandef)
static int
mt76x2_config(struct ieee80211_hw *hw, u32 changed)
{
- struct mt76x2_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
int ret = 0;
mutex_lock(&dev->mt76.mutex);
@@ -106,14 +105,14 @@ mt76x2_config(struct ieee80211_hw *hw, u32 changed)
}
if (changed & IEEE80211_CONF_CHANGE_POWER) {
- dev->txpower_conf = hw->conf.power_level * 2;
+ dev->mt76.txpower_conf = hw->conf.power_level * 2;
/* convert to per-chain power for 2x2 devices */
- dev->txpower_conf -= 6;
+ dev->mt76.txpower_conf -= 6;
if (test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) {
mt76x2_phy_set_txpower(dev);
- mt76x2_tx_set_txpwr_auto(dev, dev->txpower_conf);
+ mt76x02_tx_set_txpwr_auto(dev, dev->mt76.txpower_conf);
}
}
@@ -132,7 +131,7 @@ static void
mt76x2_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info, u32 changed)
{
- struct mt76x2_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
struct mt76x02_vif *mvif = (struct mt76x02_vif *) vif->drv_priv;
mutex_lock(&dev->mt76.mutex);
@@ -169,7 +168,7 @@ void
mt76x2_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps)
{
struct mt76x02_sta *msta = (struct mt76x02_sta *) sta->drv_priv;
- struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76);
+ struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
int idx = msta->wcid.idx;
mt76_stop_tx_queues(&dev->mt76, sta, true);
@@ -180,7 +179,7 @@ static void
mt76x2_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
const u8 *mac)
{
- struct mt76x2_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
tasklet_disable(&dev->pre_tbtt_tasklet);
set_bit(MT76_SCANNING, &dev->mt76.state);
@@ -189,7 +188,7 @@ mt76x2_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
static void
mt76x2_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
- struct mt76x2_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
clear_bit(MT76_SCANNING, &dev->mt76.state);
tasklet_enable(&dev->pre_tbtt_tasklet);
@@ -204,9 +203,9 @@ mt76x2_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
static int
mt76x2_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm)
{
- struct mt76x2_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
- *dbm = dev->txpower_cur / 2;
+ *dbm = dev->mt76.txpower_cur / 2;
/* convert from per-chain power to combined output on 2x2 devices */
*dbm += 3;
@@ -217,7 +216,7 @@ mt76x2_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm)
static void mt76x2_set_coverage_class(struct ieee80211_hw *hw,
s16 coverage_class)
{
- struct mt76x2_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
mutex_lock(&dev->mt76.mutex);
dev->coverage_class = coverage_class;
@@ -234,14 +233,14 @@ mt76x2_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
static int mt76x2_set_antenna(struct ieee80211_hw *hw, u32 tx_ant,
u32 rx_ant)
{
- struct mt76x2_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
if (!tx_ant || tx_ant > 3 || tx_ant != rx_ant)
return -EINVAL;
mutex_lock(&dev->mt76.mutex);
- dev->chainmask = (tx_ant == 3) ? 0x202 : 0x101;
+ dev->mt76.chainmask = (tx_ant == 3) ? 0x202 : 0x101;
dev->mt76.antenna_mask = tx_ant;
mt76_set_stream_caps(&dev->mt76, true);
@@ -255,7 +254,7 @@ static int mt76x2_set_antenna(struct ieee80211_hw *hw, u32 tx_ant,
static int mt76x2_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant,
u32 *rx_ant)
{
- struct mt76x2_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
mutex_lock(&dev->mt76.mutex);
*tx_ant = dev->mt76.antenna_mask;
@@ -268,7 +267,7 @@ static int mt76x2_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant,
static int
mt76x2_set_rts_threshold(struct ieee80211_hw *hw, u32 val)
{
- struct mt76x2_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
if (val != ~0 && val > 0xffff)
return -EINVAL;
@@ -281,7 +280,7 @@ mt76x2_set_rts_threshold(struct ieee80211_hw *hw, u32 val)
}
const struct ieee80211_ops mt76x2_ops = {
- .tx = mt76x2_tx,
+ .tx = mt76x02_tx,
.start = mt76x2_start,
.stop = mt76x2_stop,
.add_interface = mt76x02_add_interface,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c
index f92bebfa21fd..898aa229671c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c
@@ -19,12 +19,11 @@
#include <linux/delay.h>
#include "mt76x2.h"
-#include "mt76x2_mcu.h"
-#include "mt76x2_eeprom.h"
-#include "mt76x02_dma.h"
+#include "mcu.h"
+#include "eeprom.h"
static int
-mt76pci_load_rom_patch(struct mt76x2_dev *dev)
+mt76pci_load_rom_patch(struct mt76x02_dev *dev)
{
const struct firmware *fw = NULL;
struct mt76x02_patch_header *hdr;
@@ -90,7 +89,7 @@ out:
}
static int
-mt76pci_load_firmware(struct mt76x2_dev *dev)
+mt76pci_load_firmware(struct mt76x02_dev *dev)
{
const struct firmware *fw;
const struct mt76x02_fw_header *hdr;
@@ -141,7 +140,7 @@ mt76pci_load_firmware(struct mt76x2_dev *dev)
mt76_wr(dev, MT_MCU_PCIE_REMAP_BASE4, 0);
- val = mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_2);
+ val = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_2);
if (FIELD_GET(MT_EE_NIC_CONF_2_XTAL_OPTION, val) == 1)
mt76_set(dev, MT_MCU_COM_REG0, BIT(30));
@@ -154,6 +153,7 @@ mt76pci_load_firmware(struct mt76x2_dev *dev)
}
dev_info(dev->mt76.dev, "Firmware running!\n");
+ mt76x02_set_ethtool_fwver(&dev->mt76, hdr);
release_firmware(fw);
@@ -165,7 +165,7 @@ error:
return -ENOENT;
}
-int mt76x2_mcu_init(struct mt76x2_dev *dev)
+int mt76x2_mcu_init(struct mt76x02_dev *dev)
{
static const struct mt76_mcu_ops mt76x2_mcu_ops = {
.mcu_msg_alloc = mt76x02_mcu_msg_alloc,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c
index 920bb7c89af9..40ea5f7480fb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c
@@ -16,16 +16,17 @@
#include <linux/delay.h>
#include "mt76x2.h"
-#include "mt76x2_mcu.h"
-#include "mt76x2_eeprom.h"
+#include "mcu.h"
+#include "eeprom.h"
+#include "../mt76x02_phy.h"
static bool
-mt76x2_phy_tssi_init_cal(struct mt76x2_dev *dev)
+mt76x2_phy_tssi_init_cal(struct mt76x02_dev *dev)
{
struct ieee80211_channel *chan = dev->mt76.chandef.chan;
u32 flag = 0;
- if (!mt76x2_tssi_enabled(dev))
+ if (!mt76x02_tssi_enabled(&dev->mt76))
return false;
if (mt76x2_channel_silent(dev))
@@ -34,7 +35,7 @@ mt76x2_phy_tssi_init_cal(struct mt76x2_dev *dev)
if (chan->band == NL80211_BAND_5GHZ)
flag |= BIT(0);
- if (mt76x2_ext_pa_enabled(dev, chan->band))
+ if (mt76x02_ext_pa_enabled(&dev->mt76, chan->band))
flag |= BIT(8);
mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_TSSI, flag, true);
@@ -43,7 +44,7 @@ mt76x2_phy_tssi_init_cal(struct mt76x2_dev *dev)
}
static void
-mt76x2_phy_channel_calibrate(struct mt76x2_dev *dev, bool mac_stopped)
+mt76x2_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped)
{
struct ieee80211_channel *chan = dev->mt76.chandef.chan;
bool is_5ghz = chan->band == NL80211_BAND_5GHZ;
@@ -77,7 +78,7 @@ mt76x2_phy_channel_calibrate(struct mt76x2_dev *dev, bool mac_stopped)
dev->cal.channel_cal_done = true;
}
-void mt76x2_phy_set_antenna(struct mt76x2_dev *dev)
+void mt76x2_phy_set_antenna(struct mt76x02_dev *dev)
{
u32 val;
@@ -124,14 +125,14 @@ void mt76x2_phy_set_antenna(struct mt76x2_dev *dev)
}
static void
-mt76x2_get_agc_gain(struct mt76x2_dev *dev, u8 *dest)
+mt76x2_get_agc_gain(struct mt76x02_dev *dev, u8 *dest)
{
dest[0] = mt76_get_field(dev, MT_BBP(AGC, 8), MT_BBP_AGC_GAIN);
dest[1] = mt76_get_field(dev, MT_BBP(AGC, 9), MT_BBP_AGC_GAIN);
}
static int
-mt76x2_get_rssi_gain_thresh(struct mt76x2_dev *dev)
+mt76x2_get_rssi_gain_thresh(struct mt76x02_dev *dev)
{
switch (dev->mt76.chandef.width) {
case NL80211_CHAN_WIDTH_80:
@@ -144,7 +145,7 @@ mt76x2_get_rssi_gain_thresh(struct mt76x2_dev *dev)
}
static int
-mt76x2_get_low_rssi_gain_thresh(struct mt76x2_dev *dev)
+mt76x2_get_low_rssi_gain_thresh(struct mt76x02_dev *dev)
{
switch (dev->mt76.chandef.width) {
case NL80211_CHAN_WIDTH_80:
@@ -157,7 +158,7 @@ mt76x2_get_low_rssi_gain_thresh(struct mt76x2_dev *dev)
}
static void
-mt76x2_phy_set_gain_val(struct mt76x2_dev *dev)
+mt76x2_phy_set_gain_val(struct mt76x02_dev *dev)
{
u32 val;
u8 gain_val[2];
@@ -182,7 +183,7 @@ mt76x2_phy_set_gain_val(struct mt76x2_dev *dev)
}
static void
-mt76x2_phy_adjust_vga_gain(struct mt76x2_dev *dev)
+mt76x2_phy_adjust_vga_gain(struct mt76x02_dev *dev)
{
u32 false_cca;
u8 limit = dev->cal.low_gain > 0 ? 16 : 4;
@@ -201,7 +202,7 @@ mt76x2_phy_adjust_vga_gain(struct mt76x2_dev *dev)
}
static void
-mt76x2_phy_update_channel_gain(struct mt76x2_dev *dev)
+mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev)
{
u8 *gain = dev->cal.agc_gain_init;
u8 low_gain_delta, gain_delta;
@@ -209,7 +210,7 @@ mt76x2_phy_update_channel_gain(struct mt76x2_dev *dev)
int low_gain;
u32 val;
- dev->cal.avg_rssi_all = mt76x2_phy_get_min_avg_rssi(dev);
+ dev->cal.avg_rssi_all = mt76x02_phy_get_min_avg_rssi(&dev->mt76);
low_gain = (dev->cal.avg_rssi_all > mt76x2_get_rssi_gain_thresh(dev)) +
(dev->cal.avg_rssi_all > mt76x2_get_low_rssi_gain_thresh(dev));
@@ -264,7 +265,7 @@ mt76x2_phy_update_channel_gain(struct mt76x2_dev *dev)
mt76_rr(dev, MT_RX_STAT_1);
}
-int mt76x2_phy_set_channel(struct mt76x2_dev *dev,
+int mt76x2_phy_set_channel(struct mt76x02_dev *dev,
struct cfg80211_chan_def *chandef)
{
struct ieee80211_channel *chan = chandef->chan;
@@ -360,7 +361,7 @@ int mt76x2_phy_set_channel(struct mt76x2_dev *dev,
mt76_set(dev, MT_BBP(RXO, 13), BIT(10));
if (!dev->cal.init_cal_done) {
- u8 val = mt76x2_eeprom_get(dev, MT_EE_BT_RCAL_RESULT);
+ u8 val = mt76x02_eeprom_get(&dev->mt76, MT_EE_BT_RCAL_RESULT);
if (val != 0xff)
mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_R, 0, true);
@@ -390,7 +391,7 @@ int mt76x2_phy_set_channel(struct mt76x2_dev *dev,
sizeof(dev->cal.agc_gain_cur));
/* init default values for temp compensation */
- if (mt76x2_tssi_enabled(dev)) {
+ if (mt76x02_tssi_enabled(&dev->mt76)) {
mt76_rmw_field(dev, MT_TX_ALC_CFG_1, MT_TX_ALC_CFG_1_TEMP_COMP,
0x38);
mt76_rmw_field(dev, MT_TX_ALC_CFG_2, MT_TX_ALC_CFG_2_TEMP_COMP,
@@ -404,7 +405,7 @@ int mt76x2_phy_set_channel(struct mt76x2_dev *dev,
}
static void
-mt76x2_phy_temp_compensate(struct mt76x2_dev *dev)
+mt76x2_phy_temp_compensate(struct mt76x02_dev *dev)
{
struct mt76x2_temp_comp t;
int temp, db_diff;
@@ -433,9 +434,9 @@ mt76x2_phy_temp_compensate(struct mt76x2_dev *dev)
void mt76x2_phy_calibrate(struct work_struct *work)
{
- struct mt76x2_dev *dev;
+ struct mt76x02_dev *dev;
- dev = container_of(work, struct mt76x2_dev, cal_work.work);
+ dev = container_of(work, struct mt76x02_dev, cal_work.work);
mt76x2_phy_channel_calibrate(dev, false);
mt76x2_phy_tssi_compensate(dev, true);
mt76x2_phy_temp_compensate(dev);
@@ -444,7 +445,7 @@ void mt76x2_phy_calibrate(struct work_struct *work)
MT_CALIBRATE_INTERVAL);
}
-int mt76x2_phy_start(struct mt76x2_dev *dev)
+int mt76x2_phy_start(struct mt76x02_dev *dev)
{
int ret;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_tx.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_tx.c
index fcdf1879162e..3a2ec86d3e88 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_tx.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_tx.c
@@ -15,50 +15,17 @@
*/
#include "mt76x2.h"
-#include "mt76x02_util.h"
-#include "mt76x02_dma.h"
struct beacon_bc_data {
- struct mt76x2_dev *dev;
+ struct mt76x02_dev *dev;
struct sk_buff_head q;
struct sk_buff *tail[8];
};
-int mt76x2_tx_prepare_skb(struct mt76_dev *mdev, void *txwi,
- struct sk_buff *skb, struct mt76_queue *q,
- struct mt76_wcid *wcid, struct ieee80211_sta *sta,
- u32 *tx_info)
-{
- struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76);
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- int qsel = MT_QSEL_EDCA;
- int ret;
-
- if (q == &dev->mt76.q_tx[MT_TXQ_PSD] && wcid && wcid->idx < 128)
- mt76x02_mac_wcid_set_drop(&dev->mt76, wcid->idx, false);
-
- mt76x2_mac_write_txwi(dev, txwi, skb, wcid, sta, skb->len);
-
- ret = mt76x02_insert_hdr_pad(skb);
- if (ret < 0)
- return ret;
-
- if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
- qsel = MT_QSEL_MGMT;
-
- *tx_info = FIELD_PREP(MT_TXD_INFO_QSEL, qsel) |
- MT_TXD_INFO_80211;
-
- if (!wcid || wcid->hw_key_idx == 0xff || wcid->sw_iv)
- *tx_info |= MT_TXD_INFO_WIV;
-
- return 0;
-}
-
static void
mt76x2_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
- struct mt76x2_dev *dev = (struct mt76x2_dev *) priv;
+ struct mt76x02_dev *dev = (struct mt76x02_dev *) priv;
struct mt76x02_vif *mvif = (struct mt76x02_vif *) vif->drv_priv;
struct sk_buff *skb = NULL;
@@ -76,7 +43,7 @@ static void
mt76x2_add_buffered_bc(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
struct beacon_bc_data *data = priv;
- struct mt76x2_dev *dev = data->dev;
+ struct mt76x02_dev *dev = data->dev;
struct mt76x02_vif *mvif = (struct mt76x02_vif *) vif->drv_priv;
struct ieee80211_tx_info *info;
struct sk_buff *skb;
@@ -97,7 +64,7 @@ mt76x2_add_buffered_bc(void *priv, u8 *mac, struct ieee80211_vif *vif)
}
static void
-mt76x2_resync_beacon_timer(struct mt76x2_dev *dev)
+mt76x2_resync_beacon_timer(struct mt76x02_dev *dev)
{
u32 timer_val = dev->beacon_int << 4;
@@ -129,7 +96,7 @@ mt76x2_resync_beacon_timer(struct mt76x2_dev *dev)
void mt76x2_pre_tbtt_tasklet(unsigned long arg)
{
- struct mt76x2_dev *dev = (struct mt76x2_dev *) arg;
+ struct mt76x02_dev *dev = (struct mt76x02_dev *) arg;
struct mt76_queue *q = &dev->mt76.q_tx[MT_TXQ_PSD];
struct beacon_bc_data data = {};
struct sk_buff *skb;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_phy_common.c b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c
index 3b704a70fad1..f00aed915ee8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_phy_common.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c
@@ -16,11 +16,12 @@
*/
#include "mt76x2.h"
-#include "mt76x2_eeprom.h"
-#include "mt76x2_mcu.h"
+#include "eeprom.h"
+#include "mcu.h"
+#include "../mt76x02_phy.h"
static void
-mt76x2_adjust_high_lna_gain(struct mt76x2_dev *dev, int reg, s8 offset)
+mt76x2_adjust_high_lna_gain(struct mt76x02_dev *dev, int reg, s8 offset)
{
s8 gain;
@@ -30,7 +31,7 @@ mt76x2_adjust_high_lna_gain(struct mt76x2_dev *dev, int reg, s8 offset)
}
static void
-mt76x2_adjust_agc_gain(struct mt76x2_dev *dev, int reg, s8 offset)
+mt76x2_adjust_agc_gain(struct mt76x02_dev *dev, int reg, s8 offset)
{
s8 gain;
@@ -39,7 +40,7 @@ mt76x2_adjust_agc_gain(struct mt76x2_dev *dev, int reg, s8 offset)
mt76_rmw_field(dev, MT_BBP(AGC, reg), MT_BBP_AGC_GAIN, gain);
}
-void mt76x2_apply_gain_adj(struct mt76x2_dev *dev)
+void mt76x2_apply_gain_adj(struct mt76x02_dev *dev)
{
s8 *gain_adj = dev->cal.rx.high_gain;
@@ -51,7 +52,7 @@ void mt76x2_apply_gain_adj(struct mt76x2_dev *dev)
}
EXPORT_SYMBOL_GPL(mt76x2_apply_gain_adj);
-void mt76x2_phy_set_txpower_regs(struct mt76x2_dev *dev,
+void mt76x2_phy_set_txpower_regs(struct mt76x02_dev *dev,
enum nl80211_band band)
{
u32 pa_mode[2];
@@ -64,7 +65,7 @@ void mt76x2_phy_set_txpower_regs(struct mt76x2_dev *dev,
mt76_wr(dev, MT_TX_ALC_CFG_2, 0x35160a00);
mt76_wr(dev, MT_TX_ALC_CFG_3, 0x35160a06);
- if (mt76x2_ext_pa_enabled(dev, band)) {
+ if (mt76x02_ext_pa_enabled(&dev->mt76, band)) {
mt76_wr(dev, MT_RF_PA_MODE_ADJ0, 0x0000ec00);
mt76_wr(dev, MT_RF_PA_MODE_ADJ1, 0x0000ec00);
} else {
@@ -75,7 +76,7 @@ void mt76x2_phy_set_txpower_regs(struct mt76x2_dev *dev,
pa_mode[0] = 0x0000ffff;
pa_mode[1] = 0x00ff00ff;
- if (mt76x2_ext_pa_enabled(dev, band)) {
+ if (mt76x02_ext_pa_enabled(&dev->mt76, band)) {
mt76_wr(dev, MT_TX_ALC_CFG_2, 0x2f0f0400);
mt76_wr(dev, MT_TX_ALC_CFG_3, 0x2f0f0476);
} else {
@@ -83,7 +84,7 @@ void mt76x2_phy_set_txpower_regs(struct mt76x2_dev *dev,
mt76_wr(dev, MT_TX_ALC_CFG_3, 0x1b0f0476);
}
- if (mt76x2_ext_pa_enabled(dev, band))
+ if (mt76x02_ext_pa_enabled(&dev->mt76, band))
pa_mode_adj = 0x04000000;
else
pa_mode_adj = 0;
@@ -97,7 +98,7 @@ void mt76x2_phy_set_txpower_regs(struct mt76x2_dev *dev,
mt76_wr(dev, MT_RF_PA_MODE_CFG0, pa_mode[0]);
mt76_wr(dev, MT_RF_PA_MODE_CFG1, pa_mode[1]);
- if (mt76x2_ext_pa_enabled(dev, band)) {
+ if (mt76x02_ext_pa_enabled(&dev->mt76, band)) {
u32 val;
if (band == NL80211_BAND_2GHZ)
@@ -124,37 +125,6 @@ void mt76x2_phy_set_txpower_regs(struct mt76x2_dev *dev,
}
EXPORT_SYMBOL_GPL(mt76x2_phy_set_txpower_regs);
-static void
-mt76x2_limit_rate_power(struct mt76_rate_power *r, int limit)
-{
- int i;
-
- for (i = 0; i < sizeof(r->all); i++)
- if (r->all[i] > limit)
- r->all[i] = limit;
-}
-
-static u32
-mt76x2_tx_power_mask(u8 v1, u8 v2, u8 v3, u8 v4)
-{
- u32 val = 0;
-
- val |= (v1 & (BIT(6) - 1)) << 0;
- val |= (v2 & (BIT(6) - 1)) << 8;
- val |= (v3 & (BIT(6) - 1)) << 16;
- val |= (v4 & (BIT(6) - 1)) << 24;
- return val;
-}
-
-static void
-mt76x2_add_rate_power_offset(struct mt76_rate_power *r, int offset)
-{
- int i;
-
- for (i = 0; i < sizeof(r->all); i++)
- r->all[i] += offset;
-}
-
static int
mt76x2_get_min_rate_power(struct mt76_rate_power *r)
{
@@ -174,7 +144,7 @@ mt76x2_get_min_rate_power(struct mt76_rate_power *r)
return ret;
}
-void mt76x2_phy_set_txpower(struct mt76x2_dev *dev)
+void mt76x2_phy_set_txpower(struct mt76x02_dev *dev)
{
enum nl80211_chan_width width = dev->mt76.chandef.width;
struct ieee80211_channel *chan = dev->mt76.chandef.chan;
@@ -191,9 +161,9 @@ void mt76x2_phy_set_txpower(struct mt76x2_dev *dev)
delta = txp.delta_bw80;
mt76x2_get_rate_power(dev, &t, chan);
- mt76x2_add_rate_power_offset(&t, txp.chain[0].target_power);
- mt76x2_limit_rate_power(&t, dev->txpower_conf);
- dev->txpower_cur = mt76x2_get_max_rate_power(&t);
+ mt76x02_add_rate_power_offset(&t, txp.chain[0].target_power);
+ mt76x02_limit_rate_power(&t, dev->mt76.txpower_conf);
+ dev->mt76.txpower_cur = mt76x02_get_max_rate_power(&t);
base_power = mt76x2_get_min_rate_power(&t);
delta += base_power - txp.chain[0].target_power;
@@ -211,40 +181,22 @@ void mt76x2_phy_set_txpower(struct mt76x2_dev *dev)
txp_1 = 0x2f;
}
- mt76x2_add_rate_power_offset(&t, -base_power);
+ mt76x02_add_rate_power_offset(&t, -base_power);
dev->target_power = txp.chain[0].target_power;
dev->target_power_delta[0] = txp_0 - txp.chain[0].target_power;
dev->target_power_delta[1] = txp_1 - txp.chain[0].target_power;
- dev->rate_power = t;
-
- mt76_rmw_field(dev, MT_TX_ALC_CFG_0, MT_TX_ALC_CFG_0_CH_INIT_0, txp_0);
- mt76_rmw_field(dev, MT_TX_ALC_CFG_0, MT_TX_ALC_CFG_0_CH_INIT_1, txp_1);
-
- mt76_wr(dev, MT_TX_PWR_CFG_0,
- mt76x2_tx_power_mask(t.cck[0], t.cck[2], t.ofdm[0], t.ofdm[2]));
- mt76_wr(dev, MT_TX_PWR_CFG_1,
- mt76x2_tx_power_mask(t.ofdm[4], t.ofdm[6], t.ht[0], t.ht[2]));
- mt76_wr(dev, MT_TX_PWR_CFG_2,
- mt76x2_tx_power_mask(t.ht[4], t.ht[6], t.ht[8], t.ht[10]));
- mt76_wr(dev, MT_TX_PWR_CFG_3,
- mt76x2_tx_power_mask(t.ht[12], t.ht[14], t.ht[0], t.ht[2]));
- mt76_wr(dev, MT_TX_PWR_CFG_4,
- mt76x2_tx_power_mask(t.ht[4], t.ht[6], 0, 0));
- mt76_wr(dev, MT_TX_PWR_CFG_7,
- mt76x2_tx_power_mask(t.ofdm[6], t.vht[8], t.ht[6], t.vht[8]));
- mt76_wr(dev, MT_TX_PWR_CFG_8,
- mt76x2_tx_power_mask(t.ht[14], t.vht[8], t.vht[8], 0));
- mt76_wr(dev, MT_TX_PWR_CFG_9,
- mt76x2_tx_power_mask(t.ht[6], t.vht[8], t.vht[8], 0));
+ dev->mt76.rate_power = t;
+
+ mt76x02_phy_set_txpower(&dev->mt76, txp_0, txp_1);
}
EXPORT_SYMBOL_GPL(mt76x2_phy_set_txpower);
-void mt76x2_configure_tx_delay(struct mt76x2_dev *dev,
+void mt76x2_configure_tx_delay(struct mt76x02_dev *dev,
enum nl80211_band band, u8 bw)
{
u32 cfg0, cfg1;
- if (mt76x2_ext_pa_enabled(dev, band)) {
+ if (mt76x02_ext_pa_enabled(&dev->mt76, band)) {
cfg0 = bw ? 0x000b0c01 : 0x00101101;
cfg1 = 0x00011414;
} else {
@@ -258,7 +210,7 @@ void mt76x2_configure_tx_delay(struct mt76x2_dev *dev,
}
EXPORT_SYMBOL_GPL(mt76x2_configure_tx_delay);
-void mt76x2_phy_set_bw(struct mt76x2_dev *dev, int width, u8 ctrl)
+void mt76x2_phy_set_bw(struct mt76x02_dev *dev, int width, u8 ctrl)
{
int core_val, agc_val;
@@ -284,7 +236,7 @@ void mt76x2_phy_set_bw(struct mt76x2_dev *dev, int width, u8 ctrl)
}
EXPORT_SYMBOL_GPL(mt76x2_phy_set_bw);
-void mt76x2_phy_set_band(struct mt76x2_dev *dev, int band, bool primary_upper)
+void mt76x2_phy_set_band(struct mt76x02_dev *dev, int band, bool primary_upper)
{
switch (band) {
case NL80211_BAND_2GHZ:
@@ -302,54 +254,7 @@ void mt76x2_phy_set_band(struct mt76x2_dev *dev, int band, bool primary_upper)
}
EXPORT_SYMBOL_GPL(mt76x2_phy_set_band);
-int mt76x2_phy_get_min_avg_rssi(struct mt76x2_dev *dev)
-{
- struct mt76x02_sta *sta;
- struct mt76_wcid *wcid;
- int i, j, min_rssi = 0;
- s8 cur_rssi;
-
- local_bh_disable();
- rcu_read_lock();
-
- for (i = 0; i < ARRAY_SIZE(dev->mt76.wcid_mask); i++) {
- unsigned long mask = dev->mt76.wcid_mask[i];
-
- if (!mask)
- continue;
-
- for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1) {
- if (!(mask & 1))
- continue;
-
- wcid = rcu_dereference(dev->mt76.wcid[j]);
- if (!wcid)
- continue;
-
- sta = container_of(wcid, struct mt76x02_sta, wcid);
- spin_lock(&dev->mt76.rx_lock);
- if (sta->inactive_count++ < 5)
- cur_rssi = ewma_signal_read(&sta->rssi);
- else
- cur_rssi = 0;
- spin_unlock(&dev->mt76.rx_lock);
-
- if (cur_rssi < min_rssi)
- min_rssi = cur_rssi;
- }
- }
-
- rcu_read_unlock();
- local_bh_enable();
-
- if (!min_rssi)
- return -75;
-
- return min_rssi;
-}
-EXPORT_SYMBOL_GPL(mt76x2_phy_get_min_avg_rssi);
-
-void mt76x2_phy_tssi_compensate(struct mt76x2_dev *dev, bool wait)
+void mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev, bool wait)
{
struct ieee80211_channel *chan = dev->mt76.chandef.chan;
struct mt76x2_tx_power_info txp;
@@ -370,7 +275,7 @@ void mt76x2_phy_tssi_compensate(struct mt76x2_dev *dev, bool wait)
dev->cal.tssi_comp_pending = false;
mt76x2_get_power_info(dev, &txp, chan);
- if (mt76x2_ext_pa_enabled(dev, chan->band))
+ if (mt76x02_ext_pa_enabled(&dev->mt76, chan->band))
t.pa_mode = 1;
t.cal_mode = BIT(1);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
index feb5cec66c67..57baf8d1c830 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
@@ -17,7 +17,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include "mt76x02_usb.h"
+#include "../mt76x02_usb.h"
#include "mt76x2u.h"
static const struct usb_device_id mt76x2u_device_table[] = {
@@ -37,7 +37,7 @@ static int mt76x2u_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
- struct mt76x2_dev *dev;
+ struct mt76x02_dev *dev;
int err;
dev = mt76x2u_alloc_device(&intf->dev);
@@ -72,7 +72,7 @@ err:
static void mt76x2u_disconnect(struct usb_interface *intf)
{
struct usb_device *udev = interface_to_usbdev(intf);
- struct mt76x2_dev *dev = usb_get_intfdata(intf);
+ struct mt76x02_dev *dev = usb_get_intfdata(intf);
struct ieee80211_hw *hw = mt76_hw(dev);
set_bit(MT76_REMOVED, &dev->mt76.state);
@@ -87,7 +87,7 @@ static void mt76x2u_disconnect(struct usb_interface *intf)
static int __maybe_unused mt76x2u_suspend(struct usb_interface *intf,
pm_message_t state)
{
- struct mt76x2_dev *dev = usb_get_intfdata(intf);
+ struct mt76x02_dev *dev = usb_get_intfdata(intf);
struct mt76_usb *usb = &dev->mt76.usb;
mt76u_stop_queues(&dev->mt76);
@@ -99,7 +99,7 @@ static int __maybe_unused mt76x2u_suspend(struct usb_interface *intf,
static int __maybe_unused mt76x2u_resume(struct usb_interface *intf)
{
- struct mt76x2_dev *dev = usb_get_intfdata(intf);
+ struct mt76x02_dev *dev = usb_get_intfdata(intf);
struct mt76_usb *usb = &dev->mt76.usb;
int err;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2u_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c
index e41880c43fa7..c82f16efa327 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2u_init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c
@@ -17,10 +17,11 @@
#include <linux/delay.h>
#include "mt76x2u.h"
-#include "mt76x02_util.h"
-#include "mt76x2_eeprom.h"
+#include "eeprom.h"
+#include "../mt76x02_phy.h"
+#include "../mt76x02_usb.h"
-static void mt76x2u_init_dma(struct mt76x2_dev *dev)
+static void mt76x2u_init_dma(struct mt76x02_dev *dev)
{
u32 val = mt76_rr(dev, MT_VEND_ADDR(CFG, MT_USB_U3DMA_CFG));
@@ -35,7 +36,7 @@ static void mt76x2u_init_dma(struct mt76x2_dev *dev)
mt76_wr(dev, MT_VEND_ADDR(CFG, MT_USB_U3DMA_CFG), val);
}
-static void mt76x2u_power_on_rf_patch(struct mt76x2_dev *dev)
+static void mt76x2u_power_on_rf_patch(struct mt76x02_dev *dev)
{
mt76_set(dev, MT_VEND_ADDR(CFG, 0x130), BIT(0) | BIT(16));
udelay(1);
@@ -55,7 +56,7 @@ static void mt76x2u_power_on_rf_patch(struct mt76x2_dev *dev)
mt76_set(dev, MT_VEND_ADDR(CFG, 0x14c), BIT(19) | BIT(20));
}
-static void mt76x2u_power_on_rf(struct mt76x2_dev *dev, int unit)
+static void mt76x2u_power_on_rf(struct mt76x02_dev *dev, int unit)
{
int shift = unit ? 8 : 0;
u32 val = (BIT(1) | BIT(3) | BIT(4) | BIT(5)) << shift;
@@ -77,7 +78,7 @@ static void mt76x2u_power_on_rf(struct mt76x2_dev *dev, int unit)
mt76_set(dev, 0x530, 0xf);
}
-static void mt76x2u_power_on(struct mt76x2_dev *dev)
+static void mt76x2u_power_on(struct mt76x02_dev *dev)
{
u32 val;
@@ -113,7 +114,7 @@ static void mt76x2u_power_on(struct mt76x2_dev *dev)
mt76x2u_power_on_rf(dev, 1);
}
-static int mt76x2u_init_eeprom(struct mt76x2_dev *dev)
+static int mt76x2u_init_eeprom(struct mt76x02_dev *dev)
{
u32 val, i;
@@ -129,33 +130,33 @@ static int mt76x2u_init_eeprom(struct mt76x2_dev *dev)
put_unaligned_le32(val, dev->mt76.eeprom.data + i);
}
- mt76x2_eeprom_parse_hw_cap(dev);
+ mt76x02_eeprom_parse_hw_cap(&dev->mt76);
return 0;
}
-struct mt76x2_dev *mt76x2u_alloc_device(struct device *pdev)
+struct mt76x02_dev *mt76x2u_alloc_device(struct device *pdev)
{
static const struct mt76_driver_ops drv_ops = {
- .tx_prepare_skb = mt76x2u_tx_prepare_skb,
- .tx_complete_skb = mt76x02_tx_complete_skb,
+ .tx_prepare_skb = mt76x02u_tx_prepare_skb,
+ .tx_complete_skb = mt76x02u_tx_complete_skb,
.tx_status_data = mt76x02_tx_status_data,
- .rx_skb = mt76x2_queue_rx_skb,
+ .rx_skb = mt76x02_queue_rx_skb,
};
- struct mt76x2_dev *dev;
+ struct mt76x02_dev *dev;
struct mt76_dev *mdev;
mdev = mt76_alloc_device(sizeof(*dev), &mt76x2u_ops);
if (!mdev)
return NULL;
- dev = container_of(mdev, struct mt76x2_dev, mt76);
+ dev = container_of(mdev, struct mt76x02_dev, mt76);
mdev->dev = pdev;
mdev->drv = &drv_ops;
return dev;
}
-static void mt76x2u_init_beacon_offsets(struct mt76x2_dev *dev)
+static void mt76x2u_init_beacon_offsets(struct mt76x02_dev *dev)
{
mt76_wr(dev, MT_BCN_OFFSET(0), 0x18100800);
mt76_wr(dev, MT_BCN_OFFSET(1), 0x38302820);
@@ -163,23 +164,14 @@ static void mt76x2u_init_beacon_offsets(struct mt76x2_dev *dev)
mt76_wr(dev, MT_BCN_OFFSET(3), 0x78706860);
}
-int mt76x2u_init_hardware(struct mt76x2_dev *dev)
+int mt76x2u_init_hardware(struct mt76x02_dev *dev)
{
- static const u16 beacon_offsets[] = {
- /* 512 byte per beacon */
- 0xc000, 0xc200, 0xc400, 0xc600,
- 0xc800, 0xca00, 0xcc00, 0xce00,
- 0xd000, 0xd200, 0xd400, 0xd600,
- 0xd800, 0xda00, 0xdc00, 0xde00
- };
const struct mt76_wcid_addr addr = {
.macaddr = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
.ba_mask = 0,
};
int i, err;
- dev->beacon_offsets = beacon_offsets;
-
mt76x2_reset_wlan(dev, true);
mt76x2u_power_on(dev);
@@ -212,12 +204,13 @@ int mt76x2u_init_hardware(struct mt76x2_dev *dev)
if (err < 0)
return err;
- mt76x2u_mac_setaddr(dev, dev->mt76.eeprom.data + MT_EE_MAC_ADDR);
+ mt76x02_mac_setaddr(&dev->mt76,
+ dev->mt76.eeprom.data + MT_EE_MAC_ADDR);
dev->mt76.rxfilter = mt76_rr(dev, MT_RX_FILTR_CFG);
mt76x2u_init_beacon_offsets(dev);
- if (!mt76x2_wait_for_bbp(dev))
+ if (!mt76x02_wait_for_txrx_idle(&dev->mt76))
return -ETIMEDOUT;
/* reset wcid table */
@@ -244,13 +237,13 @@ int mt76x2u_init_hardware(struct mt76x2_dev *dev)
if (err < 0)
return err;
- mt76x2u_phy_set_rxpath(dev);
- mt76x2u_phy_set_txdac(dev);
+ mt76x02_phy_set_rxpath(&dev->mt76);
+ mt76x02_phy_set_txdac(&dev->mt76);
return mt76x2u_mac_stop(dev);
}
-int mt76x2u_register_device(struct mt76x2_dev *dev)
+int mt76x2u_register_device(struct mt76x02_dev *dev)
{
struct ieee80211_hw *hw = mt76_hw(dev);
struct wiphy *wiphy = hw->wiphy;
@@ -263,11 +256,11 @@ int mt76x2u_register_device(struct mt76x2_dev *dev)
if (err < 0)
return err;
- err = mt76u_mcu_init_rx(&dev->mt76);
+ err = mt76u_alloc_queues(&dev->mt76);
if (err < 0)
- return err;
+ goto fail;
- err = mt76u_alloc_queues(&dev->mt76);
+ err = mt76u_mcu_init_rx(&dev->mt76);
if (err < 0)
goto fail;
@@ -301,14 +294,14 @@ fail:
return err;
}
-void mt76x2u_stop_hw(struct mt76x2_dev *dev)
+void mt76x2u_stop_hw(struct mt76x02_dev *dev)
{
mt76u_stop_stat_wk(&dev->mt76);
cancel_delayed_work_sync(&dev->cal_work);
mt76x2u_mac_stop(dev);
}
-void mt76x2u_cleanup(struct mt76x2_dev *dev)
+void mt76x2u_cleanup(struct mt76x02_dev *dev)
{
mt76x02_mcu_set_radio_state(&dev->mt76, false, false);
mt76x2u_stop_hw(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2u_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c
index 9604c6a809be..dbd635aa763b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2u_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c
@@ -15,9 +15,9 @@
*/
#include "mt76x2u.h"
-#include "mt76x2_eeprom.h"
+#include "eeprom.h"
-static void mt76x2u_mac_reset_counters(struct mt76x2_dev *dev)
+static void mt76x2u_mac_reset_counters(struct mt76x02_dev *dev)
{
mt76_rr(dev, MT_RX_STAT_0);
mt76_rr(dev, MT_RX_STAT_1);
@@ -27,12 +27,12 @@ static void mt76x2u_mac_reset_counters(struct mt76x2_dev *dev)
mt76_rr(dev, MT_TX_STA_2);
}
-static void mt76x2u_mac_fixup_xtal(struct mt76x2_dev *dev)
+static void mt76x2u_mac_fixup_xtal(struct mt76x02_dev *dev)
{
s8 offset = 0;
u16 eep_val;
- eep_val = mt76x2_eeprom_get(dev, MT_EE_XTAL_TRIM_2);
+ eep_val = mt76x02_eeprom_get(&dev->mt76, MT_EE_XTAL_TRIM_2);
offset = eep_val & 0x7f;
if ((eep_val & 0xff) == 0xff)
@@ -42,7 +42,7 @@ static void mt76x2u_mac_fixup_xtal(struct mt76x2_dev *dev)
eep_val >>= 8;
if (eep_val == 0x00 || eep_val == 0xff) {
- eep_val = mt76x2_eeprom_get(dev, MT_EE_XTAL_TRIM_1);
+ eep_val = mt76x02_eeprom_get(&dev->mt76, MT_EE_XTAL_TRIM_1);
eep_val &= 0xff;
if (eep_val == 0x00 || eep_val == 0xff)
@@ -67,7 +67,7 @@ static void mt76x2u_mac_fixup_xtal(struct mt76x2_dev *dev)
/* init fce */
mt76_clear(dev, MT_FCE_L2_STUFF, MT_FCE_L2_STUFF_WR_MPDU_LEN_EN);
- eep_val = mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_2);
+ eep_val = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_2);
switch (FIELD_GET(MT_EE_NIC_CONF_2_XTAL_OPTION, eep_val)) {
case 0:
mt76_wr(dev, MT_XO_CTRL7, 0x5c1fee80);
@@ -80,7 +80,7 @@ static void mt76x2u_mac_fixup_xtal(struct mt76x2_dev *dev)
}
}
-int mt76x2u_mac_reset(struct mt76x2_dev *dev)
+int mt76x2u_mac_reset(struct mt76x02_dev *dev)
{
mt76_wr(dev, MT_WPDMA_GLO_CFG, BIT(4) | BIT(5));
@@ -114,12 +114,12 @@ int mt76x2u_mac_reset(struct mt76x2_dev *dev)
return 0;
}
-int mt76x2u_mac_start(struct mt76x2_dev *dev)
+int mt76x2u_mac_start(struct mt76x02_dev *dev)
{
mt76x2u_mac_reset_counters(dev);
mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX);
- wait_for_wpdma(dev);
+ mt76x02_wait_for_wpdma(&dev->mt76, 1000);
usleep_range(50, 100);
mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter);
@@ -131,7 +131,7 @@ int mt76x2u_mac_start(struct mt76x2_dev *dev)
return 0;
}
-int mt76x2u_mac_stop(struct mt76x2_dev *dev)
+int mt76x2u_mac_stop(struct mt76x02_dev *dev)
{
int i, count = 0, val;
bool stopped = false;
@@ -212,7 +212,7 @@ int mt76x2u_mac_stop(struct mt76x2_dev *dev)
return 0;
}
-void mt76x2u_mac_resume(struct mt76x2_dev *dev)
+void mt76x2u_mac_resume(struct mt76x02_dev *dev)
{
mt76_wr(dev, MT_MAC_SYS_CTRL,
MT_MAC_SYS_CTRL_ENABLE_TX |
@@ -220,21 +220,3 @@ void mt76x2u_mac_resume(struct mt76x2_dev *dev)
mt76_set(dev, MT_TXOP_CTRL_CFG, BIT(20));
mt76_set(dev, MT_TXOP_HLDR_ET, BIT(1));
}
-
-void mt76x2u_mac_setaddr(struct mt76x2_dev *dev, u8 *addr)
-{
- ether_addr_copy(dev->mt76.macaddr, addr);
-
- if (!is_valid_ether_addr(dev->mt76.macaddr)) {
- eth_random_addr(dev->mt76.macaddr);
- dev_info(dev->mt76.dev,
- "Invalid MAC address, using random address %pM\n",
- dev->mt76.macaddr);
- }
-
- mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(dev->mt76.macaddr));
- mt76_wr(dev, MT_MAC_ADDR_DW1,
- get_unaligned_le16(dev->mt76.macaddr + 4) |
- FIELD_PREP(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff));
-}
-
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2u_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
index c6855549c312..224609d6915f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2u_main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
@@ -15,11 +15,10 @@
*/
#include "mt76x2u.h"
-#include "mt76x02_util.h"
static int mt76x2u_start(struct ieee80211_hw *hw)
{
- struct mt76x2_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
int ret;
mutex_lock(&dev->mt76.mutex);
@@ -37,7 +36,7 @@ out:
static void mt76x2u_stop(struct ieee80211_hw *hw)
{
- struct mt76x2_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
mutex_lock(&dev->mt76.mutex);
clear_bit(MT76_STATE_RUNNING, &dev->mt76.state);
@@ -48,17 +47,17 @@ static void mt76x2u_stop(struct ieee80211_hw *hw)
static int mt76x2u_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
- struct mt76x2_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
if (!ether_addr_equal(dev->mt76.macaddr, vif->addr))
- mt76x2u_mac_setaddr(dev, vif->addr);
+ mt76x02_mac_setaddr(&dev->mt76, vif->addr);
mt76x02_vif_init(&dev->mt76, vif, 0);
return 0;
}
static int
-mt76x2u_set_channel(struct mt76x2_dev *dev,
+mt76x2u_set_channel(struct mt76x02_dev *dev,
struct cfg80211_chan_def *chandef)
{
int err;
@@ -86,7 +85,7 @@ static void
mt76x2u_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info, u32 changed)
{
- struct mt76x2_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
mutex_lock(&dev->mt76.mutex);
@@ -108,7 +107,7 @@ mt76x2u_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
static int
mt76x2u_config(struct ieee80211_hw *hw, u32 changed)
{
- struct mt76x2_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
int err = 0;
mutex_lock(&dev->mt76.mutex);
@@ -128,10 +127,10 @@ mt76x2u_config(struct ieee80211_hw *hw, u32 changed)
}
if (changed & IEEE80211_CONF_CHANGE_POWER) {
- dev->txpower_conf = hw->conf.power_level * 2;
+ dev->mt76.txpower_conf = hw->conf.power_level * 2;
/* convert to per-chain power for 2x2 devices */
- dev->txpower_conf -= 6;
+ dev->mt76.txpower_conf -= 6;
if (test_bit(MT76_STATE_RUNNING, &dev->mt76.state))
mt76x2_phy_set_txpower(dev);
@@ -146,7 +145,7 @@ static void
mt76x2u_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
const u8 *mac)
{
- struct mt76x2_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
set_bit(MT76_SCANNING, &dev->mt76.state);
}
@@ -154,13 +153,13 @@ mt76x2u_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
static void
mt76x2u_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
- struct mt76x2_dev *dev = hw->priv;
+ struct mt76x02_dev *dev = hw->priv;
clear_bit(MT76_SCANNING, &dev->mt76.state);
}
const struct ieee80211_ops mt76x2u_ops = {
- .tx = mt76x2_tx,
+ .tx = mt76x02_tx,
.start = mt76x2u_start,
.stop = mt76x2u_stop,
.add_interface = mt76x2u_add_interface,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2u_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c
index fe86b9c696d9..259ceae2a3a9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2u_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c
@@ -17,8 +17,8 @@
#include <linux/firmware.h>
#include "mt76x2u.h"
-#include "mt76x2_eeprom.h"
-#include "mt76x02_usb.h"
+#include "eeprom.h"
+#include "../mt76x02_usb.h"
#define MT_CMD_HDR_LEN 4
@@ -29,7 +29,7 @@
#define MT76U_MCU_DLM_OFFSET 0x110000
#define MT76U_MCU_ROM_PATCH_OFFSET 0x90000
-int mt76x2u_mcu_set_dynamic_vga(struct mt76x2_dev *dev, u8 channel, bool ap,
+int mt76x2u_mcu_set_dynamic_vga(struct mt76x02_dev *dev, u8 channel, bool ap,
bool ext, int rssi, u32 false_cca)
{
struct {
@@ -53,14 +53,14 @@ int mt76x2u_mcu_set_dynamic_vga(struct mt76x2_dev *dev, u8 channel, bool ap,
return mt76_mcu_send_msg(dev, skb, CMD_DYNC_VGA_OP, true);
}
-static void mt76x2u_mcu_load_ivb(struct mt76x2_dev *dev)
+static void mt76x2u_mcu_load_ivb(struct mt76x02_dev *dev)
{
mt76u_vendor_request(&dev->mt76, MT_VEND_DEV_MODE,
USB_DIR_OUT | USB_TYPE_VENDOR,
0x12, 0, NULL, 0);
}
-static void mt76x2u_mcu_enable_patch(struct mt76x2_dev *dev)
+static void mt76x2u_mcu_enable_patch(struct mt76x02_dev *dev)
{
struct mt76_usb *usb = &dev->mt76.usb;
const u8 data[] = {
@@ -75,7 +75,7 @@ static void mt76x2u_mcu_enable_patch(struct mt76x2_dev *dev)
0x12, 0, usb->data, sizeof(data));
}
-static void mt76x2u_mcu_reset_wmt(struct mt76x2_dev *dev)
+static void mt76x2u_mcu_reset_wmt(struct mt76x02_dev *dev)
{
struct mt76_usb *usb = &dev->mt76.usb;
u8 data[] = {
@@ -89,7 +89,7 @@ static void mt76x2u_mcu_reset_wmt(struct mt76x2_dev *dev)
0x12, 0, usb->data, sizeof(data));
}
-static int mt76x2u_mcu_load_rom_patch(struct mt76x2_dev *dev)
+static int mt76x2u_mcu_load_rom_patch(struct mt76x02_dev *dev)
{
bool rom_protect = !is_mt7612(dev);
struct mt76x02_patch_header *hdr;
@@ -176,7 +176,7 @@ out:
return err;
}
-static int mt76x2u_mcu_load_firmware(struct mt76x2_dev *dev)
+static int mt76x2u_mcu_load_firmware(struct mt76x02_dev *dev)
{
u32 val, dlm_offset = MT76U_MCU_DLM_OFFSET;
const struct mt76x02_fw_header *hdr;
@@ -261,13 +261,14 @@ static int mt76x2u_mcu_load_firmware(struct mt76x2_dev *dev)
/* enable FCE to send in-band cmd */
mt76_wr(dev, MT_FCE_PSE_CTRL, 0x1);
dev_dbg(dev->mt76.dev, "firmware running\n");
+ mt76x02_set_ethtool_fwver(&dev->mt76, hdr);
out:
release_firmware(fw);
return err;
}
-int mt76x2u_mcu_fw_init(struct mt76x2_dev *dev)
+int mt76x2u_mcu_fw_init(struct mt76x02_dev *dev)
{
int err;
@@ -278,7 +279,7 @@ int mt76x2u_mcu_fw_init(struct mt76x2_dev *dev)
return mt76x2u_mcu_load_firmware(dev);
}
-int mt76x2u_mcu_init(struct mt76x2_dev *dev)
+int mt76x2u_mcu_init(struct mt76x02_dev *dev)
{
int err;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2u_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c
index 97f40fef5559..b11f8a6a6254 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2u_phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c
@@ -15,42 +15,10 @@
*/
#include "mt76x2u.h"
-#include "mt76x2_eeprom.h"
+#include "eeprom.h"
+#include "../mt76x02_phy.h"
-void mt76x2u_phy_set_rxpath(struct mt76x2_dev *dev)
-{
- u32 val;
-
- val = mt76_rr(dev, MT_BBP(AGC, 0));
- val &= ~BIT(4);
-
- switch (dev->chainmask & 0xf) {
- case 2:
- val |= BIT(3);
- break;
- default:
- val &= ~BIT(3);
- break;
- }
- mt76_wr(dev, MT_BBP(AGC, 0), val);
-}
-
-void mt76x2u_phy_set_txdac(struct mt76x2_dev *dev)
-{
- int txpath;
-
- txpath = (dev->chainmask >> 8) & 0xf;
- switch (txpath) {
- case 2:
- mt76_set(dev, MT_BBP(TXBE, 5), 0x3);
- break;
- default:
- mt76_clear(dev, MT_BBP(TXBE, 5), 0x3);
- break;
- }
-}
-
-void mt76x2u_phy_channel_calibrate(struct mt76x2_dev *dev)
+void mt76x2u_phy_channel_calibrate(struct mt76x02_dev *dev)
{
struct ieee80211_channel *chan = dev->mt76.chandef.chan;
bool is_5ghz = chan->band == NL80211_BAND_5GHZ;
@@ -72,7 +40,7 @@ void mt76x2u_phy_channel_calibrate(struct mt76x2_dev *dev)
}
static void
-mt76x2u_phy_update_channel_gain(struct mt76x2_dev *dev)
+mt76x2u_phy_update_channel_gain(struct mt76x02_dev *dev)
{
u8 channel = dev->mt76.chandef.chan->hw_value;
int freq, freq1;
@@ -101,7 +69,7 @@ mt76x2u_phy_update_channel_gain(struct mt76x2_dev *dev)
break;
}
- dev->cal.avg_rssi_all = mt76x2_phy_get_min_avg_rssi(dev);
+ dev->cal.avg_rssi_all = mt76x02_phy_get_min_avg_rssi(&dev->mt76);
false_cca = FIELD_GET(MT_RX_STAT_1_CCA_ERRORS,
mt76_rr(dev, MT_RX_STAT_1));
@@ -111,9 +79,9 @@ mt76x2u_phy_update_channel_gain(struct mt76x2_dev *dev)
void mt76x2u_phy_calibrate(struct work_struct *work)
{
- struct mt76x2_dev *dev;
+ struct mt76x02_dev *dev;
- dev = container_of(work, struct mt76x2_dev, cal_work.work);
+ dev = container_of(work, struct mt76x02_dev, cal_work.work);
mt76x2_phy_tssi_compensate(dev, false);
mt76x2u_phy_update_channel_gain(dev);
@@ -121,7 +89,7 @@ void mt76x2u_phy_calibrate(struct work_struct *work)
MT_CALIBRATE_INTERVAL);
}
-int mt76x2u_phy_set_channel(struct mt76x2_dev *dev,
+int mt76x2u_phy_set_channel(struct mt76x02_dev *dev,
struct cfg80211_chan_def *chandef)
{
u32 ext_cca_chan[4] = {
@@ -209,7 +177,7 @@ int mt76x2u_phy_set_channel(struct mt76x2_dev *dev,
mt76_set(dev, MT_BBP(RXO, 13), BIT(10));
if (!dev->cal.init_cal_done) {
- u8 val = mt76x2_eeprom_get(dev, MT_EE_BT_RCAL_RESULT);
+ u8 val = mt76x02_eeprom_get(&dev->mt76, MT_EE_BT_RCAL_RESULT);
if (val != 0xff)
mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_R,
@@ -235,7 +203,7 @@ int mt76x2u_phy_set_channel(struct mt76x2_dev *dev,
if (scan)
return 0;
- if (mt76x2_tssi_enabled(dev)) {
+ if (mt76x02_tssi_enabled(&dev->mt76)) {
/* init default values for temp compensation */
mt76_rmw_field(dev, MT_TX_ALC_CFG_1, MT_TX_ALC_CFG_1_TEMP_COMP,
0x38);
@@ -250,7 +218,7 @@ int mt76x2u_phy_set_channel(struct mt76x2_dev *dev,
chan = dev->mt76.chandef.chan;
if (chan->band == NL80211_BAND_5GHZ)
flag |= BIT(0);
- if (mt76x2_ext_pa_enabled(dev, chan->band))
+ if (mt76x02_ext_pa_enabled(&dev->mt76, chan->band))
flag |= BIT(8);
mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_TSSI,
flag, false);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_core.c b/drivers/net/wireless/mediatek/mt76/mt76x2_core.c
deleted file mode 100644
index 2629779e8d3e..000000000000
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_core.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/delay.h>
-#include "mt76x2.h"
-#include "mt76x2_trace.h"
-
-void mt76x2_set_irq_mask(struct mt76x2_dev *dev, u32 clear, u32 set)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&dev->irq_lock, flags);
- dev->irqmask &= ~clear;
- dev->irqmask |= set;
- mt76_wr(dev, MT_INT_MASK_CSR, dev->irqmask);
- spin_unlock_irqrestore(&dev->irq_lock, flags);
-}
-
-void mt76x2_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
-{
- struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76);
-
- mt76x2_irq_enable(dev, MT_INT_RX_DONE(q));
-}
-
-irqreturn_t mt76x2_irq_handler(int irq, void *dev_instance)
-{
- struct mt76x2_dev *dev = dev_instance;
- u32 intr;
-
- intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
- mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
-
- if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state))
- return IRQ_NONE;
-
- trace_dev_irq(dev, intr, dev->irqmask);
-
- intr &= dev->irqmask;
-
- if (intr & MT_INT_TX_DONE_ALL) {
- mt76x2_irq_disable(dev, MT_INT_TX_DONE_ALL);
- tasklet_schedule(&dev->tx_tasklet);
- }
-
- if (intr & MT_INT_RX_DONE(0)) {
- mt76x2_irq_disable(dev, MT_INT_RX_DONE(0));
- napi_schedule(&dev->mt76.napi[0]);
- }
-
- if (intr & MT_INT_RX_DONE(1)) {
- mt76x2_irq_disable(dev, MT_INT_RX_DONE(1));
- napi_schedule(&dev->mt76.napi[1]);
- }
-
- if (intr & MT_INT_PRE_TBTT)
- tasklet_schedule(&dev->pre_tbtt_tasklet);
-
- /* send buffered multicast frames now */
- if (intr & MT_INT_TBTT)
- mt76_queue_kick(dev, &dev->mt76.q_tx[MT_TXQ_PSD]);
-
- if (intr & MT_INT_TX_STAT) {
- mt76x2_mac_poll_tx_status(dev, true);
- tasklet_schedule(&dev->tx_tasklet);
- }
-
- if (intr & MT_INT_GPTIMER) {
- mt76x2_irq_disable(dev, MT_INT_GPTIMER);
- tasklet_schedule(&dev->dfs_pd.dfs_tasklet);
- }
-
- return IRQ_HANDLED;
-}
-
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_dma.c b/drivers/net/wireless/mediatek/mt76/mt76x2_dma.c
deleted file mode 100644
index 879ed9138841..000000000000
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_dma.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "mt76x2.h"
-#include "mt76x02_dma.h"
-
-static int
-mt76x2_init_tx_queue(struct mt76x2_dev *dev, struct mt76_queue *q,
- int idx, int n_desc)
-{
- int ret;
-
- q->regs = dev->mt76.mmio.regs + MT_TX_RING_BASE + idx * MT_RING_SIZE;
- q->ndesc = n_desc;
- q->hw_idx = idx;
-
- ret = mt76_queue_alloc(dev, q);
- if (ret)
- return ret;
-
- mt76x2_irq_enable(dev, MT_INT_TX_DONE(idx));
-
- return 0;
-}
-
-static int
-mt76x2_init_rx_queue(struct mt76x2_dev *dev, struct mt76_queue *q,
- int idx, int n_desc, int bufsize)
-{
- int ret;
-
- q->regs = dev->mt76.mmio.regs + MT_RX_RING_BASE + idx * MT_RING_SIZE;
- q->ndesc = n_desc;
- q->buf_size = bufsize;
-
- ret = mt76_queue_alloc(dev, q);
- if (ret)
- return ret;
-
- mt76x2_irq_enable(dev, MT_INT_RX_DONE(idx));
-
- return 0;
-}
-
-static void
-mt76x2_tx_tasklet(unsigned long data)
-{
- struct mt76x2_dev *dev = (struct mt76x2_dev *) data;
- int i;
-
- mt76x2_mac_process_tx_status_fifo(dev);
-
- for (i = MT_TXQ_MCU; i >= 0; i--)
- mt76_queue_tx_cleanup(dev, i, false);
-
- mt76x2_mac_poll_tx_status(dev, false);
- mt76x2_irq_enable(dev, MT_INT_TX_DONE_ALL);
-}
-
-int mt76x2_dma_init(struct mt76x2_dev *dev)
-{
- int ret;
- int i;
- struct mt76_txwi_cache __maybe_unused *t;
- struct mt76_queue *q;
-
- BUILD_BUG_ON(sizeof(t->txwi) < sizeof(struct mt76x02_txwi));
- BUILD_BUG_ON(sizeof(struct mt76x02_rxwi) > MT_RX_HEADROOM);
-
- mt76_dma_attach(&dev->mt76);
-
- tasklet_init(&dev->tx_tasklet, mt76x2_tx_tasklet, (unsigned long) dev);
-
- mt76_wr(dev, MT_WPDMA_RST_IDX, ~0);
-
- for (i = 0; i < IEEE80211_NUM_ACS; i++) {
- ret = mt76x2_init_tx_queue(dev, &dev->mt76.q_tx[i],
- mt76_ac_to_hwq(i), MT_TX_RING_SIZE);
- if (ret)
- return ret;
- }
-
- ret = mt76x2_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_PSD],
- MT_TX_HW_QUEUE_MGMT, MT_TX_RING_SIZE);
- if (ret)
- return ret;
-
- ret = mt76x2_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU],
- MT_TX_HW_QUEUE_MCU, MT_MCU_RING_SIZE);
- if (ret)
- return ret;
-
- ret = mt76x2_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MCU], 1,
- MT_MCU_RING_SIZE, MT_RX_BUF_SIZE);
- if (ret)
- return ret;
-
- q = &dev->mt76.q_rx[MT_RXQ_MAIN];
- q->buf_offset = MT_RX_HEADROOM - sizeof(struct mt76x02_rxwi);
- ret = mt76x2_init_rx_queue(dev, q, 0, MT76x2_RX_RING_SIZE, MT_RX_BUF_SIZE);
- if (ret)
- return ret;
-
- return mt76_init_queues(dev);
-}
-
-void mt76x2_dma_cleanup(struct mt76x2_dev *dev)
-{
- tasklet_kill(&dev->tx_tasklet);
- mt76_dma_cleanup(&dev->mt76);
-}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x2_mac.h
deleted file mode 100644
index 66a57294fcfc..000000000000
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_mac.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef __MT76x2_MAC_H
-#define __MT76x2_MAC_H
-
-#include "mt76.h"
-#include "mt76x02_mac.h"
-
-struct mt76x2_dev;
-struct mt76x2_sta;
-struct mt76x02_vif;
-
-struct mt76x2_tx_info {
- unsigned long jiffies;
- u8 tries;
-
- u8 wcid;
- u8 pktid;
- u8 retry;
-};
-
-static inline struct mt76x2_tx_info *
-mt76x2_skb_tx_info(struct sk_buff *skb)
-{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-
- return (void *) info->status.status_driver_data;
-}
-
-int mt76x2_mac_start(struct mt76x2_dev *dev);
-void mt76x2_mac_stop(struct mt76x2_dev *dev, bool force);
-void mt76x2_mac_resume(struct mt76x2_dev *dev);
-void mt76x2_mac_set_bssid(struct mt76x2_dev *dev, u8 idx, const u8 *addr);
-
-int mt76x2_mac_process_rx(struct mt76x2_dev *dev, struct sk_buff *skb,
- void *rxi);
-void mt76x2_mac_write_txwi(struct mt76x2_dev *dev, struct mt76x02_txwi *txwi,
- struct sk_buff *skb, struct mt76_wcid *wcid,
- struct ieee80211_sta *sta, int len);
-
-int mt76x2_mac_set_beacon(struct mt76x2_dev *dev, u8 vif_idx,
- struct sk_buff *skb);
-void mt76x2_mac_set_beacon_enable(struct mt76x2_dev *dev, u8 vif_idx, bool val);
-
-void mt76x2_mac_poll_tx_status(struct mt76x2_dev *dev, bool irq);
-void mt76x2_mac_process_tx_status_fifo(struct mt76x2_dev *dev);
-
-void mt76x2_mac_work(struct work_struct *work);
-
-#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_mac_common.c b/drivers/net/wireless/mediatek/mt76/mt76x2_mac_common.c
deleted file mode 100644
index 126650742ba4..000000000000
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_mac_common.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
- * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "mt76x2.h"
-#include "mt76x02_util.h"
-
-void mt76x2_mac_stop(struct mt76x2_dev *dev, bool force)
-{
- bool stopped = false;
- u32 rts_cfg;
- int i;
-
- mt76_wr(dev, MT_MAC_SYS_CTRL, 0);
-
- rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG);
- mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg & ~MT_TX_RTS_CFG_RETRY_LIMIT);
-
- /* Wait for MAC to become idle */
- for (i = 0; i < 300; i++) {
- if ((mt76_rr(dev, MT_MAC_STATUS) &
- (MT_MAC_STATUS_RX | MT_MAC_STATUS_TX)) ||
- mt76_rr(dev, MT_BBP(IBI, 12))) {
- udelay(1);
- continue;
- }
-
- stopped = true;
- break;
- }
-
- if (force && !stopped) {
- mt76_set(dev, MT_BBP(CORE, 4), BIT(1));
- mt76_clear(dev, MT_BBP(CORE, 4), BIT(1));
-
- mt76_set(dev, MT_BBP(CORE, 4), BIT(0));
- mt76_clear(dev, MT_BBP(CORE, 4), BIT(0));
- }
-
- mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg);
-}
-EXPORT_SYMBOL_GPL(mt76x2_mac_stop);
-
-void mt76x2_mac_write_txwi(struct mt76x2_dev *dev, struct mt76x02_txwi *txwi,
- struct sk_buff *skb, struct mt76_wcid *wcid,
- struct ieee80211_sta *sta, int len)
-{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_tx_rate *rate = &info->control.rates[0];
- struct ieee80211_key_conf *key = info->control.hw_key;
- u16 rate_ht_mask = FIELD_PREP(MT_RXWI_RATE_PHY, BIT(1) | BIT(2));
- u8 nss;
- s8 txpwr_adj, max_txpwr_adj;
- u8 ccmp_pn[8];
-
- memset(txwi, 0, sizeof(*txwi));
-
- if (wcid)
- txwi->wcid = wcid->idx;
- else
- txwi->wcid = 0xff;
-
- txwi->pktid = 1;
-
- if (wcid && wcid->sw_iv && key) {
- u64 pn = atomic64_inc_return(&key->tx_pn);
- ccmp_pn[0] = pn;
- ccmp_pn[1] = pn >> 8;
- ccmp_pn[2] = 0;
- ccmp_pn[3] = 0x20 | (key->keyidx << 6);
- ccmp_pn[4] = pn >> 16;
- ccmp_pn[5] = pn >> 24;
- ccmp_pn[6] = pn >> 32;
- ccmp_pn[7] = pn >> 40;
- txwi->iv = *((__le32 *)&ccmp_pn[0]);
- txwi->eiv = *((__le32 *)&ccmp_pn[1]);
- }
-
- spin_lock_bh(&dev->mt76.lock);
- if (wcid && (rate->idx < 0 || !rate->count)) {
- txwi->rate = wcid->tx_rate;
- max_txpwr_adj = wcid->max_txpwr_adj;
- nss = wcid->tx_rate_nss;
- } else {
- txwi->rate = mt76x02_mac_tx_rate_val(&dev->mt76, rate, &nss);
- max_txpwr_adj = mt76x2_tx_get_max_txpwr_adj(&dev->mt76, rate);
- }
- spin_unlock_bh(&dev->mt76.lock);
-
- txpwr_adj = mt76x2_tx_get_txpwr_adj(dev, dev->txpower_conf,
- max_txpwr_adj);
- txwi->ctl2 = FIELD_PREP(MT_TX_PWR_ADJ, txpwr_adj);
-
- if (mt76xx_rev(dev) >= MT76XX_REV_E4)
- txwi->txstream = 0x13;
- else if (mt76xx_rev(dev) >= MT76XX_REV_E3 &&
- !(txwi->rate & cpu_to_le16(rate_ht_mask)))
- txwi->txstream = 0x93;
-
- mt76x02_mac_fill_txwi(txwi, skb, sta, len, nss);
-}
-EXPORT_SYMBOL_GPL(mt76x2_mac_write_txwi);
-
-int mt76x2_mac_get_rssi(struct mt76x2_dev *dev, s8 rssi, int chain)
-{
- struct mt76x2_rx_freq_cal *cal = &dev->cal.rx;
-
- rssi += cal->rssi_offset[chain];
- rssi -= cal->lna_gain;
-
- return rssi;
-}
-
-static struct mt76x02_sta *
-mt76x2_rx_get_sta(struct mt76x2_dev *dev, u8 idx)
-{
- struct mt76_wcid *wcid;
-
- if (idx >= ARRAY_SIZE(dev->mt76.wcid))
- return NULL;
-
- wcid = rcu_dereference(dev->mt76.wcid[idx]);
- if (!wcid)
- return NULL;
-
- return container_of(wcid, struct mt76x02_sta, wcid);
-}
-
-static struct mt76_wcid *
-mt76x2_rx_get_sta_wcid(struct mt76x2_dev *dev, struct mt76x02_sta *sta,
- bool unicast)
-{
- if (!sta)
- return NULL;
-
- if (unicast)
- return &sta->wcid;
- else
- return &sta->vif->group_wcid;
-}
-
-int mt76x2_mac_process_rx(struct mt76x2_dev *dev, struct sk_buff *skb,
- void *rxi)
-{
- struct mt76_rx_status *status = (struct mt76_rx_status *) skb->cb;
- struct mt76x02_rxwi *rxwi = rxi;
- struct mt76x02_sta *sta;
- u32 rxinfo = le32_to_cpu(rxwi->rxinfo);
- u32 ctl = le32_to_cpu(rxwi->ctl);
- u16 rate = le16_to_cpu(rxwi->rate);
- u16 tid_sn = le16_to_cpu(rxwi->tid_sn);
- bool unicast = rxwi->rxinfo & cpu_to_le32(MT_RXINFO_UNICAST);
- int pad_len = 0;
- u8 pn_len;
- u8 wcid;
- int len;
-
- if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state))
- return -EINVAL;
-
- if (rxinfo & MT_RXINFO_L2PAD)
- pad_len += 2;
-
- if (rxinfo & MT_RXINFO_DECRYPT) {
- status->flag |= RX_FLAG_DECRYPTED;
- status->flag |= RX_FLAG_MMIC_STRIPPED;
- status->flag |= RX_FLAG_MIC_STRIPPED;
- status->flag |= RX_FLAG_IV_STRIPPED;
- }
-
- wcid = FIELD_GET(MT_RXWI_CTL_WCID, ctl);
- sta = mt76x2_rx_get_sta(dev, wcid);
- status->wcid = mt76x2_rx_get_sta_wcid(dev, sta, unicast);
-
- len = FIELD_GET(MT_RXWI_CTL_MPDU_LEN, ctl);
- pn_len = FIELD_GET(MT_RXINFO_PN_LEN, rxinfo);
- if (pn_len) {
- int offset = ieee80211_get_hdrlen_from_skb(skb) + pad_len;
- u8 *data = skb->data + offset;
-
- status->iv[0] = data[7];
- status->iv[1] = data[6];
- status->iv[2] = data[5];
- status->iv[3] = data[4];
- status->iv[4] = data[1];
- status->iv[5] = data[0];
-
- /*
- * Driver CCMP validation can't deal with fragments.
- * Let mac80211 take care of it.
- */
- if (rxinfo & MT_RXINFO_FRAG) {
- status->flag &= ~RX_FLAG_IV_STRIPPED;
- } else {
- pad_len += pn_len << 2;
- len -= pn_len << 2;
- }
- }
-
- mt76x02_remove_hdr_pad(skb, pad_len);
-
- if ((rxinfo & MT_RXINFO_BA) && !(rxinfo & MT_RXINFO_NULL))
- status->aggr = true;
-
- if (WARN_ON_ONCE(len > skb->len))
- return -EINVAL;
-
- pskb_trim(skb, len);
- status->chains = BIT(0) | BIT(1);
- status->chain_signal[0] = mt76x2_mac_get_rssi(dev, rxwi->rssi[0], 0);
- status->chain_signal[1] = mt76x2_mac_get_rssi(dev, rxwi->rssi[1], 1);
- status->signal = max(status->chain_signal[0], status->chain_signal[1]);
- status->freq = dev->mt76.chandef.chan->center_freq;
- status->band = dev->mt76.chandef.chan->band;
-
- status->tid = FIELD_GET(MT_RXWI_TID, tid_sn);
- status->seqno = FIELD_GET(MT_RXWI_SN, tid_sn);
-
- if (sta) {
- ewma_signal_add(&sta->rssi, status->signal);
- sta->inactive_count = 0;
- }
-
- return mt76x02_mac_process_rate(status, rate);
-}
-EXPORT_SYMBOL_GPL(mt76x2_mac_process_rx);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_tx_common.c b/drivers/net/wireless/mediatek/mt76/mt76x2_tx_common.c
deleted file mode 100644
index dbb3071bed1b..000000000000
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_tx_common.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
- * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "mt76x2.h"
-#include "dma.h"
-
-void mt76x2_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
- struct sk_buff *skb)
-{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct mt76x2_dev *dev = hw->priv;
- struct ieee80211_vif *vif = info->control.vif;
- struct mt76_wcid *wcid = &dev->mt76.global_wcid;
-
- if (control->sta) {
- struct mt76x02_sta *msta;
-
- msta = (struct mt76x02_sta *)control->sta->drv_priv;
- wcid = &msta->wcid;
- /* sw encrypted frames */
- if (!info->control.hw_key && wcid->hw_key_idx != 0xff)
- control->sta = NULL;
- }
-
- if (vif && !control->sta) {
- struct mt76x02_vif *mvif;
-
- mvif = (struct mt76x02_vif *)vif->drv_priv;
- wcid = &mvif->group_wcid;
- }
-
- mt76_tx(&dev->mt76, control->sta, wcid, skb);
-}
-EXPORT_SYMBOL_GPL(mt76x2_tx);
-
-s8 mt76x2_tx_get_max_txpwr_adj(struct mt76_dev *mdev,
- const struct ieee80211_tx_rate *rate)
-{
- struct mt76x2_dev *dev = (struct mt76x2_dev *) mdev;
- s8 max_txpwr;
-
- if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
- u8 mcs = ieee80211_rate_get_vht_mcs(rate);
-
- if (mcs == 8 || mcs == 9) {
- max_txpwr = dev->rate_power.vht[8];
- } else {
- u8 nss, idx;
-
- nss = ieee80211_rate_get_vht_nss(rate);
- idx = ((nss - 1) << 3) + mcs;
- max_txpwr = dev->rate_power.ht[idx & 0xf];
- }
- } else if (rate->flags & IEEE80211_TX_RC_MCS) {
- max_txpwr = dev->rate_power.ht[rate->idx & 0xf];
- } else {
- enum nl80211_band band = dev->mt76.chandef.chan->band;
-
- if (band == NL80211_BAND_2GHZ) {
- const struct ieee80211_rate *r;
- struct wiphy *wiphy = mt76_hw(dev)->wiphy;
- struct mt76_rate_power *rp = &dev->rate_power;
-
- r = &wiphy->bands[band]->bitrates[rate->idx];
- if (r->flags & IEEE80211_RATE_SHORT_PREAMBLE)
- max_txpwr = rp->cck[r->hw_value & 0x3];
- else
- max_txpwr = rp->ofdm[r->hw_value & 0x7];
- } else {
- max_txpwr = dev->rate_power.ofdm[rate->idx & 0x7];
- }
- }
-
- return max_txpwr;
-}
-EXPORT_SYMBOL_GPL(mt76x2_tx_get_max_txpwr_adj);
-
-s8 mt76x2_tx_get_txpwr_adj(struct mt76x2_dev *dev, s8 txpwr, s8 max_txpwr_adj)
-{
- txpwr = min_t(s8, txpwr, dev->txpower_conf);
- txpwr -= (dev->target_power + dev->target_power_delta[0]);
- txpwr = min_t(s8, txpwr, max_txpwr_adj);
-
- if (!dev->enable_tpc)
- return 0;
- else if (txpwr >= 0)
- return min_t(s8, txpwr, 7);
- else
- return (txpwr < -16) ? 8 : (txpwr + 32) / 2;
-}
-EXPORT_SYMBOL_GPL(mt76x2_tx_get_txpwr_adj);
-
-void mt76x2_tx_set_txpwr_auto(struct mt76x2_dev *dev, s8 txpwr)
-{
- s8 txpwr_adj;
-
- txpwr_adj = mt76x2_tx_get_txpwr_adj(dev, txpwr,
- dev->rate_power.ofdm[4]);
- mt76_rmw_field(dev, MT_PROT_AUTO_TX_CFG,
- MT_PROT_AUTO_TX_CFG_PROT_PADJ, txpwr_adj);
- mt76_rmw_field(dev, MT_PROT_AUTO_TX_CFG,
- MT_PROT_AUTO_TX_CFG_AUTO_PADJ, txpwr_adj);
-}
-EXPORT_SYMBOL_GPL(mt76x2_tx_set_txpwr_auto);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2u_core.c b/drivers/net/wireless/mediatek/mt76/mt76x2u_core.c
deleted file mode 100644
index c2ccdebca470..000000000000
--- a/drivers/net/wireless/mediatek/mt76/mt76x2u_core.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "mt76x2u.h"
-#include "dma.h"
-#include "mt76x02_util.h"
-#include "mt76x02_usb.h"
-
-static int
-mt76x2u_check_skb_rooms(struct sk_buff *skb)
-{
- int hdr_len = ieee80211_get_hdrlen_from_skb(skb);
- u32 need_head;
-
- need_head = sizeof(struct mt76x02_txwi) + MT_DMA_HDR_LEN;
- if (hdr_len % 4)
- need_head += 2;
- return skb_cow(skb, need_head);
-}
-
-int mt76x2u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
- struct sk_buff *skb, struct mt76_queue *q,
- struct mt76_wcid *wcid, struct ieee80211_sta *sta,
- u32 *tx_info)
-{
- struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76);
- struct mt76x02_txwi *txwi;
- int err, len = skb->len;
-
- err = mt76x2u_check_skb_rooms(skb);
- if (err < 0)
- return -ENOMEM;
-
- mt76x02_insert_hdr_pad(skb);
-
- txwi = skb_push(skb, sizeof(struct mt76x02_txwi));
- mt76x2_mac_write_txwi(dev, txwi, skb, wcid, sta, len);
-
- return mt76x02u_set_txinfo(skb, wcid, q2ep(q->hw_idx));
-}
diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c
index cf79b8c67b52..bf0e9e666bc4 100644
--- a/drivers/net/wireless/mediatek/mt76/tx.c
+++ b/drivers/net/wireless/mediatek/mt76/tx.c
@@ -91,11 +91,23 @@ mt76_txq_get_qid(struct ieee80211_txq *txq)
return txq->ac;
}
+static void
+mt76_check_agg_ssn(struct mt76_txq *mtxq, struct sk_buff *skb)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+
+ if (!ieee80211_is_data_qos(hdr->frame_control))
+ return;
+
+ mtxq->agg_ssn = le16_to_cpu(hdr->seq_ctrl) + 0x10;
+}
+
void
mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta,
struct mt76_wcid *wcid, struct sk_buff *skb)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct mt76_queue *q;
int qid = skb_get_queue_mapping(skb);
@@ -108,6 +120,19 @@ mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta,
ieee80211_get_tx_rates(info->control.vif, sta, skb,
info->control.rates, 1);
+ if (sta && ieee80211_is_data_qos(hdr->frame_control)) {
+ struct ieee80211_txq *txq;
+ struct mt76_txq *mtxq;
+ u8 tid;
+
+ tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
+ txq = sta->txq[tid];
+ mtxq = (struct mt76_txq *) txq->drv_priv;
+
+ if (mtxq->aggr)
+ mt76_check_agg_ssn(mtxq, skb);
+ }
+
q = &dev->q_tx[qid];
spin_lock_bh(&q->lock);
@@ -144,17 +169,6 @@ mt76_txq_dequeue(struct mt76_dev *dev, struct mt76_txq *mtxq, bool ps)
}
static void
-mt76_check_agg_ssn(struct mt76_txq *mtxq, struct sk_buff *skb)
-{
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-
- if (!ieee80211_is_data_qos(hdr->frame_control))
- return;
-
- mtxq->agg_ssn = le16_to_cpu(hdr->seq_ctrl) + 0x10;
-}
-
-static void
mt76_queue_ps_skb(struct mt76_dev *dev, struct ieee80211_sta *sta,
struct sk_buff *skb, bool last)
{
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index be43e2941dc4..6b643ea701e3 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/module.h>
#include "mt76.h"
#include "usb_trace.h"
#include "dma.h"
@@ -279,12 +280,13 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf *buf,
struct urb *urb = buf->urb;
int i;
+ spin_lock_bh(&q->rx_page_lock);
for (i = 0; i < nsgs; i++) {
struct page *page;
void *data;
int offset;
- data = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC);
+ data = page_frag_alloc(&q->rx_page, len, GFP_ATOMIC);
if (!data)
break;
@@ -292,6 +294,7 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf *buf,
offset = data - page_address(page);
sg_set_page(&urb->sg[i], page, sglen, offset);
}
+ spin_unlock_bh(&q->rx_page_lock);
if (i < nsgs) {
int j;
@@ -383,9 +386,9 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len)
min_len = MT_DMA_HDR_LEN + MT_RX_RXWI_LEN +
MT_FCE_INFO_LEN;
- if (data_len < min_len || WARN_ON(!dma_len) ||
- WARN_ON(dma_len + MT_DMA_HDR_LEN > data_len) ||
- WARN_ON(dma_len & 0x3))
+ if (data_len < min_len || !dma_len ||
+ dma_len + MT_DMA_HDR_LEN > data_len ||
+ (dma_len & 0x3))
return -EINVAL;
return dma_len;
}
@@ -520,6 +523,7 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
int i, err, nsgs;
+ spin_lock_init(&q->rx_page_lock);
spin_lock_init(&q->lock);
q->entry = devm_kzalloc(dev->dev,
MT_NUM_RX_ENTRIES * sizeof(*q->entry),
@@ -557,12 +561,15 @@ static void mt76u_free_rx(struct mt76_dev *dev)
for (i = 0; i < q->ndesc; i++)
mt76u_buf_free(&q->entry[i].ubuf);
+ spin_lock_bh(&q->rx_page_lock);
if (!q->rx_page.va)
- return;
+ goto out;
page = virt_to_page(q->rx_page.va);
__page_frag_cache_drain(page, q->rx_page.pagecnt_bias);
memset(&q->rx_page, 0, sizeof(q->rx_page));
+out:
+ spin_unlock_bh(&q->rx_page_lock);
}
static void mt76u_stop_rx(struct mt76_dev *dev)
diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 452d4b7c832d..51b33ec78fac 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -141,8 +141,8 @@ qtnf_change_virtual_intf(struct wiphy *wiphy,
ret = qtnf_cmd_send_change_intf_type(vif, type, mac_addr);
if (ret) {
- pr_err("VIF%u.%u: failed to change VIF type: %d\n",
- vif->mac->macid, vif->vifid, ret);
+ pr_err("VIF%u.%u: failed to change type to %d\n",
+ vif->mac->macid, vif->vifid, type);
return ret;
}
@@ -216,7 +216,6 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct wiphy *wiphy,
eth_zero_addr(vif->mac_addr);
eth_zero_addr(vif->bssid);
vif->bss_priority = QTNF_DEF_BSS_PRIORITY;
- vif->sta_state = QTNF_STA_DISCONNECTED;
memset(&vif->wdev, 0, sizeof(vif->wdev));
vif->wdev.wiphy = wiphy;
vif->wdev.iftype = type;
@@ -229,18 +228,22 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct wiphy *wiphy,
if (params)
mac_addr = params->macaddr;
- if (qtnf_cmd_send_add_intf(vif, type, mac_addr)) {
- pr_err("VIF%u.%u: failed to add VIF\n", mac->macid, vif->vifid);
+ ret = qtnf_cmd_send_add_intf(vif, type, mac_addr);
+ if (ret) {
+ pr_err("VIF%u.%u: failed to add VIF %pM\n",
+ mac->macid, vif->vifid, mac_addr);
goto err_cmd;
}
if (!is_valid_ether_addr(vif->mac_addr)) {
pr_err("VIF%u.%u: FW reported bad MAC: %pM\n",
mac->macid, vif->vifid, vif->mac_addr);
+ ret = -EINVAL;
goto err_mac;
}
- if (qtnf_core_net_attach(mac, vif, name, name_assign_t)) {
+ ret = qtnf_core_net_attach(mac, vif, name, name_assign_t);
+ if (ret) {
pr_err("VIF%u.%u: failed to attach netdev\n", mac->macid,
vif->vifid);
goto err_net;
@@ -256,7 +259,7 @@ err_mac:
err_cmd:
vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
- return ERR_PTR(-EFAULT);
+ return ERR_PTR(ret);
}
static int qtnf_mgmt_set_appie(struct qtnf_vif *vif,
@@ -335,12 +338,11 @@ static int qtnf_stop_ap(struct wiphy *wiphy, struct net_device *dev)
qtnf_scan_done(vif->mac, true);
ret = qtnf_cmd_send_stop_ap(vif);
- if (ret) {
+ if (ret)
pr_err("VIF%u.%u: failed to stop AP operation in FW\n",
vif->mac->macid, vif->vifid);
- netif_carrier_off(vif->netdev);
- }
+ netif_carrier_off(vif->netdev);
return ret;
}
@@ -478,19 +480,31 @@ qtnf_dump_station(struct wiphy *wiphy, struct net_device *dev,
const struct qtnf_sta_node *sta_node;
int ret;
- sta_node = qtnf_sta_list_lookup_index(&vif->sta_list, idx);
+ switch (vif->wdev.iftype) {
+ case NL80211_IFTYPE_STATION:
+ if (idx != 0 || !vif->wdev.current_bss)
+ return -ENOENT;
- if (unlikely(!sta_node))
- return -ENOENT;
+ ether_addr_copy(mac, vif->bssid);
+ break;
+ case NL80211_IFTYPE_AP:
+ sta_node = qtnf_sta_list_lookup_index(&vif->sta_list, idx);
+ if (unlikely(!sta_node))
+ return -ENOENT;
- ether_addr_copy(mac, sta_node->mac_addr);
+ ether_addr_copy(mac, sta_node->mac_addr);
+ break;
+ default:
+ return -ENOTSUPP;
+ }
- ret = qtnf_cmd_get_sta_info(vif, sta_node->mac_addr, sinfo);
+ ret = qtnf_cmd_get_sta_info(vif, mac, sinfo);
- if (unlikely(ret == -ENOENT)) {
- qtnf_sta_list_del(vif, mac);
- cfg80211_del_sta(vif->netdev, mac, GFP_KERNEL);
- sinfo->filled = 0;
+ if (vif->wdev.iftype == NL80211_IFTYPE_AP) {
+ if (ret == -ENOENT) {
+ cfg80211_del_sta(vif->netdev, mac, GFP_KERNEL);
+ sinfo->filled = 0;
+ }
}
sinfo->generation = vif->generation;
@@ -521,9 +535,16 @@ static int qtnf_del_key(struct wiphy *wiphy, struct net_device *dev,
int ret;
ret = qtnf_cmd_send_del_key(vif, key_index, pairwise, mac_addr);
- if (ret)
- pr_err("VIF%u.%u: failed to delete key: idx=%u pw=%u\n",
- vif->mac->macid, vif->vifid, key_index, pairwise);
+ if (ret) {
+ if (ret == -ENOENT) {
+ pr_debug("VIF%u.%u: key index %d out of bounds\n",
+ vif->mac->macid, vif->vifid, key_index);
+ } else {
+ pr_err("VIF%u.%u: failed to delete key: idx=%u pw=%u\n",
+ vif->mac->macid, vif->vifid,
+ key_index, pairwise);
+ }
+ }
return ret;
}
@@ -590,6 +611,7 @@ qtnf_del_station(struct wiphy *wiphy, struct net_device *dev,
if (ret)
pr_err("VIF%u.%u: failed to delete STA %pM\n",
vif->mac->macid, vif->vifid, params->mac);
+
return ret;
}
@@ -597,21 +619,25 @@ static int
qtnf_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
{
struct qtnf_wmac *mac = wiphy_priv(wiphy);
+ int ret;
cancel_delayed_work_sync(&mac->scan_timeout);
mac->scan_req = request;
- if (qtnf_cmd_send_scan(mac)) {
+ ret = qtnf_cmd_send_scan(mac);
+ if (ret) {
pr_err("MAC%u: failed to start scan\n", mac->macid);
mac->scan_req = NULL;
- return -EFAULT;
+ goto out;
}
+ pr_debug("MAC%u: scan started\n", mac->macid);
queue_delayed_work(mac->bus->workqueue, &mac->scan_timeout,
QTNF_SCAN_TIMEOUT_SEC * HZ);
- return 0;
+out:
+ return ret;
}
static int
@@ -624,9 +650,6 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev,
if (vif->wdev.iftype != NL80211_IFTYPE_STATION)
return -EOPNOTSUPP;
- if (vif->sta_state != QTNF_STA_DISCONNECTED)
- return -EBUSY;
-
if (sme->bssid)
ether_addr_copy(vif->bssid, sme->bssid);
else
@@ -634,13 +657,13 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev,
ret = qtnf_cmd_send_connect(vif, sme);
if (ret) {
- pr_err("VIF%u.%u: failed to connect\n", vif->mac->macid,
- vif->vifid);
- return ret;
+ pr_err("VIF%u.%u: failed to connect\n",
+ vif->mac->macid, vif->vifid);
+ goto out;
}
- vif->sta_state = QTNF_STA_CONNECTING;
- return 0;
+out:
+ return ret;
}
static int
@@ -662,22 +685,18 @@ qtnf_disconnect(struct wiphy *wiphy, struct net_device *dev,
goto out;
}
- qtnf_scan_done(mac, true);
-
- if (vif->sta_state == QTNF_STA_DISCONNECTED)
- goto out;
-
ret = qtnf_cmd_send_disconnect(vif, reason_code);
- if (ret) {
- pr_err("VIF%u.%u: failed to disconnect\n", mac->macid,
- vif->vifid);
- goto out;
+ if (ret)
+ pr_err("VIF%u.%u: failed to disconnect\n",
+ mac->macid, vif->vifid);
+
+ if (vif->wdev.current_bss) {
+ netif_carrier_off(vif->netdev);
+ cfg80211_disconnected(vif->netdev, reason_code,
+ NULL, 0, true, GFP_KERNEL);
}
out:
- if (vif->sta_state == QTNF_STA_CONNECTING)
- vif->sta_state = QTNF_STA_DISCONNECTED;
-
return ret;
}
@@ -747,7 +766,6 @@ qtnf_dump_survey(struct wiphy *wiphy, struct net_device *dev,
default:
pr_debug("failed to get chan(%d) stats from card\n",
chan->hw_value);
- ret = -EINVAL;
break;
}
@@ -770,6 +788,7 @@ qtnf_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
ret = qtnf_cmd_get_channel(vif, chandef);
if (ret) {
pr_err("%s: failed to get channel: %d\n", ndev->name, ret);
+ ret = -ENODATA;
goto out;
}
@@ -779,6 +798,7 @@ qtnf_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
chandef->center_freq1, chandef->center_freq2,
chandef->width);
ret = -ENODATA;
+ goto out;
}
out:
@@ -848,10 +868,8 @@ static int qtnf_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
ret = qtnf_cmd_send_pm_set(vif, enabled ? QLINK_PM_AUTO_STANDBY :
QLINK_PM_OFF, timeout);
- if (ret) {
+ if (ret)
pr_err("%s: failed to set PM mode ret=%d\n", dev->name, ret);
- return ret;
- }
return ret;
}
@@ -971,9 +989,16 @@ static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy_in,
ret = qtnf_cmd_reg_notify(bus, req);
if (ret) {
- if (ret != -EOPNOTSUPP && ret != -EALREADY)
+ if (ret == -EOPNOTSUPP) {
+ pr_warn("reg update not supported\n");
+ } else if (ret == -EALREADY) {
+ pr_info("regulatory domain is already set to %c%c",
+ req->alpha2[0], req->alpha2[1]);
+ } else {
pr_err("failed to update reg domain to %c%c\n",
req->alpha2[0], req->alpha2[1]);
+ }
+
return;
}
@@ -1088,6 +1113,10 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
if (hw_info->hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD)
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD);
+ if (hw_info->hw_capab & QLINK_HW_CAPAB_SCAN_DWELL)
+ wiphy_ext_feature_set(wiphy,
+ NL80211_EXT_FEATURE_SET_SCAN_DWELL);
+
wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2;
@@ -1106,6 +1135,9 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
if (hw_info->hw_capab & QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR)
wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
+ if (!(hw_info->hw_capab & QLINK_HW_CAPAB_OBSS_SCAN))
+ wiphy->features |= NL80211_FEATURE_NEED_OBSS_SCAN;
+
#ifdef CONFIG_PM
if (macinfo->wowlan)
wiphy->wowlan = macinfo->wowlan;
@@ -1120,6 +1152,15 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED;
}
+ if (mac->macinfo.extended_capabilities_len) {
+ wiphy->extended_capabilities =
+ mac->macinfo.extended_capabilities;
+ wiphy->extended_capabilities_mask =
+ mac->macinfo.extended_capabilities_mask;
+ wiphy->extended_capabilities_len =
+ mac->macinfo.extended_capabilities_len;
+ }
+
strlcpy(wiphy->fw_version, hw_info->fw_version,
sizeof(wiphy->fw_version));
wiphy->hw_version = hw_info->hw_version;
@@ -1143,7 +1184,8 @@ void qtnf_netdev_updown(struct net_device *ndev, bool up)
struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev);
if (qtnf_cmd_send_updown_intf(vif, up))
- pr_err("failed to send up/down command to FW\n");
+ pr_err("failed to send %s command to VIF%u.%u\n",
+ up ? "UP" : "DOWN", vif->mac->macid, vif->vifid);
}
void qtnf_virtual_intf_cleanup(struct net_device *ndev)
@@ -1151,57 +1193,20 @@ void qtnf_virtual_intf_cleanup(struct net_device *ndev)
struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev);
struct qtnf_wmac *mac = wiphy_priv(vif->wdev.wiphy);
- if (vif->wdev.iftype == NL80211_IFTYPE_STATION) {
- switch (vif->sta_state) {
- case QTNF_STA_DISCONNECTED:
- break;
- case QTNF_STA_CONNECTING:
- cfg80211_connect_result(vif->netdev,
- vif->bssid, NULL, 0,
- NULL, 0,
- WLAN_STATUS_UNSPECIFIED_FAILURE,
- GFP_KERNEL);
- qtnf_disconnect(vif->wdev.wiphy, ndev,
- WLAN_REASON_DEAUTH_LEAVING);
- break;
- case QTNF_STA_CONNECTED:
- cfg80211_disconnected(vif->netdev,
- WLAN_REASON_DEAUTH_LEAVING,
- NULL, 0, 1, GFP_KERNEL);
- qtnf_disconnect(vif->wdev.wiphy, ndev,
- WLAN_REASON_DEAUTH_LEAVING);
- break;
- }
-
- vif->sta_state = QTNF_STA_DISCONNECTED;
- }
+ if (vif->wdev.iftype == NL80211_IFTYPE_STATION)
+ qtnf_disconnect(vif->wdev.wiphy, ndev,
+ WLAN_REASON_DEAUTH_LEAVING);
qtnf_scan_done(mac, true);
}
void qtnf_cfg80211_vif_reset(struct qtnf_vif *vif)
{
- if (vif->wdev.iftype == NL80211_IFTYPE_STATION) {
- switch (vif->sta_state) {
- case QTNF_STA_CONNECTING:
- cfg80211_connect_result(vif->netdev,
- vif->bssid, NULL, 0,
- NULL, 0,
- WLAN_STATUS_UNSPECIFIED_FAILURE,
- GFP_KERNEL);
- break;
- case QTNF_STA_CONNECTED:
- cfg80211_disconnected(vif->netdev,
- WLAN_REASON_DEAUTH_LEAVING,
- NULL, 0, 1, GFP_KERNEL);
- break;
- case QTNF_STA_DISCONNECTED:
- break;
- }
- }
+ if (vif->wdev.iftype == NL80211_IFTYPE_STATION)
+ cfg80211_disconnected(vif->netdev, WLAN_REASON_DEAUTH_LEAVING,
+ NULL, 0, 1, GFP_KERNEL);
cfg80211_shutdown_all_interfaces(vif->wdev.wiphy);
- vif->sta_state = QTNF_STA_DISCONNECTED;
}
void qtnf_band_init_rates(struct ieee80211_supported_band *band)
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index ae9e77300533..bfdc1ad30c13 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -80,7 +80,6 @@ static int qtnf_cmd_resp_result_decode(enum qlink_cmd_result qcode)
static int qtnf_cmd_send_with_reply(struct qtnf_bus *bus,
struct sk_buff *cmd_skb,
struct sk_buff **response_skb,
- u16 *result_code,
size_t const_resp_size,
size_t *var_resp_size)
{
@@ -88,7 +87,8 @@ static int qtnf_cmd_send_with_reply(struct qtnf_bus *bus,
const struct qlink_resp *resp;
struct sk_buff *resp_skb = NULL;
u16 cmd_id;
- u8 mac_id, vif_id;
+ u8 mac_id;
+ u8 vif_id;
int ret;
cmd = (struct qlink_cmd *)cmd_skb->data;
@@ -97,8 +97,11 @@ static int qtnf_cmd_send_with_reply(struct qtnf_bus *bus,
vif_id = cmd->vifid;
cmd->mhdr.len = cpu_to_le16(cmd_skb->len);
- if (unlikely(bus->fw_state != QTNF_FW_STATE_ACTIVE &&
- le16_to_cpu(cmd->cmd_id) != QLINK_CMD_FW_INIT)) {
+ pr_debug("VIF%u.%u cmd=0x%.4X\n", mac_id, vif_id,
+ le16_to_cpu(cmd->cmd_id));
+
+ if (bus->fw_state != QTNF_FW_STATE_ACTIVE &&
+ le16_to_cpu(cmd->cmd_id) != QLINK_CMD_FW_INIT) {
pr_warn("VIF%u.%u: drop cmd 0x%.4X in fw state %d\n",
mac_id, vif_id, le16_to_cpu(cmd->cmd_id),
bus->fw_state);
@@ -106,24 +109,16 @@ static int qtnf_cmd_send_with_reply(struct qtnf_bus *bus,
return -ENODEV;
}
- pr_debug("VIF%u.%u cmd=0x%.4X\n", mac_id, vif_id,
- le16_to_cpu(cmd->cmd_id));
-
ret = qtnf_trans_send_cmd_with_resp(bus, cmd_skb, &resp_skb);
-
- if (unlikely(ret))
+ if (ret)
goto out;
resp = (const struct qlink_resp *)resp_skb->data;
ret = qtnf_cmd_check_reply_header(resp, cmd_id, mac_id, vif_id,
const_resp_size);
-
- if (unlikely(ret))
+ if (ret)
goto out;
- if (likely(result_code))
- *result_code = le16_to_cpu(resp->result);
-
/* Return length of variable part of response */
if (response_skb && var_resp_size)
*var_resp_size = le16_to_cpu(resp->mhdr.len) - const_resp_size;
@@ -134,14 +129,18 @@ out:
else
consume_skb(resp_skb);
+ if (!ret && resp)
+ return qtnf_cmd_resp_result_decode(le16_to_cpu(resp->result));
+
+ pr_warn("VIF%u.%u: cmd 0x%.4X failed: %d\n",
+ mac_id, vif_id, le16_to_cpu(cmd->cmd_id), ret);
+
return ret;
}
-static inline int qtnf_cmd_send(struct qtnf_bus *bus,
- struct sk_buff *cmd_skb,
- u16 *result_code)
+static inline int qtnf_cmd_send(struct qtnf_bus *bus, struct sk_buff *cmd_skb)
{
- return qtnf_cmd_send_with_reply(bus, cmd_skb, NULL, result_code,
+ return qtnf_cmd_send_with_reply(bus, cmd_skb, NULL,
sizeof(struct qlink_resp), NULL);
}
@@ -228,7 +227,6 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif,
struct sk_buff *cmd_skb;
struct qlink_cmd_start_ap *cmd;
struct qlink_auth_encr *aen;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret;
int i;
@@ -329,30 +327,21 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif,
}
qtnf_bus_lock(vif->mac->bus);
-
- ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
-
- if (unlikely(ret))
- goto out;
-
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
- vif->vifid, res_code);
- ret = -EFAULT;
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
+ if (ret)
goto out;
- }
netif_carrier_on(vif->netdev);
out:
qtnf_bus_unlock(vif->mac->bus);
+
return ret;
}
int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif)
{
struct sk_buff *cmd_skb;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
@@ -362,23 +351,13 @@ int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif)
return -ENOMEM;
qtnf_bus_lock(vif->mac->bus);
-
- ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
-
- if (unlikely(ret))
- goto out;
-
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
- vif->vifid, res_code);
- ret = -EFAULT;
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
+ if (ret)
goto out;
- }
-
- netif_carrier_off(vif->netdev);
out:
qtnf_bus_unlock(vif->mac->bus);
+
return ret;
}
@@ -386,7 +365,6 @@ int qtnf_cmd_send_register_mgmt(struct qtnf_vif *vif, u16 frame_type, bool reg)
{
struct sk_buff *cmd_skb;
struct qlink_cmd_mgmt_frame_register *cmd;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
@@ -401,20 +379,13 @@ int qtnf_cmd_send_register_mgmt(struct qtnf_vif *vif, u16 frame_type, bool reg)
cmd->frame_type = cpu_to_le16(frame_type);
cmd->do_register = reg;
- ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
-
- if (unlikely(ret))
- goto out;
-
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
- vif->vifid, res_code);
- ret = -EFAULT;
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
+ if (ret)
goto out;
- }
out:
qtnf_bus_unlock(vif->mac->bus);
+
return ret;
}
@@ -423,7 +394,6 @@ int qtnf_cmd_send_mgmt_frame(struct qtnf_vif *vif, u32 cookie, u16 flags,
{
struct sk_buff *cmd_skb;
struct qlink_cmd_mgmt_frame_tx *cmd;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret;
if (sizeof(*cmd) + len > QTNF_MAX_CMD_BUF_SIZE) {
@@ -448,20 +418,13 @@ int qtnf_cmd_send_mgmt_frame(struct qtnf_vif *vif, u32 cookie, u16 flags,
if (len && buf)
qtnf_cmd_skb_put_buffer(cmd_skb, buf, len);
- ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
-
- if (unlikely(ret))
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
+ if (ret)
goto out;
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
- vif->vifid, res_code);
- ret = -EFAULT;
- goto out;
- }
-
out:
qtnf_bus_unlock(vif->mac->bus);
+
return ret;
}
@@ -469,7 +432,6 @@ int qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif *vif, u8 frame_type,
const u8 *buf, size_t len)
{
struct sk_buff *cmd_skb;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret;
if (len > QTNF_MAX_CMD_BUF_SIZE) {
@@ -487,21 +449,13 @@ int qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif *vif, u8 frame_type,
qtnf_cmd_tlv_ie_set_add(cmd_skb, frame_type, buf, len);
qtnf_bus_lock(vif->mac->bus);
-
- ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
-
- if (unlikely(ret))
- goto out;
-
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("VIF%u.%u frame %u: CMD failed: %u\n", vif->mac->macid,
- vif->vifid, frame_type, res_code);
- ret = -EFAULT;
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
+ if (ret)
goto out;
- }
out:
qtnf_bus_unlock(vif->mac->bus);
+
return ret;
}
@@ -544,6 +498,9 @@ qtnf_sta_info_parse_rate(struct rate_info *rate_dst,
rate_dst->flags |= RATE_INFO_FLAGS_MCS;
else if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_VHT_MCS)
rate_dst->flags |= RATE_INFO_FLAGS_VHT_MCS;
+
+ if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_SHORT_GI)
+ rate_dst->flags |= RATE_INFO_FLAGS_SHORT_GI;
}
static void
@@ -730,7 +687,6 @@ int qtnf_cmd_get_sta_info(struct qtnf_vif *vif, const u8 *sta_mac,
struct qlink_cmd_get_sta_info *cmd;
const struct qlink_resp_get_sta_info *resp;
size_t var_resp_len;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret = 0;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
@@ -745,31 +701,13 @@ int qtnf_cmd_get_sta_info(struct qtnf_vif *vif, const u8 *sta_mac,
ether_addr_copy(cmd->sta_addr, sta_mac);
ret = qtnf_cmd_send_with_reply(vif->mac->bus, cmd_skb, &resp_skb,
- &res_code, sizeof(*resp),
- &var_resp_len);
-
- if (unlikely(ret))
- goto out;
-
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- switch (res_code) {
- case QLINK_CMD_RESULT_ENOTFOUND:
- pr_warn("VIF%u.%u: %pM STA not found\n",
- vif->mac->macid, vif->vifid, sta_mac);
- ret = -ENOENT;
- break;
- default:
- pr_err("VIF%u.%u: can't get info for %pM: %u\n",
- vif->mac->macid, vif->vifid, sta_mac, res_code);
- ret = -EFAULT;
- break;
- }
+ sizeof(*resp), &var_resp_len);
+ if (ret)
goto out;
- }
resp = (const struct qlink_resp_get_sta_info *)resp_skb->data;
- if (unlikely(!ether_addr_equal(sta_mac, resp->sta_addr))) {
+ if (!ether_addr_equal(sta_mac, resp->sta_addr)) {
pr_err("VIF%u.%u: wrong mac in reply: %pM != %pM\n",
vif->mac->macid, vif->vifid, resp->sta_addr, sta_mac);
ret = -EINVAL;
@@ -795,7 +733,6 @@ static int qtnf_cmd_send_add_change_intf(struct qtnf_vif *vif,
struct sk_buff *cmd_skb, *resp_skb = NULL;
struct qlink_cmd_manage_intf *cmd;
const struct qlink_resp_manage_intf *resp;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret = 0;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
@@ -828,17 +765,9 @@ static int qtnf_cmd_send_add_change_intf(struct qtnf_vif *vif,
eth_zero_addr(cmd->intf_info.mac_addr);
ret = qtnf_cmd_send_with_reply(vif->mac->bus, cmd_skb, &resp_skb,
- &res_code, sizeof(*resp), NULL);
-
- if (unlikely(ret))
- goto out;
-
- ret = qtnf_cmd_resp_result_decode(res_code);
- if (ret) {
- pr_err("VIF%u.%u: CMD %d failed: %u\n", vif->mac->macid,
- vif->vifid, cmd_type, res_code);
+ sizeof(*resp), NULL);
+ if (ret)
goto out;
- }
resp = (const struct qlink_resp_manage_intf *)resp_skb->data;
ether_addr_copy(vif->mac_addr, resp->intf_info.mac_addr);
@@ -868,7 +797,6 @@ int qtnf_cmd_send_del_intf(struct qtnf_vif *vif)
{
struct sk_buff *cmd_skb;
struct qlink_cmd_manage_intf *cmd;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret = 0;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
@@ -897,17 +825,9 @@ int qtnf_cmd_send_del_intf(struct qtnf_vif *vif)
eth_zero_addr(cmd->intf_info.mac_addr);
- ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
-
- if (unlikely(ret))
- goto out;
-
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
- vif->vifid, res_code);
- ret = -EFAULT;
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
+ if (ret)
goto out;
- }
out:
qtnf_bus_unlock(vif->mac->bus);
@@ -1353,8 +1273,7 @@ static int qtnf_parse_variable_mac_info(struct qtnf_wmac *mac,
ext_capa_mask = NULL;
}
- kfree(mac->macinfo.extended_capabilities);
- kfree(mac->macinfo.extended_capabilities_mask);
+ qtnf_mac_ext_caps_free(mac);
mac->macinfo.extended_capabilities = ext_capa;
mac->macinfo.extended_capabilities_mask = ext_capa_mask;
mac->macinfo.extended_capabilities_len = ext_capa_len;
@@ -1732,7 +1651,6 @@ int qtnf_cmd_get_mac_info(struct qtnf_wmac *mac)
struct sk_buff *cmd_skb, *resp_skb = NULL;
const struct qlink_resp_get_mac_info *resp;
size_t var_data_len;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret = 0;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
@@ -1742,18 +1660,11 @@ int qtnf_cmd_get_mac_info(struct qtnf_wmac *mac)
return -ENOMEM;
qtnf_bus_lock(mac->bus);
-
- ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, &res_code,
+ ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb,
sizeof(*resp), &var_data_len);
- if (unlikely(ret))
+ if (ret)
goto out;
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code);
- ret = -EFAULT;
- goto out;
- }
-
resp = (const struct qlink_resp_get_mac_info *)resp_skb->data;
qtnf_cmd_resp_proc_mac_info(mac, resp);
ret = qtnf_parse_variable_mac_info(mac, resp->var_info, var_data_len);
@@ -1769,7 +1680,6 @@ int qtnf_cmd_get_hw_info(struct qtnf_bus *bus)
{
struct sk_buff *cmd_skb, *resp_skb = NULL;
const struct qlink_resp_get_hw_info *resp;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret = 0;
size_t info_len;
@@ -1780,18 +1690,10 @@ int qtnf_cmd_get_hw_info(struct qtnf_bus *bus)
return -ENOMEM;
qtnf_bus_lock(bus);
-
- ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb, &res_code,
+ ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb,
sizeof(*resp), &info_len);
-
- if (unlikely(ret))
- goto out;
-
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("cmd exec failed: 0x%.4X\n", res_code);
- ret = -EFAULT;
+ if (ret)
goto out;
- }
resp = (const struct qlink_resp_get_hw_info *)resp_skb->data;
ret = qtnf_cmd_resp_proc_hw_info(bus, resp, info_len);
@@ -1810,7 +1712,6 @@ int qtnf_cmd_band_info_get(struct qtnf_wmac *mac,
size_t info_len;
struct qlink_cmd_band_info_get *cmd;
struct qlink_resp_band_info_get *resp;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret = 0;
u8 qband;
@@ -1838,18 +1739,10 @@ int qtnf_cmd_band_info_get(struct qtnf_wmac *mac,
cmd->band = qband;
qtnf_bus_lock(mac->bus);
-
- ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, &res_code,
+ ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb,
sizeof(*resp), &info_len);
-
- if (unlikely(ret))
- goto out;
-
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code);
- ret = -EFAULT;
+ if (ret)
goto out;
- }
resp = (struct qlink_resp_band_info_get *)resp_skb->data;
if (resp->band != qband) {
@@ -1873,7 +1766,6 @@ int qtnf_cmd_send_get_phy_params(struct qtnf_wmac *mac)
struct sk_buff *cmd_skb, *resp_skb = NULL;
size_t response_size;
struct qlink_resp_phy_params *resp;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret = 0;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0,
@@ -1883,19 +1775,11 @@ int qtnf_cmd_send_get_phy_params(struct qtnf_wmac *mac)
return -ENOMEM;
qtnf_bus_lock(mac->bus);
-
- ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, &res_code,
+ ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb,
sizeof(*resp), &response_size);
-
- if (unlikely(ret))
+ if (ret)
goto out;
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code);
- ret = -EFAULT;
- goto out;
- }
-
resp = (struct qlink_resp_phy_params *)resp_skb->data;
ret = qtnf_cmd_resp_proc_phy_params(mac, resp->info, response_size);
@@ -1910,7 +1794,6 @@ int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed)
{
struct wiphy *wiphy = priv_to_wiphy(mac);
struct sk_buff *cmd_skb;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret = 0;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0,
@@ -1931,26 +1814,19 @@ int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed)
qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_COVERAGE_CLASS,
wiphy->coverage_class);
- ret = qtnf_cmd_send(mac->bus, cmd_skb, &res_code);
-
- if (unlikely(ret))
- goto out;
-
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code);
- ret = -EFAULT;
+ ret = qtnf_cmd_send(mac->bus, cmd_skb);
+ if (ret)
goto out;
- }
out:
qtnf_bus_unlock(mac->bus);
+
return ret;
}
int qtnf_cmd_send_init_fw(struct qtnf_bus *bus)
{
struct sk_buff *cmd_skb;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret = 0;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
@@ -1960,20 +1836,13 @@ int qtnf_cmd_send_init_fw(struct qtnf_bus *bus)
return -ENOMEM;
qtnf_bus_lock(bus);
-
- ret = qtnf_cmd_send(bus, cmd_skb, &res_code);
-
- if (unlikely(ret))
+ ret = qtnf_cmd_send(bus, cmd_skb);
+ if (ret)
goto out;
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("cmd exec failed: 0x%.4X\n", res_code);
- ret = -EFAULT;
- goto out;
- }
-
out:
qtnf_bus_unlock(bus);
+
return ret;
}
@@ -1988,9 +1857,7 @@ void qtnf_cmd_send_deinit_fw(struct qtnf_bus *bus)
return;
qtnf_bus_lock(bus);
-
- qtnf_cmd_send(bus, cmd_skb, NULL);
-
+ qtnf_cmd_send(bus, cmd_skb);
qtnf_bus_unlock(bus);
}
@@ -1999,7 +1866,6 @@ int qtnf_cmd_send_add_key(struct qtnf_vif *vif, u8 key_index, bool pairwise,
{
struct sk_buff *cmd_skb;
struct qlink_cmd_add_key *cmd;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret = 0;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
@@ -2031,19 +1897,13 @@ int qtnf_cmd_send_add_key(struct qtnf_vif *vif, u8 key_index, bool pairwise,
params->seq,
params->seq_len);
- ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
- if (unlikely(ret))
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
+ if (ret)
goto out;
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("VIF%u.%u: CMD failed: %u\n",
- vif->mac->macid, vif->vifid, res_code);
- ret = -EFAULT;
- goto out;
- }
-
out:
qtnf_bus_unlock(vif->mac->bus);
+
return ret;
}
@@ -2052,7 +1912,6 @@ int qtnf_cmd_send_del_key(struct qtnf_vif *vif, u8 key_index, bool pairwise,
{
struct sk_buff *cmd_skb;
struct qlink_cmd_del_key *cmd;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret = 0;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
@@ -2072,19 +1931,14 @@ int qtnf_cmd_send_del_key(struct qtnf_vif *vif, u8 key_index, bool pairwise,
cmd->key_index = key_index;
cmd->pairwise = pairwise;
- ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
- if (unlikely(ret))
- goto out;
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("VIF%u.%u: CMD failed: %u\n",
- vif->mac->macid, vif->vifid, res_code);
- ret = -EFAULT;
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
+ if (ret)
goto out;
- }
out:
qtnf_bus_unlock(vif->mac->bus);
+
return ret;
}
@@ -2093,7 +1947,6 @@ int qtnf_cmd_send_set_default_key(struct qtnf_vif *vif, u8 key_index,
{
struct sk_buff *cmd_skb;
struct qlink_cmd_set_def_key *cmd;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret = 0;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
@@ -2108,19 +1961,14 @@ int qtnf_cmd_send_set_default_key(struct qtnf_vif *vif, u8 key_index,
cmd->key_index = key_index;
cmd->unicast = unicast;
cmd->multicast = multicast;
- ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
- if (unlikely(ret))
- goto out;
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
- vif->vifid, res_code);
- ret = -EFAULT;
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
+ if (ret)
goto out;
- }
out:
qtnf_bus_unlock(vif->mac->bus);
+
return ret;
}
@@ -2128,7 +1976,6 @@ int qtnf_cmd_send_set_default_mgmt_key(struct qtnf_vif *vif, u8 key_index)
{
struct sk_buff *cmd_skb;
struct qlink_cmd_set_def_mgmt_key *cmd;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret = 0;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
@@ -2141,19 +1988,14 @@ int qtnf_cmd_send_set_default_mgmt_key(struct qtnf_vif *vif, u8 key_index)
cmd = (struct qlink_cmd_set_def_mgmt_key *)cmd_skb->data;
cmd->key_index = key_index;
- ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
- if (unlikely(ret))
- goto out;
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
- vif->vifid, res_code);
- ret = -EFAULT;
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
+ if (ret)
goto out;
- }
out:
qtnf_bus_unlock(vif->mac->bus);
+
return ret;
}
@@ -2183,7 +2025,6 @@ int qtnf_cmd_send_change_sta(struct qtnf_vif *vif, const u8 *mac,
{
struct sk_buff *cmd_skb;
struct qlink_cmd_change_sta *cmd;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret = 0;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
@@ -2214,19 +2055,13 @@ int qtnf_cmd_send_change_sta(struct qtnf_vif *vif, const u8 *mac,
goto out;
}
- ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
- if (unlikely(ret))
- goto out;
-
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
- vif->vifid, res_code);
- ret = -EFAULT;
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
+ if (ret)
goto out;
- }
out:
qtnf_bus_unlock(vif->mac->bus);
+
return ret;
}
@@ -2235,7 +2070,6 @@ int qtnf_cmd_send_del_sta(struct qtnf_vif *vif,
{
struct sk_buff *cmd_skb;
struct qlink_cmd_del_sta *cmd;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret = 0;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
@@ -2256,19 +2090,13 @@ int qtnf_cmd_send_del_sta(struct qtnf_vif *vif,
cmd->subtype = params->subtype;
cmd->reason_code = cpu_to_le16(params->reason_code);
- ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
- if (unlikely(ret))
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
+ if (ret)
goto out;
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
- vif->vifid, res_code);
- ret = -EFAULT;
- goto out;
- }
-
out:
qtnf_bus_unlock(vif->mac->bus);
+
return ret;
}
@@ -2312,7 +2140,6 @@ static void qtnf_cmd_randmac_tlv_add(struct sk_buff *cmd_skb,
int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
{
struct sk_buff *cmd_skb;
- u16 res_code = QLINK_CMD_RESULT_OK;
struct ieee80211_channel *sc;
struct cfg80211_scan_request *scan_req = mac->scan_req;
int n_channels;
@@ -2370,20 +2197,28 @@ int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
scan_req->mac_addr_mask);
}
- ret = qtnf_cmd_send(mac->bus, cmd_skb, &res_code);
+ if (scan_req->flags & NL80211_SCAN_FLAG_FLUSH) {
+ pr_debug("MAC%u: flush cache before scan\n", mac->macid);
- if (unlikely(ret))
- goto out;
+ qtnf_cmd_skb_put_tlv_tag(cmd_skb, QTN_TLV_ID_SCAN_FLUSH);
+ }
- pr_debug("MAC%u: scan started\n", mac->macid);
+ if (scan_req->duration) {
+ pr_debug("MAC%u: %s scan duration %u\n", mac->macid,
+ scan_req->duration_mandatory ? "mandatory" : "max",
+ scan_req->duration);
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code);
- ret = -EFAULT;
- goto out;
+ qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_SCAN_DWELL,
+ scan_req->duration);
}
+
+ ret = qtnf_cmd_send(mac->bus, cmd_skb);
+ if (ret)
+ goto out;
+
out:
qtnf_bus_unlock(mac->bus);
+
return ret;
}
@@ -2393,7 +2228,6 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif,
struct sk_buff *cmd_skb;
struct qlink_cmd_connect *cmd;
struct qlink_auth_encr *aen;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret;
int i;
u32 connect_flags = 0;
@@ -2474,20 +2308,13 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif,
qtnf_cmd_channel_tlv_add(cmd_skb, sme->channel);
qtnf_bus_lock(vif->mac->bus);
-
- ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
-
- if (unlikely(ret))
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
+ if (ret)
goto out;
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
- vif->vifid, res_code);
- ret = -EFAULT;
- goto out;
- }
out:
qtnf_bus_unlock(vif->mac->bus);
+
return ret;
}
@@ -2495,7 +2322,6 @@ int qtnf_cmd_send_disconnect(struct qtnf_vif *vif, u16 reason_code)
{
struct sk_buff *cmd_skb;
struct qlink_cmd_disconnect *cmd;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
@@ -2509,19 +2335,13 @@ int qtnf_cmd_send_disconnect(struct qtnf_vif *vif, u16 reason_code)
cmd = (struct qlink_cmd_disconnect *)cmd_skb->data;
cmd->reason = cpu_to_le16(reason_code);
- ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
-
- if (unlikely(ret))
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
+ if (ret)
goto out;
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
- vif->vifid, res_code);
- ret = -EFAULT;
- goto out;
- }
out:
qtnf_bus_unlock(vif->mac->bus);
+
return ret;
}
@@ -2529,7 +2349,6 @@ int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif, bool up)
{
struct sk_buff *cmd_skb;
struct qlink_cmd_updown *cmd;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
@@ -2542,20 +2361,13 @@ int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif, bool up)
cmd->if_up = !!up;
qtnf_bus_lock(vif->mac->bus);
-
- ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
-
- if (unlikely(ret))
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
+ if (ret)
goto out;
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
- vif->vifid, res_code);
- ret = -EFAULT;
- goto out;
- }
out:
qtnf_bus_unlock(vif->mac->bus);
+
return ret;
}
@@ -2563,7 +2375,6 @@ int qtnf_cmd_reg_notify(struct qtnf_bus *bus, struct regulatory_request *req)
{
struct sk_buff *cmd_skb;
int ret;
- u16 res_code;
struct qlink_cmd_reg_notify *cmd;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
@@ -2604,29 +2415,10 @@ int qtnf_cmd_reg_notify(struct qtnf_bus *bus, struct regulatory_request *req)
}
qtnf_bus_lock(bus);
-
- ret = qtnf_cmd_send(bus, cmd_skb, &res_code);
+ ret = qtnf_cmd_send(bus, cmd_skb);
if (ret)
goto out;
- switch (res_code) {
- case QLINK_CMD_RESULT_ENOTSUPP:
- pr_warn("reg update not supported\n");
- ret = -EOPNOTSUPP;
- break;
- case QLINK_CMD_RESULT_EALREADY:
- pr_info("regulatory domain is already set to %c%c",
- req->alpha2[0], req->alpha2[1]);
- ret = -EALREADY;
- break;
- case QLINK_CMD_RESULT_OK:
- ret = 0;
- break;
- default:
- ret = -EFAULT;
- break;
- }
-
out:
qtnf_bus_unlock(bus);
@@ -2640,7 +2432,6 @@ int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel,
struct qlink_cmd_get_chan_stats *cmd;
struct qlink_resp_get_chan_stats *resp;
size_t var_data_len;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret = 0;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
@@ -2654,25 +2445,10 @@ int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel,
cmd = (struct qlink_cmd_get_chan_stats *)cmd_skb->data;
cmd->channel = cpu_to_le16(channel);
- ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, &res_code,
+ ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb,
sizeof(*resp), &var_data_len);
- if (unlikely(ret)) {
- qtnf_bus_unlock(mac->bus);
- return ret;
- }
-
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- switch (res_code) {
- case QLINK_CMD_RESULT_ENOTFOUND:
- ret = -ENOENT;
- break;
- default:
- pr_err("cmd exec failed: 0x%.4X\n", res_code);
- ret = -EFAULT;
- break;
- }
+ if (ret)
goto out;
- }
resp = (struct qlink_resp_get_chan_stats *)resp_skb->data;
ret = qtnf_cmd_resp_proc_chan_stat_info(stats, resp->info,
@@ -2681,6 +2457,7 @@ int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel,
out:
qtnf_bus_unlock(mac->bus);
consume_skb(resp_skb);
+
return ret;
}
@@ -2690,7 +2467,6 @@ int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif,
struct qtnf_wmac *mac = vif->mac;
struct qlink_cmd_chan_switch *cmd;
struct sk_buff *cmd_skb;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, vif->vifid,
@@ -2707,32 +2483,13 @@ int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif,
cmd->block_tx = params->block_tx;
cmd->beacon_count = params->count;
- ret = qtnf_cmd_send(mac->bus, cmd_skb, &res_code);
-
- if (unlikely(ret))
+ ret = qtnf_cmd_send(mac->bus, cmd_skb);
+ if (ret)
goto out;
- switch (res_code) {
- case QLINK_CMD_RESULT_OK:
- ret = 0;
- break;
- case QLINK_CMD_RESULT_ENOTFOUND:
- ret = -ENOENT;
- break;
- case QLINK_CMD_RESULT_ENOTSUPP:
- ret = -EOPNOTSUPP;
- break;
- case QLINK_CMD_RESULT_EALREADY:
- ret = -EALREADY;
- break;
- case QLINK_CMD_RESULT_INVALID:
- default:
- ret = -EFAULT;
- break;
- }
-
out:
qtnf_bus_unlock(mac->bus);
+
return ret;
}
@@ -2742,7 +2499,6 @@ int qtnf_cmd_get_channel(struct qtnf_vif *vif, struct cfg80211_chan_def *chdef)
const struct qlink_resp_channel_get *resp;
struct sk_buff *cmd_skb;
struct sk_buff *resp_skb = NULL;
- u16 res_code = QLINK_CMD_RESULT_OK;
int ret;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
@@ -2752,25 +2508,18 @@ int qtnf_cmd_get_channel(struct qtnf_vif *vif, struct cfg80211_chan_def *chdef)
return -ENOMEM;
qtnf_bus_lock(bus);
-
- ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb, &res_code,
+ ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb,
sizeof(*resp), NULL);
-
- qtnf_bus_unlock(bus);
-
- if (unlikely(ret))
+ if (ret)
goto out;
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- ret = -ENODATA;
- goto out;
- }
-
resp = (const struct qlink_resp_channel_get *)resp_skb->data;
qlink_chandef_q2cfg(priv_to_wiphy(vif->mac), &resp->chan, chdef);
out:
+ qtnf_bus_unlock(bus);
consume_skb(resp_skb);
+
return ret;
}
@@ -2782,7 +2531,6 @@ int qtnf_cmd_start_cac(const struct qtnf_vif *vif,
struct sk_buff *cmd_skb;
struct qlink_cmd_start_cac *cmd;
int ret;
- u16 res_code;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_START_CAC,
@@ -2795,19 +2543,12 @@ int qtnf_cmd_start_cac(const struct qtnf_vif *vif,
qlink_chandef_cfg2q(chdef, &cmd->chan);
qtnf_bus_lock(bus);
- ret = qtnf_cmd_send(bus, cmd_skb, &res_code);
- qtnf_bus_unlock(bus);
-
+ ret = qtnf_cmd_send(bus, cmd_skb);
if (ret)
- return ret;
+ goto out;
- switch (res_code) {
- case QLINK_CMD_RESULT_OK:
- break;
- default:
- ret = -EOPNOTSUPP;
- break;
- }
+out:
+ qtnf_bus_unlock(bus);
return ret;
}
@@ -2819,7 +2560,6 @@ int qtnf_cmd_set_mac_acl(const struct qtnf_vif *vif,
struct sk_buff *cmd_skb;
struct qlink_tlv_hdr *tlv;
size_t acl_size = qtnf_cmd_acl_data_size(params);
- u16 res_code;
int ret;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
@@ -2834,22 +2574,12 @@ int qtnf_cmd_set_mac_acl(const struct qtnf_vif *vif,
qlink_acl_data_cfg2q(params, (struct qlink_acl_data *)tlv->val);
qtnf_bus_lock(bus);
- ret = qtnf_cmd_send(bus, cmd_skb, &res_code);
- qtnf_bus_unlock(bus);
-
- if (unlikely(ret))
- return ret;
+ ret = qtnf_cmd_send(bus, cmd_skb);
+ if (ret)
+ goto out;
- switch (res_code) {
- case QLINK_CMD_RESULT_OK:
- break;
- case QLINK_CMD_RESULT_INVALID:
- ret = -EINVAL;
- break;
- default:
- ret = -EOPNOTSUPP;
- break;
- }
+out:
+ qtnf_bus_unlock(bus);
return ret;
}
@@ -2858,7 +2588,6 @@ int qtnf_cmd_send_pm_set(const struct qtnf_vif *vif, u8 pm_mode, int timeout)
{
struct qtnf_bus *bus = vif->mac->bus;
struct sk_buff *cmd_skb;
- u16 res_code = QLINK_CMD_RESULT_OK;
struct qlink_cmd_pm_set *cmd;
int ret = 0;
@@ -2873,18 +2602,13 @@ int qtnf_cmd_send_pm_set(const struct qtnf_vif *vif, u8 pm_mode, int timeout)
qtnf_bus_lock(bus);
- ret = qtnf_cmd_send(bus, cmd_skb, &res_code);
-
- if (unlikely(ret))
+ ret = qtnf_cmd_send(bus, cmd_skb);
+ if (ret)
goto out;
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("cmd exec failed: 0x%.4X\n", res_code);
- ret = -EFAULT;
- }
-
out:
qtnf_bus_unlock(bus);
+
return ret;
}
@@ -2893,7 +2617,6 @@ int qtnf_cmd_send_wowlan_set(const struct qtnf_vif *vif,
{
struct qtnf_bus *bus = vif->mac->bus;
struct sk_buff *cmd_skb;
- u16 res_code = QLINK_CMD_RESULT_OK;
struct qlink_cmd_wowlan_set *cmd;
u32 triggers = 0;
int count = 0;
@@ -2929,16 +2652,10 @@ int qtnf_cmd_send_wowlan_set(const struct qtnf_vif *vif,
cmd->triggers = cpu_to_le32(triggers);
- ret = qtnf_cmd_send(bus, cmd_skb, &res_code);
-
- if (unlikely(ret))
+ ret = qtnf_cmd_send(bus, cmd_skb);
+ if (ret)
goto out;
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("cmd exec failed: 0x%.4X\n", res_code);
- ret = -EFAULT;
- }
-
out:
qtnf_bus_unlock(bus);
return ret;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c
index 19abbc4e23e0..5d18a4a917c9 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
@@ -304,6 +304,19 @@ void qtnf_mac_iface_comb_free(struct qtnf_wmac *mac)
}
}
+void qtnf_mac_ext_caps_free(struct qtnf_wmac *mac)
+{
+ if (mac->macinfo.extended_capabilities_len) {
+ kfree(mac->macinfo.extended_capabilities);
+ mac->macinfo.extended_capabilities = NULL;
+
+ kfree(mac->macinfo.extended_capabilities_mask);
+ mac->macinfo.extended_capabilities_mask = NULL;
+
+ mac->macinfo.extended_capabilities_len = 0;
+ }
+}
+
static void qtnf_vif_reset_handler(struct work_struct *work)
{
struct qtnf_vif *vif = container_of(work, struct qtnf_vif, reset_work);
@@ -370,6 +383,7 @@ static void qtnf_mac_scan_timeout(struct work_struct *work)
static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus,
unsigned int macid)
{
+ struct qtnf_vif *vif;
struct wiphy *wiphy;
struct qtnf_wmac *mac;
unsigned int i;
@@ -382,18 +396,20 @@ static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus,
mac->macid = macid;
mac->bus = bus;
+ mutex_init(&mac->mac_lock);
+ INIT_DELAYED_WORK(&mac->scan_timeout, qtnf_mac_scan_timeout);
for (i = 0; i < QTNF_MAX_INTF; i++) {
- memset(&mac->iflist[i], 0, sizeof(struct qtnf_vif));
- mac->iflist[i].wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
- mac->iflist[i].mac = mac;
- mac->iflist[i].vifid = i;
- qtnf_sta_list_init(&mac->iflist[i].sta_list);
- mutex_init(&mac->mac_lock);
- INIT_DELAYED_WORK(&mac->scan_timeout, qtnf_mac_scan_timeout);
- mac->iflist[i].stats64 =
- netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
- if (!mac->iflist[i].stats64)
+ vif = &mac->iflist[i];
+
+ memset(vif, 0, sizeof(*vif));
+ vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+ vif->mac = mac;
+ vif->vifid = i;
+ qtnf_sta_list_init(&vif->sta_list);
+
+ vif->stats64 = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
+ if (!vif->stats64)
pr_warn("VIF%u.%u: per cpu stats allocation failed\n",
macid, i);
}
@@ -493,8 +509,7 @@ static void qtnf_core_mac_detach(struct qtnf_bus *bus, unsigned int macid)
}
qtnf_mac_iface_comb_free(mac);
- kfree(mac->macinfo.extended_capabilities);
- kfree(mac->macinfo.extended_capabilities_mask);
+ qtnf_mac_ext_caps_free(mac);
kfree(mac->macinfo.wowlan);
wiphy_free(wiphy);
bus->mac[macid] = NULL;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h
index a1e338a1f055..293055049caa 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -64,12 +64,6 @@ struct qtnf_sta_list {
atomic_t size;
};
-enum qtnf_sta_state {
- QTNF_STA_DISCONNECTED,
- QTNF_STA_CONNECTING,
- QTNF_STA_CONNECTED
-};
-
struct qtnf_vif {
struct wireless_dev wdev;
u8 bssid[ETH_ALEN];
@@ -77,7 +71,6 @@ struct qtnf_vif {
u8 vifid;
u8 bss_priority;
u8 bss_status;
- enum qtnf_sta_state sta_state;
u16 mgmt_frames_bitmask;
struct net_device *netdev;
struct qtnf_wmac *mac;
@@ -151,6 +144,7 @@ struct qtnf_hw_info {
struct qtnf_vif *qtnf_mac_get_free_vif(struct qtnf_wmac *mac);
struct qtnf_vif *qtnf_mac_get_base_vif(struct qtnf_wmac *mac);
void qtnf_mac_iface_comb_free(struct qtnf_wmac *mac);
+void qtnf_mac_ext_caps_free(struct qtnf_wmac *mac);
struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus);
int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *priv,
const char *name, unsigned char name_assign_type);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c
index 68da81bec4e9..8b542b431b75 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -171,24 +171,14 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif,
return -EPROTO;
}
- if (vif->sta_state != QTNF_STA_CONNECTING) {
- pr_err("VIF%u.%u: BSS_JOIN event when STA is not connecting\n",
- vif->mac->macid, vif->vifid);
- return -EPROTO;
- }
-
pr_debug("VIF%u.%u: BSSID:%pM\n", vif->mac->macid, vif->vifid,
join_info->bssid);
cfg80211_connect_result(vif->netdev, join_info->bssid, NULL, 0, NULL,
0, le16_to_cpu(join_info->status), GFP_KERNEL);
- if (le16_to_cpu(join_info->status) == WLAN_STATUS_SUCCESS) {
- vif->sta_state = QTNF_STA_CONNECTED;
+ if (le16_to_cpu(join_info->status) == WLAN_STATUS_SUCCESS)
netif_carrier_on(vif->netdev);
- } else {
- vif->sta_state = QTNF_STA_DISCONNECTED;
- }
return 0;
}
@@ -211,16 +201,10 @@ qtnf_event_handle_bss_leave(struct qtnf_vif *vif,
return -EPROTO;
}
- if (vif->sta_state != QTNF_STA_CONNECTED)
- pr_warn("VIF%u.%u: BSS_LEAVE event when STA is not connected\n",
- vif->mac->macid, vif->vifid);
-
pr_debug("VIF%u.%u: disconnected\n", vif->mac->macid, vif->vifid);
cfg80211_disconnected(vif->netdev, le16_to_cpu(leave_info->reason),
NULL, 0, 0, GFP_KERNEL);
-
- vif->sta_state = QTNF_STA_DISCONNECTED;
netif_carrier_off(vif->netdev);
return 0;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
index d1637f2354a6..16795dbe475b 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
@@ -242,7 +242,8 @@ static int qtnf_pcie_init_memory(struct qtnf_pcie_bus_priv *priv)
return 0;
}
-static void qtnf_pcie_control_rx_callback(void *arg, const u8 *buf, size_t len)
+static void qtnf_pcie_control_rx_callback(void *arg, const u8 __iomem *buf,
+ size_t len)
{
struct qtnf_pcie_bus_priv *priv = arg;
struct qtnf_bus *bus = pci_get_drvdata(priv->pdev);
@@ -260,7 +261,7 @@ static void qtnf_pcie_control_rx_callback(void *arg, const u8 *buf, size_t len)
return;
}
- skb_put_data(skb, buf, len);
+ memcpy_fromio(skb_put(skb, len), buf, len);
qtnf_trans_handle_rx_ctl_packet(bus, skb);
}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index 99d37e3efba6..8d62addea895 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -71,6 +71,7 @@ struct qlink_msg_header {
* @QLINK_HW_CAPAB_DFS_OFFLOAD: device implements DFS offload functionality
* @QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR: device supports MAC Address
* Randomization in probe requests.
+ * @QLINK_HW_CAPAB_OBSS_SCAN: device can perform OBSS scanning.
*/
enum qlink_hw_capab {
QLINK_HW_CAPAB_REG_UPDATE = BIT(0),
@@ -78,6 +79,8 @@ enum qlink_hw_capab {
QLINK_HW_CAPAB_DFS_OFFLOAD = BIT(2),
QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR = BIT(3),
QLINK_HW_CAPAB_PWR_MGMT = BIT(4),
+ QLINK_HW_CAPAB_OBSS_SCAN = BIT(5),
+ QLINK_HW_CAPAB_SCAN_DWELL = BIT(6),
};
enum qlink_iface_type {
@@ -1149,6 +1152,8 @@ enum qlink_tlv_id {
QTN_TLV_ID_MAX_SCAN_SSIDS = 0x0409,
QTN_TLV_ID_WOWLAN_CAPAB = 0x0410,
QTN_TLV_ID_WOWLAN_PATTERN = 0x0411,
+ QTN_TLV_ID_SCAN_FLUSH = 0x0412,
+ QTN_TLV_ID_SCAN_DWELL = 0x0413,
};
struct qlink_tlv_hdr {
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
index 54caeb38917c..960d5d97492f 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
@@ -40,6 +40,14 @@ static inline void qtnf_cmd_skb_put_tlv_arr(struct sk_buff *skb,
memcpy(hdr->val, arr, arr_len);
}
+static inline void qtnf_cmd_skb_put_tlv_tag(struct sk_buff *skb, u16 tlv_id)
+{
+ struct qlink_tlv_hdr *hdr = skb_put(skb, sizeof(*hdr));
+
+ hdr->type = cpu_to_le16(tlv_id);
+ hdr->len = cpu_to_le16(0);
+}
+
static inline void qtnf_cmd_skb_put_tlv_u8(struct sk_buff *skb, u16 tlv_id,
u8 value)
{
diff --git a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c
index aa106dd0a14b..2ec334199c2b 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c
@@ -42,19 +42,18 @@ static void qtnf_shm_handle_new_data(struct qtnf_shm_ipc *ipc)
if (unlikely(size == 0 || size > QTN_IPC_MAX_DATA_SZ)) {
pr_err("wrong rx packet size: %zu\n", size);
rx_buff_ok = false;
- } else {
- memcpy_fromio(ipc->rx_data, ipc->shm_region->data, size);
+ }
+
+ if (likely(rx_buff_ok)) {
+ ipc->rx_packet_count++;
+ ipc->rx_callback.fn(ipc->rx_callback.arg,
+ ipc->shm_region->data, size);
}
writel(QTNF_SHM_IPC_ACK, &shm_reg_hdr->flags);
readl(&shm_reg_hdr->flags); /* flush PCIe write */
ipc->interrupt.fn(ipc->interrupt.arg);
-
- if (likely(rx_buff_ok)) {
- ipc->rx_packet_count++;
- ipc->rx_callback.fn(ipc->rx_callback.arg, ipc->rx_data, size);
- }
}
static void qtnf_shm_ipc_irq_work(struct work_struct *work)
diff --git a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h
index 453dd6477b12..c2a3702a9ee7 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h
@@ -32,7 +32,7 @@ struct qtnf_shm_ipc_int {
};
struct qtnf_shm_ipc_rx_callback {
- void (*fn)(void *arg, const u8 *buf, size_t len);
+ void (*fn)(void *arg, const u8 __iomem *buf, size_t len);
void *arg;
};
@@ -51,8 +51,6 @@ struct qtnf_shm_ipc {
u8 waiting_for_ack;
- u8 rx_data[QTN_IPC_MAX_DATA_SZ] __aligned(sizeof(u32));
-
struct qtnf_shm_ipc_int interrupt;
struct qtnf_shm_ipc_rx_callback rx_callback;
diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h
index 0f3b98c5227f..87bc21bb5e8b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/wifi.h
+++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h
@@ -1905,10 +1905,6 @@ struct rtl_efuse {
u8 efuse_map[2][EFUSE_MAX_LOGICAL_SIZE];
u16 efuse_usedbytes;
u8 efuse_usedpercentage;
-#ifdef EFUSE_REPG_WORKAROUND
- bool efuse_re_pg_sec1flag;
- u8 efuse_re_pg_data[8];
-#endif
u8 autoload_failflag;
u8 autoload_status;
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 89b0d0fade9f..26b187336875 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -27,6 +27,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/pm_runtime.h>
+#include <linux/pm_wakeirq.h>
#include "wlcore.h"
#include "debug.h"
@@ -957,6 +958,8 @@ static void wl1271_recovery_work(struct work_struct *work)
BUG_ON(wl->conf.recovery.bug_on_recovery &&
!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags));
+ clear_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags);
+
if (wl->conf.recovery.no_recovery) {
wl1271_info("No recovery (chosen on module load). Fw will remain stuck.");
goto out_unlock;
@@ -6625,13 +6628,25 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context)
}
#ifdef CONFIG_PM
+ device_init_wakeup(wl->dev, true);
+
ret = enable_irq_wake(wl->irq);
if (!ret) {
wl->irq_wake_enabled = true;
- device_init_wakeup(wl->dev, 1);
if (pdev_data->pwr_in_suspend)
wl->hw->wiphy->wowlan = &wlcore_wowlan_support;
}
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
+ if (res) {
+ wl->wakeirq = res->start;
+ wl->wakeirq_flags = res->flags & IRQF_TRIGGER_MASK;
+ ret = dev_pm_set_dedicated_wake_irq(wl->dev, wl->wakeirq);
+ if (ret)
+ wl->wakeirq = -ENODEV;
+ } else {
+ wl->wakeirq = -ENODEV;
+ }
#endif
disable_irq(wl->irq);
wl1271_power_off(wl);
@@ -6659,6 +6674,9 @@ out_unreg:
wl1271_unregister_hw(wl);
out_irq:
+ if (wl->wakeirq >= 0)
+ dev_pm_clear_wake_irq(wl->dev);
+ device_init_wakeup(wl->dev, false);
free_irq(wl->irq, wl);
out_free_nvs:
@@ -6710,6 +6728,7 @@ static int __maybe_unused wlcore_runtime_resume(struct device *dev)
int ret;
unsigned long start_time = jiffies;
bool pending = false;
+ bool recovery = false;
/* Nothing to do if no ELP mode requested */
if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags))
@@ -6726,7 +6745,7 @@ static int __maybe_unused wlcore_runtime_resume(struct device *dev)
ret = wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP);
if (ret < 0) {
- wl12xx_queue_recovery_work(wl);
+ recovery = true;
goto err;
}
@@ -6734,11 +6753,12 @@ static int __maybe_unused wlcore_runtime_resume(struct device *dev)
ret = wait_for_completion_timeout(&compl,
msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT));
if (ret == 0) {
- wl1271_error("ELP wakeup timeout!");
- wl12xx_queue_recovery_work(wl);
+ wl1271_warning("ELP wakeup timeout!");
/* Return no error for runtime PM for recovery */
- return 0;
+ ret = 0;
+ recovery = true;
+ goto err;
}
}
@@ -6753,6 +6773,12 @@ err:
spin_lock_irqsave(&wl->wl_lock, flags);
wl->elp_compl = NULL;
spin_unlock_irqrestore(&wl->wl_lock, flags);
+
+ if (recovery) {
+ set_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags);
+ wl12xx_queue_recovery_work(wl);
+ }
+
return ret;
}
@@ -6815,10 +6841,16 @@ int wlcore_remove(struct platform_device *pdev)
if (!wl->initialized)
return 0;
- if (wl->irq_wake_enabled) {
- device_init_wakeup(wl->dev, 0);
- disable_irq_wake(wl->irq);
+ if (wl->wakeirq >= 0) {
+ dev_pm_clear_wake_irq(wl->dev);
+ wl->wakeirq = -ENODEV;
}
+
+ device_init_wakeup(wl->dev, false);
+
+ if (wl->irq_wake_enabled)
+ disable_irq_wake(wl->irq);
+
wl1271_unregister_hw(wl);
pm_runtime_put_sync(wl->dev);
diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c
index 750bea3574ee..4c2154b9e6a3 100644
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -241,7 +241,7 @@ static const struct of_device_id wlcore_sdio_of_match_table[] = {
{ }
};
-static int wlcore_probe_of(struct device *dev, int *irq,
+static int wlcore_probe_of(struct device *dev, int *irq, int *wakeirq,
struct wlcore_platdev_data *pdev_data)
{
struct device_node *np = dev->of_node;
@@ -259,6 +259,8 @@ static int wlcore_probe_of(struct device *dev, int *irq,
return -EINVAL;
}
+ *wakeirq = irq_of_parse_and_map(np, 1);
+
/* optional clock frequency params */
of_property_read_u32(np, "ref-clock-frequency",
&pdev_data->ref_clock_freq);
@@ -268,7 +270,7 @@ static int wlcore_probe_of(struct device *dev, int *irq,
return 0;
}
#else
-static int wlcore_probe_of(struct device *dev, int *irq,
+static int wlcore_probe_of(struct device *dev, int *irq, int *wakeirq,
struct wlcore_platdev_data *pdev_data)
{
return -ENODATA;
@@ -280,10 +282,10 @@ static int wl1271_probe(struct sdio_func *func,
{
struct wlcore_platdev_data *pdev_data;
struct wl12xx_sdio_glue *glue;
- struct resource res[1];
+ struct resource res[2];
mmc_pm_flag_t mmcflags;
int ret = -ENOMEM;
- int irq;
+ int irq, wakeirq;
const char *chip_family;
/* We are only able to handle the wlan function */
@@ -308,7 +310,7 @@ static int wl1271_probe(struct sdio_func *func,
/* Use block mode for transferring over one block size of data */
func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
- ret = wlcore_probe_of(&func->dev, &irq, pdev_data);
+ ret = wlcore_probe_of(&func->dev, &irq, &wakeirq, pdev_data);
if (ret)
goto out;
@@ -351,6 +353,11 @@ static int wl1271_probe(struct sdio_func *func,
irqd_get_trigger_type(irq_get_irq_data(irq));
res[0].name = "irq";
+ res[1].start = wakeirq;
+ res[1].flags = IORESOURCE_IRQ |
+ irqd_get_trigger_type(irq_get_irq_data(wakeirq));
+ res[1].name = "wakeirq";
+
ret = platform_device_add_resources(glue->core, res, ARRAY_SIZE(res));
if (ret) {
dev_err(glue->dev, "can't add resources\n");
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index d4b1f66ef457..dd14850b0603 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -199,8 +199,10 @@ struct wl1271 {
struct wl1271_if_operations *if_ops;
int irq;
+ int wakeirq;
int irq_flags;
+ int wakeirq_flags;
spinlock_t wl_lock;
diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_mac.c b/drivers/net/wireless/zydas/zd1211rw/zd_mac.c
index 1f6d9f357e57..9ccd780695f0 100644
--- a/drivers/net/wireless/zydas/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zydas/zd1211rw/zd_mac.c
@@ -235,7 +235,7 @@ void zd_mac_clear(struct zd_mac *mac)
{
flush_workqueue(zd_workqueue);
zd_chip_clear(&mac->chip);
- ZD_ASSERT(!spin_is_locked(&mac->lock));
+ lockdep_assert_held(&mac->lock);
ZD_MEMCLEAR(mac, sizeof(struct zd_mac));
}
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c
index 99a4656d113d..3861cb659cb9 100644
--- a/drivers/ssb/driver_chipcommon.c
+++ b/drivers/ssb/driver_chipcommon.c
@@ -425,7 +425,7 @@ void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc,
*m = chipco_read32(cc, SSB_CHIPCO_CLOCK_M2);
break;
}
- /* Fallthough */
+ /* Fall through */
default:
*m = chipco_read32(cc, SSB_CHIPCO_CLOCK_SB);
}