From f28396d060cff5c6519f883cb28ae0116ce479f1 Mon Sep 17 00:00:00 2001 From: Vivek Date: Tue, 11 Feb 2020 12:09:02 +0530 Subject: [PATCH] qcacmn: Add API to print scheduler history The scheduler maintains a history of the recent messages in the scheduler that were queued, started or completed execution. This information can be reviewed while debugging issues if the scheduler is taking longer to process any message. The new API will print the scheduler history on request. Change-Id: I2ed7989296f6891cfd9779e7b96383253d680f51 CRs-Fixed: 2599281 --- scheduler/inc/scheduler_api.h | 11 +++++++- scheduler/src/scheduler_core.c | 51 +++++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/scheduler/inc/scheduler_api.h b/scheduler/inc/scheduler_api.h index fa13775753..b4e98a4d21 100644 --- a/scheduler/inc/scheduler_api.h +++ b/scheduler/inc/scheduler_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -92,6 +92,15 @@ struct scheduler_msg { #endif /* WLAN_SCHED_HISTORY_SIZE */ }; +/** + * sched_history_print() - print scheduler history + * + * This API prints the scheduler history. + * + * Return: None + */ +void sched_history_print(void); + typedef QDF_STATUS (*scheduler_msg_process_fn_t) (struct scheduler_msg *msg); typedef void (*hdd_suspend_callback)(void); diff --git a/scheduler/src/scheduler_core.c b/scheduler/src/scheduler_core.c index 055af4fff5..10d90548ab 100644 --- a/scheduler/src/scheduler_core.c +++ b/scheduler/src/scheduler_core.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -28,6 +28,15 @@ DEFINE_QDF_FLEX_MEM_POOL(sched_pool, sizeof(struct scheduler_msg), #ifdef WLAN_SCHED_HISTORY_SIZE +#define SCHEDULER_HISTORY_HEADER "|Callback "\ + "|Message Type" \ + "|Queue Duration(us)|Queue Depth" \ + "|Run Duration(us)|" + +#define SCHEDULER_HISTORY_LINE "--------------------------------------" \ + "--------------------------------------" \ + "--------------------------------------" + /** * struct sched_history_item - metrics for a scheduler message * @callback: the message's execution callback @@ -87,12 +96,52 @@ static void sched_history_stop(void) sched_history_index %= WLAN_SCHED_HISTORY_SIZE; } +void sched_history_print(void) +{ + struct sched_history_item *history, *item; + uint32_t history_idx; + uint32_t idx, index; + + history = qdf_mem_malloc(sizeof(*history) * WLAN_SCHED_HISTORY_SIZE); + + if (!history) { + sched_err("Mem alloc failed"); + return; + } + + qdf_mem_copy(history, &sched_history, + (sizeof(*history) * WLAN_SCHED_HISTORY_SIZE)); + history_idx = sched_history_index; + + sched_nofl_fatal(SCHEDULER_HISTORY_LINE); + sched_nofl_fatal(SCHEDULER_HISTORY_HEADER); + sched_nofl_fatal(SCHEDULER_HISTORY_LINE); + + for (idx = 0; idx < WLAN_SCHED_HISTORY_SIZE; idx++) { + index = (history_idx + idx) % WLAN_SCHED_HISTORY_SIZE; + item = history + index; + + if (!item->callback) + continue; + + sched_nofl_fatal("%40pF|%12d|%18d|%11d|%16d|", + item->callback, item->type_id, + item->queue_duration_us, + item->queue_depth, + item->run_duration_us); + } + + sched_nofl_fatal(SCHEDULER_HISTORY_LINE); + + qdf_mem_free(history); +} #else /* WLAN_SCHED_HISTORY_SIZE */ static inline void sched_history_queue(struct scheduler_mq_type *queue, struct scheduler_msg *msg) { } static inline void sched_history_start(struct scheduler_msg *msg) { } static inline void sched_history_stop(void) { } +void sched_history_print(void) { } #endif /* WLAN_SCHED_HISTORY_SIZE */