mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 00:22:00 +02:00
Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for v5.17. Major changes: ath11k * qca6390/wcn6855: report signal and tx bitrate * qca6390: rfkill support * qca6390/wcn6855: regdb.bin support ath5k * switch to rate table based lookup
This commit is contained in:
commit
68b930ad46
|
|
@ -1522,7 +1522,7 @@ static struct ath10k_dump_file_data *ath10k_coredump_build(struct ath10k *ar)
|
|||
mutex_lock(&ar->dump_mutex);
|
||||
|
||||
dump_data = (struct ath10k_dump_file_data *)(buf);
|
||||
strlcpy(dump_data->df_magic, "ATH10K-FW-DUMP",
|
||||
strscpy(dump_data->df_magic, "ATH10K-FW-DUMP",
|
||||
sizeof(dump_data->df_magic));
|
||||
dump_data->len = cpu_to_le32(len);
|
||||
|
||||
|
|
@ -1543,11 +1543,11 @@ static struct ath10k_dump_file_data *ath10k_coredump_build(struct ath10k *ar)
|
|||
dump_data->vht_cap_info = cpu_to_le32(ar->vht_cap_info);
|
||||
dump_data->num_rf_chains = cpu_to_le32(ar->num_rf_chains);
|
||||
|
||||
strlcpy(dump_data->fw_ver, ar->hw->wiphy->fw_version,
|
||||
strscpy(dump_data->fw_ver, ar->hw->wiphy->fw_version,
|
||||
sizeof(dump_data->fw_ver));
|
||||
|
||||
dump_data->kernel_ver_code = 0;
|
||||
strlcpy(dump_data->kernel_ver, init_utsname()->release,
|
||||
strscpy(dump_data->kernel_ver, init_utsname()->release,
|
||||
sizeof(dump_data->kernel_ver));
|
||||
|
||||
dump_data->tv_sec = cpu_to_le64(crash_data->timestamp.tv_sec);
|
||||
|
|
|
|||
|
|
@ -175,8 +175,11 @@ static void __ath11k_ahb_ext_irq_disable(struct ath11k_base *ab)
|
|||
|
||||
ath11k_ahb_ext_grp_disable(irq_grp);
|
||||
|
||||
napi_synchronize(&irq_grp->napi);
|
||||
napi_disable(&irq_grp->napi);
|
||||
if (irq_grp->napi_enabled) {
|
||||
napi_synchronize(&irq_grp->napi);
|
||||
napi_disable(&irq_grp->napi);
|
||||
irq_grp->napi_enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -300,7 +303,10 @@ static void ath11k_ahb_ext_irq_enable(struct ath11k_base *ab)
|
|||
for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
|
||||
struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
|
||||
|
||||
napi_enable(&irq_grp->napi);
|
||||
if (!irq_grp->napi_enabled) {
|
||||
napi_enable(&irq_grp->napi);
|
||||
irq_grp->napi_enabled = true;
|
||||
}
|
||||
ath11k_ahb_ext_grp_enable(irq_grp);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.target_ce_count = 11,
|
||||
.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq8074,
|
||||
.svc_to_ce_map_len = 21,
|
||||
.rfkill_pin = 0,
|
||||
.rfkill_cfg = 0,
|
||||
.rfkill_on_level = 0,
|
||||
.single_pdev_only = false,
|
||||
.rxdma1_enable = true,
|
||||
.num_rxmda_per_pdev = 1,
|
||||
|
|
@ -84,6 +87,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.num_peers = 512,
|
||||
.supports_suspend = false,
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
|
||||
.supports_regdb = false,
|
||||
.fix_l1ss = true,
|
||||
.credit_flow = false,
|
||||
.max_tx_ring = DP_TCL_NUM_RING_MAX,
|
||||
|
|
@ -91,6 +95,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.supports_dynamic_smps_6ghz = false,
|
||||
.alloc_cacheable_memory = true,
|
||||
.wakeup_mhi = false,
|
||||
.supports_rssi_stats = false,
|
||||
.fw_wmi_diag_event = false,
|
||||
},
|
||||
{
|
||||
.hw_rev = ATH11K_HW_IPQ6018_HW10,
|
||||
|
|
@ -113,6 +119,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.target_ce_count = 11,
|
||||
.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq6018,
|
||||
.svc_to_ce_map_len = 19,
|
||||
.rfkill_pin = 0,
|
||||
.rfkill_cfg = 0,
|
||||
.rfkill_on_level = 0,
|
||||
.single_pdev_only = false,
|
||||
.rxdma1_enable = true,
|
||||
.num_rxmda_per_pdev = 1,
|
||||
|
|
@ -142,6 +151,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.num_peers = 512,
|
||||
.supports_suspend = false,
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
|
||||
.supports_regdb = false,
|
||||
.fix_l1ss = true,
|
||||
.credit_flow = false,
|
||||
.max_tx_ring = DP_TCL_NUM_RING_MAX,
|
||||
|
|
@ -149,6 +159,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.supports_dynamic_smps_6ghz = false,
|
||||
.alloc_cacheable_memory = true,
|
||||
.wakeup_mhi = false,
|
||||
.supports_rssi_stats = false,
|
||||
.fw_wmi_diag_event = false,
|
||||
},
|
||||
{
|
||||
.name = "qca6390 hw2.0",
|
||||
|
|
@ -171,6 +183,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.target_ce_count = 9,
|
||||
.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
|
||||
.svc_to_ce_map_len = 14,
|
||||
.rfkill_pin = 48,
|
||||
.rfkill_cfg = 0,
|
||||
.rfkill_on_level = 1,
|
||||
.single_pdev_only = true,
|
||||
.rxdma1_enable = false,
|
||||
.num_rxmda_per_pdev = 2,
|
||||
|
|
@ -199,6 +214,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.num_peers = 512,
|
||||
.supports_suspend = true,
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
|
||||
.supports_regdb = true,
|
||||
.fix_l1ss = true,
|
||||
.credit_flow = true,
|
||||
.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
|
||||
|
|
@ -206,6 +222,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.supports_dynamic_smps_6ghz = false,
|
||||
.alloc_cacheable_memory = false,
|
||||
.wakeup_mhi = true,
|
||||
.supports_rssi_stats = true,
|
||||
.fw_wmi_diag_event = true,
|
||||
},
|
||||
{
|
||||
.name = "qcn9074 hw1.0",
|
||||
|
|
@ -228,6 +246,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.target_ce_count = 9,
|
||||
.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qcn9074,
|
||||
.svc_to_ce_map_len = 18,
|
||||
.rfkill_pin = 0,
|
||||
.rfkill_cfg = 0,
|
||||
.rfkill_on_level = 0,
|
||||
.rxdma1_enable = true,
|
||||
.num_rxmda_per_pdev = 1,
|
||||
.rx_mac_buf_ring = false,
|
||||
|
|
@ -256,6 +277,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.num_peers = 128,
|
||||
.supports_suspend = false,
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074),
|
||||
.supports_regdb = false,
|
||||
.fix_l1ss = true,
|
||||
.credit_flow = false,
|
||||
.max_tx_ring = DP_TCL_NUM_RING_MAX,
|
||||
|
|
@ -263,6 +285,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.supports_dynamic_smps_6ghz = true,
|
||||
.alloc_cacheable_memory = true,
|
||||
.wakeup_mhi = false,
|
||||
.supports_rssi_stats = false,
|
||||
.fw_wmi_diag_event = false,
|
||||
},
|
||||
{
|
||||
.name = "wcn6855 hw2.0",
|
||||
|
|
@ -285,6 +309,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.target_ce_count = 9,
|
||||
.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
|
||||
.svc_to_ce_map_len = 14,
|
||||
.rfkill_pin = 0,
|
||||
.rfkill_cfg = 0,
|
||||
.rfkill_on_level = 0,
|
||||
.single_pdev_only = true,
|
||||
.rxdma1_enable = false,
|
||||
.num_rxmda_per_pdev = 2,
|
||||
|
|
@ -313,6 +340,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.num_peers = 512,
|
||||
.supports_suspend = true,
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),
|
||||
.supports_regdb = true,
|
||||
.fix_l1ss = false,
|
||||
.credit_flow = true,
|
||||
.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
|
||||
|
|
@ -320,6 +348,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.supports_dynamic_smps_6ghz = false,
|
||||
.alloc_cacheable_memory = false,
|
||||
.wakeup_mhi = true,
|
||||
.supports_rssi_stats = true,
|
||||
.fw_wmi_diag_event = true,
|
||||
},
|
||||
{
|
||||
.name = "wcn6855 hw2.1",
|
||||
|
|
@ -342,6 +372,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.target_ce_count = 9,
|
||||
.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
|
||||
.svc_to_ce_map_len = 14,
|
||||
.rfkill_pin = 0,
|
||||
.rfkill_cfg = 0,
|
||||
.rfkill_on_level = 0,
|
||||
.single_pdev_only = true,
|
||||
.rxdma1_enable = false,
|
||||
.num_rxmda_per_pdev = 2,
|
||||
|
|
@ -369,6 +402,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.num_peers = 512,
|
||||
.supports_suspend = true,
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),
|
||||
.supports_regdb = true,
|
||||
.fix_l1ss = false,
|
||||
.credit_flow = true,
|
||||
.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
|
||||
|
|
@ -376,6 +410,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.supports_dynamic_smps_6ghz = false,
|
||||
.alloc_cacheable_memory = false,
|
||||
.wakeup_mhi = true,
|
||||
.supports_rssi_stats = true,
|
||||
.fw_wmi_diag_event = true,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -736,10 +772,12 @@ static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int ath11k_core_fetch_board_data_api_1(struct ath11k_base *ab,
|
||||
struct ath11k_board_data *bd)
|
||||
int ath11k_core_fetch_board_data_api_1(struct ath11k_base *ab,
|
||||
struct ath11k_board_data *bd,
|
||||
const char *name)
|
||||
{
|
||||
bd->fw = ath11k_core_firmware_request(ab, ATH11K_DEFAULT_BOARD_FILE);
|
||||
bd->fw = ath11k_core_firmware_request(ab, name);
|
||||
|
||||
if (IS_ERR(bd->fw))
|
||||
return PTR_ERR(bd->fw);
|
||||
|
||||
|
|
@ -767,7 +805,7 @@ int ath11k_core_fetch_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd)
|
|||
goto success;
|
||||
|
||||
ab->bd_api = 1;
|
||||
ret = ath11k_core_fetch_board_data_api_1(ab, bd);
|
||||
ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_DEFAULT_BOARD_FILE);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to fetch board-2.bin or board.bin from %s\n",
|
||||
ab->hw_params.fw.dir);
|
||||
|
|
@ -779,6 +817,18 @@ int ath11k_core_fetch_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ath11k_core_fetch_regdb(struct ath11k_base *ab, struct ath11k_board_data *bd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_REGDB_FILE_NAME);
|
||||
if (ret)
|
||||
ath11k_dbg(ab, ATH11K_DBG_BOOT, "failed to fetch %s from %s\n",
|
||||
ATH11K_REGDB_FILE_NAME, ab->hw_params.fw.dir);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath11k_core_stop(struct ath11k_base *ab)
|
||||
{
|
||||
if (!test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags))
|
||||
|
|
@ -1009,6 +1059,27 @@ static int ath11k_core_start(struct ath11k_base *ab,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int ath11k_core_rfkill_config(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k *ar;
|
||||
int ret = 0, i;
|
||||
|
||||
if (!(ab->target_caps.sys_cap_info & WMI_SYS_CAP_INFO_RFKILL))
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
ar = ab->pdevs[i].ar;
|
||||
|
||||
ret = ath11k_mac_rfkill_config(ar);
|
||||
if (ret && ret != -EOPNOTSUPP) {
|
||||
ath11k_warn(ab, "failed to configure rfkill: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -1055,6 +1126,13 @@ int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab)
|
|||
goto err_core_stop;
|
||||
}
|
||||
ath11k_hif_irq_enable(ab);
|
||||
|
||||
ret = ath11k_core_rfkill_config(ab);
|
||||
if (ret && ret != -EOPNOTSUPP) {
|
||||
ath11k_err(ab, "failed to config rfkill: %d\n", ret);
|
||||
goto err_core_stop;
|
||||
}
|
||||
|
||||
mutex_unlock(&ab->core_lock);
|
||||
|
||||
return 0;
|
||||
|
|
@ -1120,6 +1198,7 @@ void ath11k_core_halt(struct ath11k *ar)
|
|||
cancel_delayed_work_sync(&ar->scan.timeout);
|
||||
cancel_work_sync(&ar->regd_update_work);
|
||||
cancel_work_sync(&ab->update_11d_work);
|
||||
cancel_work_sync(&ab->rfkill_work);
|
||||
|
||||
rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL);
|
||||
synchronize_rcu();
|
||||
|
|
@ -1127,6 +1206,28 @@ void ath11k_core_halt(struct ath11k *ar)
|
|||
idr_init(&ar->txmgmt_idr);
|
||||
}
|
||||
|
||||
static void ath11k_rfkill_work(struct work_struct *work)
|
||||
{
|
||||
struct ath11k_base *ab = container_of(work, struct ath11k_base, rfkill_work);
|
||||
struct ath11k *ar;
|
||||
bool rfkill_radio_on;
|
||||
int i;
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
rfkill_radio_on = ab->rfkill_radio_on;
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
ar = ab->pdevs[i].ar;
|
||||
if (!ar)
|
||||
continue;
|
||||
|
||||
/* notify cfg80211 radio state change */
|
||||
ath11k_mac_rfkill_enable_radio(ar, rfkill_radio_on);
|
||||
wiphy_rfkill_set_hw_state(ar->hw->wiphy, !rfkill_radio_on);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath11k_update_11d(struct work_struct *work)
|
||||
{
|
||||
struct ath11k_base *ab = container_of(work, struct ath11k_base, update_11d_work);
|
||||
|
|
@ -1333,6 +1434,7 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,
|
|||
init_waitqueue_head(&ab->qmi.cold_boot_waitq);
|
||||
INIT_WORK(&ab->restart_work, ath11k_core_restart);
|
||||
INIT_WORK(&ab->update_11d_work, ath11k_update_11d);
|
||||
INIT_WORK(&ab->rfkill_work, ath11k_rfkill_work);
|
||||
timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0);
|
||||
init_completion(&ab->htc_suspend);
|
||||
init_completion(&ab->wow.wakeup_completed);
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ struct ath11k_ext_irq_grp {
|
|||
u32 num_irq;
|
||||
u32 grp_id;
|
||||
u64 timestamp;
|
||||
bool napi_enabled;
|
||||
struct napi_struct napi;
|
||||
struct net_device napi_ndev;
|
||||
};
|
||||
|
|
@ -382,10 +383,13 @@ struct ath11k_sta {
|
|||
struct work_struct update_wk;
|
||||
struct work_struct set_4addr_wk;
|
||||
struct rate_info txrate;
|
||||
u32 peer_nss;
|
||||
struct rate_info last_txrate;
|
||||
u64 rx_duration;
|
||||
u64 tx_duration;
|
||||
u8 rssi_comb;
|
||||
s8 rssi_beacon;
|
||||
s8 chain_signal[IEEE80211_MAX_CHAINS];
|
||||
struct ath11k_htt_tx_stats *tx_stats;
|
||||
struct ath11k_rx_peer_stats *rx_stats;
|
||||
|
||||
|
|
@ -416,6 +420,10 @@ enum ath11k_state {
|
|||
/* Antenna noise floor */
|
||||
#define ATH11K_DEFAULT_NOISE_FLOOR -95
|
||||
|
||||
#define ATH11K_INVALID_RSSI_FULL -1
|
||||
|
||||
#define ATH11K_INVALID_RSSI_EMPTY -128
|
||||
|
||||
struct ath11k_fw_stats {
|
||||
struct dentry *debugfs_fwstats;
|
||||
u32 pdev_id;
|
||||
|
|
@ -736,7 +744,6 @@ struct ath11k_base {
|
|||
u32 wlan_init_status;
|
||||
int irq_num[ATH11K_IRQ_NUM_MAX];
|
||||
struct ath11k_ext_irq_grp ext_irq_grp[ATH11K_EXT_IRQ_GRP_NUM_MAX];
|
||||
struct napi_struct *napi;
|
||||
struct ath11k_targ_cap target_caps;
|
||||
u32 ext_service_bitmap[WMI_SERVICE_EXT_BM_SIZE];
|
||||
bool pdevs_macaddr_valid;
|
||||
|
|
@ -779,6 +786,10 @@ struct ath11k_base {
|
|||
|
||||
struct ath11k_dbring_cap *db_caps;
|
||||
u32 num_db_cap;
|
||||
struct work_struct rfkill_work;
|
||||
|
||||
/* true means radio is on */
|
||||
bool rfkill_radio_on;
|
||||
|
||||
/* To synchronize 11d scan vdev id */
|
||||
struct mutex vdev_id_11d_lock;
|
||||
|
|
@ -969,6 +980,10 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,
|
|||
void ath11k_core_free(struct ath11k_base *ath11k);
|
||||
int ath11k_core_fetch_bdf(struct ath11k_base *ath11k,
|
||||
struct ath11k_board_data *bd);
|
||||
int ath11k_core_fetch_regdb(struct ath11k_base *ab, struct ath11k_board_data *bd);
|
||||
int ath11k_core_fetch_board_data_api_1(struct ath11k_base *ab,
|
||||
struct ath11k_board_data *bd,
|
||||
const char *name);
|
||||
void ath11k_core_free_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd);
|
||||
int ath11k_core_check_dt(struct ath11k_base *ath11k);
|
||||
|
||||
|
|
|
|||
|
|
@ -126,6 +126,11 @@ void ath11k_debugfs_fw_stats_process(struct ath11k_base *ab, struct sk_buff *skb
|
|||
goto complete;
|
||||
}
|
||||
|
||||
if (stats.stats_id == WMI_REQUEST_RSSI_PER_CHAIN_STAT) {
|
||||
ar->debug.fw_stats_done = true;
|
||||
goto complete;
|
||||
}
|
||||
|
||||
if (stats.stats_id == WMI_REQUEST_VDEV_STAT) {
|
||||
if (list_empty(&stats.vdevs)) {
|
||||
ath11k_warn(ab, "empty vdev stats");
|
||||
|
|
@ -229,6 +234,38 @@ static int ath11k_debugfs_fw_stats_request(struct ath11k *ar,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id,
|
||||
u32 vdev_id, u32 stats_id)
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct stats_request_params req_param;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (ar->state != ATH11K_STATE_ON) {
|
||||
ret = -ENETDOWN;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
req_param.pdev_id = pdev_id;
|
||||
req_param.vdev_id = vdev_id;
|
||||
req_param.stats_id = stats_id;
|
||||
|
||||
ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
|
||||
if (ret)
|
||||
ath11k_warn(ab, "failed to request fw stats: %d\n", ret);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"debug get fw stat pdev id %d vdev id %d stats id 0x%x\n",
|
||||
pdev_id, vdev_id, stats_id);
|
||||
|
||||
err_unlock:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath11k_open_pdev_stats(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct ath11k *ar = inode->i_private;
|
||||
|
|
|
|||
|
|
@ -117,6 +117,8 @@ 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);
|
||||
int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id,
|
||||
u32 vdev_id, u32 stats_id);
|
||||
|
||||
static inline bool ath11k_debugfs_is_pktlog_lite_mode_enabled(struct ath11k *ar)
|
||||
{
|
||||
|
|
@ -216,6 +218,12 @@ static inline int ath11k_debugfs_rx_filter(struct ath11k *ar)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int ath11k_debugfs_get_fw_stats(struct ath11k *ar,
|
||||
u32 pdev_id, u32 vdev_id, u32 stats_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MAC80211_DEBUGFS*/
|
||||
|
||||
#endif /* _ATH11K_DEBUGFS_H_ */
|
||||
|
|
|
|||
|
|
@ -126,85 +126,9 @@ void ath11k_debugfs_sta_add_tx_stats(struct ath11k_sta *arsta,
|
|||
}
|
||||
|
||||
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;
|
||||
enum hal_tx_rate_stats_pkt_type pkt_type;
|
||||
enum hal_tx_rate_stats_sgi sgi;
|
||||
enum hal_tx_rate_stats_bw bw;
|
||||
struct ath11k_peer *peer;
|
||||
struct ath11k_sta *arsta;
|
||||
struct ieee80211_sta *sta;
|
||||
u16 rate;
|
||||
u8 rate_idx = 0;
|
||||
int ret;
|
||||
u8 mcs;
|
||||
|
||||
rcu_read_lock();
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
peer = ath11k_peer_find_by_id(ab, ts->peer_id);
|
||||
if (!peer || !peer->sta) {
|
||||
ath11k_warn(ab, "failed to find the peer\n");
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
sta = peer->sta;
|
||||
arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
|
||||
memset(&arsta->txrate, 0, sizeof(arsta->txrate));
|
||||
pkt_type = FIELD_GET(HAL_TX_RATE_STATS_INFO0_PKT_TYPE,
|
||||
ts->rate_stats);
|
||||
mcs = FIELD_GET(HAL_TX_RATE_STATS_INFO0_MCS,
|
||||
ts->rate_stats);
|
||||
sgi = FIELD_GET(HAL_TX_RATE_STATS_INFO0_SGI,
|
||||
ts->rate_stats);
|
||||
bw = FIELD_GET(HAL_TX_RATE_STATS_INFO0_BW, ts->rate_stats);
|
||||
|
||||
if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11A ||
|
||||
pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11B) {
|
||||
ret = ath11k_mac_hw_ratecode_to_legacy_rate(mcs,
|
||||
pkt_type,
|
||||
&rate_idx,
|
||||
&rate);
|
||||
if (ret < 0)
|
||||
goto err_out;
|
||||
arsta->txrate.legacy = rate;
|
||||
} else if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11N) {
|
||||
if (mcs > 7) {
|
||||
ath11k_warn(ab, "Invalid HT mcs index %d\n", mcs);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
arsta->txrate.mcs = mcs + 8 * (arsta->last_txrate.nss - 1);
|
||||
arsta->txrate.flags = RATE_INFO_FLAGS_MCS;
|
||||
if (sgi)
|
||||
arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
} else if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11AC) {
|
||||
if (mcs > 9) {
|
||||
ath11k_warn(ab, "Invalid VHT mcs index %d\n", mcs);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
arsta->txrate.mcs = mcs;
|
||||
arsta->txrate.flags = RATE_INFO_FLAGS_VHT_MCS;
|
||||
if (sgi)
|
||||
arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
} else if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11AX) {
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
arsta->txrate.nss = arsta->last_txrate.nss;
|
||||
arsta->txrate.bw = ath11k_mac_bw_to_mac80211_bw(bw);
|
||||
|
||||
ath11k_debugfs_sta_add_tx_stats(arsta, peer_stats, rate_idx);
|
||||
|
||||
err_out:
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
rcu_read_unlock();
|
||||
ath11k_dp_tx_update_txcompl(ar, ts);
|
||||
}
|
||||
|
||||
static ssize_t ath11k_dbg_sta_dump_tx_stats(struct file *file,
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ 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 */
|
||||
|
|
@ -34,7 +33,6 @@ ath11k_debugfs_sta_add_tx_stats(struct ath11k_sta *arsta,
|
|||
}
|
||||
|
||||
static inline void ath11k_debugfs_sta_update_txcompl(struct ath11k *ar,
|
||||
struct sk_buff *msdu,
|
||||
struct hal_tx_status *ts)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1360,25 +1360,6 @@ int ath11k_dp_htt_tlv_iter(struct ath11k_base *ab, const void *ptr, size_t len,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline u32 ath11k_he_gi_to_nl80211_he_gi(u8 sgi)
|
||||
{
|
||||
u32 ret = 0;
|
||||
|
||||
switch (sgi) {
|
||||
case RX_MSDU_START_SGI_0_8_US:
|
||||
ret = NL80211_RATE_INFO_HE_GI_0_8;
|
||||
break;
|
||||
case RX_MSDU_START_SGI_1_6_US:
|
||||
ret = NL80211_RATE_INFO_HE_GI_1_6;
|
||||
break;
|
||||
case RX_MSDU_START_SGI_3_2_US:
|
||||
ret = NL80211_RATE_INFO_HE_GI_3_2;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
ath11k_update_per_peer_tx_stats(struct ath11k *ar,
|
||||
struct htt_ppdu_stats *ppdu_stats, u8 user)
|
||||
|
|
@ -1497,14 +1478,15 @@ ath11k_update_per_peer_tx_stats(struct ath11k *ar,
|
|||
arsta->txrate.mcs = mcs;
|
||||
arsta->txrate.flags = RATE_INFO_FLAGS_HE_MCS;
|
||||
arsta->txrate.he_dcm = dcm;
|
||||
arsta->txrate.he_gi = ath11k_he_gi_to_nl80211_he_gi(sgi);
|
||||
arsta->txrate.he_ru_alloc = ath11k_he_ru_tones_to_nl80211_he_ru_alloc(
|
||||
(user_rate->ru_end -
|
||||
arsta->txrate.he_gi = ath11k_mac_he_gi_to_nl80211_he_gi(sgi);
|
||||
arsta->txrate.he_ru_alloc = ath11k_mac_phy_he_ru_to_nl80211_he_ru_alloc
|
||||
((user_rate->ru_end -
|
||||
user_rate->ru_start) + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
arsta->txrate.nss = nss;
|
||||
|
||||
arsta->txrate.bw = ath11k_mac_bw_to_mac80211_bw(bw);
|
||||
arsta->tx_duration += tx_duration;
|
||||
memcpy(&arsta->last_txrate, &arsta->txrate, sizeof(struct rate_info));
|
||||
|
|
@ -2384,7 +2366,7 @@ static void ath11k_dp_rx_h_rate(struct ath11k *ar, struct hal_rx_desc *rx_desc,
|
|||
}
|
||||
rx_status->encoding = RX_ENC_HE;
|
||||
rx_status->nss = nss;
|
||||
rx_status->he_gi = ath11k_he_gi_to_nl80211_he_gi(sgi);
|
||||
rx_status->he_gi = ath11k_mac_he_gi_to_nl80211_he_gi(sgi);
|
||||
rx_status->bw = ath11k_mac_bw_to_mac80211_bw(bw);
|
||||
break;
|
||||
}
|
||||
|
|
@ -2768,6 +2750,7 @@ static void ath11k_dp_rx_update_peer_stats(struct ath11k_sta *arsta,
|
|||
{
|
||||
struct ath11k_rx_peer_stats *rx_stats = arsta->rx_stats;
|
||||
u32 num_msdu;
|
||||
int i;
|
||||
|
||||
if (!rx_stats)
|
||||
return;
|
||||
|
|
@ -2829,6 +2812,13 @@ static void ath11k_dp_rx_update_peer_stats(struct ath11k_sta *arsta,
|
|||
rx_stats->ru_alloc_cnt[ppdu_info->ru_alloc] += num_msdu;
|
||||
|
||||
arsta->rssi_comb = ppdu_info->rssi_comb;
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(arsta->chain_signal) >
|
||||
ARRAY_SIZE(ppdu_info->rssi_chain_pri20));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(arsta->chain_signal); i++)
|
||||
arsta->chain_signal[i] = ppdu_info->rssi_chain_pri20[i];
|
||||
|
||||
rx_stats->rx_duration += ppdu_info->rx_duration;
|
||||
arsta->rx_duration = rx_stats->rx_duration;
|
||||
}
|
||||
|
|
@ -3847,7 +3837,7 @@ int ath11k_dp_process_rx_err(struct ath11k_base *ab, struct napi_struct *napi,
|
|||
ath11k_hal_rx_msdu_link_info_get(link_desc_va, &num_msdus, msdu_cookies,
|
||||
&rbm);
|
||||
if (rbm != HAL_RX_BUF_RBM_WBM_IDLE_DESC_LIST &&
|
||||
rbm != ab->hw_params.hal_params->rx_buf_rbm) {
|
||||
rbm != HAL_RX_BUF_RBM_SW3_BM) {
|
||||
ab->soc_stats.invalid_rbm++;
|
||||
ath11k_warn(ab, "invalid return buffer manager %d\n", rbm);
|
||||
ath11k_dp_rx_link_desc_return(ab, desc,
|
||||
|
|
|
|||
|
|
@ -415,6 +415,105 @@ static void ath11k_dp_tx_cache_peer_stats(struct ath11k *ar,
|
|||
}
|
||||
}
|
||||
|
||||
void ath11k_dp_tx_update_txcompl(struct ath11k *ar, struct hal_tx_status *ts)
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct ath11k_per_peer_tx_stats *peer_stats = &ar->cached_stats;
|
||||
enum hal_tx_rate_stats_pkt_type pkt_type;
|
||||
enum hal_tx_rate_stats_sgi sgi;
|
||||
enum hal_tx_rate_stats_bw bw;
|
||||
struct ath11k_peer *peer;
|
||||
struct ath11k_sta *arsta;
|
||||
struct ieee80211_sta *sta;
|
||||
u16 rate, ru_tones;
|
||||
u8 mcs, rate_idx, ofdma;
|
||||
int ret;
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
peer = ath11k_peer_find_by_id(ab, ts->peer_id);
|
||||
if (!peer || !peer->sta) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_DP_TX,
|
||||
"failed to find the peer by id %u\n", ts->peer_id);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
sta = peer->sta;
|
||||
arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
|
||||
memset(&arsta->txrate, 0, sizeof(arsta->txrate));
|
||||
pkt_type = FIELD_GET(HAL_TX_RATE_STATS_INFO0_PKT_TYPE,
|
||||
ts->rate_stats);
|
||||
mcs = FIELD_GET(HAL_TX_RATE_STATS_INFO0_MCS,
|
||||
ts->rate_stats);
|
||||
sgi = FIELD_GET(HAL_TX_RATE_STATS_INFO0_SGI,
|
||||
ts->rate_stats);
|
||||
bw = FIELD_GET(HAL_TX_RATE_STATS_INFO0_BW, ts->rate_stats);
|
||||
ru_tones = FIELD_GET(HAL_TX_RATE_STATS_INFO0_TONES_IN_RU, ts->rate_stats);
|
||||
ofdma = FIELD_GET(HAL_TX_RATE_STATS_INFO0_OFDMA_TX, ts->rate_stats);
|
||||
|
||||
/* This is to prefer choose the real NSS value arsta->last_txrate.nss,
|
||||
* if it is invalid, then choose the NSS value while assoc.
|
||||
*/
|
||||
if (arsta->last_txrate.nss)
|
||||
arsta->txrate.nss = arsta->last_txrate.nss;
|
||||
else
|
||||
arsta->txrate.nss = arsta->peer_nss;
|
||||
|
||||
if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11A ||
|
||||
pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11B) {
|
||||
ret = ath11k_mac_hw_ratecode_to_legacy_rate(mcs,
|
||||
pkt_type,
|
||||
&rate_idx,
|
||||
&rate);
|
||||
if (ret < 0)
|
||||
goto err_out;
|
||||
arsta->txrate.legacy = rate;
|
||||
} else if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11N) {
|
||||
if (mcs > 7) {
|
||||
ath11k_warn(ab, "Invalid HT mcs index %d\n", mcs);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (arsta->txrate.nss != 0)
|
||||
arsta->txrate.mcs = mcs + 8 * (arsta->txrate.nss - 1);
|
||||
arsta->txrate.flags = RATE_INFO_FLAGS_MCS;
|
||||
if (sgi)
|
||||
arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
} else if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11AC) {
|
||||
if (mcs > 9) {
|
||||
ath11k_warn(ab, "Invalid VHT mcs index %d\n", mcs);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
arsta->txrate.mcs = mcs;
|
||||
arsta->txrate.flags = RATE_INFO_FLAGS_VHT_MCS;
|
||||
if (sgi)
|
||||
arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
} else if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11AX) {
|
||||
if (mcs > 11) {
|
||||
ath11k_warn(ab, "Invalid HE mcs index %d\n", mcs);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
arsta->txrate.mcs = mcs;
|
||||
arsta->txrate.flags = RATE_INFO_FLAGS_HE_MCS;
|
||||
arsta->txrate.he_gi = ath11k_mac_he_gi_to_nl80211_he_gi(sgi);
|
||||
}
|
||||
|
||||
arsta->txrate.bw = ath11k_mac_bw_to_mac80211_bw(bw);
|
||||
if (ofdma && pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11AX) {
|
||||
arsta->txrate.bw = RATE_INFO_BW_HE_RU;
|
||||
arsta->txrate.he_ru_alloc =
|
||||
ath11k_mac_he_ru_tones_to_nl80211_he_ru_alloc(ru_tones);
|
||||
}
|
||||
|
||||
if (ath11k_debugfs_is_extd_tx_stats_enabled(ar))
|
||||
ath11k_debugfs_sta_add_tx_stats(arsta, peer_stats, rate_idx);
|
||||
|
||||
err_out:
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
}
|
||||
|
||||
static void ath11k_dp_tx_complete_msdu(struct ath11k *ar,
|
||||
struct sk_buff *msdu,
|
||||
struct hal_tx_status *ts)
|
||||
|
|
@ -460,7 +559,8 @@ 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 (unlikely(ath11k_debugfs_is_extd_tx_stats_enabled(ar))) {
|
||||
if (unlikely(ath11k_debugfs_is_extd_tx_stats_enabled(ar)) ||
|
||||
ab->hw_params.single_pdev_only) {
|
||||
if (ts->flags & HAL_TX_STATUS_FLAGS_FIRST_MSDU) {
|
||||
if (ar->last_ppdu_id == 0) {
|
||||
ar->last_ppdu_id = ts->ppdu_id;
|
||||
|
|
@ -468,12 +568,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_debugfs_sta_update_txcompl(ar, msdu, ts);
|
||||
ath11k_dp_tx_update_txcompl(ar, ts);
|
||||
memset(&ar->cached_stats, 0,
|
||||
sizeof(struct ath11k_per_peer_tx_stats));
|
||||
} else {
|
||||
ar->cached_stats.is_ampdu = false;
|
||||
ath11k_debugfs_sta_update_txcompl(ar, msdu, ts);
|
||||
ath11k_dp_tx_update_txcompl(ar, ts);
|
||||
memset(&ar->cached_stats, 0,
|
||||
sizeof(struct ath11k_per_peer_tx_stats));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ struct ath11k_dp_htt_wbm_tx_status {
|
|||
int ack_rssi;
|
||||
};
|
||||
|
||||
void ath11k_dp_tx_update_txcompl(struct ath11k *ar, struct hal_tx_status *ts);
|
||||
int ath11k_dp_tx_htt_h2t_ver_req_msg(struct ath11k_base *ab);
|
||||
int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
|
||||
struct ath11k_sta *arsta, struct sk_buff *skb);
|
||||
|
|
|
|||
|
|
@ -371,7 +371,7 @@ int ath11k_hal_wbm_desc_parse_err(struct ath11k_base *ab, void *desc,
|
|||
|
||||
ret_buf_mgr = FIELD_GET(BUFFER_ADDR_INFO1_RET_BUF_MGR,
|
||||
wbm_desc->buf_addr_info.info1);
|
||||
if (ret_buf_mgr != ab->hw_params.hal_params->rx_buf_rbm) {
|
||||
if (ret_buf_mgr != HAL_RX_BUF_RBM_SW3_BM) {
|
||||
ab->soc_stats.invalid_rbm++;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -1038,7 +1038,9 @@ ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab,
|
|||
|
||||
ru_tones = FIELD_GET(HAL_RX_HE_SIG_B1_MU_INFO_INFO0_RU_ALLOCATION,
|
||||
info0);
|
||||
ppdu_info->ru_alloc = ath11k_he_ru_tones_to_nl80211_he_ru_alloc(ru_tones);
|
||||
ppdu_info->ru_alloc =
|
||||
ath11k_mac_phy_he_ru_to_nl80211_he_ru_alloc(ru_tones);
|
||||
|
||||
ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_MU_MIMO;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1079,6 +1081,9 @@ ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab,
|
|||
break;
|
||||
}
|
||||
case HAL_PHYRX_RSSI_LEGACY: {
|
||||
int i;
|
||||
bool db2dbm = test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,
|
||||
ab->wmi_ab.svc_map);
|
||||
struct hal_rx_phyrx_rssi_legacy_info *rssi =
|
||||
(struct hal_rx_phyrx_rssi_legacy_info *)tlv_data;
|
||||
|
||||
|
|
@ -1089,6 +1094,14 @@ ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab,
|
|||
ppdu_info->rssi_comb =
|
||||
FIELD_GET(HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO1_RSSI_COMB,
|
||||
__le32_to_cpu(rssi->info0));
|
||||
|
||||
if (db2dbm) {
|
||||
for (i = 0; i < ARRAY_SIZE(rssi->preamble); i++) {
|
||||
ppdu_info->rssi_chain_pri20[i] =
|
||||
le32_get_bits(rssi->preamble[i].rssi_2040,
|
||||
HAL_RX_PHYRX_RSSI_PREAMBLE_PRI20);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HAL_RX_MPDU_START: {
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ struct hal_rx_mon_ppdu_info {
|
|||
u8 ldpc;
|
||||
u8 beamformed;
|
||||
u8 rssi_comb;
|
||||
u8 rssi_chain_pri20[HAL_RX_MAX_NSS];
|
||||
u8 tid;
|
||||
u8 dcm;
|
||||
u8 ru_alloc;
|
||||
|
|
@ -262,8 +263,17 @@ struct hal_rx_he_sig_b2_ofdma_info {
|
|||
|
||||
#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO1_RSSI_COMB GENMASK(15, 8)
|
||||
|
||||
#define HAL_RX_PHYRX_RSSI_PREAMBLE_PRI20 GENMASK(7, 0)
|
||||
|
||||
struct hal_rx_phyrx_chain_rssi {
|
||||
__le32 rssi_2040;
|
||||
__le32 rssi_80;
|
||||
} __packed;
|
||||
|
||||
struct hal_rx_phyrx_rssi_legacy_info {
|
||||
__le32 rsvd[35];
|
||||
__le32 rsvd[3];
|
||||
struct hal_rx_phyrx_chain_rssi pre_rssi[HAL_RX_MAX_NSS];
|
||||
struct hal_rx_phyrx_chain_rssi preamble[HAL_RX_MAX_NSS];
|
||||
__le32 info0;
|
||||
} __packed;
|
||||
|
||||
|
|
@ -353,33 +363,6 @@ ath11k_hal_rx_parse_mon_status(struct ath11k_base *ab,
|
|||
struct hal_rx_mon_ppdu_info *ppdu_info,
|
||||
struct sk_buff *skb);
|
||||
|
||||
static inline u32 ath11k_he_ru_tones_to_nl80211_he_ru_alloc(u16 ru_tones)
|
||||
{
|
||||
u32 ret = 0;
|
||||
|
||||
switch (ru_tones) {
|
||||
case RU_26:
|
||||
ret = NL80211_RATE_INFO_HE_RU_ALLOC_26;
|
||||
break;
|
||||
case RU_52:
|
||||
ret = NL80211_RATE_INFO_HE_RU_ALLOC_52;
|
||||
break;
|
||||
case RU_106:
|
||||
ret = NL80211_RATE_INFO_HE_RU_ALLOC_106;
|
||||
break;
|
||||
case RU_242:
|
||||
ret = NL80211_RATE_INFO_HE_RU_ALLOC_242;
|
||||
break;
|
||||
case RU_484:
|
||||
ret = NL80211_RATE_INFO_HE_RU_ALLOC_484;
|
||||
break;
|
||||
case RU_996:
|
||||
ret = NL80211_RATE_INFO_HE_RU_ALLOC_996;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_0 0xDDBEEF
|
||||
#define REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_1 0xADBEEF
|
||||
#define REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_2 0xBDBEEF
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@
|
|||
#define ATH11K_DEFAULT_CAL_FILE "caldata.bin"
|
||||
#define ATH11K_AMSS_FILE "amss.bin"
|
||||
#define ATH11K_M3_FILE "m3.bin"
|
||||
#define ATH11K_REGDB_FILE_NAME "regdb.bin"
|
||||
|
||||
enum ath11k_hw_rate_cck {
|
||||
ATH11K_HW_RATE_CCK_LP_11M = 0,
|
||||
|
|
@ -151,6 +152,9 @@ struct ath11k_hw_params {
|
|||
u32 svc_to_ce_map_len;
|
||||
|
||||
bool single_pdev_only;
|
||||
u32 rfkill_pin;
|
||||
u32 rfkill_cfg;
|
||||
u32 rfkill_on_level;
|
||||
|
||||
bool rxdma1_enable;
|
||||
int num_rxmda_per_pdev;
|
||||
|
|
@ -178,6 +182,7 @@ struct ath11k_hw_params {
|
|||
u32 num_peers;
|
||||
bool supports_suspend;
|
||||
u32 hal_desc_sz;
|
||||
bool supports_regdb;
|
||||
bool fix_l1ss;
|
||||
bool credit_flow;
|
||||
u8 max_tx_ring;
|
||||
|
|
@ -185,6 +190,8 @@ struct ath11k_hw_params {
|
|||
bool supports_dynamic_smps_6ghz;
|
||||
bool alloc_cacheable_memory;
|
||||
bool wakeup_mhi;
|
||||
bool supports_rssi_stats;
|
||||
bool fw_wmi_diag_event;
|
||||
};
|
||||
|
||||
struct ath11k_hw_ops {
|
||||
|
|
|
|||
|
|
@ -246,6 +246,93 @@ static const u32 ath11k_smps_map[] = {
|
|||
static int ath11k_start_vdev_delay(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
|
||||
enum nl80211_he_ru_alloc ath11k_mac_phy_he_ru_to_nl80211_he_ru_alloc(u16 ru_phy)
|
||||
{
|
||||
enum nl80211_he_ru_alloc ret;
|
||||
|
||||
switch (ru_phy) {
|
||||
case RU_26:
|
||||
ret = NL80211_RATE_INFO_HE_RU_ALLOC_26;
|
||||
break;
|
||||
case RU_52:
|
||||
ret = NL80211_RATE_INFO_HE_RU_ALLOC_52;
|
||||
break;
|
||||
case RU_106:
|
||||
ret = NL80211_RATE_INFO_HE_RU_ALLOC_106;
|
||||
break;
|
||||
case RU_242:
|
||||
ret = NL80211_RATE_INFO_HE_RU_ALLOC_242;
|
||||
break;
|
||||
case RU_484:
|
||||
ret = NL80211_RATE_INFO_HE_RU_ALLOC_484;
|
||||
break;
|
||||
case RU_996:
|
||||
ret = NL80211_RATE_INFO_HE_RU_ALLOC_996;
|
||||
break;
|
||||
default:
|
||||
ret = NL80211_RATE_INFO_HE_RU_ALLOC_26;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
enum nl80211_he_ru_alloc ath11k_mac_he_ru_tones_to_nl80211_he_ru_alloc(u16 ru_tones)
|
||||
{
|
||||
enum nl80211_he_ru_alloc ret;
|
||||
|
||||
switch (ru_tones) {
|
||||
case 26:
|
||||
ret = NL80211_RATE_INFO_HE_RU_ALLOC_26;
|
||||
break;
|
||||
case 52:
|
||||
ret = NL80211_RATE_INFO_HE_RU_ALLOC_52;
|
||||
break;
|
||||
case 106:
|
||||
ret = NL80211_RATE_INFO_HE_RU_ALLOC_106;
|
||||
break;
|
||||
case 242:
|
||||
ret = NL80211_RATE_INFO_HE_RU_ALLOC_242;
|
||||
break;
|
||||
case 484:
|
||||
ret = NL80211_RATE_INFO_HE_RU_ALLOC_484;
|
||||
break;
|
||||
case 996:
|
||||
ret = NL80211_RATE_INFO_HE_RU_ALLOC_996;
|
||||
break;
|
||||
case (996 * 2):
|
||||
ret = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
|
||||
break;
|
||||
default:
|
||||
ret = NL80211_RATE_INFO_HE_RU_ALLOC_26;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
enum nl80211_he_gi ath11k_mac_he_gi_to_nl80211_he_gi(u8 sgi)
|
||||
{
|
||||
enum nl80211_he_gi ret;
|
||||
|
||||
switch (sgi) {
|
||||
case RX_MSDU_START_SGI_0_8_US:
|
||||
ret = NL80211_RATE_INFO_HE_GI_0_8;
|
||||
break;
|
||||
case RX_MSDU_START_SGI_1_6_US:
|
||||
ret = NL80211_RATE_INFO_HE_GI_1_6;
|
||||
break;
|
||||
case RX_MSDU_START_SGI_3_2_US:
|
||||
ret = NL80211_RATE_INFO_HE_GI_3_2;
|
||||
break;
|
||||
default:
|
||||
ret = NL80211_RATE_INFO_HE_GI_0_8;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
u8 ath11k_mac_bw_to_mac80211_bw(u8 bw)
|
||||
{
|
||||
u8 ret = 0;
|
||||
|
|
@ -2541,8 +2628,12 @@ static void ath11k_peer_assoc_prepare(struct ath11k *ar,
|
|||
struct peer_assoc_params *arg,
|
||||
bool reassoc)
|
||||
{
|
||||
struct ath11k_sta *arsta;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
|
||||
memset(arg, 0, sizeof(*arg));
|
||||
|
||||
reinit_completion(&ar->peer_assoc_done);
|
||||
|
|
@ -2559,6 +2650,8 @@ static void ath11k_peer_assoc_prepare(struct ath11k *ar,
|
|||
ath11k_peer_assoc_h_qos(ar, vif, sta, arg);
|
||||
ath11k_peer_assoc_h_smps(sta, arg);
|
||||
|
||||
arsta->peer_nss = arg->peer_nss;
|
||||
|
||||
/* TODO: amsdu_disable req? */
|
||||
}
|
||||
|
||||
|
|
@ -5478,6 +5571,63 @@ static int ath11k_mac_mgmt_tx(struct ath11k *ar, struct sk_buff *skb,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ath11k_mac_rfkill_config(struct ath11k *ar)
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
u32 param;
|
||||
int ret;
|
||||
|
||||
if (ab->hw_params.rfkill_pin == 0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_MAC,
|
||||
"mac rfkill_pin %d rfkill_cfg %d rfkill_on_level %d",
|
||||
ab->hw_params.rfkill_pin, ab->hw_params.rfkill_cfg,
|
||||
ab->hw_params.rfkill_on_level);
|
||||
|
||||
param = FIELD_PREP(WMI_RFKILL_CFG_RADIO_LEVEL,
|
||||
ab->hw_params.rfkill_on_level) |
|
||||
FIELD_PREP(WMI_RFKILL_CFG_GPIO_PIN_NUM,
|
||||
ab->hw_params.rfkill_pin) |
|
||||
FIELD_PREP(WMI_RFKILL_CFG_PIN_AS_GPIO,
|
||||
ab->hw_params.rfkill_cfg);
|
||||
|
||||
ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_HW_RFKILL_CONFIG,
|
||||
param, ar->pdev->pdev_id);
|
||||
if (ret) {
|
||||
ath11k_warn(ab,
|
||||
"failed to set rfkill config 0x%x: %d\n",
|
||||
param, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath11k_mac_rfkill_enable_radio(struct ath11k *ar, bool enable)
|
||||
{
|
||||
enum wmi_rfkill_enable_radio param;
|
||||
int ret;
|
||||
|
||||
if (enable)
|
||||
param = WMI_RFKILL_ENABLE_RADIO_ON;
|
||||
else
|
||||
param = WMI_RFKILL_ENABLE_RADIO_OFF;
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac %d rfkill enable %d",
|
||||
ar->pdev_idx, param);
|
||||
|
||||
ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_RFKILL_ENABLE,
|
||||
param, ar->pdev->pdev_id);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to set rfkill enable param %d: %d\n",
|
||||
param, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath11k_mac_op_tx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_tx_control *control,
|
||||
struct sk_buff *skb)
|
||||
|
|
@ -5710,6 +5860,7 @@ static void ath11k_mac_op_stop(struct ieee80211_hw *hw)
|
|||
cancel_delayed_work_sync(&ar->scan.timeout);
|
||||
cancel_work_sync(&ar->regd_update_work);
|
||||
cancel_work_sync(&ar->ab->update_11d_work);
|
||||
cancel_work_sync(&ar->ab->rfkill_work);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
list_for_each_entry_safe(ppdu_stats, tmp, &ar->ppdu_stats_info, list) {
|
||||
|
|
@ -7775,12 +7926,45 @@ static int ath11k_mac_op_get_survey(struct ieee80211_hw *hw, int idx,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void ath11k_mac_put_chain_rssi(struct station_info *sinfo,
|
||||
struct ath11k_sta *arsta,
|
||||
char *pre,
|
||||
bool clear)
|
||||
{
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
int i;
|
||||
s8 rssi;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
|
||||
sinfo->chains &= ~BIT(i);
|
||||
rssi = arsta->chain_signal[i];
|
||||
if (clear)
|
||||
arsta->chain_signal[i] = ATH11K_INVALID_RSSI_FULL;
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
|
||||
"mac sta statistics %s rssi[%d] %d\n", pre, i, rssi);
|
||||
|
||||
if (rssi != ATH11K_DEFAULT_NOISE_FLOOR &&
|
||||
rssi != ATH11K_INVALID_RSSI_FULL &&
|
||||
rssi != ATH11K_INVALID_RSSI_EMPTY &&
|
||||
rssi != 0) {
|
||||
sinfo->chain_signal[i] = rssi;
|
||||
sinfo->chains |= BIT(i);
|
||||
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct station_info *sinfo)
|
||||
{
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
s8 signal;
|
||||
bool db2dbm = test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,
|
||||
ar->ab->wmi_ab.svc_map);
|
||||
|
||||
sinfo->rx_duration = arsta->rx_duration;
|
||||
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
|
||||
|
|
@ -7803,9 +7987,32 @@ static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw,
|
|||
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
|
||||
}
|
||||
|
||||
/* TODO: Use real NF instead of default one. */
|
||||
sinfo->signal = arsta->rssi_comb + ATH11K_DEFAULT_NOISE_FLOOR;
|
||||
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
|
||||
ath11k_mac_put_chain_rssi(sinfo, arsta, "ppdu", false);
|
||||
|
||||
if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) &&
|
||||
arsta->arvif->vdev_type == WMI_VDEV_TYPE_STA &&
|
||||
ar->ab->hw_params.supports_rssi_stats &&
|
||||
!ath11k_debugfs_get_fw_stats(ar, ar->pdev->pdev_id, 0,
|
||||
WMI_REQUEST_RSSI_PER_CHAIN_STAT)) {
|
||||
ath11k_mac_put_chain_rssi(sinfo, arsta, "fw stats", true);
|
||||
}
|
||||
|
||||
signal = arsta->rssi_comb;
|
||||
if (!signal &&
|
||||
arsta->arvif->vdev_type == WMI_VDEV_TYPE_STA &&
|
||||
ar->ab->hw_params.supports_rssi_stats &&
|
||||
!(ath11k_debugfs_get_fw_stats(ar, ar->pdev->pdev_id, 0,
|
||||
WMI_REQUEST_VDEV_STAT)))
|
||||
signal = arsta->rssi_beacon;
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
|
||||
"mac sta statistics db2dbm %u rssi comb %d rssi beacon %d\n",
|
||||
db2dbm, arsta->rssi_comb, arsta->rssi_beacon);
|
||||
|
||||
if (signal) {
|
||||
sinfo->signal = db2dbm ? signal : signal + ATH11K_DEFAULT_NOISE_FLOOR;
|
||||
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct ieee80211_ops ath11k_ops = {
|
||||
|
|
|
|||
|
|
@ -147,6 +147,8 @@ u8 ath11k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
|
|||
|
||||
void __ath11k_mac_scan_finish(struct ath11k *ar);
|
||||
void ath11k_mac_scan_finish(struct ath11k *ar);
|
||||
int ath11k_mac_rfkill_enable_radio(struct ath11k *ar, bool enable);
|
||||
int ath11k_mac_rfkill_config(struct ath11k *ar);
|
||||
|
||||
struct ath11k_vif *ath11k_mac_get_arvif(struct ath11k *ar, u32 vdev_id);
|
||||
struct ath11k_vif *ath11k_mac_get_arvif_by_vdev_id(struct ath11k_base *ab,
|
||||
|
|
@ -162,6 +164,9 @@ void ath11k_mac_drain_tx(struct ath11k *ar);
|
|||
void ath11k_mac_peer_cleanup_all(struct ath11k *ar);
|
||||
int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx);
|
||||
u8 ath11k_mac_bw_to_mac80211_bw(u8 bw);
|
||||
u32 ath11k_mac_he_gi_to_nl80211_he_gi(u8 sgi);
|
||||
enum nl80211_he_ru_alloc ath11k_mac_phy_he_ru_to_nl80211_he_ru_alloc(u16 ru_phy);
|
||||
enum nl80211_he_ru_alloc ath11k_mac_he_ru_tones_to_nl80211_he_ru_alloc(u16 ru_tones);
|
||||
enum ath11k_supported_bw ath11k_mac_mac80211_bw_to_ath11k_bw(enum rate_info_bw bw);
|
||||
enum hal_encrypt_type ath11k_dp_tx_get_encrypt_type(u32 cipher);
|
||||
void ath11k_mac_handle_beacon(struct ath11k *ar, struct sk_buff *skb);
|
||||
|
|
|
|||
|
|
@ -683,8 +683,11 @@ static void __ath11k_pci_ext_irq_disable(struct ath11k_base *sc)
|
|||
|
||||
ath11k_pci_ext_grp_disable(irq_grp);
|
||||
|
||||
napi_synchronize(&irq_grp->napi);
|
||||
napi_disable(&irq_grp->napi);
|
||||
if (irq_grp->napi_enabled) {
|
||||
napi_synchronize(&irq_grp->napi);
|
||||
napi_disable(&irq_grp->napi);
|
||||
irq_grp->napi_enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -712,7 +715,10 @@ static void ath11k_pci_ext_irq_enable(struct ath11k_base *ab)
|
|||
for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
|
||||
struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
|
||||
|
||||
napi_enable(&irq_grp->napi);
|
||||
if (!irq_grp->napi_enabled) {
|
||||
napi_enable(&irq_grp->napi);
|
||||
irq_grp->napi_enabled = true;
|
||||
}
|
||||
ath11k_pci_ext_grp_enable(irq_grp);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1584,6 +1584,50 @@ static struct qmi_elem_info qmi_wlanfw_cold_boot_cal_done_ind_msg_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_wlan_ini_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct qmi_wlanfw_wlan_ini_req_msg_v01,
|
||||
enablefwlog_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct qmi_wlanfw_wlan_ini_req_msg_v01,
|
||||
enablefwlog),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_wlan_ini_resp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct qmi_response_type_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct qmi_wlanfw_wlan_ini_resp_msg_v01,
|
||||
resp),
|
||||
.ei_array = qmi_response_type_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
static int ath11k_qmi_host_cap_send(struct ath11k_base *ab)
|
||||
{
|
||||
struct qmi_wlanfw_host_cap_req_msg_v01 req;
|
||||
|
|
@ -2161,7 +2205,8 @@ static int ath11k_qmi_load_file_target_mem(struct ath11k_base *ab,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab)
|
||||
static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab,
|
||||
bool regdb)
|
||||
{
|
||||
struct device *dev = ab->dev;
|
||||
char filename[ATH11K_QMI_MAX_BDF_FILE_NAME_SIZE];
|
||||
|
|
@ -2172,13 +2217,21 @@ static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab)
|
|||
const u8 *tmp;
|
||||
|
||||
memset(&bd, 0, sizeof(bd));
|
||||
ret = ath11k_core_fetch_bdf(ab, &bd);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "qmi failed to fetch board file: %d\n", ret);
|
||||
goto out;
|
||||
|
||||
if (regdb) {
|
||||
ret = ath11k_core_fetch_regdb(ab, &bd);
|
||||
} else {
|
||||
ret = ath11k_core_fetch_bdf(ab, &bd);
|
||||
if (ret)
|
||||
ath11k_warn(ab, "qmi failed to fetch board file: %d\n", ret);
|
||||
}
|
||||
|
||||
if (bd.len >= SELFMAG && memcmp(bd.data, ELFMAG, SELFMAG) == 0)
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (regdb)
|
||||
bdf_type = ATH11K_QMI_BDF_TYPE_REGDB;
|
||||
else if (bd.len >= SELFMAG && memcmp(bd.data, ELFMAG, SELFMAG) == 0)
|
||||
bdf_type = ATH11K_QMI_BDF_TYPE_ELF;
|
||||
else
|
||||
bdf_type = ATH11K_QMI_BDF_TYPE_BIN;
|
||||
|
|
@ -2193,8 +2246,8 @@ static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab)
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* QCA6390 does not support cal data, skip it */
|
||||
if (bdf_type == ATH11K_QMI_BDF_TYPE_ELF)
|
||||
/* QCA6390/WCN6855 does not support cal data, skip it */
|
||||
if (bdf_type == ATH11K_QMI_BDF_TYPE_ELF || bdf_type == ATH11K_QMI_BDF_TYPE_REGDB)
|
||||
goto out;
|
||||
|
||||
if (ab->qmi.target.eeprom_caldata) {
|
||||
|
|
@ -2495,6 +2548,48 @@ static int ath11k_qmi_wlanfw_wlan_cfg_send(struct ath11k_base *ab)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int ath11k_qmi_wlanfw_wlan_ini_send(struct ath11k_base *ab, bool enable)
|
||||
{
|
||||
int ret;
|
||||
struct qmi_txn txn;
|
||||
struct qmi_wlanfw_wlan_ini_req_msg_v01 req = {};
|
||||
struct qmi_wlanfw_wlan_ini_resp_msg_v01 resp = {};
|
||||
|
||||
req.enablefwlog_valid = true;
|
||||
req.enablefwlog = enable ? 1 : 0;
|
||||
|
||||
ret = qmi_txn_init(&ab->qmi.handle, &txn,
|
||||
qmi_wlanfw_wlan_ini_resp_msg_v01_ei, &resp);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
|
||||
QMI_WLANFW_WLAN_INI_REQ_V01,
|
||||
QMI_WLANFW_WLAN_INI_REQ_MSG_V01_MAX_LEN,
|
||||
qmi_wlanfw_wlan_ini_req_msg_v01_ei, &req);
|
||||
if (ret < 0) {
|
||||
ath11k_warn(ab, "qmi failed to send wlan ini request, err = %d\n",
|
||||
ret);
|
||||
qmi_txn_cancel(&txn);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
|
||||
if (ret < 0) {
|
||||
ath11k_warn(ab, "qmi failed wlan ini request, err = %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
|
||||
ath11k_warn(ab, "qmi wlan ini request failed, result: %d, err: %d\n",
|
||||
resp.resp.result, resp.resp.error);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ath11k_qmi_firmware_stop(struct ath11k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -2515,6 +2610,14 @@ int ath11k_qmi_firmware_start(struct ath11k_base *ab,
|
|||
|
||||
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware start\n");
|
||||
|
||||
if (ab->hw_params.fw_wmi_diag_event) {
|
||||
ret = ath11k_qmi_wlanfw_wlan_ini_send(ab, true);
|
||||
if (ret < 0) {
|
||||
ath11k_warn(ab, "qmi failed to send wlan fw ini:%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ath11k_qmi_wlanfw_wlan_cfg_send(ab);
|
||||
if (ret < 0) {
|
||||
ath11k_warn(ab, "qmi failed to send wlan cfg: %d\n", ret);
|
||||
|
|
@ -2626,7 +2729,10 @@ static int ath11k_qmi_event_load_bdf(struct ath11k_qmi *qmi)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = ath11k_qmi_load_bdf_qmi(ab);
|
||||
if (ab->hw_params.supports_regdb)
|
||||
ath11k_qmi_load_bdf_qmi(ab, true);
|
||||
|
||||
ret = ath11k_qmi_load_bdf_qmi(ab, false);
|
||||
if (ret < 0) {
|
||||
ath11k_warn(ab, "failed to load board data file: %d\n", ret);
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ enum ath11k_qmi_file_type {
|
|||
enum ath11k_qmi_bdf_type {
|
||||
ATH11K_QMI_BDF_TYPE_BIN = 0,
|
||||
ATH11K_QMI_BDF_TYPE_ELF = 1,
|
||||
ATH11K_QMI_BDF_TYPE_REGDB = 4,
|
||||
};
|
||||
|
||||
enum ath11k_qmi_event_type {
|
||||
|
|
@ -427,10 +428,12 @@ struct qmi_wlanfw_m3_info_resp_msg_v01 {
|
|||
#define QMI_WLANFW_WLAN_MODE_RESP_MSG_V01_MAX_LEN 7
|
||||
#define QMI_WLANFW_WLAN_CFG_REQ_MSG_V01_MAX_LEN 803
|
||||
#define QMI_WLANFW_WLAN_CFG_RESP_MSG_V01_MAX_LEN 7
|
||||
#define QMI_WLANFW_WLAN_INI_REQ_MSG_V01_MAX_LEN 4
|
||||
#define QMI_WLANFW_WLAN_MODE_REQ_V01 0x0022
|
||||
#define QMI_WLANFW_WLAN_MODE_RESP_V01 0x0022
|
||||
#define QMI_WLANFW_WLAN_CFG_REQ_V01 0x0023
|
||||
#define QMI_WLANFW_WLAN_CFG_RESP_V01 0x0023
|
||||
#define QMI_WLANFW_WLAN_INI_REQ_V01 0x002F
|
||||
#define QMI_WLANFW_MAX_STR_LEN_V01 16
|
||||
#define QMI_WLANFW_MAX_NUM_CE_V01 12
|
||||
#define QMI_WLANFW_MAX_NUM_SVC_V01 24
|
||||
|
|
@ -472,6 +475,16 @@ struct qmi_wlanfw_wlan_cfg_resp_msg_v01 {
|
|||
struct qmi_response_type_v01 resp;
|
||||
};
|
||||
|
||||
struct qmi_wlanfw_wlan_ini_req_msg_v01 {
|
||||
/* Must be set to true if enablefwlog is being passed */
|
||||
u8 enablefwlog_valid;
|
||||
u8 enablefwlog;
|
||||
};
|
||||
|
||||
struct qmi_wlanfw_wlan_ini_resp_msg_v01 {
|
||||
struct qmi_response_type_v01 resp;
|
||||
};
|
||||
|
||||
int ath11k_qmi_firmware_start(struct ath11k_base *ab,
|
||||
u32 mode);
|
||||
void ath11k_qmi_firmware_stop(struct ath11k_base *ab);
|
||||
|
|
|
|||
|
|
@ -280,6 +280,34 @@ TRACE_EVENT(ath11k_log_dbg_dump,
|
|||
__get_str(msg)
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(ath11k_wmi_diag,
|
||||
TP_PROTO(struct ath11k_base *ab, const void *data, size_t len),
|
||||
|
||||
TP_ARGS(ab, data, len),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(device, dev_name(ab->dev))
|
||||
__string(driver, dev_driver_string(ab->dev))
|
||||
__field(u16, len)
|
||||
__dynamic_array(u8, data, len)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(device, dev_name(ab->dev));
|
||||
__assign_str(driver, dev_driver_string(ab->dev));
|
||||
__entry->len = len;
|
||||
memcpy(__get_dynamic_array(data), data, len);
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"%s %s tlv diag len %d",
|
||||
__get_str(driver),
|
||||
__get_str(device),
|
||||
__entry->len
|
||||
)
|
||||
);
|
||||
|
||||
#endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/
|
||||
|
||||
/* we don't want to use include/trace/events */
|
||||
|
|
|
|||
|
|
@ -73,6 +73,14 @@ struct wmi_tlv_dma_buf_release_parse {
|
|||
bool meta_data_done;
|
||||
};
|
||||
|
||||
struct wmi_tlv_fw_stats_parse {
|
||||
const struct wmi_stats_event *ev;
|
||||
const struct wmi_per_chain_rssi_stats *rssi;
|
||||
struct ath11k_fw_stats *stats;
|
||||
int rssi_num;
|
||||
bool chain_rssi_done;
|
||||
};
|
||||
|
||||
static const struct wmi_tlv_policy wmi_tlv_policies[] = {
|
||||
[WMI_TAG_ARRAY_BYTE]
|
||||
= { .min_len = 0 },
|
||||
|
|
@ -120,6 +128,8 @@ static const struct wmi_tlv_policy wmi_tlv_policies[] = {
|
|||
= { .min_len = sizeof(struct wmi_peer_assoc_conf_event) },
|
||||
[WMI_TAG_STATS_EVENT]
|
||||
= { .min_len = sizeof(struct wmi_stats_event) },
|
||||
[WMI_TAG_RFKILL_EVENT] = {
|
||||
.min_len = sizeof(struct wmi_rfkill_state_change_ev) },
|
||||
[WMI_TAG_PDEV_CTL_FAILSAFE_CHECK_EVENT]
|
||||
= { .min_len = sizeof(struct wmi_pdev_ctl_failsafe_chk_event) },
|
||||
[WMI_TAG_HOST_SWFDA_EVENT] = {
|
||||
|
|
@ -132,6 +142,8 @@ static const struct wmi_tlv_policy wmi_tlv_policies[] = {
|
|||
.min_len = sizeof(struct wmi_obss_color_collision_event) },
|
||||
[WMI_TAG_11D_NEW_COUNTRY_EVENT] = {
|
||||
.min_len = sizeof(struct wmi_11d_new_cc_ev) },
|
||||
[WMI_TAG_PER_CHAIN_RSSI_STATS] = {
|
||||
.min_len = sizeof(struct wmi_per_chain_rssi_stats) },
|
||||
};
|
||||
|
||||
#define PRIMAP(_hw_mode_) \
|
||||
|
|
@ -514,6 +526,8 @@ static int ath11k_pull_service_ready_tlv(struct ath11k_base *ab,
|
|||
cap->default_dbs_hw_mode_index = ev->default_dbs_hw_mode_index;
|
||||
cap->num_msdu_desc = ev->num_msdu_desc;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "wmi sys cap info 0x%x\n", cap->sys_cap_info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3595,6 +3609,8 @@ ath11k_wmi_obss_color_collision_event(struct ath11k_base *ab, struct sk_buff *sk
|
|||
return;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
ev = tb[WMI_TAG_OBSS_COLOR_COLLISION_EVT];
|
||||
if (!ev) {
|
||||
ath11k_warn(ab, "failed to fetch obss color collision ev");
|
||||
|
|
@ -3625,6 +3641,7 @@ ath11k_wmi_obss_color_collision_event(struct ath11k_base *ab, struct sk_buff *sk
|
|||
|
||||
exit:
|
||||
kfree(tb);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -5554,47 +5571,107 @@ ath11k_wmi_pull_bcn_stats(const struct wmi_bcn_stats *src,
|
|||
dst->tx_bcn_outage_cnt = src->tx_bcn_outage_cnt;
|
||||
}
|
||||
|
||||
int ath11k_wmi_pull_fw_stats(struct ath11k_base *ab, struct sk_buff *skb,
|
||||
struct ath11k_fw_stats *stats)
|
||||
static int ath11k_wmi_tlv_rssi_chain_parse(struct ath11k_base *ab,
|
||||
u16 tag, u16 len,
|
||||
const void *ptr, void *data)
|
||||
{
|
||||
const void **tb;
|
||||
const struct wmi_stats_event *ev;
|
||||
const void *data;
|
||||
int i, ret;
|
||||
u32 len = skb->len;
|
||||
struct wmi_tlv_fw_stats_parse *parse = data;
|
||||
const struct wmi_stats_event *ev = parse->ev;
|
||||
struct ath11k_fw_stats *stats = parse->stats;
|
||||
struct ath11k *ar;
|
||||
struct ath11k_vif *arvif;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ath11k_sta *arsta;
|
||||
const struct wmi_rssi_stats *stats_rssi = (const struct wmi_rssi_stats *)ptr;
|
||||
int j, ret = 0;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, len, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ev = tb[WMI_TAG_STATS_EVENT];
|
||||
data = tb[WMI_TAG_ARRAY_BYTE];
|
||||
if (!ev || !data) {
|
||||
ath11k_warn(ab, "failed to fetch update stats ev");
|
||||
kfree(tb);
|
||||
if (tag != WMI_TAG_RSSI_STATS)
|
||||
return -EPROTO;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
ar = ath11k_mac_get_ar_by_pdev_id(ab, ev->pdev_id);
|
||||
stats->stats_id = WMI_REQUEST_RSSI_PER_CHAIN_STAT;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"wmi stats vdev id %d mac %pM\n",
|
||||
stats_rssi->vdev_id, stats_rssi->peer_macaddr.addr);
|
||||
|
||||
arvif = ath11k_mac_get_arvif(ar, stats_rssi->vdev_id);
|
||||
if (!arvif) {
|
||||
ath11k_warn(ab, "not found vif for vdev id %d\n",
|
||||
stats_rssi->vdev_id);
|
||||
ret = -EPROTO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"wmi stats update ev pdev_id %d pdev %i vdev %i bcn %i\n",
|
||||
ev->pdev_id,
|
||||
ev->num_pdev_stats, ev->num_vdev_stats,
|
||||
ev->num_bcn_stats);
|
||||
"wmi stats bssid %pM vif %pK\n",
|
||||
arvif->bssid, arvif->vif);
|
||||
|
||||
sta = ieee80211_find_sta_by_ifaddr(ar->hw,
|
||||
arvif->bssid,
|
||||
NULL);
|
||||
if (!sta) {
|
||||
ath11k_warn(ab, "not found station for bssid %pM\n",
|
||||
arvif->bssid);
|
||||
ret = -EPROTO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(arsta->chain_signal) >
|
||||
ARRAY_SIZE(stats_rssi->rssi_avg_beacon));
|
||||
|
||||
for (j = 0; j < ARRAY_SIZE(arsta->chain_signal); j++) {
|
||||
arsta->chain_signal[j] = stats_rssi->rssi_avg_beacon[j];
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"wmi stats beacon rssi[%d] %d data rssi[%d] %d\n",
|
||||
j,
|
||||
stats_rssi->rssi_avg_beacon[j],
|
||||
j,
|
||||
stats_rssi->rssi_avg_data[j]);
|
||||
}
|
||||
|
||||
exit:
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath11k_wmi_tlv_fw_stats_data_parse(struct ath11k_base *ab,
|
||||
struct wmi_tlv_fw_stats_parse *parse,
|
||||
const void *ptr,
|
||||
u16 len)
|
||||
{
|
||||
struct ath11k_fw_stats *stats = parse->stats;
|
||||
const struct wmi_stats_event *ev = parse->ev;
|
||||
struct ath11k *ar;
|
||||
struct ath11k_vif *arvif;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ath11k_sta *arsta;
|
||||
int i, ret = 0;
|
||||
const void *data = ptr;
|
||||
|
||||
if (!ev) {
|
||||
ath11k_warn(ab, "failed to fetch update stats ev");
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
stats->pdev_id = ev->pdev_id;
|
||||
stats->stats_id = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
ar = ath11k_mac_get_ar_by_pdev_id(ab, ev->pdev_id);
|
||||
|
||||
for (i = 0; i < ev->num_pdev_stats; i++) {
|
||||
const struct wmi_pdev_stats *src;
|
||||
struct ath11k_fw_stats_pdev *dst;
|
||||
|
||||
src = data;
|
||||
if (len < sizeof(*src)) {
|
||||
kfree(tb);
|
||||
return -EPROTO;
|
||||
ret = -EPROTO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
stats->stats_id = WMI_REQUEST_PDEV_STAT;
|
||||
|
|
@ -5618,12 +5695,29 @@ int ath11k_wmi_pull_fw_stats(struct ath11k_base *ab, struct sk_buff *skb,
|
|||
|
||||
src = data;
|
||||
if (len < sizeof(*src)) {
|
||||
kfree(tb);
|
||||
return -EPROTO;
|
||||
ret = -EPROTO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
stats->stats_id = WMI_REQUEST_VDEV_STAT;
|
||||
|
||||
arvif = ath11k_mac_get_arvif(ar, src->vdev_id);
|
||||
if (arvif) {
|
||||
sta = ieee80211_find_sta_by_ifaddr(ar->hw,
|
||||
arvif->bssid,
|
||||
NULL);
|
||||
if (sta) {
|
||||
arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
arsta->rssi_beacon = src->beacon_snr;
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"wmi stats vdev id %d snr %d\n",
|
||||
src->vdev_id, src->beacon_snr);
|
||||
} else {
|
||||
ath11k_warn(ab, "not found station for bssid %pM\n",
|
||||
arvif->bssid);
|
||||
}
|
||||
}
|
||||
|
||||
data += sizeof(*src);
|
||||
len -= sizeof(*src);
|
||||
|
||||
|
|
@ -5641,8 +5735,8 @@ int ath11k_wmi_pull_fw_stats(struct ath11k_base *ab, struct sk_buff *skb,
|
|||
|
||||
src = data;
|
||||
if (len < sizeof(*src)) {
|
||||
kfree(tb);
|
||||
return -EPROTO;
|
||||
ret = -EPROTO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
stats->stats_id = WMI_REQUEST_BCN_STAT;
|
||||
|
|
@ -5658,8 +5752,67 @@ int ath11k_wmi_pull_fw_stats(struct ath11k_base *ab, struct sk_buff *skb,
|
|||
list_add_tail(&dst->list, &stats->bcn);
|
||||
}
|
||||
|
||||
kfree(tb);
|
||||
return 0;
|
||||
exit:
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath11k_wmi_tlv_fw_stats_parse(struct ath11k_base *ab,
|
||||
u16 tag, u16 len,
|
||||
const void *ptr, void *data)
|
||||
{
|
||||
struct wmi_tlv_fw_stats_parse *parse = data;
|
||||
int ret = 0;
|
||||
|
||||
switch (tag) {
|
||||
case WMI_TAG_STATS_EVENT:
|
||||
parse->ev = (struct wmi_stats_event *)ptr;
|
||||
parse->stats->pdev_id = parse->ev->pdev_id;
|
||||
break;
|
||||
case WMI_TAG_ARRAY_BYTE:
|
||||
ret = ath11k_wmi_tlv_fw_stats_data_parse(ab, parse, ptr, len);
|
||||
break;
|
||||
case WMI_TAG_PER_CHAIN_RSSI_STATS:
|
||||
parse->rssi = (struct wmi_per_chain_rssi_stats *)ptr;
|
||||
|
||||
if (parse->ev->stats_id & WMI_REQUEST_RSSI_PER_CHAIN_STAT)
|
||||
parse->rssi_num = parse->rssi->num_per_chain_rssi_stats;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"wmi stats id 0x%x num chain %d\n",
|
||||
parse->ev->stats_id,
|
||||
parse->rssi_num);
|
||||
break;
|
||||
case WMI_TAG_ARRAY_STRUCT:
|
||||
if (parse->rssi_num && !parse->chain_rssi_done) {
|
||||
ret = ath11k_wmi_tlv_iter(ab, ptr, len,
|
||||
ath11k_wmi_tlv_rssi_chain_parse,
|
||||
parse);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to parse rssi chain %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
parse->chain_rssi_done = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_pull_fw_stats(struct ath11k_base *ab, struct sk_buff *skb,
|
||||
struct ath11k_fw_stats *stats)
|
||||
{
|
||||
struct wmi_tlv_fw_stats_parse parse = { };
|
||||
|
||||
stats->stats_id = 0;
|
||||
parse.stats = stats;
|
||||
|
||||
return ath11k_wmi_tlv_iter(ab, skb->data, skb->len,
|
||||
ath11k_wmi_tlv_fw_stats_parse,
|
||||
&parse);
|
||||
}
|
||||
|
||||
size_t ath11k_wmi_fw_stats_num_vdevs(struct list_head *head)
|
||||
|
|
@ -6395,13 +6548,16 @@ static void ath11k_bcn_tx_status_event(struct ath11k_base *ab, struct sk_buff *s
|
|||
return;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
arvif = ath11k_mac_get_arvif_by_vdev_id(ab, vdev_id);
|
||||
if (!arvif) {
|
||||
ath11k_warn(ab, "invalid vdev id %d in bcn_tx_status",
|
||||
vdev_id);
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
ath11k_mac_bcn_tx_event(arvif);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void ath11k_vdev_stopped_event(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
|
|
@ -7182,6 +7338,40 @@ ath11k_wmi_pdev_dfs_radar_detected_event(struct ath11k_base *ab, struct sk_buff
|
|||
kfree(tb);
|
||||
}
|
||||
|
||||
static void ath11k_rfkill_state_change_event(struct ath11k_base *ab,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
const struct wmi_rfkill_state_change_ev *ev;
|
||||
const void **tb;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ev = tb[WMI_TAG_RFKILL_EVENT];
|
||||
if (!ev) {
|
||||
kfree(tb);
|
||||
return;
|
||||
}
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_MAC,
|
||||
"wmi tlv rfkill state change gpio %d type %d radio_state %d\n",
|
||||
ev->gpio_pin_num,
|
||||
ev->int_type,
|
||||
ev->radio_state);
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
ab->rfkill_radio_on = (ev->radio_state == WMI_RFKILL_RADIO_STATE_ON);
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
queue_work(ab->workqueue, &ab->rfkill_work);
|
||||
kfree(tb);
|
||||
}
|
||||
|
||||
static void
|
||||
ath11k_wmi_pdev_temperature_event(struct ath11k_base *ab,
|
||||
struct sk_buff *skb)
|
||||
|
|
@ -7335,6 +7525,13 @@ static void ath11k_wmi_event_wow_wakeup_host(struct ath11k_base *ab, struct sk_b
|
|||
complete(&ab->wow.wakeup_completed);
|
||||
}
|
||||
|
||||
static void
|
||||
ath11k_wmi_diag_event(struct ath11k_base *ab,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
trace_ath11k_wmi_diag(ab, skb->data, skb->len);
|
||||
}
|
||||
|
||||
static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
{
|
||||
struct wmi_cmd_hdr *cmd_hdr;
|
||||
|
|
@ -7454,6 +7651,12 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
|
|||
case WMI_11D_NEW_COUNTRY_EVENTID:
|
||||
ath11k_reg_11d_new_cc_event(ab, skb);
|
||||
break;
|
||||
case WMI_RFKILL_STATE_CHANGE_EVENTID:
|
||||
ath11k_rfkill_state_change_event(ab, skb);
|
||||
break;
|
||||
case WMI_DIAG_EVENTID:
|
||||
ath11k_wmi_diag_event(ab, skb);
|
||||
break;
|
||||
/* TODO: Add remaining events */
|
||||
default:
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "Unknown eventid: 0x%x\n", id);
|
||||
|
|
|
|||
|
|
@ -4439,6 +4439,17 @@ struct wmi_stats_event {
|
|||
u32 num_peer_extd2_stats;
|
||||
} __packed;
|
||||
|
||||
struct wmi_rssi_stats {
|
||||
u32 vdev_id;
|
||||
u32 rssi_avg_beacon[WMI_MAX_CHAINS];
|
||||
u32 rssi_avg_data[WMI_MAX_CHAINS];
|
||||
struct wmi_mac_addr peer_macaddr;
|
||||
} __packed;
|
||||
|
||||
struct wmi_per_chain_rssi_stats {
|
||||
u32 num_per_chain_rssi_stats;
|
||||
} __packed;
|
||||
|
||||
struct wmi_pdev_ctl_failsafe_chk_event {
|
||||
u32 pdev_id;
|
||||
u32 ctl_failsafe_status;
|
||||
|
|
@ -5204,6 +5215,31 @@ struct target_resource_config {
|
|||
u32 twt_ap_sta_count;
|
||||
};
|
||||
|
||||
enum wmi_sys_cap_info_flags {
|
||||
WMI_SYS_CAP_INFO_RXTX_LED = BIT(0),
|
||||
WMI_SYS_CAP_INFO_RFKILL = BIT(1),
|
||||
};
|
||||
|
||||
#define WMI_RFKILL_CFG_GPIO_PIN_NUM GENMASK(5, 0)
|
||||
#define WMI_RFKILL_CFG_RADIO_LEVEL BIT(6)
|
||||
#define WMI_RFKILL_CFG_PIN_AS_GPIO GENMASK(10, 7)
|
||||
|
||||
enum wmi_rfkill_enable_radio {
|
||||
WMI_RFKILL_ENABLE_RADIO_ON = 0,
|
||||
WMI_RFKILL_ENABLE_RADIO_OFF = 1,
|
||||
};
|
||||
|
||||
enum wmi_rfkill_radio_state {
|
||||
WMI_RFKILL_RADIO_STATE_OFF = 1,
|
||||
WMI_RFKILL_RADIO_STATE_ON = 2,
|
||||
};
|
||||
|
||||
struct wmi_rfkill_state_change_ev {
|
||||
u32 gpio_pin_num;
|
||||
u32 int_type;
|
||||
u32 radio_state;
|
||||
} __packed;
|
||||
|
||||
#define WMI_MAX_MEM_REQS 32
|
||||
|
||||
#define MAX_RADIOS 3
|
||||
|
|
|
|||
|
|
@ -727,6 +727,43 @@ ath5k_get_rate_hw_value(const struct ieee80211_hw *hw,
|
|||
return hw_rate;
|
||||
}
|
||||
|
||||
static bool ath5k_merge_ratetbl(struct ieee80211_sta *sta,
|
||||
struct ath5k_buf *bf,
|
||||
struct ieee80211_tx_info *tx_info)
|
||||
{
|
||||
struct ieee80211_sta_rates *ratetbl;
|
||||
u8 i;
|
||||
|
||||
if (!sta)
|
||||
return false;
|
||||
|
||||
ratetbl = rcu_dereference(sta->rates);
|
||||
if (!ratetbl)
|
||||
return false;
|
||||
|
||||
if (tx_info->control.rates[0].idx < 0 ||
|
||||
tx_info->control.rates[0].count == 0)
|
||||
{
|
||||
i = 0;
|
||||
} else {
|
||||
bf->rates[0] = tx_info->control.rates[0];
|
||||
i = 1;
|
||||
}
|
||||
|
||||
for ( ; i < IEEE80211_TX_MAX_RATES; i++) {
|
||||
bf->rates[i].idx = ratetbl->rate[i].idx;
|
||||
bf->rates[i].flags = ratetbl->rate[i].flags;
|
||||
if (tx_info->control.use_rts)
|
||||
bf->rates[i].count = ratetbl->rate[i].count_rts;
|
||||
else if (tx_info->control.use_cts_prot)
|
||||
bf->rates[i].count = ratetbl->rate[i].count_cts;
|
||||
else
|
||||
bf->rates[i].count = ratetbl->rate[i].count;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf,
|
||||
struct ath5k_txq *txq, int padsize,
|
||||
|
|
@ -737,6 +774,7 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf,
|
|||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
unsigned int pktlen, flags, keyidx = AR5K_TXKEYIX_INVALID;
|
||||
struct ieee80211_rate *rate;
|
||||
struct ieee80211_sta *sta;
|
||||
unsigned int mrr_rate[3], mrr_tries[3];
|
||||
int i, ret;
|
||||
u16 hw_rate;
|
||||
|
|
@ -753,8 +791,16 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf,
|
|||
if (dma_mapping_error(ah->dev, bf->skbaddr))
|
||||
return -ENOSPC;
|
||||
|
||||
ieee80211_get_tx_rates(info->control.vif, (control) ? control->sta : NULL, skb, bf->rates,
|
||||
ARRAY_SIZE(bf->rates));
|
||||
if (control)
|
||||
sta = control->sta;
|
||||
else
|
||||
sta = NULL;
|
||||
|
||||
if (!ath5k_merge_ratetbl(sta, bf, info)) {
|
||||
ieee80211_get_tx_rates(info->control.vif,
|
||||
sta, skb, bf->rates,
|
||||
ARRAY_SIZE(bf->rates));
|
||||
}
|
||||
|
||||
rate = ath5k_get_rate(ah->hw, info, bf, 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -590,6 +590,13 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
|
|||
return;
|
||||
}
|
||||
|
||||
if (pkt_len > 2 * MAX_RX_BUF_SIZE) {
|
||||
dev_err(&hif_dev->udev->dev,
|
||||
"ath9k_htc: invalid pkt_len (%x)\n", pkt_len);
|
||||
RX_STAT_INC(skb_dropped);
|
||||
return;
|
||||
}
|
||||
|
||||
pad_len = 4 - (pkt_len & 0x3);
|
||||
if (pad_len == 4)
|
||||
pad_len = 0;
|
||||
|
|
|
|||
|
|
@ -281,6 +281,7 @@ struct ath9k_htc_rxbuf {
|
|||
struct ath9k_htc_rx {
|
||||
struct list_head rxbuf;
|
||||
spinlock_t rxbuflock;
|
||||
bool initialized;
|
||||
};
|
||||
|
||||
#define ATH9K_HTC_TX_CLEANUP_INTERVAL 50 /* ms */
|
||||
|
|
@ -305,6 +306,7 @@ struct ath9k_htc_tx {
|
|||
DECLARE_BITMAP(tx_slot, MAX_TX_BUF_NUM);
|
||||
struct timer_list cleanup_timer;
|
||||
spinlock_t tx_lock;
|
||||
bool initialized;
|
||||
};
|
||||
|
||||
struct ath9k_htc_tx_ctl {
|
||||
|
|
|
|||
|
|
@ -813,6 +813,11 @@ int ath9k_tx_init(struct ath9k_htc_priv *priv)
|
|||
skb_queue_head_init(&priv->tx.data_vi_queue);
|
||||
skb_queue_head_init(&priv->tx.data_vo_queue);
|
||||
skb_queue_head_init(&priv->tx.tx_failed);
|
||||
|
||||
/* Allow ath9k_wmi_event_tasklet(WMI_TXSTATUS_EVENTID) to operate. */
|
||||
smp_wmb();
|
||||
priv->tx.initialized = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1130,6 +1135,10 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb,
|
|||
struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
/* Check if ath9k_rx_init() completed. */
|
||||
if (!data_race(priv->rx.initialized))
|
||||
goto err;
|
||||
|
||||
spin_lock_irqsave(&priv->rx.rxbuflock, flags);
|
||||
list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) {
|
||||
if (!tmp_buf->in_process) {
|
||||
|
|
@ -1185,6 +1194,10 @@ int ath9k_rx_init(struct ath9k_htc_priv *priv)
|
|||
list_add_tail(&rxbuf->list, &priv->rx.rxbuf);
|
||||
}
|
||||
|
||||
/* Allow ath9k_htc_rxep() to operate. */
|
||||
smp_wmb();
|
||||
priv->rx.initialized = true;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
|
|
|
|||
|
|
@ -169,6 +169,10 @@ void ath9k_wmi_event_tasklet(struct tasklet_struct *t)
|
|||
&wmi->drv_priv->fatal_work);
|
||||
break;
|
||||
case WMI_TXSTATUS_EVENTID:
|
||||
/* Check if ath9k_tx_init() completed. */
|
||||
if (!data_race(priv->tx.initialized))
|
||||
break;
|
||||
|
||||
spin_lock_bh(&priv->tx.tx_lock);
|
||||
if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) {
|
||||
spin_unlock_bh(&priv->tx.tx_lock);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user