These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / net / wireless / ath / ath10k / debug.c
index 301081d..6cc1aa3 100644 (file)
@@ -124,17 +124,35 @@ EXPORT_SYMBOL(ath10k_info);
 
 void ath10k_print_driver_info(struct ath10k *ar)
 {
-       ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d wmi %d cal %s max_sta %d\n",
+       char fw_features[128] = {};
+       char boardinfo[100];
+
+       ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));
+
+       if (ar->id.bmi_ids_valid)
+               scnprintf(boardinfo, sizeof(boardinfo), "bmi %d:%d",
+                         ar->id.bmi_chip_id, ar->id.bmi_board_id);
+       else
+               scnprintf(boardinfo, sizeof(boardinfo), "sub %04x:%04x",
+                         ar->id.subsystem_vendor, ar->id.subsystem_device);
+
+       ath10k_info(ar, "%s (0x%08x, 0x%08x %s) fw %s fwapi %d bdapi %d htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d features %s\n",
                    ar->hw_params.name,
                    ar->target_version,
                    ar->chip_id,
+                   boardinfo,
                    ar->hw->wiphy->fw_version,
                    ar->fw_api,
+                   ar->bd_api,
                    ar->htt.target_version_major,
                    ar->htt.target_version_minor,
                    ar->wmi.op_version,
+                   ar->htt.op_version,
                    ath10k_cal_mode_str(ar->cal_mode),
-                   ar->max_num_stations);
+                   ar->max_num_stations,
+                   test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags),
+                   !test_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags),
+                   fw_features);
        ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n",
                    config_enabled(CONFIG_ATH10K_DEBUG),
                    config_enabled(CONFIG_ATH10K_DEBUGFS),
@@ -273,28 +291,6 @@ static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
        spin_unlock_bh(&ar->data_lock);
 }
 
-static size_t ath10k_debug_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;
-}
-
-static size_t ath10k_debug_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;
-}
-
 void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
 {
        struct ath10k_fw_stats stats = {};
@@ -311,7 +307,7 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
        ret = ath10k_wmi_pull_fw_stats(ar, skb, &stats);
        if (ret) {
                ath10k_warn(ar, "failed to pull fw stats: %d\n", ret);
-               goto unlock;
+               goto free;
        }
 
        /* Stat data may exceed htc-wmi buffer limit. In such case firmware
@@ -331,8 +327,8 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
                goto free;
        }
 
-       num_peers = ath10k_debug_fw_stats_num_peers(&ar->debug.fw_stats.peers);
-       num_vdevs = ath10k_debug_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs);
+       num_peers = ath10k_wmi_fw_stats_num_peers(&ar->debug.fw_stats.peers);
+       num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs);
        is_start = (list_empty(&ar->debug.fw_stats.pdevs) &&
                    !list_empty(&stats.pdevs));
        is_end = (!list_empty(&ar->debug.fw_stats.pdevs) &&
@@ -374,18 +370,17 @@ free:
        ath10k_debug_fw_stats_vdevs_free(&stats.vdevs);
        ath10k_debug_fw_stats_peers_free(&stats.peers);
 
-unlock:
        spin_unlock_bh(&ar->data_lock);
 }
 
 static int ath10k_debug_fw_stats_request(struct ath10k *ar)
 {
-       unsigned long timeout;
+       unsigned long timeout, time_left;
        int ret;
 
        lockdep_assert_held(&ar->conf_mutex);
 
-       timeout = jiffies + msecs_to_jiffies(1*HZ);
+       timeout = jiffies + msecs_to_jiffies(1 * HZ);
 
        ath10k_debug_fw_stats_reset(ar);
 
@@ -395,18 +390,16 @@ static int ath10k_debug_fw_stats_request(struct ath10k *ar)
 
                reinit_completion(&ar->debug.fw_stats_complete);
 
-               ret = ath10k_wmi_request_stats(ar,
-                                              WMI_STAT_PDEV |
-                                              WMI_STAT_VDEV |
-                                              WMI_STAT_PEER);
+               ret = ath10k_wmi_request_stats(ar, ar->fw_stats_req_mask);
                if (ret) {
                        ath10k_warn(ar, "could not request stats (%d)\n", ret);
                        return ret;
                }
 
-               ret = wait_for_completion_timeout(&ar->debug.fw_stats_complete,
-                                                 1*HZ);
-               if (ret == 0)
+               time_left =
+               wait_for_completion_timeout(&ar->debug.fw_stats_complete,
+                                           1 * HZ);
+               if (!time_left)
                        return -ETIMEDOUT;
 
                spin_lock_bh(&ar->data_lock);
@@ -420,240 +413,6 @@ static int ath10k_debug_fw_stats_request(struct ath10k *ar)
        return 0;
 }
 
-/* FIXME: How to calculate the buffer size sanely? */
-#define ATH10K_FW_STATS_BUF_SIZE (1024*1024)
-
-static void ath10k_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;
-       int i;
-
-       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_debug_fw_stats_num_peers(&fw_stats->peers);
-       num_vdevs = ath10k_debug_fw_stats_num_vdevs(&fw_stats->vdevs);
-
-       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);
-       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");
-       len += scnprintf(buf + len, buf_len - len, "%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 continous 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);
-
-       len += scnprintf(buf + len, buf_len - len, "\n");
-       len += scnprintf(buf + len, buf_len - len, "%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);
-
-       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) {
-               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");
-       }
-
-       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) {
-               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");
-       }
-
-unlock:
-       spin_unlock_bh(&ar->data_lock);
-
-       if (len >= buf_len)
-               buf[len - 1] = 0;
-       else
-               buf[len] = 0;
-}
-
 static int ath10k_fw_stats_open(struct inode *inode, struct file *file)
 {
        struct ath10k *ar = inode->i_private;
@@ -679,7 +438,12 @@ static int ath10k_fw_stats_open(struct inode *inode, struct file *file)
                goto err_free;
        }
 
-       ath10k_fw_stats_fill(ar, &ar->debug.fw_stats, buf);
+       ret = ath10k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, buf);
+       if (ret) {
+               ath10k_warn(ar, "failed to fill fw stats: %d\n", ret);
+               goto err_free;
+       }
+
        file->private_data = buf;
 
        mutex_unlock(&ar->conf_mutex);
@@ -1355,12 +1119,8 @@ static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,
 
        mutex_lock(&ar->conf_mutex);
 
-       if (ar->debug.htt_max_amsdu)
-               amsdu = ar->debug.htt_max_amsdu;
-
-       if (ar->debug.htt_max_ampdu)
-               ampdu = ar->debug.htt_max_ampdu;
-
+       amsdu = ar->htt.max_num_amsdu;
+       ampdu = ar->htt.max_num_ampdu;
        mutex_unlock(&ar->conf_mutex);
 
        len = scnprintf(buf, sizeof(buf), "%u %u\n", amsdu, ampdu);
@@ -1394,8 +1154,8 @@ static ssize_t ath10k_write_htt_max_amsdu_ampdu(struct file *file,
                goto out;
 
        res = count;
-       ar->debug.htt_max_amsdu = amsdu;
-       ar->debug.htt_max_ampdu = ampdu;
+       ar->htt.max_num_amsdu = amsdu;
+       ar->htt.max_num_ampdu = ampdu;
 
 out:
        mutex_unlock(&ar->conf_mutex);
@@ -1708,6 +1468,61 @@ static int ath10k_debug_cal_data_release(struct inode *inode,
        return 0;
 }
 
+static ssize_t ath10k_write_ani_enable(struct file *file,
+                                      const char __user *user_buf,
+                                      size_t count, loff_t *ppos)
+{
+       struct ath10k *ar = file->private_data;
+       int ret;
+       u8 enable;
+
+       if (kstrtou8_from_user(user_buf, count, 0, &enable))
+               return -EINVAL;
+
+       mutex_lock(&ar->conf_mutex);
+
+       if (ar->ani_enabled == enable) {
+               ret = count;
+               goto exit;
+       }
+
+       ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->ani_enable,
+                                       enable);
+       if (ret) {
+               ath10k_warn(ar, "ani_enable failed from debugfs: %d\n", ret);
+               goto exit;
+       }
+       ar->ani_enabled = enable;
+
+       ret = count;
+
+exit:
+       mutex_unlock(&ar->conf_mutex);
+
+       return ret;
+}
+
+static ssize_t ath10k_read_ani_enable(struct file *file, char __user *user_buf,
+                                     size_t count, loff_t *ppos)
+{
+       struct ath10k *ar = file->private_data;
+       int len = 0;
+       char buf[32];
+
+       len = scnprintf(buf, sizeof(buf) - len, "%d\n",
+                       ar->ani_enabled);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_ani_enable = {
+       .read = ath10k_read_ani_enable,
+       .write = ath10k_write_ani_enable,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
 static const struct file_operations fops_cal_data = {
        .open = ath10k_debug_cal_data_open,
        .read = ath10k_debug_cal_data_read,
@@ -1783,6 +1598,233 @@ static const struct file_operations fops_nf_cal_period = {
        .llseek = default_llseek,
 };
 
+#define ATH10K_TPC_CONFIG_BUF_SIZE     (1024 * 1024)
+
+static int ath10k_debug_tpc_stats_request(struct ath10k *ar)
+{
+       int ret;
+       unsigned long time_left;
+
+       lockdep_assert_held(&ar->conf_mutex);
+
+       reinit_completion(&ar->debug.tpc_complete);
+
+       ret = ath10k_wmi_pdev_get_tpc_config(ar, WMI_TPC_CONFIG_PARAM);
+       if (ret) {
+               ath10k_warn(ar, "failed to request tpc config: %d\n", ret);
+               return ret;
+       }
+
+       time_left = wait_for_completion_timeout(&ar->debug.tpc_complete,
+                                               1 * HZ);
+       if (time_left == 0)
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+void ath10k_debug_tpc_stats_process(struct ath10k *ar,
+                                   struct ath10k_tpc_stats *tpc_stats)
+{
+       spin_lock_bh(&ar->data_lock);
+
+       kfree(ar->debug.tpc_stats);
+       ar->debug.tpc_stats = tpc_stats;
+       complete(&ar->debug.tpc_complete);
+
+       spin_unlock_bh(&ar->data_lock);
+}
+
+static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats,
+                                  unsigned int j, char *buf, unsigned int *len)
+{
+       unsigned int i, buf_len;
+       static const char table_str[][5] = { "CDD",
+                                            "STBC",
+                                            "TXBF" };
+       static const char pream_str[][6] = { "CCK",
+                                            "OFDM",
+                                            "HT20",
+                                            "HT40",
+                                            "VHT20",
+                                            "VHT40",
+                                            "VHT80",
+                                            "HTCUP" };
+
+       buf_len = ATH10K_TPC_CONFIG_BUF_SIZE;
+       *len += scnprintf(buf + *len, buf_len - *len,
+                         "********************************\n");
+       *len += scnprintf(buf + *len, buf_len - *len,
+                         "******************* %s POWER TABLE ****************\n",
+                         table_str[j]);
+       *len += scnprintf(buf + *len, buf_len - *len,
+                         "********************************\n");
+       *len += scnprintf(buf + *len, buf_len - *len,
+                         "No.  Preamble Rate_code tpc_value1 tpc_value2 tpc_value3\n");
+
+       for (i = 0; i < tpc_stats->rate_max; i++) {
+               *len += scnprintf(buf + *len, buf_len - *len,
+                                 "%8d %s 0x%2x %s\n", i,
+                                 pream_str[tpc_stats->tpc_table[j].pream_idx[i]],
+                                 tpc_stats->tpc_table[j].rate_code[i],
+                                 tpc_stats->tpc_table[j].tpc_value[i]);
+       }
+
+       *len += scnprintf(buf + *len, buf_len - *len,
+                         "***********************************\n");
+}
+
+static void ath10k_tpc_stats_fill(struct ath10k *ar,
+                                 struct ath10k_tpc_stats *tpc_stats,
+                                 char *buf)
+{
+       unsigned int len, j, buf_len;
+
+       len = 0;
+       buf_len = ATH10K_TPC_CONFIG_BUF_SIZE;
+
+       spin_lock_bh(&ar->data_lock);
+
+       if (!tpc_stats) {
+               ath10k_warn(ar, "failed to get tpc stats\n");
+               goto unlock;
+       }
+
+       len += scnprintf(buf + len, buf_len - len, "\n");
+       len += scnprintf(buf + len, buf_len - len,
+                        "*************************************\n");
+       len += scnprintf(buf + len, buf_len - len,
+                        "TPC config for channel %4d mode %d\n",
+                        tpc_stats->chan_freq,
+                        tpc_stats->phy_mode);
+       len += scnprintf(buf + len, buf_len - len,
+                        "*************************************\n");
+       len += scnprintf(buf + len, buf_len - len,
+                        "CTL           =  0x%2x Reg. Domain            = %2d\n",
+                        tpc_stats->ctl,
+                        tpc_stats->reg_domain);
+       len += scnprintf(buf + len, buf_len - len,
+                        "Antenna Gain  = %2d Reg. Max Antenna Gain     =  %2d\n",
+                        tpc_stats->twice_antenna_gain,
+                        tpc_stats->twice_antenna_reduction);
+       len += scnprintf(buf + len, buf_len - len,
+                        "Power Limit   = %2d Reg. Max Power            = %2d\n",
+                        tpc_stats->power_limit,
+                        tpc_stats->twice_max_rd_power / 2);
+       len += scnprintf(buf + len, buf_len - len,
+                        "Num tx chains = %2d Num supported rates       = %2d\n",
+                        tpc_stats->num_tx_chain,
+                        tpc_stats->rate_max);
+
+       for (j = 0; j < tpc_stats->num_tx_chain ; j++) {
+               switch (j) {
+               case WMI_TPC_TABLE_TYPE_CDD:
+                       if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
+                               len += scnprintf(buf + len, buf_len - len,
+                                                "CDD not supported\n");
+                               break;
+                       }
+
+                       ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
+                       break;
+               case WMI_TPC_TABLE_TYPE_STBC:
+                       if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
+                               len += scnprintf(buf + len, buf_len - len,
+                                                "STBC not supported\n");
+                               break;
+                       }
+
+                       ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
+                       break;
+               case WMI_TPC_TABLE_TYPE_TXBF:
+                       if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
+                               len += scnprintf(buf + len, buf_len - len,
+                                                "TXBF not supported\n***************************\n");
+                               break;
+                       }
+
+                       ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
+                       break;
+               default:
+                       len += scnprintf(buf + len, buf_len - len,
+                                        "Invalid Type\n");
+                       break;
+               }
+       }
+
+unlock:
+       spin_unlock_bh(&ar->data_lock);
+
+       if (len >= buf_len)
+               buf[len - 1] = 0;
+       else
+               buf[len] = 0;
+}
+
+static int ath10k_tpc_stats_open(struct inode *inode, struct file *file)
+{
+       struct ath10k *ar = inode->i_private;
+       void *buf = NULL;
+       int ret;
+
+       mutex_lock(&ar->conf_mutex);
+
+       if (ar->state != ATH10K_STATE_ON) {
+               ret = -ENETDOWN;
+               goto err_unlock;
+       }
+
+       buf = vmalloc(ATH10K_TPC_CONFIG_BUF_SIZE);
+       if (!buf) {
+               ret = -ENOMEM;
+               goto err_unlock;
+       }
+
+       ret = ath10k_debug_tpc_stats_request(ar);
+       if (ret) {
+               ath10k_warn(ar, "failed to request tpc config stats: %d\n",
+                           ret);
+               goto err_free;
+       }
+
+       ath10k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf);
+       file->private_data = buf;
+
+       mutex_unlock(&ar->conf_mutex);
+       return 0;
+
+err_free:
+       vfree(buf);
+
+err_unlock:
+       mutex_unlock(&ar->conf_mutex);
+       return ret;
+}
+
+static int ath10k_tpc_stats_release(struct inode *inode, struct file *file)
+{
+       vfree(file->private_data);
+
+       return 0;
+}
+
+static ssize_t ath10k_tpc_stats_read(struct file *file, char __user *user_buf,
+                                    size_t count, loff_t *ppos)
+{
+       const char *buf = file->private_data;
+       unsigned int len = strlen(buf);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_tpc_stats = {
+       .open = ath10k_tpc_stats_open,
+       .release = ath10k_tpc_stats_release,
+       .read = ath10k_tpc_stats_read,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
 int ath10k_debug_start(struct ath10k *ar)
 {
        int ret;
@@ -1842,9 +1884,6 @@ void ath10k_debug_stop(struct ath10k *ar)
        if (ar->debug.htt_stats_mask != 0)
                cancel_delayed_work(&ar->debug.htt_stats_dwork);
 
-       ar->debug.htt_max_amsdu = 0;
-       ar->debug.htt_max_ampdu = 0;
-
        ath10k_wmi_pdev_pktlog_disable(ar);
 }
 
@@ -1991,6 +2030,50 @@ static const struct file_operations fops_pktlog_filter = {
        .open = simple_open
 };
 
+static ssize_t ath10k_write_quiet_period(struct file *file,
+                                        const char __user *ubuf,
+                                        size_t count, loff_t *ppos)
+{
+       struct ath10k *ar = file->private_data;
+       u32 period;
+
+       if (kstrtouint_from_user(ubuf, count, 0, &period))
+               return -EINVAL;
+
+       if (period < ATH10K_QUIET_PERIOD_MIN) {
+               ath10k_warn(ar, "Quiet period %u can not be lesser than 25ms\n",
+                           period);
+               return -EINVAL;
+       }
+       mutex_lock(&ar->conf_mutex);
+       ar->thermal.quiet_period = period;
+       ath10k_thermal_set_throttling(ar);
+       mutex_unlock(&ar->conf_mutex);
+
+       return count;
+}
+
+static ssize_t ath10k_read_quiet_period(struct file *file, char __user *ubuf,
+                                       size_t count, loff_t *ppos)
+{
+       char buf[32];
+       struct ath10k *ar = file->private_data;
+       int len = 0;
+
+       mutex_lock(&ar->conf_mutex);
+       len = scnprintf(buf, sizeof(buf) - len, "%d\n",
+                       ar->thermal.quiet_period);
+       mutex_unlock(&ar->conf_mutex);
+
+       return simple_read_from_buffer(ubuf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_quiet_period = {
+       .read = ath10k_read_quiet_period,
+       .write = ath10k_write_quiet_period,
+       .open = simple_open
+};
+
 int ath10k_debug_create(struct ath10k *ar)
 {
        ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
@@ -2010,6 +2093,8 @@ void ath10k_debug_destroy(struct ath10k *ar)
        ar->debug.fw_crash_data = NULL;
 
        ath10k_debug_fw_stats_reset(ar);
+
+       kfree(ar->debug.tpc_stats);
 }
 
 int ath10k_debug_register(struct ath10k *ar)
@@ -2026,6 +2111,7 @@ int ath10k_debug_register(struct ath10k *ar)
        INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork,
                          ath10k_debug_htt_stats_dwork);
 
+       init_completion(&ar->debug.tpc_complete);
        init_completion(&ar->debug.fw_stats_complete);
 
        debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar,
@@ -2068,6 +2154,9 @@ int ath10k_debug_register(struct ath10k *ar)
        debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
                            ar, &fops_cal_data);
 
+       debugfs_create_file("ani_enable", S_IRUSR | S_IWUSR,
+                           ar->debug.debugfs_phy, ar, &fops_ani_enable);
+
        debugfs_create_file("nf_cal_period", S_IRUSR | S_IWUSR,
                            ar->debug.debugfs_phy, ar, &fops_nf_cal_period);
 
@@ -2088,6 +2177,12 @@ int ath10k_debug_register(struct ath10k *ar)
        debugfs_create_file("pktlog_filter", S_IRUGO | S_IWUSR,
                            ar->debug.debugfs_phy, ar, &fops_pktlog_filter);
 
+       debugfs_create_file("quiet_period", S_IRUGO | S_IWUSR,
+                           ar->debug.debugfs_phy, ar, &fops_quiet_period);
+
+       debugfs_create_file("tpc_stats", S_IRUSR,
+                           ar->debug.debugfs_phy, ar, &fops_tpc_stats);
+
        return 0;
 }