qcacmn: Add debug for TSO seg double-free
Add TSO segment debug code, in a featurized way, so that when disabled, it will tolerate redundant returns to the internal pool and when enabled, it will check sanity on free, and record a history of last 16 actions on the segment in the object. Goes with the corresponding cld3 component counterpart. Change-Id: Ifee2ceae940043031e4861d0e4f5d19a51262229 CRs-Fixed: 2036665
This commit is contained in:

committed by
snandini

parent
21f852f52c
commit
c59be52d47
@@ -476,6 +476,62 @@ void __printf(3, 4) qdf_snprintf(char *str_buffer, unsigned int size,
|
||||
char *str_format, ...);
|
||||
|
||||
#define QDF_SNPRINTF qdf_snprintf
|
||||
|
||||
#ifdef TSOSEG_DEBUG
|
||||
static inline
|
||||
int qdf_tso_seg_dbg_record(struct qdf_tso_seg_elem_t *tsoseg,
|
||||
uint16_t caller)
|
||||
{
|
||||
int rc = -1;
|
||||
|
||||
if (tsoseg != NULL) {
|
||||
tsoseg->dbg.cur++; tsoseg->dbg.cur &= 0x0f;
|
||||
tsoseg->dbg.history[tsoseg->dbg.cur] = caller;
|
||||
rc = tsoseg->dbg.cur;
|
||||
}
|
||||
return rc;
|
||||
};
|
||||
static inline void qdf_tso_seg_dbg_bug(char *msg)
|
||||
{
|
||||
qdf_print(msg);
|
||||
QDF_BUG(0);
|
||||
};
|
||||
|
||||
static inline void
|
||||
qdf_tso_seg_dbg_setowner(struct qdf_tso_seg_elem_t *tsoseg, void *owner)
|
||||
{
|
||||
tsoseg->dbg.txdesc = owner;
|
||||
};
|
||||
|
||||
static inline void
|
||||
qdf_tso_seg_dbg_zero(struct qdf_tso_seg_elem_t *tsoseg)
|
||||
{
|
||||
memset(tsoseg, 0, offsetof(struct qdf_tso_seg_elem_t, dbg));
|
||||
return;
|
||||
};
|
||||
|
||||
#else
|
||||
static inline
|
||||
int qdf_tso_seg_dbg_record(struct qdf_tso_seg_elem_t *tsoseg,
|
||||
uint16_t caller)
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
static inline void qdf_tso_seg_dbg_bug(char *msg)
|
||||
{
|
||||
};
|
||||
static inline void
|
||||
qdf_tso_seg_dbg_setowner(struct qdf_tso_seg_elem_t *tsoseg, void *owner)
|
||||
{
|
||||
};
|
||||
static inline int
|
||||
qdf_tso_seg_dbg_zero(struct qdf_tso_seg_elem_t *tsoseg)
|
||||
{
|
||||
memset(tsoseg, 0, sizeof(struct qdf_tso_seg_elem_t));
|
||||
return 0;
|
||||
};
|
||||
|
||||
#endif /* TSOSEG_DEBUG */
|
||||
#else
|
||||
|
||||
#define DPTRACE(x)
|
||||
|
@@ -690,6 +690,33 @@ struct qdf_tso_seg_t {
|
||||
struct qdf_tso_frag_t tso_frags[FRAG_NUM_MAX];
|
||||
};
|
||||
|
||||
/**
|
||||
* TSO seg elem action caller locations: goes into dbg.history below.
|
||||
* Needed to be defined outside of the feature so that
|
||||
* callers can be coded without ifdefs (even if they get
|
||||
* resolved to nothing)
|
||||
*/
|
||||
enum tsoseg_dbg_caller_e {
|
||||
TSOSEG_LOC_UNDEFINED,
|
||||
TSOSEG_LOC_INIT1,
|
||||
TSOSEG_LOC_INIT2,
|
||||
TSOSEG_LOC_DEINIT,
|
||||
TSOSEG_LOC_PREPARETSO,
|
||||
TSOSEG_LOC_TXPREPLLFAST,
|
||||
TSOSEG_LOC_UNMAPTSO,
|
||||
TSOSEG_LOC_ALLOC,
|
||||
TSOSEG_LOC_FREE,
|
||||
};
|
||||
#ifdef TSOSEG_DEBUG
|
||||
|
||||
#define MAX_TSO_SEG_ACT_HISTORY 16
|
||||
struct qdf_tso_seg_dbg_t {
|
||||
void *txdesc; /* owner - (ol_txrx_tx_desc_t *) */
|
||||
int cur; /* index of last valid entry */
|
||||
uint16_t history[MAX_TSO_SEG_ACT_HISTORY];
|
||||
};
|
||||
#endif /* TSOSEG_DEBUG */
|
||||
|
||||
/**
|
||||
* qdf_tso_seg_elem_t - tso segment element
|
||||
* @seg: instance of segment
|
||||
@@ -700,6 +727,9 @@ struct qdf_tso_seg_elem_t {
|
||||
uint16_t cookie:15,
|
||||
on_freelist:1;
|
||||
struct qdf_tso_seg_elem_t *next;
|
||||
#ifdef TSOSEG_DEBUG
|
||||
struct qdf_tso_seg_dbg_t dbg;
|
||||
#endif /* TSOSEG_DEBUG */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -1982,6 +1982,7 @@ void __qdf_nbuf_unmap_tso_segment(qdf_device_t osdev,
|
||||
qdf_assert(0);
|
||||
return;
|
||||
}
|
||||
qdf_tso_seg_dbg_record(tso_seg, TSOSEG_LOC_UNMAPTSO);
|
||||
dma_unmap_single(osdev->dev,
|
||||
tso_seg->seg.tso_frags[num_frags].paddr,
|
||||
tso_seg->seg.tso_frags[num_frags].length,
|
||||
|
Reference in New Issue
Block a user