1 /* 2 * Copyright (c) 2018-2019 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|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|%8u|%8u|", 81 cmd_list->cmd.cmd_type, 82 cmd_list->cmd.cmd_id, 83 cmd_list->cmd.is_blocking, 84 cmd_list->cmd.is_high_priority); 85 } 86 } 87 88 static void wlan_ser_print_pdev_queue( 89 struct wlan_serialization_pdev_queue *ser_pdev_q_obj, 90 enum wlan_serialization_node node_type) 91 { 92 /*Dump the active queue*/ 93 wlan_ser_print_queues(&ser_pdev_q_obj->active_list, 94 node_type, true); 95 96 /*Dump the pending queue*/ 97 wlan_ser_print_queues(&ser_pdev_q_obj->pending_list, 98 node_type, false); 99 } 100 101 static void wlan_ser_print_vdev_queue( 102 struct wlan_serialization_vdev_queue *ser_vdev_q_obj, 103 enum wlan_serialization_node node_type) 104 { 105 /*Dump the active queue*/ 106 wlan_ser_print_queues(&ser_vdev_q_obj->active_list, 107 node_type, true); 108 109 /*Dump the pending queue*/ 110 wlan_ser_print_queues(&ser_vdev_q_obj->pending_list, 111 node_type, false); 112 } 113 114 static void wlan_ser_print_all_history( 115 struct wlan_serialization_pdev_queue *pdev_queue, 116 bool for_vdev_queue, 117 uint32_t vdev_id) 118 { 119 uint8_t idx; 120 uint8_t data_idx; 121 struct ser_history *history_info; 122 struct ser_data *data; 123 124 history_info = &pdev_queue->history; 125 126 ser_err_no_fl(WLAN_SER_LINE WLAN_SER_LINE); 127 ser_err_no_fl("Queue Commands History"); 128 ser_err_no_fl(WLAN_SER_LINE WLAN_SER_LINE); 129 ser_err_no_fl(WLAN_SER_HISTORY_HEADER); 130 ser_err_no_fl(WLAN_SER_LINE WLAN_SER_LINE); 131 132 for (idx = 0; idx < SER_MAX_HISTORY_CMDS; idx++) { 133 data_idx = (history_info->index + idx) % SER_MAX_HISTORY_CMDS; 134 135 data = &history_info->data[data_idx]; 136 137 if (data->ser_reason >= SER_QUEUE_ACTION_MAX) { 138 ser_debug("Invalid Serialization Reason"); 139 continue; 140 } 141 142 if (!data->data_updated) 143 continue; 144 145 if (for_vdev_queue) { 146 if (vdev_id != data->vdev_id) 147 continue; 148 } 149 ser_err_no_fl( 150 "%8d|%6d|%7d|%8d|%8d|%6s|%7s|%17s|", 151 data->cmd_type, 152 data->cmd_id, 153 data->vdev_id, 154 data->is_blocking, 155 data->is_high_priority, 156 data->add_remove ? "ADD" : "REMOVE", 157 data->active_pending ? "ACTIVE" : "PENDING", 158 ser_reason_string[data->ser_reason]); 159 } 160 } 161 162 QDF_STATUS wlan_ser_print_history( 163 struct wlan_objmgr_vdev *vdev, uint8_t val, 164 uint32_t sub_val) 165 { 166 struct wlan_ser_pdev_obj *ser_pdev; 167 struct wlan_ser_vdev_obj *ser_vdev; 168 struct wlan_serialization_pdev_queue *pdev_q; 169 struct wlan_serialization_vdev_queue *vdev_q; 170 bool for_vdev_queue = false; 171 uint32_t vdev_id = WLAN_INVALID_VDEV_ID; 172 173 ser_pdev = wlan_serialization_get_pdev_obj( 174 wlan_vdev_get_pdev(vdev)); 175 176 ser_vdev = wlan_serialization_get_vdev_obj(vdev); 177 178 switch (val) { 179 /* 180 * Print scan pdev queues 181 */ 182 case SER_PDEV_QUEUE_COMP_SCAN: 183 ser_err_no_fl("Serialization SCAN Queues(LIVE)"); 184 pdev_q = &ser_pdev->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; 185 wlan_ser_print_pdev_queue(pdev_q, WLAN_SER_PDEV_NODE); 186 break; 187 /* 188 * Print non scan queues 189 */ 190 case SER_PDEV_QUEUE_COMP_NON_SCAN: 191 pdev_q = &ser_pdev->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; 192 ser_err_no_fl("Serialization NON SCAN Queues(LIVE)"); 193 switch (sub_val) { 194 /* 195 * Print non scan pdev queues 196 */ 197 case SER_PDEV_QUEUE_TYPE: 198 wlan_ser_print_pdev_queue(pdev_q, WLAN_SER_PDEV_NODE); 199 break; 200 /* 201 * Print non scan pdev queues 202 */ 203 case SER_VDEV_QUEUE_TYPE: 204 vdev_q = 205 &ser_vdev->vdev_q[SER_VDEV_QUEUE_COMP_NON_SCAN]; 206 for_vdev_queue = true; 207 vdev_id = wlan_vdev_get_id(vdev); 208 wlan_ser_print_vdev_queue(vdev_q, WLAN_SER_VDEV_NODE); 209 break; 210 default: 211 ser_err("Invalid parameter for queue type(pdev/vdev)"); 212 } 213 break; 214 default: 215 ser_err("Invalid pramater for queue type(scan/non_scan"); 216 goto error; 217 } 218 219 wlan_ser_print_all_history(pdev_q, for_vdev_queue, vdev_id); 220 error: 221 return QDF_STATUS_SUCCESS; 222 } 223 224 qdf_export_symbol(wlan_ser_print_history); 225 226 void wlan_ser_update_cmd_history( 227 struct wlan_serialization_pdev_queue *pdev_queue, 228 struct wlan_serialization_command *cmd, 229 enum ser_queue_reason ser_reason, 230 bool add_remove, 231 bool active_queue) 232 { 233 struct ser_data *ser_data_info; 234 struct ser_history *ser_history_info; 235 236 ser_history_info = &pdev_queue->history; 237 ser_history_info->index %= SER_MAX_HISTORY_CMDS; 238 239 ser_data_info = &ser_history_info->data[ser_history_info->index]; 240 241 ser_data_info->cmd_type = cmd->cmd_type; 242 ser_data_info->cmd_id = cmd->cmd_id; 243 ser_data_info->is_blocking = cmd->is_blocking; 244 ser_data_info->is_high_priority = cmd->is_high_priority; 245 ser_data_info->add_remove = add_remove; 246 ser_data_info->active_pending = active_queue; 247 ser_data_info->ser_reason = ser_reason; 248 ser_data_info->vdev_id = wlan_vdev_get_id(cmd->vdev); 249 ser_data_info->data_updated = true; 250 251 ser_history_info->index++; 252 } 253 #endif 254