Debugfs support to do hardware warm reset with WMI command
WMI_PDEV_PARAM_PDEV_RESET for 10.4 and 10.2.4(if wmi
service is enabled in the firmware for backward compatibility).

This change is purely for debugging purpose when hardware hangs/mutes.

This hardware reset won't affect the connectivity but there will be small
pause in data traffic. Here we are doing BB/MAC level reset and hence
whenever the BB/MAC watchdog is triggered, it does a hardware_chip_reset.
So the target will be in the active state.

Below command used to warm reset the hardware.
echo 1 > /sys/kernel/debug/ieee80211/phyX/ath10k/warm_hw_reset

Tested in QCA988X with firmware ver 10.2.4.70.45
Tested in QCA4019 with firmware ver 10.4-3.2.1.1-00011

Signed-off-by: Maharaja Kennadyrajan <[email protected]>
---
 drivers/net/wireless/ath/ath10k/debug.c | 49 +++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/wmi.c   |  2 +-
 drivers/net/wireless/ath/ath10k/wmi.h   | 16 ++++++++++-
 3 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/debug.c 
b/drivers/net/wireless/ath/ath10k/debug.c
index 4926722..0baaad9 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -2297,6 +2297,52 @@ static ssize_t ath10k_tpc_stats_final_read(struct file 
*file,
        .llseek = default_llseek,
 };
 
+static ssize_t ath10k_write_warm_hw_reset(struct file *file,
+                                         const char __user *user_buf,
+                                         size_t count, loff_t *ppos)
+{
+       struct ath10k *ar = file->private_data;
+       int ret;
+       bool val;
+
+       if (kstrtobool_from_user(user_buf, count, &val))
+               return -EFAULT;
+
+       if (!val)
+               return -EINVAL;
+
+       mutex_lock(&ar->conf_mutex);
+
+       if (ar->state != ATH10K_STATE_ON) {
+               ret = -ENETDOWN;
+               goto exit;
+       }
+
+       if (!(test_bit(WMI_SERVICE_RESET_CHIP, ar->wmi.svc_map)))
+               ath10k_warn(ar, "wmi service for reset chip is not 
available\n");
+
+       ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->pdev_reset,
+                                       WMI_RST_MODE_WARM_RESET);
+
+       if (ret) {
+               ath10k_warn(ar, "failed to enable warm hw reset: %d\n", ret);
+               goto exit;
+       }
+
+       ret = count;
+
+exit:
+       mutex_unlock(&ar->conf_mutex);
+       return ret;
+}
+
+static const struct file_operations fops_warm_hw_reset = {
+       .write = ath10k_write_warm_hw_reset,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
 int ath10k_debug_create(struct ath10k *ar)
 {
        ar->debug.cal_data = vzalloc(ATH10K_DEBUG_CAL_DATA_LEN);
@@ -2425,6 +2471,9 @@ int ath10k_debug_register(struct ath10k *ar)
                                    ar->debug.debugfs_phy, ar,
                                    &fops_tpc_stats_final);
 
+       debugfs_create_file("warm_hw_reset", 0600, ar->debug.debugfs_phy, ar,
+                           &fops_warm_hw_reset);
+
        return 0;
 }
 
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c 
b/drivers/net/wireless/ath/ath10k/wmi.c
index 877249a..2fb972e 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1333,7 +1333,7 @@
        .enable_per_tid_ampdu = WMI_PDEV_PARAM_UNSUPPORTED,
        .cca_threshold = WMI_PDEV_PARAM_UNSUPPORTED,
        .rts_fixed_rate = WMI_PDEV_PARAM_UNSUPPORTED,
-       .pdev_reset = WMI_PDEV_PARAM_UNSUPPORTED,
+       .pdev_reset = WMI_10X_PDEV_PARAM_PDEV_RESET,
        .wapi_mbssid_offset = WMI_PDEV_PARAM_UNSUPPORTED,
        .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
        .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h 
b/drivers/net/wireless/ath/ath10k/wmi.h
index d68afb6..e24d869 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -462,6 +462,7 @@ static inline char *wmi_service_name(int service_id)
        SVCSTR(WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS);
        SVCSTR(WMI_SERVICE_HOST_DFS_CHECK_SUPPORT);
        SVCSTR(WMI_SERVICE_TPC_STATS_FINAL);
+       SVCSTR(WMI_SERVICE_RESET_CHIP);
        default:
                return NULL;
        }
@@ -3934,7 +3935,11 @@ enum wmi_10x_pdev_param {
        WMI_10X_PDEV_PARAM_REMOVE_MCAST2UCAST_BUFFER,
        WMI_10X_PDEV_PARAM_PEER_STA_PS_STATECHG_ENABLE,
        WMI_10X_PDEV_PARAM_RTS_FIXED_RATE,
-       WMI_10X_PDEV_PARAM_CAL_PERIOD
+       WMI_10X_PDEV_PARAM_CAL_PERIOD,
+       WMI_10X_PDEV_PARAM_ATF_STRICT_SCH,
+       WMI_10X_PDEV_PARAM_ATF_SCHED_DURATION,
+       WMI_10X_PDEV_PARAM_SET_PROMISC_MODE_CMDID,
+       WMI_10X_PDEV_PARAM_PDEV_RESET
 };
 
 enum wmi_10_4_pdev_param {
@@ -6501,6 +6506,15 @@ struct wmi_force_fw_hang_cmd {
        __le32 delay_ms;
 } __packed;
 
+enum wmi_pdev_reset_mode_type {
+       WMI_RST_MODE_TX_FLUSH = 1,
+       WMI_RST_MODE_WARM_RESET,
+       WMI_RST_MODE_COLD_RESET,
+       WMI_RST_MODE_WARM_RESET_RESTORE_CAL,
+       WMI_RST_MODE_COLD_RESET_RESTORE_CAL,
+       WMI_RST_MODE_MAX,
+};
+
 enum ath10k_dbglog_level {
        ATH10K_DBGLOG_LEVEL_VERBOSE = 0,
        ATH10K_DBGLOG_LEVEL_INFO = 1,
-- 
1.9.1


_______________________________________________
ath10k mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/ath10k

Reply via email to