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 struct ser_history *history_info; 121 struct ser_data *data; 122 123 history_info = &pdev_queue->history; 124 125 if (!history_info->index) 126 return; 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 < history_info->index; idx++) { 135 data = &history_info->data[idx]; 136 137 if (data->ser_reason >= SER_QUEUE_ACTION_MAX) { 138 ser_err("Invalid Serialization Reason"); 139 continue; 140 } 141 142 if (for_vdev_queue) { 143 if (vdev_id != data->vdev_id) 144 continue; 145 } 146 ser_err_no_fl( 147 "%8d|%6d|%7d|%8d|%8d|%6s|%7s|%17s|", 148 data->cmd_type, 149 data->cmd_id, 150 data->vdev_id, 151 data->is_blocking, 152 data->is_high_priority, 153 data->add_remove ? "ADD" : "REMOVE", 154 data->active_pending ? "ACTIVE" : "PENDING", 155 ser_reason_string[data->ser_reason]); 156 } 157 } 158 159 QDF_STATUS wlan_ser_print_history( 160 struct wlan_objmgr_vdev *vdev, uint8_t val, 161 uint32_t sub_val) 162 { 163 struct wlan_ser_pdev_obj *ser_pdev; 164 struct wlan_ser_vdev_obj *ser_vdev; 165 struct wlan_serialization_pdev_queue *pdev_q; 166 struct wlan_serialization_vdev_queue *vdev_q; 167 bool for_vdev_queue = false; 168 uint32_t vdev_id; 169 170 ser_pdev = wlan_serialization_get_pdev_obj( 171 wlan_vdev_get_pdev(vdev)); 172 173 ser_vdev = wlan_serialization_get_vdev_obj(vdev); 174 175 switch (val) { 176 /* 177 * Print scan pdev queues 178 */ 179 case SER_PDEV_QUEUE_COMP_SCAN: 180 ser_err_no_fl("Serialization SCAN Queues(LIVE)"); 181 pdev_q = &ser_pdev->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; 182 wlan_ser_print_pdev_queue(pdev_q, WLAN_SER_PDEV_NODE); 183 break; 184 /* 185 * Print non scan queues 186 */ 187 case SER_PDEV_QUEUE_COMP_NON_SCAN: 188 pdev_q = &ser_pdev->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; 189 ser_err_no_fl("Serialization NON SCAN Queues(LIVE)"); 190 switch (sub_val) { 191 /* 192 * Print non scan pdev queues 193 */ 194 case SER_PDEV_QUEUE_TYPE: 195 wlan_ser_print_pdev_queue(pdev_q, WLAN_SER_PDEV_NODE); 196 break; 197 /* 198 * Print non scan pdev queues 199 */ 200 case SER_VDEV_QUEUE_TYPE: 201 vdev_q = 202 &ser_vdev->vdev_q[SER_VDEV_QUEUE_COMP_NON_SCAN]; 203 for_vdev_queue = true; 204 vdev_id = wlan_vdev_get_id(vdev); 205 wlan_ser_print_vdev_queue(vdev_q, WLAN_SER_VDEV_NODE); 206 break; 207 default: 208 ser_err("Invalid parameter for queue type(pdev/vdev)"); 209 } 210 break; 211 default: 212 ser_err("Invalid pramater for queue type(scan/non_scan"); 213 goto error; 214 } 215 216 wlan_ser_print_all_history(pdev_q, for_vdev_queue, vdev_id); 217 error: 218 return QDF_STATUS_SUCCESS; 219 } 220 221 void wlan_ser_update_cmd_history( 222 struct wlan_serialization_pdev_queue *pdev_queue, 223 struct wlan_serialization_command *cmd, 224 enum ser_queue_reason ser_reason, 225 bool add_remove, 226 bool active_queue) 227 { 228 struct ser_data *ser_data_info; 229 struct ser_history *ser_history_info; 230 231 ser_history_info = &pdev_queue->history; 232 ser_history_info->index %= SER_MAX_HISTORY_CMDS; 233 234 ser_data_info = &ser_history_info->data[ser_history_info->index]; 235 236 ser_data_info->cmd_type = cmd->cmd_type; 237 ser_data_info->cmd_id = cmd->cmd_id; 238 ser_data_info->is_blocking = cmd->is_blocking; 239 ser_data_info->is_high_priority = cmd->is_high_priority; 240 ser_data_info->add_remove = add_remove; 241 ser_data_info->active_pending = active_queue; 242 ser_data_info->ser_reason = ser_reason; 243 ser_data_info->vdev_id = wlan_vdev_get_id(cmd->vdev); 244 245 ser_history_info->index++; 246 } 247 #endif 248