1 /* 2 * Copyright (c) 2018-2020 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 * DOC: wlan_serialization_debug.c 20 * This file defines the debug functions for serialization component. 21 */ 22 23 #include <wlan_objmgr_vdev_obj.h> 24 #include <wlan_objmgr_pdev_obj.h> 25 #include <wlan_utility.h> 26 #include "wlan_serialization_utils_i.h" 27 #include "wlan_serialization_main_i.h" 28 #include "wlan_serialization_queue_i.h" 29 #include "wlan_serialization_debug_i.h" 30 31 #ifdef WLAN_SER_DEBUG 32 const char *ser_reason_string[SER_QUEUE_ACTION_MAX] = { 33 "REQUEST", 34 "REMOVE", 35 "CANCEL", 36 "TIMEOUT", 37 "ACTIVATION_FAILED", 38 "PENDING_TO_ACTIVE", 39 }; 40 41 static void wlan_ser_print_queues( 42 qdf_list_t *queue, 43 enum wlan_serialization_node node_type, 44 bool is_active_queue) 45 { 46 struct wlan_serialization_command_list *cmd_list = NULL; 47 uint32_t queuelen; 48 QDF_STATUS status = QDF_STATUS_E_FAILURE; 49 qdf_list_node_t *nnode = NULL; 50 bool is_pdev_queue = false; 51 52 if (node_type == WLAN_SER_PDEV_NODE) 53 is_pdev_queue = true; 54 55 ser_err_no_fl(WLAN_SER_LINE); 56 ser_err_no_fl("%s %s Queue", (is_pdev_queue) ? "PDEV" : "VDEV", 57 (is_active_queue ? "Active" : "Pending")); 58 59 ser_err_no_fl(WLAN_SER_LINE); 60 ser_err_no_fl("|CMD_TYPE|CMD_ID|VDEV_ID|BLOCKING|PRIORITY|"); 61 ser_err_no_fl(WLAN_SER_LINE); 62 63 queuelen = wlan_serialization_list_size(queue); 64 while (queuelen--) { 65 status = wlan_serialization_get_cmd_from_queue(queue, &nnode); 66 if (status != QDF_STATUS_SUCCESS) 67 break; 68 69 if (node_type == WLAN_SER_PDEV_NODE) 70 cmd_list = qdf_container_of( 71 nnode, 72 struct wlan_serialization_command_list, 73 pdev_node); 74 else 75 cmd_list = qdf_container_of( 76 nnode, 77 struct wlan_serialization_command_list, 78 vdev_node); 79 80 ser_err_no_fl("|%8u|%6u|%6u|%8u|%8u|", 81 cmd_list->cmd.cmd_type, 82 cmd_list->cmd.cmd_id, 83 wlan_vdev_get_id(cmd_list->cmd.vdev), 84 cmd_list->cmd.is_blocking, 85 cmd_list->cmd.is_high_priority); 86 } 87 } 88 89 static void wlan_ser_print_pdev_queue( 90 struct wlan_serialization_pdev_queue *ser_pdev_q_obj, 91 enum wlan_serialization_node node_type) 92 { 93 /*Dump the active queue*/ 94 wlan_ser_print_queues(&ser_pdev_q_obj->active_list, 95 node_type, true); 96 97 /*Dump the pending queue*/ 98 wlan_ser_print_queues(&ser_pdev_q_obj->pending_list, 99 node_type, false); 100 } 101 102 static void wlan_ser_print_vdev_queue( 103 struct wlan_serialization_vdev_queue *ser_vdev_q_obj, 104 enum wlan_serialization_node node_type) 105 { 106 /*Dump the active queue*/ 107 wlan_ser_print_queues(&ser_vdev_q_obj->active_list, 108 node_type, true); 109 110 /*Dump the pending queue*/ 111 wlan_ser_print_queues(&ser_vdev_q_obj->pending_list, 112 node_type, false); 113 } 114 115 static void wlan_ser_print_all_history( 116 struct wlan_serialization_pdev_queue *pdev_queue, 117 bool for_vdev_queue, 118 uint32_t vdev_id) 119 { 120 uint8_t idx; 121 uint8_t data_idx; 122 struct ser_history *history_info; 123 struct ser_data *data; 124 125 history_info = &pdev_queue->history; 126 127 ser_err_no_fl(WLAN_SER_LINE WLAN_SER_LINE); 128 ser_err_no_fl("Queue Commands History"); 129 ser_err_no_fl(WLAN_SER_LINE WLAN_SER_LINE); 130 ser_err_no_fl(WLAN_SER_HISTORY_HEADER); 131 ser_err_no_fl(WLAN_SER_LINE WLAN_SER_LINE); 132 133 for (idx = 0; idx < SER_MAX_HISTORY_CMDS; idx++) { 134 data_idx = (history_info->index + idx) % SER_MAX_HISTORY_CMDS; 135 136 data = &history_info->data[data_idx]; 137 138 if (data->ser_reason >= SER_QUEUE_ACTION_MAX) { 139 ser_debug("Invalid Serialization Reason"); 140 continue; 141 } 142 143 if (!data->data_updated) 144 continue; 145 146 if (for_vdev_queue) { 147 if (vdev_id != data->vdev_id) 148 continue; 149 } 150 ser_err_no_fl( 151 "%8d|%6d|%7d|%8d|%8d|%6s|%7s|%17s|", 152 data->cmd_type, 153 data->cmd_id, 154 data->vdev_id, 155 data->is_blocking, 156 data->is_high_priority, 157 data->add_remove ? "ADD" : "REMOVE", 158 data->active_pending ? "ACTIVE" : "PENDING", 159 ser_reason_string[data->ser_reason]); 160 } 161 } 162 163 QDF_STATUS wlan_ser_print_history( 164 struct wlan_objmgr_vdev *vdev, uint8_t val, 165 uint32_t sub_val) 166 { 167 struct wlan_ser_pdev_obj *ser_pdev; 168 struct wlan_ser_vdev_obj *ser_vdev; 169 struct wlan_serialization_pdev_queue *pdev_q; 170 struct wlan_serialization_vdev_queue *vdev_q; 171 bool for_vdev_queue = false; 172 uint32_t vdev_id = WLAN_INVALID_VDEV_ID; 173 174 ser_pdev = wlan_serialization_get_pdev_obj( 175 wlan_vdev_get_pdev(vdev)); 176 177 ser_vdev = wlan_serialization_get_vdev_obj(vdev); 178 179 switch (val) { 180 /* 181 * Print scan pdev queues 182 */ 183 case SER_PDEV_QUEUE_COMP_SCAN: 184 ser_err_no_fl("Serialization SCAN Queues(LIVE)"); 185 pdev_q = &ser_pdev->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; 186 wlan_ser_print_pdev_queue(pdev_q, WLAN_SER_PDEV_NODE); 187 break; 188 /* 189 * Print non scan queues 190 */ 191 case SER_PDEV_QUEUE_COMP_NON_SCAN: 192 pdev_q = &ser_pdev->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; 193 ser_err_no_fl("Serialization NON SCAN Queues(LIVE)"); 194 switch (sub_val) { 195 /* 196 * Print non scan pdev queues 197 */ 198 case SER_PDEV_QUEUE_TYPE: 199 wlan_ser_print_pdev_queue(pdev_q, WLAN_SER_PDEV_NODE); 200 break; 201 /* 202 * Print non scan pdev queues 203 */ 204 case SER_VDEV_QUEUE_TYPE: 205 vdev_q = 206 &ser_vdev->vdev_q[SER_VDEV_QUEUE_COMP_NON_SCAN]; 207 for_vdev_queue = true; 208 vdev_id = wlan_vdev_get_id(vdev); 209 wlan_ser_print_vdev_queue(vdev_q, WLAN_SER_VDEV_NODE); 210 break; 211 default: 212 ser_err("Invalid parameter for queue type(pdev/vdev)"); 213 } 214 break; 215 default: 216 ser_err("Invalid pramater for queue type(scan/non_scan"); 217 goto error; 218 } 219 220 wlan_ser_print_all_history(pdev_q, for_vdev_queue, vdev_id); 221 error: 222 return QDF_STATUS_SUCCESS; 223 } 224 225 qdf_export_symbol(wlan_ser_print_history); 226 227 void wlan_ser_update_cmd_history( 228 struct wlan_serialization_pdev_queue *pdev_queue, 229 struct wlan_serialization_command *cmd, 230 enum ser_queue_reason ser_reason, 231 bool add_remove, 232 bool active_queue) 233 { 234 struct ser_data *ser_data_info; 235 struct ser_history *ser_history_info; 236 237 ser_history_info = &pdev_queue->history; 238 ser_history_info->index %= SER_MAX_HISTORY_CMDS; 239 240 ser_data_info = &ser_history_info->data[ser_history_info->index]; 241 242 ser_data_info->cmd_type = cmd->cmd_type; 243 ser_data_info->cmd_id = cmd->cmd_id; 244 ser_data_info->is_blocking = cmd->is_blocking; 245 ser_data_info->is_high_priority = cmd->is_high_priority; 246 ser_data_info->add_remove = add_remove; 247 ser_data_info->active_pending = active_queue; 248 ser_data_info->ser_reason = ser_reason; 249 ser_data_info->vdev_id = wlan_vdev_get_id(cmd->vdev); 250 ser_data_info->data_updated = true; 251 252 ser_history_info->index++; 253 } 254 #endif 255