1 /* 2 * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved. 3 * 4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc. 5 * 6 * 7 * Permission to use, copy, modify, and/or distribute this software for 8 * any purpose with or without fee is hereby granted, provided that the 9 * above copyright notice and this permission notice appear in all 10 * copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 19 * PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 /* 23 * This file was originally distributed by Qualcomm Atheros, Inc. 24 * under proprietary terms before Copyright ownership was assigned 25 * to the Linux Foundation. 26 */ 27 28 /* 29 * Host WMI unified implementation 30 */ 31 #include "athdefs.h" 32 #include "osapi_linux.h" 33 #include "a_types.h" 34 #include "a_debug.h" 35 #include "ol_if_athvar.h" 36 #include "ol_defines.h" 37 #include "htc_api.h" 38 #include "htc_api.h" 39 #include "dbglog_host.h" 40 #include "wmi_unified_priv.h" 41 #include "wmi_unified_param.h" 42 43 #ifndef WMI_NON_TLV_SUPPORT 44 #include "wmi_tlv_helper.h" 45 #endif 46 47 #include <linux/debugfs.h> 48 49 /* This check for CONFIG_WIN temporary added due to redeclaration compilation 50 error in MCL. Error is caused due to inclusion of wmi.h in wmi_unified_api.h 51 which gets included here through ol_if_athvar.h. Eventually it is expected that 52 wmi.h will be removed from wmi_unified_api.h after cleanup, which will need 53 WMI_CMD_HDR to be defined here. */ 54 #ifdef CONFIG_WIN 55 /* Copied from wmi.h */ 56 #undef MS 57 #define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB) 58 #undef SM 59 #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK) 60 #undef WO 61 #define WO(_f) ((_f##_OFFSET) >> 2) 62 63 #undef GET_FIELD 64 #define GET_FIELD(_addr, _f) MS(*((A_UINT32 *)(_addr) + WO(_f)), _f) 65 #undef SET_FIELD 66 #define SET_FIELD(_addr, _f, _val) \ 67 (*((A_UINT32 *)(_addr) + WO(_f)) = \ 68 (*((A_UINT32 *)(_addr) + WO(_f)) & ~_f##_MASK) | SM(_val, _f)) 69 70 #define WMI_GET_FIELD(_msg_buf, _msg_type, _f) \ 71 GET_FIELD(_msg_buf, _msg_type ## _ ## _f) 72 73 #define WMI_SET_FIELD(_msg_buf, _msg_type, _f, _val) \ 74 SET_FIELD(_msg_buf, _msg_type ## _ ## _f, _val) 75 76 #define WMI_EP_APASS 0x0 77 #define WMI_EP_LPASS 0x1 78 #define WMI_EP_SENSOR 0x2 79 80 /* 81 * * Control Path 82 * */ 83 typedef PREPACK struct { 84 A_UINT32 commandId:24, 85 reserved:2, /* used for WMI endpoint ID */ 86 plt_priv:6; /* platform private */ 87 } POSTPACK WMI_CMD_HDR; /* used for commands and events */ 88 89 #define WMI_CMD_HDR_COMMANDID_LSB 0 90 #define WMI_CMD_HDR_COMMANDID_MASK 0x00ffffff 91 #define WMI_CMD_HDR_COMMANDID_OFFSET 0x00000000 92 #define WMI_CMD_HDR_WMI_ENDPOINTID_MASK 0x03000000 93 #define WMI_CMD_HDR_WMI_ENDPOINTID_OFFSET 24 94 #define WMI_CMD_HDR_PLT_PRIV_LSB 24 95 #define WMI_CMD_HDR_PLT_PRIV_MASK 0xff000000 96 #define WMI_CMD_HDR_PLT_PRIV_OFFSET 0x00000000 97 /* end of copy wmi.h */ 98 #endif /* CONFIG_WIN */ 99 100 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)) 101 /* TODO Cleanup this backported function */ 102 static int qcacld_bp_seq_printf(struct seq_file *m, const char *f, ...) 103 { 104 va_list args; 105 106 va_start(args, f); 107 seq_printf(m, f, args); 108 va_end(args); 109 110 return m->count; 111 } 112 113 #define seq_printf(m, fmt, ...) qcacld_bp_seq_printf((m), fmt, ##__VA_ARGS__) 114 #endif 115 116 #define WMI_MIN_HEAD_ROOM 64 117 118 #ifdef WMI_INTERFACE_EVENT_LOGGING 119 #ifndef MAX_WMI_INSTANCES 120 #ifdef CONFIG_MCL 121 #define MAX_WMI_INSTANCES 1 122 #else 123 #define MAX_WMI_INSTANCES 3 124 #endif 125 #define CUSTOM_MGMT_CMD_DATA_SIZE 4 126 #endif 127 128 #ifdef CONFIG_MCL 129 /* WMI commands */ 130 uint32_t g_wmi_command_buf_idx = 0; 131 struct wmi_command_debug wmi_command_log_buffer[WMI_EVENT_DEBUG_MAX_ENTRY]; 132 133 /* WMI commands TX completed */ 134 uint32_t g_wmi_command_tx_cmp_buf_idx = 0; 135 struct wmi_command_debug 136 wmi_command_tx_cmp_log_buffer[WMI_EVENT_DEBUG_MAX_ENTRY]; 137 138 /* WMI events when processed */ 139 uint32_t g_wmi_event_buf_idx = 0; 140 struct wmi_event_debug wmi_event_log_buffer[WMI_EVENT_DEBUG_MAX_ENTRY]; 141 142 /* WMI events when queued */ 143 uint32_t g_wmi_rx_event_buf_idx = 0; 144 struct wmi_event_debug wmi_rx_event_log_buffer[WMI_EVENT_DEBUG_MAX_ENTRY]; 145 #endif 146 147 #define WMI_COMMAND_RECORD(h, a, b) { \ 148 if (wmi_log_max_entry <= \ 149 *(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx)) \ 150 *(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx) = 0;\ 151 ((struct wmi_command_debug *)h->log_info.wmi_command_log_buf_info.buf)\ 152 [*(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx)]\ 153 .command = a; \ 154 qdf_mem_copy(((struct wmi_command_debug *)h->log_info. \ 155 wmi_command_log_buf_info.buf) \ 156 [*(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx)].data,\ 157 b, wmi_record_max_length); \ 158 ((struct wmi_command_debug *)h->log_info.wmi_command_log_buf_info.buf)\ 159 [*(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx)].\ 160 time = qdf_get_log_timestamp(); \ 161 (*(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx))++; \ 162 h->log_info.wmi_command_log_buf_info.length++; \ 163 } 164 165 #define WMI_COMMAND_TX_CMP_RECORD(h, a, b) { \ 166 if (wmi_log_max_entry <= \ 167 *(h->log_info.wmi_command_tx_cmp_log_buf_info.p_buf_tail_idx))\ 168 *(h->log_info.wmi_command_tx_cmp_log_buf_info. \ 169 p_buf_tail_idx) = 0; \ 170 ((struct wmi_command_debug *)h->log_info. \ 171 wmi_command_tx_cmp_log_buf_info.buf) \ 172 [*(h->log_info.wmi_command_tx_cmp_log_buf_info. \ 173 p_buf_tail_idx)]. \ 174 command = a; \ 175 qdf_mem_copy(((struct wmi_command_debug *)h->log_info. \ 176 wmi_command_tx_cmp_log_buf_info.buf) \ 177 [*(h->log_info.wmi_command_tx_cmp_log_buf_info. \ 178 p_buf_tail_idx)]. \ 179 data, b, wmi_record_max_length); \ 180 ((struct wmi_command_debug *)h->log_info. \ 181 wmi_command_tx_cmp_log_buf_info.buf) \ 182 [*(h->log_info.wmi_command_tx_cmp_log_buf_info. \ 183 p_buf_tail_idx)]. \ 184 time = qdf_get_log_timestamp(); \ 185 (*(h->log_info.wmi_command_tx_cmp_log_buf_info.p_buf_tail_idx))++;\ 186 h->log_info.wmi_command_tx_cmp_log_buf_info.length++; \ 187 } 188 189 #define WMI_EVENT_RECORD(h, a, b) { \ 190 if (wmi_log_max_entry <= \ 191 *(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx)) \ 192 *(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx) = 0;\ 193 ((struct wmi_event_debug *)h->log_info.wmi_event_log_buf_info.buf)\ 194 [*(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx)]. \ 195 event = a; \ 196 qdf_mem_copy(((struct wmi_event_debug *)h->log_info. \ 197 wmi_event_log_buf_info.buf) \ 198 [*(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx)].data, b,\ 199 wmi_record_max_length); \ 200 ((struct wmi_event_debug *)h->log_info.wmi_event_log_buf_info.buf)\ 201 [*(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx)].time =\ 202 qdf_get_log_timestamp(); \ 203 (*(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx))++; \ 204 h->log_info.wmi_event_log_buf_info.length++; \ 205 } 206 207 #define WMI_RX_EVENT_RECORD(h, a, b) { \ 208 if (wmi_log_max_entry <= \ 209 *(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx))\ 210 *(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx) = 0;\ 211 ((struct wmi_event_debug *)h->log_info.wmi_rx_event_log_buf_info.buf)\ 212 [*(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx)].\ 213 event = a; \ 214 qdf_mem_copy(((struct wmi_event_debug *)h->log_info. \ 215 wmi_rx_event_log_buf_info.buf) \ 216 [*(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx)].\ 217 data, b, wmi_record_max_length); \ 218 ((struct wmi_event_debug *)h->log_info.wmi_rx_event_log_buf_info.buf)\ 219 [*(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx)].\ 220 time = qdf_get_log_timestamp(); \ 221 (*(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx))++; \ 222 h->log_info.wmi_rx_event_log_buf_info.length++; \ 223 } 224 225 #ifdef CONFIG_MCL 226 uint32_t g_wmi_mgmt_command_buf_idx = 0; 227 struct 228 wmi_command_debug wmi_mgmt_command_log_buffer[WMI_MGMT_EVENT_DEBUG_MAX_ENTRY]; 229 230 /* wmi_mgmt commands TX completed */ 231 uint32_t g_wmi_mgmt_command_tx_cmp_buf_idx = 0; 232 struct wmi_command_debug 233 wmi_mgmt_command_tx_cmp_log_buffer[WMI_MGMT_EVENT_DEBUG_MAX_ENTRY]; 234 235 /* wmi_mgmt events when processed */ 236 uint32_t g_wmi_mgmt_event_buf_idx = 0; 237 struct wmi_event_debug 238 wmi_mgmt_event_log_buffer[WMI_MGMT_EVENT_DEBUG_MAX_ENTRY]; 239 #endif 240 241 #define WMI_MGMT_COMMAND_RECORD(h, a, b) { \ 242 if (wmi_mgmt_log_max_entry <= \ 243 *(h->log_info.wmi_mgmt_command_log_buf_info.p_buf_tail_idx)) \ 244 *(h->log_info.wmi_mgmt_command_log_buf_info. \ 245 p_buf_tail_idx) = 0; \ 246 ((struct wmi_command_debug *)h->log_info. \ 247 wmi_mgmt_command_log_buf_info.buf) \ 248 [*(h->log_info.wmi_mgmt_command_log_buf_info.p_buf_tail_idx)].\ 249 command = a; \ 250 qdf_mem_copy(((struct wmi_command_debug *)h->log_info. \ 251 wmi_mgmt_command_log_buf_info.buf) \ 252 [*(h->log_info.wmi_mgmt_command_log_buf_info.p_buf_tail_idx)].\ 253 data, b, \ 254 wmi_record_max_length); \ 255 ((struct wmi_command_debug *)h->log_info. \ 256 wmi_mgmt_command_log_buf_info.buf) \ 257 [*(h->log_info.wmi_mgmt_command_log_buf_info.p_buf_tail_idx)].\ 258 time = qdf_get_log_timestamp(); \ 259 (*(h->log_info.wmi_mgmt_command_log_buf_info.p_buf_tail_idx))++;\ 260 h->log_info.wmi_mgmt_command_log_buf_info.length++; \ 261 } 262 263 #define WMI_MGMT_COMMAND_TX_CMP_RECORD(h, a, b) { \ 264 if (wmi_mgmt_log_max_entry <= \ 265 *(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info. \ 266 p_buf_tail_idx)) \ 267 *(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info. \ 268 p_buf_tail_idx) = 0; \ 269 ((struct wmi_command_debug *)h->log_info. \ 270 wmi_mgmt_command_tx_cmp_log_buf_info.buf) \ 271 [*(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info. \ 272 p_buf_tail_idx)].command = a; \ 273 qdf_mem_copy(((struct wmi_command_debug *)h->log_info. \ 274 wmi_mgmt_command_tx_cmp_log_buf_info.buf)\ 275 [*(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info. \ 276 p_buf_tail_idx)].data, b, \ 277 wmi_record_max_length); \ 278 ((struct wmi_command_debug *)h->log_info. \ 279 wmi_mgmt_command_tx_cmp_log_buf_info.buf) \ 280 [*(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info. \ 281 p_buf_tail_idx)].time = \ 282 qdf_get_log_timestamp(); \ 283 (*(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info. \ 284 p_buf_tail_idx))++; \ 285 h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.length++; \ 286 } 287 288 #define WMI_MGMT_EVENT_RECORD(h, a, b) { \ 289 if (wmi_mgmt_log_max_entry <= \ 290 *(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx))\ 291 *(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx) = 0;\ 292 ((struct wmi_event_debug *)h->log_info.wmi_mgmt_event_log_buf_info.buf)\ 293 [*(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx)]\ 294 .event = a; \ 295 qdf_mem_copy(((struct wmi_event_debug *)h->log_info. \ 296 wmi_mgmt_event_log_buf_info.buf) \ 297 [*(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx)].\ 298 data, b, wmi_record_max_length); \ 299 ((struct wmi_event_debug *)h->log_info.wmi_mgmt_event_log_buf_info.buf)\ 300 [*(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx)].\ 301 time = qdf_get_log_timestamp(); \ 302 (*(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx))++; \ 303 h->log_info.wmi_mgmt_event_log_buf_info.length++; \ 304 } 305 306 /* These are defined to made it as module param, which can be configured */ 307 uint32_t wmi_log_max_entry = WMI_EVENT_DEBUG_MAX_ENTRY; 308 uint32_t wmi_mgmt_log_max_entry = WMI_MGMT_EVENT_DEBUG_MAX_ENTRY; 309 uint32_t wmi_record_max_length = WMI_EVENT_DEBUG_ENTRY_MAX_LENGTH; 310 uint32_t wmi_display_size = 100; 311 312 static uint8_t *wmi_id_to_name(uint32_t wmi_command); 313 314 /** 315 * wmi_log_init() - Initialize WMI event logging 316 * @wmi_handle: WMI handle. 317 * 318 * Return: Initialization status 319 */ 320 #ifdef CONFIG_MCL 321 static QDF_STATUS wmi_log_init(struct wmi_unified *wmi_handle) 322 { 323 struct wmi_log_buf_t *cmd_log_buf = 324 &wmi_handle->log_info.wmi_command_log_buf_info; 325 struct wmi_log_buf_t *cmd_tx_cmpl_log_buf = 326 &wmi_handle->log_info.wmi_command_tx_cmp_log_buf_info; 327 328 struct wmi_log_buf_t *event_log_buf = 329 &wmi_handle->log_info.wmi_event_log_buf_info; 330 struct wmi_log_buf_t *rx_event_log_buf = 331 &wmi_handle->log_info.wmi_rx_event_log_buf_info; 332 333 struct wmi_log_buf_t *mgmt_cmd_log_buf = 334 &wmi_handle->log_info.wmi_mgmt_command_log_buf_info; 335 struct wmi_log_buf_t *mgmt_cmd_tx_cmp_log_buf = 336 &wmi_handle->log_info.wmi_mgmt_command_tx_cmp_log_buf_info; 337 struct wmi_log_buf_t *mgmt_event_log_buf = 338 &wmi_handle->log_info.wmi_mgmt_event_log_buf_info; 339 340 /* WMI commands */ 341 cmd_log_buf->length = 0; 342 cmd_log_buf->buf_tail_idx = 0; 343 cmd_log_buf->buf = wmi_command_log_buffer; 344 cmd_log_buf->p_buf_tail_idx = &g_wmi_command_buf_idx; 345 346 /* WMI commands TX completed */ 347 cmd_tx_cmpl_log_buf->length = 0; 348 cmd_tx_cmpl_log_buf->buf_tail_idx = 0; 349 cmd_tx_cmpl_log_buf->buf = wmi_command_tx_cmp_log_buffer; 350 cmd_tx_cmpl_log_buf->p_buf_tail_idx = &g_wmi_command_tx_cmp_buf_idx; 351 352 /* WMI events when processed */ 353 event_log_buf->length = 0; 354 event_log_buf->buf_tail_idx = 0; 355 event_log_buf->buf = wmi_event_log_buffer; 356 event_log_buf->p_buf_tail_idx = &g_wmi_event_buf_idx; 357 358 /* WMI events when queued */ 359 rx_event_log_buf->length = 0; 360 rx_event_log_buf->buf_tail_idx = 0; 361 rx_event_log_buf->buf = wmi_rx_event_log_buffer; 362 rx_event_log_buf->p_buf_tail_idx = &g_wmi_rx_event_buf_idx; 363 364 /* WMI Management commands */ 365 mgmt_cmd_log_buf->length = 0; 366 mgmt_cmd_log_buf->buf_tail_idx = 0; 367 mgmt_cmd_log_buf->buf = wmi_mgmt_command_log_buffer; 368 mgmt_cmd_log_buf->p_buf_tail_idx = &g_wmi_mgmt_command_buf_idx; 369 370 /* WMI Management commands Tx completed*/ 371 mgmt_cmd_tx_cmp_log_buf->length = 0; 372 mgmt_cmd_tx_cmp_log_buf->buf_tail_idx = 0; 373 mgmt_cmd_tx_cmp_log_buf->buf = wmi_mgmt_command_tx_cmp_log_buffer; 374 mgmt_cmd_tx_cmp_log_buf->p_buf_tail_idx = 375 &g_wmi_mgmt_command_tx_cmp_buf_idx; 376 377 /* WMI Management events when processed*/ 378 mgmt_event_log_buf->length = 0; 379 mgmt_event_log_buf->buf_tail_idx = 0; 380 mgmt_event_log_buf->buf = wmi_mgmt_event_log_buffer; 381 mgmt_event_log_buf->p_buf_tail_idx = &g_wmi_mgmt_event_buf_idx; 382 383 qdf_spinlock_create(&wmi_handle->log_info.wmi_record_lock); 384 wmi_handle->log_info.wmi_logging_enable = 1; 385 386 return QDF_STATUS_SUCCESS; 387 } 388 #else 389 static QDF_STATUS wmi_log_init(struct wmi_unified *wmi_handle) 390 { 391 struct wmi_log_buf_t *cmd_log_buf = 392 &wmi_handle->log_info.wmi_command_log_buf_info; 393 struct wmi_log_buf_t *cmd_tx_cmpl_log_buf = 394 &wmi_handle->log_info.wmi_command_tx_cmp_log_buf_info; 395 396 struct wmi_log_buf_t *event_log_buf = 397 &wmi_handle->log_info.wmi_event_log_buf_info; 398 struct wmi_log_buf_t *rx_event_log_buf = 399 &wmi_handle->log_info.wmi_rx_event_log_buf_info; 400 401 struct wmi_log_buf_t *mgmt_cmd_log_buf = 402 &wmi_handle->log_info.wmi_mgmt_command_log_buf_info; 403 struct wmi_log_buf_t *mgmt_cmd_tx_cmp_log_buf = 404 &wmi_handle->log_info.wmi_mgmt_command_tx_cmp_log_buf_info; 405 struct wmi_log_buf_t *mgmt_event_log_buf = 406 &wmi_handle->log_info.wmi_mgmt_event_log_buf_info; 407 408 wmi_handle->log_info.wmi_logging_enable = 0; 409 410 /* WMI commands */ 411 cmd_log_buf->length = 0; 412 cmd_log_buf->buf_tail_idx = 0; 413 cmd_log_buf->buf = (struct wmi_command_debug *) qdf_mem_malloc( 414 wmi_log_max_entry * sizeof(struct wmi_command_debug)); 415 416 if (!cmd_log_buf->buf) { 417 qdf_print("no memory for WMI command log buffer..\n"); 418 return QDF_STATUS_E_NOMEM; 419 } 420 cmd_log_buf->p_buf_tail_idx = &cmd_log_buf->buf_tail_idx; 421 422 /* WMI commands TX completed */ 423 cmd_tx_cmpl_log_buf->length = 0; 424 cmd_tx_cmpl_log_buf->buf_tail_idx = 0; 425 cmd_tx_cmpl_log_buf->buf = (struct wmi_command_debug *) qdf_mem_malloc( 426 wmi_log_max_entry * sizeof(struct wmi_command_debug)); 427 428 if (!cmd_tx_cmpl_log_buf->buf) { 429 qdf_print("no memory for WMI Command Tx Complete log buffer..\n"); 430 return QDF_STATUS_E_NOMEM; 431 } 432 cmd_tx_cmpl_log_buf->p_buf_tail_idx = 433 &cmd_tx_cmpl_log_buf->buf_tail_idx; 434 435 /* WMI events when processed */ 436 event_log_buf->length = 0; 437 event_log_buf->buf_tail_idx = 0; 438 event_log_buf->buf = (struct wmi_event_debug *) qdf_mem_malloc( 439 wmi_log_max_entry * sizeof(struct wmi_event_debug)); 440 441 if (!event_log_buf->buf) { 442 qdf_print("no memory for WMI Event log buffer..\n"); 443 return QDF_STATUS_E_NOMEM; 444 } 445 event_log_buf->p_buf_tail_idx = &event_log_buf->buf_tail_idx; 446 447 /* WMI events when queued */ 448 rx_event_log_buf->length = 0; 449 rx_event_log_buf->buf_tail_idx = 0; 450 rx_event_log_buf->buf = (struct wmi_event_debug *) qdf_mem_malloc( 451 wmi_log_max_entry * sizeof(struct wmi_event_debug)); 452 453 if (!rx_event_log_buf->buf) { 454 qdf_print("no memory for WMI Event Rx log buffer..\n"); 455 return QDF_STATUS_E_NOMEM; 456 } 457 rx_event_log_buf->p_buf_tail_idx = &rx_event_log_buf->buf_tail_idx; 458 459 /* WMI Management commands */ 460 mgmt_cmd_log_buf->length = 0; 461 mgmt_cmd_log_buf->buf_tail_idx = 0; 462 mgmt_cmd_log_buf->buf = (struct wmi_command_debug *) qdf_mem_malloc( 463 wmi_mgmt_log_max_entry * 464 sizeof(struct wmi_command_debug)); 465 466 if (!mgmt_cmd_log_buf->buf) { 467 qdf_print("no memory for WMI Management Command log buffer..\n"); 468 return QDF_STATUS_E_NOMEM; 469 } 470 mgmt_cmd_log_buf->p_buf_tail_idx = &mgmt_cmd_log_buf->buf_tail_idx; 471 472 /* WMI Management commands Tx completed*/ 473 mgmt_cmd_tx_cmp_log_buf->length = 0; 474 mgmt_cmd_tx_cmp_log_buf->buf_tail_idx = 0; 475 mgmt_cmd_tx_cmp_log_buf->buf = (struct wmi_command_debug *) 476 qdf_mem_malloc( 477 wmi_mgmt_log_max_entry * 478 sizeof(struct wmi_command_debug)); 479 480 if (!mgmt_cmd_tx_cmp_log_buf->buf) { 481 qdf_print("no memory for WMI Management Command Tx complete log buffer..\n"); 482 return QDF_STATUS_E_NOMEM; 483 } 484 mgmt_cmd_tx_cmp_log_buf->p_buf_tail_idx = 485 &mgmt_cmd_tx_cmp_log_buf->buf_tail_idx; 486 487 /* WMI Management events when processed*/ 488 mgmt_event_log_buf->length = 0; 489 mgmt_event_log_buf->buf_tail_idx = 0; 490 491 mgmt_event_log_buf->buf = (struct wmi_event_debug *) qdf_mem_malloc( 492 wmi_mgmt_log_max_entry * 493 sizeof(struct wmi_event_debug)); 494 495 if (!mgmt_event_log_buf->buf) { 496 qdf_print("no memory for WMI Management Event log buffer..\n"); 497 return QDF_STATUS_E_NOMEM; 498 } 499 mgmt_event_log_buf->p_buf_tail_idx = &mgmt_event_log_buf->buf_tail_idx; 500 501 qdf_spinlock_create(&wmi_handle->log_info.wmi_record_lock); 502 wmi_handle->log_info.wmi_logging_enable = 1; 503 504 return QDF_STATUS_SUCCESS; 505 } 506 #endif 507 508 /** 509 * wmi_log_buffer_free() - Free all dynamic allocated buffer memory for 510 * event logging 511 * @wmi_handle: WMI handle. 512 * 513 * Return: None 514 */ 515 #ifndef CONFIG_MCL 516 static inline void wmi_log_buffer_free(struct wmi_unified *wmi_handle) 517 { 518 if (wmi_handle->log_info.wmi_command_log_buf_info.buf) 519 qdf_mem_free(wmi_handle->log_info.wmi_command_log_buf_info.buf); 520 if (wmi_handle->log_info.wmi_command_tx_cmp_log_buf_info.buf) 521 qdf_mem_free( 522 wmi_handle->log_info.wmi_command_tx_cmp_log_buf_info.buf); 523 if (wmi_handle->log_info.wmi_event_log_buf_info.buf) 524 qdf_mem_free(wmi_handle->log_info.wmi_event_log_buf_info.buf); 525 if (wmi_handle->log_info.wmi_rx_event_log_buf_info.buf) 526 qdf_mem_free( 527 wmi_handle->log_info.wmi_rx_event_log_buf_info.buf); 528 if (wmi_handle->log_info.wmi_mgmt_command_log_buf_info.buf) 529 qdf_mem_free( 530 wmi_handle->log_info.wmi_mgmt_command_log_buf_info.buf); 531 if (wmi_handle->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.buf) 532 qdf_mem_free( 533 wmi_handle->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.buf); 534 if (wmi_handle->log_info.wmi_mgmt_event_log_buf_info.buf) 535 qdf_mem_free( 536 wmi_handle->log_info.wmi_mgmt_event_log_buf_info.buf); 537 wmi_handle->log_info.wmi_logging_enable = 0; 538 qdf_spinlock_destroy(&wmi_handle->log_info.wmi_record_lock); 539 } 540 #else 541 static inline void wmi_log_buffer_free(struct wmi_unified *wmi_handle) 542 { 543 /* Do Nothing */ 544 } 545 #endif 546 547 #ifdef CONFIG_MCL 548 const int8_t * const debugfs_dir[MAX_WMI_INSTANCES] = {"WMI0"}; 549 #else 550 const int8_t * const debugfs_dir[MAX_WMI_INSTANCES] = {"WMI0", "WMI1", "WMI2"}; 551 #endif 552 553 /* debugfs routines*/ 554 555 /** 556 * debug_wmi_##func_base##_show() - debugfs functions to display content of 557 * command and event buffers. Macro uses max buffer length to display 558 * buffer when it is wraparound. 559 * 560 * @m: debugfs handler to access wmi_handle 561 * @v: Variable arguments (not used) 562 * 563 * Return: Length of characters printed 564 */ 565 #define GENERATE_COMMAND_DEBUG_SHOW_FUNCS(func_base, wmi_ring_size) \ 566 static int debug_wmi_##func_base##_show(struct seq_file *m, \ 567 void *v) \ 568 { \ 569 wmi_unified_t wmi_handle = (wmi_unified_t) m->private; \ 570 struct wmi_log_buf_t *wmi_log = \ 571 &wmi_handle->log_info.wmi_##func_base##_buf_info;\ 572 int pos, nread, outlen; \ 573 int i; \ 574 \ 575 qdf_spin_lock(&wmi_handle->log_info.wmi_record_lock); \ 576 if (!wmi_log->length) { \ 577 qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock);\ 578 return seq_printf(m, \ 579 "no elements to read from ring buffer!\n"); \ 580 } \ 581 \ 582 if (wmi_log->length <= wmi_ring_size) \ 583 nread = wmi_log->length; \ 584 else \ 585 nread = wmi_ring_size; \ 586 \ 587 if (*(wmi_log->p_buf_tail_idx) == 0) \ 588 /* tail can be 0 after wrap-around */ \ 589 pos = wmi_ring_size - 1; \ 590 else \ 591 pos = *(wmi_log->p_buf_tail_idx) - 1; \ 592 \ 593 outlen = seq_printf(m, "Length = %d\n", wmi_log->length);\ 594 qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock); \ 595 while (nread--) { \ 596 struct wmi_command_debug *wmi_record; \ 597 \ 598 wmi_record = (struct wmi_command_debug *) \ 599 &(((struct wmi_command_debug *)wmi_log->buf)[pos]);\ 600 outlen += seq_printf(m, "CMD ID = %x\n", \ 601 (wmi_record->command)); \ 602 outlen += seq_printf(m, "CMD = "); \ 603 for (i = 0; i < (wmi_record_max_length/ \ 604 sizeof(uint32_t)); i++) \ 605 outlen += seq_printf(m, "%x ", \ 606 wmi_record->data[i]); \ 607 outlen += seq_printf(m, "\n"); \ 608 \ 609 if (pos == 0) \ 610 pos = wmi_ring_size - 1; \ 611 else \ 612 pos--; \ 613 } \ 614 \ 615 return outlen; \ 616 } \ 617 618 #define GENERATE_EVENT_DEBUG_SHOW_FUNCS(func_base, wmi_ring_size) \ 619 static int debug_wmi_##func_base##_show(struct seq_file *m, \ 620 void *v) \ 621 { \ 622 wmi_unified_t wmi_handle = (wmi_unified_t) m->private; \ 623 struct wmi_log_buf_t *wmi_log = \ 624 &wmi_handle->log_info.wmi_##func_base##_buf_info;\ 625 int pos, nread, outlen; \ 626 int i; \ 627 \ 628 qdf_spin_lock(&wmi_handle->log_info.wmi_record_lock); \ 629 if (!wmi_log->length) { \ 630 qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock);\ 631 return seq_printf(m, \ 632 "no elements to read from ring buffer!\n"); \ 633 } \ 634 \ 635 if (wmi_log->length <= wmi_ring_size) \ 636 nread = wmi_log->length; \ 637 else \ 638 nread = wmi_ring_size; \ 639 \ 640 if (*(wmi_log->p_buf_tail_idx) == 0) \ 641 /* tail can be 0 after wrap-around */ \ 642 pos = wmi_ring_size - 1; \ 643 else \ 644 pos = *(wmi_log->p_buf_tail_idx) - 1; \ 645 \ 646 outlen = seq_printf(m, "Length = %d\n", wmi_log->length);\ 647 qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock); \ 648 while (nread--) { \ 649 struct wmi_event_debug *wmi_record; \ 650 \ 651 wmi_record = (struct wmi_event_debug *) \ 652 &(((struct wmi_event_debug *)wmi_log->buf)[pos]);\ 653 outlen += seq_printf(m, "Event ID = %x\n", \ 654 (wmi_record->event)); \ 655 outlen += seq_printf(m, "CMD = "); \ 656 for (i = 0; i < (wmi_record_max_length/ \ 657 sizeof(uint32_t)); i++) \ 658 outlen += seq_printf(m, "%x ", \ 659 wmi_record->data[i]); \ 660 outlen += seq_printf(m, "\n"); \ 661 \ 662 if (pos == 0) \ 663 pos = wmi_ring_size - 1; \ 664 else \ 665 pos--; \ 666 } \ 667 \ 668 return outlen; \ 669 } 670 671 GENERATE_COMMAND_DEBUG_SHOW_FUNCS(command_log, wmi_display_size); 672 GENERATE_COMMAND_DEBUG_SHOW_FUNCS(command_tx_cmp_log, wmi_display_size); 673 GENERATE_EVENT_DEBUG_SHOW_FUNCS(event_log, wmi_display_size); 674 GENERATE_EVENT_DEBUG_SHOW_FUNCS(rx_event_log, wmi_display_size); 675 GENERATE_COMMAND_DEBUG_SHOW_FUNCS(mgmt_command_log, wmi_display_size); 676 GENERATE_COMMAND_DEBUG_SHOW_FUNCS(mgmt_command_tx_cmp_log, 677 wmi_display_size); 678 GENERATE_EVENT_DEBUG_SHOW_FUNCS(mgmt_event_log, wmi_display_size); 679 680 /** 681 * debug_wmi_enable_show() - debugfs functions to display enable state of 682 * wmi logging feature. 683 * 684 * @m: debugfs handler to access wmi_handle 685 * @v: Variable arguments (not used) 686 * 687 * Return: always 1 688 */ 689 static int debug_wmi_enable_show(struct seq_file *m, void *v) 690 { 691 wmi_unified_t wmi_handle = (wmi_unified_t) m->private; 692 693 return seq_printf(m, "%d\n", wmi_handle->log_info.wmi_logging_enable); 694 695 } 696 697 /** 698 * debug_wmi_log_size_show() - debugfs functions to display configured size of 699 * wmi logging command/event buffer and management command/event buffer. 700 * 701 * @m: debugfs handler to access wmi_handle 702 * @v: Variable arguments (not used) 703 * 704 * Return: Length of characters printed 705 */ 706 static int debug_wmi_log_size_show(struct seq_file *m, void *v) 707 { 708 709 seq_printf(m, "WMI command/event log max size:%d\n", wmi_log_max_entry); 710 return seq_printf(m, "WMI management command/events log max size:%d\n", 711 wmi_mgmt_log_max_entry); 712 } 713 714 /** 715 * debug_wmi_##func_base##_write() - debugfs functions to clear 716 * wmi logging command/event buffer and management command/event buffer. 717 * 718 * @file: file handler to access wmi_handle 719 * @buf: received data buffer 720 * @count: length of received buffer 721 * @ppos: Not used 722 * 723 * Return: count 724 */ 725 #define GENERATE_DEBUG_WRITE_FUNCS(func_base, wmi_ring_size, wmi_record_type)\ 726 static ssize_t debug_wmi_##func_base##_write(struct file *file, \ 727 const char __user *buf, \ 728 size_t count, loff_t *ppos) \ 729 { \ 730 int k, ret; \ 731 wmi_unified_t wmi_handle = file->private_data; \ 732 struct wmi_log_buf_t *wmi_log = &wmi_handle->log_info. \ 733 wmi_##func_base##_buf_info; \ 734 \ 735 ret = sscanf(buf, "%d", &k); \ 736 if ((ret != 1) || (k != 0)) { \ 737 qdf_print("Wrong input, echo 0 to clear the wmi buffer\n");\ 738 return -EINVAL; \ 739 } \ 740 \ 741 qdf_spin_lock(&wmi_handle->log_info.wmi_record_lock); \ 742 qdf_mem_zero(wmi_log->buf, wmi_ring_size * \ 743 sizeof(struct wmi_record_type)); \ 744 wmi_log->length = 0; \ 745 *(wmi_log->p_buf_tail_idx) = 0; \ 746 qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock); \ 747 \ 748 return count; \ 749 } 750 751 GENERATE_DEBUG_WRITE_FUNCS(command_log, wmi_log_max_entry, 752 wmi_command_debug); 753 GENERATE_DEBUG_WRITE_FUNCS(command_tx_cmp_log, wmi_log_max_entry, 754 wmi_command_debug); 755 GENERATE_DEBUG_WRITE_FUNCS(event_log, wmi_log_max_entry, 756 wmi_event_debug); 757 GENERATE_DEBUG_WRITE_FUNCS(rx_event_log, wmi_log_max_entry, 758 wmi_event_debug); 759 GENERATE_DEBUG_WRITE_FUNCS(mgmt_command_log, wmi_mgmt_log_max_entry, 760 wmi_command_debug); 761 GENERATE_DEBUG_WRITE_FUNCS(mgmt_command_tx_cmp_log, 762 wmi_mgmt_log_max_entry, wmi_command_debug); 763 GENERATE_DEBUG_WRITE_FUNCS(mgmt_event_log, wmi_mgmt_log_max_entry, 764 wmi_event_debug); 765 766 /** 767 * debug_wmi_enable_write() - debugfs functions to enable/disable 768 * wmi logging feature. 769 * 770 * @file: file handler to access wmi_handle 771 * @buf: received data buffer 772 * @count: length of received buffer 773 * @ppos: Not used 774 * 775 * Return: count 776 */ 777 static ssize_t debug_wmi_enable_write(struct file *file, const char __user *buf, 778 size_t count, loff_t *ppos) 779 { 780 wmi_unified_t wmi_handle = file->private_data; 781 int k, ret; 782 783 ret = sscanf(buf, "%d", &k); 784 if ((ret != 1) || ((k != 0) && (k != 1))) 785 return -EINVAL; 786 787 wmi_handle->log_info.wmi_logging_enable = k; 788 return count; 789 } 790 791 /** 792 * debug_wmi_log_size_write() - reserved. 793 * 794 * @file: file handler to access wmi_handle 795 * @buf: received data buffer 796 * @count: length of received buffer 797 * @ppos: Not used 798 * 799 * Return: count 800 */ 801 static ssize_t debug_wmi_log_size_write(struct file *file, 802 const char __user *buf, size_t count, loff_t *ppos) 803 { 804 return -EINVAL; 805 } 806 807 /* Structure to maintain debug information */ 808 struct wmi_debugfs_info { 809 const char *name; 810 struct dentry *de[MAX_WMI_INSTANCES]; 811 const struct file_operations *ops; 812 }; 813 814 #define DEBUG_FOO(func_base) { .name = #func_base, \ 815 .ops = &debug_##func_base##_ops } 816 817 /** 818 * debug_##func_base##_open() - Open debugfs entry for respective command 819 * and event buffer. 820 * 821 * @inode: node for debug dir entry 822 * @file: file handler 823 * 824 * Return: open status 825 */ 826 #define GENERATE_DEBUG_STRUCTS(func_base) \ 827 static int debug_##func_base##_open(struct inode *inode, \ 828 struct file *file) \ 829 { \ 830 return single_open(file, debug_##func_base##_show, \ 831 inode->i_private); \ 832 } \ 833 \ 834 \ 835 static struct file_operations debug_##func_base##_ops = { \ 836 .open = debug_##func_base##_open, \ 837 .read = seq_read, \ 838 .llseek = seq_lseek, \ 839 .write = debug_##func_base##_write, \ 840 .release = single_release, \ 841 }; 842 843 GENERATE_DEBUG_STRUCTS(wmi_command_log); 844 GENERATE_DEBUG_STRUCTS(wmi_command_tx_cmp_log); 845 GENERATE_DEBUG_STRUCTS(wmi_event_log); 846 GENERATE_DEBUG_STRUCTS(wmi_rx_event_log); 847 GENERATE_DEBUG_STRUCTS(wmi_mgmt_command_log); 848 GENERATE_DEBUG_STRUCTS(wmi_mgmt_command_tx_cmp_log); 849 GENERATE_DEBUG_STRUCTS(wmi_mgmt_event_log); 850 GENERATE_DEBUG_STRUCTS(wmi_enable); 851 GENERATE_DEBUG_STRUCTS(wmi_log_size); 852 853 struct wmi_debugfs_info wmi_debugfs_infos[] = { 854 DEBUG_FOO(wmi_command_log), 855 DEBUG_FOO(wmi_command_tx_cmp_log), 856 DEBUG_FOO(wmi_event_log), 857 DEBUG_FOO(wmi_rx_event_log), 858 DEBUG_FOO(wmi_mgmt_command_log), 859 DEBUG_FOO(wmi_mgmt_command_tx_cmp_log), 860 DEBUG_FOO(wmi_mgmt_event_log), 861 DEBUG_FOO(wmi_enable), 862 DEBUG_FOO(wmi_log_size), 863 }; 864 865 #define NUM_DEBUG_INFOS (sizeof(wmi_debugfs_infos) / \ 866 sizeof(wmi_debugfs_infos[0])) 867 868 /** 869 * wmi_debugfs_create() - Create debug_fs entry for wmi logging. 870 * 871 * @wmi_handle: wmi handle 872 * @par_entry: debug directory entry 873 * @id: Index to debug info data array 874 * 875 * Return: none 876 */ 877 static void wmi_debugfs_create(wmi_unified_t wmi_handle, 878 struct dentry *par_entry, int id) 879 { 880 int i; 881 882 if (par_entry == NULL || (id < 0) || (id >= MAX_WMI_INSTANCES)) 883 goto out; 884 885 for (i = 0; i < NUM_DEBUG_INFOS; ++i) { 886 887 wmi_debugfs_infos[i].de[id] = debugfs_create_file( 888 wmi_debugfs_infos[i].name, 0644, par_entry, 889 wmi_handle, wmi_debugfs_infos[i].ops); 890 891 if (wmi_debugfs_infos[i].de[id] == NULL) { 892 qdf_print("%s: debug Entry creation failed!\n", 893 __func__); 894 goto out; 895 } 896 } 897 898 return; 899 900 out: 901 qdf_print("%s: debug Entry creation failed!\n", __func__); 902 wmi_log_buffer_free(wmi_handle); 903 return; 904 } 905 906 /** 907 * wmi_debugfs_remove() - Remove debugfs entry for wmi logging. 908 * @wmi_handle: wmi handle 909 * @dentry: debugfs directory entry 910 * @id: Index to debug info data array 911 * 912 * Return: none 913 */ 914 static void wmi_debugfs_remove(wmi_unified_t wmi_handle) 915 { 916 int i; 917 struct dentry *dentry = wmi_handle->log_info.wmi_log_debugfs_dir; 918 int id = wmi_handle->log_info.wmi_instance_id; 919 920 if (dentry && (!(id < 0) || (id >= MAX_WMI_INSTANCES))) { 921 for (i = 0; i < NUM_DEBUG_INFOS; ++i) { 922 if (wmi_debugfs_infos[i].de[id]) 923 wmi_debugfs_infos[i].de[id] = NULL; 924 } 925 } 926 927 if (dentry) 928 debugfs_remove_recursive(dentry); 929 } 930 931 /** 932 * wmi_debugfs_init() - debugfs functions to create debugfs directory and to 933 * create debugfs enteries. 934 * 935 * @h: wmi handler 936 * 937 * Return: init status 938 */ 939 static QDF_STATUS wmi_debugfs_init(wmi_unified_t wmi_handle) 940 { 941 static int wmi_index; 942 943 if (wmi_index < MAX_WMI_INSTANCES) 944 wmi_handle->log_info.wmi_log_debugfs_dir = 945 debugfs_create_dir(debugfs_dir[wmi_index], NULL); 946 947 if (wmi_handle->log_info.wmi_log_debugfs_dir == NULL) { 948 qdf_print("error while creating debugfs dir for %s\n", 949 debugfs_dir[wmi_index]); 950 return QDF_STATUS_E_FAILURE; 951 } 952 953 wmi_debugfs_create(wmi_handle, wmi_handle->log_info.wmi_log_debugfs_dir, 954 wmi_index); 955 wmi_handle->log_info.wmi_instance_id = wmi_index++; 956 957 return QDF_STATUS_SUCCESS; 958 } 959 960 /** 961 * wmi_mgmt_cmd_record() - Wrapper function for mgmt command logging macro 962 * 963 * @wmi_handle: wmi handle 964 * @cmd: mgmt command 965 * @header: pointer to 802.11 header 966 * @vdev_id: vdev id 967 * @chanfreq: channel frequency 968 * 969 * Return: none 970 */ 971 void wmi_mgmt_cmd_record(wmi_unified_t wmi_handle, uint32_t cmd, 972 void *header, uint32_t vdev_id, uint32_t chanfreq) 973 { 974 975 uint32_t data[CUSTOM_MGMT_CMD_DATA_SIZE]; 976 977 data[0] = ((struct wmi_command_header *)header)->type; 978 data[1] = ((struct wmi_command_header *)header)->sub_type; 979 data[2] = vdev_id; 980 data[3] = chanfreq; 981 982 qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock); 983 984 WMI_MGMT_COMMAND_RECORD(wmi_handle, cmd, data); 985 986 qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock); 987 } 988 #else 989 /** 990 * wmi_debugfs_remove() - Remove debugfs entry for wmi logging. 991 * @wmi_handle: wmi handle 992 * @dentry: debugfs directory entry 993 * @id: Index to debug info data array 994 * 995 * Return: none 996 */ 997 static void wmi_debugfs_remove(wmi_unified_t wmi_handle) { } 998 void wmi_mgmt_cmd_record(wmi_unified_t wmi_handle, uint32_t cmd, 999 void *header, uint32_t vdev_id, uint32_t chanfreq) { } 1000 #endif /*WMI_INTERFACE_EVENT_LOGGING */ 1001 1002 int wmi_get_host_credits(wmi_unified_t wmi_handle); 1003 /* WMI buffer APIs */ 1004 1005 #ifdef MEMORY_DEBUG 1006 wmi_buf_t 1007 wmi_buf_alloc_debug(wmi_unified_t wmi_handle, uint16_t len, uint8_t *file_name, 1008 uint32_t line_num) 1009 { 1010 wmi_buf_t wmi_buf; 1011 1012 if (roundup(len + WMI_MIN_HEAD_ROOM, 4) > wmi_handle->max_msg_len) { 1013 QDF_ASSERT(0); 1014 return NULL; 1015 } 1016 1017 wmi_buf = qdf_nbuf_alloc_debug(NULL, 1018 roundup(len + WMI_MIN_HEAD_ROOM, 4), 1019 WMI_MIN_HEAD_ROOM, 4, false, file_name, 1020 line_num); 1021 1022 if (!wmi_buf) 1023 return NULL; 1024 1025 /* Clear the wmi buffer */ 1026 OS_MEMZERO(qdf_nbuf_data(wmi_buf), len); 1027 1028 /* 1029 * Set the length of the buffer to match the allocation size. 1030 */ 1031 qdf_nbuf_set_pktlen(wmi_buf, len); 1032 1033 return wmi_buf; 1034 } 1035 1036 void wmi_buf_free(wmi_buf_t net_buf) 1037 { 1038 qdf_nbuf_free(net_buf); 1039 } 1040 #else 1041 wmi_buf_t wmi_buf_alloc(wmi_unified_t wmi_handle, uint16_t len) 1042 { 1043 wmi_buf_t wmi_buf; 1044 1045 if (roundup(len + WMI_MIN_HEAD_ROOM, 4) > wmi_handle->max_msg_len) { 1046 QDF_ASSERT(0); 1047 return NULL; 1048 } 1049 1050 wmi_buf = qdf_nbuf_alloc(NULL, roundup(len + WMI_MIN_HEAD_ROOM, 4), 1051 WMI_MIN_HEAD_ROOM, 4, false); 1052 if (!wmi_buf) 1053 return NULL; 1054 1055 /* Clear the wmi buffer */ 1056 OS_MEMZERO(qdf_nbuf_data(wmi_buf), len); 1057 1058 /* 1059 * Set the length of the buffer to match the allocation size. 1060 */ 1061 qdf_nbuf_set_pktlen(wmi_buf, len); 1062 return wmi_buf; 1063 } 1064 1065 void wmi_buf_free(wmi_buf_t net_buf) 1066 { 1067 qdf_nbuf_free(net_buf); 1068 } 1069 #endif 1070 1071 /** 1072 * wmi_get_max_msg_len() - get maximum WMI message length 1073 * @wmi_handle: WMI handle. 1074 * 1075 * This function returns the maximum WMI message length 1076 * 1077 * Return: maximum WMI message length 1078 */ 1079 uint16_t wmi_get_max_msg_len(wmi_unified_t wmi_handle) 1080 { 1081 return wmi_handle->max_msg_len - WMI_MIN_HEAD_ROOM; 1082 } 1083 1084 #ifdef CONFIG_MCL 1085 static uint8_t *wmi_id_to_name(uint32_t wmi_command) 1086 { 1087 switch (wmi_command) { 1088 /* initialize the wlan sub system */ 1089 CASE_RETURN_STRING(WMI_INIT_CMDID); 1090 1091 /* Scan specific commands */ 1092 1093 /* start scan request to FW */ 1094 CASE_RETURN_STRING(WMI_START_SCAN_CMDID); 1095 /* stop scan request to FW */ 1096 CASE_RETURN_STRING(WMI_STOP_SCAN_CMDID); 1097 /* full list of channels as defined by the regulatory 1098 * that will be used by scanner */ 1099 CASE_RETURN_STRING(WMI_SCAN_CHAN_LIST_CMDID); 1100 /* overwrite default priority table in scan scheduler */ 1101 CASE_RETURN_STRING(WMI_SCAN_SCH_PRIO_TBL_CMDID); 1102 /* This command to adjust the priority and min.max_rest_time 1103 * of an on ongoing scan request. 1104 */ 1105 CASE_RETURN_STRING(WMI_SCAN_UPDATE_REQUEST_CMDID); 1106 1107 /* PDEV(physical device) specific commands */ 1108 /* set regulatorty ctl id used by FW to determine the exact 1109 * ctl power limits */ 1110 CASE_RETURN_STRING(WMI_PDEV_SET_REGDOMAIN_CMDID); 1111 /* set channel. mainly used for supporting monitor mode */ 1112 CASE_RETURN_STRING(WMI_PDEV_SET_CHANNEL_CMDID); 1113 /* set pdev specific parameters */ 1114 CASE_RETURN_STRING(WMI_PDEV_SET_PARAM_CMDID); 1115 /* enable packet log */ 1116 CASE_RETURN_STRING(WMI_PDEV_PKTLOG_ENABLE_CMDID); 1117 /* disable packet log*/ 1118 CASE_RETURN_STRING(WMI_PDEV_PKTLOG_DISABLE_CMDID); 1119 /* set wmm parameters */ 1120 CASE_RETURN_STRING(WMI_PDEV_SET_WMM_PARAMS_CMDID); 1121 /* set HT cap ie that needs to be carried probe requests 1122 * HT/VHT channels */ 1123 CASE_RETURN_STRING(WMI_PDEV_SET_HT_CAP_IE_CMDID); 1124 /* set VHT cap ie that needs to be carried on probe 1125 * requests on VHT channels */ 1126 CASE_RETURN_STRING(WMI_PDEV_SET_VHT_CAP_IE_CMDID); 1127 1128 /* Command to send the DSCP-to-TID map to the target */ 1129 CASE_RETURN_STRING(WMI_PDEV_SET_DSCP_TID_MAP_CMDID); 1130 /* set quiet ie parameters. primarily used in AP mode */ 1131 CASE_RETURN_STRING(WMI_PDEV_SET_QUIET_MODE_CMDID); 1132 /* Enable/Disable Green AP Power Save */ 1133 CASE_RETURN_STRING(WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID); 1134 /* get TPC config for the current operating channel */ 1135 CASE_RETURN_STRING(WMI_PDEV_GET_TPC_CONFIG_CMDID); 1136 1137 /* set the base MAC address for the physical device before 1138 * a VDEV is created. For firmware that does not support 1139 * this feature and this command, the pdev MAC address will 1140 * not be changed. */ 1141 CASE_RETURN_STRING(WMI_PDEV_SET_BASE_MACADDR_CMDID); 1142 1143 /* eeprom content dump , the same to bdboard data */ 1144 CASE_RETURN_STRING(WMI_PDEV_DUMP_CMDID); 1145 1146 /* VDEV(virtual device) specific commands */ 1147 /* vdev create */ 1148 CASE_RETURN_STRING(WMI_VDEV_CREATE_CMDID); 1149 /* vdev delete */ 1150 CASE_RETURN_STRING(WMI_VDEV_DELETE_CMDID); 1151 /* vdev start request */ 1152 CASE_RETURN_STRING(WMI_VDEV_START_REQUEST_CMDID); 1153 /* vdev restart request (RX only, NO TX, used for CAC period)*/ 1154 CASE_RETURN_STRING(WMI_VDEV_RESTART_REQUEST_CMDID); 1155 /* vdev up request */ 1156 CASE_RETURN_STRING(WMI_VDEV_UP_CMDID); 1157 /* vdev stop request */ 1158 CASE_RETURN_STRING(WMI_VDEV_STOP_CMDID); 1159 /* vdev down request */ 1160 CASE_RETURN_STRING(WMI_VDEV_DOWN_CMDID); 1161 /* set a vdev param */ 1162 CASE_RETURN_STRING(WMI_VDEV_SET_PARAM_CMDID); 1163 /* set a key (used for setting per peer unicast 1164 * and per vdev multicast) */ 1165 CASE_RETURN_STRING(WMI_VDEV_INSTALL_KEY_CMDID); 1166 1167 /* wnm sleep mode command */ 1168 CASE_RETURN_STRING(WMI_VDEV_WNM_SLEEPMODE_CMDID); 1169 CASE_RETURN_STRING(WMI_VDEV_WMM_ADDTS_CMDID); 1170 CASE_RETURN_STRING(WMI_VDEV_WMM_DELTS_CMDID); 1171 CASE_RETURN_STRING(WMI_VDEV_SET_WMM_PARAMS_CMDID); 1172 CASE_RETURN_STRING(WMI_VDEV_SET_GTX_PARAMS_CMDID); 1173 CASE_RETURN_STRING(WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMDID); 1174 1175 CASE_RETURN_STRING(WMI_VDEV_PLMREQ_START_CMDID); 1176 CASE_RETURN_STRING(WMI_VDEV_PLMREQ_STOP_CMDID); 1177 CASE_RETURN_STRING(WMI_VDEV_TSF_TSTAMP_ACTION_CMDID); 1178 CASE_RETURN_STRING(WMI_VDEV_SET_IE_CMDID); 1179 1180 /* peer specific commands */ 1181 1182 /** create a peer */ 1183 CASE_RETURN_STRING(WMI_PEER_CREATE_CMDID); 1184 /** delete a peer */ 1185 CASE_RETURN_STRING(WMI_PEER_DELETE_CMDID); 1186 /** flush specific tid queues of a peer */ 1187 CASE_RETURN_STRING(WMI_PEER_FLUSH_TIDS_CMDID); 1188 /** set a parameter of a peer */ 1189 CASE_RETURN_STRING(WMI_PEER_SET_PARAM_CMDID); 1190 /* set peer to associated state. will cary all parameters 1191 * determined during assocication time */ 1192 CASE_RETURN_STRING(WMI_PEER_ASSOC_CMDID); 1193 /* add a wds (4 address ) entry. used only for testing 1194 * WDS feature on AP products */ 1195 CASE_RETURN_STRING(WMI_PEER_ADD_WDS_ENTRY_CMDID); 1196 /* remove wds (4 address ) entry. used only for testing WDS 1197 * feature on AP products */ 1198 CASE_RETURN_STRING(WMI_PEER_REMOVE_WDS_ENTRY_CMDID); 1199 /* set up mcast info for multicast to unicast conversion */ 1200 CASE_RETURN_STRING(WMI_PEER_MCAST_GROUP_CMDID); 1201 /* request peer info from FW to get PEER_INFO_EVENTID */ 1202 CASE_RETURN_STRING(WMI_PEER_INFO_REQ_CMDID); 1203 1204 /* beacon/management specific commands */ 1205 1206 /* transmit beacon by reference. used for transmitting beacon 1207 * on low latency interface like pcie */ 1208 CASE_RETURN_STRING(WMI_BCN_TX_CMDID); 1209 /* transmit beacon by value */ 1210 CASE_RETURN_STRING(WMI_PDEV_SEND_BCN_CMDID); 1211 /* set the beacon template. used in beacon offload mode to setup 1212 * the common beacon template with the FW to be used by FW to 1213 * generate beacons */ 1214 CASE_RETURN_STRING(WMI_BCN_TMPL_CMDID); 1215 /* set beacon filter with FW */ 1216 CASE_RETURN_STRING(WMI_BCN_FILTER_RX_CMDID); 1217 /* enable/disable filtering of probe requests in the firmware */ 1218 CASE_RETURN_STRING(WMI_PRB_REQ_FILTER_RX_CMDID); 1219 /* transmit management frame by value. will be deprecated */ 1220 CASE_RETURN_STRING(WMI_MGMT_TX_CMDID); 1221 /* set the probe response template. used in beacon offload mode 1222 * to setup the common probe response template with the FW to 1223 * be used by FW to generate probe responses */ 1224 CASE_RETURN_STRING(WMI_PRB_TMPL_CMDID); 1225 1226 /* commands to directly control ba negotiation directly from 1227 * host. only used in test mode */ 1228 1229 /* turn off FW Auto addba mode and let host control addba */ 1230 CASE_RETURN_STRING(WMI_ADDBA_CLEAR_RESP_CMDID); 1231 /* send add ba request */ 1232 CASE_RETURN_STRING(WMI_ADDBA_SEND_CMDID); 1233 CASE_RETURN_STRING(WMI_ADDBA_STATUS_CMDID); 1234 /* send del ba */ 1235 CASE_RETURN_STRING(WMI_DELBA_SEND_CMDID); 1236 /* set add ba response will be used by FW to generate 1237 * addba response*/ 1238 CASE_RETURN_STRING(WMI_ADDBA_SET_RESP_CMDID); 1239 /* send single VHT MPDU with AMSDU */ 1240 CASE_RETURN_STRING(WMI_SEND_SINGLEAMSDU_CMDID); 1241 1242 /* Station power save specific config */ 1243 /* enable/disable station powersave */ 1244 CASE_RETURN_STRING(WMI_STA_POWERSAVE_MODE_CMDID); 1245 /* set station power save specific parameter */ 1246 CASE_RETURN_STRING(WMI_STA_POWERSAVE_PARAM_CMDID); 1247 /* set station mimo powersave mode */ 1248 CASE_RETURN_STRING(WMI_STA_MIMO_PS_MODE_CMDID); 1249 1250 /* DFS-specific commands */ 1251 /* enable DFS (radar detection)*/ 1252 CASE_RETURN_STRING(WMI_PDEV_DFS_ENABLE_CMDID); 1253 /* disable DFS (radar detection)*/ 1254 CASE_RETURN_STRING(WMI_PDEV_DFS_DISABLE_CMDID); 1255 /* enable DFS phyerr/parse filter offload */ 1256 CASE_RETURN_STRING(WMI_DFS_PHYERR_FILTER_ENA_CMDID); 1257 /* enable DFS phyerr/parse filter offload */ 1258 CASE_RETURN_STRING(WMI_DFS_PHYERR_FILTER_DIS_CMDID); 1259 1260 /* Roaming specific commands */ 1261 /* set roam scan mode */ 1262 CASE_RETURN_STRING(WMI_ROAM_SCAN_MODE); 1263 /* set roam scan rssi threshold below which roam 1264 * scan is enabled */ 1265 CASE_RETURN_STRING(WMI_ROAM_SCAN_RSSI_THRESHOLD); 1266 /* set roam scan period for periodic roam scan mode */ 1267 CASE_RETURN_STRING(WMI_ROAM_SCAN_PERIOD); 1268 /* set roam scan trigger rssi change threshold */ 1269 CASE_RETURN_STRING(WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD); 1270 /* set roam AP profile */ 1271 CASE_RETURN_STRING(WMI_ROAM_AP_PROFILE); 1272 /* set channel list for roam scans */ 1273 CASE_RETURN_STRING(WMI_ROAM_CHAN_LIST); 1274 /* offload scan specific commands */ 1275 /* set offload scan AP profile */ 1276 CASE_RETURN_STRING(WMI_OFL_SCAN_ADD_AP_PROFILE); 1277 /* remove offload scan AP profile */ 1278 CASE_RETURN_STRING(WMI_OFL_SCAN_REMOVE_AP_PROFILE); 1279 /* set offload scan period */ 1280 CASE_RETURN_STRING(WMI_OFL_SCAN_PERIOD); 1281 1282 /* P2P specific commands */ 1283 /* set P2P device info. FW will used by FW to create P2P IE 1284 * to be carried in probe response generated during p2p listen 1285 * and for p2p discoverability */ 1286 CASE_RETURN_STRING(WMI_P2P_DEV_SET_DEVICE_INFO); 1287 /* enable/disable p2p discoverability on STA/AP VDEVs */ 1288 CASE_RETURN_STRING(WMI_P2P_DEV_SET_DISCOVERABILITY); 1289 /* set p2p ie to be carried in beacons generated by FW for GO */ 1290 CASE_RETURN_STRING(WMI_P2P_GO_SET_BEACON_IE); 1291 /* set p2p ie to be carried in probe response frames generated 1292 * by FW for GO */ 1293 CASE_RETURN_STRING(WMI_P2P_GO_SET_PROBE_RESP_IE); 1294 /* set the vendor specific p2p ie data. 1295 * FW will use this to parse the P2P NoA 1296 * attribute in the beacons/probe responses received. 1297 */ 1298 CASE_RETURN_STRING(WMI_P2P_SET_VENDOR_IE_DATA_CMDID); 1299 /* set the configure of p2p find offload */ 1300 CASE_RETURN_STRING(WMI_P2P_DISC_OFFLOAD_CONFIG_CMDID); 1301 /* set the vendor specific p2p ie data for p2p find offload */ 1302 CASE_RETURN_STRING(WMI_P2P_DISC_OFFLOAD_APPIE_CMDID); 1303 /* set the BSSID/device name pattern of p2p find offload */ 1304 CASE_RETURN_STRING(WMI_P2P_DISC_OFFLOAD_PATTERN_CMDID); 1305 /* set OppPS related parameters **/ 1306 CASE_RETURN_STRING(WMI_P2P_SET_OPPPS_PARAM_CMDID); 1307 1308 /* AP power save specific config 1309 * set AP power save specific param */ 1310 CASE_RETURN_STRING(WMI_AP_PS_PEER_PARAM_CMDID); 1311 /* set AP UAPSD coex pecific param */ 1312 CASE_RETURN_STRING(WMI_AP_PS_PEER_UAPSD_COEX_CMDID); 1313 1314 /* Rate-control specific commands */ 1315 CASE_RETURN_STRING(WMI_PEER_RATE_RETRY_SCHED_CMDID); 1316 1317 /* WLAN Profiling commands. */ 1318 CASE_RETURN_STRING(WMI_WLAN_PROFILE_TRIGGER_CMDID); 1319 CASE_RETURN_STRING(WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID); 1320 CASE_RETURN_STRING(WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID); 1321 CASE_RETURN_STRING(WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID); 1322 CASE_RETURN_STRING(WMI_WLAN_PROFILE_LIST_PROFILE_ID_CMDID); 1323 1324 /* Suspend resume command Ids */ 1325 CASE_RETURN_STRING(WMI_PDEV_SUSPEND_CMDID); 1326 CASE_RETURN_STRING(WMI_PDEV_RESUME_CMDID); 1327 1328 /* Beacon filter commands */ 1329 /* add a beacon filter */ 1330 CASE_RETURN_STRING(WMI_ADD_BCN_FILTER_CMDID); 1331 /* remove a beacon filter */ 1332 CASE_RETURN_STRING(WMI_RMV_BCN_FILTER_CMDID); 1333 1334 /* WOW Specific WMI commands */ 1335 /* add pattern for awake */ 1336 CASE_RETURN_STRING(WMI_WOW_ADD_WAKE_PATTERN_CMDID); 1337 /* deleta a wake pattern */ 1338 CASE_RETURN_STRING(WMI_WOW_DEL_WAKE_PATTERN_CMDID); 1339 /* enable/deisable wake event */ 1340 CASE_RETURN_STRING(WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID); 1341 /* enable WOW */ 1342 CASE_RETURN_STRING(WMI_WOW_ENABLE_CMDID); 1343 /* host woke up from sleep event to FW. Generated in response 1344 * to WOW Hardware event */ 1345 CASE_RETURN_STRING(WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID); 1346 1347 /* RTT measurement related cmd */ 1348 /* reques to make an RTT measurement */ 1349 CASE_RETURN_STRING(WMI_RTT_MEASREQ_CMDID); 1350 /* reques to report a tsf measurement */ 1351 CASE_RETURN_STRING(WMI_RTT_TSF_CMDID); 1352 1353 /* spectral scan command */ 1354 /* configure spectral scan */ 1355 CASE_RETURN_STRING(WMI_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID); 1356 /* enable/disable spectral scan and trigger */ 1357 CASE_RETURN_STRING(WMI_VDEV_SPECTRAL_SCAN_ENABLE_CMDID); 1358 1359 /* F/W stats */ 1360 /* one time request for stats */ 1361 CASE_RETURN_STRING(WMI_REQUEST_STATS_CMDID); 1362 /* Push MCC Adaptive Scheduler Stats to Firmware */ 1363 CASE_RETURN_STRING(WMI_MCC_SCHED_TRAFFIC_STATS_CMDID); 1364 1365 /* ARP OFFLOAD REQUEST*/ 1366 CASE_RETURN_STRING(WMI_SET_ARP_NS_OFFLOAD_CMDID); 1367 1368 /* Proactive ARP Response Add Pattern Command*/ 1369 CASE_RETURN_STRING(WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMDID); 1370 1371 /* Proactive ARP Response Del Pattern Command*/ 1372 CASE_RETURN_STRING(WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMDID); 1373 1374 /* NS offload confid*/ 1375 CASE_RETURN_STRING(WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID); 1376 1377 /* GTK offload Specific WMI commands */ 1378 CASE_RETURN_STRING(WMI_GTK_OFFLOAD_CMDID); 1379 1380 /* CSA offload Specific WMI commands */ 1381 /* csa offload enable */ 1382 CASE_RETURN_STRING(WMI_CSA_OFFLOAD_ENABLE_CMDID); 1383 /* chan switch command */ 1384 CASE_RETURN_STRING(WMI_CSA_OFFLOAD_CHANSWITCH_CMDID); 1385 1386 /* Chatter commands */ 1387 /* Change chatter mode of operation */ 1388 CASE_RETURN_STRING(WMI_CHATTER_SET_MODE_CMDID); 1389 /* chatter add coalescing filter command */ 1390 CASE_RETURN_STRING(WMI_CHATTER_ADD_COALESCING_FILTER_CMDID); 1391 /* chatter delete coalescing filter command */ 1392 CASE_RETURN_STRING(WMI_CHATTER_DELETE_COALESCING_FILTER_CMDID); 1393 /* chatter coalecing query command */ 1394 CASE_RETURN_STRING(WMI_CHATTER_COALESCING_QUERY_CMDID); 1395 1396 /* addba specific commands */ 1397 /* start the aggregation on this TID */ 1398 CASE_RETURN_STRING(WMI_PEER_TID_ADDBA_CMDID); 1399 /* stop the aggregation on this TID */ 1400 CASE_RETURN_STRING(WMI_PEER_TID_DELBA_CMDID); 1401 1402 /* set station mimo powersave method */ 1403 CASE_RETURN_STRING(WMI_STA_DTIM_PS_METHOD_CMDID); 1404 /* Configure the Station UAPSD AC Auto Trigger Parameters */ 1405 CASE_RETURN_STRING(WMI_STA_UAPSD_AUTO_TRIG_CMDID); 1406 /* Configure the Keep Alive Parameters */ 1407 CASE_RETURN_STRING(WMI_STA_KEEPALIVE_CMDID); 1408 1409 /* Request ssn from target for a sta/tid pair */ 1410 CASE_RETURN_STRING(WMI_BA_REQ_SSN_CMDID); 1411 /* misc command group */ 1412 /* echo command mainly used for testing */ 1413 CASE_RETURN_STRING(WMI_ECHO_CMDID); 1414 1415 /* !!IMPORTANT!! 1416 * If you need to add a new WMI command to the CASE_RETURN_STRING(WMI_GRP_MISC sub-group, 1417 * please make sure you add it BEHIND CASE_RETURN_STRING(WMI_PDEV_UTF_CMDID); 1418 * as we MUST have a fixed value here to maintain compatibility between 1419 * UTF and the ART2 driver 1420 */ 1421 /* UTF WMI commands */ 1422 CASE_RETURN_STRING(WMI_PDEV_UTF_CMDID); 1423 1424 /* set debug log config */ 1425 CASE_RETURN_STRING(WMI_DBGLOG_CFG_CMDID); 1426 /* QVIT specific command id */ 1427 CASE_RETURN_STRING(WMI_PDEV_QVIT_CMDID); 1428 /* Factory Testing Mode request command 1429 * used for integrated chipsets */ 1430 CASE_RETURN_STRING(WMI_PDEV_FTM_INTG_CMDID); 1431 /* set and get keepalive parameters command */ 1432 CASE_RETURN_STRING(WMI_VDEV_SET_KEEPALIVE_CMDID); 1433 CASE_RETURN_STRING(WMI_VDEV_GET_KEEPALIVE_CMDID); 1434 /* For fw recovery test command */ 1435 CASE_RETURN_STRING(WMI_FORCE_FW_HANG_CMDID); 1436 /* Set Mcast/Bdcast filter */ 1437 CASE_RETURN_STRING(WMI_SET_MCASTBCAST_FILTER_CMDID); 1438 /* set thermal management params */ 1439 CASE_RETURN_STRING(WMI_THERMAL_MGMT_CMDID); 1440 CASE_RETURN_STRING(WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID); 1441 CASE_RETURN_STRING(WMI_LRO_CONFIG_CMDID); 1442 CASE_RETURN_STRING(WMI_TRANSFER_DATA_TO_FLASH_CMDID); 1443 CASE_RETURN_STRING(WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID); 1444 CASE_RETURN_STRING(WMI_VDEV_WISA_CMDID); 1445 CASE_RETURN_STRING(WMI_SCAN_ADAPTIVE_DWELL_CONFIG_CMDID); 1446 CASE_RETURN_STRING(WMI_WOW_SET_ACTION_WAKE_UP_CMDID); 1447 CASE_RETURN_STRING(WMI_MAWC_SENSOR_REPORT_IND_CMDID); 1448 CASE_RETURN_STRING(WMI_ROAM_CONFIGURE_MAWC_CMDID); 1449 CASE_RETURN_STRING(WMI_NLO_CONFIGURE_MAWC_CMDID); 1450 CASE_RETURN_STRING(WMI_EXTSCAN_CONFIGURE_MAWC_CMDID); 1451 /* GPIO Configuration */ 1452 CASE_RETURN_STRING(WMI_GPIO_CONFIG_CMDID); 1453 CASE_RETURN_STRING(WMI_GPIO_OUTPUT_CMDID); 1454 1455 /* Txbf configuration command */ 1456 CASE_RETURN_STRING(WMI_TXBF_CMDID); 1457 1458 /* FWTEST Commands */ 1459 CASE_RETURN_STRING(WMI_FWTEST_VDEV_MCC_SET_TBTT_MODE_CMDID); 1460 /* set NoA descs */ 1461 CASE_RETURN_STRING(WMI_FWTEST_P2P_SET_NOA_PARAM_CMDID); 1462 1463 /* TDLS Configuration */ 1464 /* enable/disable TDLS */ 1465 CASE_RETURN_STRING(WMI_TDLS_SET_STATE_CMDID); 1466 /* set tdls peer state */ 1467 CASE_RETURN_STRING(WMI_TDLS_PEER_UPDATE_CMDID); 1468 1469 /* Resmgr Configuration */ 1470 /* Adaptive OCS is enabled by default in the FW. 1471 * This command is used to disable FW based adaptive OCS. 1472 */ 1473 CASE_RETURN_STRING 1474 (WMI_RESMGR_ADAPTIVE_OCS_ENABLE_DISABLE_CMDID); 1475 /* set the requested channel time quota for the home channels */ 1476 CASE_RETURN_STRING(WMI_RESMGR_SET_CHAN_TIME_QUOTA_CMDID); 1477 /* set the requested latency for the home channels */ 1478 CASE_RETURN_STRING(WMI_RESMGR_SET_CHAN_LATENCY_CMDID); 1479 1480 /* STA SMPS Configuration */ 1481 /* force SMPS mode */ 1482 CASE_RETURN_STRING(WMI_STA_SMPS_FORCE_MODE_CMDID); 1483 /* set SMPS parameters */ 1484 CASE_RETURN_STRING(WMI_STA_SMPS_PARAM_CMDID); 1485 1486 /* Wlan HB commands */ 1487 /* enalbe/disable wlan HB */ 1488 CASE_RETURN_STRING(WMI_HB_SET_ENABLE_CMDID); 1489 /* set tcp parameters for wlan HB */ 1490 CASE_RETURN_STRING(WMI_HB_SET_TCP_PARAMS_CMDID); 1491 /* set tcp pkt filter for wlan HB */ 1492 CASE_RETURN_STRING(WMI_HB_SET_TCP_PKT_FILTER_CMDID); 1493 /* set udp parameters for wlan HB */ 1494 CASE_RETURN_STRING(WMI_HB_SET_UDP_PARAMS_CMDID); 1495 /* set udp pkt filter for wlan HB */ 1496 CASE_RETURN_STRING(WMI_HB_SET_UDP_PKT_FILTER_CMDID); 1497 1498 /* Wlan RMC commands*/ 1499 /* enable/disable RMC */ 1500 CASE_RETURN_STRING(WMI_RMC_SET_MODE_CMDID); 1501 /* configure action frame period */ 1502 CASE_RETURN_STRING(WMI_RMC_SET_ACTION_PERIOD_CMDID); 1503 /* For debug/future enhancement purposes only, 1504 * configures/finetunes RMC algorithms */ 1505 CASE_RETURN_STRING(WMI_RMC_CONFIG_CMDID); 1506 1507 /* WLAN MHF offload commands */ 1508 /* enable/disable MHF offload */ 1509 CASE_RETURN_STRING(WMI_MHF_OFFLOAD_SET_MODE_CMDID); 1510 /* Plumb routing table for MHF offload */ 1511 CASE_RETURN_STRING(WMI_MHF_OFFLOAD_PLUMB_ROUTING_TBL_CMDID); 1512 1513 /* location scan commands */ 1514 /* start batch scan */ 1515 CASE_RETURN_STRING(WMI_BATCH_SCAN_ENABLE_CMDID); 1516 /* stop batch scan */ 1517 CASE_RETURN_STRING(WMI_BATCH_SCAN_DISABLE_CMDID); 1518 /* get batch scan result */ 1519 CASE_RETURN_STRING(WMI_BATCH_SCAN_TRIGGER_RESULT_CMDID); 1520 /* OEM related cmd */ 1521 CASE_RETURN_STRING(WMI_OEM_REQ_CMDID); 1522 CASE_RETURN_STRING(WMI_OEM_REQUEST_CMDID); 1523 /* NAN request cmd */ 1524 CASE_RETURN_STRING(WMI_NAN_CMDID); 1525 /* Modem power state cmd */ 1526 CASE_RETURN_STRING(WMI_MODEM_POWER_STATE_CMDID); 1527 CASE_RETURN_STRING(WMI_REQUEST_STATS_EXT_CMDID); 1528 CASE_RETURN_STRING(WMI_OBSS_SCAN_ENABLE_CMDID); 1529 CASE_RETURN_STRING(WMI_OBSS_SCAN_DISABLE_CMDID); 1530 CASE_RETURN_STRING(WMI_PEER_GET_ESTIMATED_LINKSPEED_CMDID); 1531 CASE_RETURN_STRING(WMI_ROAM_SCAN_CMD); 1532 CASE_RETURN_STRING(WMI_PDEV_SET_LED_CONFIG_CMDID); 1533 CASE_RETURN_STRING(WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID); 1534 CASE_RETURN_STRING(WMI_CHAN_AVOID_UPDATE_CMDID); 1535 CASE_RETURN_STRING(WMI_COEX_CONFIG_CMDID); 1536 CASE_RETURN_STRING(WMI_WOW_IOAC_ADD_KEEPALIVE_CMDID); 1537 CASE_RETURN_STRING(WMI_WOW_IOAC_DEL_KEEPALIVE_CMDID); 1538 CASE_RETURN_STRING(WMI_WOW_IOAC_ADD_WAKE_PATTERN_CMDID); 1539 CASE_RETURN_STRING(WMI_WOW_IOAC_DEL_WAKE_PATTERN_CMDID); 1540 CASE_RETURN_STRING(WMI_REQUEST_LINK_STATS_CMDID); 1541 CASE_RETURN_STRING(WMI_START_LINK_STATS_CMDID); 1542 CASE_RETURN_STRING(WMI_CLEAR_LINK_STATS_CMDID); 1543 CASE_RETURN_STRING(WMI_GET_FW_MEM_DUMP_CMDID); 1544 CASE_RETURN_STRING(WMI_LPI_MGMT_SNOOPING_CONFIG_CMDID); 1545 CASE_RETURN_STRING(WMI_LPI_START_SCAN_CMDID); 1546 CASE_RETURN_STRING(WMI_LPI_STOP_SCAN_CMDID); 1547 CASE_RETURN_STRING(WMI_EXTSCAN_START_CMDID); 1548 CASE_RETURN_STRING(WMI_EXTSCAN_STOP_CMDID); 1549 CASE_RETURN_STRING 1550 (WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID); 1551 CASE_RETURN_STRING(WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID); 1552 CASE_RETURN_STRING(WMI_EXTSCAN_GET_CACHED_RESULTS_CMDID); 1553 CASE_RETURN_STRING(WMI_EXTSCAN_GET_WLAN_CHANGE_RESULTS_CMDID); 1554 CASE_RETURN_STRING(WMI_EXTSCAN_SET_CAPABILITIES_CMDID); 1555 CASE_RETURN_STRING(WMI_EXTSCAN_GET_CAPABILITIES_CMDID); 1556 CASE_RETURN_STRING(WMI_EXTSCAN_CONFIGURE_HOTLIST_SSID_MONITOR_CMDID); 1557 CASE_RETURN_STRING(WMI_ROAM_SYNCH_COMPLETE); 1558 CASE_RETURN_STRING(WMI_D0_WOW_ENABLE_DISABLE_CMDID); 1559 CASE_RETURN_STRING(WMI_EXTWOW_ENABLE_CMDID); 1560 CASE_RETURN_STRING(WMI_EXTWOW_SET_APP_TYPE1_PARAMS_CMDID); 1561 CASE_RETURN_STRING(WMI_EXTWOW_SET_APP_TYPE2_PARAMS_CMDID); 1562 CASE_RETURN_STRING(WMI_UNIT_TEST_CMDID); 1563 CASE_RETURN_STRING(WMI_ROAM_SET_RIC_REQUEST_CMDID); 1564 CASE_RETURN_STRING(WMI_PDEV_GET_TEMPERATURE_CMDID); 1565 CASE_RETURN_STRING(WMI_SET_DHCP_SERVER_OFFLOAD_CMDID); 1566 CASE_RETURN_STRING(WMI_TPC_CHAINMASK_CONFIG_CMDID); 1567 CASE_RETURN_STRING(WMI_IPA_OFFLOAD_ENABLE_DISABLE_CMDID); 1568 CASE_RETURN_STRING(WMI_SCAN_PROB_REQ_OUI_CMDID); 1569 CASE_RETURN_STRING(WMI_TDLS_SET_OFFCHAN_MODE_CMDID); 1570 CASE_RETURN_STRING(WMI_PDEV_SET_LED_FLASHING_CMDID); 1571 CASE_RETURN_STRING(WMI_MDNS_OFFLOAD_ENABLE_CMDID); 1572 CASE_RETURN_STRING(WMI_MDNS_SET_FQDN_CMDID); 1573 CASE_RETURN_STRING(WMI_MDNS_SET_RESPONSE_CMDID); 1574 CASE_RETURN_STRING(WMI_MDNS_GET_STATS_CMDID); 1575 CASE_RETURN_STRING(WMI_ROAM_INVOKE_CMDID); 1576 CASE_RETURN_STRING(WMI_SET_ANTENNA_DIVERSITY_CMDID); 1577 CASE_RETURN_STRING(WMI_SAP_OFL_ENABLE_CMDID); 1578 CASE_RETURN_STRING(WMI_APFIND_CMDID); 1579 CASE_RETURN_STRING(WMI_PASSPOINT_LIST_CONFIG_CMDID); 1580 CASE_RETURN_STRING(WMI_OCB_SET_SCHED_CMDID); 1581 CASE_RETURN_STRING(WMI_OCB_SET_CONFIG_CMDID); 1582 CASE_RETURN_STRING(WMI_OCB_SET_UTC_TIME_CMDID); 1583 CASE_RETURN_STRING(WMI_OCB_START_TIMING_ADVERT_CMDID); 1584 CASE_RETURN_STRING(WMI_OCB_STOP_TIMING_ADVERT_CMDID); 1585 CASE_RETURN_STRING(WMI_OCB_GET_TSF_TIMER_CMDID); 1586 CASE_RETURN_STRING(WMI_DCC_GET_STATS_CMDID); 1587 CASE_RETURN_STRING(WMI_DCC_CLEAR_STATS_CMDID); 1588 CASE_RETURN_STRING(WMI_DCC_UPDATE_NDL_CMDID); 1589 CASE_RETURN_STRING(WMI_ROAM_FILTER_CMDID); 1590 CASE_RETURN_STRING(WMI_ROAM_SUBNET_CHANGE_CONFIG_CMDID); 1591 CASE_RETURN_STRING(WMI_DEBUG_MESG_FLUSH_CMDID); 1592 CASE_RETURN_STRING(WMI_PEER_SET_RATE_REPORT_CONDITION_CMDID); 1593 CASE_RETURN_STRING(WMI_SOC_SET_PCL_CMDID); 1594 CASE_RETURN_STRING(WMI_SOC_SET_HW_MODE_CMDID); 1595 CASE_RETURN_STRING(WMI_SOC_SET_DUAL_MAC_CONFIG_CMDID); 1596 CASE_RETURN_STRING(WMI_WOW_ENABLE_ICMPV6_NA_FLT_CMDID); 1597 CASE_RETURN_STRING(WMI_DIAG_EVENT_LOG_CONFIG_CMDID); 1598 CASE_RETURN_STRING(WMI_PACKET_FILTER_CONFIG_CMDID); 1599 CASE_RETURN_STRING(WMI_PACKET_FILTER_ENABLE_CMDID); 1600 CASE_RETURN_STRING(WMI_SAP_SET_BLACKLIST_PARAM_CMDID); 1601 CASE_RETURN_STRING(WMI_WOW_UDP_SVC_OFLD_CMDID); 1602 CASE_RETURN_STRING(WMI_MGMT_TX_SEND_CMDID); 1603 CASE_RETURN_STRING(WMI_SOC_SET_ANTENNA_MODE_CMDID); 1604 CASE_RETURN_STRING(WMI_WOW_HOSTWAKEUP_GPIO_PIN_PATTERN_CONFIG_CMDID); 1605 CASE_RETURN_STRING(WMI_AP_PS_EGAP_PARAM_CMDID); 1606 CASE_RETURN_STRING(WMI_PMF_OFFLOAD_SET_SA_QUERY_CMDID); 1607 CASE_RETURN_STRING(WMI_BPF_GET_CAPABILITY_CMDID); 1608 CASE_RETURN_STRING(WMI_BPF_GET_VDEV_STATS_CMDID); 1609 CASE_RETURN_STRING(WMI_BPF_SET_VDEV_INSTRUCTIONS_CMDID); 1610 CASE_RETURN_STRING(WMI_BPF_DEL_VDEV_INSTRUCTIONS_CMDID); 1611 CASE_RETURN_STRING(WMI_NDI_GET_CAP_REQ_CMDID); 1612 CASE_RETURN_STRING(WMI_NDP_INITIATOR_REQ_CMDID); 1613 CASE_RETURN_STRING(WMI_NDP_RESPONDER_REQ_CMDID); 1614 CASE_RETURN_STRING(WMI_NDP_END_REQ_CMDID); 1615 CASE_RETURN_STRING(WMI_PEER_UPDATE_WDS_ENTRY_CMDID); 1616 CASE_RETURN_STRING(WMI_PEER_ADD_PROXY_STA_ENTRY_CMDID); 1617 CASE_RETURN_STRING(WMI_PDEV_FIPS_CMDID); 1618 CASE_RETURN_STRING(WMI_PDEV_SMART_ANT_ENABLE_CMDID); 1619 CASE_RETURN_STRING(WMI_PDEV_SMART_ANT_SET_RX_ANTENNA_CMDID); 1620 CASE_RETURN_STRING(WMI_PDEV_SET_ANTENNA_SWITCH_TABLE_CMDID); 1621 CASE_RETURN_STRING(WMI_PDEV_SET_CTL_TABLE_CMDID); 1622 CASE_RETURN_STRING(WMI_PDEV_SET_MIMOGAIN_TABLE_CMDID); 1623 CASE_RETURN_STRING(WMI_PDEV_GET_TPC_CMDID); 1624 CASE_RETURN_STRING(WMI_MIB_STATS_ENABLE_CMDID); 1625 CASE_RETURN_STRING(WMI_PDEV_GET_ANI_CCK_CONFIG_CMDID); 1626 CASE_RETURN_STRING(WMI_PDEV_GET_ANI_OFDM_CONFIG_CMDID); 1627 CASE_RETURN_STRING(WMI_VDEV_RATEMASK_CMDID); 1628 CASE_RETURN_STRING(WMI_VDEV_ATF_REQUEST_CMDID); 1629 CASE_RETURN_STRING(WMI_VDEV_SET_DSCP_TID_MAP_CMDID); 1630 CASE_RETURN_STRING(WMI_VDEV_FILTER_NEIGHBOR_RX_PACKETS_CMDID); 1631 CASE_RETURN_STRING(WMI_VDEV_SET_QUIET_MODE_CMDID); 1632 CASE_RETURN_STRING(WMI_PEER_SMART_ANT_SET_TX_ANTENNA_CMDID); 1633 CASE_RETURN_STRING(WMI_PEER_SMART_ANT_SET_TRAIN_INFO_CMDID); 1634 CASE_RETURN_STRING(WMI_PEER_SMART_ANT_SET_NODE_CONFIG_OPS_CMDID); 1635 CASE_RETURN_STRING(WMI_PEER_ATF_REQUEST_CMDID); 1636 CASE_RETURN_STRING(WMI_FWTEST_CMDID); 1637 CASE_RETURN_STRING(WMI_QBOOST_CFG_CMDID); 1638 CASE_RETURN_STRING(WMI_PDEV_GET_NFCAL_POWER_CMDID); 1639 CASE_RETURN_STRING(WMI_PDEV_SET_PCL_CMDID); 1640 CASE_RETURN_STRING(WMI_PDEV_SET_HW_MODE_CMDID); 1641 CASE_RETURN_STRING(WMI_PDEV_SET_MAC_CONFIG_CMDID); 1642 CASE_RETURN_STRING(WMI_PDEV_SET_ANTENNA_MODE_CMDID); 1643 CASE_RETURN_STRING(WMI_ROAM_SET_MBO_PARAM_CMDID); 1644 CASE_RETURN_STRING(WMI_CHAN_AVOID_RPT_ALLOW_CMDID); 1645 CASE_RETURN_STRING(WMI_SET_PERIODIC_CHANNEL_STATS_CONFIG_CMDID); 1646 CASE_RETURN_STRING(WMI_VDEV_SET_CUSTOM_AGGR_SIZE_CMDID); 1647 CASE_RETURN_STRING(WMI_PDEV_WAL_POWER_DEBUG_CMDID); 1648 CASE_RETURN_STRING(WMI_PEER_BWF_REQUEST_CMDID); 1649 CASE_RETURN_STRING(WMI_DBGLOG_TIME_STAMP_SYNC_CMDID); 1650 CASE_RETURN_STRING(WMI_P2P_LISTEN_OFFLOAD_START_CMDID); 1651 CASE_RETURN_STRING(WMI_P2P_LISTEN_OFFLOAD_STOP_CMDID); 1652 CASE_RETURN_STRING(WMI_PEER_REORDER_QUEUE_SETUP_CMDID); 1653 CASE_RETURN_STRING(WMI_PEER_REORDER_QUEUE_REMOVE_CMDID); 1654 CASE_RETURN_STRING(WMI_SET_MULTIPLE_MCAST_FILTER_CMDID); 1655 CASE_RETURN_STRING(WMI_READ_DATA_FROM_FLASH_CMDID); 1656 CASE_RETURN_STRING(WMI_PDEV_SET_REORDER_TIMEOUT_VAL_CMDID); 1657 CASE_RETURN_STRING(WMI_PEER_SET_RX_BLOCKSIZE_CMDID); 1658 CASE_RETURN_STRING(WMI_PDEV_SET_WAKEUP_CONFIG_CMDID); 1659 CASE_RETURN_STRING(WMI_PDEV_GET_ANTDIV_STATUS_CMDID); 1660 CASE_RETURN_STRING(WMI_PEER_ANTDIV_INFO_REQ_CMDID); 1661 CASE_RETURN_STRING(WMI_MNT_FILTER_CMDID); 1662 CASE_RETURN_STRING(WMI_PDEV_GET_CHIP_POWER_STATS_CMDID); 1663 CASE_RETURN_STRING(WMI_COEX_GET_ANTENNA_ISOLATION_CMDID); 1664 CASE_RETURN_STRING(WMI_PDEV_SET_STATS_THRESHOLD_CMDID); 1665 CASE_RETURN_STRING(WMI_REQUEST_WLAN_STATS_CMDID); 1666 CASE_RETURN_STRING(WMI_VDEV_ENCRYPT_DECRYPT_DATA_REQ_CMDID); 1667 } 1668 1669 return "Invalid WMI cmd"; 1670 } 1671 1672 static inline void wma_log_cmd_id(uint32_t cmd_id, uint32_t tag) 1673 { 1674 WMI_LOGD("Send WMI command:%s command_id:%d htc_tag:%d\n", 1675 wmi_id_to_name(cmd_id), cmd_id, tag); 1676 } 1677 #else 1678 static uint8_t *wmi_id_to_name(uint32_t wmi_command) 1679 { 1680 return "Invalid WMI cmd"; 1681 } 1682 #endif 1683 1684 1685 /** 1686 * wmi_is_runtime_pm_cmd() - check if a cmd is from suspend resume sequence 1687 * @cmd: command to check 1688 * 1689 * Return: true if the command is part of the suspend resume sequence. 1690 */ 1691 #ifdef CONFIG_MCL 1692 static bool wmi_is_runtime_pm_cmd(uint32_t cmd_id) 1693 { 1694 switch (cmd_id) { 1695 case WMI_WOW_ENABLE_CMDID: 1696 case WMI_PDEV_SUSPEND_CMDID: 1697 case WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID: 1698 case WMI_WOW_ADD_WAKE_PATTERN_CMDID: 1699 case WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID: 1700 case WMI_PDEV_RESUME_CMDID: 1701 case WMI_WOW_DEL_WAKE_PATTERN_CMDID: 1702 case WMI_D0_WOW_ENABLE_DISABLE_CMDID: 1703 return true; 1704 1705 default: 1706 return false; 1707 } 1708 } 1709 1710 /** 1711 * wmi_is_pm_resume_cmd() - check if a cmd is part of the resume sequence 1712 * @cmd_id: command to check 1713 * 1714 * Return: true if the command is part of the resume sequence. 1715 */ 1716 static bool wmi_is_pm_resume_cmd(uint32_t cmd_id) 1717 { 1718 switch (cmd_id) { 1719 case WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID: 1720 case WMI_PDEV_RESUME_CMDID: 1721 return true; 1722 1723 default: 1724 return false; 1725 } 1726 } 1727 #else 1728 static bool wmi_is_runtime_pm_cmd(uint32_t cmd_id) 1729 { 1730 return false; 1731 } 1732 static bool wmi_is_pm_resume_cmd(uint32_t cmd_id) 1733 { 1734 return false; 1735 } 1736 #endif 1737 1738 /** 1739 * wmi_unified_cmd_send() - WMI command API 1740 * @wmi_handle: handle to wmi 1741 * @buf: wmi buf 1742 * @len: wmi buffer length 1743 * @cmd_id: wmi command id 1744 * 1745 * Note, it is NOT safe to access buf after calling this function! 1746 * 1747 * Return: 0 on success 1748 */ 1749 QDF_STATUS wmi_unified_cmd_send(wmi_unified_t wmi_handle, wmi_buf_t buf, 1750 uint32_t len, uint32_t cmd_id) 1751 { 1752 HTC_PACKET *pkt; 1753 A_STATUS status; 1754 uint16_t htc_tag = 0; 1755 1756 if (wmi_get_runtime_pm_inprogress(wmi_handle)) { 1757 if (wmi_is_runtime_pm_cmd(cmd_id)) 1758 htc_tag = HTC_TX_PACKET_TAG_AUTO_PM; 1759 } else if (qdf_atomic_read(&wmi_handle->is_target_suspended) && 1760 (!wmi_is_pm_resume_cmd(cmd_id))) { 1761 QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR, 1762 "%s: Target is suspended", __func__); 1763 QDF_ASSERT(0); 1764 return QDF_STATUS_E_BUSY; 1765 } 1766 if (wmi_handle->wmi_stopinprogress) { 1767 QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR, 1768 "WMI stop in progress\n"); 1769 return QDF_STATUS_E_INVAL; 1770 } 1771 1772 #ifndef WMI_NON_TLV_SUPPORT 1773 /* Do sanity check on the TLV parameter structure */ 1774 if (wmi_handle->target_type == WMI_TLV_TARGET) { 1775 void *buf_ptr = (void *)qdf_nbuf_data(buf); 1776 1777 if (wmitlv_check_command_tlv_params(NULL, buf_ptr, len, cmd_id) 1778 != 0) { 1779 QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR, 1780 "\nERROR: %s: Invalid WMI Param Buffer for Cmd:%d", 1781 __func__, cmd_id); 1782 return QDF_STATUS_E_INVAL; 1783 } 1784 } 1785 #endif 1786 1787 if (qdf_nbuf_push_head(buf, sizeof(WMI_CMD_HDR)) == NULL) { 1788 QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR, 1789 "%s, Failed to send cmd %x, no memory", 1790 __func__, cmd_id); 1791 return QDF_STATUS_E_NOMEM; 1792 } 1793 1794 WMI_SET_FIELD(qdf_nbuf_data(buf), WMI_CMD_HDR, COMMANDID, cmd_id); 1795 1796 qdf_atomic_inc(&wmi_handle->pending_cmds); 1797 if (qdf_atomic_read(&wmi_handle->pending_cmds) >= WMI_MAX_CMDS) { 1798 QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR, 1799 "\n%s: hostcredits = %d", __func__, 1800 wmi_get_host_credits(wmi_handle)); 1801 htc_dump_counter_info(wmi_handle->htc_handle); 1802 qdf_atomic_dec(&wmi_handle->pending_cmds); 1803 QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR, 1804 "%s: MAX %d WMI Pending cmds reached.", __func__, 1805 WMI_MAX_CMDS); 1806 QDF_BUG(0); 1807 return QDF_STATUS_E_BUSY; 1808 } 1809 1810 pkt = qdf_mem_malloc(sizeof(*pkt)); 1811 if (!pkt) { 1812 qdf_atomic_dec(&wmi_handle->pending_cmds); 1813 QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR, 1814 "%s, Failed to alloc htc packet %x, no memory", 1815 __func__, cmd_id); 1816 return QDF_STATUS_E_NOMEM; 1817 } 1818 1819 SET_HTC_PACKET_INFO_TX(pkt, 1820 NULL, 1821 qdf_nbuf_data(buf), len + sizeof(WMI_CMD_HDR), 1822 wmi_handle->wmi_endpoint_id, htc_tag); 1823 1824 SET_HTC_PACKET_NET_BUF_CONTEXT(pkt, buf); 1825 #ifdef CONFIG_MCL 1826 wma_log_cmd_id(cmd_id, htc_tag); 1827 #endif 1828 1829 #ifdef WMI_INTERFACE_EVENT_LOGGING 1830 if (wmi_handle->log_info.wmi_logging_enable) { 1831 qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock); 1832 /*Record 16 bytes of WMI cmd data - 1833 * * exclude TLV and WMI headers */ 1834 if (wmi_handle->log_info.is_management_record(cmd_id)) { 1835 WMI_MGMT_COMMAND_RECORD(wmi_handle, cmd_id, 1836 ((uint32_t *) qdf_nbuf_data(buf) + 1837 wmi_handle->log_info.buf_offset_command)); 1838 } else { 1839 WMI_COMMAND_RECORD(wmi_handle, cmd_id, 1840 ((uint32_t *) qdf_nbuf_data(buf) + 1841 wmi_handle->log_info.buf_offset_command)); 1842 } 1843 qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock); 1844 } 1845 #endif 1846 1847 status = htc_send_pkt(wmi_handle->htc_handle, pkt); 1848 1849 if (A_OK != status) { 1850 qdf_atomic_dec(&wmi_handle->pending_cmds); 1851 QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR, 1852 "%s %d, htc_send_pkt failed", __func__, __LINE__); 1853 qdf_mem_free(pkt); 1854 1855 } 1856 if (status) 1857 return QDF_STATUS_E_FAILURE; 1858 1859 return QDF_STATUS_SUCCESS; 1860 } 1861 1862 /** 1863 * wmi_unified_get_event_handler_ix() - gives event handler's index 1864 * @wmi_handle: handle to wmi 1865 * @event_id: wmi event id 1866 * 1867 * Return: event handler's index 1868 */ 1869 static int wmi_unified_get_event_handler_ix(wmi_unified_t wmi_handle, 1870 uint32_t event_id) 1871 { 1872 uint32_t idx = 0; 1873 int32_t invalid_idx = -1; 1874 1875 for (idx = 0; (idx < wmi_handle->max_event_idx && 1876 idx < WMI_UNIFIED_MAX_EVENT); ++idx) { 1877 if (wmi_handle->event_id[idx] == event_id && 1878 wmi_handle->event_handler[idx] != NULL) { 1879 return idx; 1880 } 1881 } 1882 1883 return invalid_idx; 1884 } 1885 1886 /** 1887 * wmi_unified_register_event_handler() - register wmi event handler 1888 * @wmi_handle: handle to wmi 1889 * @event_id: wmi event id 1890 * @handler_func: wmi event handler function 1891 * @rx_ctx: rx execution context for wmi rx events 1892 * 1893 * Return: 0 on success 1894 */ 1895 int wmi_unified_register_event_handler(wmi_unified_t wmi_handle, 1896 uint32_t event_id, 1897 wmi_unified_event_handler handler_func, 1898 uint8_t rx_ctx) 1899 { 1900 uint32_t idx = 0; 1901 uint32_t evt_id; 1902 1903 #ifndef CONFIG_MCL 1904 if (event_id >= wmi_events_max || 1905 wmi_handle->wmi_events[event_id] == WMI_EVENT_ID_INVALID) { 1906 qdf_print("%s: Event id %d is unavailable\n", 1907 __func__, event_id); 1908 return QDF_STATUS_E_FAILURE; 1909 } 1910 evt_id = wmi_handle->wmi_events[event_id]; 1911 #else 1912 evt_id = event_id; 1913 #endif 1914 if (wmi_unified_get_event_handler_ix(wmi_handle, evt_id) != -1) { 1915 qdf_print("%s : event handler already registered 0x%x\n", 1916 __func__, evt_id); 1917 return QDF_STATUS_E_FAILURE; 1918 } 1919 if (wmi_handle->max_event_idx == WMI_UNIFIED_MAX_EVENT) { 1920 qdf_print("%s : no more event handlers 0x%x\n", 1921 __func__, evt_id); 1922 return QDF_STATUS_E_FAILURE; 1923 } 1924 idx = wmi_handle->max_event_idx; 1925 wmi_handle->event_handler[idx] = handler_func; 1926 wmi_handle->event_id[idx] = evt_id; 1927 qdf_spin_lock_bh(&wmi_handle->ctx_lock); 1928 wmi_handle->ctx[idx] = rx_ctx; 1929 qdf_spin_unlock_bh(&wmi_handle->ctx_lock); 1930 wmi_handle->max_event_idx++; 1931 1932 return 0; 1933 } 1934 1935 /** 1936 * wmi_unified_unregister_event_handler() - unregister wmi event handler 1937 * @wmi_handle: handle to wmi 1938 * @event_id: wmi event id 1939 * 1940 * Return: 0 on success 1941 */ 1942 int wmi_unified_unregister_event_handler(wmi_unified_t wmi_handle, 1943 uint32_t event_id) 1944 { 1945 uint32_t idx = 0; 1946 uint32_t evt_id; 1947 1948 #ifndef CONFIG_MCL 1949 if (event_id >= wmi_events_max || 1950 wmi_handle->wmi_events[event_id] == WMI_EVENT_ID_INVALID) { 1951 qdf_print("%s: Event id %d is unavailable\n", 1952 __func__, event_id); 1953 return QDF_STATUS_E_FAILURE; 1954 } 1955 evt_id = wmi_handle->wmi_events[event_id]; 1956 #else 1957 evt_id = event_id; 1958 #endif 1959 1960 idx = wmi_unified_get_event_handler_ix(wmi_handle, evt_id); 1961 if (idx == -1) { 1962 qdf_print("%s : event handler is not registered: evt id 0x%x\n", 1963 __func__, evt_id); 1964 return QDF_STATUS_E_FAILURE; 1965 } 1966 wmi_handle->event_handler[idx] = NULL; 1967 wmi_handle->event_id[idx] = 0; 1968 --wmi_handle->max_event_idx; 1969 wmi_handle->event_handler[idx] = 1970 wmi_handle->event_handler[wmi_handle->max_event_idx]; 1971 wmi_handle->event_id[idx] = 1972 wmi_handle->event_id[wmi_handle->max_event_idx]; 1973 1974 return 0; 1975 } 1976 1977 /** 1978 * wmi_process_fw_event_default_ctx() - process in default caller context 1979 * @wmi_handle: handle to wmi 1980 * @htc_packet: pointer to htc packet 1981 * @exec_ctx: execution context for wmi fw event 1982 * 1983 * Event process by below function will be in default caller context. 1984 * wmi internally provides rx work thread processing context. 1985 * 1986 * Return: none 1987 */ 1988 static void wmi_process_fw_event_default_ctx(struct wmi_unified *wmi_handle, 1989 HTC_PACKET *htc_packet, uint8_t exec_ctx) 1990 { 1991 wmi_buf_t evt_buf; 1992 evt_buf = (wmi_buf_t) htc_packet->pPktContext; 1993 1994 #ifndef CONFIG_MCL 1995 wmi_handle->rx_ops.wma_process_fw_event_handler_cbk 1996 (wmi_handle->scn_handle, evt_buf, exec_ctx); 1997 #else 1998 wmi_handle->rx_ops.wma_process_fw_event_handler_cbk(wmi_handle, 1999 evt_buf, exec_ctx); 2000 #endif 2001 2002 return; 2003 } 2004 2005 /** 2006 * wmi_process_fw_event_worker_thread_ctx() - process in worker thread context 2007 * @wmi_handle: handle to wmi 2008 * @htc_packet: pointer to htc packet 2009 * 2010 * Event process by below function will be in worker thread context. 2011 * Use this method for events which are not critical and not 2012 * handled in protocol stack. 2013 * 2014 * Return: none 2015 */ 2016 static void wmi_process_fw_event_worker_thread_ctx 2017 (struct wmi_unified *wmi_handle, HTC_PACKET *htc_packet) 2018 { 2019 wmi_buf_t evt_buf; 2020 uint32_t id; 2021 uint8_t *data; 2022 2023 evt_buf = (wmi_buf_t) htc_packet->pPktContext; 2024 id = WMI_GET_FIELD(qdf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID); 2025 data = qdf_nbuf_data(evt_buf); 2026 2027 #ifdef WMI_INTERFACE_EVENT_LOGGING 2028 if (wmi_handle->log_info.wmi_logging_enable) { 2029 qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock); 2030 /* Exclude 4 bytes of TLV header */ 2031 WMI_RX_EVENT_RECORD(wmi_handle, id, ((uint8_t *) data + 2032 wmi_handle->log_info.buf_offset_event)); 2033 qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock); 2034 } 2035 #endif 2036 qdf_spin_lock_bh(&wmi_handle->eventq_lock); 2037 qdf_nbuf_queue_add(&wmi_handle->event_queue, evt_buf); 2038 qdf_spin_unlock_bh(&wmi_handle->eventq_lock); 2039 schedule_work(&wmi_handle->rx_event_work); 2040 return; 2041 } 2042 2043 /** 2044 * wmi_control_rx() - process fw events callbacks 2045 * @ctx: handle to wmi 2046 * @htc_packet: pointer to htc packet 2047 * 2048 * Return: none 2049 */ 2050 static void wmi_control_rx(void *ctx, HTC_PACKET *htc_packet) 2051 { 2052 struct wmi_unified *wmi_handle = (struct wmi_unified *)ctx; 2053 wmi_buf_t evt_buf; 2054 uint32_t id; 2055 uint32_t idx = 0; 2056 enum wmi_rx_exec_ctx exec_ctx; 2057 2058 evt_buf = (wmi_buf_t) htc_packet->pPktContext; 2059 id = WMI_GET_FIELD(qdf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID); 2060 idx = wmi_unified_get_event_handler_ix(wmi_handle, id); 2061 if (qdf_unlikely(idx == A_ERROR)) { 2062 qdf_print 2063 ("%s :event handler is not registered: event id 0x%x\n", 2064 __func__, id); 2065 qdf_nbuf_free(evt_buf); 2066 return; 2067 } 2068 qdf_spin_lock_bh(&wmi_handle->ctx_lock); 2069 exec_ctx = wmi_handle->ctx[idx]; 2070 qdf_spin_unlock_bh(&wmi_handle->ctx_lock); 2071 2072 if (exec_ctx == WMI_RX_WORK_CTX) { 2073 wmi_process_fw_event_worker_thread_ctx 2074 (wmi_handle, htc_packet); 2075 } else if (exec_ctx > WMI_RX_WORK_CTX) { 2076 wmi_process_fw_event_default_ctx 2077 (wmi_handle, htc_packet, exec_ctx); 2078 } else { 2079 qdf_print("%s :Invalid event context %d\n", __func__, exec_ctx); 2080 qdf_nbuf_free(evt_buf); 2081 } 2082 2083 } 2084 2085 /** 2086 * wmi_process_fw_event() - process any fw event 2087 * @wmi_handle: wmi handle 2088 * @evt_buf: fw event buffer 2089 * 2090 * This function process fw event in caller context 2091 * 2092 * Return: none 2093 */ 2094 void wmi_process_fw_event(struct wmi_unified *wmi_handle, wmi_buf_t evt_buf) 2095 { 2096 __wmi_control_rx(wmi_handle, evt_buf); 2097 } 2098 2099 /** 2100 * __wmi_control_rx() - process serialize wmi event callback 2101 * @wmi_handle: wmi handle 2102 * @evt_buf: fw event buffer 2103 * 2104 * Return: none 2105 */ 2106 void __wmi_control_rx(struct wmi_unified *wmi_handle, wmi_buf_t evt_buf) 2107 { 2108 uint32_t id; 2109 uint8_t *data; 2110 uint32_t len; 2111 void *wmi_cmd_struct_ptr = NULL; 2112 #ifndef WMI_NON_TLV_SUPPORT 2113 int tlv_ok_status = 0; 2114 #endif 2115 uint32_t idx = 0; 2116 2117 id = WMI_GET_FIELD(qdf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID); 2118 2119 if (qdf_nbuf_pull_head(evt_buf, sizeof(WMI_CMD_HDR)) == NULL) 2120 goto end; 2121 2122 data = qdf_nbuf_data(evt_buf); 2123 len = qdf_nbuf_len(evt_buf); 2124 2125 #ifndef WMI_NON_TLV_SUPPORT 2126 if (wmi_handle->target_type == WMI_TLV_TARGET) { 2127 /* Validate and pad(if necessary) the TLVs */ 2128 tlv_ok_status = 2129 wmitlv_check_and_pad_event_tlvs(wmi_handle->scn_handle, 2130 data, len, id, 2131 &wmi_cmd_struct_ptr); 2132 if (tlv_ok_status != 0) { 2133 QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR, 2134 "%s: Error: id=0x%d, wmitlv check status=%d\n", 2135 __func__, id, tlv_ok_status); 2136 goto end; 2137 } 2138 } 2139 #endif 2140 2141 idx = wmi_unified_get_event_handler_ix(wmi_handle, id); 2142 if (idx == A_ERROR) { 2143 QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR, 2144 "%s : event handler is not registered: event id 0x%x\n", 2145 __func__, id); 2146 goto end; 2147 } 2148 #ifdef WMI_INTERFACE_EVENT_LOGGING 2149 if (wmi_handle->log_info.wmi_logging_enable) { 2150 qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock); 2151 /* Exclude 4 bytes of TLV header */ 2152 if (wmi_handle->log_info.is_management_record(id)) { 2153 WMI_MGMT_EVENT_RECORD(wmi_handle, id, ((uint8_t *) data 2154 + wmi_handle->log_info.buf_offset_event)); 2155 } else { 2156 WMI_EVENT_RECORD(wmi_handle, id, ((uint8_t *) data + 2157 wmi_handle->log_info.buf_offset_event)); 2158 } 2159 qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock); 2160 } 2161 #endif 2162 /* Call the WMI registered event handler */ 2163 if (wmi_handle->target_type == WMI_TLV_TARGET) 2164 wmi_handle->event_handler[idx] (wmi_handle->scn_handle, 2165 wmi_cmd_struct_ptr, len); 2166 else 2167 wmi_handle->event_handler[idx] (wmi_handle->scn_handle, 2168 data, len); 2169 2170 end: 2171 /* Free event buffer and allocated event tlv */ 2172 #ifndef WMI_NON_TLV_SUPPORT 2173 if (wmi_handle->target_type == WMI_TLV_TARGET) 2174 wmitlv_free_allocated_event_tlvs(id, &wmi_cmd_struct_ptr); 2175 #endif 2176 2177 qdf_nbuf_free(evt_buf); 2178 2179 } 2180 2181 /** 2182 * wmi_rx_event_work() - process rx event in rx work queue context 2183 * @work: rx work queue struct 2184 * 2185 * This function process any fw event to serialize it through rx worker thread. 2186 * 2187 * Return: none 2188 */ 2189 static void wmi_rx_event_work(struct work_struct *work) 2190 { 2191 struct wmi_unified *wmi = container_of(work, struct wmi_unified, 2192 rx_event_work); 2193 wmi_buf_t buf; 2194 2195 qdf_spin_lock_bh(&wmi->eventq_lock); 2196 buf = qdf_nbuf_queue_remove(&wmi->event_queue); 2197 qdf_spin_unlock_bh(&wmi->eventq_lock); 2198 while (buf) { 2199 __wmi_control_rx(wmi, buf); 2200 qdf_spin_lock_bh(&wmi->eventq_lock); 2201 buf = qdf_nbuf_queue_remove(&wmi->event_queue); 2202 qdf_spin_unlock_bh(&wmi->eventq_lock); 2203 } 2204 } 2205 2206 #ifdef FEATURE_RUNTIME_PM 2207 /** 2208 * wmi_runtime_pm_init() - initialize runtime pm wmi variables 2209 * @wmi_handle: wmi context 2210 */ 2211 static void wmi_runtime_pm_init(struct wmi_unified *wmi_handle) 2212 { 2213 qdf_atomic_init(&wmi_handle->runtime_pm_inprogress); 2214 } 2215 2216 /** 2217 * wmi_set_runtime_pm_inprogress() - set runtime pm progress flag 2218 * @wmi_handle: wmi context 2219 * @val: runtime pm progress flag 2220 */ 2221 void wmi_set_runtime_pm_inprogress(wmi_unified_t wmi_handle, A_BOOL val) 2222 { 2223 qdf_atomic_set(&wmi_handle->runtime_pm_inprogress, val); 2224 } 2225 2226 /** 2227 * wmi_get_runtime_pm_inprogress() - get runtime pm progress flag 2228 * @wmi_handle: wmi context 2229 */ 2230 inline bool wmi_get_runtime_pm_inprogress(wmi_unified_t wmi_handle) 2231 { 2232 return qdf_atomic_read(&wmi_handle->runtime_pm_inprogress); 2233 } 2234 #else 2235 static void wmi_runtime_pm_init(struct wmi_unified *wmi_handle) 2236 { 2237 } 2238 #endif 2239 2240 /** 2241 * wmi_unified_attach() - attach for unified WMI 2242 * @scn_handle: handle to SCN 2243 * @osdev: OS device context 2244 * @target_type: TLV or not-TLV based target 2245 * @use_cookie: cookie based allocation enabled/disabled 2246 * @ops: umac rx callbacks 2247 * 2248 * @Return: wmi handle. 2249 */ 2250 void *wmi_unified_attach(void *scn_handle, 2251 osdev_t osdev, enum wmi_target_type target_type, 2252 bool use_cookie, struct wmi_rx_ops *rx_ops) 2253 { 2254 struct wmi_unified *wmi_handle; 2255 2256 #ifdef CONFIG_MCL 2257 wmi_handle = 2258 (struct wmi_unified *)os_malloc(NULL, 2259 sizeof(struct wmi_unified), 2260 GFP_ATOMIC); 2261 #else 2262 wmi_handle = 2263 (struct wmi_unified *) qdf_mem_malloc( 2264 sizeof(struct wmi_unified)); 2265 #endif 2266 if (wmi_handle == NULL) { 2267 qdf_print("allocation of wmi handle failed %zu\n", 2268 sizeof(struct wmi_unified)); 2269 return NULL; 2270 } 2271 OS_MEMZERO(wmi_handle, sizeof(struct wmi_unified)); 2272 wmi_handle->scn_handle = scn_handle; 2273 qdf_atomic_init(&wmi_handle->pending_cmds); 2274 qdf_atomic_init(&wmi_handle->is_target_suspended); 2275 wmi_runtime_pm_init(wmi_handle); 2276 qdf_spinlock_create(&wmi_handle->eventq_lock); 2277 qdf_nbuf_queue_init(&wmi_handle->event_queue); 2278 INIT_WORK(&wmi_handle->rx_event_work, wmi_rx_event_work); 2279 #ifdef WMI_INTERFACE_EVENT_LOGGING 2280 if (QDF_STATUS_SUCCESS == wmi_log_init(wmi_handle)) { 2281 qdf_spinlock_create(&wmi_handle->log_info.wmi_record_lock); 2282 wmi_debugfs_init(wmi_handle); 2283 } 2284 #endif 2285 /* Attach mc_thread context processing function */ 2286 wmi_handle->rx_ops.wma_process_fw_event_handler_cbk = 2287 rx_ops->wma_process_fw_event_handler_cbk; 2288 wmi_handle->target_type = target_type; 2289 if (target_type == WMI_TLV_TARGET) 2290 wmi_tlv_attach(wmi_handle); 2291 else 2292 wmi_non_tlv_attach(wmi_handle); 2293 /* Assign target cookie capablity */ 2294 wmi_handle->use_cookie = use_cookie; 2295 wmi_handle->osdev = osdev; 2296 wmi_handle->wmi_stopinprogress = 0; 2297 qdf_spinlock_create(&wmi_handle->ctx_lock); 2298 2299 return wmi_handle; 2300 } 2301 2302 /** 2303 * wmi_unified_detach() - detach for unified WMI 2304 * 2305 * @wmi_handle : handle to wmi. 2306 * 2307 * @Return: none. 2308 */ 2309 void wmi_unified_detach(struct wmi_unified *wmi_handle) 2310 { 2311 wmi_buf_t buf; 2312 2313 cancel_work_sync(&wmi_handle->rx_event_work); 2314 2315 wmi_debugfs_remove(wmi_handle); 2316 2317 buf = qdf_nbuf_queue_remove(&wmi_handle->event_queue); 2318 while (buf) { 2319 qdf_nbuf_free(buf); 2320 buf = qdf_nbuf_queue_remove(&wmi_handle->event_queue); 2321 } 2322 2323 #ifdef WMI_INTERFACE_EVENT_LOGGING 2324 wmi_log_buffer_free(wmi_handle); 2325 #endif 2326 2327 qdf_spinlock_destroy(&wmi_handle->eventq_lock); 2328 qdf_spinlock_destroy(&wmi_handle->ctx_lock); 2329 OS_FREE(wmi_handle); 2330 wmi_handle = NULL; 2331 } 2332 2333 /** 2334 * wmi_unified_remove_work() - detach for WMI work 2335 * @wmi_handle: handle to WMI 2336 * 2337 * A function that does not fully detach WMI, but just remove work 2338 * queue items associated with it. This is used to make sure that 2339 * before any other processing code that may destroy related contexts 2340 * (HTC, etc), work queue processing on WMI has already been stopped. 2341 * 2342 * Return: None 2343 */ 2344 void 2345 wmi_unified_remove_work(struct wmi_unified *wmi_handle) 2346 { 2347 wmi_buf_t buf; 2348 2349 QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_INFO, 2350 "Enter: %s", __func__); 2351 cancel_work_sync(&wmi_handle->rx_event_work); 2352 qdf_spin_lock_bh(&wmi_handle->eventq_lock); 2353 buf = qdf_nbuf_queue_remove(&wmi_handle->event_queue); 2354 while (buf) { 2355 qdf_nbuf_free(buf); 2356 buf = qdf_nbuf_queue_remove(&wmi_handle->event_queue); 2357 } 2358 qdf_spin_unlock_bh(&wmi_handle->eventq_lock); 2359 QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_INFO, 2360 "Done: %s", __func__); 2361 } 2362 2363 /** 2364 * wmi_htc_tx_complete() - Process htc tx completion 2365 * 2366 * @ctx: handle to wmi 2367 * @htc_packet: pointer to htc packet 2368 * 2369 * @Return: none. 2370 */ 2371 static void wmi_htc_tx_complete(void *ctx, HTC_PACKET *htc_pkt) 2372 { 2373 struct wmi_unified *wmi_handle = (struct wmi_unified *)ctx; 2374 wmi_buf_t wmi_cmd_buf = GET_HTC_PACKET_NET_BUF_CONTEXT(htc_pkt); 2375 u_int8_t *buf_ptr; 2376 u_int32_t len; 2377 #ifdef WMI_INTERFACE_EVENT_LOGGING 2378 uint32_t cmd_id; 2379 #endif 2380 2381 ASSERT(wmi_cmd_buf); 2382 #ifdef WMI_INTERFACE_EVENT_LOGGING 2383 if (wmi_handle->log_info.wmi_logging_enable) { 2384 cmd_id = WMI_GET_FIELD(qdf_nbuf_data(wmi_cmd_buf), 2385 WMI_CMD_HDR, COMMANDID); 2386 2387 qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock); 2388 /* Record 16 bytes of WMI cmd tx complete data 2389 - exclude TLV and WMI headers */ 2390 if (wmi_handle->log_info.is_management_record(cmd_id)) { 2391 WMI_MGMT_COMMAND_TX_CMP_RECORD(wmi_handle, cmd_id, 2392 ((uint32_t *) qdf_nbuf_data(wmi_cmd_buf) + 2393 wmi_handle->log_info.buf_offset_command)); 2394 } else { 2395 WMI_COMMAND_TX_CMP_RECORD(wmi_handle, cmd_id, 2396 ((uint32_t *) qdf_nbuf_data(wmi_cmd_buf) + 2397 wmi_handle->log_info.buf_offset_command)); 2398 } 2399 2400 qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock); 2401 } 2402 #endif 2403 buf_ptr = (u_int8_t *) wmi_buf_data(wmi_cmd_buf); 2404 len = qdf_nbuf_len(wmi_cmd_buf); 2405 qdf_mem_zero(buf_ptr, len); 2406 qdf_nbuf_free(wmi_cmd_buf); 2407 qdf_mem_free(htc_pkt); 2408 qdf_atomic_dec(&wmi_handle->pending_cmds); 2409 } 2410 2411 /** 2412 * wmi_get_host_credits() - WMI API to get updated host_credits 2413 * 2414 * @wmi_handle: handle to WMI. 2415 * 2416 * @Return: updated host_credits. 2417 */ 2418 int 2419 wmi_unified_connect_htc_service(struct wmi_unified *wmi_handle, 2420 void *htc_handle) 2421 { 2422 2423 int status; 2424 HTC_SERVICE_CONNECT_RESP response; 2425 HTC_SERVICE_CONNECT_REQ connect; 2426 2427 OS_MEMZERO(&connect, sizeof(connect)); 2428 OS_MEMZERO(&response, sizeof(response)); 2429 2430 /* meta data is unused for now */ 2431 connect.pMetaData = NULL; 2432 connect.MetaDataLength = 0; 2433 /* these fields are the same for all service endpoints */ 2434 connect.EpCallbacks.pContext = wmi_handle; 2435 connect.EpCallbacks.EpTxCompleteMultiple = 2436 NULL /* Control path completion ar6000_tx_complete */; 2437 connect.EpCallbacks.EpRecv = wmi_control_rx /* Control path rx */; 2438 connect.EpCallbacks.EpRecvRefill = NULL /* ar6000_rx_refill */; 2439 connect.EpCallbacks.EpSendFull = NULL /* ar6000_tx_queue_full */; 2440 connect.EpCallbacks.EpTxComplete = 2441 wmi_htc_tx_complete /* ar6000_tx_queue_full */; 2442 2443 /* connect to control service */ 2444 connect.service_id = WMI_CONTROL_SVC; 2445 status = htc_connect_service(htc_handle, &connect, 2446 &response); 2447 2448 if (status != EOK) { 2449 qdf_print 2450 ("Failed to connect to WMI CONTROL service status:%d \n", 2451 status); 2452 return status; 2453 } 2454 wmi_handle->wmi_endpoint_id = response.Endpoint; 2455 wmi_handle->htc_handle = htc_handle; 2456 wmi_handle->max_msg_len = response.MaxMsgLength; 2457 2458 return EOK; 2459 } 2460 2461 /** 2462 * wmi_get_host_credits() - WMI API to get updated host_credits 2463 * 2464 * @wmi_handle: handle to WMI. 2465 * 2466 * @Return: updated host_credits. 2467 */ 2468 int wmi_get_host_credits(wmi_unified_t wmi_handle) 2469 { 2470 int host_credits = 0; 2471 2472 htc_get_control_endpoint_tx_host_credits(wmi_handle->htc_handle, 2473 &host_credits); 2474 return host_credits; 2475 } 2476 2477 /** 2478 * wmi_get_pending_cmds() - WMI API to get WMI Pending Commands in the HTC 2479 * queue 2480 * 2481 * @wmi_handle: handle to WMI. 2482 * 2483 * @Return: Pending Commands in the HTC queue. 2484 */ 2485 int wmi_get_pending_cmds(wmi_unified_t wmi_handle) 2486 { 2487 return qdf_atomic_read(&wmi_handle->pending_cmds); 2488 } 2489 2490 /** 2491 * wmi_set_target_suspend() - WMI API to set target suspend state 2492 * 2493 * @wmi_handle: handle to WMI. 2494 * @val: suspend state boolean. 2495 * 2496 * @Return: none. 2497 */ 2498 void wmi_set_target_suspend(wmi_unified_t wmi_handle, A_BOOL val) 2499 { 2500 qdf_atomic_set(&wmi_handle->is_target_suspended, val); 2501 } 2502 2503 #ifndef CONFIG_MCL 2504 /** 2505 * API to flush all the previous packets associated with the wmi endpoint 2506 * 2507 * @param wmi_handle : handle to WMI. 2508 */ 2509 void 2510 wmi_flush_endpoint(wmi_unified_t wmi_handle) 2511 { 2512 htc_flush_endpoint(wmi_handle->htc_handle, 2513 wmi_handle->wmi_endpoint_id, 0); 2514 } 2515 2516 /** 2517 * generic function to block unified WMI command 2518 * @param wmi_handle : handle to WMI. 2519 * @return 0 on success and -ve on failure. 2520 */ 2521 int 2522 wmi_stop(wmi_unified_t wmi_handle) 2523 { 2524 QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_INFO, 2525 "WMI Stop\n"); 2526 wmi_handle->wmi_stopinprogress = 1; 2527 return 0; 2528 } 2529 #endif 2530