Files
android_kernel_samsung_sm86…/utils/logging/src/wlan_roam_debug.c
Deepak Dhamdhere 7e0b8ba31a qcacmn: Create roam debug log infrastructure
Add a circular buffer to hold roaming related debug log information
for peer and vdev operations in the driver. Purpose is to dump
this information after host or target crash. 256 entries will go
back much deeper into history than dmesg or wlan driver logs found
in crashScope. Information is dumped out as error messages from
crash detection points as necessary.

The support routines help to store the debug logs and dump them,
typically after peer related timeout or assert.

wlan_roam_next_debug_log_index () - Utility routine to compute next index
wlan_roam_debug_log() - Adds a log entry
wlan_roam_debug_string() - Returns debug log type string
wlan_roam_debug_dump() - Dump all wlan roam debug log records

Add new QDF module ID QDF_MODULE_ID_ROAM_DEBUG.

CRs-Fixed: 1116078
Change-Id: If2077f560405ec0414d08ef4ece0fb0d2db2ccc7
2017-10-31 17:39:09 -07:00

210 lines
6.0 KiB
C

/*
* Copyright (c) 2013-2017 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
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* DOC: Roaming debug log operations routines and global data
*/
#include <qdf_types.h>
#include <qdf_atomic.h>
#include <qdf_mem.h>
#include <qdf_time.h>
#include <qdf_trace.h>
#include <wlan_cmn.h>
#include "wlan_roam_debug.h"
/*
* wlan roam debug log is stored in this global structure. It can be accessed
* without requiring any psoc or vdev context. It will be accessible in
* the crash dump without having to dereference complex stack traces.
*/
static struct wlan_roam_debug_info global_wlan_roam_debug_table = {
{ 0 },
WLAN_ROAM_DEBUG_MAX_REC,
};
/**
* wlan_roam_next_debug_log_index() - atomically increment and wrap around index
* @index: address of index to increment
* @size: wrap around this value
*
* Return: new value of index
*/
static int wlan_roam_next_debug_log_index(qdf_atomic_t *index, int size)
{
int i = qdf_atomic_inc_return(index);
if (i == WLAN_ROAM_DEBUG_MAX_REC)
qdf_atomic_sub(WLAN_ROAM_DEBUG_MAX_REC, index);
while (i >= size)
i -= WLAN_ROAM_DEBUG_MAX_REC;
return i;
}
/**
* wlan_roam_debug_log() - Add a debug log entry to wlan roam debug records
* @vdev_id: vdev identifier
* @op: operation identifier
* @peer_id: peer id
* @mac_addr: mac address of peer, can be NULL
* @peer_obj: peer object address, can be NULL
* @arg1: extra argument #1
* @arg2: extra argument #2
*
* Return: none
*/
void wlan_roam_debug_log(uint8_t vdev_id, uint8_t op,
uint16_t peer_id, void *mac_addr,
void *peer_obj, uint32_t arg1, uint32_t arg2)
{
uint32_t i;
struct wlan_roam_debug_rec *rec;
i = wlan_roam_next_debug_log_index(
&global_wlan_roam_debug_table.index,
WLAN_ROAM_DEBUG_MAX_REC);
rec = &global_wlan_roam_debug_table.rec[i];
rec->time = qdf_get_log_timestamp();
rec->operation = op;
rec->vdev_id = vdev_id;
rec->peer_id = peer_id;
if (mac_addr)
qdf_mem_copy(rec->mac_addr.bytes, mac_addr,
WLAN_MACADDR_LEN);
else
qdf_mem_zero(rec->mac_addr.bytes,
WLAN_MACADDR_LEN);
rec->peer_obj = peer_obj;
rec->arg1 = arg1;
rec->arg2 = arg2;
}
EXPORT_SYMBOL(wlan_roam_debug_log);
/**
* wlan_roam_debug_string() - convert operation value to printable string
* @op: operation identifier
*
* Return: printable string for the operation
*/
static char *wlan_roam_debug_string(uint32_t op)
{
switch (op) {
case DEBUG_PEER_CREATE_SEND:
return "peer create send";
case DEBUG_PEER_CREATE_RESP:
return "peer create resp_event";
case DEBUG_PEER_DELETE_SEND:
return "peer delete send";
case DEBUG_PEER_DELETE_RESP:
return "peer delete resp_event";
case DEBUG_PEER_MAP_EVENT:
return "peer map event";
case DEBUG_PEER_UNMAP_EVENT:
return "peer unmap event";
case DEBUG_PEER_UNREF_DELETE:
return "peer unref delete";
case DEBUG_DELETING_PEER_OBJ:
return "peer obj deleted";
case DEBUG_ROAM_SYNCH_IND:
return "roam synch ind event";
case DEBUG_ROAM_SYNCH_CNF:
return "roam sync conf sent";
case DEBUG_ROAM_SYNCH_FAIL:
return "roam sync fail event";
case DEBUG_ROAM_EVENT:
return "roam event";
case DEBUG_WOW_ROAM_EVENT:
return "wow wakeup roam event";
case DEBUG_BUS_SUSPEND:
return "host suspend";
case DEBUG_BUS_RESUME:
return "host wakeup";
case DEBUG_WOW_REASON:
return "wow wakeup reason";
default:
return "unknown";
}
}
/**
* wlan_roam_debug_dump_table() - Print the wlan roam debug log records
* print all the valid debug records in the order of timestamp
*
* Return: none
*/
void wlan_roam_debug_dump_table(void)
{
uint32_t i;
int32_t current_index;
struct wlan_roam_debug_rec *dbg_rec;
uint64_t startt = 0;
uint32_t delta;
#define DEBUG_CLOCK_TICKS_PER_MSEC 19200
current_index = qdf_atomic_read(&global_wlan_roam_debug_table.index);
if (current_index < 0) {
QDF_TRACE(QDF_MODULE_ID_ROAM_DEBUG, QDF_TRACE_LEVEL_ERROR,
"%s: No records to dump", __func__);
return;
}
QDF_TRACE(QDF_MODULE_ID_ROAM_DEBUG, QDF_TRACE_LEVEL_ERROR,
"%s: Dumping all records. current index %d",
__func__, current_index);
i = current_index;
do {
/* wrap around */
i = (i + 1) % WLAN_ROAM_DEBUG_MAX_REC;
dbg_rec = &global_wlan_roam_debug_table.rec[i];
/* skip unused entry */
if (dbg_rec->time == 0)
continue;
if (startt == 0)
startt = dbg_rec->time;
/*
* Divide by 19200 == right shift 8 bits, then divide by 75
* 32 bit computation keeps both 32 and 64 bit compilers happy.
* The value will roll over after approx. 33554 seconds.
*/
delta = (uint32_t) (((dbg_rec->time - startt) >> 8) &
0xffffffff);
delta = delta / (DEBUG_CLOCK_TICKS_PER_MSEC >> 8);
QDF_TRACE(QDF_MODULE_ID_ROAM_DEBUG, QDF_TRACE_LEVEL_ERROR,
"index = %5d timestamp = 0x%016llx delta ms = %-12u",
i, dbg_rec->time, delta);
QDF_TRACE(QDF_MODULE_ID_ROAM_DEBUG, QDF_TRACE_LEVEL_ERROR,
"info = %-24s vdev_id = %-3d mac addr = %pM",
wlan_roam_debug_string(dbg_rec->operation),
(int8_t) dbg_rec->vdev_id, dbg_rec->mac_addr.bytes);
QDF_TRACE(QDF_MODULE_ID_ROAM_DEBUG, QDF_TRACE_LEVEL_ERROR,
"peer obj = 0x%p peer_id = %-4d",
dbg_rec->peer_obj, (int8_t) dbg_rec->peer_id);
QDF_TRACE(QDF_MODULE_ID_ROAM_DEBUG, QDF_TRACE_LEVEL_ERROR,
"arg1 = 0x%-8x arg2 = 0x%-8x",
dbg_rec->arg1, dbg_rec->arg2);
} while (i != current_index);
}
EXPORT_SYMBOL(global_wlan_roam_debug_table);