|
@@ -3018,8 +3018,6 @@ static void ath10k_wmi_update_noa(struct ath10k *ar, struct ath10k_vif *arvif,
|
|
|
memcpy(skb_put(bcn, arvif->u.ap.noa_len),
|
|
|
arvif->u.ap.noa_data,
|
|
|
arvif->u.ap.noa_len);
|
|
|
-
|
|
|
- return;
|
|
|
}
|
|
|
|
|
|
static int ath10k_wmi_op_pull_swba_ev(struct ath10k *ar, struct sk_buff *skb,
|
|
@@ -3507,7 +3505,7 @@ void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
|
|
|
tsf);
|
|
|
if (res < 0) {
|
|
|
ath10k_dbg(ar, ATH10K_DBG_WMI, "failed to process fft report: %d\n",
|
|
|
- res);
|
|
|
+ res);
|
|
|
return;
|
|
|
}
|
|
|
break;
|
|
@@ -3835,9 +3833,258 @@ void ath10k_wmi_event_dcs_interference(struct ath10k *ar, struct sk_buff *skb)
|
|
|
ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_DCS_INTERFERENCE_EVENTID\n");
|
|
|
}
|
|
|
|
|
|
+static u8 ath10k_tpc_config_get_rate(struct ath10k *ar,
|
|
|
+ struct wmi_pdev_tpc_config_event *ev,
|
|
|
+ u32 rate_idx, u32 num_chains,
|
|
|
+ u32 rate_code, u8 type)
|
|
|
+{
|
|
|
+ u8 tpc, num_streams, preamble, ch, stm_idx;
|
|
|
+
|
|
|
+ num_streams = ATH10K_HW_NSS(rate_code);
|
|
|
+ preamble = ATH10K_HW_PREAMBLE(rate_code);
|
|
|
+ ch = num_chains - 1;
|
|
|
+
|
|
|
+ tpc = min_t(u8, ev->rates_array[rate_idx], ev->max_reg_allow_pow[ch]);
|
|
|
+
|
|
|
+ if (__le32_to_cpu(ev->num_tx_chain) <= 1)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ if (preamble == WMI_RATE_PREAMBLE_CCK)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ stm_idx = num_streams - 1;
|
|
|
+ if (num_chains <= num_streams)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ switch (type) {
|
|
|
+ case WMI_TPC_TABLE_TYPE_STBC:
|
|
|
+ tpc = min_t(u8, tpc,
|
|
|
+ ev->max_reg_allow_pow_agstbc[ch - 1][stm_idx]);
|
|
|
+ break;
|
|
|
+ case WMI_TPC_TABLE_TYPE_TXBF:
|
|
|
+ tpc = min_t(u8, tpc,
|
|
|
+ ev->max_reg_allow_pow_agtxbf[ch - 1][stm_idx]);
|
|
|
+ break;
|
|
|
+ case WMI_TPC_TABLE_TYPE_CDD:
|
|
|
+ tpc = min_t(u8, tpc,
|
|
|
+ ev->max_reg_allow_pow_agcdd[ch - 1][stm_idx]);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ ath10k_warn(ar, "unknown wmi tpc table type: %d\n", type);
|
|
|
+ tpc = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+out:
|
|
|
+ return tpc;
|
|
|
+}
|
|
|
+
|
|
|
+static void ath10k_tpc_config_disp_tables(struct ath10k *ar,
|
|
|
+ struct wmi_pdev_tpc_config_event *ev,
|
|
|
+ struct ath10k_tpc_stats *tpc_stats,
|
|
|
+ u8 *rate_code, u16 *pream_table, u8 type)
|
|
|
+{
|
|
|
+ u32 i, j, pream_idx, flags;
|
|
|
+ u8 tpc[WMI_TPC_TX_N_CHAIN];
|
|
|
+ char tpc_value[WMI_TPC_TX_N_CHAIN * WMI_TPC_BUF_SIZE];
|
|
|
+ char buff[WMI_TPC_BUF_SIZE];
|
|
|
+
|
|
|
+ flags = __le32_to_cpu(ev->flags);
|
|
|
+
|
|
|
+ switch (type) {
|
|
|
+ case WMI_TPC_TABLE_TYPE_CDD:
|
|
|
+ if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_CDD)) {
|
|
|
+ ath10k_dbg(ar, ATH10K_DBG_WMI, "CDD not supported\n");
|
|
|
+ tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case WMI_TPC_TABLE_TYPE_STBC:
|
|
|
+ if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_STBC)) {
|
|
|
+ ath10k_dbg(ar, ATH10K_DBG_WMI, "STBC not supported\n");
|
|
|
+ tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case WMI_TPC_TABLE_TYPE_TXBF:
|
|
|
+ if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_TXBF)) {
|
|
|
+ ath10k_dbg(ar, ATH10K_DBG_WMI, "TXBF not supported\n");
|
|
|
+ tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
|
|
|
+ "invalid table type in wmi tpc event: %d\n", type);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ pream_idx = 0;
|
|
|
+ for (i = 0; i < __le32_to_cpu(ev->rate_max); i++) {
|
|
|
+ memset(tpc_value, 0, sizeof(tpc_value));
|
|
|
+ memset(buff, 0, sizeof(buff));
|
|
|
+ if (i == pream_table[pream_idx])
|
|
|
+ pream_idx++;
|
|
|
+
|
|
|
+ for (j = 0; j < WMI_TPC_TX_N_CHAIN; j++) {
|
|
|
+ if (j >= __le32_to_cpu(ev->num_tx_chain))
|
|
|
+ break;
|
|
|
+
|
|
|
+ tpc[j] = ath10k_tpc_config_get_rate(ar, ev, i, j + 1,
|
|
|
+ rate_code[i],
|
|
|
+ type);
|
|
|
+ snprintf(buff, sizeof(buff), "%8d ", tpc[j]);
|
|
|
+ strncat(tpc_value, buff, strlen(buff));
|
|
|
+ }
|
|
|
+ tpc_stats->tpc_table[type].pream_idx[i] = pream_idx;
|
|
|
+ tpc_stats->tpc_table[type].rate_code[i] = rate_code[i];
|
|
|
+ memcpy(tpc_stats->tpc_table[type].tpc_value[i],
|
|
|
+ tpc_value, sizeof(tpc_value));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb)
|
|
|
{
|
|
|
- ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PDEV_TPC_CONFIG_EVENTID\n");
|
|
|
+ u32 i, j, pream_idx, num_tx_chain;
|
|
|
+ u8 rate_code[WMI_TPC_RATE_MAX], rate_idx;
|
|
|
+ u16 pream_table[WMI_TPC_PREAM_TABLE_MAX];
|
|
|
+ struct wmi_pdev_tpc_config_event *ev;
|
|
|
+ struct ath10k_tpc_stats *tpc_stats;
|
|
|
+
|
|
|
+ ev = (struct wmi_pdev_tpc_config_event *)skb->data;
|
|
|
+
|
|
|
+ tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC);
|
|
|
+ if (!tpc_stats)
|
|
|
+ return;
|
|
|
+
|
|
|
+ /* Create the rate code table based on the chains supported */
|
|
|
+ rate_idx = 0;
|
|
|
+ pream_idx = 0;
|
|
|
+
|
|
|
+ /* Fill CCK rate code */
|
|
|
+ for (i = 0; i < 4; i++) {
|
|
|
+ rate_code[rate_idx] =
|
|
|
+ ATH10K_HW_RATECODE(i, 0, WMI_RATE_PREAMBLE_CCK);
|
|
|
+ rate_idx++;
|
|
|
+ }
|
|
|
+ pream_table[pream_idx] = rate_idx;
|
|
|
+ pream_idx++;
|
|
|
+
|
|
|
+ /* Fill OFDM rate code */
|
|
|
+ for (i = 0; i < 8; i++) {
|
|
|
+ rate_code[rate_idx] =
|
|
|
+ ATH10K_HW_RATECODE(i, 0, WMI_RATE_PREAMBLE_OFDM);
|
|
|
+ rate_idx++;
|
|
|
+ }
|
|
|
+ pream_table[pream_idx] = rate_idx;
|
|
|
+ pream_idx++;
|
|
|
+
|
|
|
+ num_tx_chain = __le32_to_cpu(ev->num_tx_chain);
|
|
|
+
|
|
|
+ /* Fill HT20 rate code */
|
|
|
+ for (i = 0; i < num_tx_chain; i++) {
|
|
|
+ for (j = 0; j < 8; j++) {
|
|
|
+ rate_code[rate_idx] =
|
|
|
+ ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_HT);
|
|
|
+ rate_idx++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ pream_table[pream_idx] = rate_idx;
|
|
|
+ pream_idx++;
|
|
|
+
|
|
|
+ /* Fill HT40 rate code */
|
|
|
+ for (i = 0; i < num_tx_chain; i++) {
|
|
|
+ for (j = 0; j < 8; j++) {
|
|
|
+ rate_code[rate_idx] =
|
|
|
+ ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_HT);
|
|
|
+ rate_idx++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ pream_table[pream_idx] = rate_idx;
|
|
|
+ pream_idx++;
|
|
|
+
|
|
|
+ /* Fill VHT20 rate code */
|
|
|
+ for (i = 0; i < __le32_to_cpu(ev->num_tx_chain); i++) {
|
|
|
+ for (j = 0; j < 10; j++) {
|
|
|
+ rate_code[rate_idx] =
|
|
|
+ ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_VHT);
|
|
|
+ rate_idx++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ pream_table[pream_idx] = rate_idx;
|
|
|
+ pream_idx++;
|
|
|
+
|
|
|
+ /* Fill VHT40 rate code */
|
|
|
+ for (i = 0; i < num_tx_chain; i++) {
|
|
|
+ for (j = 0; j < 10; j++) {
|
|
|
+ rate_code[rate_idx] =
|
|
|
+ ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_VHT);
|
|
|
+ rate_idx++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ pream_table[pream_idx] = rate_idx;
|
|
|
+ pream_idx++;
|
|
|
+
|
|
|
+ /* Fill VHT80 rate code */
|
|
|
+ for (i = 0; i < num_tx_chain; i++) {
|
|
|
+ for (j = 0; j < 10; j++) {
|
|
|
+ rate_code[rate_idx] =
|
|
|
+ ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_VHT);
|
|
|
+ rate_idx++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ pream_table[pream_idx] = rate_idx;
|
|
|
+ pream_idx++;
|
|
|
+
|
|
|
+ rate_code[rate_idx++] =
|
|
|
+ ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_CCK);
|
|
|
+ rate_code[rate_idx++] =
|
|
|
+ ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_OFDM);
|
|
|
+ rate_code[rate_idx++] =
|
|
|
+ ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_CCK);
|
|
|
+ rate_code[rate_idx++] =
|
|
|
+ ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_OFDM);
|
|
|
+ rate_code[rate_idx++] =
|
|
|
+ ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_OFDM);
|
|
|
+
|
|
|
+ pream_table[pream_idx] = ATH10K_TPC_PREAM_TABLE_END;
|
|
|
+
|
|
|
+ tpc_stats->chan_freq = __le32_to_cpu(ev->chan_freq);
|
|
|
+ tpc_stats->phy_mode = __le32_to_cpu(ev->phy_mode);
|
|
|
+ tpc_stats->ctl = __le32_to_cpu(ev->ctl);
|
|
|
+ tpc_stats->reg_domain = __le32_to_cpu(ev->reg_domain);
|
|
|
+ tpc_stats->twice_antenna_gain = a_sle32_to_cpu(ev->twice_antenna_gain);
|
|
|
+ tpc_stats->twice_antenna_reduction =
|
|
|
+ __le32_to_cpu(ev->twice_antenna_reduction);
|
|
|
+ tpc_stats->power_limit = __le32_to_cpu(ev->power_limit);
|
|
|
+ tpc_stats->twice_max_rd_power = __le32_to_cpu(ev->twice_max_rd_power);
|
|
|
+ tpc_stats->num_tx_chain = __le32_to_cpu(ev->num_tx_chain);
|
|
|
+ tpc_stats->rate_max = __le32_to_cpu(ev->rate_max);
|
|
|
+
|
|
|
+ ath10k_tpc_config_disp_tables(ar, ev, tpc_stats,
|
|
|
+ rate_code, pream_table,
|
|
|
+ WMI_TPC_TABLE_TYPE_CDD);
|
|
|
+ ath10k_tpc_config_disp_tables(ar, ev, tpc_stats,
|
|
|
+ rate_code, pream_table,
|
|
|
+ WMI_TPC_TABLE_TYPE_STBC);
|
|
|
+ ath10k_tpc_config_disp_tables(ar, ev, tpc_stats,
|
|
|
+ rate_code, pream_table,
|
|
|
+ WMI_TPC_TABLE_TYPE_TXBF);
|
|
|
+
|
|
|
+ ath10k_debug_tpc_stats_process(ar, tpc_stats);
|
|
|
+
|
|
|
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
|
|
|
+ "wmi event tpc config channel %d mode %d ctl %d regd %d gain %d %d limit %d max_power %d tx_chanins %d rates %d\n",
|
|
|
+ __le32_to_cpu(ev->chan_freq),
|
|
|
+ __le32_to_cpu(ev->phy_mode),
|
|
|
+ __le32_to_cpu(ev->ctl),
|
|
|
+ __le32_to_cpu(ev->reg_domain),
|
|
|
+ a_sle32_to_cpu(ev->twice_antenna_gain),
|
|
|
+ __le32_to_cpu(ev->twice_antenna_reduction),
|
|
|
+ __le32_to_cpu(ev->power_limit),
|
|
|
+ __le32_to_cpu(ev->twice_max_rd_power) / 2,
|
|
|
+ __le32_to_cpu(ev->num_tx_chain),
|
|
|
+ __le32_to_cpu(ev->rate_max));
|
|
|
}
|
|
|
|
|
|
void ath10k_wmi_event_pdev_ftm_intg(struct ath10k *ar, struct sk_buff *skb)
|
|
@@ -5090,7 +5337,7 @@ static struct sk_buff *ath10k_wmi_10_4_op_gen_init(struct ath10k *ar)
|
|
|
config.rx_timeout_pri[2] = __cpu_to_le32(TARGET_10_4_RX_TIMEOUT_LO_PRI);
|
|
|
config.rx_timeout_pri[3] = __cpu_to_le32(TARGET_10_4_RX_TIMEOUT_HI_PRI);
|
|
|
|
|
|
- config.rx_decap_mode = __cpu_to_le32(TARGET_10_4_RX_DECAP_MODE);
|
|
|
+ config.rx_decap_mode = __cpu_to_le32(ar->wmi.rx_decap_mode);
|
|
|
config.scan_max_pending_req = __cpu_to_le32(TARGET_10_4_SCAN_MAX_REQS);
|
|
|
config.bmiss_offload_max_vdev =
|
|
|
__cpu_to_le32(TARGET_10_4_BMISS_OFFLOAD_MAX_VDEV);
|
|
@@ -6356,6 +6603,399 @@ ath10k_wmi_op_gen_delba_send(struct ath10k *ar, u32 vdev_id, const u8 *mac,
|
|
|
return skb;
|
|
|
}
|
|
|
|
|
|
+static struct sk_buff *
|
|
|
+ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config(struct ath10k *ar, u32 param)
|
|
|
+{
|
|
|
+ struct wmi_pdev_get_tpc_config_cmd *cmd;
|
|
|
+ struct sk_buff *skb;
|
|
|
+
|
|
|
+ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
|
|
|
+ if (!skb)
|
|
|
+ return ERR_PTR(-ENOMEM);
|
|
|
+
|
|
|
+ cmd = (struct wmi_pdev_get_tpc_config_cmd *)skb->data;
|
|
|
+ cmd->param = __cpu_to_le32(param);
|
|
|
+
|
|
|
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
|
|
|
+ "wmi pdev get tcp config param:%d\n", param);
|
|
|
+ return skb;
|
|
|
+}
|
|
|
+
|
|
|
+size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head)
|
|
|
+{
|
|
|
+ struct ath10k_fw_stats_peer *i;
|
|
|
+ size_t num = 0;
|
|
|
+
|
|
|
+ list_for_each_entry(i, head, list)
|
|
|
+ ++num;
|
|
|
+
|
|
|
+ return num;
|
|
|
+}
|
|
|
+
|
|
|
+size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head)
|
|
|
+{
|
|
|
+ struct ath10k_fw_stats_vdev *i;
|
|
|
+ size_t num = 0;
|
|
|
+
|
|
|
+ list_for_each_entry(i, head, list)
|
|
|
+ ++num;
|
|
|
+
|
|
|
+ return num;
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+ath10k_wmi_fw_pdev_base_stats_fill(const struct ath10k_fw_stats_pdev *pdev,
|
|
|
+ char *buf, u32 *length)
|
|
|
+{
|
|
|
+ u32 len = *length;
|
|
|
+ u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
|
|
|
+
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "\n");
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s\n",
|
|
|
+ "ath10k PDEV stats");
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
|
|
|
+ "=================");
|
|
|
+
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "Channel noise floor", pdev->ch_noise_floor);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
|
|
|
+ "Channel TX power", pdev->chan_tx_power);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
|
|
|
+ "TX frame count", pdev->tx_frame_count);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
|
|
|
+ "RX frame count", pdev->rx_frame_count);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
|
|
|
+ "RX clear count", pdev->rx_clear_count);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
|
|
|
+ "Cycle count", pdev->cycle_count);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
|
|
|
+ "PHY error count", pdev->phy_err_count);
|
|
|
+
|
|
|
+ *length = len;
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+ath10k_wmi_fw_pdev_extra_stats_fill(const struct ath10k_fw_stats_pdev *pdev,
|
|
|
+ char *buf, u32 *length)
|
|
|
+{
|
|
|
+ u32 len = *length;
|
|
|
+ u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
|
|
|
+
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
|
|
|
+ "RTS bad count", pdev->rts_bad);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
|
|
|
+ "RTS good count", pdev->rts_good);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
|
|
|
+ "FCS bad count", pdev->fcs_bad);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
|
|
|
+ "No beacon count", pdev->no_beacons);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
|
|
|
+ "MIB int count", pdev->mib_int_count);
|
|
|
+
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "\n");
|
|
|
+ *length = len;
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+ath10k_wmi_fw_pdev_tx_stats_fill(const struct ath10k_fw_stats_pdev *pdev,
|
|
|
+ char *buf, u32 *length)
|
|
|
+{
|
|
|
+ u32 len = *length;
|
|
|
+ u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
|
|
|
+
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "\n%30s\n",
|
|
|
+ "ath10k PDEV TX stats");
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
|
|
|
+ "=================");
|
|
|
+
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "HTT cookies queued", pdev->comp_queued);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "HTT cookies disp.", pdev->comp_delivered);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "MSDU queued", pdev->msdu_enqued);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "MPDU queued", pdev->mpdu_enqued);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "MSDUs dropped", pdev->wmm_drop);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "Local enqued", pdev->local_enqued);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "Local freed", pdev->local_freed);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "HW queued", pdev->hw_queued);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "PPDUs reaped", pdev->hw_reaped);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "Num underruns", pdev->underrun);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "PPDUs cleaned", pdev->tx_abort);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "MPDUs requed", pdev->mpdus_requed);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "Excessive retries", pdev->tx_ko);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "HW rate", pdev->data_rc);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "Sched self tiggers", pdev->self_triggers);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "Dropped due to SW retries",
|
|
|
+ pdev->sw_retry_failure);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "Illegal rate phy errors",
|
|
|
+ pdev->illgl_rate_phy_err);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "Pdev continuous xretry", pdev->pdev_cont_xretry);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "TX timeout", pdev->pdev_tx_timeout);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "PDEV resets", pdev->pdev_resets);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "PHY underrun", pdev->phy_underrun);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "MPDU is more than txop limit", pdev->txop_ovf);
|
|
|
+ *length = len;
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+ath10k_wmi_fw_pdev_rx_stats_fill(const struct ath10k_fw_stats_pdev *pdev,
|
|
|
+ char *buf, u32 *length)
|
|
|
+{
|
|
|
+ u32 len = *length;
|
|
|
+ u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
|
|
|
+
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "\n%30s\n",
|
|
|
+ "ath10k PDEV RX stats");
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
|
|
|
+ "=================");
|
|
|
+
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "Mid PPDU route change",
|
|
|
+ pdev->mid_ppdu_route_change);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "Tot. number of statuses", pdev->status_rcvd);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "Extra frags on rings 0", pdev->r0_frags);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "Extra frags on rings 1", pdev->r1_frags);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "Extra frags on rings 2", pdev->r2_frags);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "Extra frags on rings 3", pdev->r3_frags);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "MSDUs delivered to HTT", pdev->htt_msdus);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "MPDUs delivered to HTT", pdev->htt_mpdus);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "MSDUs delivered to stack", pdev->loc_msdus);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "MPDUs delivered to stack", pdev->loc_mpdus);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "Oversized AMSUs", pdev->oversize_amsdu);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "PHY errors", pdev->phy_errs);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "PHY errors drops", pdev->phy_err_drop);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
|
|
+ "MPDU errors (FCS, MIC, ENC)", pdev->mpdu_errs);
|
|
|
+ *length = len;
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+ath10k_wmi_fw_vdev_stats_fill(const struct ath10k_fw_stats_vdev *vdev,
|
|
|
+ char *buf, u32 *length)
|
|
|
+{
|
|
|
+ u32 len = *length;
|
|
|
+ u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
|
|
|
+ "vdev id", vdev->vdev_id);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
|
|
|
+ "beacon snr", vdev->beacon_snr);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
|
|
|
+ "data snr", vdev->data_snr);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
|
|
|
+ "num rx frames", vdev->num_rx_frames);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
|
|
|
+ "num rts fail", vdev->num_rts_fail);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
|
|
|
+ "num rts success", vdev->num_rts_success);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
|
|
|
+ "num rx err", vdev->num_rx_err);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
|
|
|
+ "num rx discard", vdev->num_rx_discard);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
|
|
|
+ "num tx not acked", vdev->num_tx_not_acked);
|
|
|
+
|
|
|
+ for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames); i++)
|
|
|
+ len += scnprintf(buf + len, buf_len - len,
|
|
|
+ "%25s [%02d] %u\n",
|
|
|
+ "num tx frames", i,
|
|
|
+ vdev->num_tx_frames[i]);
|
|
|
+
|
|
|
+ for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_retries); i++)
|
|
|
+ len += scnprintf(buf + len, buf_len - len,
|
|
|
+ "%25s [%02d] %u\n",
|
|
|
+ "num tx frames retries", i,
|
|
|
+ vdev->num_tx_frames_retries[i]);
|
|
|
+
|
|
|
+ for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_failures); i++)
|
|
|
+ len += scnprintf(buf + len, buf_len - len,
|
|
|
+ "%25s [%02d] %u\n",
|
|
|
+ "num tx frames failures", i,
|
|
|
+ vdev->num_tx_frames_failures[i]);
|
|
|
+
|
|
|
+ for (i = 0 ; i < ARRAY_SIZE(vdev->tx_rate_history); i++)
|
|
|
+ len += scnprintf(buf + len, buf_len - len,
|
|
|
+ "%25s [%02d] 0x%08x\n",
|
|
|
+ "tx rate history", i,
|
|
|
+ vdev->tx_rate_history[i]);
|
|
|
+
|
|
|
+ for (i = 0 ; i < ARRAY_SIZE(vdev->beacon_rssi_history); i++)
|
|
|
+ len += scnprintf(buf + len, buf_len - len,
|
|
|
+ "%25s [%02d] %u\n",
|
|
|
+ "beacon rssi history", i,
|
|
|
+ vdev->beacon_rssi_history[i]);
|
|
|
+
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "\n");
|
|
|
+ *length = len;
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+ath10k_wmi_fw_peer_stats_fill(const struct ath10k_fw_stats_peer *peer,
|
|
|
+ char *buf, u32 *length)
|
|
|
+{
|
|
|
+ u32 len = *length;
|
|
|
+ u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
|
|
|
+
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %pM\n",
|
|
|
+ "Peer MAC address", peer->peer_macaddr);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
|
|
|
+ "Peer RSSI", peer->peer_rssi);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
|
|
|
+ "Peer TX rate", peer->peer_tx_rate);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
|
|
|
+ "Peer RX rate", peer->peer_rx_rate);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "\n");
|
|
|
+ *length = len;
|
|
|
+}
|
|
|
+
|
|
|
+void ath10k_wmi_main_op_fw_stats_fill(struct ath10k *ar,
|
|
|
+ struct ath10k_fw_stats *fw_stats,
|
|
|
+ char *buf)
|
|
|
+{
|
|
|
+ u32 len = 0;
|
|
|
+ u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
|
|
|
+ const struct ath10k_fw_stats_pdev *pdev;
|
|
|
+ const struct ath10k_fw_stats_vdev *vdev;
|
|
|
+ const struct ath10k_fw_stats_peer *peer;
|
|
|
+ size_t num_peers;
|
|
|
+ size_t num_vdevs;
|
|
|
+
|
|
|
+ spin_lock_bh(&ar->data_lock);
|
|
|
+
|
|
|
+ pdev = list_first_entry_or_null(&fw_stats->pdevs,
|
|
|
+ struct ath10k_fw_stats_pdev, list);
|
|
|
+ if (!pdev) {
|
|
|
+ ath10k_warn(ar, "failed to get pdev stats\n");
|
|
|
+ goto unlock;
|
|
|
+ }
|
|
|
+
|
|
|
+ num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers);
|
|
|
+ num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs);
|
|
|
+
|
|
|
+ ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len);
|
|
|
+ ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len);
|
|
|
+ ath10k_wmi_fw_pdev_rx_stats_fill(pdev, buf, &len);
|
|
|
+
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "\n");
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
|
|
|
+ "ath10k VDEV stats", num_vdevs);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
|
|
|
+ "=================");
|
|
|
+
|
|
|
+ list_for_each_entry(vdev, &fw_stats->vdevs, list) {
|
|
|
+ ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len);
|
|
|
+ }
|
|
|
+
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "\n");
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
|
|
|
+ "ath10k PEER stats", num_peers);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
|
|
|
+ "=================");
|
|
|
+
|
|
|
+ list_for_each_entry(peer, &fw_stats->peers, list) {
|
|
|
+ ath10k_wmi_fw_peer_stats_fill(peer, buf, &len);
|
|
|
+ }
|
|
|
+
|
|
|
+unlock:
|
|
|
+ spin_unlock_bh(&ar->data_lock);
|
|
|
+
|
|
|
+ if (len >= buf_len)
|
|
|
+ buf[len - 1] = 0;
|
|
|
+ else
|
|
|
+ buf[len] = 0;
|
|
|
+}
|
|
|
+
|
|
|
+void ath10k_wmi_10x_op_fw_stats_fill(struct ath10k *ar,
|
|
|
+ struct ath10k_fw_stats *fw_stats,
|
|
|
+ char *buf)
|
|
|
+{
|
|
|
+ unsigned int len = 0;
|
|
|
+ unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE;
|
|
|
+ const struct ath10k_fw_stats_pdev *pdev;
|
|
|
+ const struct ath10k_fw_stats_vdev *vdev;
|
|
|
+ const struct ath10k_fw_stats_peer *peer;
|
|
|
+ size_t num_peers;
|
|
|
+ size_t num_vdevs;
|
|
|
+
|
|
|
+ spin_lock_bh(&ar->data_lock);
|
|
|
+
|
|
|
+ pdev = list_first_entry_or_null(&fw_stats->pdevs,
|
|
|
+ struct ath10k_fw_stats_pdev, list);
|
|
|
+ if (!pdev) {
|
|
|
+ ath10k_warn(ar, "failed to get pdev stats\n");
|
|
|
+ goto unlock;
|
|
|
+ }
|
|
|
+
|
|
|
+ num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers);
|
|
|
+ num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs);
|
|
|
+
|
|
|
+ ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len);
|
|
|
+ ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len);
|
|
|
+ ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len);
|
|
|
+ ath10k_wmi_fw_pdev_rx_stats_fill(pdev, buf, &len);
|
|
|
+
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "\n");
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
|
|
|
+ "ath10k VDEV stats", num_vdevs);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
|
|
|
+ "=================");
|
|
|
+
|
|
|
+ list_for_each_entry(vdev, &fw_stats->vdevs, list) {
|
|
|
+ ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len);
|
|
|
+ }
|
|
|
+
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "\n");
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
|
|
|
+ "ath10k PEER stats", num_peers);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
|
|
|
+ "=================");
|
|
|
+
|
|
|
+ list_for_each_entry(peer, &fw_stats->peers, list) {
|
|
|
+ ath10k_wmi_fw_peer_stats_fill(peer, buf, &len);
|
|
|
+ }
|
|
|
+
|
|
|
+unlock:
|
|
|
+ spin_unlock_bh(&ar->data_lock);
|
|
|
+
|
|
|
+ if (len >= buf_len)
|
|
|
+ buf[len - 1] = 0;
|
|
|
+ else
|
|
|
+ buf[len] = 0;
|
|
|
+}
|
|
|
+
|
|
|
static const struct wmi_ops wmi_ops = {
|
|
|
.rx = ath10k_wmi_op_rx,
|
|
|
.map_svc = wmi_main_svc_map,
|
|
@@ -6414,6 +7054,7 @@ static const struct wmi_ops wmi_ops = {
|
|
|
.gen_addba_send = ath10k_wmi_op_gen_addba_send,
|
|
|
.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
|
|
|
.gen_delba_send = ath10k_wmi_op_gen_delba_send,
|
|
|
+ .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
|
|
|
/* .gen_bcn_tmpl not implemented */
|
|
|
/* .gen_prb_tmpl not implemented */
|
|
|
/* .gen_p2p_go_bcn_ie not implemented */
|
|
@@ -6479,6 +7120,7 @@ static const struct wmi_ops wmi_10_1_ops = {
|
|
|
.gen_addba_send = ath10k_wmi_op_gen_addba_send,
|
|
|
.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
|
|
|
.gen_delba_send = ath10k_wmi_op_gen_delba_send,
|
|
|
+ .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
|
|
|
/* .gen_bcn_tmpl not implemented */
|
|
|
/* .gen_prb_tmpl not implemented */
|
|
|
/* .gen_p2p_go_bcn_ie not implemented */
|
|
@@ -6545,6 +7187,7 @@ static const struct wmi_ops wmi_10_2_ops = {
|
|
|
.gen_addba_send = ath10k_wmi_op_gen_addba_send,
|
|
|
.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
|
|
|
.gen_delba_send = ath10k_wmi_op_gen_delba_send,
|
|
|
+ .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
|
|
|
};
|
|
|
|
|
|
static const struct wmi_ops wmi_10_2_4_ops = {
|
|
@@ -6606,6 +7249,8 @@ static const struct wmi_ops wmi_10_2_4_ops = {
|
|
|
.gen_addba_send = ath10k_wmi_op_gen_addba_send,
|
|
|
.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
|
|
|
.gen_delba_send = ath10k_wmi_op_gen_delba_send,
|
|
|
+ .gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config,
|
|
|
+ .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
|
|
|
/* .gen_bcn_tmpl not implemented */
|
|
|
/* .gen_prb_tmpl not implemented */
|
|
|
/* .gen_p2p_go_bcn_ie not implemented */
|