diff --git a/qdf/inc/qdf_types.h b/qdf/inc/qdf_types.h index 42555a0da4..d462fdcc82 100644 --- a/qdf/inc/qdf_types.h +++ b/qdf/inc/qdf_types.h @@ -319,6 +319,7 @@ typedef void (*qdf_timer_func_t)(void *); * @QDF_MODULE_ID_REGULATORY : REGULATORY module ID * @QDF_MODULE_ID_NAN: NAN module ID * @QDF_MODULE_ID_SPECTRAL: Spectral module ID + * @QDF_MODULE_ID_ROAM_DEBUG: Roam Debug logging * @QDF_MODULE_ID_ANY: anything * @QDF_MODULE_ID_MAX: Max place holder module ID */ @@ -411,6 +412,7 @@ typedef enum { QDF_MODULE_ID_SPECTRAL, QDF_MODULE_ID_OBJ_MGR, QDF_MODULE_ID_NSS, + QDF_MODULE_ID_ROAM_DEBUG, QDF_MODULE_ID_ANY, QDF_MODULE_ID_MAX, } QDF_MODULE_ID; diff --git a/qdf/linux/src/qdf_trace.c b/qdf/linux/src/qdf_trace.c index 1d6405158e..eab0d013c1 100644 --- a/qdf/linux/src/qdf_trace.c +++ b/qdf/linux/src/qdf_trace.c @@ -2057,6 +2057,7 @@ struct category_name_info g_qdf_category_name[MAX_SUPPORTED_CATEGORY] = { [QDF_MODULE_ID_OBJ_MGR] = {"OBJMGR"}, [QDF_MODULE_ID_SERIALIZATION] = {"SER"}, [QDF_MODULE_ID_NSS] = {"NSS"}, + [QDF_MODULE_ID_ROAM_DEBUG] = {"roam debug"}, [QDF_MODULE_ID_ANY] = {"ANY"}, }; EXPORT_SYMBOL(g_qdf_category_name); @@ -2523,6 +2524,7 @@ static void set_default_trace_levels(struct category_info *cinfo) [QDF_MODULE_ID_OBJ_MGR] = QDF_TRACE_LEVEL_INFO, [QDF_MODULE_ID_SERIALIZATION] = QDF_TRACE_LEVEL_NONE, [QDF_MODULE_ID_NSS] = QDF_TRACE_LEVEL_ERROR, + [QDF_MODULE_ID_ROAM_DEBUG] = QDF_TRACE_LEVEL_ERROR, [QDF_MODULE_ID_ANY] = QDF_TRACE_LEVEL_NONE, }; diff --git a/utils/logging/inc/wlan_roam_debug.h b/utils/logging/inc/wlan_roam_debug.h new file mode 100644 index 0000000000..35b9c3a63e --- /dev/null +++ b/utils/logging/inc/wlan_roam_debug.h @@ -0,0 +1,122 @@ +/* + * 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 declarations + */ +#ifndef _WLAN_ROAM_DEBUG_H_ +#define _WLAN_ROAM_DEBUG_H_ + + +/** + * struct wlan_roam_debug_rec - roam debug information record definition + * @time: timestamp when record was added + * @operation: identifier for operation, command, event, etc. + * @vdev_id: vdev identifier + * @peer_id: peer_id. Range 0 - 255, 0xffff is invalid peer_id. + * @mac_addr: mac address of peer + * @peer_obj: pointer to peer object + * @arg1: Optional argument #1 + * @arg2: Opttional argument #2 + */ +struct wlan_roam_debug_rec { + uint64_t time; + uint8_t operation; + uint8_t vdev_id; + uint16_t peer_id; + struct qdf_mac_addr mac_addr; + void *peer_obj; + uint32_t arg1; + uint32_t arg2; +}; + +#define WLAN_ROAM_DEBUG_MAX_REC 256 +/** + * struct wlan_roam_debug_info - Buffer to store the wma debug records + * @index: index of the most recent entry in the circular buffer + * @num_max_rec: maximum records stored in the records array + * @rec: array to store wma debug records, used in circular fashion + */ +struct wlan_roam_debug_info { + qdf_atomic_t index; + uint32_t num_max_rec; + struct wlan_roam_debug_rec rec[WLAN_ROAM_DEBUG_MAX_REC]; +}; + +/** + * @DEBUG_PEER_CREATE_SEND: sent peer_create command to firmware + * @DEBUG_PEER_CREATE_RESP: received peer create response + * @DEBUG_PEER_DELETE_SEND: sent peer delete command to firmware + * @DEBUG_PEER_DELETE_RESP: received peer delete response + * @DEBUG_PEER_MAP_EVENT: received peer map event + * @DEBUG_PEER_UNMAP_EVENT: received peer unmap event + * @DEBUG_PEER_UNREF_DELETE: peer reference is decremented + * @DEBUG_DELETING_PEER_OBJ: peer object is deleted + * @DEBUG_ROAM_SYNCH_IND: received roam offload sync indication + * @DEBUG_ROAM_SYNCH_CNF: sent roam offload sync confirmation + * @DEBUG_ROAM_SYNCH_FAIL: received roam sync failure indication + * @DEBUG_ROAM_EVENT: received roam event + * @DEBUG_BUS_SUSPEND: host going into suspend mode + * @DEBUG_BUS_RESUME: host operation resumed + */ + +enum peer_debug_op { + DEBUG_PEER_CREATE_SEND = 0, + DEBUG_PEER_CREATE_RESP, + DEBUG_PEER_DELETE_SEND, + DEBUG_PEER_DELETE_RESP, + DEBUG_PEER_MAP_EVENT, + DEBUG_PEER_UNMAP_EVENT, + DEBUG_PEER_UNREF_DELETE, + DEBUG_DELETING_PEER_OBJ, + DEBUG_ROAM_SYNCH_IND, + DEBUG_ROAM_SYNCH_CNF, + DEBUG_ROAM_SYNCH_FAIL, + DEBUG_ROAM_EVENT, + DEBUG_WOW_ROAM_EVENT, + DEBUG_BUS_SUSPEND, + DEBUG_BUS_RESUME, + DEBUG_WOW_REASON, +}; + +#define DEBUG_INVALID_PEER_ID 0xffff +#define DEBUG_INVALID_VDEV_ID 0xff + +/** + * 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); + +/** + * wlan_roam_debug_dump_table() - Print the roam debug log records + * print all the valid debug records in the order of timestamp + * + * Return: none + */ +void wlan_roam_debug_dump_table(void); +#endif /* _WLAN_ROAM_DEBUG_H_ */ diff --git a/utils/logging/src/wlan_roam_debug.c b/utils/logging/src/wlan_roam_debug.c new file mode 100644 index 0000000000..0c663c8c8b --- /dev/null +++ b/utils/logging/src/wlan_roam_debug.c @@ -0,0 +1,209 @@ +/* + * 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 +#include +#include +#include +#include +#include +#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); + + +