1 /* 2 * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* 20 * DOC: Roaming debug log operations routines and global data 21 */ 22 23 #include <qdf_types.h> 24 #include <qdf_atomic.h> 25 #include <qdf_mem.h> 26 #include <qdf_time.h> 27 #include <qdf_trace.h> 28 #include <qdf_module.h> 29 #include <wlan_cmn.h> 30 #include "wlan_roam_debug.h" 31 32 /* 33 * wlan roam debug log is stored in this global structure. It can be accessed 34 * without requiring any psoc or vdev context. It will be accessible in 35 * the crash dump without having to dereference complex stack traces. 36 */ 37 static struct wlan_roam_debug_info global_wlan_roam_debug_table = { 38 { 0 }, 39 WLAN_ROAM_DEBUG_MAX_REC, 40 }; 41 42 /** 43 * wlan_roam_next_debug_log_index() - atomically increment and wrap around index 44 * @index: address of index to increment 45 * @size: wrap around this value 46 * 47 * Return: new value of index 48 */ 49 static int wlan_roam_next_debug_log_index(qdf_atomic_t *index, int size) 50 { 51 int i = qdf_atomic_inc_return(index); 52 53 if (i == WLAN_ROAM_DEBUG_MAX_REC) 54 qdf_atomic_sub(WLAN_ROAM_DEBUG_MAX_REC, index); 55 while (i >= size) 56 i -= WLAN_ROAM_DEBUG_MAX_REC; 57 58 return i; 59 } 60 61 /** 62 * wlan_roam_debug_log() - Add a debug log entry to wlan roam debug records 63 * @vdev_id: vdev identifier 64 * @op: operation identifier 65 * @peer_id: peer id 66 * @mac_addr: mac address of peer, can be NULL 67 * @peer_obj: peer object address, can be NULL 68 * @arg1: extra argument #1 69 * @arg2: extra argument #2 70 * 71 * Return: none 72 */ 73 void wlan_roam_debug_log(uint8_t vdev_id, uint8_t op, 74 uint16_t peer_id, void *mac_addr, 75 void *peer_obj, uint32_t arg1, uint32_t arg2) 76 { 77 uint32_t i; 78 struct wlan_roam_debug_rec *rec; 79 80 i = wlan_roam_next_debug_log_index( 81 &global_wlan_roam_debug_table.index, 82 WLAN_ROAM_DEBUG_MAX_REC); 83 rec = &global_wlan_roam_debug_table.rec[i]; 84 rec->time = qdf_get_log_timestamp(); 85 rec->operation = op; 86 rec->vdev_id = vdev_id; 87 rec->peer_id = peer_id; 88 if (mac_addr) 89 qdf_mem_copy(rec->mac_addr.bytes, mac_addr, 90 QDF_MAC_ADDR_SIZE); 91 else 92 qdf_mem_zero(rec->mac_addr.bytes, 93 QDF_MAC_ADDR_SIZE); 94 rec->peer_obj = peer_obj; 95 rec->arg1 = arg1; 96 rec->arg2 = arg2; 97 } 98 qdf_export_symbol(wlan_roam_debug_log); 99 100 /** 101 * wlan_roam_debug_string() - convert operation value to printable string 102 * @op: operation identifier 103 * 104 * Return: printable string for the operation 105 */ 106 static char *wlan_roam_debug_string(uint32_t op) 107 { 108 switch (op) { 109 case DEBUG_PEER_CREATE_SEND: 110 return "peer create send"; 111 case DEBUG_PEER_CREATE_RESP: 112 return "peer create resp_event"; 113 case DEBUG_PEER_DELETE_SEND: 114 return "peer delete send"; 115 case DEBUG_PEER_DELETE_RESP: 116 return "peer delete resp_event"; 117 case DEBUG_PEER_MAP_EVENT: 118 return "peer map event"; 119 case DEBUG_PEER_UNMAP_EVENT: 120 return "peer unmap event"; 121 case DEBUG_PEER_UNREF_DELETE: 122 return "peer unref delete"; 123 case DEBUG_DELETING_PEER_OBJ: 124 return "peer obj deleted"; 125 case DEBUG_ROAM_SYNCH_IND: 126 return "roam synch ind event"; 127 case DEBUG_ROAM_SYNCH_CNF: 128 return "roam sync conf sent"; 129 case DEBUG_ROAM_SYNCH_FAIL: 130 return "roam sync fail event"; 131 case DEBUG_ROAM_EVENT: 132 return "roam event"; 133 case DEBUG_WOW_ROAM_EVENT: 134 return "wow wakeup roam event"; 135 case DEBUG_BUS_SUSPEND: 136 return "host suspend"; 137 case DEBUG_BUS_RESUME: 138 return "host wakeup"; 139 case DEBUG_WOW_REASON: 140 return "wow wakeup reason"; 141 default: 142 return "unknown"; 143 } 144 } 145 146 /** 147 * wlan_roam_debug_dump_table() - Print the wlan roam debug log records 148 * print all the valid debug records in the order of timestamp 149 * 150 * Return: none 151 */ 152 void wlan_roam_debug_dump_table(void) 153 { 154 uint32_t i; 155 int32_t current_index; 156 struct wlan_roam_debug_rec *dbg_rec; 157 uint64_t startt = 0; 158 uint32_t delta; 159 160 #define DEBUG_CLOCK_TICKS_PER_MSEC 19200 161 162 current_index = qdf_atomic_read(&global_wlan_roam_debug_table.index); 163 if (current_index < 0) { 164 QDF_TRACE(QDF_MODULE_ID_ROAM_DEBUG, QDF_TRACE_LEVEL_ERROR, 165 "%s: No records to dump", __func__); 166 return; 167 } 168 QDF_TRACE(QDF_MODULE_ID_ROAM_DEBUG, QDF_TRACE_LEVEL_ERROR, 169 "%s: Dumping all records. current index %d", 170 __func__, current_index); 171 172 i = current_index; 173 do { 174 /* wrap around */ 175 i = (i + 1) % WLAN_ROAM_DEBUG_MAX_REC; 176 dbg_rec = &global_wlan_roam_debug_table.rec[i]; 177 /* skip unused entry */ 178 if (dbg_rec->time == 0) 179 continue; 180 if (startt == 0) 181 startt = dbg_rec->time; 182 183 /* 184 * Divide by 19200 == right shift 8 bits, then divide by 75 185 * 32 bit computation keeps both 32 and 64 bit compilers happy. 186 * The value will roll over after approx. 33554 seconds. 187 */ 188 delta = (uint32_t) (((dbg_rec->time - startt) >> 8) & 189 0xffffffff); 190 delta = delta / (DEBUG_CLOCK_TICKS_PER_MSEC >> 8); 191 192 QDF_TRACE(QDF_MODULE_ID_ROAM_DEBUG, QDF_TRACE_LEVEL_ERROR, 193 "index = %5d timestamp = 0x%016llx delta ms = %-12u", 194 i, dbg_rec->time, delta); 195 QDF_TRACE(QDF_MODULE_ID_ROAM_DEBUG, QDF_TRACE_LEVEL_ERROR, 196 "info = %-24s vdev_id = %-3d mac addr = %pM", 197 wlan_roam_debug_string(dbg_rec->operation), 198 (int8_t) dbg_rec->vdev_id, dbg_rec->mac_addr.bytes); 199 QDF_TRACE(QDF_MODULE_ID_ROAM_DEBUG, QDF_TRACE_LEVEL_ERROR, 200 "peer obj = 0x%pK peer_id = %-4d", 201 dbg_rec->peer_obj, (int8_t) dbg_rec->peer_id); 202 QDF_TRACE(QDF_MODULE_ID_ROAM_DEBUG, QDF_TRACE_LEVEL_ERROR, 203 "arg1 = 0x%-8x arg2 = 0x%-8x", 204 dbg_rec->arg1, dbg_rec->arg2); 205 } while (i != current_index); 206 } 207 qdf_export_symbol(global_wlan_roam_debug_table); 208 209 210 211