1 /* 2 * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 /** 20 * DOC: wlan_serialization_debug.c 21 * This file defines the debug functions for serialization component. 22 */ 23 24 #include <wlan_objmgr_vdev_obj.h> 25 #include <wlan_objmgr_pdev_obj.h> 26 #include <wlan_utility.h> 27 #include "wlan_serialization_utils_i.h" 28 #include "wlan_serialization_main_i.h" 29 #include "wlan_serialization_queue_i.h" 30 #include "wlan_serialization_debug_i.h" 31 32 #ifdef WLAN_SER_DEBUG 33 const char *ser_reason_string[SER_QUEUE_ACTION_MAX] = { 34 "REQUEST", 35 "REMOVE", 36 "CANCEL", 37 "TIMEOUT", 38 "ACTIVATION_FAILED", 39 "PENDING_TO_ACTIVE", 40 }; 41 42 static void wlan_ser_print_queues( 43 qdf_list_t *queue, 44 enum wlan_serialization_node node_type, 45 bool is_active_queue) 46 { 47 struct wlan_serialization_command_list *cmd_list = NULL; 48 uint32_t queuelen; 49 QDF_STATUS status = QDF_STATUS_E_FAILURE; 50 qdf_list_node_t *nnode = NULL; 51 bool is_pdev_queue = false; 52 53 if (node_type == WLAN_SER_PDEV_NODE) 54 is_pdev_queue = true; 55 56 ser_err_no_fl(WLAN_SER_LINE); 57 ser_err_no_fl("%s %s Queue", (is_pdev_queue) ? "PDEV" : "VDEV", 58 (is_active_queue ? "Active" : "Pending")); 59 60 ser_err_no_fl(WLAN_SER_LINE); 61 ser_err_no_fl("|CMD_TYPE|CMD_ID|VDEV_ID|BLOCKING|PRIORITY|"); 62 ser_err_no_fl(WLAN_SER_LINE); 63 64 queuelen = wlan_serialization_list_size(queue); 65 while (queuelen--) { 66 status = wlan_serialization_get_cmd_from_queue(queue, &nnode); 67 if (status != QDF_STATUS_SUCCESS) 68 break; 69 70 if (node_type == WLAN_SER_PDEV_NODE) 71 cmd_list = qdf_container_of( 72 nnode, 73 struct wlan_serialization_command_list, 74 pdev_node); 75 else 76 cmd_list = qdf_container_of( 77 nnode, 78 struct wlan_serialization_command_list, 79 vdev_node); 80 81 ser_err_no_fl("|%8u|%6u|%6u|%8u|%8u|", 82 cmd_list->cmd.cmd_type, 83 cmd_list->cmd.cmd_id, 84 wlan_vdev_get_id(cmd_list->cmd.vdev), 85 cmd_list->cmd.is_blocking, 86 cmd_list->cmd.is_high_priority); 87 } 88 } 89 90 static void wlan_ser_print_pdev_queue( 91 struct wlan_serialization_pdev_queue *ser_pdev_q_obj, 92 enum wlan_serialization_node node_type) 93 { 94 /*Dump the active queue*/ 95 wlan_ser_print_queues(&ser_pdev_q_obj->active_list, 96 node_type, true); 97 98 /*Dump the pending queue*/ 99 wlan_ser_print_queues(&ser_pdev_q_obj->pending_list, 100 node_type, false); 101 } 102 103 static void wlan_ser_print_vdev_queue( 104 struct wlan_serialization_vdev_queue *ser_vdev_q_obj, 105 enum wlan_serialization_node node_type) 106 { 107 /*Dump the active queue*/ 108 wlan_ser_print_queues(&ser_vdev_q_obj->active_list, 109 node_type, true); 110 111 /*Dump the pending queue*/ 112 wlan_ser_print_queues(&ser_vdev_q_obj->pending_list, 113 node_type, false); 114 } 115 116 static void wlan_ser_print_all_history( 117 struct wlan_serialization_pdev_queue *pdev_queue, 118 bool for_vdev_queue, 119 uint32_t vdev_id) 120 { 121 uint8_t idx; 122 uint8_t data_idx; 123 struct ser_history *history_info; 124 struct ser_data *data; 125 126 history_info = &pdev_queue->history; 127 128 ser_err_no_fl(WLAN_SER_LINE WLAN_SER_LINE); 129 ser_err_no_fl("Queue Commands History"); 130 ser_err_no_fl(WLAN_SER_LINE WLAN_SER_LINE); 131 ser_err_no_fl(WLAN_SER_HISTORY_HEADER); 132 ser_err_no_fl(WLAN_SER_LINE WLAN_SER_LINE); 133 134 for (idx = 0; idx < SER_MAX_HISTORY_CMDS; idx++) { 135 data_idx = (history_info->index + idx) % SER_MAX_HISTORY_CMDS; 136 137 data = &history_info->data[data_idx]; 138 139 if (data->ser_reason >= SER_QUEUE_ACTION_MAX) { 140 ser_debug("Invalid Serialization Reason"); 141 continue; 142 } 143 144 if (!data->data_updated) 145 continue; 146 147 if (for_vdev_queue) { 148 if (vdev_id != data->vdev_id) 149 continue; 150 } 151 ser_err_no_fl( 152 "|0x%016llx|%8d|%6d|%7d|%8d|%8d|%6s|%7s|%17s|", 153 data->time, 154 data->cmd_type, 155 data->cmd_id, 156 data->vdev_id, 157 data->is_blocking, 158 data->is_high_priority, 159 data->add_remove ? "ADD" : "REMOVE", 160 data->active_pending ? "ACTIVE" : "PENDING", 161 ser_reason_string[data->ser_reason]); 162 } 163 } 164 165 QDF_STATUS wlan_ser_print_history( 166 struct wlan_objmgr_vdev *vdev, uint8_t val, 167 uint32_t sub_val) 168 { 169 struct wlan_ser_pdev_obj *ser_pdev; 170 struct wlan_ser_vdev_obj *ser_vdev; 171 struct wlan_serialization_pdev_queue *pdev_q; 172 struct wlan_serialization_vdev_queue *vdev_q; 173 bool for_vdev_queue = false; 174 uint32_t vdev_id = WLAN_INVALID_VDEV_ID; 175 176 ser_pdev = wlan_serialization_get_pdev_obj( 177 wlan_vdev_get_pdev(vdev)); 178 179 ser_vdev = wlan_serialization_get_vdev_obj(vdev); 180 181 switch (val) { 182 /* 183 * Print scan pdev queues 184 */ 185 case SER_PDEV_QUEUE_COMP_SCAN: 186 ser_err_no_fl("Serialization SCAN Queues(LIVE)"); 187 pdev_q = &ser_pdev->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; 188 wlan_ser_print_pdev_queue(pdev_q, WLAN_SER_PDEV_NODE); 189 break; 190 /* 191 * Print non scan queues 192 */ 193 case SER_PDEV_QUEUE_COMP_NON_SCAN: 194 pdev_q = &ser_pdev->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; 195 ser_err_no_fl("Serialization NON SCAN Queues(LIVE)"); 196 switch (sub_val) { 197 /* 198 * Print non scan pdev queues 199 */ 200 case SER_PDEV_QUEUE_TYPE: 201 wlan_ser_print_pdev_queue(pdev_q, WLAN_SER_PDEV_NODE); 202 break; 203 /* 204 * Print non scan pdev queues 205 */ 206 case SER_VDEV_QUEUE_TYPE: 207 vdev_q = 208 &ser_vdev->vdev_q[SER_VDEV_QUEUE_COMP_NON_SCAN]; 209 for_vdev_queue = true; 210 vdev_id = wlan_vdev_get_id(vdev); 211 wlan_ser_print_vdev_queue(vdev_q, WLAN_SER_VDEV_NODE); 212 break; 213 default: 214 ser_err("Invalid parameter for queue type(pdev/vdev)"); 215 } 216 break; 217 default: 218 ser_err("Invalid pramater for queue type(scan/non_scan"); 219 goto error; 220 } 221 222 wlan_ser_print_all_history(pdev_q, for_vdev_queue, vdev_id); 223 error: 224 return QDF_STATUS_SUCCESS; 225 } 226 227 qdf_export_symbol(wlan_ser_print_history); 228 229 void wlan_ser_update_cmd_history( 230 struct wlan_serialization_pdev_queue *pdev_queue, 231 struct wlan_serialization_command *cmd, 232 enum ser_queue_reason ser_reason, 233 bool add_remove, 234 bool active_queue) 235 { 236 struct ser_data *ser_data_info; 237 struct ser_history *ser_history_info; 238 239 ser_history_info = &pdev_queue->history; 240 ser_history_info->index %= SER_MAX_HISTORY_CMDS; 241 242 ser_data_info = &ser_history_info->data[ser_history_info->index]; 243 244 ser_data_info->cmd_type = cmd->cmd_type; 245 ser_data_info->cmd_id = cmd->cmd_id; 246 ser_data_info->is_blocking = cmd->is_blocking; 247 ser_data_info->is_high_priority = cmd->is_high_priority; 248 ser_data_info->add_remove = add_remove; 249 ser_data_info->active_pending = active_queue; 250 ser_data_info->ser_reason = ser_reason; 251 ser_data_info->vdev_id = wlan_vdev_get_id(cmd->vdev); 252 ser_data_info->data_updated = true; 253 ser_data_info->time = qdf_get_log_timestamp(); 254 255 ser_history_info->index++; 256 } 257 #endif 258