qcacmn: Dump WMI work queue stack for watchdog bite
In the event of an WMI work queue watchdog bite, dump the stack trace to aid in debugging. Change-Id: I7f3df5a56904748fb80afb1aef1aed90d20fbbc0 CRs-Fixed: 2145913
This commit is contained in:
@@ -81,4 +81,10 @@ int qdf_wake_up_process(qdf_thread_t *thread);
|
|||||||
*/
|
*/
|
||||||
void qdf_print_thread_trace(qdf_thread_t *thread);
|
void qdf_print_thread_trace(qdf_thread_t *thread);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qdf_get_current_task() - get current task struct
|
||||||
|
*
|
||||||
|
* Return: pointer to task struct
|
||||||
|
*/
|
||||||
|
qdf_thread_t *qdf_get_current_task(void);
|
||||||
#endif /* __QDF_THREADS_H */
|
#endif /* __QDF_THREADS_H */
|
||||||
|
@@ -45,6 +45,7 @@
|
|||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <linux/kthread.h>
|
#include <linux/kthread.h>
|
||||||
#include <linux/stacktrace.h>
|
#include <linux/stacktrace.h>
|
||||||
|
#include <qdf_defer.h>
|
||||||
|
|
||||||
/* Function declarations and documenation */
|
/* Function declarations and documenation */
|
||||||
|
|
||||||
@@ -154,3 +155,8 @@ void qdf_print_thread_trace(qdf_thread_t *thread) { }
|
|||||||
#endif /* KERNEL_VERSION(4, 14, 0) */
|
#endif /* KERNEL_VERSION(4, 14, 0) */
|
||||||
EXPORT_SYMBOL(qdf_print_thread_trace);
|
EXPORT_SYMBOL(qdf_print_thread_trace);
|
||||||
|
|
||||||
|
qdf_thread_t *qdf_get_current_task(void)
|
||||||
|
{
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(qdf_get_current_task);
|
||||||
|
@@ -48,6 +48,7 @@
|
|||||||
#ifdef DFS_COMPONENT_ENABLE
|
#ifdef DFS_COMPONENT_ENABLE
|
||||||
#include <wlan_dfs_public_struct.h>
|
#include <wlan_dfs_public_struct.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <qdf_threads.h>
|
||||||
|
|
||||||
#define WMI_UNIFIED_MAX_EVENT 0x100
|
#define WMI_UNIFIED_MAX_EVENT 0x100
|
||||||
#define WMI_MAX_CMDS 1024
|
#define WMI_MAX_CMDS 1024
|
||||||
@@ -175,6 +176,18 @@ struct fwdebug {
|
|||||||
};
|
};
|
||||||
#endif /* WLAN_OPEN_SOURCE */
|
#endif /* WLAN_OPEN_SOURCE */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct wmi_wq_dbg_info - WMI WQ debug info
|
||||||
|
* @ wd_msg_type_id - wmi event id
|
||||||
|
* @ wmi_wq - WMI workqueue struct
|
||||||
|
* @ task - WMI workqueue task struct
|
||||||
|
*/
|
||||||
|
struct wmi_wq_dbg_info {
|
||||||
|
uint16_t wd_msg_type_id;
|
||||||
|
qdf_workqueue_t *wmi_wq;
|
||||||
|
qdf_thread_t *task;
|
||||||
|
};
|
||||||
|
|
||||||
struct wmi_ops {
|
struct wmi_ops {
|
||||||
QDF_STATUS (*send_vdev_create_cmd)(wmi_unified_t wmi_handle,
|
QDF_STATUS (*send_vdev_create_cmd)(wmi_unified_t wmi_handle,
|
||||||
uint8_t macaddr[IEEE80211_ADDR_LEN],
|
uint8_t macaddr[IEEE80211_ADDR_LEN],
|
||||||
|
@@ -1883,7 +1883,11 @@ static inline void wmi_workqueue_watchdog_warn(uint16_t msg_type_id)
|
|||||||
#ifdef CONFIG_SLUB_DEBUG_ON
|
#ifdef CONFIG_SLUB_DEBUG_ON
|
||||||
static void wmi_workqueue_watchdog_bite(void *arg)
|
static void wmi_workqueue_watchdog_bite(void *arg)
|
||||||
{
|
{
|
||||||
wmi_workqueue_watchdog_warn(*(uint16_t *)arg);
|
struct wmi_wq_dbg_info *info = arg;
|
||||||
|
|
||||||
|
wmi_workqueue_watchdog_warn(info->wd_msg_type_id);
|
||||||
|
qdf_print_thread_trace(info->task);
|
||||||
|
|
||||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
|
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
|
||||||
"%s: Going down for WMI WQ Watchdog Bite!", __func__);
|
"%s: Going down for WMI WQ Watchdog Bite!", __func__);
|
||||||
QDF_BUG(0);
|
QDF_BUG(0);
|
||||||
@@ -1891,7 +1895,9 @@ static void wmi_workqueue_watchdog_bite(void *arg)
|
|||||||
#else
|
#else
|
||||||
static inline void wmi_workqueue_watchdog_bite(void *arg)
|
static inline void wmi_workqueue_watchdog_bite(void *arg)
|
||||||
{
|
{
|
||||||
wmi_workqueue_watchdog_warn(*(uint16_t *)arg);
|
struct wmi_wq_dbg_info *info = arg;
|
||||||
|
|
||||||
|
wmi_workqueue_watchdog_warn(info->wd_msg_type_id);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1908,18 +1914,20 @@ static void wmi_rx_event_work(void *arg)
|
|||||||
wmi_buf_t buf;
|
wmi_buf_t buf;
|
||||||
struct wmi_unified *wmi = arg;
|
struct wmi_unified *wmi = arg;
|
||||||
qdf_timer_t wd_timer;
|
qdf_timer_t wd_timer;
|
||||||
uint16_t wd_msg_type_id;
|
struct wmi_wq_dbg_info info;
|
||||||
|
|
||||||
/* initialize WMI workqueue watchdog timer */
|
/* initialize WMI workqueue watchdog timer */
|
||||||
qdf_timer_init(NULL, &wd_timer, &wmi_workqueue_watchdog_bite,
|
qdf_timer_init(NULL, &wd_timer, &wmi_workqueue_watchdog_bite,
|
||||||
&wd_msg_type_id, QDF_TIMER_TYPE_SW);
|
&info, QDF_TIMER_TYPE_SW);
|
||||||
qdf_spin_lock_bh(&wmi->eventq_lock);
|
qdf_spin_lock_bh(&wmi->eventq_lock);
|
||||||
buf = qdf_nbuf_queue_remove(&wmi->event_queue);
|
buf = qdf_nbuf_queue_remove(&wmi->event_queue);
|
||||||
qdf_spin_unlock_bh(&wmi->eventq_lock);
|
qdf_spin_unlock_bh(&wmi->eventq_lock);
|
||||||
while (buf) {
|
while (buf) {
|
||||||
qdf_timer_start(&wd_timer, WMI_WQ_WD_TIMEOUT);
|
qdf_timer_start(&wd_timer, WMI_WQ_WD_TIMEOUT);
|
||||||
wd_msg_type_id =
|
info.wd_msg_type_id =
|
||||||
WMI_GET_FIELD(qdf_nbuf_data(buf), WMI_CMD_HDR, COMMANDID);
|
WMI_GET_FIELD(qdf_nbuf_data(buf), WMI_CMD_HDR, COMMANDID);
|
||||||
|
info.wmi_wq = wmi->wmi_rx_work_queue;
|
||||||
|
info.task = qdf_get_current_task();
|
||||||
__wmi_control_rx(wmi, buf);
|
__wmi_control_rx(wmi, buf);
|
||||||
qdf_timer_stop(&wd_timer);
|
qdf_timer_stop(&wd_timer);
|
||||||
qdf_spin_lock_bh(&wmi->eventq_lock);
|
qdf_spin_lock_bh(&wmi->eventq_lock);
|
||||||
|
Reference in New Issue
Block a user