aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/net/wireless/qcom,ath11k.yaml6
-rw-r--r--drivers/bus/mhi/core/init.c9
-rw-r--r--drivers/bus/mhi/core/internal.h1
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c85
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h8
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c1
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c21
-rw-r--r--drivers/net/wireless/ath/ath10k/p2p.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/qmi.c4
-rw-r--r--drivers/net/wireless/ath/ath10k/rx_desc.h2
-rw-r--r--drivers/net/wireless/ath/ath10k/sdio.c20
-rw-r--r--drivers/net/wireless/ath/ath10k/usb.c7
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.c4
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c11
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h7
-rw-r--r--drivers/net/wireless/ath/ath11k/ahb.c27
-rw-r--r--drivers/net/wireless/ath/ath11k/core.c41
-rw-r--r--drivers/net/wireless/ath/ath11k/core.h22
-rw-r--r--drivers/net/wireless/ath/ath11k/dp.c2
-rw-r--r--drivers/net/wireless/ath/ath11k/dp.h2
-rw-r--r--drivers/net/wireless/ath/ath11k/dp_rx.c18
-rw-r--r--drivers/net/wireless/ath/ath11k/dp_tx.c13
-rw-r--r--drivers/net/wireless/ath/ath11k/hal_desc.h8
-rw-r--r--drivers/net/wireless/ath/ath11k/hw.c4
-rw-r--r--drivers/net/wireless/ath/ath11k/hw.h1
-rw-r--r--drivers/net/wireless/ath/ath11k/mac.c198
-rw-r--r--drivers/net/wireless/ath/ath11k/mac.h2
-rw-r--r--drivers/net/wireless/ath/ath11k/mhi.c4
-rw-r--r--drivers/net/wireless/ath/ath11k/pci.c7
-rw-r--r--drivers/net/wireless/ath/ath11k/peer.c44
-rw-r--r--drivers/net/wireless/ath/ath11k/peer.h2
-rw-r--r--drivers/net/wireless/ath/ath11k/qmi.c78
-rw-r--r--drivers/net/wireless/ath/ath11k/qmi.h5
-rw-r--r--drivers/net/wireless/ath/ath11k/reg.c7
-rw-r--r--drivers/net/wireless/ath/ath11k/reg.h1
-rw-r--r--drivers/net/wireless/ath/ath11k/rx_desc.h2
-rw-r--r--drivers/net/wireless/ath/ath11k/testmode.c4
-rw-r--r--drivers/net/wireless/ath/ath11k/wmi.c294
-rw-r--r--drivers/net/wireless/ath/ath11k/wmi.h52
-rw-r--r--drivers/net/wireless/ath/ath6kl/testmode.c1
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/ar5008_phy.c15
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h14
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h7
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9340_initvals.h101
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9485_initvals.h7
-rw-r--r--drivers/net/wireless/ath/ath9k/dynack.c11
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c1
-rw-r--r--drivers/net/wireless/ath/dfs_pattern_detector.c14
-rw-r--r--drivers/net/wireless/ath/dfs_pri_detector.c9
-rw-r--r--drivers/net/wireless/ath/regd.c1
-rw-r--r--drivers/net/wireless/ath/wcn36xx/main.c2
-rw-r--r--drivers/net/wireless/ath/wcn36xx/smd.c4
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c3
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c1
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c7
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c26
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c11
-rw-r--r--drivers/net/wireless/cisco/airo.c126
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c2
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_hw.c17
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_ioctl.c15
-rw-r--r--drivers/net/wireless/intersil/orinoco/hermes.c1
-rw-r--r--drivers/net/wireless/intersil/orinoco/hermes.h15
-rw-r--r--drivers/net/wireless/intersil/orinoco/hw.c32
-rw-r--r--drivers/net/wireless/intersil/orinoco/orinoco_usb.c168
-rw-r--r--drivers/net/wireless/intersil/prism54/isl_ioctl.c5
-rw-r--r--drivers/net/wireless/marvell/mwifiex/main.c6
-rw-r--r--drivers/net/wireless/marvell/mwifiex/pcie.c24
-rw-r--r--drivers/net/wireless/marvell/mwifiex/pcie.h2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sdio.h2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sta_event.c1
-rw-r--r--drivers/net/wireless/marvell/mwifiex/uap_cmd.c1
-rw-r--r--drivers/net/wireless/marvell/mwifiex/wmm.c1
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/dma.c12
-rw-r--r--drivers/net/wireless/microchip/wilc1000/cfg80211.c7
-rw-r--r--drivers/net/wireless/microchip/wilc1000/hif.c17
-rw-r--r--drivers/net/wireless/microchip/wilc1000/hif.h1
-rw-r--r--drivers/net/wireless/microchip/wilc1000/netdev.c38
-rw-r--r--drivers/net/wireless/microchip/wilc1000/netdev.h11
-rw-r--r--drivers/net/wireless/microchip/wilc1000/wlan.c335
-rw-r--r--drivers/net/wireless/microchip/wilc1000/wlan.h30
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c6
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2800lib.c62
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00.h10
-rw-r--r--drivers/net/wireless/ray_cs.c6
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c48
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c28
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c6
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c6
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c7
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c6
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c6
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c96
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/usb.c1
-rw-r--r--drivers/net/wireless/realtek/rtw88/coex.c1538
-rw-r--r--drivers/net/wireless/realtek/rtw88/coex.h47
-rw-r--r--drivers/net/wireless/realtek/rtw88/debug.c27
-rw-r--r--drivers/net/wireless/realtek/rtw88/debug.h1
-rw-r--r--drivers/net/wireless/realtek/rtw88/fw.c6
-rw-r--r--drivers/net/wireless/realtek/rtw88/fw.h11
-rw-r--r--drivers/net/wireless/realtek/rtw88/mac80211.c9
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.c59
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.h41
-rw-r--r--drivers/net/wireless/realtek/rtw88/phy.c6
-rw-r--r--drivers/net/wireless/realtek/rtw88/ps.c135
-rw-r--r--drivers/net/wireless/realtek/rtw88/ps.h3
-rw-r--r--drivers/net/wireless/realtek/rtw88/reg.h17
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8723d.c96
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8723d.h3
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821c.c16
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821c.h2
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822b.c55
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822c.c119
-rw-r--r--drivers/net/wireless/realtek/rtw88/wow.c8
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_hal.c3
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_sdio.c6
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_sdio_ops.c173
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_usb.c36
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_usb_ops.c2
-rw-r--r--drivers/net/wireless/rsi/rsi_sdio.h8
-rw-r--r--drivers/net/wireless/st/cw1200/bh.c10
-rw-r--r--drivers/net/wireless/st/cw1200/main.c2
-rw-r--r--drivers/net/wireless/st/cw1200/wsm.c8
-rw-r--r--drivers/net/wireless/ti/wl1251/cmd.c2
-rw-r--r--drivers/net/wireless/ti/wl1251/debugfs.c2
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c4
-rw-r--r--drivers/net/wireless/ti/wlcore/spi.c3
-rw-r--r--drivers/net/wireless/ti/wlcore/sysfs.c2
-rw-r--r--drivers/net/wireless/wl3501_cs.c8
-rw-r--r--drivers/net/wireless/zydas/zd1211rw/zd_usb.c15
-rw-r--r--include/linux/mhi.h2
-rw-r--r--net/qrtr/mhi.c6
150 files changed, 3496 insertions, 1488 deletions
diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath11k.yaml b/Documentation/devicetree/bindings/net/wireless/qcom,ath11k.yaml
index 4b365c9d9378..6af999191559 100644
--- a/Documentation/devicetree/bindings/net/wireless/qcom,ath11k.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath11k.yaml
@@ -144,6 +144,12 @@ properties:
* reg
* reg-names
+ qcom,ath11k-calibration-variant:
+ $ref: /schemas/types.yaml#/definitions/string
+ description:
+ string to uniquely identify variant of the calibration data in the
+ board-2.bin for designs with colliding bus and device specific ids
+
required:
- compatible
- reg
diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/core/init.c
index 0ffdebde8265..381fdea2eb9f 100644
--- a/drivers/bus/mhi/core/init.c
+++ b/drivers/bus/mhi/core/init.c
@@ -758,7 +758,6 @@ static int parse_ch_cfg(struct mhi_controller *mhi_cntrl,
mhi_chan->offload_ch = ch_cfg->offload_channel;
mhi_chan->db_cfg.reset_req = ch_cfg->doorbell_mode_switch;
mhi_chan->pre_alloc = ch_cfg->auto_queue;
- mhi_chan->auto_start = ch_cfg->auto_start;
/*
* If MHI host allocates buffers, then the channel direction
@@ -1160,11 +1159,6 @@ static int mhi_driver_probe(struct device *dev)
goto exit_probe;
ul_chan->xfer_cb = mhi_drv->ul_xfer_cb;
- if (ul_chan->auto_start) {
- ret = mhi_prepare_channel(mhi_cntrl, ul_chan);
- if (ret)
- goto exit_probe;
- }
}
ret = -EINVAL;
@@ -1198,9 +1192,6 @@ static int mhi_driver_probe(struct device *dev)
if (ret)
goto exit_probe;
- if (dl_chan && dl_chan->auto_start)
- mhi_prepare_channel(mhi_cntrl, dl_chan);
-
mhi_device_put(mhi_dev);
return ret;
diff --git a/drivers/bus/mhi/core/internal.h b/drivers/bus/mhi/core/internal.h
index 7989269ddd96..33c23203c531 100644
--- a/drivers/bus/mhi/core/internal.h
+++ b/drivers/bus/mhi/core/internal.h
@@ -563,7 +563,6 @@ struct mhi_chan {
bool configured;
bool offload_ch;
bool pre_alloc;
- bool auto_start;
bool wake_capable;
};
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index d73ad60b571c..796107b14d9f 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -651,6 +651,7 @@ static const char *const ath10k_core_fw_feature_str[] = {
[ATH10K_FW_FEATURE_NON_BMI] = "non-bmi",
[ATH10K_FW_FEATURE_SINGLE_CHAN_INFO_PER_CHANNEL] = "single-chan-info-per-channel",
[ATH10K_FW_FEATURE_PEER_FIXED_RATE] = "peer-fixed-rate",
+ [ATH10K_FW_FEATURE_IRAM_RECOVERY] = "iram-recovery",
};
static unsigned int ath10k_core_get_fw_feature_str(char *buf,
@@ -2604,6 +2605,78 @@ static int ath10k_core_compat_services(struct ath10k *ar)
return 0;
}
+#define TGT_IRAM_READ_PER_ITR (8 * 1024)
+
+static int ath10k_core_copy_target_iram(struct ath10k *ar)
+{
+ const struct ath10k_hw_mem_layout *hw_mem;
+ const struct ath10k_mem_region *tmp, *mem_region = NULL;
+ dma_addr_t paddr;
+ void *vaddr = NULL;
+ u8 num_read_itr;
+ int i, ret;
+ u32 len, remaining_len;
+
+ hw_mem = ath10k_coredump_get_mem_layout(ar);
+ if (!hw_mem)
+ return -ENOMEM;
+
+ for (i = 0; i < hw_mem->region_table.size; i++) {
+ tmp = &hw_mem->region_table.regions[i];
+ if (tmp->type == ATH10K_MEM_REGION_TYPE_REG) {
+ mem_region = tmp;
+ break;
+ }
+ }
+
+ if (!mem_region)
+ return -ENOMEM;
+
+ for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
+ if (ar->wmi.mem_chunks[i].req_id ==
+ WMI_IRAM_RECOVERY_HOST_MEM_REQ_ID) {
+ vaddr = ar->wmi.mem_chunks[i].vaddr;
+ len = ar->wmi.mem_chunks[i].len;
+ break;
+ }
+ }
+
+ if (!vaddr || !len) {
+ ath10k_warn(ar, "No allocated memory for IRAM back up");
+ return -ENOMEM;
+ }
+
+ len = (len < mem_region->len) ? len : mem_region->len;
+ paddr = mem_region->start;
+ num_read_itr = len / TGT_IRAM_READ_PER_ITR;
+ remaining_len = len % TGT_IRAM_READ_PER_ITR;
+ for (i = 0; i < num_read_itr; i++) {
+ ret = ath10k_hif_diag_read(ar, paddr, vaddr,
+ TGT_IRAM_READ_PER_ITR);
+ if (ret) {
+ ath10k_warn(ar, "failed to copy firmware IRAM contents: %d",
+ ret);
+ return ret;
+ }
+
+ paddr += TGT_IRAM_READ_PER_ITR;
+ vaddr += TGT_IRAM_READ_PER_ITR;
+ }
+
+ if (remaining_len) {
+ ret = ath10k_hif_diag_read(ar, paddr, vaddr, remaining_len);
+ if (ret) {
+ ath10k_warn(ar, "failed to copy firmware IRAM contents: %d",
+ ret);
+ return ret;
+ }
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "target IRAM back up completed\n");
+
+ return 0;
+}
+
int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
const struct ath10k_fw_components *fw)
{
@@ -2636,7 +2709,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
if (status)
goto err;
- /* Some of of qca988x solutions are having global reset issue
+ /* Some of qca988x solutions are having global reset issue
* during target initialization. Bypassing PLL setting before
* downloading firmware and letting the SoC run on REF_CLK is
* fixing the problem. Corresponding firmware change is also
@@ -2765,6 +2838,16 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
ath10k_dbg(ar, ATH10K_DBG_BOOT, "firmware %s booted\n",
ar->hw->wiphy->fw_version);
+ if (test_bit(ATH10K_FW_FEATURE_IRAM_RECOVERY,
+ ar->running_fw->fw_file.fw_features)) {
+ status = ath10k_core_copy_target_iram(ar);
+ if (status) {
+ ath10k_warn(ar, "failed to copy target iram contents: %d",
+ status);
+ goto err_hif_stop;
+ }
+ }
+
if (test_bit(WMI_SERVICE_EXT_RES_CFG_SUPPORT, ar->wmi.svc_map) &&
mode == ATH10K_FIRMWARE_MODE_NORMAL) {
val = 0;
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index b50ab9e229dc..f3853bd26275 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -84,6 +84,11 @@
#define ATH10K_MAX_RETRY_COUNT 30
+#define ATH10K_ITER_NORMAL_FLAGS (IEEE80211_IFACE_ITER_NORMAL | \
+ IEEE80211_IFACE_SKIP_SDATA_NOT_IN_DRIVER)
+#define ATH10K_ITER_RESUME_FLAGS (IEEE80211_IFACE_ITER_RESUME_ALL |\
+ IEEE80211_IFACE_SKIP_SDATA_NOT_IN_DRIVER)
+
struct ath10k;
static inline const char *ath10k_bus_str(enum ath10k_bus bus)
@@ -829,6 +834,9 @@ enum ath10k_fw_features {
/* Firmware allows setting peer fixed rate */
ATH10K_FW_FEATURE_PEER_FIXED_RATE = 21,
+ /* Firmware support IRAM recovery */
+ ATH10K_FW_FEATURE_IRAM_RECOVERY = 22,
+
/* keep last */
ATH10K_FW_FEATURE_COUNT,
};
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index e8250a665433..b72cd81fdc79 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1764,7 +1764,7 @@ static ssize_t ath10k_write_simulate_radar(struct file *file,
struct ath10k *ar = file->private_data;
struct ath10k_vif *arvif;
- /* Just check for for the first vif alone, as all the vifs will be
+ /* Just check for the first vif alone, as all the vifs will be
* sharing the same channel and if the channel is disabled, all the
* vifs will share the same 'is_started' state.
*/
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 5c1af2021883..9c4e6cf2137a 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -3878,7 +3878,6 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
return ath10k_htt_rx_proc_rx_frag_ind(htt,
&resp->rx_frag_ind,
skb);
- break;
}
case HTT_T2H_MSG_TYPE_TEST:
break;
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 2e3eb5bbe49c..dc32c7852a24 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2066,7 +2066,7 @@ static void ath10k_mac_handle_beacon_iter(void *data, u8 *mac,
void ath10k_mac_handle_beacon(struct ath10k *ar, struct sk_buff *skb)
{
ieee80211_iterate_active_interfaces_atomic(ar->hw,
- IEEE80211_IFACE_ITER_NORMAL,
+ ATH10K_ITER_NORMAL_FLAGS,
ath10k_mac_handle_beacon_iter,
skb);
}
@@ -2099,7 +2099,7 @@ static void ath10k_mac_handle_beacon_miss_iter(void *data, u8 *mac,
void ath10k_mac_handle_beacon_miss(struct ath10k *ar, u32 vdev_id)
{
ieee80211_iterate_active_interfaces_atomic(ar->hw,
- IEEE80211_IFACE_ITER_NORMAL,
+ ATH10K_ITER_NORMAL_FLAGS,
ath10k_mac_handle_beacon_miss_iter,
&vdev_id);
}
@@ -3433,7 +3433,7 @@ void ath10k_mac_tx_unlock(struct ath10k *ar, int reason)
return;
ieee80211_iterate_active_interfaces_atomic(ar->hw,
- IEEE80211_IFACE_ITER_RESUME_ALL,
+ ATH10K_ITER_RESUME_FLAGS,
ath10k_mac_tx_unlock_iter,
ar);
@@ -3522,7 +3522,7 @@ void ath10k_mac_handle_tx_pause_vdev(struct ath10k *ar, u32 vdev_id,
spin_lock_bh(&ar->htt.tx_lock);
ieee80211_iterate_active_interfaces_atomic(ar->hw,
- IEEE80211_IFACE_ITER_RESUME_ALL,
+ ATH10K_ITER_RESUME_FLAGS,
ath10k_mac_handle_tx_pause_iter,
&arg);
spin_unlock_bh(&ar->htt.tx_lock);
@@ -5457,7 +5457,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
/* Some firmware revisions don't wait for beacon tx completion before
* sending another SWBA event. This could lead to hardware using old
* (freed) beacon data in some cases, e.g. tx credit starvation
- * combined with missed TBTT. This is very very rare.
+ * combined with missed TBTT. This is very rare.
*
* On non-IOMMU-enabled hosts this could be a possible security issue
* because hw could beacon some random data on the air. On
@@ -8696,7 +8696,7 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw,
if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH) {
ieee80211_iterate_active_interfaces_atomic(
hw,
- IEEE80211_IFACE_ITER_NORMAL,
+ ATH10K_ITER_NORMAL_FLAGS,
ath10k_mac_change_chanctx_cnt_iter,
&arg);
if (arg.n_vifs == 0)
@@ -8709,7 +8709,7 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw,
ieee80211_iterate_active_interfaces_atomic(
hw,
- IEEE80211_IFACE_ITER_NORMAL,
+ ATH10K_ITER_NORMAL_FLAGS,
ath10k_mac_change_chanctx_fill_iter,
&arg);
ath10k_mac_update_vif_chan(ar, arg.vifs, arg.n_vifs);
@@ -9169,10 +9169,11 @@ static int ath10k_mac_op_set_tid_config(struct ieee80211_hw *hw,
goto exit;
}
+ ret = 0;
+
if (sta)
goto exit;
- ret = 0;
arvif->tids_rst = 0;
data.curr_vif = vif;
data.ar = ar;
@@ -9593,14 +9594,12 @@ static void ath10k_get_arvif_iter(void *data, u8 *mac,
struct ath10k_vif *ath10k_get_arvif(struct ath10k *ar, u32 vdev_id)
{
struct ath10k_vif_iter arvif_iter;
- u32 flags;
memset(&arvif_iter, 0, sizeof(struct ath10k_vif_iter));
arvif_iter.vdev_id = vdev_id;
- flags = IEEE80211_IFACE_ITER_RESUME_ALL;
ieee80211_iterate_active_interfaces_atomic(ar->hw,
- flags,
+ ATH10K_ITER_RESUME_FLAGS,
ath10k_get_arvif_iter,
&arvif_iter);
if (!arvif_iter.arvif) {
diff --git a/drivers/net/wireless/ath/ath10k/p2p.c b/drivers/net/wireless/ath/ath10k/p2p.c
index 29c737b2f432..517b30f56b72 100644
--- a/drivers/net/wireless/ath/ath10k/p2p.c
+++ b/drivers/net/wireless/ath/ath10k/p2p.c
@@ -139,7 +139,7 @@ void ath10k_p2p_noa_update_by_vdev_id(struct ath10k *ar, u32 vdev_id,
};
ieee80211_iterate_active_interfaces_atomic(ar->hw,
- IEEE80211_IFACE_ITER_NORMAL,
+ ATH10K_ITER_NORMAL_FLAGS,
ath10k_p2p_noa_update_vdev_iter,
&arg);
}
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 36426efdb2ea..8ab262931dce 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -3236,7 +3236,7 @@ static int ath10k_pci_init_irq(struct ath10k *ar)
if (ret == 0)
return 0;
- /* fall-through */
+ /* MHI failed, try legacy irq next */
}
/* Try legacy irq
diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c
index ae6b1f402adf..07e478f9a808 100644
--- a/drivers/net/wireless/ath/ath10k/qmi.c
+++ b/drivers/net/wireless/ath/ath10k/qmi.c
@@ -917,7 +917,7 @@ static void ath10k_qmi_msa_ready_ind(struct qmi_handle *qmi_hdl,
ath10k_qmi_driver_event_post(qmi, ATH10K_QMI_EVENT_MSA_READY_IND, NULL);
}
-static struct qmi_msg_handler qmi_msg_handler[] = {
+static const struct qmi_msg_handler qmi_msg_handler[] = {
{
.type = QMI_INDICATION,
.msg_id = QMI_WLFW_FW_READY_IND_V01,
@@ -981,7 +981,7 @@ static void ath10k_qmi_del_server(struct qmi_handle *qmi_hdl,
NULL);
}
-static struct qmi_ops ath10k_qmi_ops = {
+static const struct qmi_ops ath10k_qmi_ops = {
.new_server = ath10k_qmi_new_server,
.del_server = ath10k_qmi_del_server,
};
diff --git a/drivers/net/wireless/ath/ath10k/rx_desc.h b/drivers/net/wireless/ath/ath10k/rx_desc.h
index dec1582005b9..f2b6bf8f0d60 100644
--- a/drivers/net/wireless/ath/ath10k/rx_desc.h
+++ b/drivers/net/wireless/ath/ath10k/rx_desc.h
@@ -68,7 +68,7 @@ struct rx_attention {
* first_msdu is set.
*
* peer_idx_invalid
- * Indicates no matching entries within the the max search
+ * Indicates no matching entries within the max search
* count. Only set when first_msdu is set.
*
* peer_idx_timeout
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
index 81ddaafb6721..aa1f86028f01 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -1248,7 +1248,7 @@ static int ath10k_sdio_bmi_exchange_msg(struct ath10k *ar,
* Wait for first 4 bytes to be in FIFO
* If CONSERVATIVE_BMI_READ is enabled, also wait for
* a BMI command credit, which indicates that the ENTIRE
- * response is available in the the FIFO
+ * response is available in the FIFO
*
* CASE 3: length > 128
* Wait for the first 4 bytes to be in FIFO
@@ -1962,9 +1962,15 @@ static void ath10k_sdio_hif_stop(struct ath10k *ar)
{
struct ath10k_sdio_bus_request *req, *tmp_req;
struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct sk_buff *skb;
ath10k_sdio_irq_disable(ar);
+ cancel_work_sync(&ar_sdio->async_work_rx);
+
+ while ((skb = skb_dequeue(&ar_sdio->rx_head)))
+ dev_kfree_skb_any(skb);
+
cancel_work_sync(&ar_sdio->wr_async_work);
spin_lock_bh(&ar_sdio->wr_async_lock);
@@ -2307,8 +2313,8 @@ static int ath10k_sdio_dump_memory_section(struct ath10k *ar,
}
count = 0;
-
- for (i = 0; cur_section; i++) {
+ i = 0;
+ for (; cur_section; cur_section = next_section) {
section_size = cur_section->end - cur_section->start;
if (section_size <= 0) {
@@ -2318,7 +2324,7 @@ static int ath10k_sdio_dump_memory_section(struct ath10k *ar,
break;
}
- if ((i + 1) == mem_region->section_table.size) {
+ if (++i == mem_region->section_table.size) {
/* last section */
next_section = NULL;
skip_size = 0;
@@ -2361,12 +2367,6 @@ static int ath10k_sdio_dump_memory_section(struct ath10k *ar,
}
count += skip_size;
-
- if (!next_section)
- /* this was the last section */
- break;
-
- cur_section = next_section;
}
return count;
diff --git a/drivers/net/wireless/ath/ath10k/usb.c b/drivers/net/wireless/ath/ath10k/usb.c
index 05a620ff6fe2..19b9c27e30e2 100644
--- a/drivers/net/wireless/ath/ath10k/usb.c
+++ b/drivers/net/wireless/ath/ath10k/usb.c
@@ -997,6 +997,8 @@ static int ath10k_usb_probe(struct usb_interface *interface,
ar_usb = ath10k_usb_priv(ar);
ret = ath10k_usb_create(ar, interface);
+ if (ret)
+ goto err;
ar_usb->ar = ar;
ar->dev_id = product_id;
@@ -1009,7 +1011,7 @@ static int ath10k_usb_probe(struct usb_interface *interface,
ret = ath10k_core_register(ar, &bus_params);
if (ret) {
ath10k_warn(ar, "failed to register driver core: %d\n", ret);
- goto err;
+ goto err_usb_destroy;
}
/* TODO: remove this once USB support is fully implemented */
@@ -1017,6 +1019,9 @@ static int ath10k_usb_probe(struct usb_interface *interface,
return 0;
+err_usb_destroy:
+ ath10k_usb_destroy(ar);
+
err:
ath10k_core_destroy(ar);
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index 932266d1111b..7b5834157fe5 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -1401,13 +1401,15 @@ static int ath10k_wmi_tlv_svc_avail_parse(struct ath10k *ar, u16 tag, u16 len,
switch (tag) {
case WMI_TLV_TAG_STRUCT_SERVICE_AVAILABLE_EVENT:
+ arg->service_map_ext_valid = true;
arg->service_map_ext_len = *(__le32 *)ptr;
arg->service_map_ext = ptr + sizeof(__le32);
return 0;
default:
break;
}
- return -EPROTO;
+
+ return 0;
}
static int ath10k_wmi_tlv_op_pull_svc_avail(struct ath10k *ar,
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 1fa7107a5051..c491acebdb46 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1894,7 +1894,7 @@ static void ath10k_wmi_tx_beacons_iter(void *data, u8 *mac,
static void ath10k_wmi_tx_beacons_nowait(struct ath10k *ar)
{
ieee80211_iterate_active_interfaces_atomic(ar->hw,
- IEEE80211_IFACE_ITER_NORMAL,
+ ATH10K_ITER_NORMAL_FLAGS,
ath10k_wmi_tx_beacons_iter,
NULL);
}
@@ -5751,8 +5751,13 @@ void ath10k_wmi_event_service_available(struct ath10k *ar, struct sk_buff *skb)
ret);
}
- ath10k_wmi_map_svc_ext(ar, arg.service_map_ext, ar->wmi.svc_map,
- __le32_to_cpu(arg.service_map_ext_len));
+ /*
+ * Initialization of "arg.service_map_ext_valid" to ZERO is necessary
+ * for the below logic to work.
+ */
+ if (arg.service_map_ext_valid)
+ ath10k_wmi_map_svc_ext(ar, arg.service_map_ext, ar->wmi.svc_map,
+ __le32_to_cpu(arg.service_map_ext_len));
}
static int ath10k_wmi_event_temperature(struct ath10k *ar, struct sk_buff *skb)
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 4898e19b0af6..d870f7067cb7 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -3060,6 +3060,8 @@ struct host_memory_chunk {
__le32 size;
} __packed;
+#define WMI_IRAM_RECOVERY_HOST_MEM_REQ_ID 8
+
struct wmi_host_mem_chunks {
__le32 count;
/* some fw revisions require at least 1 chunk regardless of count */
@@ -3832,7 +3834,7 @@ enum wmi_pdev_param {
WMI_PDEV_PARAM_BEACON_TX_MODE,
/*
* Resource manager off chan mode .
- * 0: turn off off chan mode. 1: turn on offchan mode
+ * 0: turn off offchan mode. 1: turn on offchan mode
*/
WMI_PDEV_PARAM_RESMGR_OFFCHAN_MODE,
/*
@@ -3936,7 +3938,7 @@ enum wmi_10x_pdev_param {
WMI_10X_PDEV_PARAM_BEACON_TX_MODE,
/*
* Resource manager off chan mode .
- * 0: turn off off chan mode. 1: turn on offchan mode
+ * 0: turn off offchan mode. 1: turn on offchan mode
*/
WMI_10X_PDEV_PARAM_RESMGR_OFFCHAN_MODE,
/*
@@ -6917,6 +6919,7 @@ struct wmi_svc_rdy_ev_arg {
};
struct wmi_svc_avail_ev_arg {
+ bool service_map_ext_valid;
__le32 service_map_ext_len;
const __le32 *service_map_ext;
};
diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c
index 430723c64adc..c7843f461dd2 100644
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -340,6 +340,31 @@ static void ath11k_ahb_power_down(struct ath11k_base *ab)
rproc_shutdown(ab_ahb->tgt_rproc);
}
+static int ath11k_ahb_fwreset_from_cold_boot(struct ath11k_base *ab)
+{
+ int timeout;
+
+ if (ath11k_cold_boot_cal == 0 || ab->qmi.cal_done ||
+ ab->hw_params.cold_boot_calib == 0)
+ return 0;
+
+ ath11k_dbg(ab, ATH11K_DBG_AHB, "wait for cold boot done\n");
+ timeout = wait_event_timeout(ab->qmi.cold_boot_waitq,
+ (ab->qmi.cal_done == 1),
+ ATH11K_COLD_BOOT_FW_RESET_DELAY);
+ if (timeout <= 0) {
+ ath11k_cold_boot_cal = 0;
+ ath11k_warn(ab, "Coldboot Calibration failed timed out\n");
+ }
+
+ /* reset the firmware */
+ ath11k_ahb_power_down(ab);
+ ath11k_ahb_power_up(ab);
+
+ ath11k_dbg(ab, ATH11K_DBG_AHB, "exited from cold boot mode\n");
+ return 0;
+}
+
static void ath11k_ahb_init_qmi_ce_config(struct ath11k_base *ab)
{
struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg;
@@ -700,6 +725,8 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
goto err_ce_free;
}
+ ath11k_ahb_fwreset_from_cold_boot(ab);
+
return 0;
err_ce_free:
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index ebd6886a8c18..da20ed752ca5 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -7,6 +7,7 @@
#include <linux/slab.h>
#include <linux/remoteproc.h>
#include <linux/firmware.h>
+#include <linux/of.h>
#include "core.h"
#include "dp_tx.h"
#include "dp_rx.h"
@@ -65,6 +66,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_monitor = true,
.supports_shadow_regs = false,
.idle_ps = false,
+ .cold_boot_calib = true,
},
{
.hw_rev = ATH11K_HW_IPQ6018_HW10,
@@ -102,6 +104,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_monitor = true,
.supports_shadow_regs = false,
.idle_ps = false,
+ .cold_boot_calib = true,
},
{
.name = "qca6390 hw2.0",
@@ -138,17 +141,48 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_monitor = false,
.supports_shadow_regs = true,
.idle_ps = true,
+ .cold_boot_calib = false,
},
};
+int ath11k_core_check_dt(struct ath11k_base *ab)
+{
+ size_t max_len = sizeof(ab->qmi.target.bdf_ext);
+ const char *variant = NULL;
+ struct device_node *node;
+
+ node = ab->dev->of_node;
+ if (!node)
+ return -ENOENT;
+
+ of_property_read_string(node, "qcom,ath11k-calibration-variant",
+ &variant);
+ if (!variant)
+ return -ENODATA;
+
+ if (strscpy(ab->qmi.target.bdf_ext, variant, max_len) < 0)
+ ath11k_dbg(ab, ATH11K_DBG_BOOT,
+ "bdf variant string is longer than the buffer can accommodate (variant: %s)\n",
+ variant);
+
+ return 0;
+}
+
static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name,
size_t name_len)
{
+ /* strlen(',variant=') + strlen(ab->qmi.target.bdf_ext) */
+ char variant[9 + ATH11K_QMI_BDF_EXT_STR_LENGTH] = { 0 };
+
+ if (ab->qmi.target.bdf_ext[0] != '\0')
+ scnprintf(variant, sizeof(variant), ",variant=%s",
+ ab->qmi.target.bdf_ext);
+
scnprintf(name, name_len,
- "bus=%s,qmi-chip-id=%d,qmi-board-id=%d",
+ "bus=%s,qmi-chip-id=%d,qmi-board-id=%d%s",
ath11k_bus_str(ab->hif.bus),
ab->qmi.target.chip_id,
- ab->qmi.target.board_id);
+ ab->qmi.target.board_id, variant);
ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot using board name '%s'\n", name);
@@ -774,8 +808,10 @@ static void ath11k_core_restart(struct work_struct *work)
complete(&ar->scan.started);
complete(&ar->scan.completed);
complete(&ar->peer_assoc_done);
+ complete(&ar->peer_delete_done);
complete(&ar->install_key_done);
complete(&ar->vdev_setup_done);
+ complete(&ar->vdev_delete_done);
complete(&ar->bss_survey_done);
complete(&ar->thermal.wmi_sync);
@@ -923,6 +959,7 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,
INIT_LIST_HEAD(&ab->peers);
init_waitqueue_head(&ab->peer_mapping_wq);
init_waitqueue_head(&ab->wmi_ab.tx_credits_wq);
+ init_waitqueue_head(&ab->qmi.cold_boot_waitq);
INIT_WORK(&ab->restart_work, ath11k_core_restart);
timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0);
ab->dev = dev;
diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index 18b97420f0d8..317b15e333d3 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -75,12 +75,14 @@ static inline enum wme_ac ath11k_tid_to_ac(u32 tid)
enum ath11k_skb_flags {
ATH11K_SKB_HW_80211_ENCAP = BIT(0),
+ ATH11K_SKB_CIPHER_SET = BIT(1),
};
struct ath11k_skb_cb {
dma_addr_t paddr;
u8 eid;
u8 flags;
+ u32 cipher;
struct ath11k *ar;
struct ieee80211_vif *vif;
} __packed;
@@ -111,8 +113,13 @@ enum ath11k_firmware_mode {
/* factory tests etc */
ATH11K_FIRMWARE_MODE_FTM,
+
+ /* Cold boot calibration */
+ ATH11K_FIRMWARE_MODE_COLD_BOOT = 7,
};
+extern bool ath11k_cold_boot_cal;
+
#define ATH11K_IRQ_NUM_MAX 52
#define ATH11K_EXT_IRQ_NUM_MAX 16
@@ -425,11 +432,7 @@ struct ath11k_per_peer_tx_stats {
};
#define ATH11K_FLUSH_TIMEOUT (5 * HZ)
-
-struct ath11k_vdev_stop_status {
- bool stop_in_progress;
- u32 vdev_id;
-};
+#define ATH11K_VDEV_DELETE_TIMEOUT_HZ (5 * HZ)
struct ath11k {
struct ath11k_base *ab;
@@ -500,13 +503,14 @@ struct ath11k {
u8 lmac_id;
struct completion peer_assoc_done;
+ struct completion peer_delete_done;
int install_key_status;
struct completion install_key_done;
int last_wmi_vdev_start_status;
- struct ath11k_vdev_stop_status vdev_stop_status;
struct completion vdev_setup_done;
+ struct completion vdev_delete_done;
int num_peers;
int max_num_peers;
@@ -723,9 +727,6 @@ struct ath11k_base {
} stats;
u32 pktlog_defs_checksum;
- /* Round robbin based TCL ring selector */
- atomic_t tcl_ring_selector;
-
struct ath11k_dbring_cap *db_caps;
u32 num_db_cap;
@@ -883,6 +884,7 @@ void ath11k_core_free(struct ath11k_base *ath11k);
int ath11k_core_fetch_bdf(struct ath11k_base *ath11k,
struct ath11k_board_data *bd);
void ath11k_core_free_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd);
+int ath11k_core_check_dt(struct ath11k_base *ath11k);
void ath11k_core_halt(struct ath11k *ar);
@@ -907,6 +909,8 @@ static inline const char *ath11k_scan_state_str(enum ath11k_scan_state state)
static inline struct ath11k_skb_cb *ATH11K_SKB_CB(struct sk_buff *skb)
{
+ BUILD_BUG_ON(sizeof(struct ath11k_skb_cb) >
+ IEEE80211_TX_INFO_DRIVER_DATA_SIZE);
return (struct ath11k_skb_cb *)&IEEE80211_SKB_CB(skb)->driver_data;
}
diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c
index 59dd185a0cfc..f977056ae5e8 100644
--- a/drivers/net/wireless/ath/ath11k/dp.c
+++ b/drivers/net/wireless/ath/ath11k/dp.c
@@ -381,7 +381,7 @@ static int ath11k_dp_srng_common_setup(struct ath11k_base *ab)
HAL_WBM2SW_RELEASE, i, 0,
DP_TX_COMP_RING_SIZE);
if (ret) {
- ath11k_warn(ab, "failed to set up tcl_comp ring ring (%d) :%d\n",
+ ath11k_warn(ab, "failed to set up tcl_comp ring (%d) :%d\n",
i, ret);
goto err;
}
diff --git a/drivers/net/wireless/ath/ath11k/dp.h b/drivers/net/wireless/ath/ath11k/dp.h
index ee8db812589b..d4fd02375fad 100644
--- a/drivers/net/wireless/ath/ath11k/dp.h
+++ b/drivers/net/wireless/ath/ath11k/dp.h
@@ -423,7 +423,7 @@ enum htt_srng_ring_id {
* Used only by Consumer ring to generate ring_sw_int_p.
* Ring entries low threshold water mark, that is used
* in combination with the interrupt timer as well as
- * the the clearing of the level interrupt.
+ * the clearing of the level interrupt.
* b'16:18 - prefetch_timer_cfg:
* Used only by Consumer ring to set timer mode to
* support Application prefetch handling.
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index 01625327eef7..5de619d5c4e2 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -377,7 +377,7 @@ static int ath11k_dp_rxdma_buf_ring_free(struct ath11k *ar,
spin_lock_bh(&rx_ring->idr_lock);
idr_for_each_entry(&rx_ring->bufs_idr, skb, buf_id) {
idr_remove(&rx_ring->bufs_idr, buf_id);
- /* TODO: Understand where internal driver does this dma_unmap of
+ /* TODO: Understand where internal driver does this dma_unmap
* of rxdma_buffer.
*/
dma_unmap_single(ar->ab->dev, ATH11K_SKB_RXCB(skb)->paddr,
@@ -399,7 +399,7 @@ static int ath11k_dp_rxdma_buf_ring_free(struct ath11k *ar,
spin_lock_bh(&rx_ring->idr_lock);
idr_for_each_entry(&rx_ring->bufs_idr, skb, buf_id) {
idr_remove(&rx_ring->bufs_idr, buf_id);
- /* XXX: Understand where internal driver does this dma_unmap of
+ /* XXX: Understand where internal driver does this dma_unmap
* of rxdma_buffer.
*/
dma_unmap_single(ar->ab->dev, ATH11K_SKB_RXCB(skb)->paddr,
@@ -960,7 +960,7 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id,
rx_tid->ba_win_sz = ba_win_sz;
- /* TODO: Optimize the memory allocation for qos tid based on the
+ /* TODO: Optimize the memory allocation for qos tid based on
* the actual BA window size in REO tid update path.
*/
if (tid == HAL_DESC_REO_NON_QOS_TID)
@@ -2715,7 +2715,7 @@ static struct sk_buff *ath11k_dp_rx_alloc_mon_status_buf(struct ath11k_base *ab,
paddr = dma_map_single(ab->dev, skb->data,
skb->len + skb_tailroom(skb),
- DMA_BIDIRECTIONAL);
+ DMA_FROM_DEVICE);
if (unlikely(dma_mapping_error(ab->dev, paddr)))
goto fail_free_skb;
@@ -2731,7 +2731,7 @@ static struct sk_buff *ath11k_dp_rx_alloc_mon_status_buf(struct ath11k_base *ab,
fail_dma_unmap:
dma_unmap_single(ab->dev, paddr, skb->len + skb_tailroom(skb),
- DMA_BIDIRECTIONAL);
+ DMA_FROM_DEVICE);
fail_free_skb:
dev_kfree_skb_any(skb);
fail_alloc_skb:
@@ -2795,7 +2795,7 @@ fail_desc_get:
idr_remove(&rx_ring->bufs_idr, buf_id);
spin_unlock_bh(&rx_ring->idr_lock);
dma_unmap_single(ab->dev, paddr, skb->len + skb_tailroom(skb),
- DMA_BIDIRECTIONAL);
+ DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
ath11k_hal_srng_access_end(ab, srng);
spin_unlock_bh(&srng->lock);
@@ -2856,13 +2856,9 @@ static int ath11k_dp_rx_reap_mon_status_ring(struct ath11k_base *ab, int mac_id,
rxcb = ATH11K_SKB_RXCB(skb);
- dma_sync_single_for_cpu(ab->dev, rxcb->paddr,
- skb->len + skb_tailroom(skb),
- DMA_FROM_DEVICE);
-
dma_unmap_single(ab->dev, rxcb->paddr,
skb->len + skb_tailroom(skb),
- DMA_BIDIRECTIONAL);
+ DMA_FROM_DEVICE);
tlv = (struct hal_tlv_hdr *)skb->data;
if (FIELD_GET(HAL_TLV_HDR_TAG, tlv->tl) !=
diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c
index 3d962eee4d61..6a3fcea6c233 100644
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
@@ -84,7 +84,6 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
struct ath11k_dp *dp = &ab->dp;
struct hal_tx_info ti = {0};
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_key_conf *key = info->control.hw_key;
struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB(skb);
struct hal_srng *tcl_ring;
struct ieee80211_hdr *hdr = (void *)skb->data;
@@ -105,14 +104,14 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
pool_id = skb_get_queue_mapping(skb) & (ATH11K_HW_MAX_QUEUES - 1);
- /* Let the default ring selection be based on a round robin
- * fashion where one of the 3 tcl rings are selected based on
- * the tcl_ring_selector counter. In case that ring
+ /* Let the default ring selection be based on current processor
+ * number, where one of the 3 tcl rings are selected based on
+ * the smp_processor_id(). In case that ring
* is full/busy, we resort to other available rings.
* If all rings are full, we drop the packet.
* //TODO Add throttling logic when all rings are full
*/
- ring_selector = atomic_inc_return(&ab->tcl_ring_selector);
+ ring_selector = smp_processor_id();
tcl_ring_sel:
tcl_ring_retry = false;
@@ -149,9 +148,9 @@ tcl_ring_sel:
ti.meta_data_flags = arvif->tcl_metadata;
if (ti.encap_type == HAL_TCL_ENCAP_TYPE_RAW) {
- if (key) {
+ if (skb_cb->flags & ATH11K_SKB_CIPHER_SET) {
ti.encrypt_type =
- ath11k_dp_tx_get_encrypt_type(key->cipher);
+ ath11k_dp_tx_get_encrypt_type(skb_cb->cipher);
if (ieee80211_has_protected(hdr->frame_control))
skb_put(skb, IEEE80211_CCMP_MIC_LEN);
diff --git a/drivers/net/wireless/ath/ath11k/hal_desc.h b/drivers/net/wireless/ath/ath11k/hal_desc.h
index 8a592814efa0..1b713cb13b90 100644
--- a/drivers/net/wireless/ath/ath11k/hal_desc.h
+++ b/drivers/net/wireless/ath/ath11k/hal_desc.h
@@ -716,7 +716,7 @@ struct hal_reo_dest_ring {
*
* rx_msdu_info
* General information related to the MSDU that is passed
- * on from RXDMA all the way to to the REO destination ring.
+ * on from RXDMA all the way to the REO destination ring.
*
* queue_addr_lo
* Address (lower 32 bits) of the REO queue descriptor.
@@ -1425,7 +1425,7 @@ struct hal_ce_srng_dest_desc {
#define HAL_CE_DST_STATUS_DESC_FLAGS_GATHER BIT(11)
#define HAL_CE_DST_STATUS_DESC_FLAGS_LEN GENMASK(31, 16)
-#define HAL_CE_DST_STATUS_DESC_META_INFO_DATA GENMASK(7, 0)
+#define HAL_CE_DST_STATUS_DESC_META_INFO_DATA GENMASK(15, 0)
#define HAL_CE_DST_STATUS_DESC_META_INFO_RING_ID GENMASK(27, 20)
#define HAL_CE_DST_STATUS_DESC_META_INFO_LOOP_CNT HAL_SRNG_DESC_LOOP_CNT
@@ -1946,7 +1946,7 @@ enum hal_rx_reo_queue_pn_size {
#define HAL_RX_REO_QUEUE_INFO3_TIMEOUT_COUNT GENMASK(9, 4)
#define HAL_RX_REO_QUEUE_INFO3_FWD_DUE_TO_BAR_CNT GENMASK(15, 10)
-#define HAL_RX_REO_QUEUE_INFO3_DUPLICATE_COUNT GENMASK(31, 10)
+#define HAL_RX_REO_QUEUE_INFO3_DUPLICATE_COUNT GENMASK(31, 16)
#define HAL_RX_REO_QUEUE_INFO4_FRAME_IN_ORD_COUNT GENMASK(23, 0)
#define HAL_RX_REO_QUEUE_INFO4_BAR_RECVD_COUNT GENMASK(31, 24)
@@ -2432,7 +2432,7 @@ struct hal_reo_flush_timeout_list_status {
#define HAL_REO_DESC_THRESH_STATUS_INFO1_LINK_DESC_COUNTER0 GENMASK(23, 0)
#define HAL_REO_DESC_THRESH_STATUS_INFO2_LINK_DESC_COUNTER1 GENMASK(23, 0)
#define HAL_REO_DESC_THRESH_STATUS_INFO3_LINK_DESC_COUNTER2 GENMASK(23, 0)
-#define HAL_REO_DESC_THRESH_STATUS_INFO4_LINK_DESC_COUNTER_SUM GENMASK(23, 0)
+#define HAL_REO_DESC_THRESH_STATUS_INFO4_LINK_DESC_COUNTER_SUM GENMASK(25, 0)
struct hal_reo_desc_thresh_reached_status {
struct hal_reo_status_hdr hdr;
diff --git a/drivers/net/wireless/ath/ath11k/hw.c b/drivers/net/wireless/ath/ath11k/hw.c
index 11a411b76fe4..66331da35012 100644
--- a/drivers/net/wireless/ath/ath11k/hw.c
+++ b/drivers/net/wireless/ath/ath11k/hw.c
@@ -127,7 +127,7 @@ static void ath11k_init_wmi_config_ipq8074(struct ath11k_base *ab,
config->beacon_tx_offload_max_vdev = ab->num_radios * TARGET_MAX_BCN_OFFLD;
config->rx_batchmode = TARGET_RX_BATCHMODE;
config->peer_map_unmap_v2_support = 1;
- config->twt_ap_pdev_count = 2;
+ config->twt_ap_pdev_count = ab->num_radios;
config->twt_ap_sta_count = 1000;
}
@@ -157,7 +157,7 @@ static int ath11k_hw_mac_id_to_srng_id_qca6390(struct ath11k_hw_params *hw,
const struct ath11k_hw_ops ipq8074_ops = {
.get_hw_mac_from_pdev_id = ath11k_hw_ipq8074_mac_from_pdev_id,
- .wmi_init_config = ath11k_init_wmi_config_qca6390,
+ .wmi_init_config = ath11k_init_wmi_config_ipq8074,
.mac_id_to_pdev_id = ath11k_hw_mac_id_to_pdev_id_ipq8074,
.mac_id_to_srng_id = ath11k_hw_mac_id_to_srng_id_ipq8074,
};
diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h
index 1dda4257e6d7..17c4560b1c73 100644
--- a/drivers/net/wireless/ath/ath11k/hw.h
+++ b/drivers/net/wireless/ath/ath11k/hw.h
@@ -161,6 +161,7 @@ struct ath11k_hw_params {
bool supports_monitor;
bool supports_shadow_regs;
bool idle_ps;
+ bool cold_boot_calib;
};
struct ath11k_hw_ops {
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 7f8dd47d2333..ebed24ec7368 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -537,31 +537,6 @@ struct ath11k *ath11k_mac_get_ar_by_pdev_id(struct ath11k_base *ab, u32 pdev_id)
return NULL;
}
-struct ath11k *ath11k_mac_get_ar_vdev_stop_status(struct ath11k_base *ab,
- u32 vdev_id)
-{
- int i;
- struct ath11k_pdev *pdev;
- struct ath11k *ar;
-
- for (i = 0; i < ab->num_radios; i++) {
- pdev = rcu_dereference(ab->pdevs_active[i]);
- if (pdev && pdev->ar) {
- ar = pdev->ar;
-
- spin_lock_bh(&ar->data_lock);
- if (ar->vdev_stop_status.stop_in_progress &&
- ar->vdev_stop_status.vdev_id == vdev_id) {
- ar->vdev_stop_status.stop_in_progress = false;
- spin_unlock_bh(&ar->data_lock);
- return ar;
- }
- spin_unlock_bh(&ar->data_lock);
- }
- }
- return NULL;
-}
-
static void ath11k_pdev_caps_update(struct ath11k *ar)
{
struct ath11k_base *ab = ar->ab;
@@ -1850,6 +1825,52 @@ static void ath11k_recalculate_mgmt_rate(struct ath11k *ar,
ath11k_warn(ar->ab, "failed to set beacon tx rate %d\n", ret);
}
+static int ath11k_mac_fils_discovery(struct ath11k_vif *arvif,
+ struct ieee80211_bss_conf *info)
+{
+ struct ath11k *ar = arvif->ar;
+ struct sk_buff *tmpl;
+ int ret;
+ u32 interval;
+ bool unsol_bcast_probe_resp_enabled = false;
+
+ if (info->fils_discovery.max_interval) {
+ interval = info->fils_discovery.max_interval;
+
+ tmpl = ieee80211_get_fils_discovery_tmpl(ar->hw, arvif->vif);
+ if (tmpl)
+ ret = ath11k_wmi_fils_discovery_tmpl(ar, arvif->vdev_id,
+ tmpl);
+ } else if (info->unsol_bcast_probe_resp_interval) {
+ unsol_bcast_probe_resp_enabled = 1;
+ interval = info->unsol_bcast_probe_resp_interval;
+
+ tmpl = ieee80211_get_unsol_bcast_probe_resp_tmpl(ar->hw,
+ arvif->vif);
+ if (tmpl)
+ ret = ath11k_wmi_probe_resp_tmpl(ar, arvif->vdev_id,
+ tmpl);
+ } else { /* Disable */
+ return ath11k_wmi_fils_discovery(ar, arvif->vdev_id, 0, false);
+ }
+
+ if (!tmpl) {
+ ath11k_warn(ar->ab,
+ "mac vdev %i failed to retrieve %s template\n",
+ arvif->vdev_id, (unsol_bcast_probe_resp_enabled ?
+ "unsolicited broadcast probe response" :
+ "FILS discovery"));
+ return -EPERM;
+ }
+ kfree_skb(tmpl);
+
+ if (!ret)
+ ret = ath11k_wmi_fils_discovery(ar, arvif->vdev_id, interval,
+ unsol_bcast_probe_resp_enabled);
+
+ return ret;
+}
+
static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info,
@@ -2111,6 +2132,10 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
}
}
+ if (changed & BSS_CHANGED_FILS_DISCOVERY ||
+ changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP)
+ ath11k_mac_fils_discovery(arvif, info);
+
mutex_unlock(&ar->conf_mutex);
}
@@ -3729,11 +3754,6 @@ static int ath11k_mac_copy_he_cap(struct ath11k *ar,
he_cap_elem->mac_cap_info[1] &=
IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK;
- he_cap_elem->phy_cap_info[4] &=
- ~IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_MASK;
- he_cap_elem->phy_cap_info[4] &=
- ~IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_MASK;
- he_cap_elem->phy_cap_info[4] |= (ar->num_tx_chains - 1) << 2;
he_cap_elem->phy_cap_info[5] &=
~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;
@@ -3977,21 +3997,20 @@ static void ath11k_mgmt_over_wmi_tx_purge(struct ath11k *ar)
static void ath11k_mgmt_over_wmi_tx_work(struct work_struct *work)
{
struct ath11k *ar = container_of(work, struct ath11k, wmi_mgmt_tx_work);
- struct ieee80211_tx_info *info;
+ struct ath11k_skb_cb *skb_cb;
struct ath11k_vif *arvif;
struct sk_buff *skb;
int ret;
while ((skb = skb_dequeue(&ar->wmi_mgmt_tx_queue)) != NULL) {
- info = IEEE80211_SKB_CB(skb);
- if (!info->control.vif) {
- ath11k_warn(ar->ab, "no vif found for mgmt frame, flags 0x%x\n",
- info->control.flags);
+ skb_cb = ATH11K_SKB_CB(skb);
+ if (!skb_cb->vif) {
+ ath11k_warn(ar->ab, "no vif found for mgmt frame\n");
ieee80211_free_txskb(ar->hw, skb);
continue;
}
- arvif = ath11k_vif_to_arvif(info->control.vif);
+ arvif = ath11k_vif_to_arvif(skb_cb->vif);
if (ar->allocated_vdev_map & (1LL << arvif->vdev_id) &&
arvif->is_started) {
ret = ath11k_mac_mgmt_tx_wmi(ar, arvif, skb);
@@ -4004,8 +4023,8 @@ static void ath11k_mgmt_over_wmi_tx_work(struct work_struct *work)
}
} else {
ath11k_warn(ar->ab,
- "dropping mgmt frame for vdev %d, flags 0x%x is_started %d\n",
- arvif->vdev_id, info->control.flags,
+ "dropping mgmt frame for vdev %d, is_started %d\n",
+ arvif->vdev_id,
arvif->is_started);
ieee80211_free_txskb(ar->hw, skb);
}
@@ -4053,10 +4072,20 @@ static void ath11k_mac_op_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif = info->control.vif;
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_key_conf *key = info->control.hw_key;
+ u32 info_flags = info->flags;
bool is_prb_rsp;
int ret;
- if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
+ memset(skb_cb, 0, sizeof(*skb_cb));
+ skb_cb->vif = vif;
+
+ if (key) {
+ skb_cb->cipher = key->cipher;
+ skb_cb->flags |= ATH11K_SKB_CIPHER_SET;
+ }
+
+ if (info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
skb_cb->flags |= ATH11K_SKB_HW_80211_ENCAP;
} else if (ieee80211_is_mgmt(hdr->frame_control)) {
is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control);
@@ -4094,7 +4123,8 @@ static int ath11k_mac_config_mon_status_default(struct ath11k *ar, bool enable)
if (enable) {
tlv_filter = ath11k_mac_mon_status_filter_default;
- tlv_filter.rx_filter = ath11k_debugfs_rx_filter(ar);
+ if (ath11k_debugfs_rx_filter(ar))
+ tlv_filter.rx_filter = ath11k_debugfs_rx_filter(ar);
}
for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
@@ -4578,8 +4608,22 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
err_peer_del:
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
+ reinit_completion(&ar->peer_delete_done);
+
+ ret = ath11k_wmi_send_peer_delete_cmd(ar, vif->addr,
+ arvif->vdev_id);
+ if (ret) {
+ ath11k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n",
+ arvif->vdev_id, vif->addr);
+ return ret;
+ }
+
+ ret = ath11k_wait_for_peer_delete_done(ar, arvif->vdev_id,
+ vif->addr);
+ if (ret)
+ return ret;
+
ar->num_peers--;
- ath11k_wmi_send_peer_delete_cmd(ar, vif->addr, arvif->vdev_id);
}
err_vdev_del:
@@ -4614,6 +4658,7 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,
struct ath11k *ar = hw->priv;
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
struct ath11k_base *ab = ar->ab;
+ unsigned long time_left;
int ret;
int i;
@@ -4622,10 +4667,6 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,
ath11k_dbg(ab, ATH11K_DBG_MAC, "mac remove interface (vdev %d)\n",
arvif->vdev_id);
- spin_lock_bh(&ar->data_lock);
- list_del(&arvif->list);
- spin_unlock_bh(&ar->data_lock);
-
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
ret = ath11k_peer_delete(ar, arvif->vdev_id, vif->addr);
if (ret)
@@ -4633,16 +4674,33 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,
arvif->vdev_id, ret);
}
+ reinit_completion(&ar->vdev_delete_done);
+
ret = ath11k_wmi_vdev_delete(ar, arvif->vdev_id);
- if (ret)
+ if (ret) {
ath11k_warn(ab, "failed to delete WMI vdev %d: %d\n",
arvif->vdev_id, ret);
+ goto err_vdev_del;
+ }
+
+ time_left = wait_for_completion_timeout(&ar->vdev_delete_done,
+ ATH11K_VDEV_DELETE_TIMEOUT_HZ);
+ if (time_left == 0) {
+ ath11k_warn(ab, "Timeout in receiving vdev delete response\n");
+ goto err_vdev_del;
+ }
+ ab->free_vdev_map |= 1LL << (arvif->vdev_id);
+ ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id);
ar->num_created_vdevs--;
+
ath11k_dbg(ab, ATH11K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n",
vif->addr, arvif->vdev_id);
- ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id);
- ab->free_vdev_map |= 1LL << (arvif->vdev_id);
+
+err_vdev_del:
+ spin_lock_bh(&ar->data_lock);
+ list_del(&arvif->list);
+ spin_unlock_bh(&ar->data_lock);
ath11k_peer_cleanup(ar, arvif->vdev_id);
@@ -4946,13 +5004,6 @@ static int ath11k_mac_vdev_stop(struct ath11k_vif *arvif)
reinit_completion(&ar->vdev_setup_done);
- spin_lock_bh(&ar->data_lock);
-
- ar->vdev_stop_status.stop_in_progress = true;
- ar->vdev_stop_status.vdev_id = arvif->vdev_id;
-
- spin_unlock_bh(&ar->data_lock);
-
ret = ath11k_wmi_vdev_stop(ar, arvif->vdev_id);
if (ret) {
ath11k_warn(ar->ab, "failed to stop WMI vdev %i: %d\n",
@@ -4981,10 +5032,6 @@ static int ath11k_mac_vdev_stop(struct ath11k_vif *arvif)
return 0;
err:
- spin_lock_bh(&ar->data_lock);
- ar->vdev_stop_status.stop_in_progress = false;
- spin_unlock_bh(&ar->data_lock);
-
return ret;
}
@@ -5225,20 +5272,26 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
arvif->vdev_type != WMI_VDEV_TYPE_AP &&
arvif->vdev_type != WMI_VDEV_TYPE_MONITOR) {
memcpy(&arvif->chanctx, ctx, sizeof(*ctx));
- mutex_unlock(&ar->conf_mutex);
- return 0;
+ ret = 0;
+ goto out;
}
if (WARN_ON(arvif->is_started)) {
- mutex_unlock(&ar->conf_mutex);
- return -EBUSY;
+ ret = -EBUSY;
+ goto out;
}
if (ab->hw_params.vdev_start_delay) {
param.vdev_id = arvif->vdev_id;
param.peer_type = WMI_PEER_TYPE_DEFAULT;
param.peer_addr = ar->mac_addr;
+
ret = ath11k_peer_create(ar, arvif, NULL, &param);
+ if (ret) {
+ ath11k_warn(ab, "failed to create peer after vdev start delay: %d",
+ ret);
+ goto out;
+ }
}
ret = ath11k_mac_vdev_start(arvif, &ctx->def);
@@ -5246,23 +5299,21 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
ath11k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n",
arvif->vdev_id, vif->addr,
ctx->def.chan->center_freq, ret);
- goto err;
+ goto out;
}
if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
ret = ath11k_monitor_vdev_up(ar, arvif->vdev_id);
if (ret)
- goto err;
+ goto out;
}
arvif->is_started = true;
/* TODO: Setup ps and cts/rts protection */
- mutex_unlock(&ar->conf_mutex);
+ ret = 0;
- return 0;
-
-err:
+out:
mutex_unlock(&ar->conf_mutex);
return ret;
@@ -6258,6 +6309,13 @@ static int __ath11k_mac_register(struct ath11k *ar)
ar->hw->wiphy->num_iftype_ext_capab =
ARRAY_SIZE(ath11k_iftypes_ext_capa);
+ if (ar->supports_6ghz) {
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_FILS_DISCOVERY);
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);
+ }
+
ath11k_reg_init(ar);
if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) {
@@ -6397,7 +6455,9 @@ int ath11k_mac_allocate(struct ath11k_base *ab)
INIT_LIST_HEAD(&ar->ppdu_stats_info);
mutex_init(&ar->conf_mutex);
init_completion(&ar->vdev_setup_done);
+ init_completion(&ar->vdev_delete_done);
init_completion(&ar->peer_assoc_done);
+ init_completion(&ar->peer_delete_done);
init_completion(&ar->install_key_done);
init_completion(&ar->bss_survey_done);
init_completion(&ar->scan.started);
diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h
index 0607479774a9..597104a9078d 100644
--- a/drivers/net/wireless/ath/ath11k/mac.h
+++ b/drivers/net/wireless/ath/ath11k/mac.h
@@ -137,8 +137,6 @@ struct ath11k_vif *ath11k_mac_get_arvif_by_vdev_id(struct ath11k_base *ab,
u32 vdev_id);
struct ath11k *ath11k_mac_get_ar_by_vdev_id(struct ath11k_base *ab, u32 vdev_id);
struct ath11k *ath11k_mac_get_ar_by_pdev_id(struct ath11k_base *ab, u32 pdev_id);
-struct ath11k *ath11k_mac_get_ar_vdev_stop_status(struct ath11k_base *ab,
- u32 vdev_id);
void ath11k_mac_drain_tx(struct ath11k *ar);
void ath11k_mac_peer_cleanup_all(struct ath11k *ar);
diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c
index aded9a719d51..47a1ce1bee4f 100644
--- a/drivers/net/wireless/ath/ath11k/mhi.c
+++ b/drivers/net/wireless/ath/ath11k/mhi.c
@@ -24,7 +24,6 @@ static struct mhi_channel_config ath11k_mhi_channels[] = {
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
- .auto_start = false,
},
{
.num = 1,
@@ -39,7 +38,6 @@ static struct mhi_channel_config ath11k_mhi_channels[] = {
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
- .auto_start = false,
},
{
.num = 20,
@@ -54,7 +52,6 @@ static struct mhi_channel_config ath11k_mhi_channels[] = {
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
- .auto_start = true,
},
{
.num = 21,
@@ -69,7 +66,6 @@ static struct mhi_channel_config ath11k_mhi_channels[] = {
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = true,
- .auto_start = true,
},
};
diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index d7eb6b7160bb..b75f47dc36de 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -380,9 +380,9 @@ static void ath11k_pci_sync_ce_irqs(struct ath11k_base *ab)
}
}
-static void ath11k_pci_ce_tasklet(unsigned long data)
+static void ath11k_pci_ce_tasklet(struct tasklet_struct *t)
{
- struct ath11k_ce_pipe *ce_pipe = (struct ath11k_ce_pipe *)data;
+ struct ath11k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq);
ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);
@@ -581,8 +581,7 @@ static int ath11k_pci_config_irq(struct ath11k_base *ab)
irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
- tasklet_init(&ce_pipe->intr_tq, ath11k_pci_ce_tasklet,
- (unsigned long)ce_pipe);
+ tasklet_setup(&ce_pipe->intr_tq, ath11k_pci_ce_tasklet);
ret = request_irq(irq, ath11k_pci_ce_interrupt_handler,
IRQF_SHARED, irq_name[irq_idx],
diff --git a/drivers/net/wireless/ath/ath11k/peer.c b/drivers/net/wireless/ath/ath11k/peer.c
index 61ad9300eafb..1866d82678fa 100644
--- a/drivers/net/wireless/ath/ath11k/peer.c
+++ b/drivers/net/wireless/ath/ath11k/peer.c
@@ -177,12 +177,36 @@ static int ath11k_wait_for_peer_deleted(struct ath11k *ar, int vdev_id, const u8
return ath11k_wait_for_peer_common(ar->ab, vdev_id, addr, false);
}
+int ath11k_wait_for_peer_delete_done(struct ath11k *ar, u32 vdev_id,
+ const u8 *addr)
+{
+ int ret;
+ unsigned long time_left;
+
+ ret = ath11k_wait_for_peer_deleted(ar, vdev_id, addr);
+ if (ret) {
+ ath11k_warn(ar->ab, "failed wait for peer deleted");
+ return ret;
+ }
+
+ time_left = wait_for_completion_timeout(&ar->peer_delete_done,
+ 3 * HZ);
+ if (time_left == 0) {
+ ath11k_warn(ar->ab, "Timeout in receiving peer delete response\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr)
{
int ret;
lockdep_assert_held(&ar->conf_mutex);
+ reinit_completion(&ar->peer_delete_done);
+
ret = ath11k_wmi_send_peer_delete_cmd(ar, addr, vdev_id);
if (ret) {
ath11k_warn(ar->ab,
@@ -191,7 +215,7 @@ int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr)
return ret;
}
- ret = ath11k_wait_for_peer_deleted(ar, vdev_id, addr);
+ ret = ath11k_wait_for_peer_delete_done(ar, vdev_id, addr);
if (ret)
return ret;
@@ -247,8 +271,22 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
spin_unlock_bh(&ar->ab->base_lock);
ath11k_warn(ar->ab, "failed to find peer %pM on vdev %i after creation\n",
param->peer_addr, param->vdev_id);
- ath11k_wmi_send_peer_delete_cmd(ar, param->peer_addr,
- param->vdev_id);
+
+ reinit_completion(&ar->peer_delete_done);
+
+ ret = ath11k_wmi_send_peer_delete_cmd(ar, param->peer_addr,
+ param->vdev_id);
+ if (ret) {
+ ath11k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n",
+ param->vdev_id, param->peer_addr);
+ return ret;
+ }
+
+ ret = ath11k_wait_for_peer_delete_done(ar, param->vdev_id,
+ param->peer_addr);
+ if (ret)
+ return ret;
+
return -ENOENT;
}
diff --git a/drivers/net/wireless/ath/ath11k/peer.h b/drivers/net/wireless/ath/ath11k/peer.h
index 5d125ce8984e..bba2e00b6944 100644
--- a/drivers/net/wireless/ath/ath11k/peer.h
+++ b/drivers/net/wireless/ath/ath11k/peer.h
@@ -41,5 +41,7 @@ void ath11k_peer_cleanup(struct ath11k *ar, u32 vdev_id);
int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr);
int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
struct ieee80211_sta *sta, struct peer_create_params *param);
+int ath11k_wait_for_peer_delete_done(struct ath11k *ar, u32 vdev_id,
+ const u8 *addr);
#endif /* _PEER_H_ */
diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c
index c2b165158225..d128c335bf5b 100644
--- a/drivers/net/wireless/ath/ath11k/qmi.c
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
@@ -14,6 +14,12 @@
#define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02
#define HOST_CSTATE_BIT 0x04
+bool ath11k_cold_boot_cal = 1;
+EXPORT_SYMBOL(ath11k_cold_boot_cal);
+module_param_named(cold_boot_cal, ath11k_cold_boot_cal, bool, 0644);
+MODULE_PARM_DESC(cold_boot_cal,
+ "Decrease the channel switch time but increase the driver load time (Default: true)");
+
static struct qmi_elem_info qmi_wlanfw_host_cap_req_msg_v01_ei[] = {
{
.data_type = QMI_OPT_FLAG,
@@ -1585,15 +1591,17 @@ static int ath11k_qmi_fw_ind_register_send(struct ath11k_base *ab)
struct qmi_wlanfw_ind_register_resp_msg_v01 *resp;
struct qmi_handle *handle = &ab->qmi.handle;
struct qmi_txn txn;
- int ret = 0;
+ int ret;
req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return -ENOMEM;
resp = kzalloc(sizeof(*resp), GFP_KERNEL);
- if (!resp)
+ if (!resp) {
+ ret = -ENOMEM;
goto resp_out;
+ }
req->client_id_valid = 1;
req->client_id = QMI_WLANFW_CLIENT_ID;
@@ -1769,9 +1777,16 @@ static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab)
ath11k_warn(ab, "qmi mem size is low to load caldata\n");
return -EINVAL;
}
- /* TODO ath11k does not support cold boot calibration */
- ab->qmi.target_mem[idx].paddr = 0;
- ab->qmi.target_mem[idx].vaddr = NULL;
+
+ if (ath11k_cold_boot_cal && ab->hw_params.cold_boot_calib) {
+ ab->qmi.target_mem[idx].paddr =
+ ATH11K_QMI_CALDB_ADDRESS;
+ ab->qmi.target_mem[idx].vaddr =
+ (void *)ATH11K_QMI_CALDB_ADDRESS;
+ } else {
+ ab->qmi.target_mem[idx].paddr = 0;
+ ab->qmi.target_mem[idx].vaddr = NULL;
+ }
ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
idx++;
@@ -1793,6 +1808,7 @@ static int ath11k_qmi_request_target_cap(struct ath11k_base *ab)
struct qmi_wlanfw_cap_resp_msg_v01 resp;
struct qmi_txn txn = {};
int ret = 0;
+ int r;
memset(&req, 0, sizeof(req));
memset(&resp, 0, sizeof(resp));
@@ -1858,6 +1874,10 @@ static int ath11k_qmi_request_target_cap(struct ath11k_base *ab)
ab->qmi.target.fw_build_timestamp,
ab->qmi.target.fw_build_id);
+ r = ath11k_core_check_dt(ab);
+ if (r)
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "DT bdf variant name not set.\n");
+
out:
return ret;
}
@@ -2352,6 +2372,32 @@ int ath11k_qmi_firmware_start(struct ath11k_base *ab,
return 0;
}
+static int ath11k_qmi_process_coldboot_calibration(struct ath11k_base *ab)
+{
+ int timeout;
+ int ret;
+
+ ret = ath11k_qmi_wlanfw_mode_send(ab, ATH11K_FIRMWARE_MODE_COLD_BOOT);
+ if (ret < 0) {
+ ath11k_warn(ab, "qmi failed to send wlan fw mode:%d\n", ret);
+ return ret;
+ }
+
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "Coldboot calibration wait started\n");
+
+ timeout = wait_event_timeout(ab->qmi.cold_boot_waitq,
+ (ab->qmi.cal_done == 1),
+ ATH11K_COLD_BOOT_FW_RESET_DELAY);
+ if (timeout <= 0) {
+ ath11k_warn(ab, "Coldboot Calibration failed - wait ended\n");
+ return 0;
+ }
+
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "Coldboot calibration done\n");
+
+ return 0;
+}
+
static int
ath11k_qmi_driver_event_post(struct ath11k_qmi *qmi,
enum ath11k_qmi_event_type type,
@@ -2501,11 +2547,18 @@ static void ath11k_qmi_msg_fw_ready_cb(struct qmi_handle *qmi_hdl,
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_FW_READY, NULL);
}
-static void ath11k_qmi_msg_cold_boot_cal_done_cb(struct qmi_handle *qmi,
+static void ath11k_qmi_msg_cold_boot_cal_done_cb(struct qmi_handle *qmi_hdl,
struct sockaddr_qrtr *sq,
struct qmi_txn *txn,
const void *decoded)
{
+ struct ath11k_qmi *qmi = container_of(qmi_hdl,
+ struct ath11k_qmi, handle);
+ struct ath11k_base *ab = qmi->ab;
+
+ ab->qmi.cal_done = 1;
+ wake_up(&ab->qmi.cold_boot_waitq);
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi cold boot calibration done\n");
}
static const struct qmi_msg_handler ath11k_qmi_msg_handlers[] = {
@@ -2618,9 +2671,16 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work)
break;
}
- ath11k_core_qmi_firmware_ready(ab);
- ab->qmi.cal_done = 1;
- set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags);
+ if (ath11k_cold_boot_cal && ab->qmi.cal_done == 0 &&
+ ab->hw_params.cold_boot_calib) {
+ ath11k_qmi_process_coldboot_calibration(ab);
+ } else {
+ clear_bit(ATH11K_FLAG_CRASH_FLUSH,
+ &ab->dev_flags);
+ clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
+ ath11k_core_qmi_firmware_ready(ab);
+ set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags);
+ }
break;
case ATH11K_QMI_EVENT_COLD_BOOT_CAL_DONE:
diff --git a/drivers/net/wireless/ath/ath11k/qmi.h b/drivers/net/wireless/ath/ath11k/qmi.h
index b0a818f0401b..92925c9eac67 100644
--- a/drivers/net/wireless/ath/ath11k/qmi.h
+++ b/drivers/net/wireless/ath/ath11k/qmi.h
@@ -12,6 +12,7 @@
#define ATH11K_HOST_VERSION_STRING "WIN"
#define ATH11K_QMI_WLANFW_TIMEOUT_MS 5000
#define ATH11K_QMI_MAX_BDF_FILE_NAME_SIZE 64
+#define ATH11K_QMI_CALDB_ADDRESS 0x4BA00000
#define ATH11K_QMI_BDF_MAX_SIZE (256 * 1024)
#define ATH11K_QMI_CALDATA_OFFSET (128 * 1024)
#define ATH11K_QMI_WLANFW_MAX_BUILD_ID_LEN_V01 128
@@ -24,6 +25,7 @@
#define ATH11K_QMI_RESP_LEN_MAX 8192
#define ATH11K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01 32
#define ATH11K_QMI_CALDB_SIZE 0x480000
+#define ATH11K_QMI_BDF_EXT_STR_LENGTH 0x20
#define QMI_WLFW_REQUEST_MEM_IND_V01 0x0035
#define QMI_WLFW_FW_MEM_READY_IND_V01 0x0037
@@ -33,6 +35,7 @@
#define QMI_WLANFW_MAX_DATA_SIZE_V01 6144
#define ATH11K_FIRMWARE_MODE_OFF 4
#define ATH11K_QMI_TARGET_MEM_MODE_DEFAULT 0
+#define ATH11K_COLD_BOOT_FW_RESET_DELAY (40 * HZ)
struct ath11k_base;
@@ -101,6 +104,7 @@ struct target_info {
u32 fw_version;
char fw_build_timestamp[ATH11K_QMI_WLANFW_MAX_TIMESTAMP_LEN_V01 + 1];
char fw_build_id[ATH11K_QMI_WLANFW_MAX_BUILD_ID_LEN_V01 + 1];
+ char bdf_ext[ATH11K_QMI_BDF_EXT_STR_LENGTH];
};
struct m3_mem_region {
@@ -125,6 +129,7 @@ struct ath11k_qmi {
struct target_info target;
struct m3_mem_region m3_mem;
unsigned int service_ins_id;
+ wait_queue_head_t cold_boot_waitq;
};
#define QMI_WLANFW_HOST_CAP_REQ_MSG_V01_MAX_LEN 189
diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c
index f6a1f0352989..b876fec7fa1b 100644
--- a/drivers/net/wireless/ath/ath11k/reg.c
+++ b/drivers/net/wireless/ath/ath11k/reg.c
@@ -80,6 +80,7 @@ ath11k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
*/
init_country_param.flags = ALPHA_IS_SET;
memcpy(&init_country_param.cc_info.alpha2, request->alpha2, 2);
+ init_country_param.cc_info.alpha2[2] = 0;
ret = ath11k_wmi_send_init_country_cmd(ar, init_country_param);
if (ret)
@@ -277,6 +278,7 @@ ath11k_map_fw_dfs_region(enum ath11k_dfs_region dfs_region)
case ATH11K_DFS_REG_KR:
return NL80211_DFS_ETSI;
case ATH11K_DFS_REG_MKK:
+ case ATH11K_DFS_REG_MKK_N:
return NL80211_DFS_JP;
default:
return NL80211_DFS_UNSET;
@@ -584,7 +586,6 @@ ath11k_reg_build_regd(struct ath11k_base *ab,
if (!tmp_regd)
goto ret;
- tmp_regd->n_reg_rules = num_rules;
memcpy(tmp_regd->alpha2, reg_info->alpha2, REG_ALPHA2_LEN + 1);
memcpy(alpha2, reg_info->alpha2, REG_ALPHA2_LEN + 1);
alpha2[2] = '\0';
@@ -597,7 +598,7 @@ ath11k_reg_build_regd(struct ath11k_base *ab,
/* Update reg_rules[] below. Firmware is expected to
* send these rules in order(2G rules first and then 5G)
*/
- for (; i < tmp_regd->n_reg_rules; i++) {
+ for (; i < num_rules; i++) {
if (reg_info->num_2g_reg_rules &&
(i < reg_info->num_2g_reg_rules)) {
reg_rule = reg_info->reg_rules_2g_ptr + i;
@@ -652,6 +653,8 @@ ath11k_reg_build_regd(struct ath11k_base *ab,
flags);
}
+ tmp_regd->n_reg_rules = i;
+
if (intersect) {
default_regd = ab->default_regd[reg_info->phy_id];
diff --git a/drivers/net/wireless/ath/ath11k/reg.h b/drivers/net/wireless/ath/ath11k/reg.h
index 39b7fc943541..65d56d44796f 100644
--- a/drivers/net/wireless/ath/ath11k/reg.h
+++ b/drivers/net/wireless/ath/ath11k/reg.h
@@ -20,6 +20,7 @@ enum ath11k_dfs_region {
ATH11K_DFS_REG_MKK,
ATH11K_DFS_REG_CN,
ATH11K_DFS_REG_KR,
+ ATH11K_DFS_REG_MKK_N,
ATH11K_DFS_REG_UNDEF,
};
diff --git a/drivers/net/wireless/ath/ath11k/rx_desc.h b/drivers/net/wireless/ath/ath11k/rx_desc.h
index 1c4264637a41..86494da1069a 100644
--- a/drivers/net/wireless/ath/ath11k/rx_desc.h
+++ b/drivers/net/wireless/ath/ath11k/rx_desc.h
@@ -170,7 +170,7 @@ struct rx_attention {
*
* ast_index_not_found
* Only valid when first_msdu is set. Indicates no AST matching
- * entries within the the max search count.
+ * entries within the max search count.
*
* ast_index_timeout
* Only valid when first_msdu is set. Indicates an unsuccessful
diff --git a/drivers/net/wireless/ath/ath11k/testmode.c b/drivers/net/wireless/ath/ath11k/testmode.c
index d2dc9db01491..4bf1931adbaa 100644
--- a/drivers/net/wireless/ath/ath11k/testmode.c
+++ b/drivers/net/wireless/ath/ath11k/testmode.c
@@ -51,7 +51,7 @@ bool ath11k_tm_event_wmi(struct ath11k *ar, u32 cmd_id, struct sk_buff *skb)
ret = nla_put_u32(nl_skb, ATH11K_TM_ATTR_CMD, ATH11K_TM_CMD_WMI);
if (ret) {
ath11k_warn(ar->ab,
- "failed to to put testmode wmi event cmd attribute: %d\n",
+ "failed to put testmode wmi event cmd attribute: %d\n",
ret);
kfree_skb(nl_skb);
goto out;
@@ -60,7 +60,7 @@ bool ath11k_tm_event_wmi(struct ath11k *ar, u32 cmd_id, struct sk_buff *skb)
ret = nla_put_u32(nl_skb, ATH11K_TM_ATTR_WMI_CMDID, cmd_id);
if (ret) {
ath11k_warn(ar->ab,
- "failed to to put testmode wmi even cmd_id: %d\n",
+ "failed to put testmode wmi even cmd_id: %d\n",
ret);
kfree_skb(nl_skb);
goto out;
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index 8eca92520837..f6f726979710 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -122,6 +122,12 @@ static const struct wmi_tlv_policy wmi_tlv_policies[] = {
= { .min_len = sizeof(struct wmi_stats_event) },
[WMI_TAG_PDEV_CTL_FAILSAFE_CHECK_EVENT]
= { .min_len = sizeof(struct wmi_pdev_ctl_failsafe_chk_event) },
+ [WMI_TAG_HOST_SWFDA_EVENT] = {
+ .min_len = sizeof(struct wmi_fils_discovery_event) },
+ [WMI_TAG_OFFLOAD_PRB_RSP_TX_STATUS_EVENT] = {
+ .min_len = sizeof(struct wmi_probe_resp_tx_status_event) },
+ [WMI_TAG_VDEV_DELETE_RESP_EVENT] = {
+ .min_len = sizeof(struct wmi_vdev_delete_resp_event) },
};
#define PRIMAP(_hw_mode_) \
@@ -362,7 +368,7 @@ ath11k_pull_mac_phy_cap_svc_ready_ext(struct ath11k_pdev_wmi *wmi_handle,
* For example, for 4x4 capable macphys, first 4 chains can be used for first
* mac and the remaing 4 chains can be used for the second mac or vice-versa.
* In this case, tx/rx chainmask 0xf will be advertised for first mac and 0xf0
- * will be advertised for second mac or vice-versa. Compute the shift value for
+ * will be advertised for second mac or vice-versa. Compute the shift value
* for tx/rx chainmask which will be used to advertise supported ht/vht rates to
* mac80211.
*/
@@ -1946,6 +1952,11 @@ void ath11k_wmi_start_scan_init(struct ath11k *ar,
WMI_SCAN_EVENT_DEQUEUED;
arg->scan_flags |= WMI_SCAN_CHAN_STAT_EVENT;
arg->num_bssid = 1;
+
+ /* fill bssid_list[0] with 0xff, otherwise bssid and RA will be
+ * ZEROs in probe request
+ */
+ eth_broadcast_addr(arg->bssid_list[0].addr);
}
static inline void
@@ -3064,6 +3075,137 @@ int ath11k_wmi_send_bss_color_change_enable_cmd(struct ath11k *ar, u32 vdev_id,
return ret;
}
+int ath11k_wmi_fils_discovery_tmpl(struct ath11k *ar, u32 vdev_id,
+ struct sk_buff *tmpl)
+{
+ struct wmi_tlv *tlv;
+ struct sk_buff *skb;
+ void *ptr;
+ int ret, len;
+ size_t aligned_len;
+ struct wmi_fils_discovery_tmpl_cmd *cmd;
+
+ aligned_len = roundup(tmpl->len, 4);
+ len = sizeof(*cmd) + TLV_HDR_SIZE + aligned_len;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "WMI vdev %i set FILS discovery template\n", vdev_id);
+
+ skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_fils_discovery_tmpl_cmd *)skb->data;
+ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG,
+ WMI_TAG_FILS_DISCOVERY_TMPL_CMD) |
+ FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
+ cmd->vdev_id = vdev_id;
+ cmd->buf_len = tmpl->len;
+ ptr = skb->data + sizeof(*cmd);
+
+ tlv = ptr;
+ tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) |
+ FIELD_PREP(WMI_TLV_LEN, aligned_len);
+ memcpy(tlv->value, tmpl->data, tmpl->len);
+
+ ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_FILS_DISCOVERY_TMPL_CMDID);
+ if (ret) {
+ ath11k_warn(ar->ab,
+ "WMI vdev %i failed to send FILS discovery template command\n",
+ vdev_id);
+ dev_kfree_skb(skb);
+ }
+ return ret;
+}
+
+int ath11k_wmi_probe_resp_tmpl(struct ath11k *ar, u32 vdev_id,
+ struct sk_buff *tmpl)
+{
+ struct wmi_probe_tmpl_cmd *cmd;
+ struct wmi_bcn_prb_info *probe_info;
+ struct wmi_tlv *tlv;
+ struct sk_buff *skb;
+ void *ptr;
+ int ret, len;
+ size_t aligned_len = roundup(tmpl->len, 4);
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "WMI vdev %i set probe response template\n", vdev_id);
+
+ len = sizeof(*cmd) + sizeof(*probe_info) + TLV_HDR_SIZE + aligned_len;
+
+ skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_probe_tmpl_cmd *)skb->data;
+ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_PRB_TMPL_CMD) |
+ FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
+ cmd->vdev_id = vdev_id;
+ cmd->buf_len = tmpl->len;
+
+ ptr = skb->data + sizeof(*cmd);
+
+ probe_info = ptr;
+ len = sizeof(*probe_info);
+ probe_info->tlv_header = FIELD_PREP(WMI_TLV_TAG,
+ WMI_TAG_BCN_PRB_INFO) |
+ FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE);
+ probe_info->caps = 0;
+ probe_info->erp = 0;
+
+ ptr += sizeof(*probe_info);
+
+ tlv = ptr;
+ tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) |
+ FIELD_PREP(WMI_TLV_LEN, aligned_len);
+ memcpy(tlv->value, tmpl->data, tmpl->len);
+
+ ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_PRB_TMPL_CMDID);
+ if (ret) {
+ ath11k_warn(ar->ab,
+ "WMI vdev %i failed to send probe response template command\n",
+ vdev_id);
+ dev_kfree_skb(skb);
+ }
+ return ret;
+}
+
+int ath11k_wmi_fils_discovery(struct ath11k *ar, u32 vdev_id, u32 interval,
+ bool unsol_bcast_probe_resp_enabled)
+{
+ struct sk_buff *skb;
+ int ret, len;
+ struct wmi_fils_discovery_cmd *cmd;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "WMI vdev %i set %s interval to %u TU\n",
+ vdev_id, unsol_bcast_probe_resp_enabled ?
+ "unsolicited broadcast probe response" : "FILS discovery",
+ interval);
+
+ len = sizeof(*cmd);
+ skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_fils_discovery_cmd *)skb->data;
+ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ENABLE_FILS_CMD) |
+ FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE);
+ cmd->vdev_id = vdev_id;
+ cmd->interval = interval;
+ cmd->config = unsol_bcast_probe_resp_enabled;
+
+ ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_ENABLE_FILS_CMDID);
+ if (ret) {
+ ath11k_warn(ar->ab,
+ "WMI vdev %i failed to send FILS discovery enable/disable command\n",
+ vdev_id);
+ dev_kfree_skb(skb);
+ }
+ return ret;
+}
+
static void
ath11k_fill_band_to_mac_param(struct ath11k_base *soc,
struct wmi_host_pdev_band_to_mac *band_to_mac)
@@ -3351,9 +3493,6 @@ int ath11k_wmi_cmd_init(struct ath11k_base *ab)
init_param.hw_mode_id = wmi_sc->preferred_hw_mode;
init_param.mem_chunks = wmi_sc->mem_chunks;
- if (wmi_sc->preferred_hw_mode == WMI_HOST_HW_MODE_SINGLE)
- init_param.hw_mode_id = WMI_HOST_HW_MODE_MAX;
-
if (ab->hw_params.needs_band_to_mac) {
init_param.num_band_to_mac = ab->num_radios;
ath11k_fill_band_to_mac_param(ab, init_param.band_to_mac);
@@ -4242,6 +4381,34 @@ static int ath11k_pull_peer_del_resp_ev(struct ath11k_base *ab, struct sk_buff *
return 0;
}
+static int ath11k_pull_vdev_del_resp_ev(struct ath11k_base *ab,
+ struct sk_buff *skb,
+ u32 *vdev_id)
+{
+ const void **tb;
+ const struct wmi_vdev_delete_resp_event *ev;
+ int ret;
+
+ tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
+ if (IS_ERR(tb)) {
+ ret = PTR_ERR(tb);
+ ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
+ return ret;
+ }
+
+ ev = tb[WMI_TAG_VDEV_DELETE_RESP_EVENT];
+ if (!ev) {
+ ath11k_warn(ab, "failed to fetch vdev delete resp ev");
+ kfree(tb);
+ return -EPROTO;
+ }
+
+ *vdev_id = ev->vdev_id;
+
+ kfree(tb);
+ return 0;
+}
+
static int ath11k_pull_bcn_tx_status_ev(struct ath11k_base *ab, void *evt_buf,
u32 len, u32 *vdev_id,
u32 *tx_status)
@@ -5563,15 +5730,54 @@ static int ath11k_ready_event(struct ath11k_base *ab, struct sk_buff *skb)
static void ath11k_peer_delete_resp_event(struct ath11k_base *ab, struct sk_buff *skb)
{
struct wmi_peer_delete_resp_event peer_del_resp;
+ struct ath11k *ar;
if (ath11k_pull_peer_del_resp_ev(ab, skb, &peer_del_resp) != 0) {
ath11k_warn(ab, "failed to extract peer delete resp");
return;
}
- /* TODO: Do we need to validate whether ath11k_peer_find() return NULL
- * Why this is needed when there is HTT event for peer delete
- */
+ rcu_read_lock();
+ ar = ath11k_mac_get_ar_by_vdev_id(ab, peer_del_resp.vdev_id);
+ if (!ar) {
+ ath11k_warn(ab, "invalid vdev id in peer delete resp ev %d",
+ peer_del_resp.vdev_id);
+ rcu_read_unlock();
+ return;
+ }
+
+ complete(&ar->peer_delete_done);
+ rcu_read_unlock();
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "peer delete resp for vdev id %d addr %pM\n",
+ peer_del_resp.vdev_id, peer_del_resp.peer_macaddr.addr);
+}
+
+static void ath11k_vdev_delete_resp_event(struct ath11k_base *ab,
+ struct sk_buff *skb)
+{
+ struct ath11k *ar;
+ u32 vdev_id = 0;
+
+ if (ath11k_pull_vdev_del_resp_ev(ab, skb, &vdev_id) != 0) {
+ ath11k_warn(ab, "failed to extract vdev delete resp");
+ return;
+ }
+
+ rcu_read_lock();
+ ar = ath11k_mac_get_ar_by_vdev_id(ab, vdev_id);
+ if (!ar) {
+ ath11k_warn(ab, "invalid vdev id in vdev delete resp ev %d",
+ vdev_id);
+ rcu_read_unlock();
+ return;
+ }
+
+ complete(&ar->vdev_delete_done);
+
+ rcu_read_unlock();
+
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "vdev delete resp for vdev id %d\n",
+ vdev_id);
}
static inline const char *ath11k_wmi_vdev_resp_print(u32 vdev_resp_status)
@@ -5650,7 +5856,7 @@ static void ath11k_vdev_stopped_event(struct ath11k_base *ab, struct sk_buff *sk
}
rcu_read_lock();
- ar = ath11k_mac_get_ar_vdev_stop_status(ab, vdev_id);
+ ar = ath11k_mac_get_ar_by_vdev_id(ab, vdev_id);
if (!ar) {
ath11k_warn(ab, "invalid vdev id in vdev stopped ev %d",
vdev_id);
@@ -6429,6 +6635,68 @@ ath11k_wmi_pdev_temperature_event(struct ath11k_base *ab,
ath11k_thermal_event_temperature(ar, ev.temp);
}
+static void ath11k_fils_discovery_event(struct ath11k_base *ab,
+ struct sk_buff *skb)
+{
+ const void **tb;
+ const struct wmi_fils_discovery_event *ev;
+ int ret;
+
+ tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
+ if (IS_ERR(tb)) {
+ ret = PTR_ERR(tb);
+ ath11k_warn(ab,
+ "failed to parse FILS discovery event tlv %d\n",
+ ret);
+ return;
+ }
+
+ ev = tb[WMI_TAG_HOST_SWFDA_EVENT];
+ if (!ev) {
+ ath11k_warn(ab, "failed to fetch FILS discovery event\n");
+ kfree(tb);
+ return;
+ }
+
+ ath11k_warn(ab,
+ "FILS discovery frame expected from host for vdev_id: %u, transmission scheduled at %u, next TBTT: %u\n",
+ ev->vdev_id, ev->fils_tt, ev->tbtt);
+
+ kfree(tb);
+}
+
+static void ath11k_probe_resp_tx_status_event(struct ath11k_base *ab,
+ struct sk_buff *skb)
+{
+ const void **tb;
+ const struct wmi_probe_resp_tx_status_event *ev;
+ int ret;
+
+ tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
+ if (IS_ERR(tb)) {
+ ret = PTR_ERR(tb);
+ ath11k_warn(ab,
+ "failed to parse probe response transmission status event tlv: %d\n",
+ ret);
+ return;
+ }
+
+ ev = tb[WMI_TAG_OFFLOAD_PRB_RSP_TX_STATUS_EVENT];
+ if (!ev) {
+ ath11k_warn(ab,
+ "failed to fetch probe response transmission status event");
+ kfree(tb);
+ return;
+ }
+
+ if (ev->tx_status)
+ ath11k_warn(ab,
+ "Probe response transmission failed for vdev_id %u, status %u\n",
+ ev->vdev_id, ev->tx_status);
+
+ kfree(tb);
+}
+
static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
{
struct wmi_cmd_hdr *cmd_hdr;
@@ -6515,9 +6783,14 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
case WMI_PDEV_DMA_RING_BUF_RELEASE_EVENTID:
ath11k_wmi_pdev_dma_ring_buf_release_event(ab, skb);
break;
+ case WMI_HOST_FILS_DISCOVERY_EVENTID:
+ ath11k_fils_discovery_event(ab, skb);
+ break;
+ case WMI_OFFLOAD_PROB_RESP_TX_STATUS_EVENTID:
+ ath11k_probe_resp_tx_status_event(ab, skb);
+ break;
/* add Unsupported events here */
case WMI_TBTTOFFSET_EXT_UPDATE_EVENTID:
- case WMI_VDEV_DELETE_RESP_EVENTID:
case WMI_PEER_OPER_MODE_CHANGE_EVENTID:
case WMI_TWT_ENABLE_EVENTID:
case WMI_TWT_DISABLE_EVENTID:
@@ -6528,6 +6801,9 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
case WMI_PDEV_DFS_RADAR_DETECTION_EVENTID:
ath11k_wmi_pdev_dfs_radar_detected_event(ab, skb);
break;
+ case WMI_VDEV_DELETE_RESP_EVENTID:
+ ath11k_vdev_delete_resp_event(ab, skb);
+ break;
/* TODO: Add remaining events */
default:
ath11k_dbg(ab, ATH11K_DBG_WMI, "Unknown eventid: 0x%x\n", id);
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index 5a32ba0eb4f5..4c802c51b3d9 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -319,6 +319,7 @@ enum wmi_tlv_cmd_id {
WMI_BCN_OFFLOAD_CTRL_CMDID,
WMI_BSS_COLOR_CHANGE_ENABLE_CMDID,
WMI_VDEV_BCN_OFFLOAD_QUIET_CONFIG_CMDID,
+ WMI_FILS_DISCOVERY_TMPL_CMDID,
WMI_ADDBA_CLEAR_RESP_CMDID = WMI_TLV_CMD(WMI_GRP_BA_NEG),
WMI_ADDBA_SEND_CMDID,
WMI_ADDBA_STATUS_CMDID,
@@ -351,6 +352,8 @@ enum wmi_tlv_cmd_id {
WMI_ROAM_CONFIGURE_MAWC_CMDID,
WMI_ROAM_SET_MBO_PARAM_CMDID,
WMI_ROAM_PER_CONFIG_CMDID,
+ WMI_ROAM_BTM_CONFIG_CMDID,
+ WMI_ENABLE_FILS_CMDID,
WMI_OFL_SCAN_ADD_AP_PROFILE = WMI_TLV_CMD(WMI_GRP_OFL_SCAN),
WMI_OFL_SCAN_REMOVE_AP_PROFILE,
WMI_OFL_SCAN_PERIOD,
@@ -642,6 +645,8 @@ enum wmi_tlv_event_id {
WMI_MGMT_TX_COMPLETION_EVENTID,
WMI_MGMT_TX_BUNDLE_COMPLETION_EVENTID,
WMI_TBTTOFFSET_EXT_UPDATE_EVENTID,
+ WMI_OFFCHAN_DATA_TX_COMPLETION_EVENTID,
+ WMI_HOST_FILS_DISCOVERY_EVENTID,
WMI_TX_DELBA_COMPLETE_EVENTID = WMI_TLV_CMD(WMI_GRP_BA_NEG),
WMI_TX_ADDBA_COMPLETE_EVENTID,
WMI_BA_RSP_SSN_EVENTID,
@@ -1810,6 +1815,7 @@ enum wmi_tlv_tag {
/* TODO add all the missing cmds */
WMI_TAG_PDEV_PEER_PKTLOG_FILTER_CMD = 0x301,
WMI_TAG_PDEV_PEER_PKTLOG_FILTER_INFO,
+ WMI_TAG_FILS_DISCOVERY_TMPL_CMD = 0x344,
WMI_TAG_MAX
};
@@ -3348,7 +3354,6 @@ struct wmi_mgmt_params {
void *pdata;
u16 desc_id;
u8 *macaddr;
- void *qdf_ctx;
};
enum wmi_sta_ps_mode {
@@ -4013,6 +4018,10 @@ struct wmi_regulatory_rule_struct {
u32 flag_info;
};
+struct wmi_vdev_delete_resp_event {
+ u32 vdev_id;
+} __packed;
+
struct wmi_peer_delete_resp_event {
u32 vdev_id;
struct wmi_mac_addr peer_macaddr;
@@ -4076,6 +4085,17 @@ struct wmi_peer_assoc_conf_arg {
const u8 *macaddr;
};
+struct wmi_fils_discovery_event {
+ u32 vdev_id;
+ u32 fils_tt;
+ u32 tbtt;
+} __packed;
+
+struct wmi_probe_resp_tx_status_event {
+ u32 vdev_id;
+ u32 tx_status;
+} __packed;
+
/*
* PDEV statistics
*/
@@ -4908,6 +4928,30 @@ struct wmi_dma_buf_release_meta_data {
u32 ch_width;
} __packed;
+enum wmi_fils_discovery_cmd_type {
+ WMI_FILS_DISCOVERY_CMD,
+ WMI_UNSOL_BCAST_PROBE_RESP,
+};
+
+struct wmi_fils_discovery_cmd {
+ u32 tlv_header;
+ u32 vdev_id;
+ u32 interval;
+ u32 config; /* enum wmi_fils_discovery_cmd_type */
+} __packed;
+
+struct wmi_fils_discovery_tmpl_cmd {
+ u32 tlv_header;
+ u32 vdev_id;
+ u32 buf_len;
+} __packed;
+
+struct wmi_probe_tmpl_cmd {
+ u32 tlv_header;
+ u32 vdev_id;
+ u32 buf_len;
+} __packed;
+
struct target_resource_config {
u32 num_vdevs;
u32 num_peers;
@@ -5121,4 +5165,10 @@ int ath11k_wmi_vdev_spectral_enable(struct ath11k *ar, u32 vdev_id,
u32 trigger, u32 enable);
int ath11k_wmi_vdev_spectral_conf(struct ath11k *ar,
struct ath11k_wmi_vdev_spectral_conf_param *param);
+int ath11k_wmi_fils_discovery_tmpl(struct ath11k *ar, u32 vdev_id,
+ struct sk_buff *tmpl);
+int ath11k_wmi_fils_discovery(struct ath11k *ar, u32 vdev_id, u32 interval,
+ bool unsol_bcast_probe_resp_enabled);
+int ath11k_wmi_probe_resp_tmpl(struct ath11k *ar, u32 vdev_id,
+ struct sk_buff *tmpl);
#endif
diff --git a/drivers/net/wireless/ath/ath6kl/testmode.c b/drivers/net/wireless/ath/ath6kl/testmode.c
index f3906dbe5495..89c7c4e25169 100644
--- a/drivers/net/wireless/ath/ath6kl/testmode.c
+++ b/drivers/net/wireless/ath/ath6kl/testmode.c
@@ -94,7 +94,6 @@ int ath6kl_tm_cmd(struct wiphy *wiphy, struct wireless_dev *wdev,
return 0;
- break;
case ATH6KL_TM_CMD_RX_REPORT:
default:
return -EOPNOTSUPP;
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index dbc47702a268..b137e7f34397 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -1821,8 +1821,8 @@ int ath6kl_wmi_cmd_send(struct wmi *wmi, u8 if_idx, struct sk_buff *skb,
/* Only for OPT_TX_CMD, use BE endpoint. */
if (cmd_id == WMI_OPT_TX_FRAME_CMDID) {
- ret = ath6kl_wmi_data_hdr_add(wmi, skb, OPT_MSGTYPE,
- false, false, 0, NULL, if_idx);
+ ret = ath6kl_wmi_data_hdr_add(wmi, skb, OPT_MSGTYPE, false,
+ WMI_DATA_HDR_DATA_TYPE_802_3, 0, NULL, if_idx);
if (ret) {
dev_kfree_skb(skb);
return ret;
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index 2fa30834a88d..6610d76131fa 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -102,13 +102,8 @@ static void ar5008_write_bank6(struct ath_hw *ah, unsigned int *writecnt)
REGWRITE_BUFFER_FLUSH(ah);
}
-/**
+/*
* ar5008_hw_phy_modify_rx_buffer() - perform analog swizzling of parameters
- * @rfbuf:
- * @reg32:
- * @numBits:
- * @firstBit:
- * @column:
*
* Performs analog "swizzling" of parameters into their location.
* Used on external AR2133/AR5133 radios.
@@ -198,10 +193,8 @@ static void ar5008_hw_force_bias(struct ath_hw *ah, u16 synth_freq)
ar5008_write_bank6(ah, &reg_writes);
}
-/**
+/*
* ar5008_hw_set_channel - tune to a channel on the external AR2133/AR5133 radios
- * @ah: atheros hardware structure
- * @chan:
*
* For the external AR2133/AR5133 radios, takes the MHz channel value and set
* the channel value. Assumes writes enabled to analog bus and bank6 register
@@ -430,10 +423,8 @@ void ar5008_hw_cmn_spur_mitigate(struct ath_hw *ah,
REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
}
-/**
+/*
* ar5008_hw_spur_mitigate - convert baseband spur frequency for external radios
- * @ah: atheros hardware structure
- * @chan:
*
* For non single-chip solutions. Converts to baseband spur frequency given the
* input channel frequency and compute register settings below.
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
index c07866a2fdf9..16d5c0c5e2a8 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
@@ -1724,20 +1724,6 @@ static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p2[][2] = {
{0x00004044, 0x00000000},
};
-static const u32 ar9300PciePhy_clkreq_enable_L1_2p2[][2] = {
- /* Addr allmodes */
- {0x00004040, 0x0825365e},
- {0x00004040, 0x0008003b},
- {0x00004044, 0x00000000},
-};
-
-static const u32 ar9300PciePhy_clkreq_disable_L1_2p2[][2] = {
- /* Addr allmodes */
- {0x00004040, 0x0821365e},
- {0x00004040, 0x0008003b},
- {0x00004044, 0x00000000},
-};
-
static const u32 ar9300_2p2_baseband_core_txfir_coeff_japan_2484[][2] = {
/* Addr allmodes */
{0x0000a398, 0x00000000},
diff --git a/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h b/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h
index 29479afbc4f1..3e783fc13553 100644
--- a/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h
@@ -1010,11 +1010,4 @@ static const u32 ar9331_common_rx_gain_1p1[][2] = {
{0x0000a1fc, 0x00000296},
};
-static const u32 ar9331_common_tx_gain_offset1_1[][1] = {
- {0x00000000},
- {0x00000003},
- {0x00000000},
- {0x00000000},
-};
-
#endif /* INITVALS_9330_1P1_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h
index 2eb163fc1c18..3da4ea564148 100644
--- a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h
@@ -621,107 +621,6 @@ static const u32 ar9340Modes_high_ob_db_tx_gain_table_1p0[][5] = {
{0x00016448, 0x8e481666, 0x8e481666, 0x8e481266, 0x8e481266},
};
-static const u32 ar9340Modes_ub124_tx_gain_table_1p0[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
- {0x00009820, 0x206a022e, 0x206a022e, 0x206a00ae, 0x206a00ae},
- {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
- {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec82d2e, 0x7ec82d2e},
- {0x0000a2dc, 0xfef5d402, 0xfef5d402, 0xfdab5b52, 0xfdab5b52},
- {0x0000a2e0, 0xfe896600, 0xfe896600, 0xfd339c84, 0xfd339c84},
- {0x0000a2e4, 0xff01f800, 0xff01f800, 0xfec3e000, 0xfec3e000},
- {0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffc0000, 0xfffc0000},
- {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
- {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
- {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
- {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
- {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
- {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
- {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
- {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
- {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
- {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
- {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
- {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
- {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
- {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
- {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
- {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
- {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
- {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
- {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
- {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
- {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83},
- {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
- {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
- {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
- {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
- {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
- {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
- {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
- {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
- {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
- {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
- {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
- {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
- {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
- {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
- {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
- {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
- {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
- {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
- {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
- {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
- {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
- {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
- {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
- {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
- {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
- {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
- {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
- {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
- {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
- {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
- {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x00016044, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4},
- {0x00016048, 0x8e480086, 0x8e480086, 0x8e480086, 0x8e480086},
- {0x00016444, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4},
- {0x00016448, 0x8e480086, 0x8e480086, 0x8e480086, 0x8e480086},
- {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
- {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
- {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
- {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
- {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
- {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
- {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
- {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
- {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
- {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
- {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
- {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
- {0x0000b2dc, 0xfef5d402, 0xfef5d402, 0xfdab5b52, 0xfdab5b52},
- {0x0000b2e0, 0xfe896600, 0xfe896600, 0xfd339c84, 0xfd339c84},
- {0x0000b2e4, 0xff01f800, 0xff01f800, 0xfec3e000, 0xfec3e000},
- {0x0000b2e8, 0xfffe0000, 0xfffe0000, 0xfffc0000, 0xfffc0000},
-};
-
static const u32 ar9340Modes_low_ob_db_tx_gain_table_1p0[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
index bdf6f107f6f1..4afe52c0456e 100644
--- a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
@@ -1006,13 +1006,6 @@ static const u32 ar9485_1_1_soc_preamble[][2] = {
{0x00007048, 0x00000002},
};
-static const u32 ar9485_fast_clock_1_1_baseband_postamble[][3] = {
- /* Addr 5G_HT20 5G_HT40 */
- {0x00009e00, 0x03721821, 0x03721821},
- {0x0000a230, 0x0000400b, 0x00004016},
- {0x0000a254, 0x00000898, 0x00001130},
-};
-
static const u32 ar9485_1_1_baseband_postamble[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
diff --git a/drivers/net/wireless/ath/ath9k/dynack.c b/drivers/net/wireless/ath/ath9k/dynack.c
index fbeb4a739d32..321ff54fdb42 100644
--- a/drivers/net/wireless/ath/ath9k/dynack.c
+++ b/drivers/net/wireless/ath/ath9k/dynack.c
@@ -44,9 +44,8 @@ static u32 ath_dynack_get_max_to(struct ath_hw *ah)
return 600;
}
-/**
+/*
* ath_dynack_ewma - EWMA (Exponentially Weighted Moving Average) calculation
- *
*/
static inline int ath_dynack_ewma(int old, int new)
{
@@ -247,8 +246,12 @@ void ath_dynack_sample_tx_ts(struct ath_hw *ah, struct sk_buff *skb,
ridx = ts->ts_rateindex;
da->st_rbf.ts[da->st_rbf.t_rb].tstamp = ts->ts_tstamp;
- ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_dest, hdr->addr1);
- ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_src, hdr->addr2);
+
+ /* ether_addr_copy() gives a false warning on gcc-10 so use memcpy()
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97490
+ */
+ memcpy(da->st_rbf.addr[da->st_rbf.t_rb].h_dest, hdr->addr1, ETH_ALEN);
+ memcpy(da->st_rbf.addr[da->st_rbf.t_rb].h_src, hdr->addr2, ETH_ALEN);
if (!(info->status.rates[ridx].flags & IEEE80211_TX_RC_MCS)) {
const struct ieee80211_rate *rate;
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 6609ce122e6e..b66eeb577272 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -2308,7 +2308,6 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)
ath_dbg(ath9k_hw_common(ah), BEACON,
"%s: unsupported opmode: %d\n", __func__, ah->opmode);
return;
- break;
}
REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period);
diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.c b/drivers/net/wireless/ath/dfs_pattern_detector.c
index 0813473793df..80390495ea25 100644
--- a/drivers/net/wireless/ath/dfs_pattern_detector.c
+++ b/drivers/net/wireless/ath/dfs_pattern_detector.c
@@ -23,7 +23,7 @@
/**
* struct radar_types - contains array of patterns defined for one DFS domain
- * @domain: DFS regulatory domain
+ * @region: regulatory DFS region
* @num_radar_types: number of radar types to follow
* @radar_types: radar types array
*/
@@ -133,8 +133,9 @@ static const struct radar_types *dfs_domains[] = {
/**
* get_dfs_domain_radar_types() - get radar types for a given DFS domain
- * @param domain DFS domain
- * @return radar_types ptr on success, NULL if DFS domain is not supported
+ * @region: regulatory DFS region
+ *
+ * Return value: radar_types ptr on success, NULL if DFS domain is not supported
*/
static const struct radar_types *
get_dfs_domain_radar_types(enum nl80211_dfs_regions region)
@@ -227,9 +228,10 @@ fail:
/**
* channel_detector_get() - get channel detector for given frequency
- * @param dpd instance pointer
- * @param freq frequency in MHz
- * @return pointer to channel detector on success, NULL otherwise
+ * @dpd: DPD instance pointer
+ * @freq: freq frequency in MHz
+ *
+ * Return value: pointer to channel detector on success, NULL otherwise
*
* Return existing channel detector for the given frequency or return a
* newly create one.
diff --git a/drivers/net/wireless/ath/dfs_pri_detector.c b/drivers/net/wireless/ath/dfs_pri_detector.c
index 05b0464c6b92..d07c454c9c00 100644
--- a/drivers/net/wireless/ath/dfs_pri_detector.c
+++ b/drivers/net/wireless/ath/dfs_pri_detector.c
@@ -29,18 +29,17 @@ struct ath_dfs_pool_stats global_dfs_pool_stats = {};
(MIN + PRI_TOLERANCE == MAX - PRI_TOLERANCE ? \
MIN + PRI_TOLERANCE : RUNTIME)
-/**
+/*
* struct pulse_elem - elements in pulse queue
- * @ts: time stamp in usecs
*/
struct pulse_elem {
struct list_head head;
u64 ts;
};
-/**
+/*
* pde_get_multiple() - get number of multiples considering a given tolerance
- * @return factor if abs(val - factor*fraction) <= tolerance, 0 otherwise
+ * Return value: factor if abs(val - factor*fraction) <= tolerance, 0 otherwise
*/
static u32 pde_get_multiple(u32 val, u32 fraction, u32 tolerance)
{
@@ -70,7 +69,7 @@ static u32 pde_get_multiple(u32 val, u32 fraction, u32 tolerance)
return factor;
}
-/**
+/*
* DOC: Singleton Pulse and Sequence Pools
*
* Instances of pri_sequence and pulse_elem are kept in singleton pools to
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c
index bee9110b91f3..b2400e2417a5 100644
--- a/drivers/net/wireless/ath/regd.c
+++ b/drivers/net/wireless/ath/regd.c
@@ -360,6 +360,7 @@ ath_reg_apply_beaconing_flags(struct wiphy *wiphy,
/**
* ath_reg_apply_ir_flags()
* @wiphy: the wiphy to use
+ * @reg: regulatory structure - used for country selection
* @initiator: the regulatory hint initiator
*
* If no country IE has been received always enable passive scan
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index 706728fba72d..5867bd9c2f64 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -910,6 +910,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
* place where AID is available.
*/
wcn36xx_smd_config_sta(wcn, vif, sta);
+ wcn36xx_enable_keep_alive_null_packet(wcn, vif);
} else {
wcn36xx_dbg(WCN36XX_DBG_MAC,
"disassociated bss %pM vif %pM AID=%d\n",
@@ -1246,6 +1247,7 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL);
ieee80211_hw_set(wcn->hw, SINGLE_SCAN_ON_ALL_BANDS);
ieee80211_hw_set(wcn->hw, REPORTS_TX_ACK_STATUS);
+ ieee80211_hw_set(wcn->hw, CONNECTION_MONITOR);
wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
index 766400f7b61c..acf533fae46a 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -78,6 +78,7 @@ static struct wcn36xx_cfg_val wcn36xx_cfg_vals[] = {
WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10),
WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0),
WCN36XX_CFG_VAL(ENABLE_DYNAMIC_RA_START_RATE, 133), /* MCS 5 */
+ WCN36XX_CFG_VAL(LINK_FAIL_TX_CNT, 1000),
};
static struct wcn36xx_cfg_val wcn3680_cfg_vals[] = {
@@ -162,7 +163,7 @@ static struct wcn36xx_cfg_val wcn3680_cfg_vals[] = {
WCN36XX_CFG_VAL(ENABLE_RTSCTS_HTVHT, 0),
WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_IDLE_WLAN_LEN, 30000),
WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_IDLE_BT_LEN, 120000),
- WCN36XX_CFG_VAL(LINK_FAIL_TX_CNT, 200),
+ WCN36XX_CFG_VAL(LINK_FAIL_TX_CNT, 1000),
WCN36XX_CFG_VAL(TOGGLE_ARP_BDRATES, 0),
WCN36XX_CFG_VAL(OPTIMIZE_CA_EVENT, 0),
WCN36XX_CFG_VAL(EXT_SCAN_CONC_MODE, 0),
@@ -2175,6 +2176,7 @@ int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_BMPS_REQ);
msg_body.bss_index = vif_priv->bss_index;
+ msg_body.send_data_null = 1;
PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 421aebbb49e5..8699f8279a8b 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -262,7 +262,7 @@ struct fw_map *wil_find_fw_mapping(const char *section)
/**
* Check address validity for WMI buffer; remap if needed
* @wil: driver data
- * @ptr: internal (linker) fw/ucode address
+ * @ptr_: internal (linker) fw/ucode address
* @size: if non zero, validate the block does not
* exceed the device memory (bar)
*
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index f9ebb98b0e3c..ce8c102df7b3 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -367,7 +367,7 @@ static int mmc_submit_one(struct mmc_data *md, struct mmc_request *mr,
* @func: SDIO function
* @write: direction flag
* @addr: dongle memory address as source/destination
- * @pkt: skb pointer
+ * @pktlist: skb buffer head pointer
*
* This function takes the respbonsibility as the interface function to MMC
* stack for block data access. It assumes that the skb passed down by the
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index a2dbbb977d0c..0ee421f30aa2 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -2137,7 +2137,8 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
BRCMF_WSEC_MAX_PSK_LEN);
else if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_SAE) {
/* clean up user-space RSNE */
- if (brcmf_fil_iovar_data_set(ifp, "wpaie", NULL, 0)) {
+ err = brcmf_fil_iovar_data_set(ifp, "wpaie", NULL, 0);
+ if (err) {
bphy_err(drvr, "failed to clean up user-space RSNE\n");
goto done;
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
index 430d2cca98b3..bc3f4e4edcdf 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
@@ -384,6 +384,7 @@ int brcmf_fweh_activate_events(struct brcmf_if *ifp)
* @drvr: driver information object.
* @event_packet: event packet to process.
* @packet_len: length of the packet
+ * @gfp: memory allocation flags.
*
* If the packet buffer contains a firmware event message it will
* dispatch the event to a registered handler (using worker).
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index 39381cbde89e..45bc502fcb34 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -759,6 +759,7 @@ static void brcmf_pcie_bus_console_init(struct brcmf_pciedev_info *devinfo)
/**
* brcmf_pcie_bus_console_read - reads firmware messages
*
+ * @devinfo: pointer to the device data structure
* @error: specifies if error has occurred (prints messages unconditionally)
*/
static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo,
@@ -1936,16 +1937,18 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
fwreq = brcmf_pcie_prepare_fw_request(devinfo);
if (!fwreq) {
ret = -ENOMEM;
- goto fail_bus;
+ goto fail_brcmf;
}
ret = brcmf_fw_get_firmwares(bus->dev, fwreq, brcmf_pcie_setup);
if (ret < 0) {
kfree(fwreq);
- goto fail_bus;
+ goto fail_brcmf;
}
return 0;
+fail_brcmf:
+ brcmf_free(&devinfo->pdev->dev);
fail_bus:
kfree(bus->msgbuf);
kfree(bus);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 99987a789e7e..16ed325795a8 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -625,6 +625,10 @@ BRCMF_FW_DEF(4359, "brcmfmac4359-sdio");
BRCMF_FW_DEF(4373, "brcmfmac4373-sdio");
BRCMF_FW_DEF(43012, "brcmfmac43012-sdio");
+/* firmware config files */
+MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcm/brcmfmac*-sdio.*.txt");
+MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcm/brcmfmac*-pcie.*.txt");
+
static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143),
BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x0000001F, 43241B0),
@@ -1340,7 +1344,7 @@ static void brcmf_sdio_free_glom(struct brcmf_sdio *bus)
static inline u8 brcmf_sdio_getdatoffset(u8 *swheader)
{
u32 hdrvalue;
- hdrvalue = *(u32 *)swheader;
+ hdrvalue = le32_to_cpu(*(__le32 *)swheader);
return (u8)((hdrvalue & SDPCM_DOFFSET_MASK) >> SDPCM_DOFFSET_SHIFT);
}
@@ -1349,7 +1353,7 @@ static inline bool brcmf_sdio_fromevntchan(u8 *swheader)
u32 hdrvalue;
u8 ret;
- hdrvalue = *(u32 *)swheader;
+ hdrvalue = le32_to_cpu(*(__le32 *)swheader);
ret = (u8)((hdrvalue & SDPCM_CHANNEL_MASK) >> SDPCM_CHANNEL_SHIFT);
return (ret == SDPCM_EVENT_CHANNEL);
@@ -3517,6 +3521,7 @@ static int brcmf_sdio_bus_preinit(struct device *dev)
struct brcmf_sdio *bus = sdiodev->bus;
struct brcmf_core *core = bus->sdio_core;
u32 value;
+ __le32 iovar;
int err;
/* maxctl provided by common layer */
@@ -3537,16 +3542,16 @@ static int brcmf_sdio_bus_preinit(struct device *dev)
*/
if (core->rev < 12) {
/* for sdio core rev < 12, disable txgloming */
- value = 0;
- err = brcmf_iovar_data_set(dev, "bus:txglom", &value,
- sizeof(u32));
+ iovar = 0;
+ err = brcmf_iovar_data_set(dev, "bus:txglom", &iovar,
+ sizeof(iovar));
} else {
/* otherwise, set txglomalign */
value = sdiodev->settings->bus.sdio.sd_sgentry_align;
/* SDIO ADMA requires at least 32 bit alignment */
- value = max_t(u32, value, ALIGNMENT);
- err = brcmf_iovar_data_set(dev, "bus:txglomalign", &value,
- sizeof(u32));
+ iovar = cpu_to_le32(max_t(u32, value, ALIGNMENT));
+ err = brcmf_iovar_data_set(dev, "bus:txglomalign", &iovar,
+ sizeof(iovar));
}
if (err < 0)
@@ -3555,9 +3560,9 @@ static int brcmf_sdio_bus_preinit(struct device *dev)
bus->tx_hdrlen = SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN;
if (sdiodev->sg_support) {
bus->txglom = false;
- value = 1;
+ iovar = cpu_to_le32(1);
err = brcmf_iovar_data_set(bus->sdiodev->dev, "bus:rxglom",
- &value, sizeof(u32));
+ &iovar, sizeof(iovar));
if (err < 0) {
/* bus:rxglom is allowed to fail */
err = 0;
@@ -4541,6 +4546,7 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus)
brcmf_sdiod_intr_unregister(bus->sdiodev);
brcmf_detach(bus->sdiodev->dev);
+ brcmf_free(bus->sdiodev->dev);
cancel_work_sync(&bus->datawork);
if (bus->brcmf_wq)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c
index c9fb4b0cffaf..2631eb7569eb 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c
@@ -942,14 +942,19 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
index = TX_SEQ_TO_INDEX(seq);
ack_recd = false;
if (ba_recd) {
+ int block_acked;
+
bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
+ if (bindex < AMPDU_TX_BA_MAX_WSIZE)
+ block_acked = isset(bitmap, bindex);
+ else
+ block_acked = 0;
brcms_dbg_ht(wlc->hw->d11core,
"tid %d seq %d, start_seq %d, bindex %d set %d, index %d\n",
tid, seq, start_seq, bindex,
- isset(bitmap, bindex), index);
+ block_acked, index);
/* if acked then clear bit and free packet */
- if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
- && isset(bitmap, bindex)) {
+ if (block_acked) {
ini->txretry[index] = 0;
/*
diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c
index 87b9398b03fd..ba62bb2995d9 100644
--- a/drivers/net/wireless/cisco/airo.c
+++ b/drivers/net/wireless/cisco/airo.c
@@ -1115,7 +1115,8 @@ static int enable_MAC(struct airo_info *ai, int lock);
static void disable_MAC(struct airo_info *ai, int lock);
static void enable_interrupts(struct airo_info*);
static void disable_interrupts(struct airo_info*);
-static u16 issuecommand(struct airo_info*, Cmd *pCmd, Resp *pRsp);
+static u16 issuecommand(struct airo_info*, Cmd *pCmd, Resp *pRsp,
+ bool may_sleep);
static int bap_setup(struct airo_info*, u16 rid, u16 offset, int whichbap);
static int aux_bap_read(struct airo_info*, __le16 *pu16Dst, int bytelen,
int whichbap);
@@ -1130,8 +1131,10 @@ static int PC4500_writerid(struct airo_info*, u16 rid, const void
static int do_writerid(struct airo_info*, u16 rid, const void *rid_data,
int len, int dummy);
static u16 transmit_allocate(struct airo_info*, int lenPayload, int raw);
-static int transmit_802_3_packet(struct airo_info*, int len, char *pPacket);
-static int transmit_802_11_packet(struct airo_info*, int len, char *pPacket);
+static int transmit_802_3_packet(struct airo_info*, int len, char *pPacket,
+ bool may_sleep);
+static int transmit_802_11_packet(struct airo_info*, int len, char *pPacket,
+ bool may_sleep);
static int mpi_send_packet(struct net_device *dev);
static void mpi_unmap_card(struct pci_dev *pci);
@@ -1144,7 +1147,6 @@ static int airo_thread(void *data);
static void timer_func(struct net_device *dev);
static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev);
-static void airo_read_wireless_stats(struct airo_info *local);
#ifdef CISCO_EXT
static int readrids(struct net_device *dev, aironet_ioctl *comp);
static int writerids(struct net_device *dev, aironet_ioctl *comp);
@@ -1200,7 +1202,6 @@ struct airo_info {
#define JOB_MIC 5
#define JOB_EVENT 6
#define JOB_AUTOWEP 7
-#define JOB_WSTATS 8
#define JOB_SCAN_RESULTS 9
unsigned long jobs;
int (*bap_read)(struct airo_info*, __le16 *pu16Dst, int bytelen,
@@ -1755,7 +1756,7 @@ static int readBSSListRid(struct airo_info *ai, int first,
if (down_interruptible(&ai->sem))
return -ERESTARTSYS;
ai->list_bss_task = current;
- issuecommand(ai, &cmd, &rsp);
+ issuecommand(ai, &cmd, &rsp, true);
up(&ai->sem);
/* Let the command take effect */
schedule_timeout_uninterruptible(3 * HZ);
@@ -2098,7 +2099,7 @@ static void get_tx_error(struct airo_info *ai, s32 fid)
}
}
-static void airo_end_xmit(struct net_device *dev)
+static void airo_end_xmit(struct net_device *dev, bool may_sleep)
{
u16 status;
int i;
@@ -2109,7 +2110,7 @@ static void airo_end_xmit(struct net_device *dev)
clear_bit(JOB_XMIT, &priv->jobs);
clear_bit(FLAG_PENDING_XMIT, &priv->flags);
- status = transmit_802_3_packet (priv, fids[fid], skb->data);
+ status = transmit_802_3_packet(priv, fids[fid], skb->data, may_sleep);
up(&priv->sem);
i = 0;
@@ -2166,11 +2167,11 @@ static netdev_tx_t airo_start_xmit(struct sk_buff *skb,
set_bit(JOB_XMIT, &priv->jobs);
wake_up_interruptible(&priv->thr_wait);
} else
- airo_end_xmit(dev);
+ airo_end_xmit(dev, false);
return NETDEV_TX_OK;
}
-static void airo_end_xmit11(struct net_device *dev)
+static void airo_end_xmit11(struct net_device *dev, bool may_sleep)
{
u16 status;
int i;
@@ -2181,7 +2182,7 @@ static void airo_end_xmit11(struct net_device *dev)
clear_bit(JOB_XMIT11, &priv->jobs);
clear_bit(FLAG_PENDING_XMIT11, &priv->flags);
- status = transmit_802_11_packet (priv, fids[fid], skb->data);
+ status = transmit_802_11_packet(priv, fids[fid], skb->data, may_sleep);
up(&priv->sem);
i = MAX_FIDS / 2;
@@ -2245,7 +2246,7 @@ static netdev_tx_t airo_start_xmit11(struct sk_buff *skb,
set_bit(JOB_XMIT11, &priv->jobs);
wake_up_interruptible(&priv->thr_wait);
} else
- airo_end_xmit11(dev);
+ airo_end_xmit11(dev, false);
return NETDEV_TX_OK;
}
@@ -2288,18 +2289,14 @@ static struct net_device_stats *airo_get_stats(struct net_device *dev)
struct airo_info *local = dev->ml_priv;
if (!test_bit(JOB_STATS, &local->jobs)) {
- /* Get stats out of the card if available */
- if (down_trylock(&local->sem) != 0) {
- set_bit(JOB_STATS, &local->jobs);
- wake_up_interruptible(&local->thr_wait);
- } else
- airo_read_stats(dev);
+ set_bit(JOB_STATS, &local->jobs);
+ wake_up_interruptible(&local->thr_wait);
}
return &dev->stats;
}
-static void airo_set_promisc(struct airo_info *ai)
+static void airo_set_promisc(struct airo_info *ai, bool may_sleep)
{
Cmd cmd;
Resp rsp;
@@ -2308,7 +2305,7 @@ static void airo_set_promisc(struct airo_info *ai)
cmd.cmd = CMD_SETMODE;
clear_bit(JOB_PROMISC, &ai->jobs);
cmd.parm0=(ai->flags&IFF_PROMISC) ? PROMISC : NOPROMISC;
- issuecommand(ai, &cmd, &rsp);
+ issuecommand(ai, &cmd, &rsp, may_sleep);
up(&ai->sem);
}
@@ -2322,7 +2319,7 @@ static void airo_set_multicast_list(struct net_device *dev)
set_bit(JOB_PROMISC, &ai->jobs);
wake_up_interruptible(&ai->thr_wait);
} else
- airo_set_promisc(ai);
+ airo_set_promisc(ai, false);
}
if ((dev->flags&IFF_ALLMULTI) || !netdev_mc_empty(dev)) {
@@ -2482,7 +2479,7 @@ static int mpi_init_descriptors (struct airo_info *ai)
cmd.parm0 = FID_RX;
cmd.parm1 = (ai->rxfids[0].card_ram_off - ai->pciaux);
cmd.parm2 = MPI_MAX_FIDS;
- rc = issuecommand(ai, &cmd, &rsp);
+ rc = issuecommand(ai, &cmd, &rsp, true);
if (rc != SUCCESS) {
airo_print_err(ai->dev->name, "Couldn't allocate RX FID");
return rc;
@@ -2510,7 +2507,7 @@ static int mpi_init_descriptors (struct airo_info *ai)
}
ai->txfids[i-1].tx_desc.eoc = 1; /* Last descriptor has EOC set */
- rc = issuecommand(ai, &cmd, &rsp);
+ rc = issuecommand(ai, &cmd, &rsp, true);
if (rc != SUCCESS) {
airo_print_err(ai->dev->name, "Couldn't allocate TX FID");
return rc;
@@ -2524,7 +2521,7 @@ static int mpi_init_descriptors (struct airo_info *ai)
cmd.parm0 = RID_RW;
cmd.parm1 = (ai->config_desc.card_ram_off - ai->pciaux);
cmd.parm2 = 1; /* Magic number... */
- rc = issuecommand(ai, &cmd, &rsp);
+ rc = issuecommand(ai, &cmd, &rsp, true);
if (rc != SUCCESS) {
airo_print_err(ai->dev->name, "Couldn't allocate RID");
return rc;
@@ -3150,15 +3147,13 @@ static int airo_thread(void *data)
}
if (test_bit(JOB_XMIT, &ai->jobs))
- airo_end_xmit(dev);
+ airo_end_xmit(dev, true);
else if (test_bit(JOB_XMIT11, &ai->jobs))
- airo_end_xmit11(dev);
+ airo_end_xmit11(dev, true);
else if (test_bit(JOB_STATS, &ai->jobs))
airo_read_stats(dev);
- else if (test_bit(JOB_WSTATS, &ai->jobs))
- airo_read_wireless_stats(ai);
else if (test_bit(JOB_PROMISC, &ai->jobs))
- airo_set_promisc(ai);
+ airo_set_promisc(ai, true);
else if (test_bit(JOB_MIC, &ai->jobs))
micinit(ai);
else if (test_bit(JOB_EVENT, &ai->jobs))
@@ -3281,11 +3276,9 @@ static void airo_handle_link(struct airo_info *ai)
set_bit(FLAG_UPDATE_UNI, &ai->flags);
set_bit(FLAG_UPDATE_MULTI, &ai->flags);
- if (down_trylock(&ai->sem) != 0) {
- set_bit(JOB_EVENT, &ai->jobs);
- wake_up_interruptible(&ai->thr_wait);
- } else
- airo_send_event(ai->dev);
+ set_bit(JOB_EVENT, &ai->jobs);
+ wake_up_interruptible(&ai->thr_wait);
+
netif_carrier_on(ai->dev);
} else if (!scan_forceloss) {
if (auto_wep && !ai->expires) {
@@ -3609,7 +3602,7 @@ static int enable_MAC(struct airo_info *ai, int lock)
if (!test_bit(FLAG_ENABLED, &ai->flags)) {
memset(&cmd, 0, sizeof(cmd));
cmd.cmd = MAC_ENABLE;
- rc = issuecommand(ai, &cmd, &rsp);
+ rc = issuecommand(ai, &cmd, &rsp, true);
if (rc == SUCCESS)
set_bit(FLAG_ENABLED, &ai->flags);
} else
@@ -3641,7 +3634,7 @@ static void disable_MAC(struct airo_info *ai, int lock)
netif_carrier_off(ai->dev);
memset(&cmd, 0, sizeof(cmd));
cmd.cmd = MAC_DISABLE; // disable in case already enabled
- issuecommand(ai, &cmd, &rsp);
+ issuecommand(ai, &cmd, &rsp, true);
clear_bit(FLAG_ENABLED, &ai->flags);
}
if (lock == 1)
@@ -3844,7 +3837,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
cmd.parm0 = cmd.parm1 = cmd.parm2 = 0;
if (lock && down_interruptible(&ai->sem))
return ERROR;
- if (issuecommand(ai, &cmd, &rsp) != SUCCESS) {
+ if (issuecommand(ai, &cmd, &rsp, true) != SUCCESS) {
if (lock)
up(&ai->sem);
return ERROR;
@@ -3854,7 +3847,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
// Let's figure out if we need to use the AUX port
if (!test_bit(FLAG_MPI,&ai->flags)) {
cmd.cmd = CMD_ENABLEAUX;
- if (issuecommand(ai, &cmd, &rsp) != SUCCESS) {
+ if (issuecommand(ai, &cmd, &rsp, true) != SUCCESS) {
if (lock)
up(&ai->sem);
airo_print_err(ai->dev->name, "Error checking for AUX port");
@@ -3966,7 +3959,8 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
return SUCCESS;
}
-static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp)
+static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp,
+ bool may_sleep)
{
// Im really paranoid about letting it run forever!
int max_tries = 600000;
@@ -3983,8 +3977,8 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp)
if ((IN4500(ai, COMMAND)) == pCmd->cmd)
// PC4500 didn't notice command, try again
OUT4500(ai, COMMAND, pCmd->cmd);
- if (!in_atomic() && (max_tries & 255) == 0)
- schedule();
+ if (may_sleep && (max_tries & 255) == 0)
+ cond_resched();
}
if (max_tries == -1) {
@@ -4141,7 +4135,7 @@ static int PC4500_accessrid(struct airo_info *ai, u16 rid, u16 accmd)
memset(&cmd, 0, sizeof(cmd));
cmd.cmd = accmd;
cmd.parm0 = rid;
- status = issuecommand(ai, &cmd, &rsp);
+ status = issuecommand(ai, &cmd, &rsp, true);
if (status != 0) return status;
if ((rsp.status & 0x7F00) != 0) {
return (accmd << 8) + (rsp.rsp0 & 0xFF);
@@ -4177,7 +4171,7 @@ static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len, in
memcpy_toio(ai->config_desc.card_ram_off,
&ai->config_desc.rid_desc, sizeof(Rid));
- rc = issuecommand(ai, &cmd, &rsp);
+ rc = issuecommand(ai, &cmd, &rsp, true);
if (rsp.status & 0x7f00)
rc = rsp.rsp0;
@@ -4256,7 +4250,7 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
memcpy(ai->config_desc.virtual_host_addr,
pBuf, len);
- rc = issuecommand(ai, &cmd, &rsp);
+ rc = issuecommand(ai, &cmd, &rsp, true);
if ((rc & 0xff00) != 0) {
airo_print_err(ai->dev->name, "%s: Write rid Error %d",
__func__, rc);
@@ -4302,7 +4296,7 @@ static u16 transmit_allocate(struct airo_info *ai, int lenPayload, int raw)
cmd.parm0 = lenPayload;
if (down_interruptible(&ai->sem))
return ERROR;
- if (issuecommand(ai, &cmd, &rsp) != SUCCESS) {
+ if (issuecommand(ai, &cmd, &rsp, true) != SUCCESS) {
txFid = ERROR;
goto done;
}
@@ -4348,7 +4342,8 @@ done:
/* In general BAP1 is dedicated to transmiting packets. However,
since we need a BAP when accessing RIDs, we also use BAP1 for that.
Make sure the BAP1 spinlock is held when this is called. */
-static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket)
+static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket,
+ bool may_sleep)
{
__le16 payloadLen;
Cmd cmd;
@@ -4386,12 +4381,14 @@ static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket)
memset(&cmd, 0, sizeof(cmd));
cmd.cmd = CMD_TRANSMIT;
cmd.parm0 = txFid;
- if (issuecommand(ai, &cmd, &rsp) != SUCCESS) return ERROR;
+ if (issuecommand(ai, &cmd, &rsp, may_sleep) != SUCCESS)
+ return ERROR;
if ((rsp.status & 0xFF00) != 0) return ERROR;
return SUCCESS;
}
-static int transmit_802_11_packet(struct airo_info *ai, int len, char *pPacket)
+static int transmit_802_11_packet(struct airo_info *ai, int len, char *pPacket,
+ bool may_sleep)
{
__le16 fc, payloadLen;
Cmd cmd;
@@ -4426,7 +4423,8 @@ static int transmit_802_11_packet(struct airo_info *ai, int len, char *pPacket)
memset(&cmd, 0, sizeof(cmd));
cmd.cmd = CMD_TRANSMIT;
cmd.parm0 = txFid;
- if (issuecommand(ai, &cmd, &rsp) != SUCCESS) return ERROR;
+ if (issuecommand(ai, &cmd, &rsp, may_sleep) != SUCCESS)
+ return ERROR;
if ((rsp.status & 0xFF00) != 0) return ERROR;
return SUCCESS;
}
@@ -5490,7 +5488,7 @@ static int proc_BSSList_open(struct inode *inode, struct file *file)
kfree(file->private_data);
return -ERESTARTSYS;
}
- issuecommand(ai, &cmd, &rsp);
+ issuecommand(ai, &cmd, &rsp, true);
up(&ai->sem);
data->readlen = 0;
return 0;
@@ -5627,7 +5625,7 @@ static int __maybe_unused airo_pci_suspend(struct device *dev_d)
netif_device_detach(dev);
ai->power = PMSG_SUSPEND;
cmd.cmd = HOSTSLEEP;
- issuecommand(ai, &cmd, &rsp);
+ issuecommand(ai, &cmd, &rsp, true);
device_wakeup_enable(dev_d);
return 0;
@@ -5787,7 +5785,7 @@ static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid)
}
#define airo_get_max_quality(cap_rid) (memcmp((cap_rid)->prodName, "350", 3) ? 0x20 : 0xa0)
-#define airo_get_avg_quality(cap_rid) (memcmp((cap_rid)->prodName, "350", 3) ? 0x10 : 0x50);
+#define airo_get_avg_quality(cap_rid) (memcmp((cap_rid)->prodName, "350", 3) ? 0x10 : 0x50)
/*------------------------------------------------------------------*/
/*
@@ -5970,7 +5968,7 @@ static int airo_set_wap(struct net_device *dev,
cmd.cmd = CMD_LOSE_SYNC;
if (down_interruptible(&local->sem))
return -ERESTARTSYS;
- issuecommand(local, &cmd, &rsp);
+ issuecommand(local, &cmd, &rsp, true);
up(&local->sem);
} else {
memset(APList_rid, 0, sizeof(*APList_rid));
@@ -7268,7 +7266,7 @@ static int airo_set_scan(struct net_device *dev,
ai->scan_timeout = RUN_AT(3*HZ);
memset(&cmd, 0, sizeof(cmd));
cmd.cmd = CMD_LISTBSS;
- issuecommand(ai, &cmd, &rsp);
+ issuecommand(ai, &cmd, &rsp, true);
wake = 1;
out:
@@ -7535,7 +7533,7 @@ static int airo_config_commit(struct net_device *dev,
writeConfigRid(local, 0);
enable_MAC(local, 0);
if (test_bit (FLAG_RESET, &local->flags))
- airo_set_promisc(local);
+ airo_set_promisc(local, true);
else
up(&local->sem);
@@ -7732,15 +7730,12 @@ static void airo_read_wireless_stats(struct airo_info *local)
__le32 *vals = stats_rid.vals;
/* Get stats out of the card */
- clear_bit(JOB_WSTATS, &local->jobs);
- if (local->power.event) {
- up(&local->sem);
+ if (local->power.event)
return;
- }
+
readCapabilityRid(local, &cap_rid, 0);
readStatusRid(local, &status_rid, 0);
readStatsRid(local, &stats_rid, RID_STATS, 0);
- up(&local->sem);
/* The status */
local->wstats.status = le16_to_cpu(status_rid.mode);
@@ -7783,15 +7778,10 @@ static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
{
struct airo_info *local = dev->ml_priv;
- if (!test_bit(JOB_WSTATS, &local->jobs)) {
- /* Get stats out of the card if available */
- if (down_trylock(&local->sem) != 0) {
- set_bit(JOB_WSTATS, &local->jobs);
- wake_up_interruptible(&local->thr_wait);
- } else
- airo_read_wireless_stats(local);
+ if (!down_interruptible(&local->sem)) {
+ airo_read_wireless_stats(local);
+ up(&local->sem);
}
-
return &local->wstats;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index cbdebefb854a..8698ca4d30de 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -1202,13 +1202,11 @@ static int iwl_mvm_mac_ctx_send(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return iwl_mvm_mac_ctxt_cmd_sta(mvm, vif, action,
force_assoc_off,
bssid_override);
- break;
case NL80211_IFTYPE_AP:
if (!vif->p2p)
return iwl_mvm_mac_ctxt_cmd_ap(mvm, vif, action);
else
return iwl_mvm_mac_ctxt_cmd_go(mvm, vif, action);
- break;
case NL80211_IFTYPE_MONITOR:
return iwl_mvm_mac_ctxt_cmd_listener(mvm, vif, action);
case NL80211_IFTYPE_P2P_DEVICE:
diff --git a/drivers/net/wireless/intersil/hostap/hostap_hw.c b/drivers/net/wireless/intersil/hostap/hostap_hw.c
index 22cfb6452644..9a19046217df 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_hw.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_hw.c
@@ -3169,22 +3169,15 @@ prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx,
/* Initialize tasklets for handling hardware IRQ related operations
* outside hw IRQ handler */
-#define HOSTAP_TASKLET_INIT(q, f, d) \
-do { memset((q), 0, sizeof(*(q))); (q)->func = (void(*)(unsigned long))(f); } \
-while (0)
- HOSTAP_TASKLET_INIT(&local->bap_tasklet, hostap_bap_tasklet,
- (unsigned long) local);
-
- HOSTAP_TASKLET_INIT(&local->info_tasklet, hostap_info_tasklet,
- (unsigned long) local);
+ tasklet_setup(&local->bap_tasklet, hostap_bap_tasklet);
+ tasklet_setup(&local->info_tasklet, hostap_info_tasklet);
hostap_info_init(local);
- HOSTAP_TASKLET_INIT(&local->rx_tasklet,
- hostap_rx_tasklet, (unsigned long) local);
+ tasklet_setup(&local->rx_tasklet, hostap_rx_tasklet);
skb_queue_head_init(&local->rx_list);
- HOSTAP_TASKLET_INIT(&local->sta_tx_exc_tasklet,
- hostap_sta_tx_exc_tasklet, (unsigned long) local);
+ tasklet_setup(&local->sta_tx_exc_tasklet,
+ hostap_sta_tx_exc_tasklet);
skb_queue_head_init(&local->sta_tx_exc_list);
INIT_LIST_HEAD(&local->cmd_queue);
diff --git a/drivers/net/wireless/intersil/hostap/hostap_ioctl.c b/drivers/net/wireless/intersil/hostap/hostap_ioctl.c
index 514c7b01dbf6..49766b285230 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_ioctl.c
@@ -44,19 +44,8 @@ static struct iw_statistics *hostap_get_wireless_stats(struct net_device *dev)
if (local->iw_mode != IW_MODE_MASTER &&
local->iw_mode != IW_MODE_REPEAT) {
- int update = 1;
-#ifdef in_atomic
- /* RID reading might sleep and it must not be called in
- * interrupt context or while atomic. However, this
- * function seems to be called while atomic (at least in Linux
- * 2.5.59). Update signal quality values only if in suitable
- * context. Otherwise, previous values read from tick timer
- * will be used. */
- if (in_atomic())
- update = 0;
-#endif /* in_atomic */
-
- if (update && prism2_update_comms_qual(dev) == 0)
+
+ if (prism2_update_comms_qual(dev) == 0)
wstats->qual.updated = IW_QUAL_ALL_UPDATED |
IW_QUAL_DBM;
diff --git a/drivers/net/wireless/intersil/orinoco/hermes.c b/drivers/net/wireless/intersil/orinoco/hermes.c
index 43790fbea0e0..6d4b7f64efcf 100644
--- a/drivers/net/wireless/intersil/orinoco/hermes.c
+++ b/drivers/net/wireless/intersil/orinoco/hermes.c
@@ -763,6 +763,7 @@ static const struct hermes_ops hermes_ops_local = {
.init_cmd_wait = hermes_doicmd_wait,
.allocate = hermes_allocate,
.read_ltv = hermes_read_ltv,
+ .read_ltv_pr = hermes_read_ltv,
.write_ltv = hermes_write_ltv,
.bap_pread = hermes_bap_pread,
.bap_pwrite = hermes_bap_pwrite,
diff --git a/drivers/net/wireless/intersil/orinoco/hermes.h b/drivers/net/wireless/intersil/orinoco/hermes.h
index 9f668185b7d2..3dc561a5cb7a 100644
--- a/drivers/net/wireless/intersil/orinoco/hermes.h
+++ b/drivers/net/wireless/intersil/orinoco/hermes.h
@@ -386,6 +386,8 @@ struct hermes_ops {
int (*allocate)(struct hermes *hw, u16 size, u16 *fid);
int (*read_ltv)(struct hermes *hw, int bap, u16 rid, unsigned buflen,
u16 *length, void *buf);
+ int (*read_ltv_pr)(struct hermes *hw, int bap, u16 rid,
+ unsigned buflen, u16 *length, void *buf);
int (*write_ltv)(struct hermes *hw, int bap, u16 rid,
u16 length, const void *value);
int (*bap_pread)(struct hermes *hw, int bap, void *buf, int len,
@@ -494,6 +496,8 @@ static inline void hermes_clear_words(struct hermes *hw, int off,
#define HERMES_READ_RECORD(hw, bap, rid, buf) \
(hw->ops->read_ltv((hw), (bap), (rid), sizeof(*buf), NULL, (buf)))
+#define HERMES_READ_RECORD_PR(hw, bap, rid, buf) \
+ (hw->ops->read_ltv_pr((hw), (bap), (rid), sizeof(*buf), NULL, (buf)))
#define HERMES_WRITE_RECORD(hw, bap, rid, buf) \
(hw->ops->write_ltv((hw), (bap), (rid), \
HERMES_BYTES_TO_RECLEN(sizeof(*buf)), (buf)))
@@ -509,6 +513,17 @@ static inline int hermes_read_wordrec(struct hermes *hw, int bap, u16 rid,
return err;
}
+static inline int hermes_read_wordrec_pr(struct hermes *hw, int bap, u16 rid,
+ u16 *word)
+{
+ __le16 rec;
+ int err;
+
+ err = HERMES_READ_RECORD_PR(hw, bap, rid, &rec);
+ *word = le16_to_cpu(rec);
+ return err;
+}
+
static inline int hermes_write_wordrec(struct hermes *hw, int bap, u16 rid,
u16 word)
{
diff --git a/drivers/net/wireless/intersil/orinoco/hw.c b/drivers/net/wireless/intersil/orinoco/hw.c
index 61af5a28f269..2c7adb4be100 100644
--- a/drivers/net/wireless/intersil/orinoco/hw.c
+++ b/drivers/net/wireless/intersil/orinoco/hw.c
@@ -78,7 +78,7 @@ int determine_fw_capabilities(struct orinoco_private *priv,
char tmp[SYMBOL_MAX_VER_LEN + 1] __attribute__((aligned(2)));
/* Get the hardware version */
- err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_NICID, &nic_id);
+ err = HERMES_READ_RECORD_PR(hw, USER_BAP, HERMES_RID_NICID, &nic_id);
if (err) {
dev_err(dev, "Cannot read hardware identity: error %d\n",
err);
@@ -101,7 +101,7 @@ int determine_fw_capabilities(struct orinoco_private *priv,
priv->firmware_type = determine_firmware_type(&nic_id);
/* Get the firmware version */
- err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_STAID, &sta_id);
+ err = HERMES_READ_RECORD_PR(hw, USER_BAP, HERMES_RID_STAID, &sta_id);
if (err) {
dev_err(dev, "Cannot read station identity: error %d\n",
err);
@@ -177,7 +177,7 @@ int determine_fw_capabilities(struct orinoco_private *priv,
/* 3Com MAC : 00:50:DA:* */
memset(tmp, 0, sizeof(tmp));
/* Get the Symbol firmware version */
- err = hw->ops->read_ltv(hw, USER_BAP,
+ err = hw->ops->read_ltv_pr(hw, USER_BAP,
HERMES_RID_SECONDARYVERSION_SYMBOL,
SYMBOL_MAX_VER_LEN, NULL, &tmp);
if (err) {
@@ -286,7 +286,7 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
u16 reclen;
/* Get the MAC address */
- err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
+ err = hw->ops->read_ltv_pr(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
ETH_ALEN, NULL, dev_addr);
if (err) {
dev_warn(dev, "Failed to read MAC address!\n");
@@ -296,7 +296,7 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
dev_dbg(dev, "MAC address %pM\n", dev_addr);
/* Get the station name */
- err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
+ err = hw->ops->read_ltv_pr(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
sizeof(nickbuf), &reclen, &nickbuf);
if (err) {
dev_err(dev, "failed to read station name\n");
@@ -312,7 +312,7 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
dev_dbg(dev, "Station name \"%s\"\n", priv->nick);
/* Get allowed channels */
- err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CHANNELLIST,
+ err = hermes_read_wordrec_pr(hw, USER_BAP, HERMES_RID_CHANNELLIST,
&priv->channel_mask);
if (err) {
dev_err(dev, "Failed to read channel list!\n");
@@ -320,13 +320,13 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
}
/* Get initial AP density */
- err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE,
+ err = hermes_read_wordrec_pr(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE,
&priv->ap_density);
if (err || priv->ap_density < 1 || priv->ap_density > 3)
priv->has_sensitivity = 0;
/* Get initial RTS threshold */
- err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
+ err = hermes_read_wordrec_pr(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
&priv->rts_thresh);
if (err) {
dev_err(dev, "Failed to read RTS threshold!\n");
@@ -335,11 +335,11 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
/* Get initial fragmentation settings */
if (priv->has_mwo)
- err = hermes_read_wordrec(hw, USER_BAP,
+ err = hermes_read_wordrec_pr(hw, USER_BAP,
HERMES_RID_CNFMWOROBUST_AGERE,
&priv->mwo_robust);
else
- err = hermes_read_wordrec(hw, USER_BAP,
+ err = hermes_read_wordrec_pr(hw, USER_BAP,
HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
&priv->frag_thresh);
if (err) {
@@ -351,7 +351,7 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
if (priv->has_pm) {
priv->pm_on = 0;
priv->pm_mcast = 1;
- err = hermes_read_wordrec(hw, USER_BAP,
+ err = hermes_read_wordrec_pr(hw, USER_BAP,
HERMES_RID_CNFMAXSLEEPDURATION,
&priv->pm_period);
if (err) {
@@ -359,7 +359,7 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
"period!\n");
goto out;
}
- err = hermes_read_wordrec(hw, USER_BAP,
+ err = hermes_read_wordrec_pr(hw, USER_BAP,
HERMES_RID_CNFPMHOLDOVERDURATION,
&priv->pm_timeout);
if (err) {
@@ -371,7 +371,7 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
/* Preamble setup */
if (priv->has_preamble) {
- err = hermes_read_wordrec(hw, USER_BAP,
+ err = hermes_read_wordrec_pr(hw, USER_BAP,
HERMES_RID_CNFPREAMBLE_SYMBOL,
&priv->preamble);
if (err) {
@@ -381,21 +381,21 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
}
/* Retry settings */
- err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT,
+ err = hermes_read_wordrec_pr(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT,
&priv->short_retry_limit);
if (err) {
dev_err(dev, "Failed to read short retry limit\n");
goto out;
}
- err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT,
+ err = hermes_read_wordrec_pr(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT,
&priv->long_retry_limit);
if (err) {
dev_err(dev, "Failed to read long retry limit\n");
goto out;
}
- err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME,
+ err = hermes_read_wordrec_pr(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME,
&priv->retry_lifetime);
if (err) {
dev_err(dev, "Failed to read max retry lifetime\n");
diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
index b849d27bd741..dd31929261ab 100644
--- a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
+++ b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
@@ -665,26 +665,43 @@ static void ezusb_request_in_callback(struct ezusb_priv *upriv,
} /* switch */
}
+typedef void (*ezusb_ctx_wait)(struct ezusb_priv *, struct request_context *);
-static void ezusb_req_ctx_wait(struct ezusb_priv *upriv,
- struct request_context *ctx)
+static void ezusb_req_ctx_wait_compl(struct ezusb_priv *upriv,
+ struct request_context *ctx)
{
switch (ctx->state) {
case EZUSB_CTX_QUEUED:
case EZUSB_CTX_REQ_SUBMITTED:
case EZUSB_CTX_REQ_COMPLETE:
case EZUSB_CTX_RESP_RECEIVED:
- if (in_softirq()) {
- /* If we get called from a timer, timeout timers don't
- * get the chance to run themselves. So we make sure
- * that we don't sleep for ever */
- int msecs = DEF_TIMEOUT * (1000 / HZ);
-
- while (!try_wait_for_completion(&ctx->done) && msecs--)
- udelay(1000);
- } else {
- wait_for_completion(&ctx->done);
- }
+ wait_for_completion(&ctx->done);
+ break;
+ default:
+ /* Done or failed - nothing to wait for */
+ break;
+ }
+}
+
+static void ezusb_req_ctx_wait_poll(struct ezusb_priv *upriv,
+ struct request_context *ctx)
+{
+ int msecs;
+
+ switch (ctx->state) {
+ case EZUSB_CTX_QUEUED:
+ case EZUSB_CTX_REQ_SUBMITTED:
+ case EZUSB_CTX_REQ_COMPLETE:
+ case EZUSB_CTX_RESP_RECEIVED:
+ /* If we get called from a timer or with our lock acquired, then
+ * we can't wait for the completion and have to poll. This won't
+ * happen if the USB controller completes the URB requests in
+ * BH.
+ */
+ msecs = DEF_TIMEOUT * (1000 / HZ);
+
+ while (!try_wait_for_completion(&ctx->done) && msecs--)
+ udelay(1000);
break;
default:
/* Done or failed - nothing to wait for */
@@ -692,6 +709,12 @@ static void ezusb_req_ctx_wait(struct ezusb_priv *upriv,
}
}
+static void ezusb_req_ctx_wait_skip(struct ezusb_priv *upriv,
+ struct request_context *ctx)
+{
+ WARN(1, "Shouldn't be invoked for in_rid\n");
+}
+
static inline u16 build_crc(struct ezusb_packet *data)
{
u16 crc = 0;
@@ -853,14 +876,13 @@ static int ezusb_firmware_download(struct ezusb_priv *upriv,
static int ezusb_access_ltv(struct ezusb_priv *upriv,
struct request_context *ctx,
u16 length, const void *data, u16 frame_type,
- void *ans_buff, unsigned ans_size, u16 *ans_length)
+ void *ans_buff, unsigned ans_size, u16 *ans_length,
+ ezusb_ctx_wait ezusb_ctx_wait_func)
{
int req_size;
int retval = 0;
enum ezusb_state state;
- BUG_ON(in_irq());
-
if (!upriv->udev) {
retval = -ENODEV;
goto exit;
@@ -885,7 +907,7 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv,
spin_unlock_bh(&upriv->reply_count_lock);
if (ctx->in_rid)
- ezusb_req_ctx_wait(upriv, ctx);
+ ezusb_ctx_wait_func(upriv, ctx);
state = ctx->state;
switch (state) {
@@ -946,8 +968,9 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv,
return retval;
}
-static int ezusb_write_ltv(struct hermes *hw, int bap, u16 rid,
- u16 length, const void *data)
+static int __ezusb_write_ltv(struct hermes *hw, int bap, u16 rid,
+ u16 length, const void *data,
+ ezusb_ctx_wait ezusb_ctx_wait_func)
{
struct ezusb_priv *upriv = hw->priv;
u16 frame_type;
@@ -973,11 +996,20 @@ static int ezusb_write_ltv(struct hermes *hw, int bap, u16 rid,
frame_type = EZUSB_FRAME_CONTROL;
return ezusb_access_ltv(upriv, ctx, length, data, frame_type,
- NULL, 0, NULL);
+ NULL, 0, NULL, ezusb_ctx_wait_func);
}
-static int ezusb_read_ltv(struct hermes *hw, int bap, u16 rid,
- unsigned bufsize, u16 *length, void *buf)
+static int ezusb_write_ltv(struct hermes *hw, int bap, u16 rid,
+ u16 length, const void *data)
+{
+ return __ezusb_write_ltv(hw, bap, rid, length, data,
+ ezusb_req_ctx_wait_poll);
+}
+
+static int __ezusb_read_ltv(struct hermes *hw, int bap, u16 rid,
+ unsigned bufsize, u16 *length, void *buf,
+ ezusb_ctx_wait ezusb_ctx_wait_func)
+
{
struct ezusb_priv *upriv = hw->priv;
struct request_context *ctx;
@@ -990,34 +1022,33 @@ static int ezusb_read_ltv(struct hermes *hw, int bap, u16 rid,
return -ENOMEM;
return ezusb_access_ltv(upriv, ctx, 0, NULL, EZUSB_FRAME_CONTROL,
- buf, bufsize, length);
+ buf, bufsize, length, ezusb_req_ctx_wait_poll);
}
-static int ezusb_doicmd_wait(struct hermes *hw, u16 cmd, u16 parm0, u16 parm1,
- u16 parm2, struct hermes_response *resp)
+static int ezusb_read_ltv(struct hermes *hw, int bap, u16 rid,
+ unsigned bufsize, u16 *length, void *buf)
{
- struct ezusb_priv *upriv = hw->priv;
- struct request_context *ctx;
+ return __ezusb_read_ltv(hw, bap, rid, bufsize, length, buf,
+ ezusb_req_ctx_wait_poll);
+}
- __le16 data[4] = {
- cpu_to_le16(cmd),
- cpu_to_le16(parm0),
- cpu_to_le16(parm1),
- cpu_to_le16(parm2),
- };
- netdev_dbg(upriv->dev,
- "0x%04X, parm0 0x%04X, parm1 0x%04X, parm2 0x%04X\n", cmd,
- parm0, parm1, parm2);
- ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_DOCMD, EZUSB_RID_ACK);
- if (!ctx)
- return -ENOMEM;
+static int ezusb_read_ltv_preempt(struct hermes *hw, int bap, u16 rid,
+ unsigned bufsize, u16 *length, void *buf)
+{
+ return __ezusb_read_ltv(hw, bap, rid, bufsize, length, buf,
+ ezusb_req_ctx_wait_compl);
+}
- return ezusb_access_ltv(upriv, ctx, sizeof(data), &data,
- EZUSB_FRAME_CONTROL, NULL, 0, NULL);
+static int ezusb_doicmd_wait(struct hermes *hw, u16 cmd, u16 parm0, u16 parm1,
+ u16 parm2, struct hermes_response *resp)
+{
+ WARN_ON_ONCE(1);
+ return -EINVAL;
}
-static int ezusb_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0,
- struct hermes_response *resp)
+static int __ezusb_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0,
+ struct hermes_response *resp,
+ ezusb_ctx_wait ezusb_ctx_wait_func)
{
struct ezusb_priv *upriv = hw->priv;
struct request_context *ctx;
@@ -1034,7 +1065,14 @@ static int ezusb_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0,
return -ENOMEM;
return ezusb_access_ltv(upriv, ctx, sizeof(data), &data,
- EZUSB_FRAME_CONTROL, NULL, 0, NULL);
+ EZUSB_FRAME_CONTROL, NULL, 0, NULL,
+ ezusb_ctx_wait_func);
+}
+
+static int ezusb_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0,
+ struct hermes_response *resp)
+{
+ return __ezusb_docmd_wait(hw, cmd, parm0, resp, ezusb_req_ctx_wait_poll);
}
static int ezusb_bap_pread(struct hermes *hw, int bap,
@@ -1092,7 +1130,7 @@ static int ezusb_read_pda(struct hermes *hw, __le16 *pda,
return ezusb_access_ltv(upriv, ctx, sizeof(data), &data,
EZUSB_FRAME_CONTROL, &pda[2], pda_len - 4,
- NULL);
+ NULL, ezusb_req_ctx_wait_compl);
}
static int ezusb_program_init(struct hermes *hw, u32 entry_point)
@@ -1106,7 +1144,8 @@ static int ezusb_program_init(struct hermes *hw, u32 entry_point)
return -ENOMEM;
return ezusb_access_ltv(upriv, ctx, sizeof(data), &data,
- EZUSB_FRAME_CONTROL, NULL, 0, NULL);
+ EZUSB_FRAME_CONTROL, NULL, 0, NULL,
+ ezusb_req_ctx_wait_compl);
}
static int ezusb_program_end(struct hermes *hw)
@@ -1119,7 +1158,8 @@ static int ezusb_program_end(struct hermes *hw)
return -ENOMEM;
return ezusb_access_ltv(upriv, ctx, 0, NULL,
- EZUSB_FRAME_CONTROL, NULL, 0, NULL);
+ EZUSB_FRAME_CONTROL, NULL, 0, NULL,
+ ezusb_req_ctx_wait_compl);
}
static int ezusb_program_bytes(struct hermes *hw, const char *buf,
@@ -1135,7 +1175,8 @@ static int ezusb_program_bytes(struct hermes *hw, const char *buf,
return -ENOMEM;
err = ezusb_access_ltv(upriv, ctx, sizeof(data), &data,
- EZUSB_FRAME_CONTROL, NULL, 0, NULL);
+ EZUSB_FRAME_CONTROL, NULL, 0, NULL,
+ ezusb_req_ctx_wait_compl);
if (err)
return err;
@@ -1144,7 +1185,8 @@ static int ezusb_program_bytes(struct hermes *hw, const char *buf,
return -ENOMEM;
return ezusb_access_ltv(upriv, ctx, len, buf,
- EZUSB_FRAME_CONTROL, NULL, 0, NULL);
+ EZUSB_FRAME_CONTROL, NULL, 0, NULL,
+ ezusb_req_ctx_wait_compl);
}
static int ezusb_program(struct hermes *hw, const char *buf,
@@ -1223,13 +1265,6 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb->len < ETH_HLEN)
goto drop;
- ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_TX, 0);
- if (!ctx)
- goto busy;
-
- memset(ctx->buf, 0, BULK_BUF_SIZE);
- buf = ctx->buf->data;
-
tx_control = 0;
err = orinoco_process_xmit_skb(skb, dev, priv, &tx_control,
@@ -1237,6 +1272,13 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev)
if (err)
goto drop;
+ ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_TX, 0);
+ if (!ctx)
+ goto drop;
+
+ memset(ctx->buf, 0, BULK_BUF_SIZE);
+ buf = ctx->buf->data;
+
{
__le16 *tx_cntl = (__le16 *)buf;
*tx_cntl = cpu_to_le16(tx_control);
@@ -1264,7 +1306,8 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev)
tx_size = ALIGN(buf - ctx->buf->data, 2);
err = ezusb_access_ltv(upriv, ctx, tx_size, NULL,
- EZUSB_FRAME_DATA, NULL, 0, NULL);
+ EZUSB_FRAME_DATA, NULL, 0, NULL,
+ ezusb_req_ctx_wait_skip);
if (err) {
netif_start_queue(dev);
@@ -1349,7 +1392,6 @@ static int ezusb_init(struct hermes *hw)
struct ezusb_priv *upriv = hw->priv;
int retval;
- BUG_ON(in_interrupt());
if (!upriv)
return -EINVAL;
@@ -1362,14 +1404,16 @@ static int ezusb_init(struct hermes *hw)
usb_kill_urb(upriv->read_urb);
ezusb_submit_in_urb(upriv);
- retval = ezusb_write_ltv(hw, 0, EZUSB_RID_INIT1,
- HERMES_BYTES_TO_RECLEN(2), "\x10\x00");
+ retval = __ezusb_write_ltv(hw, 0, EZUSB_RID_INIT1,
+ HERMES_BYTES_TO_RECLEN(2), "\x10\x00",
+ ezusb_req_ctx_wait_compl);
if (retval < 0) {
printk(KERN_ERR PFX "EZUSB_RID_INIT1 error %d\n", retval);
return retval;
}
- retval = ezusb_docmd_wait(hw, HERMES_CMD_INIT, 0, NULL);
+ retval = __ezusb_docmd_wait(hw, HERMES_CMD_INIT, 0, NULL,
+ ezusb_req_ctx_wait_compl);
if (retval < 0) {
printk(KERN_ERR PFX "HERMES_CMD_INIT error %d\n", retval);
return retval;
@@ -1448,7 +1492,6 @@ static inline void ezusb_delete(struct ezusb_priv *upriv)
struct list_head *tmp_item;
unsigned long flags;
- BUG_ON(in_interrupt());
BUG_ON(!upriv);
mutex_lock(&upriv->mtx);
@@ -1533,6 +1576,7 @@ static const struct hermes_ops ezusb_ops = {
.init_cmd_wait = ezusb_doicmd_wait,
.allocate = ezusb_allocate,
.read_ltv = ezusb_read_ltv,
+ .read_ltv_pr = ezusb_read_ltv_preempt,
.write_ltv = ezusb_write_ltv,
.bap_pread = ezusb_bap_pread,
.read_pda = ezusb_read_pda,
diff --git a/drivers/net/wireless/intersil/prism54/isl_ioctl.c b/drivers/net/wireless/intersil/prism54/isl_ioctl.c
index 2076f449b6e2..5e5ceafe098b 100644
--- a/drivers/net/wireless/intersil/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/intersil/prism54/isl_ioctl.c
@@ -54,7 +54,7 @@ static const unsigned char scan_rate_list[] = { 2, 4, 11, 22,
/**
* prism54_mib_mode_helper - MIB change mode helper function
- * @mib: the &struct islpci_mib object to modify
+ * @priv: the &struct islpci_private object to modify
* @iw_mode: new mode (%IW_MODE_*)
*
* This is a helper function, hence it does not lock. Make sure
@@ -114,14 +114,13 @@ prism54_mib_mode_helper(islpci_private *priv, u32 iw_mode)
return 0;
}
-/**
+/*
* prism54_mib_init - fill MIB cache with defaults
*
* this function initializes the struct given as @mib with defaults,
* of which many are retrieved from the global module parameter
* variables.
*/
-
void
prism54_mib_init(islpci_private *priv)
{
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index 9ba8a8f64976..ee52fb839ef7 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -1455,7 +1455,7 @@ static void mwifiex_uninit_sw(struct mwifiex_adapter *adapter)
}
/*
- * This function gets called during PCIe function level reset.
+ * This function can be used for shutting down the adapter SW.
*/
int mwifiex_shutdown_sw(struct mwifiex_adapter *adapter)
{
@@ -1471,6 +1471,8 @@ int mwifiex_shutdown_sw(struct mwifiex_adapter *adapter)
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
mwifiex_deauthenticate(priv, NULL);
+ mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
+
mwifiex_uninit_sw(adapter);
adapter->is_up = false;
@@ -1481,7 +1483,7 @@ int mwifiex_shutdown_sw(struct mwifiex_adapter *adapter)
}
EXPORT_SYMBOL_GPL(mwifiex_shutdown_sw);
-/* This function gets called during PCIe function level reset. Required
+/* This function can be used for reinitting the adapter SW. Required
* code is extracted from mwifiex_add_card()
*/
int
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 6a10ff0377a2..5f0a61b974ee 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -429,7 +429,6 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev)
struct mwifiex_private *priv;
const struct mwifiex_pcie_card_reg *reg;
u32 fw_status;
- int ret;
card = pci_get_drvdata(pdev);
@@ -441,7 +440,7 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev)
reg = card->pcie.reg;
if (reg)
- ret = mwifiex_read_reg(adapter, reg->fw_status, &fw_status);
+ mwifiex_read_reg(adapter, reg->fw_status, &fw_status);
else
fw_status = -1;
@@ -526,6 +525,8 @@ static void mwifiex_pcie_reset_prepare(struct pci_dev *pdev)
clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags);
clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags);
mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
+
+ card->pci_reset_ongoing = true;
}
/*
@@ -554,6 +555,8 @@ static void mwifiex_pcie_reset_done(struct pci_dev *pdev)
dev_err(&pdev->dev, "reinit failed: %d\n", ret);
else
mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
+
+ card->pci_reset_ongoing = false;
}
static const struct pci_error_handlers mwifiex_pcie_err_handler = {
@@ -3139,12 +3142,23 @@ static void mwifiex_cleanup_pcie(struct mwifiex_adapter *adapter)
struct pcie_service_card *card = adapter->card;
struct pci_dev *pdev = card->dev;
const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
- int ret;
u32 fw_status;
- cancel_work_sync(&card->work);
+ /* Perform the cancel_work_sync() only when we're not resetting
+ * the card. It's because that function never returns if we're
+ * in reset path. If we're here when resetting the card, it means
+ * that we failed to reset the card (reset failure path).
+ */
+ if (!card->pci_reset_ongoing) {
+ mwifiex_dbg(adapter, MSG, "performing cancel_work_sync()...\n");
+ cancel_work_sync(&card->work);
+ mwifiex_dbg(adapter, MSG, "cancel_work_sync() done\n");
+ } else {
+ mwifiex_dbg(adapter, MSG,
+ "skipped cancel_work_sync() because we're in card reset failure path\n");
+ }
- ret = mwifiex_read_reg(adapter, reg->fw_status, &fw_status);
+ mwifiex_read_reg(adapter, reg->fw_status, &fw_status);
if (fw_status == FIRMWARE_READY_PCIE) {
mwifiex_dbg(adapter, INFO,
"Clearing driver ready signature\n");
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h
index 843d57eda820..5ed613d65709 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.h
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.h
@@ -242,6 +242,8 @@ struct pcie_service_card {
struct mwifiex_msix_context share_irq_ctx;
struct work_struct work;
unsigned long work_flags;
+
+ bool pci_reset_ongoing;
};
static inline int
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.h b/drivers/net/wireless/marvell/mwifiex/sdio.h
index dec534a6ddb1..5648512c9300 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.h
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.h
@@ -43,8 +43,6 @@
#define BLOCK_MODE 1
#define BYTE_MODE 0
-#define REG_PORT 0
-
#define MWIFIEX_SDIO_IO_PORT_MASK 0xfffff
#define MWIFIEX_SDIO_BYTE_MODE_MASK 0x80000000
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
index 119ccacd1fcc..6b5d35d9e69f 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
@@ -201,6 +201,7 @@ static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,
mwifiex_dbg(priv->adapter, INFO,
"info: SNMP_RESP: DTIM period=%u\n",
ul_temp);
+ break;
default:
break;
}
@@ -1393,6 +1394,7 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
break;
case HostCmd_CMD_TDLS_OPER:
ret = mwifiex_ret_tdls_oper(priv, resp);
+ break;
case HostCmd_CMD_MC_POLICY:
break;
case HostCmd_CMD_CHAN_REPORT_REQUEST:
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c
index bc79ca4cb803..68c63268e2e6 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_event.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c
@@ -99,6 +99,7 @@ static int mwifiex_check_ibss_peer_capabilities(struct mwifiex_private *priv,
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895:
sta_ptr->max_amsdu =
MWIFIEX_TX_DATA_BUF_SIZE_4K;
+ break;
default:
break;
}
diff --git a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
index b48a85d791f6..18e89777b784 100644
--- a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
+++ b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
@@ -108,6 +108,7 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv,
if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
bss_config->wpa_cfg.pairwise_cipher_wpa2 |=
CIPHER_AES_CCMP;
+ break;
default:
break;
}
diff --git a/drivers/net/wireless/marvell/mwifiex/wmm.c b/drivers/net/wireless/marvell/mwifiex/wmm.c
index b8f19ca73414..0b375608df7d 100644
--- a/drivers/net/wireless/marvell/mwifiex/wmm.c
+++ b/drivers/net/wireless/marvell/mwifiex/wmm.c
@@ -1396,6 +1396,7 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
break;
case 0:
mwifiex_write_data_complete(adapter, skb, 0, ret);
+ break;
default:
break;
}
diff --git a/drivers/net/wireless/mediatek/mt7601u/dma.c b/drivers/net/wireless/mediatek/mt7601u/dma.c
index 09f931d4598c..5f99054f535b 100644
--- a/drivers/net/wireless/mediatek/mt7601u/dma.c
+++ b/drivers/net/wireless/mediatek/mt7601u/dma.c
@@ -212,9 +212,9 @@ out:
spin_unlock_irqrestore(&dev->rx_lock, flags);
}
-static void mt7601u_rx_tasklet(unsigned long data)
+static void mt7601u_rx_tasklet(struct tasklet_struct *t)
{
- struct mt7601u_dev *dev = (struct mt7601u_dev *) data;
+ struct mt7601u_dev *dev = from_tasklet(dev, t, rx_tasklet);
struct mt7601u_dma_buf_rx *e;
while ((e = mt7601u_rx_get_pending_entry(dev))) {
@@ -266,9 +266,9 @@ out:
spin_unlock_irqrestore(&dev->tx_lock, flags);
}
-static void mt7601u_tx_tasklet(unsigned long data)
+static void mt7601u_tx_tasklet(struct tasklet_struct *t)
{
- struct mt7601u_dev *dev = (struct mt7601u_dev *) data;
+ struct mt7601u_dev *dev = from_tasklet(dev, t, tx_tasklet);
struct sk_buff_head skbs;
unsigned long flags;
@@ -507,8 +507,8 @@ int mt7601u_dma_init(struct mt7601u_dev *dev)
{
int ret = -ENOMEM;
- tasklet_init(&dev->tx_tasklet, mt7601u_tx_tasklet, (unsigned long) dev);
- tasklet_init(&dev->rx_tasklet, mt7601u_rx_tasklet, (unsigned long) dev);
+ tasklet_setup(&dev->tx_tasklet, mt7601u_tx_tasklet);
+ tasklet_setup(&dev->rx_tasklet, mt7601u_rx_tasklet);
ret = mt7601u_alloc_tx(dev);
if (ret)
diff --git a/drivers/net/wireless/microchip/wilc1000/cfg80211.c b/drivers/net/wireless/microchip/wilc1000/cfg80211.c
index c1ac1d84790f..e3dd205cbbe5 100644
--- a/drivers/net/wireless/microchip/wilc1000/cfg80211.c
+++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.c
@@ -1709,7 +1709,7 @@ int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type,
{
struct wilc *wl;
struct wilc_vif *vif;
- int ret;
+ int ret, i;
wl = wilc_create_wiphy(dev);
if (!wl)
@@ -1725,7 +1725,10 @@ int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type,
wl->io_type = io_type;
wl->hif_func = ops;
wl->chip_ps_state = WILC_CHIP_WAKEDUP;
- INIT_LIST_HEAD(&wl->txq_head.list);
+
+ for (i = 0; i < NQUEUES; i++)
+ INIT_LIST_HEAD(&wl->txq[i].txq_head.list);
+
INIT_LIST_HEAD(&wl->rxq_head.list);
INIT_LIST_HEAD(&wl->vif_list);
diff --git a/drivers/net/wireless/microchip/wilc1000/hif.c b/drivers/net/wireless/microchip/wilc1000/hif.c
index d025a3093015..a133736a7821 100644
--- a/drivers/net/wireless/microchip/wilc1000/hif.c
+++ b/drivers/net/wireless/microchip/wilc1000/hif.c
@@ -1276,6 +1276,23 @@ int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr)
return result;
}
+int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr)
+{
+ struct wid wid;
+ int result;
+
+ wid.id = WID_MAC_ADDR;
+ wid.type = WID_STR;
+ wid.size = ETH_ALEN;
+ wid.val = mac_addr;
+
+ result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+ if (result)
+ netdev_err(vif->ndev, "Failed to get mac address\n");
+
+ return result;
+}
+
int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ies,
size_t ies_len)
{
diff --git a/drivers/net/wireless/microchip/wilc1000/hif.h b/drivers/net/wireless/microchip/wilc1000/hif.h
index db9179171f05..58811911213b 100644
--- a/drivers/net/wireless/microchip/wilc1000/hif.h
+++ b/drivers/net/wireless/microchip/wilc1000/hif.h
@@ -168,6 +168,7 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
u8 cipher_mode);
int wilc_set_pmkid_info(struct wilc_vif *vif, struct wilc_pmkid_attr *pmkid);
int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr);
+int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr);
int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ies,
size_t ies_len);
int wilc_disconnect(struct wilc_vif *vif);
diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.c b/drivers/net/wireless/microchip/wilc1000/netdev.c
index 20615c7ec168..2a1fbbdd6a4b 100644
--- a/drivers/net/wireless/microchip/wilc1000/netdev.c
+++ b/drivers/net/wireless/microchip/wilc1000/netdev.c
@@ -628,6 +628,43 @@ static struct net_device_stats *mac_stats(struct net_device *dev)
return &vif->netstats;
}
+static int wilc_set_mac_addr(struct net_device *dev, void *p)
+{
+ int result;
+ struct wilc_vif *vif = netdev_priv(dev);
+ struct wilc *wilc = vif->wilc;
+ struct sockaddr *addr = (struct sockaddr *)p;
+ unsigned char mac_addr[ETH_ALEN];
+ struct wilc_vif *tmp_vif;
+ int srcu_idx;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EINVAL;
+
+ srcu_idx = srcu_read_lock(&wilc->srcu);
+ list_for_each_entry_rcu(tmp_vif, &wilc->vif_list, list) {
+ wilc_get_mac_address(tmp_vif, mac_addr);
+ if (ether_addr_equal(addr->sa_data, mac_addr)) {
+ if (vif != tmp_vif) {
+ srcu_read_unlock(&wilc->srcu, srcu_idx);
+ return -EINVAL;
+ }
+ srcu_read_unlock(&wilc->srcu, srcu_idx);
+ return 0;
+ }
+ }
+ srcu_read_unlock(&wilc->srcu, srcu_idx);
+
+ result = wilc_set_mac_address(vif, (u8 *)addr->sa_data);
+ if (result)
+ return result;
+
+ ether_addr_copy(vif->bssid, addr->sa_data);
+ ether_addr_copy(vif->ndev->dev_addr, addr->sa_data);
+
+ return result;
+}
+
static void wilc_set_multicast_list(struct net_device *dev)
{
struct netdev_hw_addr *ha;
@@ -813,6 +850,7 @@ static const struct net_device_ops wilc_netdev_ops = {
.ndo_init = mac_init_fn,
.ndo_open = wilc_mac_open,
.ndo_stop = wilc_mac_close,
+ .ndo_set_mac_address = wilc_set_mac_addr,
.ndo_start_xmit = wilc_mac_xmit,
.ndo_get_stats = mac_stats,
.ndo_set_rx_mode = wilc_set_multicast_list,
diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.h b/drivers/net/wireless/microchip/wilc1000/netdev.h
index d0a006b68d08..86209b391a3d 100644
--- a/drivers/net/wireless/microchip/wilc1000/netdev.h
+++ b/drivers/net/wireless/microchip/wilc1000/netdev.h
@@ -197,6 +197,14 @@ struct wilc_vif {
struct cfg80211_bss *bss;
};
+struct wilc_tx_queue_status {
+ u8 buffer[AC_BUFFER_SIZE];
+ u16 end_index;
+ u16 cnt[NQUEUES];
+ u16 sum;
+ bool initialized;
+};
+
struct wilc {
struct wiphy *wiphy;
const struct wilc_hif_func *hif_func;
@@ -245,9 +253,10 @@ struct wilc {
u32 rx_buffer_offset;
u8 *tx_buffer;
- struct txq_entry_t txq_head;
+ struct txq_handle txq[NQUEUES];
int txq_entries;
+ struct wilc_tx_queue_status tx_q_limit;
struct rxq_entry_t rxq_head;
const struct firmware *firmware;
diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.c b/drivers/net/wireless/microchip/wilc1000/wlan.c
index 6a82fb2f283e..993ea7c03429 100644
--- a/drivers/net/wireless/microchip/wilc1000/wlan.c
+++ b/drivers/net/wireless/microchip/wilc1000/wlan.c
@@ -6,6 +6,7 @@
#include <linux/if_ether.h>
#include <linux/ip.h>
+#include <net/dsfield.h>
#include "cfg80211.h"
#include "wlan_cfg.h"
@@ -28,33 +29,34 @@ static inline void release_bus(struct wilc *wilc, enum bus_release release)
mutex_unlock(&wilc->hif_cs);
}
-static void wilc_wlan_txq_remove(struct wilc *wilc, struct txq_entry_t *tqe)
+static void wilc_wlan_txq_remove(struct wilc *wilc, u8 q_num,
+ struct txq_entry_t *tqe)
{
list_del(&tqe->list);
wilc->txq_entries -= 1;
+ wilc->txq[q_num].count--;
}
static struct txq_entry_t *
-wilc_wlan_txq_remove_from_head(struct net_device *dev)
+wilc_wlan_txq_remove_from_head(struct wilc *wilc, u8 q_num)
{
struct txq_entry_t *tqe = NULL;
unsigned long flags;
- struct wilc_vif *vif = netdev_priv(dev);
- struct wilc *wilc = vif->wilc;
spin_lock_irqsave(&wilc->txq_spinlock, flags);
- if (!list_empty(&wilc->txq_head.list)) {
- tqe = list_first_entry(&wilc->txq_head.list, struct txq_entry_t,
- list);
+ if (!list_empty(&wilc->txq[q_num].txq_head.list)) {
+ tqe = list_first_entry(&wilc->txq[q_num].txq_head.list,
+ struct txq_entry_t, list);
list_del(&tqe->list);
wilc->txq_entries -= 1;
+ wilc->txq[q_num].count--;
}
spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
return tqe;
}
-static void wilc_wlan_txq_add_to_tail(struct net_device *dev,
+static void wilc_wlan_txq_add_to_tail(struct net_device *dev, u8 q_num,
struct txq_entry_t *tqe)
{
unsigned long flags;
@@ -63,15 +65,16 @@ static void wilc_wlan_txq_add_to_tail(struct net_device *dev,
spin_lock_irqsave(&wilc->txq_spinlock, flags);
- list_add_tail(&tqe->list, &wilc->txq_head.list);
+ list_add_tail(&tqe->list, &wilc->txq[q_num].txq_head.list);
wilc->txq_entries += 1;
+ wilc->txq[q_num].count++;
spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
complete(&wilc->txq_event);
}
-static void wilc_wlan_txq_add_to_head(struct wilc_vif *vif,
+static void wilc_wlan_txq_add_to_head(struct wilc_vif *vif, u8 q_num,
struct txq_entry_t *tqe)
{
unsigned long flags;
@@ -81,8 +84,9 @@ static void wilc_wlan_txq_add_to_head(struct wilc_vif *vif,
spin_lock_irqsave(&wilc->txq_spinlock, flags);
- list_add(&tqe->list, &wilc->txq_head.list);
+ list_add(&tqe->list, &wilc->txq[q_num].txq_head.list);
wilc->txq_entries += 1;
+ wilc->txq[q_num].count++;
spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
mutex_unlock(&wilc->txq_add_to_head_cs);
@@ -212,7 +216,7 @@ static void wilc_wlan_txq_filter_dup_tcp_ack(struct net_device *dev)
tqe = f->pending_acks[i].txqe;
if (tqe) {
- wilc_wlan_txq_remove(wilc, tqe);
+ wilc_wlan_txq_remove(wilc, tqe->q_num, tqe);
tqe->status = 1;
if (tqe->tx_complete_func)
tqe->tx_complete_func(tqe->priv,
@@ -258,18 +262,148 @@ static int wilc_wlan_txq_add_cfg_pkt(struct wilc_vif *vif, u8 *buffer,
}
tqe = kmalloc(sizeof(*tqe), GFP_ATOMIC);
- if (!tqe)
+ if (!tqe) {
+ complete(&wilc->cfg_event);
return 0;
+ }
tqe->type = WILC_CFG_PKT;
tqe->buffer = buffer;
tqe->buffer_size = buffer_size;
tqe->tx_complete_func = NULL;
tqe->priv = NULL;
+ tqe->q_num = AC_VO_Q;
tqe->ack_idx = NOT_TCP_ACK;
tqe->vif = vif;
- wilc_wlan_txq_add_to_head(vif, tqe);
+ wilc_wlan_txq_add_to_head(vif, AC_VO_Q, tqe);
+
+ return 1;
+}
+
+static bool is_ac_q_limit(struct wilc *wl, u8 q_num)
+{
+ u8 factors[NQUEUES] = {1, 1, 1, 1};
+ u16 i;
+ unsigned long flags;
+ struct wilc_tx_queue_status *q = &wl->tx_q_limit;
+ u8 end_index;
+ u8 q_limit;
+ bool ret = false;
+
+ spin_lock_irqsave(&wl->txq_spinlock, flags);
+ if (!q->initialized) {
+ for (i = 0; i < AC_BUFFER_SIZE; i++)
+ q->buffer[i] = i % NQUEUES;
+
+ for (i = 0; i < NQUEUES; i++) {
+ q->cnt[i] = AC_BUFFER_SIZE * factors[i] / NQUEUES;
+ q->sum += q->cnt[i];
+ }
+ q->end_index = AC_BUFFER_SIZE - 1;
+ q->initialized = 1;
+ }
+
+ end_index = q->end_index;
+ q->cnt[q->buffer[end_index]] -= factors[q->buffer[end_index]];
+ q->cnt[q_num] += factors[q_num];
+ q->sum += (factors[q_num] - factors[q->buffer[end_index]]);
+
+ q->buffer[end_index] = q_num;
+ if (end_index > 0)
+ q->end_index--;
+ else
+ q->end_index = AC_BUFFER_SIZE - 1;
+
+ if (!q->sum)
+ q_limit = 1;
+ else
+ q_limit = (q->cnt[q_num] * FLOW_CONTROL_UPPER_THRESHOLD / q->sum) + 1;
+
+ if (wl->txq[q_num].count <= q_limit)
+ ret = true;
+
+ spin_unlock_irqrestore(&wl->txq_spinlock, flags);
+
+ return ret;
+}
+
+static inline u8 ac_classify(struct wilc *wilc, struct sk_buff *skb)
+{
+ u8 q_num = AC_BE_Q;
+ u8 dscp;
+
+ switch (skb->protocol) {
+ case htons(ETH_P_IP):
+ dscp = ipv4_get_dsfield(ip_hdr(skb)) & 0xfc;
+ break;
+ case htons(ETH_P_IPV6):
+ dscp = ipv6_get_dsfield(ipv6_hdr(skb)) & 0xfc;
+ break;
+ default:
+ return q_num;
+ }
+
+ switch (dscp) {
+ case 0x08:
+ case 0x20:
+ case 0x40:
+ q_num = AC_BK_Q;
+ break;
+ case 0x80:
+ case 0xA0:
+ case 0x28:
+ q_num = AC_VI_Q;
+ break;
+ case 0xC0:
+ case 0xD0:
+ case 0xE0:
+ case 0x88:
+ case 0xB8:
+ q_num = AC_VO_Q;
+ break;
+ }
+
+ return q_num;
+}
+
+static inline int ac_balance(struct wilc *wl, u8 *ratio)
+{
+ u8 i, max_count = 0;
+
+ if (!ratio)
+ return -EINVAL;
+
+ for (i = 0; i < NQUEUES; i++)
+ if (wl->txq[i].fw.count > max_count)
+ max_count = wl->txq[i].fw.count;
+
+ for (i = 0; i < NQUEUES; i++)
+ ratio[i] = max_count - wl->txq[i].fw.count;
+
+ return 0;
+}
+
+static inline void ac_update_fw_ac_pkt_info(struct wilc *wl, u32 reg)
+{
+ wl->txq[AC_BK_Q].fw.count = FIELD_GET(BK_AC_COUNT_FIELD, reg);
+ wl->txq[AC_BE_Q].fw.count = FIELD_GET(BE_AC_COUNT_FIELD, reg);
+ wl->txq[AC_VI_Q].fw.count = FIELD_GET(VI_AC_COUNT_FIELD, reg);
+ wl->txq[AC_VO_Q].fw.count = FIELD_GET(VO_AC_COUNT_FIELD, reg);
+
+ wl->txq[AC_BK_Q].fw.acm = FIELD_GET(BK_AC_ACM_STAT_FIELD, reg);
+ wl->txq[AC_BE_Q].fw.acm = FIELD_GET(BE_AC_ACM_STAT_FIELD, reg);
+ wl->txq[AC_VI_Q].fw.acm = FIELD_GET(VI_AC_ACM_STAT_FIELD, reg);
+ wl->txq[AC_VO_Q].fw.acm = FIELD_GET(VO_AC_ACM_STAT_FIELD, reg);
+}
+
+static inline u8 ac_change(struct wilc *wilc, u8 *ac)
+{
+ do {
+ if (wilc->txq[*ac].fw.acm == 0)
+ return 0;
+ (*ac)++;
+ } while (*ac < NQUEUES);
return 1;
}
@@ -281,16 +415,21 @@ int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
struct txq_entry_t *tqe;
struct wilc_vif *vif = netdev_priv(dev);
struct wilc *wilc;
+ u8 q_num;
wilc = vif->wilc;
- if (wilc->quit)
+ if (wilc->quit) {
+ tx_complete_fn(priv, 0);
return 0;
+ }
tqe = kmalloc(sizeof(*tqe), GFP_ATOMIC);
- if (!tqe)
+ if (!tqe) {
+ tx_complete_fn(priv, 0);
return 0;
+ }
tqe->type = WILC_NET_PKT;
tqe->buffer = buffer;
tqe->buffer_size = buffer_size;
@@ -298,10 +437,24 @@ int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
tqe->priv = priv;
tqe->vif = vif;
- tqe->ack_idx = NOT_TCP_ACK;
- if (vif->ack_filter.enabled)
- tcp_process(dev, tqe);
- wilc_wlan_txq_add_to_tail(dev, tqe);
+ q_num = ac_classify(wilc, priv);
+ tqe->q_num = q_num;
+ if (ac_change(wilc, &q_num)) {
+ tx_complete_fn(priv, 0);
+ kfree(tqe);
+ return 0;
+ }
+
+ if (is_ac_q_limit(wilc, q_num)) {
+ tqe->ack_idx = NOT_TCP_ACK;
+ if (vif->ack_filter.enabled)
+ tcp_process(dev, tqe);
+ wilc_wlan_txq_add_to_tail(dev, q_num, tqe);
+ } else {
+ tx_complete_fn(priv, 0);
+ kfree(tqe);
+ }
+
return wilc->txq_entries;
}
@@ -315,34 +468,39 @@ int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer,
wilc = vif->wilc;
- if (wilc->quit)
+ if (wilc->quit) {
+ tx_complete_fn(priv, 0);
return 0;
+ }
tqe = kmalloc(sizeof(*tqe), GFP_ATOMIC);
- if (!tqe)
+ if (!tqe) {
+ tx_complete_fn(priv, 0);
return 0;
+ }
tqe->type = WILC_MGMT_PKT;
tqe->buffer = buffer;
tqe->buffer_size = buffer_size;
tqe->tx_complete_func = tx_complete_fn;
tqe->priv = priv;
+ tqe->q_num = AC_BE_Q;
tqe->ack_idx = NOT_TCP_ACK;
tqe->vif = vif;
- wilc_wlan_txq_add_to_tail(dev, tqe);
+ wilc_wlan_txq_add_to_tail(dev, AC_VO_Q, tqe);
return 1;
}
-static struct txq_entry_t *wilc_wlan_txq_get_first(struct wilc *wilc)
+static struct txq_entry_t *wilc_wlan_txq_get_first(struct wilc *wilc, u8 q_num)
{
struct txq_entry_t *tqe = NULL;
unsigned long flags;
spin_lock_irqsave(&wilc->txq_spinlock, flags);
- if (!list_empty(&wilc->txq_head.list))
- tqe = list_first_entry(&wilc->txq_head.list, struct txq_entry_t,
- list);
+ if (!list_empty(&wilc->txq[q_num].txq_head.list))
+ tqe = list_first_entry(&wilc->txq[q_num].txq_head.list,
+ struct txq_entry_t, list);
spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
@@ -350,13 +508,14 @@ static struct txq_entry_t *wilc_wlan_txq_get_first(struct wilc *wilc)
}
static struct txq_entry_t *wilc_wlan_txq_get_next(struct wilc *wilc,
- struct txq_entry_t *tqe)
+ struct txq_entry_t *tqe,
+ u8 q_num)
{
unsigned long flags;
spin_lock_irqsave(&wilc->txq_spinlock, flags);
- if (!list_is_last(&tqe->list, &wilc->txq_head.list))
+ if (!list_is_last(&tqe->list, &wilc->txq[q_num].txq_head.list))
tqe = list_next_entry(tqe, list);
else
tqe = NULL;
@@ -479,54 +638,92 @@ EXPORT_SYMBOL_GPL(host_sleep_notify);
int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
{
int i, entries = 0;
+ u8 k, ac;
u32 sum;
u32 reg;
+ u8 ac_desired_ratio[NQUEUES] = {0, 0, 0, 0};
+ u8 ac_preserve_ratio[NQUEUES] = {1, 1, 1, 1};
+ u8 *num_pkts_to_add;
+ u8 vmm_entries_ac[WILC_VMM_TBL_SIZE];
u32 offset = 0;
+ bool max_size_over = 0, ac_exist = 0;
int vmm_sz = 0;
- struct txq_entry_t *tqe;
+ struct txq_entry_t *tqe_q[NQUEUES];
int ret = 0;
int counter;
int timeout;
u32 vmm_table[WILC_VMM_TBL_SIZE];
+ u8 ac_pkt_num_to_chip[NQUEUES] = {0, 0, 0, 0};
const struct wilc_hif_func *func;
+ int srcu_idx;
u8 *txb = wilc->tx_buffer;
- struct net_device *dev;
struct wilc_vif *vif;
if (wilc->quit)
goto out_update_cnt;
+ if (ac_balance(wilc, ac_desired_ratio))
+ return -EINVAL;
+
mutex_lock(&wilc->txq_add_to_head_cs);
- tqe = wilc_wlan_txq_get_first(wilc);
- if (!tqe)
- goto out_unlock;
- dev = tqe->vif->ndev;
- wilc_wlan_txq_filter_dup_tcp_ack(dev);
+
+ srcu_idx = srcu_read_lock(&wilc->srcu);
+ list_for_each_entry_rcu(vif, &wilc->vif_list, list)
+ wilc_wlan_txq_filter_dup_tcp_ack(vif->ndev);
+ srcu_read_unlock(&wilc->srcu, srcu_idx);
+
+ for (ac = 0; ac < NQUEUES; ac++)
+ tqe_q[ac] = wilc_wlan_txq_get_first(wilc, ac);
+
i = 0;
sum = 0;
- while (tqe && (i < (WILC_VMM_TBL_SIZE - 1))) {
- if (tqe->type == WILC_CFG_PKT)
- vmm_sz = ETH_CONFIG_PKT_HDR_OFFSET;
- else if (tqe->type == WILC_NET_PKT)
- vmm_sz = ETH_ETHERNET_HDR_OFFSET;
- else
- vmm_sz = HOST_HDR_OFFSET;
-
- vmm_sz += tqe->buffer_size;
- vmm_sz = ALIGN(vmm_sz, 4);
-
- if ((sum + vmm_sz) > WILC_TX_BUFF_SIZE)
- break;
+ max_size_over = 0;
+ num_pkts_to_add = ac_desired_ratio;
+ do {
+ ac_exist = 0;
+ for (ac = 0; (ac < NQUEUES) && (!max_size_over); ac++) {
+ if (!tqe_q[ac])
+ continue;
+
+ vif = tqe_q[ac]->vif;
+ ac_exist = 1;
+ for (k = 0; (k < num_pkts_to_add[ac]) &&
+ (!max_size_over) && tqe_q[ac]; k++) {
+ if (i >= (WILC_VMM_TBL_SIZE - 1)) {
+ max_size_over = 1;
+ break;
+ }
- vmm_table[i] = vmm_sz / 4;
- if (tqe->type == WILC_CFG_PKT)
- vmm_table[i] |= BIT(10);
- cpu_to_le32s(&vmm_table[i]);
+ if (tqe_q[ac]->type == WILC_CFG_PKT)
+ vmm_sz = ETH_CONFIG_PKT_HDR_OFFSET;
+ else if (tqe_q[ac]->type == WILC_NET_PKT)
+ vmm_sz = ETH_ETHERNET_HDR_OFFSET;
+ else
+ vmm_sz = HOST_HDR_OFFSET;
- i++;
- sum += vmm_sz;
- tqe = wilc_wlan_txq_get_next(wilc, tqe);
- }
+ vmm_sz += tqe_q[ac]->buffer_size;
+ vmm_sz = ALIGN(vmm_sz, 4);
+
+ if ((sum + vmm_sz) > WILC_TX_BUFF_SIZE) {
+ max_size_over = 1;
+ break;
+ }
+ vmm_table[i] = vmm_sz / 4;
+ if (tqe_q[ac]->type == WILC_CFG_PKT)
+ vmm_table[i] |= BIT(10);
+
+ cpu_to_le32s(&vmm_table[i]);
+ vmm_entries_ac[i] = ac;
+
+ i++;
+ sum += vmm_sz;
+ tqe_q[ac] = wilc_wlan_txq_get_next(wilc,
+ tqe_q[ac],
+ ac);
+ }
+ }
+ num_pkts_to_add = ac_preserve_ratio;
+ } while (!max_size_over && ac_exist);
if (i == 0)
goto out_unlock;
@@ -540,8 +737,10 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
if (ret)
break;
- if ((reg & 0x1) == 0)
+ if ((reg & 0x1) == 0) {
+ ac_update_fw_ac_pkt_info(wilc, reg);
break;
+ }
counter++;
if (counter > 200) {
@@ -610,11 +809,13 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
offset = 0;
i = 0;
do {
+ struct txq_entry_t *tqe;
u32 header, buffer_offset;
char *bssid;
u8 mgmt_ptk = 0;
- tqe = wilc_wlan_txq_remove_from_head(dev);
+ tqe = wilc_wlan_txq_remove_from_head(wilc, vmm_entries_ac[i]);
+ ac_pkt_num_to_chip[vmm_entries_ac[i]]++;
if (!tqe)
break;
@@ -639,8 +840,11 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
if (tqe->type == WILC_CFG_PKT) {
buffer_offset = ETH_CONFIG_PKT_HDR_OFFSET;
} else if (tqe->type == WILC_NET_PKT) {
+ int prio = tqe->q_num;
+
bssid = tqe->vif->bssid;
buffer_offset = ETH_ETHERNET_HDR_OFFSET;
+ memcpy(&txb[offset + 4], &prio, sizeof(prio));
memcpy(&txb[offset + 8], bssid, 6);
} else {
buffer_offset = HOST_HDR_OFFSET;
@@ -658,6 +862,8 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
vif->ack_filter.pending_acks[tqe->ack_idx].txqe = NULL;
kfree(tqe);
} while (--entries);
+ for (i = 0; i < NQUEUES; i++)
+ wilc->txq[i].fw.count += ac_pkt_num_to_chip[i];
acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
@@ -956,14 +1162,17 @@ void wilc_wlan_cleanup(struct net_device *dev)
{
struct txq_entry_t *tqe;
struct rxq_entry_t *rqe;
+ u8 ac;
struct wilc_vif *vif = netdev_priv(dev);
struct wilc *wilc = vif->wilc;
wilc->quit = 1;
- while ((tqe = wilc_wlan_txq_remove_from_head(dev))) {
- if (tqe->tx_complete_func)
- tqe->tx_complete_func(tqe->priv, 0);
- kfree(tqe);
+ for (ac = 0; ac < NQUEUES; ac++) {
+ while ((tqe = wilc_wlan_txq_remove_from_head(wilc, ac))) {
+ if (tqe->tx_complete_func)
+ tqe->tx_complete_func(tqe->priv, 0);
+ kfree(tqe);
+ }
}
while ((rqe = wilc_wlan_rxq_remove(wilc)))
diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.h b/drivers/net/wireless/microchip/wilc1000/wlan.h
index 7689569cd82f..3d2104f19819 100644
--- a/drivers/net/wireless/microchip/wilc1000/wlan.h
+++ b/drivers/net/wireless/microchip/wilc1000/wlan.h
@@ -207,6 +207,18 @@
#define MODALIAS "WILC_SPI"
+#define NQUEUES 4
+#define AC_BUFFER_SIZE 1000
+
+#define VO_AC_COUNT_FIELD GENMASK(31, 25)
+#define VO_AC_ACM_STAT_FIELD BIT(24)
+#define VI_AC_COUNT_FIELD GENMASK(23, 17)
+#define VI_AC_ACM_STAT_FIELD BIT(16)
+#define BE_AC_COUNT_FIELD GENMASK(15, 9)
+#define BE_AC_ACM_STAT_FIELD BIT(8)
+#define BK_AC_COUNT_FIELD GENMASK(7, 3)
+#define BK_AC_ACM_STAT_FIELD BIT(1)
+
#define WILC_PKT_HDR_CONFIG_FIELD BIT(31)
#define WILC_PKT_HDR_OFFSET_FIELD GENMASK(30, 22)
#define WILC_PKT_HDR_TOTAL_LEN_FIELD GENMASK(21, 11)
@@ -295,10 +307,17 @@
* Tx/Rx Queue Structure
*
********************************************/
+enum ip_pkt_priority {
+ AC_VO_Q = 0,
+ AC_VI_Q = 1,
+ AC_BE_Q = 2,
+ AC_BK_Q = 3
+};
struct txq_entry_t {
struct list_head list;
int type;
+ u8 q_num;
int ack_idx;
u8 *buffer;
int buffer_size;
@@ -308,6 +327,17 @@ struct txq_entry_t {
void (*tx_complete_func)(void *priv, int status);
};
+struct txq_fw_recv_queue_stat {
+ u8 acm;
+ u8 count;
+};
+
+struct txq_handle {
+ struct txq_entry_t txq_head;
+ u16 count;
+ struct txq_fw_recv_queue_stat fw;
+};
+
struct rxq_entry_t {
struct list_head list;
u8 *buffer;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
index 5337e67092ca..0f328ce47fee 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
@@ -299,19 +299,19 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sysctl_bar = qtnf_map_bar(pdev, QTN_SYSCTL_BAR);
if (IS_ERR(sysctl_bar)) {
pr_err("failed to map BAR%u\n", QTN_SYSCTL_BAR);
- return ret;
+ return PTR_ERR(sysctl_bar);
}
dmareg_bar = qtnf_map_bar(pdev, QTN_DMA_BAR);
if (IS_ERR(dmareg_bar)) {
pr_err("failed to map BAR%u\n", QTN_DMA_BAR);
- return ret;
+ return PTR_ERR(dmareg_bar);
}
epmem_bar = qtnf_map_bar(pdev, QTN_SHMEM_BAR);
if (IS_ERR(epmem_bar)) {
pr_err("failed to map BAR%u\n", QTN_SHMEM_BAR);
- return ret;
+ return PTR_ERR(epmem_bar);
}
chipid = qtnf_chip_id_get(sysctl_bar);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index fed6d21cd6ce..5264b0a1f098 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -1228,6 +1228,17 @@ static int rt2800_check_hung(struct data_queue *queue)
return queue->wd_count > 16;
}
+static void rt2800_update_survey(struct rt2x00_dev *rt2x00dev)
+{
+ struct ieee80211_channel *chan = rt2x00dev->hw->conf.chandef.chan;
+ struct rt2x00_chan_survey *chan_survey =
+ &rt2x00dev->chan_survey[chan->hw_value];
+
+ chan_survey->time_idle += rt2800_register_read(rt2x00dev, CH_IDLE_STA);
+ chan_survey->time_busy += rt2800_register_read(rt2x00dev, CH_BUSY_STA);
+ chan_survey->time_ext_busy += rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC);
+}
+
void rt2800_watchdog(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;
@@ -1237,6 +1248,8 @@ void rt2800_watchdog(struct rt2x00_dev *rt2x00dev)
if (test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags))
return;
+ rt2800_update_survey(rt2x00dev);
+
queue_for_each(rt2x00dev, queue) {
switch (queue->qid) {
case QID_AC_VO:
@@ -5553,6 +5566,12 @@ void rt2800_config(struct rt2x00_dev *rt2x00dev,
rt2800_config_lna_gain(rt2x00dev, libconf);
if (flags & IEEE80211_CONF_CHANGE_CHANNEL) {
+ /*
+ * To provide correct survey data for survey-based ACS algorithm
+ * we have to save survey data for current channel before switching.
+ */
+ rt2800_update_survey(rt2x00dev);
+
rt2800_config_channel(rt2x00dev, libconf->conf,
&libconf->rf, &libconf->channel);
rt2800_config_txpower(rt2x00dev, libconf->conf->chandef.chan,
@@ -10111,12 +10130,20 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
}
/*
- * Create channel information array
+ * Create channel information and survey arrays
*/
info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
+ rt2x00dev->chan_survey =
+ kcalloc(spec->num_channels, sizeof(struct rt2x00_chan_survey),
+ GFP_KERNEL);
+ if (!rt2x00dev->chan_survey) {
+ kfree(info);
+ return -ENOMEM;
+ }
+
spec->channels_info = info;
default_power1 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
@@ -10503,27 +10530,30 @@ int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
struct survey_info *survey)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- struct ieee80211_conf *conf = &hw->conf;
- u32 idle, busy, busy_ext;
+ struct rt2x00_chan_survey *chan_survey =
+ &rt2x00dev->chan_survey[idx];
+ enum nl80211_band band = NL80211_BAND_2GHZ;
- if (idx != 0)
+ if (idx >= rt2x00dev->bands[band].n_channels) {
+ idx -= rt2x00dev->bands[band].n_channels;
+ band = NL80211_BAND_5GHZ;
+ }
+
+ if (idx >= rt2x00dev->bands[band].n_channels)
return -ENOENT;
- survey->channel = conf->chandef.chan;
+ if (idx == 0)
+ rt2800_update_survey(rt2x00dev);
- idle = rt2800_register_read(rt2x00dev, CH_IDLE_STA);
- busy = rt2800_register_read(rt2x00dev, CH_BUSY_STA);
- busy_ext = rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC);
+ survey->channel = &rt2x00dev->bands[band].channels[idx];
- if (idle || busy) {
- survey->filled = SURVEY_INFO_TIME |
- SURVEY_INFO_TIME_BUSY |
- SURVEY_INFO_TIME_EXT_BUSY;
+ survey->filled = SURVEY_INFO_TIME |
+ SURVEY_INFO_TIME_BUSY |
+ SURVEY_INFO_TIME_EXT_BUSY;
- survey->time = (idle + busy) / 1000;
- survey->time_busy = busy / 1000;
- survey->time_ext_busy = busy_ext / 1000;
- }
+ survey->time = div_u64(chan_survey->time_idle + chan_survey->time_busy, 1000);
+ survey->time_busy = div_u64(chan_survey->time_busy, 1000);
+ survey->time_ext_busy = div_u64(chan_survey->time_ext_busy, 1000);
if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
survey->filled |= SURVEY_INFO_IN_USE;
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index 780be81863b6..9f6fc40649be 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -182,6 +182,15 @@ struct rf_channel {
};
/*
+ * Information structure for channel survey.
+ */
+struct rt2x00_chan_survey {
+ u64 time_idle;
+ u64 time_busy;
+ u64 time_ext_busy;
+};
+
+/*
* Channel information structure
*/
struct channel_info {
@@ -752,6 +761,7 @@ struct rt2x00_dev {
*/
struct ieee80211_hw *hw;
struct ieee80211_supported_band bands[NUM_NL80211_BANDS];
+ struct rt2x00_chan_survey *chan_survey;
enum nl80211_band curr_band;
int curr_freq;
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index bf3fbd14eda3..590bd974d94f 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -877,10 +877,10 @@ static int ray_hw_xmit(unsigned char *data, int len, struct net_device *dev,
switch (ccsindex = get_free_tx_ccs(local)) {
case ECCSBUSY:
pr_debug("ray_hw_xmit tx_ccs table busy\n");
- /* fall through */
+ fallthrough;
case ECCSFULL:
pr_debug("ray_hw_xmit No free tx ccs\n");
- /* fall through */
+ fallthrough;
case ECARDGONE:
netif_stop_queue(dev);
return XMIT_NO_CCS;
@@ -1272,7 +1272,7 @@ static int ray_set_mode(struct net_device *dev, struct iw_request_info *info,
switch (wrqu->mode) {
case IW_MODE_ADHOC:
card_mode = 0;
- /* Fall through */
+ fallthrough;
case IW_MODE_INFRA:
local->sparm.b5.a_network_type = card_mode;
break;
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
index fb57cc8b2e47..7a71f063015a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
@@ -1628,17 +1628,17 @@ static void btc8723b2ant_action_wifi_link_process(struct btc_coexist
static bool btc8723b2ant_action_wifi_idle_process(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
- u8 wifi_rssi_state, wifi_rssi_state1, bt_rssi_state;
+ u8 wifi_rssi_state1;
u8 ap_num = 0;
u8 tmp = BT_8723B_2ANT_WIFI_RSSI_COEXSWITCH_THRES -
coex_dm->switch_thres_offset - coex_dm->switch_thres_offset;
- wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
+ btc8723b2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
wifi_rssi_state1 = btc8723b2ant_wifi_rssi_state(btcoexist, 1, 2,
tmp, 0);
tmp = BT_8723B_2ANT_BT_RSSI_COEXSWITCH_THRES -
coex_dm->switch_thres_offset - coex_dm->switch_thres_offset;
- bt_rssi_state = btc8723b2ant_bt_rssi_state(btcoexist, 2, tmp, 0);
+ btc8723b2ant_bt_rssi_state(btcoexist, 2, tmp, 0);
btcoexist->btc_get(btcoexist, BTC_GET_U1_AP_NUM, &ap_num);
@@ -2764,10 +2764,10 @@ static void btc8723b2ant_tdma_duration_adjust(struct btc_coexist *btcoexist,
/* SCO only or SCO+PAN(HS) */
static void btc8723b2ant_action_sco(struct btc_coexist *btcoexist)
{
- u8 wifi_rssi_state, bt_rssi_state;
+ u8 bt_rssi_state;
u32 wifi_bw;
- wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
+ btc8723b2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
bt_rssi_state = btc8723b2ant_bt_rssi_state(
btcoexist, 2, BT_8723B_2ANT_BT_RSSI_COEXSWITCH_THRES -
coex_dm->switch_thres_offset,
@@ -2807,12 +2807,12 @@ static void btc8723b2ant_action_sco(struct btc_coexist *btcoexist)
static void btc8723b2ant_action_hid(struct btc_coexist *btcoexist)
{
- u8 wifi_rssi_state, bt_rssi_state;
+ u8 bt_rssi_state;
u32 wifi_bw;
u8 tmp = BT_8723B_2ANT_BT_RSSI_COEXSWITCH_THRES -
coex_dm->switch_thres_offset;
- wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
+ btc8723b2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
bt_rssi_state = btc8723b2ant_bt_rssi_state(btcoexist, 2, tmp, 0);
btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
@@ -2852,13 +2852,13 @@ static void btc8723b2ant_action_hid(struct btc_coexist *btcoexist)
/* A2DP only / PAN(EDR) only/ A2DP+PAN(HS) */
static void btc8723b2ant_action_a2dp(struct btc_coexist *btcoexist)
{
- u8 wifi_rssi_state, wifi_rssi_state1, bt_rssi_state;
+ u8 wifi_rssi_state1, bt_rssi_state;
u32 wifi_bw;
u8 ap_num = 0;
u8 tmp = BT_8723B_2ANT_BT_RSSI_COEXSWITCH_THRES -
coex_dm->switch_thres_offset;
- wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
+ btc8723b2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
wifi_rssi_state1 = btc8723b2ant_wifi_rssi_state(btcoexist, 1, 2, 40, 0);
bt_rssi_state = btc8723b2ant_bt_rssi_state(btcoexist, 2, tmp, 0);
@@ -2926,12 +2926,12 @@ static void btc8723b2ant_action_a2dp(struct btc_coexist *btcoexist)
static void btc8723b2ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist)
{
- u8 wifi_rssi_state, wifi_rssi_state1, bt_rssi_state;
+ u8 wifi_rssi_state1, bt_rssi_state;
u32 wifi_bw;
u8 tmp = BT_8723B_2ANT_WIFI_RSSI_COEXSWITCH_THRES -
coex_dm->switch_thres_offset;
- wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
+ btc8723b2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
wifi_rssi_state1 = btc8723b2ant_wifi_rssi_state(btcoexist, 1, 2,
tmp, 0);
tmp = BT_8723B_2ANT_BT_RSSI_COEXSWITCH_THRES -
@@ -2973,12 +2973,12 @@ static void btc8723b2ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist)
static void btc8723b2ant_action_pan_edr(struct btc_coexist *btcoexist)
{
- u8 wifi_rssi_state, wifi_rssi_state1, bt_rssi_state;
+ u8 wifi_rssi_state1, bt_rssi_state;
u32 wifi_bw;
u8 tmp = BT_8723B_2ANT_WIFI_RSSI_COEXSWITCH_THRES -
coex_dm->switch_thres_offset;
- wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
+ btc8723b2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
wifi_rssi_state1 = btc8723b2ant_wifi_rssi_state(btcoexist, 1, 2,
tmp, 0);
tmp = BT_8723B_2ANT_BT_RSSI_COEXSWITCH_THRES -
@@ -3025,13 +3025,13 @@ static void btc8723b2ant_action_pan_edr(struct btc_coexist *btcoexist)
/* PAN(HS) only */
static void btc8723b2ant_action_pan_hs(struct btc_coexist *btcoexist)
{
- u8 wifi_rssi_state, wifi_rssi_state1, bt_rssi_state;
+ u8 bt_rssi_state;
u32 wifi_bw;
u8 tmp = BT_8723B_2ANT_WIFI_RSSI_COEXSWITCH_THRES -
coex_dm->switch_thres_offset;
- wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
- wifi_rssi_state1 = btc8723b2ant_wifi_rssi_state(btcoexist, 1, 2,
+ btc8723b2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
+ btc8723b2ant_wifi_rssi_state(btcoexist, 1, 2,
tmp, 0);
tmp = BT_8723B_2ANT_BT_RSSI_COEXSWITCH_THRES -
coex_dm->switch_thres_offset;
@@ -3063,12 +3063,12 @@ static void btc8723b2ant_action_pan_hs(struct btc_coexist *btcoexist)
/* PAN(EDR) + A2DP */
static void btc8723b2ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist)
{
- u8 wifi_rssi_state, wifi_rssi_state1, bt_rssi_state;
+ u8 wifi_rssi_state1, bt_rssi_state;
u32 wifi_bw;
u8 tmp = BT_8723B_2ANT_WIFI_RSSI_COEXSWITCH_THRES -
coex_dm->switch_thres_offset;
- wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
+ btc8723b2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
wifi_rssi_state1 = btc8723b2ant_wifi_rssi_state(btcoexist, 1, 2,
tmp, 0);
tmp = BT_8723B_2ANT_BT_RSSI_COEXSWITCH_THRES -
@@ -3118,12 +3118,12 @@ static void btc8723b2ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist)
static void btc8723b2ant_action_pan_edr_hid(struct btc_coexist *btcoexist)
{
- u8 wifi_rssi_state, wifi_rssi_state1, bt_rssi_state;
+ u8 wifi_rssi_state1, bt_rssi_state;
u32 wifi_bw;
u8 tmp = BT_8723B_2ANT_WIFI_RSSI_COEXSWITCH_THRES -
coex_dm->switch_thres_offset;
- wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
+ btc8723b2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
wifi_rssi_state1 = btc8723b2ant_wifi_rssi_state(btcoexist, 1, 2,
tmp, 0);
tmp = BT_8723B_2ANT_BT_RSSI_COEXSWITCH_THRES -
@@ -3182,12 +3182,12 @@ static void btc8723b2ant_action_pan_edr_hid(struct btc_coexist *btcoexist)
/* HID + A2DP + PAN(EDR) */
static void btc8723b2ant_action_hid_a2dp_pan_edr(struct btc_coexist *btcoexist)
{
- u8 wifi_rssi_state, wifi_rssi_state1, bt_rssi_state;
+ u8 wifi_rssi_state1, bt_rssi_state;
u32 wifi_bw;
u8 tmp = BT_8723B_2ANT_WIFI_RSSI_COEXSWITCH_THRES -
coex_dm->switch_thres_offset;
- wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
+ btc8723b2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
wifi_rssi_state1 = btc8723b2ant_wifi_rssi_state(btcoexist, 1, 2,
tmp, 0);
tmp = BT_8723B_2ANT_BT_RSSI_COEXSWITCH_THRES -
@@ -3241,13 +3241,13 @@ static void btc8723b2ant_action_hid_a2dp_pan_edr(struct btc_coexist *btcoexist)
static void btc8723b2ant_action_hid_a2dp(struct btc_coexist *btcoexist)
{
- u8 wifi_rssi_state, wifi_rssi_state1, bt_rssi_state;
+ u8 wifi_rssi_state1, bt_rssi_state;
u32 wifi_bw;
u8 ap_num = 0;
u8 tmp = BT_8723B_2ANT_WIFI_RSSI_COEXSWITCH_THRES -
coex_dm->switch_thres_offset;
- wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
+ btc8723b2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
wifi_rssi_state1 = btc8723b2ant_wifi_rssi_state(btcoexist, 1, 2,
tmp, 0);
tmp = BT_8723B_2ANT_BT_RSSI_COEXSWITCH_THRES -
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c
index 9f5e85be9764..a18dffc8753a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c
@@ -1901,7 +1901,6 @@ static void btc8821a1ant_run_coexist_mechanism(struct btc_coexist *btcoexist)
bool increase_scan_dev_num = false;
bool bt_ctrl_agg_buf_size = false;
u8 agg_buf_size = 5;
- u8 wifi_rssi_state = BTC_RSSI_STATE_HIGH;
u32 wifi_link_status = 0;
u32 num_of_wifi_link = 0;
bool wifi_under_5g = false;
@@ -1962,8 +1961,7 @@ static void btc8821a1ant_run_coexist_mechanism(struct btc_coexist *btcoexist)
btc8821a1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0);
} else {
if (wifi_connected) {
- wifi_rssi_state =
- btc8821a1ant_wifi_rssi_state(btcoexist, 1, 2,
+ btc8821a1ant_wifi_rssi_state(btcoexist, 1, 2,
30, 0);
btc8821a1ant_limited_tx(btcoexist,
NORMAL_EXEC, 1, 1,
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c
index e53789f11b08..447caa4aad32 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c
@@ -1448,17 +1448,15 @@ static void btc8821a2ant_init_coex_dm(struct btc_coexist *btcoexist)
static void btc8821a2ant_action_bt_inquiry(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
- u8 wifi_rssi_state, wifi_rssi_state1, bt_rssi_state;
bool wifi_connected = false;
bool low_pwr_disable = true;
bool scan = false, link = false, roam = false;
- wifi_rssi_state =
- btc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
- wifi_rssi_state1 = btc8821a2ant_wifi_rssi_state(btcoexist, 1, 2,
+ btc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
+ btc8821a2ant_wifi_rssi_state(btcoexist, 1, 2,
BT_8821A_2ANT_WIFI_RSSI_COEXSWITCH_THRES, 0);
- bt_rssi_state = btc8821a2ant_bt_rssi_state(btcoexist,
- 2, BT_8821A_2ANT_BT_RSSI_COEXSWITCH_THRES, 0);
+ btc8821a2ant_bt_rssi_state(btcoexist,
+ 2, BT_8821A_2ANT_BT_RSSI_COEXSWITCH_THRES, 0);
btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER,
&low_pwr_disable);
@@ -1516,15 +1514,14 @@ static void btc8821a2ant_action_wifi_link_process(struct btc_coexist *btcoexist)
static bool btc8821a2ant_action_wifi_idle_process(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
- u8 wifi_rssi_state, wifi_rssi_state1, bt_rssi_state;
+ u8 wifi_rssi_state1;
u8 ap_num = 0;
- wifi_rssi_state =
- btc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
+ btc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
wifi_rssi_state1 = btc8821a2ant_wifi_rssi_state(btcoexist, 1, 2,
BT_8821A_2ANT_WIFI_RSSI_COEXSWITCH_THRES - 20, 0);
- bt_rssi_state = btc8821a2ant_bt_rssi_state(btcoexist,
- 2, BT_8821A_2ANT_BT_RSSI_COEXSWITCH_THRES, 0);
+ btc8821a2ant_bt_rssi_state(btcoexist,
+ 2, BT_8821A_2ANT_BT_RSSI_COEXSWITCH_THRES, 0);
btcoexist->btc_get(btcoexist, BTC_GET_U1_AP_NUM, &ap_num);
@@ -2987,11 +2984,11 @@ static void btc8821a2ant_action_pan_edr(struct btc_coexist *btcoexist)
/* PAN(HS) only */
static void btc8821a2ant_action_pan_hs(struct btc_coexist *btcoexist)
{
- u8 wifi_rssi_state, wifi_rssi_state1, bt_rssi_state;
+ u8 wifi_rssi_state, bt_rssi_state;
u32 wifi_bw;
wifi_rssi_state = btc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
- wifi_rssi_state1 = btc8821a2ant_wifi_rssi_state(btcoexist, 1, 2,
+ btc8821a2ant_wifi_rssi_state(btcoexist, 1, 2,
BT_8821A_2ANT_WIFI_RSSI_COEXSWITCH_THRES, 0);
bt_rssi_state = btc8821a2ant_bt_rssi_state(btcoexist,
2, BT_8821A_2ANT_BT_RSSI_COEXSWITCH_THRES, 0);
@@ -3274,11 +3271,11 @@ static void btc8821a2ant_act_hid_a2dp_pan_edr(struct btc_coexist *btcoexist)
static void btc8821a2ant_action_hid_a2dp(struct btc_coexist *btcoexist)
{
u32 wifi_bw;
- u8 wifi_rssi_state, wifi_rssi_state1, bt_rssi_state;
+ u8 wifi_rssi_state, bt_rssi_state;
u8 ap_num = 0;
wifi_rssi_state = btc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
- wifi_rssi_state1 = btc8821a2ant_wifi_rssi_state(btcoexist, 1, 2,
+ btc8821a2ant_wifi_rssi_state(btcoexist, 1, 2,
BT_8821A_2ANT_WIFI_RSSI_COEXSWITCH_THRES, 0);
bt_rssi_state = btc8821a2ant_bt_rssi_state(btcoexist,
3, BT_8821A_2ANT_BT_RSSI_COEXSWITCH_THRES, 37);
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
index 2c05369b79e4..be4c0e60d44d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
@@ -47,30 +47,17 @@ 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;
+ bool ret = false;
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);
- }
+ spin_lock_bh(&rtlpriv->locks.entry_list_lock);
+ if (!list_empty(&rtlpriv->entry_list))
+ ret = true;
+ spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
}
- if (cnt > 0)
- return true;
- else
- return false;
+ return ret;
}
static bool halbtc_legacy(struct rtl_priv *adapter)
@@ -253,9 +240,6 @@ bool halbtc_send_bt_mp_operation(struct btc_coexist *btcoexist, u8 op_code,
rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"btmpinfo wait req_num=%d wait=%ld\n", req_num, wait_ms);
- if (in_interrupt())
- return false;
-
if (wait_for_completion_timeout(&btcoexist->bt_mp_comp,
msecs_to_jiffies(wait_ms)) == 0) {
rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c
index 63f9ea21962f..bd9160b166c5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c
@@ -1226,7 +1226,6 @@ static int _rtl88ee_set_media_status(struct ieee80211_hw *hw,
default:
pr_err("Network type %d not support!\n", type);
return 1;
- break;
}
/* MSR_INFRA == Link in infrastructure network;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c
index 9be032e8ec95..12d0b3a87af7 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c
@@ -1348,7 +1348,7 @@ static bool _rtl88e_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable,
static u8 _rtl88e_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb)
{
- u32 reg_eac, reg_e94, reg_e9c, reg_ea4;
+ u32 reg_eac, reg_e94, reg_e9c;
u8 result = 0x00;
rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1c);
@@ -1365,7 +1365,7 @@ static u8 _rtl88e_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb)
reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD);
reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD);
reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD);
- reg_ea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD);
+ rtl_get_bbreg(hw, 0xea4, MASKDWORD);
if (!(reg_eac & BIT(28)) &&
(((reg_e94 & 0x03FF0000) >> 16) != 0x142) &&
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c
index b9775eec4c54..c948dafa0c80 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c
@@ -674,12 +674,12 @@ void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw,
u8 fw_queue = QSLT_BEACON;
__le32 *pdesc = (__le32 *)pdesc8;
- dma_addr_t mapping = dma_map_single(&rtlpci->pdev->dev, skb->data,
- skb->len, DMA_TO_DEVICE);
-
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
__le16 fc = hdr->frame_control;
+ dma_addr_t mapping = dma_map_single(&rtlpci->pdev->dev, skb->data,
+ skb->len, DMA_TO_DEVICE);
+
if (dma_mapping_error(&rtlpci->pdev->dev, mapping)) {
rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE,
"DMA mapping error\n");
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c
index c0635309a92d..4165175cf5c0 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c
@@ -527,12 +527,12 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw,
u8 fw_queue = QSLT_BEACON;
__le32 *pdesc = (__le32 *)pdesc8;
- dma_addr_t mapping = dma_map_single(&rtlpci->pdev->dev, skb->data,
- skb->len, DMA_TO_DEVICE);
-
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
__le16 fc = hdr->frame_control;
+ dma_addr_t mapping = dma_map_single(&rtlpci->pdev->dev, skb->data,
+ skb->len, DMA_TO_DEVICE);
+
if (dma_mapping_error(&rtlpci->pdev->dev, mapping)) {
rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE,
"DMA mapping error\n");
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c
index 2890a495a23e..8d2c6d8d32d9 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c
@@ -113,7 +113,7 @@ void rtl92c_read_chip_version(struct ieee80211_hw *hw)
/**
* writeLLT - LLT table write access
- * @io: io callback
+ * @hw: Pointer to the ieee80211_hw structure.
* @address: LLT logical address.
* @data: LLT data content
*
@@ -145,11 +145,10 @@ bool rtl92c_llt_write(struct ieee80211_hw *hw, u32 address, u32 data)
/**
* rtl92c_init_LLT_table - Init LLT table
- * @io: io callback
- * @boundary:
+ * @hw: Pointer to the ieee80211_hw structure.
+ * @boundary: Page boundary.
*
* Realtek hardware access function.
- *
*/
bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary)
{
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
index 1ad0cf37f60b..87f959d5d861 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
@@ -448,7 +448,7 @@ static void _rtl_fill_usb_tx_desc(__le32 *txdesc)
set_tx_desc_first_seg(txdesc, 1);
}
-/**
+/*
* For HW recovery information
*/
static void _rtl_tx_desc_checksum(__le32 *txdesc)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c
index e34d33e73e52..68ec009ea157 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c
@@ -2566,7 +2566,7 @@ static void _rtl92d_phy_lc_calibrate_sw(struct ieee80211_hw *hw, bool is2t)
}
RTPRINT(rtlpriv, FINIT, INIT_IQK,
"PHY_LCK finish delay for %d ms=2\n", timecount);
- u4tmp = rtl_get_rfreg(hw, index, RF_SYN_G4, RFREG_OFFSET_MASK);
+ rtl_get_rfreg(hw, index, RF_SYN_G4, RFREG_OFFSET_MASK);
if (index == 0 && rtlhal->interfaceindex == 0) {
RTPRINT(rtlpriv, FINIT, INIT_IQK,
"path-A / 5G LCK\n");
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c
index 8944712274b5..c02813fba934 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c
@@ -664,12 +664,14 @@ void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw,
struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
u8 fw_queue = QSLT_BEACON;
- dma_addr_t mapping = dma_map_single(&rtlpci->pdev->dev, skb->data,
- skb->len, DMA_TO_DEVICE);
+
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
__le16 fc = hdr->frame_control;
__le32 *pdesc = (__le32 *)pdesc8;
+ dma_addr_t mapping = dma_map_single(&rtlpci->pdev->dev, skb->data,
+ skb->len, DMA_TO_DEVICE);
+
if (dma_mapping_error(&rtlpci->pdev->dev, mapping)) {
rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE,
"DMA mapping error\n");
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c
index a36dc6e726d2..f8a1de6e9849 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c
@@ -1132,7 +1132,6 @@ static int _rtl8723e_set_media_status(struct ieee80211_hw *hw,
default:
pr_err("Network type %d not support!\n", type);
return 1;
- break;
}
/* MSR_INFRA == Link in infrastructure network;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c
index fa0eed434d4f..fe9b407dc2af 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c
@@ -1147,10 +1147,8 @@ static void _rtl8723e_phy_iq_calibrate(struct ieee80211_hw *hw,
const u32 retrycount = 2;
- u32 bbvalue;
-
if (t == 0) {
- bbvalue = rtl_get_bbreg(hw, 0x800, MASKDWORD);
+ rtl_get_bbreg(hw, 0x800, MASKDWORD);
rtl8723_save_adda_registers(hw, adda_reg,
rtlphy->adda_backup, 16);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c
index e3ee91b7ea8d..340b3d68a54e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c
@@ -528,12 +528,12 @@ void rtl8723e_tx_fill_cmddesc(struct ieee80211_hw *hw,
u8 fw_queue = QSLT_BEACON;
__le32 *pdesc = (__le32 *)pdesc8;
- dma_addr_t mapping = dma_map_single(&rtlpci->pdev->dev, skb->data,
- skb->len, DMA_TO_DEVICE);
-
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
__le16 fc = hdr->frame_control;
+ dma_addr_t mapping = dma_map_single(&rtlpci->pdev->dev, skb->data,
+ skb->len, DMA_TO_DEVICE);
+
if (dma_mapping_error(&rtlpci->pdev->dev, mapping)) {
rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE,
"DMA mapping error\n");
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c
index f09f55b0468a..2b9313cb93db 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c
@@ -2178,7 +2178,7 @@ static u8 _get_right_chnl_place_for_iqk(u8 chnl)
static void _rtl8723be_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t)
{
u8 tmpreg;
- u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal;
+ u32 rf_a_mode = 0, rf_b_mode = 0;
struct rtl_priv *rtlpriv = rtl_priv(hw);
tmpreg = rtl_read_byte(rtlpriv, 0xd03);
@@ -2202,7 +2202,7 @@ static void _rtl8723be_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t)
rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS,
(rf_b_mode & 0x8FFFF) | 0x10000);
}
- lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS);
+ rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS);
rtl_set_rfreg(hw, RF90_PATH_A, 0xb0, RFREG_OFFSET_MASK, 0xdfbe0);
rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, 0x8c0a);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c
index 559ab78687c3..5a7cd270575a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c
@@ -50,7 +50,6 @@ static void _rtl8723be_query_rxphystatus(struct ieee80211_hw *hw,
pstatus->rx_mimo_signalquality[1] = -1;
if (is_cck) {
- u8 cck_highpwr;
u8 cck_agc_rpt;
cck_agc_rpt = p_phystrpt->cck_agc_rpt_ofdm_cfosho_a;
@@ -59,8 +58,7 @@ static void _rtl8723be_query_rxphystatus(struct ieee80211_hw *hw,
/* (2)PWDB, Average PWDB cacluated by
* hardware (for rate adaptive)
*/
- cck_highpwr = (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2,
- BIT(9));
+ rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, BIT(9));
lan_idx = ((cck_agc_rpt & 0xE0) >> 5);
vga_idx = (cck_agc_rpt & 0x1f);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
index f41a7643b9c4..372d6f8caf06 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
@@ -62,7 +62,7 @@ static void rtl8812ae_fixspur(struct ieee80211_hw *hw,
rtl_set_bbreg(hw, RRFMOD, 0xC00, 0x2);
/* 0x8AC[11:10] = 2'b10*/
- /* <20120914, Kordan> A workarould to resolve
+ /* <20120914, Kordan> A workaround to resolve
* 2480Mhz spur by setting ADC clock as 160M. (Asked by Binson)
*/
if (band_width == HT_CHANNEL_WIDTH_20 &&
@@ -82,7 +82,7 @@ static void rtl8812ae_fixspur(struct ieee80211_hw *hw,
/*0x8C4[30] = 0*/
}
} else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
- /* <20120914, Kordan> A workarould to resolve
+ /* <20120914, Kordan> A workaround to resolve
* 2480Mhz spur by setting ADC clock as 160M.
*/
if (band_width == HT_CHANNEL_WIDTH_20 &&
@@ -594,11 +594,10 @@ void rtl8821ae_phy_switch_wirelessband(struct ieee80211_hw *hw, u8 band)
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl_dm *rtldm = rtl_dm(rtlpriv);
u8 current_band = rtlhal->current_bandtype;
- u32 txpath, rxpath;
s8 bb_diff_between_band;
- txpath = rtl8821ae_phy_query_bb_reg(hw, RTXPATH, 0xf0);
- rxpath = rtl8821ae_phy_query_bb_reg(hw, RCCK_RX, 0x0f000000);
+ rtl8821ae_phy_query_bb_reg(hw, RTXPATH, 0xf0);
+ rtl8821ae_phy_query_bb_reg(hw, RCCK_RX, 0x0f000000);
rtlhal->current_bandtype = (enum band_type) band;
/* reconfig BB/RF according to wireless mode */
if (rtlhal->current_bandtype == BAND_ON_2_4G) {
@@ -1581,7 +1580,7 @@ static void _rtl8821ae_phy_txpower_by_rate_configuration(struct ieee80211_hw *hw
}
/* string is in decimal */
-static bool _rtl8812ae_get_integer_from_string(char *str, u8 *pint)
+static bool _rtl8812ae_get_integer_from_string(const char *str, u8 *pint)
{
u16 i = 0;
*pint = 0;
@@ -1599,7 +1598,7 @@ static bool _rtl8812ae_get_integer_from_string(char *str, u8 *pint)
return true;
}
-static bool _rtl8812ae_eq_n_byte(u8 *str1, u8 *str2, u32 num)
+static bool _rtl8812ae_eq_n_byte(const char *str1, const char *str2, u32 num)
{
if (num == 0)
return false;
@@ -1637,10 +1636,11 @@ static s8 _rtl8812ae_phy_get_chnl_idx_of_txpwr_lmt(struct ieee80211_hw *hw,
return channel_index;
}
-static void _rtl8812ae_phy_set_txpower_limit(struct ieee80211_hw *hw, u8 *pregulation,
- u8 *pband, u8 *pbandwidth,
- u8 *prate_section, u8 *prf_path,
- u8 *pchannel, u8 *ppower_limit)
+static void _rtl8812ae_phy_set_txpower_limit(struct ieee80211_hw *hw,
+ const char *pregulation,
+ const char *pband, const char *pbandwidth,
+ const char *prate_section, const char *prf_path,
+ const char *pchannel, const char *ppower_limit)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &rtlpriv->phy;
@@ -1648,8 +1648,8 @@ static void _rtl8812ae_phy_set_txpower_limit(struct ieee80211_hw *hw, u8 *pregul
u8 channel_index;
s8 power_limit = 0, prev_power_limit, ret;
- if (!_rtl8812ae_get_integer_from_string((char *)pchannel, &channel) ||
- !_rtl8812ae_get_integer_from_string((char *)ppower_limit,
+ if (!_rtl8812ae_get_integer_from_string(pchannel, &channel) ||
+ !_rtl8812ae_get_integer_from_string(ppower_limit,
&power_limit)) {
rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
"Illegal index of pwr_lmt table [chnl %d][val %d]\n",
@@ -1659,42 +1659,42 @@ static void _rtl8812ae_phy_set_txpower_limit(struct ieee80211_hw *hw, u8 *pregul
power_limit = power_limit > MAX_POWER_INDEX ?
MAX_POWER_INDEX : power_limit;
- if (_rtl8812ae_eq_n_byte(pregulation, (u8 *)("FCC"), 3))
+ if (_rtl8812ae_eq_n_byte(pregulation, "FCC", 3))
regulation = 0;
- else if (_rtl8812ae_eq_n_byte(pregulation, (u8 *)("MKK"), 3))
+ else if (_rtl8812ae_eq_n_byte(pregulation, "MKK", 3))
regulation = 1;
- else if (_rtl8812ae_eq_n_byte(pregulation, (u8 *)("ETSI"), 4))
+ else if (_rtl8812ae_eq_n_byte(pregulation, "ETSI", 4))
regulation = 2;
- else if (_rtl8812ae_eq_n_byte(pregulation, (u8 *)("WW13"), 4))
+ else if (_rtl8812ae_eq_n_byte(pregulation, "WW13", 4))
regulation = 3;
- if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("CCK"), 3))
+ if (_rtl8812ae_eq_n_byte(prate_section, "CCK", 3))
rate_section = 0;
- else if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("OFDM"), 4))
+ else if (_rtl8812ae_eq_n_byte(prate_section, "OFDM", 4))
rate_section = 1;
- else if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("HT"), 2) &&
- _rtl8812ae_eq_n_byte(prf_path, (u8 *)("1T"), 2))
+ else if (_rtl8812ae_eq_n_byte(prate_section, "HT", 2) &&
+ _rtl8812ae_eq_n_byte(prf_path, "1T", 2))
rate_section = 2;
- else if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("HT"), 2) &&
- _rtl8812ae_eq_n_byte(prf_path, (u8 *)("2T"), 2))
+ else if (_rtl8812ae_eq_n_byte(prate_section, "HT", 2) &&
+ _rtl8812ae_eq_n_byte(prf_path, "2T", 2))
rate_section = 3;
- else if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("VHT"), 3) &&
- _rtl8812ae_eq_n_byte(prf_path, (u8 *)("1T"), 2))
+ else if (_rtl8812ae_eq_n_byte(prate_section, "VHT", 3) &&
+ _rtl8812ae_eq_n_byte(prf_path, "1T", 2))
rate_section = 4;
- else if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("VHT"), 3) &&
- _rtl8812ae_eq_n_byte(prf_path, (u8 *)("2T"), 2))
+ else if (_rtl8812ae_eq_n_byte(prate_section, "VHT", 3) &&
+ _rtl8812ae_eq_n_byte(prf_path, "2T", 2))
rate_section = 5;
- if (_rtl8812ae_eq_n_byte(pbandwidth, (u8 *)("20M"), 3))
+ if (_rtl8812ae_eq_n_byte(pbandwidth, "20M", 3))
bandwidth = 0;
- else if (_rtl8812ae_eq_n_byte(pbandwidth, (u8 *)("40M"), 3))
+ else if (_rtl8812ae_eq_n_byte(pbandwidth, "40M", 3))
bandwidth = 1;
- else if (_rtl8812ae_eq_n_byte(pbandwidth, (u8 *)("80M"), 3))
+ else if (_rtl8812ae_eq_n_byte(pbandwidth, "80M", 3))
bandwidth = 2;
- else if (_rtl8812ae_eq_n_byte(pbandwidth, (u8 *)("160M"), 4))
+ else if (_rtl8812ae_eq_n_byte(pbandwidth, "160M", 4))
bandwidth = 3;
- if (_rtl8812ae_eq_n_byte(pband, (u8 *)("2.4G"), 4)) {
+ if (_rtl8812ae_eq_n_byte(pband, "2.4G", 4)) {
ret = _rtl8812ae_phy_get_chnl_idx_of_txpwr_lmt(hw,
BAND_ON_2_4G,
channel);
@@ -1718,7 +1718,7 @@ static void _rtl8812ae_phy_set_txpower_limit(struct ieee80211_hw *hw, u8 *pregul
regulation, bandwidth, rate_section, channel_index,
rtlphy->txpwr_limit_2_4g[regulation][bandwidth]
[rate_section][channel_index][RF90_PATH_A]);
- } else if (_rtl8812ae_eq_n_byte(pband, (u8 *)("5G"), 2)) {
+ } else if (_rtl8812ae_eq_n_byte(pband, "5G", 2)) {
ret = _rtl8812ae_phy_get_chnl_idx_of_txpwr_lmt(hw,
BAND_ON_5G,
channel);
@@ -1749,10 +1749,10 @@ static void _rtl8812ae_phy_set_txpower_limit(struct ieee80211_hw *hw, u8 *pregul
}
static void _rtl8812ae_phy_config_bb_txpwr_lmt(struct ieee80211_hw *hw,
- u8 *regulation, u8 *band,
- u8 *bandwidth, u8 *rate_section,
- u8 *rf_path, u8 *channel,
- u8 *power_limit)
+ const char *regulation, const char *band,
+ const char *bandwidth, const char *rate_section,
+ const char *rf_path, const char *channel,
+ const char *power_limit)
{
_rtl8812ae_phy_set_txpower_limit(hw, regulation, band, bandwidth,
rate_section, rf_path, channel,
@@ -1765,7 +1765,7 @@ static void _rtl8821ae_phy_read_and_config_txpwr_lmt(struct ieee80211_hw *hw)
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
u32 i = 0;
u32 array_len;
- u8 **array;
+ const char **array;
if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
array_len = RTL8812AE_TXPWR_LMT_ARRAY_LEN;
@@ -1778,13 +1778,13 @@ static void _rtl8821ae_phy_read_and_config_txpwr_lmt(struct ieee80211_hw *hw)
rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, "\n");
for (i = 0; i < array_len; i += 7) {
- u8 *regulation = array[i];
- u8 *band = array[i+1];
- u8 *bandwidth = array[i+2];
- u8 *rate = array[i+3];
- u8 *rf_path = array[i+4];
- u8 *chnl = array[i+5];
- u8 *val = array[i+6];
+ const char *regulation = array[i];
+ const char *band = array[i+1];
+ const char *bandwidth = array[i+2];
+ const char *rate = array[i+3];
+ const char *rf_path = array[i+4];
+ const char *chnl = array[i+5];
+ const char *val = array[i+6];
_rtl8812ae_phy_config_bb_txpwr_lmt(hw, regulation, band,
bandwidth, rate, rf_path,
@@ -2085,12 +2085,10 @@ bool rtl8812ae_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
return __rtl8821ae_phy_config_with_headerfile(hw,
radioa_array_table_a, radioa_arraylen_a,
_rtl8821ae_config_rf_radio_a);
- break;
case RF90_PATH_B:
return __rtl8821ae_phy_config_with_headerfile(hw,
radioa_array_table_b, radioa_arraylen_b,
_rtl8821ae_config_rf_radio_b);
- break;
case RF90_PATH_C:
case RF90_PATH_D:
pr_err("switch case %#x not processed\n", rfpath);
@@ -2116,7 +2114,6 @@ bool rtl8821ae_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
return __rtl8821ae_phy_config_with_headerfile(hw,
radioa_array_table, radioa_arraylen,
_rtl8821ae_config_rf_radio_a);
- break;
case RF90_PATH_B:
case RF90_PATH_C:
@@ -2449,8 +2446,9 @@ static s8 _rtl8812ae_phy_get_txpower_limit(struct ieee80211_hw *hw,
else if (band == BAND_ON_5G)
channel_temp = _rtl8812ae_phy_get_chnl_idx_of_txpwr_lmt(hw,
BAND_ON_5G, channel);
- else if (band == BAND_ON_BOTH)
+ else if (band == BAND_ON_BOTH) {
;/* BAND_ON_BOTH don't care temporarily */
+ }
if (band_temp == -1 || regulation == -1 || bandwidth_temp == -1 ||
rate_section == -1 || channel_temp == -1) {
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c
index 85093b3e5373..27c8a5d96520 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c
@@ -2654,7 +2654,7 @@ u32 RTL8821AE_AGC_TAB_1TARRAYLEN = ARRAY_SIZE(RTL8821AE_AGC_TAB_ARRAY);
* TXPWR_LMT.TXT
******************************************************************************/
-u8 *RTL8812AE_TXPWR_LMT[] = {
+const char *RTL8812AE_TXPWR_LMT[] = {
"FCC", "2.4G", "20M", "CCK", "1T", "01", "36",
"ETSI", "2.4G", "20M", "CCK", "1T", "01", "32",
"MKK", "2.4G", "20M", "CCK", "1T", "01", "32",
@@ -3223,7 +3223,7 @@ u8 *RTL8812AE_TXPWR_LMT[] = {
u32 RTL8812AE_TXPWR_LMT_ARRAY_LEN = ARRAY_SIZE(RTL8812AE_TXPWR_LMT);
-u8 *RTL8821AE_TXPWR_LMT[] = {
+const char *RTL8821AE_TXPWR_LMT[] = {
"FCC", "2.4G", "20M", "CCK", "1T", "01", "32",
"ETSI", "2.4G", "20M", "CCK", "1T", "01", "32",
"MKK", "2.4G", "20M", "CCK", "1T", "01", "32",
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h
index 540159c25078..76c62b7c0fb2 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h
@@ -28,7 +28,7 @@ extern u32 RTL8821AE_AGC_TAB_ARRAY[];
extern u32 RTL8812AE_AGC_TAB_1TARRAYLEN;
extern u32 RTL8812AE_AGC_TAB_ARRAY[];
extern u32 RTL8812AE_TXPWR_LMT_ARRAY_LEN;
-extern u8 *RTL8812AE_TXPWR_LMT[];
+extern const char *RTL8812AE_TXPWR_LMT[];
extern u32 RTL8821AE_TXPWR_LMT_ARRAY_LEN;
-extern u8 *RTL8821AE_TXPWR_LMT[];
+extern const char *RTL8821AE_TXPWR_LMT[];
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c
index 06e073defad6..d62b87f010c9 100644
--- a/drivers/net/wireless/realtek/rtlwifi/usb.c
+++ b/drivers/net/wireless/realtek/rtlwifi/usb.c
@@ -731,7 +731,6 @@ static int _rtl_usb_receive(struct ieee80211_hw *hw)
err_out:
usb_kill_anchored_urbs(&rtlusb->rx_submitted);
- _rtl_usb_cleanup_rx(hw);
return err;
}
diff --git a/drivers/net/wireless/realtek/rtw88/coex.c b/drivers/net/wireless/realtek/rtw88/coex.c
index aa08fd7d9fcd..c704c6885a18 100644
--- a/drivers/net/wireless/realtek/rtw88/coex.c
+++ b/drivers/net/wireless/realtek/rtw88/coex.c
@@ -8,6 +8,7 @@
#include "ps.h"
#include "debug.h"
#include "reg.h"
+#include "phy.h"
static u8 rtw_coex_next_rssi_state(struct rtw_dev *rtwdev, u8 pre_state,
u8 rssi, u8 rssi_thresh)
@@ -38,7 +39,7 @@ static void rtw_coex_limited_tx(struct rtw_dev *rtwdev,
struct rtw_chip_info *chip = rtwdev->chip;
struct rtw_coex *coex = &rtwdev->coex;
struct rtw_coex_stat *coex_stat = &coex->stat;
- bool wifi_under_b_mode = false;
+ u8 num_of_active_port = 1;
if (!chip->scbd_support)
return;
@@ -70,17 +71,13 @@ static void rtw_coex_limited_tx(struct rtw_dev *rtwdev,
/* set queue life time to avoid can't reach tx retry limit
* if tx is always broken by GNT_BT
*/
- rtw_write8_set(rtwdev, REG_LIFETIME_EN, 0xf);
+ if (num_of_active_port <= 1)
+ rtw_write8_set(rtwdev, REG_LIFETIME_EN, 0xf);
rtw_write16(rtwdev, REG_RETRY_LIMIT, 0x0808);
/* auto rate fallback step within 8 retries */
- if (wifi_under_b_mode) {
- rtw_write32(rtwdev, REG_DARFRC, 0x1000000);
- rtw_write32(rtwdev, REG_DARFRCH, 0x1010101);
- } else {
- rtw_write32(rtwdev, REG_DARFRC, 0x1000000);
- rtw_write32(rtwdev, REG_DARFRCH, 0x4030201);
- }
+ rtw_write32(rtwdev, REG_DARFRC, 0x1000000);
+ rtw_write32(rtwdev, REG_DARFRCH, 0x4030201);
} else {
rtw_write8_clr(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE);
rtw_write8_clr(rtwdev, REG_LIFETIME_EN, 0xf);
@@ -101,39 +98,84 @@ static void rtw_coex_limited_wl(struct rtw_dev *rtwdev)
{
struct rtw_coex *coex = &rtwdev->coex;
struct rtw_coex_dm *coex_dm = &coex->dm;
- struct rtw_coex_stat *coex_stat = &coex->stat;
bool tx_limit = false;
bool tx_agg_ctrl = false;
- if (coex->under_5g ||
- coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
- /* no need to limit tx */
- } else {
+ if (!coex->under_5g && coex_dm->bt_status != COEX_BTSTATUS_NCON_IDLE) {
tx_limit = true;
- if (coex_stat->bt_hid_exist || coex_stat->bt_hfp_exist ||
- coex_stat->bt_hid_pair_num > 0)
- tx_agg_ctrl = true;
+ tx_agg_ctrl = true;
}
rtw_coex_limited_tx(rtwdev, tx_limit, tx_agg_ctrl);
}
-static void rtw_coex_wl_ccklock_action(struct rtw_dev *rtwdev)
+static bool rtw_coex_freerun_check(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ u8 bt_rssi;
+ u8 ant_distance = 10;
+
+ if (coex_stat->bt_disabled)
+ return false;
+
+ if (efuse->share_ant || ant_distance <= 5 || !coex_stat->wl_gl_busy)
+ return false;
+
+ if (ant_distance >= 40 || coex_stat->bt_hid_pair_num >= 2)
+ return true;
+
+ /* ant_distance = 5 ~ 40 */
+ if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]) &&
+ COEX_RSSI_HIGH(coex_dm->bt_rssi_state[0]))
+ return true;
+
+ if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)
+ bt_rssi = coex_dm->bt_rssi_state[0];
+ else
+ bt_rssi = coex_dm->bt_rssi_state[1];
+
+ if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&
+ COEX_RSSI_HIGH(bt_rssi) &&
+ coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] <= 5)
+ return true;
+
+ return false;
+}
+
+static void rtw_coex_wl_slot_extend(struct rtw_dev *rtwdev, bool enable)
{
struct rtw_coex *coex = &rtwdev->coex;
struct rtw_coex_stat *coex_stat = &coex->stat;
u8 para[6] = {0};
- if (coex->stop_dm)
+ para[0] = COEX_H2C69_WL_LEAKAP;
+ para[1] = PARA1_H2C69_DIS_5MS;
+
+ if (enable)
+ para[1] = PARA1_H2C69_EN_5MS;
+ else
+ coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
+
+ coex_stat->wl_slot_extend = enable;
+ rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
+}
+
+static void rtw_coex_wl_ccklock_action(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+
+ if (coex->manual_control || coex->stop_dm)
return;
- para[0] = COEX_H2C69_WL_LEAKAP;
if (coex_stat->tdma_timer_base == 3 && coex_stat->wl_slot_extend) {
- para[1] = PARA1_H2C69_DIS_5MS; /* disable 5ms extend */
- rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
- coex_stat->wl_slot_extend = false;
- coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], set h2c 0x69 opcode 12 to turn off 5ms WL slot extend!!\n");
+ rtw_coex_wl_slot_extend(rtwdev, false);
return;
}
@@ -144,16 +186,20 @@ static void rtw_coex_wl_ccklock_action(struct rtw_dev *rtwdev)
else
coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], 5ms WL slot extend cnt = %d!!\n",
+ coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND]);
+
if (coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] == 7) {
- para[1] = 0x1; /* disable 5ms extend */
- rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
- coex_stat->wl_slot_extend = false;
- coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], set h2c 0x69 opcode 12 to turn off 5ms WL slot extend!!\n");
+ rtw_coex_wl_slot_extend(rtwdev, false);
}
} else if (!coex_stat->wl_slot_extend && coex_stat->wl_cck_lock) {
- para[1] = 0x0; /* enable 5ms extend */
- rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
- coex_stat->wl_slot_extend = true;
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], set h2c 0x69 opcode 12 to turn on 5ms WL slot extend!!\n");
+
+ rtw_coex_wl_slot_extend(rtwdev, true);
}
}
@@ -161,11 +207,48 @@ static void rtw_coex_wl_ccklock_detect(struct rtw_dev *rtwdev)
{
struct rtw_coex *coex = &rtwdev->coex;
struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
- /* TODO: wait for rx_rate_change_notify implement */
- coex_stat->wl_cck_lock = false;
- coex_stat->wl_cck_lock_pre = false;
- coex_stat->wl_cck_lock_ever = false;
+ bool is_cck_lock_rate = false;
+
+ if (coex_dm->bt_status == COEX_BTSTATUS_INQ_PAGE ||
+ coex_stat->bt_setup_link) {
+ coex_stat->wl_cck_lock = false;
+ coex_stat->wl_cck_lock_pre = false;
+ return;
+ }
+
+ if (coex_stat->wl_rx_rate <= COEX_CCK_2 ||
+ coex_stat->wl_rts_rx_rate <= COEX_CCK_2)
+ is_cck_lock_rate = true;
+
+ if (coex_stat->wl_connected && coex_stat->wl_gl_busy &&
+ COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&
+ (coex_dm->bt_status == COEX_BTSTATUS_ACL_BUSY ||
+ coex_dm->bt_status == COEX_BTSTATUS_ACL_SCO_BUSY ||
+ coex_dm->bt_status == COEX_BTSTATUS_SCO_BUSY)) {
+ if (is_cck_lock_rate) {
+ coex_stat->wl_cck_lock = true;
+
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], cck locking...\n");
+
+ } else {
+ coex_stat->wl_cck_lock = false;
+
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], cck unlock...\n");
+ }
+ } else {
+ coex_stat->wl_cck_lock = false;
+ }
+
+ /* CCK lock identification */
+ if (coex_stat->wl_cck_lock && !coex_stat->wl_cck_lock_pre)
+ ieee80211_queue_delayed_work(rtwdev->hw, &coex->wl_ccklock_work,
+ 3 * HZ);
+
+ coex_stat->wl_cck_lock_pre = coex_stat->wl_cck_lock;
}
static void rtw_coex_wl_noisy_detect(struct rtw_dev *rtwdev)
@@ -174,11 +257,12 @@ static void rtw_coex_wl_noisy_detect(struct rtw_dev *rtwdev)
struct rtw_coex_stat *coex_stat = &coex->stat;
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
u32 cnt_cck;
+ bool wl_cck_lock = false;
/* wifi noisy environment identification */
cnt_cck = dm_info->cck_ok_cnt + dm_info->cck_err_cnt;
- if (!coex_stat->wl_gl_busy) {
+ if (!coex_stat->wl_gl_busy && !wl_cck_lock) {
if (cnt_cck > 250) {
if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] < 5)
coex_stat->cnt_wl[COEX_CNT_WL_NOISY2]++;
@@ -211,6 +295,9 @@ static void rtw_coex_wl_noisy_detect(struct rtw_dev *rtwdev)
coex_stat->wl_noisy_level = 1;
else
coex_stat->wl_noisy_level = 0;
+
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], wl_noisy_level = %d\n",
+ coex_stat->wl_noisy_level);
}
}
@@ -219,6 +306,8 @@ static void rtw_coex_tdma_timer_base(struct rtw_dev *rtwdev, u8 type)
struct rtw_coex *coex = &rtwdev->coex;
struct rtw_coex_stat *coex_stat = &coex->stat;
u8 para[2] = {0};
+ u8 times;
+ u16 tbtt_interval = coex_stat->wl_beacon_interval;
if (coex_stat->tdma_timer_base == type)
return;
@@ -227,13 +316,33 @@ static void rtw_coex_tdma_timer_base(struct rtw_dev *rtwdev, u8 type)
para[0] = COEX_H2C69_TDMA_SLOT;
- if (type == 3) /* 4-slot */
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], tbtt_interval = %d\n",
+ tbtt_interval);
+
+ if (type == TDMA_TIMER_TYPE_4SLOT && tbtt_interval < 120) {
para[1] = PARA1_H2C69_TDMA_4SLOT; /* 4-slot */
- else /* 2-slot */
+ } else if (tbtt_interval < 80 && tbtt_interval > 0) {
+ times = 100 / tbtt_interval;
+ if (100 % tbtt_interval != 0)
+ times++;
+
+ para[1] = FIELD_PREP(PARA1_H2C69_TBTT_TIMES, times);
+ } else if (tbtt_interval >= 180) {
+ times = tbtt_interval / 100;
+ if (tbtt_interval % 100 <= 80)
+ times--;
+
+ para[1] = FIELD_PREP(PARA1_H2C69_TBTT_TIMES, times) |
+ FIELD_PREP(PARA1_H2C69_TBTT_DIV100, 1);
+ } else {
para[1] = PARA1_H2C69_TDMA_2SLOT;
+ }
rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): h2c_0x69 = 0x%x\n",
+ __func__, para[1]);
+
/* no 5ms_wl_slot_extend for 4-slot mode */
if (coex_stat->tdma_timer_base == 3)
rtw_coex_wl_ccklock_action(rtwdev);
@@ -307,6 +416,9 @@ static void rtw_coex_check_rfk(struct rtw_dev *rtwdev)
if (coex_rfe->wlg_at_btg && chip->scbd_support &&
coex_stat->bt_iqk_state != 0xff) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], (Before Ant Setup) Delay by IQK\n");
+
wait_cnt = COEX_RFK_TIMEOUT / COEX_MIN_DELAY;
do {
/* BT RFK */
@@ -318,6 +430,10 @@ static void rtw_coex_check_rfk(struct rtw_dev *rtwdev)
if (!btk && !wlk)
break;
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], (Before Ant Setup) wlk = %d, btk = %d\n",
+ wlk, btk);
+
mdelay(COEX_MIN_DELAY);
} while (++cnt < wait_cnt);
@@ -334,9 +450,16 @@ static void rtw_coex_query_bt_info(struct rtw_dev *rtwdev)
if (coex_stat->bt_disabled)
return;
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
+
rtw_fw_query_bt_info(rtwdev);
}
+static void rtw_coex_gnt_workaround(struct rtw_dev *rtwdev, bool force, u8 mode)
+{
+ rtw_coex_set_gnt_fix(rtwdev);
+}
+
static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev)
{
struct rtw_chip_info *chip = rtwdev->chip;
@@ -352,21 +475,23 @@ static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev)
}
if (coex_stat->bt_disabled != bt_disabled) {
- rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: BT state changed (%d) -> (%d)\n",
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], BT state changed (%d) -> (%d)\n",
coex_stat->bt_disabled, bt_disabled);
coex_stat->bt_disabled = bt_disabled;
coex_stat->bt_ble_scan_type = 0;
coex_dm->cur_bt_lna_lvl = 0;
- }
- if (!coex_stat->bt_disabled) {
- coex_stat->bt_reenable = true;
- ieee80211_queue_delayed_work(rtwdev->hw,
- &coex->bt_reenable_work, 15 * HZ);
- } else {
- coex_stat->bt_mailbox_reply = false;
- coex_stat->bt_reenable = false;
+ if (!coex_stat->bt_disabled) {
+ coex_stat->bt_reenable = true;
+ ieee80211_queue_delayed_work(rtwdev->hw,
+ &coex->bt_reenable_work,
+ 15 * HZ);
+ } else {
+ coex_stat->bt_mailbox_reply = false;
+ coex_stat->bt_reenable = false;
+ }
}
}
@@ -420,6 +545,12 @@ static void rtw_coex_update_wl_link_info(struct rtw_dev *rtwdev, u8 reason)
coex_dm->wl_rssi_state[i] = rssi_state;
}
+ if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 ||
+ coex_stat->wl_hi_pri_task2 || coex_stat->wl_gl_busy)
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, true);
+ else
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false);
+
switch (reason) {
case COEX_RSN_5GSCANSTART:
case COEX_RSN_5GSWITCHBAND:
@@ -535,6 +666,23 @@ out:
return ret;
}
+#define case_BTSTATUS(src) \
+ case COEX_BTSTATUS_##src: return #src
+
+static const char *rtw_coex_get_bt_status_string(u8 bt_status)
+{
+ switch (bt_status) {
+ case_BTSTATUS(NCON_IDLE);
+ case_BTSTATUS(CON_IDLE);
+ case_BTSTATUS(INQ_PAGE);
+ case_BTSTATUS(ACL_BUSY);
+ case_BTSTATUS(SCO_BUSY);
+ case_BTSTATUS(ACL_SCO_BUSY);
+ default:
+ return "Unknown";
+ }
+}
+
static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev)
{
struct rtw_coex *coex = &rtwdev->coex;
@@ -551,20 +699,11 @@ static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev)
rssi_state = coex_dm->bt_rssi_state[i];
rssi_step = chip->bt_rssi_step[i];
rssi = coex_stat->bt_rssi;
- rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state,
- rssi, rssi_step);
+ rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state, rssi,
+ rssi_step);
coex_dm->bt_rssi_state[i] = rssi_state;
}
- for (i = 0; i < COEX_RSSI_STEP; i++) {
- rssi_state = coex_dm->wl_rssi_state[i];
- rssi_step = chip->wl_rssi_step[i];
- rssi = rtwdev->dm_info.min_rssi;
- rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state,
- rssi, rssi_step);
- coex_dm->wl_rssi_state[i] = rssi_state;
- }
-
if (coex_stat->bt_ble_scan_en &&
coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE] % 3 == 0) {
u8 scan_type;
@@ -623,6 +762,7 @@ static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev)
coex_dm->bt_status = COEX_BTSTATUS_INQ_PAGE;
} else if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) {
coex_dm->bt_status = COEX_BTSTATUS_NCON_IDLE;
+ coex_stat->bt_multi_link_remain = false;
} else if (coex_stat->bt_info_lb2 == COEX_INFO_CONNECTION) {
coex_dm->bt_status = COEX_BTSTATUS_CON_IDLE;
} else if ((coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) ||
@@ -639,7 +779,8 @@ static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev)
coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE]++;
- rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: bt status(%d)\n", coex_dm->bt_status);
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(), %s!!!\n", __func__,
+ rtw_coex_get_bt_status_string(coex_dm->bt_status));
}
static void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type)
@@ -659,6 +800,8 @@ static void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type)
if (center_chan == 0 || (efuse->share_ant && center_chan <= 14)) {
link = 0;
+ center_chan = 0;
+ bw = 0;
} else if (center_chan <= 14) {
link = 0x1;
@@ -682,6 +825,9 @@ static void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type)
coex_dm->wl_ch_info[2] = bw;
rtw_fw_wl_ch_info(rtwdev, link, center_chan, bw);
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], %s: para[0:2] = 0x%x 0x%x 0x%x\n", __func__, link,
+ center_chan, bw);
}
static void rtw_coex_set_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl)
@@ -714,6 +860,8 @@ static void rtw_coex_set_bt_rx_gain(struct rtw_dev *rtwdev, u8 bt_lna_lvl)
} else {
rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, false);
}
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): bt_rx_LNA_level = %d\n",
+ __func__, bt_lna_lvl);
}
static void rtw_coex_set_rf_para(struct rtw_dev *rtwdev,
@@ -723,7 +871,7 @@ static void rtw_coex_set_rf_para(struct rtw_dev *rtwdev,
struct rtw_coex_stat *coex_stat = &coex->stat;
u8 offset = 0;
- if (coex->freerun && coex_stat->wl_noisy_level <= 1)
+ if (coex->freerun && coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] <= 5)
offset = 3;
rtw_coex_set_wl_tx_power(rtwdev, para.wl_pwr_dec_lvl);
@@ -765,11 +913,13 @@ static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control)
const struct rtw_hw_reg *btg_reg = chip->btg_reg;
if (wifi_control) {
- rtw_write32_set(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH);
+ rtw_write8_set(rtwdev, REG_SYS_SDIO_CTRL + 3,
+ BIT_LTE_MUX_CTRL_PATH >> 24);
if (btg_reg)
rtw_write8_set(rtwdev, btg_reg->addr, btg_reg->mask);
} else {
- rtw_write32_clr(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH);
+ rtw_write8_clr(rtwdev, REG_SYS_SDIO_CTRL + 3,
+ BIT_LTE_MUX_CTRL_PATH >> 24);
if (btg_reg)
rtw_write8_clr(rtwdev, btg_reg->addr, btg_reg->mask);
}
@@ -777,52 +927,134 @@ static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control)
static void rtw_coex_set_gnt_bt(struct rtw_dev *rtwdev, u8 state)
{
- rtw_coex_write_indirect_reg(rtwdev, 0x38, 0xc000, state);
- rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x0c00, state);
+ rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0xc000, state);
+ rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0c00, state);
}
static void rtw_coex_set_gnt_wl(struct rtw_dev *rtwdev, u8 state)
{
- rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x3000, state);
- rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x0300, state);
+ rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x3000, state);
+ rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0300, state);
+}
+
+static void rtw_btc_wltoggle_table_a(struct rtw_dev *rtwdev, bool force,
+ u8 table_case)
+{
+ struct rtw_chip_info *chip = rtwdev->chip;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ u8 h2c_para[6] = {0};
+ u32 table_wl = 0x5a5a5a5a;
+
+ h2c_para[0] = COEX_H2C69_TOGGLE_TABLE_A;
+ /* no definition */
+ h2c_para[1] = 0x1;
+
+ if (efuse->share_ant) {
+ if (table_case < chip->table_sant_num)
+ table_wl = chip->table_sant[table_case].wl;
+ } else {
+ if (table_case < chip->table_nsant_num)
+ table_wl = chip->table_nsant[table_case].wl;
+ }
+
+ /* tell WL FW WL slot toggle table-A*/
+ h2c_para[2] = (u8)u32_get_bits(table_wl, GENMASK(7, 0));
+ h2c_para[3] = (u8)u32_get_bits(table_wl, GENMASK(15, 8));
+ h2c_para[4] = (u8)u32_get_bits(table_wl, GENMASK(23, 16));
+ h2c_para[5] = (u8)u32_get_bits(table_wl, GENMASK(31, 24));
+
+ rtw_fw_bt_wifi_control(rtwdev, h2c_para[0], &h2c_para[1]);
+
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], %s(): H2C = [%02x %02x %02x %02x %02x %02x]\n",
+ __func__, h2c_para[0], h2c_para[1], h2c_para[2],
+ h2c_para[3], h2c_para[4], h2c_para[5]);
+}
+
+#define COEX_WL_SLOT_TOGLLE 0x5a5a5aaa
+static void rtw_btc_wltoggle_table_b(struct rtw_dev *rtwdev, bool force,
+ u8 interval, u32 table)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ u8 cur_h2c_para[6] = {0};
+ u8 i;
+
+ cur_h2c_para[0] = COEX_H2C69_TOGGLE_TABLE_B;
+ cur_h2c_para[1] = interval;
+ cur_h2c_para[2] = (u8)u32_get_bits(table, GENMASK(7, 0));
+ cur_h2c_para[3] = (u8)u32_get_bits(table, GENMASK(15, 8));
+ cur_h2c_para[4] = (u8)u32_get_bits(table, GENMASK(23, 16));
+ cur_h2c_para[5] = (u8)u32_get_bits(table, GENMASK(31, 24));
+
+ coex_stat->wl_toggle_interval = interval;
+
+ for (i = 0; i <= 5; i++)
+ coex_stat->wl_toggle_para[i] = cur_h2c_para[i];
+
+ rtw_fw_bt_wifi_control(rtwdev, cur_h2c_para[0], &cur_h2c_para[1]);
+
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], %s(): H2C = [%02x %02x %02x %02x %02x %02x]\n",
+ __func__, cur_h2c_para[0], cur_h2c_para[1], cur_h2c_para[2],
+ cur_h2c_para[3], cur_h2c_para[4], cur_h2c_para[5]);
}
-static void rtw_coex_set_table(struct rtw_dev *rtwdev, u32 table0, u32 table1)
+static void rtw_coex_set_table(struct rtw_dev *rtwdev, bool force, u32 table0,
+ u32 table1)
{
-#define DEF_BRK_TABLE_VAL 0xf0ffffff
+#define DEF_BRK_TABLE_VAL 0xf0ffffff
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+
+ /* If last tdma is wl slot toggle, force write table*/
+ if (!force && coex_dm->reason != COEX_RSN_LPS) {
+ if (table0 == rtw_read32(rtwdev, REG_BT_COEX_TABLE0) &&
+ table1 == rtw_read32(rtwdev, REG_BT_COEX_TABLE1))
+ return;
+ }
rtw_write32(rtwdev, REG_BT_COEX_TABLE0, table0);
rtw_write32(rtwdev, REG_BT_COEX_TABLE1, table1);
rtw_write32(rtwdev, REG_BT_COEX_BRK_TABLE, DEF_BRK_TABLE_VAL);
+
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], %s(): 0x6c0 = %x, 0x6c4 = %x\n", __func__, table0,
+ table1);
}
-static void rtw_coex_table(struct rtw_dev *rtwdev, u8 type)
+static void rtw_coex_table(struct rtw_dev *rtwdev, bool force, u8 type)
{
struct rtw_coex *coex = &rtwdev->coex;
struct rtw_coex_dm *coex_dm = &coex->dm;
struct rtw_chip_info *chip = rtwdev->chip;
struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
coex_dm->cur_table = type;
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], Coex_Table - %d\n", type);
+
if (efuse->share_ant) {
if (type < chip->table_sant_num)
- rtw_coex_set_table(rtwdev,
+ rtw_coex_set_table(rtwdev, force,
chip->table_sant[type].bt,
chip->table_sant[type].wl);
} else {
type = type - 100;
if (type < chip->table_nsant_num)
- rtw_coex_set_table(rtwdev,
+ rtw_coex_set_table(rtwdev, force,
chip->table_nsant[type].bt,
chip->table_nsant[type].wl);
}
+ if (coex_stat->wl_slot_toggle_change)
+ rtw_btc_wltoggle_table_a(rtwdev, true, type);
}
static void rtw_coex_ignore_wlan_act(struct rtw_dev *rtwdev, bool enable)
{
struct rtw_coex *coex = &rtwdev->coex;
- if (coex->stop_dm)
+ if (coex->manual_control || coex->stop_dm)
return;
rtw_fw_bt_ignore_wlan_action(rtwdev, enable);
@@ -841,15 +1073,18 @@ static void rtw_coex_power_save_state(struct rtw_dev *rtwdev, u8 ps_type,
case COEX_PS_WIFI_NATIVE:
/* recover to original 32k low power setting */
coex_stat->wl_force_lps_ctrl = false;
-
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], %s(): COEX_PS_WIFI_NATIVE\n", __func__);
rtw_leave_lps(rtwdev);
break;
case COEX_PS_LPS_OFF:
coex_stat->wl_force_lps_ctrl = true;
if (lps_mode)
- rtw_fw_coex_tdma_type(rtwdev, 0x8, 0, 0, 0, 0);
+ rtw_fw_coex_tdma_type(rtwdev, 0, 0, 0, 0, 0);
rtw_leave_lps(rtwdev);
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], %s(): COEX_PS_LPS_OFF\n", __func__);
break;
default:
break;
@@ -862,10 +1097,14 @@ static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2,
struct rtw_coex *coex = &rtwdev->coex;
struct rtw_coex_dm *coex_dm = &coex->dm;
struct rtw_chip_info *chip = rtwdev->chip;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
u8 ps_type = COEX_PS_WIFI_NATIVE;
bool ap_enable = false;
if (ap_enable && (byte1 & BIT(4) && !(byte1 & BIT(5)))) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): AP mode\n",
+ __func__);
+
byte1 &= ~BIT(4);
byte1 |= BIT(5);
@@ -875,12 +1114,20 @@ static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2,
ps_type = COEX_PS_WIFI_NATIVE;
rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);
} else if (byte1 & BIT(4) && !(byte1 & BIT(5))) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], %s(): Force LPS (byte1 = 0x%x)\n", __func__,
+ byte1);
+
if (chip->pstdma_type == COEX_PSTDMA_FORCE_LPSOFF)
ps_type = COEX_PS_LPS_OFF;
else
ps_type = COEX_PS_LPS_ON;
rtw_coex_power_save_state(rtwdev, ps_type, 0x50, 0x4);
} else {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], %s(): native power save (byte1 = 0x%x)\n",
+ __func__, byte1);
+
ps_type = COEX_PS_WIFI_NATIVE;
rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);
}
@@ -892,6 +1139,14 @@ static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2,
coex_dm->ps_tdma_para[4] = byte5;
rtw_fw_coex_tdma_type(rtwdev, byte1, byte2, byte3, byte4, byte5);
+
+ if (byte1 & BIT(2)) {
+ coex_stat->wl_slot_toggle = true;
+ coex_stat->wl_slot_toggle_change = false;
+ } else {
+ coex_stat->wl_slot_toggle_change = coex_stat->wl_slot_toggle;
+ coex_stat->wl_slot_toggle = false;
+ }
}
static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase)
@@ -905,26 +1160,24 @@ static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase)
bool turn_on;
bool wl_busy = false;
- if (tcase & TDMA_4SLOT)/* 4-slot (50ms) mode */
- rtw_coex_tdma_timer_base(rtwdev, 3);
+ if (tcase & TDMA_4SLOT) /* 4-slot (50ms) mode */
+ rtw_coex_tdma_timer_base(rtwdev, TDMA_TIMER_TYPE_4SLOT);
else
- rtw_coex_tdma_timer_base(rtwdev, 0);
+ rtw_coex_tdma_timer_base(rtwdev, TDMA_TIMER_TYPE_2SLOT);
type = (u8)(tcase & 0xff);
turn_on = (type == 0 || type == 100) ? false : true;
- if (!force) {
- if (turn_on == coex_dm->cur_ps_tdma_on &&
- type == coex_dm->cur_ps_tdma) {
- return;
- }
- }
-
- /* enable TBTT interrupt */
- if (turn_on)
- rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
+ if (!force && turn_on == coex_dm->cur_ps_tdma_on &&
+ type == coex_dm->cur_ps_tdma) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], Skip TDMA because no change TDMA(%s, %d)\n",
+ (coex_dm->cur_ps_tdma_on ? "on" : "off"),
+ coex_dm->cur_ps_tdma);
+ return;
+ }
wl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
if ((coex_stat->bt_a2dp_exist &&
@@ -934,6 +1187,10 @@ static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase)
else
rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, true);
+ /* update pre state */
+ coex_dm->cur_ps_tdma_on = turn_on;
+ coex_dm->cur_ps_tdma = type;
+
if (efuse->share_ant) {
if (type < chip->tdma_sant_num)
rtw_coex_set_tdma(rtwdev,
@@ -953,17 +1210,16 @@ static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase)
chip->tdma_nsant[n].para[4]);
}
- /* update pre state */
- coex_dm->cur_ps_tdma_on = turn_on;
- coex_dm->cur_ps_tdma = type;
- rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: coex tdma type (%d)\n", type);
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], coex tdma type(%s, %d)\n",
+ turn_on ? "on" : "off", type);
}
static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase)
{
struct rtw_coex *coex = &rtwdev->coex;
struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_coex_rfe *coex_rfe = &coex->rfe;
struct rtw_coex_dm *coex_dm = &coex->dm;
u8 ctrl_type = COEX_SWITCH_CTRL_MAX;
u8 pos_type = COEX_SWITCH_TO_MAX;
@@ -976,8 +1232,14 @@ static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase)
/* avoid switch coex_ctrl_owner during BT IQK */
rtw_coex_check_rfk(rtwdev);
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], coex_stat->bt_disabled = 0x%x\n",
+ coex_stat->bt_disabled);
+
switch (phase) {
case COEX_SET_ANT_POWERON:
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], %s() - PHASE_COEX_POWERON\n", __func__);
/* set path control owner to BT at power-on */
if (coex_stat->bt_disabled)
rtw_coex_coex_ctrl_owner(rtwdev, true);
@@ -988,6 +1250,8 @@ static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase)
pos_type = COEX_SWITCH_TO_BT;
break;
case COEX_SET_ANT_INIT:
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], %s() - PHASE_COEX_INIT\n", __func__);
if (coex_stat->bt_disabled) {
/* set GNT_BT to SW low */
rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW);
@@ -1009,10 +1273,12 @@ static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase)
pos_type = COEX_SWITCH_TO_BT;
break;
case COEX_SET_ANT_WONLY:
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], %s() - PHASE_WLANONLY_INIT\n", __func__);
/* set GNT_BT to SW Low */
rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW);
- /* Set GNT_WL to SW high */
+ /* set GNT_WL to SW high */
rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
/* set path control owner to wl at initial step */
@@ -1022,6 +1288,8 @@ static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase)
pos_type = COEX_SWITCH_TO_WLG;
break;
case COEX_SET_ANT_WOFF:
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], %s() - PHASE_WLAN_OFF\n", __func__);
/* set path control owner to BT */
rtw_coex_coex_ctrl_owner(rtwdev, false);
@@ -1029,6 +1297,8 @@ static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase)
pos_type = COEX_SWITCH_TO_NOCARE;
break;
case COEX_SET_ANT_2G:
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], %s() - PHASE_2G_RUNTIME\n", __func__);
/* set GNT_BT to PTA */
rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
@@ -1042,8 +1312,11 @@ static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase)
pos_type = COEX_SWITCH_TO_NOCARE;
break;
case COEX_SET_ANT_5G:
- /* set GNT_BT to PTA */
- rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH);
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], %s() - PHASE_5G_RUNTIME\n", __func__);
+
+ /* set GNT_BT to HW PTA */
+ rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
/* set GNT_WL to SW high */
rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
@@ -1055,8 +1328,11 @@ static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase)
pos_type = COEX_SWITCH_TO_WLA;
break;
case COEX_SET_ANT_2G_FREERUN:
- /* set GNT_BT to SW high */
- rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH);
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], %s() - PHASE_2G_FREERUN\n", __func__);
+
+ /* set GNT_BT to HW PTA */
+ rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
/* Set GNT_WL to SW high */
rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
@@ -1068,10 +1344,12 @@ static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase)
pos_type = COEX_SWITCH_TO_WLG_BT;
break;
case COEX_SET_ANT_2G_WLBT:
- /* set GNT_BT to SW high */
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], %s() - PHASE_2G_WLBT\n", __func__);
+ /* set GNT_BT to HW PTA */
rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
- /* Set GNT_WL to SW high */
+ /* Set GNT_WL to HW PTA */
rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA);
/* set path control owner to wl at runtime step */
@@ -1085,10 +1363,58 @@ static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase)
return;
}
- if (ctrl_type < COEX_SWITCH_CTRL_MAX && pos_type < COEX_SWITCH_TO_MAX)
+ if (ctrl_type < COEX_SWITCH_CTRL_MAX && pos_type < COEX_SWITCH_TO_MAX &&
+ coex_rfe->ant_switch_exist)
rtw_coex_set_ant_switch(rtwdev, ctrl_type, pos_type);
}
+#define case_ALGO(src) \
+ case COEX_ALGO_##src: return #src
+
+static const char *rtw_coex_get_algo_string(u8 algo)
+{
+ switch (algo) {
+ case_ALGO(NOPROFILE);
+ case_ALGO(HFP);
+ case_ALGO(HID);
+ case_ALGO(A2DP);
+ case_ALGO(PAN);
+ case_ALGO(A2DP_HID);
+ case_ALGO(A2DP_PAN);
+ case_ALGO(PAN_HID);
+ case_ALGO(A2DP_PAN_HID);
+ default:
+ return "Unknown";
+ }
+}
+
+#define case_BT_PROFILE(src) \
+ case BPM_##src: return #src
+
+static const char *rtw_coex_get_bt_profile_string(u8 bt_profile)
+{
+ switch (bt_profile) {
+ case_BT_PROFILE(NOPROFILE);
+ case_BT_PROFILE(HFP);
+ case_BT_PROFILE(HID);
+ case_BT_PROFILE(A2DP);
+ case_BT_PROFILE(PAN);
+ case_BT_PROFILE(HID_HFP);
+ case_BT_PROFILE(A2DP_HFP);
+ case_BT_PROFILE(A2DP_HID);
+ case_BT_PROFILE(A2DP_HID_HFP);
+ case_BT_PROFILE(PAN_HFP);
+ case_BT_PROFILE(PAN_HID);
+ case_BT_PROFILE(PAN_HID_HFP);
+ case_BT_PROFILE(PAN_A2DP);
+ case_BT_PROFILE(PAN_A2DP_HFP);
+ case_BT_PROFILE(PAN_A2DP_HID);
+ case_BT_PROFILE(PAN_A2DP_HID_HFP);
+ default:
+ return "Unknown";
+ }
+}
+
static u8 rtw_coex_algorithm(struct rtw_dev *rtwdev)
{
struct rtw_coex *coex = &rtwdev->coex;
@@ -1149,6 +1475,10 @@ static u8 rtw_coex_algorithm(struct rtw_dev *rtwdev)
break;
}
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], BT Profile = %s => Algorithm = %s\n",
+ rtw_coex_get_bt_profile_string(profile_map),
+ rtw_coex_get_algo_string(algorithm));
return algorithm;
}
@@ -1158,6 +1488,9 @@ static void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev)
struct rtw_chip_info *chip = rtwdev->chip;
u8 table_case, tdma_case;
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+
if (efuse->share_ant) {
/* Shared-Ant */
table_case = 2;
@@ -1168,8 +1501,7 @@ static void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev)
tdma_case = 100;
}
- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
- rtw_coex_table(rtwdev, table_case);
+ rtw_coex_table(rtwdev, false, table_case);
rtw_coex_tdma(rtwdev, false, tdma_case);
}
@@ -1181,13 +1513,16 @@ static void rtw_coex_action_freerun(struct rtw_dev *rtwdev)
struct rtw_efuse *efuse = &rtwdev->efuse;
struct rtw_chip_info *chip = rtwdev->chip;
u8 level = 0;
+ bool bt_afh_loss = true;
+
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
if (efuse->share_ant)
return;
coex->freerun = true;
- if (coex_stat->wl_connected)
+ if (bt_afh_loss)
rtw_coex_update_wl_ch_info(rtwdev, COEX_MEDIA_CONNECT);
rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN);
@@ -1211,41 +1546,49 @@ static void rtw_coex_action_freerun(struct rtw_dev *rtwdev)
else
rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[level]);
- rtw_coex_table(rtwdev, 100);
+ rtw_coex_table(rtwdev, false, 100);
rtw_coex_tdma(rtwdev, false, 100);
}
-static void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev)
+static void rtw_coex_action_rf4ce(struct rtw_dev *rtwdev)
{
struct rtw_efuse *efuse = &rtwdev->efuse;
struct rtw_chip_info *chip = rtwdev->chip;
u8 table_case, tdma_case;
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
+
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+
if (efuse->share_ant) {
/* Shared-Ant */
- table_case = 2;
- tdma_case = 0;
+ table_case = 9;
+ tdma_case = 16;
} else {
/* Non-Shared-Ant */
table_case = 100;
tdma_case = 100;
}
- rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
- rtw_coex_table(rtwdev, table_case);
+ rtw_coex_table(rtwdev, false, table_case);
rtw_coex_tdma(rtwdev, false, tdma_case);
}
-static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev)
+static void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev)
{
struct rtw_efuse *efuse = &rtwdev->efuse;
struct rtw_chip_info *chip = rtwdev->chip;
u8 table_case, tdma_case;
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
+
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+
if (efuse->share_ant) {
/* Shared-Ant */
- table_case = 1;
+ table_case = 2;
tdma_case = 0;
} else {
/* Non-Shared-Ant */
@@ -1253,9 +1596,45 @@ static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev)
tdma_case = 100;
}
+ rtw_coex_table(rtwdev, false, table_case);
+ rtw_coex_tdma(rtwdev, false, tdma_case);
+}
+
+static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 table_case, tdma_case;
+
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
+
rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
- rtw_coex_table(rtwdev, table_case);
+
+ if (efuse->share_ant) { /* Shared-Ant */
+ if (coex_stat->wl_gl_busy) {
+ table_case = 26;
+ if (coex_stat->bt_hid_exist &&
+ coex_stat->bt_profile_num == 1) {
+ tdma_case = 20;
+ } else {
+ tdma_case = 20;
+ }
+ } else {
+ table_case = 1;
+ tdma_case = 0;
+ }
+ } else { /* Non-Shared-Ant */
+ if (coex_stat->wl_gl_busy)
+ table_case = 115;
+ else
+ table_case = 100;
+ tdma_case = 100;
+ }
+
+ rtw_coex_table(rtwdev, false, table_case);
rtw_coex_tdma(rtwdev, false, tdma_case);
}
@@ -1269,10 +1648,14 @@ static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev)
struct rtw_coex_rfe *coex_rfe = &coex->rfe;
u8 table_case = 0xff, tdma_case = 0xff;
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+
if (coex_rfe->ant_switch_with_bt &&
coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
if (efuse->share_ant &&
- COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) {
+ COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&
+ coex_stat->wl_gl_busy) {
table_case = 0;
tdma_case = 0;
} else if (!efuse->share_ant) {
@@ -1283,9 +1666,7 @@ static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev)
if (table_case != 0xff && tdma_case != 0xff) {
rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN);
- rtw_coex_table(rtwdev, table_case);
- rtw_coex_tdma(rtwdev, false, tdma_case);
- return;
+ goto exit;
}
rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
@@ -1296,8 +1677,12 @@ static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev)
table_case = 10;
tdma_case = 3;
} else if (coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
- table_case = 6;
- tdma_case = 7;
+ table_case = 11;
+
+ if (coex_stat->lo_pri_rx + coex_stat->lo_pri_tx > 250)
+ tdma_case = 17;
+ else
+ tdma_case = 7;
} else {
table_case = 12;
tdma_case = 7;
@@ -1308,7 +1693,7 @@ static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev)
table_case = 112;
tdma_case = 104;
} else if ((coex_stat->bt_ble_scan_type & 0x2) &&
- coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
+ coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
table_case = 114;
tdma_case = 103;
} else {
@@ -1317,8 +1702,8 @@ static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev)
}
}
- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
- rtw_coex_table(rtwdev, table_case);
+exit:
+ rtw_coex_table(rtwdev, false, table_case);
rtw_coex_tdma(rtwdev, false, tdma_case);
}
@@ -1332,6 +1717,10 @@ static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev)
u8 table_case, tdma_case;
u32 slot_type = 0;
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+
if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 ||
coex_stat->wl_hi_pri_task2)
wl_hi_pri = true;
@@ -1339,7 +1728,10 @@ static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev)
if (efuse->share_ant) {
/* Shared-Ant */
if (wl_hi_pri) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], bt inq/page + wifi hi-pri task\n");
table_case = 15;
+
if (coex_stat->bt_profile_num > 0)
tdma_case = 10;
else if (coex_stat->wl_hi_pri_task1)
@@ -1349,6 +1741,8 @@ static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev)
else
tdma_case = 9;
} else if (coex_stat->wl_gl_busy) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], bt inq/page + wifi busy\n");
if (coex_stat->bt_profile_num == 0) {
table_case = 12;
tdma_case = 18;
@@ -1363,43 +1757,53 @@ static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev)
tdma_case = 26;
}
} else if (coex_stat->wl_connected) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], bt inq/page + wifi connected\n");
table_case = 9;
tdma_case = 27;
} else {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], bt inq/page + wifi not-connected\n");
table_case = 1;
tdma_case = 0;
}
} else {
/* Non_Shared-Ant */
if (wl_hi_pri) {
- table_case = 113;
- if (coex_stat->bt_a2dp_exist &&
- !coex_stat->bt_pan_exist)
- tdma_case = 111;
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], bt inq/page + wifi hi-pri task\n");
+ table_case = 114;
+
+ if (coex_stat->bt_profile_num > 0)
+ tdma_case = 110;
else if (coex_stat->wl_hi_pri_task1)
tdma_case = 106;
else if (!coex_stat->bt_page)
tdma_case = 108;
else
tdma_case = 109;
- } else if (coex_stat->wl_gl_busy) {
+ } else if (coex_stat->wl_gl_busy) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], bt inq/page + wifi busy\n");
table_case = 114;
tdma_case = 121;
} else if (coex_stat->wl_connected) {
- table_case = 100;
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], bt inq/page + wifi connected\n");
+ table_case = 101;
tdma_case = 100;
} else {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], bt inq/page + wifi not-connected\n");
table_case = 101;
tdma_case = 100;
}
}
- rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: wifi hi(%d), bt page(%d)\n",
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], wifi hi(%d), bt page(%d)\n",
wl_hi_pri, coex_stat->bt_page);
- rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
- rtw_coex_table(rtwdev, table_case);
+ rtw_coex_table(rtwdev, false, table_case);
rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
}
@@ -1411,6 +1815,10 @@ static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev)
struct rtw_chip_info *chip = rtwdev->chip;
u8 table_case, tdma_case;
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+
if (efuse->share_ant) {
/* Shared-Ant */
if (coex_stat->bt_multi_link) {
@@ -1431,9 +1839,7 @@ static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev)
}
}
- rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
- rtw_coex_table(rtwdev, table_case);
+ rtw_coex_table(rtwdev, false, table_case);
rtw_coex_tdma(rtwdev, false, tdma_case);
}
@@ -1444,62 +1850,80 @@ static void rtw_coex_action_bt_hid(struct rtw_dev *rtwdev)
struct rtw_efuse *efuse = &rtwdev->efuse;
struct rtw_chip_info *chip = rtwdev->chip;
u8 table_case, tdma_case;
- u32 wl_bw;
+ u32 slot_type = 0;
+ bool bt_multi_link_remain = false, is_toggle_table = false;
- wl_bw = rtwdev->hal.current_band_width;
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
if (efuse->share_ant) {
/* Shared-Ant */
if (coex_stat->bt_ble_exist) {
/* RCU */
- if (!coex_stat->wl_gl_busy)
- table_case = 14;
- else
- table_case = 15;
-
- if (coex_stat->bt_a2dp_active || wl_bw == 0)
- tdma_case = 18;
- else if (coex_stat->wl_gl_busy)
- tdma_case = 8;
- else
- tdma_case = 4;
+ if (coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] > 5) {
+ table_case = 26;
+ tdma_case = 2;
+ } else {
+ table_case = 27;
+ tdma_case = 9;
+ }
} else {
- if (coex_stat->bt_a2dp_active || wl_bw == 0) {
- table_case = 8;
- tdma_case = 4;
+ /* Legacy HID */
+ if (coex_stat->bt_profile_num == 1 &&
+ (coex_stat->bt_multi_link ||
+ (coex_stat->lo_pri_rx +
+ coex_stat->lo_pri_tx > 360) ||
+ coex_stat->bt_slave ||
+ bt_multi_link_remain)) {
+ slot_type = TDMA_4SLOT;
+ table_case = 12;
+ tdma_case = 20;
+ } else if (coex_stat->bt_a2dp_active) {
+ table_case = 9;
+ tdma_case = 18;
+ } else if (coex_stat->bt_418_hid_exist &&
+ coex_stat->wl_gl_busy) {
+ is_toggle_table = true;
+ slot_type = TDMA_4SLOT;
+ table_case = 9;
+ tdma_case = 24;
+ } else if (coex_stat->bt_ble_hid_exist &&
+ coex_stat->wl_gl_busy) {
+ table_case = 32;
+ tdma_case = 9;
} else {
- /* for 4/18 HID */
- if (coex_stat->bt_418_hid_exist &&
- coex_stat->wl_gl_busy)
- table_case = 12;
- else
- table_case = 10;
- tdma_case = 4;
+ table_case = 9;
+ tdma_case = 9;
}
}
} else {
/* Non-Shared-Ant */
- if (coex_stat->bt_a2dp_active) {
- table_case = 113;
- tdma_case = 118;
- } else if (coex_stat->bt_ble_exist) {
+ if (coex_stat->bt_ble_exist) {
/* BLE */
+ if (coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] > 5) {
+ table_case = 121;
+ tdma_case = 102;
+ } else {
+ table_case = 122;
+ tdma_case = 109;
+ }
+ } else if (coex_stat->bt_a2dp_active) {
table_case = 113;
-
- if (coex_stat->wl_gl_busy)
- tdma_case = 106;
- else
- tdma_case = 104;
+ tdma_case = 118;
} else {
table_case = 113;
tdma_case = 104;
}
}
- rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
- rtw_coex_table(rtwdev, table_case);
- rtw_coex_tdma(rtwdev, false, tdma_case);
+ rtw_coex_table(rtwdev, false, table_case);
+ if (is_toggle_table) {
+ rtw_btc_wltoggle_table_a(rtwdev, true, table_case);
+ rtw_btc_wltoggle_table_b(rtwdev, false, 1, COEX_WL_SLOT_TOGLLE);
+ }
+
+ rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
}
static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev)
@@ -1512,19 +1936,24 @@ static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev)
u8 table_case, tdma_case;
u32 slot_type = 0;
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
+
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+
+ slot_type = TDMA_4SLOT;
+
if (efuse->share_ant) {
/* Shared-Ant */
- slot_type = TDMA_4SLOT;
-
if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
- table_case = 10;
+ table_case = 12;
else
table_case = 9;
- if (coex_stat->wl_gl_busy)
- tdma_case = 13;
- else
+ if (coex_stat->wl_connecting || !coex_stat->wl_gl_busy)
tdma_case = 14;
+ else
+ tdma_case = 13;
} else {
/* Non-Shared-Ant */
table_case = 112;
@@ -1535,9 +1964,7 @@ static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev)
tdma_case = 113;
}
- rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
- rtw_coex_table(rtwdev, table_case);
+ rtw_coex_table(rtwdev, false, table_case);
rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
}
@@ -1550,6 +1977,11 @@ static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev)
u8 table_case, tdma_case;
bool ap_enable = false;
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
+
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+
if (efuse->share_ant) { /* Shared-Ant */
if (ap_enable) {
table_case = 2;
@@ -1571,9 +2003,7 @@ static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev)
}
}
- rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
- rtw_coex_table(rtwdev, table_case);
+ rtw_coex_table(rtwdev, false, table_case);
rtw_coex_tdma(rtwdev, false, tdma_case);
}
@@ -1585,6 +2015,10 @@ static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev)
struct rtw_chip_info *chip = rtwdev->chip;
u8 table_case, tdma_case;
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+
if (efuse->share_ant) {
/* Shared-Ant */
if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
@@ -1595,7 +2029,7 @@ static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev)
if (coex_stat->wl_gl_busy)
tdma_case = 17;
else
- tdma_case = 19;
+ tdma_case = 20;
} else {
/* Non-Shared-Ant */
table_case = 112;
@@ -1606,9 +2040,7 @@ static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev)
tdma_case = 119;
}
- rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
- rtw_coex_table(rtwdev, table_case);
+ rtw_coex_table(rtwdev, false, table_case);
rtw_coex_tdma(rtwdev, false, tdma_case);
}
@@ -1619,22 +2051,34 @@ static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev)
struct rtw_coex_dm *coex_dm = &coex->dm;
struct rtw_efuse *efuse = &rtwdev->efuse;
struct rtw_chip_info *chip = rtwdev->chip;
- u8 table_case, tdma_case;
+ u8 table_case, tdma_case, interval;
u32 slot_type = 0;
+ bool is_toggle_table = false;
+
+ slot_type = TDMA_4SLOT;
+
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
if (efuse->share_ant) {
/* Shared-Ant */
- slot_type = TDMA_4SLOT;
-
- if (coex_stat->bt_ble_exist)
- table_case = 26;
- else
+ if (coex_stat->bt_ble_exist) {
+ table_case = 26; /* for RCU */
+ } else if (coex_stat->bt_418_hid_exist) {
table_case = 9;
-
- if (coex_stat->wl_gl_busy) {
- tdma_case = 13;
+ interval = 1;
} else {
+ table_case = 9;
+ }
+
+ if (coex_stat->wl_connecting || !coex_stat->wl_gl_busy) {
tdma_case = 14;
+ } else if (coex_stat->bt_418_hid_exist) {
+ is_toggle_table = true;
+ tdma_case = 23;
+ } else {
+ tdma_case = 13;
}
} else {
/* Non-Shared-Ant */
@@ -1649,9 +2093,11 @@ static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev)
tdma_case = 113;
}
- rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
- rtw_coex_table(rtwdev, table_case);
+ rtw_coex_table(rtwdev, false, table_case);
+ if (is_toggle_table) {
+ rtw_btc_wltoggle_table_a(rtwdev, true, table_case);
+ rtw_btc_wltoggle_table_b(rtwdev, false, interval, COEX_WL_SLOT_TOGLLE);
+ }
rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
}
@@ -1662,19 +2108,37 @@ static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev)
struct rtw_efuse *efuse = &rtwdev->efuse;
struct rtw_chip_info *chip = rtwdev->chip;
u8 table_case, tdma_case;
+ bool wl_cpt_test = false, bt_cpt_test = false;
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
+
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
if (efuse->share_ant) {
/* Shared-Ant */
- if (coex_stat->wl_gl_busy &&
- coex_stat->wl_noisy_level == 0)
- table_case = 14;
- else
- table_case = 10;
+ if (wl_cpt_test) {
+ if (coex_stat->wl_gl_busy) {
+ table_case = 20;
+ tdma_case = 17;
+ } else {
+ table_case = 10;
+ tdma_case = 15;
+ }
+ } else if (bt_cpt_test) {
+ table_case = 26;
+ tdma_case = 26;
+ } else {
+ if (coex_stat->wl_gl_busy &&
+ coex_stat->wl_noisy_level == 0)
+ table_case = 14;
+ else
+ table_case = 10;
- if (coex_stat->wl_gl_busy)
- tdma_case = 15;
- else
- tdma_case = 20;
+ if (coex_stat->wl_gl_busy)
+ tdma_case = 15;
+ else
+ tdma_case = 20;
+ }
} else {
/* Non-Shared-Ant */
table_case = 112;
@@ -1685,9 +2149,12 @@ static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev)
tdma_case = 120;
}
- rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
- rtw_coex_table(rtwdev, table_case);
+ if (wl_cpt_test)
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[1]);
+ else
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+
+ rtw_coex_table(rtwdev, false, table_case);
rtw_coex_tdma(rtwdev, false, tdma_case);
}
@@ -1699,6 +2166,11 @@ static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev)
struct rtw_chip_info *chip = rtwdev->chip;
u8 table_case, tdma_case;
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
+
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+
if (efuse->share_ant) {
/* Shared-Ant */
table_case = 9;
@@ -1717,9 +2189,7 @@ static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev)
tdma_case = 119;
}
- rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
- rtw_coex_table(rtwdev, table_case);
+ rtw_coex_table(rtwdev, false, table_case);
rtw_coex_tdma(rtwdev, false, tdma_case);
}
@@ -1731,6 +2201,10 @@ static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev)
struct rtw_chip_info *chip = rtwdev->chip;
u8 table_case, tdma_case;
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+
if (efuse->share_ant) {
/* Shared-Ant */
table_case = 10;
@@ -1749,9 +2223,7 @@ static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev)
tdma_case = 120;
}
- rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
- rtw_coex_table(rtwdev, table_case);
+ rtw_coex_table(rtwdev, false, table_case);
rtw_coex_tdma(rtwdev, false, tdma_case);
}
@@ -1761,6 +2233,11 @@ static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev)
struct rtw_chip_info *chip = rtwdev->chip;
u8 table_case, tdma_case;
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
+
+ rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+
rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
if (efuse->share_ant) {
@@ -1773,9 +2250,7 @@ static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev)
tdma_case = 100;
}
- rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
- rtw_coex_table(rtwdev, table_case);
+ rtw_coex_table(rtwdev, false, table_case);
rtw_coex_tdma(rtwdev, false, tdma_case);
}
@@ -1785,6 +2260,10 @@ static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev)
struct rtw_chip_info *chip = rtwdev->chip;
u8 table_case, tdma_case;
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+
if (efuse->share_ant) {
/* Shared-Ant */
table_case = 2;
@@ -1795,9 +2274,7 @@ static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev)
tdma_case = 100;
}
- rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
- rtw_coex_table(rtwdev, table_case);
+ rtw_coex_table(rtwdev, false, table_case);
rtw_coex_tdma(rtwdev, false, tdma_case);
}
@@ -1811,6 +2288,11 @@ static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev)
if (coex->under_5g)
return;
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
+
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+
if (efuse->share_ant) {
/* Shared-Ant */
table_case = 28;
@@ -1821,9 +2303,7 @@ static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev)
tdma_case = 100;
}
- rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
- rtw_coex_table(rtwdev, table_case);
+ rtw_coex_table(rtwdev, false, table_case);
rtw_coex_tdma(rtwdev, false, tdma_case);
}
@@ -1836,8 +2316,11 @@ static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev)
u8 table_case, tdma_case;
u32 slot_type = 0;
- if (efuse->share_ant) {
- /* Shared-Ant */
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+
+ if (efuse->share_ant) { /* Shared-Ant */
if (coex_stat->bt_a2dp_exist) {
slot_type = TDMA_4SLOT;
table_case = 9;
@@ -1846,9 +2329,9 @@ static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev)
table_case = 9;
tdma_case = 7;
}
- } else {
- /* Non-Shared-Ant */
+ } else { /* Non-Shared-Ant */
if (coex_stat->bt_a2dp_exist) {
+ slot_type = TDMA_4SLOT;
table_case = 112;
tdma_case = 111;
} else {
@@ -1857,9 +2340,7 @@ static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev)
}
}
- rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
- rtw_coex_table(rtwdev, table_case);
+ rtw_coex_table(rtwdev, false, table_case);
rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
}
@@ -1869,6 +2350,10 @@ static void rtw_coex_action_wl_not_connected(struct rtw_dev *rtwdev)
struct rtw_chip_info *chip = rtwdev->chip;
u8 table_case, tdma_case;
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+
if (efuse->share_ant) {
/* Shared-Ant */
table_case = 1;
@@ -1879,9 +2364,7 @@ static void rtw_coex_action_wl_not_connected(struct rtw_dev *rtwdev)
tdma_case = 100;
}
- rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
- rtw_coex_table(rtwdev, table_case);
+ rtw_coex_table(rtwdev, false, table_case);
rtw_coex_tdma(rtwdev, false, tdma_case);
}
@@ -1889,17 +2372,9 @@ static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev)
{
struct rtw_coex *coex = &rtwdev->coex;
struct rtw_coex_stat *coex_stat = &coex->stat;
- struct rtw_coex_dm *coex_dm = &coex->dm;
- struct rtw_efuse *efuse = &rtwdev->efuse;
u8 algorithm;
- /* Non-Shared-Ant */
- if (!efuse->share_ant && coex_stat->wl_gl_busy &&
- COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&
- COEX_RSSI_HIGH(coex_dm->bt_rssi_state[0])) {
- rtw_coex_action_freerun(rtwdev);
- return;
- }
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
algorithm = rtw_coex_algorithm(rtwdev);
@@ -1908,10 +2383,15 @@ static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev)
rtw_coex_action_bt_hfp(rtwdev);
break;
case COEX_ALGO_HID:
- rtw_coex_action_bt_hid(rtwdev);
+ if (rtw_coex_freerun_check(rtwdev))
+ rtw_coex_action_freerun(rtwdev);
+ else
+ rtw_coex_action_bt_hid(rtwdev);
break;
case COEX_ALGO_A2DP:
- if (coex_stat->bt_a2dp_sink)
+ if (rtw_coex_freerun_check(rtwdev))
+ rtw_coex_action_freerun(rtwdev);
+ else if (coex_stat->bt_a2dp_sink)
rtw_coex_action_bt_a2dpsink(rtwdev);
else
rtw_coex_action_bt_a2dp(rtwdev);
@@ -1920,7 +2400,10 @@ static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev)
rtw_coex_action_bt_pan(rtwdev);
break;
case COEX_ALGO_A2DP_HID:
- rtw_coex_action_bt_a2dp_hid(rtwdev);
+ if (rtw_coex_freerun_check(rtwdev))
+ rtw_coex_action_freerun(rtwdev);
+ else
+ rtw_coex_action_bt_a2dp_hid(rtwdev);
break;
case COEX_ALGO_A2DP_PAN:
rtw_coex_action_bt_a2dp_pan(rtwdev);
@@ -1943,6 +2426,7 @@ static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason)
struct rtw_coex *coex = &rtwdev->coex;
struct rtw_coex_dm *coex_dm = &coex->dm;
struct rtw_coex_stat *coex_stat = &coex->stat;
+ bool rf4ce_en = false;
lockdep_assert_held(&rtwdev->mutex);
@@ -1951,20 +2435,38 @@ static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason)
coex_dm->reason = reason;
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): reason = %d\n", __func__,
+ reason);
+
/* update wifi_link_info_ext variable */
rtw_coex_update_wl_link_info(rtwdev, reason);
rtw_coex_monitor_bt_enable(rtwdev);
- if (coex->stop_dm)
+ if (coex->manual_control) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], return for Manual CTRL!!\n");
return;
+ }
- if (coex_stat->wl_under_ips)
+ if (coex->stop_dm) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], return for Stop Coex DM!!\n");
return;
+ }
+
+ if (coex_stat->wl_under_ips) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], return for wifi is under IPS!!\n");
+ return;
+ }
if (coex->freeze && coex_dm->reason == COEX_RSN_BTINFO &&
- !coex_stat->bt_setup_link)
+ !coex_stat->bt_setup_link) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], return for coex_freeze!!\n");
return;
+ }
coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN]++;
coex->freerun = false;
@@ -1976,10 +2478,16 @@ static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason)
goto exit;
}
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], WiFi is single-port 2G!!\n");
coex_stat->wl_coex_mode = COEX_WLINK_2G1PORT;
- rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
+
if (coex_stat->bt_disabled) {
- rtw_coex_action_wl_only(rtwdev);
+ if (coex_stat->wl_connected && rf4ce_en)
+ rtw_coex_action_rf4ce(rtwdev);
+ else if (!coex_stat->wl_connected)
+ rtw_coex_action_wl_not_connected(rtwdev);
+ else
+ rtw_coex_action_wl_only(rtwdev);
goto exit;
}
@@ -2010,18 +2518,21 @@ static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason)
goto exit;
}
- if (coex_stat->wl_linkscan_proc) {
+ if (coex_stat->wl_linkscan_proc && !coex->freerun) {
rtw_coex_action_wl_linkscan(rtwdev);
goto exit;
}
- if (coex_stat->wl_connected)
+ if (coex_stat->wl_connected) {
rtw_coex_action_wl_connected(rtwdev);
- else
+ goto exit;
+ } else {
rtw_coex_action_wl_not_connected(rtwdev);
+ goto exit;
+ }
exit:
- rtw_coex_set_gnt_fix(rtwdev);
+ rtw_coex_gnt_workaround(rtwdev, false, coex_stat->wl_coex_mode);
rtw_coex_limited_wl(rtwdev);
}
@@ -2048,14 +2559,26 @@ static void rtw_coex_init_coex_var(struct rtw_dev *rtwdev)
coex_dm->wl_rssi_state[i] = COEX_RSSI_STATE_LOW;
coex_stat->wl_coex_mode = COEX_WLINK_MAX;
+ coex_stat->wl_rx_rate = DESC_RATE5_5M;
+ coex_stat->wl_rts_rx_rate = DESC_RATE5_5M;
}
static void __rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
{
struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
rtw_coex_init_coex_var(rtwdev);
+
+ coex_stat->kt_ver = u8_get_bits(rtw_read8(rtwdev, 0xf1), GENMASK(7, 4));
+
rtw_coex_monitor_bt_enable(rtwdev);
+ rtw_coex_wl_slot_extend(rtwdev, coex_stat->wl_slot_extend);
+
+ rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
+
rtw_coex_set_rfe_type(rtwdev);
rtw_coex_set_init(rtwdev);
@@ -2073,21 +2596,24 @@ static void __rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);
rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);
coex->stop_dm = true;
+
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): RF Off\n",
+ __func__);
} else if (wifi_only) {
rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WONLY);
- rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN,
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF,
true);
coex->stop_dm = true;
} else {
rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_INIT);
- rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN,
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF,
true);
coex->stop_dm = false;
coex->freeze = true;
}
/* PTA parameter */
- rtw_coex_table(rtwdev, 0);
+ rtw_coex_table(rtwdev, true, 1);
rtw_coex_tdma(rtwdev, true, 0);
rtw_coex_query_bt_info(rtwdev);
}
@@ -2095,12 +2621,16 @@ static void __rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
void rtw_coex_power_on_setting(struct rtw_dev *rtwdev)
{
struct rtw_coex *coex = &rtwdev->coex;
+ u8 table_case = 1;
+
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
coex->stop_dm = true;
coex->wl_rf_off = false;
/* enable BB, we can write 0x948 */
- rtw_write8_set(rtwdev, REG_SYS_FUNC_EN, BIT(0) | BIT(1));
+ rtw_write8_set(rtwdev, REG_SYS_FUNC_EN,
+ BIT_FEN_BB_GLB_RST | BIT_FEN_BB_RSTB);
rtw_coex_monitor_bt_enable(rtwdev);
rtw_coex_set_rfe_type(rtwdev);
@@ -2108,8 +2638,10 @@ void rtw_coex_power_on_setting(struct rtw_dev *rtwdev)
/* set antenna path to BT */
rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_POWERON);
+ rtw_coex_table(rtwdev, true, table_case);
/* red x issue */
rtw_write8(rtwdev, 0xff1a, 0x0);
+ rtw_coex_set_gnt_debug(rtwdev);
}
void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
@@ -2122,10 +2654,12 @@ void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type)
struct rtw_coex *coex = &rtwdev->coex;
struct rtw_coex_stat *coex_stat = &coex->stat;
- if (coex->stop_dm)
+ if (coex->manual_control || coex->stop_dm)
return;
if (type == COEX_IPS_ENTER) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], IPS ENTER notify\n");
+
coex_stat->wl_under_ips = true;
/* for lps off */
@@ -2134,11 +2668,11 @@ void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type)
rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);
rtw_coex_action_coex_all_off(rtwdev);
} else if (type == COEX_IPS_LEAVE) {
- rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], IPS LEAVE notify\n");
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);
/* run init hw config (exclude wifi only) */
__rtw_coex_init_hw_config(rtwdev, false);
- /* sw all off */
coex_stat->wl_under_ips = false;
}
@@ -2149,10 +2683,12 @@ void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type)
struct rtw_coex *coex = &rtwdev->coex;
struct rtw_coex_stat *coex_stat = &coex->stat;
- if (coex->stop_dm)
+ if (coex->manual_control || coex->stop_dm)
return;
if (type == COEX_LPS_ENABLE) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], LPS ENABLE notify\n");
+
coex_stat->wl_under_lps = true;
if (coex_stat->wl_force_lps_ctrl) {
@@ -2161,10 +2697,13 @@ void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type)
} else {
/* for native ps */
rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false);
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_WLBUSY, false);
rtw_coex_run_coex(rtwdev, COEX_RSN_LPS);
}
} else if (type == COEX_LPS_DISABLE) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], LPS DISABLE notify\n");
+
coex_stat->wl_under_lps = false;
/* for lps off */
@@ -2172,6 +2711,8 @@ void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type)
if (!coex_stat->wl_force_lps_ctrl)
rtw_coex_query_bt_info(rtwdev);
+
+ rtw_coex_run_coex(rtwdev, COEX_RSN_LPS);
}
}
@@ -2180,25 +2721,34 @@ void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type)
struct rtw_coex *coex = &rtwdev->coex;
struct rtw_coex_stat *coex_stat = &coex->stat;
- if (coex->stop_dm)
+ if (coex->manual_control || coex->stop_dm)
return;
coex->freeze = false;
-
- if (type != COEX_SCAN_FINISH)
- rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN |
- COEX_SCBD_ONOFF, true);
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);
if (type == COEX_SCAN_START_5G) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], SCAN START notify (5G)\n");
+
rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
rtw_coex_run_coex(rtwdev, COEX_RSN_5GSCANSTART);
} else if ((type == COEX_SCAN_START_2G) || (type == COEX_SCAN_START)) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], SCAN START notify (2G)\n");
+
coex_stat->wl_hi_pri_task2 = true;
/* Force antenna setup for no scan result issue */
rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
rtw_coex_run_coex(rtwdev, COEX_RSN_2GSCANSTART);
} else {
+ coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] = 30; /* To do */
+
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], SCAN FINISH notify (Scan-AP = %d)\n",
+ coex_stat->cnt_wl[COEX_CNT_WL_SCANAP]);
+
coex_stat->wl_hi_pri_task2 = false;
rtw_coex_run_coex(rtwdev, COEX_RSN_SCANFINISH);
}
@@ -2208,9 +2758,20 @@ void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type)
{
struct rtw_coex *coex = &rtwdev->coex;
- if (coex->stop_dm)
+ if (coex->manual_control || coex->stop_dm)
return;
+ if (type == COEX_SWITCH_TO_5G) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): TO_5G\n",
+ __func__);
+ } else if (type == COEX_SWITCH_TO_24G_NOFORSCAN) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], %s(): TO_24G_NOFORSCAN\n", __func__);
+ } else {
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): TO_2G\n",
+ __func__);
+ }
+
if (type == COEX_SWITCH_TO_5G)
rtw_coex_run_coex(rtwdev, COEX_RSN_5GSWITCHBAND);
else if (type == COEX_SWITCH_TO_24G_NOFORSCAN)
@@ -2224,22 +2785,33 @@ void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type)
struct rtw_coex *coex = &rtwdev->coex;
struct rtw_coex_stat *coex_stat = &coex->stat;
- if (coex->stop_dm)
+ if (coex->manual_control || coex->stop_dm)
return;
- rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN |
- COEX_SCBD_ONOFF, true);
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);
if (type == COEX_ASSOCIATE_5G_START) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G start\n",
+ __func__);
+
rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONSTART);
} else if (type == COEX_ASSOCIATE_5G_FINISH) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G finish\n",
+ __func__);
+
rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONFINISH);
} else if (type == COEX_ASSOCIATE_START) {
coex_stat->wl_hi_pri_task1 = true;
+ coex_stat->wl_connecting = true;
coex_stat->cnt_wl[COEX_CNT_WL_CONNPKT] = 2;
+ coex_stat->wl_connecting = true;
+ ieee80211_queue_delayed_work(rtwdev->hw,
+ &coex->wl_connecting_work, 2 * HZ);
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G start\n",
+ __func__);
/* Force antenna setup for no scan result issue */
rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
@@ -2254,7 +2826,10 @@ void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type)
} else {
coex_stat->wl_hi_pri_task1 = false;
coex->freeze = false;
+ coex_stat->wl_connecting = false;
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G finish\n",
+ __func__);
rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONFINISH);
}
}
@@ -2263,17 +2838,22 @@ void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type)
{
struct rtw_coex *coex = &rtwdev->coex;
struct rtw_coex_stat *coex_stat = &coex->stat;
- u8 para[6] = {0};
- if (coex->stop_dm)
+ if (coex->manual_control || coex->stop_dm)
return;
if (type == COEX_MEDIA_CONNECT_5G) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G\n", __func__);
+
rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
rtw_coex_run_coex(rtwdev, COEX_RSN_5GMEDIA);
} else if (type == COEX_MEDIA_CONNECT) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G\n", __func__);
+
+ coex_stat->wl_connecting = false;
+
rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
/* Force antenna setup for no scan result issue */
@@ -2281,18 +2861,11 @@ void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type)
/* Set CCK Rx high Pri */
rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 1);
-
- /* always enable 5ms extend if connect */
- para[0] = COEX_H2C69_WL_LEAKAP;
- para[1] = PARA1_H2C69_EN_5MS; /* enable 5ms extend */
- rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
- coex_stat->wl_slot_extend = true;
rtw_coex_run_coex(rtwdev, COEX_RSN_2GMEDIA);
} else {
- rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false);
-
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): disconnect!!\n",
+ __func__);
rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 0);
-
rtw_coex_run_coex(rtwdev, COEX_RSN_MEDIADISCON);
}
@@ -2304,25 +2877,35 @@ void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
struct rtw_coex *coex = &rtwdev->coex;
struct rtw_coex_stat *coex_stat = &coex->stat;
struct rtw_chip_info *chip = rtwdev->chip;
- unsigned long bt_relink_time;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ u32 bt_relink_time;
u8 i, rsp_source = 0, type;
bool inq_page = false;
rsp_source = buf[0] & 0xf;
if (rsp_source >= COEX_BTINFO_SRC_MAX)
- rsp_source = COEX_BTINFO_SRC_WL_FW;
+ return;
+ coex_stat->cnt_bt_info_c2h[rsp_source]++;
if (rsp_source == COEX_BTINFO_SRC_BT_IQK) {
coex_stat->bt_iqk_state = buf[1];
- if (coex_stat->bt_iqk_state == 1)
+ if (coex_stat->bt_iqk_state == 0)
coex_stat->cnt_bt[COEX_CNT_BT_IQK]++;
else if (coex_stat->bt_iqk_state == 2)
coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]++;
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], BT IQK by bt_info, data0 = 0x%02x\n",
+ buf[1]);
+
return;
}
if (rsp_source == COEX_BTINFO_SRC_BT_SCBD) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], BT Scoreboard change notify by WL FW c2h, 0xaa = 0x%02x, 0xab = 0x%02x\n",
+ buf[1], buf[2]);
+
rtw_coex_monitor_bt_enable(rtwdev);
if (coex_stat->bt_disabled != coex_stat->bt_disabled_pre) {
coex_stat->bt_disabled_pre = coex_stat->bt_disabled;
@@ -2331,6 +2914,24 @@ void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
return;
}
+ if (rsp_source == COEX_BTINFO_SRC_H2C60) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], H2C 0x60 content replied by WL FW: H2C_0x60 = [%02x %02x %02x %02x %02x]\n",
+ buf[1], buf[2], buf[3], buf[4], buf[5]);
+
+ for (i = 1; i <= COEX_WL_TDMA_PARA_LENGTH; i++)
+ coex_dm->fw_tdma_para[i - 1] = buf[i];
+ return;
+ }
+
+ if (rsp_source == COEX_BTINFO_SRC_WL_FW) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], bt_info reply by WL FW\n");
+
+ rtw_coex_update_bt_link_info(rtwdev);
+ return;
+ }
+
if (rsp_source == COEX_BTINFO_SRC_BT_RSP ||
rsp_source == COEX_BTINFO_SRC_BT_ACT) {
if (coex_stat->bt_disabled) {
@@ -2339,30 +2940,36 @@ void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
ieee80211_queue_delayed_work(rtwdev->hw,
&coex->bt_reenable_work,
15 * HZ);
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], BT enable detected by bt_info\n");
}
}
- for (i = 0; i < length; i++) {
- if (i < COEX_BTINFO_LENGTH_MAX)
- coex_stat->bt_info_c2h[rsp_source][i] = buf[i];
- else
- break;
- }
+ if (length != COEX_BTINFO_LENGTH) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], Bt_info length = %d invalid!!\n", length);
- if (rsp_source == COEX_BTINFO_SRC_WL_FW) {
- rtw_coex_update_bt_link_info(rtwdev);
- rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
return;
}
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], Bt_info[%d], len=%d, data=[%02x %02x %02x %02x %02x %02x]\n",
+ buf[0], length, buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+
+ for (i = 0; i < COEX_BTINFO_LENGTH; i++)
+ coex_stat->bt_info_c2h[rsp_source][i] = buf[i];
+
/* get the same info from bt, skip it */
if (coex_stat->bt_info_c2h[rsp_source][1] == coex_stat->bt_info_lb2 &&
coex_stat->bt_info_c2h[rsp_source][2] == coex_stat->bt_info_lb3 &&
coex_stat->bt_info_c2h[rsp_source][3] == coex_stat->bt_info_hb0 &&
coex_stat->bt_info_c2h[rsp_source][4] == coex_stat->bt_info_hb1 &&
coex_stat->bt_info_c2h[rsp_source][5] == coex_stat->bt_info_hb2 &&
- coex_stat->bt_info_c2h[rsp_source][6] == coex_stat->bt_info_hb3)
+ coex_stat->bt_info_c2h[rsp_source][6] == coex_stat->bt_info_hb3) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], Return because Btinfo duplicate!!\n");
return;
+ }
coex_stat->bt_info_lb2 = coex_stat->bt_info_c2h[rsp_source][1];
coex_stat->bt_info_lb3 = coex_stat->bt_info_c2h[rsp_source][2];
@@ -2388,6 +2995,40 @@ void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
4 * HZ);
}
coex_stat->bt_acl_busy = ((coex_stat->bt_info_lb2 & BIT(3)) == BIT(3));
+ if (chip->ble_hid_profile_support) {
+ if (coex_stat->bt_info_lb2 & BIT(5)) {
+ if (coex_stat->bt_info_hb1 & BIT(0)) {
+ /*BLE HID*/
+ coex_stat->bt_ble_hid_exist = true;
+ } else {
+ coex_stat->bt_ble_hid_exist = false;
+ }
+ coex_stat->bt_ble_exist = false;
+ } else if (coex_stat->bt_info_hb1 & BIT(0)) {
+ /*RCU*/
+ coex_stat->bt_ble_hid_exist = false;
+ coex_stat->bt_ble_exist = true;
+ } else {
+ coex_stat->bt_ble_hid_exist = false;
+ coex_stat->bt_ble_exist = false;
+ }
+ } else {
+ if (coex_stat->bt_info_hb1 & BIT(0)) {
+ if (coex_stat->bt_hid_slot == 1 &&
+ coex_stat->hi_pri_rx + 100 < coex_stat->hi_pri_tx &&
+ coex_stat->hi_pri_rx < 100) {
+ coex_stat->bt_ble_hid_exist = true;
+ coex_stat->bt_ble_exist = false;
+ } else {
+ coex_stat->bt_ble_hid_exist = false;
+ coex_stat->bt_ble_exist = true;
+ }
+ } else {
+ coex_stat->bt_ble_hid_exist = false;
+ coex_stat->bt_ble_exist = false;
+ }
+ }
+
coex_stat->cnt_bt[COEX_CNT_BT_RETRY] = coex_stat->bt_info_lb3 & 0xf;
if (coex_stat->cnt_bt[COEX_CNT_BT_RETRY] >= 1)
coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]++;
@@ -2398,22 +3039,13 @@ void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
coex_stat->cnt_bt[COEX_CNT_BT_INQ]++;
coex_stat->bt_page = ((coex_stat->bt_info_lb3 & BIT(7)) == BIT(7));
- if (coex_stat->bt_page) {
+ if (coex_stat->bt_page)
coex_stat->cnt_bt[COEX_CNT_BT_PAGE]++;
- if (coex_stat->wl_linkscan_proc ||
- coex_stat->wl_hi_pri_task1 ||
- coex_stat->wl_hi_pri_task2 || coex_stat->wl_gl_busy)
- rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, true);
- else
- rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false);
- } else {
- rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false);
- }
/* unit: % (value-100 to translate to unit: dBm in coex info) */
if (chip->bt_rssi_type == COEX_BTRSSI_RATIO) {
coex_stat->bt_rssi = coex_stat->bt_info_hb0 * 2 + 10;
- } else { /* original unit: dbm -> unit: % -> value-100 in coex info */
+ } else {
if (coex_stat->bt_info_hb0 <= 127)
coex_stat->bt_rssi = 100;
else if (256 - coex_stat->bt_info_hb0 <= 100)
@@ -2422,7 +3054,6 @@ void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
coex_stat->bt_rssi = 0;
}
- coex_stat->bt_ble_exist = ((coex_stat->bt_info_hb1 & BIT(0)) == BIT(0));
if (coex_stat->bt_info_hb1 & BIT(1))
coex_stat->cnt_bt[COEX_CNT_BT_REINIT]++;
@@ -2432,11 +3063,14 @@ void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
if (coex_stat->bt_reenable)
bt_relink_time = 6 * HZ;
else
- bt_relink_time = 2 * HZ;
+ bt_relink_time = 1 * HZ;
ieee80211_queue_delayed_work(rtwdev->hw,
&coex->bt_relink_work,
bt_relink_time);
+
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], Re-Link start in BT info!!\n");
}
if (coex_stat->bt_info_hb1 & BIT(3))
@@ -2448,8 +3082,21 @@ void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH]++;
coex_stat->bt_multi_link = ((coex_stat->bt_info_hb1 & BIT(7)) == BIT(7));
+ /* for multi_link = 0 but bt pkt remain exist */
+ /* Use PS-TDMA to protect WL RX */
+ if (!coex_stat->bt_multi_link && coex_stat->bt_multi_link_pre) {
+ coex_stat->bt_multi_link_remain = true;
+ ieee80211_queue_delayed_work(rtwdev->hw,
+ &coex->bt_multi_link_remain_work,
+ 3 * HZ);
+ }
+ coex_stat->bt_multi_link_pre = coex_stat->bt_multi_link;
+
/* resend wifi info to bt, it is reset and lost the info */
- if ((coex_stat->bt_info_hb1 & BIT(1))) {
+ if (coex_stat->bt_info_hb1 & BIT(1)) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], BT Re-init, send wifi BW & Chnl to BT!!\n");
+
if (coex_stat->wl_connected)
type = COEX_MEDIA_CONNECT;
else
@@ -2459,8 +3106,11 @@ void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
/* if ignore_wlan_act && not set_up_link */
if ((coex_stat->bt_info_hb1 & BIT(3)) &&
- (!(coex_stat->bt_info_hb1 & BIT(2))))
+ (!(coex_stat->bt_info_hb1 & BIT(2)))) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], BT ext info bit3 check, set BT NOT to ignore Wlan active!!\n");
rtw_coex_ignore_wlan_act(rtwdev, false);
+ }
coex_stat->bt_opp_exist = ((coex_stat->bt_info_hb2 & BIT(0)) == BIT(0));
if (coex_stat->bt_info_hb2 & BIT(1))
@@ -2472,7 +3122,7 @@ void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
coex_stat->bt_hid_pair_num = (coex_stat->bt_info_hb2 & 0xc0) >> 6;
if (coex_stat->bt_hid_pair_num > 0 && coex_stat->bt_hid_slot >= 2)
coex_stat->bt_418_hid_exist = true;
- else if (coex_stat->bt_hid_pair_num == 0)
+ else if (coex_stat->bt_hid_pair_num == 0 || coex_stat->bt_hid_slot == 1)
coex_stat->bt_418_hid_exist = false;
if ((coex_stat->bt_info_lb2 & 0x49) == 0x49)
@@ -2493,6 +3143,9 @@ void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
u8 val;
int i;
+ rtw_dbg(rtwdev, RTW_DBG_COEX,
+ "[BTCoex], WiFi Fw Dbg info = %8ph (len = %d)\n",
+ buf, length);
if (WARN(length < 8, "invalid wl info c2h length\n"))
return;
@@ -2504,7 +3157,7 @@ void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
if (buf[i] >= val)
coex_stat->wl_fw_dbg_info[i] = buf[i] - val;
else
- coex_stat->wl_fw_dbg_info[i] = val - buf[i];
+ coex_stat->wl_fw_dbg_info[i] = 255 - val + buf[i];
coex_stat->wl_fw_dbg_info_pre[i] = buf[i];
}
@@ -2514,13 +3167,8 @@ void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
rtw_coex_wl_ccklock_detect(rtwdev);
}
-void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev)
+void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev, u32 type)
{
- struct rtw_coex *coex = &rtwdev->coex;
-
- if (coex->stop_dm)
- return;
-
rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
}
@@ -2585,6 +3233,41 @@ void rtw_coex_bt_remain_work(struct work_struct *work)
mutex_unlock(&rtwdev->mutex);
}
+void rtw_coex_wl_connecting_work(struct work_struct *work)
+{
+ struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
+ coex.wl_connecting_work.work);
+ struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
+
+ mutex_lock(&rtwdev->mutex);
+ coex_stat->wl_connecting = false;
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], WL connecting stop!!\n");
+ rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
+ mutex_unlock(&rtwdev->mutex);
+}
+
+void rtw_coex_bt_multi_link_remain_work(struct work_struct *work)
+{
+ struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
+ coex.bt_multi_link_remain_work.work);
+ struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
+
+ mutex_lock(&rtwdev->mutex);
+ coex_stat->bt_multi_link_remain = false;
+ mutex_unlock(&rtwdev->mutex);
+}
+
+void rtw_coex_wl_ccklock_work(struct work_struct *work)
+{
+ struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
+ coex.wl_ccklock_work.work);
+ struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
+
+ mutex_lock(&rtwdev->mutex);
+ coex_stat->wl_cck_lock = false;
+ mutex_unlock(&rtwdev->mutex);
+}
+
#ifdef CONFIG_RTW88_DEBUGFS
#define INFO_SIZE 80
@@ -2628,6 +3311,81 @@ static const char *rtw_coex_get_reason_string(u8 reason)
}
}
+static u8 rtw_coex_get_table_index(struct rtw_dev *rtwdev, u32 wl_reg_6c0,
+ u32 wl_reg_6c4)
+{
+ struct rtw_chip_info *chip = rtwdev->chip;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ u8 ans = 0xFF;
+ u8 n, i;
+ u32 load_bt_val;
+ u32 load_wl_val;
+ bool share_ant = efuse->share_ant;
+
+ if (share_ant)
+ n = chip->table_sant_num;
+ else
+ n = chip->table_nsant_num;
+
+ for (i = 0; i < n; i++) {
+ if (share_ant) {
+ load_bt_val = chip->table_sant[i].bt;
+ load_wl_val = chip->table_sant[i].wl;
+ } else {
+ load_bt_val = chip->table_nsant[i].bt;
+ load_wl_val = chip->table_nsant[i].wl;
+ }
+
+ if (wl_reg_6c0 == load_bt_val &&
+ wl_reg_6c4 == load_wl_val) {
+ ans = i;
+ if (!share_ant)
+ ans += 100;
+ break;
+ }
+ }
+
+ return ans;
+}
+
+static u8 rtw_coex_get_tdma_index(struct rtw_dev *rtwdev, u8 *tdma_para)
+{
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 ans = 0xFF;
+ u8 n, i, j;
+ u8 load_cur_tab_val;
+ bool valid = false;
+ bool share_ant = efuse->share_ant;
+
+ if (share_ant)
+ n = chip->tdma_sant_num;
+ else
+ n = chip->tdma_nsant_num;
+
+ for (i = 0; i < n; i++) {
+ valid = false;
+ for (j = 0; j < 5; j++) {
+ if (share_ant)
+ load_cur_tab_val = chip->tdma_sant[i].para[j];
+ else
+ load_cur_tab_val = chip->tdma_nsant[i].para[j];
+
+ if (*(tdma_para + j) != load_cur_tab_val)
+ break;
+
+ if (j == 4)
+ valid = true;
+ }
+ if (valid) {
+ ans = i;
+ break;
+ }
+ }
+
+ return ans;
+}
+
static int rtw_coex_addr_info(struct rtw_dev *rtwdev,
const struct rtw_reg_domain *reg,
char addr_info[], int n)
@@ -2873,6 +3631,19 @@ static void rtw_coex_vif_stat_iter(void *data, u8 *mac,
&sta_iter_data);
}
+#define case_WLINK(src) \
+ case COEX_WLINK_##src: return #src
+
+static const char *rtw_coex_get_wl_coex_mode(u8 coex_wl_link_mode)
+{
+ switch (coex_wl_link_mode) {
+ case_WLINK(2G1PORT);
+ case_WLINK(5G);
+ default:
+ return "Unknown";
+ }
+}
+
void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
{
struct rtw_chip_info *chip = rtwdev->chip;
@@ -2894,14 +3665,23 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
score_board_BW = rtw_coex_read_scbd(rtwdev);
score_board_WB = coex_stat->score_board;
- wl_reg_6c0 = rtw_read32(rtwdev, 0x6c0);
- wl_reg_6c4 = rtw_read32(rtwdev, 0x6c4);
- wl_reg_6c8 = rtw_read32(rtwdev, 0x6c8);
- wl_reg_6cc = rtw_read32(rtwdev, 0x6cc);
- wl_reg_778 = rtw_read32(rtwdev, 0x778);
- bt_hi_pri = rtw_read32(rtwdev, 0x770);
- bt_lo_pri = rtw_read32(rtwdev, 0x774);
- rtw_write8(rtwdev, 0x76e, 0xc);
+ wl_reg_6c0 = rtw_read32(rtwdev, REG_BT_COEX_TABLE0);
+ wl_reg_6c4 = rtw_read32(rtwdev, REG_BT_COEX_TABLE1);
+ wl_reg_6c8 = rtw_read32(rtwdev, REG_BT_COEX_BRK_TABLE);
+ wl_reg_6cc = rtw_read32(rtwdev, REG_BT_COEX_TABLE_H);
+ wl_reg_778 = rtw_read8(rtwdev, REG_BT_STAT_CTRL);
+
+ bt_hi_pri = rtw_read32(rtwdev, REG_BT_ACT_STATISTICS);
+ bt_lo_pri = rtw_read32(rtwdev, REG_BT_ACT_STATISTICS_1);
+ rtw_write8(rtwdev, REG_BT_COEX_ENH_INTR_CTRL,
+ BIT_R_GRANTALL_WLMASK | BIT_STATIS_BT_EN);
+
+ coex_stat->hi_pri_tx = FIELD_GET(MASKLWORD, bt_hi_pri);
+ coex_stat->hi_pri_rx = FIELD_GET(MASKHWORD, bt_hi_pri);
+
+ coex_stat->lo_pri_tx = FIELD_GET(MASKLWORD, bt_lo_pri);
+ coex_stat->lo_pri_rx = FIELD_GET(MASKHWORD, bt_lo_pri);
+
sys_lte = rtw_read8(rtwdev, 0x73);
lte_coex = rtw_coex_read_indirect_reg(rtwdev, 0x38);
bt_coex = rtw_coex_read_indirect_reg(rtwdev, 0x54);
@@ -2919,9 +3699,24 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
coex_stat->bt_mailbox_reply = true;
}
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
seq_printf(m, "**********************************************\n");
seq_printf(m, "\t\tBT Coexist info %x\n", chip->id);
seq_printf(m, "**********************************************\n");
+
+ if (coex->manual_control) {
+ seq_puts(m, "============[Under Manual Control]============\n");
+ seq_puts(m, "==========================================\n");
+
+ } else if (coex->stop_dm) {
+ seq_puts(m, "============[Coex is STOPPED]============\n");
+ seq_puts(m, "==========================================\n");
+
+ } else if (coex->freeze) {
+ seq_puts(m, "============[coex_freeze]============\n");
+ seq_puts(m, "==========================================\n");
+ }
+
seq_printf(m, "%-40s = %s/ %d\n",
"Mech/ RFE",
efuse->share_ant ? "Shared" : "Non-Shared",
@@ -2938,15 +3733,17 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
coex_stat->bt_slave ? "Slave" : "Master",
coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH],
coex_dm->ignore_wl_act);
- seq_printf(m, "%-40s = %u.%u/ 0x%x/ %c\n",
- "WL FW/ BT FW/ KT",
+ seq_printf(m, "%-40s = %u.%u/ 0x%x/ 0x%x/ %c\n",
+ "WL FW/ BT FW/ BT FW Desired/ KT",
fw->version, fw->sub_version,
- coex_stat->patch_ver, coex_stat->kt_ver + 65);
+ coex_stat->patch_ver,
+ chip->wl_fw_desired_ver, coex_stat->kt_ver + 65);
seq_printf(m, "%-40s = %u/ %u/ %u/ ch-(%u)\n",
"AFH Map",
coex_dm->wl_ch_info[0], coex_dm->wl_ch_info[1],
coex_dm->wl_ch_info[2], hal->current_channel);
+ rtw_debugfs_get_simple_phy_info(m);
seq_printf(m, "**********************************************\n");
seq_printf(m, "\t\tBT Status\n");
seq_printf(m, "**********************************************\n");
@@ -2965,6 +3762,7 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
coex_stat->bt_hid_exist ?
(coex_stat->bt_ble_exist ? "HID(RCU)," :
coex_stat->bt_hid_slot >= 2 ? "HID(4/18)" :
+ coex_stat->bt_ble_hid_exist ? "HID(BLE)" :
"HID(2/18),") : "",
coex_stat->bt_pan_exist ? coex_stat->bt_opp_exist ?
"OPP," : "PAN," : "",
@@ -2989,8 +3787,8 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
score_board_WB, score_board_BW);
seq_printf(m, "%-40s = %u/%u, %u/%u\n",
"Hi-Pri TX/RX, Lo-Pri TX/RX",
- bt_hi_pri & 0xffff, bt_hi_pri >> 16,
- bt_lo_pri & 0xffff, bt_lo_pri >> 16);
+ coex_stat->hi_pri_tx, coex_stat->hi_pri_rx,
+ coex_stat->lo_pri_tx, coex_stat->lo_pri_rx);
for (i = 0; i < COEX_BTINFO_SRC_BT_IQK; i++)
seq_printf(m, "%-40s = %7ph\n",
rtw_coex_get_bt_info_src_string(i),
@@ -3015,20 +3813,45 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
vif_iter_data.file = m;
rtw_iterate_vifs_atomic(rtwdev, rtw_coex_vif_stat_iter, &vif_iter_data);
- seq_printf(m, "**********************************************\n");
- seq_printf(m, "\t\tMechanism\n");
- seq_printf(m, "**********************************************\n");
- seq_printf(m, "%-40s = %5ph (case-%d)\n",
- "TDMA",
- coex_dm->ps_tdma_para, coex_dm->cur_ps_tdma);
- seq_printf(m, "%-40s = %d\n",
- "Timer base", coex_stat->tdma_timer_base);
- seq_printf(m, "%-40s = %d/ 0x%08x/ 0x%08x/ 0x%08x\n",
+ if (coex->manual_control) {
+ seq_printf(m, "**********************************************\n");
+ seq_printf(m, "\t\tMechanism (Under Manual)\n");
+ seq_printf(m, "**********************************************\n");
+ seq_printf(m, "%-40s = %5ph (%d)\n",
+ "TDMA Now",
+ coex_dm->fw_tdma_para,
+ rtw_coex_get_tdma_index(rtwdev,
+ &coex_dm->fw_tdma_para[0]));
+ } else {
+ seq_printf(m, "**********************************************\n");
+ seq_printf(m, "\t\tMechanism\n");
+ seq_printf(m, "**********************************************\n");
+ seq_printf(m, "%-40s = %5ph (case-%d)\n",
+ "TDMA",
+ coex_dm->ps_tdma_para, coex_dm->cur_ps_tdma);
+ }
+ seq_printf(m, "%-40s = %s/ %s/ %d\n",
+ "Coex Mode/Free Run/Timer base",
+ rtw_coex_get_wl_coex_mode(coex_stat->wl_coex_mode),
+ coex->freerun ? "Yes" : "No",
+ coex_stat->tdma_timer_base);
+ seq_printf(m, "%-40s = %d(%d)/ 0x%08x/ 0x%08x/ 0x%08x\n",
"Table/ 0x6c0/ 0x6c4/ 0x6c8",
- coex_dm->cur_table, wl_reg_6c0, wl_reg_6c4, wl_reg_6c8);
- seq_printf(m, "%-40s = 0x%08x/ 0x%08x/ reason (%s)\n",
- "0x778/ 0x6cc/ Reason",
- wl_reg_778, wl_reg_6cc, rtw_coex_get_reason_string(reason));
+ coex_dm->cur_table,
+ rtw_coex_get_table_index(rtwdev, wl_reg_6c0, wl_reg_6c4),
+ wl_reg_6c0, wl_reg_6c4, wl_reg_6c8);
+ seq_printf(m, "%-40s = 0x%08x/ 0x%08x/ %d/ reason (%s)\n",
+ "0x778/ 0x6cc/ Run Count/ Reason",
+ wl_reg_778, wl_reg_6cc,
+ coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN],
+ rtw_coex_get_reason_string(reason));
+ seq_printf(m, "%-40s = %3ph\n",
+ "AFH Map to BT",
+ coex_dm->wl_ch_info);
+ seq_printf(m, "%-40s = %s/ %d\n",
+ "AntDiv/ BtCtrlLPS/ g_busy",
+ coex_stat->wl_force_lps_ctrl ? "On" : "Off",
+ coex_stat->wl_gl_busy);
seq_printf(m, "%-40s = %u/ %u/ %u/ %u/ %u\n",
"Null All/ Retry/ Ack/ BT Empty/ BT Late",
coex_stat->wl_fw_dbg_info[1], coex_stat->wl_fw_dbg_info[2],
@@ -3040,6 +3863,12 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
coex_stat->wl_fw_dbg_info[7],
coex_stat->wl_slot_extend ? "Yes" : "No",
coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]);
+ seq_printf(m, "%-40s = %d/ %d/ %s/ %d\n",
+ "WL_TxPw/ BT_TxPw/ WL_Rx/ BT_LNA_Lvl",
+ coex_dm->cur_wl_pwr_lvl,
+ coex_dm->cur_bt_pwr_lvl,
+ coex_dm->cur_wl_rx_low_gain_en ? "On" : "Off",
+ coex_dm->cur_bt_lna_lvl);
seq_printf(m, "**********************************************\n");
seq_printf(m, "\t\tHW setting\n");
@@ -3074,5 +3903,22 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
coex_stat->wl_noisy_level);
rtw_coex_set_coexinfo_hw(rtwdev, m);
+ seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n",
+ "EVM A/ EVM B/ SNR A/ SNR B",
+ -dm_info->rx_evm_dbm[RF_PATH_A],
+ -dm_info->rx_evm_dbm[RF_PATH_B],
+ -dm_info->rx_snr[RF_PATH_A],
+ -dm_info->rx_snr[RF_PATH_B]);
+ seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n",
+ "CCK-CCA/CCK-FA/OFDM-CCA/OFDM-FA",
+ dm_info->cck_cca_cnt, dm_info->cck_fa_cnt,
+ dm_info->ofdm_cca_cnt, dm_info->ofdm_fa_cnt);
+ seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n", "CRC OK CCK/11g/11n/11ac",
+ dm_info->cck_ok_cnt, dm_info->ofdm_ok_cnt,
+ dm_info->ht_ok_cnt, dm_info->vht_ok_cnt);
+ seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n", "CRC Err CCK/11g/11n/11ac",
+ dm_info->cck_err_cnt, dm_info->ofdm_err_cnt,
+ dm_info->ht_err_cnt, dm_info->vht_err_cnt);
+
}
#endif /* CONFIG_RTW88_DEBUGFS */
diff --git a/drivers/net/wireless/realtek/rtw88/coex.h b/drivers/net/wireless/realtek/rtw88/coex.h
index 44720fdfc053..8ab9852ec9ed 100644
--- a/drivers/net/wireless/realtek/rtw88/coex.h
+++ b/drivers/net/wireless/realtek/rtw88/coex.h
@@ -5,12 +5,7 @@
#ifndef __RTW_COEX_H__
#define __RTW_COEX_H__
-/* BT profile map bit definition */
-#define BPM_HFP BIT(0)
-#define BPM_HID BIT(1)
-#define BPM_A2DP BIT(2)
-#define BPM_PAN BIT(3)
-
+#define COEX_CCK_2 0x1
#define COEX_RESP_ACK_BY_WL_FW 0x1
#define COEX_REQUEST_TIMEOUT msecs_to_jiffies(10)
@@ -27,10 +22,19 @@
#define COEX_H2C69_TDMA_SLOT 0xb
#define PARA1_H2C69_TDMA_4SLOT 0xc1
#define PARA1_H2C69_TDMA_2SLOT 0x1
+#define PARA1_H2C69_TBTT_TIMES GENMASK(5, 0)
+#define PARA1_H2C69_TBTT_DIV100 BIT(7)
+
+#define COEX_H2C69_TOGGLE_TABLE_A 0xd
+#define COEX_H2C69_TOGGLE_TABLE_B 0x7
#define TDMA_4SLOT BIT(8)
+#define TDMA_TIMER_TYPE_2SLOT 0
+#define TDMA_TIMER_TYPE_4SLOT 3
+
#define COEX_RSSI_STEP 4
+
#define COEX_RSSI_HIGH(rssi) \
({ typeof(rssi) __rssi__ = rssi; \
(__rssi__ == COEX_RSSI_STATE_HIGH || \
@@ -146,6 +150,25 @@ enum coex_algorithm {
COEX_ALGO_MAX
};
+enum coex_bt_profile {
+ BPM_NOPROFILE = 0,
+ BPM_HFP = BIT(0),
+ BPM_HID = BIT(1),
+ BPM_A2DP = BIT(2),
+ BPM_PAN = BIT(3),
+ BPM_HID_HFP = BPM_HID | BPM_HFP,
+ BPM_A2DP_HFP = BPM_A2DP | BPM_HFP,
+ BPM_A2DP_HID = BPM_A2DP | BPM_HID,
+ BPM_A2DP_HID_HFP = BPM_A2DP | BPM_HID | BPM_HFP,
+ BPM_PAN_HFP = BPM_PAN | BPM_HFP,
+ BPM_PAN_HID = BPM_PAN | BPM_HID,
+ BPM_PAN_HID_HFP = BPM_PAN | BPM_HID | BPM_HFP,
+ BPM_PAN_A2DP = BPM_PAN | BPM_A2DP,
+ BPM_PAN_A2DP_HFP = BPM_PAN | BPM_A2DP | BPM_HFP,
+ BPM_PAN_A2DP_HID = BPM_PAN | BPM_A2DP | BPM_HID,
+ BPM_PAN_A2DP_HID_HFP = BPM_PAN | BPM_A2DP | BPM_HID | BPM_HFP,
+};
+
enum coex_wl_link_mode {
COEX_WLINK_2G1PORT = 0x0,
COEX_WLINK_5G = 0x3,
@@ -365,19 +388,21 @@ void rtw_coex_bt_reenable_work(struct work_struct *work);
void rtw_coex_defreeze_work(struct work_struct *work);
void rtw_coex_wl_remain_work(struct work_struct *work);
void rtw_coex_bt_remain_work(struct work_struct *work);
+void rtw_coex_wl_connecting_work(struct work_struct *work);
+void rtw_coex_bt_multi_link_remain_work(struct work_struct *work);
+void rtw_coex_wl_ccklock_work(struct work_struct *work);
void rtw_coex_power_on_setting(struct rtw_dev *rtwdev);
void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only);
void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type);
void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type);
void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type);
-void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 action);
-void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 status);
-void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 len);
+void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type);
+void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type);
+void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length);
void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length);
void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type);
-void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev);
-
+void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev, u32 type);
void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m);
#endif
diff --git a/drivers/net/wireless/realtek/rtw88/debug.c b/drivers/net/wireless/realtek/rtw88/debug.c
index efbba9caef3b..19fc2d8bf3e9 100644
--- a/drivers/net/wireless/realtek/rtw88/debug.c
+++ b/drivers/net/wireless/realtek/rtw88/debug.c
@@ -619,6 +619,29 @@ static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v)
return 0;
}
+void rtw_debugfs_get_simple_phy_info(struct seq_file *m)
+{
+ struct rtw_debugfs_priv *debugfs_priv = m->private;
+ struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
+ struct rtw_hal *hal = &rtwdev->hal;
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+ struct rtw_traffic_stats *stats = &rtwdev->stats;
+
+ seq_printf(m, "%-40s = %ddBm/ %d\n", "RSSI/ STA Channel",
+ dm_info->rssi[RF_PATH_A] - 100, hal->current_channel);
+
+ seq_printf(m, "TP {Tx, Rx} = {%u, %u}Mbps\n",
+ stats->tx_throughput, stats->rx_throughput);
+
+ seq_puts(m, "[Tx Rate] = ");
+ rtw_print_rate(m, dm_info->tx_rate);
+ seq_printf(m, "(0x%x)\n", dm_info->tx_rate);
+
+ seq_puts(m, "[Rx Rate] = ");
+ rtw_print_rate(m, dm_info->curr_rx_rate);
+ seq_printf(m, "(0x%x)\n", dm_info->curr_rx_rate);
+}
+
static int rtw_debugfs_get_phy_info(struct seq_file *m, void *v)
{
struct rtw_debugfs_priv *debugfs_priv = m->private;
@@ -777,7 +800,7 @@ static ssize_t rtw_debugfs_set_coex_enable(struct file *filp,
}
mutex_lock(&rtwdev->mutex);
- coex->stop_dm = enable == 0;
+ coex->manual_control = enable == 0;
mutex_unlock(&rtwdev->mutex);
return count;
@@ -790,7 +813,7 @@ static int rtw_debugfs_get_coex_enable(struct seq_file *m, void *v)
struct rtw_coex *coex = &rtwdev->coex;
seq_printf(m, "coex mechanism %s\n",
- coex->stop_dm ? "disabled" : "enabled");
+ coex->manual_control ? "disabled" : "enabled");
return 0;
}
diff --git a/drivers/net/wireless/realtek/rtw88/debug.h b/drivers/net/wireless/realtek/rtw88/debug.h
index a0f36f29b4a6..e16e0da26e77 100644
--- a/drivers/net/wireless/realtek/rtw88/debug.h
+++ b/drivers/net/wireless/realtek/rtw88/debug.h
@@ -26,6 +26,7 @@ enum rtw_debug_mask {
#ifdef CONFIG_RTW88_DEBUGFS
void rtw_debugfs_init(struct rtw_dev *rtwdev);
+void rtw_debugfs_get_simple_phy_info(struct seq_file *m);
#else
diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c
index b2fd87834f23..f1453ee24d11 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.c
+++ b/drivers/net/wireless/realtek/rtw88/fw.c
@@ -13,6 +13,7 @@
#include "debug.h"
#include "util.h"
#include "wow.h"
+#include "ps.h"
static void rtw_fw_c2h_cmd_handle_ext(struct rtw_dev *rtwdev,
struct sk_buff *skb)
@@ -183,6 +184,9 @@ void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset,
case C2H_BT_MP_INFO:
rtw_coex_info_response(rtwdev, skb);
break;
+ case C2H_WLAN_RFON:
+ complete(&rtwdev->lps_leave_check);
+ break;
default:
/* pass offset for further operation */
*((u32 *)skb->cb) = pkt_offset;
@@ -628,7 +632,7 @@ void rtw_fw_set_nlo_info(struct rtw_dev *rtwdev, bool enable)
SET_NLO_FUN_EN(h2c_pkt, enable);
if (enable) {
- if (rtw_fw_lps_deep_mode)
+ if (rtw_get_lps_deep_mode(rtwdev) != LPS_DEEP_MODE_NONE)
SET_NLO_PS_32K(h2c_pkt, enable);
SET_NLO_IGNORE_SECURITY(h2c_pkt, enable);
SET_NLO_LOC_NLO_INFO(h2c_pkt, loc_nlo);
diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h
index 08644540d259..39c905c1b1d8 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.h
+++ b/drivers/net/wireless/realtek/rtw88/fw.h
@@ -31,6 +31,7 @@ enum rtw_c2h_cmd_id {
C2H_RA_RPT = 0x0c,
C2H_HW_FEATURE_REPORT = 0x19,
C2H_WLAN_INFO = 0x27,
+ C2H_WLAN_RFON = 0x32,
C2H_HW_FEATURE_DUMP = 0xfd,
C2H_HALMAC = 0xff,
};
@@ -72,6 +73,14 @@ enum rtw_fw_rf_type {
FW_RF_MAX_TYPE = 0xF,
};
+enum rtw_fw_feature {
+ FW_FEATURE_SIG = BIT(0),
+ FW_FEATURE_LPS_C2H = BIT(1),
+ FW_FEATURE_LCLK = BIT(2),
+ FW_FEATURE_PG = BIT(3),
+ FW_FEATURE_MAX = BIT(31),
+};
+
struct rtw_coex_info_req {
u8 seq;
u8 op_code;
@@ -177,7 +186,7 @@ struct rtw_fw_hdr {
u8 subversion;
u8 subindex;
__le32 rsvd; /* 0x08 */
- __le32 rsvd2; /* 0x0C */
+ __le32 feature; /* 0x0C */
u8 month; /* 0x10 */
u8 day;
u8 hour;
diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c
index c92fba2fa480..1f1b639cd124 100644
--- a/drivers/net/wireless/realtek/rtw88/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
@@ -351,6 +351,8 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
{
struct rtw_dev *rtwdev = hw->priv;
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
u32 config = 0;
mutex_lock(&rtwdev->mutex);
@@ -381,6 +383,11 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
config |= PORT_SET_BSSID;
}
+ if (changed & BSS_CHANGED_BEACON_INT) {
+ if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_STATION)
+ coex_stat->wl_beacon_interval = conf->beacon_int;
+ }
+
if (changed & BSS_CHANGED_BEACON)
rtw_fw_download_rsvd_page(rtwdev);
@@ -519,7 +526,7 @@ static int rtw_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
}
/* download new cam settings for PG to backup */
- if (rtw_fw_lps_deep_mode == LPS_DEEP_MODE_PG)
+ if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_PG)
rtw_fw_download_rsvd_page(rtwdev);
out:
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index 565efd880624..47969a6f957c 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -16,17 +16,17 @@
#include "debug.h"
#include "bf.h"
-unsigned int rtw_fw_lps_deep_mode;
-EXPORT_SYMBOL(rtw_fw_lps_deep_mode);
+bool rtw_disable_lps_deep_mode;
+EXPORT_SYMBOL(rtw_disable_lps_deep_mode);
bool rtw_bf_support = true;
unsigned int rtw_debug_mask;
EXPORT_SYMBOL(rtw_debug_mask);
-module_param_named(lps_deep_mode, rtw_fw_lps_deep_mode, uint, 0644);
+module_param_named(disable_lps_deep, rtw_disable_lps_deep_mode, bool, 0644);
module_param_named(support_bf, rtw_bf_support, bool, 0644);
module_param_named(debug_mask, rtw_debug_mask, uint, 0644);
-MODULE_PARM_DESC(lps_deep_mode, "Deeper PS mode. If 0, deep PS is disabled");
+MODULE_PARM_DESC(disable_lps_deep, "Set Y to disable Deep PS");
MODULE_PARM_DESC(support_bf, "Set Y to enable beamformee support");
MODULE_PARM_DESC(debug_mask, "Debugging mask");
@@ -196,7 +196,7 @@ static void rtw_watch_dog_work(struct work_struct *work)
clear_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
if (busy_traffic != test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags))
- rtw_coex_wl_status_change_notify(rtwdev);
+ rtw_coex_wl_status_change_notify(rtwdev, 0);
if (stats->tx_cnt > RTW_LPS_THRESHOLD ||
stats->rx_cnt > RTW_LPS_THRESHOLD)
@@ -1023,6 +1023,26 @@ static int rtw_wait_firmware_completion(struct rtw_dev *rtwdev)
return 0;
}
+static enum rtw_lps_deep_mode rtw_update_lps_deep_mode(struct rtw_dev *rtwdev,
+ struct rtw_fw_state *fw)
+{
+ struct rtw_chip_info *chip = rtwdev->chip;
+
+ if (rtw_disable_lps_deep_mode || !chip->lps_deep_mode_supported ||
+ !fw->feature)
+ return LPS_DEEP_MODE_NONE;
+
+ if ((chip->lps_deep_mode_supported & BIT(LPS_DEEP_MODE_PG)) &&
+ (fw->feature & FW_FEATURE_PG))
+ return LPS_DEEP_MODE_PG;
+
+ if ((chip->lps_deep_mode_supported & BIT(LPS_DEEP_MODE_LCLK)) &&
+ (fw->feature & FW_FEATURE_LCLK))
+ return LPS_DEEP_MODE_LCLK;
+
+ return LPS_DEEP_MODE_NONE;
+}
+
static int rtw_power_on(struct rtw_dev *rtwdev)
{
struct rtw_chip_info *chip = rtwdev->chip;
@@ -1097,6 +1117,9 @@ int rtw_core_start(struct rtw_dev *rtwdev)
rtw_sec_enable_sec_engine(rtwdev);
+ rtwdev->lps_conf.deep_mode = rtw_update_lps_deep_mode(rtwdev, &rtwdev->fw);
+ rtwdev->lps_conf.wow_deep_mode = rtw_update_lps_deep_mode(rtwdev, &rtwdev->wow_fw);
+
/* rcr reset after powered on */
rtw_write32(rtwdev, REG_RCR, rtwdev->hal.rcr);
@@ -1130,6 +1153,9 @@ void rtw_core_stop(struct rtw_dev *rtwdev)
cancel_delayed_work_sync(&coex->defreeze_work);
cancel_delayed_work_sync(&coex->wl_remain_work);
cancel_delayed_work_sync(&coex->bt_remain_work);
+ cancel_delayed_work_sync(&coex->wl_connecting_work);
+ cancel_delayed_work_sync(&coex->bt_multi_link_remain_work);
+ cancel_delayed_work_sync(&coex->wl_ccklock_work);
mutex_lock(&rtwdev->mutex);
@@ -1259,6 +1285,17 @@ static void rtw_unset_supported_band(struct ieee80211_hw *hw,
kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]);
}
+static void __update_firmware_feature(struct rtw_dev *rtwdev,
+ struct rtw_fw_state *fw)
+{
+ u32 feature;
+ const struct rtw_fw_hdr *fw_hdr =
+ (const struct rtw_fw_hdr *)fw->firmware->data;
+
+ feature = le32_to_cpu(fw_hdr->feature);
+ fw->feature = feature & FW_FEATURE_SIG ? feature : 0;
+}
+
static void __update_firmware_info(struct rtw_dev *rtwdev,
struct rtw_fw_state *fw)
{
@@ -1269,6 +1306,8 @@ static void __update_firmware_info(struct rtw_dev *rtwdev,
fw->version = le16_to_cpu(fw_hdr->version);
fw->sub_version = fw_hdr->subversion;
fw->sub_index = fw_hdr->subindex;
+
+ __update_firmware_feature(rtwdev, fw);
}
static void __update_firmware_info_legacy(struct rtw_dev *rtwdev,
@@ -1622,6 +1661,10 @@ int rtw_core_init(struct rtw_dev *rtwdev)
INIT_DELAYED_WORK(&coex->defreeze_work, rtw_coex_defreeze_work);
INIT_DELAYED_WORK(&coex->wl_remain_work, rtw_coex_wl_remain_work);
INIT_DELAYED_WORK(&coex->bt_remain_work, rtw_coex_bt_remain_work);
+ INIT_DELAYED_WORK(&coex->wl_connecting_work, rtw_coex_wl_connecting_work);
+ INIT_DELAYED_WORK(&coex->bt_multi_link_remain_work,
+ rtw_coex_bt_multi_link_remain_work);
+ INIT_DELAYED_WORK(&coex->wl_ccklock_work, rtw_coex_wl_ccklock_work);
INIT_WORK(&rtwdev->c2h_work, rtw_c2h_work);
INIT_WORK(&rtwdev->fw_recovery_work, rtw_fw_recovery_work);
INIT_WORK(&rtwdev->ba_work, rtw_txq_ba_work);
@@ -1639,14 +1682,11 @@ int rtw_core_init(struct rtw_dev *rtwdev)
mutex_init(&rtwdev->hal.tx_power_mutex);
init_waitqueue_head(&rtwdev->coex.wait);
+ init_completion(&rtwdev->lps_leave_check);
rtwdev->sec.total_cam_num = 32;
rtwdev->hal.current_channel = 1;
set_bit(RTW_BC_MC_MACID, rtwdev->mac_id_map);
- if (!(BIT(rtw_fw_lps_deep_mode) & chip->lps_deep_mode_supported))
- rtwdev->lps_conf.deep_mode = LPS_DEEP_MODE_NONE;
- else
- rtwdev->lps_conf.deep_mode = rtw_fw_lps_deep_mode;
rtw_stats_init(rtwdev);
@@ -1671,6 +1711,7 @@ int rtw_core_init(struct rtw_dev *rtwdev)
return ret;
}
}
+
return 0;
}
EXPORT_SYMBOL(rtw_core_init);
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index ffb02e614217..9a318dfd04f9 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -37,7 +37,7 @@
#define RTW_TP_SHIFT 18 /* bytes/2s --> Mbps */
extern bool rtw_bf_support;
-extern unsigned int rtw_fw_lps_deep_mode;
+extern bool rtw_disable_lps_deep_mode;
extern unsigned int rtw_debug_mask;
extern const struct ieee80211_ops rtw_ops;
@@ -664,6 +664,7 @@ enum rtw_pwr_state {
struct rtw_lps_conf {
enum rtw_lps_mode mode;
enum rtw_lps_deep_mode deep_mode;
+ enum rtw_lps_deep_mode wow_deep_mode;
enum rtw_pwr_state state;
u8 awake_interval;
u8 rlbm;
@@ -1173,6 +1174,7 @@ struct rtw_chip_info {
u8 bt_desired_ver;
bool scbd_support;
bool new_scbd10_def; /* true: fix 2M(8822c) */
+ bool ble_hid_profile_support;
u8 pstdma_type; /* 0: LPSoff, 1:LPSon */
u8 bt_rssi_type;
u8 ant_isolation;
@@ -1197,6 +1199,7 @@ struct rtw_chip_info {
const struct coex_5g_afh_map *afh_5g;
const struct rtw_hw_reg *btg_reg;
const struct rtw_reg_domain *coex_info_hw_regs;
+ u32 wl_fw_desired_ver;
};
enum rtw_coex_bt_state_cnt {
@@ -1218,6 +1221,7 @@ enum rtw_coex_bt_state_cnt {
};
enum rtw_coex_wl_state_cnt {
+ COEX_CNT_WL_SCANAP,
COEX_CNT_WL_CONNPKT,
COEX_CNT_WL_COEXRUN,
COEX_CNT_WL_NOISY0,
@@ -1240,6 +1244,8 @@ struct rtw_coex_rfe {
bool wlg_at_btg;
};
+#define COEX_WL_TDMA_PARA_LENGTH 5
+
struct rtw_coex_dm {
bool cur_ps_tdma_on;
bool cur_wl_rx_low_gain_en;
@@ -1259,6 +1265,7 @@ struct rtw_coex_dm {
u32 cur_ant_pos_type;
u32 cur_switch_status;
u32 setting_tdma;
+ u8 fw_tdma_para[COEX_WL_TDMA_PARA_LENGTH];
};
#define COEX_BTINFO_SRC_WL_FW 0x0
@@ -1266,7 +1273,8 @@ struct rtw_coex_dm {
#define COEX_BTINFO_SRC_BT_ACT 0x2
#define COEX_BTINFO_SRC_BT_IQK 0x3
#define COEX_BTINFO_SRC_BT_SCBD 0x4
-#define COEX_BTINFO_SRC_MAX 0x5
+#define COEX_BTINFO_SRC_H2C60 0x5
+#define COEX_BTINFO_SRC_MAX 0x6
#define COEX_INFO_FTP BIT(7)
#define COEX_INFO_A2DP BIT(6)
@@ -1277,6 +1285,7 @@ struct rtw_coex_dm {
#define COEX_INFO_SCO_ESCO BIT(1)
#define COEX_INFO_CONNECTION BIT(0)
#define COEX_BTINFO_LENGTH_MAX 10
+#define COEX_BTINFO_LENGTH 7
struct rtw_coex_stat {
bool bt_disabled;
@@ -1298,6 +1307,8 @@ struct rtw_coex_stat {
bool bt_fix_2M;
bool bt_setup_link;
bool bt_multi_link;
+ bool bt_multi_link_pre;
+ bool bt_multi_link_remain;
bool bt_a2dp_sink;
bool bt_a2dp_active;
bool bt_reenable;
@@ -1305,6 +1316,7 @@ struct rtw_coex_stat {
bool bt_init_scan;
bool bt_slave;
bool bt_418_hid_exist;
+ bool bt_ble_hid_exist;
bool bt_mailbox_reply;
bool wl_under_lps;
@@ -1322,9 +1334,16 @@ struct rtw_coex_stat {
bool wl_cck_lock;
bool wl_cck_lock_pre;
bool wl_cck_lock_ever;
+ bool wl_connecting;
+ bool wl_slot_toggle;
+ bool wl_slot_toggle_change; /* if toggle to no-toggle */
u32 bt_supported_version;
u32 bt_supported_feature;
+ u32 hi_pri_tx;
+ u32 hi_pri_rx;
+ u32 lo_pri_tx;
+ u32 lo_pri_rx;
u32 patch_ver;
u16 bt_reg_vendor_ae;
u16 bt_reg_vendor_ac;
@@ -1346,13 +1365,21 @@ struct rtw_coex_stat {
u8 bt_a2dp_bitpool;
u8 bt_iqk_state;
+ u16 wl_beacon_interval;
u8 wl_noisy_level;
u8 wl_fw_dbg_info[10];
u8 wl_fw_dbg_info_pre[10];
+ u8 wl_rx_rate;
+ u8 wl_tx_rate;
+ u8 wl_rts_rx_rate;
u8 wl_coex_mode;
+ u8 wl_iot_peer;
u8 ampdu_max_time;
u8 wl_tput_dir;
+ u8 wl_toggle_para[6];
+ u8 wl_toggle_interval;
+
u16 score_board;
u16 retry_limit;
@@ -1362,6 +1389,9 @@ struct rtw_coex_stat {
/* counters to record wifi states */
u32 cnt_wl[COEX_CNT_WL_MAX];
+ /* counters to record bt c2h data */
+ u32 cnt_bt_info_c2h[COEX_BTINFO_SRC_MAX];
+
u32 darfrc;
u32 darfrch;
};
@@ -1377,6 +1407,7 @@ struct rtw_coex {
bool freeze;
bool freerun;
bool wl_rf_off;
+ bool manual_control;
struct rtw_coex_stat stat;
struct rtw_coex_dm dm;
@@ -1387,6 +1418,10 @@ struct rtw_coex {
struct delayed_work defreeze_work;
struct delayed_work wl_remain_work;
struct delayed_work bt_remain_work;
+ struct delayed_work wl_connecting_work;
+ struct delayed_work bt_multi_link_remain_work;
+ struct delayed_work wl_ccklock_work;
+
};
#define DPK_RF_REG_NUM 7
@@ -1633,6 +1668,7 @@ struct rtw_fw_state {
u8 sub_index;
u16 h2c_version;
u8 prev_dump_seq;
+ u32 feature;
};
struct rtw_hal {
@@ -1739,6 +1775,7 @@ struct rtw_dev {
/* lps power state & handler work */
struct rtw_lps_conf lps_conf;
bool ps_enabled;
+ struct completion lps_leave_check;
struct dentry *debugfs;
diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c
index 5cd9cc42648e..d44960cd940c 100644
--- a/drivers/net/wireless/realtek/rtw88/phy.c
+++ b/drivers/net/wireless/realtek/rtw88/phy.c
@@ -541,6 +541,12 @@ static void rtw_phy_cck_pd(struct rtw_dev *rtwdev)
else
dm_info->cck_fa_avg = (dm_info->cck_fa_avg * 3 + cck_fa) >> 2;
+ rtw_dbg(rtwdev, RTW_DBG_PHY, "IGI=0x%x, rssi_min=%d, cck_fa=%d\n",
+ dm_info->igi_history[0], dm_info->min_rssi,
+ dm_info->fa_history[0]);
+ rtw_dbg(rtwdev, RTW_DBG_PHY, "cck_fa_avg=%d, cck_pd_default=%d\n",
+ dm_info->cck_fa_avg, dm_info->cck_pd_default);
+
level = rtw_phy_cck_pd_lv(rtwdev);
if (level >= CCK_PD_LV_MAX)
diff --git a/drivers/net/wireless/realtek/rtw88/ps.c b/drivers/net/wireless/realtek/rtw88/ps.c
index 7a189a9926fe..3bead34c3d10 100644
--- a/drivers/net/wireless/realtek/rtw88/ps.c
+++ b/drivers/net/wireless/realtek/rtw88/ps.c
@@ -68,48 +68,39 @@ int rtw_leave_ips(struct rtw_dev *rtwdev)
void rtw_power_mode_change(struct rtw_dev *rtwdev, bool enter)
{
u8 request, confirm, polling;
- u8 polling_cnt;
- u8 retry_cnt = 0;
-
- for (retry_cnt = 0; retry_cnt < 3; retry_cnt++) {
- request = rtw_read8(rtwdev, rtwdev->hci.rpwm_addr);
- confirm = rtw_read8(rtwdev, rtwdev->hci.cpwm_addr);
-
- /* toggle to request power mode, others remain 0 */
- request ^= request | BIT_RPWM_TOGGLE;
- if (!enter) {
- request |= POWER_MODE_ACK;
- } else {
- request |= POWER_MODE_LCLK;
- if (rtw_fw_lps_deep_mode == LPS_DEEP_MODE_PG)
- request |= POWER_MODE_PG;
- }
-
- rtw_write8(rtwdev, rtwdev->hci.rpwm_addr, request);
-
- if (enter)
- return;
-
- /* check confirm power mode has left power save state */
- for (polling_cnt = 0; polling_cnt < 50; polling_cnt++) {
- polling = rtw_read8(rtwdev, rtwdev->hci.cpwm_addr);
- if ((polling ^ confirm) & BIT_RPWM_TOGGLE)
- return;
- udelay(100);
- }
-
- /* in case of fw/hw missed the request, retry */
- rtw_warn(rtwdev, "failed to leave deep PS, retry=%d\n",
- retry_cnt);
+ int ret;
+
+ request = rtw_read8(rtwdev, rtwdev->hci.rpwm_addr);
+ confirm = rtw_read8(rtwdev, rtwdev->hci.cpwm_addr);
+
+ /* toggle to request power mode, others remain 0 */
+ request ^= request | BIT_RPWM_TOGGLE;
+ if (enter) {
+ request |= POWER_MODE_LCLK;
+ if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_PG)
+ request |= POWER_MODE_PG;
}
+ /* Each request require an ack from firmware */
+ request |= POWER_MODE_ACK;
- /* Hit here means that driver failed to change hardware power mode to
- * active state after retry 3 times. If the power state is locked at
- * Deep sleep, most of the hardware circuits is not working, even
- * register read/write. It should be treated as fatal error and
- * requires an entire analysis about the firmware/hardware
- */
- WARN(1, "Hardware power state locked\n");
+ rtw_write8(rtwdev, rtwdev->hci.rpwm_addr, request);
+
+ /* Check firmware get the power requset and ack via cpwm register */
+ ret = read_poll_timeout_atomic(rtw_read8, polling,
+ (polling ^ confirm) & BIT_RPWM_TOGGLE,
+ 100, 15000, true, rtwdev,
+ rtwdev->hci.cpwm_addr);
+ if (ret) {
+ /* Hit here means that driver failed to get an ack from firmware.
+ * The reason could be that hardware is locked at Deep sleep,
+ * so most of the hardware circuits are not working, even
+ * register read/write; or firmware is locked in some state and
+ * cannot get the request. It should be treated as fatal error
+ * and requires an entire analysis about the firmware/hardware.
+ */
+ WARN(1, "firmware failed to ack driver for %s Deep Power mode\n",
+ enter ? "entering" : "leaving");
+ }
}
EXPORT_SYMBOL(rtw_power_mode_change);
@@ -118,7 +109,7 @@ static void __rtw_leave_lps_deep(struct rtw_dev *rtwdev)
rtw_hci_deep_ps(rtwdev, false);
}
-static void rtw_fw_leave_lps_state_check(struct rtw_dev *rtwdev)
+static int __rtw_fw_leave_lps_check_reg(struct rtw_dev *rtwdev)
{
int i;
@@ -136,12 +127,53 @@ static void rtw_fw_leave_lps_state_check(struct rtw_dev *rtwdev)
*/
for (i = 0 ; i < LEAVE_LPS_TRY_CNT; i++) {
if (rtw_read32_mask(rtwdev, REG_TCR, BIT_PWRMGT_HWDATA_EN) == 0)
- return;
+ return 0;
msleep(20);
}
- rtw_write32_mask(rtwdev, REG_TCR, BIT_PWRMGT_HWDATA_EN, 0);
- rtw_warn(rtwdev, "firmware failed to restore hardware setting\n");
+ return -EBUSY;
+}
+
+static int __rtw_fw_leave_lps_check_c2h(struct rtw_dev *rtwdev)
+{
+ if (wait_for_completion_timeout(&rtwdev->lps_leave_check,
+ LEAVE_LPS_TIMEOUT))
+ return 0;
+ return -EBUSY;
+}
+
+static void rtw_fw_leave_lps_check(struct rtw_dev *rtwdev)
+{
+ bool ret = false;
+ struct rtw_fw_state *fw;
+
+ if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags))
+ fw = &rtwdev->wow_fw;
+ else
+ fw = &rtwdev->fw;
+
+ if (fw->feature & FW_FEATURE_LPS_C2H)
+ ret = __rtw_fw_leave_lps_check_c2h(rtwdev);
+ else
+ ret = __rtw_fw_leave_lps_check_reg(rtwdev);
+
+ if (ret) {
+ rtw_write32_clr(rtwdev, REG_TCR, BIT_PWRMGT_HWDATA_EN);
+ rtw_warn(rtwdev, "firmware failed to leave lps state\n");
+ }
+}
+
+static void rtw_fw_leave_lps_check_prepare(struct rtw_dev *rtwdev)
+{
+ struct rtw_fw_state *fw;
+
+ if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags))
+ fw = &rtwdev->wow_fw;
+ else
+ fw = &rtwdev->fw;
+
+ if (fw->feature & FW_FEATURE_LPS_C2H)
+ reinit_completion(&rtwdev->lps_leave_check);
}
static void rtw_leave_lps_core(struct rtw_dev *rtwdev)
@@ -154,17 +186,26 @@ static void rtw_leave_lps_core(struct rtw_dev *rtwdev)
conf->smart_ps = 0;
rtw_hci_link_ps(rtwdev, false);
+ rtw_fw_leave_lps_check_prepare(rtwdev);
rtw_fw_set_pwr_mode(rtwdev);
- rtw_fw_leave_lps_state_check(rtwdev);
+ rtw_fw_leave_lps_check(rtwdev);
clear_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags);
rtw_coex_lps_notify(rtwdev, COEX_LPS_DISABLE);
}
+enum rtw_lps_deep_mode rtw_get_lps_deep_mode(struct rtw_dev *rtwdev)
+{
+ if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags))
+ return rtwdev->lps_conf.wow_deep_mode;
+ else
+ return rtwdev->lps_conf.deep_mode;
+}
+
static void __rtw_enter_lps_deep(struct rtw_dev *rtwdev)
{
- if (rtwdev->lps_conf.deep_mode == LPS_DEEP_MODE_NONE)
+ if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_NONE)
return;
if (!test_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags)) {
@@ -173,7 +214,7 @@ static void __rtw_enter_lps_deep(struct rtw_dev *rtwdev)
return;
}
- if (rtw_fw_lps_deep_mode == LPS_DEEP_MODE_PG)
+ if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_PG)
rtw_fw_set_pg_info(rtwdev);
rtw_hci_deep_ps(rtwdev, true);
diff --git a/drivers/net/wireless/realtek/rtw88/ps.h b/drivers/net/wireless/realtek/rtw88/ps.h
index 19afceca7d0e..7819391c8663 100644
--- a/drivers/net/wireless/realtek/rtw88/ps.h
+++ b/drivers/net/wireless/realtek/rtw88/ps.h
@@ -12,6 +12,7 @@
#define POWER_MODE_LCLK BIT(0)
#define LEAVE_LPS_TRY_CNT 5
+#define LEAVE_LPS_TIMEOUT msecs_to_jiffies(100)
int rtw_enter_ips(struct rtw_dev *rtwdev);
int rtw_leave_ips(struct rtw_dev *rtwdev);
@@ -20,5 +21,5 @@ void rtw_power_mode_change(struct rtw_dev *rtwdev, bool enter);
void rtw_enter_lps(struct rtw_dev *rtwdev, u8 port_id);
void rtw_leave_lps(struct rtw_dev *rtwdev);
void rtw_leave_lps_deep(struct rtw_dev *rtwdev);
-
+enum rtw_lps_deep_mode rtw_get_lps_deep_mode(struct rtw_dev *rtwdev);
#endif
diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h
index 86b94c008a27..cf9a3b674d30 100644
--- a/drivers/net/wireless/realtek/rtw88/reg.h
+++ b/drivers/net/wireless/realtek/rtw88/reg.h
@@ -60,7 +60,7 @@
#define REG_GPIO_MUXCFG 0x0040
#define BIT_FSPI_EN BIT(19)
#define BIT_EN_SIC BIT(12)
-#define BIT_BT_AOD_GPIO3 BIT(9)
+
#define BIT_PO_BT_PTA_PINS BIT(9)
#define BIT_BT_PTA_EN BIT(5)
#define BIT_WLRFE_4_5_EN BIT(2)
@@ -463,11 +463,17 @@
#define REG_BT_COEX_TABLE_H3 0x06CF
#define REG_BBPSF_CTRL 0x06DC
-#define REG_BT_COEX_V2 0x0763
-#define BIT_GNT_BT_POLARITY BIT(4)
+#define REG_BT_COEX_V2 0x0762
+#define BIT_GNT_BT_POLARITY BIT(12)
#define BIT_LTE_COEX_EN BIT(7)
+#define REG_BT_COEX_ENH_INTR_CTRL 0x76E
+#define BIT_R_GRANTALL_WLMASK BIT(3)
+#define BIT_STATIS_BT_EN BIT(2)
+#define REG_BT_ACT_STATISTICS 0x0770
+#define REG_BT_ACT_STATISTICS_1 0x0774
#define REG_BT_STAT_CTRL 0x0778
#define REG_BT_TDMA_TIME 0x0790
+#define BIT_MASK_SAMPLE_RATE GENMASK(5, 0)
#define REG_LTR_IDLE_LATENCY 0x0798
#define REG_LTR_ACTIVE_LATENCY 0x079C
#define REG_LTR_CTRL_BASIC 0x07A4
@@ -483,6 +489,8 @@
#define REG_2ND_CCA_CTRL 0x0976
#define REG_CCK0_FAREPORT 0xa2c
+#define BIT_CCK0_2RX BIT(18)
+#define BIT_CCK0_MRC BIT(22)
#define REG_DIS_DPD 0x0a70
#define DIS_DPD_MASK GENMASK(9, 0)
@@ -618,6 +626,9 @@
#define REG_ANAPAR 0x1c30
#define BIT_ANAPAR_BTPS BIT(22)
#define REG_RSTB_SEL 0x1c38
+#define BIT_DAC_OFF_ENABLE BIT(4)
+#define BIT_PI_IGNORE_GNT_BT BIT(3)
+#define BIT_NOMASK_TXBT_ENABLE BIT(3)
#define REG_HRCV_MSG 0x1cf
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
index 3ddd170f1651..9268ea8b6dda 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
@@ -192,6 +192,7 @@ static void rtw8723d_phy_set_param(struct rtw_dev *rtwdev)
rtw_write32(rtwdev, REG_LTR_CTRL_BASIC + 4, WLAN_LTR_CTRL2);
rtw_phy_init(rtwdev);
+ rtwdev->dm_info.cck_pd_default = rtw_read8(rtwdev, REG_CSRATIO) & 0x1f;
rtw_write16_set(rtwdev, REG_TXDMA_OFFSET_CHK, BIT_DROP_DATA_EN);
@@ -1498,6 +1499,34 @@ out:
rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] finished\n");
}
+static void rtw8723d_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl)
+{
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+ u8 pd[CCK_PD_LV_MAX] = {3, 7, 13, 13, 13};
+ u8 cck_n_rx;
+
+ rtw_dbg(rtwdev, RTW_DBG_PHY, "lv: (%d) -> (%d)\n",
+ dm_info->cck_pd_lv[RTW_CHANNEL_WIDTH_20][RF_PATH_A], new_lvl);
+
+ if (dm_info->cck_pd_lv[RTW_CHANNEL_WIDTH_20][RF_PATH_A] == new_lvl)
+ return;
+
+ cck_n_rx = (rtw_read8_mask(rtwdev, REG_CCK0_FAREPORT, BIT_CCK0_2RX) &&
+ rtw_read8_mask(rtwdev, REG_CCK0_FAREPORT, BIT_CCK0_MRC)) ? 2 : 1;
+ rtw_dbg(rtwdev, RTW_DBG_PHY,
+ "is_linked=%d, lv=%d, n_rx=%d, cs_ratio=0x%x, pd_th=0x%x, cck_fa_avg=%d\n",
+ rtw_is_assoc(rtwdev), new_lvl, cck_n_rx,
+ dm_info->cck_pd_default + new_lvl * 2,
+ pd[new_lvl], dm_info->cck_fa_avg);
+
+ dm_info->cck_fa_avg = CCK_FA_AVG_RESET;
+
+ dm_info->cck_pd_lv[RTW_CHANNEL_WIDTH_20][RF_PATH_A] = new_lvl;
+ rtw_write32_mask(rtwdev, REG_PWRTH, 0x3f0000, pd[new_lvl]);
+ rtw_write32_mask(rtwdev, REG_PWRTH2, 0x1f0000,
+ dm_info->cck_pd_default + new_lvl * 2);
+}
+
/* for coex */
static void rtw8723d_coex_cfg_init(struct rtw_dev *rtwdev)
{
@@ -1506,14 +1535,14 @@ static void rtw8723d_coex_cfg_init(struct rtw_dev *rtwdev)
/* BT report packet sample rate */
/* 0x790[5:0]=0x5 */
- rtw_write8_set(rtwdev, REG_BT_TDMA_TIME, 0x05);
+ rtw_write8_mask(rtwdev, REG_BT_TDMA_TIME, BIT_MASK_SAMPLE_RATE, 0x5);
/* enable BT counter statistics */
rtw_write8(rtwdev, REG_BT_STAT_CTRL, 0x1);
/* enable PTA (3-wire function form BT side) */
rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_PTA_EN);
- rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_AOD_GPIO3);
+ rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_PO_BT_PTA_PINS);
/* enable PTA (tx/rx signal form WiFi side) */
rtw_write8_set(rtwdev, REG_QUEUE_CTRL, BIT_PTA_WL_TX_EN);
@@ -1931,6 +1960,7 @@ static struct rtw_chip_ops rtw8723d_ops = {
.efuse_grant = rtw8723d_efuse_grant,
.false_alarm_statistics = rtw8723d_false_alarm_statistics,
.phy_calibration = rtw8723d_phy_calibration,
+ .cck_pd_set = rtw8723d_phy_cck_pd_set,
.pwr_track = rtw8723d_pwr_track,
.config_bfee = NULL,
.set_gid_table = NULL,
@@ -1949,19 +1979,19 @@ static struct rtw_chip_ops rtw8723d_ops = {
static const struct coex_table_para table_sant_8723d[] = {
{0xffffffff, 0xffffffff}, /* case-0 */
{0x55555555, 0x55555555},
- {0x65555555, 0x65555555},
+ {0x66555555, 0x66555555},
{0xaaaaaaaa, 0xaaaaaaaa},
{0x5a5a5a5a, 0x5a5a5a5a},
{0xfafafafa, 0xfafafafa}, /* case-5 */
- {0xa5555555, 0xaaaa5aaa},
- {0x6a5a5a5a, 0x5a5a5a5a},
+ {0x6a5a5555, 0xaaaaaaaa},
+ {0x6a5a56aa, 0x6a5a56aa},
{0x6a5a5a5a, 0x6a5a5a5a},
{0x66555555, 0x5a5a5a5a},
- {0x65555555, 0x6a5a5a5a}, /* case-10 */
- {0x65555555, 0xfafafafa},
+ {0x66555555, 0x6a5a5a5a}, /* case-10 */
+ {0x66555555, 0x6a5a5aaa},
{0x66555555, 0x5a5a5aaa},
- {0x65555555, 0x5aaa5aaa},
- {0x65555555, 0xaaaa5aaa},
+ {0x66555555, 0x6aaa5aaa},
+ {0x66555555, 0xaaaa5aaa},
{0x66555555, 0xaaaaaaaa}, /* case-15 */
{0xffff55ff, 0xfafafafa},
{0xffff55ff, 0x6afa5afa},
@@ -1970,38 +2000,41 @@ static const struct coex_table_para table_sant_8723d[] = {
{0xaa5555aa, 0x6a5a5a5a}, /* case-20 */
{0xaa5555aa, 0xaaaaaaaa},
{0xffffffff, 0x5a5a5a5a},
- {0xffffffff, 0x6a5a5a5a},
+ {0xffffffff, 0x5a5a5a5a},
{0xffffffff, 0x55555555},
- {0xffffffff, 0x6a5a5aaa}, /* case-25 */
+ {0xffffffff, 0x5a5a5aaa}, /* case-25 */
{0x55555555, 0x5a5a5a5a},
{0x55555555, 0xaaaaaaaa},
- {0x55555555, 0x6a6a6a6a},
- {0x656a656a, 0x656a656a}
+ {0x55555555, 0x6a5a6a5a},
+ {0x66556655, 0x66556655},
+ {0x66556aaa, 0x6a5a6aaa}, /* case-30 */
+ {0xffffffff, 0x5aaa5aaa},
+ {0x56555555, 0x5a5a5aaa},
};
/* Non-Shared-Antenna Coex Table */
static const struct coex_table_para table_nsant_8723d[] = {
{0xffffffff, 0xffffffff}, /* case-100 */
{0x55555555, 0x55555555},
- {0x65555555, 0x65555555},
+ {0x66555555, 0x66555555},
{0xaaaaaaaa, 0xaaaaaaaa},
{0x5a5a5a5a, 0x5a5a5a5a},
{0xfafafafa, 0xfafafafa}, /* case-105 */
{0x5afa5afa, 0x5afa5afa},
{0x55555555, 0xfafafafa},
- {0x65555555, 0xfafafafa},
- {0x65555555, 0x5a5a5a5a},
- {0x65555555, 0x6a5a5a5a}, /* case-110 */
- {0x65555555, 0xaaaaaaaa},
+ {0x66555555, 0xfafafafa},
+ {0x66555555, 0x5a5a5a5a},
+ {0x66555555, 0x6a5a5a5a}, /* case-110 */
+ {0x66555555, 0xaaaaaaaa},
{0xffff55ff, 0xfafafafa},
{0xffff55ff, 0x5afa5afa},
{0xffff55ff, 0xaaaaaaaa},
- {0xaaffffaa, 0xfafafafa}, /* case-115 */
+ {0xffff55ff, 0xffff55ff}, /* case-115 */
{0xaaffffaa, 0x5afa5afa},
{0xaaffffaa, 0xaaaaaaaa},
{0xffffffff, 0xfafafafa},
{0xffffffff, 0x5afa5afa},
- {0xffffffff, 0xaaaaaaaa},/* case-120 */
+ {0xffffffff, 0xaaaaaaaa}, /* case-120 */
{0x55ff55ff, 0x5afa5afa},
{0x55ff55ff, 0xaaaaaaaa},
{0x55ff55ff, 0x55ff55ff}
@@ -2009,31 +2042,31 @@ static const struct coex_table_para table_nsant_8723d[] = {
/* Shared-Antenna TDMA */
static const struct coex_tdma_para tdma_sant_8723d[] = {
- { {0x08, 0x00, 0x00, 0x00, 0x00} }, /* case-0 */
+ { {0x00, 0x00, 0x00, 0x00, 0x00} }, /* case-0 */
{ {0x61, 0x45, 0x03, 0x11, 0x11} }, /* case-1 */
{ {0x61, 0x3a, 0x03, 0x11, 0x11} },
- { {0x61, 0x20, 0x03, 0x11, 0x11} },
{ {0x61, 0x30, 0x03, 0x11, 0x11} },
+ { {0x61, 0x20, 0x03, 0x11, 0x11} },
{ {0x61, 0x10, 0x03, 0x11, 0x11} }, /* case-5 */
- { {0x61, 0x48, 0x03, 0x11, 0x10} },
+ { {0x61, 0x45, 0x03, 0x11, 0x10} },
{ {0x61, 0x3a, 0x03, 0x11, 0x10} },
{ {0x61, 0x30, 0x03, 0x11, 0x10} },
{ {0x61, 0x20, 0x03, 0x11, 0x10} },
{ {0x61, 0x10, 0x03, 0x11, 0x10} }, /* case-10 */
- { {0x61, 0x10, 0x03, 0x11, 0x14} },
+ { {0x61, 0x08, 0x03, 0x11, 0x14} },
{ {0x61, 0x08, 0x03, 0x10, 0x14} },
- { {0x51, 0x10, 0x03, 0x10, 0x54} },
- { {0x51, 0x10, 0x03, 0x10, 0x55} },
- { {0x51, 0x10, 0x07, 0x10, 0x54} }, /* case-15 */
+ { {0x51, 0x08, 0x03, 0x10, 0x54} },
+ { {0x51, 0x08, 0x03, 0x10, 0x55} },
+ { {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-15 */
{ {0x51, 0x45, 0x03, 0x10, 0x50} },
{ {0x51, 0x3a, 0x03, 0x10, 0x50} },
{ {0x51, 0x30, 0x03, 0x10, 0x50} },
{ {0x51, 0x20, 0x03, 0x10, 0x50} },
- { {0x51, 0x15, 0x03, 0x10, 0x50} }, /* case-20 */
+ { {0x51, 0x10, 0x03, 0x10, 0x50} }, /* case-20 */
{ {0x51, 0x4a, 0x03, 0x10, 0x50} },
{ {0x51, 0x0c, 0x03, 0x10, 0x54} },
{ {0x55, 0x08, 0x03, 0x10, 0x54} },
- { {0x65, 0x10, 0x03, 0x11, 0x11} },
+ { {0x65, 0x10, 0x03, 0x11, 0x10} },
{ {0x51, 0x10, 0x03, 0x10, 0x51} }, /* case-25 */
{ {0x51, 0x08, 0x03, 0x10, 0x50} },
{ {0x61, 0x08, 0x03, 0x11, 0x11} }
@@ -2041,7 +2074,7 @@ static const struct coex_tdma_para tdma_sant_8723d[] = {
/* Non-Shared-Antenna TDMA */
static const struct coex_tdma_para tdma_nsant_8723d[] = {
- { {0x00, 0x00, 0x00, 0x40, 0x01} }, /* case-100 */
+ { {0x00, 0x00, 0x00, 0x00, 0x01} }, /* case-100 */
{ {0x61, 0x45, 0x03, 0x11, 0x11} }, /* case-101 */
{ {0x61, 0x3a, 0x03, 0x11, 0x11} },
{ {0x61, 0x30, 0x03, 0x11, 0x11} },
@@ -2062,7 +2095,7 @@ static const struct coex_tdma_para tdma_nsant_8723d[] = {
{ {0x51, 0x30, 0x03, 0x10, 0x50} },
{ {0x51, 0x20, 0x03, 0x10, 0x50} },
{ {0x51, 0x10, 0x03, 0x10, 0x50} }, /* case-120 */
- { {0x51, 0x08, 0x03, 0x10, 0x50} },
+ { {0x51, 0x08, 0x03, 0x10, 0x50} }
};
/* rssi in percentage % (dbm = % - 100) */
@@ -2719,6 +2752,7 @@ struct rtw_chip_info rtw8723d_hw_spec = {
.bt_desired_ver = 0x2f,
.scbd_support = true,
.new_scbd10_def = true,
+ .ble_hid_profile_support = false,
.pstdma_type = COEX_PSTDMA_FORCE_LPSOFF,
.bt_rssi_type = COEX_BTRSSI_RATIO,
.ant_isolation = 15,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
index 7894d321cd7e..41d35174a542 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
@@ -163,6 +163,7 @@ static inline s32 iqk_mult(s32 x, s32 y, s32 *ext)
#define REG_CCK0_SYS 0x0a00
#define BIT_CCK_SIDE_BAND BIT(4)
#define REG_CCK_ANT_SEL_11N 0x0a04
+#define REG_PWRTH 0x0a08
#define REG_CCK_FA_RST_11N 0x0a2c
#define BIT_MASK_CCK_CNT_KEEP BIT(12)
#define BIT_MASK_CCK_CNT_EN BIT(13)
@@ -175,6 +176,8 @@ static inline s32 iqk_mult(s32 x, s32 y, s32 *ext)
#define REG_CCK_CCA_CNT_11N 0x0a60
#define BIT_MASK_CCK_FA_MSB GENMASK(7, 0)
#define BIT_MASK_CCK_FA_LSB GENMASK(15, 8)
+#define REG_PWRTH2 0x0aa8
+#define REG_CSRATIO 0x0aaa
#define REG_OFDM_FA_HOLDC_11N 0x0c00
#define BIT_MASK_OFDM_FA_KEEP BIT(31)
#define REG_BB_RX_PATH_11N 0x0c04
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
index da2e7415be8f..fbfd85439d1f 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
@@ -656,8 +656,7 @@ static void rtw8821c_coex_cfg_init(struct rtw_dev *rtwdev)
rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
/* BT report packet sample rate */
- rtw_write8_mask(rtwdev, REG_BT_TDMA_TIME, SAMPLE_RATE_MASK,
- SAMPLE_RATE);
+ rtw_write8_mask(rtwdev, REG_BT_TDMA_TIME, BIT_MASK_SAMPLE_RATE, 0x5);
/* enable BT counter statistics */
rtw_write8(rtwdev, REG_BT_STAT_CTRL, BT_CNT_ENABLE);
@@ -1021,6 +1020,7 @@ static void rtw8821c_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
u8 pd[CCK_PD_LV_MAX] = {3, 7, 13, 13, 13};
+ u8 cck_n_rx;
if (dm_info->min_rssi > 60) {
new_lvl = 4;
@@ -1028,9 +1028,20 @@ static void rtw8821c_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl)
goto set_cck_pd;
}
+ rtw_dbg(rtwdev, RTW_DBG_PHY, "lv: (%d) -> (%d)\n",
+ dm_info->cck_pd_lv[RTW_CHANNEL_WIDTH_20][RF_PATH_A], new_lvl);
+
if (dm_info->cck_pd_lv[RTW_CHANNEL_WIDTH_20][RF_PATH_A] == new_lvl)
return;
+ cck_n_rx = (rtw_read8_mask(rtwdev, REG_CCK0_FAREPORT, BIT_CCK0_2RX) &&
+ rtw_read8_mask(rtwdev, REG_CCK0_FAREPORT, BIT_CCK0_MRC)) ? 2 : 1;
+ rtw_dbg(rtwdev, RTW_DBG_PHY,
+ "is_linked=%d, lv=%d, n_rx=%d, cs_ratio=0x%x, pd_th=0x%x, cck_fa_avg=%d\n",
+ rtw_is_assoc(rtwdev), new_lvl, cck_n_rx,
+ dm_info->cck_pd_default + new_lvl * 2,
+ pd[new_lvl], dm_info->cck_fa_avg);
+
dm_info->cck_fa_avg = CCK_FA_AVG_RESET;
set_cck_pd:
@@ -1819,6 +1830,7 @@ struct rtw_chip_info rtw8821c_hw_spec = {
.bt_desired_ver = 0x46,
.scbd_support = true,
.new_scbd10_def = false,
+ .ble_hid_profile_support = false,
.pstdma_type = COEX_PSTDMA_FORCE_LPSOFF,
.bt_rssi_type = COEX_BTRSSI_RATIO,
.ant_isolation = 15,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.h b/drivers/net/wireless/realtek/rtw88/rtw8821c.h
index bd01e82b6bcd..e11e3fc41c95 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.h
@@ -231,8 +231,6 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data)
#define REG_IQKFAILMSK 0x1bf0
#define BIT_MASK_R_RFE_SEL_15 GENMASK(31, 28)
#define BIT_SDIO_INT BIT(18)
-#define SAMPLE_RATE_MASK GENMASK(5, 0)
-#define SAMPLE_RATE 0x5
#define BT_CNT_ENABLE 0x1
#define BIT_BCN_QUEUE BIT(3)
#define BCN_PRI_EN 0x1
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
index 22d0dd640ac9..f1789155e901 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
@@ -87,7 +87,7 @@ static const u32 rtw8822b_txscale_tbl[RTW_TXSCALE_SIZE] = {
0x2d3, 0x2fe, 0x32b, 0x35c, 0x38e, 0x3c4, 0x3fe
};
-static const u8 rtw8822b_get_swing_index(struct rtw_dev *rtwdev)
+static u8 rtw8822b_get_swing_index(struct rtw_dev *rtwdev)
{
u8 i = 0;
u32 swing, table_value;
@@ -1120,21 +1120,21 @@ static void rtw8822b_coex_cfg_init(struct rtw_dev *rtwdev)
/* BT report packet sample rate */
/* 0x790[5:0]=0x5 */
- rtw_write8_set(rtwdev, REG_BT_TDMA_TIME, 0x05);
+ rtw_write8_mask(rtwdev, REG_BT_TDMA_TIME, BIT_MASK_SAMPLE_RATE, 0x5);
/* enable BT counter statistics */
rtw_write8(rtwdev, REG_BT_STAT_CTRL, 0x1);
/* enable PTA (3-wire function form BT side) */
rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_PTA_EN);
- rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_AOD_GPIO3);
+ rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_PO_BT_PTA_PINS);
/* enable PTA (tx/rx signal form WiFi side) */
rtw_write8_set(rtwdev, REG_QUEUE_CTRL, BIT_PTA_WL_TX_EN);
/* wl tx signal to PTA not case EDCCA */
rtw_write8_clr(rtwdev, REG_QUEUE_CTRL, BIT_PTA_EDCCA_EN);
/* GNT_BT=1 while select both */
- rtw_write8_set(rtwdev, REG_BT_COEX_V2, BIT_GNT_BT_POLARITY);
+ rtw_write16_set(rtwdev, REG_BT_COEX_V2, BIT_GNT_BT_POLARITY);
}
static void rtw8822b_coex_cfg_ant_switch(struct rtw_dev *rtwdev,
@@ -1341,6 +1341,7 @@ static void rtw8822b_coex_cfg_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain)
coex_dm->cur_wl_rx_low_gain_en = low_gain;
if (coex_dm->cur_wl_rx_low_gain_en) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], Hi-Li Table On!\n");
for (i = 0; i < ARRAY_SIZE(wl_rx_low_gain_on); i++)
rtw_write32(rtwdev, REG_RX_GAIN_EN, wl_rx_low_gain_on[i]);
@@ -1350,6 +1351,7 @@ static void rtw8822b_coex_cfg_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain)
rtw_write_rf(rtwdev, RF_PATH_B, RF_RCKD, 0x2, 0x1);
rtw_write_rf(rtwdev, RF_PATH_B, RF_RCK, 0x3f, 0x3f);
} else {
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], Hi-Li Table Off!\n");
for (i = 0; i < ARRAY_SIZE(wl_rx_low_gain_off); i++)
rtw_write32(rtwdev, 0x81c, wl_rx_low_gain_off[i]);
@@ -2141,14 +2143,14 @@ static const struct coex_table_para table_sant_8822b[] = {
{0xaaaaaaaa, 0xaaaaaaaa},
{0x5a5a5a5a, 0x5a5a5a5a},
{0xfafafafa, 0xfafafafa}, /* case-5 */
- {0x6a5a6a5a, 0xaaaaaaaa},
+ {0x6a5a5555, 0xaaaaaaaa},
{0x6a5a56aa, 0x6a5a56aa},
{0x6a5a5a5a, 0x6a5a5a5a},
{0x66555555, 0x5a5a5a5a},
{0x66555555, 0x6a5a5a5a}, /* case-10 */
{0x66555555, 0xfafafafa},
{0x66555555, 0x5a5a5aaa},
- {0x66555555, 0x5aaa5aaa},
+ {0x66555555, 0x6aaa5aaa},
{0x66555555, 0xaaaa5aaa},
{0x66555555, 0xaaaaaaaa}, /* case-15 */
{0xffff55ff, 0xfafafafa},
@@ -2158,13 +2160,16 @@ static const struct coex_table_para table_sant_8822b[] = {
{0xaa5555aa, 0x6a5a5a5a}, /* case-20 */
{0xaa5555aa, 0xaaaaaaaa},
{0xffffffff, 0x5a5a5a5a},
- {0xffffffff, 0x6a5a5a5a},
+ {0xffffffff, 0x5a5a5a5a},
{0xffffffff, 0x55555555},
{0xffffffff, 0x6a5a5aaa}, /* case-25 */
{0x55555555, 0x5a5a5a5a},
{0x55555555, 0xaaaaaaaa},
{0x55555555, 0x6a5a6a5a},
- {0x66556655, 0x66556655}
+ {0x66556655, 0x66556655},
+ {0x66556aaa, 0x6a5a6aaa}, /* case-30 */
+ {0xffffffff, 0x5aaa5aaa},
+ {0x56555555, 0x5a5a5aaa},
};
/* Non-Shared-Antenna Coex Table */
@@ -2184,7 +2189,7 @@ static const struct coex_table_para table_nsant_8822b[] = {
{0xffff55ff, 0xfafafafa},
{0xffff55ff, 0x5afa5afa},
{0xffff55ff, 0xaaaaaaaa},
- {0xaaffffaa, 0xfafafafa}, /* case-115 */
+ {0xffff55ff, 0xffff55ff}, /* case-115 */
{0xaaffffaa, 0x5afa5afa},
{0xaaffffaa, 0xaaaaaaaa},
{0xffffffff, 0xfafafafa},
@@ -2213,7 +2218,7 @@ static const struct coex_tdma_para tdma_sant_8822b[] = {
{ {0x51, 0x08, 0x03, 0x10, 0x54} },
{ {0x51, 0x08, 0x03, 0x10, 0x55} },
{ {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-15 */
- { {0x51, 0x45, 0x03, 0x10, 0x10} },
+ { {0x51, 0x45, 0x03, 0x10, 0x50} },
{ {0x51, 0x3a, 0x03, 0x10, 0x50} },
{ {0x51, 0x30, 0x03, 0x10, 0x50} },
{ {0x51, 0x20, 0x03, 0x10, 0x50} },
@@ -2221,7 +2226,7 @@ static const struct coex_tdma_para tdma_sant_8822b[] = {
{ {0x51, 0x4a, 0x03, 0x10, 0x50} },
{ {0x51, 0x0c, 0x03, 0x10, 0x54} },
{ {0x55, 0x08, 0x03, 0x10, 0x54} },
- { {0x65, 0x10, 0x03, 0x11, 0x11} },
+ { {0x65, 0x10, 0x03, 0x11, 0x10} },
{ {0x51, 0x10, 0x03, 0x10, 0x51} }, /* case-25 */
{ {0x51, 0x08, 0x03, 0x10, 0x50} },
{ {0x61, 0x08, 0x03, 0x11, 0x11} }
@@ -2230,7 +2235,7 @@ static const struct coex_tdma_para tdma_sant_8822b[] = {
/* Non-Shared-Antenna TDMA */
static const struct coex_tdma_para tdma_nsant_8822b[] = {
{ {0x00, 0x00, 0x00, 0x00, 0x00} }, /* case-100 */
- { {0x61, 0x45, 0x03, 0x11, 0x11} },
+ { {0x61, 0x45, 0x03, 0x11, 0x11} }, /* case-101 */
{ {0x61, 0x3a, 0x03, 0x11, 0x11} },
{ {0x61, 0x30, 0x03, 0x11, 0x11} },
{ {0x61, 0x20, 0x03, 0x11, 0x11} },
@@ -2249,13 +2254,13 @@ static const struct coex_tdma_para tdma_nsant_8822b[] = {
{ {0x51, 0x3a, 0x03, 0x10, 0x50} },
{ {0x51, 0x30, 0x03, 0x10, 0x50} },
{ {0x51, 0x20, 0x03, 0x10, 0x50} },
- { {0x51, 0x10, 0x03, 0x10, 0x50} } /* case-120 */
+ { {0x51, 0x10, 0x03, 0x10, 0x50} }, /* case-120 */
+ { {0x51, 0x08, 0x03, 0x10, 0x50} }
};
/* rssi in percentage % (dbm = % - 100) */
static const u8 wl_rssi_step_8822b[] = {60, 50, 44, 30};
static const u8 bt_rssi_step_8822b[] = {30, 30, 30, 30};
-static const struct coex_5g_afh_map afh_5g_8822b[] = { {0, 0, 0} };
/* wl_tx_dec_power, bt_tx_dec_power, wl_rx_gain, bt_rx_lna_constrain */
static const struct coex_rf_para rf_para_tx_8822b[] = {
@@ -2276,6 +2281,27 @@ static const struct coex_rf_para rf_para_rx_8822b[] = {
{1, 13, true, 1}
};
+static const struct coex_5g_afh_map afh_5g_8822b[] = {
+ {120, 2, 4},
+ {124, 8, 8},
+ {128, 17, 8},
+ {132, 26, 10},
+ {136, 34, 8},
+ {140, 42, 10},
+ {144, 51, 8},
+ {149, 62, 8},
+ {153, 71, 10},
+ {157, 77, 4},
+ {118, 2, 4},
+ {126, 12, 16},
+ {134, 29, 16},
+ {142, 46, 16},
+ {151, 66, 16},
+ {159, 76, 4},
+ {122, 10, 20},
+ {138, 37, 34},
+ {155, 68, 20}
+};
static_assert(ARRAY_SIZE(rf_para_tx_8822b) == ARRAY_SIZE(rf_para_rx_8822b));
static const u8
@@ -2481,6 +2507,7 @@ struct rtw_chip_info rtw8822b_hw_spec = {
.bt_desired_ver = 0x6,
.scbd_support = true,
.new_scbd10_def = false,
+ .ble_hid_profile_support = false,
.pstdma_type = COEX_PSTDMA_FORCE_LPSOFF,
.bt_rssi_type = COEX_BTRSSI_RATIO,
.ant_isolation = 15,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
index e37300e98517..7dd3ccb73793 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
@@ -2132,28 +2132,28 @@ static void rtw8822c_coex_cfg_init(struct rtw_dev *rtwdev)
/* enable TBTT nterrupt */
rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
- /* BT report packet sample rate */
+ /* BT report packet sample rate */
/* 0x790[5:0]=0x5 */
- rtw_write8_set(rtwdev, REG_BT_TDMA_TIME, 0x05);
+ rtw_write8_mask(rtwdev, REG_BT_TDMA_TIME, BIT_MASK_SAMPLE_RATE, 0x5);
/* enable BT counter statistics */
rtw_write8(rtwdev, REG_BT_STAT_CTRL, 0x1);
/* enable PTA (3-wire function form BT side) */
rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_PTA_EN);
- rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_AOD_GPIO3);
+ rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_PO_BT_PTA_PINS);
/* enable PTA (tx/rx signal form WiFi side) */
rtw_write8_set(rtwdev, REG_QUEUE_CTRL, BIT_PTA_WL_TX_EN);
/* wl tx signal to PTA not case EDCCA */
rtw_write8_clr(rtwdev, REG_QUEUE_CTRL, BIT_PTA_EDCCA_EN);
/* GNT_BT=1 while select both */
- rtw_write8_set(rtwdev, REG_BT_COEX_V2, BIT_GNT_BT_POLARITY);
- /* BT_CCA = ~GNT_WL_BB, (not or GNT_BT_BB, LTE_Rx */
+ rtw_write16_set(rtwdev, REG_BT_COEX_V2, BIT_GNT_BT_POLARITY);
+ /* BT_CCA = ~GNT_WL_BB, not or GNT_BT_BB, LTE_Rx */
rtw_write8_clr(rtwdev, REG_DUMMY_PAGE4_V1, BIT_BTCCA_CTRL);
/* to avoid RF parameter error */
- rtw_write_rf(rtwdev, RF_PATH_B, 0x1, 0xfffff, 0x40000);
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_MODOPT, 0xfffff, 0x40000);
}
static void rtw8822c_coex_cfg_gnt_fix(struct rtw_dev *rtwdev)
@@ -2190,10 +2190,10 @@ static void rtw8822c_coex_cfg_gnt_fix(struct rtw_dev *rtwdev)
* disable WL-S1 BB chage RF mode if GNT_BT
* since RF TRx mask can do it
*/
- rtw_write8_mask(rtwdev, 0x1c32, BIT(6), 1);
- rtw_write8_mask(rtwdev, 0x1c39, BIT(4), 0);
- rtw_write8_mask(rtwdev, 0x1c3b, BIT(4), 1);
- rtw_write8_mask(rtwdev, 0x4160, BIT(3), 1);
+ rtw_write8_mask(rtwdev, REG_ANAPAR + 2, BIT_ANAPAR_BTPS >> 16, 1);
+ rtw_write8_mask(rtwdev, REG_RSTB_SEL + 1, BIT_DAC_OFF_ENABLE, 0);
+ rtw_write8_mask(rtwdev, REG_RSTB_SEL + 3, BIT_DAC_OFF_ENABLE, 1);
+ rtw_write8_mask(rtwdev, REG_IGN_GNTBT4, BIT_PI_IGNORE_GNT_BT, 1);
/* disable WL-S0 BB chage RF mode if wifi is at 5G,
* or antenna path is separated
@@ -2201,26 +2201,32 @@ static void rtw8822c_coex_cfg_gnt_fix(struct rtw_dev *rtwdev)
if (coex_stat->wl_coex_mode == COEX_WLINK_5G ||
coex->under_5g || !efuse->share_ant) {
if (coex_stat->kt_ver >= 3) {
- rtw_write8_mask(rtwdev, 0x1860, BIT(3), 0);
- rtw_write8_mask(rtwdev, 0x1ca7, BIT(3), 1);
+ rtw_write8_mask(rtwdev, REG_IGN_GNT_BT1,
+ BIT_PI_IGNORE_GNT_BT, 0);
+ rtw_write8_mask(rtwdev, REG_NOMASK_TXBT,
+ BIT_NOMASK_TXBT_ENABLE, 1);
} else {
- rtw_write8_mask(rtwdev, 0x1860, BIT(3), 1);
+ rtw_write8_mask(rtwdev, REG_IGN_GNT_BT1,
+ BIT_PI_IGNORE_GNT_BT, 1);
}
} else {
/* shared-antenna */
- rtw_write8_mask(rtwdev, 0x1860, BIT(3), 0);
- if (coex_stat->kt_ver >= 3)
- rtw_write8_mask(rtwdev, 0x1ca7, BIT(3), 0);
+ rtw_write8_mask(rtwdev, REG_IGN_GNT_BT1,
+ BIT_PI_IGNORE_GNT_BT, 0);
+ if (coex_stat->kt_ver >= 3) {
+ rtw_write8_mask(rtwdev, REG_NOMASK_TXBT,
+ BIT_NOMASK_TXBT_ENABLE, 0);
+ }
}
}
static void rtw8822c_coex_cfg_gnt_debug(struct rtw_dev *rtwdev)
{
- rtw_write8_mask(rtwdev, 0x66, BIT(4), 0);
- rtw_write8_mask(rtwdev, 0x67, BIT(0), 0);
- rtw_write8_mask(rtwdev, 0x42, BIT(3), 0);
- rtw_write8_mask(rtwdev, 0x65, BIT(7), 0);
- rtw_write8_mask(rtwdev, 0x73, BIT(3), 0);
+ rtw_write8_mask(rtwdev, REG_PAD_CTRL1 + 2, BIT_BTGP_SPI_EN >> 16, 0);
+ rtw_write8_mask(rtwdev, REG_PAD_CTRL1 + 3, BIT_BTGP_JTAG_EN >> 24, 0);
+ rtw_write8_mask(rtwdev, REG_GPIO_MUXCFG + 2, BIT_FSPI_EN >> 16, 0);
+ rtw_write8_mask(rtwdev, REG_PAD_CTRL1 + 1, BIT_LED1DIS >> 8, 0);
+ rtw_write8_mask(rtwdev, REG_SYS_SDIO_CTRL + 3, BIT_DBG_GNT_WL_BT >> 24, 0);
}
static void rtw8822c_coex_cfg_rfe_type(struct rtw_dev *rtwdev)
@@ -2241,9 +2247,9 @@ static void rtw8822c_coex_cfg_rfe_type(struct rtw_dev *rtwdev)
coex_rfe->wlg_at_btg = false;
/* disable LTE coex in wifi side */
- rtw_coex_write_indirect_reg(rtwdev, 0x38, BIT_LTE_COEX_EN, 0x0);
- rtw_coex_write_indirect_reg(rtwdev, 0xa0, MASKLWORD, 0xffff);
- rtw_coex_write_indirect_reg(rtwdev, 0xa4, MASKLWORD, 0xffff);
+ rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, BIT_LTE_COEX_EN, 0x0);
+ rtw_coex_write_indirect_reg(rtwdev, LTE_WL_TRX_CTRL, MASKLWORD, 0xffff);
+ rtw_coex_write_indirect_reg(rtwdev, LTE_BT_TRX_CTRL, MASKLWORD, 0xffff);
}
static void rtw8822c_coex_cfg_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr)
@@ -2268,16 +2274,22 @@ static void rtw8822c_coex_cfg_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain)
coex_dm->cur_wl_rx_low_gain_en = low_gain;
if (coex_dm->cur_wl_rx_low_gain_en) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], Hi-Li Table On!\n");
+
/* set Rx filter corner RCK offset */
- rtw_write_rf(rtwdev, RF_PATH_A, 0xde, 0xfffff, 0x22);
- rtw_write_rf(rtwdev, RF_PATH_A, 0x1d, 0xfffff, 0x36);
- rtw_write_rf(rtwdev, RF_PATH_B, 0xde, 0xfffff, 0x22);
- rtw_write_rf(rtwdev, RF_PATH_B, 0x1d, 0xfffff, 0x36);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_RCKD, RFREG_MASK, 0x22);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_RCK, RFREG_MASK, 0x36);
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_RCKD, RFREG_MASK, 0x22);
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_RCK, RFREG_MASK, 0x36);
+
} else {
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], Hi-Li Table Off!\n");
+
/* set Rx filter corner RCK offset */
- rtw_write_rf(rtwdev, RF_PATH_A, 0xde, 0xfffff, 0x20);
- rtw_write_rf(rtwdev, RF_PATH_A, 0x1d, 0xfffff, 0x0);
- rtw_write_rf(rtwdev, RF_PATH_B, 0x1d, 0xfffff, 0x0);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_RCKD, RFREG_MASK, 0x20);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_RCK, RFREG_MASK, 0x0);
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_RCKD, RFREG_MASK, 0x20);
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_RCK, RFREG_MASK, 0x0);
}
}
@@ -2442,7 +2454,7 @@ static void rtw8822c_dpk_rxbb_dc_cal(struct rtw_dev *rtwdev, u8 path)
static u8 rtw8822c_dpk_dc_corr_check(struct rtw_dev *rtwdev, u8 path)
{
u16 dc_i, dc_q;
- u8 corr_val, corr_idx;
+ u8 corr_idx;
rtw_write32(rtwdev, REG_RXSRAM_CTL, 0x000900f0);
dc_i = (u16)rtw_read32_mask(rtwdev, REG_STAT_RPT, GENMASK(27, 16));
@@ -2455,7 +2467,7 @@ static u8 rtw8822c_dpk_dc_corr_check(struct rtw_dev *rtwdev, u8 path)
rtw_write32(rtwdev, REG_RXSRAM_CTL, 0x000000f0);
corr_idx = (u8)rtw_read32_mask(rtwdev, REG_STAT_RPT, GENMASK(7, 0));
- corr_val = (u8)rtw_read32_mask(rtwdev, REG_STAT_RPT, GENMASK(15, 8));
+ rtw_read32_mask(rtwdev, REG_STAT_RPT, GENMASK(15, 8));
if (dc_i > 200 || dc_q > 200 || corr_idx < 40 || corr_idx > 65)
return 1;
@@ -3442,6 +3454,10 @@ rtw8822c_phy_cck_pd_set_reg(struct rtw_dev *rtwdev,
rtw8822c_cck_pd_reg[bw][nrx].reg_cs,
rtw8822c_cck_pd_reg[bw][nrx].mask_cs,
cs);
+
+ rtw_dbg(rtwdev, RTW_DBG_PHY,
+ "is_linked=%d, bw=%d, nrx=%d, cs_ratio=0x%x, pd_th=0x%x\n",
+ rtw_is_assoc(rtwdev), bw, nrx, cs, pd);
}
static void rtw8822c_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl)
@@ -3455,6 +3471,10 @@ static void rtw8822c_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl)
nrx = (u8)rtw_read32_mask(rtwdev, 0x1a2c, 0x60000);
bw = (u8)rtw_read32_mask(rtwdev, 0x9b0, 0xc);
+ rtw_dbg(rtwdev, RTW_DBG_PHY, "lv: (%d) -> (%d) bw=%d nr=%d cck_fa_avg=%d\n",
+ dm_info->cck_pd_lv[bw][nrx], new_lvl, bw, nrx,
+ dm_info->cck_fa_avg);
+
if (dm_info->cck_pd_lv[bw][nrx] == new_lvl)
return;
@@ -3983,14 +4003,14 @@ static const struct coex_table_para table_sant_8822c[] = {
{0xaaaaaaaa, 0xaaaaaaaa},
{0x5a5a5a5a, 0x5a5a5a5a},
{0xfafafafa, 0xfafafafa}, /* case-5 */
- {0x6a5a6a5a, 0xaaaaaaaa},
+ {0x6a5a5555, 0xaaaaaaaa},
{0x6a5a56aa, 0x6a5a56aa},
{0x6a5a5a5a, 0x6a5a5a5a},
{0x66555555, 0x5a5a5a5a},
{0x66555555, 0x6a5a5a5a}, /* case-10 */
- {0x66555555, 0xfafafafa},
+ {0x66555555, 0x6a5a5aaa},
{0x66555555, 0x5a5a5aaa},
- {0x66555555, 0x5aaa5aaa},
+ {0x66555555, 0x6aaa5aaa},
{0x66555555, 0xaaaa5aaa},
{0x66555555, 0xaaaaaaaa}, /* case-15 */
{0xffff55ff, 0xfafafafa},
@@ -4000,13 +4020,16 @@ static const struct coex_table_para table_sant_8822c[] = {
{0xaa5555aa, 0x6a5a5a5a}, /* case-20 */
{0xaa5555aa, 0xaaaaaaaa},
{0xffffffff, 0x5a5a5a5a},
- {0xffffffff, 0x6a5a5a5a},
+ {0xffffffff, 0x5a5a5a5a},
{0xffffffff, 0x55555555},
- {0xffffffff, 0x6a5a5aaa}, /* case-25 */
+ {0xffffffff, 0x5a5a5aaa}, /* case-25 */
{0x55555555, 0x5a5a5a5a},
{0x55555555, 0xaaaaaaaa},
{0x55555555, 0x6a5a6a5a},
- {0x66556655, 0x66556655}
+ {0x66556655, 0x66556655},
+ {0x66556aaa, 0x6a5a6aaa}, /*case-30*/
+ {0xffffffff, 0x5aaa5aaa},
+ {0x56555555, 0x5a5a5aaa},
};
/* Non-Shared-Antenna Coex Table */
@@ -4026,12 +4049,12 @@ static const struct coex_table_para table_nsant_8822c[] = {
{0xffff55ff, 0xfafafafa},
{0xffff55ff, 0x5afa5afa},
{0xffff55ff, 0xaaaaaaaa},
- {0xaaffffaa, 0xfafafafa}, /* case-115 */
+ {0xffff55ff, 0xffff55ff}, /* case-115 */
{0xaaffffaa, 0x5afa5afa},
{0xaaffffaa, 0xaaaaaaaa},
{0xffffffff, 0xfafafafa},
{0xffffffff, 0x5afa5afa},
- {0xffffffff, 0xaaaaaaaa},/* case-120 */
+ {0xffffffff, 0xaaaaaaaa}, /* case-120 */
{0x55ff55ff, 0x5afa5afa},
{0x55ff55ff, 0xaaaaaaaa},
{0x55ff55ff, 0x55ff55ff}
@@ -4040,7 +4063,7 @@ static const struct coex_table_para table_nsant_8822c[] = {
/* Shared-Antenna TDMA */
static const struct coex_tdma_para tdma_sant_8822c[] = {
{ {0x00, 0x00, 0x00, 0x00, 0x00} }, /* case-0 */
- { {0x61, 0x45, 0x03, 0x11, 0x11} },
+ { {0x61, 0x45, 0x03, 0x11, 0x11} }, /* case-1 */
{ {0x61, 0x3a, 0x03, 0x11, 0x11} },
{ {0x61, 0x30, 0x03, 0x11, 0x11} },
{ {0x61, 0x20, 0x03, 0x11, 0x11} },
@@ -4055,7 +4078,7 @@ static const struct coex_tdma_para tdma_sant_8822c[] = {
{ {0x51, 0x08, 0x03, 0x10, 0x54} },
{ {0x51, 0x08, 0x03, 0x10, 0x55} },
{ {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-15 */
- { {0x51, 0x45, 0x03, 0x10, 0x10} },
+ { {0x51, 0x45, 0x03, 0x10, 0x50} },
{ {0x51, 0x3a, 0x03, 0x10, 0x50} },
{ {0x51, 0x30, 0x03, 0x10, 0x50} },
{ {0x51, 0x20, 0x03, 0x10, 0x50} },
@@ -4063,7 +4086,7 @@ static const struct coex_tdma_para tdma_sant_8822c[] = {
{ {0x51, 0x4a, 0x03, 0x10, 0x50} },
{ {0x51, 0x0c, 0x03, 0x10, 0x54} },
{ {0x55, 0x08, 0x03, 0x10, 0x54} },
- { {0x65, 0x10, 0x03, 0x11, 0x11} },
+ { {0x65, 0x10, 0x03, 0x11, 0x10} },
{ {0x51, 0x10, 0x03, 0x10, 0x51} }, /* case-25 */
{ {0x51, 0x08, 0x03, 0x10, 0x50} },
{ {0x61, 0x08, 0x03, 0x11, 0x11} }
@@ -4091,7 +4114,8 @@ static const struct coex_tdma_para tdma_nsant_8822c[] = {
{ {0x51, 0x3a, 0x03, 0x10, 0x50} },
{ {0x51, 0x30, 0x03, 0x10, 0x50} },
{ {0x51, 0x20, 0x03, 0x10, 0x50} },
- { {0x51, 0x10, 0x03, 0x10, 0x50} } /* case-120 */
+ { {0x51, 0x10, 0x03, 0x10, 0x50} }, /* case-120 */
+ { {0x51, 0x08, 0x03, 0x10, 0x50} }
};
/* rssi in percentage % (dbm = % - 100) */
@@ -4337,10 +4361,11 @@ struct rtw_chip_info rtw8822c_hw_spec = {
.wowlan_stub = &rtw_wowlan_stub_8822c,
.max_sched_scan_ssids = 4,
#endif
- .coex_para_ver = 0x20070217,
- .bt_desired_ver = 0x17,
+ .coex_para_ver = 0x201029,
+ .bt_desired_ver = 0x1c,
.scbd_support = true,
.new_scbd10_def = true,
+ .ble_hid_profile_support = true,
.pstdma_type = COEX_PSTDMA_FORCE_LPSOFF,
.bt_rssi_type = COEX_BTRSSI_DBM,
.ant_isolation = 15,
diff --git a/drivers/net/wireless/realtek/rtw88/wow.c b/drivers/net/wireless/realtek/rtw88/wow.c
index 2fcdf70a3a77..fc9544f4e5e4 100644
--- a/drivers/net/wireless/realtek/rtw88/wow.c
+++ b/drivers/net/wireless/realtek/rtw88/wow.c
@@ -332,7 +332,8 @@ static void rtw_wow_fw_security_type_iter(struct ieee80211_hw *hw,
key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
break;
default:
- rtw_err(rtwdev, "Unsupported key type for wowlan mode\n");
+ rtw_err(rtwdev, "Unsupported key type for wowlan mode: %#x\n",
+ key->cipher);
hw_key_type = 0;
break;
}
@@ -555,7 +556,7 @@ static int rtw_wow_leave_no_link_ps(struct rtw_dev *rtwdev)
int ret = 0;
if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) {
- if (rtw_fw_lps_deep_mode)
+ if (rtw_get_lps_deep_mode(rtwdev) != LPS_DEEP_MODE_NONE)
rtw_leave_lps_deep(rtwdev);
} else {
if (test_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags)) {
@@ -616,7 +617,8 @@ static int rtw_wow_enter_ps(struct rtw_dev *rtwdev)
if (rtw_wow_mgd_linked(rtwdev))
ret = rtw_wow_enter_linked_ps(rtwdev);
- else if (rtw_wow_no_link(rtwdev) && rtw_fw_lps_deep_mode)
+ else if (rtw_wow_no_link(rtwdev) &&
+ rtw_get_lps_deep_mode(rtwdev) != LPS_DEEP_MODE_NONE)
ret = rtw_wow_enter_no_link_ps(rtwdev);
return ret;
diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c
index 3f7e3cfb6f00..ce9892152f4d 100644
--- a/drivers/net/wireless/rsi/rsi_91x_hal.c
+++ b/drivers/net/wireless/rsi/rsi_91x_hal.c
@@ -248,7 +248,8 @@ int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb)
rsi_set_len_qno(&data_desc->len_qno,
(skb->len - FRAME_DESC_SZ),
RSI_WIFI_MGMT_Q);
- if ((skb->len - header_size) == EAPOL4_PACKET_LEN) {
+ if (((skb->len - header_size) == EAPOL4_PACKET_LEN) ||
+ ((skb->len - header_size) == EAPOL4_PACKET_LEN - 2)) {
data_desc->misc_flags |=
RSI_DESC_REQUIRE_CFM_TO_HOST;
xtend_desc->confirm_frame_type = EAPOL4_CONFIRM;
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index a7b8684143f4..592e9dadcb55 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -153,9 +153,7 @@ static void rsi_handle_interrupt(struct sdio_func *function)
if (adapter->priv->fsm_state == FSM_FW_NOT_LOADED)
return;
- dev->sdio_irq_task = current;
- rsi_interrupt_handler(adapter);
- dev->sdio_irq_task = NULL;
+ rsi_set_event(&dev->rx_thread.event);
}
/**
@@ -1058,8 +1056,6 @@ static int rsi_probe(struct sdio_func *pfunction,
rsi_dbg(ERR_ZONE, "%s: Unable to init rx thrd\n", __func__);
goto fail_kill_thread;
}
- skb_queue_head_init(&sdev->rx_q.head);
- sdev->rx_q.num_rx_pkts = 0;
sdio_claim_host(pfunction);
if (sdio_claim_irq(pfunction, rsi_handle_interrupt)) {
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
index 7825c9a889d3..8ace1874e5cb 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
@@ -60,39 +60,20 @@ int rsi_sdio_master_access_msword(struct rsi_hw *adapter, u16 ms_word)
return status;
}
+static void rsi_rx_handler(struct rsi_hw *adapter);
+
void rsi_sdio_rx_thread(struct rsi_common *common)
{
struct rsi_hw *adapter = common->priv;
struct rsi_91x_sdiodev *sdev = adapter->rsi_dev;
- struct sk_buff *skb;
- int status;
do {
rsi_wait_event(&sdev->rx_thread.event, EVENT_WAIT_FOREVER);
rsi_reset_event(&sdev->rx_thread.event);
+ rsi_rx_handler(adapter);
+ } while (!atomic_read(&sdev->rx_thread.thread_done));
- while (true) {
- if (atomic_read(&sdev->rx_thread.thread_done))
- goto out;
-
- skb = skb_dequeue(&sdev->rx_q.head);
- if (!skb)
- break;
- if (sdev->rx_q.num_rx_pkts > 0)
- sdev->rx_q.num_rx_pkts--;
- status = rsi_read_pkt(common, skb->data, skb->len);
- if (status) {
- rsi_dbg(ERR_ZONE, "Failed to read the packet\n");
- dev_kfree_skb(skb);
- break;
- }
- dev_kfree_skb(skb);
- }
- } while (1);
-
-out:
rsi_dbg(INFO_ZONE, "%s: Terminated SDIO RX thread\n", __func__);
- skb_queue_purge(&sdev->rx_q.head);
atomic_inc(&sdev->rx_thread.thread_done);
complete_and_exit(&sdev->rx_thread.completion, 0);
}
@@ -113,10 +94,6 @@ static int rsi_process_pkt(struct rsi_common *common)
u32 rcv_pkt_len = 0;
int status = 0;
u8 value = 0;
- struct sk_buff *skb;
-
- if (dev->rx_q.num_rx_pkts >= RSI_MAX_RX_PKTS)
- return 0;
num_blks = ((adapter->interrupt_status & 1) |
((adapter->interrupt_status >> RECV_NUM_BLOCKS) << 1));
@@ -144,22 +121,19 @@ static int rsi_process_pkt(struct rsi_common *common)
rcv_pkt_len = (num_blks * 256);
- skb = dev_alloc_skb(rcv_pkt_len);
- if (!skb)
- return -ENOMEM;
-
- status = rsi_sdio_host_intf_read_pkt(adapter, skb->data, rcv_pkt_len);
+ status = rsi_sdio_host_intf_read_pkt(adapter, dev->pktbuffer,
+ rcv_pkt_len);
if (status) {
rsi_dbg(ERR_ZONE, "%s: Failed to read packet from card\n",
__func__);
- dev_kfree_skb(skb);
return status;
}
- skb_put(skb, rcv_pkt_len);
- skb_queue_tail(&dev->rx_q.head, skb);
- dev->rx_q.num_rx_pkts++;
- rsi_set_event(&dev->rx_thread.event);
+ status = rsi_read_pkt(common, dev->pktbuffer, rcv_pkt_len);
+ if (status) {
+ rsi_dbg(ERR_ZONE, "Failed to read the packet\n");
+ return status;
+ }
return 0;
}
@@ -251,18 +225,17 @@ int rsi_init_sdio_slave_regs(struct rsi_hw *adapter)
}
/**
- * rsi_interrupt_handler() - This function read and process SDIO interrupts.
+ * rsi_rx_handler() - Read and process SDIO interrupts.
* @adapter: Pointer to the adapter structure.
*
* Return: None.
*/
-void rsi_interrupt_handler(struct rsi_hw *adapter)
+static void rsi_rx_handler(struct rsi_hw *adapter)
{
struct rsi_common *common = adapter->priv;
struct rsi_91x_sdiodev *dev =
(struct rsi_91x_sdiodev *)adapter->rsi_dev;
int status;
- enum sdio_interrupt_type isr_type;
u8 isr_status = 0;
u8 fw_status = 0;
@@ -293,73 +266,69 @@ void rsi_interrupt_handler(struct rsi_hw *adapter)
__func__, isr_status, (1 << MSDU_PKT_PENDING),
(1 << FW_ASSERT_IND));
- do {
- RSI_GET_SDIO_INTERRUPT_TYPE(isr_status, isr_type);
-
- switch (isr_type) {
- case BUFFER_AVAILABLE:
- status = rsi_sdio_check_buffer_status(adapter,
- 0);
- if (status < 0)
- rsi_dbg(ERR_ZONE,
- "%s: Failed to check buffer status\n",
- __func__);
- rsi_sdio_ack_intr(common->priv,
- (1 << PKT_BUFF_AVAILABLE));
- rsi_set_event(&common->tx_thread.event);
-
- rsi_dbg(ISR_ZONE,
- "%s: ==> BUFFER_AVAILABLE <==\n",
- __func__);
- dev->buff_status_updated = true;
- break;
-
- case FIRMWARE_ASSERT_IND:
+ if (isr_status & BIT(PKT_BUFF_AVAILABLE)) {
+ status = rsi_sdio_check_buffer_status(adapter, 0);
+ if (status < 0)
rsi_dbg(ERR_ZONE,
- "%s: ==> FIRMWARE Assert <==\n",
+ "%s: Failed to check buffer status\n",
__func__);
- status = rsi_sdio_read_register(common->priv,
+ rsi_sdio_ack_intr(common->priv,
+ BIT(PKT_BUFF_AVAILABLE));
+ rsi_set_event(&common->tx_thread.event);
+
+ rsi_dbg(ISR_ZONE, "%s: ==> BUFFER_AVAILABLE <==\n",
+ __func__);
+ dev->buff_status_updated = true;
+
+ isr_status &= ~BIT(PKT_BUFF_AVAILABLE);
+ }
+
+ if (isr_status & BIT(FW_ASSERT_IND)) {
+ rsi_dbg(ERR_ZONE, "%s: ==> FIRMWARE Assert <==\n",
+ __func__);
+ status = rsi_sdio_read_register(common->priv,
SDIO_FW_STATUS_REG,
&fw_status);
- if (status) {
- rsi_dbg(ERR_ZONE,
- "%s: Failed to read f/w reg\n",
- __func__);
- } else {
- rsi_dbg(ERR_ZONE,
- "%s: Firmware Status is 0x%x\n",
- __func__ , fw_status);
- rsi_sdio_ack_intr(common->priv,
- (1 << FW_ASSERT_IND));
- }
-
- common->fsm_state = FSM_CARD_NOT_READY;
- break;
-
- case MSDU_PACKET_PENDING:
- rsi_dbg(ISR_ZONE, "Pkt pending interrupt\n");
- dev->rx_info.total_sdio_msdu_pending_intr++;
-
- status = rsi_process_pkt(common);
- if (status) {
- rsi_dbg(ERR_ZONE,
- "%s: Failed to read pkt\n",
- __func__);
- mutex_unlock(&common->rx_lock);
- return;
- }
- break;
- default:
- rsi_sdio_ack_intr(common->priv, isr_status);
- dev->rx_info.total_sdio_unknown_intr++;
- isr_status = 0;
- rsi_dbg(ISR_ZONE,
- "Unknown Interrupt %x\n",
- isr_status);
- break;
+ if (status) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to read f/w reg\n",
+ __func__);
+ } else {
+ rsi_dbg(ERR_ZONE,
+ "%s: Firmware Status is 0x%x\n",
+ __func__, fw_status);
+ rsi_sdio_ack_intr(common->priv,
+ BIT(FW_ASSERT_IND));
}
- isr_status ^= BIT(isr_type - 1);
- } while (isr_status);
+
+ common->fsm_state = FSM_CARD_NOT_READY;
+
+ isr_status &= ~BIT(FW_ASSERT_IND);
+ }
+
+ if (isr_status & BIT(MSDU_PKT_PENDING)) {
+ rsi_dbg(ISR_ZONE, "Pkt pending interrupt\n");
+ dev->rx_info.total_sdio_msdu_pending_intr++;
+
+ status = rsi_process_pkt(common);
+ if (status) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to read pkt\n",
+ __func__);
+ mutex_unlock(&common->rx_lock);
+ return;
+ }
+
+ isr_status &= ~BIT(MSDU_PKT_PENDING);
+ }
+
+ if (isr_status) {
+ rsi_sdio_ack_intr(common->priv, isr_status);
+ dev->rx_info.total_sdio_unknown_intr++;
+ isr_status = 0;
+ rsi_dbg(ISR_ZONE, "Unknown Interrupt %x\n",
+ isr_status);
+ }
+
mutex_unlock(&common->rx_lock);
} while (1);
}
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index a62d41c0ccbc..a4a533c2a783 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (c) 2014 Redpine Signals Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -75,7 +75,7 @@ static int rsi_usb_card_write(struct rsi_hw *adapter,
* rsi_write_multiple() - This function writes multiple bytes of information
* to the USB card.
* @adapter: Pointer to the adapter structure.
- * @addr: Address of the register.
+ * @endpoint: Type of endpoint.
* @data: Pointer to the data that has to be written.
* @count: Number of multiple bytes to be written.
*
@@ -313,6 +313,8 @@ static void rsi_rx_urb_kill(struct rsi_hw *adapter, u8 ep_num)
/**
* rsi_rx_urb_submit() - This function submits the given URB to the USB stack.
* @adapter: Pointer to the adapter structure.
+ * @ep_num: Endpoint number.
+ * @mem_flags: The type of memory to allocate.
*
* Return: 0 on success, a negative error code on failure.
*/
@@ -741,24 +743,24 @@ static int rsi_reset_card(struct rsi_hw *adapter)
if (ret < 0)
goto fail;
} else {
- if ((rsi_usb_master_reg_write(adapter,
- NWP_WWD_INTERRUPT_TIMER,
- NWP_WWD_INT_TIMER_CLKS,
- RSI_9116_REG_SIZE)) < 0) {
+ ret = rsi_usb_master_reg_write(adapter,
+ NWP_WWD_INTERRUPT_TIMER,
+ NWP_WWD_INT_TIMER_CLKS,
+ RSI_9116_REG_SIZE);
+ if (ret < 0)
goto fail;
- }
- if ((rsi_usb_master_reg_write(adapter,
- NWP_WWD_SYSTEM_RESET_TIMER,
- NWP_WWD_SYS_RESET_TIMER_CLKS,
- RSI_9116_REG_SIZE)) < 0) {
+ ret = rsi_usb_master_reg_write(adapter,
+ NWP_WWD_SYSTEM_RESET_TIMER,
+ NWP_WWD_SYS_RESET_TIMER_CLKS,
+ RSI_9116_REG_SIZE);
+ if (ret < 0)
goto fail;
- }
- if ((rsi_usb_master_reg_write(adapter,
- NWP_WWD_MODE_AND_RSTART,
- NWP_WWD_TIMER_DISABLE,
- RSI_9116_REG_SIZE)) < 0) {
+ ret = rsi_usb_master_reg_write(adapter,
+ NWP_WWD_MODE_AND_RSTART,
+ NWP_WWD_TIMER_DISABLE,
+ RSI_9116_REG_SIZE);
+ if (ret < 0)
goto fail;
- }
}
rsi_dbg(INFO_ZONE, "Reset card done\n");
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb_ops.c b/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
index b1687d22f73f..4ffcdde1acb1 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (c) 2014 Redpine Signals Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
diff --git a/drivers/net/wireless/rsi/rsi_sdio.h b/drivers/net/wireless/rsi/rsi_sdio.h
index 9afc1d0d2684..1c756263cf15 100644
--- a/drivers/net/wireless/rsi/rsi_sdio.h
+++ b/drivers/net/wireless/rsi/rsi_sdio.h
@@ -107,11 +107,6 @@ struct receive_info {
u32 buf_available_counter;
};
-struct rsi_sdio_rx_q {
- u8 num_rx_pkts;
- struct sk_buff_head head;
-};
-
struct rsi_91x_sdiodev {
struct sdio_func *pfunction;
struct task_struct *sdio_irq_task;
@@ -124,11 +119,10 @@ struct rsi_91x_sdiodev {
u16 tx_blk_size;
u8 write_fail;
bool buff_status_updated;
- struct rsi_sdio_rx_q rx_q;
struct rsi_thread rx_thread;
+ u8 pktbuffer[8192] __aligned(4);
};
-void rsi_interrupt_handler(struct rsi_hw *adapter);
int rsi_init_sdio_slave_regs(struct rsi_hw *adapter);
int rsi_sdio_read_register(struct rsi_hw *adapter, u32 addr, u8 *data);
int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter, u8 *pkt, u32 length);
diff --git a/drivers/net/wireless/st/cw1200/bh.c b/drivers/net/wireless/st/cw1200/bh.c
index 02efe8483cba..c364a3987618 100644
--- a/drivers/net/wireless/st/cw1200/bh.c
+++ b/drivers/net/wireless/st/cw1200/bh.c
@@ -85,7 +85,7 @@ int cw1200_register_bh(struct cw1200_common *priv)
void cw1200_unregister_bh(struct cw1200_common *priv)
{
- atomic_add(1, &priv->bh_term);
+ atomic_inc(&priv->bh_term);
wake_up(&priv->bh_wq);
flush_workqueue(priv->bh_workqueue);
@@ -107,7 +107,7 @@ void cw1200_irq_handler(struct cw1200_common *priv)
if (/* WARN_ON */(priv->bh_error))
return;
- if (atomic_add_return(1, &priv->bh_rx) == 1)
+ if (atomic_inc_return(&priv->bh_rx) == 1)
wake_up(&priv->bh_wq);
}
EXPORT_SYMBOL_GPL(cw1200_irq_handler);
@@ -120,7 +120,7 @@ void cw1200_bh_wakeup(struct cw1200_common *priv)
return;
}
- if (atomic_add_return(1, &priv->bh_tx) == 1)
+ if (atomic_inc_return(&priv->bh_tx) == 1)
wake_up(&priv->bh_wq);
}
@@ -382,7 +382,7 @@ static int cw1200_bh_tx_helper(struct cw1200_common *priv,
BUG_ON(tx_len < sizeof(*wsm));
BUG_ON(__le16_to_cpu(wsm->len) != tx_len);
- atomic_add(1, &priv->bh_tx);
+ atomic_inc(&priv->bh_tx);
tx_len = priv->hwbus_ops->align_size(
priv->hwbus_priv, tx_len);
@@ -537,7 +537,7 @@ static int cw1200_bh(void *arg)
pr_debug("[BH] Device resume.\n");
atomic_set(&priv->bh_suspend, CW1200_BH_RESUMED);
wake_up(&priv->bh_evt_wq);
- atomic_add(1, &priv->bh_rx);
+ atomic_inc(&priv->bh_rx);
goto done;
}
diff --git a/drivers/net/wireless/st/cw1200/main.c b/drivers/net/wireless/st/cw1200/main.c
index f7fe56affbcd..326b1cc1d2bc 100644
--- a/drivers/net/wireless/st/cw1200/main.c
+++ b/drivers/net/wireless/st/cw1200/main.c
@@ -381,6 +381,7 @@ static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr,
CW1200_LINK_ID_MAX,
cw1200_skb_dtor,
priv)) {
+ destroy_workqueue(priv->workqueue);
ieee80211_free_hw(hw);
return NULL;
}
@@ -392,6 +393,7 @@ static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr,
for (; i > 0; i--)
cw1200_queue_deinit(&priv->tx_queue[i - 1]);
cw1200_queue_stats_deinit(&priv->tx_queue_stats);
+ destroy_workqueue(priv->workqueue);
ieee80211_free_hw(hw);
return NULL;
}
diff --git a/drivers/net/wireless/st/cw1200/wsm.c b/drivers/net/wireless/st/cw1200/wsm.c
index d9b6147bbb52..99624dd34886 100644
--- a/drivers/net/wireless/st/cw1200/wsm.c
+++ b/drivers/net/wireless/st/cw1200/wsm.c
@@ -1139,7 +1139,7 @@ static int wsm_cmd_send(struct cw1200_common *priv,
pr_err("Outstanding outgoing frames: %d\n", priv->hw_bufs_used);
/* Kill BH thread to report the error to the top layer. */
- atomic_add(1, &priv->bh_term);
+ atomic_inc(&priv->bh_term);
wake_up(&priv->bh_wq);
ret = -ETIMEDOUT;
}
@@ -1160,7 +1160,7 @@ done:
void wsm_lock_tx(struct cw1200_common *priv)
{
wsm_cmd_lock(priv);
- if (atomic_add_return(1, &priv->tx_lock) == 1) {
+ if (atomic_inc_return(&priv->tx_lock) == 1) {
if (wsm_flush_tx(priv))
pr_debug("[WSM] TX is locked.\n");
}
@@ -1169,7 +1169,7 @@ void wsm_lock_tx(struct cw1200_common *priv)
void wsm_lock_tx_async(struct cw1200_common *priv)
{
- if (atomic_add_return(1, &priv->tx_lock) == 1)
+ if (atomic_inc_return(&priv->tx_lock) == 1)
pr_debug("[WSM] TX is locked (async).\n");
}
@@ -1223,7 +1223,7 @@ bool wsm_flush_tx(struct cw1200_common *priv)
void wsm_unlock_tx(struct cw1200_common *priv)
{
int tx_lock;
- tx_lock = atomic_sub_return(1, &priv->tx_lock);
+ tx_lock = atomic_dec_return(&priv->tx_lock);
BUG_ON(tx_lock < 0);
if (tx_lock == 0) {
diff --git a/drivers/net/wireless/ti/wl1251/cmd.c b/drivers/net/wireless/ti/wl1251/cmd.c
index 9547aea01b0f..e1095b8de2bd 100644
--- a/drivers/net/wireless/ti/wl1251/cmd.c
+++ b/drivers/net/wireless/ti/wl1251/cmd.c
@@ -63,7 +63,7 @@ out:
*
* @wl: wl struct
* @buf: buffer containing the command, with all headers, must work with dma
- * @len: length of the buffer
+ * @buf_len: length of the buffer
* @answer: is answer needed
*/
int wl1251_cmd_test(struct wl1251 *wl, void *buf, size_t buf_len, u8 answer)
diff --git a/drivers/net/wireless/ti/wl1251/debugfs.c b/drivers/net/wireless/ti/wl1251/debugfs.c
index d48746e640cc..a1b778a0fda0 100644
--- a/drivers/net/wireless/ti/wl1251/debugfs.c
+++ b/drivers/net/wireless/ti/wl1251/debugfs.c
@@ -39,7 +39,7 @@ static const struct file_operations name## _ops = { \
#define DEBUGFS_ADD(name, parent) \
wl->debugfs.name = debugfs_create_file(#name, 0400, parent, \
- wl, &name## _ops); \
+ wl, &name## _ops) \
#define DEBUGFS_DEL(name) \
do { \
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 6863fd552d5e..122c7a4b374f 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -2227,7 +2227,7 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
switch (ieee80211_vif_type_p2p(vif)) {
case NL80211_IFTYPE_P2P_CLIENT:
wlvif->p2p = 1;
- /* fall-through */
+ fallthrough;
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_P2P_DEVICE:
wlvif->bss_type = BSS_TYPE_STA_BSS;
@@ -2237,7 +2237,7 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
break;
case NL80211_IFTYPE_P2P_GO:
wlvif->p2p = 1;
- /* fall-through */
+ fallthrough;
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_MESH_POINT:
wlvif->bss_type = BSS_TYPE_AP_BSS;
diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c
index 18c4d998ce4b..f26fc150ecd0 100644
--- a/drivers/net/wireless/ti/wlcore/spi.c
+++ b/drivers/net/wireless/ti/wlcore/spi.c
@@ -391,7 +391,7 @@ static int wl12xx_spi_set_power(struct device *child, bool enable)
return ret;
}
-/**
+/*
* wl12xx_spi_set_block_size
*
* This function is not needed for spi mode, but need to be present.
@@ -431,7 +431,6 @@ MODULE_DEVICE_TABLE(of, wlcore_spi_of_match_table);
/**
* wlcore_probe_of - DT node parsing.
* @spi: SPI slave device parameters.
- * @res: resource parameters.
* @glue: wl12xx SPI bus to slave device glue parameters.
* @pdev_data: wlcore device parameters
*/
diff --git a/drivers/net/wireless/ti/wlcore/sysfs.c b/drivers/net/wireless/ti/wlcore/sysfs.c
index 7ac1814182ba..5cf0379b88b6 100644
--- a/drivers/net/wireless/ti/wlcore/sysfs.c
+++ b/drivers/net/wireless/ti/wlcore/sysfs.c
@@ -100,7 +100,7 @@ static ssize_t wl1271_sysfs_read_fwlog(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buffer, loff_t pos, size_t count)
{
- struct device *dev = container_of(kobj, struct device, kobj);
+ struct device *dev = kobj_to_dev(kobj);
struct wl1271 *wl = dev_get_drvdata(dev);
ssize_t len;
int ret;
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 026e88b80bfc..8ca5789c7b37 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -134,7 +134,7 @@ static const struct {
/**
* iw_valid_channel - validate channel in regulatory domain
- * @reg_comain: regulatory domain
+ * @reg_domain: regulatory domain
* @channel: channel to validate
*
* Returns 0 if invalid in the specified regulatory domain, non-zero if valid.
@@ -458,11 +458,9 @@ out:
/**
* wl3501_send_pkt - Send a packet.
* @this: Card
- *
- * Send a packet.
- *
- * data = Ethernet raw frame. (e.g. data[0] - data[5] is Dest MAC Addr,
+ * @data: Ethernet raw frame. (e.g. data[0] - data[5] is Dest MAC Addr,
* data[6] - data[11] is Src MAC Addr)
+ * @len: Packet length
* Ref: IEEE 802.11
*/
static int wl3501_send_pkt(struct wl3501_card *this, u8 *data, u16 len)
diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_usb.c b/drivers/net/wireless/zydas/zd1211rw/zd_usb.c
index 66367ab7e4c1..5c4cd0e1adeb 100644
--- a/drivers/net/wireless/zydas/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zydas/zd1211rw/zd_usb.c
@@ -1711,11 +1711,6 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
count, USB_MAX_IOREAD16_COUNT);
return -EINVAL;
}
- if (in_atomic()) {
- dev_dbg_f(zd_usb_dev(usb),
- "error: io in atomic context not supported\n");
- return -EWOULDBLOCK;
- }
if (!usb_int_enabled(usb)) {
dev_dbg_f(zd_usb_dev(usb),
"error: usb interrupt not enabled\n");
@@ -1882,11 +1877,6 @@ int zd_usb_iowrite16v_async(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
count, USB_MAX_IOWRITE16_COUNT);
return -EINVAL;
}
- if (in_atomic()) {
- dev_dbg_f(zd_usb_dev(usb),
- "error: io in atomic context not supported\n");
- return -EWOULDBLOCK;
- }
udev = zd_usb_to_usbdev(usb);
@@ -1966,11 +1956,6 @@ int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits)
int i, req_len, actual_req_len;
u16 bit_value_template;
- if (in_atomic()) {
- dev_dbg_f(zd_usb_dev(usb),
- "error: io in atomic context not supported\n");
- return -EWOULDBLOCK;
- }
if (bits < USB_MIN_RFWRITE_BIT_COUNT) {
dev_dbg_f(zd_usb_dev(usb),
"error: bits %d are smaller than"
diff --git a/include/linux/mhi.h b/include/linux/mhi.h
index b9bb7dff32e2..cb7cd54c5e63 100644
--- a/include/linux/mhi.h
+++ b/include/linux/mhi.h
@@ -214,7 +214,6 @@ enum mhi_db_brst_mode {
* @offload_channel: The client manages the channel completely
* @doorbell_mode_switch: Channel switches to doorbell mode on M0 transition
* @auto_queue: Framework will automatically queue buffers for DL traffic
- * @auto_start: Automatically start (open) this channel
* @wake-capable: Channel capable of waking up the system
*/
struct mhi_channel_config {
@@ -232,7 +231,6 @@ struct mhi_channel_config {
bool offload_channel;
bool doorbell_mode_switch;
bool auto_queue;
- bool auto_start;
bool wake_capable;
};
diff --git a/net/qrtr/mhi.c b/net/qrtr/mhi.c
index ff0c41467fc1..2bf2b1943e61 100644
--- a/net/qrtr/mhi.c
+++ b/net/qrtr/mhi.c
@@ -76,6 +76,11 @@ static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev,
struct qrtr_mhi_dev *qdev;
int rc;
+ /* start channels */
+ rc = mhi_prepare_for_transfer(mhi_dev);
+ if (rc)
+ return rc;
+
qdev = devm_kzalloc(&mhi_dev->dev, sizeof(*qdev), GFP_KERNEL);
if (!qdev)
return -ENOMEM;
@@ -99,6 +104,7 @@ static void qcom_mhi_qrtr_remove(struct mhi_device *mhi_dev)
struct qrtr_mhi_dev *qdev = dev_get_drvdata(&mhi_dev->dev);
qrtr_endpoint_unregister(&qdev->ep);
+ mhi_unprepare_from_transfer(mhi_dev);
dev_set_drvdata(&mhi_dev->dev, NULL);
}