summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath/ath10k/bmi.h6
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.c168
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.h132
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c53
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h1
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c27
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.c137
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.h87
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c77
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c27
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c51
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h3
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc_pipe.c2
-rw-r--r--drivers/net/wireless/ath/wil6210/Makefile1
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c613
-rw-r--r--drivers/net/wireless/ath/wil6210/debugfs.c49
-rw-r--r--drivers/net/wireless/ath/wil6210/interrupt.c6
-rw-r--r--drivers/net/wireless/ath/wil6210/ioctl.c180
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c7
-rw-r--r--drivers/net/wireless/ath/wil6210/netdev.c8
-rw-r--r--drivers/net/wireless/ath/wil6210/pcie_bus.c98
-rw-r--r--drivers/net/wireless/ath/wil6210/pm.c228
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.c71
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h40
-rw-r--r--drivers/net/wireless/ath/wil6210/wil_platform.h7
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c147
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.h27
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c15
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c69
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h6
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c1
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h43
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c444
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h47
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-8000.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-9000.c14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-a000.c8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-config.h11
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-csr.h8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.h12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-fh.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-fw-api.h205
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-fw-error-dump.h8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h16
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-io.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-modparams.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c95
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-trans.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-trans.h167
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/coex.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/constants.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c82
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-coex.h10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h29
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-mac.h10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-power.h45
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h88
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-scan.h34
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h46
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-stats.h29
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tof.h18
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h67
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h555
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c52
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c65
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/led.c5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c42
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h25
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/nvm.c133
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c32
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c48
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tdls.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/time-event.c5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tof.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tt.c14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tx.c27
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/drv.c12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/internal.h3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans.c135
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c172
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/tx.c5
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cfg80211.c2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cfp.c2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/debugfs.c3
-rw-r--r--drivers/net/wireless/marvell/mwifiex/main.h2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/scan.c4
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c4
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/commands.c12
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/base.c180
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/base.h14
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h22
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h32
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c52
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h41
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h3
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h38
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c871
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h45
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c85
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h7
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/core.c5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/debug.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/debug.h7
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c69
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c3
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h14
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c70
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c3
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c3
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h16
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c72
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c3
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h17
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/wifi.h18
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_hal.c4
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_main.c9
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_mgmt.c120
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_sdio.c21
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_usb.c1
-rw-r--r--drivers/net/wireless/rsi/rsi_boot_params.h15
-rw-r--r--drivers/net/wireless/rsi/rsi_hal.h3
-rw-r--r--drivers/net/wireless/rsi/rsi_main.h28
-rw-r--r--drivers/net/wireless/rsi/rsi_mgmt.h76
-rw-r--r--drivers/net/wireless/ti/wlcore/sdio.c1
-rw-r--r--drivers/net/wireless/ti/wlcore/spi.c8
145 files changed, 5601 insertions, 1734 deletions
diff --git a/drivers/net/wireless/ath/ath10k/bmi.h b/drivers/net/wireless/ath/ath10k/bmi.h
index 0342073ed397..9c0839b2ca8f 100644
--- a/drivers/net/wireless/ath/ath10k/bmi.h
+++ b/drivers/net/wireless/ath/ath10k/bmi.h
@@ -83,6 +83,8 @@ enum bmi_cmd_id {
#define BMI_NVRAM_SEG_NAME_SZ 16
#define BMI_PARAM_GET_EEPROM_BOARD_ID 0x10
+#define BMI_PARAM_GET_FLASH_BOARD_ID 0x8000
+#define BMI_PARAM_FLASH_SECTION_ALL 0x10000
#define ATH10K_BMI_BOARD_ID_FROM_OTP_MASK 0x7c00
#define ATH10K_BMI_BOARD_ID_FROM_OTP_LSB 10
@@ -188,8 +190,8 @@ struct bmi_target_info {
u32 type;
};
-/* in msec */
-#define BMI_COMMUNICATION_TIMEOUT_HZ (2 * HZ)
+/* in jiffies */
+#define BMI_COMMUNICATION_TIMEOUT_HZ (3 * HZ)
#define BMI_CE_NUM_TO_TARG 0
#define BMI_CE_NUM_TO_HOST 1
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
index ee1090ca2eac..08b84c8c3614 100644
--- a/drivers/net/wireless/ath/ath10k/ce.c
+++ b/drivers/net/wireless/ath/ath10k/ce.c
@@ -59,205 +59,243 @@
* the buffer is sent/received.
*/
+static inline unsigned int
+ath10k_set_ring_byte(unsigned int offset,
+ struct ath10k_hw_ce_regs_addr_map *addr_map)
+{
+ return ((offset << addr_map->lsb) & addr_map->mask);
+}
+
+static inline unsigned int
+ath10k_get_ring_byte(unsigned int offset,
+ struct ath10k_hw_ce_regs_addr_map *addr_map)
+{
+ return ((offset & addr_map->mask) >> (addr_map->lsb));
+}
+
static inline void ath10k_ce_dest_ring_write_index_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- ath10k_pci_write32(ar, ce_ctrl_addr + DST_WR_INDEX_ADDRESS, n);
+ ath10k_pci_write32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->dst_wr_index_addr, n);
}
static inline u32 ath10k_ce_dest_ring_write_index_get(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- return ath10k_pci_read32(ar, ce_ctrl_addr + DST_WR_INDEX_ADDRESS);
+ return ath10k_pci_read32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->dst_wr_index_addr);
}
static inline void ath10k_ce_src_ring_write_index_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- ath10k_pci_write32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS, n);
+ ath10k_pci_write32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->sr_wr_index_addr, n);
}
static inline u32 ath10k_ce_src_ring_write_index_get(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- return ath10k_pci_read32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS);
+ return ath10k_pci_read32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->sr_wr_index_addr);
}
static inline u32 ath10k_ce_src_ring_read_index_get(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- return ath10k_pci_read32(ar, ce_ctrl_addr + CURRENT_SRRI_ADDRESS);
+ return ath10k_pci_read32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->current_srri_addr);
}
static inline void ath10k_ce_src_ring_base_addr_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int addr)
{
- ath10k_pci_write32(ar, ce_ctrl_addr + SR_BA_ADDRESS, addr);
+ ath10k_pci_write32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->sr_base_addr, addr);
}
static inline void ath10k_ce_src_ring_size_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- ath10k_pci_write32(ar, ce_ctrl_addr + SR_SIZE_ADDRESS, n);
+ ath10k_pci_write32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->sr_size_addr, n);
}
static inline void ath10k_ce_src_ring_dmax_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- u32 ctrl1_addr = ath10k_pci_read32((ar),
- (ce_ctrl_addr) + CE_CTRL1_ADDRESS);
+ struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs;
+ u32 ctrl1_addr = ath10k_pci_read32(ar,
+ ce_ctrl_addr + ctrl_regs->addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS,
- (ctrl1_addr & ~CE_CTRL1_DMAX_LENGTH_MASK) |
- CE_CTRL1_DMAX_LENGTH_SET(n));
+ ath10k_pci_write32(ar, ce_ctrl_addr + ctrl_regs->addr,
+ (ctrl1_addr & ~(ctrl_regs->dmax->mask)) |
+ ath10k_set_ring_byte(n, ctrl_regs->dmax));
}
static inline void ath10k_ce_src_ring_byte_swap_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- u32 ctrl1_addr = ath10k_pci_read32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS);
+ struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs;
+ u32 ctrl1_addr = ath10k_pci_read32(ar, ce_ctrl_addr + ctrl_regs->addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS,
- (ctrl1_addr & ~CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) |
- CE_CTRL1_SRC_RING_BYTE_SWAP_EN_SET(n));
+ ath10k_pci_write32(ar, ce_ctrl_addr + ctrl_regs->addr,
+ (ctrl1_addr & ~(ctrl_regs->src_ring->mask)) |
+ ath10k_set_ring_byte(n, ctrl_regs->src_ring));
}
static inline void ath10k_ce_dest_ring_byte_swap_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- u32 ctrl1_addr = ath10k_pci_read32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS);
+ struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs;
+ u32 ctrl1_addr = ath10k_pci_read32(ar, ce_ctrl_addr + ctrl_regs->addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS,
- (ctrl1_addr & ~CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK) |
- CE_CTRL1_DST_RING_BYTE_SWAP_EN_SET(n));
+ ath10k_pci_write32(ar, ce_ctrl_addr + ctrl_regs->addr,
+ (ctrl1_addr & ~(ctrl_regs->dst_ring->mask)) |
+ ath10k_set_ring_byte(n, ctrl_regs->dst_ring));
}
static inline u32 ath10k_ce_dest_ring_read_index_get(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- return ath10k_pci_read32(ar, ce_ctrl_addr + CURRENT_DRRI_ADDRESS);
+ return ath10k_pci_read32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->current_drri_addr);
}
static inline void ath10k_ce_dest_ring_base_addr_set(struct ath10k *ar,
u32 ce_ctrl_addr,
u32 addr)
{
- ath10k_pci_write32(ar, ce_ctrl_addr + DR_BA_ADDRESS, addr);
+ ath10k_pci_write32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->dr_base_addr, addr);
}
static inline void ath10k_ce_dest_ring_size_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- ath10k_pci_write32(ar, ce_ctrl_addr + DR_SIZE_ADDRESS, n);
+ ath10k_pci_write32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->dr_size_addr, n);
}
static inline void ath10k_ce_src_ring_highmark_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS);
+ struct ath10k_hw_ce_dst_src_wm_regs *srcr_wm = ar->hw_ce_regs->wm_srcr;
+ u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + srcr_wm->addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS,
- (addr & ~SRC_WATERMARK_HIGH_MASK) |
- SRC_WATERMARK_HIGH_SET(n));
+ ath10k_pci_write32(ar, ce_ctrl_addr + srcr_wm->addr,
+ (addr & ~(srcr_wm->wm_high->mask)) |
+ (ath10k_set_ring_byte(n, srcr_wm->wm_high)));
}
static inline void ath10k_ce_src_ring_lowmark_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS);
+ struct ath10k_hw_ce_dst_src_wm_regs *srcr_wm = ar->hw_ce_regs->wm_srcr;
+ u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + srcr_wm->addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS,
- (addr & ~SRC_WATERMARK_LOW_MASK) |
- SRC_WATERMARK_LOW_SET(n));
+ ath10k_pci_write32(ar, ce_ctrl_addr + srcr_wm->addr,
+ (addr & ~(srcr_wm->wm_low->mask)) |
+ (ath10k_set_ring_byte(n, srcr_wm->wm_low)));
}
static inline void ath10k_ce_dest_ring_highmark_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS);
+ struct ath10k_hw_ce_dst_src_wm_regs *dstr_wm = ar->hw_ce_regs->wm_dstr;
+ u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + dstr_wm->addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS,
- (addr & ~DST_WATERMARK_HIGH_MASK) |
- DST_WATERMARK_HIGH_SET(n));
+ ath10k_pci_write32(ar, ce_ctrl_addr + dstr_wm->addr,
+ (addr & ~(dstr_wm->wm_high->mask)) |
+ (ath10k_set_ring_byte(n, dstr_wm->wm_high)));
}
static inline void ath10k_ce_dest_ring_lowmark_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS);
+ struct ath10k_hw_ce_dst_src_wm_regs *dstr_wm = ar->hw_ce_regs->wm_dstr;
+ u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + dstr_wm->addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS,
- (addr & ~DST_WATERMARK_LOW_MASK) |
- DST_WATERMARK_LOW_SET(n));
+ ath10k_pci_write32(ar, ce_ctrl_addr + dstr_wm->addr,
+ (addr & ~(dstr_wm->wm_low->mask)) |
+ (ath10k_set_ring_byte(n, dstr_wm->wm_low)));
}
static inline void ath10k_ce_copy_complete_inter_enable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- u32 host_ie_addr = ath10k_pci_read32(ar,
- ce_ctrl_addr + HOST_IE_ADDRESS);
+ struct ath10k_hw_ce_host_ie *host_ie = ar->hw_ce_regs->host_ie;
+ u32 host_ie_addr = ath10k_pci_read32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->host_ie_addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS,
- host_ie_addr | HOST_IE_COPY_COMPLETE_MASK);
+ ath10k_pci_write32(ar, ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr,
+ host_ie_addr | host_ie->copy_complete->mask);
}
static inline void ath10k_ce_copy_complete_intr_disable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- u32 host_ie_addr = ath10k_pci_read32(ar,
- ce_ctrl_addr + HOST_IE_ADDRESS);
+ struct ath10k_hw_ce_host_ie *host_ie = ar->hw_ce_regs->host_ie;
+ u32 host_ie_addr = ath10k_pci_read32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->host_ie_addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS,
- host_ie_addr & ~HOST_IE_COPY_COMPLETE_MASK);
+ ath10k_pci_write32(ar, ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr,
+ host_ie_addr & ~(host_ie->copy_complete->mask));
}
static inline void ath10k_ce_watermark_intr_disable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- u32 host_ie_addr = ath10k_pci_read32(ar,
- ce_ctrl_addr + HOST_IE_ADDRESS);
+ struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
+ u32 host_ie_addr = ath10k_pci_read32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->host_ie_addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS,
- host_ie_addr & ~CE_WATERMARK_MASK);
+ ath10k_pci_write32(ar, ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr,
+ host_ie_addr & ~(wm_regs->wm_mask));
}
static inline void ath10k_ce_error_intr_enable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- u32 misc_ie_addr = ath10k_pci_read32(ar,
- ce_ctrl_addr + MISC_IE_ADDRESS);
+ struct ath10k_hw_ce_misc_regs *misc_regs = ar->hw_ce_regs->misc_regs;
+ u32 misc_ie_addr = ath10k_pci_read32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->misc_ie_addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + MISC_IE_ADDRESS,
- misc_ie_addr | CE_ERROR_MASK);
+ ath10k_pci_write32(ar, ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr,
+ misc_ie_addr | misc_regs->err_mask);
}
static inline void ath10k_ce_error_intr_disable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- u32 misc_ie_addr = ath10k_pci_read32(ar,
- ce_ctrl_addr + MISC_IE_ADDRESS);
+ struct ath10k_hw_ce_misc_regs *misc_regs = ar->hw_ce_regs->misc_regs;
+ u32 misc_ie_addr = ath10k_pci_read32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->misc_ie_addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + MISC_IE_ADDRESS,
- misc_ie_addr & ~CE_ERROR_MASK);
+ ath10k_pci_write32(ar, ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr,
+ misc_ie_addr & ~(misc_regs->err_mask));
}
static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int mask)
{
- ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IS_ADDRESS, mask);
+ struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
+
+ ath10k_pci_write32(ar, ce_ctrl_addr + wm_regs->addr, mask);
}
/*
@@ -594,6 +632,7 @@ int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
unsigned int nentries_mask = src_ring->nentries_mask;
unsigned int sw_index = src_ring->sw_index;
unsigned int read_index;
+ struct ce_desc *desc;
if (src_ring->hw_index == sw_index) {
/*
@@ -623,6 +662,9 @@ int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
/* sanity */
src_ring->per_transfer_context[sw_index] = NULL;
+ desc = CE_SRC_RING_TO_DESC(src_ring->base_addr_owner_space,
+ sw_index);
+ desc->nbytes = 0;
/* Update sw_index */
sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
@@ -715,13 +757,13 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
+ struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
u32 ctrl_addr = ce_state->ctrl_addr;
spin_lock_bh(&ar_pci->ce_lock);
/* Clear the copy-complete interrupts that will be handled here. */
- ath10k_ce_engine_int_status_clear(ar, ctrl_addr,
- HOST_IS_COPY_COMPLETE_MASK);
+ ath10k_ce_engine_int_status_clear(ar, ctrl_addr, wm_regs->cc_mask);
spin_unlock_bh(&ar_pci->ce_lock);
@@ -737,7 +779,7 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id)
* Misc CE interrupts are not being handled, but still need
* to be cleared.
*/
- ath10k_ce_engine_int_status_clear(ar, ctrl_addr, CE_WATERMARK_MASK);
+ ath10k_ce_engine_int_status_clear(ar, ctrl_addr, wm_regs->wm_mask);
spin_unlock_bh(&ar_pci->ce_lock);
}
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h
index e76a98242b98..95743a57525d 100644
--- a/drivers/net/wireless/ath/ath10k/ce.h
+++ b/drivers/net/wireless/ath/ath10k/ce.h
@@ -263,143 +263,11 @@ struct ce_attr {
void (*recv_cb)(struct ath10k_ce_pipe *);
};
-#define SR_BA_ADDRESS 0x0000
-#define SR_SIZE_ADDRESS 0x0004
-#define DR_BA_ADDRESS 0x0008
-#define DR_SIZE_ADDRESS 0x000c
-#define CE_CMD_ADDRESS 0x0018
-
-#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MSB 17
-#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB 17
-#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK 0x00020000
-#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_SET(x) \
- (((0 | (x)) << CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB) & \
- CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK)
-
-#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MSB 16
-#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB 16
-#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK 0x00010000
-#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_GET(x) \
- (((x) & CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) >> \
- CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB)
-#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_SET(x) \
- (((0 | (x)) << CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB) & \
- CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK)
-
-#define CE_CTRL1_DMAX_LENGTH_MSB 15
-#define CE_CTRL1_DMAX_LENGTH_LSB 0
-#define CE_CTRL1_DMAX_LENGTH_MASK 0x0000ffff
-#define CE_CTRL1_DMAX_LENGTH_GET(x) \
- (((x) & CE_CTRL1_DMAX_LENGTH_MASK) >> CE_CTRL1_DMAX_LENGTH_LSB)
-#define CE_CTRL1_DMAX_LENGTH_SET(x) \
- (((0 | (x)) << CE_CTRL1_DMAX_LENGTH_LSB) & CE_CTRL1_DMAX_LENGTH_MASK)
-
-#define CE_CTRL1_ADDRESS 0x0010
-#define CE_CTRL1_HW_MASK 0x0007ffff
-#define CE_CTRL1_SW_MASK 0x0007ffff
-#define CE_CTRL1_HW_WRITE_MASK 0x00000000
-#define CE_CTRL1_SW_WRITE_MASK 0x0007ffff
-#define CE_CTRL1_RSTMASK 0xffffffff
-#define CE_CTRL1_RESET 0x00000080
-
-#define CE_CMD_HALT_STATUS_MSB 3
-#define CE_CMD_HALT_STATUS_LSB 3
-#define CE_CMD_HALT_STATUS_MASK 0x00000008
-#define CE_CMD_HALT_STATUS_GET(x) \
- (((x) & CE_CMD_HALT_STATUS_MASK) >> CE_CMD_HALT_STATUS_LSB)
-#define CE_CMD_HALT_STATUS_SET(x) \
- (((0 | (x)) << CE_CMD_HALT_STATUS_LSB) & CE_CMD_HALT_STATUS_MASK)
-#define CE_CMD_HALT_STATUS_RESET 0
-#define CE_CMD_HALT_MSB 0
-#define CE_CMD_HALT_MASK 0x00000001
-
-#define HOST_IE_COPY_COMPLETE_MSB 0
-#define HOST_IE_COPY_COMPLETE_LSB 0
-#define HOST_IE_COPY_COMPLETE_MASK 0x00000001
-#define HOST_IE_COPY_COMPLETE_GET(x) \
- (((x) & HOST_IE_COPY_COMPLETE_MASK) >> HOST_IE_COPY_COMPLETE_LSB)
-#define HOST_IE_COPY_COMPLETE_SET(x) \
- (((0 | (x)) << HOST_IE_COPY_COMPLETE_LSB) & HOST_IE_COPY_COMPLETE_MASK)
-#define HOST_IE_COPY_COMPLETE_RESET 0
-#define HOST_IE_ADDRESS 0x002c
-
-#define HOST_IS_DST_RING_LOW_WATERMARK_MASK 0x00000010
-#define HOST_IS_DST_RING_HIGH_WATERMARK_MASK 0x00000008
-#define HOST_IS_SRC_RING_LOW_WATERMARK_MASK 0x00000004
-#define HOST_IS_SRC_RING_HIGH_WATERMARK_MASK 0x00000002
-#define HOST_IS_COPY_COMPLETE_MASK 0x00000001
-#define HOST_IS_ADDRESS 0x0030
-
-#define MISC_IE_ADDRESS 0x0034
-
-#define MISC_IS_AXI_ERR_MASK 0x00000400
-
-#define MISC_IS_DST_ADDR_ERR_MASK 0x00000200
-#define MISC_IS_SRC_LEN_ERR_MASK 0x00000100
-#define MISC_IS_DST_MAX_LEN_VIO_MASK 0x00000080
-#define MISC_IS_DST_RING_OVERFLOW_MASK 0x00000040
-#define MISC_IS_SRC_RING_OVERFLOW_MASK 0x00000020
-
-#define MISC_IS_ADDRESS 0x0038
-
-#define SR_WR_INDEX_ADDRESS 0x003c
-
-#define DST_WR_INDEX_ADDRESS 0x0040
-
-#define CURRENT_SRRI_ADDRESS 0x0044
-
-#define CURRENT_DRRI_ADDRESS 0x0048
-
-#define SRC_WATERMARK_LOW_MSB 31
-#define SRC_WATERMARK_LOW_LSB 16
-#define SRC_WATERMARK_LOW_MASK 0xffff0000
-#define SRC_WATERMARK_LOW_GET(x) \
- (((x) & SRC_WATERMARK_LOW_MASK) >> SRC_WATERMARK_LOW_LSB)
-#define SRC_WATERMARK_LOW_SET(x) \
- (((0 | (x)) << SRC_WATERMARK_LOW_LSB) & SRC_WATERMARK_LOW_MASK)
-#define SRC_WATERMARK_LOW_RESET 0
-#define SRC_WATERMARK_HIGH_MSB 15
-#define SRC_WATERMARK_HIGH_LSB 0
-#define SRC_WATERMARK_HIGH_MASK 0x0000ffff
-#define SRC_WATERMARK_HIGH_GET(x) \
- (((x) & SRC_WATERMARK_HIGH_MASK) >> SRC_WATERMARK_HIGH_LSB)
-#define SRC_WATERMARK_HIGH_SET(x) \
- (((0 | (x)) << SRC_WATERMARK_HIGH_LSB) & SRC_WATERMARK_HIGH_MASK)
-#define SRC_WATERMARK_HIGH_RESET 0
-#define SRC_WATERMARK_ADDRESS 0x004c
-
-#define DST_WATERMARK_LOW_LSB 16
-#define DST_WATERMARK_LOW_MASK 0xffff0000
-#define DST_WATERMARK_LOW_SET(x) \
- (((0 | (x)) << DST_WATERMARK_LOW_LSB) & DST_WATERMARK_LOW_MASK)
-#define DST_WATERMARK_LOW_RESET 0
-#define DST_WATERMARK_HIGH_MSB 15
-#define DST_WATERMARK_HIGH_LSB 0
-#define DST_WATERMARK_HIGH_MASK 0x0000ffff
-#define DST_WATERMARK_HIGH_GET(x) \
- (((x) & DST_WATERMARK_HIGH_MASK) >> DST_WATERMARK_HIGH_LSB)
-#define DST_WATERMARK_HIGH_SET(x) \
- (((0 | (x)) << DST_WATERMARK_HIGH_LSB) & DST_WATERMARK_HIGH_MASK)
-#define DST_WATERMARK_HIGH_RESET 0
-#define DST_WATERMARK_ADDRESS 0x0050
-
static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id)
{
return CE0_BASE_ADDRESS + (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS) * ce_id;
}
-#define CE_WATERMARK_MASK (HOST_IS_SRC_RING_LOW_WATERMARK_MASK | \
- HOST_IS_SRC_RING_HIGH_WATERMARK_MASK | \
- HOST_IS_DST_RING_LOW_WATERMARK_MASK | \
- HOST_IS_DST_RING_HIGH_WATERMARK_MASK)
-
-#define CE_ERROR_MASK (MISC_IS_AXI_ERR_MASK | \
- MISC_IS_DST_ADDR_ERR_MASK | \
- MISC_IS_SRC_LEN_ERR_MASK | \
- MISC_IS_DST_MAX_LEN_VIO_MASK | \
- MISC_IS_DST_RING_OVERFLOW_MASK | \
- MISC_IS_SRC_RING_OVERFLOW_MASK)
-
#define CE_SRC_RING_TO_DESC(baddr, idx) \
(&(((struct ce_desc *)baddr)[idx]))
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index eea111d704c5..75c5c903c8a6 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -72,6 +72,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca988x_ops,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
+ .vht160_mcs_rx_highest = 0,
+ .vht160_mcs_tx_highest = 0,
},
{
.id = QCA9887_HW_1_0_VERSION,
@@ -93,6 +95,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca988x_ops,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
+ .vht160_mcs_rx_highest = 0,
+ .vht160_mcs_tx_highest = 0,
},
{
.id = QCA6174_HW_2_1_VERSION,
@@ -113,6 +117,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca988x_ops,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
+ .vht160_mcs_rx_highest = 0,
+ .vht160_mcs_tx_highest = 0,
},
{
.id = QCA6174_HW_2_1_VERSION,
@@ -133,6 +139,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca988x_ops,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
+ .vht160_mcs_rx_highest = 0,
+ .vht160_mcs_tx_highest = 0,
},
{
.id = QCA6174_HW_3_0_VERSION,
@@ -153,6 +161,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca988x_ops,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
+ .vht160_mcs_rx_highest = 0,
+ .vht160_mcs_tx_highest = 0,
},
{
.id = QCA6174_HW_3_2_VERSION,
@@ -176,6 +186,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.target_cpu_freq = 176000000,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
+ .vht160_mcs_rx_highest = 0,
+ .vht160_mcs_tx_highest = 0,
},
{
.id = QCA99X0_HW_2_0_DEV_VERSION,
@@ -202,6 +214,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca99x0_ops,
.decap_align_bytes = 1,
.spectral_bin_discard = 4,
+ .vht160_mcs_rx_highest = 0,
+ .vht160_mcs_tx_highest = 0,
},
{
.id = QCA9984_HW_1_0_DEV_VERSION,
@@ -229,6 +243,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca99x0_ops,
.decap_align_bytes = 1,
.spectral_bin_discard = 12,
+
+ /* Can do only 2x2 VHT160 or 80+80. 1560Mbps is 4x4 80Mhz
+ * or 2x2 160Mhz, long-guard-interval.
+ */
+ .vht160_mcs_rx_highest = 1560,
+ .vht160_mcs_tx_highest = 1560,
},
{
.id = QCA9888_HW_2_0_DEV_VERSION,
@@ -255,6 +275,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca99x0_ops,
.decap_align_bytes = 1,
.spectral_bin_discard = 12,
+
+ /* Can do only 1x1 VHT160 or 80+80. 780Mbps is 2x2 80Mhz or
+ * 1x1 160Mhz, long-guard-interval.
+ */
+ .vht160_mcs_rx_highest = 780,
+ .vht160_mcs_tx_highest = 780,
},
{
.id = QCA9377_HW_1_0_DEV_VERSION,
@@ -275,6 +301,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca988x_ops,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
+ .vht160_mcs_rx_highest = 0,
+ .vht160_mcs_tx_highest = 0,
},
{
.id = QCA9377_HW_1_1_DEV_VERSION,
@@ -297,6 +325,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.target_cpu_freq = 176000000,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
+ .vht160_mcs_rx_highest = 0,
+ .vht160_mcs_tx_highest = 0,
},
{
.id = QCA4019_HW_1_0_DEV_VERSION,
@@ -324,6 +354,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca99x0_ops,
.decap_align_bytes = 1,
.spectral_bin_discard = 4,
+ .vht160_mcs_rx_highest = 0,
+ .vht160_mcs_tx_highest = 0,
},
};
@@ -691,7 +723,7 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
{
u32 result, address;
u8 board_id, chip_id;
- int ret;
+ int ret, bmi_board_id_param;
address = ar->hw_params.patch_load_addr;
@@ -715,8 +747,13 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
return ret;
}
- ret = ath10k_bmi_execute(ar, address, BMI_PARAM_GET_EEPROM_BOARD_ID,
- &result);
+ if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT ||
+ ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE)
+ bmi_board_id_param = BMI_PARAM_GET_FLASH_BOARD_ID;
+ else
+ bmi_board_id_param = BMI_PARAM_GET_EEPROM_BOARD_ID;
+
+ ret = ath10k_bmi_execute(ar, address, bmi_board_id_param, &result);
if (ret) {
ath10k_err(ar, "could not execute otp for board id check: %d\n",
ret);
@@ -845,6 +882,11 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
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);
@@ -2449,24 +2491,29 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
case ATH10K_HW_QCA988X:
case ATH10K_HW_QCA9887:
ar->regs = &qca988x_regs;
+ ar->hw_ce_regs = &qcax_ce_regs;
ar->hw_values = &qca988x_values;
break;
case ATH10K_HW_QCA6174:
case ATH10K_HW_QCA9377:
ar->regs = &qca6174_regs;
+ ar->hw_ce_regs = &qcax_ce_regs;
ar->hw_values = &qca6174_values;
break;
case ATH10K_HW_QCA99X0:
case ATH10K_HW_QCA9984:
ar->regs = &qca99x0_regs;
+ ar->hw_ce_regs = &qcax_ce_regs;
ar->hw_values = &qca99x0_values;
break;
case ATH10K_HW_QCA9888:
ar->regs = &qca99x0_regs;
+ ar->hw_ce_regs = &qcax_ce_regs;
ar->hw_values = &qca9888_values;
break;
case ATH10K_HW_QCA4019:
ar->regs = &qca4019_regs;
+ ar->hw_ce_regs = &qcax_ce_regs;
ar->hw_values = &qca4019_values;
break;
default:
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 8fc08a5043db..1aa5cf12fce0 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -794,6 +794,7 @@ struct ath10k {
struct completion target_suspend;
const struct ath10k_hw_regs *regs;
+ const struct ath10k_hw_ce_regs *hw_ce_regs;
const struct ath10k_hw_values *hw_values;
struct ath10k_bmi bmi;
struct ath10k_wmi wmi;
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 84b6067ff6e7..398dda978d6e 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -829,6 +829,19 @@ static void ath10k_htt_rx_h_signal(struct ath10k *ar,
struct ieee80211_rx_status *status,
struct htt_rx_desc *rxd)
{
+ int i;
+
+ for (i = 0; i < IEEE80211_MAX_CHAINS ; i++) {
+ status->chains &= ~BIT(i);
+
+ if (rxd->ppdu_start.rssi_chains[i].pri20_mhz != 0x80) {
+ status->chain_signal[i] = ATH10K_DEFAULT_NOISE_FLOOR +
+ rxd->ppdu_start.rssi_chains[i].pri20_mhz;
+
+ status->chains |= BIT(i);
+ }
+ }
+
/* FIXME: Get real NF */
status->signal = ATH10K_DEFAULT_NOISE_FLOOR +
rxd->ppdu_start.rssi_comb;
@@ -2229,9 +2242,15 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar,
txrate.mcs = ATH10K_HW_MCS_RATE(peer_stats->ratecode);
sgi = ATH10K_HW_GI(peer_stats->flags);
- if (((txrate.flags == WMI_RATE_PREAMBLE_HT) ||
- (txrate.flags == WMI_RATE_PREAMBLE_VHT)) && txrate.mcs > 9) {
- ath10k_warn(ar, "Invalid mcs %hhd peer stats", txrate.mcs);
+ if (txrate.flags == WMI_RATE_PREAMBLE_VHT && txrate.mcs > 9) {
+ ath10k_warn(ar, "Invalid VHT mcs %hhd peer stats", txrate.mcs);
+ return;
+ }
+
+ if (txrate.flags == WMI_RATE_PREAMBLE_HT &&
+ (txrate.mcs > 7 || txrate.nss < 1)) {
+ ath10k_warn(ar, "Invalid HT mcs %hhd nss %hhd peer stats",
+ txrate.mcs, txrate.nss);
return;
}
@@ -2254,7 +2273,7 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar,
arsta->txrate.legacy = rate;
} else if (txrate.flags == WMI_RATE_PREAMBLE_HT) {
arsta->txrate.flags = RATE_INFO_FLAGS_MCS;
- arsta->txrate.mcs = txrate.mcs;
+ arsta->txrate.mcs = txrate.mcs + 8 * (txrate.nss - 1);
} else {
arsta->txrate.flags = RATE_INFO_FLAGS_VHT_MCS;
arsta->txrate.mcs = txrate.mcs;
diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c
index c866ab524571..afb0c01cbb55 100644
--- a/drivers/net/wireless/ath/ath10k/hw.c
+++ b/drivers/net/wireless/ath/ath10k/hw.c
@@ -15,6 +15,7 @@
*/
#include <linux/types.h>
+#include <linux/bitops.h>
#include "core.h"
#include "hw.h"
#include "hif.h"
@@ -191,6 +192,142 @@ const struct ath10k_hw_values qca4019_values = {
.ce_desc_meta_data_lsb = 4,
};
+static struct ath10k_hw_ce_regs_addr_map qcax_src_ring = {
+ .msb = 0x00000010,
+ .lsb = 0x00000010,
+ .mask = GENMASK(16, 16),
+};
+
+static struct ath10k_hw_ce_regs_addr_map qcax_dst_ring = {
+ .msb = 0x00000011,
+ .lsb = 0x00000011,
+ .mask = GENMASK(17, 17),
+};
+
+static struct ath10k_hw_ce_regs_addr_map qcax_dmax = {
+ .msb = 0x0000000f,
+ .lsb = 0x00000000,
+ .mask = GENMASK(15, 0),
+};
+
+static struct ath10k_hw_ce_ctrl1 qcax_ctrl1 = {
+ .addr = 0x00000010,
+ .hw_mask = 0x0007ffff,
+ .sw_mask = 0x0007ffff,
+ .hw_wr_mask = 0x00000000,
+ .sw_wr_mask = 0x0007ffff,
+ .reset_mask = 0xffffffff,
+ .reset = 0x00000080,
+ .src_ring = &qcax_src_ring,
+ .dst_ring = &qcax_dst_ring,
+ .dmax = &qcax_dmax,
+};
+
+static struct ath10k_hw_ce_regs_addr_map qcax_cmd_halt_status = {
+ .msb = 0x00000003,
+ .lsb = 0x00000003,
+ .mask = GENMASK(3, 3),
+};
+
+static struct ath10k_hw_ce_cmd_halt qcax_cmd_halt = {
+ .msb = 0x00000000,
+ .mask = GENMASK(0, 0),
+ .status_reset = 0x00000000,
+ .status = &qcax_cmd_halt_status,
+};
+
+static struct ath10k_hw_ce_regs_addr_map qcax_host_ie_cc = {
+ .msb = 0x00000000,
+ .lsb = 0x00000000,
+ .mask = GENMASK(0, 0),
+};
+
+static struct ath10k_hw_ce_host_ie qcax_host_ie = {
+ .copy_complete_reset = 0x00000000,
+ .copy_complete = &qcax_host_ie_cc,
+};
+
+static struct ath10k_hw_ce_host_wm_regs qcax_wm_reg = {
+ .dstr_lmask = 0x00000010,
+ .dstr_hmask = 0x00000008,
+ .srcr_lmask = 0x00000004,
+ .srcr_hmask = 0x00000002,
+ .cc_mask = 0x00000001,
+ .wm_mask = 0x0000001E,
+ .addr = 0x00000030,
+};
+
+static struct ath10k_hw_ce_misc_regs qcax_misc_reg = {
+ .axi_err = 0x00000400,
+ .dstr_add_err = 0x00000200,
+ .srcr_len_err = 0x00000100,
+ .dstr_mlen_vio = 0x00000080,
+ .dstr_overflow = 0x00000040,
+ .srcr_overflow = 0x00000020,
+ .err_mask = 0x000007E0,
+ .addr = 0x00000038,
+};
+
+static struct ath10k_hw_ce_regs_addr_map qcax_src_wm_low = {
+ .msb = 0x0000001f,
+ .lsb = 0x00000010,
+ .mask = GENMASK(31, 16),
+};
+
+static struct ath10k_hw_ce_regs_addr_map qcax_src_wm_high = {
+ .msb = 0x0000000f,
+ .lsb = 0x00000000,
+ .mask = GENMASK(15, 0),
+};
+
+static struct ath10k_hw_ce_dst_src_wm_regs qcax_wm_src_ring = {
+ .addr = 0x0000004c,
+ .low_rst = 0x00000000,
+ .high_rst = 0x00000000,
+ .wm_low = &qcax_src_wm_low,
+ .wm_high = &qcax_src_wm_high,
+};
+
+static struct ath10k_hw_ce_regs_addr_map qcax_dst_wm_low = {
+ .lsb = 0x00000010,
+ .mask = GENMASK(31, 16),
+};
+
+static struct ath10k_hw_ce_regs_addr_map qcax_dst_wm_high = {
+ .msb = 0x0000000f,
+ .lsb = 0x00000000,
+ .mask = GENMASK(15, 0),
+};
+
+static struct ath10k_hw_ce_dst_src_wm_regs qcax_wm_dst_ring = {
+ .addr = 0x00000050,
+ .low_rst = 0x00000000,
+ .high_rst = 0x00000000,
+ .wm_low = &qcax_dst_wm_low,
+ .wm_high = &qcax_dst_wm_high,
+};
+
+struct ath10k_hw_ce_regs qcax_ce_regs = {
+ .sr_base_addr = 0x00000000,
+ .sr_size_addr = 0x00000004,
+ .dr_base_addr = 0x00000008,
+ .dr_size_addr = 0x0000000c,
+ .ce_cmd_addr = 0x00000018,
+ .misc_ie_addr = 0x00000034,
+ .sr_wr_index_addr = 0x0000003c,
+ .dst_wr_index_addr = 0x00000040,
+ .current_srri_addr = 0x00000044,
+ .current_drri_addr = 0x00000048,
+ .host_ie_addr = 0x0000002c,
+ .ctrl1_regs = &qcax_ctrl1,
+ .cmd_halt = &qcax_cmd_halt,
+ .host_ie = &qcax_host_ie,
+ .wm_regs = &qcax_wm_reg,
+ .misc_regs = &qcax_misc_reg,
+ .wm_srcr = &qcax_wm_src_ring,
+ .wm_dstr = &qcax_wm_dst_ring,
+};
+
const struct ath10k_hw_clk_params qca6174_clk[ATH10K_HW_REFCLK_COUNT] = {
{
.refclk = 48000000,
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index d34272803fd7..97dc1479f44e 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -268,6 +268,86 @@ extern const struct ath10k_hw_regs qca6174_regs;
extern const struct ath10k_hw_regs qca99x0_regs;
extern const struct ath10k_hw_regs qca4019_regs;
+struct ath10k_hw_ce_regs_addr_map {
+ u32 msb;
+ u32 lsb;
+ u32 mask;
+};
+
+struct ath10k_hw_ce_ctrl1 {
+ u32 addr;
+ u32 hw_mask;
+ u32 sw_mask;
+ u32 hw_wr_mask;
+ u32 sw_wr_mask;
+ u32 reset_mask;
+ u32 reset;
+ struct ath10k_hw_ce_regs_addr_map *src_ring;
+ struct ath10k_hw_ce_regs_addr_map *dst_ring;
+ struct ath10k_hw_ce_regs_addr_map *dmax; };
+
+struct ath10k_hw_ce_cmd_halt {
+ u32 status_reset;
+ u32 msb;
+ u32 mask;
+ struct ath10k_hw_ce_regs_addr_map *status; };
+
+struct ath10k_hw_ce_host_ie {
+ u32 copy_complete_reset;
+ struct ath10k_hw_ce_regs_addr_map *copy_complete; };
+
+struct ath10k_hw_ce_host_wm_regs {
+ u32 dstr_lmask;
+ u32 dstr_hmask;
+ u32 srcr_lmask;
+ u32 srcr_hmask;
+ u32 cc_mask;
+ u32 wm_mask;
+ u32 addr;
+};
+
+struct ath10k_hw_ce_misc_regs {
+ u32 axi_err;
+ u32 dstr_add_err;
+ u32 srcr_len_err;
+ u32 dstr_mlen_vio;
+ u32 dstr_overflow;
+ u32 srcr_overflow;
+ u32 err_mask;
+ u32 addr;
+};
+
+struct ath10k_hw_ce_dst_src_wm_regs {
+ u32 addr;
+ u32 low_rst;
+ u32 high_rst;
+ struct ath10k_hw_ce_regs_addr_map *wm_low;
+ struct ath10k_hw_ce_regs_addr_map *wm_high; };
+
+struct ath10k_hw_ce_regs {
+ u32 sr_base_addr;
+ u32 sr_size_addr;
+ u32 dr_base_addr;
+ u32 dr_size_addr;
+ u32 ce_cmd_addr;
+ u32 misc_ie_addr;
+ u32 sr_wr_index_addr;
+ u32 dst_wr_index_addr;
+ u32 current_srri_addr;
+ u32 current_drri_addr;
+ u32 ddr_addr_for_rri_low;
+ u32 ddr_addr_for_rri_high;
+ u32 ce_rri_low;
+ u32 ce_rri_high;
+ u32 host_ie_addr;
+ struct ath10k_hw_ce_host_wm_regs *wm_regs;
+ struct ath10k_hw_ce_misc_regs *misc_regs;
+ struct ath10k_hw_ce_ctrl1 *ctrl1_regs;
+ struct ath10k_hw_ce_cmd_halt *cmd_halt;
+ struct ath10k_hw_ce_host_ie *host_ie;
+ struct ath10k_hw_ce_dst_src_wm_regs *wm_srcr;
+ struct ath10k_hw_ce_dst_src_wm_regs *wm_dstr; };
+
struct ath10k_hw_values {
u32 rtc_state_val_on;
u8 ce_count;
@@ -282,6 +362,7 @@ extern const struct ath10k_hw_values qca6174_values;
extern const struct ath10k_hw_values qca99x0_values;
extern const struct ath10k_hw_values qca9888_values;
extern const struct ath10k_hw_values qca4019_values;
+extern 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);
@@ -454,6 +535,12 @@ struct ath10k_hw_params {
/* Number of bytes to be discarded for each FFT sample */
int spectral_bin_discard;
+
+ /* The board may have a restricted NSS for 160 or 80+80 vs what it
+ * can do for 80Mhz.
+ */
+ int vht160_mcs_rx_highest;
+ int vht160_mcs_tx_highest;
};
struct htt_rx_desc;
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 16cf250f6c39..4a71815490ae 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2519,6 +2519,20 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x\n",
sta->addr, arg->peer_max_mpdu, arg->peer_flags);
+
+ if (arg->peer_vht_rates.rx_max_rate &&
+ (sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK)) {
+ switch (arg->peer_vht_rates.rx_max_rate) {
+ case 1560:
+ /* Must be 2x2 at 160Mhz is all it can do. */
+ arg->peer_bw_rxnss_override = 2;
+ break;
+ case 780:
+ /* Can only do 1x1 at 160Mhz (Long Guard Interval) */
+ arg->peer_bw_rxnss_override = 1;
+ break;
+ }
+ }
}
static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
@@ -4361,6 +4375,7 @@ static int ath10k_mac_get_vht_cap_bf_sound_dim(struct ath10k *ar)
static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
{
struct ieee80211_sta_vht_cap vht_cap = {0};
+ struct ath10k_hw_params *hw = &ar->hw_params;
u16 mcs_map;
u32 val;
int i;
@@ -4390,7 +4405,7 @@ static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
* mode until that's resolved.
*/
if ((ar->vht_cap_info & IEEE80211_VHT_CAP_SHORT_GI_160) &&
- !(ar->vht_cap_info & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))
+ (ar->vht_cap_info & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) == 0)
vht_cap.cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
mcs_map = 0;
@@ -4407,6 +4422,17 @@ static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
+ /* If we are supporting 160Mhz or 80+80, then the NIC may be able to do
+ * a restricted NSS for 160 or 80+80 vs what it can do for 80Mhz. Give
+ * user-space a clue if that is the case.
+ */
+ if ((vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) &&
+ (hw->vht160_mcs_rx_highest != 0 ||
+ hw->vht160_mcs_tx_highest != 0)) {
+ vht_cap.vht_mcs.rx_highest = cpu_to_le16(hw->vht160_mcs_rx_highest);
+ vht_cap.vht_mcs.tx_highest = cpu_to_le16(hw->vht160_mcs_tx_highest);
+ }
+
return vht_cap;
}
@@ -6072,6 +6098,20 @@ 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);
+ num_tdls_stations = ath10k_mac_tdls_vif_stations_count(hw, vif);
+ num_tdls_vifs = ath10k_mac_tdls_vifs_count(hw);
+
+ if (sta->tdls) {
+ if (num_tdls_stations >= ar->max_num_tdls_vdevs) {
+ ath10k_warn(ar, "vdev %i exceeded maximum number of tdls vdevs %i\n",
+ arvif->vdev_id,
+ ar->max_num_tdls_vdevs);
+ ret = -ELNRNG;
+ goto exit;
+ }
+ peer_type = WMI_PEER_TYPE_TDLS;
+ }
+
ret = ath10k_mac_inc_num_stations(arvif, sta);
if (ret) {
ath10k_warn(ar, "refusing to associate station: too many connected already (%d)\n",
@@ -6079,9 +6119,6 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
goto exit;
}
- if (sta->tdls)
- peer_type = WMI_PEER_TYPE_TDLS;
-
ret = ath10k_peer_create(ar, vif, sta, arvif->vdev_id,
sta->addr, peer_type);
if (ret) {
@@ -6112,35 +6149,17 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
if (!sta->tdls)
goto exit;
- num_tdls_stations = ath10k_mac_tdls_vif_stations_count(hw, vif);
- num_tdls_vifs = ath10k_mac_tdls_vifs_count(hw);
-
- if (num_tdls_vifs >= ar->max_num_tdls_vdevs &&
- num_tdls_stations == 0) {
- ath10k_warn(ar, "vdev %i exceeded maximum number of tdls vdevs %i\n",
- arvif->vdev_id, ar->max_num_tdls_vdevs);
- ath10k_peer_delete(ar, arvif->vdev_id, sta->addr);
+ ret = ath10k_wmi_update_fw_tdls_state(ar, arvif->vdev_id,
+ WMI_TDLS_ENABLE_ACTIVE);
+ if (ret) {
+ ath10k_warn(ar, "failed to update fw tdls state on vdev %i: %i\n",
+ arvif->vdev_id, ret);
+ ath10k_peer_delete(ar, arvif->vdev_id,
+ sta->addr);
ath10k_mac_dec_num_stations(arvif, sta);
- ret = -ENOBUFS;
goto exit;
}
- if (num_tdls_stations == 0) {
- /* This is the first tdls peer in current vif */
- enum wmi_tdls_state state = WMI_TDLS_ENABLE_ACTIVE;
-
- ret = ath10k_wmi_update_fw_tdls_state(ar, arvif->vdev_id,
- state);
- if (ret) {
- ath10k_warn(ar, "failed to update fw tdls state on vdev %i: %i\n",
- arvif->vdev_id, ret);
- ath10k_peer_delete(ar, arvif->vdev_id,
- sta->addr);
- ath10k_mac_dec_num_stations(arvif, sta);
- goto exit;
- }
- }
-
ret = ath10k_mac_tdls_peer_update(ar, arvif->vdev_id, sta,
WMI_TDLS_PEER_STATE_PEERING);
if (ret) {
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 1e9806f57ee4..4f3f513dac4f 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -101,7 +101,8 @@ static int ath10k_pci_init_irq(struct ath10k *ar);
static int ath10k_pci_deinit_irq(struct ath10k *ar);
static int ath10k_pci_request_irq(struct ath10k *ar);
static void ath10k_pci_free_irq(struct ath10k *ar);
-static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
+static int ath10k_pci_bmi_wait(struct ath10k *ar,
+ struct ath10k_ce_pipe *tx_pipe,
struct ath10k_ce_pipe *rx_pipe,
struct bmi_xfer *xfer);
static int ath10k_pci_qca99x0_chip_reset(struct ath10k *ar);
@@ -1846,7 +1847,7 @@ int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar,
if (ret)
goto err_resp;
- ret = ath10k_pci_bmi_wait(ce_tx, ce_rx, &xfer);
+ ret = ath10k_pci_bmi_wait(ar, ce_tx, ce_rx, &xfer);
if (ret) {
u32 unused_buffer;
unsigned int unused_nbytes;
@@ -1913,23 +1914,37 @@ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state)
xfer->rx_done = true;
}
-static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
+static int ath10k_pci_bmi_wait(struct ath10k *ar,
+ struct ath10k_ce_pipe *tx_pipe,
struct ath10k_ce_pipe *rx_pipe,
struct bmi_xfer *xfer)
{
unsigned long timeout = jiffies + BMI_COMMUNICATION_TIMEOUT_HZ;
+ unsigned long started = jiffies;
+ unsigned long dur;
+ int ret;
while (time_before_eq(jiffies, timeout)) {
ath10k_pci_bmi_send_done(tx_pipe);
ath10k_pci_bmi_recv_data(rx_pipe);
- if (xfer->tx_done && (xfer->rx_done == xfer->wait_for_resp))
- return 0;
+ if (xfer->tx_done && (xfer->rx_done == xfer->wait_for_resp)) {
+ ret = 0;
+ goto out;
+ }
schedule();
}
- return -ETIMEDOUT;
+ ret = -ETIMEDOUT;
+
+out:
+ dur = jiffies - started;
+ if (dur > HZ)
+ ath10k_dbg(ar, ATH10K_DBG_BMI,
+ "bmi cmd took %lu jiffies hz %d ret %d\n",
+ dur, HZ, ret);
+ return ret;
}
/*
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index a66e2482897f..3efb404b83c0 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -4481,31 +4481,17 @@ static int ath10k_wmi_alloc_chunk(struct ath10k *ar, u32 req_id,
u32 num_units, u32 unit_len)
{
dma_addr_t paddr;
- u32 pool_size = 0;
+ u32 pool_size;
int idx = ar->wmi.num_mem_chunks;
- void *vaddr = NULL;
-
- if (ar->wmi.num_mem_chunks == ARRAY_SIZE(ar->wmi.mem_chunks))
- return -ENOMEM;
+ void *vaddr;
- while (!vaddr && num_units) {
- pool_size = num_units * round_up(unit_len, 4);
- if (!pool_size)
- return -EINVAL;
+ pool_size = num_units * round_up(unit_len, 4);
+ vaddr = dma_alloc_coherent(ar->dev, pool_size, &paddr, GFP_KERNEL);
- vaddr = kzalloc(pool_size, GFP_KERNEL | __GFP_NOWARN);
- if (!vaddr)
- num_units /= 2;
- }
-
- if (!num_units)
+ if (!vaddr)
return -ENOMEM;
- paddr = dma_map_single(ar->dev, vaddr, pool_size, DMA_BIDIRECTIONAL);
- if (dma_mapping_error(ar->dev, paddr)) {
- kfree(vaddr);
- return -ENOMEM;
- }
+ memset(vaddr, 0, pool_size);
ar->wmi.mem_chunks[idx].vaddr = vaddr;
ar->wmi.mem_chunks[idx].paddr = paddr;
@@ -5947,15 +5933,6 @@ static struct sk_buff *ath10k_wmi_10_4_op_gen_init(struct ath10k *ar)
int ath10k_wmi_start_scan_verify(const struct wmi_start_scan_arg *arg)
{
- if (arg->ie_len && !arg->ie)
- return -EINVAL;
- if (arg->n_channels && !arg->channels)
- return -EINVAL;
- if (arg->n_ssids && !arg->ssids)
- return -EINVAL;
- if (arg->n_bssids && !arg->bssids)
- return -EINVAL;
-
if (arg->ie_len > WLAN_SCAN_PARAMS_MAX_IE_LEN)
return -EINVAL;
if (arg->n_channels > ARRAY_SIZE(arg->channels))
@@ -6756,7 +6733,12 @@ ath10k_wmi_peer_assoc_fill_10_4(struct ath10k *ar, void *buf,
struct wmi_10_4_peer_assoc_complete_cmd *cmd = buf;
ath10k_wmi_peer_assoc_fill_10_2(ar, buf, arg);
- cmd->peer_bw_rxnss_override = 0;
+ if (arg->peer_bw_rxnss_override)
+ cmd->peer_bw_rxnss_override =
+ __cpu_to_le32((arg->peer_bw_rxnss_override - 1) |
+ BIT(PEER_BW_RXNSS_OVERRIDE_OFFSET));
+ else
+ cmd->peer_bw_rxnss_override = 0;
}
static int
@@ -8289,11 +8271,10 @@ void ath10k_wmi_free_host_mem(struct ath10k *ar)
/* free the host memory chunks requested by firmware */
for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
- dma_unmap_single(ar->dev,
- ar->wmi.mem_chunks[i].paddr,
- ar->wmi.mem_chunks[i].len,
- DMA_BIDIRECTIONAL);
- kfree(ar->wmi.mem_chunks[i].vaddr);
+ dma_free_coherent(ar->dev,
+ ar->wmi.mem_chunks[i].len,
+ ar->wmi.mem_chunks[i].vaddr,
+ ar->wmi.mem_chunks[i].paddr);
}
ar->wmi.num_mem_chunks = 0;
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 1b4865a55595..baa38c8f847c 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -6028,6 +6028,8 @@ struct wmi_10_2_peer_assoc_complete_cmd {
__le32 info0; /* WMI_PEER_ASSOC_INFO0_ */
} __packed;
+#define PEER_BW_RXNSS_OVERRIDE_OFFSET 31
+
struct wmi_10_4_peer_assoc_complete_cmd {
struct wmi_10_2_peer_assoc_complete_cmd cmd;
__le32 peer_bw_rxnss_override;
@@ -6051,6 +6053,7 @@ struct wmi_peer_assoc_complete_arg {
u32 peer_vht_caps;
enum wmi_phy_mode peer_phymode;
struct wmi_vht_rate_set_arg peer_vht_rates;
+ u32 peer_bw_rxnss_override;
};
struct wmi_peer_add_wds_entry_cmd {
diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
index 5c0ba83a44aa..546243e11737 100644
--- a/drivers/net/wireless/ath/ath6kl/htc_pipe.c
+++ b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
@@ -382,7 +382,7 @@ static enum htc_send_queue_result htc_try_send(struct htc_target *target,
list_for_each_entry_safe(packet, tmp_pkt,
txq, list) {
ath6kl_dbg(ATH6KL_DBG_HTC,
- "%s: Indicat overflowed TX pkts: %p\n",
+ "%s: Indicate overflowed TX pkts: %p\n",
__func__, packet);
action = ep->ep_cb.tx_full(ep->target, packet);
if (action == HTC_SEND_FULL_DROP) {
diff --git a/drivers/net/wireless/ath/wil6210/Makefile b/drivers/net/wireless/ath/wil6210/Makefile
index 89bf2f9eca1d..4ae21da78e9e 100644
--- a/drivers/net/wireless/ath/wil6210/Makefile
+++ b/drivers/net/wireless/ath/wil6210/Makefile
@@ -10,7 +10,6 @@ wil6210-y += interrupt.o
wil6210-y += txrx.o
wil6210-y += debug.o
wil6210-y += rx_reorder.o
-wil6210-y += ioctl.o
wil6210-y += fw.o
wil6210-y += pm.o
wil6210-y += pmc.o
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index fdaa99c541ac..0b5383a62d42 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -16,6 +16,7 @@
#include <linux/etherdevice.h>
#include <linux/moduleparam.h>
+#include <net/netlink.h>
#include "wil6210.h"
#include "wmi.h"
@@ -41,6 +42,126 @@ static struct ieee80211_channel wil_60ghz_channels[] = {
/* channel 4 not supported yet */
};
+/* Vendor id to be used in vendor specific command and events
+ * to user space.
+ * NOTE: The authoritative place for definition of QCA_NL80211_VENDOR_ID,
+ * vendor subcmd definitions prefixed with QCA_NL80211_VENDOR_SUBCMD, and
+ * qca_wlan_vendor_attr is open source file src/common/qca-vendor.h in
+ * git://w1.fi/srv/git/hostap.git; the values here are just a copy of that
+ */
+
+#define QCA_NL80211_VENDOR_ID 0x001374
+
+#define WIL_MAX_RF_SECTORS (128)
+#define WIL_CID_ALL (0xff)
+
+enum qca_wlan_vendor_attr_rf_sector {
+ QCA_ATTR_MAC_ADDR = 6,
+ QCA_ATTR_PAD = 13,
+ QCA_ATTR_TSF = 29,
+ QCA_ATTR_DMG_RF_SECTOR_INDEX = 30,
+ QCA_ATTR_DMG_RF_SECTOR_TYPE = 31,
+ QCA_ATTR_DMG_RF_MODULE_MASK = 32,
+ QCA_ATTR_DMG_RF_SECTOR_CFG = 33,
+ QCA_ATTR_DMG_RF_SECTOR_MAX,
+};
+
+enum qca_wlan_vendor_attr_dmg_rf_sector_type {
+ QCA_ATTR_DMG_RF_SECTOR_TYPE_RX,
+ QCA_ATTR_DMG_RF_SECTOR_TYPE_TX,
+ QCA_ATTR_DMG_RF_SECTOR_TYPE_MAX
+};
+
+enum qca_wlan_vendor_attr_dmg_rf_sector_cfg {
+ QCA_ATTR_DMG_RF_SECTOR_CFG_INVALID = 0,
+ QCA_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX,
+ QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE0,
+ QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE1,
+ QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE2,
+ QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_HI,
+ QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_LO,
+ QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16,
+
+ /* keep last */
+ QCA_ATTR_DMG_RF_SECTOR_CFG_AFTER_LAST,
+ QCA_ATTR_DMG_RF_SECTOR_CFG_MAX =
+ QCA_ATTR_DMG_RF_SECTOR_CFG_AFTER_LAST - 1
+};
+
+static const struct
+nla_policy wil_rf_sector_policy[QCA_ATTR_DMG_RF_SECTOR_MAX + 1] = {
+ [QCA_ATTR_MAC_ADDR] = { .len = ETH_ALEN },
+ [QCA_ATTR_DMG_RF_SECTOR_INDEX] = { .type = NLA_U16 },
+ [QCA_ATTR_DMG_RF_SECTOR_TYPE] = { .type = NLA_U8 },
+ [QCA_ATTR_DMG_RF_MODULE_MASK] = { .type = NLA_U32 },
+ [QCA_ATTR_DMG_RF_SECTOR_CFG] = { .type = NLA_NESTED },
+};
+
+static const struct
+nla_policy wil_rf_sector_cfg_policy[QCA_ATTR_DMG_RF_SECTOR_CFG_MAX + 1] = {
+ [QCA_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX] = { .type = NLA_U8 },
+ [QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE0] = { .type = NLA_U32 },
+ [QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE1] = { .type = NLA_U32 },
+ [QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE2] = { .type = NLA_U32 },
+ [QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_HI] = { .type = NLA_U32 },
+ [QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_LO] = { .type = NLA_U32 },
+ [QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16] = { .type = NLA_U32 },
+};
+
+enum qca_nl80211_vendor_subcmds {
+ QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SECTOR_CFG = 139,
+ QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SECTOR_CFG = 140,
+ QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SELECTED_SECTOR = 141,
+ QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SELECTED_SECTOR = 142,
+};
+
+static int wil_rf_sector_get_cfg(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len);
+static int wil_rf_sector_set_cfg(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len);
+static int wil_rf_sector_get_selected(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len);
+static int wil_rf_sector_set_selected(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len);
+
+/* vendor specific commands */
+static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = {
+ {
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
+ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SECTOR_CFG,
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .doit = wil_rf_sector_get_cfg
+ },
+ {
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
+ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SECTOR_CFG,
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .doit = wil_rf_sector_set_cfg
+ },
+ {
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
+ .info.subcmd =
+ QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SELECTED_SECTOR,
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .doit = wil_rf_sector_get_selected
+ },
+ {
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
+ .info.subcmd =
+ QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SELECTED_SECTOR,
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .doit = wil_rf_sector_set_selected
+ },
+};
+
static struct ieee80211_supported_band wil_band_60ghz = {
.channels = wil_60ghz_channels,
.n_channels = ARRAY_SIZE(wil_60ghz_channels),
@@ -1325,6 +1446,8 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
wil_set_recovery_state(wil, fw_recovery_idle);
+ set_bit(wil_status_resetting, wil->status);
+
mutex_lock(&wil->mutex);
wmi_pcp_stop(wil);
@@ -1571,6 +1694,42 @@ static int wil_cfg80211_set_power_mgmt(struct wiphy *wiphy,
return wil_ps_update(wil, ps_profile);
}
+static int wil_cfg80211_suspend(struct wiphy *wiphy,
+ struct cfg80211_wowlan *wow)
+{
+ struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+ int rc;
+
+ /* Setting the wakeup trigger based on wow is TBD */
+
+ if (test_bit(wil_status_suspended, wil->status)) {
+ wil_dbg_pm(wil, "trying to suspend while suspended\n");
+ return 0;
+ }
+
+ rc = wil_can_suspend(wil, false);
+ if (rc)
+ goto out;
+
+ wil_dbg_pm(wil, "suspending\n");
+
+ wil_p2p_stop_discovery(wil);
+
+ wil_abort_scan(wil, true);
+
+out:
+ return rc;
+}
+
+static int wil_cfg80211_resume(struct wiphy *wiphy)
+{
+ struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+
+ wil_dbg_pm(wil, "resuming\n");
+
+ return 0;
+}
+
static const struct cfg80211_ops wil_cfg80211_ops = {
.add_virtual_intf = wil_cfg80211_add_iface,
.del_virtual_intf = wil_cfg80211_del_iface,
@@ -1602,6 +1761,8 @@ static const struct cfg80211_ops wil_cfg80211_ops = {
.start_p2p_device = wil_cfg80211_start_p2p_device,
.stop_p2p_device = wil_cfg80211_stop_p2p_device,
.set_power_mgmt = wil_cfg80211_set_power_mgmt,
+ .suspend = wil_cfg80211_suspend,
+ .resume = wil_cfg80211_resume,
};
static void wil_wiphy_init(struct wiphy *wiphy)
@@ -1637,6 +1798,9 @@ static void wil_wiphy_init(struct wiphy *wiphy)
wiphy->n_cipher_suites = ARRAY_SIZE(wil_cipher_suites);
wiphy->mgmt_stypes = wil_mgmt_stypes;
wiphy->features |= NL80211_FEATURE_SK_TX_STATUS;
+
+ wiphy->n_vendor_commands = ARRAY_SIZE(wil_nl80211_vendor_commands);
+ wiphy->vendor_commands = wil_nl80211_vendor_commands;
}
struct wireless_dev *wil_cfg80211_init(struct device *dev)
@@ -1695,3 +1859,452 @@ void wil_p2p_wdev_free(struct wil6210_priv *wil)
kfree(p2p_wdev);
}
}
+
+static int wil_rf_sector_status_to_rc(u8 status)
+{
+ switch (status) {
+ case WMI_RF_SECTOR_STATUS_SUCCESS:
+ return 0;
+ case WMI_RF_SECTOR_STATUS_BAD_PARAMETERS_ERROR:
+ return -EINVAL;
+ case WMI_RF_SECTOR_STATUS_BUSY_ERROR:
+ return -EAGAIN;
+ case WMI_RF_SECTOR_STATUS_NOT_SUPPORTED_ERROR:
+ return -EOPNOTSUPP;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int wil_rf_sector_get_cfg(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ struct wil6210_priv *wil = wdev_to_wil(wdev);
+ int rc;
+ struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1];
+ u16 sector_index;
+ u8 sector_type;
+ u32 rf_modules_vec;
+ struct wmi_get_rf_sector_params_cmd cmd;
+ struct {
+ struct wmi_cmd_hdr wmi;
+ struct wmi_get_rf_sector_params_done_event evt;
+ } __packed reply;
+ struct sk_buff *msg;
+ struct nlattr *nl_cfgs, *nl_cfg;
+ u32 i;
+ struct wmi_rf_sector_info *si;
+
+ if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities))
+ return -EOPNOTSUPP;
+
+ rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len,
+ wil_rf_sector_policy, NULL);
+ if (rc) {
+ wil_err(wil, "Invalid rf sector ATTR\n");
+ return rc;
+ }
+
+ if (!tb[QCA_ATTR_DMG_RF_SECTOR_INDEX] ||
+ !tb[QCA_ATTR_DMG_RF_SECTOR_TYPE] ||
+ !tb[QCA_ATTR_DMG_RF_MODULE_MASK]) {
+ wil_err(wil, "Invalid rf sector spec\n");
+ return -EINVAL;
+ }
+
+ sector_index = nla_get_u16(
+ tb[QCA_ATTR_DMG_RF_SECTOR_INDEX]);
+ if (sector_index >= WIL_MAX_RF_SECTORS) {
+ wil_err(wil, "Invalid sector index %d\n", sector_index);
+ return -EINVAL;
+ }
+
+ sector_type = nla_get_u8(tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]);
+ if (sector_type >= QCA_ATTR_DMG_RF_SECTOR_TYPE_MAX) {
+ wil_err(wil, "Invalid sector type %d\n", sector_type);
+ return -EINVAL;
+ }
+
+ rf_modules_vec = nla_get_u32(
+ tb[QCA_ATTR_DMG_RF_MODULE_MASK]);
+ if (rf_modules_vec >= BIT(WMI_MAX_RF_MODULES_NUM)) {
+ wil_err(wil, "Invalid rf module mask 0x%x\n", rf_modules_vec);
+ return -EINVAL;
+ }
+
+ cmd.sector_idx = cpu_to_le16(sector_index);
+ cmd.sector_type = sector_type;
+ cmd.rf_modules_vec = rf_modules_vec & 0xFF;
+ memset(&reply, 0, sizeof(reply));
+ rc = wmi_call(wil, WMI_GET_RF_SECTOR_PARAMS_CMDID, &cmd, sizeof(cmd),
+ WMI_GET_RF_SECTOR_PARAMS_DONE_EVENTID,
+ &reply, sizeof(reply),
+ 500);
+ if (rc)
+ return rc;
+ if (reply.evt.status) {
+ wil_err(wil, "get rf sector cfg failed with status %d\n",
+ reply.evt.status);
+ return wil_rf_sector_status_to_rc(reply.evt.status);
+ }
+
+ msg = cfg80211_vendor_cmd_alloc_reply_skb(
+ wiphy, 64 * WMI_MAX_RF_MODULES_NUM);
+ if (!msg)
+ return -ENOMEM;
+
+ if (nla_put_u64_64bit(msg, QCA_ATTR_TSF,
+ le64_to_cpu(reply.evt.tsf),
+ QCA_ATTR_PAD))
+ goto nla_put_failure;
+
+ nl_cfgs = nla_nest_start(msg, QCA_ATTR_DMG_RF_SECTOR_CFG);
+ if (!nl_cfgs)
+ goto nla_put_failure;
+ for (i = 0; i < WMI_MAX_RF_MODULES_NUM; i++) {
+ if (!(rf_modules_vec & BIT(i)))
+ continue;
+ nl_cfg = nla_nest_start(msg, i);
+ if (!nl_cfg)
+ goto nla_put_failure;
+ si = &reply.evt.sectors_info[i];
+ if (nla_put_u8(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX,
+ i) ||
+ nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE0,
+ le32_to_cpu(si->etype0)) ||
+ nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE1,
+ le32_to_cpu(si->etype1)) ||
+ nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE2,
+ le32_to_cpu(si->etype2)) ||
+ nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_HI,
+ le32_to_cpu(si->psh_hi)) ||
+ nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_LO,
+ le32_to_cpu(si->psh_lo)) ||
+ nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16,
+ le32_to_cpu(si->dtype_swch_off)))
+ goto nla_put_failure;
+ nla_nest_end(msg, nl_cfg);
+ }
+
+ nla_nest_end(msg, nl_cfgs);
+ rc = cfg80211_vendor_cmd_reply(msg);
+ return rc;
+nla_put_failure:
+ kfree_skb(msg);
+ return -ENOBUFS;
+}
+
+static int wil_rf_sector_set_cfg(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ struct wil6210_priv *wil = wdev_to_wil(wdev);
+ int rc, tmp;
+ struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1];
+ struct nlattr *tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_MAX + 1];
+ u16 sector_index, rf_module_index;
+ u8 sector_type;
+ u32 rf_modules_vec = 0;
+ struct wmi_set_rf_sector_params_cmd cmd;
+ struct {
+ struct wmi_cmd_hdr wmi;
+ struct wmi_set_rf_sector_params_done_event evt;
+ } __packed reply;
+ struct nlattr *nl_cfg;
+ struct wmi_rf_sector_info *si;
+
+ if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities))
+ return -EOPNOTSUPP;
+
+ rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len,
+ wil_rf_sector_policy, NULL);
+ if (rc) {
+ wil_err(wil, "Invalid rf sector ATTR\n");
+ return rc;
+ }
+
+ if (!tb[QCA_ATTR_DMG_RF_SECTOR_INDEX] ||
+ !tb[QCA_ATTR_DMG_RF_SECTOR_TYPE] ||
+ !tb[QCA_ATTR_DMG_RF_SECTOR_CFG]) {
+ wil_err(wil, "Invalid rf sector spec\n");
+ return -EINVAL;
+ }
+
+ sector_index = nla_get_u16(
+ tb[QCA_ATTR_DMG_RF_SECTOR_INDEX]);
+ if (sector_index >= WIL_MAX_RF_SECTORS) {
+ wil_err(wil, "Invalid sector index %d\n", sector_index);
+ return -EINVAL;
+ }
+
+ sector_type = nla_get_u8(tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]);
+ if (sector_type >= QCA_ATTR_DMG_RF_SECTOR_TYPE_MAX) {
+ wil_err(wil, "Invalid sector type %d\n", sector_type);
+ return -EINVAL;
+ }
+
+ memset(&cmd, 0, sizeof(cmd));
+
+ cmd.sector_idx = cpu_to_le16(sector_index);
+ cmd.sector_type = sector_type;
+ nla_for_each_nested(nl_cfg, tb[QCA_ATTR_DMG_RF_SECTOR_CFG],
+ tmp) {
+ rc = nla_parse_nested(tb2, QCA_ATTR_DMG_RF_SECTOR_CFG_MAX,
+ nl_cfg, wil_rf_sector_cfg_policy,
+ NULL);
+ if (rc) {
+ wil_err(wil, "invalid sector cfg\n");
+ return -EINVAL;
+ }
+
+ if (!tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX] ||
+ !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE0] ||
+ !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE1] ||
+ !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE2] ||
+ !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_HI] ||
+ !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_LO] ||
+ !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16]) {
+ wil_err(wil, "missing cfg params\n");
+ return -EINVAL;
+ }
+
+ rf_module_index = nla_get_u8(
+ tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX]);
+ if (rf_module_index >= WMI_MAX_RF_MODULES_NUM) {
+ wil_err(wil, "invalid RF module index %d\n",
+ rf_module_index);
+ return -EINVAL;
+ }
+ rf_modules_vec |= BIT(rf_module_index);
+ si = &cmd.sectors_info[rf_module_index];
+ si->etype0 = cpu_to_le32(nla_get_u32(
+ tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE0]));
+ si->etype1 = cpu_to_le32(nla_get_u32(
+ tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE1]));
+ si->etype2 = cpu_to_le32(nla_get_u32(
+ tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE2]));
+ si->psh_hi = cpu_to_le32(nla_get_u32(
+ tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_HI]));
+ si->psh_lo = cpu_to_le32(nla_get_u32(
+ tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_LO]));
+ si->dtype_swch_off = cpu_to_le32(nla_get_u32(
+ tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16]));
+ }
+
+ cmd.rf_modules_vec = rf_modules_vec & 0xFF;
+ memset(&reply, 0, sizeof(reply));
+ rc = wmi_call(wil, WMI_SET_RF_SECTOR_PARAMS_CMDID, &cmd, sizeof(cmd),
+ WMI_SET_RF_SECTOR_PARAMS_DONE_EVENTID,
+ &reply, sizeof(reply),
+ 500);
+ if (rc)
+ return rc;
+ return wil_rf_sector_status_to_rc(reply.evt.status);
+}
+
+static int wil_rf_sector_get_selected(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ struct wil6210_priv *wil = wdev_to_wil(wdev);
+ int rc;
+ struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1];
+ u8 sector_type, mac_addr[ETH_ALEN];
+ int cid = 0;
+ struct wmi_get_selected_rf_sector_index_cmd cmd;
+ struct {
+ struct wmi_cmd_hdr wmi;
+ struct wmi_get_selected_rf_sector_index_done_event evt;
+ } __packed reply;
+ struct sk_buff *msg;
+
+ if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities))
+ return -EOPNOTSUPP;
+
+ rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len,
+ wil_rf_sector_policy, NULL);
+ if (rc) {
+ wil_err(wil, "Invalid rf sector ATTR\n");
+ return rc;
+ }
+
+ if (!tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]) {
+ wil_err(wil, "Invalid rf sector spec\n");
+ return -EINVAL;
+ }
+ sector_type = nla_get_u8(tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]);
+ if (sector_type >= QCA_ATTR_DMG_RF_SECTOR_TYPE_MAX) {
+ wil_err(wil, "Invalid sector type %d\n", sector_type);
+ return -EINVAL;
+ }
+
+ if (tb[QCA_ATTR_MAC_ADDR]) {
+ ether_addr_copy(mac_addr, nla_data(tb[QCA_ATTR_MAC_ADDR]));
+ cid = wil_find_cid(wil, mac_addr);
+ if (cid < 0) {
+ wil_err(wil, "invalid MAC address %pM\n", mac_addr);
+ return -ENOENT;
+ }
+ } else {
+ if (test_bit(wil_status_fwconnected, wil->status)) {
+ wil_err(wil, "must specify MAC address when connected\n");
+ return -EINVAL;
+ }
+ }
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.cid = (u8)cid;
+ cmd.sector_type = sector_type;
+ memset(&reply, 0, sizeof(reply));
+ rc = wmi_call(wil, WMI_GET_SELECTED_RF_SECTOR_INDEX_CMDID,
+ &cmd, sizeof(cmd),
+ WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID,
+ &reply, sizeof(reply),
+ 500);
+ if (rc)
+ return rc;
+ if (reply.evt.status) {
+ wil_err(wil, "get rf selected sector cfg failed with status %d\n",
+ reply.evt.status);
+ return wil_rf_sector_status_to_rc(reply.evt.status);
+ }
+
+ msg = cfg80211_vendor_cmd_alloc_reply_skb(
+ wiphy, 64 * WMI_MAX_RF_MODULES_NUM);
+ if (!msg)
+ return -ENOMEM;
+
+ if (nla_put_u64_64bit(msg, QCA_ATTR_TSF,
+ le64_to_cpu(reply.evt.tsf),
+ QCA_ATTR_PAD) ||
+ nla_put_u16(msg, QCA_ATTR_DMG_RF_SECTOR_INDEX,
+ le16_to_cpu(reply.evt.sector_idx)))
+ goto nla_put_failure;
+
+ rc = cfg80211_vendor_cmd_reply(msg);
+ return rc;
+nla_put_failure:
+ kfree_skb(msg);
+ return -ENOBUFS;
+}
+
+static int wil_rf_sector_wmi_set_selected(struct wil6210_priv *wil,
+ u16 sector_index,
+ u8 sector_type, u8 cid)
+{
+ struct wmi_set_selected_rf_sector_index_cmd cmd;
+ struct {
+ struct wmi_cmd_hdr wmi;
+ struct wmi_set_selected_rf_sector_index_done_event evt;
+ } __packed reply;
+ int rc;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.sector_idx = cpu_to_le16(sector_index);
+ cmd.sector_type = sector_type;
+ cmd.cid = (u8)cid;
+ memset(&reply, 0, sizeof(reply));
+ rc = wmi_call(wil, WMI_SET_SELECTED_RF_SECTOR_INDEX_CMDID,
+ &cmd, sizeof(cmd),
+ WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID,
+ &reply, sizeof(reply),
+ 500);
+ if (rc)
+ return rc;
+ return wil_rf_sector_status_to_rc(reply.evt.status);
+}
+
+static int wil_rf_sector_set_selected(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ struct wil6210_priv *wil = wdev_to_wil(wdev);
+ int rc;
+ struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1];
+ u16 sector_index;
+ u8 sector_type, mac_addr[ETH_ALEN], i;
+ int cid = 0;
+
+ if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities))
+ return -EOPNOTSUPP;
+
+ rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len,
+ wil_rf_sector_policy, NULL);
+ if (rc) {
+ wil_err(wil, "Invalid rf sector ATTR\n");
+ return rc;
+ }
+
+ if (!tb[QCA_ATTR_DMG_RF_SECTOR_INDEX] ||
+ !tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]) {
+ wil_err(wil, "Invalid rf sector spec\n");
+ return -EINVAL;
+ }
+
+ sector_index = nla_get_u16(
+ tb[QCA_ATTR_DMG_RF_SECTOR_INDEX]);
+ if (sector_index >= WIL_MAX_RF_SECTORS &&
+ sector_index != WMI_INVALID_RF_SECTOR_INDEX) {
+ wil_err(wil, "Invalid sector index %d\n", sector_index);
+ return -EINVAL;
+ }
+
+ sector_type = nla_get_u8(tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]);
+ if (sector_type >= QCA_ATTR_DMG_RF_SECTOR_TYPE_MAX) {
+ wil_err(wil, "Invalid sector type %d\n", sector_type);
+ return -EINVAL;
+ }
+
+ if (tb[QCA_ATTR_MAC_ADDR]) {
+ ether_addr_copy(mac_addr, nla_data(tb[QCA_ATTR_MAC_ADDR]));
+ if (!is_broadcast_ether_addr(mac_addr)) {
+ cid = wil_find_cid(wil, mac_addr);
+ if (cid < 0) {
+ wil_err(wil, "invalid MAC address %pM\n",
+ mac_addr);
+ return -ENOENT;
+ }
+ } else {
+ if (sector_index != WMI_INVALID_RF_SECTOR_INDEX) {
+ wil_err(wil, "broadcast MAC valid only with unlocking\n");
+ return -EINVAL;
+ }
+ cid = -1;
+ }
+ } else {
+ if (test_bit(wil_status_fwconnected, wil->status)) {
+ wil_err(wil, "must specify MAC address when connected\n");
+ return -EINVAL;
+ }
+ /* otherwise, using cid=0 for unassociated station */
+ }
+
+ if (cid >= 0) {
+ rc = wil_rf_sector_wmi_set_selected(wil, sector_index,
+ sector_type, cid);
+ } else {
+ /* unlock all cids */
+ rc = wil_rf_sector_wmi_set_selected(
+ wil, WMI_INVALID_RF_SECTOR_INDEX, sector_type,
+ WIL_CID_ALL);
+ if (rc == -EINVAL) {
+ for (i = 0; i < WIL6210_MAX_CID; i++) {
+ rc = wil_rf_sector_wmi_set_selected(
+ wil, WMI_INVALID_RF_SECTOR_INDEX,
+ sector_type, i);
+ /* the FW will silently ignore and return
+ * success for unused cid, so abort the loop
+ * on any other error
+ */
+ if (rc) {
+ wil_err(wil, "unlock cid %d failed with status %d\n",
+ i, rc);
+ break;
+ }
+ }
+ }
+ }
+
+ return rc;
+}
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 5b0f9fc66bb6..f82506d276d3 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -509,6 +509,10 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf,
void *buf;
size_t ret;
+ if (test_bit(wil_status_suspending, wil_blob->wil->status) ||
+ test_bit(wil_status_suspended, wil_blob->wil->status))
+ return 0;
+
if (pos < 0)
return -EINVAL;
@@ -1600,6 +1604,49 @@ static const struct file_operations fops_fw_version = {
.llseek = seq_lseek,
};
+/*---------suspend_stats---------*/
+static ssize_t wil_write_suspend_stats(struct file *file,
+ const char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ struct wil6210_priv *wil = file->private_data;
+
+ memset(&wil->suspend_stats, 0, sizeof(wil->suspend_stats));
+
+ return len;
+}
+
+static ssize_t wil_read_suspend_stats(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct wil6210_priv *wil = file->private_data;
+ static char text[400];
+ int n;
+
+ n = snprintf(text, sizeof(text),
+ "Suspend statistics:\n"
+ "successful suspends:%ld failed suspends:%ld\n"
+ "successful resumes:%ld failed resumes:%ld\n"
+ "rejected by host:%ld rejected by device:%ld\n",
+ wil->suspend_stats.successful_suspends,
+ wil->suspend_stats.failed_suspends,
+ wil->suspend_stats.successful_resumes,
+ wil->suspend_stats.failed_resumes,
+ wil->suspend_stats.rejected_by_host,
+ wil->suspend_stats.rejected_by_device);
+
+ n = min_t(int, n, sizeof(text));
+
+ return simple_read_from_buffer(user_buf, count, ppos, text, n);
+}
+
+static const struct file_operations fops_suspend_stats = {
+ .read = wil_read_suspend_stats,
+ .write = wil_write_suspend_stats,
+ .open = simple_open,
+};
+
/*----------------*/
static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil,
struct dentry *dbg)
@@ -1652,6 +1699,7 @@ static const struct {
{"led_blink_time", 0644, &fops_led_blink_time},
{"fw_capabilities", 0444, &fops_fw_capabilities},
{"fw_version", 0444, &fops_fw_version},
+ {"suspend_stats", 0644, &fops_suspend_stats},
};
static void wil6210_debugfs_init_files(struct wil6210_priv *wil,
@@ -1698,6 +1746,7 @@ static const struct dbg_off dbg_wil_off[] = {
WIL_FIELD(discovery_mode, 0644, doff_u8),
WIL_FIELD(chip_revision, 0444, doff_u8),
WIL_FIELD(abft_len, 0644, doff_u8),
+ WIL_FIELD(wakeup_trigger, 0644, doff_u8),
{},
};
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c
index cab1e5c0e374..cad8a95c4e4e 100644
--- a/drivers/net/wireless/ath/wil6210/interrupt.c
+++ b/drivers/net/wireless/ath/wil6210/interrupt.c
@@ -467,6 +467,12 @@ static irqreturn_t wil6210_thread_irq(int irq, void *cookie)
wil6210_unmask_irq_pseudo(wil);
+ if (wil->suspend_resp_rcvd) {
+ wil_dbg_irq(wil, "set suspend_resp_comp to true\n");
+ wil->suspend_resp_comp = true;
+ wake_up_interruptible(&wil->wq);
+ }
+
return IRQ_HANDLED;
}
diff --git a/drivers/net/wireless/ath/wil6210/ioctl.c b/drivers/net/wireless/ath/wil6210/ioctl.c
deleted file mode 100644
index 630380078236..000000000000
--- a/drivers/net/wireless/ath/wil6210/ioctl.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (c) 2014 Qualcomm Atheros, Inc.
- *
- * 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/uaccess.h>
-
-#include "wil6210.h"
-#include <uapi/linux/wil6210_uapi.h>
-
-#define wil_hex_dump_ioctl(prefix_str, buf, len) \
- print_hex_dump_debug("DBG[IOC ]" prefix_str, \
- DUMP_PREFIX_OFFSET, 16, 1, buf, len, true)
-#define wil_dbg_ioctl(wil, fmt, arg...) wil_dbg(wil, "DBG[IOC ]" fmt, ##arg)
-
-static void __iomem *wil_ioc_addr(struct wil6210_priv *wil, uint32_t addr,
- uint32_t size, enum wil_memio_op op)
-{
- void __iomem *a;
- u32 off;
-
- switch (op & wil_mmio_addr_mask) {
- case wil_mmio_addr_linker:
- a = wmi_buffer(wil, cpu_to_le32(addr));
- break;
- case wil_mmio_addr_ahb:
- a = wmi_addr(wil, addr);
- break;
- case wil_mmio_addr_bar:
- a = wmi_addr(wil, addr + WIL6210_FW_HOST_OFF);
- break;
- default:
- wil_err(wil, "Unsupported address mode, op = 0x%08x\n", op);
- return NULL;
- }
-
- off = a - wil->csr;
- if (size >= WIL6210_MEM_SIZE - off) {
- wil_err(wil, "Requested block does not fit into memory: "
- "off = 0x%08x size = 0x%08x\n", off, size);
- return NULL;
- }
-
- return a;
-}
-
-static int wil_ioc_memio_dword(struct wil6210_priv *wil, void __user *data)
-{
- struct wil_memio io;
- void __iomem *a;
- bool need_copy = false;
-
- if (copy_from_user(&io, data, sizeof(io)))
- return -EFAULT;
-
- wil_dbg_ioctl(wil, "IO: addr = 0x%08x val = 0x%08x op = 0x%08x\n",
- io.addr, io.val, io.op);
-
- a = wil_ioc_addr(wil, io.addr, sizeof(u32), io.op);
- if (!a) {
- wil_err(wil, "invalid address 0x%08x, op = 0x%08x\n", io.addr,
- io.op);
- return -EINVAL;
- }
- /* operation */
- switch (io.op & wil_mmio_op_mask) {
- case wil_mmio_read:
- io.val = readl(a);
- need_copy = true;
- break;
- case wil_mmio_write:
- writel(io.val, a);
- wmb(); /* make sure write propagated to HW */
- break;
- default:
- wil_err(wil, "Unsupported operation, op = 0x%08x\n", io.op);
- return -EINVAL;
- }
-
- if (need_copy) {
- wil_dbg_ioctl(wil, "IO done: addr = 0x%08x"
- " val = 0x%08x op = 0x%08x\n",
- io.addr, io.val, io.op);
- if (copy_to_user(data, &io, sizeof(io)))
- return -EFAULT;
- }
-
- return 0;
-}
-
-static int wil_ioc_memio_block(struct wil6210_priv *wil, void __user *data)
-{
- struct wil_memio_block io;
- void *block;
- void __iomem *a;
- int rc = 0;
-
- if (copy_from_user(&io, data, sizeof(io)))
- return -EFAULT;
-
- wil_dbg_ioctl(wil, "IO: addr = 0x%08x size = 0x%08x op = 0x%08x\n",
- io.addr, io.size, io.op);
-
- /* size */
- if (io.size % 4) {
- wil_err(wil, "size is not multiple of 4: 0x%08x\n", io.size);
- return -EINVAL;
- }
-
- a = wil_ioc_addr(wil, io.addr, io.size, io.op);
- if (!a) {
- wil_err(wil, "invalid address 0x%08x, op = 0x%08x\n", io.addr,
- io.op);
- return -EINVAL;
- }
-
- block = kmalloc(io.size, GFP_USER);
- if (!block)
- return -ENOMEM;
-
- /* operation */
- switch (io.op & wil_mmio_op_mask) {
- case wil_mmio_read:
- wil_memcpy_fromio_32(block, a, io.size);
- wil_hex_dump_ioctl("Read ", block, io.size);
- if (copy_to_user(io.block, block, io.size)) {
- rc = -EFAULT;
- goto out_free;
- }
- break;
- case wil_mmio_write:
- if (copy_from_user(block, io.block, io.size)) {
- rc = -EFAULT;
- goto out_free;
- }
- wil_memcpy_toio_32(a, block, io.size);
- wmb(); /* make sure write propagated to HW */
- wil_hex_dump_ioctl("Write ", block, io.size);
- break;
- default:
- wil_err(wil, "Unsupported operation, op = 0x%08x\n", io.op);
- rc = -EINVAL;
- break;
- }
-
-out_free:
- kfree(block);
- return rc;
-}
-
-int wil_ioctl(struct wil6210_priv *wil, void __user *data, int cmd)
-{
- int ret;
-
- switch (cmd) {
- case WIL_IOCTL_MEMIO:
- ret = wil_ioc_memio_dword(wil, data);
- break;
- case WIL_IOCTL_MEMIO_BLOCK:
- ret = wil_ioc_memio_block(wil, data);
- break;
- default:
- wil_dbg_ioctl(wil, "Unsupported IOCTL 0x%04x\n", cmd);
- return -ENOIOCTLCMD;
- }
-
- wil_dbg_ioctl(wil, "ioctl(0x%04x) -> %d\n", cmd, ret);
- return ret;
-}
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 32086792dfc3..daf944a71901 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -576,6 +576,9 @@ int wil_priv_init(struct wil6210_priv *wil)
wil->ps_profile = WMI_PS_PROFILE_TYPE_DEFAULT;
+ wil->wakeup_trigger = WMI_WAKEUP_TRIGGER_UCAST |
+ WMI_WAKEUP_TRIGGER_BCAST;
+
return 0;
out_wmi_wq:
@@ -586,8 +589,10 @@ out_wmi_wq:
void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps)
{
- if (wil->platform_ops.bus_request)
+ if (wil->platform_ops.bus_request) {
+ wil->bus_request_kbps = kbps;
wil->platform_ops.bus_request(wil->platform_handle, kbps);
+ }
}
/**
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
index 708facd5f667..4a6ab2d0fdf1 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -42,20 +42,12 @@ static int wil_stop(struct net_device *ndev)
return wil_down(wil);
}
-static int wil_do_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
-{
- struct wil6210_priv *wil = ndev_to_wil(ndev);
-
- return wil_ioctl(wil, ifr->ifr_data, cmd);
-}
-
static const struct net_device_ops wil_netdev_ops = {
.ndo_open = wil_open,
.ndo_stop = wil_stop,
.ndo_start_xmit = wil_start_xmit,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
- .ndo_do_ioctl = wil_do_ioctl,
};
static int wil6210_netdev_poll_rx(struct napi_struct *napi, int budget)
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c
index b38515fc7ce7..d571feb2370e 100644
--- a/drivers/net/wireless/ath/wil6210/pcie_bus.c
+++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016 Qualcomm Atheros, Inc.
+ * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -26,6 +26,10 @@ static bool use_msi = true;
module_param(use_msi, bool, 0444);
MODULE_PARM_DESC(use_msi, " Use MSI interrupt, default - true");
+static bool ftm_mode;
+module_param(ftm_mode, bool, 0444);
+MODULE_PARM_DESC(ftm_mode, " Set factory test mode, default - false");
+
#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
static int wil6210_pm_notify(struct notifier_block *notify_block,
@@ -36,13 +40,15 @@ static int wil6210_pm_notify(struct notifier_block *notify_block,
static
void wil_set_capabilities(struct wil6210_priv *wil)
{
+ const char *wil_fw_name;
u32 jtag_id = wil_r(wil, RGF_USER_JTAG_DEV_ID);
u8 chip_revision = (wil_r(wil, RGF_USER_REVISION_ID) &
RGF_USER_REVISION_ID_MASK);
bitmap_zero(wil->hw_capabilities, hw_capability_last);
bitmap_zero(wil->fw_capabilities, WMI_FW_CAPABILITY_MAX);
- wil->wil_fw_name = WIL_FW_NAME_DEFAULT;
+ wil->wil_fw_name = ftm_mode ? WIL_FW_NAME_FTM_DEFAULT :
+ WIL_FW_NAME_DEFAULT;
wil->chip_revision = chip_revision;
switch (jtag_id) {
@@ -51,9 +57,11 @@ void wil_set_capabilities(struct wil6210_priv *wil)
case REVISION_ID_SPARROW_D0:
wil->hw_name = "Sparrow D0";
wil->hw_version = HW_VER_SPARROW_D0;
- if (wil_fw_verify_file_exists(wil,
- WIL_FW_NAME_SPARROW_PLUS))
- wil->wil_fw_name = WIL_FW_NAME_SPARROW_PLUS;
+ wil_fw_name = ftm_mode ? WIL_FW_NAME_FTM_SPARROW_PLUS :
+ WIL_FW_NAME_SPARROW_PLUS;
+
+ if (wil_fw_verify_file_exists(wil, wil_fw_name))
+ wil->wil_fw_name = wil_fw_name;
break;
case REVISION_ID_SPARROW_B0:
wil->hw_name = "Sparrow B0";
@@ -104,8 +112,6 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil)
wil_dbg_misc(wil, "if_pcie_enable, wmi_only %d\n", wmi_only);
- pdev->msi_enabled = 0;
-
pci_set_master(pdev);
wil_dbg_misc(wil, "Setup %s interrupt\n", use_msi ? "MSI" : "INTx");
@@ -183,6 +189,13 @@ static int wil_platform_rop_fw_recovery(void *wil_handle)
return 0;
}
+static void wil_platform_ops_uninit(struct wil6210_priv *wil)
+{
+ if (wil->platform_ops.uninit)
+ wil->platform_ops.uninit(wil->platform_handle);
+ memset(&wil->platform_ops, 0, sizeof(wil->platform_ops));
+}
+
static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct wil6210_priv *wil;
@@ -192,16 +205,18 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
.ramdump = wil_platform_rop_ramdump,
.fw_recovery = wil_platform_rop_fw_recovery,
};
+ u32 bar_size = pci_resource_len(pdev, 0);
/* check HW */
dev_info(&pdev->dev, WIL_NAME
- " device found [%04x:%04x] (rev %x)\n",
- (int)pdev->vendor, (int)pdev->device, (int)pdev->revision);
-
- if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) {
- dev_err(&pdev->dev, "Not " WIL_NAME "? "
- "BAR0 size is %lu while expecting %lu\n",
- (ulong)pci_resource_len(pdev, 0), WIL6210_MEM_SIZE);
+ " device found [%04x:%04x] (rev %x) bar size 0x%x\n",
+ (int)pdev->vendor, (int)pdev->device, (int)pdev->revision,
+ bar_size);
+
+ if ((bar_size < WIL6210_MIN_MEM_SIZE) ||
+ (bar_size > WIL6210_MAX_MEM_SIZE)) {
+ dev_err(&pdev->dev, "Unexpected BAR0 size 0x%x\n",
+ bar_size);
return -ENODEV;
}
@@ -214,6 +229,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
wil->pdev = pdev;
pci_set_drvdata(pdev, wil);
+ wil->bar_size = bar_size;
/* rollback to if_free */
wil->platform_handle =
@@ -241,7 +257,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
rc = pci_enable_device(pdev);
- if (rc) {
+ if (rc && pdev->msi_enabled == 0) {
wil_err(wil,
"pci_enable_device failed, retry with MSI only\n");
/* Work around for platforms that can't allocate IRQ:
@@ -256,6 +272,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_plat;
}
/* rollback to err_disable_pdev */
+ pci_set_power_state(pdev, PCI_D0);
rc = pci_request_region(pdev, 0, WIL_NAME);
if (rc) {
@@ -276,6 +293,15 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
wil_set_capabilities(wil);
wil6210_clear_irq(wil);
+ wil->keep_radio_on_during_sleep =
+ wil->platform_ops.keep_radio_on_during_sleep &&
+ wil->platform_ops.keep_radio_on_during_sleep(
+ wil->platform_handle) &&
+ test_bit(WMI_FW_CAPABILITY_D3_SUSPEND, wil->fw_capabilities);
+
+ wil_info(wil, "keep_radio_on_during_sleep (%d)\n",
+ wil->keep_radio_on_during_sleep);
+
/* FW should raise IRQ when ready */
rc = wil_if_pcie_enable(wil);
if (rc) {
@@ -316,8 +342,7 @@ err_release_reg:
err_disable_pdev:
pci_disable_device(pdev);
err_plat:
- if (wil->platform_ops.uninit)
- wil->platform_ops.uninit(wil->platform_handle);
+ wil_platform_ops_uninit(wil);
if_free:
wil_if_free(wil);
@@ -346,8 +371,7 @@ static void wil_pcie_remove(struct pci_dev *pdev)
pci_iounmap(pdev, csr);
pci_release_region(pdev, 0);
pci_disable_device(pdev);
- if (wil->platform_ops.uninit)
- wil->platform_ops.uninit(wil->platform_handle);
+ wil_platform_ops_uninit(wil);
wil_if_free(wil);
}
@@ -374,15 +398,16 @@ static int wil6210_suspend(struct device *dev, bool is_runtime)
goto out;
rc = wil_suspend(wil, is_runtime);
- if (rc)
- goto out;
-
- /* TODO: how do I bring card in low power state? */
-
- /* disable bus mastering */
- pci_clear_master(pdev);
- /* PCI will call pci_save_state(pdev) and pci_prepare_to_sleep(pdev) */
+ if (!rc) {
+ wil->suspend_stats.successful_suspends++;
+ /* If platform device supports keep_radio_on_during_sleep
+ * it will control PCIe master
+ */
+ if (!wil->keep_radio_on_during_sleep)
+ /* disable bus mastering */
+ pci_clear_master(pdev);
+ }
out:
return rc;
}
@@ -395,12 +420,21 @@ static int wil6210_resume(struct device *dev, bool is_runtime)
wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system");
- /* allow master */
- pci_set_master(pdev);
-
+ /* If platform device supports keep_radio_on_during_sleep it will
+ * control PCIe master
+ */
+ if (!wil->keep_radio_on_during_sleep)
+ /* allow master */
+ pci_set_master(pdev);
rc = wil_resume(wil, is_runtime);
- if (rc)
- pci_clear_master(pdev);
+ if (rc) {
+ wil_err(wil, "device failed to resume (%d)\n", rc);
+ wil->suspend_stats.failed_resumes++;
+ if (!wil->keep_radio_on_during_sleep)
+ pci_clear_master(pdev);
+ } else {
+ wil->suspend_stats.successful_resumes++;
+ }
return rc;
}
diff --git a/drivers/net/wireless/ath/wil6210/pm.c b/drivers/net/wireless/ath/wil6210/pm.c
index 2ae4fe85cc8c..ce1f384e7f8e 100644
--- a/drivers/net/wireless/ath/wil6210/pm.c
+++ b/drivers/net/wireless/ath/wil6210/pm.c
@@ -15,6 +15,7 @@
*/
#include "wil6210.h"
+#include <linux/jiffies.h>
int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime)
{
@@ -61,20 +62,170 @@ out:
wil_dbg_pm(wil, "can_suspend: %s => %s (%d)\n",
is_runtime ? "runtime" : "system", rc ? "No" : "Yes", rc);
+ if (rc)
+ wil->suspend_stats.rejected_by_host++;
+
return rc;
}
-int wil_suspend(struct wil6210_priv *wil, bool is_runtime)
+static int wil_resume_keep_radio_on(struct wil6210_priv *wil)
{
int rc = 0;
- struct net_device *ndev = wil_to_ndev(wil);
- wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system");
+ /* wil_status_resuming will be cleared when getting
+ * WMI_TRAFFIC_RESUME_EVENTID
+ */
+ set_bit(wil_status_resuming, wil->status);
+ clear_bit(wil_status_suspended, wil->status);
+ wil_c(wil, RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
+ wil_unmask_irq(wil);
- if (test_bit(wil_status_suspended, wil->status)) {
- wil_dbg_pm(wil, "trying to suspend while suspended\n");
- return 0;
+ wil6210_bus_request(wil, wil->bus_request_kbps_pre_suspend);
+
+ /* Send WMI resume request to the device */
+ rc = wmi_resume(wil);
+ if (rc) {
+ wil_err(wil, "device failed to resume (%d), resetting\n", rc);
+ rc = wil_down(wil);
+ if (rc) {
+ wil_err(wil, "wil_down failed (%d)\n", rc);
+ goto out;
+ }
+ rc = wil_up(wil);
+ if (rc) {
+ wil_err(wil, "wil_up failed (%d)\n", rc);
+ goto out;
+ }
+ }
+
+ /* Wake all queues */
+ if (test_bit(wil_status_fwconnected, wil->status))
+ wil_update_net_queues_bh(wil, NULL, false);
+
+out:
+ if (rc)
+ set_bit(wil_status_suspended, wil->status);
+ return rc;
+}
+
+static int wil_suspend_keep_radio_on(struct wil6210_priv *wil)
+{
+ int rc = 0;
+ unsigned long start, data_comp_to;
+
+ wil_dbg_pm(wil, "suspend keep radio on\n");
+
+ /* Prevent handling of new tx and wmi commands */
+ set_bit(wil_status_suspending, wil->status);
+ wil_update_net_queues_bh(wil, NULL, true);
+
+ if (!wil_is_tx_idle(wil)) {
+ wil_dbg_pm(wil, "Pending TX data, reject suspend\n");
+ wil->suspend_stats.rejected_by_host++;
+ goto reject_suspend;
+ }
+
+ if (!wil_is_rx_idle(wil)) {
+ wil_dbg_pm(wil, "Pending RX data, reject suspend\n");
+ wil->suspend_stats.rejected_by_host++;
+ goto reject_suspend;
+ }
+
+ if (!wil_is_wmi_idle(wil)) {
+ wil_dbg_pm(wil, "Pending WMI events, reject suspend\n");
+ wil->suspend_stats.rejected_by_host++;
+ goto reject_suspend;
+ }
+
+ /* Send WMI suspend request to the device */
+ rc = wmi_suspend(wil);
+ if (rc) {
+ wil_dbg_pm(wil, "wmi_suspend failed, reject suspend (%d)\n",
+ rc);
+ goto reject_suspend;
+ }
+
+ /* 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_is_rx_idle(wil)) {
+ if (time_after(jiffies, data_comp_to)) {
+ if (wil_is_rx_idle(wil))
+ break;
+ wil_err(wil,
+ "TO waiting for idle RX, suspend failed\n");
+ wil->suspend_stats.failed_suspends++;
+ goto resume_after_fail;
+ }
+ wil_dbg_ratelimited(wil, "rx vring is not empty -> NAPI\n");
+ napi_synchronize(&wil->napi_rx);
+ msleep(20);
+ }
+ }
+
+ /* In case of pending WMI events, reject the suspend
+ * and resume the device.
+ * This can happen if the device sent the WMI events before
+ * approving the suspend.
+ */
+ if (!wil_is_wmi_idle(wil)) {
+ wil_err(wil, "suspend failed due to pending WMI events\n");
+ wil->suspend_stats.failed_suspends++;
+ goto resume_after_fail;
+ }
+
+ wil_mask_irq(wil);
+
+ /* Disable device reset on PERST */
+ wil_s(wil, RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
+
+ if (wil->platform_ops.suspend) {
+ rc = wil->platform_ops.suspend(wil->platform_handle, true);
+ if (rc) {
+ wil_err(wil, "platform device failed to suspend (%d)\n",
+ rc);
+ wil->suspend_stats.failed_suspends++;
+ wil_c(wil, RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
+ wil_unmask_irq(wil);
+ goto resume_after_fail;
+ }
+ }
+
+ /* Save the current bus request to return to the same in resume */
+ wil->bus_request_kbps_pre_suspend = wil->bus_request_kbps;
+ wil6210_bus_request(wil, 0);
+
+ set_bit(wil_status_suspended, wil->status);
+ clear_bit(wil_status_suspending, wil->status);
+
+ return rc;
+
+resume_after_fail:
+ set_bit(wil_status_resuming, wil->status);
+ clear_bit(wil_status_suspending, wil->status);
+ rc = wmi_resume(wil);
+ /* if resume succeeded, reject the suspend */
+ if (!rc) {
+ rc = -EBUSY;
+ if (test_bit(wil_status_fwconnected, wil->status))
+ wil_update_net_queues_bh(wil, NULL, false);
}
+ return rc;
+
+reject_suspend:
+ clear_bit(wil_status_suspending, wil->status);
+ if (test_bit(wil_status_fwconnected, wil->status))
+ wil_update_net_queues_bh(wil, NULL, false);
+ return -EBUSY;
+}
+
+static int wil_suspend_radio_off(struct wil6210_priv *wil)
+{
+ int rc = 0;
+ struct net_device *ndev = wil_to_ndev(wil);
+
+ wil_dbg_pm(wil, "suspend radio off\n");
/* if netif up, hardware is alive, shut it down */
if (ndev->flags & IFF_UP) {
@@ -90,7 +241,7 @@ int wil_suspend(struct wil6210_priv *wil, bool is_runtime)
wil_disable_irq(wil);
if (wil->platform_ops.suspend) {
- rc = wil->platform_ops.suspend(wil->platform_handle);
+ rc = wil->platform_ops.suspend(wil->platform_handle, false);
if (rc) {
wil_enable_irq(wil);
goto out;
@@ -100,6 +251,50 @@ int wil_suspend(struct wil6210_priv *wil, bool is_runtime)
set_bit(wil_status_suspended, wil->status);
out:
+ wil_dbg_pm(wil, "suspend radio off: %d\n", rc);
+
+ return rc;
+}
+
+static int wil_resume_radio_off(struct wil6210_priv *wil)
+{
+ int rc = 0;
+ struct net_device *ndev = wil_to_ndev(wil);
+
+ wil_dbg_pm(wil, "Enabling PCIe IRQ\n");
+ wil_enable_irq(wil);
+ /* if netif up, bring hardware up
+ * During open(), IFF_UP set after actual device method
+ * invocation. This prevent recursive call to wil_up()
+ * wil_status_suspended will be cleared in wil_reset
+ */
+ if (ndev->flags & IFF_UP)
+ rc = wil_up(wil);
+ else
+ clear_bit(wil_status_suspended, wil->status);
+
+ return rc;
+}
+
+int wil_suspend(struct wil6210_priv *wil, bool is_runtime)
+{
+ int rc = 0;
+ struct net_device *ndev = wil_to_ndev(wil);
+ bool keep_radio_on = ndev->flags & IFF_UP &&
+ wil->keep_radio_on_during_sleep;
+
+ wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system");
+
+ if (test_bit(wil_status_suspended, wil->status)) {
+ wil_dbg_pm(wil, "trying to suspend while suspended\n");
+ return 0;
+ }
+
+ if (!keep_radio_on)
+ rc = wil_suspend_radio_off(wil);
+ else
+ rc = wil_suspend_keep_radio_on(wil);
+
wil_dbg_pm(wil, "suspend: %s => %d\n",
is_runtime ? "runtime" : "system", rc);
@@ -110,29 +305,24 @@ int wil_resume(struct wil6210_priv *wil, bool is_runtime)
{
int rc = 0;
struct net_device *ndev = wil_to_ndev(wil);
+ bool keep_radio_on = ndev->flags & IFF_UP &&
+ wil->keep_radio_on_during_sleep;
wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system");
if (wil->platform_ops.resume) {
- rc = wil->platform_ops.resume(wil->platform_handle);
+ rc = wil->platform_ops.resume(wil->platform_handle,
+ keep_radio_on);
if (rc) {
wil_err(wil, "platform_ops.resume : %d\n", rc);
goto out;
}
}
- wil_dbg_pm(wil, "Enabling PCIe IRQ\n");
- wil_enable_irq(wil);
-
- /* if netif up, bring hardware up
- * During open(), IFF_UP set after actual device method
- * invocation. This prevent recursive call to wil_up().
- * wil_status_suspended will be cleared in wil_reset
- */
- if (ndev->flags & IFF_UP)
- rc = wil_up(wil);
+ if (keep_radio_on)
+ rc = wil_resume_keep_radio_on(wil);
else
- clear_bit(wil_status_suspended, wil->status);
+ rc = wil_resume_radio_off(wil);
out:
wil_dbg_pm(wil, "resume: %s => %d\n",
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index 84d91606e6f3..ec57bcce9601 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -104,6 +104,51 @@ static inline int wil_vring_avail_high(struct vring *vring)
return wil_vring_avail_tx(vring) > wil_vring_wmark_high(vring);
}
+/* returns true when all tx vrings are empty */
+bool wil_is_tx_idle(struct wil6210_priv *wil)
+{
+ int i;
+ unsigned long data_comp_to;
+
+ for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
+ struct vring *vring = &wil->vring_tx[i];
+ int vring_index = vring - wil->vring_tx;
+ struct vring_tx_data *txdata = &wil->vring_tx_data[vring_index];
+
+ spin_lock(&txdata->lock);
+
+ if (!vring->va || !txdata->enabled) {
+ spin_unlock(&txdata->lock);
+ continue;
+ }
+
+ data_comp_to = jiffies + msecs_to_jiffies(
+ WIL_DATA_COMPLETION_TO_MS);
+ if (test_bit(wil_status_napi_en, wil->status)) {
+ while (!wil_vring_is_empty(vring)) {
+ if (time_after(jiffies, data_comp_to)) {
+ wil_dbg_pm(wil,
+ "TO waiting for idle tx\n");
+ spin_unlock(&txdata->lock);
+ return false;
+ }
+ wil_dbg_ratelimited(wil,
+ "tx vring is not empty -> NAPI\n");
+ spin_unlock(&txdata->lock);
+ napi_synchronize(&wil->napi_tx);
+ msleep(20);
+ spin_lock(&txdata->lock);
+ if (!vring->va || !txdata->enabled)
+ break;
+ }
+ }
+
+ spin_unlock(&txdata->lock);
+ }
+
+ return true;
+}
+
/* wil_val_in_range - check if value in [min,max) */
static inline bool wil_val_in_range(int val, int min, int max)
{
@@ -406,6 +451,18 @@ static inline int wil_is_back_req(u8 fc)
(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK_REQ);
}
+bool wil_is_rx_idle(struct wil6210_priv *wil)
+{
+ struct vring_rx_desc *_d;
+ struct vring *vring = &wil->vring_rx;
+
+ _d = (struct vring_rx_desc *)&vring->va[vring->swhead].rx;
+ if (_d->dma.status & RX_DMA_STATUS_DU)
+ return false;
+
+ return true;
+}
+
/**
* reap 1 frame from @swhead
*
@@ -1812,6 +1869,15 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
spin_lock(&txdata->lock);
+ if (test_bit(wil_status_suspending, wil->status) ||
+ test_bit(wil_status_suspended, wil->status) ||
+ test_bit(wil_status_resuming, wil->status)) {
+ wil_dbg_txrx(wil,
+ "suspend/resume in progress. drop packet\n");
+ spin_unlock(&txdata->lock);
+ return -EINVAL;
+ }
+
rc = (skb_is_gso(skb) ? __wil_tx_vring_tso : __wil_tx_vring)
(wil, vring, skb);
@@ -1864,6 +1930,11 @@ static inline void __wil_update_net_queues(struct wil6210_priv *wil,
return;
}
+ /* Do not wake the queues in suspend flow */
+ if (test_bit(wil_status_suspending, wil->status) ||
+ test_bit(wil_status_suspended, wil->status))
+ return;
+
/* check wake */
for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
struct vring *cur_vring = &wil->vring_tx[i];
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index b00c803a1e83..d085ccfc7228 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -37,8 +37,13 @@ extern bool debug_fw;
extern bool disable_ap_sme;
#define WIL_NAME "wil6210"
-#define WIL_FW_NAME_DEFAULT "wil6210.fw" /* code Sparrow B0 */
-#define WIL_FW_NAME_SPARROW_PLUS "wil6210_sparrow_plus.fw" /* code Sparrow D0 */
+
+#define WIL_FW_NAME_DEFAULT "wil6210.fw"
+#define WIL_FW_NAME_FTM_DEFAULT "wil6210_ftm.fw"
+
+#define WIL_FW_NAME_SPARROW_PLUS "wil6210_sparrow_plus.fw"
+#define WIL_FW_NAME_FTM_SPARROW_PLUS "wil6210_sparrow_plus_ftm.fw"
+
#define WIL_BOARD_FILE_NAME "wil6210.brd" /* board & radio parameters */
#define WIL_DEFAULT_BUS_REQUEST_KBPS 128000 /* ~1Gbps */
@@ -53,7 +58,8 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1)
return (x >> b0) & ((1 << (b1 - b0 + 1)) - 1);
}
-#define WIL6210_MEM_SIZE (2*1024*1024UL)
+#define WIL6210_MIN_MEM_SIZE (2 * 1024 * 1024UL)
+#define WIL6210_MAX_MEM_SIZE (4 * 1024 * 1024UL)
#define WIL_TX_Q_LEN_DEFAULT (4000)
#define WIL_RX_RING_SIZE_ORDER_DEFAULT (10)
@@ -77,6 +83,15 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1)
*/
#define WIL_MAX_MPDU_OVERHEAD (62)
+struct wil_suspend_stats {
+ unsigned long successful_suspends;
+ unsigned long failed_suspends;
+ unsigned long successful_resumes;
+ unsigned long failed_resumes;
+ unsigned long rejected_by_device;
+ unsigned long rejected_by_host;
+};
+
/* Calculate MAC buffer size for the firmware. It includes all overhead,
* as it will go over the air, and need to be 8 byte aligned
*/
@@ -284,6 +299,8 @@ enum {
#define ISR_MISC_MBOX_EVT BIT_DMA_EP_MISC_ICR_FW_INT(1)
#define ISR_MISC_FW_ERROR BIT_DMA_EP_MISC_ICR_FW_INT(3)
+#define WIL_DATA_COMPLETION_TO_MS 200
+
/* Hardware definitions end */
struct fw_map {
u32 from; /* linker address - from, inclusive */
@@ -412,7 +429,9 @@ enum { /* for wil6210_priv.status */
wil_status_irqen, /* FIXME: interrupts enabled - for debug */
wil_status_napi_en, /* NAPI enabled protected by wil->mutex */
wil_status_resetting, /* reset in progress */
+ wil_status_suspending, /* suspend in progress */
wil_status_suspended, /* suspend completed, device is suspended */
+ wil_status_resuming, /* resume in progress */
wil_status_last /* keep last */
};
@@ -594,6 +613,7 @@ extern u8 led_polarity;
struct wil6210_priv {
struct pci_dev *pdev;
+ u32 bar_size;
struct wireless_dev *wdev;
void __iomem *csr;
DECLARE_BITMAP(status, wil_status_last);
@@ -676,9 +696,12 @@ struct wil6210_priv {
struct wil_blob_wrapper blobs[ARRAY_SIZE(fw_mapping)];
u8 discovery_mode;
u8 abft_len;
+ u8 wakeup_trigger;
+ struct wil_suspend_stats suspend_stats;
void *platform_handle;
struct wil_platform_ops platform_ops;
+ bool keep_radio_on_during_sleep;
struct pmc_ctx pmc;
@@ -701,6 +724,11 @@ struct wil6210_priv {
struct notifier_block pm_notify;
#endif /* CONFIG_PM_SLEEP */
#endif /* CONFIG_PM */
+
+ bool suspend_resp_rcvd;
+ bool suspend_resp_comp;
+ u32 bus_request_kbps;
+ u32 bus_request_kbps_pre_suspend;
};
#define wil_to_wiphy(i) (i->wdev->wiphy)
@@ -949,7 +977,6 @@ void wil6210_unmask_irq_rx(struct wil6210_priv *wil);
int wil_iftype_nl2wmi(enum nl80211_iftype type);
-int wil_ioctl(struct wil6210_priv *wil, void __user *data, int cmd);
int wil_request_firmware(struct wil6210_priv *wil, const char *name,
bool load);
bool wil_fw_verify_file_exists(struct wil6210_priv *wil, const char *name);
@@ -957,6 +984,11 @@ bool wil_fw_verify_file_exists(struct wil6210_priv *wil, const char *name);
int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime);
int wil_suspend(struct wil6210_priv *wil, bool is_runtime);
int wil_resume(struct wil6210_priv *wil, bool is_runtime);
+bool wil_is_wmi_idle(struct wil6210_priv *wil);
+int wmi_resume(struct wil6210_priv *wil);
+int wmi_suspend(struct wil6210_priv *wil);
+bool wil_is_tx_idle(struct wil6210_priv *wil);
+bool wil_is_rx_idle(struct wil6210_priv *wil);
int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size);
void wil_fw_core_dump(struct wil6210_priv *wil);
diff --git a/drivers/net/wireless/ath/wil6210/wil_platform.h b/drivers/net/wireless/ath/wil6210/wil_platform.h
index f8c41172a3f4..5d9e4bfcb045 100644
--- a/drivers/net/wireless/ath/wil6210/wil_platform.h
+++ b/drivers/net/wireless/ath/wil6210/wil_platform.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2016 Qualcomm Atheros, Inc.
+ * Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -33,10 +33,11 @@ enum wil_platform_event {
*/
struct wil_platform_ops {
int (*bus_request)(void *handle, uint32_t kbps /* KBytes/Sec */);
- int (*suspend)(void *handle);
- int (*resume)(void *handle);
+ int (*suspend)(void *handle, bool keep_device_power);
+ int (*resume)(void *handle, bool device_powered_on);
void (*uninit)(void *handle);
int (*notify)(void *handle, enum wil_platform_event evt);
+ bool (*keep_radio_on_during_sleep)(void *handle);
};
/**
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 0a5020f31de1..65ef67321fc0 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -37,6 +37,8 @@ module_param(led_id, byte, 0444);
MODULE_PARM_DESC(led_id,
" 60G device led enablement. Set the led ID (0-2) to enable");
+#define WIL_WAIT_FOR_SUSPEND_RESUME_COMP 200
+
/**
* WMI event receiving - theory of operations
*
@@ -157,7 +159,7 @@ void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_)
return NULL;
off = HOSTADDR(ptr);
- if (off > WIL6210_MEM_SIZE - 4)
+ if (off > wil->bar_size - 4)
return NULL;
return wil->csr + off;
@@ -177,7 +179,7 @@ void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr)
return NULL;
off = HOSTADDR(ptr);
- if (off > WIL6210_MEM_SIZE - 4)
+ if (off > wil->bar_size - 4)
return NULL;
return wil->csr + off;
@@ -233,6 +235,16 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
return -EAGAIN;
}
+ /* Allow sending only suspend / resume commands during susepnd flow */
+ if ((test_bit(wil_status_suspending, wil->status) ||
+ test_bit(wil_status_suspended, wil->status) ||
+ test_bit(wil_status_resuming, wil->status)) &&
+ ((cmdid != WMI_TRAFFIC_SUSPEND_CMDID) &&
+ (cmdid != WMI_TRAFFIC_RESUME_CMDID))) {
+ wil_err(wil, "WMI: reject send_command during suspend\n");
+ return -EINVAL;
+ }
+
if (!head) {
wil_err(wil, "WMI head is garbage: 0x%08x\n", r->head);
return -EINVAL;
@@ -862,6 +874,11 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
return;
}
+ if (test_bit(wil_status_suspended, wil->status)) {
+ wil_err(wil, "suspended. cannot handle WMI event\n");
+ return;
+ }
+
for (n = 0;; n++) {
u16 len;
bool q;
@@ -914,6 +931,15 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
struct wmi_cmd_hdr *wmi = &evt->event.wmi;
u16 id = le16_to_cpu(wmi->command_id);
u32 tstamp = le32_to_cpu(wmi->fw_timestamp);
+ if (test_bit(wil_status_resuming, wil->status)) {
+ if (id == WMI_TRAFFIC_RESUME_EVENTID)
+ clear_bit(wil_status_resuming,
+ wil->status);
+ else
+ wil_err(wil,
+ "WMI evt %d while resuming\n",
+ id);
+ }
spin_lock_irqsave(&wil->wmi_ev_lock, flags);
if (wil->reply_id && wil->reply_id == id) {
if (wil->reply_buf) {
@@ -921,6 +947,11 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
min(len, wil->reply_size));
immed_reply = true;
}
+ if (id == WMI_TRAFFIC_SUSPEND_EVENTID) {
+ wil_dbg_wmi(wil,
+ "set suspend_resp_rcvd\n");
+ wil->suspend_resp_rcvd = true;
+ }
}
spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
@@ -1762,6 +1793,85 @@ void wmi_event_flush(struct wil6210_priv *wil)
spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
}
+int wmi_suspend(struct wil6210_priv *wil)
+{
+ int rc;
+ struct wmi_traffic_suspend_cmd cmd = {
+ .wakeup_trigger = wil->wakeup_trigger,
+ };
+ struct {
+ struct wmi_cmd_hdr wmi;
+ struct wmi_traffic_suspend_event evt;
+ } __packed reply;
+ u32 suspend_to = WIL_WAIT_FOR_SUSPEND_RESUME_COMP;
+
+ wil->suspend_resp_rcvd = false;
+ wil->suspend_resp_comp = false;
+
+ reply.evt.status = WMI_TRAFFIC_SUSPEND_REJECTED;
+
+ rc = wmi_call(wil, WMI_TRAFFIC_SUSPEND_CMDID, &cmd, sizeof(cmd),
+ WMI_TRAFFIC_SUSPEND_EVENTID, &reply, sizeof(reply),
+ suspend_to);
+ if (rc) {
+ wil_err(wil, "wmi_call for suspend req failed, rc=%d\n", rc);
+ if (rc == -ETIME)
+ /* wmi_call TO */
+ wil->suspend_stats.rejected_by_device++;
+ else
+ wil->suspend_stats.rejected_by_host++;
+ goto out;
+ }
+
+ wil_dbg_wmi(wil, "waiting for suspend_response_completed\n");
+
+ rc = wait_event_interruptible_timeout(wil->wq,
+ wil->suspend_resp_comp,
+ msecs_to_jiffies(suspend_to));
+ if (rc == 0) {
+ wil_err(wil, "TO waiting for suspend_response_completed\n");
+ if (wil->suspend_resp_rcvd)
+ /* Device responded but we TO due to another reason */
+ wil->suspend_stats.rejected_by_host++;
+ else
+ wil->suspend_stats.rejected_by_device++;
+ rc = -EBUSY;
+ goto out;
+ }
+
+ wil_dbg_wmi(wil, "suspend_response_completed rcvd\n");
+ if (reply.evt.status == WMI_TRAFFIC_SUSPEND_REJECTED) {
+ wil_dbg_pm(wil, "device rejected the suspend\n");
+ wil->suspend_stats.rejected_by_device++;
+ }
+ rc = reply.evt.status;
+
+out:
+ wil->suspend_resp_rcvd = false;
+ wil->suspend_resp_comp = false;
+
+ return rc;
+}
+
+int wmi_resume(struct wil6210_priv *wil)
+{
+ int rc;
+ struct {
+ struct wmi_cmd_hdr wmi;
+ struct wmi_traffic_resume_event evt;
+ } __packed reply;
+
+ reply.evt.status = WMI_TRAFFIC_RESUME_FAILED;
+
+ rc = wmi_call(wil, WMI_TRAFFIC_RESUME_CMDID, NULL, 0,
+ WMI_TRAFFIC_RESUME_EVENTID, &reply, sizeof(reply),
+ WIL_WAIT_FOR_SUSPEND_RESUME_COMP);
+ if (rc)
+ return rc;
+
+ return reply.evt.status;
+}
+
static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id,
void *d, int len)
{
@@ -1851,3 +1961,36 @@ void wmi_event_worker(struct work_struct *work)
}
wil_dbg_wmi(wil, "event_worker: Finished\n");
}
+
+bool wil_is_wmi_idle(struct wil6210_priv *wil)
+{
+ ulong flags;
+ struct wil6210_mbox_ring *r = &wil->mbox_ctl.rx;
+ bool rc = false;
+
+ spin_lock_irqsave(&wil->wmi_ev_lock, flags);
+
+ /* Check if there are pending WMI events in the events queue */
+ if (!list_empty(&wil->pending_wmi_ev)) {
+ wil_dbg_pm(wil, "Pending WMI events in queue\n");
+ goto out;
+ }
+
+ /* Check if there is a pending WMI call */
+ if (wil->reply_id) {
+ wil_dbg_pm(wil, "Pending WMI call\n");
+ goto out;
+ }
+
+ /* Check if there are pending RX events in mbox */
+ r->head = wil_r(wil, RGF_MBOX +
+ offsetof(struct wil6210_mbox_ctl, rx.head));
+ if (r->tail != r->head)
+ wil_dbg_pm(wil, "Pending WMI mbox events\n");
+ else
+ rc = true;
+
+out:
+ spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
+ return rc;
+}
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h
index f7f5f4f801e3..256f63c57da0 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.h
+++ b/drivers/net/wireless/ath/wil6210/wmi.h
@@ -59,6 +59,7 @@ enum wmi_fw_capability {
WMI_FW_CAPABILITY_DISABLE_AP_SME = 4,
WMI_FW_CAPABILITY_WMI_ONLY = 5,
WMI_FW_CAPABILITY_THERMAL_THROTTLING = 7,
+ WMI_FW_CAPABILITY_D3_SUSPEND = 8,
WMI_FW_CAPABILITY_MAX,
};
@@ -157,7 +158,7 @@ enum wmi_command_id {
WMI_FLASH_READ_CMDID = 0x902,
WMI_FLASH_WRITE_CMDID = 0x903,
/* Power management */
- WMI_TRAFFIC_DEFERRAL_CMDID = 0x904,
+ WMI_TRAFFIC_SUSPEND_CMDID = 0x904,
WMI_TRAFFIC_RESUME_CMDID = 0x905,
/* P2P */
WMI_P2P_CFG_CMDID = 0x910,
@@ -500,8 +501,14 @@ struct wmi_port_delete_cmd {
u8 reserved[3];
} __packed;
-/* WMI_TRAFFIC_DEFERRAL_CMDID */
-struct wmi_traffic_deferral_cmd {
+/* WMI_TRAFFIC_SUSPEND_CMD wakeup trigger bit mask values */
+enum wmi_wakeup_trigger {
+ WMI_WAKEUP_TRIGGER_UCAST = 0x01,
+ WMI_WAKEUP_TRIGGER_BCAST = 0x02,
+};
+
+/* WMI_TRAFFIC_SUSPEND_CMDID */
+struct wmi_traffic_suspend_cmd {
/* Bit vector: bit[0] - wake on Unicast, bit[1] - wake on Broadcast */
u8 wakeup_trigger;
} __packed;
@@ -1084,7 +1091,7 @@ enum wmi_event_id {
WMI_FLASH_READ_DONE_EVENTID = 0x1902,
WMI_FLASH_WRITE_DONE_EVENTID = 0x1903,
/* Power management */
- WMI_TRAFFIC_DEFERRAL_EVENTID = 0x1904,
+ WMI_TRAFFIC_SUSPEND_EVENTID = 0x1904,
WMI_TRAFFIC_RESUME_EVENTID = 0x1905,
/* P2P */
WMI_P2P_CFG_DONE_EVENTID = 0x1910,
@@ -1926,14 +1933,14 @@ struct wmi_link_maintain_cfg_read_done_event {
struct wmi_link_maintain_cfg lm_cfg;
} __packed;
-enum wmi_traffic_deferral_status {
- WMI_TRAFFIC_DEFERRAL_APPROVED = 0x0,
- WMI_TRAFFIC_DEFERRAL_REJECTED = 0x1,
+enum wmi_traffic_suspend_status {
+ WMI_TRAFFIC_SUSPEND_APPROVED = 0x0,
+ WMI_TRAFFIC_SUSPEND_REJECTED = 0x1,
};
-/* WMI_TRAFFIC_DEFERRAL_EVENTID */
-struct wmi_traffic_deferral_event {
- /* enum wmi_traffic_deferral_status_e */
+/* WMI_TRAFFIC_SUSPEND_EVENTID */
+struct wmi_traffic_suspend_event {
+ /* enum wmi_traffic_suspend_status_e */
u8 status;
} __packed;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index 9b970dc2b922..984c1d0560b1 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -108,12 +108,14 @@ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev)
int ret = 0;
u8 data;
u32 addr, gpiocontrol;
- unsigned long flags;
pdata = &sdiodev->settings->bus.sdio;
if (pdata->oob_irq_supported) {
brcmf_dbg(SDIO, "Enter, register OOB IRQ %d\n",
pdata->oob_irq_nr);
+ spin_lock_init(&sdiodev->irq_en_lock);
+ sdiodev->irq_en = true;
+
ret = request_irq(pdata->oob_irq_nr, brcmf_sdiod_oob_irqhandler,
pdata->oob_irq_flags, "brcmf_oob_intr",
&sdiodev->func[1]->dev);
@@ -122,10 +124,6 @@ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev)
return ret;
}
sdiodev->oob_irq_requested = true;
- spin_lock_init(&sdiodev->irq_en_lock);
- spin_lock_irqsave(&sdiodev->irq_en_lock, flags);
- sdiodev->irq_en = true;
- spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags);
ret = enable_irq_wake(pdata->oob_irq_nr);
if (ret != 0) {
@@ -706,7 +704,7 @@ done:
int brcmf_sdiod_recv_chain(struct brcmf_sdio_dev *sdiodev,
struct sk_buff_head *pktq, uint totlen)
{
- struct sk_buff *glom_skb;
+ struct sk_buff *glom_skb = NULL;
struct sk_buff *skb;
u32 addr = sdiodev->sbwad;
int err = 0;
@@ -727,10 +725,8 @@ int brcmf_sdiod_recv_chain(struct brcmf_sdio_dev *sdiodev,
return -ENOMEM;
err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr,
glom_skb);
- if (err) {
- brcmu_pkt_buf_free_skb(glom_skb);
+ if (err)
goto done;
- }
skb_queue_walk(pktq, skb) {
memcpy(skb->data, glom_skb->data, skb->len);
@@ -741,6 +737,7 @@ int brcmf_sdiod_recv_chain(struct brcmf_sdio_dev *sdiodev,
pktq);
done:
+ brcmu_pkt_buf_free_skb(glom_skb);
return err;
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index b8f042146fc9..2443c71a202f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -719,6 +719,8 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
{
struct brcmf_scan_params_le params_le;
struct cfg80211_scan_request *scan_request;
+ u64 reqid;
+ u32 bucket;
s32 err = 0;
brcmf_dbg(SCAN, "Enter\n");
@@ -749,7 +751,7 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
&params_le, sizeof(params_le));
if (err)
- brcmf_err("Scan abort failed\n");
+ brcmf_err("Scan abort failed\n");
}
brcmf_scan_config_mpc(ifp, 1);
@@ -758,11 +760,21 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
* e-scan can be initiated internally
* which takes precedence.
*/
- if (cfg->internal_escan) {
- brcmf_dbg(SCAN, "scheduled scan completed\n");
- cfg->internal_escan = false;
- if (!aborted)
- cfg80211_sched_scan_results(cfg_to_wiphy(cfg), 0);
+ if (cfg->int_escan_map) {
+ brcmf_dbg(SCAN, "scheduled scan completed (%x)\n",
+ cfg->int_escan_map);
+ while (cfg->int_escan_map) {
+ bucket = __ffs(cfg->int_escan_map);
+ cfg->int_escan_map &= ~BIT(bucket);
+ reqid = brcmf_pno_find_reqid_by_bucket(cfg->pno,
+ bucket);
+ if (!aborted) {
+ brcmf_dbg(SCAN, "report results: reqid=%llu\n",
+ reqid);
+ cfg80211_sched_scan_results(cfg_to_wiphy(cfg),
+ reqid);
+ }
+ }
} else if (scan_request) {
struct cfg80211_scan_info info = {
.aborted = aborted,
@@ -1011,7 +1023,7 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg,
if (!ssid_le.SSID_len)
brcmf_dbg(SCAN, "%d: Broadcast scan\n", i);
else
- brcmf_dbg(SCAN, "%d: scan for %s size =%d\n",
+ brcmf_dbg(SCAN, "%d: scan for %.32s size=%d\n",
i, ssid_le.SSID, ssid_le.SSID_len);
memcpy(ptr, &ssid_le, sizeof(ssid_le));
ptr += sizeof(ssid_le);
@@ -3011,7 +3023,7 @@ void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg)
struct escan_info *escan = &cfg->escan_info;
set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);
- if (cfg->internal_escan || cfg->scan_request) {
+ if (cfg->int_escan_map || cfg->scan_request) {
escan->escan_state = WL_ESCAN_STATE_IDLE;
brcmf_notify_escan_complete(cfg, escan->ifp, true, true);
}
@@ -3034,7 +3046,7 @@ static void brcmf_escan_timeout(unsigned long data)
struct brcmf_cfg80211_info *cfg =
(struct brcmf_cfg80211_info *)data;
- if (cfg->internal_escan || cfg->scan_request) {
+ if (cfg->int_escan_map || cfg->scan_request) {
brcmf_err("timer expired\n");
schedule_work(&cfg->escan_timeout_work);
}
@@ -3120,7 +3132,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
if (brcmf_p2p_scan_finding_common_channel(cfg, bss_info_le))
goto exit;
- if (!cfg->internal_escan && !cfg->scan_request) {
+ if (!cfg->int_escan_map && !cfg->scan_request) {
brcmf_dbg(SCAN, "result without cfg80211 request\n");
goto exit;
}
@@ -3166,7 +3178,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
if (brcmf_p2p_scan_finding_common_channel(cfg, NULL))
goto exit;
- if (cfg->internal_escan || cfg->scan_request) {
+ if (cfg->int_escan_map || cfg->scan_request) {
brcmf_inform_bss(cfg);
aborted = status != BRCMF_E_STATUS_SUCCESS;
brcmf_notify_escan_complete(cfg, ifp, aborted, false);
@@ -3248,17 +3260,21 @@ static int brcmf_internal_escan_add_info(struct cfg80211_scan_request *req,
return 0;
}
-static int brcmf_start_internal_escan(struct brcmf_if *ifp,
+static int brcmf_start_internal_escan(struct brcmf_if *ifp, u32 fwmap,
struct cfg80211_scan_request *request)
{
struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
int err;
if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
+ if (cfg->int_escan_map)
+ brcmf_dbg(SCAN, "aborting internal scan: map=%u\n",
+ cfg->int_escan_map);
/* Abort any on-going scan */
brcmf_abort_scanning(cfg);
}
+ brcmf_dbg(SCAN, "start internal scan: map=%u\n", fwmap);
set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
cfg->escan_info.run = brcmf_run_escan;
err = brcmf_do_escan(ifp, request);
@@ -3266,7 +3282,7 @@ static int brcmf_start_internal_escan(struct brcmf_if *ifp,
clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
return err;
}
- cfg->internal_escan = true;
+ cfg->int_escan_map = fwmap;
return 0;
}
@@ -3308,6 +3324,7 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
struct wiphy *wiphy = cfg_to_wiphy(cfg);
int i, err = 0;
struct brcmf_pno_scanresults_le *pfn_result;
+ u32 bucket_map;
u32 result_count;
u32 status;
u32 datalen;
@@ -3352,6 +3369,7 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
goto out_err;
}
+ bucket_map = 0;
for (i = 0; i < result_count; i++) {
netinfo = &netinfo_start[i];
@@ -3359,6 +3377,7 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
netinfo->SSID_len = IEEE80211_MAX_SSID_LEN;
brcmf_dbg(SCAN, "SSID:%.32s Channel:%d\n",
netinfo->SSID, netinfo->channel);
+ bucket_map |= brcmf_pno_get_bucket_map(cfg->pno, netinfo);
err = brcmf_internal_escan_add_info(request,
netinfo->SSID,
netinfo->SSID_len,
@@ -3367,7 +3386,10 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
goto out_err;
}
- err = brcmf_start_internal_escan(ifp, request);
+ if (!bucket_map)
+ goto free_req;
+
+ err = brcmf_start_internal_escan(ifp, bucket_map, request);
if (!err)
goto free_req;
@@ -3386,11 +3408,11 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
- brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n",
+ brcmf_dbg(SCAN, "Enter: n_match_sets=%d n_ssids=%d\n",
req->n_match_sets, req->n_ssids);
if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) {
- brcmf_err("Scanning suppressed: status (%lu)\n",
+ brcmf_err("Scanning suppressed: status=%lu\n",
cfg->scan_status);
return -EAGAIN;
}
@@ -3411,8 +3433,8 @@ static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,
struct brcmf_if *ifp = netdev_priv(ndev);
brcmf_dbg(SCAN, "enter\n");
- brcmf_pno_clean(ifp);
- if (cfg->internal_escan)
+ brcmf_pno_stop_sched_scan(ifp, reqid);
+ if (cfg->int_escan_map)
brcmf_notify_escan_complete(cfg, ifp, true, true);
return 0;
}
@@ -6755,7 +6777,7 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy,
/* ignore non-ISO3166 country codes */
for (i = 0; i < sizeof(req->alpha2); i++)
if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') {
- brcmf_err("not a ISO3166 code (0x%02x 0x%02x)\n",
+ brcmf_err("not an ISO3166 code (0x%02x 0x%02x)\n",
req->alpha2[0], req->alpha2[1]);
return;
}
@@ -6940,6 +6962,13 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
brcmf_p2p_detach(&cfg->p2p);
goto wiphy_unreg_out;
}
+ err = brcmf_pno_attach(cfg);
+ if (err) {
+ brcmf_err("PNO initialisation failed (%d)\n", err);
+ brcmf_btcoex_detach(cfg);
+ brcmf_p2p_detach(&cfg->p2p);
+ goto wiphy_unreg_out;
+ }
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_TDLS)) {
err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1);
@@ -6972,6 +7001,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
return cfg;
detach:
+ brcmf_pno_detach(cfg);
brcmf_btcoex_detach(cfg);
brcmf_p2p_detach(&cfg->p2p);
wiphy_unreg_out:
@@ -6991,6 +7021,7 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
if (!cfg)
return;
+ brcmf_pno_detach(cfg);
brcmf_btcoex_detach(cfg);
wiphy_unregister(cfg->wiphy);
kfree(cfg->ops);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
index a1c2e0af1774..12ff15446c6c 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
@@ -273,7 +273,7 @@ struct brcmf_cfg80211_wowl {
* @pub: common driver information.
* @channel: current channel.
* @active_scan: current scan mode.
- * @internal_escan: indicates internally initiated e-scan is running.
+ * @int_escan_map: bucket map for which internal e-scan is done.
* @ibss_starter: indicates this sta is ibss starter.
* @pwr_save: indicate whether dongle to support power save mode.
* @dongle_up: indicate whether dongle up or not.
@@ -289,6 +289,7 @@ struct brcmf_cfg80211_wowl {
* @vif_cnt: number of vif instances.
* @vif_event: vif event signalling.
* @wowl: wowl related information.
+ * @pno: information of pno module.
*/
struct brcmf_cfg80211_info {
struct wiphy *wiphy;
@@ -305,7 +306,7 @@ struct brcmf_cfg80211_info {
struct brcmf_pub *pub;
u32 channel;
bool active_scan;
- bool internal_escan;
+ u32 int_escan_map;
bool ibss_starter;
bool pwr_save;
bool dongle_up;
@@ -322,6 +323,7 @@ struct brcmf_cfg80211_info {
struct brcmu_d11inf d11inf;
struct brcmf_assoclist_le assoclist;
struct brcmf_cfg80211_wowl wowl;
+ struct brcmf_pno_info *pno;
};
/**
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index 511d190c6cca..c60b897e479a 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -30,6 +30,7 @@
#include "debug.h"
#include "fwil_types.h"
#include "p2p.h"
+#include "pno.h"
#include "cfg80211.h"
#include "fwil.h"
#include "feature.h"
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
index fe264a5798f1..35919d9e8e13 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
@@ -78,6 +78,7 @@ do { \
#define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL)
#define BRCMF_FIL_ON() (brcmf_msg_level & BRCMF_FIL_VAL)
#define BRCMF_FWCON_ON() (brcmf_msg_level & BRCMF_FWCON_VAL)
+#define BRCMF_SCAN_ON() (brcmf_msg_level & BRCMF_SCAN_VAL)
#else /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */
@@ -96,6 +97,7 @@ do { \
#define BRCMF_EVENT_ON() 0
#define BRCMF_FIL_ON() 0
#define BRCMF_FWCON_ON() 0
+#define BRCMF_SCAN_ON() 0
#endif /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
index 8c18fad3edc9..b857d539b9ac 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
@@ -806,6 +806,17 @@ struct brcmf_pno_macaddr_le {
};
/**
+ * struct brcmf_pno_bssid_le - bssid configuration for PNO scan.
+ *
+ * @bssid: BSS network identifier.
+ * @flags: flags for this BSSID.
+ */
+struct brcmf_pno_bssid_le {
+ u8 bssid[ETH_ALEN];
+ __le16 flags;
+};
+
+/**
* struct brcmf_pktcnt_le - packet counters.
*
* @rx_good_pkt: packets (MSDUs & MMPDUs) received from this station
@@ -835,15 +846,18 @@ struct brcmf_gtk_keyinfo_le {
u8 replay_counter[BRCMF_RSN_REPLAY_LEN];
};
+#define BRCMF_PNO_REPORT_NO_BATCH BIT(2)
+
/**
* struct brcmf_gscan_bucket_config - configuration data for channel bucket.
*
- * @bucket_end_index: !unknown!
- * @bucket_freq_multiple: !unknown!
- * @flag: !unknown!
- * @reserved: !unknown!
- * @repeat: !unknown!
- * @max_freq_multiple: !unknown!
+ * @bucket_end_index: last channel index in @channel_list in
+ * @struct brcmf_pno_config_le.
+ * @bucket_freq_multiple: scan interval expressed in N * @scan_freq.
+ * @flag: channel bucket report flags.
+ * @reserved: for future use.
+ * @repeat: number of scan at interval for exponential scan.
+ * @max_freq_multiple: maximum scan interval for exponential scan.
*/
struct brcmf_gscan_bucket_config {
u8 bucket_end_index;
@@ -855,16 +869,19 @@ struct brcmf_gscan_bucket_config {
};
/* version supported which must match firmware */
-#define BRCMF_GSCAN_CFG_VERSION 1
+#define BRCMF_GSCAN_CFG_VERSION 2
/**
* enum brcmf_gscan_cfg_flags - bit values for gscan flags.
*
* @BRCMF_GSCAN_CFG_FLAGS_ALL_RESULTS: send probe responses/beacons to host.
+ * @BRCMF_GSCAN_CFG_ALL_BUCKETS_IN_1ST_SCAN: all buckets will be included in
+ * first scan cycle.
* @BRCMF_GSCAN_CFG_FLAGS_CHANGE_ONLY: indicated only flags member is changed.
*/
enum brcmf_gscan_cfg_flags {
BRCMF_GSCAN_CFG_FLAGS_ALL_RESULTS = BIT(0),
+ BRCMF_GSCAN_CFG_ALL_BUCKETS_IN_1ST_SCAN = BIT(3),
BRCMF_GSCAN_CFG_FLAGS_CHANGE_ONLY = BIT(7),
};
@@ -884,12 +901,12 @@ enum brcmf_gscan_cfg_flags {
*/
struct brcmf_gscan_config {
__le16 version;
- u8 flags;
- u8 buffer_threshold;
- u8 swc_nbssid_threshold;
- u8 swc_rssi_window_size;
- u8 count_of_channel_buckets;
- u8 retry_threshold;
+ u8 flags;
+ u8 buffer_threshold;
+ u8 swc_nbssid_threshold;
+ u8 swc_rssi_window_size;
+ u8 count_of_channel_buckets;
+ u8 retry_threshold;
__le16 lost_ap_window;
struct brcmf_gscan_bucket_config bucket[1];
};
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
index a473445ed7c4..ffa243e2e2d0 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
@@ -14,6 +14,7 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/netdevice.h>
+#include <linux/gcd.h>
#include <net/cfg80211.h>
#include "core.h"
@@ -35,6 +36,67 @@
#define BRCMF_PNO_HIDDEN_BIT 2
#define BRCMF_PNO_SCHED_SCAN_PERIOD 30
+#define BRCMF_PNO_MAX_BUCKETS 16
+#define GSCAN_BATCH_NO_THR_SET 101
+#define GSCAN_RETRY_THRESHOLD 3
+
+struct brcmf_pno_info {
+ int n_reqs;
+ struct cfg80211_sched_scan_request *reqs[BRCMF_PNO_MAX_BUCKETS];
+ struct mutex req_lock;
+};
+
+#define ifp_to_pno(_ifp) ((_ifp)->drvr->config->pno)
+
+static int brcmf_pno_store_request(struct brcmf_pno_info *pi,
+ struct cfg80211_sched_scan_request *req)
+{
+ if (WARN(pi->n_reqs == BRCMF_PNO_MAX_BUCKETS,
+ "pno request storage full\n"))
+ return -ENOSPC;
+
+ brcmf_dbg(SCAN, "reqid=%llu\n", req->reqid);
+ mutex_lock(&pi->req_lock);
+ pi->reqs[pi->n_reqs++] = req;
+ mutex_unlock(&pi->req_lock);
+ return 0;
+}
+
+static int brcmf_pno_remove_request(struct brcmf_pno_info *pi, u64 reqid)
+{
+ int i, err = 0;
+
+ mutex_lock(&pi->req_lock);
+
+ /* find request */
+ for (i = 0; i < pi->n_reqs; i++) {
+ if (pi->reqs[i]->reqid == reqid)
+ break;
+ }
+ /* request not found */
+ if (WARN(i == pi->n_reqs, "reqid not found\n")) {
+ err = -ENOENT;
+ goto done;
+ }
+
+ brcmf_dbg(SCAN, "reqid=%llu\n", reqid);
+ pi->n_reqs--;
+
+ /* if last we are done */
+ if (!pi->n_reqs || i == pi->n_reqs)
+ goto done;
+
+ /* fill the gap with remaining requests */
+ while (i <= pi->n_reqs - 1) {
+ pi->reqs[i] = pi->reqs[i + 1];
+ i++;
+ }
+
+done:
+ mutex_unlock(&pi->req_lock);
+ return err;
+}
+
static int brcmf_pno_channel_config(struct brcmf_if *ifp,
struct brcmf_pno_config_le *cfg)
{
@@ -57,16 +119,11 @@ static int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq,
/* set extra pno params */
flags = BIT(BRCMF_PNO_IMMEDIATE_SCAN_BIT) |
- BIT(BRCMF_PNO_REPORT_SEPARATELY_BIT) |
BIT(BRCMF_PNO_ENABLE_ADAPTSCAN_BIT);
pfn_param.repeat = BRCMF_PNO_REPEAT;
pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX;
/* set up pno scan fr */
- if (scan_freq < BRCMF_PNO_SCHED_SCAN_MIN_PERIOD) {
- brcmf_dbg(SCAN, "scan period too small, using minimum\n");
- scan_freq = BRCMF_PNO_SCHED_SCAN_MIN_PERIOD;
- }
pfn_param.scan_freq = cpu_to_le32(scan_freq);
if (mscan) {
@@ -101,12 +158,24 @@ exit:
return err;
}
-static int brcmf_pno_set_random(struct brcmf_if *ifp, u8 *mac_addr,
- u8 *mac_mask)
+static int brcmf_pno_set_random(struct brcmf_if *ifp, struct brcmf_pno_info *pi)
{
struct brcmf_pno_macaddr_le pfn_mac;
+ u8 *mac_addr = NULL;
+ u8 *mac_mask = NULL;
int err, i;
+ for (i = 0; i < pi->n_reqs; i++)
+ if (pi->reqs[i]->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
+ mac_addr = pi->reqs[i]->mac_addr;
+ mac_mask = pi->reqs[i]->mac_addr_mask;
+ break;
+ }
+
+ /* no random mac requested */
+ if (!mac_addr)
+ return 0;
+
pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER;
pfn_mac.flags = BRCMF_PFN_MAC_OUI_ONLY | BRCMF_PFN_SET_MAC_UNASSOC;
@@ -120,6 +189,8 @@ static int brcmf_pno_set_random(struct brcmf_if *ifp, u8 *mac_addr,
/* Set locally administered */
pfn_mac.mac[0] |= 0x02;
+ brcmf_dbg(SCAN, "enabling random mac: reqid=%llu mac=%pM\n",
+ pi->reqs[i]->reqid, pfn_mac.mac);
err = brcmf_fil_iovar_data_set(ifp, "pfn_macaddr", &pfn_mac,
sizeof(pfn_mac));
if (err)
@@ -132,6 +203,7 @@ static int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid,
bool active)
{
struct brcmf_pno_net_param_le pfn;
+ int err;
pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN);
pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY);
@@ -142,7 +214,28 @@ static int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid,
pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT);
pfn.ssid.SSID_len = cpu_to_le32(ssid->ssid_len);
memcpy(pfn.ssid.SSID, ssid->ssid, ssid->ssid_len);
- return brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn, sizeof(pfn));
+
+ brcmf_dbg(SCAN, "adding ssid=%.32s (active=%d)\n", ssid->ssid, active);
+ err = brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn, sizeof(pfn));
+ if (err < 0)
+ brcmf_err("adding failed: err=%d\n", err);
+ return err;
+}
+
+static int brcmf_pno_add_bssid(struct brcmf_if *ifp, const u8 *bssid)
+{
+ struct brcmf_pno_bssid_le bssid_cfg;
+ int err;
+
+ memcpy(bssid_cfg.bssid, bssid, ETH_ALEN);
+ bssid_cfg.flags = 0;
+
+ brcmf_dbg(SCAN, "adding bssid=%pM\n", bssid);
+ err = brcmf_fil_iovar_data_set(ifp, "pfn_add_bssid", &bssid_cfg,
+ sizeof(bssid_cfg));
+ if (err < 0)
+ brcmf_err("adding failed: err=%d\n", err);
+ return err;
}
static bool brcmf_is_ssid_active(struct cfg80211_ssid *ssid,
@@ -163,7 +256,7 @@ static bool brcmf_is_ssid_active(struct cfg80211_ssid *ssid,
return false;
}
-int brcmf_pno_clean(struct brcmf_if *ifp)
+static int brcmf_pno_clean(struct brcmf_if *ifp)
{
int ret;
@@ -179,73 +272,320 @@ int brcmf_pno_clean(struct brcmf_if *ifp)
return ret;
}
-int brcmf_pno_start_sched_scan(struct brcmf_if *ifp,
- struct cfg80211_sched_scan_request *req)
+static int brcmf_pno_get_bucket_channels(struct cfg80211_sched_scan_request *r,
+ struct brcmf_pno_config_le *pno_cfg)
{
- struct brcmf_pno_config_le pno_cfg;
- struct cfg80211_ssid *ssid;
+ u32 n_chan = le32_to_cpu(pno_cfg->channel_num);
u16 chan;
- int i, ret;
+ int i, err = 0;
- /* clean up everything */
- ret = brcmf_pno_clean(ifp);
- if (ret < 0) {
- brcmf_err("failed error=%d\n", ret);
- return ret;
+ for (i = 0; i < r->n_channels; i++) {
+ if (n_chan >= BRCMF_NUMCHANNELS) {
+ err = -ENOSPC;
+ goto done;
+ }
+ chan = r->channels[i]->hw_value;
+ brcmf_dbg(SCAN, "[%d] Chan : %u\n", n_chan, chan);
+ pno_cfg->channel_list[n_chan++] = cpu_to_le16(chan);
}
+ /* return number of channels */
+ err = n_chan;
+done:
+ pno_cfg->channel_num = cpu_to_le32(n_chan);
+ return err;
+}
- /* configure pno */
- ret = brcmf_pno_config(ifp, req->scan_plans[0].interval, 0, 0);
- if (ret < 0)
- return ret;
-
- /* configure random mac */
- if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
- ret = brcmf_pno_set_random(ifp, req->mac_addr,
- req->mac_addr_mask);
- if (ret < 0)
- return ret;
+static int brcmf_pno_prep_fwconfig(struct brcmf_pno_info *pi,
+ struct brcmf_pno_config_le *pno_cfg,
+ struct brcmf_gscan_bucket_config **buckets,
+ u32 *scan_freq)
+{
+ struct cfg80211_sched_scan_request *sr;
+ struct brcmf_gscan_bucket_config *fw_buckets;
+ int i, err, chidx;
+
+ brcmf_dbg(SCAN, "n_reqs=%d\n", pi->n_reqs);
+ if (WARN_ON(!pi->n_reqs))
+ return -ENODATA;
+
+ /*
+ * actual scan period is determined using gcd() for each
+ * scheduled scan period.
+ */
+ *scan_freq = pi->reqs[0]->scan_plans[0].interval;
+ for (i = 1; i < pi->n_reqs; i++) {
+ sr = pi->reqs[i];
+ *scan_freq = gcd(sr->scan_plans[0].interval, *scan_freq);
+ }
+ if (*scan_freq < BRCMF_PNO_SCHED_SCAN_MIN_PERIOD) {
+ brcmf_dbg(SCAN, "scan period too small, using minimum\n");
+ *scan_freq = BRCMF_PNO_SCHED_SCAN_MIN_PERIOD;
}
- /* configure channels to use */
- for (i = 0; i < req->n_channels; i++) {
- chan = req->channels[i]->hw_value;
- pno_cfg.channel_list[i] = cpu_to_le16(chan);
+ *buckets = NULL;
+ fw_buckets = kcalloc(pi->n_reqs, sizeof(*fw_buckets), GFP_KERNEL);
+ if (!fw_buckets)
+ return -ENOMEM;
+
+ memset(pno_cfg, 0, sizeof(*pno_cfg));
+ for (i = 0; i < pi->n_reqs; i++) {
+ sr = pi->reqs[i];
+ chidx = brcmf_pno_get_bucket_channels(sr, pno_cfg);
+ if (chidx < 0) {
+ err = chidx;
+ goto fail;
+ }
+ fw_buckets[i].bucket_end_index = chidx - 1;
+ fw_buckets[i].bucket_freq_multiple =
+ sr->scan_plans[0].interval / *scan_freq;
+ /* assure period is non-zero */
+ if (!fw_buckets[i].bucket_freq_multiple)
+ fw_buckets[i].bucket_freq_multiple = 1;
+ fw_buckets[i].flag = BRCMF_PNO_REPORT_NO_BATCH;
}
- if (req->n_channels) {
- pno_cfg.channel_num = cpu_to_le32(req->n_channels);
- brcmf_pno_channel_config(ifp, &pno_cfg);
+
+ if (BRCMF_SCAN_ON()) {
+ brcmf_err("base period=%u\n", *scan_freq);
+ for (i = 0; i < pi->n_reqs; i++) {
+ brcmf_err("[%d] period %u max %u repeat %u flag %x idx %u\n",
+ i, fw_buckets[i].bucket_freq_multiple,
+ le16_to_cpu(fw_buckets[i].max_freq_multiple),
+ fw_buckets[i].repeat, fw_buckets[i].flag,
+ fw_buckets[i].bucket_end_index);
+ }
}
+ *buckets = fw_buckets;
+ return pi->n_reqs;
- /* configure each match set */
- for (i = 0; i < req->n_match_sets; i++) {
- ssid = &req->match_sets[i].ssid;
- if (!ssid->ssid_len) {
- brcmf_err("skip broadcast ssid\n");
- continue;
+fail:
+ kfree(fw_buckets);
+ return err;
+}
+
+static int brcmf_pno_config_networks(struct brcmf_if *ifp,
+ struct brcmf_pno_info *pi)
+{
+ struct cfg80211_sched_scan_request *r;
+ struct cfg80211_match_set *ms;
+ bool active;
+ int i, j, err = 0;
+
+ for (i = 0; i < pi->n_reqs; i++) {
+ r = pi->reqs[i];
+
+ for (j = 0; j < r->n_match_sets; j++) {
+ ms = &r->match_sets[j];
+ if (ms->ssid.ssid_len) {
+ active = brcmf_is_ssid_active(&ms->ssid, r);
+ err = brcmf_pno_add_ssid(ifp, &ms->ssid,
+ active);
+ }
+ if (!err && is_valid_ether_addr(ms->bssid))
+ err = brcmf_pno_add_bssid(ifp, ms->bssid);
+
+ if (err < 0)
+ return err;
}
+ }
+ return 0;
+}
- ret = brcmf_pno_add_ssid(ifp, ssid,
- brcmf_is_ssid_active(ssid, req));
- if (ret < 0)
- brcmf_dbg(SCAN, ">>> PNO filter %s for ssid (%s)\n",
- ret == 0 ? "set" : "failed", ssid->ssid);
+static int brcmf_pno_config_sched_scans(struct brcmf_if *ifp)
+{
+ struct brcmf_pno_info *pi;
+ struct brcmf_gscan_config *gscan_cfg;
+ struct brcmf_gscan_bucket_config *buckets;
+ struct brcmf_pno_config_le pno_cfg;
+ size_t gsz;
+ u32 scan_freq;
+ int err, n_buckets;
+
+ pi = ifp_to_pno(ifp);
+ n_buckets = brcmf_pno_prep_fwconfig(pi, &pno_cfg, &buckets,
+ &scan_freq);
+ if (n_buckets < 0)
+ return n_buckets;
+
+ gsz = sizeof(*gscan_cfg) + (n_buckets - 1) * sizeof(*buckets);
+ gscan_cfg = kzalloc(gsz, GFP_KERNEL);
+ if (!gscan_cfg) {
+ err = -ENOMEM;
+ goto free_buckets;
}
+
+ /* clean up everything */
+ err = brcmf_pno_clean(ifp);
+ if (err < 0) {
+ brcmf_err("failed error=%d\n", err);
+ goto free_gscan;
+ }
+
+ /* configure pno */
+ err = brcmf_pno_config(ifp, scan_freq, 0, 0);
+ if (err < 0)
+ goto free_gscan;
+
+ err = brcmf_pno_channel_config(ifp, &pno_cfg);
+ if (err < 0)
+ goto clean;
+
+ gscan_cfg->version = cpu_to_le16(BRCMF_GSCAN_CFG_VERSION);
+ gscan_cfg->retry_threshold = GSCAN_RETRY_THRESHOLD;
+ gscan_cfg->buffer_threshold = GSCAN_BATCH_NO_THR_SET;
+ gscan_cfg->flags = BRCMF_GSCAN_CFG_ALL_BUCKETS_IN_1ST_SCAN;
+
+ gscan_cfg->count_of_channel_buckets = n_buckets;
+ memcpy(&gscan_cfg->bucket[0], buckets,
+ n_buckets * sizeof(*buckets));
+
+ err = brcmf_fil_iovar_data_set(ifp, "pfn_gscan_cfg", gscan_cfg, gsz);
+
+ if (err < 0)
+ goto clean;
+
+ /* configure random mac */
+ err = brcmf_pno_set_random(ifp, pi);
+ if (err < 0)
+ goto clean;
+
+ err = brcmf_pno_config_networks(ifp, pi);
+ if (err < 0)
+ goto clean;
+
/* Enable the PNO */
- ret = brcmf_fil_iovar_int_set(ifp, "pfn", 1);
+ err = brcmf_fil_iovar_int_set(ifp, "pfn", 1);
+
+clean:
+ if (err < 0)
+ brcmf_pno_clean(ifp);
+free_gscan:
+ kfree(gscan_cfg);
+free_buckets:
+ kfree(buckets);
+ return err;
+}
+
+int brcmf_pno_start_sched_scan(struct brcmf_if *ifp,
+ struct cfg80211_sched_scan_request *req)
+{
+ struct brcmf_pno_info *pi;
+ int ret;
+
+ brcmf_dbg(TRACE, "reqid=%llu\n", req->reqid);
+
+ pi = ifp_to_pno(ifp);
+ ret = brcmf_pno_store_request(pi, req);
if (ret < 0)
- brcmf_err("PNO enable failed!! ret=%d\n", ret);
+ return ret;
- return ret;
+ ret = brcmf_pno_config_sched_scans(ifp);
+ if (ret < 0) {
+ brcmf_pno_remove_request(pi, req->reqid);
+ if (pi->n_reqs)
+ (void)brcmf_pno_config_sched_scans(ifp);
+ return ret;
+ }
+ return 0;
+}
+
+int brcmf_pno_stop_sched_scan(struct brcmf_if *ifp, u64 reqid)
+{
+ struct brcmf_pno_info *pi;
+ int err;
+
+ brcmf_dbg(TRACE, "reqid=%llu\n", reqid);
+
+ pi = ifp_to_pno(ifp);
+ err = brcmf_pno_remove_request(pi, reqid);
+ if (err)
+ return err;
+
+ brcmf_pno_clean(ifp);
+
+ if (pi->n_reqs)
+ (void)brcmf_pno_config_sched_scans(ifp);
+
+ return 0;
+}
+
+int brcmf_pno_attach(struct brcmf_cfg80211_info *cfg)
+{
+ struct brcmf_pno_info *pi;
+
+ brcmf_dbg(TRACE, "enter\n");
+ pi = kzalloc(sizeof(*pi), GFP_KERNEL);
+ if (!pi)
+ return -ENOMEM;
+
+ cfg->pno = pi;
+ mutex_init(&pi->req_lock);
+ return 0;
+}
+
+void brcmf_pno_detach(struct brcmf_cfg80211_info *cfg)
+{
+ struct brcmf_pno_info *pi;
+
+ brcmf_dbg(TRACE, "enter\n");
+ pi = cfg->pno;
+ cfg->pno = NULL;
+
+ WARN_ON(pi->n_reqs);
+ mutex_destroy(&pi->req_lock);
+ kfree(pi);
}
void brcmf_pno_wiphy_params(struct wiphy *wiphy, bool gscan)
{
/* scheduled scan settings */
- wiphy->max_sched_scan_reqs = gscan ? 2 : 1;
+ wiphy->max_sched_scan_reqs = gscan ? BRCMF_PNO_MAX_BUCKETS : 1;
wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
wiphy->max_sched_scan_plan_interval = BRCMF_PNO_SCHED_SCAN_MAX_PERIOD;
}
+u64 brcmf_pno_find_reqid_by_bucket(struct brcmf_pno_info *pi, u32 bucket)
+{
+ u64 reqid = 0;
+
+ mutex_lock(&pi->req_lock);
+
+ if (bucket < pi->n_reqs)
+ reqid = pi->reqs[bucket]->reqid;
+
+ mutex_unlock(&pi->req_lock);
+ return reqid;
+}
+
+u32 brcmf_pno_get_bucket_map(struct brcmf_pno_info *pi,
+ struct brcmf_pno_net_info_le *ni)
+{
+ struct cfg80211_sched_scan_request *req;
+ struct cfg80211_match_set *ms;
+ u32 bucket_map = 0;
+ int i, j;
+
+ mutex_lock(&pi->req_lock);
+ for (i = 0; i < pi->n_reqs; i++) {
+ req = pi->reqs[i];
+
+ if (!req->n_match_sets)
+ continue;
+ for (j = 0; j < req->n_match_sets; j++) {
+ ms = &req->match_sets[j];
+ if (ms->ssid.ssid_len == ni->SSID_len &&
+ !memcmp(ms->ssid.ssid, ni->SSID, ni->SSID_len)) {
+ bucket_map |= BIT(i);
+ break;
+ }
+ if (is_valid_ether_addr(ms->bssid) &&
+ !memcmp(ms->bssid, ni->bssid, ETH_ALEN)) {
+ bucket_map |= BIT(i);
+ break;
+ }
+ }
+ }
+ mutex_unlock(&pi->req_lock);
+ return bucket_map;
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
index 07ec51f6bec1..cd9e35ae3b21 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
@@ -21,12 +21,8 @@
#define BRCMF_PNO_SCHED_SCAN_MIN_PERIOD 10
#define BRCMF_PNO_SCHED_SCAN_MAX_PERIOD 508
-/**
- * brcmf_pno_clean - disable and clear pno in firmware.
- *
- * @ifp: interface object used.
- */
-int brcmf_pno_clean(struct brcmf_if *ifp);
+/* forward declaration */
+struct brcmf_pno_info;
/**
* brcmf_pno_start_sched_scan - initiate scheduled scan on device.
@@ -38,6 +34,14 @@ int brcmf_pno_start_sched_scan(struct brcmf_if *ifp,
struct cfg80211_sched_scan_request *req);
/**
+ * brcmf_pno_stop_sched_scan - terminate scheduled scan on device.
+ *
+ * @ifp: interface object used.
+ * @reqid: unique identifier of scan to be stopped.
+ */
+int brcmf_pno_stop_sched_scan(struct brcmf_if *ifp, u64 reqid);
+
+/**
* brcmf_pno_wiphy_params - fill scheduled scan parameters in wiphy instance.
*
* @wiphy: wiphy instance to be used.
@@ -45,4 +49,35 @@ int brcmf_pno_start_sched_scan(struct brcmf_if *ifp,
*/
void brcmf_pno_wiphy_params(struct wiphy *wiphy, bool gscan);
+/**
+ * brcmf_pno_attach - allocate and attach module information.
+ *
+ * @cfg: cfg80211 context used.
+ */
+int brcmf_pno_attach(struct brcmf_cfg80211_info *cfg);
+
+/**
+ * brcmf_pno_detach - detach and free module information.
+ *
+ * @cfg: cfg80211 context used.
+ */
+void brcmf_pno_detach(struct brcmf_cfg80211_info *cfg);
+
+/**
+ * brcmf_pno_find_reqid_by_bucket - find request id for given bucket index.
+ *
+ * @pi: pno instance used.
+ * @bucket: index of firmware bucket.
+ */
+u64 brcmf_pno_find_reqid_by_bucket(struct brcmf_pno_info *pi, u32 bucket);
+
+/**
+ * brcmf_pno_get_bucket_map - determine bucket map for given netinfo.
+ *
+ * @pi: pno instance used.
+ * @netinfo: netinfo to compare with bucket configuration.
+ */
+u32 brcmf_pno_get_bucket_map(struct brcmf_pno_info *pi,
+ struct brcmf_pno_net_info_le *netinfo);
+
#endif /* _BRCMF_PNO_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 5653d6dd38f6..fd7b5addc54f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -612,7 +612,9 @@ BRCMF_FW_NVRAM_DEF(43340, "brcmfmac43340-sdio.bin", "brcmfmac43340-sdio.txt");
BRCMF_FW_NVRAM_DEF(4335, "brcmfmac4335-sdio.bin", "brcmfmac4335-sdio.txt");
BRCMF_FW_NVRAM_DEF(43362, "brcmfmac43362-sdio.bin", "brcmfmac43362-sdio.txt");
BRCMF_FW_NVRAM_DEF(4339, "brcmfmac4339-sdio.bin", "brcmfmac4339-sdio.txt");
-BRCMF_FW_NVRAM_DEF(43430, "brcmfmac43430-sdio.bin", "brcmfmac43430-sdio.txt");
+BRCMF_FW_NVRAM_DEF(43430A0, "brcmfmac43430a0-sdio.bin", "brcmfmac43430a0-sdio.txt");
+/* Note the names are not postfixed with a1 for backward compatibility */
+BRCMF_FW_NVRAM_DEF(43430A1, "brcmfmac43430-sdio.bin", "brcmfmac43430-sdio.txt");
BRCMF_FW_NVRAM_DEF(43455, "brcmfmac43455-sdio.bin", "brcmfmac43455-sdio.txt");
BRCMF_FW_NVRAM_DEF(4354, "brcmfmac4354-sdio.bin", "brcmfmac4354-sdio.txt");
BRCMF_FW_NVRAM_DEF(4356, "brcmfmac4356-sdio.bin", "brcmfmac4356-sdio.txt");
@@ -630,7 +632,8 @@ static struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339),
- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43430_CHIP_ID, 0xFFFFFFFF, 43430),
+ BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43430_CHIP_ID, 0x00000001, 43430A0),
+ BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43430_CHIP_ID, 0xFFFFFFFE, 43430A1),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFFFFFC0, 43455),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, 4354),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356)
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c
index 89137717c1fc..766bb2037b94 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c
@@ -70,8 +70,8 @@
#include "iwl-agn-hw.h"
/* Highest firmware API version supported */
-#define IWL8000_UCODE_API_MAX 30
-#define IWL8265_UCODE_API_MAX 30
+#define IWL8000_UCODE_API_MAX 31
+#define IWL8265_UCODE_API_MAX 31
/* Lowest firmware API version supported */
#define IWL8000_UCODE_API_MIN 22
@@ -98,7 +98,6 @@
IWL8265_FW_PRE __stringify(api) ".ucode"
#define NVM_HW_SECTION_NUM_FAMILY_8000 10
-#define DEFAULT_NVM_FILE_FAMILY_8000B "nvmData-8000B"
#define DEFAULT_NVM_FILE_FAMILY_8000C "nvmData-8000C"
/* Max SDIO RX/TX aggregation sizes of the ADDBA request/response */
@@ -162,10 +161,11 @@ static const struct iwl_tt_params iwl8000_tt_params = {
.dccm2_len = IWL8260_DCCM2_LEN, \
.smem_offset = IWL8260_SMEM_OFFSET, \
.smem_len = IWL8260_SMEM_LEN, \
- .default_nvm_file_B_step = DEFAULT_NVM_FILE_FAMILY_8000B, \
.default_nvm_file_C_step = DEFAULT_NVM_FILE_FAMILY_8000C, \
.thermal_params = &iwl8000_tt_params, \
- .apmg_not_supported = true
+ .apmg_not_supported = true, \
+ .ext_nvm = true, \
+ .dbgc_supported = true
#define IWL_DEVICE_8000 \
IWL_DEVICE_8000_COMMON, \
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c b/drivers/net/wireless/intel/iwlwifi/iwl-9000.c
index 110ceefccc15..42daaddfa740 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-9000.c
@@ -55,7 +55,7 @@
#include "iwl-agn-hw.h"
/* Highest firmware API version supported */
-#define IWL9000_UCODE_API_MAX 30
+#define IWL9000_UCODE_API_MAX 31
/* Lowest firmware API version supported */
#define IWL9000_UCODE_API_MIN 30
@@ -73,10 +73,13 @@
#define IWL9000_SMEM_LEN 0x68000
#define IWL9000_FW_PRE "iwlwifi-9000-pu-a0-jf-a0-"
+#define IWL9000RFB_FW_PRE "iwlwifi-9000-pu-a0-jf-b0-"
#define IWL9260A_FW_PRE "iwlwifi-9260-th-a0-jf-a0-"
#define IWL9260B_FW_PRE "iwlwifi-9260-th-b0-jf-b0-"
#define IWL9000_MODULE_FIRMWARE(api) \
IWL9000_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL9000RFB_MODULE_FIRMWARE(api) \
+ IWL9000RFB_FW_PRE "-" __stringify(api) ".ucode"
#define IWL9260A_MODULE_FIRMWARE(api) \
IWL9260A_FW_PRE "-" __stringify(api) ".ucode"
#define IWL9260B_MODULE_FIRMWARE(api) \
@@ -125,7 +128,7 @@ static const struct iwl_tt_params iwl9000_tt_params = {
#define IWL_DEVICE_9000 \
.ucode_api_max = IWL9000_UCODE_API_MAX, \
.ucode_api_min = IWL9000_UCODE_API_MIN, \
- .device_family = IWL_DEVICE_FAMILY_8000, \
+ .device_family = IWL_DEVICE_FAMILY_9000, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.base_params = &iwl9000_base_params, \
@@ -144,7 +147,9 @@ static const struct iwl_tt_params iwl9000_tt_params = {
.mq_rx_supported = true, \
.vht_mu_mimo_supported = true, \
.mac_addr_from_csr = true, \
- .rf_id = true
+ .rf_id = true, \
+ .ext_nvm = true, \
+ .dbgc_supported = true
const struct iwl_cfg iwl9160_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 9160",
@@ -182,6 +187,7 @@ const struct iwl_cfg iwl9270_2ac_cfg = {
const struct iwl_cfg iwl9460_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 9460",
.fw_name_pre = IWL9000_FW_PRE,
+ .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE,
IWL_DEVICE_9000,
.ht_params = &iwl9000_ht_params,
.nvm_ver = IWL9000_NVM_VERSION,
@@ -193,6 +199,7 @@ const struct iwl_cfg iwl9460_2ac_cfg = {
const struct iwl_cfg iwl9560_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 9560",
.fw_name_pre = IWL9000_FW_PRE,
+ .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE,
IWL_DEVICE_9000,
.ht_params = &iwl9000_ht_params,
.nvm_ver = IWL9000_NVM_VERSION,
@@ -202,5 +209,6 @@ const struct iwl_cfg iwl9560_2ac_cfg = {
};
MODULE_FIRMWARE(IWL9000_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL9000RFB_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL9260A_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL9260B_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-a000.c b/drivers/net/wireless/intel/iwlwifi/iwl-a000.c
index c648cfb981a3..63a4183c0de7 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-a000.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-a000.c
@@ -55,7 +55,7 @@
#include "iwl-agn-hw.h"
/* Highest firmware API version supported */
-#define IWL_A000_UCODE_API_MAX 30
+#define IWL_A000_UCODE_API_MAX 31
/* Lowest firmware API version supported */
#define IWL_A000_UCODE_API_MIN 24
@@ -103,7 +103,7 @@ static const struct iwl_ht_params iwl_a000_ht_params = {
#define IWL_DEVICE_A000 \
.ucode_api_max = IWL_A000_UCODE_API_MAX, \
.ucode_api_min = IWL_A000_UCODE_API_MIN, \
- .device_family = IWL_DEVICE_FAMILY_8000, \
+ .device_family = IWL_DEVICE_FAMILY_A000, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.base_params = &iwl_a000_base_params, \
@@ -123,7 +123,9 @@ static const struct iwl_ht_params iwl_a000_ht_params = {
.mac_addr_from_csr = true, \
.use_tfh = true, \
.rf_id = true, \
- .gen2 = true
+ .gen2 = true, \
+ .ext_nvm = true, \
+ .dbgc_supported = true
const struct iwl_cfg iwla000_2ac_cfg_hr = {
.name = "Intel(R) Dual Band Wireless AC a000",
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
index a12197e3ce78..f3236ea7edb5 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
@@ -88,6 +88,8 @@ enum iwl_device_family {
IWL_DEVICE_FAMILY_6150,
IWL_DEVICE_FAMILY_7000,
IWL_DEVICE_FAMILY_8000,
+ IWL_DEVICE_FAMILY_9000,
+ IWL_DEVICE_FAMILY_A000,
};
/*
@@ -275,6 +277,8 @@ struct iwl_pwr_tx_backoff {
* filename is constructed as fw_name_pre<api>.ucode.
* @fw_name_pre_next_step: same as @fw_name_pre, only for next step
* (if supported)
+ * @fw_name_pre_rf_next_step: same as @fw_name_pre_next_step, only for rf next
+ * step. Supported only in integrated solutions.
* @ucode_api_max: Highest version of uCode API supported by driver.
* @ucode_api_min: Lowest version of uCode API supported by driver.
* @max_inst_size: The maximal length of the fw inst section
@@ -315,6 +319,7 @@ struct iwl_pwr_tx_backoff {
* @integrated: discrete or integrated
* @gen2: a000 and on transport operation
* @cdb: CDB support
+ * @ext_nvm: extended NVM format
*
* We enable the driver to be backward compatible wrt. hardware features.
* API differences in uCode shouldn't be handled here but through TLVs
@@ -325,13 +330,13 @@ struct iwl_cfg {
const char *name;
const char *fw_name_pre;
const char *fw_name_pre_next_step;
+ const char *fw_name_pre_rf_next_step;
/* params not likely to change within a device family */
const struct iwl_base_params *base_params;
/* params likely to change within a device family */
const struct iwl_ht_params *ht_params;
const struct iwl_eeprom_params *eeprom_params;
const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
- const char *default_nvm_file_B_step;
const char *default_nvm_file_C_step;
const struct iwl_tt_params *thermal_params;
enum iwl_device_family device_family;
@@ -362,7 +367,9 @@ struct iwl_cfg {
integrated:1,
use_tfh:1,
gen2:1,
- cdb:1;
+ cdb:1,
+ ext_nvm:1,
+ dbgc_supported:1;
u8 valid_tx_ant;
u8 valid_rx_ant;
u8 non_shared_ant;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
index fa120fb55373..36fb20168598 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
@@ -316,6 +316,11 @@
#define CSR_HW_REV_DASH(_val) (((_val) & 0x0000003) >> 0)
#define CSR_HW_REV_STEP(_val) (((_val) & 0x000000C) >> 2)
+/* HW RFID */
+#define CSR_HW_RFID_FLAVOR(_val) (((_val) & 0x000000F) >> 0)
+#define CSR_HW_RFID_DASH(_val) (((_val) & 0x00000F0) >> 4)
+#define CSR_HW_RFID_STEP(_val) (((_val) & 0x0000F00) >> 8)
+#define CSR_HW_RFID_TYPE(_val) (((_val) & 0x0FFF000) >> 12)
/**
* hw_rev values
@@ -348,7 +353,8 @@ enum {
/* RF_ID value */
#define CSR_HW_RF_ID_TYPE_JF (0x00105000)
-#define CSR_HW_RF_ID_TYPE_HR (0x00109000)
+#define CSR_HW_RF_ID_TYPE_HR (0x0010A000)
+#define CSR_HW_RF_ID_TYPE_HRCDB (0x00109000)
/* EEPROM REG */
#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001)
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index 5cfacb0bca84..c8d451474b64 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -215,9 +215,13 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
char tag[8];
const char *fw_pre_name;
- if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
+ if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_9000 &&
CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_B_STEP)
fw_pre_name = cfg->fw_name_pre_next_step;
+ else if (drv->trans->cfg->integrated &&
+ CSR_HW_RFID_STEP(drv->trans->hw_rf_id) == SILICON_B_STEP &&
+ cfg->fw_name_pre_rf_next_step)
+ fw_pre_name = cfg->fw_name_pre_rf_next_step;
else
fw_pre_name = cfg->fw_name_pre;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h
index 6c537e04864e..1f8a2eeb7dff 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h
@@ -79,12 +79,12 @@
#define NVM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */
#define NVM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */
-#define NVM_RF_CFG_FLAVOR_MSK_FAMILY_8000(x) (x & 0xF)
-#define NVM_RF_CFG_DASH_MSK_FAMILY_8000(x) ((x >> 4) & 0xF)
-#define NVM_RF_CFG_STEP_MSK_FAMILY_8000(x) ((x >> 8) & 0xF)
-#define NVM_RF_CFG_TYPE_MSK_FAMILY_8000(x) ((x >> 12) & 0xFFF)
-#define NVM_RF_CFG_TX_ANT_MSK_FAMILY_8000(x) ((x >> 24) & 0xF)
-#define NVM_RF_CFG_RX_ANT_MSK_FAMILY_8000(x) ((x >> 28) & 0xF)
+#define EXT_NVM_RF_CFG_FLAVOR_MSK(x) ((x) & 0xF)
+#define EXT_NVM_RF_CFG_DASH_MSK(x) (((x) >> 4) & 0xF)
+#define EXT_NVM_RF_CFG_STEP_MSK(x) (((x) >> 8) & 0xF)
+#define EXT_NVM_RF_CFG_TYPE_MSK(x) (((x) >> 12) & 0xFFF)
+#define EXT_NVM_RF_CFG_TX_ANT_MSK(x) (((x) >> 24) & 0xF)
+#define EXT_NVM_RF_CFG_RX_ANT_MSK(x) (((x) >> 28) & 0xF)
/**
* DOC: Driver system flows - drv component
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h
index 62f9fe926d78..2a992277c671 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h
@@ -77,6 +77,8 @@
*/
#define FH_MEM_LOWER_BOUND (0x1000)
#define FH_MEM_UPPER_BOUND (0x2000)
+#define FH_MEM_LOWER_BOUND_GEN2 (0xa06000)
+#define FH_MEM_UPPER_BOUND_GEN2 (0xa08000)
/**
* Keep-Warm (KW) buffer base address.
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-api.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-api.h
new file mode 100644
index 000000000000..a004409fa984
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-api.h
@@ -0,0 +1,205 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <linuxwifi@intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#ifndef __iwl_fw_api_h__
+#define __iwl_fw_api_h__
+
+/**
+ * DOC: Host command section
+ *
+ * A host command is a command issued by the upper layer to the fw. There are
+ * several versions of fw that have several APIs. The transport layer is
+ * completely agnostic to these differences.
+ * The transport does provide helper functionality (i.e. SYNC / ASYNC mode),
+ */
+#define SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f)
+#define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8)
+#define SEQ_TO_INDEX(s) ((s) & 0xff)
+#define INDEX_TO_SEQ(i) ((i) & 0xff)
+#define SEQ_RX_FRAME cpu_to_le16(0x8000)
+
+/*
+ * those functions retrieve specific information from
+ * the id field in the iwl_host_cmd struct which contains
+ * the command id, the group id and the version of the command
+ * and vice versa
+*/
+static inline u8 iwl_cmd_opcode(u32 cmdid)
+{
+ return cmdid & 0xFF;
+}
+
+static inline u8 iwl_cmd_groupid(u32 cmdid)
+{
+ return ((cmdid & 0xFF00) >> 8);
+}
+
+static inline u8 iwl_cmd_version(u32 cmdid)
+{
+ return ((cmdid & 0xFF0000) >> 16);
+}
+
+static inline u32 iwl_cmd_id(u8 opcode, u8 groupid, u8 version)
+{
+ return opcode + (groupid << 8) + (version << 16);
+}
+
+/* make u16 wide id out of u8 group and opcode */
+#define WIDE_ID(grp, opcode) (((grp) << 8) | (opcode))
+#define DEF_ID(opcode) ((1 << 8) | (opcode))
+
+/* due to the conversion, this group is special; new groups
+ * should be defined in the appropriate fw-api header files
+ */
+#define IWL_ALWAYS_LONG_GROUP 1
+
+/**
+ * struct iwl_cmd_header
+ *
+ * This header format appears in the beginning of each command sent from the
+ * driver, and each response/notification received from uCode.
+ */
+struct iwl_cmd_header {
+ u8 cmd; /* Command ID: REPLY_RXON, etc. */
+ u8 group_id;
+ /*
+ * The driver sets up the sequence number to values of its choosing.
+ * uCode does not use this value, but passes it back to the driver
+ * when sending the response to each driver-originated command, so
+ * the driver can match the response to the command. Since the values
+ * don't get used by uCode, the driver may set up an arbitrary format.
+ *
+ * There is one exception: uCode sets bit 15 when it originates
+ * the response/notification, i.e. when the response/notification
+ * is not a direct response to a command sent by the driver. For
+ * example, uCode issues REPLY_RX when it sends a received frame
+ * to the driver; it is not a direct response to any driver command.
+ *
+ * The Linux driver uses the following format:
+ *
+ * 0:7 tfd index - position within TX queue
+ * 8:12 TX queue id
+ * 13:14 reserved
+ * 15 unsolicited RX or uCode-originated notification
+ */
+ __le16 sequence;
+} __packed;
+
+/**
+ * struct iwl_cmd_header_wide
+ *
+ * This header format appears in the beginning of each command sent from the
+ * driver, and each response/notification received from uCode.
+ * this is the wide version that contains more information about the command
+ * like length, version and command type
+ */
+struct iwl_cmd_header_wide {
+ u8 cmd;
+ u8 group_id;
+ __le16 sequence;
+ __le16 length;
+ u8 reserved;
+ u8 version;
+} __packed;
+
+/**
+ * iwl_tx_queue_cfg_actions - TXQ config options
+ * @TX_QUEUE_CFG_ENABLE_QUEUE: enable a queue
+ * @TX_QUEUE_CFG_TFD_SHORT_FORMAT: use short TFD format
+ */
+enum iwl_tx_queue_cfg_actions {
+ TX_QUEUE_CFG_ENABLE_QUEUE = BIT(0),
+ TX_QUEUE_CFG_TFD_SHORT_FORMAT = BIT(1),
+};
+
+/**
+ * struct iwl_tx_queue_cfg_cmd - txq hw scheduler config command
+ * @sta_id: station id
+ * @tid: tid of the queue
+ * @flags: see &enum iwl_tx_queue_cfg_actions
+ * @cb_size: size of TFD cyclic buffer. Value is exponent - 3.
+ * Minimum value 0 (8 TFDs), maximum value 5 (256 TFDs)
+ * @byte_cnt_addr: address of byte count table
+ * @tfdq_addr: address of TFD circular buffer
+ */
+struct iwl_tx_queue_cfg_cmd {
+ u8 sta_id;
+ u8 tid;
+ __le16 flags;
+ __le32 cb_size;
+ __le64 byte_cnt_addr;
+ __le64 tfdq_addr;
+} __packed; /* TX_QUEUE_CFG_CMD_API_S_VER_2 */
+
+/**
+ * struct iwl_tx_queue_cfg_rsp - response to txq hw scheduler config
+ * @queue_number: queue number assigned to this RA -TID
+ * @flags: set on failure
+ * @write_pointer: initial value for write pointer
+ */
+struct iwl_tx_queue_cfg_rsp {
+ __le16 queue_number;
+ __le16 flags;
+ __le16 write_pointer;
+ __le16 reserved;
+} __packed; /* TX_QUEUE_CFG_RSP_API_S_VER_2 */
+
+#endif /* __iwl_fw_api_h__*/
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-error-dump.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-error-dump.h
index 420c31dab263..cfebde68a391 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-error-dump.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-error-dump.h
@@ -116,7 +116,7 @@ enum iwl_fw_error_dump_type {
/**
* struct iwl_fw_error_dump_data - data for one type
- * @type: %enum iwl_fw_error_dump_type
+ * @type: &enum iwl_fw_error_dump_type
* @len: the length starting from %data
* @data: the data itself
*/
@@ -130,7 +130,7 @@ struct iwl_fw_error_dump_data {
* struct iwl_fw_error_dump_file - the layout of the header of the file
* @barker: must be %IWL_FW_ERROR_DUMP_BARKER
* @file_len: the length of all the file starting from %barker
- * @data: array of %struct iwl_fw_error_dump_data
+ * @data: array of &struct iwl_fw_error_dump_data
*/
struct iwl_fw_error_dump_file {
__le32 barker;
@@ -225,7 +225,7 @@ enum iwl_fw_error_dump_mem_type {
/**
* struct iwl_fw_error_dump_mem - chunk of memory
- * @type: %enum iwl_fw_error_dump_mem_type
+ * @type: &enum iwl_fw_error_dump_mem_type
* @offset: the offset from which the memory was read
* @data: the content of the memory
*/
@@ -324,7 +324,7 @@ enum iwl_fw_dbg_trigger {
/**
* struct iwl_fw_error_dump_trigger_desc - describes the trigger condition
- * @type: %enum iwl_fw_dbg_trigger
+ * @type: &enum iwl_fw_dbg_trigger
* @data: raw data about what happened
*/
struct iwl_fw_error_dump_trigger_desc {
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
index 44419e82da1b..52616f3c0184 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
@@ -244,6 +244,7 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t;
* @IWL_UCODE_TLV_API_TKIP_MIC_KEYS: This ucode supports version 2 of
* ADD_MODIFY_STA_KEY_API_S_VER_2.
* @IWL_UCODE_TLV_API_STA_TYPE: This ucode supports station type assignement.
+ * @IWL_UCODE_TLV_API_NAN2_VER2: This ucode supports NAN API version 2
*
* @NUM_IWL_UCODE_TLV_API: number of bits used
*/
@@ -255,6 +256,7 @@ enum iwl_ucode_tlv_api {
IWL_UCODE_TLV_API_SCAN_TSF_REPORT = (__force iwl_ucode_tlv_api_t)28,
IWL_UCODE_TLV_API_TKIP_MIC_KEYS = (__force iwl_ucode_tlv_api_t)29,
IWL_UCODE_TLV_API_STA_TYPE = (__force iwl_ucode_tlv_api_t)30,
+ IWL_UCODE_TLV_API_NAN2_VER2 = (__force iwl_ucode_tlv_api_t)31,
NUM_IWL_UCODE_TLV_API
#ifdef __CHECKER__
@@ -395,8 +397,8 @@ enum iwl_ucode_tlv_capa {
#define IWL_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8)
#define IWL_UCODE_SERIAL(ver) ((ver) & 0x000000FF)
-/*
- * Calibration control struct.
+/**
+ * struct iwl_tlv_calib_ctrl - Calibration control struct.
* Sent as part of the phy configuration command.
* @flow_trigger: bitmap for which calibrations to perform according to
* flow triggers.
@@ -468,7 +470,7 @@ enum iwl_fw_dbg_reg_operator {
/**
* struct iwl_fw_dbg_reg_op - an operation on a register
*
- * @op: %enum iwl_fw_dbg_reg_operator
+ * @op: &enum iwl_fw_dbg_reg_operator
* @addr: offset of the register
* @val: value
*/
@@ -526,7 +528,7 @@ struct iwl_fw_dbg_mem_seg_tlv {
* struct iwl_fw_dbg_dest_tlv - configures the destination of the debug data
*
* @version: version of the TLV - currently 0
- * @monitor_mode: %enum iwl_fw_dbg_monitor_mode
+ * @monitor_mode: &enum iwl_fw_dbg_monitor_mode
* @size_power: buffer size will be 2^(size_power + 11)
* @base_reg: addr of the base addr register (PRPH)
* @end_reg: addr of the end addr register (PRPH)
@@ -595,15 +597,15 @@ enum iwl_fw_dbg_trigger_vif_type {
/**
* struct iwl_fw_dbg_trigger_tlv - a TLV that describes the trigger
- * @id: %enum iwl_fw_dbg_trigger
- * @vif_type: %enum iwl_fw_dbg_trigger_vif_type
+ * @id: &enum iwl_fw_dbg_trigger
+ * @vif_type: &enum iwl_fw_dbg_trigger_vif_type
* @stop_conf_ids: bitmap of configurations this trigger relates to.
* if the mode is %IWL_FW_DBG_TRIGGER_STOP, then if the bit corresponding
* to the currently running configuration is set, the data should be
* collected.
* @stop_delay: how many milliseconds to wait before collecting the data
* after the STOP trigger fires.
- * @mode: %enum iwl_fw_dbg_trigger_mode - can be stop / start of both
+ * @mode: &enum iwl_fw_dbg_trigger_mode - can be stop / start of both
* @start_conf_id: if mode is %IWL_FW_DBG_TRIGGER_START, this defines what
* configuration should be applied when the triggers kicks in.
* @occurrences: number of occurrences. 0 means the trigger will never fire.
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c
index 9c8b09cf1f7b..c527b8c10370 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c
@@ -241,12 +241,12 @@ IWL_EXPORT_SYMBOL(iwl_clear_bits_prph);
void iwl_force_nmi(struct iwl_trans *trans)
{
- if (trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+ if (trans->cfg->device_family < IWL_DEVICE_FAMILY_8000) {
iwl_write_prph(trans, DEVICE_SET_NMI_REG,
DEVICE_SET_NMI_VAL_DRV);
iwl_write_prph(trans, DEVICE_SET_NMI_REG,
DEVICE_SET_NMI_VAL_HW);
- } else if (trans->cfg->gen2) {
+ } else if (trans->cfg->device_family == IWL_DEVICE_FAMILY_A000) {
iwl_write_prph(trans, UREG_NIC_SET_NMI_DRIVER,
DEVICE_SET_NMI_8000_VAL);
} else {
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h b/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h
index 4d32b10fe50c..0bd85e58cc2c 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h
@@ -114,7 +114,7 @@ enum iwl_uapsd_disable {
* @debug_level: levels are IWL_DL_*
* @ant_coupling: antenna coupling in dB, default = 0
* @nvm_file: specifies a external NVM file
- * @uapsd_disable: disable U-APSD, see %enum iwl_uapsd_disable, default =
+ * @uapsd_disable: disable U-APSD, see &enum iwl_uapsd_disable, default =
* IWL_DISABLE_UAPSD_BSS | IWL_DISABLE_UAPSD_P2P_CLIENT
* @d0i3_disable: disable d0i3, default = 1,
* @d0i3_entry_delay: time to wait after no refs are taken before
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
index 721ae6bef5da..070f3dfb94ce 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
@@ -94,30 +94,21 @@ enum wkp_nvm_offsets {
XTAL_CALIB = 0x316 - NVM_CALIB_SECTION
};
-enum family_8000_nvm_offsets {
+enum ext_nvm_offsets {
/* NVM HW-Section offset (in words) definitions */
- HW_ADDR0_WFPM_FAMILY_8000 = 0x12,
- HW_ADDR1_WFPM_FAMILY_8000 = 0x16,
- HW_ADDR0_PCIE_FAMILY_8000 = 0x8A,
- HW_ADDR1_PCIE_FAMILY_8000 = 0x8E,
- MAC_ADDRESS_OVERRIDE_FAMILY_8000 = 1,
+ MAC_ADDRESS_OVERRIDE_EXT_NVM = 1,
/* NVM SW-Section offset (in words) definitions */
- NVM_SW_SECTION_FAMILY_8000 = 0x1C0,
- NVM_VERSION_FAMILY_8000 = 0,
- RADIO_CFG_FAMILY_8000 = 0,
+ NVM_VERSION_EXT_NVM = 0,
+ RADIO_CFG_FAMILY_EXT_NVM = 0,
SKU_FAMILY_8000 = 2,
N_HW_ADDRS_FAMILY_8000 = 3,
/* NVM REGULATORY -Section offset (in words) definitions */
- NVM_CHANNELS_FAMILY_8000 = 0,
- NVM_LAR_OFFSET_FAMILY_8000_OLD = 0x4C7,
- NVM_LAR_OFFSET_FAMILY_8000 = 0x507,
- NVM_LAR_ENABLED_FAMILY_8000 = 0x7,
-
- /* NVM calibration section offset (in words) definitions */
- NVM_CALIB_SECTION_FAMILY_8000 = 0x2B8,
- XTAL_CALIB_FAMILY_8000 = 0x316 - NVM_CALIB_SECTION_FAMILY_8000
+ NVM_CHANNELS_EXTENDED = 0,
+ NVM_LAR_OFFSET_OLD = 0x4C7,
+ NVM_LAR_OFFSET = 0x507,
+ NVM_LAR_ENABLED = 0x7,
};
/* SKU Capabilities (actual values from NVM definition) */
@@ -141,7 +132,7 @@ static const u8 iwl_nvm_channels[] = {
149, 153, 157, 161, 165
};
-static const u8 iwl_nvm_channels_family_8000[] = {
+static const u8 iwl_ext_nvm_channels[] = {
/* 2.4 GHz */
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
/* 5 GHz */
@@ -151,9 +142,9 @@ static const u8 iwl_nvm_channels_family_8000[] = {
};
#define IWL_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels)
-#define IWL_NUM_CHANNELS_FAMILY_8000 ARRAY_SIZE(iwl_nvm_channels_family_8000)
+#define IWL_NUM_CHANNELS_EXT ARRAY_SIZE(iwl_ext_nvm_channels)
#define NUM_2GHZ_CHANNELS 14
-#define NUM_2GHZ_CHANNELS_FAMILY_8000 14
+#define NUM_2GHZ_CHANNELS_EXT 14
#define FIRST_2GHZ_HT_MINUS 5
#define LAST_2GHZ_HT_PLUS 9
#define LAST_5GHZ_HT 165
@@ -219,7 +210,7 @@ static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz,
u32 flags = IEEE80211_CHAN_NO_HT40;
u32 last_5ghz_ht = LAST_5GHZ_HT;
- if (cfg->device_family == IWL_DEVICE_FAMILY_8000)
+ if (cfg->ext_nvm)
last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000;
if (!is_5ghz && (nvm_flags & NVM_CHANNEL_40MHZ)) {
@@ -273,14 +264,14 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
int num_of_ch, num_2ghz_channels;
const u8 *nvm_chan;
- if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+ if (!cfg->ext_nvm) {
num_of_ch = IWL_NUM_CHANNELS;
nvm_chan = &iwl_nvm_channels[0];
num_2ghz_channels = NUM_2GHZ_CHANNELS;
} else {
- num_of_ch = IWL_NUM_CHANNELS_FAMILY_8000;
- nvm_chan = &iwl_nvm_channels_family_8000[0];
- num_2ghz_channels = NUM_2GHZ_CHANNELS_FAMILY_8000;
+ num_of_ch = IWL_NUM_CHANNELS_EXT;
+ nvm_chan = &iwl_ext_nvm_channels[0];
+ num_2ghz_channels = NUM_2GHZ_CHANNELS_EXT;
}
for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) {
@@ -479,7 +470,7 @@ IWL_EXPORT_SYMBOL(iwl_init_sbands);
static int iwl_get_sku(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
const __le16 *phy_sku)
{
- if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ if (!cfg->ext_nvm)
return le16_to_cpup(nvm_sw + SKU);
return le32_to_cpup((__le32 *)(phy_sku + SKU_FAMILY_8000));
@@ -487,20 +478,20 @@ static int iwl_get_sku(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
static int iwl_get_nvm_version(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
{
- if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ if (!cfg->ext_nvm)
return le16_to_cpup(nvm_sw + NVM_VERSION);
else
return le32_to_cpup((__le32 *)(nvm_sw +
- NVM_VERSION_FAMILY_8000));
+ NVM_VERSION_EXT_NVM));
}
static int iwl_get_radio_cfg(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
const __le16 *phy_sku)
{
- if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ if (!cfg->ext_nvm)
return le16_to_cpup(nvm_sw + RADIO_CFG);
- return le32_to_cpup((__le32 *)(phy_sku + RADIO_CFG_FAMILY_8000));
+ return le32_to_cpup((__le32 *)(phy_sku + RADIO_CFG_FAMILY_EXT_NVM));
}
@@ -508,7 +499,7 @@ static int iwl_get_n_hw_addrs(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
{
int n_hw_addr;
- if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ if (!cfg->ext_nvm)
return le16_to_cpup(nvm_sw + N_HW_ADDRS);
n_hw_addr = le32_to_cpup((__le32 *)(nvm_sw + N_HW_ADDRS_FAMILY_8000));
@@ -520,7 +511,7 @@ static void iwl_set_radio_cfg(const struct iwl_cfg *cfg,
struct iwl_nvm_data *data,
u32 radio_cfg)
{
- if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+ if (!cfg->ext_nvm) {
data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK(radio_cfg);
data->radio_cfg_step = NVM_RF_CFG_STEP_MSK(radio_cfg);
data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK(radio_cfg);
@@ -529,12 +520,12 @@ static void iwl_set_radio_cfg(const struct iwl_cfg *cfg,
}
/* set the radio configuration for family 8000 */
- data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK_FAMILY_8000(radio_cfg);
- data->radio_cfg_step = NVM_RF_CFG_STEP_MSK_FAMILY_8000(radio_cfg);
- data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK_FAMILY_8000(radio_cfg);
- data->radio_cfg_pnum = NVM_RF_CFG_FLAVOR_MSK_FAMILY_8000(radio_cfg);
- data->valid_tx_ant = NVM_RF_CFG_TX_ANT_MSK_FAMILY_8000(radio_cfg);
- data->valid_rx_ant = NVM_RF_CFG_RX_ANT_MSK_FAMILY_8000(radio_cfg);
+ data->radio_cfg_type = EXT_NVM_RF_CFG_TYPE_MSK(radio_cfg);
+ data->radio_cfg_step = EXT_NVM_RF_CFG_STEP_MSK(radio_cfg);
+ data->radio_cfg_dash = EXT_NVM_RF_CFG_DASH_MSK(radio_cfg);
+ data->radio_cfg_pnum = EXT_NVM_RF_CFG_FLAVOR_MSK(radio_cfg);
+ data->valid_tx_ant = EXT_NVM_RF_CFG_TX_ANT_MSK(radio_cfg);
+ data->valid_rx_ant = EXT_NVM_RF_CFG_RX_ANT_MSK(radio_cfg);
}
static void iwl_flip_hw_address(__le32 mac_addr0, __le32 mac_addr1, u8 *dest)
@@ -587,7 +578,7 @@ static void iwl_set_hw_address_family_8000(struct iwl_trans *trans,
};
hw_addr = (const u8 *)(mac_override +
- MAC_ADDRESS_OVERRIDE_FAMILY_8000);
+ MAC_ADDRESS_OVERRIDE_EXT_NVM);
/*
* Store the MAC address from MAO section.
@@ -629,7 +620,7 @@ static int iwl_set_hw_address(struct iwl_trans *trans,
{
if (cfg->mac_addr_from_csr) {
iwl_set_hw_address_from_csr(trans, data);
- } else if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+ } else if (!cfg->ext_nvm) {
const u8 *hw_addr = (const u8 *)(nvm_hw + HW_ADDR);
/* The byte order is little endian 16 bit, meaning 214365 */
@@ -666,7 +657,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
u16 lar_config;
const __le16 *ch_section;
- if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ if (!cfg->ext_nvm)
data = kzalloc(sizeof(*data) +
sizeof(struct ieee80211_channel) *
IWL_NUM_CHANNELS,
@@ -674,7 +665,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
else
data = kzalloc(sizeof(*data) +
sizeof(struct ieee80211_channel) *
- IWL_NUM_CHANNELS_FAMILY_8000,
+ IWL_NUM_CHANNELS_EXT,
GFP_KERNEL);
if (!data)
return NULL;
@@ -700,7 +691,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw);
- if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+ if (!cfg->ext_nvm) {
/* Checking for required sections */
if (!nvm_calib) {
IWL_ERR(trans,
@@ -715,14 +706,14 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
ch_section = &nvm_sw[NVM_CHANNELS];
} else {
u16 lar_offset = data->nvm_version < 0xE39 ?
- NVM_LAR_OFFSET_FAMILY_8000_OLD :
- NVM_LAR_OFFSET_FAMILY_8000;
+ NVM_LAR_OFFSET_OLD :
+ NVM_LAR_OFFSET;
lar_config = le16_to_cpup(regulatory + lar_offset);
data->lar_enabled = !!(lar_config &
- NVM_LAR_ENABLED_FAMILY_8000);
+ NVM_LAR_ENABLED);
lar_enabled = data->lar_enabled;
- ch_section = &regulatory[NVM_CHANNELS_FAMILY_8000];
+ ch_section = &regulatory[NVM_CHANNELS_EXTENDED];
}
/* If no valid mac address was found - bail out */
@@ -746,7 +737,7 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u8 *nvm_chan,
u32 flags = NL80211_RRF_NO_HT40;
u32 last_5ghz_ht = LAST_5GHZ_HT;
- if (cfg->device_family == IWL_DEVICE_FAMILY_8000)
+ if (cfg->ext_nvm)
last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000;
if (ch_idx < NUM_2GHZ_CHANNELS &&
@@ -793,8 +784,8 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
{
int ch_idx;
u16 ch_flags, prev_ch_flags = 0;
- const u8 *nvm_chan = cfg->device_family == IWL_DEVICE_FAMILY_8000 ?
- iwl_nvm_channels_family_8000 : iwl_nvm_channels;
+ const u8 *nvm_chan = cfg->ext_nvm ?
+ iwl_ext_nvm_channels : iwl_nvm_channels;
struct ieee80211_regdomain *regd;
int size_of_regd;
struct ieee80211_reg_rule *rule;
@@ -802,8 +793,8 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int center_freq, prev_center_freq = 0;
int valid_rules = 0;
bool new_rule;
- int max_num_ch = cfg->device_family == IWL_DEVICE_FAMILY_8000 ?
- IWL_NUM_CHANNELS_FAMILY_8000 : IWL_NUM_CHANNELS;
+ int max_num_ch = cfg->ext_nvm ?
+ IWL_NUM_CHANNELS_EXT : IWL_NUM_CHANNELS;
if (WARN_ON_ONCE(num_of_ch > NL80211_MAX_SUPP_REG_RULES))
return ERR_PTR(-EINVAL);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
index 0bde26bab15d..c0871f8f2c68 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
@@ -102,6 +102,8 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
if (!trans->dev_cmd_pool)
return NULL;
+ WARN_ON(!ops->wait_txq_empty && !ops->wait_tx_queues_empty);
+
return trans;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
index 0ebfdbb22992..a150da3c824b 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
@@ -76,6 +76,7 @@
#include "iwl-config.h"
#include "iwl-fw.h"
#include "iwl-op-mode.h"
+#include "iwl-fw-api.h"
/**
* DOC: Transport layer - what is it ?
@@ -111,104 +112,6 @@
* 6) Eventually, the free function will be called.
*/
-/**
- * DOC: Host command section
- *
- * A host command is a command issued by the upper layer to the fw. There are
- * several versions of fw that have several APIs. The transport layer is
- * completely agnostic to these differences.
- * The transport does provide helper functionality (i.e. SYNC / ASYNC mode),
- */
-#define SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f)
-#define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8)
-#define SEQ_TO_INDEX(s) ((s) & 0xff)
-#define INDEX_TO_SEQ(i) ((i) & 0xff)
-#define SEQ_RX_FRAME cpu_to_le16(0x8000)
-
-/*
- * those functions retrieve specific information from
- * the id field in the iwl_host_cmd struct which contains
- * the command id, the group id and the version of the command
- * and vice versa
-*/
-static inline u8 iwl_cmd_opcode(u32 cmdid)
-{
- return cmdid & 0xFF;
-}
-
-static inline u8 iwl_cmd_groupid(u32 cmdid)
-{
- return ((cmdid & 0xFF00) >> 8);
-}
-
-static inline u8 iwl_cmd_version(u32 cmdid)
-{
- return ((cmdid & 0xFF0000) >> 16);
-}
-
-static inline u32 iwl_cmd_id(u8 opcode, u8 groupid, u8 version)
-{
- return opcode + (groupid << 8) + (version << 16);
-}
-
-/* make u16 wide id out of u8 group and opcode */
-#define WIDE_ID(grp, opcode) ((grp << 8) | opcode)
-#define DEF_ID(opcode) ((1 << 8) | (opcode))
-
-/* due to the conversion, this group is special; new groups
- * should be defined in the appropriate fw-api header files
- */
-#define IWL_ALWAYS_LONG_GROUP 1
-
-/**
- * struct iwl_cmd_header
- *
- * This header format appears in the beginning of each command sent from the
- * driver, and each response/notification received from uCode.
- */
-struct iwl_cmd_header {
- u8 cmd; /* Command ID: REPLY_RXON, etc. */
- u8 group_id;
- /*
- * The driver sets up the sequence number to values of its choosing.
- * uCode does not use this value, but passes it back to the driver
- * when sending the response to each driver-originated command, so
- * the driver can match the response to the command. Since the values
- * don't get used by uCode, the driver may set up an arbitrary format.
- *
- * There is one exception: uCode sets bit 15 when it originates
- * the response/notification, i.e. when the response/notification
- * is not a direct response to a command sent by the driver. For
- * example, uCode issues REPLY_RX when it sends a received frame
- * to the driver; it is not a direct response to any driver command.
- *
- * The Linux driver uses the following format:
- *
- * 0:7 tfd index - position within TX queue
- * 8:12 TX queue id
- * 13:14 reserved
- * 15 unsolicited RX or uCode-originated notification
- */
- __le16 sequence;
-} __packed;
-
-/**
- * struct iwl_cmd_header_wide
- *
- * This header format appears in the beginning of each command sent from the
- * driver, and each response/notification received from uCode.
- * this is the wide version that contains more information about the command
- * like length, version and command type
- */
-struct iwl_cmd_header_wide {
- u8 cmd;
- u8 group_id;
- __le16 sequence;
- __le16 length;
- u8 reserved;
- u8 version;
-} __packed;
-
#define FH_RSCSR_FRAME_SIZE_MSK 0x00003FFF /* bits 0-13 */
#define FH_RSCSR_FRAME_INVALID 0x55550000
#define FH_RSCSR_FRAME_ALIGN 0x40
@@ -308,7 +211,7 @@ struct iwl_device_cmd {
#define IWL_MAX_CMD_TBS_PER_TFD 2
/**
- * struct iwl_hcmd_dataflag - flag for each one of the chunks of the command
+ * enum iwl_hcmd_dataflag - flag for each one of the chunks of the command
*
* @IWL_HCMD_DFL_NOCOPY: By default, the command is copied to the host command's
* ring. The transport layer doesn't map the command's buffer to DMA, but
@@ -533,44 +436,6 @@ struct iwl_trans_txq_scd_cfg {
int frame_limit;
};
-/* Available options for &struct iwl_tx_queue_cfg_cmd */
-enum iwl_tx_queue_cfg_actions {
- TX_QUEUE_CFG_ENABLE_QUEUE = BIT(0),
- TX_QUEUE_CFG_TFD_SHORT_FORMAT = BIT(1),
-};
-
-/**
- * struct iwl_tx_queue_cfg_cmd - txq hw scheduler config command
- * @sta_id: station id
- * @tid: tid of the queue
- * @flags: Bit 0 - on enable, off - disable, Bit 1 - short TFD format
- * @cb_size: size of TFD cyclic buffer. Value is exponent - 3.
- * Minimum value 0 (8 TFDs), maximum value 5 (256 TFDs)
- * @byte_cnt_addr: address of byte count table
- * @tfdq_addr: address of TFD circular buffer
- */
-struct iwl_tx_queue_cfg_cmd {
- u8 sta_id;
- u8 tid;
- __le16 flags;
- __le32 cb_size;
- __le64 byte_cnt_addr;
- __le64 tfdq_addr;
-} __packed; /* TX_QUEUE_CFG_CMD_API_S_VER_2 */
-
-/**
- * struct iwl_tx_queue_cfg_rsp - response to txq hw scheduler config
- * @queue_number: queue number assigned to this RA -TID
- * @flags: set on failure
- * @write_pointer: initial value for write pointer
- */
-struct iwl_tx_queue_cfg_rsp {
- __le16 queue_number;
- __le16 flags;
- __le16 write_pointer;
- __le16 reserved;
-} __packed; /* TX_QUEUE_CFG_RSP_API_S_VER_2 */
-
/**
* struct iwl_trans_ops - transport specific operations
*
@@ -619,7 +484,8 @@ struct iwl_tx_queue_cfg_rsp {
* @txq_disable: de-configure a Tx queue to send AMPDUs
* Must be atomic
* @txq_set_shared_mode: change Tx queue shared/unshared marking
- * @wait_tx_queue_empty: wait until tx queues are empty. May sleep.
+ * @wait_tx_queues_empty: wait until tx queues are empty. May sleep.
+ * @wait_txq_empty: wait until specific tx queue is empty. May sleep.
* @freeze_txq_timer: prevents the timer of the queue from firing until the
* queue is set to awake. Must be atomic.
* @block_txq_ptrs: stop updating the write pointers of the Tx queues. Note
@@ -692,6 +558,7 @@ struct iwl_trans_ops {
bool shared);
int (*wait_tx_queues_empty)(struct iwl_trans *trans, u32 txq_bm);
+ int (*wait_txq_empty)(struct iwl_trans *trans, int queue);
void (*freeze_txq_timer)(struct iwl_trans *trans, unsigned long txqs,
bool freeze);
void (*block_txq_ptrs)(struct iwl_trans *trans, bool block);
@@ -1041,13 +908,7 @@ iwl_trans_dump_data(struct iwl_trans *trans,
static inline struct iwl_device_cmd *
iwl_trans_alloc_tx_cmd(struct iwl_trans *trans)
{
- struct iwl_device_cmd *dev_cmd_ptr =
- kmem_cache_alloc(trans->dev_cmd_pool, GFP_ATOMIC);
-
- if (unlikely(dev_cmd_ptr == NULL))
- return NULL;
-
- return dev_cmd_ptr;
+ return kmem_cache_alloc(trans->dev_cmd_pool, GFP_ATOMIC);
}
int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
@@ -1198,6 +1059,9 @@ static inline void iwl_trans_block_txq_ptrs(struct iwl_trans *trans,
static inline int iwl_trans_wait_tx_queues_empty(struct iwl_trans *trans,
u32 txqs)
{
+ if (WARN_ON_ONCE(!trans->ops->wait_tx_queues_empty))
+ return -ENOTSUPP;
+
if (WARN_ON_ONCE(trans->state != IWL_TRANS_FW_ALIVE)) {
IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
return -EIO;
@@ -1206,6 +1070,19 @@ static inline int iwl_trans_wait_tx_queues_empty(struct iwl_trans *trans,
return trans->ops->wait_tx_queues_empty(trans, txqs);
}
+static inline int iwl_trans_wait_txq_empty(struct iwl_trans *trans, int queue)
+{
+ if (WARN_ON_ONCE(!trans->ops->wait_txq_empty))
+ return -ENOTSUPP;
+
+ if (WARN_ON_ONCE(trans->state != IWL_TRANS_FW_ALIVE)) {
+ IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
+ return -EIO;
+ }
+
+ return trans->ops->wait_txq_empty(trans, queue);
+}
+
static inline void iwl_trans_write8(struct iwl_trans *trans, u32 ofs, u8 val)
{
trans->ops->write8(trans, ofs, val);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
index 49b4418e6c35..fe7f1e424f55 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
@@ -914,7 +914,8 @@ void iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- u32 ant_isolation = le32_to_cpup((void *)pkt->data);
+ struct iwl_mvm_antenna_coupling_notif *notif = (void *)pkt->data;
+ u32 ant_isolation = le32_to_cpu(notif->isolation);
struct iwl_bt_coex_corun_lut_update_cmd cmd = {};
u8 __maybe_unused lower_bound, upper_bound;
u8 lut;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
index 4eeb6b78d952..6fda8627b726 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
@@ -110,6 +110,7 @@
#define IWL_MVM_TOF_IS_RESPONDER 0
#define IWL_MVM_SW_TX_CSUM_OFFLOAD 0
#define IWL_MVM_HW_CSUM_DISABLE 0
+#define IWL_MVM_PARSE_NVM 0
#define IWL_MVM_COLLECT_FW_ERR_DUMP 1
#define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1
#define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE 2
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index 402846650cbe..744dc069ff23 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -7,7 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -34,6 +34,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -82,7 +83,8 @@ static ssize_t iwl_dbgfs_ctdp_budget_read(struct file *file,
char buf[16];
int pos, budget;
- if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR)
+ if (!iwl_mvm_firmware_running(mvm) ||
+ mvm->cur_ucode != IWL_UCODE_REGULAR)
return -EIO;
mutex_lock(&mvm->mutex);
@@ -102,7 +104,8 @@ static ssize_t iwl_dbgfs_stop_ctdp_write(struct iwl_mvm *mvm, char *buf,
{
int ret;
- if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR)
+ if (!iwl_mvm_firmware_running(mvm) ||
+ mvm->cur_ucode != IWL_UCODE_REGULAR)
return -EIO;
mutex_lock(&mvm->mutex);
@@ -118,7 +121,8 @@ static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf,
int ret;
u32 scd_q_msk;
- if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR)
+ if (!iwl_mvm_firmware_running(mvm) ||
+ mvm->cur_ucode != IWL_UCODE_REGULAR)
return -EIO;
if (sscanf(buf, "%x", &scd_q_msk) != 1)
@@ -139,7 +143,8 @@ static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf,
struct iwl_mvm_sta *mvmsta;
int sta_id, drain, ret;
- if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR)
+ if (!iwl_mvm_firmware_running(mvm) ||
+ mvm->cur_ucode != IWL_UCODE_REGULAR)
return -EIO;
if (sscanf(buf, "%d %d", &sta_id, &drain) != 2)
@@ -172,7 +177,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
size_t ret;
u8 *ptr;
- if (!mvm->ucode_loaded)
+ if (!iwl_mvm_firmware_running(mvm))
return -EINVAL;
/* default is to dump the entire data segment */
@@ -205,7 +210,7 @@ static ssize_t iwl_dbgfs_sram_write(struct iwl_mvm *mvm, char *buf,
u32 offset, len;
u32 img_offset, img_len;
- if (!mvm->ucode_loaded)
+ if (!iwl_mvm_firmware_running(mvm))
return -EINVAL;
img = &mvm->fw->img[mvm->cur_ucode];
@@ -258,7 +263,7 @@ static ssize_t iwl_dbgfs_set_nic_temperature_write(struct iwl_mvm *mvm,
{
int temperature;
- if (!mvm->ucode_loaded && !mvm->temperature_test)
+ if (!iwl_mvm_firmware_running(mvm) && !mvm->temperature_test)
return -EIO;
if (kstrtoint(buf, 10, &temperature))
@@ -305,7 +310,7 @@ static ssize_t iwl_dbgfs_nic_temp_read(struct file *file,
int pos, ret;
s32 temp;
- if (!mvm->ucode_loaded)
+ if (!iwl_mvm_firmware_running(mvm))
return -EIO;
mutex_lock(&mvm->mutex);
@@ -371,7 +376,7 @@ static ssize_t iwl_dbgfs_disable_power_off_write(struct iwl_mvm *mvm, char *buf,
{
int ret, val;
- if (!mvm->ucode_loaded)
+ if (!iwl_mvm_firmware_running(mvm))
return -EIO;
if (!strncmp("disable_power_off_d0=", buf, 21)) {
@@ -583,7 +588,11 @@ iwl_dbgfs_bt_force_ant_write(struct iwl_mvm *mvm, char *buf,
mvm->bt_force_ant_mode = bt_force_ant_mode;
IWL_DEBUG_COEX(mvm, "Force mode: %s\n",
modes_str[mvm->bt_force_ant_mode]);
- ret = iwl_send_bt_init_conf(mvm);
+
+ if (iwl_mvm_firmware_running(mvm))
+ ret = iwl_send_bt_init_conf(mvm);
+ else
+ ret = 0;
out:
mutex_unlock(&mvm->mutex);
@@ -800,6 +809,9 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
{
int __maybe_unused ret;
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+
mutex_lock(&mvm->mutex);
/* allow one more restart that we're provoking here */
@@ -817,7 +829,12 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
size_t count, loff_t *ppos)
{
- int ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_NMI);
+ int ret;
+
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+
+ ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_NMI);
if (ret)
return ret;
@@ -857,6 +874,9 @@ iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf,
{
u8 scan_rx_ant;
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+
if (sscanf(buf, "%hhx", &scan_rx_ant) != 1)
return -EINVAL;
if (scan_rx_ant > ANT_ABC)
@@ -911,7 +931,11 @@ static ssize_t iwl_dbgfs_indirection_tbl_write(struct iwl_mvm *mvm,
netdev_rss_key_fill(cmd.secret_key, sizeof(cmd.secret_key));
mutex_lock(&mvm->mutex);
- ret = iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0, sizeof(cmd), &cmd);
+ if (iwl_mvm_firmware_running(mvm))
+ ret = iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0,
+ sizeof(cmd), &cmd);
+ else
+ ret = 0;
mutex_unlock(&mvm->mutex);
return ret ?: count;
@@ -931,6 +955,9 @@ static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm,
int bin_len = count / 2;
int ret = -EINVAL;
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+
/* supporting only 9000 descriptor */
if (!mvm->trans->cfg->mq_rx_supported)
return -ENOTSUPP;
@@ -1004,11 +1031,14 @@ static ssize_t iwl_dbgfs_cont_recording_write(struct iwl_mvm *mvm,
struct iwl_continuous_record_cmd cont_rec = {};
int ret, rec_mode;
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+
if (!dest)
return -EOPNOTSUPP;
if (dest->monitor_mode != SMEM_MODE ||
- trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ trans->cfg->device_family < IWL_DEVICE_FAMILY_8000)
return -EOPNOTSUPP;
ret = kstrtoint(buf, 0, &rec_mode);
@@ -1034,6 +1064,9 @@ static ssize_t iwl_dbgfs_fw_dbg_conf_write(struct iwl_mvm *mvm,
unsigned int conf_id;
int ret;
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+
ret = kstrtouint(buf, 0, &conf_id);
if (ret)
return ret;
@@ -1052,8 +1085,12 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm,
char *buf, size_t count,
loff_t *ppos)
{
- int ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE);
+ int ret;
+
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+ ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE);
if (ret)
return ret;
if (count == 0)
@@ -1184,7 +1221,8 @@ static ssize_t iwl_dbgfs_bcast_filters_write(struct iwl_mvm *mvm, char *buf,
&filter, sizeof(filter));
/* send updated bcast filtering configuration */
- if (mvm->dbgfs_bcast_filtering.override &&
+ if (iwl_mvm_firmware_running(mvm) &&
+ mvm->dbgfs_bcast_filtering.override &&
iwl_mvm_bcast_filter_build_cmd(mvm, &cmd))
err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, 0,
sizeof(cmd), &cmd);
@@ -1256,7 +1294,8 @@ static ssize_t iwl_dbgfs_bcast_filters_macs_write(struct iwl_mvm *mvm,
&mac, sizeof(mac));
/* send updated bcast filtering configuration */
- if (mvm->dbgfs_bcast_filtering.override &&
+ if (iwl_mvm_firmware_running(mvm) &&
+ mvm->dbgfs_bcast_filtering.override &&
iwl_mvm_bcast_filter_build_cmd(mvm, &cmd))
err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, 0,
sizeof(cmd), &cmd);
@@ -1473,6 +1512,9 @@ iwl_dbgfs_send_echo_cmd_write(struct iwl_mvm *mvm, char *buf,
{
int ret;
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+
mutex_lock(&mvm->mutex);
ret = iwl_mvm_send_cmd_pdu(mvm, ECHO_CMD, 0, 0, NULL);
mutex_unlock(&mvm->mutex);
@@ -1534,6 +1576,9 @@ static ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf,
size_t delta;
ssize_t ret, len;
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+
hcmd.id = iwl_cmd_id(*ppos >> 24 ? UMAC_RD_WR : LMAC_RD_WR,
DEBUG_GROUP, 0);
cmd.op = cpu_to_le32(DEBUG_MEM_OP_READ);
@@ -1586,6 +1631,9 @@ static ssize_t iwl_dbgfs_mem_write(struct file *file,
u32 op, len;
ssize_t ret;
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+
hcmd.id = iwl_cmd_id(*ppos >> 24 ? UMAC_RD_WR : LMAC_RD_WR,
DEBUG_GROUP, 0);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-coex.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-coex.h
index 204c1b13988b..c432fdb98630 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-coex.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-coex.h
@@ -99,8 +99,8 @@ enum iwl_bt_coex_enabled_modules {
/**
* struct iwl_bt_coex_cmd - bt coex configuration command
- * @mode: enum %iwl_bt_coex_mode
- * @enabled_modules: enum %iwl_bt_coex_enabled_modules
+ * @mode: &enum iwl_bt_coex_mode
+ * @enabled_modules: &enum iwl_bt_coex_enabled_modules
*
* The structure is used for the BT_COEX command.
*/
@@ -234,9 +234,9 @@ enum iwl_bt_ci_compliance {
* @mbox_msg: message from BT to WiFi
* @msg_idx: the index of the message
* @bt_ci_compliance: enum %iwl_bt_ci_compliance
- * @primary_ch_lut: LUT used for primary channel enum %iwl_bt_coex_lut_type
- * @secondary_ch_lut: LUT used for secondary channel enume %iwl_bt_coex_lut_type
- * @bt_activity_grading: the activity of BT enum %iwl_bt_activity_grading
+ * @primary_ch_lut: LUT used for primary channel &enum iwl_bt_coex_lut_type
+ * @secondary_ch_lut: LUT used for secondary channel &enum iwl_bt_coex_lut_type
+ * @bt_activity_grading: the activity of BT &enum iwl_bt_activity_grading
* @ttc_rrc_status: is TTC or RRC enabled - one bit per PHY
*/
struct iwl_bt_coex_profile_notif {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h
index 5f22cc7ac26a..edde49202786 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h
@@ -7,7 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
- * Copyright(c) 2015 Intel Deutschland GmbH
+ * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -34,6 +34,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -254,6 +255,17 @@ enum iwl_wowlan_flags {
ENABLE_STORE_BEACON = BIT(4),
};
+/**
+ * struct iwl_wowlan_config_cmd - WoWLAN configuration
+ * @wakeup_filter: filter from &enum iwl_wowlan_wakeup_filters
+ * @non_qos_seq: non-QoS sequence counter to use next
+ * @qos_seq: QoS sequence counters to use next
+ * @wowlan_ba_teardown_tids: bitmap of BA sessions to tear down
+ * @is_11n_connection: indicates HT connection
+ * @offloading_tid: TID reserved for firmware use
+ * @flags: extra flags, see &enum iwl_wowlan_flags
+ * @reserved: reserved
+ */
struct iwl_wowlan_config_cmd {
__le32 wakeup_filter;
__le16 non_qos_seq;
@@ -370,6 +382,21 @@ struct iwl_wowlan_gtk_status {
struct iwl_wowlan_rsc_tsc_params_cmd rsc;
} __packed; /* WOWLAN_GTK_MATERIAL_VER_1 */
+/**
+ * struct iwl_wowlan_status - WoWLAN status
+ * @gtk: GTK data
+ * @replay_ctr: GTK rekey replay counter
+ * @pattern_number: number of the matched pattern
+ * @non_qos_seq_ctr: non-QoS sequence counter to use next
+ * @qos_seq_ctr: QoS sequence counters to use next
+ * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason
+ * @num_of_gtk_rekeys: number of GTK rekeys
+ * @transmitted_ndps: number of transmitted neighbor discovery packets
+ * @received_beacons: number of received beacons
+ * @wake_packet_length: wakeup packet length
+ * @wake_packet_bufsize: wakeup packet buffer size
+ * @wake_packet: wakeup packet
+ */
struct iwl_wowlan_status {
struct iwl_wowlan_gtk_status gtk;
__le64 replay_ctr;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-mac.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-mac.h
index 970b030ed28d..aa5aaf7c940d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-mac.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-mac.h
@@ -329,17 +329,17 @@ struct iwl_ac_qos {
* ( MAC_CONTEXT_CMD = 0x28 )
* @id_and_color: ID and color of the MAC
* @action: action to perform, one of FW_CTXT_ACTION_*
- * @mac_type: one of FW_MAC_TYPE_*
- * @tsd_id: TSF HW timer, one of TSF_ID_*
+ * @mac_type: one of &enum iwl_mac_types
+ * @tsd_id: TSF HW timer, one of &enum iwl_tsf_id
* @node_addr: MAC address
* @bssid_addr: BSSID
* @cck_rates: basic rates available for CCK
* @ofdm_rates: basic rates available for OFDM
- * @protection_flags: combination of MAC_PROT_FLG_FLAG_*
+ * @protection_flags: combination of &enum iwl_mac_protection_flags
* @cck_short_preamble: 0x20 for enabling short preamble, 0 otherwise
* @short_slot: 0x10 for enabling short slots, 0 otherwise
- * @filter_flags: combination of MAC_FILTER_*
- * @qos_flags: from MAC_QOS_FLG_*
+ * @filter_flags: combination of &enum iwl_mac_filter_flags
+ * @qos_flags: from &enum iwl_mac_qos_flags
* @ac: one iwl_mac_qos configuration for each AC
* @mac_specific: one of struct iwl_mac_data_*, according to mac_type
*/
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-power.h
index 750510aff70b..9d87fddd29b6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-power.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-power.h
@@ -82,6 +82,8 @@
* @LTR_CFG_FLAG_SW_SET_SHORT: fixed static short LTR register
* @LTR_CFG_FLAG_SW_SET_LONG: fixed static short LONG register
* @LTR_CFG_FLAG_DENIE_C10_ON_PD: allow going into C10 on PD
+ * @LTR_CFG_FLAG_UPDATE_VALUES: update config values and short
+ * idle timeout
*/
enum iwl_ltr_config_flags {
LTR_CFG_FLAG_FEATURE_ENABLE = BIT(0),
@@ -91,11 +93,14 @@ enum iwl_ltr_config_flags {
LTR_CFG_FLAG_SW_SET_SHORT = BIT(4),
LTR_CFG_FLAG_SW_SET_LONG = BIT(5),
LTR_CFG_FLAG_DENIE_C10_ON_PD = BIT(6),
+ LTR_CFG_FLAG_UPDATE_VALUES = BIT(7),
};
/**
* struct iwl_ltr_config_cmd_v1 - configures the LTR
- * @flags: See %enum iwl_ltr_config_flags
+ * @flags: See &enum iwl_ltr_config_flags
+ * @static_long: static LTR Long register value.
+ * @static_short: static LTR Short register value.
*/
struct iwl_ltr_config_cmd_v1 {
__le32 flags;
@@ -107,11 +112,14 @@ struct iwl_ltr_config_cmd_v1 {
/**
* struct iwl_ltr_config_cmd - configures the LTR
- * @flags: See %enum iwl_ltr_config_flags
- * @static_long:
- * @static_short:
- * @ltr_cfg_values:
- * @ltr_short_idle_timeout:
+ * @flags: See &enum iwl_ltr_config_flags
+ * @static_long: static LTR Long register value.
+ * @static_short: static LTR Short register value.
+ * @ltr_cfg_values: LTR parameters table values (in usec) in folowing order:
+ * TX, RX, Short Idle, Long Idle. Used only if %LTR_CFG_FLAG_UPDATE_VALUES
+ * is set.
+ * @ltr_short_idle_timeout: LTR Short Idle timeout (in usec). Used only if
+ * %LTR_CFG_FLAG_UPDATE_VALUES is set.
*/
struct iwl_ltr_config_cmd {
__le32 flags;
@@ -140,7 +148,7 @@ struct iwl_ltr_config_cmd {
* PBW Snoozing enabled
* @POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask
* @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable.
- * @POWER_FLAGS_AP_UAPSD_MISBEHAVING_ENA_MSK: AP/GO's uAPSD misbehaving
+ * @POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK: AP/GO's uAPSD misbehaving
* detection enablement
*/
enum iwl_power_flags {
@@ -166,6 +174,7 @@ enum iwl_power_flags {
* Minimum allowed:- 3 * DTIM. Keep alive period must be
* set regardless of power scheme or current power state.
* FW use this value also when PM is disabled.
+ * @debug_flags: debug flags
* @rx_data_timeout: Minimum time (usec) from last Rx packet for AM to
* PSM transition - legacy PM
* @tx_data_timeout: Minimum time (usec) from last Tx packet for AM to
@@ -191,7 +200,8 @@ struct iwl_powertable_cmd {
/**
* enum iwl_device_power_flags - masks for device power command flags
- * @DEVIC_POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off
+ * @DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK:
+ * '1' Allow to save power by turning off
* receiver and transmitter. '0' - does not allow.
*/
enum iwl_device_power_flags {
@@ -202,7 +212,8 @@ enum iwl_device_power_flags {
* struct iwl_device_power_cmd - device wide power command.
* DEVICE_POWER_CMD = 0x77 (command, has simple generic response)
*
- * @flags: Power table command flags from DEVICE_POWER_FLAGS_*
+ * @flags: Power table command flags from &enum iwl_device_power_flags
+ * @reserved: reserved (padding)
*/
struct iwl_device_power_cmd {
/* PM_POWER_TABLE_CMD_API_S_VER_6 */
@@ -213,7 +224,7 @@ struct iwl_device_power_cmd {
/**
* struct iwl_mac_power_cmd - New power command containing uAPSD support
* MAC_PM_POWER_TABLE = 0xA9 (command, has simple generic response)
- * @id_and_color: MAC contex identifier
+ * @id_and_color: MAC contex identifier, &enum iwl_mvm_id_and_color
* @flags: Power table command flags from POWER_FLAGS_*
* @keep_alive_seconds: Keep alive period in seconds. Default - 25 sec.
* Minimum allowed:- 3 * DTIM. Keep alive period must be
@@ -223,7 +234,6 @@ struct iwl_device_power_cmd {
* PSM transition - legacy PM
* @tx_data_timeout: Minimum time (usec) from last Tx packet for AM to
* PSM transition - legacy PM
- * @sleep_interval: not in use
* @skip_dtim_periods: Number of DTIM periods to skip if Skip over DTIM flag
* is set. For example, if it is required to skip over
* one DTIM, this value need to be set to 2 (DTIM periods).
@@ -233,7 +243,6 @@ struct iwl_device_power_cmd {
* PSM transition - uAPSD
* @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled.
* Default: 80dbm
- * @num_skip_dtim: Number of DTIMs to skip if Skip over DTIM flag is set
* @snooze_interval: Maximum time between attempts to retrieve buffered data
* from the AP [msec]
* @snooze_window: A window of time in which PBW snoozing insures that all
@@ -251,8 +260,9 @@ struct iwl_device_power_cmd {
* @heavy_rx_thld_packets: RX threshold measured in number of packets
* @heavy_tx_thld_percentage: TX threshold measured in load's percentage
* @heavy_rx_thld_percentage: RX threshold measured in load's percentage
- * @limited_ps_threshold:
-*/
+ * @limited_ps_threshold: (unused)
+ * @reserved: reserved (padding)
+ */
struct iwl_mac_power_cmd {
/* CONTEXT_DESC_API_T_VER_1 */
__le32 id_and_color;
@@ -343,6 +353,7 @@ struct iwl_dev_tx_power_cmd_v3 {
* @v3: version 3 of the command, embedded here for easier software handling
* @enable_ack_reduction: enable or disable close range ack TX power
* reduction.
+ * @reserved: reserved (padding)
*/
struct iwl_dev_tx_power_cmd {
/* v4 is just an extension of v3 - keep this here */
@@ -393,7 +404,6 @@ struct iwl_geo_tx_power_profiles_cmd {
/**
* struct iwl_beacon_filter_cmd
* REPLY_BEACON_FILTERING_CMD = 0xd2 (command)
- * @id_and_color: MAC contex identifier
* @bf_energy_delta: Used for RSSI filtering, if in 'normal' state. Send beacon
* to driver if delta in Energy values calculated for this and last
* passed beacon is greater than this threshold. Zero value means that
@@ -411,7 +421,7 @@ struct iwl_geo_tx_power_profiles_cmd {
* Threshold. Typical energy threshold is -72dBm.
* @bf_temp_threshold: This threshold determines the type of temperature
* filtering (Slow or Fast) that is selected (Units are in Celsuis):
- * If the current temperature is above this threshold - Fast filter
+ * If the current temperature is above this threshold - Fast filter
* will be used, If the current temperature is below this threshold -
* Slow filter will be used.
* @bf_temp_fast_filter: Send Beacon to driver if delta in temperature values
@@ -425,7 +435,8 @@ struct iwl_geo_tx_power_profiles_cmd {
* beacon filtering; beacons will not be forced to be sent to driver
* regardless of whether its temerature has been changed.
* @bf_enable_beacon_filter: 1, beacon filtering is enabled; 0, disabled.
- * @bf_filter_escape_timer: Send beacons to to driver if no beacons were passed
+ * @bf_debug_flag: beacon filtering debug configuration
+ * @bf_escape_timer: Send beacons to to driver if no beacons were passed
* for a specific period of time. Units: Beacons.
* @ba_escape_timer: Fully receive and parse beacon if no beacons were passed
* for a longer period of time then this escape-timeout. Units: Beacons.
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h
index a10c6aae9ab9..1e34e41f52bc 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h
@@ -392,7 +392,7 @@ enum {
struct iwl_lq_cmd {
u8 sta_id;
u8 reduced_tpc;
- u16 control;
+ __le16 control;
/* LINK_QUAL_GENERAL_PARAMS_API_S_VER_1 */
u8 flags;
u8 mimo_delim;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h
index b530fa47d68a..ad7ab6dd86cb 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h
@@ -7,7 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
+ * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -34,7 +34,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
+ * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -147,7 +147,8 @@ enum iwl_csum_rx_assist_info {
/**
* struct iwl_rx_mpdu_res_start - phy info
- * @assist: see CSUM_RX_ASSIST_ above
+ * @byte_count: byte count of the frame
+ * @assist: see &enum iwl_csum_rx_assist_info
*/
struct iwl_rx_mpdu_res_start {
__le16 byte_count;
@@ -348,35 +349,106 @@ enum iwl_rx_mpdu_mac_info {
IWL_RX_MPDU_PHY_PHY_INDEX_MASK = 0xf0,
};
+/**
+ * struct iwl_rx_mpdu_desc - RX MPDU descriptor
+ */
struct iwl_rx_mpdu_desc {
/* DW2 */
+ /**
+ * @mpdu_len: MPDU length
+ */
__le16 mpdu_len;
+ /**
+ * @mac_flags1: &enum iwl_rx_mpdu_mac_flags1
+ */
u8 mac_flags1;
+ /**
+ * @mac_flags2: &enum iwl_rx_mpdu_mac_flags2
+ */
u8 mac_flags2;
/* DW3 */
+ /**
+ * @amsdu_info: &enum iwl_rx_mpdu_amsdu_info
+ */
u8 amsdu_info;
+ /**
+ * @phy_info: &enum iwl_rx_mpdu_phy_info
+ */
__le16 phy_info;
+ /**
+ * @mac_phy_idx: MAC/PHY index
+ */
u8 mac_phy_idx;
/* DW4 - carries csum data only when rpa_en == 1 */
- __le16 raw_csum; /* alledgedly unreliable */
+ /**
+ * @raw_csum: raw checksum (alledgedly unreliable)
+ */
+ __le16 raw_csum;
+ /**
+ * @l3l4_flags: &enum iwl_rx_l3l4_flags
+ */
__le16 l3l4_flags;
/* DW5 */
+ /**
+ * @status: &enum iwl_rx_mpdu_status
+ */
__le16 status;
+ /**
+ * @hash_filter: hash filter value
+ */
u8 hash_filter;
+ /**
+ * @sta_id_flags: &enum iwl_rx_mpdu_sta_id_flags
+ */
u8 sta_id_flags;
/* DW6 */
+ /**
+ * @reorder_data: &enum iwl_rx_mpdu_reorder_data
+ */
__le32 reorder_data;
/* DW7 - carries rss_hash only when rpa_en == 1 */
+ /**
+ * @rss_hash: RSS hash value
+ */
__le32 rss_hash;
/* DW8 - carries filter_match only when rpa_en == 1 */
+ /**
+ * @filter_match: filter match value
+ */
__le32 filter_match;
/* DW9 */
+ /**
+ * @rate_n_flags: RX rate/flags encoding
+ */
__le32 rate_n_flags;
/* DW10 */
- u8 energy_a, energy_b, channel, mac_context;
+ /**
+ * @energy_a: energy chain A
+ */
+ u8 energy_a;
+ /**
+ * @energy_b: energy chain B
+ */
+ u8 energy_b;
+ /**
+ * @channel: channel number
+ */
+ u8 channel;
+ /**
+ * @mac_context: MAC context mask
+ */
+ u8 mac_context;
/* DW11 */
+ /**
+ * @gp2_on_air_rise: GP2 timer value on air rise (INA)
+ */
__le32 gp2_on_air_rise;
- /* DW12 & DW13 - carries TSF only TSF_OVERLOAD bit == 0 */
+ /* DW12 & DW13 */
+ /**
+ * @tsf_on_air_rise:
+ * TSF value on air rise (INA), only valid if
+ * %IWL_RX_MPDU_PHY_TSF_OVERLOAD isn't set
+ */
__le64 tsf_on_air_rise;
} __packed;
@@ -447,7 +519,7 @@ struct iwl_rxq_sync_notification {
} __packed; /* MULTI_QUEUE_DRV_SYNC_HDR_CMD_API_S_VER_1 */
/**
- * Internal message identifier
+ * enum iwl_mvm_rxq_notif_type - Internal message identifier
*
* @IWL_MVM_RXQ_EMPTY: empty sync notification
* @IWL_MVM_RXQ_NOTIF_DEL_BA: notify RSS queues of delBA
@@ -491,7 +563,7 @@ enum iwl_mvm_pm_event {
/**
* struct iwl_mvm_pm_state_notification - station PM state notification
* @sta_id: station ID of the station changing state
- * @type: the new powersave state, see IWL_MVM_PM_EVENT_ above
+ * @type: the new powersave state, see &enum iwl_mvm_pm_event
*/
struct iwl_mvm_pm_state_notification {
u8 sta_id;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-scan.h
index 3178eb96e395..d27c67b67015 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-scan.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-scan.h
@@ -7,7 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -34,6 +34,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -67,8 +68,6 @@
#ifndef __fw_api_scan_h__
#define __fw_api_scan_h__
-#include "fw-api.h"
-
/* Scan Commands, Responses, Notifications */
/* Max number of IEs for direct SSID scans in a command */
@@ -111,7 +110,7 @@ enum scan_framework_client {
};
/**
- * iwl_scan_offload_blacklist - SCAN_OFFLOAD_BLACKLIST_S
+ * struct iwl_scan_offload_blacklist - SCAN_OFFLOAD_BLACKLIST_S
* @ssid: MAC address to filter out
* @reported_rssi: AP rssi reported to the host
* @client_bitmap: clients ignore this entry - enum scan_framework_client
@@ -135,7 +134,7 @@ enum iwl_scan_offload_band_selection {
};
/**
- * iwl_scan_offload_profile - SCAN_OFFLOAD_PROFILE_S
+ * struct iwl_scan_offload_profile - SCAN_OFFLOAD_PROFILE_S
* @ssid_index: index to ssid list in fixed part
* @unicast_cipher: encryption algorithm to match - bitmap
* @aut_alg: authentication algorithm to match - bitmap
@@ -154,8 +153,7 @@ struct iwl_scan_offload_profile {
} __packed;
/**
- * iwl_scan_offload_profile_cfg - SCAN_OFFLOAD_PROFILES_CFG_API_S_VER_1
- * @blaclist: AP list to filter off from scan results
+ * struct iwl_scan_offload_profile_cfg - SCAN_OFFLOAD_PROFILES_CFG_API_S_VER_1
* @profiles: profiles to search for match
* @blacklist_len: length of blacklist
* @num_profiles: num of profiles in the list
@@ -176,7 +174,7 @@ struct iwl_scan_offload_profile_cfg {
} __packed;
/**
- * iwl_scan_schedule_lmac - schedule of scan offload
+ * struct iwl_scan_schedule_lmac - schedule of scan offload
* @delay: delay between iterations, in seconds.
* @iterations: num of scan iterations
* @full_scan_mul: number of partial scans before each full scan
@@ -200,7 +198,7 @@ enum iwl_scan_ebs_status {
};
/**
- * iwl_scan_req_tx_cmd - SCAN_REQ_TX_CMD_API_S
+ * struct iwl_scan_req_tx_cmd - SCAN_REQ_TX_CMD_API_S
* @tx_flags: combination of TX_CMD_FLG_*
* @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is
* cleared. Combination of RATE_MCS_*
@@ -220,7 +218,7 @@ enum iwl_scan_channel_flags_lmac {
};
/**
- * iwl_scan_channel_cfg_lmac - SCAN_CHANNEL_CFG_S_VER2
+ * struct iwl_scan_channel_cfg_lmac - SCAN_CHANNEL_CFG_S_VER2
* @flags: bits 1-20: directed scan to i'th ssid
* other bits &enum iwl_scan_channel_flags_lmac
* @channel_number: channel number 1-13 etc
@@ -235,7 +233,7 @@ struct iwl_scan_channel_cfg_lmac {
} __packed;
/*
- * iwl_scan_probe_segment - PROBE_SEGMENT_API_S_VER_1
+ * struct iwl_scan_probe_segment - PROBE_SEGMENT_API_S_VER_1
* @offset: offset in the data block
* @len: length of the segment
*/
@@ -263,7 +261,7 @@ enum iwl_scan_channel_flags {
IWL_SCAN_CHANNEL_FLAG_CACHE_ADD = BIT(2),
};
-/* iwl_scan_channel_opt - CHANNEL_OPTIMIZATION_API_S
+/* struct iwl_scan_channel_opt - CHANNEL_OPTIMIZATION_API_S
* @flags: enum iwl_scan_channel_flags
* @non_ebs_ratio: defines the ratio of number of scan iterations where EBS is
* involved.
@@ -276,7 +274,7 @@ struct iwl_scan_channel_opt {
} __packed;
/**
- * iwl_mvm_lmac_scan_flags
+ * enum iwl_mvm_lmac_scan_flags - LMAC scan flags
* @IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL: pass all beacons and probe responses
* without filtering.
* @IWL_MVM_LMAC_SCAN_FLAG_PASSIVE: force passive scan on all channels
@@ -320,7 +318,7 @@ enum iwl_scan_priority_ext {
};
/**
- * iwl_scan_req_lmac - SCAN_REQUEST_CMD_API_S_VER_1
+ * struct iwl_scan_req_lmac - SCAN_REQUEST_CMD_API_S_VER_1
* @reserved1: for alignment and future use
* @channel_num: num of channels to scan
* @active-dwell: dwell time for active channels
@@ -410,7 +408,7 @@ struct iwl_lmac_scan_complete_notif {
} __packed;
/**
- * iwl_scan_offload_complete - PERIODIC_SCAN_COMPLETE_NTF_API_S_VER_2
+ * struct iwl_scan_offload_complete - PERIODIC_SCAN_COMPLETE_NTF_API_S_VER_2
* @last_schedule_line: last schedule line executed (fast or regular)
* @last_schedule_iteration: last scan iteration executed before scan abort
* @status: enum iwl_scan_offload_complete_status
@@ -547,12 +545,12 @@ struct iwl_scan_config {
} __packed; /* SCAN_CONFIG_DB_CMD_API_S_3 */
/**
- * iwl_umac_scan_flags
- *@IWL_UMAC_SCAN_FLAG_PREEMPTIVE: scan process triggered by this scan request
+ * enum iwl_umac_scan_flags - UMAC scan flags
+ * @IWL_UMAC_SCAN_FLAG_PREEMPTIVE: scan process triggered by this scan request
* can be preempted by other scan requests with higher priority.
* The low priority scan will be resumed when the higher proirity scan is
* completed.
- *@IWL_UMAC_SCAN_FLAG_START_NOTIF: notification will be sent to the driver
+ * @IWL_UMAC_SCAN_FLAG_START_NOTIF: notification will be sent to the driver
* when scan starts.
*/
enum iwl_umac_scan_flags {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
index 421b9dd1fb66..c14ebd7ff77d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
@@ -197,7 +197,15 @@ enum iwl_sta_modify_flag {
STA_MODIFY_QUEUES = BIT(7),
};
-#define STA_MODE_MODIFY 1
+/**
+ * enum iwl_sta_mode - station command mode
+ * @STA_MODE_ADD: add new station
+ * @STA_MODE_MODIFY: modify the station
+ */
+enum iwl_sta_mode {
+ STA_MODE_ADD = 0,
+ STA_MODE_MODIFY = 1,
+};
/**
* enum iwl_sta_sleep_flag - type of sleep of the station
@@ -223,7 +231,7 @@ enum iwl_sta_sleep_flag {
/**
* struct iwl_mvm_keyinfo - key information
- * @key_flags: type %iwl_sta_key_flag
+ * @key_flags: type &enum iwl_sta_key_flag
* @tkip_rx_tsc_byte2: TSC[2] for key mix ph1 detection
* @tkip_rx_ttak: 10-byte unicast TKIP TTAK for Rx
* @key_offset: key offset in the fw's key table
@@ -253,17 +261,19 @@ struct iwl_mvm_keyinfo {
/**
* struct iwl_mvm_add_sta_cmd_v7 - Add/modify a station in the fw's sta table.
* ( REPLY_ADD_STA = 0x18 )
- * @add_modify: 1: modify existing, 0: add new station
+ * @add_modify: see &enum iwl_sta_mode
* @awake_acs:
* @tid_disable_tx: is tid BIT(tid) enabled for Tx. Clear BIT(x) to enable
* AMPDU for tid x. Set %STA_MODIFY_TID_DISABLE_TX to change this field.
- * @mac_id_n_color: the Mac context this station belongs to
- * @addr[ETH_ALEN]: station's MAC address
+ * @mac_id_n_color: the Mac context this station belongs to,
+ * see &enum iwl_mvm_id_and_color
+ * @addr: station's MAC address
* @sta_id: index of station in uCode's station table
* @modify_mask: STA_MODIFY_*, selects which parameters to modify vs. leave
* alone. 1 - modify, 0 - don't change.
- * @station_flags: look at %iwl_sta_flags
- * @station_flags_msk: what of %station_flags have changed
+ * @station_flags: look at &enum iwl_sta_flags
+ * @station_flags_msk: what of %station_flags have changed,
+ * also &enum iwl_sta_flags
* @add_immediate_ba_tid: tid for which to add block-ack support (Rx)
* Set %STA_MODIFY_ADD_BA_TID to use this field, and also set
* add_immediate_ba_ssn.
@@ -274,7 +284,7 @@ struct iwl_mvm_keyinfo {
* @sleep_tx_count: number of packets to transmit to station even though it is
* asleep. Used to synchronise PS-poll and u-APSD responses while ucode
* keeps track of STA sleep state.
- * @sleep_state_flags: Look at %iwl_sta_sleep_flag.
+ * @sleep_state_flags: Look at &enum iwl_sta_sleep_flag.
* @assoc_id: assoc_id to be sent in VHT PLCP (9-bit), for grp use 0, for AP
* mac-addr.
* @beamform_flags: beam forming controls
@@ -330,17 +340,19 @@ enum iwl_sta_type {
/**
* struct iwl_mvm_add_sta_cmd - Add/modify a station in the fw's sta table.
* ( REPLY_ADD_STA = 0x18 )
- * @add_modify: 1: modify existing, 0: add new station
+ * @add_modify: see &enum iwl_sta_mode
* @awake_acs:
* @tid_disable_tx: is tid BIT(tid) enabled for Tx. Clear BIT(x) to enable
* AMPDU for tid x. Set %STA_MODIFY_TID_DISABLE_TX to change this field.
- * @mac_id_n_color: the Mac context this station belongs to
- * @addr[ETH_ALEN]: station's MAC address
+ * @mac_id_n_color: the Mac context this station belongs to,
+ * see &enum iwl_mvm_id_and_color
+ * @addr: station's MAC address
* @sta_id: index of station in uCode's station table
* @modify_mask: STA_MODIFY_*, selects which parameters to modify vs. leave
* alone. 1 - modify, 0 - don't change.
- * @station_flags: look at %iwl_sta_flags
- * @station_flags_msk: what of %station_flags have changed
+ * @station_flags: look at &enum iwl_sta_flags
+ * @station_flags_msk: what of %station_flags have changed,
+ * also &enum iwl_sta_flags
* @add_immediate_ba_tid: tid for which to add block-ack support (Rx)
* Set %STA_MODIFY_ADD_BA_TID to use this field, and also set
* add_immediate_ba_ssn.
@@ -352,7 +364,7 @@ enum iwl_sta_type {
* asleep. Used to synchronise PS-poll and u-APSD responses while ucode
* keeps track of STA sleep state.
* @station_type: type of this station. See &enum iwl_sta_type.
- * @sleep_state_flags: Look at %iwl_sta_sleep_flag.
+ * @sleep_state_flags: Look at &enum iwl_sta_sleep_flag.
* @assoc_id: assoc_id to be sent in VHT PLCP (9-bit), for grp use 0, for AP
* mac-addr.
* @beamform_flags: beam forming controls
@@ -401,7 +413,7 @@ struct iwl_mvm_add_sta_cmd {
* ( REPLY_ADD_STA_KEY = 0x17 )
* @sta_id: index of station in uCode's station table
* @key_offset: key offset in key storage
- * @key_flags: type %iwl_sta_key_flag
+ * @key_flags: type &enum iwl_sta_key_flag
* @key: key material data
* @rx_secur_seq_cnt: RX security sequence counter for the key
*/
@@ -468,7 +480,7 @@ struct iwl_mvm_rm_sta_cmd {
/**
* struct iwl_mvm_mgmt_mcast_key_cmd_v1
* ( MGMT_MCAST_KEY = 0x1f )
- * @ctrl_flags: %iwl_sta_key_flag
+ * @ctrl_flags: &enum iwl_sta_key_flag
* @igtk:
* @k1: unused
* @k2: unused
@@ -489,7 +501,7 @@ struct iwl_mvm_mgmt_mcast_key_cmd_v1 {
/**
* struct iwl_mvm_mgmt_mcast_key_cmd
* ( MGMT_MCAST_KEY = 0x1f )
- * @ctrl_flags: %iwl_sta_key_flag
+ * @ctrl_flags: &enum iwl_sta_key_flag
* @igtk: IGTK master key
* @sta_id: station ID that support IGTK
* @key_id:
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-stats.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-stats.h
index 6371c342b96d..4286222f54f7 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-stats.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-stats.h
@@ -7,7 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -72,7 +72,7 @@ struct mvm_statistics_dbg {
__le32 burst_check;
__le32 burst_count;
__le32 wait_for_silence_timeout_cnt;
- __le32 reserved[3];
+ u8 reserved[12];
} __packed; /* STATISTICS_DEBUG_API_S_VER_2 */
struct mvm_statistics_div {
@@ -323,9 +323,30 @@ struct iwl_notif_statistics_cdb {
struct mvm_statistics_load_cdb load_stats;
} __packed; /* STATISTICS_NTFY_API_S_VER_12 */
-#define IWL_STATISTICS_FLG_CLEAR 0x1
-#define IWL_STATISTICS_FLG_DISABLE_NOTIF 0x2
+/**
+ * enum iwl_statistics_notif_flags - flags used in statistics notification
+ * @IWL_STATISTICS_REPLY_FLG_CLEAR: statistics were cleared after this report
+ */
+enum iwl_statistics_notif_flags {
+ IWL_STATISTICS_REPLY_FLG_CLEAR = 0x1,
+};
+/**
+ * enum iwl_statistics_cmd_flags - flags used in statistics command
+ * @IWL_STATISTICS_FLG_CLEAR: request to clear statistics after the report
+ * that's sent after this command
+ * @IWL_STATISTICS_FLG_DISABLE_NOTIF: disable unilateral statistics
+ * notifications
+ */
+enum iwl_statistics_cmd_flags {
+ IWL_STATISTICS_FLG_CLEAR = 0x1,
+ IWL_STATISTICS_FLG_DISABLE_NOTIF = 0x2,
+};
+
+/**
+ * struct iwl_statistics_cmd - statistics config command
+ * @flags: flags from &enum iwl_statistics_cmd_flags
+ */
struct iwl_statistics_cmd {
__le32 flags;
} __packed; /* STATISTICS_CMD_API_S_VER_1 */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tof.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tof.h
index 86aa51b2210e..e2acf39f784d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tof.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tof.h
@@ -63,8 +63,6 @@
#ifndef __fw_api_tof_h__
#define __fw_api_tof_h__
-#include "fw-api.h"
-
/* ToF sub-group command IDs */
enum iwl_mvm_tof_sub_grp_ids {
TOF_RANGE_REQ_CMD = 0x1,
@@ -118,11 +116,17 @@ struct iwl_tof_config_cmd {
* @bandwidth: current AP Bandwidth: 0 20MHz, 1 40MHz, 2 80MHz
* @rate: current AP rate
* @ctrl_ch_position: coding of the control channel position relative to
- * the center frequency.
- * 40MHz 0 below center, 1 above center
- * 80MHz bits [0..1]: 0 the near 20MHz to the center,
- * 1 the far 20MHz to the center
- * bit[2] as above 40MHz
+ * the center frequency:
+ *
+ * 40 MHz
+ * 0 below center, 1 above center
+ *
+ * 80 MHz
+ * bits [0..1]
+ * * 0 the near 20MHz to the center,
+ * * 1 the far 20MHz to the center
+ * bit[2]
+ * as above 40MHz
* @ftm_per_burst: FTMs per Burst
* @ftm_resp_ts_avail: '0' - we don't measure over the Initial FTM Response,
* '1' - we measure over the Initial FTM Response
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h
index 1360ebfdc51b..c30e0e95b0b0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h
@@ -74,6 +74,7 @@
* Otherwise, use rate_n_flags from the TX command
* @TX_CMD_FLG_BAR: this frame is a BA request, immediate BAR is expected
* Must set TX_CMD_FLG_ACK with this flag.
+ * @TX_CMD_FLG_TXOP_PROT: TXOP protection requested
* @TX_CMD_FLG_VHT_NDPA: mark frame is NDPA for VHT beamformer sequence
* @TX_CMD_FLG_HT_NDPA: mark frame is NDPA for HT beamformer sequence
* @TX_CMD_FLG_CSI_FDBK2HOST: mark to send feedback to host (only if good CRC)
@@ -177,29 +178,6 @@ enum iwl_tx_cmd_sec_ctrl {
TX_CMD_SEC_KEY_FROM_TABLE = 0x10,
};
-/* TODO: how does these values are OK with only 16 bit variable??? */
-/*
- * TX command next frame info
- *
- * bits 0:2 - security control (TX_CMD_SEC_*)
- * bit 3 - immediate ACK required
- * bit 4 - rate is taken from STA table
- * bit 5 - frame belongs to BA stream
- * bit 6 - immediate BA response expected
- * bit 7 - unused
- * bits 8:15 - Station ID
- * bits 16:31 - rate
- */
-#define TX_CMD_NEXT_FRAME_ACK_MSK (0x8)
-#define TX_CMD_NEXT_FRAME_STA_RATE_MSK (0x10)
-#define TX_CMD_NEXT_FRAME_BA_MSK (0x20)
-#define TX_CMD_NEXT_FRAME_IMM_BA_RSP_MSK (0x40)
-#define TX_CMD_NEXT_FRAME_FLAGS_MSK (0xf8)
-#define TX_CMD_NEXT_FRAME_STA_ID_MSK (0xff00)
-#define TX_CMD_NEXT_FRAME_STA_ID_POS (8)
-#define TX_CMD_NEXT_FRAME_RATE_MSK (0xffff0000)
-#define TX_CMD_NEXT_FRAME_RATE_POS (16)
-
/*
* TX command Frame life time in us - to be written in pm_frame_timeout
*/
@@ -224,7 +202,7 @@ enum iwl_tx_cmd_sec_ctrl {
/**
* enum iwl_tx_offload_assist_flags_pos - set %iwl_tx_cmd offload_assist values
- * @TX_CMD_OFFLD_IP_HDR_OFFSET: offset to start of IP header (in words)
+ * @TX_CMD_OFFLD_IP_HDR: offset to start of IP header (in words)
* from mac header end. For normal case it is 4 words for SNAP.
* note: tx_cmd, mac header and pad are not counted in the offset.
* This is used to help the offload in case there is tunneling such as
@@ -258,22 +236,27 @@ enum iwl_tx_offload_assist_flags_pos {
* @len: in bytes of the payload, see below for details
* @offload_assist: TX offload configuration
* @tx_flags: combination of TX_CMD_FLG_*
+ * @scratch: scratch buffer used by the device
* @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is
* cleared. Combination of RATE_MCS_*
* @sta_id: index of destination station in FW station table
* @sec_ctl: security control, TX_CMD_SEC_*
* @initial_rate_index: index into the the rate table for initial TX attempt.
* Applied if TX_CMD_FLG_STA_RATE_MSK is set, normally 0 for data frames.
+ * @reserved2: reserved
* @key: security key
- * @next_frame_flags: TX_CMD_SEC_* and TX_CMD_NEXT_FRAME_*
+ * @reserved3: reserved
* @life_time: frame life time (usecs??)
* @dram_lsb_ptr: Physical address of scratch area in the command (try_cnt +
* btkill_cnd + reserved), first 32 bits. "0" disables usage.
* @dram_msb_ptr: upper bits of the scratch physical address
* @rts_retry_limit: max attempts for RTS
* @data_retry_limit: max attempts to send the data packet
- * @tid_spec: TID/tspec
+ * @tid_tspec: TID/tspec
* @pm_frame_timeout: PM TX frame timeout
+ * @reserved4: reserved
+ * @payload: payload (same as @hdr)
+ * @hdr: 802.11 header (same as @payload)
*
* The byte count (both len and next_frame_len) includes MAC header
* (24/26/30/32 bytes)
@@ -327,10 +310,11 @@ struct iwl_dram_sec_info {
* ( TX_CMD = 0x1c )
* @len: in bytes of the payload, see below for details
* @offload_assist: TX offload configuration
- * @tx_flags: combination of &iwl_tx_cmd_flags
+ * @flags: combination of &enum iwl_tx_cmd_flags
* @dram_info: FW internal DRAM storage
* @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is
* cleared. Combination of RATE_MCS_*
+ * @hdr: 802.11 header
*/
struct iwl_tx_cmd_gen2 {
__le16 len;
@@ -545,6 +529,8 @@ struct agg_tx_status {
* @pa_integ_res_b: tx power info
* @pa_integ_res_c: tx power info
* @measurement_req_id: tx power info
+ * @reduced_tpc: transmit power reduction used
+ * @reserved: reserved
* @tfd_info: TFD information set by the FH
* @seq_ctl: sequence control from the Tx cmd
* @byte_cnt: byte count from the Tx cmd
@@ -597,11 +583,11 @@ struct iwl_mvm_tx_resp {
/**
* struct iwl_mvm_ba_notif - notifies about reception of BA
* ( BA_NOTIF = 0xc5 )
- * @sta_addr_lo32: lower 32 bits of the MAC address
- * @sta_addr_hi16: upper 16 bits of the MAC address
+ * @sta_addr: MAC address
+ * @reserved: reserved
* @sta_id: Index of recipient (BA-sending) station in fw's station table
* @tid: tid of the session
- * @seq_ctl:
+ * @seq_ctl: sequence control field
* @bitmap: the bitmap of the BA notification as seen in the air
* @scd_flow: the tx queue this BA relates to
* @scd_ssn: the index of the last contiguously sent packet
@@ -610,10 +596,10 @@ struct iwl_mvm_tx_resp {
* @reduced_txp: power reduced according to TPC. This is the actual value and
* not a copy from the LQ command. Thus, if not the first rate was used
* for Tx-ing then this value will be set to 0 by FW.
+ * @reserved1: reserved
*/
struct iwl_mvm_ba_notif {
- __le32 sta_addr_lo32;
- __le16 sta_addr_hi16;
+ u8 sta_addr[ETH_ALEN];
__le16 reserved;
u8 sta_id;
@@ -633,13 +619,13 @@ struct iwl_mvm_ba_notif {
* @q_num: TFD queue number
* @tfd_index: Index of first un-acked frame in the TFD queue
* @scd_queue: For debug only - the physical queue the TFD queue is bound to
+ * @reserved: reserved for alignment
*/
struct iwl_mvm_compressed_ba_tfd {
__le16 q_num;
__le16 tfd_index;
u8 scd_queue;
- u8 reserved;
- __le16 reserved2;
+ u8 reserved[3];
} __packed; /* COMPRESSED_BA_TFD_API_S_VER_1 */
/**
@@ -687,11 +673,12 @@ enum iwl_mvm_ba_resp_flags {
* @query_frame_cnt: SCD query frame count
* @txed: number of frames sent in the aggregation (all-TIDs)
* @done: number of frames that were Acked by the BA (all-TIDs)
+ * @reserved: reserved (for alignment)
* @wireless_time: Wireless-media time
* @tx_rate: the rate the aggregation was sent at
* @tfd_cnt: number of TFD-Q elements
* @ra_tid_cnt: number of RATID-Q elements
- * @ba_tfd: array of TFD queue status updates. See &iwl_mvm_compressed_ba_tfd
+ * @tfd: array of TFD queue status updates. See &iwl_mvm_compressed_ba_tfd
* for details.
* @ra_tid: array of RA-TID queue status updates. For debug purposes only. See
* &iwl_mvm_compressed_ba_ratid for more details.
@@ -765,6 +752,7 @@ struct iwl_mac_beacon_cmd_v7 {
* struct iwl_mac_beacon_cmd - beacon template command with offloaded CSA
* @byte_cnt: byte count of the beacon frame
* @flags: for future use
+ * @reserved: reserved
* @data: see &iwl_mac_beacon_cmd_data
*/
struct iwl_mac_beacon_cmd {
@@ -824,16 +812,17 @@ enum iwl_scd_cfg_actions {
/**
* struct iwl_scd_txq_cfg_cmd - New txq hw scheduler config command
- * @token:
+ * @token: unused
* @sta_id: station id
- * @tid:
+ * @tid: TID
* @scd_queue: scheduler queue to confiug
* @action: 1 queue enable, 0 queue disable, 2 change txq's tid owner
- * Value is one of %iwl_scd_cfg_actions options
+ * Value is one of &enum iwl_scd_cfg_actions options
* @aggregate: 1 aggregated queue, 0 otherwise
- * @tx_fifo: %enum iwl_mvm_tx_fifo
+ * @tx_fifo: &enum iwl_mvm_tx_fifo
* @window: BA window size
* @ssn: SSN for the BA agreement
+ * @reserved: reserved
*/
struct iwl_scd_txq_cfg_cmd {
u8 token;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
index f545c5f9e4e3..cc6af9bd4e10 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
@@ -130,42 +130,114 @@ enum iwl_mvm_tx_fifo {
};
-/* commands */
-enum {
+/**
+ * enum iwl_legacy_cmds - legacy group command IDs
+ */
+enum iwl_legacy_cmds {
+ /**
+ * @MVM_ALIVE:
+ * Alive data from the firmware, as described in
+ * &struct mvm_alive_resp_v3 or &struct mvm_alive_resp.
+ */
MVM_ALIVE = 0x1,
+
+ /**
+ * @REPLY_ERROR: Cause an error in the firmware, for testing purposes.
+ */
REPLY_ERROR = 0x2,
+
+ /**
+ * @ECHO_CMD: Send data to the device to have it returned immediately.
+ */
ECHO_CMD = 0x3,
+ /**
+ * @INIT_COMPLETE_NOTIF: Notification that initialization is complete.
+ */
INIT_COMPLETE_NOTIF = 0x4,
- /* PHY context commands */
+ /**
+ * @PHY_CONTEXT_CMD:
+ * Add/modify/remove a PHY context, using &struct iwl_phy_context_cmd.
+ */
PHY_CONTEXT_CMD = 0x8,
+
+ /**
+ * @DBG_CFG: Debug configuration command.
+ */
DBG_CFG = 0x9,
+
+ /**
+ * @ANTENNA_COUPLING_NOTIFICATION:
+ * Antenna coupling data, &struct iwl_mvm_antenna_coupling_notif
+ */
ANTENNA_COUPLING_NOTIFICATION = 0xa,
- /* UMAC scan commands */
+ /**
+ * @SCAN_ITERATION_COMPLETE_UMAC:
+ * Firmware indicates a scan iteration completed, using
+ * &struct iwl_umac_scan_iter_complete_notif.
+ */
SCAN_ITERATION_COMPLETE_UMAC = 0xb5,
+
+ /**
+ * @SCAN_CFG_CMD:
+ * uses &struct iwl_scan_config_v1 or &struct iwl_scan_config
+ */
SCAN_CFG_CMD = 0xc,
SCAN_REQ_UMAC = 0xd,
SCAN_ABORT_UMAC = 0xe,
+
+ /**
+ * @SCAN_COMPLETE_UMAC: uses &struct iwl_umac_scan_complete
+ */
SCAN_COMPLETE_UMAC = 0xf,
BA_WINDOW_STATUS_NOTIFICATION_ID = 0x13,
- /* station table */
+ /**
+ * @ADD_STA_KEY:
+ * &struct iwl_mvm_add_sta_key_cmd_v1 or
+ * &struct iwl_mvm_add_sta_key_cmd.
+ */
ADD_STA_KEY = 0x17,
+
+ /**
+ * @ADD_STA:
+ * &struct iwl_mvm_add_sta_cmd or &struct iwl_mvm_add_sta_cmd_v7.
+ */
ADD_STA = 0x18,
+ /**
+ * @REMOVE_STA: &struct iwl_mvm_rm_sta_cmd
+ */
REMOVE_STA = 0x19,
/* paging get item */
FW_GET_ITEM_CMD = 0x1a,
- /* TX */
+ /**
+ * @TX_CMD: uses &struct iwl_tx_cmd or &struct iwl_tx_cmd_gen2
+ */
TX_CMD = 0x1c,
+
+ /**
+ * @TXPATH_FLUSH: &struct iwl_tx_path_flush_cmd
+ */
TXPATH_FLUSH = 0x1e,
+
+ /**
+ * @MGMT_MCAST_KEY:
+ * &struct iwl_mvm_mgmt_mcast_key_cmd or
+ * &struct iwl_mvm_mgmt_mcast_key_cmd_v1
+ */
MGMT_MCAST_KEY = 0x1f,
/* scheduler config */
+ /**
+ * @SCD_QUEUE_CFG: &struct iwl_scd_txq_cfg_cmd for older hardware,
+ * &struct iwl_tx_queue_cfg_cmd with &struct iwl_tx_queue_cfg_rsp
+ * for newer (A000) hardware.
+ */
SCD_QUEUE_CFG = 0x1d,
/* global key */
@@ -179,17 +251,40 @@ enum {
TDLS_CHANNEL_SWITCH_NOTIFICATION = 0xaa,
TDLS_CONFIG_CMD = 0xa7,
- /* MAC and Binding commands */
+ /**
+ * @MAC_CONTEXT_CMD: &struct iwl_mac_ctx_cmd
+ */
MAC_CONTEXT_CMD = 0x28,
+
+ /**
+ * @TIME_EVENT_CMD:
+ * &struct iwl_time_event_cmd, response in &struct iwl_time_event_resp
+ */
TIME_EVENT_CMD = 0x29, /* both CMD and response */
+ /**
+ * @TIME_EVENT_NOTIFICATION: &struct iwl_time_event_notif
+ */
TIME_EVENT_NOTIFICATION = 0x2a,
+ /**
+ * @BINDING_CONTEXT_CMD:
+ * &struct iwl_binding_cmd or &struct iwl_binding_cmd_v1
+ */
BINDING_CONTEXT_CMD = 0x2b,
+ /**
+ * @TIME_QUOTA_CMD: &struct iwl_time_quota_cmd
+ */
TIME_QUOTA_CMD = 0x2c,
NON_QOS_TX_COUNTER_CMD = 0x2d,
+ /**
+ * @LQ_CMD: using &struct iwl_lq_cmd
+ */
LQ_CMD = 0x4e,
- /* paging block to FW cpu2 */
+ /**
+ * @FW_PAGING_BLOCK_CMD:
+ * &struct iwl_fw_paging_cmd or &struct iwl_fw_paging_cmd_v1
+ */
FW_PAGING_BLOCK_CMD = 0x4f,
/* Scan offload */
@@ -203,6 +298,9 @@ enum {
SCAN_ITERATION_COMPLETE = 0xe7,
/* Phy */
+ /**
+ * @PHY_CONFIGURATION_CMD: &struct iwl_phy_cfg_cmd
+ */
PHY_CONFIGURATION_CMD = 0x6a,
CALIB_RES_NOTIF_PHY_DB = 0x6b,
PHY_DB_CMD = 0x6c,
@@ -211,7 +309,9 @@ enum {
TOF_CMD = 0x10,
TOF_NOTIFICATION = 0x11,
- /* Power - legacy power table command */
+ /**
+ * @POWER_TABLE_CMD: &struct iwl_device_power_cmd
+ */
POWER_TABLE_CMD = 0x77,
PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION = 0x78,
LTR_CONFIG = 0xee,
@@ -222,17 +322,44 @@ enum {
/* Set/Get DC2DC frequency tune */
DC2DC_CONFIG_CMD = 0x83,
- /* NVM */
+ /**
+ * @NVM_ACCESS_CMD: using &struct iwl_nvm_access_cmd
+ */
NVM_ACCESS_CMD = 0x88,
SET_CALIB_DEFAULT_CMD = 0x8e,
BEACON_NOTIFICATION = 0x90,
+ /**
+ * @BEACON_TEMPLATE_CMD:
+ * Uses one of &struct iwl_mac_beacon_cmd_v6,
+ * &struct iwl_mac_beacon_cmd_v7 or &struct iwl_mac_beacon_cmd
+ * depending on the device version.
+ */
BEACON_TEMPLATE_CMD = 0x91,
+ /**
+ * @TX_ANT_CONFIGURATION_CMD: &struct iwl_tx_ant_cfg_cmd
+ */
TX_ANT_CONFIGURATION_CMD = 0x98,
+
+ /**
+ * @STATISTICS_CMD: &struct iwl_statistics_cmd
+ */
STATISTICS_CMD = 0x9c,
+
+ /**
+ * @STATISTICS_NOTIFICATION:
+ * one of &struct iwl_notif_statistics_v10,
+ * &struct iwl_notif_statistics_v11,
+ * &struct iwl_notif_statistics_cdb
+ */
STATISTICS_NOTIFICATION = 0x9d,
EOSP_NOTIFICATION = 0x9e,
+
+ /**
+ * @REDUCE_TX_POWER_CMD:
+ * &struct iwl_dev_tx_power_cmd_v3 or &struct iwl_dev_tx_power_cmd
+ */
REDUCE_TX_POWER_CMD = 0x9f,
/* RF-KILL commands and notifications */
@@ -241,20 +368,43 @@ enum {
MISSED_BEACONS_NOTIFICATION = 0xa2,
- /* Power - new power table command */
+ /**
+ * @MAC_PM_POWER_TABLE: using &struct iwl_mac_power_cmd
+ */
MAC_PM_POWER_TABLE = 0xa9,
+ /**
+ * @MFUART_LOAD_NOTIFICATION: &struct iwl_mfuart_load_notif
+ */
MFUART_LOAD_NOTIFICATION = 0xb1,
+ /**
+ * @RSS_CONFIG_CMD: &struct iwl_rss_config_cmd
+ */
RSS_CONFIG_CMD = 0xb3,
+ /**
+ * @REPLY_RX_PHY_CMD: &struct iwl_rx_phy_info
+ */
REPLY_RX_PHY_CMD = 0xc0,
+
+ /**
+ * @REPLY_RX_MPDU_CMD:
+ * &struct iwl_rx_mpdu_res_start or &struct iwl_rx_mpdu_desc
+ */
REPLY_RX_MPDU_CMD = 0xc1,
FRAME_RELEASE = 0xc3,
BA_NOTIF = 0xc5,
/* Location Aware Regulatory */
+ /**
+ * @MCC_UPDATE_CMD: using &struct iwl_mcc_update_cmd
+ */
MCC_UPDATE_CMD = 0xc8,
+
+ /**
+ * @MCC_CHUB_UPDATE_CMD: using &struct iwl_mcc_chub_notif
+ */
MCC_CHUB_UPDATE_CMD = 0xc9,
MARKER_CMD = 0xcb,
@@ -262,14 +412,29 @@ enum {
/* BT Coex */
BT_COEX_PRIO_TABLE = 0xcc,
BT_COEX_PROT_ENV = 0xcd,
+ /**
+ * @BT_PROFILE_NOTIFICATION: &struct iwl_bt_coex_profile_notif
+ */
BT_PROFILE_NOTIFICATION = 0xce,
+ /**
+ * @BT_CONFIG: &struct iwl_bt_coex_cmd
+ */
BT_CONFIG = 0x9b,
BT_COEX_UPDATE_SW_BOOST = 0x5a,
BT_COEX_UPDATE_CORUN_LUT = 0x5b,
BT_COEX_UPDATE_REDUCED_TXP = 0x5c,
+ /**
+ * @BT_COEX_CI: &struct iwl_bt_coex_ci_cmd
+ */
BT_COEX_CI = 0x5d,
+ /**
+ * @REPLY_SF_CFG_CMD: &struct iwl_sf_cfg_cmd
+ */
REPLY_SF_CFG_CMD = 0xd1,
+ /**
+ * @REPLY_BEACON_FILTERING_CMD: &struct iwl_beacon_filter_cmd
+ */
REPLY_BEACON_FILTERING_CMD = 0xd2,
/* DTS measurements */
@@ -283,19 +448,39 @@ enum {
BCAST_FILTER_CMD = 0xcf,
MCAST_FILTER_CMD = 0xd0,
- /* D3 commands/notifications */
+ /**
+ * @D3_CONFIG_CMD: &struct iwl_d3_manager_config
+ */
D3_CONFIG_CMD = 0xd3,
PROT_OFFLOAD_CONFIG_CMD = 0xd4,
OFFLOADS_QUERY_CMD = 0xd5,
REMOTE_WAKE_CONFIG_CMD = 0xd6,
D0I3_END_CMD = 0xed,
- /* for WoWLAN in particular */
+ /**
+ * @WOWLAN_PATTERNS: &struct iwl_wowlan_patterns_cmd
+ */
WOWLAN_PATTERNS = 0xe0,
+
+ /**
+ * @WOWLAN_CONFIGURATION: &struct iwl_wowlan_config_cmd
+ */
WOWLAN_CONFIGURATION = 0xe1,
+ /**
+ * @WOWLAN_TSC_RSC_PARAM: &struct iwl_wowlan_rsc_tsc_params_cmd
+ */
WOWLAN_TSC_RSC_PARAM = 0xe2,
+ /**
+ * @WOWLAN_TKIP_PARAM: &struct iwl_wowlan_tkip_params_cmd
+ */
WOWLAN_TKIP_PARAM = 0xe3,
+ /**
+ * @WOWLAN_KEK_KCK_MATERIAL: &struct iwl_wowlan_kek_kck_material_cmd
+ */
WOWLAN_KEK_KCK_MATERIAL = 0xe4,
+ /**
+ * @WOWLAN_GET_STATUSES: response in &struct iwl_wowlan_status
+ */
WOWLAN_GET_STATUSES = 0xe5,
WOWLAN_TX_POWER_PER_DB = 0xe6,
@@ -303,8 +488,6 @@ enum {
SCAN_OFFLOAD_PROFILES_QUERY_CMD = 0x56,
SCAN_OFFLOAD_HOTSPOTS_CONFIG_CMD = 0x58,
SCAN_OFFLOAD_HOTSPOTS_QUERY_CMD = 0x59,
-
- REPLY_MAX = 0xff,
};
/* Please keep this enum *SORTED* by hex value.
@@ -316,21 +499,42 @@ enum iwl_mac_conf_subcmd_ids {
CHANNEL_SWITCH_NOA_NOTIF = 0xFF,
};
+/**
+ * enum iwl_phy_ops_subcmd_ids - PHY group commands
+ */
enum iwl_phy_ops_subcmd_ids {
CMD_DTS_MEASUREMENT_TRIGGER_WIDE = 0x0,
CTDP_CONFIG_CMD = 0x03,
+
+ /**
+ * @TEMP_REPORTING_THRESHOLDS_CMD: &struct temp_report_ths_cmd
+ */
TEMP_REPORTING_THRESHOLDS_CMD = 0x04,
GEO_TX_POWER_LIMIT = 0x05,
CT_KILL_NOTIFICATION = 0xFE,
DTS_MEASUREMENT_NOTIF_WIDE = 0xFF,
};
+/**
+ * enum iwl_system_subcmd_ids - system group command IDs
+ */
enum iwl_system_subcmd_ids {
+ /**
+ * @SHARED_MEM_CFG_CMD:
+ * response in &struct iwl_shared_mem_cfg or
+ * &struct iwl_shared_mem_cfg_v1
+ */
SHARED_MEM_CFG_CMD = 0x0,
INIT_EXTENDED_CFG_CMD = 0x03,
};
+/**
+ * enum iwl_data_path_subcmd_ids - data path group commands
+ */
enum iwl_data_path_subcmd_ids {
+ /**
+ * @DQA_ENABLE_CMD: &struct iwl_dqa_enable_cmd
+ */
DQA_ENABLE_CMD = 0x0,
UPDATE_MU_GROUPS_CMD = 0x1,
TRIGGER_RX_QUEUES_NOTIF_CMD = 0x2,
@@ -345,6 +549,7 @@ enum iwl_prot_offload_subcmd_ids {
enum iwl_regulatory_and_nvm_subcmd_ids {
NVM_ACCESS_COMPLETE = 0x0,
+ NVM_GET_INFO = 0x2,
};
enum iwl_debug_cmds {
@@ -353,8 +558,28 @@ enum iwl_debug_cmds {
MFU_ASSERT_DUMP_NTF = 0xFE,
};
-/* command groups */
-enum {
+/**
+ * enum iwl_mvm_command_groups - command groups for the firmware
+ * @LEGACY_GROUP: legacy group, uses command IDs from &enum iwl_legacy_cmds
+ * @LONG_GROUP: legacy group with long header, also uses command IDs
+ * from &enum iwl_legacy_cmds
+ * @SYSTEM_GROUP: system group, uses command IDs from
+ * &enum iwl_system_subcmd_ids
+ * @MAC_CONF_GROUP: MAC configuration group, uses command IDs from
+ * &enum iwl_mac_conf_subcmd_ids
+ * @PHY_OPS_GROUP: PHY operations group, uses command IDs from
+ * &enum iwl_phy_ops_subcmd_ids
+ * @DATA_PATH_GROUP: data path group, uses command IDs from
+ * &enum iwl_data_path_subcmd_ids
+ * @NAN_GROUP: NAN group, uses command IDs from &enum iwl_nan_subcmd_ids
+ * @TOF_GROUP: TOF group, uses command IDs from &enum iwl_tof_subcmd_ids
+ * @PROT_OFFLOAD_GROUP: protocol offload group, uses command IDs from
+ * &enum iwl_prot_offload_subcmd_ids
+ * @REGULATORY_AND_NVM_GROUP: regulatory/NVM group, uses command IDs from
+ * &enum iwl_regulatory_and_nvm_subcmd_ids
+ * @DEBUG_GROUP: Debug group, uses command IDs from &enum iwl_debug_cmds
+ */
+enum iwl_mvm_command_groups {
LEGACY_GROUP = 0x0,
LONG_GROUP = 0x1,
SYSTEM_GROUP = 0x2,
@@ -390,13 +615,13 @@ struct iwl_tx_ant_cfg_cmd {
__le32 valid;
} __packed;
-/*
- * Calibration control struct.
+/**
+ * struct iwl_calib_ctrl - Calibration control struct.
* Sent as part of the phy configuration command.
* @flow_trigger: bitmap for which calibrations to perform according to
- * flow triggers.
+ * flow triggers, using &enum iwl_calib_cfg
* @event_trigger: bitmap for which calibrations to perform according to
- * event triggers.
+ * event triggers, using &enum iwl_calib_cfg
*/
struct iwl_calib_ctrl {
__le32 flow_trigger;
@@ -428,8 +653,10 @@ enum iwl_calib_cfg {
IWL_CALIB_CFG_AGC_IDX = BIT(18),
};
-/*
- * Phy configuration command.
+/**
+ * struct iwl_phy_cfg_cmd - Phy configuration command
+ * @phy_cfg: PHY configuration value, uses &enum iwl_fw_phy_cfg
+ * @calib_control: calibration control data
*/
struct iwl_phy_cfg_cmd {
__le32 phy_cfg;
@@ -448,15 +675,39 @@ struct iwl_phy_cfg_cmd {
#define PHY_CFG_RX_CHAIN_C BIT(14)
-/* Target of the NVM_ACCESS_CMD */
-enum {
+/**
+ * enum iwl_nvm_access_op - NVM access opcode
+ * @IWL_NVM_READ: read NVM
+ * @IWL_NVM_WRITE: write NVM
+ */
+enum iwl_nvm_access_op {
+ IWL_NVM_READ = 0,
+ IWL_NVM_WRITE = 1,
+};
+
+/**
+ * enum iwl_nvm_access_target - target of the NVM_ACCESS_CMD
+ * @NVM_ACCESS_TARGET_CACHE: access the cache
+ * @NVM_ACCESS_TARGET_OTP: access the OTP
+ * @NVM_ACCESS_TARGET_EEPROM: access the EEPROM
+ */
+enum iwl_nvm_access_target {
NVM_ACCESS_TARGET_CACHE = 0,
NVM_ACCESS_TARGET_OTP = 1,
NVM_ACCESS_TARGET_EEPROM = 2,
};
-/* Section types for NVM_ACCESS_CMD */
-enum {
+/**
+ * enum iwl_nvm_section_type - section types for NVM_ACCESS_CMD
+ * @NVM_SECTION_TYPE_SW: software section
+ * @NVM_SECTION_TYPE_REGULATORY: regulatory section
+ * @NVM_SECTION_TYPE_CALIBRATION: calibration section
+ * @NVM_SECTION_TYPE_PRODUCTION: production section
+ * @NVM_SECTION_TYPE_MAC_OVERRIDE: MAC override section
+ * @NVM_SECTION_TYPE_PHY_SKU: PHY SKU section
+ * @NVM_MAX_NUM_SECTIONS: number of sections
+ */
+enum iwl_nvm_section_type {
NVM_SECTION_TYPE_SW = 1,
NVM_SECTION_TYPE_REGULATORY = 3,
NVM_SECTION_TYPE_CALIBRATION = 4,
@@ -467,10 +718,10 @@ enum {
};
/**
- * struct iwl_nvm_access_cmd_ver2 - Request the device to send an NVM section
- * @op_code: 0 - read, 1 - write
- * @target: NVM_ACCESS_TARGET_*
- * @type: NVM_SECTION_TYPE_*
+ * struct iwl_nvm_access_cmd - Request the device to send an NVM section
+ * @op_code: &enum iwl_nvm_access_op
+ * @target: &enum iwl_nvm_access_target
+ * @type: &enum iwl_nvm_section_type
* @offset: offset in bytes into the section
* @length: in bytes, to read/write
* @data: if write operation, the data to write. On read its empty
@@ -486,7 +737,26 @@ struct iwl_nvm_access_cmd {
#define NUM_OF_FW_PAGING_BLOCKS 33 /* 32 for data and 1 block for CSS */
-/*
+/**
+ * struct iwl_fw_paging_cmd_v1 - paging layout
+ *
+ * (FW_PAGING_BLOCK_CMD = 0x4f)
+ *
+ * Send to FW the paging layout in the driver.
+ *
+ * @flags: various flags for the command
+ * @block_size: the block size in powers of 2
+ * @block_num: number of blocks specified in the command.
+ * @device_phy_addr: virtual addresses from device side
+ */
+struct iwl_fw_paging_cmd_v1 {
+ __le32 flags;
+ __le32 block_size;
+ __le32 block_num;
+ __le32 device_phy_addr[NUM_OF_FW_PAGING_BLOCKS];
+} __packed; /* FW_PAGING_BLOCK_CMD_API_S_VER_1 */
+
+/**
* struct iwl_fw_paging_cmd - paging layout
*
* (FW_PAGING_BLOCK_CMD = 0x4f)
@@ -497,16 +767,12 @@ struct iwl_nvm_access_cmd {
* @block_size: the block size in powers of 2
* @block_num: number of blocks specified in the command.
* @device_phy_addr: virtual addresses from device side
- * 32 bit address for API version 1, 64 bit address for API version 2.
-*/
+ */
struct iwl_fw_paging_cmd {
__le32 flags;
__le32 block_size;
__le32 block_num;
- union {
- __le32 addr32[NUM_OF_FW_PAGING_BLOCKS];
- __le64 addr64[NUM_OF_FW_PAGING_BLOCKS];
- } device_phy_addr;
+ __le64 device_phy_addr[NUM_OF_FW_PAGING_BLOCKS];
} __packed; /* FW_PAGING_BLOCK_CMD_API_S_VER_2 */
/*
@@ -679,12 +945,21 @@ struct iwl_error_resp {
#define MAX_MACS_IN_BINDING (3)
#define MAX_BINDINGS (4)
-/* Used to extract ID and color from the context dword */
-#define FW_CTXT_ID_POS (0)
-#define FW_CTXT_ID_MSK (0xff << FW_CTXT_ID_POS)
-#define FW_CTXT_COLOR_POS (8)
-#define FW_CTXT_COLOR_MSK (0xff << FW_CTXT_COLOR_POS)
-#define FW_CTXT_INVALID (0xffffffff)
+/**
+ * enum iwl_mvm_id_and_color - ID and color fields in context dword
+ * @FW_CTXT_ID_POS: position of the ID
+ * @FW_CTXT_ID_MSK: mask of the ID
+ * @FW_CTXT_COLOR_POS: position of the color
+ * @FW_CTXT_COLOR_MSK: mask of the color
+ * @FW_CTXT_INVALID: value used to indicate unused/invalid
+ */
+enum iwl_mvm_id_and_color {
+ FW_CTXT_ID_POS = 0,
+ FW_CTXT_ID_MSK = 0xff << FW_CTXT_ID_POS,
+ FW_CTXT_COLOR_POS = 8,
+ FW_CTXT_COLOR_MSK = 0xff << FW_CTXT_COLOR_POS,
+ FW_CTXT_INVALID = 0xffffffff,
+};
#define FW_CMD_ID_AND_COLOR(_id, _color) ((_id << FW_CTXT_ID_POS) |\
(_color << FW_CTXT_COLOR_POS))
@@ -832,7 +1107,8 @@ enum {
#define TE_V2_PLACEMENT_POS 12
#define TE_V2_ABSENCE_POS 15
-/* Time event policy values
+/**
+ * enum iwl_time_event_policy - Time event policy values
* A notification (both event and fragment) includes a status indicating weather
* the FW was able to schedule the event or not. For fragment start/end
* notification the status is always success. There is no start/end fragment
@@ -847,12 +1123,13 @@ enum {
* @TE_V2_NOTIF_HOST_FRAG_END:request/receive notification on frag end
* @TE_V2_NOTIF_INTERNAL_FRAG_START: internal FW use.
* @TE_V2_NOTIF_INTERNAL_FRAG_END: internal FW use.
+ * @T2_V2_START_IMMEDIATELY: start time event immediately
* @TE_V2_DEP_OTHER: depends on another time event
* @TE_V2_DEP_TSF: depends on a specific time
* @TE_V2_EVENT_SOCIOPATHIC: can't co-exist with other events of tha same MAC
* @TE_V2_ABSENCE: are we present or absent during the Time Event.
*/
-enum {
+enum iwl_time_event_policy {
TE_V2_DEFAULT_POLICY = 0x0,
/* notifications (event start/stop, fragment start/stop) */
@@ -867,8 +1144,6 @@ enum {
TE_V2_NOTIF_INTERNAL_FRAG_END = BIT(7),
T2_V2_START_IMMEDIATELY = BIT(11),
- TE_V2_NOTIF_MSK = 0xff,
-
/* placement characteristics */
TE_V2_DEP_OTHER = BIT(TE_V2_PLACEMENT_POS),
TE_V2_DEP_TSF = BIT(TE_V2_PLACEMENT_POS + 1),
@@ -879,12 +1154,13 @@ enum {
};
/**
- * struct iwl_time_event_cmd_api - configuring Time Events
+ * struct iwl_time_event_cmd - configuring Time Events
* with struct MAC_TIME_EVENT_DATA_API_S_VER_2 (see also
* with version 1. determined by IWL_UCODE_TLV_FLAGS)
* ( TIME_EVENT_CMD = 0x29 )
- * @id_and_color: ID and color of the relevant MAC
- * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @id_and_color: ID and color of the relevant MAC,
+ * &enum iwl_mvm_id_and_color
+ * @action: action to perform, one of &enum iwl_phy_ctxt_action
* @id: this field has two meanings, depending on the action:
* If the action is ADD, then it means the type of event to add.
* For all other actions it is the unique event ID assigned when the
@@ -900,7 +1176,8 @@ enum {
* on event and/or fragment start and/or end
* using one of TE_INDEPENDENT, TE_DEP_OTHER, TE_DEP_TSF
* TE_EVENT_SOCIOPATHIC
- * using TE_ABSENCE and using TE_NOTIF_*
+ * using TE_ABSENCE and using TE_NOTIF_*,
+ * &enum iwl_time_event_policy
*/
struct iwl_time_event_cmd {
/* COMMON_INDEX_HDR_API_S_VER_1 */
@@ -923,7 +1200,8 @@ struct iwl_time_event_cmd {
* @status: bit 0 indicates success, all others specify errors
* @id: the Time Event type
* @unique_id: the unique ID assigned (in ADD) or given (others) to the TE
- * @id_and_color: ID and color of the relevant MAC
+ * @id_and_color: ID and color of the relevant MAC,
+ * &enum iwl_mvm_id_and_color
*/
struct iwl_time_event_resp {
__le32 status;
@@ -939,7 +1217,7 @@ struct iwl_time_event_resp {
* @session_id: session's unique id
* @unique_id: unique id of the Time Event itself
* @id_and_color: ID and color of the relevant MAC
- * @action: one of TE_NOTIF_START or TE_NOTIF_END
+ * @action: &enum iwl_time_event_policy
* @status: true if scheduled, false otherwise (not executed)
*/
struct iwl_time_event_notif {
@@ -955,12 +1233,35 @@ struct iwl_time_event_notif {
/* Bindings and Time Quota */
/**
+ * struct iwl_binding_cmd_v1 - configuring bindings
+ * ( BINDING_CONTEXT_CMD = 0x2b )
+ * @id_and_color: ID and color of the relevant Binding,
+ * &enum iwl_mvm_id_and_color
+ * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @macs: array of MAC id and colors which belong to the binding,
+ * &enum iwl_mvm_id_and_color
+ * @phy: PHY id and color which belongs to the binding,
+ * &enum iwl_mvm_id_and_color
+ */
+struct iwl_binding_cmd_v1 {
+ /* COMMON_INDEX_HDR_API_S_VER_1 */
+ __le32 id_and_color;
+ __le32 action;
+ /* BINDING_DATA_API_S_VER_1 */
+ __le32 macs[MAX_MACS_IN_BINDING];
+ __le32 phy;
+} __packed; /* BINDING_CMD_API_S_VER_1 */
+
+/**
* struct iwl_binding_cmd - configuring bindings
* ( BINDING_CONTEXT_CMD = 0x2b )
- * @id_and_color: ID and color of the relevant Binding
+ * @id_and_color: ID and color of the relevant Binding,
+ * &enum iwl_mvm_id_and_color
* @action: action to perform, one of FW_CTXT_ACTION_*
* @macs: array of MAC id and colors which belong to the binding
+ * &enum iwl_mvm_id_and_color
* @phy: PHY id and color which belongs to the binding
+ * &enum iwl_mvm_id_and_color
* @lmac_id: the lmac id the binding belongs to
*/
struct iwl_binding_cmd {
@@ -970,11 +1271,10 @@ struct iwl_binding_cmd {
/* BINDING_DATA_API_S_VER_1 */
__le32 macs[MAX_MACS_IN_BINDING];
__le32 phy;
- /* BINDING_CMD_API_S_VER_1 */
__le32 lmac_id;
} __packed; /* BINDING_CMD_API_S_VER_2 */
-#define IWL_BINDING_CMD_SIZE_V1 offsetof(struct iwl_binding_cmd, lmac_id)
+#define IWL_BINDING_CMD_SIZE_V1 sizeof(struct iwl_binding_cmd_v1)
#define IWL_LMAC_24G_INDEX 0
#define IWL_LMAC_5G_INDEX 1
@@ -983,7 +1283,8 @@ struct iwl_binding_cmd {
/**
* struct iwl_time_quota_data - configuration of time quota per binding
- * @id_and_color: ID and color of the relevant Binding
+ * @id_and_color: ID and color of the relevant Binding,
+ * &enum iwl_mvm_id_and_color
* @quota: absolute time quota in TU. The scheduler will try to divide the
* remainig quota (after Time Events) according to this quota.
* @max_duration: max uninterrupted context duration in TU
@@ -1539,8 +1840,8 @@ enum iwl_sf_scenario {
#define SF_CFG_DUMMY_NOTIF_OFF BIT(16)
/**
- * Smart Fifo configuration command.
- * @state: smart fifo state, types listed in enum %iwl_sf_sate.
+ * struct iwl_sf_cfg_cmd - Smart Fifo configuration command.
+ * @state: smart fifo state, types listed in &enum iwl_sf_state.
* @watermark: Minimum allowed availabe free space in RXF for transient state.
* @long_delay_timeouts: aging and idle timer values for each scenario
* in long delay state.
@@ -1590,11 +1891,11 @@ struct iwl_mcc_update_cmd {
u8 source_id;
u8 reserved;
__le32 key;
- __le32 reserved2[5];
+ u8 reserved2[20];
} __packed; /* LAR_UPDATE_MCC_CMD_API_S_VER_2 */
/**
- * iwl_mcc_update_resp_v1 - response to MCC_UPDATE_CMD.
+ * struct iwl_mcc_update_resp_v1 - 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.
@@ -1617,7 +1918,7 @@ struct iwl_mcc_update_resp_v1 {
} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_1 */
/**
- * iwl_mcc_update_resp - response to MCC_UPDATE_CMD.
+ * struct iwl_mcc_update_resp - 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.
@@ -1659,7 +1960,7 @@ struct iwl_mcc_update_resp {
* @reserved1: reserved for alignment
*/
struct iwl_mcc_chub_notif {
- u16 mcc;
+ __le16 mcc;
u8 source_id;
u8 reserved1;
} __packed; /* LAR_MCC_NOTIFY_S */
@@ -1699,10 +2000,10 @@ enum iwl_dts_measurement_flags {
};
/**
- * iwl_dts_measurement_cmd - request DTS temperature and/or voltage measurements
+ * struct iwl_dts_measurement_cmd - request DTS temp and/or voltage measurements
*
- * @flags: indicates which measurements we want as specified in &enum
- * iwl_dts_measurement_flags
+ * @flags: indicates which measurements we want as specified in
+ * &enum iwl_dts_measurement_flags
*/
struct iwl_dts_measurement_cmd {
__le32 flags;
@@ -1754,7 +2055,7 @@ enum iwl_dts_bit_mode {
};
/**
- * iwl_ext_dts_measurement_cmd - request extended DTS temperature measurements
+ * struct iwl_ext_dts_measurement_cmd - request extended DTS temp measurements
* @control_mode: see &enum iwl_dts_control_measurement_mode
* @temperature: used when over write DTS mode is selected
* @sensor: set temperature sensor to use. See &enum iwl_dts_used
@@ -1834,7 +2135,7 @@ struct iwl_mvm_ctdp_cmd {
#define IWL_MAX_DTS_TRIPS 8
/**
- * struct iwl_temp_report_ths_cmd - set temperature thresholds
+ * struct temp_report_ths_cmd - set temperature thresholds
*
* @num_temps: number of temperature thresholds passed
* @thresholds: array with the thresholds to be configured
@@ -1856,7 +2157,7 @@ enum iwl_tdls_channel_switch_type {
}; /* TDLS_STA_CHANNEL_SWITCH_CMD_TYPE_API_E_VER_1 */
/**
- * Switch timing sub-element in a TDLS channel-switch command
+ * struct iwl_tdls_channel_switch_timing - Switch timing in TDLS channel-switch
* @frame_timestamp: GP2 timestamp of channel-switch request/response packet
* received from peer
* @max_offchan_duration: What amount of microseconds out of a DTIM is given
@@ -1876,7 +2177,7 @@ struct iwl_tdls_channel_switch_timing {
#define IWL_TDLS_CH_SW_FRAME_MAX_SIZE 200
/**
- * TDLS channel switch frame template
+ * struct iwl_tdls_channel_switch_frame - TDLS channel switch frame template
*
* A template representing a TDLS channel-switch request or response frame
*
@@ -1891,7 +2192,7 @@ struct iwl_tdls_channel_switch_frame {
} __packed; /* TDLS_STA_CHANNEL_SWITCH_FRAME_API_S_VER_1 */
/**
- * TDLS channel switch command
+ * struct iwl_tdls_channel_switch_cmd - TDLS channel switch command
*
* The command is sent to initiate a channel switch and also in response to
* incoming TDLS channel-switch request/response packets from remote peers.
@@ -1911,7 +2212,7 @@ struct iwl_tdls_channel_switch_cmd {
} __packed; /* TDLS_STA_CHANNEL_SWITCH_CMD_API_S_VER_1 */
/**
- * TDLS channel switch start notification
+ * struct iwl_tdls_channel_switch_notif - TDLS channel switch start notification
*
* @status: non-zero on success
* @offchannel_duration: duration given in microseconds
@@ -1924,7 +2225,7 @@ struct iwl_tdls_channel_switch_notif {
} __packed; /* TDLS_STA_CHANNEL_SWITCH_NTFY_API_S_VER_1 */
/**
- * TDLS station info
+ * struct iwl_tdls_sta_info - TDLS station info
*
* @sta_id: station id of the TDLS peer
* @tx_to_peer_tid: TID reserved vs. the peer for FW based Tx
@@ -1939,7 +2240,7 @@ struct iwl_tdls_sta_info {
} __packed; /* TDLS_STA_INFO_VER_1 */
/**
- * TDLS basic config command
+ * struct iwl_tdls_config_cmd - TDLS basic config command
*
* @id_and_color: MAC id and color being configured
* @tdls_peer_count: amount of currently connected TDLS peers
@@ -1963,7 +2264,7 @@ struct iwl_tdls_config_cmd {
} __packed; /* TDLS_CONFIG_CMD_API_S_VER_1 */
/**
- * TDLS per-station config information from FW
+ * struct iwl_tdls_config_sta_info_res - TDLS per-station config information
*
* @sta_id: station id of the TDLS peer
* @tx_to_peer_last_seq: last sequence number used by FW during FW-based Tx to
@@ -1975,7 +2276,7 @@ struct iwl_tdls_config_sta_info_res {
} __packed; /* TDLS_STA_INFO_RSP_VER_1 */
/**
- * TDLS config information from FW
+ * struct iwl_tdls_config_res - TDLS config information from FW
*
* @tx_to_ap_last_seq: last sequence number used by FW during FW-based Tx to AP
* @sta_info: per-station TDLS config information
@@ -1991,7 +2292,7 @@ struct iwl_tdls_config_res {
#define TX_FIFO_INTERNAL_MAX_NUM 6
/**
- * Shared memory configuration information from the FW
+ * struct iwl_shared_mem_cfg_v1 - Shared memory configuration information
*
* @shared_mem_addr: shared memory addr (pre 8000 HW set to 0x0 as MARBH is not
* accessible)
@@ -2045,7 +2346,7 @@ struct iwl_shared_mem_lmac_cfg {
} __packed; /* SHARED_MEM_ALLOC_LMAC_API_S_VER_1 */
/**
- * Shared memory configuration information from the FW
+ * struct iwl_shared_mem_cfg - Shared memory configuration information
*
* @shared_mem_addr: shared memory address
* @shared_mem_size: shared memory size
@@ -2073,7 +2374,7 @@ struct iwl_shared_mem_cfg {
} __packed; /* SHARED_MEM_ALLOC_API_S_VER_3 */
/**
- * VHT MU-MIMO group configuration
+ * struct iwl_mu_group_mgmt_cmd - VHT MU-MIMO group configuration
*
* @membership_status: a bitmap of MU groups
* @user_position:the position of station in a group. If the station is in the
@@ -2100,7 +2401,7 @@ struct iwl_mu_group_mgmt_notif {
#define MAX_STORED_BEACON_SIZE 600
/**
- * Stored beacon notification
+ * struct iwl_stored_beacon_notif - Stored beacon notification
*
* @system_time: system time on air rise
* @tsf: TSF on air rise
@@ -2135,7 +2436,7 @@ enum iwl_lqm_status {
};
/**
- * Link Quality Measurement command
+ * struct iwl_link_qual_msrmnt_cmd - Link Quality Measurement command
* @cmd_operatrion: command operation to be performed (start or stop)
* as defined above.
* @mac_id: MAC ID the measurement applies to.
@@ -2150,7 +2451,7 @@ struct iwl_link_qual_msrmnt_cmd {
} __packed /* LQM_CMD_API_S_VER_1 */;
/**
- * Link Quality Measurement notification
+ * struct iwl_link_qual_msrmnt_notif - Link Quality Measurement notification
*
* @frequent_stations_air_time: an array containing the total air time
* (in uSec) used by the most frequently transmitting stations.
@@ -2174,11 +2475,11 @@ struct iwl_link_qual_msrmnt_notif {
__le32 tx_frame_dropped;
__le32 mac_id;
__le32 status;
- __le32 reserved[3];
+ u8 reserved[12];
} __packed; /* LQM_MEASUREMENT_COMPLETE_NTF_API_S_VER1 */
/**
- * Channel switch NOA notification
+ * struct iwl_channel_switch_noa_notif - Channel switch NOA notification
*
* @id_and_color: ID and color of the MAC
*/
@@ -2259,4 +2560,88 @@ struct iwl_init_extended_cfg_cmd {
__le32 init_flags;
} __packed; /* INIT_EXTENDED_CFG_CMD_API_S_VER_1 */
+/*
+ * struct iwl_nvm_get_info - request to get NVM data
+ */
+struct iwl_nvm_get_info {
+ __le32 reserved;
+} __packed; /* GRP_REGULATORY_NVM_GET_INFO_CMD_S_VER_1 */
+
+/**
+ * struct iwl_nvm_get_info_general - general NVM data
+ * @flags: 1 - empty, 0 - valid
+ * @nvm_version: nvm version
+ * @board_type: board type
+ */
+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 */
+
+/**
+ * struct iwl_nvm_get_info_sku - mac information
+ * @enable_24g: band 2.4G enabled
+ * @enable_5g: band 5G enabled
+ * @enable_11n: 11n enabled
+ * @enable_11ac: 11ac enabled
+ * @mimo_disable: MIMO enabled
+ * @ext_crypto: Extended crypto enabled
+ */
+struct iwl_nvm_get_info_sku {
+ __le32 enable_24g;
+ __le32 enable_5g;
+ __le32 enable_11n;
+ __le32 enable_11ac;
+ __le32 mimo_disable;
+ __le32 ext_crypto;
+} __packed; /* GRP_REGULATORY_NVM_GET_INFO_MAC_SKU_SECTION_S_VER_1 */
+
+/**
+ * struct iwl_nvm_get_info_phy - phy information
+ * @tx_chains: BIT 0 chain A, BIT 1 chain B
+ * @rx_chains: BIT 0 chain A, BIT 1 chain B
+ */
+struct iwl_nvm_get_info_phy {
+ __le32 tx_chains;
+ __le32 rx_chains;
+} __packed; /* GRP_REGULATORY_NVM_GET_INFO_PHY_SKU_SECTION_S_VER_1 */
+
+#define IWL_NUM_CHANNELS (51)
+
+/**
+ * struct iwl_nvm_get_info_regulatory - regulatory information
+ * @lar_enabled: is LAR enabled
+ * @channel_profile: regulatory data of this channel
+ * @regulatory: regulatory data, see &enum iwl_nvm_channel_flags for data
+ */
+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 */
+
+/**
+ * struct iwl_nvm_get_info_rsp - response to get NVM data
+ * @general: general NVM data
+ * @mac_sku: data relating to MAC sku
+ * @phy_sku: data relating to PHY sku
+ * @regulatory: regulatory data
+ */
+struct iwl_nvm_get_info_rsp {
+ struct iwl_nvm_get_info_general general;
+ 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_1 */
+
+/**
+ * struct iwl_mvm_antenna_coupling_notif - antenna coupling notification
+ * @isolation: antenna isolation value
+ */
+struct iwl_mvm_antenna_coupling_notif {
+ __le32 isolation;
+} __packed;
+
#endif /* __fw_api_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
index c8712e6eea74..c66baf1e1443 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
@@ -640,18 +640,21 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
}
/* Make room for PRPH registers */
- for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr_comm); i++) {
- /* The range includes both boundaries */
- int num_bytes_in_chunk =
- iwl_prph_dump_addr_comm[i].end -
- iwl_prph_dump_addr_comm[i].start + 4;
-
- prph_len += sizeof(*dump_data) +
- sizeof(struct iwl_fw_error_dump_prph) +
- num_bytes_in_chunk;
+ if (!mvm->trans->cfg->gen2) {
+ for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr_comm);
+ i++) {
+ /* The range includes both boundaries */
+ int num_bytes_in_chunk =
+ iwl_prph_dump_addr_comm[i].end -
+ iwl_prph_dump_addr_comm[i].start + 4;
+
+ prph_len += sizeof(*dump_data) +
+ sizeof(struct iwl_fw_error_dump_prph) +
+ num_bytes_in_chunk;
+ }
}
- if (mvm->cfg->mq_rx_supported) {
+ if (!mvm->trans->cfg->gen2 && mvm->cfg->mq_rx_supported) {
for (i = 0; i <
ARRAY_SIZE(iwl_prph_dump_addr_9000); i++) {
/* The range includes both boundaries */
@@ -691,7 +694,8 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
}
/* Make room for fw's virtual image pages, if it exists */
- if (mvm->fw->img[mvm->cur_ucode].paging_mem_size &&
+ if (!mvm->trans->cfg->gen2 &&
+ mvm->fw->img[mvm->cur_ucode].paging_mem_size &&
mvm->fw_paging_db[0].fw_paging_block)
file_len += mvm->num_of_paging_blk *
(sizeof(*dump_data) +
@@ -704,14 +708,6 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
sizeof(*dump_info);
}
- /*
- * In 8000 HW family B-step include the ICCM (which resides separately)
- */
- if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
- CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_B_STEP)
- file_len += sizeof(*dump_data) + sizeof(*dump_mem) +
- IWL8260_ICCM_LEN;
-
if (mvm->fw_dump_desc)
file_len += sizeof(*dump_data) + sizeof(*dump_trig) +
mvm->fw_dump_desc->len;
@@ -836,21 +832,9 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
dump_data = iwl_fw_error_next_data(dump_data);
}
- if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
- CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_B_STEP) {
- dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
- dump_data->len = cpu_to_le32(IWL8260_ICCM_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(IWL8260_ICCM_OFFSET);
- iwl_trans_read_mem_bytes(mvm->trans, IWL8260_ICCM_OFFSET,
- dump_mem->data, IWL8260_ICCM_LEN);
- dump_data = iwl_fw_error_next_data(dump_data);
- }
-
/* Dump fw's virtual image */
- if (mvm->fw->img[mvm->cur_ucode].paging_mem_size &&
+ if (!mvm->trans->cfg->gen2 &&
+ mvm->fw->img[mvm->cur_ucode].paging_mem_size &&
mvm->fw_paging_db[0].fw_paging_block) {
for (i = 1; i < mvm->num_of_paging_blk + 1; i++) {
struct iwl_fw_error_dump_paging *paging;
@@ -943,7 +927,7 @@ int iwl_mvm_fw_dbg_collect_desc(struct iwl_mvm *mvm,
mvm->fw_dump_desc = desc;
mvm->fw_dump_trig = trigger;
- queue_delayed_work(system_wq, &mvm->fw_dump_wk, delay);
+ schedule_delayed_work(&mvm->fw_dump_wk, delay);
return 0;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index e6c9528eeeda..24cc406d87ef 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -384,20 +384,23 @@ static int iwl_save_fw_paging(struct iwl_mvm *mvm,
/* send paging cmd to FW in case CPU2 has paging image */
static int iwl_send_paging_cmd(struct iwl_mvm *mvm, const struct fw_img *fw)
{
- struct iwl_fw_paging_cmd paging_cmd = {
- .flags =
+ union {
+ struct iwl_fw_paging_cmd v2;
+ struct iwl_fw_paging_cmd_v1 v1;
+ } paging_cmd = {
+ .v2.flags =
cpu_to_le32(PAGING_CMD_IS_SECURED |
PAGING_CMD_IS_ENABLED |
(mvm->num_of_pages_in_last_blk <<
PAGING_CMD_NUM_OF_PAGES_IN_LAST_GRP_POS)),
- .block_size = cpu_to_le32(BLOCK_2_EXP_SIZE),
- .block_num = cpu_to_le32(mvm->num_of_paging_blk),
+ .v2.block_size = cpu_to_le32(BLOCK_2_EXP_SIZE),
+ .v2.block_num = cpu_to_le32(mvm->num_of_paging_blk),
};
- int blk_idx, size = sizeof(paging_cmd);
+ int blk_idx, size = sizeof(paging_cmd.v2);
/* A bit hard coded - but this is the old API and will be deprecated */
if (!iwl_mvm_has_new_tx_api(mvm))
- size -= NUM_OF_FW_PAGING_BLOCKS * 4;
+ size = sizeof(paging_cmd.v1);
/* loop for for all paging blocks + CSS block */
for (blk_idx = 0; blk_idx < mvm->num_of_paging_blk + 1; blk_idx++) {
@@ -408,11 +411,11 @@ static int iwl_send_paging_cmd(struct iwl_mvm *mvm, const struct fw_img *fw)
if (iwl_mvm_has_new_tx_api(mvm)) {
__le64 phy_addr = cpu_to_le64(addr);
- paging_cmd.device_phy_addr.addr64[blk_idx] = phy_addr;
+ paging_cmd.v2.device_phy_addr[blk_idx] = phy_addr;
} else {
__le32 phy_addr = cpu_to_le32(addr);
- paging_cmd.device_phy_addr.addr32[blk_idx] = phy_addr;
+ paging_cmd.v1.device_phy_addr[blk_idx] = phy_addr;
}
}
@@ -619,7 +622,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
if (WARN_ON(!fw))
return -EINVAL;
mvm->cur_ucode = ucode_type;
- mvm->ucode_loaded = false;
+ clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
iwl_init_notification_wait(&mvm->notif_wait, &alive_wait,
alive_cmd, ARRAY_SIZE(alive_cmd),
@@ -641,12 +644,12 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
if (ret) {
struct iwl_trans *trans = mvm->trans;
- if (trans->cfg->gen2)
+ if (trans->cfg->device_family == IWL_DEVICE_FAMILY_A000)
IWL_ERR(mvm,
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
iwl_read_prph(trans, UMAG_SB_CPU_1_STATUS),
iwl_read_prph(trans, UMAG_SB_CPU_2_STATUS));
- else if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+ else if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000)
IWL_ERR(mvm,
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
iwl_read_prph(trans, SB_CPU_1_STATUS),
@@ -693,7 +696,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
for (i = 0; i < IEEE80211_MAX_QUEUES; i++)
atomic_set(&mvm->mac80211_queue_stop_count[i], 0);
- mvm->ucode_loaded = true;
+ set_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
return 0;
}
@@ -738,9 +741,13 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
goto error;
}
- /* Read the NVM only at driver load time, no need to do this twice */
- if (read_nvm) {
- /* Read nvm */
+ /* Load NVM to NIC if needed */
+ if (mvm->nvm_file_name) {
+ iwl_mvm_read_external_nvm(mvm);
+ iwl_mvm_load_nvm_to_nic(mvm);
+ }
+
+ if (IWL_MVM_PARSE_NVM && read_nvm) {
ret = iwl_nvm_init(mvm, true);
if (ret) {
IWL_ERR(mvm, "Failed to read NVM: %d\n", ret);
@@ -748,14 +755,6 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
}
}
- /* In case we read the NVM from external file, load it to the NIC */
- if (mvm->nvm_file_name)
- iwl_mvm_load_nvm_to_nic(mvm);
-
- ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans);
- if (WARN_ON(ret))
- goto error;
-
ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(REGULATORY_AND_NVM_GROUP,
NVM_ACCESS_COMPLETE), 0,
sizeof(nvm_complete), &nvm_complete);
@@ -766,8 +765,21 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
}
/* We wait for the INIT complete notification */
- return iwl_wait_notification(&mvm->notif_wait, &init_wait,
- MVM_UCODE_ALIVE_TIMEOUT);
+ ret = iwl_wait_notification(&mvm->notif_wait, &init_wait,
+ MVM_UCODE_ALIVE_TIMEOUT);
+ if (ret)
+ return ret;
+
+ /* Read the NVM only at driver load time, no need to do this twice */
+ if (!IWL_MVM_PARSE_NVM && read_nvm) {
+ ret = iwl_mvm_nvm_get_from_fw(mvm);
+ if (ret) {
+ IWL_ERR(mvm, "Failed to read NVM: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
error:
iwl_remove_notification(&mvm->notif_wait, &init_wait);
@@ -1627,7 +1639,8 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
IWL_DEBUG_INFO(mvm, "RT uCode started.\n");
return 0;
error:
- iwl_mvm_stop_device(mvm);
+ if (!iwlmvm_mod_params.init_dbg)
+ iwl_mvm_stop_device(mvm);
return ret;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/led.c b/drivers/net/wireless/intel/iwlwifi/mvm/led.c
index 1e51fbe95f7c..3cac4278a5fd 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/led.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/led.c
@@ -123,14 +123,17 @@ int iwl_mvm_leds_init(struct iwl_mvm *mvm)
return ret;
}
+ mvm->init_status |= IWL_MVM_INIT_STATUS_LEDS_INIT_COMPLETE;
return 0;
}
void iwl_mvm_leds_exit(struct iwl_mvm *mvm)
{
- if (iwlwifi_mod_params.led_mode == IWL_LED_DISABLE)
+ if (iwlwifi_mod_params.led_mode == IWL_LED_DISABLE ||
+ !(mvm->init_status & IWL_MVM_INIT_STATUS_LEDS_INIT_COMPLETE))
return;
led_classdev_unregister(&mvm->led);
kfree(mvm->led.name);
+ mvm->init_status &= ~IWL_MVM_INIT_STATUS_LEDS_INIT_COMPLETE;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index 15d13017c1df..baf2c39a82fd 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -1632,9 +1632,9 @@ void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
IWL_DEBUG_INFO(mvm, "Channel Switch Started Notification\n");
- queue_delayed_work(system_wq, &mvm->cs_tx_unblock_dwork,
- msecs_to_jiffies(IWL_MVM_CS_UNBLOCK_TX_TIMEOUT *
- csa_vif->bss_conf.beacon_int));
+ schedule_delayed_work(&mvm->cs_tx_unblock_dwork,
+ msecs_to_jiffies(IWL_MVM_CS_UNBLOCK_TX_TIMEOUT *
+ csa_vif->bss_conf.beacon_int));
ieee80211_csa_finish(csa_vif);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index a67aa1f5a51c..08f86e77eba5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -735,6 +735,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
ret = ieee80211_register_hw(mvm->hw);
if (ret)
iwl_mvm_leds_exit(mvm);
+ mvm->init_status |= IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE;
if (mvm->cfg->vht_mu_mimo_supported)
wiphy_ext_feature_set(hw->wiphy,
@@ -1243,6 +1244,17 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
flush_work(&mvm->d0i3_exit_work);
flush_work(&mvm->async_handlers_wk);
flush_work(&mvm->add_stream_wk);
+
+ /*
+ * Lock and clear the firmware running bit here already, so that
+ * new commands coming in elsewhere, e.g. from debugfs, will not
+ * be able to proceed. This is important here because one of those
+ * debugfs files causes the fw_dump_wk to be triggered, and if we
+ * don't stop debugfs accesses before canceling that it could be
+ * retriggered after we flush it but before we've cleared the bit.
+ */
+ clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
+
cancel_delayed_work_sync(&mvm->fw_dump_wk);
cancel_delayed_work_sync(&mvm->cs_tx_unblock_dwork);
cancel_delayed_work_sync(&mvm->scan_timeout_dwork);
@@ -1451,7 +1463,7 @@ static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
{
u32 tfd_msk = iwl_mvm_mac_get_queues_mask(vif);
- if (tfd_msk) {
+ if (tfd_msk && !iwl_mvm_is_dqa_supported(mvm)) {
/*
* mac80211 first removes all the stations of the vif and
* then removes the vif. When it removes a station it also
@@ -1460,6 +1472,8 @@ static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
* of these AMPDU sessions are properly closed.
* We still need to take care of the shared queues of the vif.
* Flush them here.
+ * For DQA mode there is no need - broacast and multicast queue
+ * are flushed separately.
*/
mutex_lock(&mvm->mutex);
iwl_mvm_flush_tx_path(mvm, tfd_msk, 0);
@@ -3988,21 +4002,23 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
/* make sure only TDLS peers or the AP are flushed */
WARN_ON(i != mvmvif->ap_sta_id && !sta->tdls);
- msk |= mvmsta->tfd_queue_msk;
+ if (drop) {
+ if (iwl_mvm_flush_sta(mvm, mvmsta, false, 0))
+ IWL_ERR(mvm, "flush request fail\n");
+ } else {
+ msk |= mvmsta->tfd_queue_msk;
+ if (iwl_mvm_has_new_tx_api(mvm))
+ iwl_mvm_wait_sta_queues_empty(mvm, mvmsta);
+ }
}
- if (drop) {
- if (iwl_mvm_flush_tx_path(mvm, msk, 0))
- IWL_ERR(mvm, "flush request fail\n");
- mutex_unlock(&mvm->mutex);
- } else {
- mutex_unlock(&mvm->mutex);
+ mutex_unlock(&mvm->mutex);
- /* this can take a while, and we may need/want other operations
- * to succeed while doing this, so do it without the mutex held
- */
+ /* this can take a while, and we may need/want other operations
+ * to succeed while doing this, so do it without the mutex held
+ */
+ if (!drop && !iwl_mvm_has_new_tx_api(mvm))
iwl_trans_wait_tx_queues_empty(mvm->trans, msk);
- }
}
static int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,
@@ -4023,7 +4039,7 @@ static int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,
mutex_lock(&mvm->mutex);
- if (mvm->ucode_loaded) {
+ if (iwl_mvm_firmware_running(mvm)) {
ret = iwl_mvm_request_statistics(mvm, false);
if (ret)
goto out;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 52f8d7a6a7dc..9a9163f64553 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -754,6 +754,8 @@ struct iwl_mvm {
struct work_struct roc_done_wk;
+ unsigned long init_status;
+
unsigned long status;
u32 queue_sync_cookie;
@@ -765,7 +767,6 @@ struct iwl_mvm {
struct iwl_mvm_vif *bf_allowed_vif;
enum iwl_ucode_type cur_ucode;
- bool ucode_loaded;
bool hw_registered;
bool calibrating;
u32 error_event_table[2];
@@ -1086,6 +1087,15 @@ enum iwl_mvm_status {
IWL_MVM_STATUS_ROC_AUX_RUNNING,
IWL_MVM_STATUS_D3_RECONFIG,
IWL_MVM_STATUS_DUMPING_FW_LOG,
+ IWL_MVM_STATUS_FIRMWARE_RUNNING,
+};
+
+/* Keep track of completed init configuration */
+enum iwl_mvm_init_status {
+ IWL_MVM_INIT_STATUS_THERMAL_INIT_COMPLETE = BIT(0),
+ IWL_MVM_INIT_STATUS_LEDS_INIT_COMPLETE = BIT(1),
+ IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE = BIT(2),
+ IWL_MVM_INIT_STATUS_TOF_INIT_COMPLETE = BIT(3),
};
static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm)
@@ -1099,6 +1109,11 @@ static inline bool iwl_mvm_is_radio_hw_killed(struct iwl_mvm *mvm)
return test_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
}
+static inline bool iwl_mvm_firmware_running(struct iwl_mvm *mvm)
+{
+ return test_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
+}
+
/* Must be called with rcu_read_lock() held and it can only be
* released when mvmsta is not needed anymore.
*/
@@ -1188,7 +1203,7 @@ static inline bool iwl_mvm_is_lar_supported(struct iwl_mvm *mvm)
* Enable LAR only if it is supported by the FW (TLV) &&
* enabled in the NVM
*/
- if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+ if (mvm->cfg->ext_nvm)
return nvm_lar && tlv_lar;
else
return tlv_lar;
@@ -1355,6 +1370,8 @@ const char *iwl_mvm_get_tx_fail_reason(u32 status);
static inline const char *iwl_mvm_get_tx_fail_reason(u32 status) { return ""; }
#endif
int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, u32 flags);
+int iwl_mvm_flush_sta(struct iwl_mvm *mvm, void *sta, bool int_sta, u32 flags);
+
void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm);
static inline void iwl_mvm_set_tx_cmd_ccmp(struct ieee80211_tx_info *info,
@@ -1381,7 +1398,9 @@ void iwl_mvm_accu_radio_stats(struct iwl_mvm *mvm);
/* NVM */
int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic);
+int iwl_mvm_nvm_get_from_fw(struct iwl_mvm *mvm);
int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm);
+int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm);
static inline u8 iwl_mvm_get_valid_tx_ant(struct iwl_mvm *mvm)
{
@@ -1755,7 +1774,7 @@ static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm)
{
if (!iwl_mvm_has_new_tx_api(mvm))
iwl_free_fw_paging(mvm);
- mvm->ucode_loaded = false;
+ clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
mvm->fw_dbg_conf = FW_DBG_INVALID;
iwl_trans_stop_device(mvm->trans);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
index 283c41df622c..87b9ebfc653e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
@@ -77,7 +77,7 @@
/* Default NVM size to read */
#define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024)
#define IWL_MAX_NVM_SECTION_SIZE 0x1b58
-#define IWL_MAX_NVM_8000_SECTION_SIZE 0x1ffc
+#define IWL_MAX_EXT_NVM_SECTION_SIZE 0x1ffc
#define NVM_WRITE_OPCODE 1
#define NVM_READ_OPCODE 0
@@ -300,7 +300,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
bool lar_enabled;
/* Checking for required sections */
- if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+ if (!mvm->trans->cfg->ext_nvm) {
if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
!mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) {
IWL_ERR(mvm, "Can't parse empty OTP/NVM sections\n");
@@ -374,7 +374,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
*
* 4. save as "iNVM_xxx.bin" under /lib/firmware
*/
-static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
+int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
{
int ret, section_size;
u16 section_id;
@@ -391,19 +391,19 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
#define NVM_WORD1_LEN(x) (8 * (x & 0x03FF))
#define NVM_WORD2_ID(x) (x >> 12)
-#define NVM_WORD2_LEN_FAMILY_8000(x) (2 * ((x & 0xFF) << 8 | x >> 8))
-#define NVM_WORD1_ID_FAMILY_8000(x) (x >> 4)
+#define EXT_NVM_WORD2_LEN(x) (2 * (((x) & 0xFF) << 8 | (x) >> 8))
+#define EXT_NVM_WORD1_ID(x) ((x) >> 4)
#define NVM_HEADER_0 (0x2A504C54)
#define NVM_HEADER_1 (0x4E564D2A)
#define NVM_HEADER_SIZE (4 * sizeof(u32))
IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n");
- /* Maximal size depends on HW family and step */
- if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ /* Maximal size depends on NVM version */
+ if (!mvm->trans->cfg->ext_nvm)
max_section_size = IWL_MAX_NVM_SECTION_SIZE;
else
- max_section_size = IWL_MAX_NVM_8000_SECTION_SIZE;
+ max_section_size = IWL_MAX_EXT_NVM_SECTION_SIZE;
/*
* Obtain NVM image via request_firmware. Since we already used
@@ -447,10 +447,9 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
le32_to_cpu(dword_buff[3]));
/* nvm file validation, dword_buff[2] holds the file version */
- if ((CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_C_STEP &&
- le32_to_cpu(dword_buff[2]) < 0xE4A) ||
- (CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_B_STEP &&
- le32_to_cpu(dword_buff[2]) >= 0xE4A)) {
+ if (mvm->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
+ CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_C_STEP &&
+ le32_to_cpu(dword_buff[2]) < 0xE4A) {
ret = -EFAULT;
goto out;
}
@@ -472,14 +471,14 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
break;
}
- if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+ if (!mvm->trans->cfg->ext_nvm) {
section_size =
2 * NVM_WORD1_LEN(le16_to_cpu(file_sec->word1));
section_id = NVM_WORD2_ID(le16_to_cpu(file_sec->word2));
} else {
- section_size = 2 * NVM_WORD2_LEN_FAMILY_8000(
+ section_size = 2 * EXT_NVM_WORD2_LEN(
le16_to_cpu(file_sec->word2));
- section_id = NVM_WORD1_ID_FAMILY_8000(
+ section_id = EXT_NVM_WORD1_ID(
le16_to_cpu(file_sec->word1));
}
@@ -551,12 +550,99 @@ int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm)
return ret;
}
+int iwl_mvm_nvm_get_from_fw(struct iwl_mvm *mvm)
+{
+ struct iwl_nvm_get_info cmd = {};
+ struct iwl_nvm_get_info_rsp *rsp;
+ struct iwl_trans *trans = mvm->trans;
+ struct iwl_host_cmd hcmd = {
+ .flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
+ .data = { &cmd, },
+ .len = { sizeof(cmd) },
+ .id = WIDE_ID(REGULATORY_AND_NVM_GROUP, NVM_GET_INFO)
+ };
+ int ret;
+ bool lar_fw_supported = !iwlwifi_mod_params.lar_disable &&
+ fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_LAR_SUPPORT);
+
+ lockdep_assert_held(&mvm->mutex);
+
+ ret = iwl_mvm_send_cmd(mvm, &hcmd);
+ if (ret)
+ return ret;
+
+ if (WARN(iwl_rx_packet_payload_len(hcmd.resp_pkt) != sizeof(*rsp),
+ "Invalid payload len in NVM response from FW %d",
+ iwl_rx_packet_payload_len(hcmd.resp_pkt))) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ rsp = (void *)hcmd.resp_pkt->data;
+ if (le32_to_cpu(rsp->general.flags)) {
+ IWL_ERR(mvm, "Invalid NVM data from FW\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ mvm->nvm_data = kzalloc(sizeof(*mvm->nvm_data) +
+ sizeof(struct ieee80211_channel) *
+ IWL_NUM_CHANNELS, GFP_KERNEL);
+ if (!mvm->nvm_data) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ iwl_set_hw_address_from_csr(trans, mvm->nvm_data);
+ /* TODO: if platform NVM has MAC address - override it here */
+
+ if (!is_valid_ether_addr(mvm->nvm_data->hw_addr)) {
+ IWL_ERR(trans, "no valid mac address was found\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* Initialize general data */
+ mvm->nvm_data->nvm_version = le16_to_cpu(rsp->general.nvm_version);
+
+ /* Initialize MAC sku data */
+ mvm->nvm_data->sku_cap_11ac_enable =
+ le32_to_cpu(rsp->mac_sku.enable_11ac);
+ mvm->nvm_data->sku_cap_11n_enable =
+ le32_to_cpu(rsp->mac_sku.enable_11n);
+ mvm->nvm_data->sku_cap_band_24GHz_enable =
+ le32_to_cpu(rsp->mac_sku.enable_24g);
+ mvm->nvm_data->sku_cap_band_52GHz_enable =
+ le32_to_cpu(rsp->mac_sku.enable_5g);
+ mvm->nvm_data->sku_cap_mimo_disabled =
+ le32_to_cpu(rsp->mac_sku.mimo_disable);
+
+ /* Initialize PHY sku data */
+ mvm->nvm_data->valid_tx_ant = (u8)le32_to_cpu(rsp->phy_sku.tx_chains);
+ mvm->nvm_data->valid_rx_ant = (u8)le32_to_cpu(rsp->phy_sku.rx_chains);
+
+ /* Initialize regulatory data */
+ mvm->nvm_data->lar_enabled =
+ le32_to_cpu(rsp->regulatory.lar_enabled) && lar_fw_supported;
+
+ iwl_init_sbands(trans->dev, trans->cfg, mvm->nvm_data,
+ rsp->regulatory.channel_profile,
+ mvm->nvm_data->valid_tx_ant & mvm->fw->valid_tx_ant,
+ mvm->nvm_data->valid_rx_ant & mvm->fw->valid_rx_ant,
+ rsp->regulatory.lar_enabled && lar_fw_supported);
+
+ ret = 0;
+out:
+ iwl_free_resp(&hcmd);
+ return ret;
+}
+
int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic)
{
int ret, section;
u32 size_read = 0;
u8 *nvm_buffer, *temp;
- const char *nvm_file_B = mvm->cfg->default_nvm_file_B_step;
const char *nvm_file_C = mvm->cfg->default_nvm_file_C_step;
if (WARN_ON_ONCE(mvm->cfg->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS))
@@ -626,14 +712,7 @@ int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic)
/* read External NVM file from the mod param */
ret = iwl_mvm_read_external_nvm(mvm);
if (ret) {
- /* choose the nvm_file name according to the
- * HW step
- */
- if (CSR_HW_REV_STEP(mvm->trans->hw_rev) ==
- SILICON_B_STEP)
- mvm->nvm_file_name = nvm_file_B;
- else
- mvm->nvm_file_name = nvm_file_C;
+ mvm->nvm_file_name = nvm_file_C;
if ((ret == -EFAULT || ret == -ENOENT) &&
mvm->nvm_file_name) {
@@ -758,7 +837,7 @@ int iwl_mvm_init_mcc(struct iwl_mvm *mvm)
struct ieee80211_regdomain *regd;
char mcc[3];
- if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
+ if (mvm->cfg->ext_nvm) {
tlv_lar = fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_LAR_SUPPORT);
nvm_lar = mvm->nvm_data->lar_enabled;
@@ -825,8 +904,8 @@ void iwl_mvm_rx_chub_update_mcc(struct iwl_mvm *mvm,
if (WARN_ON_ONCE(!iwl_mvm_is_lar_supported(mvm)))
return;
- mcc[0] = notif->mcc >> 8;
- mcc[1] = notif->mcc & 0xff;
+ mcc[0] = le16_to_cpu(notif->mcc) >> 8;
+ mcc[1] = le16_to_cpu(notif->mcc) & 0xff;
mcc[2] = '\0';
src = notif->source_id;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 3da5ec40aaea..1da55e4a1048 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -7,6 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -33,7 +34,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -172,13 +173,14 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
~CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE);
/*
- * TODO: Bits 7-8 of CSR in 8000 HW family set the ADC sampling, and
- * shouldn't be set to any non-zero value. The same is supposed to be
- * true of the other HW, but unsetting them (such as the 7260) causes
- * automatic tests to fail on seemingly unrelated errors. Need to
- * further investigate this, but for now we'll separate cases.
+ * TODO: Bits 7-8 of CSR in 8000 HW family and higher set the ADC
+ * sampling, and shouldn't be set to any non-zero value.
+ * The same is supposed to be true of the other HW, but unsetting
+ * them (such as the 7260) causes automatic tests to fail on seemingly
+ * unrelated errors. Need to further investigate this, but for now
+ * we'll separate cases.
*/
- if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ if (mvm->trans->cfg->device_family < IWL_DEVICE_FAMILY_8000)
reg_val |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI;
iwl_trans_set_bits_mask(mvm->trans, CSR_HW_IF_CONFIG_REG,
@@ -483,6 +485,7 @@ static const struct iwl_hcmd_names iwl_mvm_prot_offload_names[] = {
*/
static const struct iwl_hcmd_names iwl_mvm_regulatory_and_nvm_names[] = {
HCMD_NAME(NVM_ACCESS_COMPLETE),
+ HCMD_NAME(NVM_GET_INFO),
};
static const struct iwl_hcmd_arr iwl_mvm_groups[] = {
@@ -588,6 +591,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mvm->fw = fw;
mvm->hw = hw;
+ mvm->init_status = 0;
+
if (iwl_mvm_has_new_rx_api(mvm)) {
op_mode->ops = &iwl_mvm_ops_mq;
trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_desc);
@@ -752,7 +757,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
iwl_mvm_unref(mvm, IWL_MVM_REF_INIT_UCODE);
mutex_unlock(&mvm->mutex);
/* returns 0 if successful, 1 if success but in rfkill */
- if (err < 0 && !iwlmvm_mod_params.init_dbg) {
+ if (err < 0) {
IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", err);
goto out_free;
}
@@ -790,12 +795,18 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
return op_mode;
out_unregister:
+ if (iwlmvm_mod_params.init_dbg)
+ return op_mode;
+
ieee80211_unregister_hw(mvm->hw);
mvm->hw_registered = false;
iwl_mvm_leds_exit(mvm);
iwl_mvm_thermal_exit(mvm);
out_free:
flush_delayed_work(&mvm->fw_dump_wk);
+
+ if (iwlmvm_mod_params.init_dbg)
+ return op_mode;
iwl_phy_db_free(mvm->phy_db);
kfree(mvm->scan_cmd);
iwl_trans_op_mode_leave(trans);
@@ -820,7 +831,10 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
iwl_mvm_thermal_exit(mvm);
- ieee80211_unregister_hw(mvm->hw);
+ if (mvm->init_status & IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE) {
+ ieee80211_unregister_hw(mvm->hw);
+ mvm->init_status &= ~IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE;
+ }
kfree(mvm->scan_cmd);
kfree(mvm->mcast_filter_cmd);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index 8d1b994ae79f..d48c2ecc0893 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -1421,8 +1421,8 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
mvm->scan_vif = iwl_mvm_vif_from_mac80211(vif);
iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN);
- queue_delayed_work(system_wq, &mvm->scan_timeout_dwork,
- msecs_to_jiffies(SCAN_TIMEOUT));
+ schedule_delayed_work(&mvm->scan_timeout_dwork,
+ msecs_to_jiffies(SCAN_TIMEOUT));
return 0;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 614d67810d05..bc52739eeb25 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -1590,6 +1590,29 @@ static void iwl_mvm_disable_sta_queues(struct iwl_mvm *mvm,
}
}
+int iwl_mvm_wait_sta_queues_empty(struct iwl_mvm *mvm,
+ struct iwl_mvm_sta *mvm_sta)
+{
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(mvm_sta->tid_data); i++) {
+ u16 txq_id;
+
+ spin_lock_bh(&mvm_sta->lock);
+ txq_id = mvm_sta->tid_data[i].txq_id;
+ spin_unlock_bh(&mvm_sta->lock);
+
+ if (txq_id == IWL_MVM_INVALID_QUEUE)
+ continue;
+
+ ret = iwl_trans_wait_txq_empty(mvm->trans, txq_id);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
@@ -1611,11 +1634,17 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
if (ret)
return ret;
/* flush its queues here since we are freeing mvm_sta */
- ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, 0);
+ ret = iwl_mvm_flush_sta(mvm, mvm_sta, false, 0);
if (ret)
return ret;
- ret = iwl_trans_wait_tx_queues_empty(mvm->trans,
- mvm_sta->tfd_queue_msk);
+ if (iwl_mvm_has_new_tx_api(mvm)) {
+ ret = iwl_mvm_wait_sta_queues_empty(mvm, mvm_sta);
+ } else {
+ u32 q_mask = mvm_sta->tfd_queue_msk;
+
+ ret = iwl_trans_wait_tx_queues_empty(mvm->trans,
+ q_mask);
+ }
if (ret)
return ret;
ret = iwl_mvm_drain_sta(mvm, mvm_sta, false);
@@ -1978,6 +2007,8 @@ static void iwl_mvm_free_bcast_sta_queues(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex);
+ iwl_mvm_flush_sta(mvm, &mvmvif->bcast_sta, true, 0);
+
if (vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_ADHOC)
iwl_mvm_disable_txq(mvm, vif->cab_queue, vif->cab_queue,
@@ -2187,6 +2218,8 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if (!iwl_mvm_is_dqa_supported(mvm))
return 0;
+ iwl_mvm_flush_sta(mvm, &mvmvif->mcast_sta, true, 0);
+
iwl_mvm_disable_txq(mvm, mvmvif->cab_queue, vif->cab_queue,
IWL_MAX_TID_COUNT, 0);
@@ -2857,8 +2890,13 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
iwl_mvm_drain_sta(mvm, mvmsta, true);
if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), 0))
IWL_ERR(mvm, "Couldn't flush the AGG queue\n");
- iwl_trans_wait_tx_queues_empty(mvm->trans,
- mvmsta->tfd_queue_msk);
+
+ if (iwl_mvm_has_new_tx_api(mvm))
+ iwl_trans_wait_txq_empty(mvm->trans, txq_id);
+
+ else
+ iwl_trans_wait_tx_queues_empty(mvm->trans, BIT(txq_id));
+
iwl_mvm_drain_sta(mvm, mvmsta, false);
iwl_mvm_sta_tx_agg(mvm, sta, tid, txq_id, false);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index ad62b67dceb2..357ff2bf75c1 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -489,6 +489,8 @@ static inline int iwl_mvm_update_sta(struct iwl_mvm *mvm,
return iwl_mvm_sta_send_to_fw(mvm, sta, true, 0);
}
+int iwl_mvm_wait_sta_queues_empty(struct iwl_mvm *mvm,
+ struct iwl_mvm_sta *mvm_sta);
int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
index df7cd87199ea..3d97436bbdf5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
@@ -551,8 +551,7 @@ void iwl_mvm_tdls_ch_switch_work(struct work_struct *work)
/* retry after a DTIM if we failed sending now */
delay = TU_TO_MS(vif->bss_conf.dtim_period * vif->bss_conf.beacon_int);
- queue_delayed_work(system_wq, &mvm->tdls_cs.dwork,
- msecs_to_jiffies(delay));
+ schedule_delayed_work(&mvm->tdls_cs.dwork, msecs_to_jiffies(delay));
out:
mutex_unlock(&mvm->mutex);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
index 2c12789e7550..3e4fa853b44d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
@@ -130,7 +130,10 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
* issue as it will have to complete before the next command is
* executed, and a new time event means a new command.
*/
- iwl_mvm_flush_tx_path(mvm, queues, CMD_ASYNC);
+ if (iwl_mvm_is_dqa_supported(mvm))
+ iwl_mvm_flush_sta(mvm, &mvm->aux_sta, true, CMD_ASYNC);
+ else
+ iwl_mvm_flush_tx_path(mvm, queues, CMD_ASYNC);
}
static void iwl_mvm_roc_finished(struct iwl_mvm *mvm)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tof.c b/drivers/net/wireless/intel/iwlwifi/mvm/tof.c
index 16ce8a56b5b9..634175b2480c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tof.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tof.c
@@ -93,17 +93,21 @@ void iwl_mvm_tof_init(struct iwl_mvm *mvm)
cpu_to_le32(TOF_RANGE_REQ_EXT_CMD);
mvm->tof_data.active_range_request = IWL_MVM_TOF_RANGE_REQ_MAX_ID;
+ mvm->init_status |= IWL_MVM_INIT_STATUS_TOF_INIT_COMPLETE;
}
void iwl_mvm_tof_clean(struct iwl_mvm *mvm)
{
struct iwl_mvm_tof_data *tof_data = &mvm->tof_data;
- if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT))
+ if (!fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_TOF_SUPPORT) ||
+ !(mvm->init_status & IWL_MVM_INIT_STATUS_TOF_INIT_COMPLETE))
return;
memset(tof_data, 0, sizeof(*tof_data));
mvm->tof_data.active_range_request = IWL_MVM_TOF_RANGE_REQ_MAX_ID;
+ mvm->init_status &= ~IWL_MVM_INIT_STATUS_TOF_INIT_COMPLETE;
}
static void iwl_tof_iterator(void *_data, u8 *mac,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
index 506d58104e1c..453a785a3ea5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
@@ -628,7 +628,8 @@ static int iwl_mvm_tzone_get_temp(struct thermal_zone_device *device,
mutex_lock(&mvm->mutex);
- if (!mvm->ucode_loaded || !(mvm->cur_ucode == IWL_UCODE_REGULAR)) {
+ if (!iwl_mvm_firmware_running(mvm) ||
+ mvm->cur_ucode != IWL_UCODE_REGULAR) {
ret = -EIO;
goto out;
}
@@ -678,7 +679,8 @@ static int iwl_mvm_tzone_set_trip_temp(struct thermal_zone_device *device,
mutex_lock(&mvm->mutex);
- if (!mvm->ucode_loaded || !(mvm->cur_ucode == IWL_UCODE_REGULAR)) {
+ if (!iwl_mvm_firmware_running(mvm) ||
+ mvm->cur_ucode != IWL_UCODE_REGULAR) {
ret = -EIO;
goto out;
}
@@ -792,7 +794,8 @@ static int iwl_mvm_tcool_set_cur_state(struct thermal_cooling_device *cdev,
mutex_lock(&mvm->mutex);
- if (!mvm->ucode_loaded || !(mvm->cur_ucode == IWL_UCODE_REGULAR)) {
+ if (!iwl_mvm_firmware_running(mvm) ||
+ mvm->cur_ucode != IWL_UCODE_REGULAR) {
ret = -EIO;
goto unlock;
}
@@ -884,10 +887,14 @@ void iwl_mvm_thermal_initialize(struct iwl_mvm *mvm, u32 min_backoff)
iwl_mvm_cooling_device_register(mvm);
iwl_mvm_thermal_zone_register(mvm);
#endif
+ mvm->init_status |= IWL_MVM_INIT_STATUS_THERMAL_INIT_COMPLETE;
}
void iwl_mvm_thermal_exit(struct iwl_mvm *mvm)
{
+ if (!(mvm->init_status & IWL_MVM_INIT_STATUS_THERMAL_INIT_COMPLETE))
+ return;
+
cancel_delayed_work_sync(&mvm->thermal_throttle.ct_kill_exit);
IWL_DEBUG_TEMP(mvm, "Exit Thermal Throttling\n");
@@ -895,4 +902,5 @@ void iwl_mvm_thermal_exit(struct iwl_mvm *mvm)
iwl_mvm_cooling_device_unregister(mvm);
iwl_mvm_thermal_zone_unregister(mvm);
#endif
+ mvm->init_status &= ~IWL_MVM_INIT_STATUS_THERMAL_INIT_COMPLETE;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index f21901cd4a4f..aa3a3f336929 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -480,8 +480,14 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
struct iwl_tx_cmd_gen2 *cmd = (void *)dev_cmd->payload;
u16 offload_assist = iwl_mvm_tx_csum(mvm, skb, hdr, info);
+ if (ieee80211_is_data_qos(hdr->frame_control)) {
+ u8 *qc = ieee80211_get_qos_ctl(hdr);
+
+ if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT)
+ offload_assist |= BIT(TX_CMD_OFFLD_AMSDU);
+ }
+
/* padding is inserted later in transport */
- /* FIXME - check for AMSDU may need to be removed */
if (ieee80211_hdrlen(hdr->frame_control) % 4 &&
!(offload_assist & BIT(TX_CMD_OFFLD_AMSDU)))
offload_assist |= BIT(TX_CMD_OFFLD_PAD);
@@ -1860,7 +1866,7 @@ out:
IWL_DEBUG_TX_REPLY(mvm,
"BA_NOTIFICATION Received from %pM, sta_id = %d\n",
- (u8 *)&ba_notif->sta_addr_lo32, ba_notif->sta_id);
+ ba_notif->sta_addr, ba_notif->sta_id);
IWL_DEBUG_TX_REPLY(mvm,
"TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = %d, scd_ssn = %d sent:%d, acked:%d\n",
@@ -1894,3 +1900,20 @@ int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, u32 flags)
IWL_ERR(mvm, "Failed to send flush command (%d)\n", ret);
return ret;
}
+
+int iwl_mvm_flush_sta(struct iwl_mvm *mvm, void *sta, bool int_sta, u32 flags)
+{
+ u32 mask;
+
+ if (int_sta) {
+ struct iwl_mvm_int_sta *int_sta = sta;
+
+ mask = int_sta->tfd_queue_msk;
+ } else {
+ struct iwl_mvm_sta *mvm_sta = sta;
+
+ mask = mvm_sta->tfd_queue_msk;
+ }
+
+ return iwl_mvm_flush_tx_path(mvm, mask, flags);
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index e51760e752d4..2d92d3708619 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -538,7 +538,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
/* a000 Series */
{IWL_PCI_DEVICE(0x2720, 0x0A10, iwla000_2ac_cfg_hr_cdb)},
- {IWL_PCI_DEVICE(0x2722, 0x0A10, iwla000_2ac_cfg_hr)},
+ {IWL_PCI_DEVICE(0x34F0, 0x0310, iwla000_2ac_cfg_jf)},
#endif /* CONFIG_IWLMVM */
{0}
@@ -672,10 +672,12 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
iwl_trans->cfg = cfg_7265d;
}
- if (iwl_trans->cfg->rf_id &&
- (cfg == &iwla000_2ac_cfg_hr || cfg == &iwla000_2ac_cfg_hr_cdb) &&
- iwl_trans->hw_rf_id == CSR_HW_RF_ID_TYPE_JF) {
- cfg = &iwla000_2ac_cfg_jf;
+ if (iwl_trans->cfg->rf_id && cfg == &iwla000_2ac_cfg_hr_cdb) {
+ if (iwl_trans->hw_rf_id == CSR_HW_RF_ID_TYPE_JF)
+ cfg = &iwla000_2ac_cfg_jf;
+ else if (iwl_trans->hw_rf_id == CSR_HW_RF_ID_TYPE_HR)
+ cfg = &iwla000_2ac_cfg_hr;
+
iwl_trans->cfg = cfg;
}
#endif
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
index fd4faaaa1484..4b7be7ba9780 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
@@ -779,6 +779,9 @@ int iwl_pcie_alloc_dma_ptr(struct iwl_trans *trans,
struct iwl_dma_ptr *ptr, size_t size);
void iwl_pcie_free_dma_ptr(struct iwl_trans *trans, struct iwl_dma_ptr *ptr);
void iwl_pcie_apply_destination(struct iwl_trans *trans);
+#ifdef CONFIG_INET
+struct iwl_tso_hdr_page *get_page_hdr(struct iwl_trans *trans, size_t len);
+#endif
/* transport gen 2 exported functions */
int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index 93cbc7a69bcd..a3c5d3b195ad 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -245,7 +245,7 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans)
*/
/* Disable L0S exit timer (platform NMI Work/Around) */
- if (trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ if (trans->cfg->device_family < IWL_DEVICE_FAMILY_8000)
iwl_set_bit(trans, CSR_GIO_CHICKEN_BITS,
CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
@@ -478,7 +478,7 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000)
iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG,
APMG_PCIDEV_STT_VAL_WAKE_ME);
- else if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
+ else if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000) {
iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
CSR_RESET_LINK_PWR_MGMT_DISABLED);
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
@@ -892,7 +892,7 @@ monitor:
if (dest->monitor_mode == EXTERNAL_MODE && trans_pcie->fw_mon_size) {
iwl_write_prph(trans, le32_to_cpu(dest->base_reg),
trans_pcie->fw_mon_phys >> dest->base_shift);
- if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+ if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000)
iwl_write_prph(trans, le32_to_cpu(dest->end_reg),
(trans_pcie->fw_mon_phys +
trans_pcie->fw_mon_size - 256) >>
@@ -1318,7 +1318,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
/* Load the given image to the HW */
- if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+ if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000)
ret = iwl_pcie_load_given_ucode_8000(trans, fw);
else
ret = iwl_pcie_load_given_ucode(trans, fw);
@@ -1435,7 +1435,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
- if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+ if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000)
udelay(2);
ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
@@ -1822,7 +1822,7 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans,
/* this bit wakes up the NIC */
__iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
- if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+ if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000)
udelay(2);
/*
@@ -2045,17 +2045,52 @@ void iwl_trans_pcie_log_scd_error(struct iwl_trans *trans, struct iwl_txq *txq)
iwl_read_direct32(trans, FH_TX_TRB_REG(fifo)));
}
-static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, u32 txq_bm)
+static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, int txq_idx)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_txq *txq;
- int cnt;
unsigned long now = jiffies;
+ u8 wr_ptr;
+
+ if (!test_bit(txq_idx, trans_pcie->queue_used))
+ return -EINVAL;
+
+ IWL_DEBUG_TX_QUEUES(trans, "Emptying queue %d...\n", txq_idx);
+ txq = trans_pcie->txq[txq_idx];
+ wr_ptr = ACCESS_ONCE(txq->write_ptr);
+
+ while (txq->read_ptr != ACCESS_ONCE(txq->write_ptr) &&
+ !time_after(jiffies,
+ now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) {
+ u8 write_ptr = ACCESS_ONCE(txq->write_ptr);
+
+ if (WARN_ONCE(wr_ptr != write_ptr,
+ "WR pointer moved while flushing %d -> %d\n",
+ wr_ptr, write_ptr))
+ return -ETIMEDOUT;
+ usleep_range(1000, 2000);
+ }
+
+ if (txq->read_ptr != txq->write_ptr) {
+ IWL_ERR(trans,
+ "fail to flush all tx fifo queues Q %d\n", txq_idx);
+ iwl_trans_pcie_log_scd_error(trans, txq);
+ return -ETIMEDOUT;
+ }
+
+ IWL_DEBUG_TX_QUEUES(trans, "Queue %d is now empty.\n", txq_idx);
+
+ return 0;
+}
+
+static int iwl_trans_pcie_wait_txqs_empty(struct iwl_trans *trans, u32 txq_bm)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ int cnt;
int ret = 0;
/* waiting for all the tx frames complete might take a while */
for (cnt = 0; cnt < trans->cfg->base_params->num_of_queues; cnt++) {
- u8 wr_ptr;
if (cnt == trans_pcie->cmd_queue)
continue;
@@ -2064,34 +2099,11 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, u32 txq_bm)
if (!(BIT(cnt) & txq_bm))
continue;
- IWL_DEBUG_TX_QUEUES(trans, "Emptying queue %d...\n", cnt);
- txq = trans_pcie->txq[cnt];
- wr_ptr = ACCESS_ONCE(txq->write_ptr);
-
- while (txq->read_ptr != ACCESS_ONCE(txq->write_ptr) &&
- !time_after(jiffies,
- now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) {
- u8 write_ptr = ACCESS_ONCE(txq->write_ptr);
-
- if (WARN_ONCE(wr_ptr != write_ptr,
- "WR pointer moved while flushing %d -> %d\n",
- wr_ptr, write_ptr))
- return -ETIMEDOUT;
- usleep_range(1000, 2000);
- }
-
- if (txq->read_ptr != txq->write_ptr) {
- IWL_ERR(trans,
- "fail to flush all tx fifo queues Q %d\n", cnt);
- ret = -ETIMEDOUT;
+ ret = iwl_trans_pcie_wait_txq_empty(trans, cnt);
+ if (ret)
break;
- }
- IWL_DEBUG_TX_QUEUES(trans, "Queue %d is now empty.\n", cnt);
}
- if (ret)
- iwl_trans_pcie_log_scd_error(trans, txq);
-
return ret;
}
@@ -2563,8 +2575,15 @@ static u32 iwl_trans_pcie_fh_regs_dump(struct iwl_trans *trans,
(*data)->len = cpu_to_le32(fh_regs_len);
val = (void *)(*data)->data;
- for (i = FH_MEM_LOWER_BOUND; i < FH_MEM_UPPER_BOUND; i += sizeof(u32))
- *val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i));
+ if (!trans->cfg->gen2)
+ for (i = FH_MEM_LOWER_BOUND; i < FH_MEM_UPPER_BOUND;
+ i += sizeof(u32))
+ *val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i));
+ else
+ for (i = FH_MEM_LOWER_BOUND_GEN2; i < FH_MEM_UPPER_BOUND_GEN2;
+ i += sizeof(u32))
+ *val++ = cpu_to_le32(iwl_trans_pcie_read_prph(trans,
+ i));
iwl_trans_release_nic_access(trans, &flags);
@@ -2714,7 +2733,7 @@ static struct iwl_trans_dump_data
trans->dbg_dest_tlv->end_shift;
/* Make "end" point to the actual end */
- if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000 ||
+ if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000 ||
trans->dbg_dest_tlv->monitor_mode == MARBH_MODE)
end += (1 << trans->dbg_dest_tlv->end_shift);
monitor_len = end - base;
@@ -2740,7 +2759,12 @@ static struct iwl_trans_dump_data
len += sizeof(*data) + IWL_CSR_TO_DUMP;
/* FH registers */
- len += sizeof(*data) + (FH_MEM_UPPER_BOUND - FH_MEM_LOWER_BOUND);
+ if (trans->cfg->gen2)
+ len += sizeof(*data) +
+ (FH_MEM_UPPER_BOUND_GEN2 - FH_MEM_LOWER_BOUND_GEN2);
+ else
+ len += sizeof(*data) +
+ (FH_MEM_UPPER_BOUND - FH_MEM_LOWER_BOUND);
if (dump_rbs) {
/* Dump RBs is supported only for pre-9000 devices (1 queue) */
@@ -2754,6 +2778,13 @@ static struct iwl_trans_dump_data
(PAGE_SIZE << trans_pcie->rx_page_order));
}
+ /* Paged memory for gen2 HW */
+ if (trans->cfg->gen2)
+ for (i = 0; i < trans_pcie->init_dram.paging_cnt; i++)
+ len += sizeof(*data) +
+ sizeof(struct iwl_fw_error_dump_paging) +
+ trans_pcie->init_dram.paging[i].size;
+
dump_data = vzalloc(len);
if (!dump_data)
return NULL;
@@ -2793,6 +2824,28 @@ static struct iwl_trans_dump_data
if (dump_rbs)
len += iwl_trans_pcie_dump_rbs(trans, &data, num_rbs);
+ /* Paged memory for gen2 HW */
+ if (trans->cfg->gen2) {
+ for (i = 0; i < trans_pcie->init_dram.paging_cnt; i++) {
+ struct iwl_fw_error_dump_paging *paging;
+ dma_addr_t addr =
+ trans_pcie->init_dram.paging[i].physical;
+ u32 page_len = trans_pcie->init_dram.paging[i].size;
+
+ data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING);
+ data->len = cpu_to_le32(sizeof(*paging) + page_len);
+ paging = (void *)data->data;
+ paging->index = cpu_to_le32(i);
+ dma_sync_single_for_cpu(trans->dev, addr, page_len,
+ DMA_BIDIRECTIONAL);
+ memcpy(paging->data,
+ trans_pcie->init_dram.paging[i].block, page_len);
+ data = iwl_fw_error_next_data(data);
+
+ len += sizeof(*data) + sizeof(*paging) + page_len;
+ }
+ }
+
len += iwl_trans_pcie_dump_monitor(trans, &data, monitor_len);
dump_data->len = len;
@@ -2835,7 +2888,6 @@ static void iwl_trans_pcie_resume(struct iwl_trans *trans)
.ref = iwl_trans_pcie_ref, \
.unref = iwl_trans_pcie_unref, \
.dump_data = iwl_trans_pcie_dump_data, \
- .wait_tx_queues_empty = iwl_trans_pcie_wait_txq_empty, \
.d3_suspend = iwl_trans_pcie_d3_suspend, \
.d3_resume = iwl_trans_pcie_d3_resume
@@ -2865,6 +2917,8 @@ static const struct iwl_trans_ops trans_ops_pcie = {
.txq_set_shared_mode = iwl_trans_pcie_txq_set_shared_mode,
+ .wait_tx_queues_empty = iwl_trans_pcie_wait_txqs_empty,
+
.freeze_txq_timer = iwl_trans_pcie_freeze_txq_timer,
.block_txq_ptrs = iwl_trans_pcie_block_txq_ptrs,
};
@@ -2884,6 +2938,7 @@ static const struct iwl_trans_ops trans_ops_pcie_gen2 = {
.txq_alloc = iwl_trans_pcie_dyn_txq_alloc,
.txq_free = iwl_trans_pcie_dyn_txq_free,
+ .wait_txq_empty = iwl_trans_pcie_wait_txq_empty,
};
struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
@@ -2988,7 +3043,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
* "dash" value). To keep hw_rev backwards compatible - we'll store it
* in the old format.
*/
- if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
+ if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000) {
unsigned long flags;
trans->hw_rev = (trans->hw_rev & 0xfff0) |
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
index 9c9bfbbabdf1..6e186501f43c 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
@@ -49,6 +49,7 @@
*
*****************************************************************************/
#include <linux/pm_runtime.h>
+#include <net/tso.h>
#include "iwl-debug.h"
#include "iwl-csr.h"
@@ -226,6 +227,143 @@ static int iwl_pcie_gen2_set_tb(struct iwl_trans *trans,
return idx;
}
+static int iwl_pcie_gen2_build_amsdu(struct iwl_trans *trans,
+ struct sk_buff *skb,
+ struct iwl_tfh_tfd *tfd, int start_len,
+ u8 hdr_len, struct iwl_device_cmd *dev_cmd)
+{
+#ifdef CONFIG_INET
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_tx_cmd *tx_cmd = (void *)dev_cmd->payload;
+ struct ieee80211_hdr *hdr = (void *)skb->data;
+ unsigned int snap_ip_tcp_hdrlen, ip_hdrlen, total_len, hdr_room;
+ unsigned int mss = skb_shinfo(skb)->gso_size;
+ u16 length, iv_len, amsdu_pad;
+ u8 *start_hdr;
+ struct iwl_tso_hdr_page *hdr_page;
+ struct page **page_ptr;
+ struct tso_t tso;
+
+ /* if the packet is protected, then it must be CCMP or GCMP */
+ iv_len = ieee80211_has_protected(hdr->frame_control) ?
+ IEEE80211_CCMP_HDR_LEN : 0;
+
+ trace_iwlwifi_dev_tx(trans->dev, skb, tfd, sizeof(*tfd),
+ &dev_cmd->hdr, start_len, NULL, 0);
+
+ ip_hdrlen = skb_transport_header(skb) - skb_network_header(skb);
+ snap_ip_tcp_hdrlen = 8 + ip_hdrlen + tcp_hdrlen(skb);
+ total_len = skb->len - snap_ip_tcp_hdrlen - hdr_len - iv_len;
+ amsdu_pad = 0;
+
+ /* total amount of header we may need for this A-MSDU */
+ hdr_room = DIV_ROUND_UP(total_len, mss) *
+ (3 + snap_ip_tcp_hdrlen + sizeof(struct ethhdr)) + iv_len;
+
+ /* Our device supports 9 segments at most, it will fit in 1 page */
+ hdr_page = get_page_hdr(trans, hdr_room);
+ if (!hdr_page)
+ return -ENOMEM;
+
+ get_page(hdr_page->page);
+ start_hdr = hdr_page->pos;
+ page_ptr = (void *)((u8 *)skb->cb + trans_pcie->page_offs);
+ *page_ptr = hdr_page->page;
+ memcpy(hdr_page->pos, skb->data + hdr_len, iv_len);
+ hdr_page->pos += iv_len;
+
+ /*
+ * Pull the ieee80211 header + IV to be able to use TSO core,
+ * we will restore it for the tx_status flow.
+ */
+ skb_pull(skb, hdr_len + iv_len);
+
+ /*
+ * Remove the length of all the headers that we don't actually
+ * have in the MPDU by themselves, but that we duplicate into
+ * all the different MSDUs inside the A-MSDU.
+ */
+ le16_add_cpu(&tx_cmd->len, -snap_ip_tcp_hdrlen);
+
+ tso_start(skb, &tso);
+
+ while (total_len) {
+ /* this is the data left for this subframe */
+ unsigned int data_left = min_t(unsigned int, mss, total_len);
+ struct sk_buff *csum_skb = NULL;
+ unsigned int tb_len;
+ dma_addr_t tb_phys;
+ struct tcphdr *tcph;
+ u8 *iph, *subf_hdrs_start = hdr_page->pos;
+
+ total_len -= data_left;
+
+ memset(hdr_page->pos, 0, amsdu_pad);
+ hdr_page->pos += amsdu_pad;
+ amsdu_pad = (4 - (sizeof(struct ethhdr) + snap_ip_tcp_hdrlen +
+ data_left)) & 0x3;
+ ether_addr_copy(hdr_page->pos, ieee80211_get_DA(hdr));
+ hdr_page->pos += ETH_ALEN;
+ ether_addr_copy(hdr_page->pos, ieee80211_get_SA(hdr));
+ hdr_page->pos += ETH_ALEN;
+
+ length = snap_ip_tcp_hdrlen + data_left;
+ *((__be16 *)hdr_page->pos) = cpu_to_be16(length);
+ hdr_page->pos += sizeof(length);
+
+ /*
+ * This will copy the SNAP as well which will be considered
+ * as MAC header.
+ */
+ tso_build_hdr(skb, hdr_page->pos, &tso, data_left, !total_len);
+ iph = hdr_page->pos + 8;
+ tcph = (void *)(iph + ip_hdrlen);
+
+ hdr_page->pos += snap_ip_tcp_hdrlen;
+
+ tb_len = hdr_page->pos - start_hdr;
+ tb_phys = dma_map_single(trans->dev, start_hdr,
+ tb_len, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(trans->dev, tb_phys))) {
+ dev_kfree_skb(csum_skb);
+ goto out_err;
+ }
+ iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, tb_len);
+ trace_iwlwifi_dev_tx_tso_chunk(trans->dev, start_hdr, tb_len);
+ /* add this subframe's headers' length to the tx_cmd */
+ le16_add_cpu(&tx_cmd->len, hdr_page->pos - subf_hdrs_start);
+
+ /* prepare the start_hdr for the next subframe */
+ start_hdr = hdr_page->pos;
+
+ /* put the payload */
+ while (data_left) {
+ tb_len = min_t(unsigned int, tso.size, data_left);
+ tb_phys = dma_map_single(trans->dev, tso.data,
+ tb_len, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(trans->dev, tb_phys))) {
+ dev_kfree_skb(csum_skb);
+ goto out_err;
+ }
+ iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, tb_len);
+ trace_iwlwifi_dev_tx_tso_chunk(trans->dev, tso.data,
+ tb_len);
+
+ data_left -= tb_len;
+ tso_build_data(skb, &tso, tb_len);
+ }
+ }
+
+ /* re -add the WiFi header and IV */
+ skb_push(skb, hdr_len + iv_len);
+
+ return 0;
+
+out_err:
+#endif
+ return -EINVAL;
+}
+
static
struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans,
struct iwl_txq *txq,
@@ -238,15 +376,21 @@ struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans,
struct iwl_tfh_tfd *tfd =
iwl_pcie_get_tfd(trans_pcie, txq, txq->write_ptr);
dma_addr_t tb_phys;
+ bool amsdu;
int i, len, tb1_len, tb2_len, hdr_len;
void *tb1_addr;
memset(tfd, 0, sizeof(*tfd));
+ amsdu = ieee80211_is_data_qos(hdr->frame_control) &&
+ (*ieee80211_get_qos_ctl(hdr) &
+ IEEE80211_QOS_CTL_A_MSDU_PRESENT);
+
tb_phys = iwl_pcie_get_first_tb_dma(txq, txq->write_ptr);
/* The first TB points to bi-directional DMA data */
- memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr,
- IWL_FIRST_TB_SIZE);
+ if (!amsdu)
+ memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr,
+ IWL_FIRST_TB_SIZE);
iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, IWL_FIRST_TB_SIZE);
@@ -262,7 +406,11 @@ struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans,
len = sizeof(struct iwl_tx_cmd_gen2) + sizeof(struct iwl_cmd_header) +
ieee80211_hdrlen(hdr->frame_control) - IWL_FIRST_TB_SIZE;
- tb1_len = ALIGN(len, 4);
+ /* do not align A-MSDU to dword as the subframe header aligns it */
+ if (amsdu)
+ tb1_len = len;
+ else
+ tb1_len = ALIGN(len, 4);
/* map the data for TB1 */
tb1_addr = ((u8 *)&dev_cmd->hdr) + IWL_FIRST_TB_SIZE;
@@ -271,8 +419,24 @@ struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans,
goto out_err;
iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, tb1_len);
- /* set up TFD's third entry to point to remainder of skb's head */
hdr_len = ieee80211_hdrlen(hdr->frame_control);
+
+ if (amsdu) {
+ if (!iwl_pcie_gen2_build_amsdu(trans, skb, tfd,
+ tb1_len + IWL_FIRST_TB_SIZE,
+ hdr_len, dev_cmd))
+ goto out_err;
+
+ /*
+ * building the A-MSDU might have changed this data, so memcpy
+ * it now
+ */
+ memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr,
+ IWL_FIRST_TB_SIZE);
+ return tfd;
+ }
+
+ /* set up TFD's third entry to point to remainder of skb's head */
tb2_len = skb_headlen(skb) - hdr_len;
if (tb2_len > 0) {
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
index 01013d273aa7..20c632f54760 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
@@ -762,7 +762,7 @@ void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr)
reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
/* Enable L1-Active */
- if (trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ if (trans->cfg->device_family < IWL_DEVICE_FAMILY_8000)
iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG,
APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
}
@@ -1987,8 +1987,7 @@ static int iwl_fill_data_tbs(struct iwl_trans *trans, struct sk_buff *skb,
}
#ifdef CONFIG_INET
-static struct iwl_tso_hdr_page *
-get_page_hdr(struct iwl_trans *trans, size_t len)
+struct iwl_tso_hdr_page *get_page_hdr(struct iwl_trans *trans, size_t len)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_tso_hdr_page *p = this_cpu_ptr(trans_pcie->tso_hdr_page);
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index c20e4944ef87..a850ec0054e2 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -3031,7 +3031,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
INIT_DELAYED_WORK(&priv->dfs_chan_sw_work,
mwifiex_dfs_chan_sw_work_queue);
- sema_init(&priv->async_sem, 1);
+ mutex_init(&priv->async_mutex);
/* Register network device */
if (register_netdevice(dev)) {
diff --git a/drivers/net/wireless/marvell/mwifiex/cfp.c b/drivers/net/wireless/marvell/mwifiex/cfp.c
index 1ff22055e54f..6e2994308526 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfp.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfp.c
@@ -350,7 +350,7 @@ mwifiex_get_cfp(struct mwifiex_private *priv, u8 band, u16 channel, u32 freq)
}
}
if (i == sband->n_channels) {
- mwifiex_dbg(priv->adapter, ERROR,
+ mwifiex_dbg(priv->adapter, WARN,
"%s: cannot find cfp by band %d\t"
"& channel=%d freq=%d\n",
__func__, band, channel, freq);
diff --git a/drivers/net/wireless/marvell/mwifiex/debugfs.c b/drivers/net/wireless/marvell/mwifiex/debugfs.c
index ae2b69db5994..f6f105a7d3ff 100644
--- a/drivers/net/wireless/marvell/mwifiex/debugfs.c
+++ b/drivers/net/wireless/marvell/mwifiex/debugfs.c
@@ -1046,6 +1046,5 @@ mwifiex_debugfs_init(void)
void
mwifiex_debugfs_remove(void)
{
- if (mwifiex_dfs_dir)
- debugfs_remove(mwifiex_dfs_dir);
+ debugfs_remove(mwifiex_dfs_dir);
}
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index c37fb2606502..f8cf3079ac7d 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -629,7 +629,7 @@ struct mwifiex_private {
struct dentry *dfs_dev_dir;
#endif
u16 current_key_index;
- struct semaphore async_sem;
+ struct mutex async_mutex;
struct cfg80211_scan_request *scan_request;
u8 cfg_bssid[6];
struct wps wps;
diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c
index ce6936d0c5c0..ae9630b49342 100644
--- a/drivers/net/wireless/marvell/mwifiex/scan.c
+++ b/drivers/net/wireless/marvell/mwifiex/scan.c
@@ -2809,7 +2809,7 @@ int mwifiex_request_scan(struct mwifiex_private *priv,
{
int ret;
- if (down_interruptible(&priv->async_sem)) {
+ if (mutex_lock_interruptible(&priv->async_mutex)) {
mwifiex_dbg(priv->adapter, ERROR,
"%s: acquire semaphore fail\n",
__func__);
@@ -2825,7 +2825,7 @@ int mwifiex_request_scan(struct mwifiex_private *priv,
/* Normal scan */
ret = mwifiex_scan_networks(priv, NULL);
- up(&priv->async_sem);
+ mutex_unlock(&priv->async_mutex);
return ret;
}
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
index 3348fb3a7514..2945775e83c5 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
@@ -1154,8 +1154,8 @@ static int mwifiex_ret_chan_region_cfg(struct mwifiex_private *priv,
return 0;
}
-int mwifiex_ret_pkt_aggr_ctrl(struct mwifiex_private *priv,
- struct host_cmd_ds_command *resp)
+static int mwifiex_ret_pkt_aggr_ctrl(struct mwifiex_private *priv,
+ struct host_cmd_ds_command *resp)
{
struct host_cmd_ds_pkt_aggr_ctrl *pkt_aggr_ctrl =
&resp->params.pkt_aggr_ctrl;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 37c3bececa1f..b39dbc3d3c1f 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -1298,12 +1298,6 @@ int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac,
int ret = 0;
u8 qband;
- cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0,
- QLINK_CMD_CHANS_INFO_GET,
- sizeof(*cmd));
- if (!cmd_skb)
- return -ENOMEM;
-
switch (band->band) {
case NL80211_BAND_2GHZ:
qband = QLINK_BAND_2GHZ;
@@ -1318,6 +1312,12 @@ int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac,
return -EINVAL;
}
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0,
+ QLINK_CMD_CHANS_INFO_GET,
+ sizeof(*cmd));
+ if (!cmd_skb)
+ return -ENOMEM;
+
cmd = (struct qlink_cmd_chans_info_get *)cmd_skb->data;
cmd->band = qband;
ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, &res_code,
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c
index 710e5b447cff..d34ad94c327b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.c
+++ b/drivers/net/wireless/realtek/rtlwifi/base.c
@@ -405,6 +405,10 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw)
ieee80211_hw_set(hw, SUPPORTS_PS);
ieee80211_hw_set(hw, PS_NULLFUNC_STACK);
}
+ if (rtlpriv->psc.fwctrl_lps) {
+ ieee80211_hw_set(hw, SUPPORTS_PS);
+ ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
+ }
hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_STATION) |
@@ -1110,6 +1114,9 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw,
if (txrate)
tcb_desc->hw_rate = txrate->hw_value;
+ if (rtl_is_tx_report_skb(hw, skb))
+ tcb_desc->use_spe_rpt = 1;
+
if (ieee80211_is_data(fc)) {
/*
*we set data rate INX 0
@@ -1306,33 +1313,26 @@ bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
}
EXPORT_SYMBOL_GPL(rtl_action_proc);
-static void setup_arp_tx(struct rtl_priv *rtlpriv, struct rtl_ps_ctl *ppsc)
+static void setup_special_tx(struct rtl_priv *rtlpriv, struct rtl_ps_ctl *ppsc,
+ int type)
{
struct ieee80211_hw *hw = rtlpriv->hw;
rtlpriv->ra.is_special_data = true;
if (rtlpriv->cfg->ops->get_btc_status())
rtlpriv->btcoexist.btc_ops->btc_special_packet_notify(
- rtlpriv, 1);
+ rtlpriv, type);
rtl_lps_leave(hw);
ppsc->last_delaylps_stamp_jiffies = jiffies;
}
-/*should call before software enc*/
-u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx,
- bool is_enc)
+static const u8 *rtl_skb_ether_type_ptr(struct ieee80211_hw *hw,
+ struct sk_buff *skb, bool is_enc)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- __le16 fc = rtl_get_fc(skb);
- u16 ether_type;
u8 mac_hdr_len = ieee80211_get_hdrlen_from_skb(skb);
u8 encrypt_header_len = 0;
u8 offset;
- const struct iphdr *ip;
-
- if (!ieee80211_is_data(fc))
- goto end;
switch (rtlpriv->sec.pairwise_enc_algorithm) {
case WEP40_ENCRYPTION:
@@ -1352,10 +1352,29 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx,
offset = mac_hdr_len + SNAP_SIZE;
if (is_enc)
offset += encrypt_header_len;
- ether_type = be16_to_cpup((__be16 *)(skb->data + offset));
+
+ return skb->data + offset;
+}
+
+/*should call before software enc*/
+u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx,
+ bool is_enc)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ __le16 fc = rtl_get_fc(skb);
+ u16 ether_type;
+ const u8 *ether_type_ptr;
+ const struct iphdr *ip;
+
+ if (!ieee80211_is_data(fc))
+ goto end;
+
+ ether_type_ptr = rtl_skb_ether_type_ptr(hw, skb, is_enc);
+ ether_type = be16_to_cpup((__be16 *)ether_type_ptr);
if (ETH_P_IP == ether_type) {
- ip = (struct iphdr *)((u8 *)skb->data + offset +
+ ip = (struct iphdr *)((u8 *)ether_type_ptr +
PROTOC_TYPE_SIZE);
if (IPPROTO_UDP == ip->protocol) {
struct udphdr *udp = (struct udphdr *)((u8 *)ip +
@@ -1372,13 +1391,15 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx,
(is_tx) ? "Tx" : "Rx");
if (is_tx)
- setup_arp_tx(rtlpriv, ppsc);
+ setup_special_tx(rtlpriv, ppsc,
+ PACKET_DHCP);
+
return true;
}
}
} else if (ETH_P_ARP == ether_type) {
if (is_tx)
- setup_arp_tx(rtlpriv, ppsc);
+ setup_special_tx(rtlpriv, ppsc, PACKET_ARP);
return true;
} else if (ETH_P_PAE == ether_type) {
@@ -1389,6 +1410,8 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx,
rtlpriv->ra.is_special_data = true;
rtl_lps_leave(hw);
ppsc->last_delaylps_stamp_jiffies = jiffies;
+
+ setup_special_tx(rtlpriv, ppsc, PACKET_EAPOL);
}
return true;
@@ -1405,6 +1428,96 @@ end:
}
EXPORT_SYMBOL_GPL(rtl_is_special_data);
+bool rtl_is_tx_report_skb(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+ u16 ether_type;
+ const u8 *ether_type_ptr;
+
+ ether_type_ptr = rtl_skb_ether_type_ptr(hw, skb, true);
+ ether_type = be16_to_cpup((__be16 *)ether_type_ptr);
+
+ /* EAPOL */
+ if (ether_type == ETH_P_PAE)
+ return true;
+
+ return false;
+}
+
+static u16 rtl_get_tx_report_sn(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_tx_report *tx_report = &rtlpriv->tx_report;
+ u16 sn;
+
+ sn = atomic_inc_return(&tx_report->sn) & 0x0FFF;
+
+ tx_report->last_sent_sn = sn;
+ tx_report->last_sent_time = jiffies;
+
+ RT_TRACE(rtlpriv, COMP_TX_REPORT, DBG_DMESG,
+ "Send TX-Report sn=0x%X\n", sn);
+
+ return sn;
+}
+
+void rtl_get_tx_report(struct rtl_tcb_desc *ptcb_desc, u8 *pdesc,
+ struct ieee80211_hw *hw)
+{
+ if (ptcb_desc->use_spe_rpt) {
+ u16 sn = rtl_get_tx_report_sn(hw);
+
+ SET_TX_DESC_SPE_RPT(pdesc, 1);
+ SET_TX_DESC_SW_DEFINE(pdesc, sn);
+ }
+}
+EXPORT_SYMBOL_GPL(rtl_get_tx_report);
+
+void rtl_tx_report_handler(struct ieee80211_hw *hw, u8 *tmp_buf, u8 c2h_cmd_len)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_tx_report *tx_report = &rtlpriv->tx_report;
+ u16 sn;
+
+ sn = ((tmp_buf[7] & 0x0F) << 8) | tmp_buf[6];
+
+ tx_report->last_recv_sn = sn;
+
+ RT_TRACE(rtlpriv, COMP_TX_REPORT, DBG_DMESG,
+ "Recv TX-Report st=0x%02X sn=0x%X retry=0x%X\n",
+ tmp_buf[0], sn, tmp_buf[2]);
+}
+EXPORT_SYMBOL_GPL(rtl_tx_report_handler);
+
+bool rtl_check_tx_report_acked(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_tx_report *tx_report = &rtlpriv->tx_report;
+
+ if (tx_report->last_sent_sn == tx_report->last_recv_sn)
+ return true;
+
+ if (time_before(tx_report->last_sent_time + 3 * HZ, jiffies)) {
+ RT_TRACE(rtlpriv, COMP_TX_REPORT, DBG_WARNING,
+ "Check TX-Report timeout!!\n");
+ return true; /* 3 sec. (timeout) seen as acked */
+ }
+
+ return false;
+}
+
+void rtl_wait_tx_report_acked(struct ieee80211_hw *hw, u32 wait_ms)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ int i;
+
+ for (i = 0; i < wait_ms; i++) {
+ if (rtl_check_tx_report_acked(hw))
+ break;
+ usleep_range(1000, 2000);
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+ "Wait 1ms (%d/%d) to disable key.\n", i, wait_ms);
+ }
+}
/*********************************************************
*
* functions called by core.c
@@ -1469,6 +1582,7 @@ int rtl_rx_agg_start(struct ieee80211_hw *hw,
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_tid_data *tid_data;
struct rtl_sta_info *sta_entry = NULL;
+ u8 reject_agg;
if (sta == NULL)
return -EINVAL;
@@ -1476,6 +1590,14 @@ int rtl_rx_agg_start(struct ieee80211_hw *hw,
if (unlikely(tid >= MAX_TID_COUNT))
return -EINVAL;
+ if (rtlpriv->cfg->ops->get_btc_status()) {
+ rtlpriv->btcoexist.btc_ops->btc_get_ampdu_cfg(rtlpriv,
+ &reject_agg,
+ NULL, NULL);
+ if (reject_agg)
+ return -EINVAL;
+ }
+
sta_entry = (struct rtl_sta_info *)sta->drv_priv;
if (!sta_entry)
return -ENXIO;
@@ -1530,6 +1652,24 @@ int rtl_tx_agg_oper(struct ieee80211_hw *hw,
return 0;
}
+void rtl_rx_ampdu_apply(struct rtl_priv *rtlpriv)
+{
+ struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
+ u8 reject_agg, ctrl_agg_size = 0, agg_size;
+
+ if (rtlpriv->cfg->ops->get_btc_status())
+ btc_ops->btc_get_ampdu_cfg(rtlpriv, &reject_agg,
+ &ctrl_agg_size, &agg_size);
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "Set RX AMPDU: coex - reject=%d, ctrl_agg_size=%d, size=%d",
+ reject_agg, ctrl_agg_size, agg_size);
+
+ rtlpriv->hw->max_rx_aggregation_subframes =
+ (ctrl_agg_size ? agg_size : IEEE80211_MAX_AMPDU_BUF);
+}
+EXPORT_SYMBOL(rtl_rx_ampdu_apply);
+
/*********************************************************
*
* wq & timer callback functions
@@ -1662,12 +1802,20 @@ void rtl_watchdog_wq_callback(void *data)
false;
}
+ /* PS is controlled by coex. */
+ if (rtlpriv->cfg->ops->get_btc_status() &&
+ rtlpriv->btcoexist.btc_ops->btc_is_bt_ctrl_lps(rtlpriv))
+ goto label_lps_done;
+
if (((rtlpriv->link_info.num_rx_inperiod +
rtlpriv->link_info.num_tx_inperiod) > 8) ||
(rtlpriv->link_info.num_rx_inperiod > 2))
rtl_lps_leave(hw);
else
rtl_lps_enter(hw);
+
+label_lps_done:
+ ;
}
rtlpriv->link_info.num_rx_inperiod = 0;
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.h b/drivers/net/wireless/realtek/rtlwifi/base.h
index 02ff0c5624a7..21fa4562f631 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.h
+++ b/drivers/net/wireless/realtek/rtlwifi/base.h
@@ -107,6 +107,11 @@ enum ap_peer {
SET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, \
(GET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr) & (~(__val))))
+#define SET_TX_DESC_SPE_RPT(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 8, 19, 1, __val)
+#define SET_TX_DESC_SW_DEFINE(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 0, 12, __val)
+
int rtl_init_core(struct ieee80211_hw *hw);
void rtl_deinit_core(struct ieee80211_hw *hw);
void rtl_init_rx_config(struct ieee80211_hw *hw);
@@ -123,6 +128,14 @@ bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb);
u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx,
bool is_enc);
+bool rtl_is_tx_report_skb(struct ieee80211_hw *hw, struct sk_buff *skb);
+void rtl_get_tx_report(struct rtl_tcb_desc *ptcb_desc, u8 *pdesc,
+ struct ieee80211_hw *hw);
+void rtl_tx_report_handler(struct ieee80211_hw *hw, u8 *tmp_buf,
+ u8 c2h_cmd_len);
+bool rtl_check_tx_report_acked(struct ieee80211_hw *hw);
+void rtl_wait_tx_report_acked(struct ieee80211_hw *hw, u32 wait_ms);
+
void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb);
int rtl_tx_agg_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid, u16 *ssn);
@@ -134,6 +147,7 @@ int rtl_rx_agg_start(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, u16 tid);
int rtl_rx_agg_stop(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, u16 tid);
+void rtl_rx_ampdu_apply(struct rtl_priv *rtlpriv);
void rtl_watchdog_wq_callback(void *data);
void rtl_fwevt_wq_callback(void *data);
void rtl_c2hcmd_wq_callback(void *data);
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h
index 39b9a3309cfd..2ac989a4b2bb 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h
@@ -37,6 +37,28 @@
#include "halbtcoutsrc.h"
+/* Interface type */
+#define RT_PCI_INTERFACE 1
+#define RT_USB_INTERFACE 2
+#define RT_SDIO_INTERFACE 3
+#define DEV_BUS_TYPE RT_PCI_INTERFACE
+
+/* IC type */
+#define RTL_HW_TYPE(adapter) (rtl_hal((struct rtl_priv *)adapter)->hw_type)
+
+#define IS_NEW_GENERATION_IC(adapter) \
+ (RTL_HW_TYPE(adapter) >= HARDWARE_TYPE_RTL8192EE)
+#define IS_HARDWARE_TYPE_8812(adapter) \
+ (RTL_HW_TYPE(adapter) == HARDWARE_TYPE_RTL8812AE)
+#define IS_HARDWARE_TYPE_8821(adapter) \
+ (RTL_HW_TYPE(adapter) == HARDWARE_TYPE_RTL8821AE)
+#define IS_HARDWARE_TYPE_8723A(adapter) \
+ (RTL_HW_TYPE(adapter) == HARDWARE_TYPE_RTL8723AE)
+#define IS_HARDWARE_TYPE_8723B(adapter) \
+ (RTL_HW_TYPE(adapter) == HARDWARE_TYPE_RTL8723BE)
+#define IS_HARDWARE_TYPE_8192E(adapter) \
+ (RTL_HW_TYPE(adapter) == HARDWARE_TYPE_RTL8192EE)
+
#include "halbtc8192e2ant.h"
#include "halbtc8723b1ant.h"
#include "halbtc8723b2ant.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c
index 9015512ed647..44c25724529e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c
@@ -3194,7 +3194,7 @@ void ex_btc8192e2ant_bt_info_notify(struct btc_coexist *btcoexist,
btc8192e2ant_run_coexist_mechanism(btcoexist);
}
-void ex_halbtc8192e2ant_halt_notify(struct btc_coexist *btcoexist)
+void ex_btc8192e2ant_halt_notify(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h
index a57d6947eaf7..65502acee52c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h
@@ -164,20 +164,20 @@ struct coex_sta_8192e_2ant {
/****************************************************************
* The following is interface which will notify coex module.
****************************************************************/
-void ex_halbtc8192e2ant_init_hwconfig(struct btc_coexist *btcoexist);
-void ex_halbtc8192e2ant_init_coex_dm(struct btc_coexist *btcoexist);
-void ex_halbtc8192e2ant_ips_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8192e2ant_lps_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8192e2ant_scan_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8192e2ant_connect_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8192e2ant_media_status_notify(struct btc_coexist *btcoexist,
+void ex_btc8192e2ant_init_hwconfig(struct btc_coexist *btcoexist);
+void ex_btc8192e2ant_init_coex_dm(struct btc_coexist *btcoexist);
+void ex_btc8192e2ant_ips_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8192e2ant_lps_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8192e2ant_scan_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8192e2ant_connect_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8192e2ant_media_status_notify(struct btc_coexist *btcoexist,
+ u8 type);
+void ex_btc8192e2ant_special_packet_notify(struct btc_coexist *btcoexist,
+ u8 type);
+void ex_btc8192e2ant_bt_info_notify(struct btc_coexist *btcoexist,
+ u8 *tmpbuf, u8 length);
+void ex_btc8192e2ant_stack_operation_notify(struct btc_coexist *btcoexist,
u8 type);
-void ex_halbtc8192e2ant_special_packet_notify(struct btc_coexist *btcoexist,
- u8 type);
-void ex_halbtc8192e2ant_bt_info_notify(struct btc_coexist *btcoexist,
- u8 *tmpbuf, u8 length);
-void ex_halbtc8192e2ant_stack_operation_notify(struct btc_coexist *btcoexist,
- u8 type);
-void ex_halbtc8192e2ant_halt_notify(struct btc_coexist *btcoexist);
-void ex_halbtc8192e2ant_periodical(struct btc_coexist *btcoexist);
-void ex_halbtc8192e2ant_display_coex_info(struct btc_coexist *btcoexist);
+void ex_btc8192e2ant_halt_notify(struct btc_coexist *btcoexist);
+void ex_btc8192e2ant_periodical(struct btc_coexist *btcoexist);
+void ex_btc8192e2ant_display_coex_info(struct btc_coexist *btcoexist);
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c
index a0f3a18add25..03998d2e9eb8 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c
@@ -2390,9 +2390,9 @@ static void halbtc8723b1ant_init_hw_config(struct btc_coexist *btcoexist,
}
/**************************************************************
- * extern function start with ex_halbtc8723b1ant_
+ * extern function start with ex_btc8723b1ant_
**************************************************************/
-void ex_halbtc8723b1ant_power_on_setting(struct btc_coexist *btcoexist)
+void ex_btc8723b1ant_power_on_setting(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
struct btc_board_info *board_info = &btcoexist->board_info;
@@ -2462,14 +2462,14 @@ void ex_halbtc8723b1ant_power_on_setting(struct btc_coexist *btcoexist)
}
-void ex_halbtc8723b1ant_init_hwconfig(struct btc_coexist *btcoexist,
- bool wifi_only)
+void ex_btc8723b1ant_init_hwconfig(struct btc_coexist *btcoexist,
+ bool wifi_only)
{
halbtc8723b1ant_init_hw_config(btcoexist, true, wifi_only);
btcoexist->stop_coex_dm = false;
}
-void ex_halbtc8723b1ant_init_coex_dm(struct btc_coexist *btcoexist)
+void ex_btc8723b1ant_init_coex_dm(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
@@ -2483,7 +2483,7 @@ void ex_halbtc8723b1ant_init_coex_dm(struct btc_coexist *btcoexist)
halbtc8723b1ant_query_bt_info(btcoexist);
}
-void ex_halbtc8723b1ant_display_coex_info(struct btc_coexist *btcoexist)
+void ex_btc8723b1ant_display_coex_info(struct btc_coexist *btcoexist)
{
struct btc_board_info *board_info = &btcoexist->board_info;
struct btc_stack_info *stack_info = &btcoexist->stack_info;
@@ -2758,7 +2758,7 @@ void ex_halbtc8723b1ant_display_coex_info(struct btc_coexist *btcoexist)
btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_COEX_STATISTICS);
}
-void ex_halbtc8723b1ant_ips_notify(struct btc_coexist *btcoexist, u8 type)
+void ex_btc8723b1ant_ips_notify(struct btc_coexist *btcoexist, u8 type)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
@@ -2787,7 +2787,7 @@ void ex_halbtc8723b1ant_ips_notify(struct btc_coexist *btcoexist, u8 type)
}
}
-void ex_halbtc8723b1ant_lps_notify(struct btc_coexist *btcoexist, u8 type)
+void ex_btc8723b1ant_lps_notify(struct btc_coexist *btcoexist, u8 type)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
@@ -2805,7 +2805,7 @@ void ex_halbtc8723b1ant_lps_notify(struct btc_coexist *btcoexist, u8 type)
}
}
-void ex_halbtc8723b1ant_scan_notify(struct btc_coexist *btcoexist, u8 type)
+void ex_btc8723b1ant_scan_notify(struct btc_coexist *btcoexist, u8 type)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
bool wifi_connected = false, bt_hs_on = false;
@@ -2891,7 +2891,7 @@ void ex_halbtc8723b1ant_scan_notify(struct btc_coexist *btcoexist, u8 type)
}
}
-void ex_halbtc8723b1ant_connect_notify(struct btc_coexist *btcoexist, u8 type)
+void ex_btc8723b1ant_connect_notify(struct btc_coexist *btcoexist, u8 type)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
bool wifi_connected = false, bt_hs_on = false;
@@ -2961,8 +2961,8 @@ void ex_halbtc8723b1ant_connect_notify(struct btc_coexist *btcoexist, u8 type)
}
}
-void ex_halbtc8723b1ant_media_status_notify(struct btc_coexist *btcoexist,
- u8 type)
+void ex_btc8723b1ant_media_status_notify(struct btc_coexist *btcoexist,
+ u8 type)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
u8 h2c_parameter[3] = {0};
@@ -3042,8 +3042,8 @@ void ex_halbtc8723b1ant_media_status_notify(struct btc_coexist *btcoexist,
btcoexist->btc_fill_h2c(btcoexist, 0x66, 3, h2c_parameter);
}
-void ex_halbtc8723b1ant_special_packet_notify(struct btc_coexist *btcoexist,
- u8 type)
+void ex_btc8723b1ant_special_packet_notify(struct btc_coexist *btcoexist,
+ u8 type)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
bool bt_hs_on = false;
@@ -3119,8 +3119,8 @@ void ex_halbtc8723b1ant_special_packet_notify(struct btc_coexist *btcoexist,
}
}
-void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
- u8 *tmp_buf, u8 length)
+void ex_btc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
+ u8 *tmp_buf, u8 length)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
u8 bt_info = 0;
@@ -3211,11 +3211,11 @@ void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED,
&wifi_connected);
if (wifi_connected)
- ex_halbtc8723b1ant_media_status_notify(btcoexist,
- BTC_MEDIA_CONNECT);
+ ex_btc8723b1ant_media_status_notify(btcoexist,
+ BTC_MEDIA_CONNECT);
else
- ex_halbtc8723b1ant_media_status_notify(btcoexist,
- BTC_MEDIA_DISCONNECT);
+ ex_btc8723b1ant_media_status_notify(btcoexist,
+ BTC_MEDIA_DISCONNECT);
}
if (coex_sta->bt_info_ext & BIT3) {
@@ -3364,7 +3364,7 @@ void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
halbtc8723b1ant_run_coexist_mechanism(btcoexist);
}
-void ex_halbtc8723b1ant_rf_status_notify(struct btc_coexist *btcoexist, u8 type)
+void ex_btc8723b1ant_rf_status_notify(struct btc_coexist *btcoexist, u8 type)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
u32 u32tmp;
@@ -3401,7 +3401,7 @@ void ex_halbtc8723b1ant_rf_status_notify(struct btc_coexist *btcoexist, u8 type)
}
}
-void ex_halbtc8723b1ant_halt_notify(struct btc_coexist *btcoexist)
+void ex_btc8723b1ant_halt_notify(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
@@ -3418,12 +3418,12 @@ void ex_halbtc8723b1ant_halt_notify(struct btc_coexist *btcoexist)
0x0, 0x0);
halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 0);
- ex_halbtc8723b1ant_media_status_notify(btcoexist, BTC_MEDIA_DISCONNECT);
+ ex_btc8723b1ant_media_status_notify(btcoexist, BTC_MEDIA_DISCONNECT);
btcoexist->stop_coex_dm = true;
}
-void ex_halbtc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state)
+void ex_btc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
@@ -3458,7 +3458,7 @@ void ex_halbtc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state)
}
}
-void ex_halbtc8723b1ant_coex_dm_reset(struct btc_coexist *btcoexist)
+void ex_btc8723b1ant_coex_dm_reset(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
@@ -3469,7 +3469,7 @@ void ex_halbtc8723b1ant_coex_dm_reset(struct btc_coexist *btcoexist)
halbtc8723b1ant_init_coex_dm(btcoexist);
}
-void ex_halbtc8723b1ant_periodical(struct btc_coexist *btcoexist)
+void ex_btc8723b1ant_periodical(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h
index 506961a1ca56..8d4fde235e11 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h
@@ -200,24 +200,25 @@ struct coex_sta_8723b_1ant {
/*************************************************************************
* The following is interface which will notify coex module.
*************************************************************************/
-void ex_halbtc8723b1ant_power_on_setting(struct btc_coexist *btcoexist);
-void ex_halbtc8723b1ant_init_hwconfig(struct btc_coexist *btcoexist,
- bool wifi_only);
-void ex_halbtc8723b1ant_init_coex_dm(struct btc_coexist *btcoexist);
-void ex_halbtc8723b1ant_ips_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8723b1ant_lps_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8723b1ant_scan_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8723b1ant_connect_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8723b1ant_media_status_notify(struct btc_coexist *btcoexist,
- u8 type);
-void ex_halbtc8723b1ant_special_packet_notify(struct btc_coexist *btcoexist,
- u8 type);
-void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
- u8 *tmpbuf, u8 length);
-void ex_halbtc8723b1ant_rf_status_notify(struct btc_coexist *btcoexist,
+void ex_btc8723b1ant_power_on_setting(struct btc_coexist *btcoexist);
+void ex_btc8723b1ant_init_hwconfig(struct btc_coexist *btcoexist,
+ bool wifi_only);
+void ex_btc8723b1ant_init_coex_dm(struct btc_coexist *btcoexist);
+void ex_btc8723b1ant_ips_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8723b1ant_lps_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8723b1ant_scan_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8723b1ant_connect_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8723b1ant_media_status_notify(struct btc_coexist *btcoexist,
u8 type);
-void ex_halbtc8723b1ant_halt_notify(struct btc_coexist *btcoexist);
-void ex_halbtc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnpstate);
-void ex_halbtc8723b1ant_coex_dm_reset(struct btc_coexist *btcoexist);
-void ex_halbtc8723b1ant_periodical(struct btc_coexist *btcoexist);
-void ex_halbtc8723b1ant_display_coex_info(struct btc_coexist *btcoexist);
+void ex_btc8723b1ant_special_packet_notify(struct btc_coexist *btcoexist,
+ u8 type);
+void ex_btc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
+ u8 *tmpbuf, u8 length);
+void ex_btc8723b1ant_rf_status_notify(struct btc_coexist *btcoexist,
+ u8 type);
+void ex_btc8723b1ant_halt_notify(struct btc_coexist *btcoexist);
+void ex_btc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnpstate);
+void ex_btc8723b1ant_coex_dm_reset(struct btc_coexist *btcoexist);
+void ex_btc8723b1ant_periodical(struct btc_coexist *btcoexist);
+void ex_btc8723b1ant_display_coex_info(struct btc_coexist *btcoexist);
+void ex_btc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state);
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h
index 50726beaeead..bc1e3042e271 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h
@@ -196,5 +196,8 @@ void ex_btc8723b2ant_bt_info_notify(struct btc_coexist *btcoexist,
void ex_btc8723b2ant_halt_notify(struct btc_coexist *btcoexist);
void ex_btc8723b2ant_periodical(struct btc_coexist *btcoexist);
void ex_btc8723b2ant_display_coex_info(struct btc_coexist *btcoexist);
+void ex_btc8723b2ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state);
+void ex_btc8723b2ant_pre_load_firmware(struct btc_coexist *btcoexist);
+void ex_btc8723b2ant_power_on_setting(struct btc_coexist *btcoexist);
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h
index cb32e7a64ae6..b0a6626fbb66 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h
@@ -170,21 +170,23 @@ struct coex_sta_8821a_1ant {
* The following is interface which will notify coex module.
*===========================================
*/
-void ex_halbtc8821a1ant_init_hwconfig(struct btc_coexist *btcoexist);
-void ex_halbtc8821a1ant_init_coex_dm(struct btc_coexist *btcoexist);
-void ex_halbtc8821a1ant_ips_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8821a1ant_lps_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8821a1ant_scan_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8821a1ant_connect_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8821a1ant_media_status_notify(struct btc_coexist *btcoexist,
- u8 type);
-void ex_halbtc8821a1ant_special_packet_notify(struct btc_coexist *btcoexist,
- u8 type);
-void ex_halbtc8821a1ant_bt_info_notify(struct btc_coexist *btcoexist,
- u8 *tmpbuf, u8 length);
-void ex_halbtc8821a1ant_halt_notify(struct btc_coexist *btcoexist);
-void ex_halbtc8821a1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnpstate);
-void ex_halbtc8821a1ant_periodical(struct btc_coexist *btcoexist);
-void ex_halbtc8821a1ant_display_coex_info(struct btc_coexist *btcoexist);
-void ex_halbtc8821a1ant_dbg_control(struct btc_coexist *btcoexist, u8 op_code,
- u8 op_len, u8 *data);
+void ex_btc8821a1ant_init_hwconfig(struct btc_coexist *btcoexist,
+ bool wifi_only);
+void ex_btc8821a1ant_init_coex_dm(struct btc_coexist *btcoexist);
+void ex_btc8821a1ant_ips_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8821a1ant_lps_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8821a1ant_scan_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8821a1ant_connect_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8821a1ant_media_status_notify(struct btc_coexist *btcoexist,
+ u8 type);
+void ex_btc8821a1ant_special_packet_notify(struct btc_coexist *btcoexist,
+ u8 type);
+void ex_btc8821a1ant_bt_info_notify(struct btc_coexist *btcoexist,
+ u8 *tmpbuf, u8 length);
+void ex_btc8821a1ant_halt_notify(struct btc_coexist *btcoexist);
+void ex_btc8821a1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnpstate);
+void ex_btc8821a1ant_periodical(struct btc_coexist *btcoexist);
+void ex_btc8821a1ant_display_coex_info(struct btc_coexist *btcoexist);
+void ex_btc8821a1ant_dbg_control(struct btc_coexist *btcoexist, u8 op_code,
+ u8 op_len, u8 *data);
+void ex_btc8821a1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state);
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h
index a1603e2d44e3..a839d5574422 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h
@@ -173,58 +173,60 @@ struct coex_sta_8821a_2ant {
*===========================================
*/
void
-ex_halbtc8821a2ant_init_hwconfig(
+ex_btc8821a2ant_init_hwconfig(
struct btc_coexist *btcoexist
);
void
-ex_halbtc8821a2ant_init_coex_dm(
+ex_btc8821a2ant_init_coex_dm(
struct btc_coexist *btcoexist
);
void
-ex_halbtc8821a2ant_ips_notify(
+ex_btc8821a2ant_ips_notify(
struct btc_coexist *btcoexist,
u8 type
);
void
-ex_halbtc8821a2ant_lps_notify(
+ex_btc8821a2ant_lps_notify(
struct btc_coexist *btcoexist,
u8 type
);
void
-ex_halbtc8821a2ant_scan_notify(
+ex_btc8821a2ant_scan_notify(
struct btc_coexist *btcoexist,
u8 type
);
void
-ex_halbtc8821a2ant_connect_notify(
+ex_btc8821a2ant_connect_notify(
struct btc_coexist *btcoexist,
u8 type
);
void
-ex_halbtc8821a2ant_media_status_notify(
+ex_btc8821a2ant_media_status_notify(
struct btc_coexist *btcoexist,
u8 type
);
void
-ex_halbtc8821a2ant_special_packet_notify(
+ex_btc8821a2ant_special_packet_notify(
struct btc_coexist *btcoexist,
u8 type
);
void
-ex_halbtc8821a2ant_bt_info_notify(
+ex_btc8821a2ant_bt_info_notify(
struct btc_coexist *btcoexist,
u8 *tmp_buf,
u8 length
);
void
-ex_halbtc8821a2ant_halt_notify(
+ex_btc8821a2ant_halt_notify(
struct btc_coexist *btcoexist
);
void
-ex_halbtc8821a2ant_periodical(
+ex_btc8821a2ant_periodical(
struct btc_coexist *btcoexist
);
void
-ex_halbtc8821a2ant_display_coex_info(
+ex_btc8821a2ant_display_coex_info(
struct btc_coexist *btcoexist
);
+void ex_btc8821a2ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state);
+void ex_btc8821a2ant_pre_load_firmware(struct btc_coexist *btcoexist);
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
index f13000612913..eaa916a0727b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
@@ -36,6 +36,20 @@ u32 btc_dbg_type[BTC_MSG_MAX];
/***************************************************
* Debug related function
***************************************************/
+
+const char *const gl_btc_wifi_bw_string[] = {
+ "11bg",
+ "HT20",
+ "HT40",
+ "HT80",
+ "HT160"
+};
+
+const char *const gl_btc_wifi_freq_string[] = {
+ "2.4G",
+ "5G"
+};
+
static bool halbtc_is_bt_coexist_available(struct btc_coexist *btcoexist)
{
if (!btcoexist->binded || NULL == btcoexist->adapter)
@@ -54,28 +68,39 @@ static bool halbtc_is_wifi_busy(struct rtl_priv *rtlpriv)
static void halbtc_dbg_init(void)
{
- u8 i;
-
- for (i = 0; i < BTC_MSG_MAX; i++)
- btc_dbg_type[i] = 0;
-
- btc_dbg_type[BTC_MSG_INTERFACE] =
-/* INTF_INIT | */
-/* INTF_NOTIFY | */
- 0;
+}
- btc_dbg_type[BTC_MSG_ALGORITHM] =
-/* ALGO_BT_RSSI_STATE | */
-/* ALGO_WIFI_RSSI_STATE | */
-/* ALGO_BT_MONITOR | */
-/* ALGO_TRACE | */
-/* ALGO_TRACE_FW | */
-/* ALGO_TRACE_FW_DETAIL | */
-/* ALGO_TRACE_FW_EXEC | */
-/* ALGO_TRACE_SW | */
-/* ALGO_TRACE_SW_DETAIL | */
-/* ALGO_TRACE_SW_EXEC | */
- 0;
+/***************************************************
+ * helper function
+ ***************************************************/
+static bool is_any_client_connect_to_ap(struct btc_coexist *btcoexist)
+{
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+ struct rtl_mac *mac = rtl_mac(rtlpriv);
+ struct rtl_sta_info *drv_priv;
+ u8 cnt = 0;
+
+ if (mac->opmode == NL80211_IFTYPE_ADHOC ||
+ mac->opmode == NL80211_IFTYPE_MESH_POINT ||
+ mac->opmode == NL80211_IFTYPE_AP) {
+ if (in_interrupt() > 0) {
+ list_for_each_entry(drv_priv, &rtlpriv->entry_list,
+ list) {
+ cnt++;
+ }
+ } else {
+ spin_lock_bh(&rtlpriv->locks.entry_list_lock);
+ list_for_each_entry(drv_priv, &rtlpriv->entry_list,
+ list) {
+ cnt++;
+ }
+ spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
+ }
+ }
+ if (cnt > 0)
+ return true;
+ else
+ return false;
}
static bool halbtc_is_bt40(struct rtl_priv *adapter)
@@ -188,12 +213,14 @@ static void halbtc_leave_lps(struct btc_coexist *btcoexist)
&ap_enable);
if (ap_enable) {
- pr_info("halbtc_leave_lps()<--dont leave lps under AP mode\n");
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "%s()<--dont leave lps under AP mode\n", __func__);
return;
}
btcoexist->bt_info.bt_ctrl_lps = true;
btcoexist->bt_info.bt_lps_on = false;
+ rtl_lps_leave(rtlpriv->mac80211.hw);
}
static void halbtc_enter_lps(struct btc_coexist *btcoexist)
@@ -209,36 +236,93 @@ static void halbtc_enter_lps(struct btc_coexist *btcoexist)
&ap_enable);
if (ap_enable) {
- pr_info("halbtc_enter_lps()<--dont enter lps under AP mode\n");
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "%s()<--dont enter lps under AP mode\n", __func__);
return;
}
btcoexist->bt_info.bt_ctrl_lps = true;
- btcoexist->bt_info.bt_lps_on = false;
+ btcoexist->bt_info.bt_lps_on = true;
+ rtl_lps_enter(rtlpriv->mac80211.hw);
}
static void halbtc_normal_lps(struct btc_coexist *btcoexist)
{
+ struct rtl_priv *rtlpriv;
+
+ rtlpriv = btcoexist->adapter;
+
if (btcoexist->bt_info.bt_ctrl_lps) {
btcoexist->bt_info.bt_lps_on = false;
+ rtl_lps_leave(rtlpriv->mac80211.hw);
btcoexist->bt_info.bt_ctrl_lps = false;
}
}
-static void halbtc_leave_low_power(void)
+static void halbtc_leave_low_power(struct btc_coexist *btcoexist)
{
}
-static void halbtc_nomal_low_power(void)
+static void halbtc_normal_low_power(struct btc_coexist *btcoexist)
{
}
-static void halbtc_disable_low_power(void)
+static void halbtc_disable_low_power(struct btc_coexist *btcoexist,
+ bool low_pwr_disable)
{
+ /* TODO: original/leave 32k low power */
+ btcoexist->bt_info.bt_disable_low_pwr = low_pwr_disable;
}
-static void halbtc_aggregation_check(void)
+static void halbtc_aggregation_check(struct btc_coexist *btcoexist)
{
+ bool need_to_act = false;
+ static unsigned long pre_time;
+ unsigned long cur_time = 0;
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+
+ /* To void continuous deleteBA=>addBA=>deleteBA=>addBA
+ * This function is not allowed to continuous called
+ * It can only be called after 8 seconds
+ */
+
+ cur_time = jiffies;
+ if (jiffies_to_msecs(cur_time - pre_time) <= 8000) {
+ /* over 8 seconds you can execute this function again. */
+ return;
+ }
+ pre_time = cur_time;
+
+ if (btcoexist->bt_info.reject_agg_pkt) {
+ need_to_act = true;
+ btcoexist->bt_info.pre_reject_agg_pkt =
+ btcoexist->bt_info.reject_agg_pkt;
+ } else {
+ if (btcoexist->bt_info.pre_reject_agg_pkt) {
+ need_to_act = true;
+ btcoexist->bt_info.pre_reject_agg_pkt =
+ btcoexist->bt_info.reject_agg_pkt;
+ }
+
+ if (btcoexist->bt_info.pre_bt_ctrl_agg_buf_size !=
+ btcoexist->bt_info.bt_ctrl_agg_buf_size) {
+ need_to_act = true;
+ btcoexist->bt_info.pre_bt_ctrl_agg_buf_size =
+ btcoexist->bt_info.bt_ctrl_agg_buf_size;
+ }
+
+ if (btcoexist->bt_info.bt_ctrl_agg_buf_size) {
+ if (btcoexist->bt_info.pre_agg_buf_size !=
+ btcoexist->bt_info.agg_buf_size) {
+ need_to_act = true;
+ }
+ btcoexist->bt_info.pre_agg_buf_size =
+ btcoexist->bt_info.agg_buf_size;
+ }
+
+ if (need_to_act)
+ rtl_rx_ampdu_apply(rtlpriv);
+ }
}
static u32 halbtc_get_bt_patch_version(struct btc_coexist *btcoexist)
@@ -246,10 +330,37 @@ static u32 halbtc_get_bt_patch_version(struct btc_coexist *btcoexist)
return 0;
}
-static s32 halbtc_get_wifi_rssi(struct rtl_priv *adapter)
+u32 halbtc_get_wifi_link_status(struct btc_coexist *btcoexist)
{
- struct rtl_priv *rtlpriv = adapter;
- s32 undec_sm_pwdb = 0;
+ /* return value:
+ * [31:16] => connected port number
+ * [15:0] => port connected bit define
+ */
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+ struct rtl_mac *mac = rtl_mac(rtlpriv);
+ u32 ret_val = 0;
+ u32 port_connected_status = 0, num_of_connected_port = 0;
+
+ if (mac->opmode == NL80211_IFTYPE_STATION &&
+ mac->link_state >= MAC80211_LINKED) {
+ port_connected_status |= WIFI_STA_CONNECTED;
+ num_of_connected_port++;
+ }
+ /* AP & ADHOC & MESH */
+ if (is_any_client_connect_to_ap(btcoexist)) {
+ port_connected_status |= WIFI_AP_CONNECTED;
+ num_of_connected_port++;
+ }
+ /* TODO: P2P Connected Status */
+
+ ret_val = (num_of_connected_port << 16) | port_connected_status;
+
+ return ret_val;
+}
+
+static s32 halbtc_get_wifi_rssi(struct rtl_priv *rtlpriv)
+{
+ int undec_sm_pwdb = 0;
if (rtlpriv->mac80211.link_state >= MAC80211_LINKED)
undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
@@ -282,7 +393,10 @@ static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf)
*bool_tmp = false;
break;
case BTC_GET_BL_WIFI_CONNECTED:
- if (rtlpriv->mac80211.link_state >= MAC80211_LINKED)
+ if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION &&
+ rtlpriv->mac80211.link_state >= MAC80211_LINKED)
+ tmp = true;
+ if (is_any_client_connect_to_ap(btcoexist))
tmp = true;
*bool_tmp = tmp;
break;
@@ -304,28 +418,18 @@ static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf)
else
*bool_tmp = false;
break;
- case BTC_GET_BL_WIFI_ROAM: /*TODO*/
+ case BTC_GET_BL_WIFI_ROAM:
if (mac->link_state == MAC80211_LINKING)
*bool_tmp = true;
else
*bool_tmp = false;
break;
- case BTC_GET_BL_WIFI_4_WAY_PROGRESS: /*TODO*/
- *bool_tmp = false;
-
- break;
- case BTC_GET_BL_WIFI_UNDER_5G:
- *bool_tmp = false; /*TODO*/
-
- case BTC_GET_BL_WIFI_DHCP: /*TODO*/
- break;
- case BTC_GET_BL_WIFI_SOFTAP_IDLE:
- *bool_tmp = true;
- break;
- case BTC_GET_BL_WIFI_SOFTAP_LINKING:
+ case BTC_GET_BL_WIFI_4_WAY_PROGRESS:
+ /* TODO */
*bool_tmp = false;
break;
- case BTC_GET_BL_WIFI_IN_EARLY_SUSPEND:
+ case BTC_GET_BL_WIFI_UNDER_5G:
+ /* TODO */
*bool_tmp = false;
break;
case BTC_GET_BL_WIFI_AP_MODE_ENABLE:
@@ -338,15 +442,25 @@ static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf)
*bool_tmp = true;
break;
case BTC_GET_BL_WIFI_UNDER_B_MODE:
- *bool_tmp = false; /*TODO*/
+ if (rtlpriv->mac80211.mode == WIRELESS_MODE_B)
+ *bool_tmp = true;
+ else
+ *bool_tmp = false;
break;
case BTC_GET_BL_EXT_SWITCH:
*bool_tmp = false;
break;
+ case BTC_GET_BL_WIFI_IS_IN_MP_MODE:
+ *bool_tmp = false;
+ break;
+ case BTC_GET_BL_IS_ASUS_8723B:
+ *bool_tmp = false;
+ break;
case BTC_GET_S4_WIFI_RSSI:
*s32_tmp = halbtc_get_wifi_rssi(rtlpriv);
break;
- case BTC_GET_S4_HS_RSSI: /*TODO*/
+ case BTC_GET_S4_HS_RSSI:
+ /* TODO */
*s32_tmp = halbtc_get_wifi_rssi(rtlpriv);
break;
case BTC_GET_U4_WIFI_BW:
@@ -359,7 +473,10 @@ static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf)
*u32_tmp = BTC_WIFI_TRAFFIC_RX;
break;
case BTC_GET_U4_WIFI_FW_VER:
- *u32_tmp = rtlhal->fw_version;
+ *u32_tmp = (rtlhal->fw_version << 16) | rtlhal->fw_subversion;
+ break;
+ case BTC_GET_U4_WIFI_LINK_STATUS:
+ *u32_tmp = halbtc_get_wifi_link_status(btcoexist);
break;
case BTC_GET_U4_BT_PATCH_VER:
*u32_tmp = halbtc_get_bt_patch_version(btcoexist);
@@ -374,10 +491,19 @@ static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf)
*u8_tmp = halbtc_get_wifi_central_chnl(btcoexist);
break;
case BTC_GET_U1_WIFI_HS_CHNL:
- *u8_tmp = 1;/*BT_OperateChnl(rtlpriv);*/
+ *u8_tmp = 1;
+ break;
+ case BTC_GET_U1_AP_NUM:
+ /* driver do not know AP num,
+ * so the return value here is not right
+ */
+ *u8_tmp = 1;
+ break;
+ case BTC_GET_U1_ANT_TYPE:
+ *u8_tmp = (u8)BTC_ANT_TYPE_0;
break;
- case BTC_GET_U1_MAC_PHY_MODE:
- *u8_tmp = BTC_MP_UNKNOWN;
+ case BTC_GET_U1_IOT_PEER:
+ *u8_tmp = 0;
break;
/************* 1Ant **************/
@@ -420,11 +546,17 @@ static bool halbtc_set(void *void_btcoexist, u8 set_type, void *in_buf)
btcoexist->bt_info.reject_agg_pkt = *bool_tmp;
break;
case BTC_SET_BL_BT_CTRL_AGG_SIZE:
- btcoexist->bt_info.bt_ctrl_buf_size = *bool_tmp;
+ btcoexist->bt_info.bt_ctrl_agg_buf_size = *bool_tmp;
break;
case BTC_SET_BL_INC_SCAN_DEV_NUM:
btcoexist->bt_info.increase_scan_dev_num = *bool_tmp;
break;
+ case BTC_SET_BL_BT_TX_RX_MASK:
+ btcoexist->bt_info.bt_tx_rx_mask = *bool_tmp;
+ break;
+ case BTC_SET_BL_MIRACAST_PLUS_BT:
+ btcoexist->bt_info.miracast_plus_bt = *bool_tmp;
+ break;
/* set some u1Byte type variables. */
case BTC_SET_U1_RSSI_ADJ_VAL_FOR_AGC_TABLE_ON:
btcoexist->bt_info.rssi_adjust_for_agc_table_on = *u8_tmp;
@@ -432,25 +564,24 @@ static bool halbtc_set(void *void_btcoexist, u8 set_type, void *in_buf)
case BTC_SET_U1_AGG_BUF_SIZE:
btcoexist->bt_info.agg_buf_size = *u8_tmp;
break;
- /* the following are some action which will be triggered */
+
+ /* the following are some action which will be triggered */
case BTC_SET_ACT_GET_BT_RSSI:
- /*BTHCI_SendGetBtRssiEvent(rtlpriv);*/
break;
case BTC_SET_ACT_AGGREGATE_CTRL:
- halbtc_aggregation_check();
+ halbtc_aggregation_check(btcoexist);
break;
- /* 1Ant */
+ /* 1Ant */
case BTC_SET_U1_RSSI_ADJ_VAL_FOR_1ANT_COEX_TYPE:
btcoexist->bt_info.rssi_adjust_for_1ant_coex_type = *u8_tmp;
break;
case BTC_SET_UI_SCAN_SIG_COMPENSATION:
- /* rtlpriv->mlmepriv.scan_compensation = *u8_tmp; */
break;
- case BTC_SET_U1_1ANT_LPS:
+ case BTC_SET_U1_LPS_VAL:
btcoexist->bt_info.lps_val = *u8_tmp;
break;
- case BTC_SET_U1_1ANT_RPWM:
+ case BTC_SET_U1_RPWM_VAL:
btcoexist->bt_info.rpwm_val = *u8_tmp;
break;
/* the following are some action which will be triggered */
@@ -464,20 +595,19 @@ static bool halbtc_set(void *void_btcoexist, u8 set_type, void *in_buf)
halbtc_normal_lps(btcoexist);
break;
case BTC_SET_ACT_DISABLE_LOW_POWER:
- halbtc_disable_low_power();
+ halbtc_disable_low_power(btcoexist, *bool_tmp);
break;
case BTC_SET_ACT_UPDATE_RAMASK:
btcoexist->bt_info.ra_mask = *u32_tmp;
break;
case BTC_SET_ACT_SEND_MIMO_PS:
break;
- case BTC_SET_ACT_INC_FORCE_EXEC_PWR_CMD_CNT:
- btcoexist->bt_info.force_exec_pwr_cmd_cnt++;
- break;
case BTC_SET_ACT_CTRL_BT_INFO: /*wait for 8812/8821*/
break;
case BTC_SET_ACT_CTRL_BT_COEX:
break;
+ case BTC_SET_ACT_CTRL_8723B_ANT:
+ break;
default:
break;
}
@@ -485,22 +615,6 @@ static bool halbtc_set(void *void_btcoexist, u8 set_type, void *in_buf)
return true;
}
-static void halbtc_display_coex_statistics(struct btc_coexist *btcoexist)
-{
-}
-
-static void halbtc_display_bt_link_info(struct btc_coexist *btcoexist)
-{
-}
-
-static void halbtc_display_bt_fw_info(struct btc_coexist *btcoexist)
-{
-}
-
-static void halbtc_display_fw_pwr_mode_cmd(struct btc_coexist *btcoexist)
-{
-}
-
/************************************************************
* IO related function
************************************************************/
@@ -574,6 +688,35 @@ static void halbtc_write_4byte(void *bt_context, u32 reg_addr, u32 data)
rtl_write_dword(rtlpriv, reg_addr, data);
}
+void halbtc_write_local_reg_1byte(void *btc_context, u32 reg_addr, u8 data)
+{
+ struct btc_coexist *btcoexist = (struct btc_coexist *)btc_context;
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+
+ if (btcoexist->chip_interface == BTC_INTF_SDIO)
+ ;
+ else if (btcoexist->chip_interface == BTC_INTF_PCI)
+ rtl_write_byte(rtlpriv, reg_addr, data);
+ else if (btcoexist->chip_interface == BTC_INTF_USB)
+ rtl_write_byte(rtlpriv, reg_addr, data);
+}
+
+void halbtc_set_macreg(void *btc_context, u32 reg_addr, u32 bit_mask, u32 data)
+{
+ struct btc_coexist *btcoexist = (struct btc_coexist *)btc_context;
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+
+ rtl_set_bbreg(rtlpriv->mac80211.hw, reg_addr, bit_mask, data);
+}
+
+u32 halbtc_get_macreg(void *btc_context, u32 reg_addr, u32 bit_mask)
+{
+ struct btc_coexist *btcoexist = (struct btc_coexist *)btc_context;
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+
+ return rtl_get_bbreg(rtlpriv->mac80211.hw, reg_addr, bit_mask);
+}
+
static void halbtc_set_bbreg(void *bt_context, u32 reg_addr, u32 bit_mask,
u32 data)
{
@@ -619,50 +762,64 @@ static void halbtc_fill_h2c_cmd(void *bt_context, u8 element_id,
cmd_len, cmd_buf);
}
-static void halbtc_display_dbg_msg(void *bt_context, u8 disp_type)
+void halbtc_set_bt_reg(void *btc_context, u8 reg_type, u32 offset, u32 set_val)
{
- struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context;
- switch (disp_type) {
- case BTC_DBG_DISP_COEX_STATISTICS:
- halbtc_display_coex_statistics(btcoexist);
- break;
- case BTC_DBG_DISP_BT_LINK_INFO:
- halbtc_display_bt_link_info(btcoexist);
- break;
- case BTC_DBG_DISP_BT_FW_VER:
- halbtc_display_bt_fw_info(btcoexist);
- break;
- case BTC_DBG_DISP_FW_PWR_MODE_CMD:
- halbtc_display_fw_pwr_mode_cmd(btcoexist);
- break;
- default:
- break;
+ struct btc_coexist *btcoexist = (struct btc_coexist *)btc_context;
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+ u8 cmd_buffer1[4] = {0};
+ u8 cmd_buffer2[4] = {0};
+ u8 *addr_to_set = (u8 *)&offset;
+ u8 *value_to_set = (u8 *)&set_val;
+ u8 oper_ver = 0;
+ u8 req_num = 0;
+
+ if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ cmd_buffer1[0] |= (oper_ver & 0x0f); /* Set OperVer */
+ cmd_buffer1[0] |= ((req_num << 4) & 0xf0); /* Set ReqNum */
+ cmd_buffer1[1] = 0x0d; /* OpCode: BT_LO_OP_WRITE_REG_VALUE */
+ cmd_buffer1[2] = value_to_set[0]; /* Set WriteRegValue */
+ rtlpriv->cfg->ops->fill_h2c_cmd(rtlpriv->mac80211.hw, 0x67, 4,
+ &cmd_buffer1[0]);
+
+ msleep(200);
+ req_num++;
+
+ cmd_buffer2[0] |= (oper_ver & 0x0f); /* Set OperVer */
+ cmd_buffer2[0] |= ((req_num << 4) & 0xf0); /* Set ReqNum */
+ cmd_buffer2[1] = 0x0c; /* OpCode: BT_LO_OP_WRITE_REG_ADDR */
+ cmd_buffer2[3] = addr_to_set[0]; /* Set WriteRegAddr */
+ rtlpriv->cfg->ops->fill_h2c_cmd(rtlpriv->mac80211.hw, 0x67, 4,
+ &cmd_buffer2[0]);
+ }
+}
+
+bool halbtc_under_ips(struct btc_coexist *btcoexist)
+{
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
+ enum rf_pwrstate rtstate;
+
+ if (ppsc->inactiveps) {
+ rtstate = ppsc->rfpwr_state;
+
+ if (rtstate != ERFON &&
+ ppsc->rfoff_reason == RF_CHANGE_BY_IPS) {
+ return true;
+ }
}
+
+ return false;
}
/*****************************************************************
* Extern functions called by other module
*****************************************************************/
-bool exhalbtc_initlize_variables(struct rtl_priv *adapter)
+bool exhalbtc_initlize_variables(void)
{
struct btc_coexist *btcoexist = &gl_bt_coexist;
- btcoexist->statistics.cnt_bind++;
-
halbtc_dbg_init();
- if (btcoexist->binded)
- return false;
- else
- btcoexist->binded = true;
-
- btcoexist->chip_interface = BTC_INTF_UNKNOWN;
-
- if (NULL == btcoexist->adapter)
- btcoexist->adapter = adapter;
-
- btcoexist->stack_info.profile_notified = false;
-
btcoexist->btc_read_1byte = halbtc_read_1byte;
btcoexist->btc_write_1byte = halbtc_write_1byte;
btcoexist->btc_write_1byte_bitmask = halbtc_bitmask_write_1byte;
@@ -670,6 +827,7 @@ bool exhalbtc_initlize_variables(struct rtl_priv *adapter)
btcoexist->btc_write_2byte = halbtc_write_2byte;
btcoexist->btc_read_4byte = halbtc_read_4byte;
btcoexist->btc_write_4byte = halbtc_write_4byte;
+ btcoexist->btc_write_local_reg_1byte = halbtc_write_local_reg_1byte;
btcoexist->btc_set_bb_reg = halbtc_set_bbreg;
btcoexist->btc_get_bb_reg = halbtc_get_bbreg;
@@ -678,10 +836,11 @@ bool exhalbtc_initlize_variables(struct rtl_priv *adapter)
btcoexist->btc_get_rf_reg = halbtc_get_rfreg;
btcoexist->btc_fill_h2c = halbtc_fill_h2c_cmd;
- btcoexist->btc_disp_dbg_msg = halbtc_display_dbg_msg;
btcoexist->btc_get = halbtc_get;
btcoexist->btc_set = halbtc_set;
+ btcoexist->btc_set_bt_reg = halbtc_set_bt_reg;
+
btcoexist->bt_info.bt_ctrl_buf_size = false;
btcoexist->bt_info.agg_buf_size = 5;
@@ -690,40 +849,148 @@ bool exhalbtc_initlize_variables(struct rtl_priv *adapter)
return true;
}
-void exhalbtc_init_hw_config(struct btc_coexist *btcoexist)
+bool exhalbtc_bind_bt_coex_withadapter(void *adapter)
{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+ struct btc_coexist *btcoexist = &gl_bt_coexist;
+ struct rtl_priv *rtlpriv = adapter;
+ u8 ant_num = 2, chip_type, single_ant_path = 0;
+
+ if (btcoexist->binded)
+ return false;
+ switch (rtlpriv->rtlhal.interface) {
+ case INTF_PCI:
+ btcoexist->chip_interface = BTC_INTF_PCI;
+ break;
+ case INTF_USB:
+ btcoexist->chip_interface = BTC_INTF_USB;
+ break;
+ default:
+ btcoexist->chip_interface = BTC_INTF_UNKNOWN;
+ break;
+ }
+
+ btcoexist->binded = true;
+ btcoexist->statistics.cnt_bind++;
+
+ btcoexist->adapter = adapter;
+
+ btcoexist->stack_info.profile_notified = false;
+
+ btcoexist->bt_info.bt_ctrl_agg_buf_size = false;
+ btcoexist->bt_info.agg_buf_size = 5;
+
+ btcoexist->bt_info.increase_scan_dev_num = false;
+ btcoexist->bt_info.miracast_plus_bt = false;
+
+ chip_type = rtl_get_hwpg_bt_type(rtlpriv);
+ exhalbtc_set_chip_type(chip_type);
+ ant_num = rtl_get_hwpg_ant_num(rtlpriv);
+ exhalbtc_set_ant_num(rtlpriv, BT_COEX_ANT_TYPE_PG, ant_num);
+
+ /* set default antenna position to main port */
+ btcoexist->board_info.btdm_ant_pos = BTC_ANTENNA_AT_MAIN_PORT;
+
+ single_ant_path = rtl_get_hwpg_single_ant_path(rtlpriv);
+ exhalbtc_set_single_ant_path(single_ant_path);
+
+ if (rtl_get_hwpg_package_type(rtlpriv) == 0)
+ btcoexist->board_info.tfbga_package = false;
+ else if (rtl_get_hwpg_package_type(rtlpriv) == 1)
+ btcoexist->board_info.tfbga_package = false;
+ else
+ btcoexist->board_info.tfbga_package = true;
+
+ if (btcoexist->board_info.tfbga_package)
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], Package Type = TFBGA\n");
+ else
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], Package Type = Non-TFBGA\n");
+
+ return true;
+}
+
+void exhalbtc_power_on_setting(struct btc_coexist *btcoexist)
+{
+ if (!halbtc_is_bt_coexist_available(btcoexist))
+ return;
+
+ btcoexist->statistics.cnt_power_on++;
+
+ if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_power_on_setting(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_power_on_setting(btcoexist);
+ }
+}
+
+void exhalbtc_pre_load_firmware(struct btc_coexist *btcoexist)
+{
+ if (!halbtc_is_bt_coexist_available(btcoexist))
+ return;
+
+ btcoexist->statistics.cnt_pre_load_firmware++;
+
+ if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_pre_load_firmware(btcoexist);
+ }
+}
+
+void exhalbtc_init_hw_config(struct btc_coexist *btcoexist, bool wifi_only)
+{
if (!halbtc_is_bt_coexist_available(btcoexist))
return;
btcoexist->statistics.cnt_init_hw_config++;
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_init_hwconfig(btcoexist);
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_init_hwconfig(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_init_hwconfig(btcoexist, wifi_only);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_init_hwconfig(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_init_hwconfig(btcoexist, wifi_only);
+ } else if (IS_HARDWARE_TYPE_8723A(btcoexist->adapter)) {
+ /* 8723A has no this function */
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_init_hwconfig(btcoexist);
+ }
}
void exhalbtc_init_coex_dm(struct btc_coexist *btcoexist)
{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
-
if (!halbtc_is_bt_coexist_available(btcoexist))
return;
btcoexist->statistics.cnt_init_coex_dm++;
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_init_coex_dm(btcoexist);
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_init_coex_dm(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_init_coex_dm(btcoexist);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_init_coex_dm(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_init_coex_dm(btcoexist);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_init_coex_dm(btcoexist);
+ }
btcoexist->initilized = true;
}
void exhalbtc_ips_notify(struct btc_coexist *btcoexist, u8 type)
{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
u8 ips_type;
if (!halbtc_is_bt_coexist_available(btcoexist))
@@ -737,18 +1004,28 @@ void exhalbtc_ips_notify(struct btc_coexist *btcoexist, u8 type)
else
ips_type = BTC_IPS_LEAVE;
- halbtc_leave_low_power();
-
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_ips_notify(btcoexist, ips_type);
+ halbtc_leave_low_power(btcoexist);
+
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_ips_notify(btcoexist, ips_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_ips_notify(btcoexist, ips_type);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_ips_notify(btcoexist, ips_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_ips_notify(btcoexist, ips_type);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_ips_notify(btcoexist, ips_type);
+ }
- halbtc_nomal_low_power();
+ halbtc_normal_low_power(btcoexist);
}
void exhalbtc_lps_notify(struct btc_coexist *btcoexist, u8 type)
{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
u8 lps_type;
if (!halbtc_is_bt_coexist_available(btcoexist))
@@ -762,14 +1039,24 @@ void exhalbtc_lps_notify(struct btc_coexist *btcoexist, u8 type)
else
lps_type = BTC_LPS_ENABLE;
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_lps_notify(btcoexist, lps_type);
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_lps_notify(btcoexist, lps_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_lps_notify(btcoexist, lps_type);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_lps_notify(btcoexist, lps_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_lps_notify(btcoexist, lps_type);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_lps_notify(btcoexist, lps_type);
+ }
}
void exhalbtc_scan_notify(struct btc_coexist *btcoexist, u8 type)
{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
u8 scan_type;
if (!halbtc_is_bt_coexist_available(btcoexist))
@@ -783,18 +1070,28 @@ void exhalbtc_scan_notify(struct btc_coexist *btcoexist, u8 type)
else
scan_type = BTC_SCAN_FINISH;
- halbtc_leave_low_power();
-
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_scan_notify(btcoexist, scan_type);
+ halbtc_leave_low_power(btcoexist);
+
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_scan_notify(btcoexist, scan_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_scan_notify(btcoexist, scan_type);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_scan_notify(btcoexist, scan_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_scan_notify(btcoexist, scan_type);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_scan_notify(btcoexist, scan_type);
+ }
- halbtc_nomal_low_power();
+ halbtc_normal_low_power(btcoexist);
}
void exhalbtc_connect_notify(struct btc_coexist *btcoexist, u8 action)
{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
u8 asso_type;
if (!halbtc_is_bt_coexist_available(btcoexist))
@@ -808,10 +1105,24 @@ void exhalbtc_connect_notify(struct btc_coexist *btcoexist, u8 action)
else
asso_type = BTC_ASSOCIATE_FINISH;
- halbtc_leave_low_power();
+ halbtc_leave_low_power(btcoexist);
+
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_connect_notify(btcoexist, asso_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_connect_notify(btcoexist, asso_type);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_connect_notify(btcoexist, asso_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_connect_notify(btcoexist, asso_type);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_connect_notify(btcoexist, asso_type);
+ }
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_connect_notify(btcoexist, asso_type);
+ halbtc_normal_low_power(btcoexist);
}
void exhalbtc_mediastatus_notify(struct btc_coexist *btcoexist,
@@ -830,15 +1141,28 @@ void exhalbtc_mediastatus_notify(struct btc_coexist *btcoexist,
else
status = BTC_MEDIA_DISCONNECT;
- halbtc_leave_low_power();
+ halbtc_leave_low_power(btcoexist);
+
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_media_status_notify(btcoexist, status);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_media_status_notify(btcoexist, status);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_media_status_notify(btcoexist, status);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_media_status_notify(btcoexist, status);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_media_status_notify(btcoexist, status);
+ }
- halbtc_nomal_low_power();
+ halbtc_normal_low_power(btcoexist);
}
void exhalbtc_special_packet_notify(struct btc_coexist *btcoexist, u8 pkt_type)
{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
u8 packet_type;
if (!halbtc_is_bt_coexist_available(btcoexist))
@@ -847,28 +1171,85 @@ void exhalbtc_special_packet_notify(struct btc_coexist *btcoexist, u8 pkt_type)
if (btcoexist->manual_control)
return;
- packet_type = BTC_PACKET_DHCP;
-
- halbtc_leave_low_power();
+ if (pkt_type == PACKET_DHCP) {
+ packet_type = BTC_PACKET_DHCP;
+ } else if (pkt_type == PACKET_EAPOL) {
+ packet_type = BTC_PACKET_EAPOL;
+ } else if (pkt_type == PACKET_ARP) {
+ packet_type = BTC_PACKET_ARP;
+ } else {
+ packet_type = BTC_PACKET_UNKNOWN;
+ return;
+ }
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_special_packet_notify(btcoexist,
- packet_type);
+ halbtc_leave_low_power(btcoexist);
+
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_special_packet_notify(btcoexist,
+ packet_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_special_packet_notify(btcoexist,
+ packet_type);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_special_packet_notify(btcoexist,
+ packet_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_special_packet_notify(btcoexist,
+ packet_type);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_special_packet_notify(btcoexist,
+ packet_type);
+ }
- halbtc_nomal_low_power();
+ halbtc_normal_low_power(btcoexist);
}
void exhalbtc_bt_info_notify(struct btc_coexist *btcoexist,
u8 *tmp_buf, u8 length)
{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
if (!halbtc_is_bt_coexist_available(btcoexist))
return;
btcoexist->statistics.cnt_bt_info_notify++;
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_bt_info_notify(btcoexist, tmp_buf, length);
+ halbtc_leave_low_power(btcoexist);
+
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_bt_info_notify(btcoexist, tmp_buf,
+ length);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_bt_info_notify(btcoexist, tmp_buf,
+ length);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_bt_info_notify(btcoexist, tmp_buf,
+ length);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_bt_info_notify(btcoexist, tmp_buf,
+ length);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_bt_info_notify(btcoexist, tmp_buf,
+ length);
+ }
+
+ halbtc_normal_low_power(btcoexist);
+}
+
+void exhalbtc_rf_status_notify(struct btc_coexist *btcoexist, u8 type)
+{
+ if (!halbtc_is_bt_coexist_available(btcoexist))
+ return;
+
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_rf_status_notify(btcoexist, type);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ }
}
void exhalbtc_stack_operation_notify(struct btc_coexist *btcoexist, u8 type)
@@ -881,44 +1262,117 @@ void exhalbtc_stack_operation_notify(struct btc_coexist *btcoexist, u8 type)
if (btcoexist->manual_control)
return;
- stack_op_type = BTC_STACK_OP_NONE;
-
- halbtc_leave_low_power();
-
- halbtc_nomal_low_power();
+ if ((type == HCI_BT_OP_INQUIRY_START) ||
+ (type == HCI_BT_OP_PAGING_START) ||
+ (type == HCI_BT_OP_PAIRING_START)) {
+ stack_op_type = BTC_STACK_OP_INQ_PAGE_PAIR_START;
+ } else if ((type == HCI_BT_OP_INQUIRY_FINISH) ||
+ (type == HCI_BT_OP_PAGING_SUCCESS) ||
+ (type == HCI_BT_OP_PAGING_UNSUCCESS) ||
+ (type == HCI_BT_OP_PAIRING_FINISH)) {
+ stack_op_type = BTC_STACK_OP_INQ_PAGE_PAIR_FINISH;
+ } else {
+ stack_op_type = BTC_STACK_OP_NONE;
+ }
}
void exhalbtc_halt_notify(struct btc_coexist *btcoexist)
{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
if (!halbtc_is_bt_coexist_available(btcoexist))
return;
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_halt_notify(btcoexist);
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_halt_notify(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_halt_notify(btcoexist);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_halt_notify(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_halt_notify(btcoexist);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_halt_notify(btcoexist);
+ }
+
+ btcoexist->binded = false;
}
void exhalbtc_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state)
{
if (!halbtc_is_bt_coexist_available(btcoexist))
return;
+
+ /* currently only 1ant we have to do the notification,
+ * once pnp is notified to sleep state, we have to leave LPS that
+ * we can sleep normally.
+ */
+
+ if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_pnp_notify(btcoexist, pnp_state);
+ else if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_pnp_notify(btcoexist, pnp_state);
+ } else if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_pnp_notify(btcoexist, pnp_state);
+ else if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_pnp_notify(btcoexist, pnp_state);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ }
}
-void exhalbtc_periodical(struct btc_coexist *btcoexist)
+void exhalbtc_coex_dm_switch(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
if (!halbtc_is_bt_coexist_available(btcoexist))
return;
- btcoexist->statistics.cnt_periodical++;
+ btcoexist->statistics.cnt_coex_dm_switch++;
+
+ halbtc_leave_low_power(btcoexist);
+
+ if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 1) {
+ btcoexist->stop_coex_dm = true;
+ ex_btc8723b1ant_coex_dm_reset(btcoexist);
+ exhalbtc_set_ant_num(rtlpriv,
+ BT_COEX_ANT_TYPE_DETECTED, 2);
+ ex_btc8723b2ant_init_hwconfig(btcoexist);
+ ex_btc8723b2ant_init_coex_dm(btcoexist);
+ btcoexist->stop_coex_dm = false;
+ }
+ }
+
+ halbtc_normal_low_power(btcoexist);
+}
- halbtc_leave_low_power();
+void exhalbtc_periodical(struct btc_coexist *btcoexist)
+{
+ if (!halbtc_is_bt_coexist_available(btcoexist))
+ return;
+ btcoexist->statistics.cnt_periodical++;
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_periodical(btcoexist);
+ halbtc_leave_low_power(btcoexist);
+
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_periodical(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ if (!halbtc_under_ips(btcoexist))
+ ex_btc8821a1ant_periodical(btcoexist);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_periodical(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_periodical(btcoexist);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_periodical(btcoexist);
+ }
- halbtc_nomal_low_power();
+ halbtc_normal_low_power(btcoexist);
}
void exhalbtc_dbg_control(struct btc_coexist *btcoexist,
@@ -927,6 +1381,17 @@ void exhalbtc_dbg_control(struct btc_coexist *btcoexist,
if (!halbtc_is_bt_coexist_available(btcoexist))
return;
btcoexist->statistics.cnt_dbg_ctrl++;
+
+ halbtc_leave_low_power(btcoexist);
+
+ halbtc_normal_low_power(btcoexist);
+}
+
+void exhalbtc_antenna_detection(struct btc_coexist *btcoexist, u32 cent_freq,
+ u32 offset, u32 span, u32 seconds)
+{
+ if (!halbtc_is_bt_coexist_available(btcoexist))
+ return;
}
void exhalbtc_stack_update_profile_info(void)
@@ -964,11 +1429,6 @@ void exhalbtc_set_bt_patch_version(u16 bt_hci_version, u16 bt_patch_version)
btcoexist->bt_info.bt_hci_ver = bt_hci_version;
}
-void exhalbtc_set_bt_exist(bool bt_exist)
-{
- gl_bt_coexist.board_info.bt_exist = bt_exist;
-}
-
void exhalbtc_set_chip_type(u8 chip_type)
{
switch (chip_type) {
@@ -1002,25 +1462,8 @@ void exhalbtc_set_ant_num(struct rtl_priv *rtlpriv, u8 type, u8 ant_num)
if (BT_COEX_ANT_TYPE_PG == type) {
gl_bt_coexist.board_info.pg_ant_num = ant_num;
gl_bt_coexist.board_info.btdm_ant_num = ant_num;
- /* The antenna position:
- * Main (default) or Aux for pgAntNum=2 && btdmAntNum =1.
- * The antenna position should be determined by
- * auto-detect mechanism.
- * The following is assumed to main,
- * and those must be modified
- * if y auto-detect mechanism is ready
- */
- if ((gl_bt_coexist.board_info.pg_ant_num == 2) &&
- (gl_bt_coexist.board_info.btdm_ant_num == 1))
- gl_bt_coexist.board_info.btdm_ant_pos =
- BTC_ANTENNA_AT_MAIN_PORT;
- else
- gl_bt_coexist.board_info.btdm_ant_pos =
- BTC_ANTENNA_AT_MAIN_PORT;
} else if (BT_COEX_ANT_TYPE_ANTDIV == type) {
gl_bt_coexist.board_info.btdm_ant_num = ant_num;
- gl_bt_coexist.board_info.btdm_ant_pos =
- BTC_ANTENNA_AT_MAIN_PORT;
} else if (type == BT_COEX_ANT_TYPE_DETECTED) {
gl_bt_coexist.board_info.btdm_ant_num = ant_num;
if (rtlpriv->cfg->mod_params->ant_sel == 1)
@@ -1032,13 +1475,33 @@ void exhalbtc_set_ant_num(struct rtl_priv *rtlpriv, u8 type, u8 ant_num)
}
}
+/* Currently used by 8723b only, S0 or S1 */
+void exhalbtc_set_single_ant_path(u8 single_ant_path)
+{
+ gl_bt_coexist.board_info.single_ant_path = single_ant_path;
+}
+
void exhalbtc_display_bt_coex_info(struct btc_coexist *btcoexist)
{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
if (!halbtc_is_bt_coexist_available(btcoexist))
return;
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_display_coex_info(btcoexist);
+ halbtc_leave_low_power(btcoexist);
+
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_display_coex_info(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_display_coex_info(btcoexist);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_display_coex_info(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_display_coex_info(btcoexist);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_display_coex_info(btcoexist);
+ }
+
+ halbtc_normal_low_power(btcoexist);
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
index c5c360e011a9..f9b87c12db09 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
@@ -153,6 +153,7 @@ struct btc_board_info {
u8 btdm_ant_pos;
u8 single_ant_path; /* current used for 8723b only, 1=>s0, 0=>s1 */
bool bt_exist;
+ bool tfbga_package;
};
enum btc_dbg_opcode {
@@ -217,6 +218,26 @@ enum btc_iot_peer {
BTC_IOT_PEER_MAX,
};
+/* for 8723b-d cut large current issue */
+enum bt_wifi_coex_state {
+ BTC_WIFI_STAT_INIT,
+ BTC_WIFI_STAT_IQK,
+ BTC_WIFI_STAT_NORMAL_OFF,
+ BTC_WIFI_STAT_MP_OFF,
+ BTC_WIFI_STAT_NORMAL,
+ BTC_WIFI_STAT_ANT_DIV,
+ BTC_WIFI_STAT_MAX
+};
+
+enum bt_ant_type {
+ BTC_ANT_TYPE_0,
+ BTC_ANT_TYPE_1,
+ BTC_ANT_TYPE_2,
+ BTC_ANT_TYPE_3,
+ BTC_ANT_TYPE_4,
+ BTC_ANT_TYPE_MAX
+};
+
enum btc_get_type {
/* type bool */
BTC_GET_BL_HS_OPERATION,
@@ -237,6 +258,9 @@ enum btc_get_type {
BTC_GET_BL_WIFI_UNDER_B_MODE,
BTC_GET_BL_EXT_SWITCH,
BTC_GET_BL_WIFI_IS_IN_MP_MODE,
+ BTC_GET_BL_IS_ASUS_8723B,
+ BTC_GET_BL_FW_READY,
+ BTC_GET_BL_RF4CE_CONNECTED,
/* type s4Byte */
BTC_GET_S4_WIFI_RSSI,
@@ -249,6 +273,11 @@ enum btc_get_type {
BTC_GET_U4_WIFI_LINK_STATUS,
BTC_GET_U4_BT_PATCH_VER,
BTC_GET_U4_VENDOR,
+ BTC_GET_U4_SUPPORTED_VERSION,
+ BTC_GET_U4_SUPPORTED_FEATURE,
+ BTC_GET_U4_WIFI_IQK_TOTAL,
+ BTC_GET_U4_WIFI_IQK_OK,
+ BTC_GET_U4_WIFI_IQK_FAIL,
/* type u1Byte */
BTC_GET_U1_WIFI_DOT11_CHNL,
@@ -256,6 +285,7 @@ enum btc_get_type {
BTC_GET_U1_WIFI_HS_CHNL,
BTC_GET_U1_MAC_PHY_MODE,
BTC_GET_U1_AP_NUM,
+ BTC_GET_U1_ANT_TYPE,
BTC_GET_U1_IOT_PEER,
/* for 1Ant */
@@ -315,6 +345,7 @@ enum btc_set_type {
/* BT Coex related */
BTC_SET_ACT_CTRL_BT_INFO,
BTC_SET_ACT_CTRL_BT_COEX,
+ BTC_SET_ACT_CTRL_8723B_ANT,
/***************************/
BTC_SET_MAX
};
@@ -433,12 +464,18 @@ struct btc_bt_info {
bool bt_disabled;
u8 rssi_adjust_for_agc_table_on;
u8 rssi_adjust_for_1ant_coex_type;
+ bool pre_bt_ctrl_agg_buf_size;
bool bt_busy;
+ u8 pre_agg_buf_size;
u8 agg_buf_size;
bool limited_dig;
+ bool pre_reject_agg_pkt;
bool reject_agg_pkt;
bool bt_ctrl_buf_size;
bool increase_scan_dev_num;
+ bool miracast_plus_bt;
+ bool bt_ctrl_agg_buf_size;
+ bool bt_tx_rx_mask;
u16 bt_hci_ver;
u16 bt_real_fw_ver;
u8 bt_fw_ver;
@@ -486,6 +523,8 @@ struct btc_statistics {
u32 cnt_coex_dm_switch;
u32 cnt_stack_operation_notify;
u32 cnt_dbg_ctrl;
+ u32 cnt_pre_load_firmware;
+ u32 cnt_power_on;
};
struct btc_bt_link_info {
@@ -560,8 +599,9 @@ bool halbtc_is_wifi_uplink(struct rtl_priv *adapter);
extern struct btc_coexist gl_bt_coexist;
-bool exhalbtc_initlize_variables(struct rtl_priv *adapter);
-void exhalbtc_init_hw_config(struct btc_coexist *btcoexist);
+bool exhalbtc_initlize_variables(void);
+bool exhalbtc_bind_bt_coex_withadapter(void *adapter);
+void exhalbtc_init_hw_config(struct btc_coexist *btcoexist, bool wifi_only);
void exhalbtc_init_coex_dm(struct btc_coexist *btcoexist);
void exhalbtc_ips_notify(struct btc_coexist *btcoexist, u8 type);
void exhalbtc_lps_notify(struct btc_coexist *btcoexist, u8 type);
@@ -591,5 +631,6 @@ void exhalbtc_signal_compensation(struct btc_coexist *btcoexist,
u8 *rssi_wifi, u8 *rssi_bt);
void exhalbtc_lps_leave(struct btc_coexist *btcoexist);
void exhalbtc_low_wifi_traffic_notify(struct btc_coexist *btcoexist);
+void exhalbtc_set_single_ant_path(u8 single_ant_path);
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
index 46e0fa6be273..4366c9817e1e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
@@ -45,42 +45,79 @@ static struct rtl_btc_ops rtl_btc_operation = {
.btc_is_disable_edca_turbo = rtl_btc_is_disable_edca_turbo,
.btc_is_bt_disabled = rtl_btc_is_bt_disabled,
.btc_special_packet_notify = rtl_btc_special_packet_notify,
+ .btc_record_pwr_mode = rtl_btc_record_pwr_mode,
+ .btc_get_lps_val = rtl_btc_get_lps_val,
+ .btc_get_rpwm_val = rtl_btc_get_rpwm_val,
+ .btc_is_bt_ctrl_lps = rtl_btc_is_bt_ctrl_lps,
+ .btc_is_bt_lps_on = rtl_btc_is_bt_lps_on,
+ .btc_get_ampdu_cfg = rtl_btc_get_ampdu_cfg,
};
-void rtl_btc_init_variables(struct rtl_priv *rtlpriv)
+void rtl_btc_record_pwr_mode(struct rtl_priv *rtlpriv, u8 *buf, u8 len)
{
- exhalbtc_initlize_variables(rtlpriv);
+ u8 safe_len;
+
+ safe_len = sizeof(gl_bt_coexist.pwr_mode_val);
+
+ if (safe_len > len)
+ safe_len = len;
+
+ memcpy(gl_bt_coexist.pwr_mode_val, buf, safe_len);
}
-void rtl_btc_init_hal_vars(struct rtl_priv *rtlpriv)
+u8 rtl_btc_get_lps_val(struct rtl_priv *rtlpriv)
{
- u8 ant_num;
- u8 bt_exist;
- u8 bt_type;
+ return gl_bt_coexist.bt_info.lps_val;
+}
- ant_num = rtl_get_hwpg_ant_num(rtlpriv);
- RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- "%s, antNum is %d\n", __func__, ant_num);
+u8 rtl_btc_get_rpwm_val(struct rtl_priv *rtlpriv)
+{
+ return gl_bt_coexist.bt_info.rpwm_val;
+}
- bt_exist = rtl_get_hwpg_bt_exist(rtlpriv);
- RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- "%s, bt_exist is %d\n", __func__, bt_exist);
- exhalbtc_set_bt_exist(bt_exist);
+bool rtl_btc_is_bt_ctrl_lps(struct rtl_priv *rtlpriv)
+{
+ return gl_bt_coexist.bt_info.bt_ctrl_lps;
+}
+
+bool rtl_btc_is_bt_lps_on(struct rtl_priv *rtlpriv)
+{
+ return gl_bt_coexist.bt_info.bt_lps_on;
+}
- bt_type = rtl_get_hwpg_bt_type(rtlpriv);
- RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%s, bt_type is %d\n",
- __func__, bt_type);
- exhalbtc_set_chip_type(bt_type);
+void rtl_btc_get_ampdu_cfg(struct rtl_priv *rtlpriv, u8 *reject_agg,
+ u8 *ctrl_agg_size, u8 *agg_size)
+{
+ if (reject_agg)
+ *reject_agg = gl_bt_coexist.bt_info.reject_agg_pkt;
+ if (ctrl_agg_size)
+ *ctrl_agg_size = gl_bt_coexist.bt_info.bt_ctrl_agg_buf_size;
+ if (agg_size)
+ *agg_size = gl_bt_coexist.bt_info.agg_buf_size;
+}
- if (rtlpriv->cfg->mod_params->ant_sel == 1)
- exhalbtc_set_ant_num(rtlpriv, BT_COEX_ANT_TYPE_DETECTED, 1);
- else
- exhalbtc_set_ant_num(rtlpriv, BT_COEX_ANT_TYPE_PG, ant_num);
+void rtl_btc_init_variables(struct rtl_priv *rtlpriv)
+{
+ exhalbtc_initlize_variables();
+ exhalbtc_bind_bt_coex_withadapter(rtlpriv);
+}
+
+void rtl_btc_init_hal_vars(struct rtl_priv *rtlpriv)
+{
+ /* move ant_num, bt_type and single_ant_path to
+ * exhalbtc_bind_bt_coex_withadapter()
+ */
}
void rtl_btc_init_hw_config(struct rtl_priv *rtlpriv)
{
- exhalbtc_init_hw_config(&gl_bt_coexist);
+ u8 bt_exist;
+
+ bt_exist = rtl_get_hwpg_bt_exist(rtlpriv);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+ "%s, bt_exist is %d\n", __func__, bt_exist);
+
+ exhalbtc_init_hw_config(&gl_bt_coexist, !bt_exist);
exhalbtc_init_coex_dm(&gl_bt_coexist);
}
@@ -118,7 +155,9 @@ void rtl_btc_periodical(struct rtl_priv *rtlpriv)
void rtl_btc_halt_notify(void)
{
- exhalbtc_halt_notify(&gl_bt_coexist);
+ struct btc_coexist *btcoexist = &gl_bt_coexist;
+
+ exhalbtc_halt_notify(btcoexist);
}
void rtl_btc_btinfo_notify(struct rtl_priv *rtlpriv, u8 *tmp_buf, u8 length)
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h
index fff5117e1c4e..6fe521cbe7f0 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h
@@ -43,6 +43,13 @@ bool rtl_btc_is_limited_dig(struct rtl_priv *rtlpriv);
bool rtl_btc_is_disable_edca_turbo(struct rtl_priv *rtlpriv);
bool rtl_btc_is_bt_disabled(struct rtl_priv *rtlpriv);
void rtl_btc_special_packet_notify(struct rtl_priv *rtlpriv, u8 pkt_type);
+void rtl_btc_record_pwr_mode(struct rtl_priv *rtlpriv, u8 *buf, u8 len);
+u8 rtl_btc_get_lps_val(struct rtl_priv *rtlpriv);
+u8 rtl_btc_get_rpwm_val(struct rtl_priv *rtlpriv);
+bool rtl_btc_is_bt_ctrl_lps(struct rtl_priv *rtlpriv);
+bool rtl_btc_is_bt_lps_on(struct rtl_priv *rtlpriv);
+void rtl_btc_get_ampdu_cfg(struct rtl_priv *rtlpriv, u8 *reject_agg,
+ u8 *ctrl_agg_size, u8 *agg_size);
struct rtl_btc_ops *rtl_btc_get_ops_pointer(void);
diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c
index a4f8e326a2bc..1a53a95d373b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/core.c
+++ b/drivers/net/wireless/realtek/rtlwifi/core.c
@@ -629,7 +629,8 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
}
/*For LPS */
- if (changed & IEEE80211_CONF_CHANGE_PS) {
+ if ((changed & IEEE80211_CONF_CHANGE_PS) &&
+ rtlpriv->psc.swctrl_lps && !rtlpriv->psc.fwctrl_lps) {
cancel_delayed_work(&rtlpriv->works.ps_work);
cancel_delayed_work(&rtlpriv->works.ps_rfon_wq);
if (conf->flags & IEEE80211_CONF_PS) {
@@ -1670,6 +1671,8 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
*so don't use rtl_cam_reset_all_entry
*or clear all entry here.
*/
+ rtl_wait_tx_report_acked(hw, 500); /* wait 500ms for TX ack */
+
rtl_cam_delete_one_entry(hw, mac_addr, key_idx);
break;
default:
diff --git a/drivers/net/wireless/realtek/rtlwifi/debug.c b/drivers/net/wireless/realtek/rtlwifi/debug.c
index 7ecac6116d5d..38fef6dbb44b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/debug.c
+++ b/drivers/net/wireless/realtek/rtlwifi/debug.c
@@ -27,7 +27,7 @@
#include <linux/moduleparam.h>
#ifdef CONFIG_RTLWIFI_DEBUG
-void _rtl_dbg_trace(struct rtl_priv *rtlpriv, int comp, int level,
+void _rtl_dbg_trace(struct rtl_priv *rtlpriv, u64 comp, int level,
const char *fmt, ...)
{
if (unlikely((comp & rtlpriv->cfg->mod_params->debug_mask) &&
diff --git a/drivers/net/wireless/realtek/rtlwifi/debug.h b/drivers/net/wireless/realtek/rtlwifi/debug.h
index bf5339f1c1bc..947718001457 100644
--- a/drivers/net/wireless/realtek/rtlwifi/debug.h
+++ b/drivers/net/wireless/realtek/rtlwifi/debug.h
@@ -105,6 +105,7 @@
#define COMP_EASY_CONCURRENT COMP_USB /* reuse of this bit is OK */
#define COMP_BT_COEXIST BIT(30)
#define COMP_IQK BIT(31)
+#define COMP_TX_REPORT BIT_ULL(32)
/*--------------------------------------------------------------
Define the rt_print components
@@ -169,7 +170,7 @@ enum dbgp_flag_e {
struct rtl_priv;
__printf(4, 5)
-void _rtl_dbg_trace(struct rtl_priv *rtlpriv, int comp, int level,
+void _rtl_dbg_trace(struct rtl_priv *rtlpriv, u64 comp, int level,
const char *fmt, ...);
__printf(4, 5)
@@ -198,7 +199,7 @@ struct rtl_priv;
__printf(4, 5)
static inline void RT_TRACE(struct rtl_priv *rtlpriv,
- int comp, int level,
+ u64 comp, int level,
const char *fmt, ...)
{
}
@@ -211,7 +212,7 @@ static inline void RTPRINT(struct rtl_priv *rtlpriv,
}
static inline void RT_PRINT_DATA(struct rtl_priv *rtlpriv,
- int comp, int level,
+ u64 comp, int level,
const char *titlestring,
const void *hexdata, size_t hexdatalen)
{
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h
index 15400ee6c04b..0c0d64aea651 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h
@@ -248,7 +248,6 @@
#define REG_RD_NAV_NXT 0x0544
#define REG_NAV_PROT_LEN 0x0546
#define REG_BCN_CTRL 0x0550
-#define REG_USTIME_TSF 0x0551
#define REG_MBID_NUM 0x0552
#define REG_DUAL_TSF_RST 0x0553
#define REG_BCN_INTERVAL 0x0554
@@ -256,6 +255,7 @@
#define REG_DRVERLYINT 0x0558
#define REG_BCNDMATIM 0x0559
#define REG_ATIMWND 0x055A
+#define REG_USTIME_TSF 0x055C
#define REG_BCN_MAX_ERR 0x055D
#define REG_RXTSF_OFFSET_CCK 0x055E
#define REG_RXTSF_OFFSET_OFDM 0x055F
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
index 7661cfa53032..774e72058d24 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
@@ -270,7 +270,7 @@ static struct rtl_hal_ops rtl8188ee_hal_ops = {
static struct rtl_mod_params rtl88ee_mod_params = {
.sw_crypto = false,
- .inactiveps = false,
+ .inactiveps = true,
.swctrl_lps = false,
.fwctrl_lps = false,
.msi_support = true,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h
index 1bb7ed35812d..9e3b58a5d2bb 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h
@@ -227,7 +227,6 @@
#define REG_RD_NAV_NXT 0x0544
#define REG_NAV_PROT_LEN 0x0546
#define REG_BCN_CTRL 0x0550
-#define REG_USTIME_TSF 0x0551
#define REG_MBID_NUM 0x0552
#define REG_DUAL_TSF_RST 0x0553
#define REG_BCN_INTERVAL 0x0554
@@ -235,6 +234,7 @@
#define REG_DRVERLYINT 0x0558
#define REG_BCNDMATIM 0x0559
#define REG_ATIMWND 0x055A
+#define REG_USTIME_TSF 0x055C
#define REG_BCN_MAX_ERR 0x055D
#define REG_RXTSF_OFFSET_CCK 0x055E
#define REG_RXTSF_OFFSET_OFDM 0x055F
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h
index b354b95936e2..d4c4e76a9244 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h
@@ -255,7 +255,6 @@
#define REG_RD_NAV_NXT 0x0544
#define REG_NAV_PROT_LEN 0x0546
#define REG_BCN_CTRL 0x0550
-#define REG_USTIME_TSF 0x0551
#define REG_MBID_NUM 0x0552
#define REG_DUAL_TSF_RST 0x0553
#define REG_BCN_INTERVAL 0x0554
@@ -263,6 +262,7 @@
#define REG_DRVERLYINT 0x0558
#define REG_BCNDMATIM 0x0559
#define REG_ATIMWND 0x055A
+#define REG_USTIME_TSF 0x055C
#define REG_BCN_MAX_ERR 0x055D
#define REG_RXTSF_OFFSET_CCK 0x055E
#define REG_RXTSF_OFFSET_OFDM 0x055F
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c
index 6f8f75ad0881..379dbc158dfc 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c
@@ -422,28 +422,80 @@ void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 u1_h2c_set_pwrmode[H2C_92E_PWEMODE_LENGTH] = { 0 };
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- u8 rlbm , power_state = 0;
+ u8 rlbm, power_state = 0, byte5 = 0;
+ u8 awake_intvl; /* DTIM = (awake_intvl - 1) */
+ struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
+ bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
+ btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
+
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
+ mode, bt_ctrl_lps);
+
+ switch (mode) {
+ case FW_PS_MIN_MODE:
+ rlbm = 0;
+ awake_intvl = 2;
+ break;
+ case FW_PS_MAX_MODE:
+ rlbm = 1;
+ awake_intvl = 2;
+ break;
+ case FW_PS_DTIM_MODE:
+ rlbm = 2;
+ awake_intvl = ppsc->reg_max_lps_awakeintvl;
+ /* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
+ * is only used in swlps.
+ */
+ break;
+ default:
+ rlbm = 2;
+ awake_intvl = 4;
+ break;
+ }
- RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , "FW LPS mode = %d\n", mode);
+ if (rtlpriv->mac80211.p2p) {
+ awake_intvl = 2;
+ rlbm = 1;
+ }
+
+ if (mode == FW_PS_ACTIVE_MODE) {
+ byte5 = 0x40;
+ power_state = FW_PWR_STATE_ACTIVE;
+ } else {
+ if (bt_ctrl_lps) {
+ byte5 = btc_ops->btc_get_lps_val(rtlpriv);
+ power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
+
+ if ((rlbm == 2) && (byte5 & BIT(4))) {
+ /* Keep awake interval to 1 to prevent from
+ * decreasing coex performance
+ */
+ awake_intvl = 2;
+ rlbm = 2;
+ }
+ } else {
+ byte5 = 0x40;
+ power_state = FW_PWR_STATE_RF_OFF;
+ }
+ }
SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
- rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/
SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
(rtlpriv->mac80211.p2p) ?
ppsc->smart_ps : 1);
SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
- ppsc->reg_max_lps_awakeintvl);
+ awake_intvl);
SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
- if (mode == FW_PS_ACTIVE_MODE)
- power_state |= FW_PWR_STATE_ACTIVE;
- else
- power_state |= FW_PWR_STATE_RF_OFF;
SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
+ SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
"rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH);
+ if (rtlpriv->cfg->ops->get_btc_status())
+ btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode,
+ H2C_92E_PWEMODE_LENGTH);
rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH,
u1_h2c_set_pwrmode);
}
@@ -842,6 +894,7 @@ void rtl92ee_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
case C2H_8192E_TX_REPORT:
RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE ,
"[C2H], C2H_8723BE_TX_REPORT!\n");
+ rtl_tx_report_handler(hw, tmp_buf, c2h_cmd_len);
break;
case C2H_8192E_BT_INFO:
RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h
index af8271967a88..b770f722daa6 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h
@@ -37,7 +37,7 @@
#define USE_OLD_WOWLAN_DEBUG_FW 0
#define H2C_92E_RSVDPAGE_LOC_LEN 5
-#define H2C_92E_PWEMODE_LENGTH 5
+#define H2C_92E_PWEMODE_LENGTH 7
#define H2C_92E_JOINBSSRPT_LENGTH 1
#define H2C_92E_AP_OFFLOAD_LENGTH 3
#define H2C_92E_WOWLAN_LENGTH 3
@@ -154,6 +154,8 @@ enum rtl8192e_c2h_evt {
SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __val)
#define SET_H2CCMD_PWRMODE_PARM_PWR_STATE(__cmd, __val) \
SET_BITS_TO_LE_1BYTE((__cmd)+4, 0, 8, __val)
+#define SET_H2CCMD_PWRMODE_PARM_BYTE5(__cmd, __val) \
+ SET_BITS_TO_LE_1BYTE((__cmd) + 5, 0, 8, __val)
#define GET_92E_H2CCMD_PWRMODE_PARM_MODE(__cmd) \
LE_BITS_TO_1BYTE(__cmd, 0, 8)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
index 48820bc497d8..eaa503b7c4b4 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
@@ -253,7 +253,7 @@ static struct rtl_hal_ops rtl8192ee_hal_ops = {
static struct rtl_mod_params rtl92ee_mod_params = {
.sw_crypto = false,
- .inactiveps = false,
+ .inactiveps = true,
.swctrl_lps = false,
.fwctrl_lps = true,
.msi_support = true,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c
index b1864bb07c2c..55f238a2a310 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c
@@ -731,6 +731,9 @@ void rtl92ee_tx_fill_desc(struct ieee80211_hw *hw,
SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
}
+ /* tx report */
+ rtl_get_tx_report(ptcb_desc, pdesc, hw);
+
SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate);
if (ieee80211_is_mgmt(fc)) {
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h
index 8053d1b12ec4..b0105c529010 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h
@@ -159,7 +159,7 @@
#define SET_TX_DESC_NULL_0(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 1, __val)
#define SET_TX_DESC_NULL_1(__pdesc, __val) \
- SET_BITS_TO_LE_4BYTE(__pdesc+8, 15, 1, __val)
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 8, 15, 1, __val)
#define SET_TX_DESC_BK(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 16, 1, __val)
#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \
@@ -167,7 +167,7 @@
#define SET_TX_DESC_RAW(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val)
#define SET_TX_DESC_SPE_RPT(__pdesc, __val) \
- SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val)
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 8, 19, 1, __val)
#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val)
#define SET_TX_DESC_BT_NULL(__pdesc, __val) \
@@ -252,15 +252,15 @@
/* Dword 6 */
#define SET_TX_DESC_SW_DEFINE(__pdesc, __val) \
- SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 12, __val)
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 0, 12, __val)
#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \
- SET_BITS_TO_LE_4BYTE(__pdesc+24, 16, 3, __val)
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 16, 3, __val)
#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \
- SET_BITS_TO_LE_4BYTE(__pdesc+24, 19, 3, __val)
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 19, 3, __val)
#define SET_TX_DESC_ANTSEL_C(__pdesc, __val) \
- SET_BITS_TO_LE_4BYTE(__pdesc+24, 22, 3, __val)
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 22, 3, __val)
#define SET_TX_DESC_ANTSEL_D(__pdesc, __val) \
- SET_BITS_TO_LE_4BYTE(__pdesc+24, 25, 3, __val)
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 25, 3, __val)
/* Dword 7 */
#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h
index 306059f9b9cc..30938cd9fce5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h
@@ -217,7 +217,6 @@
#define REG_RD_NAV_NXT 0x0544
#define REG_NAV_PROT_LEN 0x0546
#define REG_BCN_CTRL 0x0550
-#define REG_USTIME_TSF 0x0551
#define REG_MBID_NUM 0x0552
#define REG_DUAL_TSF_RST 0x0553
#define REG_BCN_INTERVAL 0x0554
@@ -225,6 +224,7 @@
#define REG_DRVERLYINT 0x0558
#define REG_BCNDMATIM 0x0559
#define REG_ATIMWND 0x055A
+#define REG_USTIME_TSF 0x055C
#define REG_BCN_MAX_ERR 0x055D
#define REG_RXTSF_OFFSET_CCK 0x055E
#define REG_RXTSF_OFFSET_OFDM 0x055F
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c
index 01205578a3f4..eb440a850643 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c
@@ -240,27 +240,80 @@ void rtl8723be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 u1_h2c_set_pwrmode[H2C_PWEMODE_LENGTH] = { 0 };
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- u8 rlbm, power_state = 0;
- RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
+ u8 rlbm, power_state = 0, byte5 = 0;
+ u8 awake_intvl; /* DTIM = (awake_intvl - 1) */
+ struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
+ bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
+ btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
+
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
+ mode, bt_ctrl_lps);
+
+ switch (mode) {
+ case FW_PS_MIN_MODE:
+ rlbm = 0;
+ awake_intvl = 2;
+ break;
+ case FW_PS_MAX_MODE:
+ rlbm = 1;
+ awake_intvl = 2;
+ break;
+ case FW_PS_DTIM_MODE:
+ rlbm = 2;
+ awake_intvl = ppsc->reg_max_lps_awakeintvl;
+ /* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
+ * is only used in swlps.
+ */
+ break;
+ default:
+ rlbm = 2;
+ awake_intvl = 4;
+ break;
+ }
+
+ if (rtlpriv->mac80211.p2p) {
+ awake_intvl = 2;
+ rlbm = 1;
+ }
+
+ if (mode == FW_PS_ACTIVE_MODE) {
+ byte5 = 0x40;
+ power_state = FW_PWR_STATE_ACTIVE;
+ } else {
+ if (bt_ctrl_lps) {
+ byte5 = btc_ops->btc_get_lps_val(rtlpriv);
+ power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
+
+ if ((rlbm == 2) && (byte5 & BIT(4))) {
+ /* Keep awake interval to 1 to prevent from
+ * decreasing coex performance
+ */
+ awake_intvl = 2;
+ rlbm = 2;
+ }
+ } else {
+ byte5 = 0x40;
+ power_state = FW_PWR_STATE_RF_OFF;
+ }
+ }
SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
- rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/
SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
(rtlpriv->mac80211.p2p) ?
ppsc->smart_ps : 1);
SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
- ppsc->reg_max_lps_awakeintvl);
+ awake_intvl);
SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
- if (mode == FW_PS_ACTIVE_MODE)
- power_state |= FW_PWR_STATE_ACTIVE;
- else
- power_state |= FW_PWR_STATE_RF_OFF;
SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
+ SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
"rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
u1_h2c_set_pwrmode, H2C_PWEMODE_LENGTH);
+ if (rtlpriv->cfg->ops->get_btc_status())
+ btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode,
+ H2C_PWEMODE_LENGTH);
rtl8723be_fill_h2c_cmd(hw, H2C_8723B_SETPWRMODE, H2C_PWEMODE_LENGTH,
u1_h2c_set_pwrmode);
}
@@ -661,6 +714,7 @@ void rtl8723be_c2h_content_parsing(struct ieee80211_hw *hw,
case C2H_8723B_TX_REPORT:
RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
"[C2H], C2H_8723BE_TX_REPORT!\n");
+ rtl_tx_report_handler(hw, tmp_buf, c2h_cmd_len);
break;
case C2H_8723B_BT_INFO:
RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h
index 2482b3bc2bfa..2de4edb62bca 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h
@@ -33,7 +33,7 @@
#define USE_OLD_WOWLAN_DEBUG_FW 0
-#define H2C_PWEMODE_LENGTH 5
+#define H2C_PWEMODE_LENGTH 7
/* Fw PS state for RPWM.
*BIT[2:0] = HW state
@@ -125,6 +125,8 @@ enum rtl8723b_c2h_evt {
SET_BITS_TO_LE_1BYTE((__ph2ccmd)+3, 0, 8, __val)
#define SET_H2CCMD_PWRMODE_PARM_PWR_STATE(__ph2ccmd, __val) \
SET_BITS_TO_LE_1BYTE((__ph2ccmd)+4, 0, 8, __val)
+#define SET_H2CCMD_PWRMODE_PARM_BYTE5(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 5, 0, 8, __val)
#define GET_88E_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd) \
LE_BITS_TO_1BYTE(__ph2ccmd, 0, 8)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
index a79f936bb394..0ce2900722f4 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
@@ -846,6 +846,9 @@ static bool _rtl8723be_init_mac(struct ieee80211_hw *hw)
return false;
}
+ if (rtlpriv->cfg->ops->get_btc_status())
+ rtlpriv->btcoexist.btc_ops->btc_power_on_setting(rtlpriv);
+
bytetmp = rtl_read_byte(rtlpriv, REG_MULTI_FUNC_CTRL);
rtl_write_byte(rtlpriv, REG_MULTI_FUNC_CTRL, bytetmp | BIT(3));
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h
index 03581d2a5da0..95c4f8e206c7 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h
@@ -261,7 +261,6 @@
#define REG_RD_NAV_NXT 0x0544
#define REG_NAV_PROT_LEN 0x0546
#define REG_BCN_CTRL 0x0550
-#define REG_USTIME_TSF 0x0551
#define REG_MBID_NUM 0x0552
#define REG_DUAL_TSF_RST 0x0553
#define REG_BCN_INTERVAL 0x0554
@@ -269,6 +268,7 @@
#define REG_DRVERLYINT 0x0558
#define REG_BCNDMATIM 0x0559
#define REG_ATIMWND 0x055A
+#define REG_USTIME_TSF 0x055C
#define REG_BCN_MAX_ERR 0x055D
#define REG_RXTSF_OFFSET_CCK 0x055E
#define REG_RXTSF_OFFSET_OFDM 0x055F
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c
index 3c6ce994c6aa..0e8944119652 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c
@@ -488,6 +488,9 @@ void rtl8723be_tx_fill_desc(struct ieee80211_hw *hw,
SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
}
+ /* tx report */
+ rtl_get_tx_report(ptcb_desc, pdesc, hw);
+
/* ptcb_desc->use_driver_rate = true; */
SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate);
if (ptcb_desc->hw_rate > DESC92C_RATEMCS0)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h
index 8a9fe41ac15b..0274659f48ed 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h
@@ -107,7 +107,7 @@
#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 13, 1, __val)
#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \
- SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 2, __val)
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 8, 14, 2, __val)
#define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 16, 1, __val)
#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \
@@ -115,7 +115,7 @@
#define SET_TX_DESC_RAW(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val)
#define SET_TX_DESC_SPE_RPT(__pdesc, __val) \
- SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val)
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 8, 19, 1, __val)
#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val)
#define SET_TX_DESC_BT_INT(__pdesc, __val) \
@@ -187,6 +187,18 @@
#define SET_TX_DESC_RTS_SC(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val)
+#define SET_TX_DESC_SW_DEFINE(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 0, 12, __val)
+#define SET_TX_DESC_MBSSID(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 12, 4, __val)
+#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 16, 3, __val)
+#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 19, 3, __val)
+#define SET_TX_DESC_ANTSEL_C(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 22, 3, __val)
+#define SET_TX_DESC_ANTSEL_D(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 25, 3, __val)
#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c
index 67aec20cdbf0..87818d2ccc4e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c
@@ -489,29 +489,80 @@ void rtl8821ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 u1_h2c_set_pwrmode[H2C_8821AE_PWEMODE_LENGTH] = { 0 };
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- u8 rlbm, power_state = 0;
+ u8 rlbm, power_state = 0, byte5 = 0;
+ u8 awake_intvl; /* DTIM = (awake_intvl - 1) */
+ struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
+ bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
+ btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
+
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
+ mode, bt_ctrl_lps);
+
+ switch (mode) {
+ case FW_PS_MIN_MODE:
+ rlbm = 0;
+ awake_intvl = 2;
+ break;
+ case FW_PS_MAX_MODE:
+ rlbm = 1;
+ awake_intvl = 2;
+ break;
+ case FW_PS_DTIM_MODE:
+ rlbm = 2;
+ awake_intvl = ppsc->reg_max_lps_awakeintvl;
+ /* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
+ * is only used in swlps.
+ */
+ break;
+ default:
+ rlbm = 2;
+ awake_intvl = 4;
+ break;
+ }
- RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
+ if (rtlpriv->mac80211.p2p) {
+ awake_intvl = 2;
+ rlbm = 1;
+ }
+
+ if (mode == FW_PS_ACTIVE_MODE) {
+ byte5 = 0x40;
+ power_state = FW_PWR_STATE_ACTIVE;
+ } else {
+ if (bt_ctrl_lps) {
+ byte5 = btc_ops->btc_get_lps_val(rtlpriv);
+ power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
+
+ if ((rlbm == 2) && (byte5 & BIT(4))) {
+ /* Keep awake interval to 1 to prevent from
+ * decreasing coex performance
+ */
+ awake_intvl = 2;
+ rlbm = 2;
+ }
+ } else {
+ byte5 = 0x40;
+ power_state = FW_PWR_STATE_RF_OFF;
+ }
+ }
SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
- rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/
SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
(rtlpriv->mac80211.p2p) ?
ppsc->smart_ps : 1);
SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
- ppsc->reg_max_lps_awakeintvl);
+ awake_intvl);
SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
- if (mode == FW_PS_ACTIVE_MODE)
- power_state |= FW_PWR_STATE_ACTIVE;
- else
- power_state |= FW_PWR_STATE_RF_OFF;
-
SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
+ SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
"rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
u1_h2c_set_pwrmode, H2C_8821AE_PWEMODE_LENGTH);
+ if (rtlpriv->cfg->ops->get_btc_status())
+ btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode,
+ H2C_8821AE_PWEMODE_LENGTH);
rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_SETPWRMODE,
H2C_8821AE_PWEMODE_LENGTH,
u1_h2c_set_pwrmode);
@@ -1871,6 +1922,9 @@ void rtl8821ae_c2h_content_parsing(struct ieee80211_hw *hw,
case C2H_8812_DBG:
RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "[C2H], C2H_8812_DBG!!\n");
break;
+ case C2H_8812_TX_REPORT:
+ rtl_tx_report_handler(hw, tmp_buf, c2h_cmd_len);
+ break;
case C2H_8812_RA_RPT:
rtl8821ae_c2h_ra_report_handler(hw, tmp_buf, c2h_cmd_len);
break;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h
index 98d871afd92a..32d46d7128f5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h
@@ -42,7 +42,7 @@
#define USE_OLD_WOWLAN_DEBUG_FW 0
#define H2C_8821AE_RSVDPAGE_LOC_LEN 5
-#define H2C_8821AE_PWEMODE_LENGTH 5
+#define H2C_8821AE_PWEMODE_LENGTH 7
#define H2C_8821AE_JOINBSSRPT_LENGTH 1
#define H2C_8821AE_AP_OFFLOAD_LENGTH 3
#define H2C_8821AE_WOWLAN_LENGTH 3
@@ -218,6 +218,8 @@ enum rtl8821a_h2c_cmd {
SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value)
#define SET_H2CCMD_PWRMODE_PARM_PWR_STATE(__cmd, __value) \
SET_BITS_TO_LE_1BYTE((__cmd)+4, 0, 8, __value)
+#define SET_H2CCMD_PWRMODE_PARM_BYTE5(__cmd, __value) \
+ SET_BITS_TO_LE_1BYTE((__cmd) + 5, 0, 8, __value)
#define GET_8821AE_H2CCMD_PWRMODE_PARM_MODE(__cmd) \
LE_BITS_TO_1BYTE(__cmd, 0, 8)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h
index ed69dbe178ff..db8bc8a2de61 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h
@@ -267,7 +267,6 @@
#define REG_RD_NAV_NXT 0x0544
#define REG_NAV_PROT_LEN 0x0546
#define REG_BCN_CTRL 0x0550
-#define REG_USTIME_TSF 0x0551
#define REG_MBID_NUM 0x0552
#define REG_DUAL_TSF_RST 0x0553
#define REG_BCN_INTERVAL 0x0554
@@ -275,6 +274,7 @@
#define REG_DRVERLYINT 0x0558
#define REG_BCNDMATIM 0x0559
#define REG_ATIMWND 0x055A
+#define REG_USTIME_TSF 0x055C
#define REG_BCN_MAX_ERR 0x055D
#define REG_RXTSF_OFFSET_CCK 0x055E
#define REG_RXTSF_OFFSET_OFDM 0x055F
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c
index 03665e82065f..749818929e8f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c
@@ -740,6 +740,9 @@ void rtl8821ae_tx_fill_desc(struct ieee80211_hw *hw,
SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
}
+ /* tx report */
+ rtl_get_tx_report(ptcb_desc, pdesc, hw);
+
/* ptcb_desc->use_driver_rate = true; */
SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate);
if (ptcb_desc->hw_rate > DESC_RATEMCS0)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h
index b6f3c564b8d1..9843a616dcec 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h
@@ -114,7 +114,7 @@
#define SET_TX_DESC_RAW(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val)
#define SET_TX_DESC_SPE_RPT(__pdesc, __val) \
- SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val)
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 8, 19, 1, __val)
#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val)
#define SET_TX_DESC_BT_INT(__pdesc, __val) \
@@ -185,8 +185,21 @@
#define SET_TX_DESC_RTS_SC(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val)
+#define SET_TX_DESC_SW_DEFINE(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 0, 12, __val)
+#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 16, 3, __val)
+#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 19, 3, __val)
+#define SET_TX_DESC_ANTSEL_C(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 22, 3, __val)
+#define SET_TX_DESC_ANTSEL_D(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 25, 3, __val)
+#define SET_TX_DESC_MBSSID(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(i(__pdesc) + 24, 12, 4, __val)
+
#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \
- SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val)
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 28, 0, 16, __val)
#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+28, 0, 16)
diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h
index c0d2601bc55f..49c0d2229274 100644
--- a/drivers/net/wireless/realtek/rtlwifi/wifi.h
+++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h
@@ -1886,6 +1886,13 @@ struct rtl_efuse {
u8 channel_plan;
};
+struct rtl_tx_report {
+ atomic_t sn;
+ u16 last_sent_sn;
+ unsigned long last_sent_time;
+ u16 last_recv_sn;
+};
+
struct rtl_ps_ctl {
bool pwrdomain_protect;
bool in_powersavemode;
@@ -2075,6 +2082,8 @@ struct rtl_tcb_desc {
u8 use_driver_rate:1;
u8 disable_ratefallback:1;
+ u8 use_spe_rpt:1;
+
u8 ratr_index;
u8 mac_id;
u8 hw_rate;
@@ -2534,6 +2543,7 @@ struct bt_coexist_info {
struct rtl_btc_ops {
void (*btc_init_variables) (struct rtl_priv *rtlpriv);
void (*btc_init_hal_vars) (struct rtl_priv *rtlpriv);
+ void (*btc_power_on_setting)(struct rtl_priv *rtlpriv);
void (*btc_init_hw_config) (struct rtl_priv *rtlpriv);
void (*btc_ips_notify) (struct rtl_priv *rtlpriv, u8 type);
void (*btc_lps_notify)(struct rtl_priv *rtlpriv, u8 type);
@@ -2550,6 +2560,13 @@ struct rtl_btc_ops {
bool (*btc_is_bt_disabled) (struct rtl_priv *rtlpriv);
void (*btc_special_packet_notify)(struct rtl_priv *rtlpriv,
u8 pkt_type);
+ void (*btc_record_pwr_mode)(struct rtl_priv *rtlpriv, u8 *buf, u8 len);
+ u8 (*btc_get_lps_val)(struct rtl_priv *rtlpriv);
+ u8 (*btc_get_rpwm_val)(struct rtl_priv *rtlpriv);
+ bool (*btc_is_bt_ctrl_lps)(struct rtl_priv *rtlpriv);
+ void (*btc_get_ampdu_cfg)(struct rtl_priv *rtlpriv, u8 *reject_agg,
+ u8 *ctrl_agg_size, u8 *agg_size);
+ bool (*btc_is_bt_lps_on)(struct rtl_priv *rtlpriv);
};
struct proxim {
@@ -2588,6 +2605,7 @@ struct rtl_priv {
struct rtl_security sec;
struct rtl_efuse efuse;
struct rtl_led_ctl ledctl;
+ struct rtl_tx_report tx_report;
struct rtl_ps_ctl psc;
struct rate_adaptive ra;
diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c
index 3d24e8ed74df..c2303599c12e 100644
--- a/drivers/net/wireless/rsi/rsi_91x_hal.c
+++ b/drivers/net/wireless/rsi/rsi_91x_hal.c
@@ -718,7 +718,8 @@ int rsi_hal_device_init(struct rsi_hw *adapter)
{
struct rsi_common *common = adapter->priv;
- common->coex_mode = 1;
+ common->coex_mode = RSI_DEV_COEX_MODE_WIFI_ALONE;
+ common->oper_mode = RSI_DEV_OPMODE_WIFI_ALONE;
adapter->device_model = RSI_DEV_9113;
switch (adapter->device_model) {
@@ -733,6 +734,7 @@ int rsi_hal_device_init(struct rsi_hw *adapter)
default:
return -EINVAL;
}
+ common->fsm_state = FSM_CARD_NOT_READY;
return 0;
}
diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c
index 8810862ae826..f1cde0ca81f9 100644
--- a/drivers/net/wireless/rsi/rsi_91x_main.c
+++ b/drivers/net/wireless/rsi/rsi_91x_main.c
@@ -123,9 +123,16 @@ int rsi_read_pkt(struct rsi_common *common, s32 rcv_pkt_len)
queueno = rsi_get_queueno(frame_desc, offset);
length = rsi_get_length(frame_desc, offset);
- extended_desc = rsi_get_extended_desc(frame_desc, offset);
+
+ /* Extended descriptor is valid for WLAN queues only */
+ if (queueno == RSI_WIFI_DATA_Q || queueno == RSI_WIFI_MGMT_Q)
+ extended_desc = rsi_get_extended_desc(frame_desc,
+ offset);
switch (queueno) {
+ case RSI_COEX_Q:
+ rsi_mgmt_pkt_recv(common, (frame_desc + offset));
+ break;
case RSI_WIFI_DATA_Q:
skb = rsi_prepare_skb(common,
(frame_desc + offset),
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index a0f04371d93b..d4d365b5d2d6 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -45,10 +45,10 @@ static struct bootup_params boot_params_20 = {
}
},
.switch_clk_g = {
- .switch_clk_info = cpu_to_le16(BIT(3)),
- .bbp_lmac_clk_reg_val = cpu_to_le16(0x121),
- .umac_clock_reg_config = 0x0,
- .qspi_uart_clock_reg_config = 0x0
+ .switch_clk_info = cpu_to_le16(0xb),
+ .bbp_lmac_clk_reg_val = cpu_to_le16(0x111),
+ .umac_clock_reg_config = cpu_to_le16(0x48),
+ .qspi_uart_clock_reg_config = cpu_to_le16(0x1211)
}
},
{
@@ -106,7 +106,10 @@ static struct bootup_params boot_params_20 = {
.wdt_prog_value = 0x0,
.wdt_soc_rst_delay = 0x0,
.dcdc_operation_mode = 0x0,
- .soc_reset_wait_cnt = 0x0
+ .soc_reset_wait_cnt = 0x0,
+ .waiting_time_at_fresh_sleep = 0x0,
+ .max_threshold_to_avoid_sleep = 0x0,
+ .beacon_resedue_alg_en = 0,
};
static struct bootup_params boot_params_40 = {
@@ -139,7 +142,7 @@ static struct bootup_params boot_params_40 = {
.switch_clk_info = cpu_to_le16(0x09),
.bbp_lmac_clk_reg_val = cpu_to_le16(0x1121),
.umac_clock_reg_config = cpu_to_le16(0x48),
- .qspi_uart_clock_reg_config = 0x0
+ .qspi_uart_clock_reg_config = cpu_to_le16(0x1211)
}
},
{
@@ -197,7 +200,10 @@ static struct bootup_params boot_params_40 = {
.wdt_prog_value = 0x0,
.wdt_soc_rst_delay = 0x0,
.dcdc_operation_mode = 0x0,
- .soc_reset_wait_cnt = 0x0
+ .soc_reset_wait_cnt = 0x0,
+ .waiting_time_at_fresh_sleep = 0x0,
+ .max_threshold_to_avoid_sleep = 0x0,
+ .beacon_resedue_alg_en = 0,
};
static u16 mcs[] = {13, 26, 39, 52, 78, 104, 117, 130};
@@ -218,6 +224,12 @@ static void rsi_set_default_parameters(struct rsi_common *common)
common->fsm_state = FSM_CARD_NOT_READY;
common->iface_down = true;
common->endpoint = EP_2GHZ_20MHZ;
+ common->driver_mode = 1; /* End to end mode */
+ common->lp_ps_handshake_mode = 0; /* Default no handShake mode*/
+ common->ulp_ps_handshake_mode = 2; /* Default PKT handShake mode*/
+ common->rf_power_val = 0; /* Default 1.9V */
+ common->wlan_rf_power_mode = 0;
+ common->obm_ant_sel_val = 2;
}
/**
@@ -750,6 +762,53 @@ int rsi_hal_load_key(struct rsi_common *common,
}
/*
+ * This function sends the common device configuration parameters to device.
+ * This frame includes the useful information to make device works on
+ * specific operating mode.
+ */
+static int rsi_send_common_dev_params(struct rsi_common *common)
+{
+ struct sk_buff *skb;
+ u16 frame_len;
+ struct rsi_config_vals *dev_cfgs;
+
+ frame_len = sizeof(struct rsi_config_vals);
+
+ rsi_dbg(MGMT_TX_ZONE, "Sending common device config params\n");
+ skb = dev_alloc_skb(frame_len);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to allocate skb\n", __func__);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, frame_len);
+
+ dev_cfgs = (struct rsi_config_vals *)skb->data;
+ memset(dev_cfgs, 0, (sizeof(struct rsi_config_vals)));
+
+ rsi_set_len_qno(&dev_cfgs->len_qno, (frame_len - FRAME_DESC_SZ),
+ RSI_COEX_Q);
+ dev_cfgs->pkt_type = COMMON_DEV_CONFIG;
+
+ dev_cfgs->lp_ps_handshake = common->lp_ps_handshake_mode;
+ dev_cfgs->ulp_ps_handshake = common->ulp_ps_handshake_mode;
+
+ dev_cfgs->unused_ulp_gpio = RSI_UNUSED_ULP_GPIO_BITMAP;
+ dev_cfgs->unused_soc_gpio_bitmap =
+ cpu_to_le32(RSI_UNUSED_SOC_GPIO_BITMAP);
+
+ dev_cfgs->opermode = common->oper_mode;
+ dev_cfgs->wlan_rf_pwr_mode = common->wlan_rf_power_mode;
+ dev_cfgs->driver_mode = common->driver_mode;
+ dev_cfgs->region_code = NL80211_DFS_FCC;
+ dev_cfgs->antenna_sel_val = common->obm_ant_sel_val;
+
+ skb_put(skb, frame_len);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/*
* rsi_load_bootup_params() - This function send bootup params to the firmware.
* @common: Pointer to the driver private structure.
*
@@ -1481,6 +1540,40 @@ out:
return -EINVAL;
}
+static int rsi_handle_card_ready(struct rsi_common *common, u8 *msg)
+{
+ switch (common->fsm_state) {
+ case FSM_CARD_NOT_READY:
+ rsi_dbg(INIT_ZONE, "Card ready indication from Common HAL\n");
+ rsi_set_default_parameters(common);
+ if (rsi_send_common_dev_params(common) < 0)
+ return -EINVAL;
+ common->fsm_state = FSM_COMMON_DEV_PARAMS_SENT;
+ break;
+ case FSM_COMMON_DEV_PARAMS_SENT:
+ rsi_dbg(INIT_ZONE, "Card ready indication from WLAN HAL\n");
+
+ /* Get usb buffer status register address */
+ common->priv->usb_buffer_status_reg = *(u32 *)&msg[8];
+ rsi_dbg(INFO_ZONE, "USB buffer status register = %x\n",
+ common->priv->usb_buffer_status_reg);
+
+ if (rsi_load_bootup_params(common)) {
+ common->fsm_state = FSM_CARD_NOT_READY;
+ return -EINVAL;
+ }
+ common->fsm_state = FSM_BOOT_PARAMS_SENT;
+ break;
+ default:
+ rsi_dbg(ERR_ZONE,
+ "%s: card ready indication in invalid state %d.\n",
+ __func__, common->fsm_state);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/**
* rsi_mgmt_pkt_recv() - This function processes the management packets
* recieved from the hardware.
@@ -1493,7 +1586,6 @@ int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg)
{
s32 msg_len = (le16_to_cpu(*(__le16 *)&msg[0]) & 0x0fff);
u16 msg_type = (msg[2]);
- int ret;
rsi_dbg(FSM_ZONE, "%s: Msg Len: %d, Msg Type: %4x\n",
__func__, msg_len, msg_type);
@@ -1503,17 +1595,7 @@ int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg)
} else if (msg_type == CARD_READY_IND) {
rsi_dbg(FSM_ZONE, "%s: Card ready indication received\n",
__func__);
- if (common->fsm_state == FSM_CARD_NOT_READY) {
- rsi_set_default_parameters(common);
-
- ret = rsi_load_bootup_params(common);
- if (ret)
- return ret;
- else
- common->fsm_state = FSM_BOOT_PARAMS_SENT;
- } else {
- return -EINVAL;
- }
+ return rsi_handle_card_ready(common, msg);
} else if (msg_type == TX_STATUS_IND) {
if (msg[15] == PROBEREQ_CONFIRM) {
common->mgmt_q_block = false;
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index 2ef844adacf3..e5ea99bb2dd8 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -139,6 +139,8 @@ static void rsi_handle_interrupt(struct sdio_func *function)
{
struct rsi_hw *adapter = sdio_get_drvdata(function);
+ if (adapter->priv->fsm_state == FSM_FW_NOT_LOADED)
+ return;
sdio_release_host(function);
rsi_interrupt_handler(adapter);
sdio_claim_host(function);
@@ -908,10 +910,19 @@ static int rsi_probe(struct sdio_func *pfunction,
__func__);
goto fail;
}
+ sdio_claim_host(pfunction);
+ if (sdio_claim_irq(pfunction, rsi_handle_interrupt)) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to request IRQ\n", __func__);
+ sdio_release_host(pfunction);
+ goto fail;
+ }
+ sdio_release_host(pfunction);
+ rsi_dbg(INIT_ZONE, "%s: Registered Interrupt handler\n", __func__);
if (rsi_hal_device_init(adapter)) {
rsi_dbg(ERR_ZONE, "%s: Failed in device init\n", __func__);
sdio_claim_host(pfunction);
+ sdio_release_irq(pfunction);
sdio_disable_func(pfunction);
sdio_release_host(pfunction);
goto fail;
@@ -923,16 +934,6 @@ static int rsi_probe(struct sdio_func *pfunction,
return -EIO;
}
- sdio_claim_host(pfunction);
- if (sdio_claim_irq(pfunction, rsi_handle_interrupt)) {
- rsi_dbg(ERR_ZONE, "%s: Failed to request IRQ\n", __func__);
- sdio_release_host(pfunction);
- goto fail;
- }
-
- sdio_release_host(pfunction);
- rsi_dbg(INIT_ZONE, "%s: Registered Interrupt handler\n", __func__);
-
return 0;
fail:
rsi_91x_deinit(adapter);
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index f5de6934f7ec..bcd7f454ef30 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -666,6 +666,7 @@ static const struct usb_device_id rsi_dev_table[] = {
{ USB_DEVICE(0x041B, 0x0301) },
{ USB_DEVICE(0x041B, 0x0201) },
{ USB_DEVICE(0x041B, 0x9330) },
+ { USB_DEVICE(0x1618, 0x9113) },
{ /* Blank */},
};
diff --git a/drivers/net/wireless/rsi/rsi_boot_params.h b/drivers/net/wireless/rsi/rsi_boot_params.h
index 5e2721f7909c..238ee96434ec 100644
--- a/drivers/net/wireless/rsi/rsi_boot_params.h
+++ b/drivers/net/wireless/rsi/rsi_boot_params.h
@@ -24,19 +24,19 @@
#define WIFI_AFEPLL_CONFIGS BIT(7)
#define WIFI_SWITCH_CLK_CONFIGS BIT(8)
-#define TA_PLL_M_VAL_20 8
-#define TA_PLL_N_VAL_20 1
+#define TA_PLL_M_VAL_20 9
+#define TA_PLL_N_VAL_20 0
#define TA_PLL_P_VAL_20 4
#define PLL960_M_VAL_20 0x14
#define PLL960_N_VAL_20 0
#define PLL960_P_VAL_20 5
-#define UMAC_CLK_40MHZ 40
+#define UMAC_CLK_40MHZ 80
-#define TA_PLL_M_VAL_40 46
-#define TA_PLL_N_VAL_40 3
-#define TA_PLL_P_VAL_40 3
+#define TA_PLL_M_VAL_40 9
+#define TA_PLL_N_VAL_40 0
+#define TA_PLL_P_VAL_40 4
#define PLL960_M_VAL_40 0x14
#define PLL960_N_VAL_40 0
@@ -122,5 +122,8 @@ struct bootup_params {
/* dcdc modes configs */
__le32 dcdc_operation_mode;
__le32 soc_reset_wait_cnt;
+ __le32 waiting_time_at_fresh_sleep;
+ __le32 max_threshold_to_avoid_sleep;
+ u8 beacon_resedue_alg_en;
} __packed;
#endif
diff --git a/drivers/net/wireless/rsi/rsi_hal.h b/drivers/net/wireless/rsi/rsi_hal.h
index b95200df5b0f..902dc540849c 100644
--- a/drivers/net/wireless/rsi/rsi_hal.h
+++ b/drivers/net/wireless/rsi/rsi_hal.h
@@ -63,6 +63,9 @@
#define COMMAN_HAL_WAIT_FOR_CARD_READY 1
+#define RSI_DEV_OPMODE_WIFI_ALONE 1
+#define RSI_DEV_COEX_MODE_WIFI_ALONE 1
+
struct bl_header {
__le32 flags;
__le32 image_no;
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index ea4fc223cea7..f3985250b593 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -31,13 +31,17 @@
#define FSM_ZONE BIT(7) /* For State Machine Msgs */
#define ISR_ZONE BIT(8) /* For Interrupt Msgs */
-#define FSM_CARD_NOT_READY 0
-#define FSM_BOOT_PARAMS_SENT 1
-#define FSM_EEPROM_READ_MAC_ADDR 2
-#define FSM_RESET_MAC_SENT 3
-#define FSM_RADIO_CAPS_SENT 4
-#define FSM_BB_RF_PROG_SENT 5
-#define FSM_MAC_INIT_DONE 6
+enum RSI_FSM_STATES {
+ FSM_FW_NOT_LOADED,
+ FSM_CARD_NOT_READY,
+ FSM_COMMON_DEV_PARAMS_SENT,
+ FSM_BOOT_PARAMS_SENT,
+ FSM_EEPROM_READ_MAC_ADDR,
+ FSM_RESET_MAC_SENT,
+ FSM_RADIO_CAPS_SENT,
+ FSM_BB_RF_PROG_SENT,
+ FSM_MAC_INIT_DONE
+};
extern u32 rsi_zone_enabled;
extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...);
@@ -60,6 +64,7 @@ extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...);
#define MAX_CONTINUOUS_VI_PKTS 4
/* Queue information */
+#define RSI_COEX_Q 0x0
#define RSI_WIFI_MGMT_Q 0x4
#define RSI_WIFI_DATA_Q 0x5
#define IEEE80211_MGMT_FRAME 0x00
@@ -206,8 +211,14 @@ struct rsi_common {
struct cqm_info cqm_info;
bool hw_data_qs_blocked;
+ u8 driver_mode;
u8 coex_mode;
-
+ u16 oper_mode;
+ u8 lp_ps_handshake_mode;
+ u8 ulp_ps_handshake_mode;
+ u8 rf_power_val;
+ u8 wlan_rf_power_mode;
+ u8 obm_ant_sel_val;
int tx_power;
u8 ant_in_use;
};
@@ -230,6 +241,7 @@ struct rsi_hw {
enum host_intf rsi_host_intf;
u16 block_size;
+ u32 usb_buffer_status_reg;
#ifdef CONFIG_RSI_DEBUGFS
struct rsi_debugfs *dfsentry;
u8 num_debugfs_entries;
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index dfbf7a50269b..dcb6db728cbd 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -205,6 +205,7 @@ enum cmd_frame_type {
CW_MODE_REQ,
PER_CMD_PKT,
ANT_SEL_FRAME = 0x20,
+ COMMON_DEV_CONFIG = 0x28,
RADIO_PARAMS_UPDATE = 0x29
};
@@ -282,6 +283,76 @@ struct rsi_radio_caps {
__le16 preamble_type;
} __packed;
+/* ULP GPIO flags */
+#define RSI_GPIO_MOTION_SENSOR_ULP_WAKEUP BIT(0)
+#define RSI_GPIO_SLEEP_IND_FROM_DEVICE BIT(1)
+#define RSI_GPIO_2_ULP BIT(2)
+#define RSI_GPIO_PUSH_BUTTON_ULP_WAKEUP BIT(3)
+
+/* SOC GPIO flags */
+#define RSI_GPIO_0_PSPI_CSN_0 BIT(0)
+#define RSI_GPIO_1_PSPI_CSN_1 BIT(1)
+#define RSI_GPIO_2_HOST_WAKEUP_INTR BIT(2)
+#define RSI_GPIO_3_PSPI_DATA_0 BIT(3)
+#define RSI_GPIO_4_PSPI_DATA_1 BIT(4)
+#define RSI_GPIO_5_PSPI_DATA_2 BIT(5)
+#define RSI_GPIO_6_PSPI_DATA_3 BIT(6)
+#define RSI_GPIO_7_I2C_SCL BIT(7)
+#define RSI_GPIO_8_I2C_SDA BIT(8)
+#define RSI_GPIO_9_UART1_RX BIT(9)
+#define RSI_GPIO_10_UART1_TX BIT(10)
+#define RSI_GPIO_11_UART1_RTS_I2S_CLK BIT(11)
+#define RSI_GPIO_12_UART1_CTS_I2S_WS BIT(12)
+#define RSI_GPIO_13_DBG_UART_RX_I2S_DIN BIT(13)
+#define RSI_GPIO_14_DBG_UART_RX_I2S_DOUT BIT(14)
+#define RSI_GPIO_15_LP_WAKEUP_BOOT_BYPASS BIT(15)
+#define RSI_GPIO_16_LED_0 BIT(16)
+#define RSI_GPIO_17_BTCOEX_WLAN_ACT_EXT_ANT_SEL BIT(17)
+#define RSI_GPIO_18_BTCOEX_BT_PRIO_EXT_ANT_SEL BIT(18)
+#define RSI_GPIO_19_BTCOEX_BT_ACT_EXT_ON_OFF BIT(19)
+#define RSI_GPIO_20_RF_RESET BIT(20)
+#define RSI_GPIO_21_SLEEP_IND_FROM_DEVICE BIT(21)
+
+#define RSI_UNUSED_SOC_GPIO_BITMAP (RSI_GPIO_9_UART1_RX | \
+ RSI_GPIO_10_UART1_TX | \
+ RSI_GPIO_11_UART1_RTS_I2S_CLK | \
+ RSI_GPIO_12_UART1_CTS_I2S_WS | \
+ RSI_GPIO_13_DBG_UART_RX_I2S_DIN | \
+ RSI_GPIO_14_DBG_UART_RX_I2S_DOUT | \
+ RSI_GPIO_15_LP_WAKEUP_BOOT_BYPASS | \
+ RSI_GPIO_17_BTCOEX_WLAN_ACT_EXT_ANT_SEL | \
+ RSI_GPIO_18_BTCOEX_BT_PRIO_EXT_ANT_SEL | \
+ RSI_GPIO_19_BTCOEX_BT_ACT_EXT_ON_OFF | \
+ RSI_GPIO_21_SLEEP_IND_FROM_DEVICE)
+
+#define RSI_UNUSED_ULP_GPIO_BITMAP (RSI_GPIO_MOTION_SENSOR_ULP_WAKEUP | \
+ RSI_GPIO_SLEEP_IND_FROM_DEVICE | \
+ RSI_GPIO_2_ULP | \
+ RSI_GPIO_PUSH_BUTTON_ULP_WAKEUP);
+struct rsi_config_vals {
+ __le16 len_qno;
+ u8 pkt_type;
+ u8 misc_flags;
+ __le16 reserved1[6];
+ u8 lp_ps_handshake;
+ u8 ulp_ps_handshake;
+ u8 sleep_config_params; /* 0 for no handshake,
+ * 1 for GPIO based handshake,
+ * 2 packet handshake
+ */
+ u8 unused_ulp_gpio;
+ __le32 unused_soc_gpio_bitmap;
+ u8 ext_pa_or_bt_coex_en;
+ u8 opermode;
+ u8 wlan_rf_pwr_mode;
+ u8 bt_rf_pwr_mode;
+ u8 zigbee_rf_pwr_mode;
+ u8 driver_mode;
+ u8 region_code;
+ u8 antenna_sel_val;
+ u8 reserved2[16];
+} __packed;
+
static inline u32 rsi_get_queueno(u8 *addr, u16 offset)
{
return (le16_to_cpu(*(__le16 *)&addr[offset]) & 0x7000) >> 12;
@@ -307,6 +378,11 @@ static inline u8 rsi_get_channel(u8 *addr)
return *(char *)(addr + 15);
}
+static inline void rsi_set_len_qno(__le16 *addr, u16 len, u8 qno)
+{
+ *addr = cpu_to_le16(len | ((qno & 7) << 12));
+}
+
int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg);
int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode,
u8 vap_status);
diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c
index 287023ef4a78..2fb38717346f 100644
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -237,6 +237,7 @@ static const struct of_device_id wlcore_sdio_of_match_table[] = {
{ .compatible = "ti,wl1273", .data = &wl127x_data },
{ .compatible = "ti,wl1281", .data = &wl128x_data },
{ .compatible = "ti,wl1283", .data = &wl128x_data },
+ { .compatible = "ti,wl1285", .data = &wl128x_data },
{ .compatible = "ti,wl1801", .data = &wl18xx_data },
{ .compatible = "ti,wl1805", .data = &wl18xx_data },
{ .compatible = "ti,wl1807", .data = &wl18xx_data },
diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c
index fa3547e06424..fdabb9242cca 100644
--- a/drivers/net/wireless/ti/wlcore/spi.c
+++ b/drivers/net/wireless/ti/wlcore/spi.c
@@ -366,17 +366,14 @@ static int __wl12xx_spi_raw_write(struct device *child, int addr,
static int __must_check wl12xx_spi_raw_write(struct device *child, int addr,
void *buf, size_t len, bool fixed)
{
- int ret;
-
/* The ELP wakeup write may fail the first time due to internal
* hardware latency. It is safer to send the wakeup command twice to
* avoid unexpected failures.
*/
if (addr == HW_ACCESS_ELP_CTRL_REG)
- ret = __wl12xx_spi_raw_write(child, addr, buf, len, fixed);
- ret = __wl12xx_spi_raw_write(child, addr, buf, len, fixed);
+ __wl12xx_spi_raw_write(child, addr, buf, len, fixed);
- return ret;
+ return __wl12xx_spi_raw_write(child, addr, buf, len, fixed);
}
/**
@@ -433,6 +430,7 @@ static const struct of_device_id wlcore_spi_of_match_table[] = {
{ .compatible = "ti,wl1273", .data = &wl127x_data},
{ .compatible = "ti,wl1281", .data = &wl128x_data},
{ .compatible = "ti,wl1283", .data = &wl128x_data},
+ { .compatible = "ti,wl1285", .data = &wl128x_data},
{ .compatible = "ti,wl1801", .data = &wl18xx_data},
{ .compatible = "ti,wl1805", .data = &wl18xx_data},
{ .compatible = "ti,wl1807", .data = &wl18xx_data},