1
0
Fork 0

wireless-drivers-next patches for v5.10

Second set of patches for v5.10. Biggest change here is wcn3680
 support to wcn36xx driver, otherwise smaller features. And naturally
 the usual fixes and cleanups.
 
 Major changes:
 
 brcmfmac
 
 * support 4-way handshake offloading for WPA/WPA2-PSK in AP mode
 
 * support SAE authentication offload in AP mode
 
 mt76
 
 * mt7663 runtime power management improvements
 
 * mt7915 A-MSDU offload
 
 wcn36xx
 
 * add support wcn3680 Wi-Fi 5 devices
 
 ath11k
 
 * spectral scan support for ipq6018
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJfbhn8AAoJEG4XJFUm622bFnMH/jI1Q+DXi2/sn3L01onNABqE
 0M/HiZj/Gli2kYrIFiXKzCCVZBA/5CIZefh8Q+brsH4ZonJriTJ/VnJcGdDU68FK
 ZqWSAkJ6+pJSaq7O/LofoTw+G0N64GPVN88ZqDMSoCyS8LDsE2QSjX6WEdeX7i9t
 BWLcdXJ/brPzxtoH43c+w05syM+NCzPACUEKADa0KU5pg+MKHqtL/2FN8CecyU8k
 ylzwH7w99mLBU3dDi8Q+EcUzOa0E+B7h56+BCcy/opCPZl0u2KGKcX/bRib1BwIB
 wAChlEppwK/x8G8ViqxkrDVn1IiY2mnlFvdExuOlWqmVqwcccY8lEe19iAnzrV4=
 =Xrmx
 -----END PGP SIGNATURE-----

Merge tag 'wireless-drivers-next-2020-09-25' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next

Kalle Valo says:

====================
wireless-drivers-next patches for v5.10

Second set of patches for v5.10. Biggest change here is wcn3680
support to wcn36xx driver, otherwise smaller features. And naturally
the usual fixes and cleanups.

Major changes:

brcmfmac

* support 4-way handshake offloading for WPA/WPA2-PSK in AP mode

* support SAE authentication offload in AP mode

mt76

* mt7663 runtime power management improvements

* mt7915 A-MSDU offload

wcn36xx

* add support wcn3680 Wi-Fi 5 devices

ath11k

* spectral scan support for ipq6018
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
zero-sugar-mainline-defconfig
David S. Miller 2020-09-25 13:16:29 -07:00
commit 7806f6561c
140 changed files with 4208 additions and 3460 deletions

View File

@ -1022,7 +1022,7 @@ static int ath10k_core_check_smbios(struct ath10k *ar)
return 0;
}
static int ath10k_core_check_dt(struct ath10k *ar)
int ath10k_core_check_dt(struct ath10k *ar)
{
struct device_node *node;
const char *variant = NULL;
@ -1043,6 +1043,7 @@ static int ath10k_core_check_dt(struct ath10k *ar)
return 0;
}
EXPORT_SYMBOL(ath10k_core_check_dt);
static int ath10k_download_fw(struct ath10k *ar)
{
@ -1437,10 +1438,17 @@ static int ath10k_core_create_board_name(struct ath10k *ar, char *name,
}
if (ar->id.qmi_ids_valid) {
scnprintf(name, name_len,
"bus=%s,qmi-board-id=%x",
ath10k_bus_str(ar->hif.bus),
ar->id.qmi_board_id);
if (with_variant && ar->id.bdf_ext[0] != '\0')
scnprintf(name, name_len,
"bus=%s,qmi-board-id=%x,qmi-chip-id=%x%s",
ath10k_bus_str(ar->hif.bus),
ar->id.qmi_board_id, ar->id.qmi_chip_id,
variant);
else
scnprintf(name, name_len,
"bus=%s,qmi-board-id=%x",
ath10k_bus_str(ar->hif.bus),
ar->id.qmi_board_id);
goto out;
}

View File

@ -1076,6 +1076,7 @@ struct ath10k {
bool bmi_ids_valid;
bool qmi_ids_valid;
u32 qmi_board_id;
u32 qmi_chip_id;
u8 bmi_board_id;
u8 bmi_eboard_id;
u8 bmi_chip_id;
@ -1315,6 +1316,7 @@ int ath10k_core_register(struct ath10k *ar,
const struct ath10k_bus_params *bus_params);
void ath10k_core_unregister(struct ath10k *ar);
int ath10k_core_fetch_board_file(struct ath10k *ar, int bd_ie_type);
int ath10k_core_check_dt(struct ath10k *ar);
void ath10k_core_free_board_files(struct ath10k *ar);
#endif /* _CORE_H_ */

View File

@ -576,6 +576,8 @@ static int ath10k_qmi_cap_send_sync_msg(struct ath10k_qmi *qmi)
if (resp->chip_info_valid) {
qmi->chip_info.chip_id = resp->chip_info.chip_id;
qmi->chip_info.chip_family = resp->chip_info.chip_family;
} else {
qmi->chip_info.chip_id = 0xFF;
}
if (resp->board_info_valid)
@ -817,12 +819,18 @@ err_setup_msa:
static int ath10k_qmi_fetch_board_file(struct ath10k_qmi *qmi)
{
struct ath10k *ar = qmi->ar;
int ret;
ar->hif.bus = ATH10K_BUS_SNOC;
ar->id.qmi_ids_valid = true;
ar->id.qmi_board_id = qmi->board_info.board_id;
ar->id.qmi_chip_id = qmi->chip_info.chip_id;
ar->hw_params.fw.dir = WCN3990_HW_1_0_FW_DIR;
ret = ath10k_core_check_dt(ar);
if (ret)
ath10k_dbg(ar, ATH10K_DBG_QMI, "DT bdf variant name not set.\n");
return ath10k_core_fetch_board_file(qmi->ar, ATH10K_BD_IE_BOARD);
}

View File

@ -18,7 +18,7 @@ ath11k-y += core.o \
dbring.o \
hw.o
ath11k-$(CONFIG_ATH11K_DEBUGFS) += debug_htt_stats.o debugfs_sta.o
ath11k-$(CONFIG_ATH11K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o
ath11k-$(CONFIG_NL80211_TESTMODE) += testmode.o
ath11k-$(CONFIG_ATH11K_TRACING) += trace.o
ath11k-$(CONFIG_THERMAL) += thermal.o

View File

@ -323,9 +323,10 @@ static void ath11k_ahb_stop(struct ath11k_base *ab)
static int ath11k_ahb_power_up(struct ath11k_base *ab)
{
struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
int ret;
ret = rproc_boot(ab->tgt_rproc);
ret = rproc_boot(ab_ahb->tgt_rproc);
if (ret)
ath11k_err(ab, "failed to boot the remote processor Q6\n");
@ -334,7 +335,9 @@ static int ath11k_ahb_power_up(struct ath11k_base *ab)
static void ath11k_ahb_power_down(struct ath11k_base *ab)
{
rproc_shutdown(ab->tgt_rproc);
struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
rproc_shutdown(ab_ahb->tgt_rproc);
}
static void ath11k_ahb_init_qmi_ce_config(struct ath11k_base *ab)
@ -600,6 +603,28 @@ static const struct ath11k_hif_ops ath11k_ahb_hif_ops = {
.power_up = ath11k_ahb_power_up,
};
static int ath11k_core_get_rproc(struct ath11k_base *ab)
{
struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
struct device *dev = ab->dev;
struct rproc *prproc;
phandle rproc_phandle;
if (of_property_read_u32(dev->of_node, "qcom,rproc", &rproc_phandle)) {
ath11k_err(ab, "failed to get q6_rproc handle\n");
return -ENOENT;
}
prproc = rproc_get_by_phandle(rproc_phandle);
if (!prproc) {
ath11k_err(ab, "failed to get rproc\n");
return -EINVAL;
}
ab_ahb->tgt_rproc = prproc;
return 0;
}
static int ath11k_ahb_probe(struct platform_device *pdev)
{
struct ath11k_base *ab;
@ -626,7 +651,9 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
return ret;
}
ab = ath11k_core_alloc(&pdev->dev, 0, ATH11K_BUS_AHB, &ath11k_ahb_bus_params);
ab = ath11k_core_alloc(&pdev->dev, sizeof(struct ath11k_ahb),
ATH11K_BUS_AHB,
&ath11k_ahb_bus_params);
if (!ab) {
dev_err(&pdev->dev, "failed to allocate ath11k base\n");
return -ENOMEM;
@ -655,6 +682,12 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
ath11k_ahb_init_qmi_ce_config(ab);
ret = ath11k_core_get_rproc(ab);
if (ret) {
ath11k_err(ab, "failed to get rproc: %d\n", ret);
goto err_ce_free;
}
ret = ath11k_core_init(ab);
if (ret) {
ath11k_err(ab, "failed to init core: %d\n", ret);
@ -685,12 +718,16 @@ err_core_free:
static int ath11k_ahb_remove(struct platform_device *pdev)
{
struct ath11k_base *ab = platform_get_drvdata(pdev);
unsigned long left;
reinit_completion(&ab->driver_recovery);
if (test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags))
wait_for_completion_timeout(&ab->driver_recovery,
ATH11K_AHB_RECOVERY_TIMEOUT);
if (test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags)) {
left = wait_for_completion_timeout(&ab->driver_recovery,
ATH11K_AHB_RECOVERY_TIMEOUT);
if (!left)
ath11k_warn(ab, "failed to receive recovery response completion\n");
}
set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags);
cancel_work_sync(&ab->restart_work);

View File

@ -10,4 +10,12 @@
#define ATH11K_AHB_RECOVERY_TIMEOUT (3 * HZ)
struct ath11k_base;
struct ath11k_ahb {
struct rproc *tgt_rproc;
};
static inline struct ath11k_ahb *ath11k_ahb_priv(struct ath11k_base *ab)
{
return (struct ath11k_ahb *)ab->drv_priv;
}
#endif

View File

@ -57,6 +57,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.vdev_start_delay = false,
.htt_peer_map_v2 = true,
.tcl_0_only = false,
.spectral_fft_sz = 2,
},
{
.hw_rev = ATH11K_HW_IPQ6018_HW10,
@ -86,6 +87,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.vdev_start_delay = false,
.htt_peer_map_v2 = true,
.tcl_0_only = false,
.spectral_fft_sz = 4,
},
{
.name = "qca6390 hw2.0",
@ -115,6 +117,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.vdev_start_delay = true,
.htt_peer_map_v2 = false,
.tcl_0_only = true,
.spectral_fft_sz = 0,
},
};
@ -412,7 +415,7 @@ static int ath11k_core_soc_create(struct ath11k_base *ab)
return ret;
}
ret = ath11k_debug_soc_create(ab);
ret = ath11k_debugfs_soc_create(ab);
if (ret) {
ath11k_err(ab, "failed to create ath11k debugfs\n");
goto err_qmi_deinit;
@ -427,7 +430,7 @@ static int ath11k_core_soc_create(struct ath11k_base *ab)
return 0;
err_debugfs_reg:
ath11k_debug_soc_destroy(ab);
ath11k_debugfs_soc_destroy(ab);
err_qmi_deinit:
ath11k_qmi_deinit_service(ab);
return ret;
@ -435,7 +438,7 @@ err_qmi_deinit:
static void ath11k_core_soc_destroy(struct ath11k_base *ab)
{
ath11k_debug_soc_destroy(ab);
ath11k_debugfs_soc_destroy(ab);
ath11k_dp_free(ab);
ath11k_reg_free(ab);
ath11k_qmi_deinit_service(ab);
@ -445,7 +448,7 @@ static int ath11k_core_pdev_create(struct ath11k_base *ab)
{
int ret;
ret = ath11k_debug_pdev_create(ab);
ret = ath11k_debugfs_pdev_create(ab);
if (ret) {
ath11k_err(ab, "failed to create core pdev debugfs: %d\n", ret);
return ret;
@ -485,7 +488,7 @@ err_dp_pdev_free:
err_mac_unregister:
ath11k_mac_unregister(ab);
err_pdev_debug:
ath11k_debug_pdev_destroy(ab);
ath11k_debugfs_pdev_destroy(ab);
return ret;
}
@ -497,7 +500,7 @@ static void ath11k_core_pdev_destroy(struct ath11k_base *ab)
ath11k_mac_unregister(ab);
ath11k_hif_irq_disable(ab);
ath11k_dp_pdev_free(ab);
ath11k_debug_pdev_destroy(ab);
ath11k_debugfs_pdev_destroy(ab);
}
static int ath11k_core_start(struct ath11k_base *ab,
@ -842,43 +845,10 @@ int ath11k_core_pre_init(struct ath11k_base *ab)
}
EXPORT_SYMBOL(ath11k_core_pre_init);
static int ath11k_core_get_rproc(struct ath11k_base *ab)
{
struct device *dev = ab->dev;
struct rproc *prproc;
phandle rproc_phandle;
if (!IS_ENABLED(CONFIG_REMOTEPROC))
return 0;
if (ab->bus_params.mhi_support)
return 0;
if (of_property_read_u32(dev->of_node, "qcom,rproc", &rproc_phandle)) {
ath11k_err(ab, "failed to get q6_rproc handle\n");
return -ENOENT;
}
prproc = rproc_get_by_phandle(rproc_phandle);
if (!prproc) {
ath11k_err(ab, "failed to get rproc\n");
return -EINVAL;
}
ab->tgt_rproc = prproc;
return 0;
}
int ath11k_core_init(struct ath11k_base *ab)
{
int ret;
ret = ath11k_core_get_rproc(ab);
if (ret) {
ath11k_err(ab, "failed to get rproc: %d\n", ret);
return ret;
}
ret = ath11k_core_soc_create(ab);
if (ret) {
ath11k_err(ab, "failed to create soc core: %d\n", ret);

View File

@ -648,7 +648,6 @@ struct ath11k_base {
struct ath11k_qmi qmi;
struct ath11k_wmi_base wmi_ab;
struct completion fw_ready;
struct rproc *tgt_rproc;
int num_radios;
/* HW channel counters frequency value in hertz common to all MACs */
u32 cc_freq_hz;

File diff suppressed because it is too large Load Diff

View File

@ -6,11 +6,8 @@
#ifndef _ATH11K_DEBUG_H_
#define _ATH11K_DEBUG_H_
#include "hal_tx.h"
#include "trace.h"
#define ATH11K_TX_POWER_MAX_VAL 70
#define ATH11K_TX_POWER_MIN_VAL 0
#include "debugfs.h"
enum ath11k_debug_mask {
ATH11K_DBG_AHB = 0x00000001,
@ -31,98 +28,6 @@ enum ath11k_debug_mask {
ATH11K_DBG_ANY = 0xffffffff,
};
/* htt_dbg_ext_stats_type */
enum ath11k_dbg_htt_ext_stats_type {
ATH11K_DBG_HTT_EXT_STATS_RESET = 0,
ATH11K_DBG_HTT_EXT_STATS_PDEV_TX = 1,
ATH11K_DBG_HTT_EXT_STATS_PDEV_RX = 2,
ATH11K_DBG_HTT_EXT_STATS_PDEV_TX_HWQ = 3,
ATH11K_DBG_HTT_EXT_STATS_PDEV_TX_SCHED = 4,
ATH11K_DBG_HTT_EXT_STATS_PDEV_ERROR = 5,
ATH11K_DBG_HTT_EXT_STATS_PDEV_TQM = 6,
ATH11K_DBG_HTT_EXT_STATS_TQM_CMDQ = 7,
ATH11K_DBG_HTT_EXT_STATS_TX_DE_INFO = 8,
ATH11K_DBG_HTT_EXT_STATS_PDEV_TX_RATE = 9,
ATH11K_DBG_HTT_EXT_STATS_PDEV_RX_RATE = 10,
ATH11K_DBG_HTT_EXT_STATS_PEER_INFO = 11,
ATH11K_DBG_HTT_EXT_STATS_TX_SELFGEN_INFO = 12,
ATH11K_DBG_HTT_EXT_STATS_TX_MU_HWQ = 13,
ATH11K_DBG_HTT_EXT_STATS_RING_IF_INFO = 14,
ATH11K_DBG_HTT_EXT_STATS_SRNG_INFO = 15,
ATH11K_DBG_HTT_EXT_STATS_SFM_INFO = 16,
ATH11K_DBG_HTT_EXT_STATS_PDEV_TX_MU = 17,
ATH11K_DBG_HTT_EXT_STATS_ACTIVE_PEERS_LIST = 18,
ATH11K_DBG_HTT_EXT_STATS_PDEV_CCA_STATS = 19,
ATH11K_DBG_HTT_EXT_STATS_TWT_SESSIONS = 20,
ATH11K_DBG_HTT_EXT_STATS_REO_RESOURCE_STATS = 21,
ATH11K_DBG_HTT_EXT_STATS_TX_SOUNDING_INFO = 22,
ATH11K_DBG_HTT_EXT_STATS_PDEV_OBSS_PD_STATS = 23,
ATH11K_DBG_HTT_EXT_STATS_RING_BACKPRESSURE_STATS = 24,
/* keep this last */
ATH11K_DBG_HTT_NUM_EXT_STATS,
};
struct debug_htt_stats_req {
bool done;
u8 pdev_id;
u8 type;
u8 peer_addr[ETH_ALEN];
struct completion cmpln;
u32 buf_len;
u8 buf[];
};
struct ath_pktlog_hdr {
u16 flags;
u16 missed_cnt;
u16 log_type;
u16 size;
u32 timestamp;
u32 type_specific_data;
u8 payload[];
};
#define ATH11K_HTT_PEER_STATS_RESET BIT(16)
#define ATH11K_HTT_STATS_BUF_SIZE (1024 * 512)
#define ATH11K_FW_STATS_BUF_SIZE (1024 * 1024)
enum ath11k_pktlog_filter {
ATH11K_PKTLOG_RX = 0x000000001,
ATH11K_PKTLOG_TX = 0x000000002,
ATH11K_PKTLOG_RCFIND = 0x000000004,
ATH11K_PKTLOG_RCUPDATE = 0x000000008,
ATH11K_PKTLOG_EVENT_SMART_ANT = 0x000000020,
ATH11K_PKTLOG_EVENT_SW = 0x000000040,
ATH11K_PKTLOG_ANY = 0x00000006f,
};
enum ath11k_pktlog_mode {
ATH11K_PKTLOG_MODE_LITE = 1,
ATH11K_PKTLOG_MODE_FULL = 2,
};
enum ath11k_pktlog_enum {
ATH11K_PKTLOG_TYPE_TX_CTRL = 1,
ATH11K_PKTLOG_TYPE_TX_STAT = 2,
ATH11K_PKTLOG_TYPE_TX_MSDU_ID = 3,
ATH11K_PKTLOG_TYPE_RX_STAT = 5,
ATH11K_PKTLOG_TYPE_RC_FIND = 6,
ATH11K_PKTLOG_TYPE_RC_UPDATE = 7,
ATH11K_PKTLOG_TYPE_TX_VIRT_ADDR = 8,
ATH11K_PKTLOG_TYPE_RX_CBF = 10,
ATH11K_PKTLOG_TYPE_RX_STATBUF = 22,
ATH11K_PKTLOG_TYPE_PPDU_STATS = 23,
ATH11K_PKTLOG_TYPE_LITE_RX = 24,
};
enum ath11k_dbg_aggr_mode {
ATH11K_DBG_AGGR_MODE_AUTO,
ATH11K_DBG_AGGR_MODE_MANUAL,
ATH11K_DBG_AGGR_MODE_MAX,
};
__printf(2, 3) void ath11k_info(struct ath11k_base *ab, const char *fmt, ...);
__printf(2, 3) void ath11k_err(struct ath11k_base *ab, const char *fmt, ...);
__printf(2, 3) void ath11k_warn(struct ath11k_base *ab, const char *fmt, ...);
@ -153,153 +58,6 @@ static inline void ath11k_dbg_dump(struct ath11k_base *ab,
}
#endif /* CONFIG_ATH11K_DEBUG */
#ifdef CONFIG_ATH11K_DEBUGFS
int ath11k_debug_soc_create(struct ath11k_base *ab);
void ath11k_debug_soc_destroy(struct ath11k_base *ab);
int ath11k_debug_pdev_create(struct ath11k_base *ab);
void ath11k_debug_pdev_destroy(struct ath11k_base *ab);
int ath11k_debug_register(struct ath11k *ar);
void ath11k_debug_unregister(struct ath11k *ar);
void ath11k_dbg_htt_ext_stats_handler(struct ath11k_base *ab,
struct sk_buff *skb);
void ath11k_debug_fw_stats_process(struct ath11k_base *ab, struct sk_buff *skb);
void ath11k_debug_fw_stats_init(struct ath11k *ar);
int ath11k_dbg_htt_stats_req(struct ath11k *ar);
static inline bool ath11k_debug_is_pktlog_lite_mode_enabled(struct ath11k *ar)
{
return (ar->debug.pktlog_mode == ATH11K_PKTLOG_MODE_LITE);
}
static inline bool ath11k_debug_is_pktlog_rx_stats_enabled(struct ath11k *ar)
{
return (!ar->debug.pktlog_peer_valid && ar->debug.pktlog_mode);
}
static inline bool ath11k_debug_is_pktlog_peer_valid(struct ath11k *ar, u8 *addr)
{
return (ar->debug.pktlog_peer_valid && ar->debug.pktlog_mode &&
ether_addr_equal(addr, ar->debug.pktlog_peer_addr));
}
static inline int ath11k_debug_is_extd_tx_stats_enabled(struct ath11k *ar)
{
return ar->debug.extd_tx_stats;
}
static inline int ath11k_debug_is_extd_rx_stats_enabled(struct ath11k *ar)
{
return ar->debug.extd_rx_stats;
}
static inline int ath11k_debug_rx_filter(struct ath11k *ar)
{
return ar->debug.rx_filter;
}
void ath11k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct dentry *dir);
void
ath11k_accumulate_per_peer_tx_stats(struct ath11k_sta *arsta,
struct ath11k_per_peer_tx_stats *peer_stats,
u8 legacy_rate_idx);
void ath11k_update_per_peer_stats_from_txcompl(struct ath11k *ar,
struct sk_buff *msdu,
struct hal_tx_status *ts);
#else
static inline int ath11k_debug_soc_create(struct ath11k_base *ab)
{
return 0;
}
static inline void ath11k_debug_soc_destroy(struct ath11k_base *ab)
{
}
static inline int ath11k_debug_pdev_create(struct ath11k_base *ab)
{
return 0;
}
static inline void ath11k_debug_pdev_destroy(struct ath11k_base *ab)
{
}
static inline int ath11k_debug_register(struct ath11k *ar)
{
return 0;
}
static inline void ath11k_debug_unregister(struct ath11k *ar)
{
}
static inline void ath11k_dbg_htt_ext_stats_handler(struct ath11k_base *ab,
struct sk_buff *skb)
{
}
static inline void ath11k_debug_fw_stats_process(struct ath11k_base *ab,
struct sk_buff *skb)
{
}
static inline void ath11k_debug_fw_stats_init(struct ath11k *ar)
{
}
static inline int ath11k_debug_is_extd_tx_stats_enabled(struct ath11k *ar)
{
return 0;
}
static inline int ath11k_debug_is_extd_rx_stats_enabled(struct ath11k *ar)
{
return 0;
}
static inline int ath11k_dbg_htt_stats_req(struct ath11k *ar)
{
return 0;
}
static inline bool ath11k_debug_is_pktlog_lite_mode_enabled(struct ath11k *ar)
{
return false;
}
static inline bool ath11k_debug_is_pktlog_rx_stats_enabled(struct ath11k *ar)
{
return false;
}
static inline bool ath11k_debug_is_pktlog_peer_valid(struct ath11k *ar, u8 *addr)
{
return false;
}
static inline int ath11k_debug_rx_filter(struct ath11k *ar)
{
return 0;
}
static inline void
ath11k_accumulate_per_peer_tx_stats(struct ath11k_sta *arsta,
struct ath11k_per_peer_tx_stats *peer_stats,
u8 legacy_rate_idx)
{
}
static inline void
ath11k_update_per_peer_stats_from_txcompl(struct ath11k *ar,
struct sk_buff *msdu,
struct hal_tx_status *ts)
{
}
#endif /* CONFIG_MAC80211_DEBUGFS*/
#define ath11k_dbg(ar, dbg_mask, fmt, ...) \
do { \
if (ath11k_debug_mask & dbg_mask) \

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,217 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
*/
#ifndef _ATH11K_DEBUGFS_H_
#define _ATH11K_DEBUGFS_H_
#include "hal_tx.h"
#define ATH11K_TX_POWER_MAX_VAL 70
#define ATH11K_TX_POWER_MIN_VAL 0
/* htt_dbg_ext_stats_type */
enum ath11k_dbg_htt_ext_stats_type {
ATH11K_DBG_HTT_EXT_STATS_RESET = 0,
ATH11K_DBG_HTT_EXT_STATS_PDEV_TX = 1,
ATH11K_DBG_HTT_EXT_STATS_PDEV_RX = 2,
ATH11K_DBG_HTT_EXT_STATS_PDEV_TX_HWQ = 3,
ATH11K_DBG_HTT_EXT_STATS_PDEV_TX_SCHED = 4,
ATH11K_DBG_HTT_EXT_STATS_PDEV_ERROR = 5,
ATH11K_DBG_HTT_EXT_STATS_PDEV_TQM = 6,
ATH11K_DBG_HTT_EXT_STATS_TQM_CMDQ = 7,
ATH11K_DBG_HTT_EXT_STATS_TX_DE_INFO = 8,
ATH11K_DBG_HTT_EXT_STATS_PDEV_TX_RATE = 9,
ATH11K_DBG_HTT_EXT_STATS_PDEV_RX_RATE = 10,
ATH11K_DBG_HTT_EXT_STATS_PEER_INFO = 11,
ATH11K_DBG_HTT_EXT_STATS_TX_SELFGEN_INFO = 12,
ATH11K_DBG_HTT_EXT_STATS_TX_MU_HWQ = 13,
ATH11K_DBG_HTT_EXT_STATS_RING_IF_INFO = 14,
ATH11K_DBG_HTT_EXT_STATS_SRNG_INFO = 15,
ATH11K_DBG_HTT_EXT_STATS_SFM_INFO = 16,
ATH11K_DBG_HTT_EXT_STATS_PDEV_TX_MU = 17,
ATH11K_DBG_HTT_EXT_STATS_ACTIVE_PEERS_LIST = 18,
ATH11K_DBG_HTT_EXT_STATS_PDEV_CCA_STATS = 19,
ATH11K_DBG_HTT_EXT_STATS_TWT_SESSIONS = 20,
ATH11K_DBG_HTT_EXT_STATS_REO_RESOURCE_STATS = 21,
ATH11K_DBG_HTT_EXT_STATS_TX_SOUNDING_INFO = 22,
ATH11K_DBG_HTT_EXT_STATS_PDEV_OBSS_PD_STATS = 23,
ATH11K_DBG_HTT_EXT_STATS_RING_BACKPRESSURE_STATS = 24,
/* keep this last */
ATH11K_DBG_HTT_NUM_EXT_STATS,
};
struct debug_htt_stats_req {
bool done;
u8 pdev_id;
u8 type;
u8 peer_addr[ETH_ALEN];
struct completion cmpln;
u32 buf_len;
u8 buf[];
};
struct ath_pktlog_hdr {
u16 flags;
u16 missed_cnt;
u16 log_type;
u16 size;
u32 timestamp;
u32 type_specific_data;
u8 payload[];
};
#define ATH11K_HTT_PEER_STATS_RESET BIT(16)
#define ATH11K_HTT_STATS_BUF_SIZE (1024 * 512)
#define ATH11K_FW_STATS_BUF_SIZE (1024 * 1024)
enum ath11k_pktlog_filter {
ATH11K_PKTLOG_RX = 0x000000001,
ATH11K_PKTLOG_TX = 0x000000002,
ATH11K_PKTLOG_RCFIND = 0x000000004,
ATH11K_PKTLOG_RCUPDATE = 0x000000008,
ATH11K_PKTLOG_EVENT_SMART_ANT = 0x000000020,
ATH11K_PKTLOG_EVENT_SW = 0x000000040,
ATH11K_PKTLOG_ANY = 0x00000006f,
};
enum ath11k_pktlog_mode {
ATH11K_PKTLOG_MODE_LITE = 1,
ATH11K_PKTLOG_MODE_FULL = 2,
};
enum ath11k_pktlog_enum {
ATH11K_PKTLOG_TYPE_TX_CTRL = 1,
ATH11K_PKTLOG_TYPE_TX_STAT = 2,
ATH11K_PKTLOG_TYPE_TX_MSDU_ID = 3,
ATH11K_PKTLOG_TYPE_RX_STAT = 5,
ATH11K_PKTLOG_TYPE_RC_FIND = 6,
ATH11K_PKTLOG_TYPE_RC_UPDATE = 7,
ATH11K_PKTLOG_TYPE_TX_VIRT_ADDR = 8,
ATH11K_PKTLOG_TYPE_RX_CBF = 10,
ATH11K_PKTLOG_TYPE_RX_STATBUF = 22,
ATH11K_PKTLOG_TYPE_PPDU_STATS = 23,
ATH11K_PKTLOG_TYPE_LITE_RX = 24,
};
enum ath11k_dbg_aggr_mode {
ATH11K_DBG_AGGR_MODE_AUTO,
ATH11K_DBG_AGGR_MODE_MANUAL,
ATH11K_DBG_AGGR_MODE_MAX,
};
#ifdef CONFIG_ATH11K_DEBUGFS
int ath11k_debugfs_soc_create(struct ath11k_base *ab);
void ath11k_debugfs_soc_destroy(struct ath11k_base *ab);
int ath11k_debugfs_pdev_create(struct ath11k_base *ab);
void ath11k_debugfs_pdev_destroy(struct ath11k_base *ab);
int ath11k_debugfs_register(struct ath11k *ar);
void ath11k_debugfs_unregister(struct ath11k *ar);
void ath11k_debugfs_fw_stats_process(struct ath11k_base *ab, struct sk_buff *skb);
void ath11k_debugfs_fw_stats_init(struct ath11k *ar);
static inline bool ath11k_debugfs_is_pktlog_lite_mode_enabled(struct ath11k *ar)
{
return (ar->debug.pktlog_mode == ATH11K_PKTLOG_MODE_LITE);
}
static inline bool ath11k_debugfs_is_pktlog_rx_stats_enabled(struct ath11k *ar)
{
return (!ar->debug.pktlog_peer_valid && ar->debug.pktlog_mode);
}
static inline bool ath11k_debugfs_is_pktlog_peer_valid(struct ath11k *ar, u8 *addr)
{
return (ar->debug.pktlog_peer_valid && ar->debug.pktlog_mode &&
ether_addr_equal(addr, ar->debug.pktlog_peer_addr));
}
static inline int ath11k_debugfs_is_extd_tx_stats_enabled(struct ath11k *ar)
{
return ar->debug.extd_tx_stats;
}
static inline int ath11k_debugfs_is_extd_rx_stats_enabled(struct ath11k *ar)
{
return ar->debug.extd_rx_stats;
}
static inline int ath11k_debugfs_rx_filter(struct ath11k *ar)
{
return ar->debug.rx_filter;
}
#else
static inline int ath11k_debugfs_soc_create(struct ath11k_base *ab)
{
return 0;
}
static inline void ath11k_debugfs_soc_destroy(struct ath11k_base *ab)
{
}
static inline int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
{
return 0;
}
static inline void ath11k_debugfs_pdev_destroy(struct ath11k_base *ab)
{
}
static inline int ath11k_debugfs_register(struct ath11k *ar)
{
return 0;
}
static inline void ath11k_debugfs_unregister(struct ath11k *ar)
{
}
static inline void ath11k_debugfs_fw_stats_process(struct ath11k_base *ab,
struct sk_buff *skb)
{
}
static inline void ath11k_debugfs_fw_stats_init(struct ath11k *ar)
{
}
static inline int ath11k_debugfs_is_extd_tx_stats_enabled(struct ath11k *ar)
{
return 0;
}
static inline int ath11k_debugfs_is_extd_rx_stats_enabled(struct ath11k *ar)
{
return 0;
}
static inline bool ath11k_debugfs_is_pktlog_lite_mode_enabled(struct ath11k *ar)
{
return false;
}
static inline bool ath11k_debugfs_is_pktlog_rx_stats_enabled(struct ath11k *ar)
{
return false;
}
static inline bool ath11k_debugfs_is_pktlog_peer_valid(struct ath11k *ar, u8 *addr)
{
return false;
}
static inline int ath11k_debugfs_rx_filter(struct ath11k *ar)
{
return 0;
}
#endif /* CONFIG_MAC80211_DEBUGFS*/
#endif /* _ATH11K_DEBUGFS_H_ */

View File

@ -8,7 +8,7 @@
#include "dp_tx.h"
#include "dp_rx.h"
#include "debug.h"
#include "debug_htt_stats.h"
#include "debugfs_htt_stats.h"
#define HTT_DBG_OUT(buf, len, fmt, ...) \
scnprintf(buf, len, fmt "\n", ##__VA_ARGS__)
@ -4253,8 +4253,8 @@ static int ath11k_dbg_htt_ext_stats_parse(struct ath11k_base *ab,
return 0;
}
void ath11k_dbg_htt_ext_stats_handler(struct ath11k_base *ab,
struct sk_buff *skb)
void ath11k_debugfs_htt_ext_stats_handler(struct ath11k_base *ab,
struct sk_buff *skb)
{
struct ath11k_htt_extd_stats_msg *msg;
struct debug_htt_stats_req *stats_req;
@ -4402,7 +4402,7 @@ static int ath11k_prep_htt_stats_cfg_params(struct ath11k *ar, u8 type,
return 0;
}
int ath11k_dbg_htt_stats_req(struct ath11k *ar)
int ath11k_debugfs_htt_stats_req(struct ath11k *ar)
{
struct debug_htt_stats_req *stats_req = ar->debug.htt_stats.stats_req;
u8 type = stats_req->type;
@ -4476,7 +4476,7 @@ static int ath11k_open_htt_stats(struct inode *inode, struct file *file)
ar->debug.htt_stats.stats_req = stats_req;
stats_req->type = type;
ret = ath11k_dbg_htt_stats_req(ar);
ret = ath11k_debugfs_htt_stats_req(ar);
if (ret < 0)
goto out;
@ -4586,7 +4586,7 @@ static const struct file_operations fops_htt_stats_reset = {
.llseek = default_llseek,
};
void ath11k_debug_htt_stats_init(struct ath11k *ar)
void ath11k_debugfs_htt_stats_init(struct ath11k *ar)
{
spin_lock_init(&ar->debug.htt_stats.lock);
debugfs_create_file("htt_stats_type", 0600, ar->debug.debugfs_pdev,

View File

@ -1660,8 +1660,6 @@ struct htt_pdev_obss_pd_stats_tlv {
u32 num_obss_tx_ppdu_failure;
};
void ath11k_debug_htt_stats_init(struct ath11k *ar);
struct htt_ring_backpressure_stats_tlv {
u32 pdev_id;
u32 current_head_idx;
@ -1687,4 +1685,29 @@ struct htt_ring_backpressure_stats_tlv {
u32 backpressure_hist[5];
};
#ifdef CONFIG_ATH11K_DEBUGFS
void ath11k_debugfs_htt_stats_init(struct ath11k *ar);
void ath11k_debugfs_htt_ext_stats_handler(struct ath11k_base *ab,
struct sk_buff *skb);
int ath11k_debugfs_htt_stats_req(struct ath11k *ar);
#else /* CONFIG_ATH11K_DEBUGFS */
static inline void ath11k_debugfs_htt_stats_init(struct ath11k *ar)
{
}
static inline void ath11k_debugfs_htt_ext_stats_handler(struct ath11k_base *ab,
struct sk_buff *skb)
{
}
static inline int ath11k_debugfs_htt_stats_req(struct ath11k *ar)
{
return 0;
}
#endif /* CONFIG_ATH11K_DEBUGFS */
#endif

View File

@ -5,16 +5,16 @@
#include <linux/vmalloc.h>
#include "debugfs_sta.h"
#include "core.h"
#include "peer.h"
#include "debug.h"
#include "dp_tx.h"
#include "debug_htt_stats.h"
#include "debugfs_htt_stats.h"
void
ath11k_accumulate_per_peer_tx_stats(struct ath11k_sta *arsta,
struct ath11k_per_peer_tx_stats *peer_stats,
u8 legacy_rate_idx)
void ath11k_debugfs_sta_add_tx_stats(struct ath11k_sta *arsta,
struct ath11k_per_peer_tx_stats *peer_stats,
u8 legacy_rate_idx)
{
struct rate_info *txrate = &arsta->txrate;
struct ath11k_htt_tx_stats *tx_stats;
@ -125,9 +125,9 @@ ath11k_accumulate_per_peer_tx_stats(struct ath11k_sta *arsta,
tx_stats->tx_duration += peer_stats->duration;
}
void ath11k_update_per_peer_stats_from_txcompl(struct ath11k *ar,
struct sk_buff *msdu,
struct hal_tx_status *ts)
void ath11k_debugfs_sta_update_txcompl(struct ath11k *ar,
struct sk_buff *msdu,
struct hal_tx_status *ts)
{
struct ath11k_base *ab = ar->ab;
struct ath11k_per_peer_tx_stats *peer_stats = &ar->cached_stats;
@ -200,7 +200,8 @@ void ath11k_update_per_peer_stats_from_txcompl(struct ath11k *ar,
arsta->txrate.nss = arsta->last_txrate.nss;
arsta->txrate.bw = ath11k_mac_bw_to_mac80211_bw(bw);
ath11k_accumulate_per_peer_tx_stats(arsta, peer_stats, rate_idx);
ath11k_debugfs_sta_add_tx_stats(arsta, peer_stats, rate_idx);
err_out:
spin_unlock_bh(&ab->base_lock);
rcu_read_unlock();
@ -428,7 +429,7 @@ ath11k_dbg_sta_open_htt_peer_stats(struct inode *inode, struct file *file)
ar->debug.htt_stats.stats_req = stats_req;
stats_req->type = ATH11K_DBG_HTT_EXT_STATS_PEER_INFO;
memcpy(stats_req->peer_addr, sta->addr, ETH_ALEN);
ret = ath11k_dbg_htt_stats_req(ar);
ret = ath11k_debugfs_htt_stats_req(ar);
mutex_unlock(&ar->conf_mutex);
if (ret < 0)
goto out;
@ -820,15 +821,15 @@ static const struct file_operations fops_htt_peer_stats_reset = {
.llseek = default_llseek,
};
void ath11k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct dentry *dir)
void ath11k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct dentry *dir)
{
struct ath11k *ar = hw->priv;
if (ath11k_debug_is_extd_tx_stats_enabled(ar))
if (ath11k_debugfs_is_extd_tx_stats_enabled(ar))
debugfs_create_file("tx_stats", 0400, dir, sta,
&fops_tx_stats);
if (ath11k_debug_is_extd_rx_stats_enabled(ar))
if (ath11k_debugfs_is_extd_rx_stats_enabled(ar))
debugfs_create_file("rx_stats", 0400, dir, sta,
&fops_rx_stats);

View File

@ -0,0 +1,44 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
*/
#ifndef _ATH11K_DEBUGFS_STA_H_
#define _ATH11K_DEBUGFS_STA_H_
#include <net/mac80211.h>
#include "core.h"
#include "hal_tx.h"
#ifdef CONFIG_ATH11K_DEBUGFS
void ath11k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct dentry *dir);
void ath11k_debugfs_sta_add_tx_stats(struct ath11k_sta *arsta,
struct ath11k_per_peer_tx_stats *peer_stats,
u8 legacy_rate_idx);
void ath11k_debugfs_sta_update_txcompl(struct ath11k *ar,
struct sk_buff *msdu,
struct hal_tx_status *ts);
#else /* CONFIG_ATH11K_DEBUGFS */
#define ath11k_debugfs_sta_op_add NULL
static inline void
ath11k_debugfs_sta_add_tx_stats(struct ath11k_sta *arsta,
struct ath11k_per_peer_tx_stats *peer_stats,
u8 legacy_rate_idx)
{
}
static inline void ath11k_debugfs_sta_update_txcompl(struct ath11k *ar,
struct sk_buff *msdu,
struct hal_tx_status *ts)
{
}
#endif /* CONFIG_ATH11K_DEBUGFS */
#endif /* _ATH11K_DEBUGFS_STA_H_ */

View File

@ -832,7 +832,7 @@ void ath11k_dp_pdev_free(struct ath11k_base *ab)
for (i = 0; i < ab->num_radios; i++) {
ar = ab->pdevs[i].ar;
ath11k_dp_rx_pdev_free(ab, i);
ath11k_debug_unregister(ar);
ath11k_debugfs_unregister(ar);
ath11k_dp_rx_pdev_mon_detach(ar);
}
}

View File

@ -9,6 +9,8 @@
#include <crypto/hash.h>
#include "core.h"
#include "debug.h"
#include "debugfs_htt_stats.h"
#include "debugfs_sta.h"
#include "hal_desc.h"
#include "hw.h"
#include "dp_rx.h"
@ -1433,9 +1435,8 @@ ath11k_update_per_peer_tx_stats(struct ath11k *ar,
HTT_USR_CMPLTN_LONG_RETRY(usr_stats->cmpltn_cmn.flags) +
HTT_USR_CMPLTN_SHORT_RETRY(usr_stats->cmpltn_cmn.flags);
if (ath11k_debug_is_extd_tx_stats_enabled(ar))
ath11k_accumulate_per_peer_tx_stats(arsta,
peer_stats, rate_idx);
if (ath11k_debugfs_is_extd_tx_stats_enabled(ar))
ath11k_debugfs_sta_add_tx_stats(arsta, peer_stats, rate_idx);
}
spin_unlock_bh(&ab->base_lock);
@ -1511,7 +1512,7 @@ static int ath11k_htt_pull_ppdu_stats(struct ath11k_base *ab,
goto exit;
}
if (ath11k_debug_is_pktlog_lite_mode_enabled(ar))
if (ath11k_debugfs_is_pktlog_lite_mode_enabled(ar))
trace_ath11k_htt_ppdu_stats(ar, skb->data, len);
ppdu_info = ath11k_dp_htt_get_ppdu_desc(ar, ppdu_id);
@ -1658,7 +1659,7 @@ void ath11k_dp_htt_htc_t2h_msg_handler(struct ath11k_base *ab,
ath11k_htt_pull_ppdu_stats(ab, skb);
break;
case HTT_T2H_MSG_TYPE_EXT_STATS_CONF:
ath11k_dbg_htt_ext_stats_handler(ab, skb);
ath11k_debugfs_htt_ext_stats_handler(ab, skb);
break;
case HTT_T2H_MSG_TYPE_PKTLOG:
ath11k_htt_pktlog(ab, skb);
@ -2909,7 +2910,7 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
memset(&ppdu_info, 0, sizeof(ppdu_info));
ppdu_info.peer_id = HAL_INVALID_PEERID;
if (ath11k_debug_is_pktlog_rx_stats_enabled(ar))
if (ath11k_debugfs_is_pktlog_rx_stats_enabled(ar))
trace_ath11k_htt_rxdesc(ar, skb->data, DP_RX_BUFFER_SIZE);
hal_status = ath11k_hal_rx_parse_mon_status(ab, &ppdu_info, skb);
@ -2937,7 +2938,7 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
arsta = (struct ath11k_sta *)peer->sta->drv_priv;
ath11k_dp_rx_update_peer_stats(arsta, &ppdu_info);
if (ath11k_debug_is_pktlog_peer_valid(ar, peer->addr))
if (ath11k_debugfs_is_pktlog_peer_valid(ar, peer->addr))
trace_ath11k_htt_rxdesc(ar, skb->data, DP_RX_BUFFER_SIZE);
spin_unlock_bh(&ab->base_lock);

View File

@ -6,6 +6,7 @@
#include "core.h"
#include "dp_tx.h"
#include "debug.h"
#include "debugfs_sta.h"
#include "hw.h"
#include "peer.h"
@ -457,7 +458,7 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar,
(info->flags & IEEE80211_TX_CTL_NO_ACK))
info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
if (ath11k_debug_is_extd_tx_stats_enabled(ar)) {
if (ath11k_debugfs_is_extd_tx_stats_enabled(ar)) {
if (ts->flags & HAL_TX_STATUS_FLAGS_FIRST_MSDU) {
if (ar->last_ppdu_id == 0) {
ar->last_ppdu_id = ts->ppdu_id;
@ -465,12 +466,12 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar,
ar->cached_ppdu_id == ar->last_ppdu_id) {
ar->cached_ppdu_id = ar->last_ppdu_id;
ar->cached_stats.is_ampdu = true;
ath11k_update_per_peer_stats_from_txcompl(ar, msdu, ts);
ath11k_debugfs_sta_update_txcompl(ar, msdu, ts);
memset(&ar->cached_stats, 0,
sizeof(struct ath11k_per_peer_tx_stats));
} else {
ar->cached_stats.is_ampdu = false;
ath11k_update_per_peer_stats_from_txcompl(ar, msdu, ts);
ath11k_debugfs_sta_update_txcompl(ar, msdu, ts);
memset(&ar->cached_stats, 0,
sizeof(struct ath11k_per_peer_tx_stats));
}

View File

@ -50,15 +50,6 @@ static struct sk_buff *ath11k_htc_build_tx_ctrl_skb(void *ab)
return skb;
}
static inline void ath11k_htc_restore_tx_skb(struct ath11k_htc *htc,
struct sk_buff *skb)
{
struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB(skb);
dma_unmap_single(htc->ab->dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
skb_pull(skb, sizeof(struct ath11k_htc_hdr));
}
static void ath11k_htc_prepare_tx_skb(struct ath11k_htc_ep *ep,
struct sk_buff *skb)
{

View File

@ -74,7 +74,6 @@ static void ath11k_init_wmi_config_qca6390(struct ath11k_base *ab,
config->beacon_tx_offload_max_vdev = 0x2;
config->num_multicast_filter_entries = 0x20;
config->num_wow_filters = 0x16;
config->num_keep_alive_pattern = 0x1;
config->num_keep_alive_pattern = 0;
}
@ -104,7 +103,12 @@ static void ath11k_init_wmi_config_ipq8074(struct ath11k_base *ab,
config->rx_timeout_pri[1] = TARGET_RX_TIMEOUT_LO_PRI;
config->rx_timeout_pri[2] = TARGET_RX_TIMEOUT_LO_PRI;
config->rx_timeout_pri[3] = TARGET_RX_TIMEOUT_HI_PRI;
config->rx_decap_mode = TARGET_DECAP_MODE_NATIVE_WIFI;
if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags))
config->rx_decap_mode = TARGET_DECAP_MODE_RAW;
else
config->rx_decap_mode = TARGET_DECAP_MODE_NATIVE_WIFI;
config->scan_max_pending_req = TARGET_SCAN_MAX_PENDING_REQS;
config->bmiss_offload_max_vdev = TARGET_BMISS_OFFLOAD_MAX_VDEV;
config->roam_offload_max_vdev = TARGET_ROAM_OFFLOAD_MAX_VDEV;

View File

@ -155,6 +155,7 @@ struct ath11k_hw_params {
bool vdev_start_delay;
bool htt_peer_map_v2;
bool tcl_0_only;
u8 spectral_fft_sz;
};
struct ath11k_hw_ops {

View File

@ -14,6 +14,7 @@
#include "dp_rx.h"
#include "testmode.h"
#include "peer.h"
#include "debugfs_sta.h"
#define CHAN2G(_channel, _freq, _flags) { \
.band = NL80211_BAND_2GHZ, \
@ -2967,7 +2968,7 @@ static int ath11k_mac_station_add(struct ath11k *ar,
ath11k_dbg(ab, ATH11K_DBG_MAC, "Added peer: %pM for VDEV: %d\n",
sta->addr, arvif->vdev_id);
if (ath11k_debug_is_extd_tx_stats_enabled(ar)) {
if (ath11k_debugfs_is_extd_tx_stats_enabled(ar)) {
arsta->tx_stats = kzalloc(sizeof(*arsta->tx_stats), GFP_KERNEL);
if (!arsta->tx_stats) {
ret = -ENOMEM;
@ -4101,7 +4102,7 @@ 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_debug_rx_filter(ar);
tlv_filter.rx_filter = ath11k_debugfs_rx_filter(ar);
}
for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
@ -5873,7 +5874,7 @@ static const struct ieee80211_ops ath11k_ops = {
.sta_statistics = ath11k_mac_op_sta_statistics,
CFG80211_TESTMODE_CMD(ath11k_tm_cmd)
#ifdef CONFIG_ATH11K_DEBUGFS
.sta_add_debugfs = ath11k_sta_add_debugfs,
.sta_add_debugfs = ath11k_debugfs_sta_op_add,
#endif
};
@ -6233,7 +6234,7 @@ static int __ath11k_mac_register(struct ath11k *ar)
goto err_free;
}
ret = ath11k_debug_register(ar);
ret = ath11k_debugfs_register(ar);
if (ret) {
ath11k_err(ar->ab, "debugfs registration failed: %d\n", ret);
goto err_free;

View File

@ -17,8 +17,6 @@
#define ATH11K_SPECTRAL_ATH11K_MIN_IB_BINS 32
#define ATH11K_SPECTRAL_ATH11K_MAX_IB_BINS 256
#define ATH11K_SPECTRAL_SAMPLE_FFT_BIN_MASK 0xFF
#define ATH11K_SPECTRAL_SCAN_COUNT_MAX 4095
/* Max channel computed by sum of 2g and 5g band channels */
@ -557,16 +555,16 @@ static u8 ath11k_spectral_get_max_exp(s8 max_index, u8 max_magnitude,
return max_exp;
}
static void ath11k_spectral_parse_16bit_fft(u8 *outbins, u8 *inbins, int num_bins)
static void ath11k_spectral_parse_fft(u8 *outbins, u8 *inbins, int num_bins, u8 fft_sz)
{
int i;
__le16 *data = (__le16 *)inbins;
int i, j;
i = 0;
j = 0;
while (i < num_bins) {
outbins[i] = (__le16_to_cpu(data[i])) &
ATH11K_SPECTRAL_SAMPLE_FFT_BIN_MASK;
outbins[i] = inbins[j];
i++;
j += fft_sz;
}
}
@ -588,6 +586,12 @@ int ath11k_spectral_process_fft(struct ath11k *ar,
lockdep_assert_held(&ar->spectral.lock);
if (!ab->hw_params.spectral_fft_sz) {
ath11k_warn(ab, "invalid bin size type for hw rev %d\n",
ab->hw_rev);
return -EINVAL;
}
tlv = (struct spectral_tlv *)data;
tlv_len = FIELD_GET(SPECTRAL_TLV_HDR_LEN, __le32_to_cpu(tlv->header));
/* convert Dword into bytes */
@ -649,9 +653,8 @@ int ath11k_spectral_process_fft(struct ath11k *ar,
freq = summary->meta.freq2;
fft_sample->freq2 = __cpu_to_be16(freq);
ath11k_spectral_parse_16bit_fft(fft_sample->data,
fft_report->bins,
num_bins);
ath11k_spectral_parse_fft(fft_sample->data, fft_report->bins, num_bins,
ab->hw_params.spectral_fft_sz);
fft_sample->max_exp = ath11k_spectral_get_max_exp(fft_sample->max_index,
search.peak_mag,
@ -959,6 +962,9 @@ int ath11k_spectral_init(struct ath11k_base *ab)
ab->wmi_ab.svc_map))
return 0;
if (!ab->hw_params.spectral_fft_sz)
return 0;
for (i = 0; i < ab->num_radios; i++) {
ar = ab->pdevs[i].ar;
sp = &ar->spectral;

View File

@ -3342,55 +3342,6 @@ int ath11k_wmi_cmd_init(struct ath11k_base *ab)
memset(&init_param, 0, sizeof(init_param));
memset(&config, 0, sizeof(config));
config.num_vdevs = ab->num_radios * TARGET_NUM_VDEVS;
if (ab->num_radios == 2) {
config.num_peers = TARGET_NUM_PEERS(DBS);
config.num_tids = TARGET_NUM_TIDS(DBS);
} else if (ab->num_radios == 3) {
config.num_peers = TARGET_NUM_PEERS(DBS_SBS);
config.num_tids = TARGET_NUM_TIDS(DBS_SBS);
} else {
/* Control should not reach here */
config.num_peers = TARGET_NUM_PEERS(SINGLE);
config.num_tids = TARGET_NUM_TIDS(SINGLE);
}
config.num_offload_peers = TARGET_NUM_OFFLD_PEERS;
config.num_offload_reorder_buffs = TARGET_NUM_OFFLD_REORDER_BUFFS;
config.num_peer_keys = TARGET_NUM_PEER_KEYS;
config.ast_skid_limit = TARGET_AST_SKID_LIMIT;
config.tx_chain_mask = (1 << ab->target_caps.num_rf_chains) - 1;
config.rx_chain_mask = (1 << ab->target_caps.num_rf_chains) - 1;
config.rx_timeout_pri[0] = TARGET_RX_TIMEOUT_LO_PRI;
config.rx_timeout_pri[1] = TARGET_RX_TIMEOUT_LO_PRI;
config.rx_timeout_pri[2] = TARGET_RX_TIMEOUT_LO_PRI;
config.rx_timeout_pri[3] = TARGET_RX_TIMEOUT_HI_PRI;
config.rx_decap_mode = TARGET_DECAP_MODE_NATIVE_WIFI;
if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags))
config.rx_decap_mode = TARGET_DECAP_MODE_RAW;
config.scan_max_pending_req = TARGET_SCAN_MAX_PENDING_REQS;
config.bmiss_offload_max_vdev = TARGET_BMISS_OFFLOAD_MAX_VDEV;
config.roam_offload_max_vdev = TARGET_ROAM_OFFLOAD_MAX_VDEV;
config.roam_offload_max_ap_profiles = TARGET_ROAM_OFFLOAD_MAX_AP_PROFILES;
config.num_mcast_groups = TARGET_NUM_MCAST_GROUPS;
config.num_mcast_table_elems = TARGET_NUM_MCAST_TABLE_ELEMS;
config.mcast2ucast_mode = TARGET_MCAST2UCAST_MODE;
config.tx_dbg_log_size = TARGET_TX_DBG_LOG_SIZE;
config.num_wds_entries = TARGET_NUM_WDS_ENTRIES;
config.dma_burst_size = TARGET_DMA_BURST_SIZE;
config.rx_skip_defrag_timeout_dup_detection_check =
TARGET_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK;
config.vow_config = TARGET_VOW_CONFIG;
config.gtk_offload_max_vdev = TARGET_GTK_OFFLOAD_MAX_VDEV;
config.num_msdu_desc = TARGET_NUM_MSDU_DESC;
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 = ab->num_radios;
config.twt_ap_sta_count = 1000;
ab->hw_params.hw_ops->wmi_init_config(ab, &config);
memcpy(&wmi_sc->wlan_resource_config, &config, sizeof(config));
@ -6301,7 +6252,7 @@ static void ath11k_peer_assoc_conf_event(struct ath11k_base *ab, struct sk_buff
static void ath11k_update_stats_event(struct ath11k_base *ab, struct sk_buff *skb)
{
ath11k_debug_fw_stats_process(ab, skb);
ath11k_debugfs_fw_stats_process(ab, skb);
}
/* PDEV_CTL_FAILSAFE_CHECK_EVENT is received from FW when the frequency scanned

View File

@ -161,33 +161,14 @@ static int reg_show(struct seq_file *seq, void *p)
return 0;
}
static const struct seq_operations register_seq_ops = {
static const struct seq_operations registers_sops = {
.start = reg_start,
.next = reg_next,
.stop = reg_stop,
.show = reg_show
};
static int open_file_registers(struct inode *inode, struct file *file)
{
struct seq_file *s;
int res;
res = seq_open(file, &register_seq_ops);
if (res == 0) {
s = file->private_data;
s->private = inode->i_private;
}
return res;
}
static const struct file_operations fops_registers = {
.open = open_file_registers,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
.owner = THIS_MODULE,
};
DEFINE_SEQ_ATTRIBUTE(registers);
/* debugfs: beacons */
@ -1005,7 +986,7 @@ ath5k_debug_init_device(struct ath5k_hw *ah)
return;
debugfs_create_file("debug", 0600, phydir, ah, &fops_debug);
debugfs_create_file("registers", 0400, phydir, ah, &fops_registers);
debugfs_create_file("registers", 0400, phydir, ah, &registers_fops);
debugfs_create_file("beacon", 0600, phydir, ah, &fops_beacon);
debugfs_create_file("reset", 0200, phydir, ah, &fops_reset);
debugfs_create_file("antenna", 0600, phydir, ah, &fops_antenna);

View File

@ -2639,6 +2639,11 @@ int ath6kl_wmi_delete_pstream_cmd(struct wmi *wmi, u8 if_idx, u8 traffic_class,
return -EINVAL;
}
if (tsid >= 16) {
ath6kl_err("invalid tsid: %d\n", tsid);
return -EINVAL;
}
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
if (!skb)
return -ENOMEM;

View File

@ -449,10 +449,19 @@ static void hif_usb_stop(void *hif_handle)
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
/* The pending URBs have to be canceled. */
spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
list_for_each_entry_safe(tx_buf, tx_buf_tmp,
&hif_dev->tx.tx_pending, list) {
usb_get_urb(tx_buf->urb);
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
usb_kill_urb(tx_buf->urb);
list_del(&tx_buf->list);
usb_free_urb(tx_buf->urb);
kfree(tx_buf->buf);
kfree(tx_buf);
spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
}
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
usb_kill_anchored_urbs(&hif_dev->mgmt_submitted);
}
@ -762,27 +771,37 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)
struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL;
unsigned long flags;
spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
list_for_each_entry_safe(tx_buf, tx_buf_tmp,
&hif_dev->tx.tx_buf, list) {
usb_get_urb(tx_buf->urb);
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
usb_kill_urb(tx_buf->urb);
list_del(&tx_buf->list);
usb_free_urb(tx_buf->urb);
kfree(tx_buf->buf);
kfree(tx_buf);
spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
}
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
hif_dev->tx.flags |= HIF_USB_TX_FLUSH;
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
list_for_each_entry_safe(tx_buf, tx_buf_tmp,
&hif_dev->tx.tx_pending, list) {
usb_get_urb(tx_buf->urb);
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
usb_kill_urb(tx_buf->urb);
list_del(&tx_buf->list);
usb_free_urb(tx_buf->urb);
kfree(tx_buf->buf);
kfree(tx_buf);
spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
}
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
usb_kill_anchored_urbs(&hif_dev->mgmt_submitted);
}

View File

@ -726,7 +726,129 @@ enum pe_stats_mask {
#define WCN36XX_HAL_CFG_AP_LINK_MONITOR_TIMEOUT 102
#define WCN36XX_HAL_CFG_BTC_DWELL_TIME_MULTIPLIER 103
#define WCN36XX_HAL_CFG_ENABLE_TDLS_OXYGEN_MODE 104
#define WCN36XX_HAL_CFG_MAX_PARAMS 105
#define WCN36XX_HAL_CFG_ENABLE_NAT_KEEP_ALIVE_FILTER 105
#define WCN36XX_HAL_CFG_ENABLE_SAP_OBSS_PROT 106
#define WCN36XX_HAL_CFG_PSPOLL_DATA_RECEP_TIMEOUT 107
#define WCN36XX_HAL_CFG_TDLS_PUAPSD_BUFFER_STA_CAPABLE 108
#define WCN36XX_HAL_CFG_TDLS_PUAPSD_MASK 109
#define WCN36XX_HAL_CFG_TDLS_PUAPSD_INACTIVITY_TIME 110
#define WCN36XX_HAL_CFG_TDLS_PUAPSD_RX_FRAME_THRESHOLD 111
#define WCN36XX_HAL_CFG_ANTENNA_DIVERSITY 112
#define WCN36XX_HAL_CFG_ATH_DISABLE 113
#define WCN36XX_HAL_CFG_FLEXCONNECT_POWER_FACTOR 114
#define WCN36XX_HAL_CFG_ENABLE_ADAPTIVE_RX_DRAIN 115
#define WCN36XX_HAL_CFG_TDLS_OFF_CHANNEL_CAPABLE 116
#define WCN36XX_HAL_CFG_MWS_COEX_V1_WAN_FREQ 117
#define WCN36XX_HAL_CFG_MWS_COEX_V1_WLAN_FREQ 118
#define WCN36XX_HAL_CFG_MWS_COEX_V1_CONFIG 119
#define WCN36XX_HAL_CFG_MWS_COEX_V1_CONFIG2 120
#define WCN36XX_HAL_CFG_MWS_COEX_V2_WAN_FREQ 121
#define WCN36XX_HAL_CFG_MWS_COEX_V2_WLAN_FREQ 122
#define WCN36XX_HAL_CFG_MWS_COEX_V2_CONFIG 123
#define WCN36XX_HAL_CFG_MWS_COEX_V2_CONFIG2 124
#define WCN36XX_HAL_CFG_MWS_COEX_V3_WAN_FREQ 125
#define WCN36XX_HAL_CFG_MWS_COEX_V3_WLAN_FREQ 126
#define WCN36XX_HAL_CFG_MWS_COEX_V3_CONFIG 127
#define WCN36XX_HAL_CFG_MWS_COEX_V3_CONFIG2 128
#define WCN36XX_HAL_CFG_MWS_COEX_V4_WAN_FREQ 129
#define WCN36XX_HAL_CFG_MWS_COEX_V4_WLAN_FREQ 130
#define WCN36XX_HAL_CFG_MWS_COEX_V4_CONFIG 131
#define WCN36XX_HAL_CFG_MWS_COEX_V4_CONFIG2 132
#define WCN36XX_HAL_CFG_MWS_COEX_V5_WAN_FREQ 133
#define WCN36XX_HAL_CFG_MWS_COEX_V5_WLAN_FREQ 134
#define WCN36XX_HAL_CFG_MWS_COEX_V5_CONFIG 135
#define WCN36XX_HAL_CFG_MWS_COEX_V5_CONFIG2 136
#define WCN36XX_HAL_CFG_MWS_COEX_V6_WAN_FREQ 137
#define WCN36XX_HAL_CFG_MWS_COEX_V6_WLAN_FREQ 138
#define WCN36XX_HAL_CFG_MWS_COEX_V6_CONFIG 139
#define WCN36XX_HAL_CFG_MWS_COEX_V6_CONFIG2 140
#define WCN36XX_HAL_CFG_MWS_COEX_V7_WAN_FREQ 141
#define WCN36XX_HAL_CFG_MWS_COEX_V7_WLAN_FREQ 142
#define WCN36XX_HAL_CFG_MWS_COEX_V7_CONFIG 143
#define WCN36XX_HAL_CFG_MWS_COEX_V7_CONFIG2 144
#define WCN36XX_HAL_CFG_MWS_COEX_V8_WAN_FREQ 145
#define WCN36XX_HAL_CFG_MWS_COEX_V8_WLAN_FREQ 146
#define WCN36XX_HAL_CFG_MWS_COEX_V8_CONFIG 147
#define WCN36XX_HAL_CFG_MWS_COEX_V8_CONFIG2 148
#define WCN36XX_HAL_CFG_MWS_COEX_V9_WAN_FREQ 149
#define WCN36XX_HAL_CFG_MWS_COEX_V9_WLAN_FREQ 150
#define WCN36XX_HAL_CFG_MWS_COEX_V9_CONFIG 151
#define WCN36XX_HAL_CFG_MWS_COEX_V9_CONFIG2 152
#define WCN36XX_HAL_CFG_MWS_COEX_V10_WAN_FREQ 153
#define WCN36XX_HAL_CFG_MWS_COEX_V10_WLAN_FREQ 154
#define WCN36XX_HAL_CFG_MWS_COEX_V10_CONFIG 155
#define WCN36XX_HAL_CFG_MWS_COEX_V10_CONFIG2 156
#define WCN36XX_HAL_CFG_MWS_COEX_MODEM_BACKOFF 157
#define WCN36XX_HAL_CFG_MWS_COEX_CONFIG1 158
#define WCN36XX_HAL_CFG_MWS_COEX_CONFIG2 159
#define WCN36XX_HAL_CFG_MWS_COEX_CONFIG3 160
#define WCN36XX_HAL_CFG_MWS_COEX_CONFIG4 161
#define WCN36XX_HAL_CFG_MWS_COEX_CONFIG5 162
#define WCN36XX_HAL_CFG_MWS_COEX_CONFIG6 163
#define WCN36XX_HAL_CFG_SAR_POWER_BACKOFF 164
#define WCN36XX_HAL_CFG_GO_LINK_MONITOR_TIMEOUT 165
#define WCN36XX_HAL_CFG_BTC_STATIC_OPP_WLAN_ACTIVE_WLAN_LEN 166
#define WCN36XX_HAL_CFG_BTC_STATIC_OPP_WLAN_ACTIVE_BT_LEN 167
#define WCN36XX_HAL_CFG_BTC_SAP_STATIC_OPP_ACTIVE_WLAN_LEN 168
#define WCN36XX_HAL_CFG_BTC_SAP_STATIC_OPP_ACTIVE_BT_LEN 169
#define WCN36XX_HAL_CFG_RMC_FIXED_RATE 170
#define WCN36XX_HAL_CFG_ASD_PROBE_INTERVAL 171
#define WCN36XX_HAL_CFG_ASD_TRIGGER_THRESHOLD 172
#define WCN36XX_HAL_CFG_ASD_RTT_RSSI_HYST_THRESHOLD 173
#define WCN36XX_HAL_CFG_BTC_CTS2S_ON_STA_DURING_SCO 174
#define WCN36XX_HAL_CFG_SHORT_PREAMBLE 175
#define WCN36XX_HAL_CFG_SHORT_SLOT_TIME 176
#define WCN36XX_HAL_CFG_DELAYED_BA 177
#define WCN36XX_HAL_CFG_IMMEDIATE_BA 178
#define WCN36XX_HAL_CFG_DOT11_MODE 179
#define WCN36XX_HAL_CFG_HT_CAPS 180
#define WCN36XX_HAL_CFG_AMPDU_PARAMS 181
#define WCN36XX_HAL_CFG_TX_BF_INFO 182
#define WCN36XX_HAL_CFG_ASC_CAP_INFO 183
#define WCN36XX_HAL_CFG_EXT_HT_CAPS 184
#define WCN36XX_HAL_CFG_QOS_ENABLED 185
#define WCN36XX_HAL_CFG_WME_ENABLED 186
#define WCN36XX_HAL_CFG_WSM_ENABLED 187
#define WCN36XX_HAL_CFG_WMM_ENABLED 188
#define WCN36XX_HAL_CFG_UAPSD_PER_AC_BITMASK 189
#define WCN36XX_HAL_CFG_MCS_RATES 190
#define WCN36XX_HAL_CFG_VHT_CAPS 191
#define WCN36XX_HAL_CFG_VHT_RX_SUPP_MCS 192
#define WCN36XX_HAL_CFG_VHT_TX_SUPP_MCS 193
#define WCN36XX_HAL_CFG_RA_FILTER_ENABLE 194
#define WCN36XX_HAL_CFG_RA_RATE_LIMIT_INTERVAL 195
#define WCN36XX_HAL_CFG_BTC_FATAL_HID_NSNIFF_BLK 196
#define WCN36XX_HAL_CFG_BTC_CRITICAL_HID_NSNIFF_BLK 197
#define WCN36XX_HAL_CFG_BTC_DYN_A2DP_TX_QUEUE_THOLD 198
#define WCN36XX_HAL_CFG_BTC_DYN_OPP_TX_QUEUE_THOLD 199
#define WCN36XX_HAL_CFG_LINK_FAIL_TIMEOUT 200
#define WCN36XX_HAL_CFG_MAX_UAPSD_CONSEC_SP 201
#define WCN36XX_HAL_CFG_MAX_UAPSD_CONSEC_RX_CNT 202
#define WCN36XX_HAL_CFG_MAX_UAPSD_CONSEC_TX_CNT 203
#define WCN36XX_HAL_CFG_MAX_UAPSD_CONSEC_RX_CNT_MEAS_WINDOW 204
#define WCN36XX_HAL_CFG_MAX_UAPSD_CONSEC_TX_CNT_MEAS_WINDOW 205
#define WCN36XX_HAL_CFG_MAX_PSPOLL_IN_WMM_UAPSD_PS_MODE 206
#define WCN36XX_HAL_CFG_MAX_UAPSD_INACTIVITY_INTERVALS 207
#define WCN36XX_HAL_CFG_ENABLE_DYNAMIC_WMMPS 208
#define WCN36XX_HAL_CFG_BURST_MODE_BE_TXOP_VALUE 209
#define WCN36XX_HAL_CFG_ENABLE_DYNAMIC_RA_START_RATE 210
#define WCN36XX_HAL_CFG_BTC_FAST_WLAN_CONN_PREF 211
#define WCN36XX_HAL_CFG_ENABLE_RTSCTS_HTVHT 212
#define WCN36XX_HAL_CFG_BTC_STATIC_OPP_WLAN_IDLE_WLAN_LEN 213
#define WCN36XX_HAL_CFG_BTC_STATIC_OPP_WLAN_IDLE_BT_LEN 214
#define WCN36XX_HAL_CFG_LINK_FAIL_TX_CNT 215
#define WCN36XX_HAL_CFG_TOGGLE_ARP_BDRATES 216
#define WCN36XX_HAL_CFG_OPTIMIZE_CA_EVENT 217
#define WCN36XX_HAL_CFG_EXT_SCAN_CONC_MODE 218
#define WCN36XX_HAL_CFG_BAR_WAKEUP_HOST_DISABLE 219
#define WCN36XX_HAL_CFG_SAR_BOFFSET_CORRECTION_ENABLE 220
#define WCN36XX_HAL_CFG_UNITS_OF_BCN_WAIT_TIME 221
#define WCN36XX_HAL_CFG_CONS_BCNMISS_COUNT 222
#define WCN36XX_HAL_CFG_BTC_DISABLE_WLAN_LINK_CRITICAL 223
#define WCN36XX_HAL_CFG_DISABLE_SCAN_DURING_SCO 224
#define WCN36XX_HAL_CFG_TRIGGER_NULLFRAME_BEFORE_HB 225
#define WCN36XX_HAL_CFG_ENABLE_POWERSAVE_OFFLOAD 226
#define WCN36XX_HAL_CFG_MAX_PARAMS 227
/* Specify the starting bitrate, 11B and 11A/G rates can be specified in
* multiples of 0.5 So for 5.5 mbps => 11. for MCS 0 - 7 rates, Bit 7 should
@ -1592,9 +1714,15 @@ struct wcn36xx_hal_config_sta_params_v1 {
u8 reserved:4;
/* These rates are the intersection of peer and self capabilities. */
struct wcn36xx_hal_supported_rates supported_rates;
struct wcn36xx_hal_supported_rates_v1 supported_rates;
u8 vht_capable;
u8 vht_tx_channel_width_set;
} __packed;
#define WCN36XX_DIFF_STA_PARAMS_V1_NOVHT 10
struct wcn36xx_hal_config_sta_req_msg_v1 {
struct wcn36xx_hal_msg_header header;
struct wcn36xx_hal_config_sta_params_v1 sta_params;
@ -2015,8 +2143,14 @@ struct wcn36xx_hal_config_bss_params_v1 {
* "STA context"
*/
struct wcn36xx_hal_config_sta_params_v1 sta;
u8 vht_capable;
u8 vht_tx_channel_width_set;
} __packed;
#define WCN36XX_DIFF_BSS_PARAMS_V1_NOVHT (WCN36XX_DIFF_STA_PARAMS_V1_NOVHT + 2)
struct wcn36xx_hal_config_bss_req_msg_v1 {
struct wcn36xx_hal_msg_header header;
struct wcn36xx_hal_config_bss_params_v1 bss_params;

View File

@ -39,10 +39,10 @@ MODULE_PARM_DESC(debug_mask, "Debugging mask");
.max_power = 25, \
}
#define CHAN5G(_freq, _idx) { \
#define CHAN5G(_freq, _idx, _phy_val) { \
.band = NL80211_BAND_5GHZ, \
.center_freq = (_freq), \
.hw_value = (_idx), \
.hw_value = (_phy_val) << HW_VALUE_PHY_SHIFT | HW_VALUE_CHANNEL(_idx), \
.max_power = 25, \
}
@ -67,29 +67,29 @@ static struct ieee80211_channel wcn_2ghz_channels[] = {
};
static struct ieee80211_channel wcn_5ghz_channels[] = {
CHAN5G(5180, 36),
CHAN5G(5200, 40),
CHAN5G(5220, 44),
CHAN5G(5240, 48),
CHAN5G(5260, 52),
CHAN5G(5280, 56),
CHAN5G(5300, 60),
CHAN5G(5320, 64),
CHAN5G(5500, 100),
CHAN5G(5520, 104),
CHAN5G(5540, 108),
CHAN5G(5560, 112),
CHAN5G(5580, 116),
CHAN5G(5600, 120),
CHAN5G(5620, 124),
CHAN5G(5640, 128),
CHAN5G(5660, 132),
CHAN5G(5700, 140),
CHAN5G(5745, 149),
CHAN5G(5765, 153),
CHAN5G(5785, 157),
CHAN5G(5805, 161),
CHAN5G(5825, 165)
CHAN5G(5180, 36, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
CHAN5G(5200, 40, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
CHAN5G(5220, 44, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
CHAN5G(5240, 48, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
CHAN5G(5260, 52, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
CHAN5G(5280, 56, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
CHAN5G(5300, 60, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
CHAN5G(5320, 64, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
CHAN5G(5500, 100, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
CHAN5G(5520, 104, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
CHAN5G(5540, 108, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
CHAN5G(5560, 112, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
CHAN5G(5580, 116, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
CHAN5G(5600, 120, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
CHAN5G(5620, 124, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
CHAN5G(5640, 128, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
CHAN5G(5660, 132, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
CHAN5G(5700, 140, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
CHAN5G(5745, 149, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
CHAN5G(5765, 153, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
CHAN5G(5785, 157, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
CHAN5G(5805, 161, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
CHAN5G(5825, 165, 0)
};
#define RATE(_bitrate, _hw_rate, _flags) { \
@ -766,7 +766,16 @@ static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
sta->ht_cap.mcs.rx_mask,
sizeof(sta->ht_cap.mcs.rx_mask));
}
if (sta->vht_cap.vht_supported) {
sta_priv->supported_rates.op_rate_mode = STA_11ac;
sta_priv->supported_rates.vht_rx_mcs_map =
sta->vht_cap.vht_mcs.rx_mcs_map;
sta_priv->supported_rates.vht_tx_mcs_map =
sta->vht_cap.vht_mcs.tx_mcs_map;
}
}
void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates)
{
u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES] = {
@ -793,6 +802,14 @@ void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates)
sizeof(*ofdm_rates) * WCN36XX_HAL_NUM_OFDM_RATES);
rates->supported_mcs_set[0] = 0xFF;
}
void wcn36xx_set_default_rates_v1(struct wcn36xx_hal_supported_rates_v1 *rates)
{
rates->op_rate_mode = STA_11ac;
rates->vht_rx_mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9;
rates->vht_tx_mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9;
}
static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
@ -1184,6 +1201,35 @@ static const struct ieee80211_ops wcn36xx_ops = {
CFG80211_TESTMODE_CMD(wcn36xx_tm_cmd)
};
static void
wcn36xx_set_ieee80211_vht_caps(struct ieee80211_sta_vht_cap *vht_cap)
{
vht_cap->vht_supported = true;
vht_cap->cap = (IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 |
IEEE80211_VHT_CAP_SHORT_GI_80 |
IEEE80211_VHT_CAP_RXSTBC_1 |
IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT |
7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
vht_cap->vht_mcs.rx_mcs_map =
cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_9 |
IEEE80211_VHT_MCS_NOT_SUPPORTED << 2 |
IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 |
IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 |
IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 |
IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 |
IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 |
IEEE80211_VHT_MCS_NOT_SUPPORTED << 14);
vht_cap->vht_mcs.rx_highest = cpu_to_le16(433);
vht_cap->vht_mcs.tx_highest = vht_cap->vht_mcs.rx_highest;
vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map;
}
static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
{
static const u32 cipher_suites[] = {
@ -1210,6 +1256,9 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
if (wcn->rf_id != RF_IRIS_WCN3620)
wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = &wcn_band_5ghz;
if (wcn->rf_id == RF_IRIS_WCN3680)
wcn36xx_set_ieee80211_vht_caps(&wcn_band_5ghz.vht_cap);
wcn->hw->wiphy->max_scan_ssids = WCN36XX_MAX_SCAN_SSIDS;
wcn->hw->wiphy->max_scan_ie_len = WCN36XX_MAX_SCAN_IE_LEN;

View File

@ -80,6 +80,102 @@ static struct wcn36xx_cfg_val wcn36xx_cfg_vals[] = {
WCN36XX_CFG_VAL(ENABLE_DYNAMIC_RA_START_RATE, 133), /* MCS 5 */
};
static struct wcn36xx_cfg_val wcn3680_cfg_vals[] = {
WCN36XX_CFG_VAL(CURRENT_TX_ANTENNA, 1),
WCN36XX_CFG_VAL(CURRENT_RX_ANTENNA, 1),
WCN36XX_CFG_VAL(LOW_GAIN_OVERRIDE, 0),
WCN36XX_CFG_VAL(POWER_STATE_PER_CHAIN, 785),
WCN36XX_CFG_VAL(CAL_PERIOD, 5),
WCN36XX_CFG_VAL(CAL_CONTROL, 1),
WCN36XX_CFG_VAL(PROXIMITY, 0),
WCN36XX_CFG_VAL(NETWORK_DENSITY, 3),
WCN36XX_CFG_VAL(MAX_MEDIUM_TIME, 4096),
WCN36XX_CFG_VAL(MAX_MPDUS_IN_AMPDU, 64),
WCN36XX_CFG_VAL(RTS_THRESHOLD, 2347),
WCN36XX_CFG_VAL(SHORT_RETRY_LIMIT, 15),
WCN36XX_CFG_VAL(LONG_RETRY_LIMIT, 15),
WCN36XX_CFG_VAL(FRAGMENTATION_THRESHOLD, 8000),
WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ZERO, 5),
WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ONE, 10),
WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_TWO, 15),
WCN36XX_CFG_VAL(FIXED_RATE, 0),
WCN36XX_CFG_VAL(RETRYRATE_POLICY, 4),
WCN36XX_CFG_VAL(RETRYRATE_SECONDARY, 0),
WCN36XX_CFG_VAL(RETRYRATE_TERTIARY, 0),
WCN36XX_CFG_VAL(FORCE_POLICY_PROTECTION, 5),
WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_24GHZ, 1),
WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_5GHZ, 5),
WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_24GHZ, 1),
WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_5GHZ, 5),
WCN36XX_CFG_VAL(MAX_BA_SESSIONS, 40),
WCN36XX_CFG_VAL(PS_DATA_INACTIVITY_TIMEOUT, 200),
WCN36XX_CFG_VAL(PS_ENABLE_BCN_FILTER, 1),
WCN36XX_CFG_VAL(PS_ENABLE_RSSI_MONITOR, 1),
WCN36XX_CFG_VAL(NUM_BEACON_PER_RSSI_AVERAGE, 20),
WCN36XX_CFG_VAL(STATS_PERIOD, 10),
WCN36XX_CFG_VAL(CFP_MAX_DURATION, 30000),
WCN36XX_CFG_VAL(FRAME_TRANS_ENABLED, 0),
WCN36XX_CFG_VAL(BA_THRESHOLD_HIGH, 128),
WCN36XX_CFG_VAL(MAX_BA_BUFFERS, 2560),
WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE, 0),
WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1),
WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1),
WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0),
WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_BT, 120000),
WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN, 30000),
WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10),
WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0),
WCN36XX_CFG_VAL(TDLS_PUAPSD_MASK, 0),
WCN36XX_CFG_VAL(TDLS_PUAPSD_BUFFER_STA_CAPABLE, 1),
WCN36XX_CFG_VAL(TDLS_PUAPSD_INACTIVITY_TIME, 0),
WCN36XX_CFG_VAL(TDLS_PUAPSD_RX_FRAME_THRESHOLD, 10),
WCN36XX_CFG_VAL(TDLS_OFF_CHANNEL_CAPABLE, 1),
WCN36XX_CFG_VAL(ENABLE_ADAPTIVE_RX_DRAIN, 1),
WCN36XX_CFG_VAL(FLEXCONNECT_POWER_FACTOR, 0),
WCN36XX_CFG_VAL(ANTENNA_DIVERSITY, 3),
WCN36XX_CFG_VAL(ATH_DISABLE, 0),
WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_ACTIVE_WLAN_LEN, 60000),
WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_ACTIVE_BT_LEN, 90000),
WCN36XX_CFG_VAL(BTC_SAP_STATIC_OPP_ACTIVE_WLAN_LEN, 30000),
WCN36XX_CFG_VAL(BTC_SAP_STATIC_OPP_ACTIVE_BT_LEN, 30000),
WCN36XX_CFG_VAL(ASD_PROBE_INTERVAL, 50),
WCN36XX_CFG_VAL(ASD_TRIGGER_THRESHOLD, -60),
WCN36XX_CFG_VAL(ASD_RTT_RSSI_HYST_THRESHOLD, 3),
WCN36XX_CFG_VAL(BTC_CTS2S_ON_STA_DURING_SCO, 0),
WCN36XX_CFG_VAL(RA_FILTER_ENABLE, 0),
WCN36XX_CFG_VAL(RA_RATE_LIMIT_INTERVAL, 60),
WCN36XX_CFG_VAL(BTC_FATAL_HID_NSNIFF_BLK, 2),
WCN36XX_CFG_VAL(BTC_CRITICAL_HID_NSNIFF_BLK, 1),
WCN36XX_CFG_VAL(BTC_DYN_A2DP_TX_QUEUE_THOLD, 0),
WCN36XX_CFG_VAL(BTC_DYN_OPP_TX_QUEUE_THOLD, 1),
WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_SP, 10),
WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_RX_CNT, 50),
WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_TX_CNT, 50),
WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_TX_CNT_MEAS_WINDOW, 500),
WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_RX_CNT_MEAS_WINDOW, 500),
WCN36XX_CFG_VAL(MAX_PSPOLL_IN_WMM_UAPSD_PS_MODE, 0),
WCN36XX_CFG_VAL(MAX_UAPSD_INACTIVITY_INTERVALS, 10),
WCN36XX_CFG_VAL(ENABLE_DYNAMIC_WMMPS, 1),
WCN36XX_CFG_VAL(BURST_MODE_BE_TXOP_VALUE, 0),
WCN36XX_CFG_VAL(ENABLE_DYNAMIC_RA_START_RATE, 136),
WCN36XX_CFG_VAL(BTC_FAST_WLAN_CONN_PREF, 1),
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(TOGGLE_ARP_BDRATES, 0),
WCN36XX_CFG_VAL(OPTIMIZE_CA_EVENT, 0),
WCN36XX_CFG_VAL(EXT_SCAN_CONC_MODE, 0),
WCN36XX_CFG_VAL(BAR_WAKEUP_HOST_DISABLE, 0),
WCN36XX_CFG_VAL(SAR_BOFFSET_CORRECTION_ENABLE, 0),
WCN36XX_CFG_VAL(BTC_DISABLE_WLAN_LINK_CRITICAL, 5),
WCN36XX_CFG_VAL(DISABLE_SCAN_DURING_SCO, 2),
WCN36XX_CFG_VAL(CONS_BCNMISS_COUNT, 0),
WCN36XX_CFG_VAL(UNITS_OF_BCN_WAIT_TIME, 0),
WCN36XX_CFG_VAL(TRIGGER_NULLFRAME_BEFORE_HB, 0),
WCN36XX_CFG_VAL(ENABLE_POWERSAVE_OFFLOAD, 0),
};
static int put_cfg_tlv_u32(struct wcn36xx *wcn, size_t *len, u32 id, u32 value)
{
struct wcn36xx_hal_cfg *entry;
@ -122,6 +218,7 @@ static inline u8 is_cap_supported(unsigned long caps, unsigned long flag)
{
return caps & flag ? 1 : 0;
}
static void wcn36xx_smd_set_bss_ht_params(struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct wcn36xx_hal_config_bss_params *bss_params)
@ -146,6 +243,15 @@ static void wcn36xx_smd_set_bss_ht_params(struct ieee80211_vif *vif,
}
}
static void
wcn36xx_smd_set_bss_vht_params(struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct wcn36xx_hal_config_bss_params_v1 *bss)
{
if (sta && sta->vht_cap.vht_supported)
bss->vht_capable = 1;
}
static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta,
struct wcn36xx_hal_config_sta_params *sta_params)
{
@ -174,6 +280,37 @@ static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta,
}
}
static void wcn36xx_smd_set_sta_vht_params(struct wcn36xx *wcn,
struct ieee80211_sta *sta,
struct wcn36xx_hal_config_sta_params_v1 *sta_params)
{
if (sta->vht_cap.vht_supported) {
unsigned long caps = sta->vht_cap.cap;
sta_params->vht_capable = sta->vht_cap.vht_supported;
sta_params->vht_ldpc_enabled =
is_cap_supported(caps, IEEE80211_VHT_CAP_RXLDPC);
if (get_feat_caps(wcn->fw_feat_caps, MU_MIMO)) {
sta_params->vht_tx_mu_beamformee_capable =
is_cap_supported(caps, IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);
if (sta_params->vht_tx_mu_beamformee_capable)
sta_params->vht_tx_bf_enabled = 1;
} else {
sta_params->vht_tx_mu_beamformee_capable = 0;
}
sta_params->vht_tx_channel_width_set = 0;
}
}
static void wcn36xx_smd_set_sta_ht_ldpc_params(struct ieee80211_sta *sta,
struct wcn36xx_hal_config_sta_params_v1 *sta_params)
{
if (sta->ht_cap.ht_supported) {
sta_params->ht_ldpc_enabled =
is_cap_supported(sta->ht_cap.cap, IEEE80211_HT_CAP_LDPC_CODING);
}
}
static void wcn36xx_smd_set_sta_default_ht_params(
struct wcn36xx_hal_config_sta_params *sta_params)
{
@ -190,6 +327,31 @@ static void wcn36xx_smd_set_sta_default_ht_params(
sta_params->dsss_cck_mode_40mhz = 1;
}
static void wcn36xx_smd_set_sta_default_vht_params(struct wcn36xx *wcn,
struct wcn36xx_hal_config_sta_params_v1 *sta_params)
{
if (wcn->rf_id == RF_IRIS_WCN3680) {
sta_params->vht_capable = 1;
sta_params->vht_tx_mu_beamformee_capable = 1;
} else {
sta_params->vht_capable = 0;
sta_params->vht_tx_mu_beamformee_capable = 0;
}
sta_params->vht_ldpc_enabled = 0;
sta_params->vht_tx_channel_width_set = 0;
sta_params->vht_tx_bf_enabled = 0;
}
static void wcn36xx_smd_set_sta_default_ht_ldpc_params(struct wcn36xx *wcn,
struct wcn36xx_hal_config_sta_params_v1 *sta_params)
{
if (wcn->rf_id == RF_IRIS_WCN3680)
sta_params->ht_ldpc_enabled = 1;
else
sta_params->ht_ldpc_enabled = 0;
}
static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@ -242,9 +404,10 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
sta_params->aid = sta_priv->aid;
wcn36xx_smd_set_sta_ht_params(sta, sta_params);
memcpy(&sta_params->supported_rates, &sta_priv->supported_rates,
sizeof(sta_priv->supported_rates));
sizeof(struct wcn36xx_hal_supported_rates));
} else {
wcn36xx_set_default_rates(&sta_params->supported_rates);
wcn36xx_set_default_rates((struct wcn36xx_hal_supported_rates *)
&sta_params->supported_rates);
wcn36xx_smd_set_sta_default_ht_params(sta_params);
}
}
@ -291,14 +454,20 @@ static void init_hal_msg(struct wcn36xx_hal_msg_header *hdr,
hdr->len = msg_size + sizeof(*hdr);
}
#define INIT_HAL_MSG(msg_body, type) \
#define __INIT_HAL_MSG(msg_body, type, version) \
do { \
memset(&msg_body, 0, sizeof(msg_body)); \
msg_body.header.msg_type = type; \
msg_body.header.msg_version = WCN36XX_HAL_MSG_VERSION0; \
msg_body.header.msg_version = version; \
msg_body.header.len = sizeof(msg_body); \
} while (0) \
#define INIT_HAL_MSG(msg_body, type) \
__INIT_HAL_MSG(msg_body, type, WCN36XX_HAL_MSG_VERSION0)
#define INIT_HAL_MSG_V1(msg_body, type) \
__INIT_HAL_MSG(msg_body, type, WCN36XX_HAL_MSG_VERSION1)
#define INIT_HAL_PTT_MSG(p_msg_body, ppt_msg_len) \
do { \
memset(p_msg_body, 0, sizeof(*p_msg_body) + ppt_msg_len); \
@ -450,6 +619,8 @@ int wcn36xx_smd_start(struct wcn36xx *wcn)
int ret;
int i;
size_t len;
int cfg_elements;
static struct wcn36xx_cfg_val *cfg_vals;
mutex_lock(&wcn->hal_mutex);
INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_REQ);
@ -462,9 +633,17 @@ int wcn36xx_smd_start(struct wcn36xx *wcn)
body = (struct wcn36xx_hal_mac_start_req_msg *)wcn->hal_buf;
len = body->header.len;
for (i = 0; i < ARRAY_SIZE(wcn36xx_cfg_vals); i++) {
ret = put_cfg_tlv_u32(wcn, &len, wcn36xx_cfg_vals[i].cfg_id,
wcn36xx_cfg_vals[i].value);
if (wcn->rf_id == RF_IRIS_WCN3680) {
cfg_vals = wcn3680_cfg_vals;
cfg_elements = ARRAY_SIZE(wcn3680_cfg_vals);
} else {
cfg_vals = wcn36xx_cfg_vals;
cfg_elements = ARRAY_SIZE(wcn36xx_cfg_vals);
}
for (i = 0; i < cfg_elements; i++) {
ret = put_cfg_tlv_u32(wcn, &len, cfg_vals[i].cfg_id,
cfg_vals[i].value);
if (ret)
goto out;
}
@ -694,8 +873,10 @@ int wcn36xx_smd_start_hw_scan(struct wcn36xx *wcn, struct ieee80211_vif *vif,
msg_body->num_channel = min_t(u8, req->n_channels,
sizeof(msg_body->channels));
for (i = 0; i < msg_body->num_channel; i++)
msg_body->channels[i] = req->channels[i]->hw_value;
for (i = 0; i < msg_body->num_channel; i++) {
msg_body->channels[i] =
HW_VALUE_CHANNEL(req->channels[i]->hw_value);
}
msg_body->header.len -= WCN36XX_MAX_SCAN_IE_LEN;
@ -1183,6 +1364,31 @@ static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx *wcn,
v1->p2p = orig->p2p;
}
static void
wcn36xx_smd_set_sta_params_v1(struct wcn36xx *wcn,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct wcn36xx_hal_config_sta_params_v1 *sta_par)
{
struct wcn36xx_sta *sta_priv = NULL;
struct wcn36xx_hal_config_sta_params sta_par_v0;
wcn36xx_smd_set_sta_params(wcn, vif, sta, &sta_par_v0);
wcn36xx_smd_convert_sta_to_v1(wcn, &sta_par_v0, sta_par);
if (sta) {
sta_priv = wcn36xx_sta_to_priv(sta);
wcn36xx_smd_set_sta_vht_params(wcn, sta, sta_par);
wcn36xx_smd_set_sta_ht_ldpc_params(sta, sta_par);
memcpy(&sta_par->supported_rates, &sta_priv->supported_rates,
sizeof(sta_par->supported_rates));
} else {
wcn36xx_set_default_rates_v1(&sta_par->supported_rates);
wcn36xx_smd_set_sta_default_vht_params(wcn, sta_par);
wcn36xx_smd_set_sta_default_ht_ldpc_params(wcn, sta_par);
}
}
static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn,
struct ieee80211_sta *sta,
void *buf,
@ -1217,53 +1423,69 @@ static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn,
}
static int wcn36xx_smd_config_sta_v1(struct wcn36xx *wcn,
const struct wcn36xx_hal_config_sta_req_msg *orig)
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
struct wcn36xx_hal_config_sta_req_msg_v1 msg_body;
struct wcn36xx_hal_config_sta_params_v1 *sta = &msg_body.sta_params;
struct wcn36xx_hal_config_sta_params_v1 *sta_params;
INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_STA_REQ);
if (wcn->rf_id == RF_IRIS_WCN3680) {
INIT_HAL_MSG_V1(msg_body, WCN36XX_HAL_CONFIG_STA_REQ);
} else {
INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_STA_REQ);
msg_body.header.len -= WCN36XX_DIFF_STA_PARAMS_V1_NOVHT;
}
wcn36xx_smd_convert_sta_to_v1(wcn, &orig->sta_params,
&msg_body.sta_params);
sta_params = &msg_body.sta_params;
wcn36xx_smd_set_sta_params_v1(wcn, vif, sta, sta_params);
PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
wcn36xx_dbg(WCN36XX_DBG_HAL,
"hal config sta v1 action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
sta->action, sta->sta_index, sta->bssid_index,
sta->bssid, sta->type, sta->mac, sta->aid);
sta_params->action, sta_params->sta_index, sta_params->bssid_index,
sta_params->bssid, sta_params->type, sta_params->mac, sta_params->aid);
return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
}
int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
static int wcn36xx_smd_config_sta_v0(struct wcn36xx *wcn,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
struct wcn36xx_hal_config_sta_req_msg msg;
struct wcn36xx_hal_config_sta_params *sta_params;
int ret;
mutex_lock(&wcn->hal_mutex);
INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_STA_REQ);
sta_params = &msg.sta_params;
wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
ret = wcn36xx_smd_config_sta_v1(wcn, &msg);
} else {
PREPARE_HAL_BUF(wcn->hal_buf, msg);
PREPARE_HAL_BUF(wcn->hal_buf, msg);
wcn36xx_dbg(WCN36XX_DBG_HAL,
"hal config sta action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
sta_params->action, sta_params->sta_index,
sta_params->bssid_index, sta_params->bssid,
sta_params->type, sta_params->mac, sta_params->aid);
wcn36xx_dbg(WCN36XX_DBG_HAL,
"hal config sta action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
sta_params->action, sta_params->sta_index,
sta_params->bssid_index, sta_params->bssid,
sta_params->type, sta_params->mac, sta_params->aid);
return wcn36xx_smd_send_and_wait(wcn, msg.header.len);
}
int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
int ret;
mutex_lock(&wcn->hal_mutex);
if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24))
ret = wcn36xx_smd_config_sta_v1(wcn, vif, sta);
else
ret = wcn36xx_smd_config_sta_v0(wcn, vif, sta);
ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len);
}
if (ret) {
wcn36xx_err("Sending hal_config_sta failed\n");
goto out;
@ -1281,174 +1503,15 @@ out:
return ret;
}
static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn,
const struct wcn36xx_hal_config_bss_req_msg *orig)
static void wcn36xx_smd_set_bss_params(struct wcn36xx *wcn,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
const u8 *bssid,
bool update,
struct wcn36xx_hal_config_bss_params *bss)
{
struct wcn36xx_hal_config_bss_req_msg_v1 *msg_body;
struct wcn36xx_hal_config_bss_params_v1 *bss;
struct wcn36xx_hal_config_sta_params_v1 *sta;
int ret;
msg_body = kzalloc(sizeof(*msg_body), GFP_KERNEL);
if (!msg_body)
return -ENOMEM;
INIT_HAL_MSG((*msg_body), WCN36XX_HAL_CONFIG_BSS_REQ);
bss = &msg_body->bss_params;
sta = &bss->sta;
/* convert orig to v1 */
memcpy(bss->bssid, &orig->bss_params.bssid, ETH_ALEN);
memcpy(bss->self_mac_addr, &orig->bss_params.self_mac_addr, ETH_ALEN);
bss->bss_type = orig->bss_params.bss_type;
bss->oper_mode = orig->bss_params.oper_mode;
bss->nw_type = orig->bss_params.nw_type;
bss->short_slot_time_supported =
orig->bss_params.short_slot_time_supported;
bss->lla_coexist = orig->bss_params.lla_coexist;
bss->llb_coexist = orig->bss_params.llb_coexist;
bss->llg_coexist = orig->bss_params.llg_coexist;
bss->ht20_coexist = orig->bss_params.ht20_coexist;
bss->lln_non_gf_coexist = orig->bss_params.lln_non_gf_coexist;
bss->lsig_tx_op_protection_full_support =
orig->bss_params.lsig_tx_op_protection_full_support;
bss->rifs_mode = orig->bss_params.rifs_mode;
bss->beacon_interval = orig->bss_params.beacon_interval;
bss->dtim_period = orig->bss_params.dtim_period;
bss->tx_channel_width_set = orig->bss_params.tx_channel_width_set;
bss->oper_channel = orig->bss_params.oper_channel;
bss->ext_channel = orig->bss_params.ext_channel;
bss->reserved = orig->bss_params.reserved;
memcpy(&bss->ssid, &orig->bss_params.ssid,
sizeof(orig->bss_params.ssid));
bss->action = orig->bss_params.action;
bss->rateset = orig->bss_params.rateset;
bss->ht = orig->bss_params.ht;
bss->obss_prot_enabled = orig->bss_params.obss_prot_enabled;
bss->rmf = orig->bss_params.rmf;
bss->ht_oper_mode = orig->bss_params.ht_oper_mode;
bss->dual_cts_protection = orig->bss_params.dual_cts_protection;
bss->max_probe_resp_retry_limit =
orig->bss_params.max_probe_resp_retry_limit;
bss->hidden_ssid = orig->bss_params.hidden_ssid;
bss->proxy_probe_resp = orig->bss_params.proxy_probe_resp;
bss->edca_params_valid = orig->bss_params.edca_params_valid;
memcpy(&bss->acbe, &orig->bss_params.acbe,
sizeof(orig->bss_params.acbe));
memcpy(&bss->acbk, &orig->bss_params.acbk,
sizeof(orig->bss_params.acbk));
memcpy(&bss->acvi, &orig->bss_params.acvi,
sizeof(orig->bss_params.acvi));
memcpy(&bss->acvo, &orig->bss_params.acvo,
sizeof(orig->bss_params.acvo));
bss->ext_set_sta_key_param_valid =
orig->bss_params.ext_set_sta_key_param_valid;
memcpy(&bss->ext_set_sta_key_param,
&orig->bss_params.ext_set_sta_key_param,
sizeof(orig->bss_params.acvo));
bss->wcn36xx_hal_persona = orig->bss_params.wcn36xx_hal_persona;
bss->spectrum_mgt_enable = orig->bss_params.spectrum_mgt_enable;
bss->tx_mgmt_power = orig->bss_params.tx_mgmt_power;
bss->max_tx_power = orig->bss_params.max_tx_power;
wcn36xx_smd_convert_sta_to_v1(wcn, &orig->bss_params.sta, sta);
PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body));
wcn36xx_dbg(WCN36XX_DBG_HAL,
"hal config bss v1 bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
bss->bssid, bss->self_mac_addr, bss->bss_type,
bss->oper_mode, bss->nw_type);
wcn36xx_dbg(WCN36XX_DBG_HAL,
"- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
sta->bssid, sta->action, sta->sta_index,
sta->bssid_index, sta->aid, sta->type, sta->mac);
ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
kfree(msg_body);
return ret;
}
static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
void *buf,
size_t len)
{
struct wcn36xx_hal_config_bss_rsp_msg *rsp;
struct wcn36xx_hal_config_bss_rsp_params *params;
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
if (len < sizeof(*rsp))
return -EINVAL;
rsp = (struct wcn36xx_hal_config_bss_rsp_msg *)buf;
params = &rsp->bss_rsp_params;
if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
wcn36xx_warn("hal config bss response failure: %d\n",
params->status);
return -EIO;
}
wcn36xx_dbg(WCN36XX_DBG_HAL,
"hal config bss rsp status %d bss_idx %d dpu_desc_index %d"
" sta_idx %d self_idx %d bcast_idx %d mac %pM"
" power %d ucast_dpu_signature %d\n",
params->status, params->bss_index, params->dpu_desc_index,
params->bss_sta_index, params->bss_self_sta_index,
params->bss_bcast_sta_idx, params->mac,
params->tx_mgmt_power, params->ucast_dpu_signature);
vif_priv->bss_index = params->bss_index;
if (sta) {
struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
sta_priv->bss_sta_index = params->bss_sta_index;
sta_priv->bss_dpu_desc_index = params->dpu_desc_index;
}
vif_priv->self_ucast_dpu_sign = params->ucast_dpu_signature;
return 0;
}
int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, const u8 *bssid,
bool update)
{
struct wcn36xx_hal_config_bss_req_msg *msg;
struct wcn36xx_hal_config_bss_params *bss;
struct wcn36xx_hal_config_sta_params *sta_params;
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
int ret;
mutex_lock(&wcn->hal_mutex);
msg = kzalloc(sizeof(*msg), GFP_KERNEL);
if (!msg) {
ret = -ENOMEM;
goto out;
}
INIT_HAL_MSG((*msg), WCN36XX_HAL_CONFIG_BSS_REQ);
bss = &msg->bss_params;
sta_params = &bss->sta;
WARN_ON(is_zero_ether_addr(bssid));
memcpy(&bss->bssid, bssid, ETH_ALEN);
@ -1502,7 +1565,6 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_NONE;
bss->reserved = 0;
wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
/* wcn->ssid is only valid in AP and IBSS mode */
bss->ssid.length = vif_priv->ssid.length;
@ -1527,6 +1589,154 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
bss->action = update;
vif_priv->bss_type = bss->bss_type;
}
static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta_80211,
const u8 *bssid,
bool update)
{
struct wcn36xx_hal_config_bss_req_msg_v1 *msg_body;
struct wcn36xx_hal_config_bss_params_v1 *bss;
struct wcn36xx_hal_config_bss_params bss_v0;
struct wcn36xx_hal_config_sta_params_v1 *sta;
struct cfg80211_chan_def *chandef;
int ret;
msg_body = kzalloc(sizeof(*msg_body), GFP_KERNEL);
if (!msg_body)
return -ENOMEM;
if (wcn->rf_id == RF_IRIS_WCN3680) {
INIT_HAL_MSG_V1((*msg_body), WCN36XX_HAL_CONFIG_BSS_REQ);
} else {
INIT_HAL_MSG((*msg_body), WCN36XX_HAL_CONFIG_BSS_REQ);
msg_body->header.len -= WCN36XX_DIFF_BSS_PARAMS_V1_NOVHT;
}
bss = &msg_body->bss_params;
sta = &bss->sta;
memset(&bss_v0, 0x00, sizeof(bss_v0));
wcn36xx_smd_set_bss_params(wcn, vif, sta_80211, bssid, update, &bss_v0);
wcn36xx_smd_set_sta_params_v1(wcn, vif, sta_80211, sta);
/* convert orig to v1 */
memcpy(bss->bssid, &bss_v0.bssid, ETH_ALEN);
memcpy(bss->self_mac_addr, &bss_v0.self_mac_addr, ETH_ALEN);
bss->bss_type = bss_v0.bss_type;
bss->oper_mode = bss_v0.oper_mode;
bss->nw_type = bss_v0.nw_type;
bss->short_slot_time_supported =
bss_v0.short_slot_time_supported;
bss->lla_coexist = bss_v0.lla_coexist;
bss->llb_coexist = bss_v0.llb_coexist;
bss->llg_coexist = bss_v0.llg_coexist;
bss->ht20_coexist = bss_v0.ht20_coexist;
bss->lln_non_gf_coexist = bss_v0.lln_non_gf_coexist;
bss->lsig_tx_op_protection_full_support =
bss_v0.lsig_tx_op_protection_full_support;
bss->rifs_mode = bss_v0.rifs_mode;
bss->beacon_interval = bss_v0.beacon_interval;
bss->dtim_period = bss_v0.dtim_period;
bss->tx_channel_width_set = bss_v0.tx_channel_width_set;
bss->oper_channel = bss_v0.oper_channel;
if (wcn->hw->conf.chandef.width == NL80211_CHAN_WIDTH_80) {
chandef = &wcn->hw->conf.chandef;
bss->ext_channel = HW_VALUE_PHY(chandef->chan->hw_value);
} else {
bss->ext_channel = bss_v0.ext_channel;
}
bss->reserved = bss_v0.reserved;
memcpy(&bss->ssid, &bss_v0.ssid,
sizeof(bss_v0.ssid));
bss->action = bss_v0.action;
bss->rateset = bss_v0.rateset;
bss->ht = bss_v0.ht;
bss->obss_prot_enabled = bss_v0.obss_prot_enabled;
bss->rmf = bss_v0.rmf;
bss->ht_oper_mode = bss_v0.ht_oper_mode;
bss->dual_cts_protection = bss_v0.dual_cts_protection;
bss->max_probe_resp_retry_limit =
bss_v0.max_probe_resp_retry_limit;
bss->hidden_ssid = bss_v0.hidden_ssid;
bss->proxy_probe_resp = bss_v0.proxy_probe_resp;
bss->edca_params_valid = bss_v0.edca_params_valid;
memcpy(&bss->acbe, &bss_v0.acbe,
sizeof(bss_v0.acbe));
memcpy(&bss->acbk, &bss_v0.acbk,
sizeof(bss_v0.acbk));
memcpy(&bss->acvi, &bss_v0.acvi,
sizeof(bss_v0.acvi));
memcpy(&bss->acvo, &bss_v0.acvo,
sizeof(bss_v0.acvo));
bss->ext_set_sta_key_param_valid =
bss_v0.ext_set_sta_key_param_valid;
memcpy(&bss->ext_set_sta_key_param,
&bss_v0.ext_set_sta_key_param,
sizeof(bss_v0.acvo));
bss->wcn36xx_hal_persona = bss_v0.wcn36xx_hal_persona;
bss->spectrum_mgt_enable = bss_v0.spectrum_mgt_enable;
bss->tx_mgmt_power = bss_v0.tx_mgmt_power;
bss->max_tx_power = bss_v0.max_tx_power;
wcn36xx_smd_set_bss_vht_params(vif, sta_80211, bss);
PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body));
wcn36xx_dbg(WCN36XX_DBG_HAL,
"hal config bss v1 bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
bss->bssid, bss->self_mac_addr, bss->bss_type,
bss->oper_mode, bss->nw_type);
wcn36xx_dbg(WCN36XX_DBG_HAL,
"- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
sta->bssid, sta->action, sta->sta_index,
sta->bssid_index, sta->aid, sta->type, sta->mac);
ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
kfree(msg_body);
return ret;
}
static int wcn36xx_smd_config_bss_v0(struct wcn36xx *wcn,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
const u8 *bssid,
bool update)
{
struct wcn36xx_hal_config_bss_req_msg *msg;
struct wcn36xx_hal_config_bss_params *bss;
struct wcn36xx_hal_config_sta_params *sta_params;
int ret;
msg = kzalloc(sizeof(*msg), GFP_KERNEL);
if (!msg)
return -ENOMEM;
INIT_HAL_MSG((*msg), WCN36XX_HAL_CONFIG_BSS_REQ);
bss = &msg->bss_params;
sta_params = &bss->sta;
wcn36xx_smd_set_bss_params(wcn, vif, sta, bssid, update, bss);
wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
PREPARE_HAL_BUF(wcn->hal_buf, (*msg));
wcn36xx_dbg(WCN36XX_DBG_HAL,
"hal config bss bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
@ -1540,13 +1750,69 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
sta_params->aid, sta_params->type,
sta_params->mac);
if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
ret = wcn36xx_smd_config_bss_v1(wcn, msg);
} else {
PREPARE_HAL_BUF(wcn->hal_buf, (*msg));
ret = wcn36xx_smd_send_and_wait(wcn, msg->header.len);
kfree(msg);
ret = wcn36xx_smd_send_and_wait(wcn, msg->header.len);
return ret;
}
static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
void *buf,
size_t len)
{
struct wcn36xx_hal_config_bss_rsp_msg *rsp;
struct wcn36xx_hal_config_bss_rsp_params *params;
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
if (len < sizeof(*rsp))
return -EINVAL;
rsp = (struct wcn36xx_hal_config_bss_rsp_msg *)buf;
params = &rsp->bss_rsp_params;
if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
wcn36xx_warn("hal config bss response failure: %d\n",
params->status);
return -EIO;
}
wcn36xx_dbg(WCN36XX_DBG_HAL,
"hal config bss rsp status %d bss_idx %d dpu_desc_index %d"
" sta_idx %d self_idx %d bcast_idx %d mac %pM"
" power %d ucast_dpu_signature %d\n",
params->status, params->bss_index, params->dpu_desc_index,
params->bss_sta_index, params->bss_self_sta_index,
params->bss_bcast_sta_idx, params->mac,
params->tx_mgmt_power, params->ucast_dpu_signature);
vif_priv->bss_index = params->bss_index;
if (sta) {
struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
sta_priv->bss_sta_index = params->bss_sta_index;
sta_priv->bss_dpu_desc_index = params->dpu_desc_index;
}
vif_priv->self_ucast_dpu_sign = params->ucast_dpu_signature;
return 0;
}
int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, const u8 *bssid,
bool update)
{
int ret;
mutex_lock(&wcn->hal_mutex);
if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24))
ret = wcn36xx_smd_config_bss_v1(wcn, vif, sta, bssid, update);
else
ret = wcn36xx_smd_config_bss_v0(wcn, vif, sta, bssid, update);
if (ret) {
wcn36xx_err("Sending hal_config_bss failed\n");
goto out;
@ -1556,12 +1822,10 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
sta,
wcn->hal_buf,
wcn->hal_rsp_len);
if (ret) {
if (ret)
wcn36xx_err("hal_config_bss response failed err=%d\n", ret);
goto out;
}
out:
kfree(msg);
mutex_unlock(&wcn->hal_mutex);
return ret;
}
@ -1928,6 +2192,7 @@ out:
mutex_unlock(&wcn->hal_mutex);
return ret;
}
int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim)
{
struct wcn36xx_hal_set_power_params_req_msg msg_body;
@ -1957,6 +2222,7 @@ out:
mutex_unlock(&wcn->hal_mutex);
return ret;
}
/* Notice: This function should be called after associated, or else it
* will be invalid
*/
@ -2636,6 +2902,7 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
kfree(hal_ind_msg);
}
}
int wcn36xx_smd_open(struct wcn36xx *wcn)
{
wcn->hal_ind_wq = create_freezable_workqueue("wcn36xx_smd_ind");

View File

@ -83,7 +83,11 @@ enum wcn36xx_ampdu_state {
WCN36XX_AMPDU_OPERATIONAL,
};
#define WCN36XX_HW_CHANNEL(__wcn) (__wcn->hw->conf.chandef.chan->hw_value)
#define HW_VALUE_PHY_SHIFT 8
#define HW_VALUE_PHY(hw_value) ((hw_value) >> HW_VALUE_PHY_SHIFT)
#define HW_VALUE_CHANNEL(hw_value) ((hw_value) & 0xFF)
#define WCN36XX_HW_CHANNEL(__wcn)\
HW_VALUE_CHANNEL(__wcn->hw->conf.chandef.chan->hw_value)
#define WCN36XX_BAND(__wcn) (__wcn->hw->conf.chandef.chan->band)
#define WCN36XX_CENTER_FREQ(__wcn) (__wcn->hw->conf.chandef.chan->center_freq)
#define WCN36XX_LISTEN_INTERVAL(__wcn) (__wcn->hw->conf.listen_interval)
@ -169,7 +173,7 @@ struct wcn36xx_sta {
u8 bss_dpu_desc_index;
bool is_data_encrypted;
/* Rates */
struct wcn36xx_hal_supported_rates supported_rates;
struct wcn36xx_hal_supported_rates_v1 supported_rates;
spinlock_t ampdu_lock; /* protects next two fields */
enum wcn36xx_ampdu_state ampdu_state[16];
@ -271,6 +275,7 @@ static inline bool wcn36xx_is_fw_version(struct wcn36xx *wcn,
wcn->fw_revision == revision);
}
void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates);
void wcn36xx_set_default_rates_v1(struct wcn36xx_hal_supported_rates_v1 *rates);
static inline
struct ieee80211_sta *wcn36xx_priv_to_sta(struct wcn36xx_sta *sta_priv)

View File

@ -56,6 +56,7 @@
#define RSN_AKM_PSK 2 /* Pre-shared Key */
#define RSN_AKM_SHA256_1X 5 /* SHA256, 802.1X */
#define RSN_AKM_SHA256_PSK 6 /* SHA256, Pre-shared Key */
#define RSN_AKM_SAE 8 /* SAE */
#define RSN_CAP_LEN 2 /* Length of RSN capabilities */
#define RSN_CAP_PTK_REPLAY_CNTR_MASK (BIT(2) | BIT(3))
#define RSN_CAP_MFPR_MASK BIT(6)
@ -4242,6 +4243,10 @@ brcmf_configure_wpaie(struct brcmf_if *ifp,
brcmf_dbg(TRACE, "RSN_AKM_MFP_1X\n");
wpa_auth |= WPA2_AUTH_1X_SHA256;
break;
case RSN_AKM_SAE:
brcmf_dbg(TRACE, "RSN_AKM_SAE\n");
wpa_auth |= WPA3_AUTH_SAE_PSK;
break;
default:
bphy_err(drvr, "Invalid key mgmt info\n");
}
@ -4259,11 +4264,12 @@ brcmf_configure_wpaie(struct brcmf_if *ifp,
brcmf_dbg(TRACE, "MFP Required\n");
mfp = BRCMF_MFP_REQUIRED;
/* Firmware only supports mfp required in
* combination with WPA2_AUTH_PSK_SHA256 or
* WPA2_AUTH_1X_SHA256.
* combination with WPA2_AUTH_PSK_SHA256,
* WPA2_AUTH_1X_SHA256, or WPA3_AUTH_SAE_PSK.
*/
if (!(wpa_auth & (WPA2_AUTH_PSK_SHA256 |
WPA2_AUTH_1X_SHA256))) {
WPA2_AUTH_1X_SHA256 |
WPA3_AUTH_SAE_PSK))) {
err = -EINVAL;
goto exit;
}
@ -4679,6 +4685,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_pub *drvr = cfg->pub;
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
struct cfg80211_crypto_settings *crypto = &settings->crypto;
const struct brcmf_tlv *ssid_ie;
const struct brcmf_tlv *country_ie;
struct brcmf_ssid_le ssid_le;
@ -4818,6 +4826,25 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
goto exit;
}
if (crypto->psk) {
brcmf_dbg(INFO, "using PSK offload\n");
profile->use_fwauth |= BIT(BRCMF_PROFILE_FWAUTH_PSK);
err = brcmf_set_pmk(ifp, crypto->psk,
BRCMF_WSEC_MAX_PSK_LEN);
if (err < 0)
goto exit;
}
if (crypto->sae_pwd) {
brcmf_dbg(INFO, "using SAE offload\n");
profile->use_fwauth |= BIT(BRCMF_PROFILE_FWAUTH_SAE);
err = brcmf_set_sae_password(ifp, crypto->sae_pwd,
crypto->sae_pwd_len);
if (err < 0)
goto exit;
}
if (profile->use_fwauth == 0)
profile->use_fwauth = BIT(BRCMF_PROFILE_FWAUTH_NONE);
err = brcmf_parse_configure_security(ifp, settings,
NL80211_IFTYPE_AP);
if (err < 0) {
@ -4904,6 +4931,7 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_pub *drvr = cfg->pub;
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
s32 err;
struct brcmf_fil_bss_enable_le bss_enable;
struct brcmf_join_params join_params;
@ -4915,6 +4943,14 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
/* first to make sure they get processed by fw. */
msleep(400);
if (profile->use_fwauth != BIT(BRCMF_PROFILE_FWAUTH_NONE)) {
if (profile->use_fwauth & BIT(BRCMF_PROFILE_FWAUTH_PSK))
brcmf_set_pmk(ifp, NULL, 0);
if (profile->use_fwauth & BIT(BRCMF_PROFILE_FWAUTH_SAE))
brcmf_set_sae_password(ifp, NULL, 0);
profile->use_fwauth = BIT(BRCMF_PROFILE_FWAUTH_NONE);
}
if (ifp->vif->mbss) {
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
return err;
@ -7063,6 +7099,13 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
wiphy_ext_feature_set(wiphy,
NL80211_EXT_FEATURE_SAE_OFFLOAD);
}
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_FWAUTH)) {
wiphy_ext_feature_set(wiphy,
NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK);
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SAE))
wiphy_ext_feature_set(wiphy,
NL80211_EXT_FEATURE_SAE_OFFLOAD_AP);
}
wiphy->mgmt_stypes = brcmf_txrx_stypes;
wiphy->max_remain_on_channel_duration = 5000;
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO)) {

View File

@ -128,6 +128,19 @@ enum brcmf_profile_fwsup {
BRCMF_PROFILE_FWSUP_SAE
};
/**
* enum brcmf_profile_fwauth - firmware authenticator profile
*
* @BRCMF_PROFILE_FWAUTH_NONE: no firmware authenticator
* @BRCMF_PROFILE_FWAUTH_PSK: authenticator for WPA/WPA2-PSK
* @BRCMF_PROFILE_FWAUTH_SAE: authenticator for SAE
*/
enum brcmf_profile_fwauth {
BRCMF_PROFILE_FWAUTH_NONE,
BRCMF_PROFILE_FWAUTH_PSK,
BRCMF_PROFILE_FWAUTH_SAE
};
/**
* struct brcmf_cfg80211_profile - profile information.
*
@ -140,6 +153,7 @@ struct brcmf_cfg80211_profile {
struct brcmf_cfg80211_security sec;
struct brcmf_wsec_key key[BRCMF_MAX_DEFAULT_KEYS];
enum brcmf_profile_fwsup use_fwsup;
u16 use_fwauth;
bool is_ft;
};

View File

@ -42,6 +42,7 @@ static const struct brcmf_feat_fwcap brcmf_fwcap_map[] = {
{ BRCMF_FEAT_MONITOR_FMT_RADIOTAP, "rtap" },
{ BRCMF_FEAT_DOT11H, "802.11h" },
{ BRCMF_FEAT_SAE, "sae" },
{ BRCMF_FEAT_FWAUTH, "idauth" },
};
#ifdef DEBUG

View File

@ -28,6 +28,7 @@
* MONITOR_FMT_HW_RX_HDR: firmware provides monitor packets with hw/ucode header
* DOT11H: firmware supports 802.11h
* SAE: simultaneous authentication of equals
* FWAUTH: Firmware authenticator
*/
#define BRCMF_FEAT_LIST \
BRCMF_FEAT_DEF(MBSS) \
@ -49,7 +50,8 @@
BRCMF_FEAT_DEF(MONITOR_FMT_RADIOTAP) \
BRCMF_FEAT_DEF(MONITOR_FMT_HW_RX_HDR) \
BRCMF_FEAT_DEF(DOT11H) \
BRCMF_FEAT_DEF(SAE)
BRCMF_FEAT_DEF(SAE) \
BRCMF_FEAT_DEF(FWAUTH)
/*
* Quirks:

View File

@ -1578,6 +1578,9 @@ void brcmf_usb_exit(void)
brcmf_dbg(USB, "Enter\n");
ret = driver_for_each_device(drv, NULL, NULL,
brcmf_usb_reset_device);
if (ret)
brcmf_err("failed to reset all usb devices %d\n", ret);
usb_deregister(&brcmf_usbdrvr);
}

View File

@ -5085,13 +5085,6 @@ int brcms_c_up(struct brcms_c_info *wlc)
return 0;
}
static uint brcms_c_down_del_timer(struct brcms_c_info *wlc)
{
uint callbacks = 0;
return callbacks;
}
static int brcms_b_bmac_down_prep(struct brcms_hardware *wlc_hw)
{
bool dev_gone;
@ -5201,8 +5194,6 @@ uint brcms_c_down(struct brcms_c_info *wlc)
callbacks++;
wlc->WDarmed = false;
}
/* cancel all other timers */
callbacks += brcms_c_down_del_timer(wlc);
wlc->pub->up = false;

View File

@ -357,61 +357,6 @@ u16 rxiq_cal_rf_reg[11] = {
RADIO_2064_REG12A,
};
static const
struct lcnphy_rx_iqcomp lcnphy_rx_iqcomp_table_rev0[] = {
{1, 0, 0},
{2, 0, 0},
{3, 0, 0},
{4, 0, 0},
{5, 0, 0},
{6, 0, 0},
{7, 0, 0},
{8, 0, 0},
{9, 0, 0},
{10, 0, 0},
{11, 0, 0},
{12, 0, 0},
{13, 0, 0},
{14, 0, 0},
{34, 0, 0},
{38, 0, 0},
{42, 0, 0},
{46, 0, 0},
{36, 0, 0},
{40, 0, 0},
{44, 0, 0},
{48, 0, 0},
{52, 0, 0},
{56, 0, 0},
{60, 0, 0},
{64, 0, 0},
{100, 0, 0},
{104, 0, 0},
{108, 0, 0},
{112, 0, 0},
{116, 0, 0},
{120, 0, 0},
{124, 0, 0},
{128, 0, 0},
{132, 0, 0},
{136, 0, 0},
{140, 0, 0},
{149, 0, 0},
{153, 0, 0},
{157, 0, 0},
{161, 0, 0},
{165, 0, 0},
{184, 0, 0},
{188, 0, 0},
{192, 0, 0},
{196, 0, 0},
{200, 0, 0},
{204, 0, 0},
{208, 0, 0},
{212, 0, 0},
{216, 0, 0},
};
static const u32 lcnphy_23bitgaincode_table[] = {
0x200100,
0x200200,

View File

@ -105,105 +105,6 @@ static const u32 dot11lcn_gain_tbl_rev0[] = {
0x00000000,
};
static const u32 dot11lcn_gain_tbl_rev1[] = {
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000008,
0x00000004,
0x00000008,
0x00000001,
0x00000005,
0x00000009,
0x0000000D,
0x00000011,
0x00000051,
0x00000091,
0x00000011,
0x00000051,
0x00000091,
0x000000d1,
0x00000053,
0x00000093,
0x000000d3,
0x000000d7,
0x00000117,
0x00000517,
0x00000917,
0x00000957,
0x00000d57,
0x00001157,
0x00001197,
0x00005197,
0x00009197,
0x0000d197,
0x00011197,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000008,
0x00000004,
0x00000008,
0x00000001,
0x00000005,
0x00000009,
0x0000000D,
0x00000011,
0x00000051,
0x00000091,
0x00000011,
0x00000051,
0x00000091,
0x000000d1,
0x00000053,
0x00000093,
0x000000d3,
0x000000d7,
0x00000117,
0x00000517,
0x00000917,
0x00000957,
0x00000d57,
0x00001157,
0x00005157,
0x00009157,
0x0000d157,
0x00011157,
0x00015157,
0x00019157,
0x0001d157,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
};
static const u16 dot11lcn_aux_gain_idx_tbl_rev0[] = {
0x0401,
0x0402,

View File

@ -2430,8 +2430,8 @@ void stop_airo_card(struct net_device *dev, int freeres)
iounmap(ai->pcimem);
if (ai->pciaux)
iounmap(ai->pciaux);
pci_free_consistent(ai->pci, PCI_SHARED_LEN,
ai->shared, ai->shared_dma);
dma_free_coherent(&ai->pci->dev, PCI_SHARED_LEN,
ai->shared, ai->shared_dma);
}
}
crypto_free_sync_skcipher(ai->tfm);
@ -2581,9 +2581,10 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci)
}
/* Reserve PKTSIZE for each fid and 2K for the Rids */
ai->shared = pci_alloc_consistent(pci, PCI_SHARED_LEN, &ai->shared_dma);
ai->shared = dma_alloc_coherent(&pci->dev, PCI_SHARED_LEN,
&ai->shared_dma, GFP_KERNEL);
if (!ai->shared) {
airo_print_err("", "Couldn't alloc_consistent %d",
airo_print_err("", "Couldn't alloc_coherent %d",
PCI_SHARED_LEN);
goto free_auxmap;
}
@ -2643,7 +2644,8 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci)
return 0;
free_shared:
pci_free_consistent(pci, PCI_SHARED_LEN, ai->shared, ai->shared_dma);
dma_free_coherent(&pci->dev, PCI_SHARED_LEN, ai->shared,
ai->shared_dma);
free_auxmap:
iounmap(ai->pciaux);
free_memmap:
@ -2930,7 +2932,8 @@ err_out_reg:
unregister_netdev(dev);
err_out_map:
if (test_bit(FLAG_MPI,&ai->flags) && pci) {
pci_free_consistent(pci, PCI_SHARED_LEN, ai->shared, ai->shared_dma);
dma_free_coherent(&pci->dev, PCI_SHARED_LEN, ai->shared,
ai->shared_dma);
iounmap(ai->pciaux);
iounmap(ai->pcimem);
mpi_unmap_card(ai->pci);

View File

@ -31,15 +31,14 @@ int mt76_queues_read(struct seq_file *s, void *data)
int i;
for (i = 0; i < ARRAY_SIZE(dev->q_tx); i++) {
struct mt76_sw_queue *q = &dev->q_tx[i];
struct mt76_queue *q = dev->q_tx[i];
if (!q->q)
if (!q)
continue;
seq_printf(s,
"%d: queued=%d head=%d tail=%d swq_queued=%d\n",
i, q->q->queued, q->q->head, q->q->tail,
q->swq_queued);
"%d: queued=%d head=%d tail=%d\n",
i, q->queued, q->head, q->tail);
}
return 0;

View File

@ -7,6 +7,76 @@
#include "mt76.h"
#include "dma.h"
static struct mt76_txwi_cache *
mt76_alloc_txwi(struct mt76_dev *dev)
{
struct mt76_txwi_cache *t;
dma_addr_t addr;
u8 *txwi;
int size;
size = L1_CACHE_ALIGN(dev->drv->txwi_size + sizeof(*t));
txwi = devm_kzalloc(dev->dev, size, GFP_ATOMIC);
if (!txwi)
return NULL;
addr = dma_map_single(dev->dev, txwi, dev->drv->txwi_size,
DMA_TO_DEVICE);
t = (struct mt76_txwi_cache *)(txwi + dev->drv->txwi_size);
t->dma_addr = addr;
return t;
}
static struct mt76_txwi_cache *
__mt76_get_txwi(struct mt76_dev *dev)
{
struct mt76_txwi_cache *t = NULL;
spin_lock(&dev->lock);
if (!list_empty(&dev->txwi_cache)) {
t = list_first_entry(&dev->txwi_cache, struct mt76_txwi_cache,
list);
list_del(&t->list);
}
spin_unlock(&dev->lock);
return t;
}
static struct mt76_txwi_cache *
mt76_get_txwi(struct mt76_dev *dev)
{
struct mt76_txwi_cache *t = __mt76_get_txwi(dev);
if (t)
return t;
return mt76_alloc_txwi(dev);
}
void
mt76_put_txwi(struct mt76_dev *dev, struct mt76_txwi_cache *t)
{
if (!t)
return;
spin_lock(&dev->lock);
list_add(&t->list, &dev->txwi_cache);
spin_unlock(&dev->lock);
}
EXPORT_SYMBOL_GPL(mt76_put_txwi);
static void
mt76_free_pending_txwi(struct mt76_dev *dev)
{
struct mt76_txwi_cache *t;
while ((t = __mt76_get_txwi(dev)) != NULL)
dma_unmap_single(dev->dev, t->dma_addr, dev->drv->txwi_size,
DMA_TO_DEVICE);
}
static int
mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
int idx, int n_desc, int bufsize,
@ -49,6 +119,7 @@ mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
struct mt76_queue_buf *buf, int nbufs, u32 info,
struct sk_buff *skb, void *txwi)
{
struct mt76_queue_entry *entry;
struct mt76_desc *desc;
u32 ctrl;
int i, idx = -1;
@ -61,10 +132,27 @@ mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
for (i = 0; i < nbufs; i += 2, buf += 2) {
u32 buf0 = buf[0].addr, buf1 = 0;
idx = q->head;
q->head = (q->head + 1) % q->ndesc;
desc = &q->desc[idx];
entry = &q->entry[idx];
if (buf[0].skip_unmap)
entry->skip_buf0 = true;
entry->skip_buf1 = i == nbufs - 1;
entry->dma_addr[0] = buf[0].addr;
entry->dma_len[0] = buf[0].len;
ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len);
if (i < nbufs - 1) {
entry->dma_addr[1] = buf[1].addr;
entry->dma_len[1] = buf[1].len;
buf1 = buf[1].addr;
ctrl |= FIELD_PREP(MT_DMA_CTL_SD_LEN1, buf[1].len);
if (buf[1].skip_unmap)
entry->skip_buf1 = true;
}
if (i == nbufs - 1)
@ -72,11 +160,6 @@ mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
else if (i == nbufs - 2)
ctrl |= MT_DMA_CTL_LAST_SEC1;
idx = q->head;
q->head = (q->head + 1) % q->ndesc;
desc = &q->desc[idx];
WRITE_ONCE(desc->buf0, cpu_to_le32(buf0));
WRITE_ONCE(desc->buf1, cpu_to_le32(buf1));
WRITE_ONCE(desc->info, cpu_to_le32(info));
@ -96,24 +179,14 @@ mt76_dma_tx_cleanup_idx(struct mt76_dev *dev, struct mt76_queue *q, int idx,
struct mt76_queue_entry *prev_e)
{
struct mt76_queue_entry *e = &q->entry[idx];
__le32 __ctrl = READ_ONCE(q->desc[idx].ctrl);
u32 ctrl = le32_to_cpu(__ctrl);
if (!e->skip_buf0) {
__le32 addr = READ_ONCE(q->desc[idx].buf0);
u32 len = FIELD_GET(MT_DMA_CTL_SD_LEN0, ctrl);
dma_unmap_single(dev->dev, le32_to_cpu(addr), len,
if (!e->skip_buf0)
dma_unmap_single(dev->dev, e->dma_addr[0], e->dma_len[0],
DMA_TO_DEVICE);
}
if (!(ctrl & MT_DMA_CTL_LAST_SEC0)) {
__le32 addr = READ_ONCE(q->desc[idx].buf1);
u32 len = FIELD_GET(MT_DMA_CTL_SD_LEN1, ctrl);
dma_unmap_single(dev->dev, le32_to_cpu(addr), len,
if (!e->skip_buf1)
dma_unmap_single(dev->dev, e->dma_addr[1], e->dma_len[1],
DMA_TO_DEVICE);
}
if (e->txwi == DMA_DUMMY_DATA)
e->txwi = NULL;
@ -137,19 +210,17 @@ mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
static void
mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q)
{
wmb();
writel(q->head, &q->regs->cpu_idx);
}
static void
mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush)
{
struct mt76_sw_queue *sq = &dev->q_tx[qid];
struct mt76_queue *q = sq->q;
struct mt76_queue *q = dev->q_tx[qid];
struct mt76_queue_entry entry;
unsigned int n_swq_queued[8] = {};
unsigned int n_queued = 0;
bool wake = false;
int i, last;
int last;
if (!q)
return;
@ -159,16 +230,9 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush)
else
last = readl(&q->regs->dma_idx);
while ((q->queued > n_queued) && q->tail != last) {
while (q->queued > 0 && q->tail != last) {
mt76_dma_tx_cleanup_idx(dev, q, q->tail, &entry);
if (entry.schedule)
n_swq_queued[entry.qid]++;
q->tail = (q->tail + 1) % q->ndesc;
n_queued++;
if (entry.skb)
dev->drv->tx_complete_skb(dev, qid, &entry);
mt76_queue_tx_complete(dev, q, &entry);
if (entry.txwi) {
if (!(dev->drv->drv_flags & MT_DRV_TXWI_NO_FREE))
@ -178,29 +242,14 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush)
if (!flush && q->tail == last)
last = readl(&q->regs->dma_idx);
}
spin_lock_bh(&q->lock);
q->queued -= n_queued;
for (i = 0; i < 4; i++) {
if (!n_swq_queued[i])
continue;
dev->q_tx[i].swq_queued -= n_swq_queued[i];
}
/* ext PHY */
for (i = 0; i < 4; i++) {
if (!n_swq_queued[i])
continue;
dev->q_tx[__MT_TXQ_MAX + i].swq_queued -= n_swq_queued[4 + i];
}
if (flush) {
spin_lock_bh(&q->lock);
mt76_dma_sync_idx(dev, q);
mt76_dma_kick_queue(dev, q);
spin_unlock_bh(&q->lock);
}
wake = wake && q->stopped &&
@ -211,8 +260,6 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush)
if (!q->queued)
wake_up(&dev->tx_wait);
spin_unlock_bh(&q->lock);
if (wake)
ieee80211_wake_queue(dev->hw, qid);
}
@ -227,7 +274,7 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
void *buf = e->buf;
int buf_len = SKB_WITH_OVERHEAD(q->buf_size);
buf_addr = le32_to_cpu(READ_ONCE(desc->buf0));
buf_addr = e->dma_addr[0];
if (len) {
u32 ctl = le32_to_cpu(READ_ONCE(desc->ctrl));
*len = FIELD_GET(MT_DMA_CTL_SD_LEN0, ctl);
@ -268,7 +315,7 @@ static int
mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid,
struct sk_buff *skb, u32 tx_info)
{
struct mt76_queue *q = dev->q_tx[qid].q;
struct mt76_queue *q = dev->q_tx[qid];
struct mt76_queue_buf buf;
dma_addr_t addr;
@ -300,7 +347,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid,
struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_sta *sta)
{
struct mt76_queue *q = dev->q_tx[qid].q;
struct mt76_queue *q = dev->q_tx[qid];
struct mt76_tx_info tx_info = {
.skb = skb,
};
@ -378,7 +425,7 @@ free:
e.skb = tx_info.skb;
e.txwi = t;
dev->drv->tx_complete_skb(dev, qid, &e);
dev->drv->tx_complete_skb(dev, &e);
mt76_put_txwi(dev, t);
return ret;
}
@ -612,6 +659,7 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
{
int i;
mt76_worker_disable(&dev->tx_worker);
netif_napi_del(&dev->tx_napi);
for (i = 0; i < ARRAY_SIZE(dev->q_tx); i++)
mt76_dma_tx_cleanup(dev, i, true);
@ -620,5 +668,7 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
netif_napi_del(&dev->napi[i]);
mt76_dma_rx_cleanup(dev, &dev->q_rx[i]);
}
mt76_free_pending_txwi(dev);
}
EXPORT_SYMBOL_GPL(mt76_dma_cleanup);

View File

@ -2,6 +2,7 @@
/*
* Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
*/
#include <linux/sched.h>
#include <linux/of.h>
#include "mt76.h"
@ -304,11 +305,11 @@ mt76_phy_init(struct mt76_dev *dev, struct ieee80211_hw *hw)
ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS);
ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU);
ieee80211_hw_set(hw, TX_AMSDU);
/* TODO: avoid linearization for SDIO */
if (!mt76_is_sdio(dev))
if (!(dev->drv->drv_flags & MT_DRV_AMSDU_OFFLOAD)) {
ieee80211_hw_set(hw, TX_AMSDU);
ieee80211_hw_set(hw, TX_FRAG_LIST);
}
ieee80211_hw_set(hw, MFP_CAPABLE);
ieee80211_hw_set(hw, AP_LINK_PS);
@ -433,14 +434,13 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
skb_queue_head_init(&dev->mcu.res_q);
init_waitqueue_head(&dev->mcu.wait);
mutex_init(&dev->mcu.mutex);
dev->tx_worker.fn = mt76_tx_worker;
INIT_LIST_HEAD(&dev->txwi_cache);
for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++)
skb_queue_head_init(&dev->rx_skb[i]);
tasklet_init(&dev->tx_tasklet, mt76_tx_tasklet, (unsigned long)dev);
dev->wq = alloc_ordered_workqueue("mt76", 0);
if (!dev->wq) {
ieee80211_free_hw(hw);
@ -483,7 +483,14 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
return ret;
}
return ieee80211_register_hw(hw);
ret = ieee80211_register_hw(hw);
if (ret)
return ret;
WARN_ON(mt76_worker_setup(hw, &dev->tx_worker, NULL, "tx"));
sched_set_fifo_low(dev->tx_worker.task);
return 0;
}
EXPORT_SYMBOL_GPL(mt76_register_device);
@ -500,12 +507,11 @@ EXPORT_SYMBOL_GPL(mt76_unregister_device);
void mt76_free_device(struct mt76_dev *dev)
{
mt76_worker_teardown(&dev->tx_worker);
if (dev->wq) {
destroy_workqueue(dev->wq);
dev->wq = NULL;
}
if (mt76_is_mmio(dev))
mt76_tx_free(dev);
ieee80211_free_hw(dev->hw);
}
EXPORT_SYMBOL_GPL(mt76_free_device);
@ -540,7 +546,7 @@ bool mt76_has_tx_pending(struct mt76_phy *phy)
offset = __MT_TXQ_MAX * (phy != &dev->phy);
for (i = 0; i < __MT_TXQ_MAX; i++) {
q = dev->q_tx[offset + i].q;
q = dev->q_tx[offset + i];
if (q && q->queued)
return true;
}
@ -870,7 +876,6 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb)
struct ieee80211_hw *hw;
struct mt76_wcid *wcid = status->wcid;
bool ps;
int i;
hw = mt76_phy_hw(dev, status->ext_phy);
if (ieee80211_is_pspoll(hdr->frame_control) && !wcid) {
@ -920,20 +925,6 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb)
dev->drv->sta_ps(dev, sta, ps);
ieee80211_sta_ps_transition(sta, ps);
if (ps)
return;
for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
struct mt76_txq *mtxq;
if (!sta->txq[i])
continue;
mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv;
if (!skb_queue_empty(&mtxq->retry_q))
ieee80211_schedule_txq(hw, sta->txq[i]);
}
}
void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames,
@ -995,8 +986,6 @@ mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif,
mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv;
mtxq->wcid = wcid;
mt76_txq_init(dev, sta->txq[i]);
}
ewma_signal_init(&wcid->rssi);
@ -1024,8 +1013,6 @@ void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif,
dev->drv->sta_remove(dev, vif, sta);
mt76_tx_status_check(dev, wcid, true);
for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
mt76_txq_remove(dev, sta->txq[i]);
mt76_wcid_mask_clear(dev->wcid_mask, idx);
mt76_wcid_mask_clear(dev->wcid_phy_mask, idx);
}

View File

@ -17,11 +17,13 @@
#include "util.h"
#include "testmode.h"
#define MT_TX_RING_SIZE 256
#define MT_MCU_RING_SIZE 32
#define MT_RX_BUF_SIZE 2048
#define MT_SKB_HEAD_LEN 128
#define MT_MAX_NON_AQL_PKT 16
#define MT_TXQ_FREE_THR 32
struct mt76_dev;
struct mt76_phy;
struct mt76_wcid;
@ -79,7 +81,8 @@ enum mt76_rxq_id {
struct mt76_queue_buf {
dma_addr_t addr;
int len;
u16 len;
bool skip_unmap;
};
struct mt76_tx_info {
@ -99,9 +102,11 @@ struct mt76_queue_entry {
struct urb *urb;
int buf_sz;
};
enum mt76_txq_id qid;
u32 dma_addr[2];
u16 dma_len[2];
u16 wcid;
bool skip_buf0:1;
bool schedule:1;
bool skip_buf1:1;
bool done:1;
};
@ -135,13 +140,6 @@ struct mt76_queue {
struct page_frag_cache rx_page;
};
struct mt76_sw_queue {
struct mt76_queue *q;
struct list_head swq;
int swq_queued;
};
struct mt76_mcu_ops {
u32 headroom;
u32 tailroom;
@ -204,6 +202,7 @@ DECLARE_EWMA(signal, 10, 8);
struct mt76_wcid {
struct mt76_rx_tid __rcu *aggr[IEEE80211_NUM_TIDS];
atomic_t non_aql_packets;
unsigned long flags;
struct ewma_signal rssi;
@ -214,6 +213,7 @@ struct mt76_wcid {
u8 sta:1;
u8 ext_phy:1;
u8 amsdu:1;
u8 rx_check_pn;
u8 rx_key_pn[IEEE80211_NUM_TIDS][6];
@ -226,11 +226,8 @@ struct mt76_wcid {
};
struct mt76_txq {
struct mt76_sw_queue *swq;
struct mt76_wcid *wcid;
struct sk_buff_head retry_q;
u16 agg_ssn;
bool send_bar;
bool aggr;
@ -309,6 +306,7 @@ struct mt76_hw_cap {
#define MT_DRV_SW_RX_AIRTIME BIT(2)
#define MT_DRV_RX_DMA_HDR BIT(3)
#define MT_DRV_HW_MGMT_TXQ BIT(4)
#define MT_DRV_AMSDU_OFFLOAD BIT(5)
struct mt76_driver_ops {
u32 drv_flags;
@ -322,7 +320,7 @@ struct mt76_driver_ops {
struct ieee80211_sta *sta,
struct mt76_tx_info *tx_info);
void (*tx_complete_skb)(struct mt76_dev *dev, enum mt76_txq_id qid,
void (*tx_complete_skb)(struct mt76_dev *dev,
struct mt76_queue_entry *e);
bool (*tx_status_data)(struct mt76_dev *dev, u8 *update);
@ -445,14 +443,24 @@ struct mt76_usb {
} mcu;
};
#define MT76S_XMIT_BUF_SZ (16 * PAGE_SIZE)
struct mt76_sdio {
struct task_struct *tx_kthread;
struct task_struct *kthread;
struct workqueue_struct *txrx_wq;
struct {
struct work_struct xmit_work;
struct work_struct status_work;
} tx;
struct {
struct work_struct recv_work;
struct work_struct net_work;
} rx;
struct work_struct stat_work;
unsigned long state;
u8 *xmit_buf[MT_TXQ_MCU_WA];
struct sdio_func *func;
void *intr_data;
struct {
struct mutex lock;
@ -593,12 +601,12 @@ struct mt76_dev {
struct sk_buff_head rx_skb[__MT_RXQ_MAX];
struct list_head txwi_cache;
struct mt76_sw_queue q_tx[2 * __MT_TXQ_MAX];
struct mt76_queue *q_tx[2 * __MT_TXQ_MAX];
struct mt76_queue q_rx[__MT_RXQ_MAX];
const struct mt76_queue_ops *queue_ops;
int tx_dma_idx[4];
struct tasklet_struct tx_tasklet;
struct mt76_worker tx_worker;
struct napi_struct tx_napi;
struct delayed_work mac_work;
@ -892,14 +900,13 @@ static inline bool mt76_testmode_enabled(struct mt76_dev *dev)
void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb);
void mt76_tx(struct mt76_phy *dev, struct ieee80211_sta *sta,
struct mt76_wcid *wcid, struct sk_buff *skb);
void mt76_txq_init(struct mt76_dev *dev, struct ieee80211_txq *txq);
void mt76_txq_remove(struct mt76_dev *dev, struct ieee80211_txq *txq);
void mt76_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
void mt76_stop_tx_queues(struct mt76_dev *dev, struct ieee80211_sta *sta,
bool send_bar);
void mt76_tx_check_agg_ssn(struct ieee80211_sta *sta, struct sk_buff *skb);
void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid);
void mt76_txq_schedule_all(struct mt76_phy *phy);
void mt76_tx_tasklet(unsigned long data);
void mt76_tx_worker(struct mt76_worker *w);
void mt76_release_buffered_frames(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
u16 tids, int nframes,
@ -932,7 +939,7 @@ struct sk_buff *mt76_tx_status_skb_get(struct mt76_dev *dev,
struct sk_buff_head *list);
void mt76_tx_status_skb_done(struct mt76_dev *dev, struct sk_buff *skb,
struct sk_buff_head *list);
void mt76_tx_complete_skb(struct mt76_dev *dev, struct sk_buff *skb);
void mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid, struct sk_buff *skb);
void mt76_tx_status_check(struct mt76_dev *dev, struct mt76_wcid *wcid,
bool flush);
int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
@ -996,8 +1003,6 @@ mt76_tx_status_get_hw(struct mt76_dev *dev, struct sk_buff *skb)
return hw;
}
void mt76_tx_free(struct mt76_dev *dev);
struct mt76_txwi_cache *mt76_get_txwi(struct mt76_dev *dev);
void mt76_put_txwi(struct mt76_dev *dev, struct mt76_txwi_cache *t);
void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames,
struct napi_struct *napi);
@ -1005,6 +1010,8 @@ void mt76_rx_poll_complete(struct mt76_dev *dev, enum mt76_rxq_id q,
struct napi_struct *napi);
void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames);
void mt76_testmode_tx_pending(struct mt76_dev *dev);
void mt76_queue_tx_complete(struct mt76_dev *dev, struct mt76_queue *q,
struct mt76_queue_entry *e);
/* usb */
static inline bool mt76u_urb_error(struct urb *urb)
@ -1039,7 +1046,7 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len,
return usb_bulk_msg(udev, pipe, data, len, actual_len, timeout);
}
int mt76_skb_adjust_pad(struct sk_buff *skb);
int mt76_skb_adjust_pad(struct sk_buff *skb, int pad);
int mt76u_vendor_request(struct mt76_dev *dev, u8 req,
u8 req_type, u16 val, u16 offset,
void *buf, size_t len);

View File

@ -29,7 +29,7 @@ mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY |
FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, mvif->sta.wcid.idx) |
FIELD_PREP(MT_DMA_FQCR0_TARGET_QID,
dev->mt76.q_tx[MT_TXQ_CAB].q->hw_idx) |
dev->mt76.q_tx[MT_TXQ_CAB]->hw_idx) |
FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, 3) |
FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, 8));
@ -78,7 +78,7 @@ void mt7603_pre_tbtt_tasklet(unsigned long arg)
data.dev = dev;
__skb_queue_head_init(&data.q);
q = dev->mt76.q_tx[MT_TXQ_BEACON].q;
q = dev->mt76.q_tx[MT_TXQ_BEACON];
spin_lock_bh(&q->lock);
ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
IEEE80211_IFACE_ITER_RESUME_ALL,
@ -95,7 +95,7 @@ void mt7603_pre_tbtt_tasklet(unsigned long arg)
if (dev->mt76.csa_complete)
goto out;
q = dev->mt76.q_tx[MT_TXQ_CAB].q;
q = dev->mt76.q_tx[MT_TXQ_CAB];
do {
nframes = skb_queue_len(&data.q);
ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
@ -136,7 +136,7 @@ void mt7603_pre_tbtt_tasklet(unsigned long arg)
out:
mt76_queue_tx_cleanup(dev, MT_TXQ_BEACON, false);
if (dev->mt76.q_tx[MT_TXQ_BEACON].q->queued >
if (dev->mt76.q_tx[MT_TXQ_BEACON]->queued >
hweight8(dev->mt76.beacon_mask))
dev->beacon_check++;
}

View File

@ -70,7 +70,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_edcca, mt7603_edcca_get,
mt7603_edcca_set, "%lld\n");
static int
mt7603_ampdu_stat_read(struct seq_file *file, void *data)
mt7603_ampdu_stat_show(struct seq_file *file, void *data)
{
struct mt7603_dev *dev = file->private;
int bound[3], i, range;
@ -91,18 +91,7 @@ mt7603_ampdu_stat_read(struct seq_file *file, void *data)
return 0;
}
static int
mt7603_ampdu_stat_open(struct inode *inode, struct file *f)
{
return single_open(f, mt7603_ampdu_stat_read, inode->i_private);
}
static const struct file_operations fops_ampdu_stat = {
.open = mt7603_ampdu_stat_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(mt7603_ampdu_stat);
void mt7603_init_debugfs(struct mt7603_dev *dev)
{
@ -112,7 +101,8 @@ void mt7603_init_debugfs(struct mt7603_dev *dev)
if (!dir)
return;
debugfs_create_file("ampdu_stat", 0400, dir, dev, &fops_ampdu_stat);
debugfs_create_file("ampdu_stat", 0400, dir, dev,
&mt7603_ampdu_stat_fops);
debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", dir,
mt76_queues_read);
debugfs_create_file("edcca", 0600, dir, dev, &fops_edcca);

View File

@ -5,8 +5,7 @@
#include "../dma.h"
static int
mt7603_init_tx_queue(struct mt7603_dev *dev, struct mt76_sw_queue *q,
int idx, int n_desc)
mt7603_init_tx_queue(struct mt7603_dev *dev, int qid, int idx, int n_desc)
{
struct mt76_queue *hwq;
int err;
@ -19,8 +18,7 @@ mt7603_init_tx_queue(struct mt7603_dev *dev, struct mt76_sw_queue *q,
if (err < 0)
return err;
INIT_LIST_HEAD(&q->swq);
q->q = hwq;
dev->mt76.q_tx[qid] = hwq;
mt7603_irq_enable(dev, MT_INT_TX_DONE(idx));
@ -123,7 +121,7 @@ void mt7603_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
mt76_rx(&dev->mt76, q, skb);
return;
}
/* fall through */
fallthrough;
default:
dev_kfree_skb(skb);
break;
@ -165,7 +163,7 @@ static int mt7603_poll_tx(struct napi_struct *napi, int budget)
mt7603_mac_sta_poll(dev);
tasklet_schedule(&dev->mt76.tx_tasklet);
mt76_worker_schedule(&dev->mt76.tx_worker);
return 0;
}
@ -193,29 +191,28 @@ int mt7603_dma_init(struct mt7603_dev *dev)
mt7603_pse_client_reset(dev);
for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) {
ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[i],
wmm_queue_map[i],
MT_TX_RING_SIZE);
ret = mt7603_init_tx_queue(dev, i, wmm_queue_map[i],
MT7603_TX_RING_SIZE);
if (ret)
return ret;
}
ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_PSD],
MT_TX_HW_QUEUE_MGMT, MT_TX_RING_SIZE);
ret = mt7603_init_tx_queue(dev, MT_TXQ_PSD,
MT_TX_HW_QUEUE_MGMT, MT7603_PSD_RING_SIZE);
if (ret)
return ret;
ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU],
ret = mt7603_init_tx_queue(dev, MT_TXQ_MCU,
MT_TX_HW_QUEUE_MCU, MT_MCU_RING_SIZE);
if (ret)
return ret;
ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_BEACON],
ret = mt7603_init_tx_queue(dev, MT_TXQ_BEACON,
MT_TX_HW_QUEUE_BCN, MT_MCU_RING_SIZE);
if (ret)
return ret;
ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_CAB],
ret = mt7603_init_tx_queue(dev, MT_TXQ_CAB,
MT_TX_HW_QUEUE_BMC, MT_MCU_RING_SIZE);
if (ret)
return ret;
@ -249,6 +246,5 @@ void mt7603_dma_cleanup(struct mt7603_dev *dev)
MT_WPDMA_GLO_CFG_RX_DMA_EN |
MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);
tasklet_kill(&dev->mt76.tx_tasklet);
mt76_dma_cleanup(&dev->mt76);
}

View File

@ -147,8 +147,14 @@ static int mt7603_check_eeprom(struct mt76_dev *dev)
}
}
static inline bool is_mt7688(struct mt7603_dev *dev)
{
return mt76_rr(dev, MT_EFUSE_BASE + 0x64) & BIT(4);
}
int mt7603_eeprom_init(struct mt7603_dev *dev)
{
u8 *eeprom;
int ret;
ret = mt7603_eeprom_load(dev);
@ -163,9 +169,16 @@ int mt7603_eeprom_init(struct mt7603_dev *dev)
MT7603_EEPROM_SIZE);
}
eeprom = (u8 *)dev->mt76.eeprom.data;
dev->mt76.cap.has_2ghz = true;
memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
ETH_ALEN);
memcpy(dev->mt76.macaddr, eeprom + MT_EE_MAC_ADDR, ETH_ALEN);
/* Check for 1SS devices */
dev->mphy.antenna_mask = 3;
if (FIELD_GET(MT_EE_NIC_CONF_0_RX_PATH, eeprom[MT_EE_NIC_CONF_0]) == 1 ||
FIELD_GET(MT_EE_NIC_CONF_0_TX_PATH, eeprom[MT_EE_NIC_CONF_0]) == 1 ||
is_mt7688(dev))
dev->mphy.antenna_mask = 1;
mt76_eeprom_override(&dev->mt76);

View File

@ -85,4 +85,7 @@ enum mt7603_eeprom_source {
MT_EE_SRC_FLASH,
};
#define MT_EE_NIC_CONF_0_RX_PATH GENMASK(3, 0)
#define MT_EE_NIC_CONF_0_TX_PATH GENMASK(7, 4)
#endif

View File

@ -536,11 +536,6 @@ int mt7603_register_device(struct mt7603_dev *dev)
tasklet_init(&dev->mt76.pre_tbtt_tasklet, mt7603_pre_tbtt_tasklet,
(unsigned long)dev);
/* Check for 7688, which only has 1SS */
dev->mphy.antenna_mask = 3;
if (mt76_rr(dev, MT_EFUSE_BASE + 0x64) & BIT(4))
dev->mphy.antenna_mask = 1;
dev->slottime = 9;
dev->sensitivity_limit = 28;
dev->dynamic_sensitivity = true;

View File

@ -445,7 +445,7 @@ void mt7603_mac_sta_poll(struct mt7603_dev *dev)
sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
for (i = 0; i < 4; i++) {
struct mt76_queue *q = dev->mt76.q_tx[i].q;
struct mt76_queue *q = dev->mt76.q_tx[i];
u8 qidx = q->hw_idx;
u8 tid = ac_to_tid[i];
u32 txtime = airtime[qidx];
@ -592,7 +592,7 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb)
switch (FIELD_GET(MT_RXV1_TX_MODE, rxdg0)) {
case MT_PHY_TYPE_CCK:
cck = true;
/* fall through */
fallthrough;
case MT_PHY_TYPE_OFDM:
i = mt76_get_rate(&dev->mt76, sband, i, cck);
break;
@ -896,7 +896,7 @@ mt7603_mac_write_txwi(struct mt7603_dev *dev, __le32 *txwi,
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data;
struct ieee80211_vif *vif = info->control.vif;
struct mt76_queue *q = dev->mt76.q_tx[qid].q;
struct mt76_queue *q = dev->mt76.q_tx[qid];
struct mt7603_vif *mvif;
int wlan_idx;
int hdr_len = ieee80211_get_hdrlen_from_skb(skb);
@ -1036,6 +1036,8 @@ int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
IEEE80211_TX_CTL_CLEAR_PS_FILT)) ||
(info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE))
mt7603_wtbl_set_ps(dev, msta, false);
mt76_tx_check_agg_ssn(sta, tx_info->skb);
}
pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
@ -1161,7 +1163,7 @@ out:
switch (FIELD_GET(MT_TX_RATE_MODE, final_rate)) {
case MT_PHY_TYPE_CCK:
cck = true;
/* fall through */
fallthrough;
case MT_PHY_TYPE_OFDM:
if (dev->mphy.chandef.chan->band == NL80211_BAND_5GHZ)
sband = &dev->mphy.sband_5g.sband;
@ -1269,8 +1271,7 @@ out:
rcu_read_unlock();
}
void mt7603_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid,
struct mt76_queue_entry *e)
void mt7603_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
{
struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
struct sk_buff *skb = e->skb;
@ -1280,10 +1281,8 @@ void mt7603_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid,
return;
}
if (qid < 4)
dev->tx_hang_check = 0;
mt76_tx_complete_skb(mdev, skb);
dev->tx_hang_check = 0;
mt76_tx_complete_skb(mdev, e->wcid, skb);
}
static bool
@ -1403,7 +1402,7 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev)
/* lock/unlock all queues to ensure that no tx is pending */
mt76_txq_schedule_all(&dev->mphy);
tasklet_disable(&dev->mt76.tx_tasklet);
mt76_worker_disable(&dev->mt76.tx_worker);
tasklet_disable(&dev->mt76.pre_tbtt_tasklet);
napi_disable(&dev->mt76.napi[0]);
napi_disable(&dev->mt76.napi[1]);
@ -1452,7 +1451,7 @@ skip_dma_reset:
clear_bit(MT76_RESET, &dev->mphy.state);
mutex_unlock(&dev->mt76.mutex);
tasklet_enable(&dev->mt76.tx_tasklet);
mt76_worker_enable(&dev->mt76.tx_worker);
napi_enable(&dev->mt76.tx_napi);
napi_schedule(&dev->mt76.tx_napi);
@ -1515,7 +1514,7 @@ static bool mt7603_tx_hang(struct mt7603_dev *dev)
int i;
for (i = 0; i < 4; i++) {
q = dev->mt76.q_tx[i].q;
q = dev->mt76.q_tx[i];
if (!q->queued)
continue;

View File

@ -75,7 +75,6 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
mtxq->wcid = &mvif->sta.wcid;
mt76_txq_init(&dev->mt76, vif->txq);
rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
out:
@ -99,7 +98,6 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
mt7603_beacon_set_timer(dev, mvif->idx, 0);
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
mt76_txq_remove(&dev->mt76, vif->txq);
spin_lock_bh(&dev->sta_poll_lock);
if (!list_empty(&msta->poll_list))
@ -514,7 +512,7 @@ mt7603_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
u16 cw_max = (1 << 10) - 1;
u32 val;
queue = dev->mt76.q_tx[queue].q->hw_idx;
queue = dev->mt76.q_tx[queue]->hw_idx;
if (params->cw_min)
cw_min = params->cw_min;

View File

@ -17,6 +17,8 @@
#define MT7603_MCU_RX_RING_SIZE 64
#define MT7603_RX_RING_SIZE 128
#define MT7603_TX_RING_SIZE 256
#define MT7603_PSD_RING_SIZE 128
#define MT7603_FIRMWARE_E1 "mt7603_e1.bin"
#define MT7603_FIRMWARE_E2 "mt7603_e2.bin"
@ -241,8 +243,7 @@ int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
struct ieee80211_sta *sta,
struct mt76_tx_info *tx_info);
void mt7603_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid,
struct mt76_queue_entry *e);
void mt7603_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
void mt7603_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb);

View File

@ -44,6 +44,8 @@ mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
(mt76_rr(dev, MT_HW_REV) & 0xff);
dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
mt76_wr(dev, MT_INT_MASK_CSR, 0);
ret = devm_request_irq(mdev->dev, pdev->irq, mt7603_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (ret)

View File

@ -35,6 +35,8 @@ mt76_wmac_probe(struct platform_device *pdev)
(mt76_rr(dev, MT_HW_REV) & 0xff);
dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
mt76_wr(dev, MT_INT_MASK_CSR, 0);
ret = devm_request_irq(mdev->dev, irq, mt7603_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (ret)

View File

@ -165,15 +165,14 @@ mt7615_reset_test_set(void *data, u64 val)
if (!mt7615_wait_for_mcu_init(dev))
return 0;
mt7615_mutex_acquire(dev);
skb = alloc_skb(1, GFP_KERNEL);
if (!skb)
return -ENOMEM;
skb_put(skb, 1);
mt76_tx_queue_skb_raw(dev, 0, skb, 0);
mt7615_mutex_acquire(dev);
mt76_tx_queue_skb_raw(dev, 0, skb, 0);
mt7615_mutex_release(dev);
return 0;
@ -221,7 +220,7 @@ mt7615_ampdu_stat_read_phy(struct mt7615_phy *phy,
}
static int
mt7615_ampdu_stat_read(struct seq_file *file, void *data)
mt7615_ampdu_stat_show(struct seq_file *file, void *data)
{
struct mt7615_dev *dev = file->private;
@ -235,18 +234,7 @@ mt7615_ampdu_stat_read(struct seq_file *file, void *data)
return 0;
}
static int
mt7615_ampdu_stat_open(struct inode *inode, struct file *f)
{
return single_open(f, mt7615_ampdu_stat_read, inode->i_private);
}
static const struct file_operations fops_ampdu_stat = {
.open = mt7615_ampdu_stat_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(mt7615_ampdu_stat);
static void
mt7615_radio_read_phy(struct mt7615_phy *phy, struct seq_file *s)
@ -340,15 +328,15 @@ mt7615_queues_read(struct seq_file *s, void *data)
int i;
for (i = 0; i < ARRAY_SIZE(queue_map); i++) {
struct mt76_sw_queue *q = &dev->mt76.q_tx[queue_map[i].id];
struct mt76_queue *q = dev->mt76.q_tx[queue_map[i].id];
if (!q->q)
if (!q)
continue;
seq_printf(s,
"%s: queued=%d head=%d tail=%d\n",
queue_map[i].queue, q->q->queued, q->q->head,
q->q->tail);
queue_map[i].queue, q->queued, q->head,
q->tail);
}
return 0;
@ -393,7 +381,7 @@ int mt7615_init_debugfs(struct mt7615_dev *dev)
mt76_queues_read);
debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir,
mt7615_queues_acq);
debugfs_create_file("ampdu_stat", 0400, dir, dev, &fops_ampdu_stat);
debugfs_create_file("ampdu_stat", 0400, dir, dev, &mt7615_ampdu_stat_fops);
debugfs_create_file("scs", 0600, dir, dev, &fops_scs);
debugfs_create_file("dbdc", 0600, dir, dev, &fops_dbdc);
debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug);

View File

@ -12,8 +12,7 @@
#include "mac.h"
static int
mt7615_init_tx_queue(struct mt7615_dev *dev, struct mt76_sw_queue *q,
int idx, int n_desc)
mt7615_init_tx_queue(struct mt7615_dev *dev, int qid, int idx, int n_desc)
{
struct mt76_queue *hwq;
int err;
@ -26,8 +25,7 @@ mt7615_init_tx_queue(struct mt7615_dev *dev, struct mt76_sw_queue *q,
if (err < 0)
return err;
INIT_LIST_HEAD(&q->swq);
q->q = hwq;
dev->mt76.q_tx[qid] = hwq;
return 0;
}
@ -45,19 +43,18 @@ mt7622_init_tx_queues_multi(struct mt7615_dev *dev)
int i;
for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) {
ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[i],
wmm_queue_map[i],
ret = mt7615_init_tx_queue(dev, i, wmm_queue_map[i],
MT7615_TX_RING_SIZE / 2);
if (ret)
return ret;
}
ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_PSD],
ret = mt7615_init_tx_queue(dev, MT_TXQ_PSD,
MT7622_TXQ_MGMT, MT7615_TX_MGMT_RING_SIZE);
if (ret)
return ret;
ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU],
ret = mt7615_init_tx_queue(dev, MT_TXQ_MCU,
MT7622_TXQ_MCU, MT7615_TX_MCU_RING_SIZE);
return ret;
}
@ -65,10 +62,9 @@ mt7622_init_tx_queues_multi(struct mt7615_dev *dev)
static int
mt7615_init_tx_queues(struct mt7615_dev *dev)
{
struct mt76_sw_queue *q;
int ret, i;
ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_FWDL],
ret = mt7615_init_tx_queue(dev, MT_TXQ_FWDL,
MT7615_TXQ_FWDL,
MT7615_TX_FWDL_RING_SIZE);
if (ret)
@ -77,52 +73,28 @@ mt7615_init_tx_queues(struct mt7615_dev *dev)
if (!is_mt7615(&dev->mt76))
return mt7622_init_tx_queues_multi(dev);
ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[0], 0,
MT7615_TX_RING_SIZE);
ret = mt7615_init_tx_queue(dev, 0, 0, MT7615_TX_RING_SIZE);
if (ret)
return ret;
for (i = 1; i < MT_TXQ_MCU; i++) {
q = &dev->mt76.q_tx[i];
INIT_LIST_HEAD(&q->swq);
q->q = dev->mt76.q_tx[0].q;
}
for (i = 1; i < MT_TXQ_MCU; i++)
dev->mt76.q_tx[i] = dev->mt76.q_tx[0];
ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU],
MT7615_TXQ_MCU,
ret = mt7615_init_tx_queue(dev, MT_TXQ_MCU, MT7615_TXQ_MCU,
MT7615_TX_MCU_RING_SIZE);
return 0;
}
static void
mt7615_tx_cleanup(struct mt7615_dev *dev)
{
int i;
mt76_queue_tx_cleanup(dev, MT_TXQ_MCU, false);
mt76_queue_tx_cleanup(dev, MT_TXQ_PSD, false);
if (is_mt7615(&dev->mt76)) {
mt76_queue_tx_cleanup(dev, MT_TXQ_BE, false);
} else {
for (i = 0; i < IEEE80211_NUM_ACS; i++)
mt76_queue_tx_cleanup(dev, i, false);
}
}
static int mt7615_poll_tx(struct napi_struct *napi, int budget)
{
struct mt7615_dev *dev;
dev = container_of(napi, struct mt7615_dev, mt76.tx_napi);
mt7615_tx_cleanup(dev);
mt76_queue_tx_cleanup(dev, MT_TXQ_MCU, false);
if (napi_complete_done(napi, 0))
mt7615_irq_enable(dev, MT_INT_TX_DONE_ALL);
mt7615_tx_cleanup(dev);
tasklet_schedule(&dev->mt76.tx_tasklet);
mt7615_irq_enable(dev, mt7615_tx_mcu_int_mask(dev));
return 0;
}
@ -306,7 +278,7 @@ int mt7615_dma_init(struct mt7615_dev *dev)
MT_WPDMA_GLO_CFG_RX_DMA_EN);
/* enable interrupts for TX/RX rings */
mt7615_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
mt7615_irq_enable(dev, MT_INT_RX_DONE_ALL | mt7615_tx_mcu_int_mask(dev) |
MT_INT_MCU_CMD);
if (is_mt7622(&dev->mt76))
@ -325,6 +297,5 @@ void mt7615_dma_cleanup(struct mt7615_dev *dev)
MT_WPDMA_GLO_CFG_RX_DMA_EN);
mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_SW_RESET);
tasklet_kill(&dev->mt76.tx_tasklet);
mt76_dma_cleanup(&dev->mt76);
}

View File

@ -125,6 +125,9 @@ mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev)
case MT_EE_2GHZ:
dev->mt76.cap.has_2ghz = true;
break;
case MT_EE_DBDC:
dev->dbdc_support = true;
/* fall through */
default:
dev->mt76.cap.has_2ghz = true;
dev->mt76.cap.has_5ghz = true;

View File

@ -217,6 +217,22 @@ static const struct ieee80211_iface_limit if_limits[] = {
}
};
static const struct ieee80211_iface_combination if_comb_radar[] = {
{
.limits = if_limits,
.n_limits = ARRAY_SIZE(if_limits),
.max_interfaces = 4,
.num_different_channels = 1,
.beacon_int_infra_match = true,
.radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
BIT(NL80211_CHAN_WIDTH_20) |
BIT(NL80211_CHAN_WIDTH_40) |
BIT(NL80211_CHAN_WIDTH_80) |
BIT(NL80211_CHAN_WIDTH_160) |
BIT(NL80211_CHAN_WIDTH_80P80),
}
};
static const struct ieee80211_iface_combination if_comb[] = {
{
.limits = if_limits,
@ -306,8 +322,13 @@ mt7615_init_wiphy(struct ieee80211_hw *hw)
hw->sta_data_size = sizeof(struct mt7615_sta);
hw->vif_data_size = sizeof(struct mt7615_vif);
wiphy->iface_combinations = if_comb;
wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
if (is_mt7663(&phy->dev->mt76)) {
wiphy->iface_combinations = if_comb;
wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
} else {
wiphy->iface_combinations = if_comb_radar;
wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_radar);
}
wiphy->reg_notifier = mt7615_regd_notifier;
wiphy->max_sched_scan_plan_interval = MT7615_MAX_SCHED_SCAN_INTERVAL;

View File

@ -378,7 +378,7 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
switch (FIELD_GET(MT_RXV1_TX_MODE, rxdg0)) {
case MT_PHY_TYPE_CCK:
cck = true;
/* fall through */
fallthrough;
case MT_PHY_TYPE_OFDM:
i = mt76_get_rate(&dev->mt76, sband, i, cck);
break;
@ -1271,7 +1271,7 @@ out:
switch (FIELD_GET(MT_TX_RATE_MODE, final_rate)) {
case MT_PHY_TYPE_CCK:
cck = true;
/* fall through */
fallthrough;
case MT_PHY_TYPE_OFDM:
mphy = &dev->mphy;
if (sta->wcid.ext_phy && dev->mt76.phy2)
@ -1400,6 +1400,9 @@ mt7615_mac_tx_free_token(struct mt7615_dev *dev, u16 token)
{
struct mt76_dev *mdev = &dev->mt76;
struct mt76_txwi_cache *txwi;
__le32 *txwi_data;
u32 val;
u8 wcid;
trace_mac_tx_free(dev, token);
@ -1410,9 +1413,13 @@ mt7615_mac_tx_free_token(struct mt7615_dev *dev, u16 token)
if (!txwi)
return;
txwi_data = (__le32 *)mt76_get_txwi_ptr(mdev, txwi);
val = le32_to_cpu(txwi_data[1]);
wcid = FIELD_GET(MT_TXD1_WLAN_IDX, val);
mt7615_txp_skb_unmap(mdev, txwi);
if (txwi->skb) {
mt76_tx_complete_skb(mdev, txwi->skb);
mt76_tx_complete_skb(mdev, wcid, txwi->skb);
txwi->skb = NULL;
}
@ -1424,6 +1431,14 @@ static void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb)
struct mt7615_tx_free *free = (struct mt7615_tx_free *)skb->data;
u8 i, count;
mt76_queue_tx_cleanup(dev, MT_TXQ_PSD, false);
if (is_mt7615(&dev->mt76)) {
mt76_queue_tx_cleanup(dev, MT_TXQ_BE, false);
} else {
for (i = 0; i < IEEE80211_NUM_ACS; i++)
mt76_queue_tx_cleanup(dev, i, false);
}
count = FIELD_GET(MT_TX_FREE_MSDU_ID_CNT, le16_to_cpu(free->ctrl));
if (is_mt7615(&dev->mt76)) {
__le16 *token = &free->token[0];
@ -1439,11 +1454,15 @@ static void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb)
dev_kfree_skb(skb);
if (test_bit(MT76_STATE_PM, &dev->phy.mt76->state))
return;
rcu_read_lock();
mt7615_mac_sta_poll(dev);
rcu_read_unlock();
tasklet_schedule(&dev->mt76.tx_tasklet);
mt7615_pm_power_save_sched(dev);
mt76_worker_schedule(&dev->mt76.tx_worker);
}
void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
@ -1478,7 +1497,7 @@ void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
mt76_rx(&dev->mt76, q, skb);
return;
}
/* fall through */
fallthrough;
default:
dev_kfree_skb(skb);
break;
@ -1845,7 +1864,7 @@ void mt7615_pm_wake_work(struct work_struct *work)
pm.wake_work);
mphy = dev->phy.mt76;
if (mt7615_driver_own(dev)) {
if (mt7615_mcu_set_drv_ctrl(dev)) {
dev_err(mphy->dev->dev, "failed to wake device\n");
goto out;
}
@ -1853,12 +1872,13 @@ void mt7615_pm_wake_work(struct work_struct *work)
spin_lock_bh(&dev->pm.txq_lock);
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
struct mt7615_sta *msta = dev->pm.tx_q[i].msta;
struct mt76_wcid *wcid = msta ? &msta->wcid : NULL;
struct ieee80211_sta *sta = NULL;
struct mt76_wcid *wcid;
if (!dev->pm.tx_q[i].skb)
continue;
wcid = msta ? &msta->wcid : &dev->mt76.global_wcid;
if (msta && wcid->sta)
sta = container_of((void *)msta, struct ieee80211_sta,
drv_priv);
@ -1868,7 +1888,7 @@ void mt7615_pm_wake_work(struct work_struct *work)
}
spin_unlock_bh(&dev->pm.txq_lock);
tasklet_schedule(&dev->mt76.tx_tasklet);
mt76_worker_schedule(&dev->mt76.tx_worker);
out:
ieee80211_wake_queues(mphy->hw);
@ -1943,7 +1963,7 @@ void mt7615_pm_power_save_work(struct work_struct *work)
goto out;
}
if (!mt7615_firmware_own(dev))
if (!mt7615_mcu_set_fw_ctrl(dev))
return;
out:
queue_delayed_work(dev->mt76.wq, &dev->pm.ps_work, delta);
@ -2110,7 +2130,7 @@ void mt7615_mac_reset_work(struct work_struct *work)
if (ext_phy)
mt76_txq_schedule_all(ext_phy);
tasklet_disable(&dev->mt76.tx_tasklet);
mt76_worker_disable(&dev->mt76.tx_worker);
napi_disable(&dev->mt76.napi[0]);
napi_disable(&dev->mt76.napi[1]);
napi_disable(&dev->mt76.tx_napi);
@ -2131,7 +2151,7 @@ void mt7615_mac_reset_work(struct work_struct *work)
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
clear_bit(MT76_RESET, &dev->mphy.state);
tasklet_enable(&dev->mt76.tx_tasklet);
mt76_worker_enable(&dev->mt76.tx_worker);
napi_enable(&dev->mt76.tx_napi);
napi_schedule(&dev->mt76.tx_napi);

View File

@ -205,7 +205,6 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
if (vif->txq) {
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
mtxq->wcid = &mvif->sta.wcid;
mt76_txq_init(&dev->mt76, vif->txq);
}
ret = mt7615_mcu_add_dev_info(dev, vif, true);
@ -256,8 +255,6 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw,
mt7615_mcu_add_dev_info(dev, vif, false);
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
if (vif->txq)
mt76_txq_remove(&dev->mt76, vif->txq);
dev->mphy.vif_mask &= ~BIT(mvif->idx);
dev->omac_mask &= ~BIT(mvif->omac_idx);
@ -361,7 +358,10 @@ mt7615_queue_key_update(struct mt7615_dev *dev, enum set_key_cmd cmd,
wd->key.keylen = key->keylen;
wd->key.cmd = cmd;
spin_lock_bh(&dev->mt76.lock);
list_add_tail(&wd->node, &dev->wd_head);
spin_unlock_bh(&dev->mt76.lock);
queue_work(dev->mt76.wq, &dev->wtbl_work);
return 0;
@ -703,7 +703,8 @@ mt7615_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
return;
}
tasklet_schedule(&dev->mt76.tx_tasklet);
dev->pm.last_activity = jiffies;
mt76_worker_schedule(&dev->mt76.tx_worker);
}
static void mt7615_tx(struct ieee80211_hw *hw,
@ -732,6 +733,7 @@ static void mt7615_tx(struct ieee80211_hw *hw,
}
if (!test_bit(MT76_STATE_PM, &mphy->state)) {
dev->pm.last_activity = jiffies;
mt76_tx(mphy, control->sta, wcid, skb);
return;
}
@ -813,7 +815,6 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
case IEEE80211_AMPDU_TX_START:
ssn = mt7615_mac_get_sta_tid_sn(dev, msta->wcid.idx, tid);
params->ssn = ssn;
mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(ssn);
ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
break;
case IEEE80211_AMPDU_TX_STOP_CONT:

View File

@ -324,6 +324,97 @@ int mt7615_rf_wr(struct mt7615_dev *dev, u32 wf, u32 reg, u32 val)
sizeof(req), false);
}
static void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en)
{
if (!is_mt7622(&dev->mt76))
return;
regmap_update_bits(dev->infracfg, MT_INFRACFG_MISC,
MT_INFRACFG_MISC_AP2CONN_WAKE,
!en * MT_INFRACFG_MISC_AP2CONN_WAKE);
}
static int mt7615_mcu_drv_pmctrl(struct mt7615_dev *dev)
{
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt76_dev *mdev = &dev->mt76;
u32 addr;
int err;
addr = is_mt7663(mdev) ? MT_PCIE_DOORBELL_PUSH : MT_CFG_LPCR_HOST;
mt76_wr(dev, addr, MT_CFG_LPCR_HOST_DRV_OWN);
mt7622_trigger_hif_int(dev, true);
addr = is_mt7663(mdev) ? MT_CONN_HIF_ON_LPCTL : MT_CFG_LPCR_HOST;
err = !mt76_poll_msec(dev, addr, MT_CFG_LPCR_HOST_FW_OWN, 0, 3000);
mt7622_trigger_hif_int(dev, false);
if (err) {
dev_err(mdev->dev, "driver own failed\n");
return -ETIMEDOUT;
}
clear_bit(MT76_STATE_PM, &mphy->state);
return 0;
}
static int mt7615_mcu_lp_drv_pmctrl(struct mt7615_dev *dev)
{
struct mt76_phy *mphy = &dev->mt76.phy;
int i;
if (!test_and_clear_bit(MT76_STATE_PM, &mphy->state))
goto out;
for (i = 0; i < MT7615_DRV_OWN_RETRY_COUNT; i++) {
mt76_wr(dev, MT_PCIE_DOORBELL_PUSH, MT_CFG_LPCR_HOST_DRV_OWN);
if (mt76_poll_msec(dev, MT_CONN_HIF_ON_LPCTL,
MT_CFG_LPCR_HOST_FW_OWN, 0, 50))
break;
}
if (i == MT7615_DRV_OWN_RETRY_COUNT) {
dev_err(dev->mt76.dev, "driver own failed\n");
set_bit(MT76_STATE_PM, &mphy->state);
return -EIO;
}
out:
dev->pm.last_activity = jiffies;
return 0;
}
static int mt7615_mcu_fw_pmctrl(struct mt7615_dev *dev)
{
struct mt76_phy *mphy = &dev->mt76.phy;
int err = 0;
u32 addr;
if (test_and_set_bit(MT76_STATE_PM, &mphy->state))
return 0;
mt7622_trigger_hif_int(dev, true);
addr = is_mt7663(&dev->mt76) ? MT_CONN_HIF_ON_LPCTL : MT_CFG_LPCR_HOST;
mt76_wr(dev, addr, MT_CFG_LPCR_HOST_FW_OWN);
if (is_mt7622(&dev->mt76) &&
!mt76_poll_msec(dev, addr, MT_CFG_LPCR_HOST_FW_OWN,
MT_CFG_LPCR_HOST_FW_OWN, 3000)) {
dev_err(dev->mt76.dev, "Timeout for firmware own\n");
clear_bit(MT76_STATE_PM, &mphy->state);
err = -EIO;
}
mt7622_trigger_hif_int(dev, false);
return err;
}
static void
mt7615_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
@ -1106,7 +1197,7 @@ mt7615_mcu_wtbl_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
tlv = mt7615_mcu_add_nested_tlv(skb, WTBL_HT, sizeof(*ht),
wtbl_tlv, sta_wtbl);
ht = (struct wtbl_ht *)tlv;
ht->ldpc = sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING;
ht->ldpc = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING);
ht->af = sta->ht_cap.ampdu_factor;
ht->mm = sta->ht_cap.ampdu_density;
ht->ht = 1;
@ -1124,7 +1215,7 @@ mt7615_mcu_wtbl_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
tlv = mt7615_mcu_add_nested_tlv(skb, WTBL_VHT, sizeof(*vht),
wtbl_tlv, sta_wtbl);
vht = (struct wtbl_vht *)tlv;
vht->ldpc = sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC,
vht->ldpc = !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC);
vht->vht = 1;
af = (sta->vht_cap.cap &
@ -1314,6 +1405,8 @@ static const struct mt7615_mcu_ops wtbl_update_ops = {
.add_tx_ba = mt7615_mcu_wtbl_tx_ba,
.add_rx_ba = mt7615_mcu_wtbl_rx_ba,
.sta_add = mt7615_mcu_wtbl_sta_add,
.set_drv_ctrl = mt7615_mcu_drv_pmctrl,
.set_fw_ctrl = mt7615_mcu_fw_pmctrl,
};
static int
@ -1410,6 +1503,8 @@ static const struct mt7615_mcu_ops sta_update_ops = {
.add_tx_ba = mt7615_mcu_sta_tx_ba,
.add_rx_ba = mt7615_mcu_sta_rx_ba,
.sta_add = mt7615_mcu_add_sta,
.set_drv_ctrl = mt7615_mcu_drv_pmctrl,
.set_fw_ctrl = mt7615_mcu_fw_pmctrl,
};
static int
@ -1823,6 +1918,8 @@ static const struct mt7615_mcu_ops uni_update_ops = {
.add_tx_ba = mt7615_mcu_uni_tx_ba,
.add_rx_ba = mt7615_mcu_uni_rx_ba,
.sta_add = mt7615_mcu_uni_add_sta,
.set_drv_ctrl = mt7615_mcu_lp_drv_pmctrl,
.set_fw_ctrl = mt7615_mcu_fw_pmctrl,
};
static int mt7615_mcu_send_firmware(struct mt7615_dev *dev, const void *data,
@ -1895,81 +1992,6 @@ static int mt7615_mcu_start_patch(struct mt7615_dev *dev)
&req, sizeof(req), true);
}
static void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en)
{
if (!is_mt7622(&dev->mt76))
return;
regmap_update_bits(dev->infracfg, MT_INFRACFG_MISC,
MT_INFRACFG_MISC_AP2CONN_WAKE,
!en * MT_INFRACFG_MISC_AP2CONN_WAKE);
}
int mt7615_driver_own(struct mt7615_dev *dev)
{
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt76_dev *mdev = &dev->mt76;
int i;
if (!test_and_clear_bit(MT76_STATE_PM, &mphy->state))
goto out;
mt7622_trigger_hif_int(dev, true);
for (i = 0; i < MT7615_DRV_OWN_RETRY_COUNT; i++) {
u32 addr;
addr = is_mt7663(mdev) ? MT_PCIE_DOORBELL_PUSH : MT_CFG_LPCR_HOST;
mt76_wr(dev, addr, MT_CFG_LPCR_HOST_DRV_OWN);
addr = is_mt7663(mdev) ? MT_CONN_HIF_ON_LPCTL : MT_CFG_LPCR_HOST;
if (mt76_poll_msec(dev, addr, MT_CFG_LPCR_HOST_FW_OWN, 0, 50))
break;
}
mt7622_trigger_hif_int(dev, false);
if (i == MT7615_DRV_OWN_RETRY_COUNT) {
dev_err(mdev->dev, "driver own failed\n");
set_bit(MT76_STATE_PM, &mphy->state);
return -EIO;
}
out:
dev->pm.last_activity = jiffies;
return 0;
}
EXPORT_SYMBOL_GPL(mt7615_driver_own);
int mt7615_firmware_own(struct mt7615_dev *dev)
{
struct mt76_phy *mphy = &dev->mt76.phy;
int err = 0;
u32 addr;
if (test_and_set_bit(MT76_STATE_PM, &mphy->state))
return 0;
mt7622_trigger_hif_int(dev, true);
addr = is_mt7663(&dev->mt76) ? MT_CONN_HIF_ON_LPCTL : MT_CFG_LPCR_HOST;
mt76_wr(dev, addr, MT_CFG_LPCR_HOST_FW_OWN);
if (is_mt7622(&dev->mt76) &&
!mt76_poll_msec(dev, addr, MT_CFG_LPCR_HOST_FW_OWN,
MT_CFG_LPCR_HOST_FW_OWN, 300)) {
dev_err(dev->mt76.dev, "Timeout for firmware own\n");
clear_bit(MT76_STATE_PM, &mphy->state);
err = -EIO;
}
mt7622_trigger_hif_int(dev, false);
return err;
}
EXPORT_SYMBOL_GPL(mt7615_firmware_own);
static int mt7615_load_patch(struct mt7615_dev *dev, u32 addr, const char *name)
{
const struct mt7615_patch_hdr *hdr;
@ -2452,7 +2474,7 @@ int mt7615_mcu_init(struct mt7615_dev *dev)
dev->mt76.mcu_ops = &mt7615_mcu_ops,
ret = mt7615_driver_own(dev);
ret = mt7615_mcu_drv_pmctrl(dev);
if (ret)
return ret;
@ -2482,7 +2504,7 @@ EXPORT_SYMBOL_GPL(mt7615_mcu_init);
void mt7615_mcu_exit(struct mt7615_dev *dev)
{
__mt76_mcu_restart(&dev->mt76);
mt7615_firmware_own(dev);
mt7615_mcu_set_fw_ctrl(dev);
skb_queue_purge(&dev->mt76.mcu.res_q);
}
EXPORT_SYMBOL_GPL(mt7615_mcu_exit);
@ -2847,14 +2869,6 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd)
.center_chan2 = ieee80211_frequency_to_channel(freq2),
};
#ifdef CONFIG_NL80211_TESTMODE
if (dev->mt76.test.state == MT76_TM_STATE_TX_FRAMES &&
dev->mt76.test.tx_antenna_mask) {
req.tx_streams = hweight8(dev->mt76.test.tx_antenna_mask);
req.rx_streams_mask = dev->mt76.test.tx_antenna_mask;
}
#endif
if (dev->mt76.hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
else if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) &&
@ -3279,7 +3293,7 @@ static int mt7615_dcoc_freq_idx(u16 freq, u8 bw)
freq = freq_bw40[idx];
break;
}
/* fall through */
fallthrough;
case NL80211_CHAN_WIDTH_40:
idx = mt7615_find_freq_idx(freq_bw40, ARRAY_SIZE(freq_bw40),
freq);

View File

@ -101,30 +101,29 @@ static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance)
static void mt7615_irq_tasklet(unsigned long data)
{
struct mt7615_dev *dev = (struct mt7615_dev *)data;
u32 intr, mask = 0;
u32 intr, mask = 0, tx_mcu_mask = mt7615_tx_mcu_int_mask(dev);
mt76_wr(dev, MT_INT_MASK_CSR, 0);
intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
intr &= dev->mt76.mmio.irqmask;
mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask);
intr &= dev->mt76.mmio.irqmask;
if (intr & MT_INT_TX_DONE_ALL) {
mask |= MT_INT_TX_DONE_ALL;
mask |= intr & MT_INT_RX_DONE_ALL;
if (intr & tx_mcu_mask)
mask |= tx_mcu_mask;
mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0);
if (intr & tx_mcu_mask)
napi_schedule(&dev->mt76.tx_napi);
}
if (intr & MT_INT_RX_DONE(0)) {
mask |= MT_INT_RX_DONE(0);
if (intr & MT_INT_RX_DONE(0))
napi_schedule(&dev->mt76.napi[0]);
}
if (intr & MT_INT_RX_DONE(1)) {
mask |= MT_INT_RX_DONE(1);
if (intr & MT_INT_RX_DONE(1))
napi_schedule(&dev->mt76.napi[1]);
}
if (intr & MT_INT_MCU_CMD) {
u32 val = mt76_rr(dev, MT_MCU_CMD);
@ -135,8 +134,6 @@ static void mt7615_irq_tasklet(unsigned long data)
wake_up(&dev->reset_wait);
}
}
mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0);
}
static u32 __mt7615_reg_addr(struct mt7615_dev *dev, u32 addr)
@ -227,6 +224,8 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,
bus_ops->rmw = mt7615_rmw;
dev->mt76.bus = bus_ops;
mt76_wr(dev, MT_INT_MASK_CSR, 0);
ret = devm_request_irq(mdev->dev, irq, mt7615_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (ret)

View File

@ -220,6 +220,8 @@ struct mt7615_phy {
#define mt7615_mcu_add_bss_info(phy, ...) (phy->dev)->mcu_ops->add_bss_info((phy), __VA_ARGS__)
#define mt7615_mcu_add_beacon(dev, ...) (dev)->mcu_ops->add_beacon_offload((dev), __VA_ARGS__)
#define mt7615_mcu_set_pm(dev, ...) (dev)->mcu_ops->set_pm_state((dev), __VA_ARGS__)
#define mt7615_mcu_set_drv_ctrl(dev) (dev)->mcu_ops->set_drv_ctrl((dev))
#define mt7615_mcu_set_fw_ctrl(dev) (dev)->mcu_ops->set_fw_ctrl((dev))
struct mt7615_mcu_ops {
int (*add_tx_ba)(struct mt7615_dev *dev,
struct ieee80211_ampdu_params *params,
@ -238,6 +240,8 @@ struct mt7615_mcu_ops {
struct ieee80211_hw *hw,
struct ieee80211_vif *vif, bool enable);
int (*set_pm_state)(struct mt7615_dev *dev, int band, int state);
int (*set_drv_ctrl)(struct mt7615_dev *dev);
int (*set_fw_ctrl)(struct mt7615_dev *dev);
};
struct mt7615_dev {
@ -278,6 +282,7 @@ struct mt7615_dev {
bool fw_debug;
bool flash_eeprom;
bool dbdc_support;
spinlock_t token_lock;
struct idr token;
@ -535,6 +540,11 @@ static inline u8 mt7615_lmac_mapping(struct mt7615_dev *dev, u8 ac)
return lmac_queue_map[ac];
}
static inline u32 mt7615_tx_mcu_int_mask(struct mt7615_dev *dev)
{
return MT_INT_TX_DONE(dev->mt76.q_tx[MT_TXQ_MCU]->hw_idx);
}
void mt7615_dma_reset(struct mt7615_dev *dev);
void mt7615_scan_work(struct work_struct *work);
void mt7615_roc_work(struct work_struct *work);
@ -608,8 +618,7 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
struct ieee80211_sta *sta,
struct mt76_tx_info *tx_info);
void mt7615_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid,
struct mt76_queue_entry *e);
void mt7615_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb);
@ -638,8 +647,6 @@ int mt7615_mcu_set_p2p_oppps(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_channel *chan, int duration);
int mt7615_firmware_own(struct mt7615_dev *dev);
int mt7615_driver_own(struct mt7615_dev *dev);
int mt7615_init_debugfs(struct mt7615_dev *dev);
int mt7615_mcu_wait_response(struct mt7615_dev *dev, int cmd, int seq);
@ -666,7 +673,6 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
struct mt76_tx_info *tx_info);
bool mt7663_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update);
void mt7663_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,
enum mt76_txq_id qid,
struct mt76_queue_entry *e);
void mt7663_usb_sdio_wtbl_work(struct work_struct *work);
int mt7663_usb_sdio_register_device(struct mt7615_dev *dev);
@ -675,9 +681,8 @@ int mt7663u_mcu_init(struct mt7615_dev *dev);
/* sdio */
u32 mt7663s_read_pcr(struct mt7615_dev *dev);
int mt7663s_mcu_init(struct mt7615_dev *dev);
int mt7663s_driver_own(struct mt7615_dev *dev);
int mt7663s_firmware_own(struct mt7615_dev *dev);
int mt7663s_kthread_run(void *data);
void mt7663s_tx_work(struct work_struct *work);
void mt7663s_rx_work(struct work_struct *work);
void mt7663s_sdio_irq(struct sdio_func *func);
#endif

View File

@ -88,7 +88,7 @@ static int mt7615_pci_suspend(struct pci_dev *pdev, pm_message_t state)
}
napi_disable(&mdev->tx_napi);
tasklet_kill(&mdev->tx_tasklet);
mt76_worker_disable(&mdev->tx_worker);
mt76_for_each_q_rx(mdev, i) {
napi_disable(&mdev->napi[i]);
@ -118,7 +118,7 @@ static int mt7615_pci_suspend(struct pci_dev *pdev, pm_message_t state)
if (err)
goto restore;
err = mt7615_firmware_own(dev);
err = mt7615_mcu_set_fw_ctrl(dev);
if (err)
goto restore;
@ -142,7 +142,7 @@ static int mt7615_pci_resume(struct pci_dev *pdev)
bool pdma_reset;
int i, err;
err = mt7615_driver_own(dev);
err = mt7615_mcu_set_drv_ctrl(dev);
if (err < 0)
return err;
@ -162,6 +162,7 @@ static int mt7615_pci_resume(struct pci_dev *pdev)
if (pdma_reset)
dev_err(mdev->dev, "PDMA engine must be reinitialized\n");
mt76_worker_enable(&mdev->tx_worker);
mt76_for_each_q_rx(mdev, i) {
napi_enable(&mdev->napi[i]);
napi_schedule(&mdev->napi[i]);

View File

@ -25,6 +25,9 @@ static void mt7615_init_work(struct work_struct *work)
mt7615_phy_init(dev);
mt7615_mcu_del_wtbl_all(dev);
mt7615_check_offload_capability(dev);
if (dev->dbdc_support)
mt7615_register_ext_phy(dev);
}
static int mt7615_init_hardware(struct mt7615_dev *dev)

View File

@ -14,8 +14,7 @@
#include "../dma.h"
#include "mac.h"
void mt7615_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid,
struct mt76_queue_entry *e)
void mt7615_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
{
if (!e->txwi) {
dev_kfree_skb_any(e->skb);
@ -45,7 +44,7 @@ void mt7615_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid,
}
if (e->skb)
mt76_tx_complete_skb(mdev, e->skb);
mt76_tx_complete_skb(mdev, e->wcid, e->skb);
}
static void
@ -107,6 +106,7 @@ mt7615_write_fw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info,
/* pass partial skb header to fw */
tx_info->buf[0].len = MT_TXD_SIZE + sizeof(*txp);
tx_info->buf[1].len = MT_CT_PARSE_LEN;
tx_info->buf[1].skip_unmap = true;
tx_info->nbuf = MT_CT_DMA_BUF_NUM;
txp->flags = cpu_to_le16(MT_CT_INFO_APPLY_TXD);

View File

@ -575,7 +575,7 @@ enum mt7615_reg_base {
#define MT_MCU_PTA_BASE 0x81060000
#define MT_MCU_PTA(_n) (MT_MCU_PTA_BASE + (_n))
#define MT_ANT_SWITCH_CON(n) MT_MCU_PTA(0x0c8)
#define MT_ANT_SWITCH_CON(_n) MT_MCU_PTA(0x0c8 + ((_n) - 1) * 4)
#define MT_ANT_SWITCH_CON_MODE(_n) (GENMASK(4, 0) << (_n * 8))
#define MT_ANT_SWITCH_CON_MODE1(_n) (GENMASK(3, 0) << (_n * 8))

View File

@ -323,7 +323,7 @@ static int mt7663s_probe(struct sdio_func *func,
{
static const struct mt76_driver_ops drv_ops = {
.txwi_size = MT_USB_TXD_SIZE,
.drv_flags = MT_DRV_RX_DMA_HDR | MT_DRV_HW_MGMT_TXQ,
.drv_flags = MT_DRV_RX_DMA_HDR,
.tx_prepare_skb = mt7663_usb_sdio_tx_prepare_skb,
.tx_complete_skb = mt7663_usb_sdio_tx_complete_skb,
.tx_status_data = mt7663_usb_sdio_tx_status_data,
@ -346,7 +346,7 @@ static int mt7663s_probe(struct sdio_func *func,
struct ieee80211_ops *ops;
struct mt7615_dev *dev;
struct mt76_dev *mdev;
int ret;
int i, ret;
ops = devm_kmemdup(&func->dev, &mt7615_ops, sizeof(mt7615_ops),
GFP_KERNEL);
@ -364,23 +364,39 @@ static int mt7663s_probe(struct sdio_func *func,
dev->ops = ops;
sdio_set_drvdata(func, dev);
mdev->sdio.tx_kthread = kthread_create(mt7663s_kthread_run, dev,
"mt7663s_tx");
if (IS_ERR(mdev->sdio.tx_kthread))
return PTR_ERR(mdev->sdio.tx_kthread);
ret = mt76s_init(mdev, func, &mt7663s_ops);
if (ret < 0)
goto err_free;
INIT_WORK(&mdev->sdio.tx.xmit_work, mt7663s_tx_work);
INIT_WORK(&mdev->sdio.rx.recv_work, mt7663s_rx_work);
ret = mt7663s_hw_init(dev, func);
if (ret)
goto err_free;
goto err_deinit;
mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
(mt76_rr(dev, MT_HW_REV) & 0xff);
dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
mdev->sdio.intr_data = devm_kmalloc(mdev->dev,
sizeof(struct mt76s_intr),
GFP_KERNEL);
if (!mdev->sdio.intr_data) {
ret = -ENOMEM;
goto err_deinit;
}
for (i = 0; i < ARRAY_SIZE(mdev->sdio.xmit_buf); i++) {
mdev->sdio.xmit_buf[i] = devm_kmalloc(mdev->dev,
MT76S_XMIT_BUF_SZ,
GFP_KERNEL);
if (!mdev->sdio.xmit_buf[i]) {
ret = -ENOMEM;
goto err_deinit;
}
}
ret = mt76s_alloc_queues(&dev->mt76);
if (ret)
goto err_deinit;
@ -426,9 +442,11 @@ static int mt7663s_suspend(struct device *dev)
return err;
}
sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
mt76s_stop_txrx(&mdev->mt76);
return mt7663s_firmware_own(mdev);
return mt7615_mcu_set_fw_ctrl(mdev);
}
static int mt7663s_resume(struct device *dev)
@ -437,7 +455,7 @@ static int mt7663s_resume(struct device *dev)
struct mt7615_dev *mdev = sdio_get_drvdata(func);
int err;
err = mt7663s_driver_own(mdev);
err = mt7615_mcu_set_drv_ctrl(mdev);
if (err)
return err;

View File

@ -53,7 +53,7 @@ mt7663s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
if (ret)
goto out;
mt76_queue_kick(dev, mdev->q_tx[MT_TXQ_MCU].q);
mt76_queue_kick(dev, mdev->q_tx[MT_TXQ_MCU]);
if (wait_resp)
ret = mt7615_mcu_wait_response(dev, cmd, seq);
@ -63,7 +63,7 @@ out:
return ret;
}
int mt7663s_driver_own(struct mt7615_dev *dev)
static int mt7663s_mcu_drv_pmctrl(struct mt7615_dev *dev)
{
struct sdio_func *func = dev->mt76.sdio.func;
struct mt76_phy *mphy = &dev->mt76.phy;
@ -75,7 +75,7 @@ int mt7663s_driver_own(struct mt7615_dev *dev)
sdio_claim_host(func);
sdio_writel(func, WHLPCR_FW_OWN_REQ_CLR, MCR_WHLPCR, 0);
sdio_writel(func, WHLPCR_FW_OWN_REQ_CLR, MCR_WHLPCR, NULL);
ret = readx_poll_timeout(mt7663s_read_pcr, dev, status,
status & WHLPCR_IS_DRIVER_OWN, 2000, 1000000);
@ -95,7 +95,7 @@ out:
return 0;
}
int mt7663s_firmware_own(struct mt7615_dev *dev)
static int mt7663s_mcu_fw_pmctrl(struct mt7615_dev *dev)
{
struct sdio_func *func = dev->mt76.sdio.func;
struct mt76_phy *mphy = &dev->mt76.phy;
@ -107,7 +107,7 @@ int mt7663s_firmware_own(struct mt7615_dev *dev)
sdio_claim_host(func);
sdio_writel(func, WHLPCR_FW_OWN_REQ_SET, MCR_WHLPCR, 0);
sdio_writel(func, WHLPCR_FW_OWN_REQ_SET, MCR_WHLPCR, NULL);
ret = readx_poll_timeout(mt7663s_read_pcr, dev, status,
!(status & WHLPCR_IS_DRIVER_OWN), 2000, 1000000);
@ -132,9 +132,10 @@ int mt7663s_mcu_init(struct mt7615_dev *dev)
.mcu_rr = mt7615_mcu_reg_rr,
.mcu_wr = mt7615_mcu_reg_wr,
};
struct mt7615_mcu_ops *mcu_ops;
int ret;
ret = mt7663s_driver_own(dev);
ret = mt7663s_mcu_drv_pmctrl(dev);
if (ret)
return ret;
@ -152,6 +153,15 @@ int mt7663s_mcu_init(struct mt7615_dev *dev)
if (ret)
return ret;
mcu_ops = devm_kmemdup(dev->mt76.dev, dev->mcu_ops, sizeof(*mcu_ops),
GFP_KERNEL);
if (!mcu_ops)
return -ENOMEM;
mcu_ops->set_drv_ctrl = mt7663s_mcu_drv_pmctrl;
mcu_ops->set_fw_ctrl = mt7663s_mcu_fw_pmctrl;
dev->mcu_ops = mcu_ops;
ret = mt7663s_mcu_init_sched(dev);
if (ret)
return ret;

View File

@ -19,21 +19,40 @@
#include "sdio.h"
#include "mac.h"
static void mt7663s_refill_sched_quota(struct mt7615_dev *dev, u32 *data)
static int mt7663s_refill_sched_quota(struct mt76_dev *dev, u32 *data)
{
struct mt76_sdio *sdio = &dev->mt76.sdio;
u32 ple_ac_data_quota[] = {
FIELD_GET(TXQ_CNT_L, data[4]), /* VO */
FIELD_GET(TXQ_CNT_H, data[3]), /* VI */
FIELD_GET(TXQ_CNT_L, data[3]), /* BE */
FIELD_GET(TXQ_CNT_H, data[2]), /* BK */
};
u32 pse_ac_data_quota[] = {
FIELD_GET(TXQ_CNT_H, data[1]), /* VO */
FIELD_GET(TXQ_CNT_L, data[1]), /* VI */
FIELD_GET(TXQ_CNT_H, data[0]), /* BE */
FIELD_GET(TXQ_CNT_L, data[0]), /* BK */
};
u32 pse_mcu_quota = FIELD_GET(TXQ_CNT_L, data[2]);
u32 pse_data_quota = 0, ple_data_quota = 0;
struct mt76_sdio *sdio = &dev->sdio;
int i;
for (i = 0; i < ARRAY_SIZE(pse_ac_data_quota); i++) {
pse_data_quota += pse_ac_data_quota[i];
ple_data_quota += ple_ac_data_quota[i];
}
if (!pse_data_quota && !ple_data_quota && !pse_mcu_quota)
return 0;
mutex_lock(&sdio->sched.lock);
sdio->sched.pse_data_quota += FIELD_GET(TXQ_CNT_L, data[0]) + /* BK */
FIELD_GET(TXQ_CNT_H, data[0]) + /* BE */
FIELD_GET(TXQ_CNT_L, data[1]) + /* VI */
FIELD_GET(TXQ_CNT_H, data[1]); /* VO */
sdio->sched.ple_data_quota += FIELD_GET(TXQ_CNT_H, data[2]) + /* BK */
FIELD_GET(TXQ_CNT_L, data[3]) + /* BE */
FIELD_GET(TXQ_CNT_H, data[3]) + /* VI */
FIELD_GET(TXQ_CNT_L, data[4]); /* VO */
sdio->sched.pse_mcu_quota += FIELD_GET(TXQ_CNT_L, data[2]);
sdio->sched.pse_mcu_quota += pse_mcu_quota;
sdio->sched.pse_data_quota += pse_data_quota;
sdio->sched.ple_data_quota += ple_data_quota;
mutex_unlock(&sdio->sched.lock);
return pse_data_quota + ple_data_quota + pse_mcu_quota;
}
static struct sk_buff *mt7663s_build_rx_skb(void *data, int data_len,
@ -61,11 +80,11 @@ static struct sk_buff *mt7663s_build_rx_skb(void *data, int data_len,
return skb;
}
static int mt7663s_rx_run_queue(struct mt7615_dev *dev, enum mt76_rxq_id qid,
static int mt7663s_rx_run_queue(struct mt76_dev *dev, enum mt76_rxq_id qid,
struct mt76s_intr *intr)
{
struct mt76_queue *q = &dev->mt76.q_rx[qid];
struct mt76_sdio *sdio = &dev->mt76.sdio;
struct mt76_queue *q = &dev->q_rx[qid];
struct mt76_sdio *sdio = &dev->sdio;
int len = 0, err, i, order;
struct page *page;
u8 *buf;
@ -86,15 +105,18 @@ static int mt7663s_rx_run_queue(struct mt7615_dev *dev, enum mt76_rxq_id qid,
buf = page_address(page);
sdio_claim_host(sdio->func);
err = sdio_readsb(sdio->func, buf, MCR_WRDR(qid), len);
sdio_release_host(sdio->func);
if (err < 0) {
dev_err(dev->mt76.dev, "sdio read data failed:%d\n", err);
dev_err(dev->dev, "sdio read data failed:%d\n", err);
__free_pages(page, order);
return err;
}
for (i = 0; i < intr->rx.num[qid]; i++) {
int index = (q->tail + i) % q->ndesc;
int index = (q->head + i) % q->ndesc;
struct mt76_queue_entry *e = &q->entry[index];
len = intr->rx.len[qid][i];
@ -109,160 +131,198 @@ static int mt7663s_rx_run_queue(struct mt7615_dev *dev, enum mt76_rxq_id qid,
__free_pages(page, order);
spin_lock_bh(&q->lock);
q->tail = (q->tail + i) % q->ndesc;
q->head = (q->head + i) % q->ndesc;
q->queued += i;
spin_unlock_bh(&q->lock);
return i;
}
static int mt7663s_tx_pick_quota(struct mt76_sdio *sdio, enum mt76_txq_id qid,
int buf_sz, int *pse_size, int *ple_size)
{
int pse_sz;
pse_sz = DIV_ROUND_UP(buf_sz + sdio->sched.deficit, MT_PSE_PAGE_SZ);
if (qid == MT_TXQ_MCU) {
if (sdio->sched.pse_mcu_quota < *pse_size + pse_sz)
return -EBUSY;
} else {
if (sdio->sched.pse_data_quota < *pse_size + pse_sz ||
sdio->sched.ple_data_quota < *ple_size)
return -EBUSY;
*ple_size = *ple_size + 1;
}
*pse_size = *pse_size + pse_sz;
return 0;
}
static void mt7663s_tx_update_quota(struct mt76_sdio *sdio, enum mt76_txq_id qid,
int pse_size, int ple_size)
{
mutex_lock(&sdio->sched.lock);
if (qid == MT_TXQ_MCU) {
sdio->sched.pse_mcu_quota -= pse_size;
} else {
sdio->sched.pse_data_quota -= pse_size;
sdio->sched.ple_data_quota -= ple_size;
}
mutex_unlock(&sdio->sched.lock);
}
static int __mt7663s_xmit_queue(struct mt76_dev *dev, u8 *data, int len)
{
struct mt76_sdio *sdio = &dev->sdio;
int err;
if (len > sdio->func->cur_blksize)
len = roundup(len, sdio->func->cur_blksize);
sdio_claim_host(sdio->func);
err = sdio_writesb(sdio->func, MCR_WTDR1, data, len);
sdio_release_host(sdio->func);
if (err)
dev_err(dev->dev, "sdio write failed: %d\n", err);
return err;
}
static int mt7663s_tx_update_sched(struct mt7615_dev *dev,
struct mt76_queue_entry *e,
bool mcu)
static int mt7663s_tx_run_queue(struct mt76_dev *dev, enum mt76_txq_id qid)
{
struct mt76_sdio *sdio = &dev->mt76.sdio;
struct mt76_phy *mphy = &dev->mt76.phy;
struct ieee80211_hdr *hdr;
int size, ret = -EBUSY;
int err, nframes = 0, len = 0, pse_sz = 0, ple_sz = 0;
struct mt76_queue *q = dev->q_tx[qid];
struct mt76_sdio *sdio = &dev->sdio;
size = DIV_ROUND_UP(e->buf_sz + sdio->sched.deficit, MT_PSE_PAGE_SZ);
if (mcu) {
if (!test_bit(MT76_STATE_MCU_RUNNING, &mphy->state))
return 0;
mutex_lock(&sdio->sched.lock);
if (sdio->sched.pse_mcu_quota > size) {
sdio->sched.pse_mcu_quota -= size;
ret = 0;
}
mutex_unlock(&sdio->sched.lock);
return ret;
}
hdr = (struct ieee80211_hdr *)(e->skb->data + MT_USB_TXD_SIZE);
if (ieee80211_is_ctl(hdr->frame_control))
return 0;
mutex_lock(&sdio->sched.lock);
if (sdio->sched.pse_data_quota > size &&
sdio->sched.ple_data_quota > 0) {
sdio->sched.pse_data_quota -= size;
sdio->sched.ple_data_quota--;
ret = 0;
}
mutex_unlock(&sdio->sched.lock);
return ret;
}
static int mt7663s_tx_run_queue(struct mt7615_dev *dev, struct mt76_queue *q)
{
bool mcu = q == dev->mt76.q_tx[MT_TXQ_MCU].q;
struct mt76_sdio *sdio = &dev->mt76.sdio;
int nframes = 0;
while (q->first != q->tail) {
while (q->first != q->head) {
struct mt76_queue_entry *e = &q->entry[q->first];
int err, len = e->skb->len;
struct sk_buff *iter;
if (mt7663s_tx_update_sched(dev, e, mcu))
if (!test_bit(MT76_STATE_MCU_RUNNING, &dev->phy.state)) {
__skb_put_zero(e->skb, 4);
err = __mt7663s_xmit_queue(dev, e->skb->data,
e->skb->len);
if (err)
return err;
goto next;
}
if (len + e->skb->len + 4 > MT76S_XMIT_BUF_SZ)
break;
if (len > sdio->func->cur_blksize)
len = roundup(len, sdio->func->cur_blksize);
if (mt7663s_tx_pick_quota(sdio, qid, e->buf_sz, &pse_sz,
&ple_sz))
break;
/* TODO: skb_walk_frags and then write to SDIO port */
err = sdio_writesb(sdio->func, MCR_WTDR1, e->skb->data, len);
if (err) {
dev_err(dev->mt76.dev, "sdio write failed: %d\n", err);
return -EIO;
}
e->done = true;
q->first = (q->first + 1) % q->ndesc;
memcpy(sdio->xmit_buf[qid] + len, e->skb->data,
skb_headlen(e->skb));
len += skb_headlen(e->skb);
nframes++;
skb_walk_frags(e->skb, iter) {
memcpy(sdio->xmit_buf[qid] + len, iter->data,
iter->len);
len += iter->len;
nframes++;
}
next:
q->first = (q->first + 1) % q->ndesc;
e->done = true;
}
if (nframes) {
memset(sdio->xmit_buf[qid] + len, 0, 4);
err = __mt7663s_xmit_queue(dev, sdio->xmit_buf[qid], len + 4);
if (err)
return err;
}
mt7663s_tx_update_quota(sdio, qid, pse_sz, ple_sz);
return nframes;
}
static int mt7663s_tx_run_queues(struct mt7615_dev *dev)
void mt7663s_tx_work(struct work_struct *work)
{
struct mt76_sdio *sdio = container_of(work, struct mt76_sdio,
tx.xmit_work);
struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio);
int i, nframes = 0;
for (i = 0; i < MT_TXQ_MCU_WA; i++) {
int ret;
ret = mt7663s_tx_run_queue(dev, dev->mt76.q_tx[i].q);
ret = mt7663s_tx_run_queue(dev, i);
if (ret < 0)
return ret;
break;
nframes += ret;
}
if (nframes)
queue_work(sdio->txrx_wq, &sdio->tx.xmit_work);
return nframes;
queue_work(sdio->txrx_wq, &sdio->tx.status_work);
}
int mt7663s_kthread_run(void *data)
void mt7663s_rx_work(struct work_struct *work)
{
struct mt7615_dev *dev = data;
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt76_sdio *sdio = container_of(work, struct mt76_sdio,
rx.recv_work);
struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio);
struct mt76s_intr *intr = sdio->intr_data;
int nframes = 0, ret;
while (!kthread_should_stop()) {
int ret;
/* disable interrupt */
sdio_claim_host(sdio->func);
sdio_writel(sdio->func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, NULL);
ret = sdio_readsb(sdio->func, intr, MCR_WHISR, sizeof(*intr));
sdio_release_host(sdio->func);
cond_resched();
if (ret < 0)
goto out;
sdio_claim_host(dev->mt76.sdio.func);
ret = mt7663s_tx_run_queues(dev);
sdio_release_host(dev->mt76.sdio.func);
trace_dev_irq(dev, intr->isr, 0);
if (ret <= 0 || !test_bit(MT76_STATE_RUNNING, &mphy->state)) {
set_current_state(TASK_INTERRUPTIBLE);
schedule();
} else {
wake_up_process(dev->mt76.sdio.kthread);
if (intr->isr & WHIER_RX0_DONE_INT_EN) {
ret = mt7663s_rx_run_queue(dev, 0, intr);
if (ret > 0) {
queue_work(sdio->txrx_wq, &sdio->rx.net_work);
nframes += ret;
}
}
return 0;
if (intr->isr & WHIER_RX1_DONE_INT_EN) {
ret = mt7663s_rx_run_queue(dev, 1, intr);
if (ret > 0) {
queue_work(sdio->txrx_wq, &sdio->rx.net_work);
nframes += ret;
}
}
if (mt7663s_refill_sched_quota(dev, intr->tx.wtqcr))
queue_work(sdio->txrx_wq, &sdio->tx.xmit_work);
if (nframes) {
queue_work(sdio->txrx_wq, &sdio->rx.recv_work);
return;
}
out:
/* enable interrupt */
sdio_claim_host(sdio->func);
sdio_writel(sdio->func, WHLPCR_INT_EN_SET, MCR_WHLPCR, NULL);
sdio_release_host(sdio->func);
}
void mt7663s_sdio_irq(struct sdio_func *func)
{
struct mt7615_dev *dev = sdio_get_drvdata(func);
struct mt76_sdio *sdio = &dev->mt76.sdio;
struct mt76s_intr intr;
/* disable interrupt */
sdio_writel(func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, 0);
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.phy.state))
return;
do {
sdio_readsb(func, &intr, MCR_WHISR, sizeof(struct mt76s_intr));
trace_dev_irq(&dev->mt76, intr.isr, 0);
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.phy.state))
goto out;
if (intr.isr & WHIER_RX0_DONE_INT_EN) {
mt7663s_rx_run_queue(dev, 0, &intr);
wake_up_process(sdio->kthread);
}
if (intr.isr & WHIER_RX1_DONE_INT_EN) {
mt7663s_rx_run_queue(dev, 1, &intr);
wake_up_process(sdio->kthread);
}
if (intr.isr & WHIER_TX_DONE_INT_EN) {
mt7663s_refill_sched_quota(dev, intr.tx.wtqcr);
mt7663s_tx_run_queues(dev);
wake_up_process(sdio->kthread);
}
} while (intr.isr);
out:
/* enable interrupt */
sdio_writel(func, WHLPCR_INT_EN_SET, MCR_WHLPCR, 0);
queue_work(sdio->txrx_wq, &sdio->rx.recv_work);
}

View File

@ -70,7 +70,7 @@ mt7615_tm_set_tx_power(struct mt7615_phy *phy)
if (dev->mt76.test.state != MT76_TM_STATE_OFF)
tx_power = dev->mt76.test.tx_power;
len = sizeof(req_hdr) + MT7615_EE_MAX - MT_EE_NIC_CONF_0;
len = MT7615_EE_MAX - MT_EE_NIC_CONF_0;
skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, sizeof(req_hdr) + len);
if (!skb)
return -ENOMEM;
@ -80,13 +80,12 @@ mt7615_tm_set_tx_power(struct mt7615_phy *phy)
target_chains = mt7615_ext_pa_enabled(dev, band) ? 1 : n_chains;
for (i = 0; i < target_chains; i++) {
int index;
ret = mt7615_eeprom_get_target_power_index(dev, chandef->chan, i);
if (ret < 0)
if (ret < 0) {
dev_kfree_skb(skb);
return -EINVAL;
}
index = ret - MT_EE_NIC_CONF_0;
if (tx_power && tx_power[i])
data[ret - MT_EE_NIC_CONF_0] = tx_power[i];
}
@ -191,7 +190,7 @@ mt7615_tm_set_tx_antenna(struct mt7615_dev *dev, bool en)
for (i = 0; i < 4; i++) {
mt76_rmw_field(dev, MT_WF_PHY_RFINTF3_0(i),
MT_WF_PHY_RFINTF3_0_ANT,
td->tx_antenna_mask & BIT(i) ? 0 : 0xa);
(td->tx_antenna_mask & BIT(i)) ? 0 : 0xa);
}

View File

@ -180,9 +180,7 @@ static int mt7663u_suspend(struct usb_interface *intf, pm_message_t state)
}
mt76u_stop_rx(&dev->mt76);
mt76u_stop_tx(&dev->mt76);
tasklet_kill(&dev->mt76.tx_tasklet);
return 0;
}

View File

@ -18,7 +18,7 @@ mt7663u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
int cmd, bool wait_resp)
{
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
int ret, seq, ep;
int ret, seq, ep, len, pad;
mutex_lock(&mdev->mcu.mutex);
@ -28,8 +28,10 @@ mt7663u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
else
ep = MT_EP_OUT_AC_BE;
put_unaligned_le32(skb->len, skb_push(skb, sizeof(skb->len)));
ret = mt76_skb_adjust_pad(skb);
len = skb->len;
put_unaligned_le32(len, skb_push(skb, sizeof(len)));
pad = round_up(skb->len, 4) + 4 - skb->len;
ret = mt76_skb_adjust_pad(skb, pad);
if (ret < 0)
goto out;

View File

@ -226,7 +226,6 @@ bool mt7663_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update)
EXPORT_SYMBOL_GPL(mt7663_usb_sdio_tx_status_data);
void mt7663_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,
enum mt76_txq_id qid,
struct mt76_queue_entry *e)
{
unsigned int headroom = MT_USB_TXD_SIZE;
@ -235,7 +234,7 @@ void mt7663_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,
headroom += MT_USB_HDR_SIZE;
skb_pull(e->skb, headroom);
mt76_tx_complete_skb(mdev, e->skb);
mt76_tx_complete_skb(mdev, e->wcid, e->skb);
}
EXPORT_SYMBOL_GPL(mt7663_usb_sdio_tx_complete_skb);
@ -248,6 +247,7 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
struct sk_buff *skb = tx_info->skb;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
int pad;
if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) &&
!msta->rate_probe) {
@ -259,10 +259,16 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
}
mt7663_usb_sdio_write_txwi(dev, wcid, qid, sta, skb);
if (mt76_is_usb(mdev))
put_unaligned_le32(skb->len, skb_push(skb, sizeof(skb->len)));
if (mt76_is_usb(mdev)) {
u32 len = skb->len;
return mt76_skb_adjust_pad(skb);
put_unaligned_le32(len, skb_push(skb, sizeof(len)));
pad = round_up(skb->len, 4) + 4 - skb->len;
} else {
pad = round_up(skb->len, 4) - skb->len;
}
return mt76_skb_adjust_pad(skb, pad);
}
EXPORT_SYMBOL_GPL(mt7663_usb_sdio_tx_prepare_skb);
@ -359,14 +365,15 @@ int mt7663_usb_sdio_register_device(struct mt7615_dev *dev)
if (err)
return err;
/* check hw sg support in order to enable AMSDU */
if (dev->mt76.usb.sg_en || mt76_is_sdio(&dev->mt76))
hw->max_tx_fragments = MT_HW_TXP_MAX_BUF_NUM;
else
hw->max_tx_fragments = 1;
hw->extra_tx_headroom += MT_USB_TXD_SIZE;
if (mt76_is_usb(&dev->mt76))
if (mt76_is_usb(&dev->mt76)) {
hw->extra_tx_headroom += MT_USB_HDR_SIZE;
/* check hw sg support in order to enable AMSDU */
if (dev->mt76.usb.sg_en)
hw->max_tx_fragments = MT_HW_TXP_MAX_BUF_NUM;
else
hw->max_tx_fragments = 1;
}
err = mt76_register_device(&dev->mt76, true, mt7615_rates,
ARRAY_SIZE(mt7615_rates));

View File

@ -10,6 +10,7 @@
#include "eeprom.h"
#include "mcu.h"
#include "initvals.h"
#include "initvals_init.h"
#include "../mt76x02_phy.h"
static void

View File

@ -11,139 +11,6 @@
#include "phy.h"
static const struct mt76_reg_pair common_mac_reg_table[] = {
{ MT_BCN_OFFSET(0), 0xf8f0e8e0 },
{ MT_BCN_OFFSET(1), 0x6f77d0c8 },
{ MT_LEGACY_BASIC_RATE, 0x0000013f },
{ MT_HT_BASIC_RATE, 0x00008003 },
{ MT_MAC_SYS_CTRL, 0x00000000 },
{ MT_RX_FILTR_CFG, 0x00017f97 },
{ MT_BKOFF_SLOT_CFG, 0x00000209 },
{ MT_TX_SW_CFG0, 0x00000000 },
{ MT_TX_SW_CFG1, 0x00080606 },
{ MT_TX_LINK_CFG, 0x00001020 },
{ MT_TX_TIMEOUT_CFG, 0x000a2090 },
{ MT_MAX_LEN_CFG, 0xa0fff | 0x00001000 },
{ MT_LED_CFG, 0x7f031e46 },
{ MT_PBF_TX_MAX_PCNT, 0x1fbf1f1f },
{ MT_PBF_RX_MAX_PCNT, 0x0000fe9f },
{ MT_TX_RETRY_CFG, 0x47d01f0f },
{ MT_AUTO_RSP_CFG, 0x00000013 },
{ MT_CCK_PROT_CFG, 0x07f40003 },
{ MT_OFDM_PROT_CFG, 0x07f42004 },
{ MT_PBF_CFG, 0x00f40006 },
{ MT_WPDMA_GLO_CFG, 0x00000030 },
{ MT_GF20_PROT_CFG, 0x01742004 },
{ MT_GF40_PROT_CFG, 0x03f42084 },
{ MT_MM20_PROT_CFG, 0x01742004 },
{ MT_MM40_PROT_CFG, 0x03f42084 },
{ MT_TXOP_CTRL_CFG, 0x0000583f },
{ MT_TX_RTS_CFG, 0x00ffff20 },
{ MT_EXP_ACK_TIME, 0x002400ca },
{ MT_TXOP_HLDR_ET, 0x00000002 },
{ MT_XIFS_TIME_CFG, 0x33a41010 },
{ MT_PWR_PIN_CFG, 0x00000000 },
};
static const struct mt76_reg_pair mt76x0_mac_reg_table[] = {
{ MT_IOCFG_6, 0xa0040080 },
{ MT_PBF_SYS_CTRL, 0x00080c00 },
{ MT_PBF_CFG, 0x77723c1f },
{ MT_FCE_PSE_CTRL, 0x00000001 },
{ MT_AMPDU_MAX_LEN_20M1S, 0xAAA99887 },
{ MT_TX_SW_CFG0, 0x00000601 },
{ MT_TX_SW_CFG1, 0x00040000 },
{ MT_TX_SW_CFG2, 0x00000000 },
{ 0xa44, 0x00000000 },
{ MT_HEADER_TRANS_CTRL_REG, 0x00000000 },
{ MT_TSO_CTRL, 0x00000000 },
{ MT_BB_PA_MODE_CFG1, 0x00500055 },
{ MT_RF_PA_MODE_CFG1, 0x00500055 },
{ MT_TX_ALC_CFG_0, 0x2F2F000C },
{ MT_TX0_BB_GAIN_ATTEN, 0x00000000 },
{ MT_TX_PWR_CFG_0, 0x3A3A3A3A },
{ MT_TX_PWR_CFG_1, 0x3A3A3A3A },
{ MT_TX_PWR_CFG_2, 0x3A3A3A3A },
{ MT_TX_PWR_CFG_3, 0x3A3A3A3A },
{ MT_TX_PWR_CFG_4, 0x3A3A3A3A },
{ MT_TX_PWR_CFG_7, 0x3A3A3A3A },
{ MT_TX_PWR_CFG_8, 0x0000003A },
{ MT_TX_PWR_CFG_9, 0x0000003A },
{ 0x150C, 0x00000002 },
{ 0x1238, 0x001700C8 },
{ MT_LDO_CTRL_0, 0x00A647B6 },
{ MT_LDO_CTRL_1, 0x6B006464 },
{ MT_HT_BASIC_RATE, 0x00004003 },
{ MT_HT_CTRL_CFG, 0x000001FF },
{ MT_TXOP_HLDR_ET, 0x00000000 },
{ MT_PN_PAD_MODE, 0x00000003 },
{ MT_TX_PROT_CFG6, 0xe3f42004 },
{ MT_TX_PROT_CFG7, 0xe3f42084 },
{ MT_TX_PROT_CFG8, 0xe3f42104 },
{ MT_VHT_HT_FBK_CFG1, 0xedcba980 },
};
static const struct mt76_reg_pair mt76x0_bbp_init_tab[] = {
{ MT_BBP(CORE, 1), 0x00000002 },
{ MT_BBP(CORE, 4), 0x00000000 },
{ MT_BBP(CORE, 24), 0x00000000 },
{ MT_BBP(CORE, 32), 0x4003000a },
{ MT_BBP(CORE, 42), 0x00000000 },
{ MT_BBP(CORE, 44), 0x00000000 },
{ MT_BBP(IBI, 11), 0x0FDE8081 },
{ MT_BBP(AGC, 0), 0x00021400 },
{ MT_BBP(AGC, 1), 0x00000003 },
{ MT_BBP(AGC, 2), 0x003A6464 },
{ MT_BBP(AGC, 15), 0x88A28CB8 },
{ MT_BBP(AGC, 22), 0x00001E21 },
{ MT_BBP(AGC, 23), 0x0000272C },
{ MT_BBP(AGC, 24), 0x00002F3A },
{ MT_BBP(AGC, 25), 0x8000005A },
{ MT_BBP(AGC, 26), 0x007C2005 },
{ MT_BBP(AGC, 33), 0x00003238 },
{ MT_BBP(AGC, 34), 0x000A0C0C },
{ MT_BBP(AGC, 37), 0x2121262C },
{ MT_BBP(AGC, 41), 0x38383E45 },
{ MT_BBP(AGC, 57), 0x00001010 },
{ MT_BBP(AGC, 59), 0xBAA20E96 },
{ MT_BBP(AGC, 63), 0x00000001 },
{ MT_BBP(TXC, 0), 0x00280403 },
{ MT_BBP(TXC, 1), 0x00000000 },
{ MT_BBP(RXC, 1), 0x00000012 },
{ MT_BBP(RXC, 2), 0x00000011 },
{ MT_BBP(RXC, 3), 0x00000005 },
{ MT_BBP(RXC, 4), 0x00000000 },
{ MT_BBP(RXC, 5), 0xF977C4EC },
{ MT_BBP(RXC, 7), 0x00000090 },
{ MT_BBP(TXO, 8), 0x00000000 },
{ MT_BBP(TXBE, 0), 0x00000000 },
{ MT_BBP(TXBE, 4), 0x00000004 },
{ MT_BBP(TXBE, 6), 0x00000000 },
{ MT_BBP(TXBE, 8), 0x00000014 },
{ MT_BBP(TXBE, 9), 0x20000000 },
{ MT_BBP(TXBE, 10), 0x00000000 },
{ MT_BBP(TXBE, 12), 0x00000000 },
{ MT_BBP(TXBE, 13), 0x00000000 },
{ MT_BBP(TXBE, 14), 0x00000000 },
{ MT_BBP(TXBE, 15), 0x00000000 },
{ MT_BBP(TXBE, 16), 0x00000000 },
{ MT_BBP(TXBE, 17), 0x00000000 },
{ MT_BBP(RXFE, 1), 0x00008800 },
{ MT_BBP(RXFE, 3), 0x00000000 },
{ MT_BBP(RXFE, 4), 0x00000000 },
{ MT_BBP(RXO, 13), 0x00000192 },
{ MT_BBP(RXO, 14), 0x00060612 },
{ MT_BBP(RXO, 15), 0xC8321B18 },
{ MT_BBP(RXO, 16), 0x0000001E },
{ MT_BBP(RXO, 17), 0x00000000 },
{ MT_BBP(RXO, 18), 0xCC00A993 },
{ MT_BBP(RXO, 19), 0xB9CB9CB9 },
{ MT_BBP(RXO, 20), 0x26c00057 },
{ MT_BBP(RXO, 21), 0x00000001 },
{ MT_BBP(RXO, 24), 0x00000006 },
{ MT_BBP(RXO, 28), 0x0000003F },
};
static const struct mt76x0_bbp_switch_item mt76x0_bbp_switch_tab[] = {
{ RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 4), 0x1FEDA049 } },
{ RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 4), 0x1FECA054 } },
@ -215,16 +82,4 @@ static const struct mt76x0_bbp_switch_item mt76x0_bbp_switch_tab[] = {
{ RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(RXFE, 0), 0x895000E0 } },
};
static const struct mt76_reg_pair mt76x0_dcoc_tab[] = {
{ MT_BBP(CAL, 47), 0x000010F0 },
{ MT_BBP(CAL, 48), 0x00008080 },
{ MT_BBP(CAL, 49), 0x00000F07 },
{ MT_BBP(CAL, 50), 0x00000040 },
{ MT_BBP(CAL, 51), 0x00000404 },
{ MT_BBP(CAL, 52), 0x00080803 },
{ MT_BBP(CAL, 53), 0x00000704 },
{ MT_BBP(CAL, 54), 0x00002828 },
{ MT_BBP(CAL, 55), 0x00005050 },
};
#endif

View File

@ -0,0 +1,159 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* (c) Copyright 2002-2010, Ralink Technology, Inc.
* Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
* Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
* Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
*/
#ifndef __MT76X0U_INITVALS_INIT_H
#define __MT76X0U_INITVALS_INIT_H
#include "phy.h"
static const struct mt76_reg_pair common_mac_reg_table[] = {
{ MT_BCN_OFFSET(0), 0xf8f0e8e0 },
{ MT_BCN_OFFSET(1), 0x6f77d0c8 },
{ MT_LEGACY_BASIC_RATE, 0x0000013f },
{ MT_HT_BASIC_RATE, 0x00008003 },
{ MT_MAC_SYS_CTRL, 0x00000000 },
{ MT_RX_FILTR_CFG, 0x00017f97 },
{ MT_BKOFF_SLOT_CFG, 0x00000209 },
{ MT_TX_SW_CFG0, 0x00000000 },
{ MT_TX_SW_CFG1, 0x00080606 },
{ MT_TX_LINK_CFG, 0x00001020 },
{ MT_TX_TIMEOUT_CFG, 0x000a2090 },
{ MT_MAX_LEN_CFG, 0xa0fff | 0x00001000 },
{ MT_LED_CFG, 0x7f031e46 },
{ MT_PBF_TX_MAX_PCNT, 0x1fbf1f1f },
{ MT_PBF_RX_MAX_PCNT, 0x0000fe9f },
{ MT_TX_RETRY_CFG, 0x47d01f0f },
{ MT_AUTO_RSP_CFG, 0x00000013 },
{ MT_CCK_PROT_CFG, 0x07f40003 },
{ MT_OFDM_PROT_CFG, 0x07f42004 },
{ MT_PBF_CFG, 0x00f40006 },
{ MT_WPDMA_GLO_CFG, 0x00000030 },
{ MT_GF20_PROT_CFG, 0x01742004 },
{ MT_GF40_PROT_CFG, 0x03f42084 },
{ MT_MM20_PROT_CFG, 0x01742004 },
{ MT_MM40_PROT_CFG, 0x03f42084 },
{ MT_TXOP_CTRL_CFG, 0x0000583f },
{ MT_TX_RTS_CFG, 0x00ffff20 },
{ MT_EXP_ACK_TIME, 0x002400ca },
{ MT_TXOP_HLDR_ET, 0x00000002 },
{ MT_XIFS_TIME_CFG, 0x33a41010 },
{ MT_PWR_PIN_CFG, 0x00000000 },
};
static const struct mt76_reg_pair mt76x0_mac_reg_table[] = {
{ MT_IOCFG_6, 0xa0040080 },
{ MT_PBF_SYS_CTRL, 0x00080c00 },
{ MT_PBF_CFG, 0x77723c1f },
{ MT_FCE_PSE_CTRL, 0x00000001 },
{ MT_AMPDU_MAX_LEN_20M1S, 0xAAA99887 },
{ MT_TX_SW_CFG0, 0x00000601 },
{ MT_TX_SW_CFG1, 0x00040000 },
{ MT_TX_SW_CFG2, 0x00000000 },
{ 0xa44, 0x00000000 },
{ MT_HEADER_TRANS_CTRL_REG, 0x00000000 },
{ MT_TSO_CTRL, 0x00000000 },
{ MT_BB_PA_MODE_CFG1, 0x00500055 },
{ MT_RF_PA_MODE_CFG1, 0x00500055 },
{ MT_TX_ALC_CFG_0, 0x2F2F000C },
{ MT_TX0_BB_GAIN_ATTEN, 0x00000000 },
{ MT_TX_PWR_CFG_0, 0x3A3A3A3A },
{ MT_TX_PWR_CFG_1, 0x3A3A3A3A },
{ MT_TX_PWR_CFG_2, 0x3A3A3A3A },
{ MT_TX_PWR_CFG_3, 0x3A3A3A3A },
{ MT_TX_PWR_CFG_4, 0x3A3A3A3A },
{ MT_TX_PWR_CFG_7, 0x3A3A3A3A },
{ MT_TX_PWR_CFG_8, 0x0000003A },
{ MT_TX_PWR_CFG_9, 0x0000003A },
{ 0x150C, 0x00000002 },
{ 0x1238, 0x001700C8 },
{ MT_LDO_CTRL_0, 0x00A647B6 },
{ MT_LDO_CTRL_1, 0x6B006464 },
{ MT_HT_BASIC_RATE, 0x00004003 },
{ MT_HT_CTRL_CFG, 0x000001FF },
{ MT_TXOP_HLDR_ET, 0x00000000 },
{ MT_PN_PAD_MODE, 0x00000003 },
{ MT_TX_PROT_CFG6, 0xe3f42004 },
{ MT_TX_PROT_CFG7, 0xe3f42084 },
{ MT_TX_PROT_CFG8, 0xe3f42104 },
{ MT_VHT_HT_FBK_CFG1, 0xedcba980 },
};
static const struct mt76_reg_pair mt76x0_bbp_init_tab[] = {
{ MT_BBP(CORE, 1), 0x00000002 },
{ MT_BBP(CORE, 4), 0x00000000 },
{ MT_BBP(CORE, 24), 0x00000000 },
{ MT_BBP(CORE, 32), 0x4003000a },
{ MT_BBP(CORE, 42), 0x00000000 },
{ MT_BBP(CORE, 44), 0x00000000 },
{ MT_BBP(IBI, 11), 0x0FDE8081 },
{ MT_BBP(AGC, 0), 0x00021400 },
{ MT_BBP(AGC, 1), 0x00000003 },
{ MT_BBP(AGC, 2), 0x003A6464 },
{ MT_BBP(AGC, 15), 0x88A28CB8 },
{ MT_BBP(AGC, 22), 0x00001E21 },
{ MT_BBP(AGC, 23), 0x0000272C },
{ MT_BBP(AGC, 24), 0x00002F3A },
{ MT_BBP(AGC, 25), 0x8000005A },
{ MT_BBP(AGC, 26), 0x007C2005 },
{ MT_BBP(AGC, 33), 0x00003238 },
{ MT_BBP(AGC, 34), 0x000A0C0C },
{ MT_BBP(AGC, 37), 0x2121262C },
{ MT_BBP(AGC, 41), 0x38383E45 },
{ MT_BBP(AGC, 57), 0x00001010 },
{ MT_BBP(AGC, 59), 0xBAA20E96 },
{ MT_BBP(AGC, 63), 0x00000001 },
{ MT_BBP(TXC, 0), 0x00280403 },
{ MT_BBP(TXC, 1), 0x00000000 },
{ MT_BBP(RXC, 1), 0x00000012 },
{ MT_BBP(RXC, 2), 0x00000011 },
{ MT_BBP(RXC, 3), 0x00000005 },
{ MT_BBP(RXC, 4), 0x00000000 },
{ MT_BBP(RXC, 5), 0xF977C4EC },
{ MT_BBP(RXC, 7), 0x00000090 },
{ MT_BBP(TXO, 8), 0x00000000 },
{ MT_BBP(TXBE, 0), 0x00000000 },
{ MT_BBP(TXBE, 4), 0x00000004 },
{ MT_BBP(TXBE, 6), 0x00000000 },
{ MT_BBP(TXBE, 8), 0x00000014 },
{ MT_BBP(TXBE, 9), 0x20000000 },
{ MT_BBP(TXBE, 10), 0x00000000 },
{ MT_BBP(TXBE, 12), 0x00000000 },
{ MT_BBP(TXBE, 13), 0x00000000 },
{ MT_BBP(TXBE, 14), 0x00000000 },
{ MT_BBP(TXBE, 15), 0x00000000 },
{ MT_BBP(TXBE, 16), 0x00000000 },
{ MT_BBP(TXBE, 17), 0x00000000 },
{ MT_BBP(RXFE, 1), 0x00008800 },
{ MT_BBP(RXFE, 3), 0x00000000 },
{ MT_BBP(RXFE, 4), 0x00000000 },
{ MT_BBP(RXO, 13), 0x00000192 },
{ MT_BBP(RXO, 14), 0x00060612 },
{ MT_BBP(RXO, 15), 0xC8321B18 },
{ MT_BBP(RXO, 16), 0x0000001E },
{ MT_BBP(RXO, 17), 0x00000000 },
{ MT_BBP(RXO, 18), 0xCC00A993 },
{ MT_BBP(RXO, 19), 0xB9CB9CB9 },
{ MT_BBP(RXO, 20), 0x26c00057 },
{ MT_BBP(RXO, 21), 0x00000001 },
{ MT_BBP(RXO, 24), 0x00000006 },
{ MT_BBP(RXO, 28), 0x0000003F },
};
static const struct mt76_reg_pair mt76x0_dcoc_tab[] = {
{ MT_BBP(CAL, 47), 0x000010F0 },
{ MT_BBP(CAL, 48), 0x00008080 },
{ MT_BBP(CAL, 49), 0x00000F07 },
{ MT_BBP(CAL, 50), 0x00000040 },
{ MT_BBP(CAL, 51), 0x00000404 },
{ MT_BBP(CAL, 52), 0x00080803 },
{ MT_BBP(CAL, 53), 0x00000704 },
{ MT_BBP(CAL, 54), 0x00002828 },
{ MT_BBP(CAL, 55), 0x00005050 },
};
#endif

View File

@ -180,6 +180,8 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
mdev->rev = mt76_rr(dev, MT_ASIC_VERSION);
dev_info(mdev->dev, "ASIC revision: %08x\n", mdev->rev);
mt76_wr(dev, MT_INT_MASK_CSR, 0);
ret = devm_request_irq(mdev->dev, pdev->irq, mt76x02_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (ret)
@ -202,7 +204,7 @@ static void mt76x0e_cleanup(struct mt76x02_dev *dev)
tasklet_disable(&dev->mt76.pre_tbtt_tasklet);
mt76x0_chip_onoff(dev, false, false);
mt76x0e_stop_hw(dev);
mt76x02_dma_cleanup(dev);
mt76_dma_cleanup(&dev->mt76);
mt76x02_mcu_cleanup(dev);
}

View File

@ -734,7 +734,7 @@ mt76x0_phy_get_delta_power(struct mt76x02_dev *dev, u8 tx_mode,
case 1:
if (chan->band == NL80211_BAND_2GHZ)
tssi_target += 29491; /* 3.6 * 8192 */
/* fall through */
fallthrough;
case 0:
break;
default:

View File

@ -15,6 +15,8 @@
#include "mt76x02_dfs.h"
#include "mt76x02_dma.h"
#define MT76x02_TX_RING_SIZE 512
#define MT76x02_PSD_RING_SIZE 128
#define MT76x02_N_WCIDS 128
#define MT_CALIBRATE_INTERVAL HZ
#define MT_MAC_WORK_INTERVAL (HZ / 10)

View File

@ -7,7 +7,7 @@
#include "mt76x02.h"
static int
mt76x02_ampdu_stat_read(struct seq_file *file, void *data)
mt76x02_ampdu_stat_show(struct seq_file *file, void *data)
{
struct mt76x02_dev *dev = file->private;
int i, j;
@ -31,11 +31,7 @@ mt76x02_ampdu_stat_read(struct seq_file *file, void *data)
return 0;
}
static int
mt76x02_ampdu_stat_open(struct inode *inode, struct file *f)
{
return single_open(f, mt76x02_ampdu_stat_read, inode->i_private);
}
DEFINE_SHOW_ATTRIBUTE(mt76x02_ampdu_stat);
static int read_txpower(struct seq_file *file, void *data)
{
@ -48,15 +44,8 @@ static int read_txpower(struct seq_file *file, void *data)
return 0;
}
static const struct file_operations fops_ampdu_stat = {
.open = mt76x02_ampdu_stat_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int
mt76x02_dfs_stat_read(struct seq_file *file, void *data)
mt76x02_dfs_stat_show(struct seq_file *file, void *data)
{
struct mt76x02_dev *dev = file->private;
struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
@ -81,18 +70,7 @@ mt76x02_dfs_stat_read(struct seq_file *file, void *data)
return 0;
}
static int
mt76x02_dfs_stat_open(struct inode *inode, struct file *f)
{
return single_open(f, mt76x02_dfs_stat_read, inode->i_private);
}
static const struct file_operations fops_dfs_stat = {
.open = mt76x02_dfs_stat_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(mt76x02_dfs_stat);
static int read_agc(struct seq_file *file, void *data)
{
@ -150,8 +128,8 @@ void mt76x02_init_debugfs(struct mt76x02_dev *dev)
debugfs_create_bool("tpc", 0600, dir, &dev->enable_tpc);
debugfs_create_file("edcca", 0600, dir, dev, &fops_edcca);
debugfs_create_file("ampdu_stat", 0400, dir, dev, &fops_ampdu_stat);
debugfs_create_file("dfs_stats", 0400, dir, dev, &fops_dfs_stat);
debugfs_create_file("ampdu_stat", 0400, dir, dev, &mt76x02_ampdu_stat_fops);
debugfs_create_file("dfs_stats", 0400, dir, dev, &mt76x02_dfs_stat_fops);
debugfs_create_devm_seqfile(dev->mt76.dev, "txpower", dir,
read_txpower);

View File

@ -429,11 +429,11 @@ static int mt76x02_dfs_create_sequence(struct mt76x02_dev *dev,
{
struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
struct mt76x02_dfs_sw_detector_params *sw_params;
u32 width_delta, with_sum, factor, cur_pri;
u32 width_delta, with_sum;
struct mt76x02_dfs_sequence seq, *seq_p;
struct mt76x02_dfs_event_rb *event_rb;
struct mt76x02_dfs_event *cur_event;
int i, j, end, pri;
int i, j, end, pri, factor, cur_pri;
event_rb = event->engine == 2 ? &dfs_pd->event_rb[1]
: &dfs_pd->event_rb[0];
@ -517,7 +517,7 @@ static u16 mt76x02_dfs_add_event_to_sequence(struct mt76x02_dev *dev,
struct mt76x02_dfs_sw_detector_params *sw_params;
struct mt76x02_dfs_sequence *seq, *tmp_seq;
u16 max_seq_len = 0;
u32 factor, pri;
int factor, pri;
sw_params = &dfs_pd->sw_dpd_params;
list_for_each_entry_safe(seq, tmp_seq, &dfs_pd->sequences, head) {

View File

@ -61,6 +61,5 @@ mt76x02_wait_for_wpdma(struct mt76_dev *dev, int timeout)
int mt76x02_dma_init(struct mt76x02_dev *dev);
void mt76x02_dma_disable(struct mt76x02_dev *dev);
void mt76x02_dma_cleanup(struct mt76x02_dev *dev);
#endif /* __MT76x02_DMA_H */

View File

@ -300,7 +300,7 @@ mt76x02_mac_process_tx_rate(struct ieee80211_tx_rate *txrate, u16 rate,
return 0;
case MT_PHY_TYPE_HT_GF:
txrate->flags |= IEEE80211_TX_RC_GREEN_FIELD;
/* fall through */
fallthrough;
case MT_PHY_TYPE_HT:
txrate->flags |= IEEE80211_TX_RC_MCS;
txrate->idx = idx;
@ -349,6 +349,8 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,
memset(txwi, 0, sizeof(*txwi));
mt76_tx_check_agg_ssn(sta, skb);
if (!info->control.hw_key && wcid && wcid->hw_key_idx != 0xff &&
ieee80211_has_protected(hdr->frame_control)) {
wcid = NULL;
@ -462,7 +464,7 @@ mt76x02_tx_rate_fallback(struct ieee80211_tx_rate *rates, int idx, int phy)
rates[1].idx = 0;
break;
}
/* fall through */
fallthrough;
default:
rates[1].idx = max_t(int, rates[0].idx - 1, 0);
break;
@ -677,7 +679,7 @@ mt76x02_mac_process_rate(struct mt76x02_dev *dev,
return 0;
case MT_PHY_TYPE_HT_GF:
status->enc_flags |= RX_ENC_FLAG_HT_GF;
/* fall through */
fallthrough;
case MT_PHY_TYPE_HT:
status->encoding = RX_ENC_HT;
status->rate_idx = idx;
@ -898,8 +900,7 @@ void mt76x02_mac_poll_tx_status(struct mt76x02_dev *dev, bool irq)
}
}
void mt76x02_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid,
struct mt76_queue_entry *e)
void mt76x02_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
{
struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
struct mt76x02_txwi *txwi;
@ -916,7 +917,7 @@ void mt76x02_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid,
txwi = (struct mt76x02_txwi *)txwi_ptr;
trace_mac_txdone(mdev, txwi->wcid, txwi->pktid);
mt76_tx_complete_skb(mdev, e->skb);
mt76_tx_complete_skb(mdev, e->wcid, e->skb);
}
EXPORT_SYMBOL_GPL(mt76x02_tx_complete_skb);

View File

@ -194,8 +194,7 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,
struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_sta *sta, int len);
void mt76x02_mac_poll_tx_status(struct mt76x02_dev *dev, bool irq);
void mt76x02_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid,
struct mt76_queue_entry *e);
void mt76x02_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
void mt76x02_update_channel(struct mt76_dev *mdev);
void mt76x02_mac_work(struct work_struct *work);

View File

@ -14,7 +14,7 @@
static void mt76x02_pre_tbtt_tasklet(unsigned long arg)
{
struct mt76x02_dev *dev = (struct mt76x02_dev *)arg;
struct mt76_queue *q = dev->mt76.q_tx[MT_TXQ_PSD].q;
struct mt76_queue *q = dev->mt76.q_tx[MT_TXQ_PSD];
struct beacon_bc_data data = {};
struct sk_buff *skb;
int i;
@ -104,8 +104,7 @@ void mt76x02e_init_beacon_config(struct mt76x02_dev *dev)
EXPORT_SYMBOL_GPL(mt76x02e_init_beacon_config);
static int
mt76x02_init_tx_queue(struct mt76x02_dev *dev, struct mt76_sw_queue *q,
int idx, int n_desc)
mt76x02_init_tx_queue(struct mt76x02_dev *dev, int qid, int idx, int n_desc)
{
struct mt76_queue *hwq;
int err;
@ -118,8 +117,7 @@ mt76x02_init_tx_queue(struct mt76x02_dev *dev, struct mt76_sw_queue *q,
if (err < 0)
return err;
INIT_LIST_HEAD(&q->swq);
q->q = hwq;
dev->mt76.q_tx[qid] = hwq;
mt76x02_irq_enable(dev, MT_INT_TX_DONE(idx));
@ -151,9 +149,11 @@ static void mt76x02_process_tx_status_fifo(struct mt76x02_dev *dev)
mt76x02_send_tx_status(dev, &stat, &update);
}
static void mt76x02_tx_tasklet(unsigned long data)
static void mt76x02_tx_worker(struct mt76_worker *w)
{
struct mt76x02_dev *dev = (struct mt76x02_dev *)data;
struct mt76x02_dev *dev;
dev = container_of(w, struct mt76x02_dev, mt76.tx_worker);
mt76x02_mac_poll_tx_status(dev, false);
mt76x02_process_tx_status_fifo(dev);
@ -178,7 +178,7 @@ static int mt76x02_poll_tx(struct napi_struct *napi, int budget)
for (i = MT_TXQ_MCU; i >= 0; i--)
mt76_queue_tx_cleanup(dev, i, false);
tasklet_schedule(&dev->mt76.tx_tasklet);
mt76_worker_schedule(&dev->mt76.tx_worker);
return 0;
}
@ -197,8 +197,7 @@ int mt76x02_dma_init(struct mt76x02_dev *dev)
if (!status_fifo)
return -ENOMEM;
tasklet_init(&dev->mt76.tx_tasklet, mt76x02_tx_tasklet,
(unsigned long)dev);
dev->mt76.tx_worker.fn = mt76x02_tx_worker;
tasklet_init(&dev->mt76.pre_tbtt_tasklet, mt76x02_pre_tbtt_tasklet,
(unsigned long)dev);
@ -210,19 +209,18 @@ int mt76x02_dma_init(struct mt76x02_dev *dev)
mt76_wr(dev, MT_WPDMA_RST_IDX, ~0);
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
ret = mt76x02_init_tx_queue(dev, &dev->mt76.q_tx[i],
mt76_ac_to_hwq(i),
MT_TX_RING_SIZE);
ret = mt76x02_init_tx_queue(dev, i, mt76_ac_to_hwq(i),
MT76x02_TX_RING_SIZE);
if (ret)
return ret;
}
ret = mt76x02_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_PSD],
MT_TX_HW_QUEUE_MGMT, MT_TX_RING_SIZE);
ret = mt76x02_init_tx_queue(dev, MT_TXQ_PSD,
MT_TX_HW_QUEUE_MGMT, MT76x02_PSD_RING_SIZE);
if (ret)
return ret;
ret = mt76x02_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU],
ret = mt76x02_init_tx_queue(dev, MT_TXQ_MCU,
MT_TX_HW_QUEUE_MCU, MT_MCU_RING_SIZE);
if (ret)
return ret;
@ -263,9 +261,10 @@ EXPORT_SYMBOL_GPL(mt76x02_rx_poll_complete);
irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance)
{
struct mt76x02_dev *dev = dev_instance;
u32 intr;
u32 intr, mask;
intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
intr &= dev->mt76.mmio.irqmask;
mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
@ -273,17 +272,17 @@ irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance)
trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask);
intr &= dev->mt76.mmio.irqmask;
mask = intr & (MT_INT_RX_DONE_ALL | MT_INT_GPTIMER);
if (intr & (MT_INT_TX_DONE_ALL | MT_INT_TX_STAT))
mask |= MT_INT_TX_DONE_ALL;
if (intr & MT_INT_RX_DONE(0)) {
mt76x02_irq_disable(dev, MT_INT_RX_DONE(0));
mt76x02_irq_disable(dev, mask);
if (intr & MT_INT_RX_DONE(0))
napi_schedule(&dev->mt76.napi[0]);
}
if (intr & MT_INT_RX_DONE(1)) {
mt76x02_irq_disable(dev, MT_INT_RX_DONE(1));
if (intr & MT_INT_RX_DONE(1))
napi_schedule(&dev->mt76.napi[1]);
}
if (intr & MT_INT_PRE_TBTT)
tasklet_schedule(&dev->mt76.pre_tbtt_tasklet);
@ -293,21 +292,17 @@ irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance)
if (dev->mt76.csa_complete)
mt76_csa_finish(&dev->mt76);
else
mt76_queue_kick(dev, dev->mt76.q_tx[MT_TXQ_PSD].q);
mt76_queue_kick(dev, dev->mt76.q_tx[MT_TXQ_PSD]);
}
if (intr & MT_INT_TX_STAT)
mt76x02_mac_poll_tx_status(dev, true);
if (intr & (MT_INT_TX_STAT | MT_INT_TX_DONE_ALL)) {
mt76x02_irq_disable(dev, MT_INT_TX_DONE_ALL);
if (intr & (MT_INT_TX_STAT | MT_INT_TX_DONE_ALL))
napi_schedule(&dev->mt76.tx_napi);
}
if (intr & MT_INT_GPTIMER) {
mt76x02_irq_disable(dev, MT_INT_GPTIMER);
if (intr & MT_INT_GPTIMER)
tasklet_schedule(&dev->dfs_pd.dfs_tasklet);
}
return IRQ_HANDLED;
}
@ -329,13 +324,6 @@ static void mt76x02_dma_enable(struct mt76x02_dev *dev)
MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);
}
void mt76x02_dma_cleanup(struct mt76x02_dev *dev)
{
tasklet_kill(&dev->mt76.tx_tasklet);
mt76_dma_cleanup(&dev->mt76);
}
EXPORT_SYMBOL_GPL(mt76x02_dma_cleanup);
void mt76x02_dma_disable(struct mt76x02_dev *dev)
{
u32 val = mt76_rr(dev, MT_WPDMA_GLO_CFG);
@ -369,7 +357,7 @@ static bool mt76x02_tx_hang(struct mt76x02_dev *dev)
int i;
for (i = 0; i < 4; i++) {
q = dev->mt76.q_tx[i].q;
q = dev->mt76.q_tx[i];
if (!q->queued)
continue;
@ -453,7 +441,7 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
set_bit(MT76_RESET, &dev->mphy.state);
tasklet_disable(&dev->mt76.pre_tbtt_tasklet);
tasklet_disable(&dev->mt76.tx_tasklet);
mt76_worker_disable(&dev->mt76.tx_worker);
napi_disable(&dev->mt76.tx_napi);
mt76_for_each_q_rx(&dev->mt76, i) {
@ -510,7 +498,7 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
clear_bit(MT76_RESET, &dev->mphy.state);
tasklet_enable(&dev->mt76.tx_tasklet);
mt76_worker_enable(&dev->mt76.tx_worker);
napi_enable(&dev->mt76.tx_napi);
napi_schedule(&dev->mt76.tx_napi);

View File

@ -19,8 +19,7 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
enum mt76_txq_id qid, struct mt76_wcid *wcid,
struct ieee80211_sta *sta,
struct mt76_tx_info *tx_info);
void mt76x02u_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid,
struct mt76_queue_entry *e);
void mt76x02u_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
void mt76x02u_init_beacon_config(struct mt76x02_dev *dev);
void mt76x02u_exit_beacon_config(struct mt76x02_dev *dev);
#endif /* __MT76x02_USB_H */

View File

@ -15,11 +15,10 @@ static void mt76x02u_remove_dma_hdr(struct sk_buff *skb)
mt76x02_remove_hdr_pad(skb, 2);
}
void mt76x02u_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid,
struct mt76_queue_entry *e)
void mt76x02u_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
{
mt76x02u_remove_dma_hdr(e->skb);
mt76_tx_complete_skb(mdev, e->skb);
mt76_tx_complete_skb(mdev, e->wcid, e->skb);
}
EXPORT_SYMBOL_GPL(mt76x02u_tx_complete_skb);
@ -46,7 +45,7 @@ EXPORT_SYMBOL_GPL(mt76x02u_mac_start);
int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags)
{
u32 info;
u32 info, pad;
/* Buffer layout:
* | 4B | xfer len | pad | 4B |
@ -58,7 +57,8 @@ int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags)
FIELD_PREP(MT_TXD_INFO_DPORT, port) | flags;
put_unaligned_le32(info, skb_push(skb, sizeof(info)));
return mt76_skb_adjust_pad(skb);
pad = round_up(skb->len, 4) + 4 - skb->len;
return mt76_skb_adjust_pad(skb, pad);
}
int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
@ -67,7 +67,7 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
struct mt76_tx_info *tx_info)
{
struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
int pid, len = tx_info->skb->len, ep = q2ep(mdev->q_tx[qid].q->hw_idx);
int pid, len = tx_info->skb->len, ep = q2ep(mdev->q_tx[qid]->hw_idx);
struct mt76x02_txwi *txwi;
bool ampdu = IEEE80211_SKB_CB(tx_info->skb)->flags & IEEE80211_TX_CTL_AMPDU;
enum mt76_qsel qsel;

View File

@ -294,8 +294,6 @@ mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif,
mvif->group_wcid.hw_key_idx = -1;
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
mtxq->wcid = &mvif->group_wcid;
mt76_txq_init(&dev->mt76, vif->txq);
}
int
@ -347,7 +345,6 @@ void mt76x02_remove_interface(struct ieee80211_hw *hw,
struct mt76x02_dev *dev = hw->priv;
struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
mt76_txq_remove(&dev->mt76, vif->txq);
dev->mphy.vif_mask &= ~BIT(mvif->idx);
}
EXPORT_SYMBOL_GPL(mt76x02_remove_interface);
@ -490,7 +487,7 @@ int mt76x02_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u8 cw_min = 5, cw_max = 10, qid;
u32 val;
qid = dev->mt76.q_tx[queue].q->hw_idx;
qid = dev->mt76.q_tx[queue]->hw_idx;
if (params->cw_min)
cw_min = fls(params->cw_min);

View File

@ -63,6 +63,8 @@ mt76x2e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
mdev->rev = mt76_rr(dev, MT_ASIC_VERSION);
dev_info(mdev->dev, "ASIC revision: %08x\n", mdev->rev);
mt76_wr(dev, MT_INT_MASK_CSR, 0);
ret = devm_request_irq(mdev->dev, pdev->irq, mt76x02_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (ret)
@ -111,7 +113,7 @@ mt76x2e_suspend(struct pci_dev *pdev, pm_message_t state)
napi_disable(&mdev->tx_napi);
tasklet_kill(&mdev->pre_tbtt_tasklet);
tasklet_kill(&mdev->tx_tasklet);
mt76_worker_disable(&mdev->tx_worker);
mt76_for_each_q_rx(mdev, i)
napi_disable(&mdev->napi[i]);
@ -145,6 +147,7 @@ mt76x2e_resume(struct pci_dev *pdev)
pci_restore_state(pdev);
mt76_worker_enable(&mdev->tx_worker);
mt76_for_each_q_rx(mdev, i) {
napi_enable(&mdev->napi[i]);
napi_schedule(&mdev->napi[i]);

View File

@ -283,7 +283,7 @@ void mt76x2_cleanup(struct mt76x02_dev *dev)
tasklet_disable(&dev->dfs_pd.dfs_tasklet);
tasklet_disable(&dev->mt76.pre_tbtt_tasklet);
mt76x2_stop_hardware(dev);
mt76x02_dma_cleanup(dev);
mt76_dma_cleanup(&dev->mt76);
mt76x02_mcu_cleanup(dev);
}

View File

@ -21,7 +21,6 @@ static int mt7915_ser_trigger_set(void *data, u64 val)
switch (val) {
case SER_SET_RECOVER_L1:
case SER_SET_RECOVER_L2:
/* fall through */
ret = mt7915_mcu_set_ser(dev, SER_ENABLE, BIT(val), 0);
if (ret)
return ret;
@ -292,15 +291,15 @@ mt7915_queues_read(struct seq_file *s, void *data)
int i;
for (i = 0; i < ARRAY_SIZE(queue_map); i++) {
struct mt76_sw_queue *q = &dev->mt76.q_tx[queue_map[i].id];
struct mt76_queue *q = dev->mt76.q_tx[queue_map[i].id];
if (!q->q)
if (!q)
continue;
seq_printf(s,
"%s: queued=%d head=%d tail=%d\n",
queue_map[i].queue, q->q->queued, q->q->head,
q->q->tail);
queue_map[i].queue, q->queued, q->head,
q->tail);
}
return 0;
@ -400,7 +399,7 @@ static int mt7915_sta_fixed_rate_set(void *data, u64 rate)
struct ieee80211_sta *sta = data;
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
return mt7915_mcu_set_fixed_rate(msta->vif->dev, sta, rate);
return mt7915_mcu_set_fixed_rate(msta->vif->phy->dev, sta, rate);
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_fixed_rate, NULL,

View File

@ -8,7 +8,6 @@
static int
mt7915_init_tx_queues(struct mt7915_dev *dev, int n_desc)
{
struct mt76_sw_queue *q;
struct mt76_queue *hwq;
int err, i;
@ -21,18 +20,14 @@ mt7915_init_tx_queues(struct mt7915_dev *dev, int n_desc)
if (err < 0)
return err;
for (i = 0; i < MT_TXQ_MCU; i++) {
q = &dev->mt76.q_tx[i];
INIT_LIST_HEAD(&q->swq);
q->q = hwq;
}
for (i = 0; i < MT_TXQ_MCU; i++)
dev->mt76.q_tx[i] = hwq;
return 0;
}
static int
mt7915_init_mcu_queue(struct mt7915_dev *dev, struct mt76_sw_queue *q,
int idx, int n_desc)
mt7915_init_mcu_queue(struct mt7915_dev *dev, int qid, int idx, int n_desc)
{
struct mt76_queue *hwq;
int err;
@ -45,8 +40,7 @@ mt7915_init_mcu_queue(struct mt7915_dev *dev, struct mt76_sw_queue *q,
if (err < 0)
return err;
INIT_LIST_HEAD(&q->swq);
q->q = hwq;
dev->mt76.q_tx[qid] = hwq;
return 0;
}
@ -72,7 +66,7 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
mt76_rx(&dev->mt76, q, skb);
return;
}
/* fall through */
fallthrough;
default:
dev_kfree_skb(skb);
break;
@ -84,8 +78,6 @@ mt7915_tx_cleanup(struct mt7915_dev *dev)
{
mt76_queue_tx_cleanup(dev, MT_TXQ_MCU, false);
mt76_queue_tx_cleanup(dev, MT_TXQ_MCU_WA, false);
mt76_queue_tx_cleanup(dev, MT_TXQ_PSD, false);
mt76_queue_tx_cleanup(dev, MT_TXQ_BE, false);
}
static int mt7915_poll_tx(struct napi_struct *napi, int budget)
@ -97,13 +89,7 @@ static int mt7915_poll_tx(struct napi_struct *napi, int budget)
mt7915_tx_cleanup(dev);
if (napi_complete_done(napi, 0))
mt7915_irq_enable(dev, MT_INT_TX_DONE_ALL);
mt7915_tx_cleanup(dev);
mt7915_mac_sta_poll(dev);
tasklet_schedule(&dev->mt76.tx_tasklet);
mt7915_irq_enable(dev, MT_INT_TX_DONE_MCU);
return 0;
}
@ -138,12 +124,120 @@ void mt7915_dma_prefetch(struct mt7915_dev *dev)
mt76_wr(dev, MT_WFDMA1_RX_RING3_EXT_CTRL, PREFETCH(0x480, 0x0));
}
static u32 __mt7915_reg_addr(struct mt7915_dev *dev, u32 addr)
{
static const struct {
u32 phys;
u32 mapped;
u32 size;
} fixed_map[] = {
{ 0x54000000, 0x02000, 0x1000 }, /* WFDMA PCIE0 MCU DMA0 */
{ 0x55000000, 0x03000, 0x1000 }, /* WFDMA PCIE0 MCU DMA1 */
{ 0x58000000, 0x06000, 0x1000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */
{ 0x59000000, 0x07000, 0x1000 }, /* WFDMA PCIE1 MCU DMA1 */
{ 0x7c000000, 0xf0000, 0x10000 }, /* CONN_INFRA */
{ 0x7c020000, 0xd0000, 0x10000 }, /* CONN_INFRA, WFDMA */
{ 0x80020000, 0xb0000, 0x10000 }, /* WF_TOP_MISC_OFF */
{ 0x81020000, 0xc0000, 0x10000 }, /* WF_TOP_MISC_ON */
{ 0x820c0000, 0x08000, 0x4000 }, /* WF_UMAC_TOP (PLE) */
{ 0x820c8000, 0x0c000, 0x2000 }, /* WF_UMAC_TOP (PSE) */
{ 0x820cc000, 0x0e000, 0x2000 }, /* WF_UMAC_TOP (PP) */
{ 0x820ce000, 0x21c00, 0x0200 }, /* WF_LMAC_TOP (WF_SEC) */
{ 0x820cf000, 0x22000, 0x1000 }, /* WF_LMAC_TOP (WF_PF) */
{ 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */
{ 0x820e0000, 0x20000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */
{ 0x820e1000, 0x20400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */
{ 0x820e2000, 0x20800, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */
{ 0x820e3000, 0x20c00, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */
{ 0x820e4000, 0x21000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */
{ 0x820e5000, 0x21400, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */
{ 0x820e7000, 0x21e00, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */
{ 0x820e9000, 0x23400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */
{ 0x820ea000, 0x24000, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */
{ 0x820eb000, 0x24200, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */
{ 0x820ec000, 0x24600, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_INT) */
{ 0x820ed000, 0x24800, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */
{ 0x820f0000, 0xa0000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */
{ 0x820f1000, 0xa0600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */
{ 0x820f2000, 0xa0800, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */
{ 0x820f3000, 0xa0c00, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */
{ 0x820f4000, 0xa1000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */
{ 0x820f5000, 0xa1400, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */
{ 0x820f7000, 0xa1e00, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */
{ 0x820f9000, 0xa3400, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */
{ 0x820fa000, 0xa4000, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */
{ 0x820fb000, 0xa4200, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */
{ 0x820fc000, 0xa4600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_INT) */
{ 0x820fd000, 0xa4800, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */
};
int i;
if (addr < 0x100000)
return addr;
for (i = 0; i < ARRAY_SIZE(fixed_map); i++) {
u32 ofs;
if (addr < fixed_map[i].phys)
continue;
ofs = addr - fixed_map[i].phys;
if (ofs > fixed_map[i].size)
continue;
return fixed_map[i].mapped + ofs;
}
if ((addr >= 0x18000000 && addr < 0x18c00000) ||
(addr >= 0x70000000 && addr < 0x78000000) ||
(addr >= 0x7c000000 && addr < 0x7c400000))
return mt7915_reg_map_l1(dev, addr);
return mt7915_reg_map_l2(dev, addr);
}
static u32 mt7915_rr(struct mt76_dev *mdev, u32 offset)
{
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
u32 addr = __mt7915_reg_addr(dev, offset);
return dev->bus_ops->rr(mdev, addr);
}
static void mt7915_wr(struct mt76_dev *mdev, u32 offset, u32 val)
{
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
u32 addr = __mt7915_reg_addr(dev, offset);
dev->bus_ops->wr(mdev, addr, val);
}
static u32 mt7915_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
{
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
u32 addr = __mt7915_reg_addr(dev, offset);
return dev->bus_ops->rmw(mdev, addr, mask, val);
}
int mt7915_dma_init(struct mt7915_dev *dev)
{
/* Increase buffer size to receive large VHT/HE MPDUs */
struct mt76_bus_ops *bus_ops;
int rx_buf_size = MT_RX_BUF_SIZE * 2;
int ret;
dev->bus_ops = dev->mt76.bus;
bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops),
GFP_KERNEL);
if (!bus_ops)
return -ENOMEM;
bus_ops->rr = mt7915_rr;
bus_ops->wr = mt7915_wr;
bus_ops->rmw = mt7915_rmw;
dev->mt76.bus = bus_ops;
mt76_dma_attach(&dev->mt76);
/* configure global setting */
@ -168,22 +262,19 @@ int mt7915_dma_init(struct mt7915_dev *dev)
return ret;
/* command to WM */
ret = mt7915_init_mcu_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU],
MT7915_TXQ_MCU_WM,
ret = mt7915_init_mcu_queue(dev, MT_TXQ_MCU, MT7915_TXQ_MCU_WM,
MT7915_TX_MCU_RING_SIZE);
if (ret)
return ret;
/* command to WA */
ret = mt7915_init_mcu_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU_WA],
MT7915_TXQ_MCU_WA,
ret = mt7915_init_mcu_queue(dev, MT_TXQ_MCU_WA, MT7915_TXQ_MCU_WA,
MT7915_TX_MCU_RING_SIZE);
if (ret)
return ret;
/* firmware download */
ret = mt7915_init_mcu_queue(dev, &dev->mt76.q_tx[MT_TXQ_FWDL],
MT7915_TXQ_FWDL,
ret = mt7915_init_mcu_queue(dev, MT_TXQ_FWDL, MT7915_TXQ_FWDL,
MT7915_TX_FWDL_RING_SIZE);
if (ret)
return ret;
@ -248,7 +339,7 @@ int mt7915_dma_init(struct mt7915_dev *dev)
MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN);
/* enable interrupts for TX/RX rings */
mt7915_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
mt7915_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_MCU |
MT_INT_MCU_CMD);
return 0;
@ -281,6 +372,5 @@ void mt7915_dma_cleanup(struct mt7915_dev *dev)
MT_WFDMA0_RST_DMASHDL_ALL_RST |
MT_WFDMA0_RST_LOGIC_RST);
tasklet_kill(&dev->mt76.tx_tasklet);
mt76_dma_cleanup(&dev->mt76);
}

View File

@ -135,6 +135,12 @@ static int mt7915_init_hardware(struct mt7915_dev *dev)
set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
/*
* force firmware operation mode into normal state,
* which should be set before firmware download stage.
*/
mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
ret = mt7915_mcu_init(dev);
if (ret)
return ret;
@ -612,6 +618,7 @@ int mt7915_register_ext_phy(struct mt7915_dev *dev)
mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1;
mt7915_init_wiphy(mphy->hw);
INIT_LIST_HEAD(&phy->stats_list);
INIT_DELAYED_WORK(&phy->mac_work, mt7915_mac_work);
/*
@ -652,7 +659,10 @@ int mt7915_register_device(struct mt7915_dev *dev)
dev->phy.dev = dev;
dev->phy.mt76 = &dev->mt76.phy;
dev->mt76.phy.priv = &dev->phy;
INIT_LIST_HEAD(&dev->phy.stats_list);
INIT_WORK(&dev->rc_work, mt7915_mac_sta_rc_work);
INIT_DELAYED_WORK(&dev->phy.mac_work, mt7915_mac_work);
INIT_LIST_HEAD(&dev->sta_rc_list);
INIT_LIST_HEAD(&dev->sta_poll_list);
spin_lock_init(&dev->sta_poll_lock);

View File

@ -88,17 +88,16 @@ bool mt7915_mac_wtbl_update(struct mt7915_dev *dev, int idx, u32 mask)
0, 5000);
}
static u32 mt7915_mac_wtbl_lmac_read(struct mt7915_dev *dev, u16 wcid,
u16 addr)
static u32 mt7915_mac_wtbl_lmac_addr(struct mt7915_dev *dev, u16 wcid)
{
mt76_wr(dev, MT_WTBLON_TOP_WDUCR,
FIELD_PREP(MT_WTBLON_TOP_WDUCR_GROUP, (wcid >> 7)));
return mt76_rr(dev, MT_WTBL_LMAC_OFFS(wcid, addr));
return MT_WTBL_LMAC_OFFS(wcid, 0);
}
/* TODO: use txfree airtime info to avoid runtime accessing in the long run */
void mt7915_mac_sta_poll(struct mt7915_dev *dev)
static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
{
static const u8 ac_to_tid[] = {
[IEEE80211_AC_BE] = 0,
@ -106,47 +105,50 @@ void mt7915_mac_sta_poll(struct mt7915_dev *dev)
[IEEE80211_AC_VI] = 4,
[IEEE80211_AC_VO] = 6
};
static const u8 hw_queue_map[] = {
[IEEE80211_AC_BK] = 0,
[IEEE80211_AC_BE] = 1,
[IEEE80211_AC_VI] = 2,
[IEEE80211_AC_VO] = 3,
};
struct ieee80211_sta *sta;
struct mt7915_sta *msta;
u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS];
LIST_HEAD(sta_poll_list);
int i;
spin_lock_bh(&dev->sta_poll_lock);
list_splice_init(&dev->sta_poll_list, &sta_poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
rcu_read_lock();
while (true) {
bool clear = false;
u32 addr;
u16 idx;
spin_lock_bh(&dev->sta_poll_lock);
if (list_empty(&dev->sta_poll_list)) {
if (list_empty(&sta_poll_list)) {
spin_unlock_bh(&dev->sta_poll_lock);
break;
}
msta = list_first_entry(&dev->sta_poll_list,
msta = list_first_entry(&sta_poll_list,
struct mt7915_sta, poll_list);
list_del_init(&msta->poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
for (i = 0, idx = msta->wcid.idx; i < IEEE80211_NUM_ACS; i++) {
u32 tx_last = msta->airtime_ac[i];
u32 rx_last = msta->airtime_ac[i + IEEE80211_NUM_ACS];
idx = msta->wcid.idx;
addr = mt7915_mac_wtbl_lmac_addr(dev, idx) + 20 * 4;
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
u32 tx_last = msta->airtime_ac[i];
u32 rx_last = msta->airtime_ac[i + 4];
msta->airtime_ac[i] = mt76_rr(dev, addr);
msta->airtime_ac[i + 4] = mt76_rr(dev, addr + 4);
msta->airtime_ac[i] =
mt7915_mac_wtbl_lmac_read(dev, idx, 20 + i);
msta->airtime_ac[i + IEEE80211_NUM_ACS] =
mt7915_mac_wtbl_lmac_read(dev, idx, 21 + i);
tx_time[i] = msta->airtime_ac[i] - tx_last;
rx_time[i] = msta->airtime_ac[i + IEEE80211_NUM_ACS] -
rx_last;
rx_time[i] = msta->airtime_ac[i + 4] - rx_last;
if ((tx_last | rx_last) & BIT(30))
clear = true;
addr += 8;
}
if (clear) {
@ -161,8 +163,9 @@ void mt7915_mac_sta_poll(struct mt7915_dev *dev)
sta = container_of((void *)msta, struct ieee80211_sta,
drv_priv);
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
u32 tx_cur = tx_time[i];
u32 rx_cur = rx_time[hw_queue_map[i]];
u8 q = mt7915_lmac_mapping(dev, i);
u32 tx_cur = tx_time[q];
u32 rx_cur = rx_time[q];
u8 tid = ac_to_tid[i];
if (!tx_cur && !rx_cur)
@ -468,7 +471,7 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
switch (mode) {
case MT_PHY_TYPE_CCK:
cck = true;
/* fall through */
fallthrough;
case MT_PHY_TYPE_OFDM:
i = mt76_get_rate(&dev->mt76, sband, i, cck);
break;
@ -487,7 +490,7 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
break;
case MT_PHY_TYPE_HE_MU:
status->flag |= RX_FLAG_RADIOTAP_HE_MU;
/* fall through */
fallthrough;
case MT_PHY_TYPE_HE_SU:
case MT_PHY_TYPE_HE_EXT_SU:
case MT_PHY_TYPE_HE_TB:
@ -565,13 +568,15 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
bool multicast = is_multicast_ether_addr(hdr->addr1);
struct ieee80211_vif *vif = info->control.vif;
struct mt76_phy *mphy = &dev->mphy;
bool ext_phy = info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY;
u8 fc_type, fc_stype, p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
__le16 fc = hdr->frame_control;
u16 tx_count = 4, seqno = 0;
u16 tx_count = 15, seqno = 0;
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
u32 val;
if (vif) {
@ -587,6 +592,10 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2;
fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4;
txwi[4] = 0;
txwi[5] = 0;
txwi[6] = 0;
if (beacon) {
p_fmt = MT_TX_TYPE_FW;
q_idx = MT_LMAC_BCN0;
@ -599,6 +608,20 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
mt7915_lmac_mapping(dev, skb_get_queue_mapping(skb));
}
if (ieee80211_is_action(fc) &&
mgmt->u.action.category == WLAN_CATEGORY_BACK &&
mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) {
u16 capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
txwi[5] |= cpu_to_le32(MT_TXD5_ADD_BA);
tid = (capab >> 2) & IEEE80211_QOS_CTL_TID_MASK;
} else if (ieee80211_is_back_req(hdr->frame_control)) {
struct ieee80211_bar *bar = (struct ieee80211_bar *)hdr;
u16 control = le16_to_cpu(bar->control);
tid = FIELD_GET(IEEE80211_BAR_CTRL_TID_INFO_MASK, control);
}
val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + MT_TXD_SIZE) |
FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) |
FIELD_PREP(MT_TXD0_Q_IDX, q_idx);
@ -609,8 +632,7 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) |
FIELD_PREP(MT_TXD1_HDR_INFO,
ieee80211_get_hdrlen_from_skb(skb) / 2) |
FIELD_PREP(MT_TXD1_TID,
skb->priority & IEEE80211_QOS_CTL_TID_MASK) |
FIELD_PREP(MT_TXD1_TID, tid) |
FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
if (ext_phy && q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0)
@ -634,10 +656,6 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
}
txwi[2] = cpu_to_le32(val);
txwi[4] = 0;
txwi[5] = 0;
txwi[6] = 0;
if (!ieee80211_is_data(fc) || multicast) {
u16 rate;
@ -665,20 +683,24 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
val = FIELD_PREP(MT_TXD7_TYPE, fc_type) |
FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype);
if (wcid->amsdu)
val |= MT_TXD7_HW_AMSDU;
txwi[7] = cpu_to_le32(val);
val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count);
if (ieee80211_is_data_qos(fc)) {
seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
val |= MT_TXD3_SN_VALID;
} else if (ieee80211_is_back_req(fc)) {
struct ieee80211_bar *bar;
if (info->flags & IEEE80211_TX_CTL_INJECTED) {
seqno = le16_to_cpu(hdr->seq_ctrl);
bar = (struct ieee80211_bar *)skb->data;
seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(bar->start_seq_num));
val |= MT_TXD3_SN_VALID;
if (ieee80211_is_back_req(hdr->frame_control)) {
struct ieee80211_bar *bar;
bar = (struct ieee80211_bar *)skb->data;
seqno = le16_to_cpu(bar->start_seq_num);
}
val |= MT_TXD3_SN_VALID |
FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno));
}
val |= FIELD_PREP(MT_TXD3_SEQ, seqno);
txwi[3] |= cpu_to_le32(val);
}
@ -715,6 +737,7 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
/* pass partial skb header to fw */
tx_info->buf[1].len = MT_CT_PARSE_LEN;
tx_info->buf[1].skip_unmap = true;
tx_info->nbuf = MT_CT_DMA_BUF_NUM;
txp->flags = cpu_to_le16(MT_CT_INFO_APPLY_TXD);
@ -747,45 +770,29 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
return 0;
}
static inline bool
mt7915_tx_check_aggr_tid(struct mt7915_sta *msta, u8 tid)
{
bool ret = false;
spin_lock_bh(&msta->ampdu_lock);
if (msta->ampdu_state[tid] == MT7915_AGGR_STOP)
ret = true;
spin_unlock_bh(&msta->ampdu_lock);
return ret;
}
static void
mt7915_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb)
mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct mt7915_sta *msta;
u16 tid;
u16 fc, tid;
u32 val;
if (!sta->ht_cap.ht_supported)
if (!sta || !sta->ht_cap.ht_supported)
return;
if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
tid = FIELD_GET(MT_TXD1_TID, le32_to_cpu(txwi[1]));
if (tid >= 6) /* skip VO queue */
return;
if (unlikely(!ieee80211_is_data_qos(hdr->frame_control)))
return;
if (unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE)))
val = le32_to_cpu(txwi[2]);
fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 |
FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4;
if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)))
return;
msta = (struct mt7915_sta *)sta->drv_priv;
tid = ieee80211_get_tid(hdr);
if (mt7915_tx_check_aggr_tid(msta, tid)) {
if (!test_and_set_bit(tid, &msta->ampdu_state))
ieee80211_start_tx_ba_session(sta, tid, 0);
mt7915_set_aggr_state(msta, tid, MT7915_AGGR_PROGRESS);
}
}
static inline void
@ -822,8 +829,6 @@ mt7915_tx_complete_status(struct mt76_dev *mdev, struct sk_buff *skb,
if (info->flags & IEEE80211_TX_CTL_AMPDU)
info->flags |= IEEE80211_TX_STAT_AMPDU;
else if (sta)
mt7915_tx_check_aggr(sta, skb);
if (stat)
ieee80211_tx_info_clear_status(info);
@ -864,6 +869,10 @@ void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
struct ieee80211_sta *sta = NULL;
u8 i, count;
/* clean DMA queues and unmap buffers first */
mt76_queue_tx_cleanup(dev, MT_TXQ_PSD, false);
mt76_queue_tx_cleanup(dev, MT_TXQ_BE, false);
/*
* TODO: MT_TX_FREE_LATENCY is msdu time from the TXD is queued into PLE,
* to the time ack is received or dropped by hw (air + hw queue time).
@ -880,6 +889,7 @@ void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
*/
if (info & MT_TX_FREE_PAIR) {
struct mt7915_sta *msta;
struct mt7915_phy *phy;
struct mt76_wcid *wcid;
u16 idx;
@ -891,8 +901,13 @@ void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
continue;
msta = container_of(wcid, struct mt7915_sta, wcid);
ieee80211_queue_work(mt76_hw(dev), &msta->stats_work);
continue;
phy = msta->vif->phy;
spin_lock_bh(&dev->sta_poll_lock);
if (list_empty(&msta->stats_list))
list_add_tail(&msta->stats_list, &phy->stats_list);
if (list_empty(&msta->poll_list))
list_add_tail(&msta->poll_list, &dev->sta_poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
}
msdu = FIELD_GET(MT_TX_FREE_MSDU_ID, info);
@ -907,6 +922,21 @@ void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
mt7915_txp_skb_unmap(mdev, txwi);
if (txwi->skb) {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txwi->skb);
void *txwi_ptr = mt76_get_txwi_ptr(mdev, txwi);
if (likely(txwi->skb->protocol != cpu_to_be16(ETH_P_PAE)))
mt7915_tx_check_aggr(sta, txwi_ptr);
if (sta && !info->tx_time_est) {
struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
int pending;
pending = atomic_dec_return(&wcid->non_aql_packets);
if (pending < 0)
atomic_cmpxchg(&wcid->non_aql_packets, pending, 0);
}
mt7915_tx_complete_status(mdev, txwi->skb, sta, stat);
txwi->skb = NULL;
}
@ -914,10 +944,12 @@ void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
mt76_put_txwi(mdev, txwi);
}
dev_kfree_skb(skb);
mt7915_mac_sta_poll(dev);
mt76_worker_schedule(&dev->mt76.tx_worker);
}
void mt7915_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid,
struct mt76_queue_entry *e)
void mt7915_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
{
struct mt7915_dev *dev;
@ -1186,7 +1218,7 @@ void mt7915_mac_reset_work(struct work_struct *work)
if (ext_phy)
mt76_txq_schedule_all(ext_phy);
tasklet_disable(&dev->mt76.tx_tasklet);
mt76_worker_disable(&dev->mt76.tx_worker);
napi_disable(&dev->mt76.napi[0]);
napi_disable(&dev->mt76.napi[1]);
napi_disable(&dev->mt76.napi[2]);
@ -1206,7 +1238,7 @@ void mt7915_mac_reset_work(struct work_struct *work)
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
clear_bit(MT76_RESET, &dev->mphy.state);
tasklet_enable(&dev->mt76.tx_tasklet);
mt76_worker_enable(&dev->mt76.tx_worker);
napi_enable(&dev->mt76.tx_napi);
napi_schedule(&dev->mt76.tx_napi);
@ -1281,39 +1313,63 @@ mt7915_mac_update_mib_stats(struct mt7915_phy *phy)
}
}
void mt7915_mac_sta_stats_work(struct work_struct *work)
static void
mt7915_mac_sta_stats_work(struct mt7915_phy *phy)
{
struct ieee80211_sta *sta;
struct ieee80211_vif *vif;
struct mt7915_sta_stats *stats;
struct mt7915_dev *dev = phy->dev;
struct mt7915_sta *msta;
struct mt7915_dev *dev;
msta = container_of(work, struct mt7915_sta, stats_work);
sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
dev = msta->vif->dev;
stats = &msta->stats;
/* use MT_TX_FREE_RATE to report Tx rate for further devices */
if (time_after(jiffies, stats->jiffies + HZ)) {
mt7915_mcu_get_rate_info(dev, RATE_CTRL_RU_INFO,
msta->wcid.idx);
stats->jiffies = jiffies;
}
if (test_and_clear_bit(IEEE80211_RC_SUPP_RATES_CHANGED |
IEEE80211_RC_NSS_CHANGED |
IEEE80211_RC_BW_CHANGED, &stats->changed))
mt7915_mcu_add_rate_ctrl(dev, vif, sta);
if (test_and_clear_bit(IEEE80211_RC_SMPS_CHANGED, &stats->changed))
mt7915_mcu_add_smps(dev, vif, sta);
LIST_HEAD(list);
spin_lock_bh(&dev->sta_poll_lock);
if (list_empty(&msta->poll_list))
list_add_tail(&msta->poll_list, &dev->sta_poll_list);
list_splice_init(&phy->stats_list, &list);
while (!list_empty(&list)) {
msta = list_first_entry(&list, struct mt7915_sta, stats_list);
list_del_init(&msta->stats_list);
spin_unlock_bh(&dev->sta_poll_lock);
/* use MT_TX_FREE_RATE to report Tx rate for further devices */
mt7915_mcu_get_rate_info(dev, RATE_CTRL_RU_INFO, msta->wcid.idx);
spin_lock_bh(&dev->sta_poll_lock);
}
spin_unlock_bh(&dev->sta_poll_lock);
}
void mt7915_mac_sta_rc_work(struct work_struct *work)
{
struct mt7915_dev *dev = container_of(work, struct mt7915_dev, rc_work);
struct ieee80211_sta *sta;
struct ieee80211_vif *vif;
struct mt7915_sta *msta;
u32 changed;
LIST_HEAD(list);
spin_lock_bh(&dev->sta_poll_lock);
list_splice_init(&dev->sta_rc_list, &list);
while (!list_empty(&list)) {
msta = list_first_entry(&list, struct mt7915_sta, rc_list);
list_del_init(&msta->rc_list);
changed = msta->stats.changed;
msta->stats.changed = 0;
spin_unlock_bh(&dev->sta_poll_lock);
sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
if (changed & (IEEE80211_RC_SUPP_RATES_CHANGED |
IEEE80211_RC_NSS_CHANGED |
IEEE80211_RC_BW_CHANGED))
mt7915_mcu_add_rate_ctrl(dev, vif, sta);
if (changed & IEEE80211_RC_SMPS_CHANGED)
mt7915_mcu_add_smps(dev, vif, sta);
spin_lock_bh(&dev->sta_poll_lock);
}
spin_unlock_bh(&dev->sta_poll_lock);
}
@ -1335,6 +1391,11 @@ void mt7915_mac_work(struct work_struct *work)
mt7915_mac_update_mib_stats(phy);
}
if (++phy->sta_work_count == 10) {
phy->sta_work_count = 0;
mt7915_mac_sta_stats_work(phy);
};
mutex_unlock(&mdev->mutex);
ieee80211_queue_delayed_work(phy->mt76->hw, &phy->mac_work,

View File

@ -137,7 +137,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
goto out;
}
mvif->omac_idx = idx;
mvif->dev = dev;
mvif->phy = phy;
mvif->band_idx = ext_phy;
if (ext_phy)
@ -155,6 +155,8 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
idx = MT7915_WTBL_RESERVED - mvif->idx;
INIT_LIST_HEAD(&mvif->sta.rc_list);
INIT_LIST_HEAD(&mvif->sta.stats_list);
INIT_LIST_HEAD(&mvif->sta.poll_list);
mvif->sta.wcid.idx = idx;
mvif->sta.wcid.ext_phy = mvif->band_idx;
@ -167,7 +169,6 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
if (vif->txq) {
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
mtxq->wcid = &mvif->sta.wcid;
mt76_txq_init(&dev->mt76, vif->txq);
}
out:
@ -190,8 +191,6 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw,
mt7915_mcu_add_dev_info(dev, vif, false);
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
if (vif->txq)
mt76_txq_remove(&dev->mt76, vif->txq);
mutex_lock(&dev->mt76.mutex);
phy->mt76->vif_mask &= ~BIT(mvif->idx);
@ -493,9 +492,9 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
if (idx < 0)
return -ENOSPC;
INIT_LIST_HEAD(&msta->rc_list);
INIT_LIST_HEAD(&msta->stats_list);
INIT_LIST_HEAD(&msta->poll_list);
INIT_WORK(&msta->stats_work, mt7915_mac_sta_stats_work);
spin_lock_init(&msta->ampdu_lock);
msta->vif = mvif;
msta->wcid.sta = 1;
msta->wcid.idx = idx;
@ -528,6 +527,10 @@ void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
spin_lock_bh(&dev->sta_poll_lock);
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
if (!list_empty(&msta->stats_list))
list_del_init(&msta->stats_list);
if (!list_empty(&msta->rc_list))
list_del_init(&msta->rc_list);
spin_unlock_bh(&dev->sta_poll_lock);
}
@ -603,23 +606,21 @@ mt7915_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
case IEEE80211_AMPDU_TX_OPERATIONAL:
mtxq->aggr = true;
mtxq->send_bar = false;
mt7915_set_aggr_state(msta, tid, MT7915_AGGR_OPERATIONAL);
mt7915_mcu_add_tx_ba(dev, params, true);
break;
case IEEE80211_AMPDU_TX_STOP_FLUSH:
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
mtxq->aggr = false;
mt7915_set_aggr_state(msta, tid, MT7915_AGGR_STOP);
clear_bit(tid, &msta->ampdu_state);
mt7915_mcu_add_tx_ba(dev, params, false);
break;
case IEEE80211_AMPDU_TX_START:
mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(ssn);
mt7915_set_aggr_state(msta, tid, MT7915_AGGR_START);
set_bit(tid, &msta->ampdu_state);
ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
break;
case IEEE80211_AMPDU_TX_STOP_CONT:
mtxq->aggr = false;
mt7915_set_aggr_state(msta, tid, MT7915_AGGR_STOP);
clear_bit(tid, &msta->ampdu_state);
mt7915_mcu_add_tx_ba(dev, params, false);
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
@ -789,18 +790,16 @@ mt7915_sta_rc_update(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
u32 changed)
{
struct mt7915_dev *dev = mt7915_hw_dev(hw);
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
rcu_read_lock();
sta = ieee80211_find_sta(vif, sta->addr);
if (!sta) {
rcu_read_unlock();
return;
}
rcu_read_unlock();
spin_lock_bh(&dev->sta_poll_lock);
msta->stats.changed |= changed;
if (list_empty(&msta->rc_list))
list_add_tail(&msta->rc_list, &dev->sta_rc_list);
spin_unlock_bh(&dev->sta_poll_lock);
set_bit(changed, &msta->stats.changed);
ieee80211_queue_work(hw, &msta->stats_work);
ieee80211_queue_work(hw, &dev->rc_work);
}
const struct ieee80211_ops mt7915_ops = {

View File

@ -522,6 +522,9 @@ mt7915_mcu_tx_rate_report(struct mt7915_dev *dev, struct sk_buff *skb)
return;
wcid = rcu_dereference(dev->mt76.wcid[wcidx]);
if (!wcid)
return;
msta = container_of(wcid, struct mt7915_sta, wcid);
stats = &msta->stats;
@ -714,8 +717,8 @@ mt7915_mcu_add_nested_subtlv(struct sk_buff *skb, int sub_tag, int sub_len,
ptlv = skb_put(skb, sub_len);
memcpy(ptlv, &tlv, sizeof(tlv));
*sub_ntlv = cpu_to_le16(le16_to_cpu(*sub_ntlv) + 1);
*len = cpu_to_le16(le16_to_cpu(*len) + sub_len);
le16_add_cpu(sub_ntlv, 1);
le16_add_cpu(len, sub_len);
return ptlv;
}
@ -933,11 +936,11 @@ mt7915_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_HE_BASIC, sizeof(*he));
he = (struct bss_info_he *)tlv;
he->he_pe_duration = vif->bss_conf.htc_trig_based_pkt_ext * 4;
he->he_pe_duration = vif->bss_conf.htc_trig_based_pkt_ext;
if (!he->he_pe_duration)
he->he_pe_duration = DEFAULT_HE_PE_DURATION;
he->he_rts_thres = cpu_to_le16(vif->bss_conf.frame_time_rts_th * 32);
he->he_rts_thres = cpu_to_le16(vif->bss_conf.frame_time_rts_th);
if (!he->he_rts_thres)
he->he_rts_thres = cpu_to_le16(DEFAULT_HE_DURATION_RTS_THRES);
@ -946,6 +949,23 @@ mt7915_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
he->max_nss_mcs[CMD_HE_MCS_BW8080] = cap->he_mcs_nss_supp.tx_mcs_80p80;
}
static void
mt7915_mcu_bss_hw_amsdu_tlv(struct sk_buff *skb)
{
#define TXD_CMP_MAP1 GENMASK(15, 0)
#define TXD_CMP_MAP2 (GENMASK(31, 0) & ~BIT(23))
struct bss_info_hw_amsdu *amsdu;
struct tlv *tlv;
tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_HW_AMSDU, sizeof(*amsdu));
amsdu = (struct bss_info_hw_amsdu *)tlv;
amsdu->cmp_bitmap_0 = cpu_to_le32(TXD_CMP_MAP1);
amsdu->cmp_bitmap_1 = cpu_to_le32(TXD_CMP_MAP2);
amsdu->trig_thres = cpu_to_le16(2);
amsdu->enable = true;
}
static void
mt7915_mcu_bss_ext_tlv(struct sk_buff *skb, struct mt7915_vif *mvif)
{
@ -1020,6 +1040,7 @@ int mt7915_mcu_add_bss_info(struct mt7915_phy *phy,
mt7915_mcu_bss_rfch_tlv(skb, vif, phy);
mt7915_mcu_bss_bmc_tlv(skb, phy);
mt7915_mcu_bss_ra_tlv(skb, vif, phy);
mt7915_mcu_bss_hw_amsdu_tlv(skb);
if (vif->bss_conf.he_support)
mt7915_mcu_bss_he_tlv(skb, vif, phy);
@ -1178,6 +1199,9 @@ mt7915_mcu_sta_ba(struct mt7915_dev *dev,
struct sk_buff *skb;
int ret;
if (enable && tx && !params->amsdu)
msta->wcid.amsdu = false;
skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta,
MT7915_STA_UPDATE_MAX_SIZE);
if (IS_ERR(skb))
@ -1407,7 +1431,7 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
he->max_nss_mcs[CMD_HE_MCS_BW160] =
he_cap->he_mcs_nss_supp.rx_mcs_160;
/* fall through */
fallthrough;
default:
he->max_nss_mcs[CMD_HE_MCS_BW80] =
he_cap->he_mcs_nss_supp.rx_mcs_80;
@ -1440,6 +1464,38 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
he->pkt_ext = 2;
}
static void
mt7915_mcu_sta_uapsd_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
struct ieee80211_vif *vif)
{
struct sta_rec_uapsd *uapsd;
struct tlv *tlv;
if (vif->type != NL80211_IFTYPE_AP || !sta->wme)
return;
tlv = mt7915_mcu_add_tlv(skb, STA_REC_APPS, sizeof(*uapsd));
uapsd = (struct sta_rec_uapsd *)tlv;
if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) {
uapsd->dac_map |= BIT(3);
uapsd->tac_map |= BIT(3);
}
if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI) {
uapsd->dac_map |= BIT(2);
uapsd->tac_map |= BIT(2);
}
if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE) {
uapsd->dac_map |= BIT(1);
uapsd->tac_map |= BIT(1);
}
if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK) {
uapsd->dac_map |= BIT(0);
uapsd->tac_map |= BIT(0);
}
uapsd->max_sp = sta->max_sp;
}
static void
mt7915_mcu_sta_muru_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
{
@ -1511,9 +1567,40 @@ mt7915_mcu_add_mu(struct mt7915_dev *dev, struct ieee80211_vif *vif,
MCU_EXT_CMD_STA_REC_UPDATE, true);
}
static void
mt7915_mcu_sta_amsdu_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
{
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
struct sta_rec_amsdu *amsdu;
struct tlv *tlv;
if (!sta->max_amsdu_len)
return;
tlv = mt7915_mcu_add_tlv(skb, STA_REC_HW_AMSDU, sizeof(*amsdu));
amsdu = (struct sta_rec_amsdu *)tlv;
amsdu->max_amsdu_num = 8;
amsdu->amsdu_en = true;
amsdu->max_mpdu_size = sta->max_amsdu_len >=
IEEE80211_MAX_MPDU_LEN_VHT_7991;
msta->wcid.amsdu = true;
}
static bool
mt7915_hw_amsdu_supported(struct ieee80211_vif *vif)
{
switch (vif->type) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_STATION:
return true;
default:
return false;
}
}
static void
mt7915_mcu_sta_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
struct ieee80211_sta *sta)
struct ieee80211_sta *sta, struct ieee80211_vif *vif)
{
struct tlv *tlv;
@ -1524,6 +1611,9 @@ mt7915_mcu_sta_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
tlv = mt7915_mcu_add_tlv(skb, STA_REC_HT, sizeof(*ht));
ht = (struct sta_rec_ht *)tlv;
ht->ht_cap = cpu_to_le16(sta->ht_cap.cap);
if (mt7915_hw_amsdu_supported(vif))
mt7915_mcu_sta_amsdu_tlv(skb, sta);
}
/* starec vht */
@ -1540,6 +1630,9 @@ mt7915_mcu_sta_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
/* starec he */
if (sta->he_cap.has_he)
mt7915_mcu_sta_he_tlv(skb, sta);
/* starec uapsd */
mt7915_mcu_sta_uapsd_tlv(skb, sta, vif);
}
static void
@ -2176,7 +2269,7 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
mt7915_mcu_sta_basic_tlv(skb, vif, sta, enable);
if (enable && sta)
mt7915_mcu_sta_tlv(dev, skb, sta);
mt7915_mcu_sta_tlv(dev, skb, sta, vif);
sta_wtbl = mt7915_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv));
@ -2335,14 +2428,6 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,
struct bss_info_bcn *bcn;
int len = MT7915_BEACON_UPDATE_SIZE + MAX_BEACON_SIZE;
rskb = mt7915_mcu_alloc_sta_req(dev, mvif, NULL, len);
if (IS_ERR(rskb))
return PTR_ERR(rskb);
tlv = mt7915_mcu_add_tlv(rskb, BSS_INFO_OFFLOAD, sizeof(*bcn));
bcn = (struct bss_info_bcn *)tlv;
bcn->enable = en;
skb = ieee80211_beacon_get_template(hw, vif, &offs);
if (!skb)
return -EINVAL;
@ -2353,6 +2438,16 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,
return -EINVAL;
}
rskb = mt7915_mcu_alloc_sta_req(dev, mvif, NULL, len);
if (IS_ERR(rskb)) {
dev_kfree_skb(skb);
return PTR_ERR(rskb);
}
tlv = mt7915_mcu_add_tlv(rskb, BSS_INFO_OFFLOAD, sizeof(*bcn));
bcn = (struct bss_info_bcn *)tlv;
bcn->enable = en;
if (mvif->band_idx) {
info = IEEE80211_SKB_CB(skb);
info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
@ -2901,6 +2996,7 @@ int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif)
struct ieee80211_tx_queue_params *q = &mvif->queue_params[ac];
struct edca *e = &req.edca[ac];
e->set = WMM_PARAM_SET;
e->queue = ac + mvif->wmm_idx * MT7915_MAX_WMM_SETS;
e->aifs = q->aifs;
e->txop = cpu_to_le16(q->txop);
@ -3052,8 +3148,10 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
.channel_band = chandef->chan->band,
};
if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) &&
chandef->chan->dfs_state != NL80211_DFS_AVAILABLE)
if (dev->mt76.hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
else if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) &&
chandef->chan->dfs_state != NL80211_DFS_AVAILABLE)
req.switch_reason = CH_SWITCH_DFS;
else
req.switch_reason = CH_SWITCH_NORMAL;

View File

@ -402,6 +402,16 @@ struct bss_info_ra {
__le32 fast_interval;
} __packed;
struct bss_info_hw_amsdu {
__le16 tag;
__le16 len;
__le32 cmp_bitmap_0;
__le32 cmp_bitmap_1;
__le16 trig_thres;
u8 enable;
u8 rsv;
} __packed;
struct bss_info_he {
__le16 tag;
__le16 len;
@ -645,6 +655,17 @@ struct sta_rec_vht {
u8 rsv[3];
} __packed;
struct sta_rec_uapsd {
__le16 tag;
__le16 len;
u8 dac_map;
u8 tac_map;
u8 max_sp;
u8 rsv0;
__le16 listen_interval;
u8 rsv1[2];
} __packed;
struct sta_rec_muru {
__le16 tag;
__le16 len;
@ -725,6 +746,15 @@ struct sta_rec_ba {
__le16 winsize;
} __packed;
struct sta_rec_amsdu {
__le16 tag;
__le16 len;
u8 max_amsdu_num;
u8 max_mpdu_size;
u8 amsdu_en;
u8 rsv;
} __packed;
struct sec_key {
u8 cipher_id;
u8 cipher_len;
@ -951,6 +981,8 @@ enum {
sizeof(struct sta_rec_he) + \
sizeof(struct sta_rec_ba) + \
sizeof(struct sta_rec_vht) + \
sizeof(struct sta_rec_uapsd) + \
sizeof(struct sta_rec_amsdu) + \
sizeof(struct tlv) + \
MT7915_WTBL_UPDATE_MAX_SIZE)
@ -962,6 +994,7 @@ enum {
sizeof(struct bss_info_basic) +\
sizeof(struct bss_info_rf_ch) +\
sizeof(struct bss_info_ra) + \
sizeof(struct bss_info_hw_amsdu) +\
sizeof(struct bss_info_he) + \
sizeof(struct bss_info_bmc_rate) +\
sizeof(struct bss_info_ext_bss) +\

Some files were not shown because too many files have changed in this diff Show More