qcacmn: Add support to log CE DST and STATUS ring events
1. Record hp/tp for ce dst and status ring to keep a track of the last reaped and posted buffers. 2. Add union ce_srng_desc to record ce srng descriptor information. Change-Id: I6f4728893d629c60f676826bf806b725326fb83d CRs-Fixed: 2465492
This commit is contained in:

committed by
nshrivas

parent
ff4d3f79f1
commit
d8b05b54d7
@@ -880,6 +880,20 @@ static inline uint32_t hal_srng_src_done_val(void *hal_soc, void *hal_ring)
|
||||
srng->u.src_ring.cached_tp) / srng->entry_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* hal_get_entrysize_from_srng() - Retrieve ring entry size
|
||||
* @hal_ring: Source ring pointer
|
||||
*
|
||||
* Return: uint8_t
|
||||
*/
|
||||
static inline
|
||||
uint8_t hal_get_entrysize_from_srng(void *hal_ring)
|
||||
{
|
||||
struct hal_srng *srng = (struct hal_srng *)hal_ring;
|
||||
|
||||
return srng->entry_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* hal_get_sw_hptp - Get SW head and tail pointer location for any ring
|
||||
* @hal_soc: Opaque HAL SOC handle
|
||||
|
@@ -379,6 +379,18 @@ union ce_desc {
|
||||
struct CE_dest_desc dest_desc;
|
||||
};
|
||||
|
||||
/**
|
||||
* union ce_srng_desc - unified data type for ce srng descriptors
|
||||
* @src_desc: ce srng Source ring descriptor
|
||||
* @dest_desc: ce srng destination ring descriptor
|
||||
* @dest_status_desc: ce srng status ring descriptor
|
||||
*/
|
||||
union ce_srng_desc {
|
||||
struct ce_srng_src_desc src_desc;
|
||||
struct ce_srng_dest_desc dest_desc;
|
||||
struct ce_srng_dest_status_desc dest_status_desc;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum hif_ce_event_type - HIF copy engine event type
|
||||
* @HIF_RX_DESC_POST: event recorded before updating write index of RX ring.
|
||||
@@ -408,6 +420,13 @@ union ce_desc {
|
||||
* @NAPI_POLL_ENTER: records the start of the napi poll function
|
||||
* @NAPI_COMPLETE: records when interrupts are reenabled
|
||||
* @NAPI_POLL_EXIT: records when the napi poll function returns
|
||||
* @HIF_RX_NBUF_ALLOC_FAILURE: record the packet when nbuf fails to allocate
|
||||
* @HIF_RX_NBUF_MAP_FAILURE: record the packet when dma map fails
|
||||
* @HIF_RX_NBUF_ENQUEUE_FAILURE: record the packet when enqueue to ce fails
|
||||
* @HIF_CE_SRC_RING_BUFFER_POST: record the packet when buffer is posted to ce src ring
|
||||
* @HIF_CE_DEST_RING_BUFFER_POST: record the packet when buffer is posted to ce dst ring
|
||||
* @HIF_CE_DEST_RING_BUFFER_REAP: record the packet when buffer is reaped from ce dst ring
|
||||
* @HIF_CE_DEST_STATUS_RING_REAP: record the packet when status ring is reaped
|
||||
*/
|
||||
enum hif_ce_event_type {
|
||||
HIF_RX_DESC_POST,
|
||||
@@ -437,6 +456,11 @@ enum hif_ce_event_type {
|
||||
HIF_RX_NBUF_ALLOC_FAILURE = 0x20,
|
||||
HIF_RX_NBUF_MAP_FAILURE,
|
||||
HIF_RX_NBUF_ENQUEUE_FAILURE,
|
||||
|
||||
HIF_CE_SRC_RING_BUFFER_POST,
|
||||
HIF_CE_DEST_RING_BUFFER_POST,
|
||||
HIF_CE_DEST_RING_BUFFER_REAP,
|
||||
HIF_CE_DEST_STATUS_RING_REAP,
|
||||
};
|
||||
|
||||
void ce_init_ce_desc_event_log(struct hif_softc *scn, int ce_id, int size);
|
||||
@@ -513,10 +537,6 @@ static inline void ce_t2h_msg_ce_cleanup(struct CE_handle *ce_hdl)
|
||||
*/
|
||||
int hif_get_wake_ce_id(struct hif_softc *scn, uint8_t *ce_id);
|
||||
|
||||
/*
|
||||
* Note: For MCL, #if defined (HIF_CONFIG_SLUB_DEBUG_ON) needs to be checked
|
||||
* for defined here
|
||||
*/
|
||||
#if defined(HIF_CONFIG_SLUB_DEBUG_ON) || defined(HIF_CE_DEBUG_DATA_BUF)
|
||||
|
||||
#ifndef HIF_CE_HISTORY_MAX
|
||||
@@ -524,10 +544,13 @@ int hif_get_wake_ce_id(struct hif_softc *scn, uint8_t *ce_id);
|
||||
#endif
|
||||
|
||||
#define CE_DEBUG_MAX_DATA_BUF_SIZE 64
|
||||
|
||||
/**
|
||||
* struct hif_ce_desc_event - structure for detailing a ce event
|
||||
* @type: what the event was
|
||||
* @time: when it happened
|
||||
* @current_hp: holds the current ring hp value
|
||||
* @current_tp: holds the current ring tp value
|
||||
* @descriptor: descriptor enqueued or dequeued
|
||||
* @memory: virtual address that was used
|
||||
* @index: location of the descriptor in the ce ring;
|
||||
@@ -535,19 +558,77 @@ int hif_get_wake_ce_id(struct hif_softc *scn, uint8_t *ce_id);
|
||||
* @actual_data_len: length of the data
|
||||
*/
|
||||
struct hif_ce_desc_event {
|
||||
uint16_t index;
|
||||
int index;
|
||||
enum hif_ce_event_type type;
|
||||
uint64_t time;
|
||||
#ifdef HELIUMPLUS
|
||||
union ce_desc descriptor;
|
||||
#else
|
||||
uint32_t current_hp;
|
||||
uint32_t current_tp;
|
||||
union ce_srng_desc descriptor;
|
||||
#endif
|
||||
void *memory;
|
||||
#ifdef HIF_CE_DEBUG_DATA_BUF
|
||||
uint8_t *data;
|
||||
size_t actual_data_len;
|
||||
#endif /* HIF_CE_DEBUG_DATA_BUF */
|
||||
};
|
||||
#else
|
||||
struct hif_ce_desc_event;
|
||||
#endif /*#if defined(HIF_CONFIG_SLUB_DEBUG_ON)||defined(HIF_CE_DEBUG_DATA_BUF)*/
|
||||
/**
|
||||
* get_next_record_index() - get the next record index
|
||||
* @table_index: atomic index variable to increment
|
||||
* @array_size: array size of the circular buffer
|
||||
*
|
||||
* Increment the atomic index and reserve the value.
|
||||
* Takes care of buffer wrap.
|
||||
* Guaranteed to be thread safe as long as fewer than array_size contexts
|
||||
* try to access the array. If there are more than array_size contexts
|
||||
* trying to access the array, full locking of the recording process would
|
||||
* be needed to have sane logging.
|
||||
*/
|
||||
int get_next_record_index(qdf_atomic_t *table_index, int array_size);
|
||||
|
||||
#if defined(HIF_CONFIG_SLUB_DEBUG_ON) || defined(HIF_CE_DEBUG_DATA_BUF)
|
||||
/**
|
||||
* hif_record_ce_srng_desc_event() - Record data pointed by the CE descriptor
|
||||
* @scn: structure detailing a ce event
|
||||
* @ce_id: length of the data
|
||||
* @type: event_type
|
||||
* @descriptor: ce src/dest/status ring descriptor
|
||||
* @memory: nbuf
|
||||
* @index: current sw/write index
|
||||
* @len: len of the buffer
|
||||
* @hal_ring: ce hw ring
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void hif_record_ce_srng_desc_event(struct hif_softc *scn, int ce_id,
|
||||
enum hif_ce_event_type type,
|
||||
union ce_srng_desc *descriptor,
|
||||
void *memory, int index,
|
||||
int len, void *hal_ring);
|
||||
#else
|
||||
static inline
|
||||
void hif_record_ce_srng_desc_event(struct hif_softc *scn, int ce_id,
|
||||
enum hif_ce_event_type type,
|
||||
union ce_srng_desc *descriptor,
|
||||
void *memory, int index,
|
||||
int len, void *hal_ring)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HIF_CE_DEBUG_DATA_BUF
|
||||
/**
|
||||
* hif_ce_desc_data_record() - Record data pointed by the CE descriptor
|
||||
* @event: structure detailing a ce event
|
||||
* @len: length of the data
|
||||
* Return:
|
||||
*/
|
||||
void hif_ce_desc_data_record(struct hif_ce_desc_event *event, int len);
|
||||
QDF_STATUS alloc_mem_ce_debug_hist_data(struct hif_softc *scn, uint32_t ce_id);
|
||||
void free_mem_ce_debug_hist_data(struct hif_softc *scn, uint32_t ce_id);
|
||||
#else
|
||||
@@ -559,6 +640,11 @@ QDF_STATUS alloc_mem_ce_debug_hist_data(struct hif_softc *scn, uint32_t ce_id)
|
||||
|
||||
static inline
|
||||
void free_mem_ce_debug_hist_data(struct hif_softc *scn, uint32_t ce_id) { }
|
||||
|
||||
static inline
|
||||
void hif_ce_desc_data_record(struct hif_ce_desc_event *event, int len)
|
||||
{
|
||||
}
|
||||
#endif /*HIF_CE_DEBUG_DATA_BUF*/
|
||||
|
||||
#ifdef HIF_CONFIG_SLUB_DEBUG_ON
|
||||
|
@@ -92,19 +92,7 @@ void hif_ce_war_enable(void)
|
||||
|
||||
static const char *ce_event_type_to_str(enum hif_ce_event_type type);
|
||||
|
||||
/**
|
||||
* get_next_record_index() - get the next record index
|
||||
* @table_index: atomic index variable to increment
|
||||
* @array_size: array size of the circular buffer
|
||||
*
|
||||
* Increment the atomic index and reserve the value.
|
||||
* Takes care of buffer wrap.
|
||||
* Guaranteed to be thread safe as long as fewer than array_size contexts
|
||||
* try to access the array. If there are more than array_size contexts
|
||||
* trying to access the array, full locking of the recording process would
|
||||
* be needed to have sane logging.
|
||||
*/
|
||||
static int get_next_record_index(qdf_atomic_t *table_index, int array_size)
|
||||
int get_next_record_index(qdf_atomic_t *table_index, int array_size)
|
||||
{
|
||||
int record_index = qdf_atomic_inc_return(table_index);
|
||||
|
||||
@@ -113,17 +101,11 @@ static int get_next_record_index(qdf_atomic_t *table_index, int array_size)
|
||||
|
||||
while (record_index >= array_size)
|
||||
record_index -= array_size;
|
||||
|
||||
return record_index;
|
||||
}
|
||||
|
||||
#ifdef HIF_CE_DEBUG_DATA_BUF
|
||||
/**
|
||||
* hif_ce_desc_data_record() - Record data pointed by the CE descriptor
|
||||
* @event: structure detailing a ce event
|
||||
* @len: length of the data
|
||||
* Return:
|
||||
*/
|
||||
static inline
|
||||
void hif_ce_desc_data_record(struct hif_ce_desc_event *event, int len)
|
||||
{
|
||||
uint8_t *data = NULL;
|
||||
@@ -146,12 +128,7 @@ void hif_ce_desc_data_record(struct hif_ce_desc_event *event, int len)
|
||||
event->actual_data_len = len;
|
||||
}
|
||||
}
|
||||
#else
|
||||
static inline
|
||||
void hif_ce_desc_data_record(struct hif_ce_desc_event *event, int len)
|
||||
{
|
||||
}
|
||||
#endif /* HIF_CE_DEBUG_DATA_BUF */
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hif_record_ce_desc_event() - record ce descriptor events
|
||||
@@ -193,14 +170,14 @@ void hif_record_ce_desc_event(struct hif_softc *scn, int ce_id,
|
||||
|
||||
event = &hist_ev[record_index];
|
||||
|
||||
qdf_mem_zero(event, sizeof(struct hif_ce_desc_event));
|
||||
|
||||
event->type = type;
|
||||
event->time = qdf_get_log_timestamp();
|
||||
|
||||
if (descriptor) {
|
||||
qdf_mem_copy(&event->descriptor, descriptor, sizeof(union ce_desc));
|
||||
} else {
|
||||
qdf_mem_zero(&event->descriptor, sizeof(union ce_desc));
|
||||
}
|
||||
if (descriptor)
|
||||
qdf_mem_copy(&event->descriptor, descriptor,
|
||||
sizeof(union ce_desc));
|
||||
|
||||
event->memory = memory;
|
||||
event->index = index;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2013-2019 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
|
||||
@@ -748,8 +748,10 @@ ce_recv_buf_enqueue_legacy(struct CE_handle *copyeng,
|
||||
dest_ring->per_transfer_context[write_index] =
|
||||
per_recv_context;
|
||||
|
||||
hif_record_ce_desc_event(scn, CE_state->id, HIF_RX_DESC_POST,
|
||||
(union ce_desc *)dest_desc, per_recv_context,
|
||||
hif_record_ce_desc_event(scn, CE_state->id,
|
||||
HIF_RX_DESC_POST,
|
||||
(union ce_desc *)dest_desc,
|
||||
per_recv_context,
|
||||
write_index, 0);
|
||||
|
||||
/* Update Destination Ring Write Index */
|
||||
|
@@ -15,8 +15,6 @@
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "hif.h"
|
||||
#include "hif_io32.h"
|
||||
#include "reg_struct.h"
|
||||
#include "ce_api.h"
|
||||
@@ -30,6 +28,7 @@
|
||||
#include "hal_api.h"
|
||||
#include "pld_common.h"
|
||||
#include "qdf_module.h"
|
||||
#include "hif.h"
|
||||
|
||||
/*
|
||||
* Support for Copy Engine hardware, which is mainly used for
|
||||
@@ -78,6 +77,58 @@
|
||||
(uint32_t)(((dma_addr) >> 32) & 0xFF);\
|
||||
} while (0)
|
||||
|
||||
#if defined(HIF_CONFIG_SLUB_DEBUG_ON) || defined(HIF_CE_DEBUG_DATA_BUF)
|
||||
void hif_record_ce_srng_desc_event(struct hif_softc *scn, int ce_id,
|
||||
enum hif_ce_event_type type,
|
||||
union ce_srng_desc *descriptor,
|
||||
void *memory, int index,
|
||||
int len, void *hal_ring)
|
||||
{
|
||||
int record_index;
|
||||
struct hif_ce_desc_event *event;
|
||||
struct ce_desc_hist *ce_hist = &scn->hif_ce_desc_hist;
|
||||
struct hif_ce_desc_event *hist_ev = NULL;
|
||||
|
||||
if (ce_id < CE_COUNT_MAX)
|
||||
hist_ev = (struct hif_ce_desc_event *)ce_hist->hist_ev[ce_id];
|
||||
else
|
||||
return;
|
||||
|
||||
if (ce_id >= CE_COUNT_MAX)
|
||||
return;
|
||||
|
||||
if (!ce_hist->enable[ce_id])
|
||||
return;
|
||||
|
||||
if (!hist_ev)
|
||||
return;
|
||||
|
||||
record_index = get_next_record_index(
|
||||
&ce_hist->history_index[ce_id], HIF_CE_HISTORY_MAX);
|
||||
|
||||
event = &hist_ev[record_index];
|
||||
|
||||
qdf_mem_zero(event, sizeof(struct hif_ce_desc_event));
|
||||
|
||||
event->type = type;
|
||||
event->time = qdf_get_log_timestamp();
|
||||
|
||||
if (descriptor)
|
||||
qdf_mem_copy(&event->descriptor, descriptor,
|
||||
hal_get_entrysize_from_srng(hal_ring));
|
||||
|
||||
if (hal_ring)
|
||||
hal_get_sw_hptp(scn->hal_soc, hal_ring, &event->current_tp,
|
||||
&event->current_hp);
|
||||
|
||||
event->memory = memory;
|
||||
event->index = index;
|
||||
|
||||
if (ce_hist->data_enable[ce_id])
|
||||
hif_ce_desc_data_record(event, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
ce_send_nolock_srng(struct CE_handle *copyeng,
|
||||
void *per_transfer_context,
|
||||
@@ -104,7 +155,7 @@ ce_send_nolock_srng(struct CE_handle *copyeng,
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
{
|
||||
enum hif_ce_event_type event_type = HIF_TX_GATHER_DESC_POST;
|
||||
enum hif_ce_event_type event_type = HIF_CE_SRC_RING_BUFFER_POST;
|
||||
struct ce_srng_src_desc *src_desc;
|
||||
|
||||
if (hal_srng_access_start(scn->hal_soc, src_ring->srng_ctx)) {
|
||||
@@ -148,9 +199,11 @@ ce_send_nolock_srng(struct CE_handle *copyeng,
|
||||
/* src_ring->write index hasn't been updated event though
|
||||
* the register has allready been written to.
|
||||
*/
|
||||
hif_record_ce_desc_event(scn, CE_state->id, event_type,
|
||||
(union ce_desc *) src_desc, per_transfer_context,
|
||||
src_ring->write_index, nbytes);
|
||||
hif_record_ce_srng_desc_event(scn, CE_state->id, event_type,
|
||||
(union ce_srng_desc *)src_desc,
|
||||
per_transfer_context,
|
||||
src_ring->write_index, nbytes,
|
||||
src_ring->srng_ctx);
|
||||
|
||||
src_ring->write_index = write_index;
|
||||
status = QDF_STATUS_SUCCESS;
|
||||
@@ -252,6 +305,7 @@ ce_recv_buf_enqueue_srng(struct CE_handle *copyeng,
|
||||
unsigned int sw_index;
|
||||
uint64_t dma_addr = buffer;
|
||||
struct hif_softc *scn = CE_state->scn;
|
||||
struct ce_srng_dest_desc *dest_desc;
|
||||
|
||||
qdf_spin_lock_bh(&CE_state->ce_index_lock);
|
||||
write_index = dest_ring->write_index;
|
||||
@@ -269,8 +323,7 @@ ce_recv_buf_enqueue_srng(struct CE_handle *copyeng,
|
||||
|
||||
if ((hal_srng_src_num_avail(scn->hal_soc,
|
||||
dest_ring->srng_ctx, false) > 0)) {
|
||||
struct ce_srng_dest_desc *dest_desc =
|
||||
hal_srng_src_get_next(scn->hal_soc,
|
||||
dest_desc = hal_srng_src_get_next(scn->hal_soc,
|
||||
dest_ring->srng_ctx);
|
||||
|
||||
if (!dest_desc) {
|
||||
@@ -292,6 +345,13 @@ ce_recv_buf_enqueue_srng(struct CE_handle *copyeng,
|
||||
|
||||
dest_ring->write_index = write_index;
|
||||
hal_srng_access_end(scn->hal_soc, dest_ring->srng_ctx);
|
||||
hif_record_ce_srng_desc_event(scn, CE_state->id,
|
||||
HIF_CE_DEST_RING_BUFFER_POST,
|
||||
(union ce_srng_desc *)dest_desc,
|
||||
per_recv_context,
|
||||
dest_ring->write_index, 0,
|
||||
dest_ring->srng_ctx);
|
||||
|
||||
Q_TARGET_ACCESS_END(scn);
|
||||
qdf_spin_unlock_bh(&CE_state->ce_index_lock);
|
||||
return status;
|
||||
@@ -412,6 +472,23 @@ ce_completed_recv_next_nolock_srng(struct CE_state *CE_state,
|
||||
done:
|
||||
hal_srng_access_end(scn->hal_soc, status_ring->srng_ctx);
|
||||
|
||||
if (status == QDF_STATUS_SUCCESS) {
|
||||
hif_record_ce_srng_desc_event(scn, CE_state->id,
|
||||
HIF_CE_DEST_RING_BUFFER_REAP,
|
||||
NULL,
|
||||
dest_ring->
|
||||
per_transfer_context[sw_index],
|
||||
dest_ring->sw_index, nbytes,
|
||||
dest_ring->srng_ctx);
|
||||
|
||||
hif_record_ce_srng_desc_event(scn, CE_state->id,
|
||||
HIF_CE_DEST_STATUS_RING_REAP,
|
||||
(union ce_srng_desc *)dest_status,
|
||||
NULL,
|
||||
-1, 0,
|
||||
status_ring->srng_ctx);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -482,11 +559,13 @@ ce_completed_send_next_nolock_srng(struct CE_state *CE_state,
|
||||
|
||||
src_desc = hal_srng_src_reap_next(scn->hal_soc, src_ring->srng_ctx);
|
||||
if (src_desc) {
|
||||
hif_record_ce_desc_event(scn, CE_state->id,
|
||||
hif_record_ce_srng_desc_event(scn, CE_state->id,
|
||||
HIF_TX_DESC_COMPLETION,
|
||||
(union ce_desc *)src_desc,
|
||||
src_ring->per_transfer_context[swi],
|
||||
swi, src_desc->nbytes);
|
||||
(union ce_srng_desc *)src_desc,
|
||||
src_ring->
|
||||
per_transfer_context[swi],
|
||||
swi, src_desc->nbytes,
|
||||
src_ring->srng_ctx);
|
||||
|
||||
/* Return data from completed source descriptor */
|
||||
*bufferp = (qdf_dma_addr_t)
|
||||
|
@@ -154,7 +154,7 @@ static void ce_tasklet(unsigned long data)
|
||||
struct CE_state *CE_state = scn->ce_id_to_state[tasklet_entry->ce_id];
|
||||
|
||||
hif_record_ce_desc_event(scn, tasklet_entry->ce_id,
|
||||
HIF_CE_TASKLET_ENTRY, NULL, NULL, 0, 0);
|
||||
HIF_CE_TASKLET_ENTRY, NULL, NULL, -1, 0);
|
||||
|
||||
if (qdf_atomic_read(&scn->link_suspended)) {
|
||||
HIF_ERROR("%s: ce %d tasklet fired after link suspend.",
|
||||
@@ -171,7 +171,7 @@ static void ce_tasklet(unsigned long data)
|
||||
* any of the Copy Engine pipes.
|
||||
*/
|
||||
hif_record_ce_desc_event(scn, tasklet_entry->ce_id,
|
||||
HIF_CE_TASKLET_RESCHEDULE, NULL, NULL, 0, 0);
|
||||
HIF_CE_TASKLET_RESCHEDULE, NULL, NULL, -1, 0);
|
||||
|
||||
ce_schedule_tasklet(tasklet_entry);
|
||||
return;
|
||||
@@ -181,7 +181,7 @@ static void ce_tasklet(unsigned long data)
|
||||
hif_irq_enable(scn, tasklet_entry->ce_id);
|
||||
|
||||
hif_record_ce_desc_event(scn, tasklet_entry->ce_id, HIF_CE_TASKLET_EXIT,
|
||||
NULL, NULL, 0, 0);
|
||||
NULL, NULL, -1, 0);
|
||||
|
||||
qdf_atomic_dec(&scn->active_tasklet_cnt);
|
||||
}
|
||||
|
Reference in New Issue
Block a user