qcacmn: Avoid logging few hif events in case of IRQ storm
In IRQ storm scenario, the events are logged to hif event desc history even though the SRNG is empty resulting in overwriting of older entries useful for debugging. Fix is to avoid recording hif events if the SRNG is empty in IRQ storm scenario. Change-Id: Id4161198c60f5fae31123c936f0f4acc1082a78b CRs-Fixed: 2753675
This commit is contained in:

committed by
snandini

parent
8e4491a9ac
commit
32a9cc93a8
@@ -328,6 +328,7 @@ enum hif_event_type {
|
|||||||
HIF_EVENT_BH_SCHED,
|
HIF_EVENT_BH_SCHED,
|
||||||
HIF_EVENT_SRNG_ACCESS_START,
|
HIF_EVENT_SRNG_ACCESS_START,
|
||||||
HIF_EVENT_SRNG_ACCESS_END,
|
HIF_EVENT_SRNG_ACCESS_END,
|
||||||
|
/* Do check hif_hist_skip_event_record when adding new events */
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef WLAN_FEATURE_DP_EVENT_HISTORY
|
#ifdef WLAN_FEATURE_DP_EVENT_HISTORY
|
||||||
@@ -358,6 +359,16 @@ struct hif_event_record {
|
|||||||
enum hif_event_type type;
|
enum hif_event_type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct hif_event_misc - history related misc info
|
||||||
|
* @last_irq_index: last irq event index in history
|
||||||
|
* @last_irq_ts: last irq timestamp
|
||||||
|
*/
|
||||||
|
struct hif_event_misc {
|
||||||
|
int32_t last_irq_index;
|
||||||
|
uint64_t last_irq_ts;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct hif_event_history - history for one interrupt group
|
* struct hif_event_history - history for one interrupt group
|
||||||
* @index: index to store new event
|
* @index: index to store new event
|
||||||
@@ -368,6 +379,7 @@ struct hif_event_record {
|
|||||||
*/
|
*/
|
||||||
struct hif_event_history {
|
struct hif_event_history {
|
||||||
qdf_atomic_t index;
|
qdf_atomic_t index;
|
||||||
|
struct hif_event_misc misc;
|
||||||
struct hif_event_record event[HIF_EVENT_HIST_MAX];
|
struct hif_event_record event[HIF_EVENT_HIST_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -573,6 +573,7 @@ struct hif_ce_desc_event {
|
|||||||
int index;
|
int index;
|
||||||
enum hif_ce_event_type type;
|
enum hif_ce_event_type type;
|
||||||
uint64_t time;
|
uint64_t time;
|
||||||
|
int cpu_id;
|
||||||
#ifdef HELIUMPLUS
|
#ifdef HELIUMPLUS
|
||||||
union ce_desc descriptor;
|
union ce_desc descriptor;
|
||||||
#else
|
#else
|
||||||
|
@@ -210,6 +210,7 @@ void hif_record_ce_desc_event(struct hif_softc *scn, int ce_id,
|
|||||||
|
|
||||||
event->type = type;
|
event->type = type;
|
||||||
event->time = qdf_get_log_timestamp();
|
event->time = qdf_get_log_timestamp();
|
||||||
|
event->cpu_id = qdf_get_cpu();
|
||||||
|
|
||||||
if (descriptor)
|
if (descriptor)
|
||||||
qdf_mem_copy(&event->descriptor, descriptor,
|
qdf_mem_copy(&event->descriptor, descriptor,
|
||||||
|
@@ -112,6 +112,7 @@ void hif_record_ce_srng_desc_event(struct hif_softc *scn, int ce_id,
|
|||||||
|
|
||||||
event->type = type;
|
event->type = type;
|
||||||
event->time = qdf_get_log_timestamp();
|
event->time = qdf_get_log_timestamp();
|
||||||
|
event->cpu_id = qdf_get_cpu();
|
||||||
|
|
||||||
if (descriptor)
|
if (descriptor)
|
||||||
qdf_mem_copy(&event->descriptor, descriptor,
|
qdf_mem_copy(&event->descriptor, descriptor,
|
||||||
|
@@ -43,6 +43,89 @@ int hif_get_next_record_index(qdf_atomic_t *table_index,
|
|||||||
return record_index & (array_size - 1);
|
return record_index & (array_size - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hif_hist_is_prev_record() - Check if index is the immediate
|
||||||
|
* previous record wrt curr_index
|
||||||
|
* @curr_index: curr index in the event history
|
||||||
|
* @index: index to be checked
|
||||||
|
* @hist_size: history size
|
||||||
|
*
|
||||||
|
* Return: true if index is immediately behind curr_index else false
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
bool hif_hist_is_prev_record(int32_t curr_index, int32_t index,
|
||||||
|
uint32_t hist_size)
|
||||||
|
{
|
||||||
|
return (((index + 1) & (hist_size - 1)) == curr_index) ?
|
||||||
|
true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hif_hist_skip_event_record() - Check if current event needs to be
|
||||||
|
* recorded or not
|
||||||
|
* @hist_ev: HIF event history
|
||||||
|
* @event: DP event entry
|
||||||
|
*
|
||||||
|
* Return: true if current event needs to be skipped else false
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
hif_hist_skip_event_record(struct hif_event_history *hist_ev,
|
||||||
|
struct hif_event_record *event)
|
||||||
|
{
|
||||||
|
struct hif_event_record *rec;
|
||||||
|
struct hif_event_record *last_irq_rec;
|
||||||
|
int32_t index;
|
||||||
|
|
||||||
|
index = qdf_atomic_read(&hist_ev->index);
|
||||||
|
if (index < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
index &= (HIF_EVENT_HIST_MAX - 1);
|
||||||
|
rec = &hist_ev->event[index];
|
||||||
|
|
||||||
|
switch (event->type) {
|
||||||
|
case HIF_EVENT_IRQ_TRIGGER:
|
||||||
|
/*
|
||||||
|
* The prev record check is to prevent skipping the IRQ event
|
||||||
|
* record in case where BH got re-scheduled due to force_break
|
||||||
|
* but there are no entries to be reaped in the rings.
|
||||||
|
*/
|
||||||
|
if (rec->type == HIF_EVENT_BH_SCHED &&
|
||||||
|
hif_hist_is_prev_record(index,
|
||||||
|
hist_ev->misc.last_irq_index,
|
||||||
|
HIF_EVENT_HIST_MAX)) {
|
||||||
|
last_irq_rec =
|
||||||
|
&hist_ev->event[hist_ev->misc.last_irq_index];
|
||||||
|
last_irq_rec->timestamp = qdf_get_log_timestamp();
|
||||||
|
last_irq_rec->cpu_id = qdf_get_cpu();
|
||||||
|
last_irq_rec->hp++;
|
||||||
|
last_irq_rec->tp = last_irq_rec->timestamp -
|
||||||
|
hist_ev->misc.last_irq_ts;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HIF_EVENT_BH_SCHED:
|
||||||
|
if (rec->type == HIF_EVENT_BH_SCHED) {
|
||||||
|
rec->timestamp = qdf_get_log_timestamp();
|
||||||
|
rec->cpu_id = qdf_get_cpu();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HIF_EVENT_SRNG_ACCESS_START:
|
||||||
|
if (event->hp == event->tp)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case HIF_EVENT_SRNG_ACCESS_END:
|
||||||
|
if (rec->type != HIF_EVENT_SRNG_ACCESS_START)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void hif_hist_record_event(struct hif_opaque_softc *hif_ctx,
|
void hif_hist_record_event(struct hif_opaque_softc *hif_ctx,
|
||||||
struct hif_event_record *event, uint8_t intr_grp_id)
|
struct hif_event_record *event, uint8_t intr_grp_id)
|
||||||
{
|
{
|
||||||
@@ -63,11 +146,19 @@ void hif_hist_record_event(struct hif_opaque_softc *hif_ctx,
|
|||||||
if (qdf_unlikely(!hist_ev))
|
if (qdf_unlikely(!hist_ev))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (hif_hist_skip_event_record(hist_ev, event))
|
||||||
|
return;
|
||||||
|
|
||||||
record_index = hif_get_next_record_index(
|
record_index = hif_get_next_record_index(
|
||||||
&hist_ev->index, HIF_EVENT_HIST_MAX);
|
&hist_ev->index, HIF_EVENT_HIST_MAX);
|
||||||
|
|
||||||
record = &hist_ev->event[record_index];
|
record = &hist_ev->event[record_index];
|
||||||
|
|
||||||
|
if (event->type == HIF_EVENT_IRQ_TRIGGER) {
|
||||||
|
hist_ev->misc.last_irq_index = record_index;
|
||||||
|
hist_ev->misc.last_irq_ts = qdf_get_log_timestamp();
|
||||||
|
}
|
||||||
|
|
||||||
record->hal_ring_id = event->hal_ring_id;
|
record->hal_ring_id = event->hal_ring_id;
|
||||||
record->hp = event->hp;
|
record->hp = event->hp;
|
||||||
record->tp = event->tp;
|
record->tp = event->tp;
|
||||||
|
Reference in New Issue
Block a user