qcacmn: Track tasklet execution and total time (sched+exec)
Add support to track tasklet execution and total time in different buckets for debugging purposes Change-Id: Ide459c385b2a44c0f16d05b37879c8b462782d72 CRs-Fixed: 2589199
This commit is contained in:

committed by
nshrivas

parent
0181445b71
commit
b976076b3b
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
|
* Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
* any purpose with or without fee is hereby granted, provided that the
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -468,6 +468,8 @@ enum hif_ce_event_type {
|
|||||||
HIF_RX_DESC_PRE_NBUF_ALLOC,
|
HIF_RX_DESC_PRE_NBUF_ALLOC,
|
||||||
HIF_RX_DESC_PRE_NBUF_MAP,
|
HIF_RX_DESC_PRE_NBUF_MAP,
|
||||||
HIF_RX_DESC_POST_NBUF_MAP,
|
HIF_RX_DESC_POST_NBUF_MAP,
|
||||||
|
|
||||||
|
HIF_EVENT_TYPE_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
void ce_init_ce_desc_event_log(struct hif_softc *scn, int ce_id, int size);
|
void ce_init_ce_desc_event_log(struct hif_softc *scn, int ce_id, int size);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015-2019 The Linux Foundation. All rights reserved.
|
* Copyright (c) 2015-2020 The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
* any purpose with or without fee is hereby granted, provided that the
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -49,6 +49,7 @@
|
|||||||
#define CE_USEFUL_SIZE 0x00000058
|
#define CE_USEFUL_SIZE 0x00000058
|
||||||
#define CE_ALL_BITMAP 0xFFFF
|
#define CE_ALL_BITMAP 0xFFFF
|
||||||
|
|
||||||
|
#define HIF_REQUESTED_EVENTS 20
|
||||||
/**
|
/**
|
||||||
* enum ce_id_type
|
* enum ce_id_type
|
||||||
*
|
*
|
||||||
@@ -70,6 +71,30 @@ enum ce_id_type {
|
|||||||
CE_ID_MAX
|
CE_ID_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum ce_buckets
|
||||||
|
*
|
||||||
|
* @ce_buckets: CE tasklet time buckets
|
||||||
|
* @CE_BUCKET_500_US: tasklet bucket to store 0-0.5ms
|
||||||
|
* @CE_BUCKET_1_MS: tasklet bucket to store 0.5-1ms
|
||||||
|
* @CE_BUCKET_2_MS: tasklet bucket to store 1-2ms
|
||||||
|
* @CE_BUCKET_5_MS: tasklet bucket to store 2-5ms
|
||||||
|
* @CE_BUCKET_10_MS: tasklet bucket to store 5-10ms
|
||||||
|
* @CE_BUCKET_BEYOND: tasklet bucket to store > 10ms
|
||||||
|
* @CE_BUCKET_MAX: enum max value
|
||||||
|
*/
|
||||||
|
#ifdef CE_TASKLET_DEBUG_ENABLE
|
||||||
|
enum ce_buckets {
|
||||||
|
CE_BUCKET_500_US,
|
||||||
|
CE_BUCKET_1_MS,
|
||||||
|
CE_BUCKET_2_MS,
|
||||||
|
CE_BUCKET_5_MS,
|
||||||
|
CE_BUCKET_10_MS,
|
||||||
|
CE_BUCKET_BEYOND,
|
||||||
|
CE_BUCKET_MAX,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
enum ce_target_type {
|
enum ce_target_type {
|
||||||
CE_SVC_LEGACY,
|
CE_SVC_LEGACY,
|
||||||
CE_SVC_SRNG,
|
CE_SVC_SRNG,
|
||||||
@@ -134,8 +159,33 @@ static inline bool hif_dummy_grp_done(struct hif_exec_context *grp_entry, int
|
|||||||
extern struct hif_execution_ops tasklet_sched_ops;
|
extern struct hif_execution_ops tasklet_sched_ops;
|
||||||
extern struct hif_execution_ops napi_sched_ops;
|
extern struct hif_execution_ops napi_sched_ops;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ce_stats
|
||||||
|
*
|
||||||
|
* @ce_per_cpu: Stats of the CEs running per CPU
|
||||||
|
* @record_index: Current index to store in time record
|
||||||
|
* @tasklet_sched_entry_ts: Timestamp when tasklet is scheduled
|
||||||
|
* @tasklet_exec_entry_ts: Timestamp when tasklet is started execuiton
|
||||||
|
* @tasklet_exec_time_record: Last N number of tasklets execution time
|
||||||
|
* @tasklet_sched_time_record: Last N number of tasklets scheduled time
|
||||||
|
* @ce_tasklet_exec_bucket: Tasklet execution time buckets
|
||||||
|
* @ce_tasklet_sched_bucket: Tasklet time in queue buckets
|
||||||
|
* @ce_tasklet_exec_last_update: Latest timestamp when bucket is updated
|
||||||
|
* @ce_tasklet_sched_last_update: Latest timestamp when bucket is updated
|
||||||
|
*/
|
||||||
struct ce_stats {
|
struct ce_stats {
|
||||||
uint32_t ce_per_cpu[CE_COUNT_MAX][QDF_MAX_AVAILABLE_CPU];
|
uint32_t ce_per_cpu[CE_COUNT_MAX][QDF_MAX_AVAILABLE_CPU];
|
||||||
|
#ifdef CE_TASKLET_DEBUG_ENABLE
|
||||||
|
uint32_t record_index[CE_COUNT_MAX];
|
||||||
|
uint64_t tasklet_sched_entry_ts[CE_COUNT_MAX];
|
||||||
|
uint64_t tasklet_exec_entry_ts[CE_COUNT_MAX];
|
||||||
|
uint64_t tasklet_exec_time_record[CE_COUNT_MAX][HIF_REQUESTED_EVENTS];
|
||||||
|
uint64_t tasklet_sched_time_record[CE_COUNT_MAX][HIF_REQUESTED_EVENTS];
|
||||||
|
uint64_t ce_tasklet_exec_bucket[CE_COUNT_MAX][CE_BUCKET_MAX];
|
||||||
|
uint64_t ce_tasklet_sched_bucket[CE_COUNT_MAX][CE_BUCKET_MAX];
|
||||||
|
uint64_t ce_tasklet_exec_last_update[CE_COUNT_MAX][CE_BUCKET_MAX];
|
||||||
|
uint64_t ce_tasklet_sched_last_update[CE_COUNT_MAX][CE_BUCKET_MAX];
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HIF_CE_state {
|
struct HIF_CE_state {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015-2019 The Linux Foundation. All rights reserved.
|
* Copyright (c) 2015-2020 The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
* any purpose with or without fee is hereby granted, provided that the
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -35,7 +35,6 @@
|
|||||||
#include "hif_debug.h"
|
#include "hif_debug.h"
|
||||||
#include "hif_napi.h"
|
#include "hif_napi.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct tasklet_work
|
* struct tasklet_work
|
||||||
*
|
*
|
||||||
@@ -139,6 +138,199 @@ static inline void ce_schedule_tasklet(struct ce_tasklet_entry *tasklet_entry)
|
|||||||
tasklet_schedule(&tasklet_entry->intr_tq);
|
tasklet_schedule(&tasklet_entry->intr_tq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CE_TASKLET_DEBUG_ENABLE
|
||||||
|
/**
|
||||||
|
* hif_record_tasklet_exec_entry_ts() - Record ce tasklet execution
|
||||||
|
* entry time
|
||||||
|
* @scn: hif_softc
|
||||||
|
* @ce_id: ce_id
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
hif_record_tasklet_exec_entry_ts(struct hif_softc *scn, uint8_t ce_id)
|
||||||
|
{
|
||||||
|
struct HIF_CE_state *hif_ce_state = HIF_GET_CE_STATE(scn);
|
||||||
|
|
||||||
|
hif_ce_state->stats.tasklet_exec_entry_ts[ce_id] =
|
||||||
|
qdf_get_log_timestamp_usecs();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hif_record_tasklet_sched_entry_ts() - Record ce tasklet scheduled
|
||||||
|
* entry time
|
||||||
|
* @scn: hif_softc
|
||||||
|
* @ce_id: ce_id
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
hif_record_tasklet_sched_entry_ts(struct hif_softc *scn, uint8_t ce_id)
|
||||||
|
{
|
||||||
|
struct HIF_CE_state *hif_ce_state = HIF_GET_CE_STATE(scn);
|
||||||
|
|
||||||
|
hif_ce_state->stats.tasklet_sched_entry_ts[ce_id] =
|
||||||
|
qdf_get_log_timestamp_usecs();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hif_ce_latency_stats() - Display ce latency information
|
||||||
|
* @hif_ctx: hif_softc struct
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
hif_ce_latency_stats(struct hif_softc *hif_ctx)
|
||||||
|
{
|
||||||
|
uint8_t i, j;
|
||||||
|
uint32_t index, start_index;
|
||||||
|
static const char * const buck_str[] = {"0 - 0.5", "0.5 - 1", "1 - 2",
|
||||||
|
"2 - 5", "5 - 10", " > 10"};
|
||||||
|
struct HIF_CE_state *hif_ce_state = HIF_GET_CE_STATE(hif_ctx);
|
||||||
|
struct ce_stats *stats = &hif_ce_state->stats;
|
||||||
|
|
||||||
|
for (i = 0; i < CE_COUNT_MAX; i++) {
|
||||||
|
qdf_nofl_info("\n\t\tCE Ring %d Tasklet Execution Bucket", i);
|
||||||
|
for (j = 0; j < CE_BUCKET_MAX; j++) {
|
||||||
|
qdf_nofl_info("\t Bucket %sms :%llu\t last update:%llu",
|
||||||
|
buck_str[j],
|
||||||
|
stats->ce_tasklet_exec_bucket[i][j],
|
||||||
|
stats->ce_tasklet_exec_last_update[i][j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
qdf_nofl_info("\n\t\tCE Ring %d Tasklet Scheduled Bucket", i);
|
||||||
|
for (j = 0; j < CE_BUCKET_MAX; j++) {
|
||||||
|
qdf_nofl_info("\t Bucket %sms :%llu\t last update :%lld",
|
||||||
|
buck_str[j],
|
||||||
|
stats->ce_tasklet_sched_bucket[i][j],
|
||||||
|
stats->
|
||||||
|
ce_tasklet_sched_last_update[i][j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
qdf_nofl_info("\n\t\t CE RING %d Last %d time records",
|
||||||
|
i, HIF_REQUESTED_EVENTS);
|
||||||
|
index = stats->record_index[i];
|
||||||
|
start_index = stats->record_index[i];
|
||||||
|
|
||||||
|
for (j = 0; j < HIF_REQUESTED_EVENTS; j++) {
|
||||||
|
qdf_nofl_info("\t Execuiton time: %luus Total Scheduled time: %luus",
|
||||||
|
stats->tasklet_exec_time_record[i][index],
|
||||||
|
stats->
|
||||||
|
tasklet_sched_time_record[i][index]);
|
||||||
|
index = (index - 1) % HIF_REQUESTED_EVENTS;
|
||||||
|
if (index == start_index)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ce_tasklet_update_bucket() - update ce execution and scehduled time latency
|
||||||
|
* in corresponding time buckets
|
||||||
|
* @stats: struct ce_stats
|
||||||
|
* @ce_id: ce_id_type
|
||||||
|
* @entry_us: timestamp when tasklet is started to execute
|
||||||
|
* @exit_us: timestamp when tasklet is completed execution
|
||||||
|
*
|
||||||
|
* Return: N/A
|
||||||
|
*/
|
||||||
|
static void ce_tasklet_update_bucket(struct HIF_CE_state *hif_ce_state,
|
||||||
|
uint8_t ce_id)
|
||||||
|
{
|
||||||
|
uint32_t index;
|
||||||
|
uint64_t exec_time, exec_ms;
|
||||||
|
uint64_t sched_time, sched_ms;
|
||||||
|
uint64_t curr_time = qdf_get_log_timestamp_usecs();
|
||||||
|
struct ce_stats *stats = &hif_ce_state->stats;
|
||||||
|
|
||||||
|
exec_time = curr_time - (stats->tasklet_exec_entry_ts[ce_id]);
|
||||||
|
sched_time = (stats->tasklet_exec_entry_ts[ce_id]) -
|
||||||
|
(stats->tasklet_sched_entry_ts[ce_id]);
|
||||||
|
|
||||||
|
index = stats->record_index[ce_id];
|
||||||
|
index = (index + 1) % HIF_REQUESTED_EVENTS;
|
||||||
|
|
||||||
|
stats->tasklet_exec_time_record[ce_id][index] = exec_time;
|
||||||
|
stats->tasklet_sched_time_record[ce_id][index] = sched_time;
|
||||||
|
stats->record_index[ce_id] = index;
|
||||||
|
|
||||||
|
exec_ms = (exec_time) / (1000);
|
||||||
|
sched_ms = (sched_time) / (1000);
|
||||||
|
|
||||||
|
if (exec_ms > 10) {
|
||||||
|
stats->ce_tasklet_exec_bucket[ce_id][CE_BUCKET_BEYOND]++;
|
||||||
|
stats->ce_tasklet_exec_last_update[ce_id][CE_BUCKET_BEYOND]
|
||||||
|
= curr_time;
|
||||||
|
} else if (exec_ms > 5) {
|
||||||
|
stats->ce_tasklet_exec_bucket[ce_id][CE_BUCKET_10_MS]++;
|
||||||
|
stats->ce_tasklet_exec_last_update[ce_id][CE_BUCKET_10_MS]
|
||||||
|
= curr_time;
|
||||||
|
} else if (exec_ms > 2) {
|
||||||
|
stats->ce_tasklet_exec_bucket[ce_id][CE_BUCKET_5_MS]++;
|
||||||
|
stats->ce_tasklet_exec_last_update[ce_id][CE_BUCKET_5_MS]
|
||||||
|
= curr_time;
|
||||||
|
} else if (exec_ms > 1) {
|
||||||
|
stats->ce_tasklet_exec_bucket[ce_id][CE_BUCKET_2_MS]++;
|
||||||
|
stats->ce_tasklet_exec_last_update[ce_id][CE_BUCKET_2_MS]
|
||||||
|
= curr_time;
|
||||||
|
} else if (exec_time > 500) {
|
||||||
|
stats->ce_tasklet_exec_bucket[ce_id][CE_BUCKET_1_MS]++;
|
||||||
|
stats->ce_tasklet_exec_last_update[ce_id][CE_BUCKET_1_MS]
|
||||||
|
= curr_time;
|
||||||
|
} else {
|
||||||
|
stats->ce_tasklet_exec_bucket[ce_id][CE_BUCKET_500_US]++;
|
||||||
|
stats->ce_tasklet_exec_last_update[ce_id][CE_BUCKET_500_US]
|
||||||
|
= curr_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sched_ms > 10) {
|
||||||
|
stats->ce_tasklet_sched_bucket[ce_id][CE_BUCKET_BEYOND]++;
|
||||||
|
stats->ce_tasklet_sched_last_update[ce_id][CE_BUCKET_BEYOND]
|
||||||
|
= curr_time;
|
||||||
|
} else if (sched_ms > 5) {
|
||||||
|
stats->ce_tasklet_sched_bucket[ce_id][CE_BUCKET_10_MS]++;
|
||||||
|
stats->ce_tasklet_sched_last_update[ce_id][CE_BUCKET_10_MS]
|
||||||
|
= curr_time;
|
||||||
|
} else if (sched_ms > 2) {
|
||||||
|
stats->ce_tasklet_sched_bucket[ce_id][CE_BUCKET_5_MS]++;
|
||||||
|
stats->ce_tasklet_sched_last_update[ce_id][CE_BUCKET_5_MS]
|
||||||
|
= curr_time;
|
||||||
|
} else if (sched_ms > 1) {
|
||||||
|
stats->ce_tasklet_sched_bucket[ce_id][CE_BUCKET_2_MS]++;
|
||||||
|
stats->ce_tasklet_sched_last_update[ce_id][CE_BUCKET_2_MS]
|
||||||
|
= curr_time;
|
||||||
|
} else if (sched_time > 500) {
|
||||||
|
stats->ce_tasklet_sched_bucket[ce_id][CE_BUCKET_1_MS]++;
|
||||||
|
stats->ce_tasklet_sched_last_update[ce_id][CE_BUCKET_1_MS]
|
||||||
|
= curr_time;
|
||||||
|
} else {
|
||||||
|
stats->ce_tasklet_sched_bucket[ce_id][CE_BUCKET_500_US]++;
|
||||||
|
stats->ce_tasklet_sched_last_update[ce_id][CE_BUCKET_500_US]
|
||||||
|
= curr_time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline void
|
||||||
|
hif_record_tasklet_exec_entry_ts(struct hif_softc *scn, uint8_t ce_id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ce_tasklet_update_bucket(struct HIF_CE_state *hif_ce_state,
|
||||||
|
uint8_t ce_id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
hif_record_tasklet_sched_entry_ts(struct hif_softc *scn, uint8_t ce_id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hif_ce_latency_stats(struct hif_softc *hif_ctx)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif /*CE_TASKLET_DEBUG_ENABLE*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ce_tasklet() - ce_tasklet
|
* ce_tasklet() - ce_tasklet
|
||||||
* @data: data
|
* @data: data
|
||||||
@@ -153,8 +345,9 @@ static void ce_tasklet(unsigned long data)
|
|||||||
struct hif_softc *scn = HIF_GET_SOFTC(hif_ce_state);
|
struct hif_softc *scn = HIF_GET_SOFTC(hif_ce_state);
|
||||||
struct CE_state *CE_state = scn->ce_id_to_state[tasklet_entry->ce_id];
|
struct CE_state *CE_state = scn->ce_id_to_state[tasklet_entry->ce_id];
|
||||||
|
|
||||||
|
hif_record_tasklet_exec_entry_ts(scn, tasklet_entry->ce_id);
|
||||||
hif_record_ce_desc_event(scn, tasklet_entry->ce_id,
|
hif_record_ce_desc_event(scn, tasklet_entry->ce_id,
|
||||||
HIF_CE_TASKLET_ENTRY, NULL, NULL, -1, 0);
|
HIF_CE_TASKLET_ENTRY, NULL, NULL, -1, 0);
|
||||||
|
|
||||||
if (qdf_atomic_read(&scn->link_suspended)) {
|
if (qdf_atomic_read(&scn->link_suspended)) {
|
||||||
HIF_ERROR("%s: ce %d tasklet fired after link suspend.",
|
HIF_ERROR("%s: ce %d tasklet fired after link suspend.",
|
||||||
@@ -182,7 +375,7 @@ static void ce_tasklet(unsigned long data)
|
|||||||
|
|
||||||
hif_record_ce_desc_event(scn, tasklet_entry->ce_id, HIF_CE_TASKLET_EXIT,
|
hif_record_ce_desc_event(scn, tasklet_entry->ce_id, HIF_CE_TASKLET_EXIT,
|
||||||
NULL, NULL, -1, 0);
|
NULL, NULL, -1, 0);
|
||||||
|
ce_tasklet_update_bucket(hif_ce_state, tasklet_entry->ce_id);
|
||||||
qdf_atomic_dec(&scn->active_tasklet_cnt);
|
qdf_atomic_dec(&scn->active_tasklet_cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,12 +532,13 @@ hif_ce_increment_interrupt_count(struct HIF_CE_state *hif_ce_state, int ce_id)
|
|||||||
*
|
*
|
||||||
* Return: none
|
* Return: none
|
||||||
*/
|
*/
|
||||||
void hif_display_ce_stats(struct HIF_CE_state *hif_ce_state)
|
void hif_display_ce_stats(struct hif_softc *hif_ctx)
|
||||||
{
|
{
|
||||||
#define STR_SIZE 128
|
#define STR_SIZE 128
|
||||||
uint8_t i, j, pos;
|
uint8_t i, j, pos;
|
||||||
char str_buffer[STR_SIZE];
|
char str_buffer[STR_SIZE];
|
||||||
int size, ret;
|
int size, ret;
|
||||||
|
struct HIF_CE_state *hif_ce_state = HIF_GET_CE_STATE(hif_ctx);
|
||||||
|
|
||||||
qdf_debug("CE interrupt statistics:");
|
qdf_debug("CE interrupt statistics:");
|
||||||
for (i = 0; i < CE_COUNT_MAX; i++) {
|
for (i = 0; i < CE_COUNT_MAX; i++) {
|
||||||
@@ -352,7 +546,7 @@ void hif_display_ce_stats(struct HIF_CE_state *hif_ce_state)
|
|||||||
pos = 0;
|
pos = 0;
|
||||||
for (j = 0; j < QDF_MAX_AVAILABLE_CPU; j++) {
|
for (j = 0; j < QDF_MAX_AVAILABLE_CPU; j++) {
|
||||||
ret = snprintf(str_buffer + pos, size, "[%d]:%d ",
|
ret = snprintf(str_buffer + pos, size, "[%d]:%d ",
|
||||||
j, hif_ce_state->stats.ce_per_cpu[i][j]);
|
j, hif_ce_state->stats.ce_per_cpu[i][j]);
|
||||||
if (ret <= 0 || ret >= size)
|
if (ret <= 0 || ret >= size)
|
||||||
break;
|
break;
|
||||||
size -= ret;
|
size -= ret;
|
||||||
@@ -360,6 +554,8 @@ void hif_display_ce_stats(struct HIF_CE_state *hif_ce_state)
|
|||||||
}
|
}
|
||||||
qdf_debug("CE id[%2d] - %s", i, str_buffer);
|
qdf_debug("CE id[%2d] - %s", i, str_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hif_ce_latency_stats(hif_ctx);
|
||||||
#undef STR_SIZE
|
#undef STR_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,6 +589,7 @@ static inline bool hif_tasklet_schedule(struct hif_opaque_softc *hif_ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
tasklet_schedule(&tasklet_entry->intr_tq);
|
tasklet_schedule(&tasklet_entry->intr_tq);
|
||||||
|
hif_record_tasklet_sched_entry_ts(scn, tasklet_entry->ce_id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015-2016,2018 The Linux Foundation. All rights reserved.
|
* Copyright (c) 2015-2016,2018,2020 The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
* any purpose with or without fee is hereby granted, provided that the
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -28,6 +28,6 @@ QDF_STATUS ce_register_irq(struct HIF_CE_state *hif_ce_state, uint32_t mask);
|
|||||||
QDF_STATUS ce_unregister_irq(struct HIF_CE_state *hif_ce_state, uint32_t mask);
|
QDF_STATUS ce_unregister_irq(struct HIF_CE_state *hif_ce_state, uint32_t mask);
|
||||||
irqreturn_t ce_dispatch_interrupt(int irq,
|
irqreturn_t ce_dispatch_interrupt(int irq,
|
||||||
struct ce_tasklet_entry *tasklet_entry);
|
struct ce_tasklet_entry *tasklet_entry);
|
||||||
void hif_display_ce_stats(struct HIF_CE_state *hif_ce_state);
|
void hif_display_ce_stats(struct hif_softc *hif_ctx);
|
||||||
void hif_clear_ce_stats(struct HIF_CE_state *hif_ce_state);
|
void hif_clear_ce_stats(struct HIF_CE_state *hif_ce_state);
|
||||||
#endif /* __CE_TASKLET_H__ */
|
#endif /* __CE_TASKLET_H__ */
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
|
* Copyright (c) 2013-2018,2020 The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
* any purpose with or without fee is hereby granted, provided that the
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -50,4 +50,6 @@ int hif_ahb_configure_irq(struct hif_pci_softc *sc);
|
|||||||
int hif_ahb_configure_grp_irq(struct hif_softc *scn,
|
int hif_ahb_configure_grp_irq(struct hif_softc *scn,
|
||||||
struct hif_exec_context *hif_ext_grp);
|
struct hif_exec_context *hif_ext_grp);
|
||||||
bool hif_ahb_needs_bmi(struct hif_softc *scn);
|
bool hif_ahb_needs_bmi(struct hif_softc *scn);
|
||||||
|
void hif_ahb_display_stats(struct hif_softc *scn);
|
||||||
|
void hif_ahb_clear_stats(struct hif_softc *scn);
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
|
* Copyright (c) 2016-2018,2020 The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
* any purpose with or without fee is hereby granted, provided that the
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -69,7 +69,8 @@ QDF_STATUS hif_initialize_ahb_ops(struct hif_bus_ops *bus_ops)
|
|||||||
bus_ops->hif_grp_irq_configure = &hif_ahb_configure_grp_irq;
|
bus_ops->hif_grp_irq_configure = &hif_ahb_configure_grp_irq;
|
||||||
bus_ops->hif_addr_in_boundary = &hif_dummy_addr_in_boundary;
|
bus_ops->hif_addr_in_boundary = &hif_dummy_addr_in_boundary;
|
||||||
bus_ops->hif_needs_bmi = &hif_ahb_needs_bmi;
|
bus_ops->hif_needs_bmi = &hif_ahb_needs_bmi;
|
||||||
|
bus_ops->hif_display_stats = &hif_ahb_display_stats;
|
||||||
|
bus_ops->hif_clear_stats = &hif_ahb_clear_stats;
|
||||||
return QDF_STATUS_SUCCESS;
|
return QDF_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1395,7 +1395,7 @@ void hif_pci_display_stats(struct hif_softc *hif_ctx)
|
|||||||
HIF_ERROR("%s, hif_ctx null", __func__);
|
HIF_ERROR("%s, hif_ctx null", __func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
hif_display_ce_stats(&pci_ctx->ce_sc);
|
hif_display_ce_stats(hif_ctx);
|
||||||
|
|
||||||
hif_print_pci_stats(pci_ctx);
|
hif_print_pci_stats(pci_ctx);
|
||||||
}
|
}
|
||||||
|
@@ -835,3 +835,23 @@ bool hif_ahb_needs_bmi(struct hif_softc *scn)
|
|||||||
{
|
{
|
||||||
return !ce_srng_based(scn);
|
return !ce_srng_based(scn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void hif_ahb_display_stats(struct hif_softc *scn)
|
||||||
|
{
|
||||||
|
if (!scn) {
|
||||||
|
HIF_ERROR("%s, hif_scn null", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hif_display_ce_stats(scn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hif_ahb_clear_stats(struct hif_softc *scn)
|
||||||
|
{
|
||||||
|
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
|
||||||
|
|
||||||
|
if (!hif_state) {
|
||||||
|
HIF_ERROR("%s, hif_state null", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hif_clear_ce_stats(hif_state);
|
||||||
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015-2019 The Linux Foundation. All rights reserved.
|
* Copyright (c) 2015-2020 The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
* any purpose with or without fee is hereby granted, provided that the
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -78,13 +78,11 @@ int hif_snoc_dump_registers(struct hif_softc *hif_ctx)
|
|||||||
|
|
||||||
void hif_snoc_display_stats(struct hif_softc *hif_ctx)
|
void hif_snoc_display_stats(struct hif_softc *hif_ctx)
|
||||||
{
|
{
|
||||||
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_ctx);
|
if (!hif_ctx) {
|
||||||
|
|
||||||
if (!hif_state) {
|
|
||||||
HIF_ERROR("%s, hif_ctx null", __func__);
|
HIF_ERROR("%s, hif_ctx null", __func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
hif_display_ce_stats(hif_state);
|
hif_display_ce_stats(hif_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hif_snoc_clear_stats(struct hif_softc *hif_ctx)
|
void hif_snoc_clear_stats(struct hif_softc *hif_ctx)
|
||||||
|
12
htc/htc.c
12
htc/htc.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
|
* Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
* any purpose with or without fee is hereby granted, provided that the
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -134,6 +134,16 @@ void htc_dump(HTC_HANDLE HTCHandle, uint8_t CmdId, bool start)
|
|||||||
hif_dump(target->hif_dev, CmdId, start);
|
hif_dump(target->hif_dev, CmdId, start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void htc_ce_tasklet_debug_dump(HTC_HANDLE htc_handle)
|
||||||
|
{
|
||||||
|
HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
|
||||||
|
|
||||||
|
if (!target->hif_dev)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hif_display_stats(target->hif_dev);
|
||||||
|
}
|
||||||
|
|
||||||
/* cleanup the HTC instance */
|
/* cleanup the HTC instance */
|
||||||
static void htc_cleanup(HTC_TARGET *target)
|
static void htc_cleanup(HTC_TARGET *target)
|
||||||
{
|
{
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2014, 2016-2019 The Linux Foundation. All rights reserved.
|
* Copyright (c) 2013-2014, 2016-2020 The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
* any purpose with or without fee is hereby granted, provided that the
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -481,6 +481,15 @@ QDF_STATUS htc_connect_service(HTC_HANDLE HTCHandle,
|
|||||||
*/
|
*/
|
||||||
void htc_dump(HTC_HANDLE HTCHandle, uint8_t CmdId, bool start);
|
void htc_dump(HTC_HANDLE HTCHandle, uint8_t CmdId, bool start);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* htc_ce_taklet_debug_dump - Dump ce tasklet rings debug data
|
||||||
|
* @HTCHandle - HTC handle
|
||||||
|
*
|
||||||
|
* Debug logs will be printed.
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
void htc_ce_tasklet_debug_dump(HTC_HANDLE htc_handle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* htc_send_pkt - Send an HTC packet
|
* htc_send_pkt - Send an HTC packet
|
||||||
* @HTCHandle - HTC handle
|
* @HTCHandle - HTC handle
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015-2019 The Linux Foundation. All rights reserved.
|
* Copyright (c) 2015-2020 The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
* any purpose with or without fee is hereby granted, provided that the
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -1808,6 +1808,7 @@ QDF_STATUS wmi_unified_cmd_send_fl(wmi_unified_t wmi_handle, wmi_buf_t buf,
|
|||||||
wmi_nofl_err("%s:%d, MAX %d WMI Pending cmds reached",
|
wmi_nofl_err("%s:%d, MAX %d WMI Pending cmds reached",
|
||||||
func, line, wmi_handle->wmi_max_cmds);
|
func, line, wmi_handle->wmi_max_cmds);
|
||||||
wmi_unified_debug_dump(wmi_handle);
|
wmi_unified_debug_dump(wmi_handle);
|
||||||
|
htc_ce_tasklet_debug_dump(wmi_handle->htc_handle);
|
||||||
qdf_trigger_self_recovery(QDF_WMI_EXCEED_MAX_PENDING_CMDS);
|
qdf_trigger_self_recovery(QDF_WMI_EXCEED_MAX_PENDING_CMDS);
|
||||||
return QDF_STATUS_E_BUSY;
|
return QDF_STATUS_E_BUSY;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user