From 3d3450c55b983c22753a0f7ff197ec1525140348 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Mon, 1 Nov 2021 15:09:58 -0700 Subject: [PATCH] ath10k-ct: Add restart_failed debugfs file. So user-space can detect hung firmware/driver/HW and know it needs to reboot to recover. Signed-off-by: Ben Greear --- ath10k-5.10/core.c | 5 +++++ ath10k-5.10/core.h | 1 + ath10k-5.10/debug.c | 22 ++++++++++++++++++++++ ath10k-5.11/core.c | 5 +++++ ath10k-5.11/core.h | 1 + ath10k-5.11/debug.c | 22 ++++++++++++++++++++++ ath10k-5.12/core.c | 5 +++++ ath10k-5.12/core.h | 1 + ath10k-5.12/debug.c | 22 ++++++++++++++++++++++ ath10k-5.13/core.c | 5 +++++ ath10k-5.13/core.h | 1 + ath10k-5.13/debug.c | 22 ++++++++++++++++++++++ ath10k-5.15/Kconfig | 2 +- ath10k-5.15/core.c | 5 +++++ ath10k-5.15/core.h | 1 + ath10k-5.15/debug.c | 22 ++++++++++++++++++++++ 16 files changed, 141 insertions(+), 1 deletion(-) diff --git a/ath10k-5.10/core.c b/ath10k-5.10/core.c index 5465474..4fb119c 100644 --- a/ath10k-5.10/core.c +++ b/ath10k-5.10/core.c @@ -2819,6 +2819,8 @@ static void ath10k_core_restart(struct work_struct *work) mutex_lock(&ar->conf_mutex); + ar->restart_failed = 0; /* assume good things */ + switch (ar->state) { case ATH10K_STATE_ON: ar->state = ATH10K_STATE_RESTARTING; @@ -2831,6 +2833,7 @@ static void ath10k_core_restart(struct work_struct *work) * or if the crash happens during FW probing */ ath10k_warn(ar, "cannot restart a device that hasn't been started\n"); + ar->restart_failed = 1; break; case ATH10K_STATE_RESTARTING: /* hw restart might be requested from multiple places */ @@ -2840,9 +2843,11 @@ static void ath10k_core_restart(struct work_struct *work) fallthrough; case ATH10K_STATE_WEDGED: ath10k_warn(ar, "device is wedged, will not restart\n"); + ar->restart_failed = 2; break; case ATH10K_STATE_UTF: ath10k_warn(ar, "firmware restart in UTF mode not supported\n"); + ar->restart_failed = 3; break; } diff --git a/ath10k-5.10/core.h b/ath10k-5.10/core.h index f7dc8be..cc05c7a 100644 --- a/ath10k-5.10/core.h +++ b/ath10k-5.10/core.h @@ -1494,6 +1494,7 @@ struct ath10k { struct sk_buff_head wmi_mgmt_tx_queue; enum ath10k_state state; + int restart_failed; /* 0: ok, 1: state-off 2: wedged */ struct work_struct register_work; struct work_struct restart_work; diff --git a/ath10k-5.10/debug.c b/ath10k-5.10/debug.c index c397063..bc3ace3 100644 --- a/ath10k-5.10/debug.c +++ b/ath10k-5.10/debug.c @@ -1787,6 +1787,25 @@ static const struct file_operations fops_chip_id = { .llseek = default_llseek, }; +static ssize_t ath10k_read_restart_failed(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath10k *ar = file->private_data; + size_t len; + char buf[50]; + + len = scnprintf(buf, sizeof(buf), "%d\n", ar->restart_failed); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_restart_failed = { + .read = ath10k_read_restart_failed, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + static int ath10k_fw_crash_dump_open(struct inode *inode, struct file *file) { struct ath10k *ar = inode->i_private; @@ -4465,6 +4484,9 @@ int ath10k_debug_register(struct ath10k *ar) debugfs_create_file("chip_id", 0400, ar->debug.debugfs_phy, ar, &fops_chip_id); + debugfs_create_file("restart_failed", 0400, ar->debug.debugfs_phy, ar, + &fops_restart_failed); + debugfs_create_file("htt_stats_mask", 0600, ar->debug.debugfs_phy, ar, &fops_htt_stats_mask); diff --git a/ath10k-5.11/core.c b/ath10k-5.11/core.c index aec07bf..1e6d2f4 100644 --- a/ath10k-5.11/core.c +++ b/ath10k-5.11/core.c @@ -2877,6 +2877,8 @@ static void ath10k_core_restart(struct work_struct *work) mutex_lock(&ar->conf_mutex); + ar->restart_failed = 0; /* assume good things */ + switch (ar->state) { case ATH10K_STATE_ON: ar->state = ATH10K_STATE_RESTARTING; @@ -2889,6 +2891,7 @@ static void ath10k_core_restart(struct work_struct *work) * or if the crash happens during FW probing */ ath10k_warn(ar, "cannot restart a device that hasn't been started\n"); + ar->restart_failed = 1; break; case ATH10K_STATE_RESTARTING: /* hw restart might be requested from multiple places */ @@ -2898,9 +2901,11 @@ static void ath10k_core_restart(struct work_struct *work) fallthrough; case ATH10K_STATE_WEDGED: ath10k_warn(ar, "device is wedged, will not restart\n"); + ar->restart_failed = 2; break; case ATH10K_STATE_UTF: ath10k_warn(ar, "firmware restart in UTF mode not supported\n"); + ar->restart_failed = 3; break; } diff --git a/ath10k-5.11/core.h b/ath10k-5.11/core.h index f126841..77363da 100644 --- a/ath10k-5.11/core.h +++ b/ath10k-5.11/core.h @@ -1508,6 +1508,7 @@ struct ath10k { struct sk_buff_head wmi_mgmt_tx_queue; enum ath10k_state state; + int restart_failed; /* 0: ok, 1: state-off 2: wedged */ struct work_struct register_work; struct work_struct restart_work; diff --git a/ath10k-5.11/debug.c b/ath10k-5.11/debug.c index 8a16805..b0a4b97 100644 --- a/ath10k-5.11/debug.c +++ b/ath10k-5.11/debug.c @@ -1787,6 +1787,25 @@ static const struct file_operations fops_chip_id = { .llseek = default_llseek, }; +static ssize_t ath10k_read_restart_failed(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath10k *ar = file->private_data; + size_t len; + char buf[50]; + + len = scnprintf(buf, sizeof(buf), "%d\n", ar->restart_failed); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_restart_failed = { + .read = ath10k_read_restart_failed, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + static int ath10k_fw_crash_dump_open(struct inode *inode, struct file *file) { struct ath10k *ar = inode->i_private; @@ -4483,6 +4502,9 @@ int ath10k_debug_register(struct ath10k *ar) debugfs_create_file("chip_id", 0400, ar->debug.debugfs_phy, ar, &fops_chip_id); + debugfs_create_file("restart_failed", 0400, ar->debug.debugfs_phy, ar, + &fops_restart_failed); + debugfs_create_file("htt_stats_mask", 0600, ar->debug.debugfs_phy, ar, &fops_htt_stats_mask); diff --git a/ath10k-5.12/core.c b/ath10k-5.12/core.c index af7d948..c3dfa4a 100644 --- a/ath10k-5.12/core.c +++ b/ath10k-5.12/core.c @@ -2893,6 +2893,8 @@ static void ath10k_core_restart(struct work_struct *work) mutex_lock(&ar->conf_mutex); + ar->restart_failed = 0; /* assume good things */ + switch (ar->state) { case ATH10K_STATE_ON: ar->state = ATH10K_STATE_RESTARTING; @@ -2905,6 +2907,7 @@ static void ath10k_core_restart(struct work_struct *work) * or if the crash happens during FW probing */ ath10k_warn(ar, "cannot restart a device that hasn't been started\n"); + ar->restart_failed = 1; break; case ATH10K_STATE_RESTARTING: /* hw restart might be requested from multiple places */ @@ -2914,9 +2917,11 @@ static void ath10k_core_restart(struct work_struct *work) fallthrough; case ATH10K_STATE_WEDGED: ath10k_warn(ar, "device is wedged, will not restart\n"); + ar->restart_failed = 2; break; case ATH10K_STATE_UTF: ath10k_warn(ar, "firmware restart in UTF mode not supported\n"); + ar->restart_failed = 3; break; } diff --git a/ath10k-5.12/core.h b/ath10k-5.12/core.h index 729de6b..fced373 100644 --- a/ath10k-5.12/core.h +++ b/ath10k-5.12/core.h @@ -1507,6 +1507,7 @@ struct ath10k { struct sk_buff_head wmi_mgmt_tx_queue; enum ath10k_state state; + int restart_failed; /* 0: ok, 1: state-off 2: wedged */ struct work_struct register_work; struct work_struct restart_work; diff --git a/ath10k-5.12/debug.c b/ath10k-5.12/debug.c index 8a16805..b0a4b97 100644 --- a/ath10k-5.12/debug.c +++ b/ath10k-5.12/debug.c @@ -1787,6 +1787,25 @@ static const struct file_operations fops_chip_id = { .llseek = default_llseek, }; +static ssize_t ath10k_read_restart_failed(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath10k *ar = file->private_data; + size_t len; + char buf[50]; + + len = scnprintf(buf, sizeof(buf), "%d\n", ar->restart_failed); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_restart_failed = { + .read = ath10k_read_restart_failed, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + static int ath10k_fw_crash_dump_open(struct inode *inode, struct file *file) { struct ath10k *ar = inode->i_private; @@ -4483,6 +4502,9 @@ int ath10k_debug_register(struct ath10k *ar) debugfs_create_file("chip_id", 0400, ar->debug.debugfs_phy, ar, &fops_chip_id); + debugfs_create_file("restart_failed", 0400, ar->debug.debugfs_phy, ar, + &fops_restart_failed); + debugfs_create_file("htt_stats_mask", 0600, ar->debug.debugfs_phy, ar, &fops_htt_stats_mask); diff --git a/ath10k-5.13/core.c b/ath10k-5.13/core.c index af7d948..c3dfa4a 100644 --- a/ath10k-5.13/core.c +++ b/ath10k-5.13/core.c @@ -2893,6 +2893,8 @@ static void ath10k_core_restart(struct work_struct *work) mutex_lock(&ar->conf_mutex); + ar->restart_failed = 0; /* assume good things */ + switch (ar->state) { case ATH10K_STATE_ON: ar->state = ATH10K_STATE_RESTARTING; @@ -2905,6 +2907,7 @@ static void ath10k_core_restart(struct work_struct *work) * or if the crash happens during FW probing */ ath10k_warn(ar, "cannot restart a device that hasn't been started\n"); + ar->restart_failed = 1; break; case ATH10K_STATE_RESTARTING: /* hw restart might be requested from multiple places */ @@ -2914,9 +2917,11 @@ static void ath10k_core_restart(struct work_struct *work) fallthrough; case ATH10K_STATE_WEDGED: ath10k_warn(ar, "device is wedged, will not restart\n"); + ar->restart_failed = 2; break; case ATH10K_STATE_UTF: ath10k_warn(ar, "firmware restart in UTF mode not supported\n"); + ar->restart_failed = 3; break; } diff --git a/ath10k-5.13/core.h b/ath10k-5.13/core.h index dd130f5..c02790d 100644 --- a/ath10k-5.13/core.h +++ b/ath10k-5.13/core.h @@ -1507,6 +1507,7 @@ struct ath10k { struct sk_buff_head wmi_mgmt_tx_queue; enum ath10k_state state; + int restart_failed; /* 0: ok, 1: state-off 2: wedged */ struct work_struct register_work; struct work_struct restart_work; diff --git a/ath10k-5.13/debug.c b/ath10k-5.13/debug.c index 8a16805..b0a4b97 100644 --- a/ath10k-5.13/debug.c +++ b/ath10k-5.13/debug.c @@ -1787,6 +1787,25 @@ static const struct file_operations fops_chip_id = { .llseek = default_llseek, }; +static ssize_t ath10k_read_restart_failed(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath10k *ar = file->private_data; + size_t len; + char buf[50]; + + len = scnprintf(buf, sizeof(buf), "%d\n", ar->restart_failed); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_restart_failed = { + .read = ath10k_read_restart_failed, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + static int ath10k_fw_crash_dump_open(struct inode *inode, struct file *file) { struct ath10k *ar = inode->i_private; @@ -4483,6 +4502,9 @@ int ath10k_debug_register(struct ath10k *ar) debugfs_create_file("chip_id", 0400, ar->debug.debugfs_phy, ar, &fops_chip_id); + debugfs_create_file("restart_failed", 0400, ar->debug.debugfs_phy, ar, + &fops_restart_failed); + debugfs_create_file("htt_stats_mask", 0600, ar->debug.debugfs_phy, ar, &fops_htt_stats_mask); diff --git a/ath10k-5.15/Kconfig b/ath10k-5.15/Kconfig index 741289e..ca007b8 100644 --- a/ath10k-5.15/Kconfig +++ b/ath10k-5.15/Kconfig @@ -44,7 +44,7 @@ config ATH10K_SNOC tristate "Qualcomm ath10k SNOC support" depends on ATH10K depends on ARCH_QCOM || COMPILE_TEST - depends on QCOM_SCM || !QCOM_SCM #if QCOM_SCM=m this can't be =y + select QCOM_SCM select QCOM_QMI_HELPERS help This module adds support for integrated WCN3990 chip connected diff --git a/ath10k-5.15/core.c b/ath10k-5.15/core.c index 644dc10..c815c00 100644 --- a/ath10k-5.15/core.c +++ b/ath10k-5.15/core.c @@ -2894,6 +2894,8 @@ static void ath10k_core_restart(struct work_struct *work) mutex_lock(&ar->conf_mutex); + ar->restart_failed = 0; /* assume good things */ + switch (ar->state) { case ATH10K_STATE_ON: ar->state = ATH10K_STATE_RESTARTING; @@ -2906,6 +2908,7 @@ static void ath10k_core_restart(struct work_struct *work) * or if the crash happens during FW probing */ ath10k_warn(ar, "cannot restart a device that hasn't been started\n"); + ar->restart_failed = 1; break; case ATH10K_STATE_RESTARTING: /* hw restart might be requested from multiple places */ @@ -2915,9 +2918,11 @@ static void ath10k_core_restart(struct work_struct *work) fallthrough; case ATH10K_STATE_WEDGED: ath10k_warn(ar, "device is wedged, will not restart\n"); + ar->restart_failed = 2; break; case ATH10K_STATE_UTF: ath10k_warn(ar, "firmware restart in UTF mode not supported\n"); + ar->restart_failed = 3; break; } diff --git a/ath10k-5.15/core.h b/ath10k-5.15/core.h index a0727da..d4c8783 100644 --- a/ath10k-5.15/core.h +++ b/ath10k-5.15/core.h @@ -1507,6 +1507,7 @@ struct ath10k { struct sk_buff_head wmi_mgmt_tx_queue; enum ath10k_state state; + int restart_failed; /* 0: ok, 1: state-off 2: wedged */ struct work_struct register_work; struct work_struct restart_work; diff --git a/ath10k-5.15/debug.c b/ath10k-5.15/debug.c index 6f840b8..af84012 100644 --- a/ath10k-5.15/debug.c +++ b/ath10k-5.15/debug.c @@ -1787,6 +1787,25 @@ static const struct file_operations fops_chip_id = { .llseek = default_llseek, }; +static ssize_t ath10k_read_restart_failed(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath10k *ar = file->private_data; + size_t len; + char buf[50]; + + len = scnprintf(buf, sizeof(buf), "%d\n", ar->restart_failed); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_restart_failed = { + .read = ath10k_read_restart_failed, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + static int ath10k_fw_crash_dump_open(struct inode *inode, struct file *file) { struct ath10k *ar = inode->i_private; @@ -4483,6 +4502,9 @@ int ath10k_debug_register(struct ath10k *ar) debugfs_create_file("chip_id", 0400, ar->debug.debugfs_phy, ar, &fops_chip_id); + debugfs_create_file("restart_failed", 0400, ar->debug.debugfs_phy, ar, + &fops_restart_failed); + debugfs_create_file("htt_stats_mask", 0600, ar->debug.debugfs_phy, ar, &fops_htt_stats_mask);