1 /* 2 * Copyright (c) 2014-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 #include <scheduler_api.h> 20 #include <scheduler_core.h> 21 #include <qdf_atomic.h> 22 #include <qdf_module.h> 23 24 QDF_STATUS scheduler_disable(void) 25 { 26 struct scheduler_ctx *sched_ctx; 27 28 sched_debug("Disabling Scheduler"); 29 30 sched_ctx = scheduler_get_context(); 31 QDF_BUG(sched_ctx); 32 if (!sched_ctx) 33 return QDF_STATUS_E_INVAL; 34 35 /* send shutdown signal to scheduler thread */ 36 qdf_atomic_set_bit(MC_SHUTDOWN_EVENT_MASK, &sched_ctx->sch_event_flag); 37 qdf_atomic_set_bit(MC_POST_EVENT_MASK, &sched_ctx->sch_event_flag); 38 qdf_wake_up_interruptible(&sched_ctx->sch_wait_queue); 39 40 /* wait for scheduler thread to shutdown */ 41 qdf_wait_single_event(&sched_ctx->sch_shutdown, 0); 42 sched_ctx->sch_thread = NULL; 43 44 /* flush any unprocessed scheduler messages */ 45 scheduler_queues_flush(sched_ctx); 46 47 return QDF_STATUS_SUCCESS; 48 } 49 50 static inline void scheduler_watchdog_notify(struct scheduler_ctx *sched) 51 { 52 char symbol[QDF_SYMBOL_LEN]; 53 54 if (sched->watchdog_callback) 55 qdf_sprint_symbol(symbol, sched->watchdog_callback); 56 57 sched_err("WLAN_BUG_RCA: Callback %s (type 0x%x) exceeded its allotted time of %ds", 58 sched->watchdog_callback ? symbol : "<null>", 59 sched->watchdog_msg_type, SCHEDULER_WATCHDOG_TIMEOUT / 1000); 60 } 61 62 #ifdef CONFIG_SLUB_DEBUG_ON 63 static void scheduler_watchdog_timeout(void *arg) 64 { 65 struct scheduler_ctx *sched = arg; 66 67 scheduler_watchdog_notify(sched); 68 if (sched->sch_thread) 69 qdf_print_thread_trace(sched->sch_thread); 70 71 /* avoid crashing during shutdown */ 72 if (qdf_atomic_test_bit(MC_SHUTDOWN_EVENT_MASK, &sched->sch_event_flag)) 73 return; 74 75 QDF_DEBUG_PANIC("Going down for Scheduler Watchdog Bite!"); 76 } 77 #else 78 static void scheduler_watchdog_timeout(void *arg) 79 { 80 scheduler_watchdog_notify((struct scheduler_ctx *)arg); 81 } 82 #endif 83 84 QDF_STATUS scheduler_enable(void) 85 { 86 struct scheduler_ctx *sched_ctx; 87 88 sched_debug("Enabling Scheduler"); 89 90 sched_ctx = scheduler_get_context(); 91 QDF_BUG(sched_ctx); 92 if (!sched_ctx) 93 return QDF_STATUS_E_INVAL; 94 95 qdf_atomic_clear_bit(MC_SHUTDOWN_EVENT_MASK, 96 &sched_ctx->sch_event_flag); 97 qdf_atomic_clear_bit(MC_POST_EVENT_MASK, 98 &sched_ctx->sch_event_flag); 99 100 /* create the scheduler thread */ 101 sched_ctx->sch_thread = qdf_create_thread(scheduler_thread, sched_ctx, 102 "scheduler_thread"); 103 if (!sched_ctx->sch_thread) { 104 sched_err("Failed to create scheduler thread"); 105 return QDF_STATUS_E_RESOURCES; 106 } 107 108 sched_debug("Scheduler thread created"); 109 110 /* wait for the scheduler thread to startup */ 111 qdf_wake_up_process(sched_ctx->sch_thread); 112 qdf_wait_single_event(&sched_ctx->sch_start_event, 0); 113 114 sched_debug("Scheduler thread started"); 115 116 return QDF_STATUS_SUCCESS; 117 } 118 119 QDF_STATUS scheduler_init(void) 120 { 121 QDF_STATUS status; 122 struct scheduler_ctx *sched_ctx; 123 124 sched_debug("Initializing Scheduler"); 125 126 status = scheduler_create_ctx(); 127 if (QDF_IS_STATUS_ERROR(status)) { 128 sched_err("Failed to create context; status:%d", status); 129 return status; 130 } 131 132 sched_ctx = scheduler_get_context(); 133 QDF_BUG(sched_ctx); 134 if (!sched_ctx) { 135 status = QDF_STATUS_E_FAILURE; 136 goto ctx_destroy; 137 } 138 139 status = scheduler_queues_init(sched_ctx); 140 if (QDF_IS_STATUS_ERROR(status)) { 141 sched_err("Failed to init queues; status:%d", status); 142 goto ctx_destroy; 143 } 144 145 status = qdf_event_create(&sched_ctx->sch_start_event); 146 if (QDF_IS_STATUS_ERROR(status)) { 147 sched_err("Failed to create start event; status:%d", status); 148 goto queues_deinit; 149 } 150 151 status = qdf_event_create(&sched_ctx->sch_shutdown); 152 if (QDF_IS_STATUS_ERROR(status)) { 153 sched_err("Failed to create shutdown event; status:%d", status); 154 goto start_event_destroy; 155 } 156 157 status = qdf_event_create(&sched_ctx->resume_sch_event); 158 if (QDF_IS_STATUS_ERROR(status)) { 159 sched_err("Failed to create resume event; status:%d", status); 160 goto shutdown_event_destroy; 161 } 162 163 qdf_spinlock_create(&sched_ctx->sch_thread_lock); 164 qdf_init_waitqueue_head(&sched_ctx->sch_wait_queue); 165 sched_ctx->sch_event_flag = 0; 166 qdf_timer_init(NULL, 167 &sched_ctx->watchdog_timer, 168 &scheduler_watchdog_timeout, 169 sched_ctx, 170 QDF_TIMER_TYPE_SW); 171 172 qdf_register_mc_timer_callback(scheduler_mc_timer_callback); 173 174 return QDF_STATUS_SUCCESS; 175 176 shutdown_event_destroy: 177 qdf_event_destroy(&sched_ctx->sch_shutdown); 178 179 start_event_destroy: 180 qdf_event_destroy(&sched_ctx->sch_start_event); 181 182 queues_deinit: 183 scheduler_queues_deinit(sched_ctx); 184 185 ctx_destroy: 186 scheduler_destroy_ctx(); 187 188 return status; 189 } 190 191 QDF_STATUS scheduler_deinit(void) 192 { 193 QDF_STATUS status; 194 struct scheduler_ctx *sched_ctx; 195 196 sched_debug("Deinitializing Scheduler"); 197 198 sched_ctx = scheduler_get_context(); 199 QDF_BUG(sched_ctx); 200 if (!sched_ctx) 201 return QDF_STATUS_E_INVAL; 202 203 qdf_timer_free(&sched_ctx->watchdog_timer); 204 qdf_spinlock_destroy(&sched_ctx->sch_thread_lock); 205 qdf_event_destroy(&sched_ctx->resume_sch_event); 206 qdf_event_destroy(&sched_ctx->sch_shutdown); 207 qdf_event_destroy(&sched_ctx->sch_start_event); 208 209 status = scheduler_queues_deinit(sched_ctx); 210 if (QDF_IS_STATUS_ERROR(status)) 211 sched_err("Failed to deinit queues; status:%d", status); 212 213 status = scheduler_destroy_ctx(); 214 if (QDF_IS_STATUS_ERROR(status)) 215 sched_err("Failed to destroy context; status:%d", status); 216 217 return QDF_STATUS_SUCCESS; 218 } 219 220 QDF_STATUS scheduler_post_msg_by_priority(uint32_t qid, 221 struct scheduler_msg *msg, 222 bool is_high_priority) 223 { 224 uint8_t qidx; 225 struct scheduler_mq_type *target_mq; 226 struct scheduler_msg *queue_msg; 227 struct scheduler_ctx *sched_ctx; 228 uint16_t src_id; 229 uint16_t dest_id; 230 uint16_t que_id; 231 232 QDF_BUG(msg); 233 if (!msg) 234 return QDF_STATUS_E_INVAL; 235 236 sched_ctx = scheduler_get_context(); 237 QDF_BUG(sched_ctx); 238 if (!sched_ctx) 239 return QDF_STATUS_E_INVAL; 240 241 if (!sched_ctx->sch_thread) { 242 sched_err("Cannot post message; scheduler thread is stopped"); 243 return QDF_STATUS_E_FAILURE; 244 } 245 246 if (msg->reserved != 0 && msg->reserved != SYS_MSG_COOKIE) { 247 QDF_DEBUG_PANIC("Scheduler messages must be initialized"); 248 return QDF_STATUS_E_FAILURE; 249 } 250 251 dest_id = scheduler_get_dest_id(qid); 252 src_id = scheduler_get_src_id(qid); 253 que_id = scheduler_get_que_id(qid); 254 255 if (que_id >= QDF_MODULE_ID_MAX || src_id >= QDF_MODULE_ID_MAX || 256 dest_id >= QDF_MODULE_ID_MAX) { 257 sched_err("Src_id/Dest_id invalid, cannot post message"); 258 return QDF_STATUS_E_FAILURE; 259 } 260 /* Target_If is a special message queue in phase 3 convergence beacause 261 * its used by both legacy WMA and as well as new UMAC components which 262 * directly populate callback handlers in message body. 263 * 1) WMA legacy messages should not have callback 264 * 2) New target_if message needs to have valid callback 265 * Clear callback handler for legacy WMA messages such that in case 266 * if someone is sending legacy WMA message from stack which has 267 * uninitialized callback then its handled properly. Also change 268 * legacy WMA message queue id to target_if queue such that its always 269 * handled in right order. 270 */ 271 if (QDF_MODULE_ID_WMA == que_id) { 272 msg->callback = NULL; 273 /* change legacy WMA message id to new target_if mq id */ 274 que_id = QDF_MODULE_ID_TARGET_IF; 275 } 276 qdf_mtrace(src_id, dest_id, msg->type, 0xFF, 0); 277 278 qidx = sched_ctx->queue_ctx.scheduler_msg_qid_to_qidx[que_id]; 279 if (qidx >= SCHEDULER_NUMBER_OF_MSG_QUEUE) { 280 sched_err("Scheduler is deinitialized ignore msg"); 281 return QDF_STATUS_E_FAILURE; 282 } 283 284 if (!sched_ctx->queue_ctx.scheduler_msg_process_fn[qidx]) { 285 QDF_DEBUG_PANIC("callback not registered for qid[%d]", que_id); 286 return QDF_STATUS_E_FAILURE; 287 } 288 289 target_mq = &(sched_ctx->queue_ctx.sch_msg_q[qidx]); 290 291 queue_msg = scheduler_core_msg_dup(msg); 292 if (!queue_msg) 293 return QDF_STATUS_E_NOMEM; 294 295 if (is_high_priority) 296 scheduler_mq_put_front(target_mq, queue_msg); 297 else 298 scheduler_mq_put(target_mq, queue_msg); 299 300 qdf_atomic_set_bit(MC_POST_EVENT_MASK, &sched_ctx->sch_event_flag); 301 qdf_wake_up_interruptible(&sched_ctx->sch_wait_queue); 302 303 return QDF_STATUS_SUCCESS; 304 } 305 306 QDF_STATUS scheduler_register_module(QDF_MODULE_ID qid, 307 scheduler_msg_process_fn_t callback) 308 { 309 struct scheduler_mq_ctx *ctx; 310 struct scheduler_ctx *sched_ctx = scheduler_get_context(); 311 312 sched_enter(); 313 314 QDF_BUG(sched_ctx); 315 if (!sched_ctx) 316 return QDF_STATUS_E_FAILURE; 317 318 if (sched_ctx->sch_last_qidx >= SCHEDULER_NUMBER_OF_MSG_QUEUE) { 319 sched_err("Already registered max %d no of message queues", 320 SCHEDULER_NUMBER_OF_MSG_QUEUE); 321 return QDF_STATUS_E_FAILURE; 322 } 323 324 ctx = &sched_ctx->queue_ctx; 325 ctx->scheduler_msg_qid_to_qidx[qid] = sched_ctx->sch_last_qidx; 326 ctx->sch_msg_q[sched_ctx->sch_last_qidx].qid = qid; 327 ctx->scheduler_msg_process_fn[sched_ctx->sch_last_qidx] = callback; 328 sched_ctx->sch_last_qidx++; 329 330 sched_exit(); 331 332 return QDF_STATUS_SUCCESS; 333 } 334 335 QDF_STATUS scheduler_deregister_module(QDF_MODULE_ID qid) 336 { 337 struct scheduler_mq_ctx *ctx; 338 struct scheduler_ctx *sched_ctx = scheduler_get_context(); 339 uint8_t qidx; 340 341 sched_enter(); 342 343 QDF_BUG(sched_ctx); 344 if (!sched_ctx) 345 return QDF_STATUS_E_FAILURE; 346 347 ctx = &sched_ctx->queue_ctx; 348 qidx = ctx->scheduler_msg_qid_to_qidx[qid]; 349 ctx->scheduler_msg_process_fn[qidx] = NULL; 350 sched_ctx->sch_last_qidx--; 351 ctx->scheduler_msg_qid_to_qidx[qidx] = SCHEDULER_NUMBER_OF_MSG_QUEUE; 352 353 sched_exit(); 354 355 return QDF_STATUS_SUCCESS; 356 } 357 358 void scheduler_resume(void) 359 { 360 struct scheduler_ctx *sched_ctx = scheduler_get_context(); 361 362 if (sched_ctx) 363 qdf_event_set(&sched_ctx->resume_sch_event); 364 } 365 366 void scheduler_register_hdd_suspend_callback(hdd_suspend_callback callback) 367 { 368 struct scheduler_ctx *sched_ctx = scheduler_get_context(); 369 370 if (sched_ctx) 371 sched_ctx->hdd_callback = callback; 372 } 373 void scheduler_wake_up_controller_thread(void) 374 { 375 struct scheduler_ctx *sched_ctx = scheduler_get_context(); 376 377 if (sched_ctx) 378 qdf_wake_up_interruptible(&sched_ctx->sch_wait_queue); 379 } 380 void scheduler_set_event_mask(uint32_t event_mask) 381 { 382 struct scheduler_ctx *sched_ctx = scheduler_get_context(); 383 384 if (sched_ctx) 385 qdf_atomic_set_bit(event_mask, &sched_ctx->sch_event_flag); 386 } 387 388 void scheduler_clear_event_mask(uint32_t event_mask) 389 { 390 struct scheduler_ctx *sched_ctx = scheduler_get_context(); 391 392 if (sched_ctx) 393 qdf_atomic_clear_bit(event_mask, &sched_ctx->sch_event_flag); 394 } 395 396 QDF_STATUS scheduler_target_if_mq_handler(struct scheduler_msg *msg) 397 { 398 QDF_STATUS status; 399 struct scheduler_ctx *sched_ctx = scheduler_get_context(); 400 QDF_STATUS (*target_if_msg_handler)(struct scheduler_msg *); 401 402 QDF_BUG(msg); 403 if (!msg) 404 return QDF_STATUS_E_FAILURE; 405 406 QDF_BUG(sched_ctx); 407 if (!sched_ctx) 408 return QDF_STATUS_E_FAILURE; 409 410 target_if_msg_handler = msg->callback; 411 412 /* Target_If is a special message queue in phase 3 convergence beacause 413 * its used by both legacy WMA and as well as new UMAC components. New 414 * UMAC components directly pass their message handlers as callback in 415 * message body. 416 * 1) All Legacy WMA messages do not contain message callback so invoke 417 * registered legacy WMA handler. Scheduler message posting APIs 418 * makes sure legacy WMA messages do not have callbacks. 419 * 2) For new messages which have valid callbacks invoke their callbacks 420 * directly. 421 */ 422 if (!target_if_msg_handler) 423 status = sched_ctx->legacy_wma_handler(msg); 424 else 425 status = target_if_msg_handler(msg); 426 427 return status; 428 } 429 430 QDF_STATUS scheduler_os_if_mq_handler(struct scheduler_msg *msg) 431 { 432 QDF_STATUS (*os_if_msg_handler)(struct scheduler_msg *); 433 434 QDF_BUG(msg); 435 if (!msg) 436 return QDF_STATUS_E_FAILURE; 437 438 os_if_msg_handler = msg->callback; 439 440 QDF_BUG(os_if_msg_handler); 441 if (!os_if_msg_handler) 442 return QDF_STATUS_E_FAILURE; 443 444 os_if_msg_handler(msg); 445 446 return QDF_STATUS_SUCCESS; 447 } 448 449 QDF_STATUS scheduler_timer_q_mq_handler(struct scheduler_msg *msg) 450 { 451 struct scheduler_ctx *sched_ctx = scheduler_get_context(); 452 qdf_mc_timer_callback_t timer_callback; 453 454 QDF_BUG(msg); 455 if (!msg) 456 return QDF_STATUS_E_FAILURE; 457 458 QDF_BUG(sched_ctx); 459 if (!sched_ctx) 460 return QDF_STATUS_E_FAILURE; 461 462 /* legacy sys message handler? */ 463 if (msg->reserved != SYS_MSG_COOKIE || msg->type != SYS_MSG_ID_MC_TIMER) 464 return sched_ctx->legacy_sys_handler(msg); 465 466 timer_callback = msg->callback; 467 QDF_BUG(timer_callback); 468 if (!timer_callback) 469 return QDF_STATUS_E_FAILURE; 470 471 timer_callback(msg->bodyptr); 472 473 return QDF_STATUS_SUCCESS; 474 } 475 476 QDF_STATUS scheduler_mlme_mq_handler(struct scheduler_msg *msg) 477 { 478 scheduler_msg_process_fn_t mlme_msg_handler; 479 480 QDF_BUG(msg); 481 if (!msg) 482 return QDF_STATUS_E_FAILURE; 483 484 mlme_msg_handler = msg->callback; 485 486 QDF_BUG(mlme_msg_handler); 487 if (!mlme_msg_handler) 488 return QDF_STATUS_E_FAILURE; 489 490 mlme_msg_handler(msg); 491 492 return QDF_STATUS_SUCCESS; 493 } 494 495 QDF_STATUS scheduler_scan_mq_handler(struct scheduler_msg *msg) 496 { 497 QDF_STATUS (*scan_q_msg_handler)(struct scheduler_msg *); 498 499 QDF_BUG(msg); 500 if (!msg) 501 return QDF_STATUS_E_FAILURE; 502 503 scan_q_msg_handler = msg->callback; 504 505 QDF_BUG(scan_q_msg_handler); 506 if (!scan_q_msg_handler) 507 return QDF_STATUS_E_FAILURE; 508 509 scan_q_msg_handler(msg); 510 511 return QDF_STATUS_SUCCESS; 512 } 513 514 QDF_STATUS scheduler_register_wma_legacy_handler(scheduler_msg_process_fn_t 515 wma_callback) 516 { 517 struct scheduler_ctx *sched_ctx = scheduler_get_context(); 518 519 QDF_BUG(sched_ctx); 520 if (!sched_ctx) 521 return QDF_STATUS_E_FAILURE; 522 523 sched_ctx->legacy_wma_handler = wma_callback; 524 525 return QDF_STATUS_SUCCESS; 526 } 527 528 QDF_STATUS scheduler_register_sys_legacy_handler(scheduler_msg_process_fn_t 529 sys_callback) 530 { 531 struct scheduler_ctx *sched_ctx = scheduler_get_context(); 532 533 QDF_BUG(sched_ctx); 534 if (!sched_ctx) 535 return QDF_STATUS_E_FAILURE; 536 537 sched_ctx->legacy_sys_handler = sys_callback; 538 539 return QDF_STATUS_SUCCESS; 540 } 541 542 QDF_STATUS scheduler_deregister_wma_legacy_handler(void) 543 { 544 struct scheduler_ctx *sched_ctx = scheduler_get_context(); 545 546 QDF_BUG(sched_ctx); 547 if (!sched_ctx) 548 return QDF_STATUS_E_FAILURE; 549 550 sched_ctx->legacy_wma_handler = NULL; 551 552 return QDF_STATUS_SUCCESS; 553 } 554 555 QDF_STATUS scheduler_deregister_sys_legacy_handler(void) 556 { 557 struct scheduler_ctx *sched_ctx = scheduler_get_context(); 558 559 QDF_BUG(sched_ctx); 560 if (!sched_ctx) 561 return QDF_STATUS_E_FAILURE; 562 563 sched_ctx->legacy_sys_handler = NULL; 564 565 return QDF_STATUS_SUCCESS; 566 } 567 568 static QDF_STATUS scheduler_msg_flush_noop(struct scheduler_msg *msg) 569 { 570 return QDF_STATUS_SUCCESS; 571 } 572 573 void scheduler_mc_timer_callback(qdf_mc_timer_t *timer) 574 { 575 struct scheduler_msg msg = {0}; 576 QDF_STATUS status; 577 578 qdf_mc_timer_callback_t callback = NULL; 579 void *user_data = NULL; 580 QDF_TIMER_TYPE type = QDF_TIMER_TYPE_SW; 581 582 QDF_BUG(timer); 583 if (!timer) 584 return; 585 586 qdf_spin_lock_irqsave(&timer->platform_info.spinlock); 587 588 switch (timer->state) { 589 case QDF_TIMER_STATE_STARTING: 590 /* we are in this state because someone just started the timer, 591 * MC timer got started and expired, but the time content have 592 * not been updated this is a rare race condition! 593 */ 594 timer->state = QDF_TIMER_STATE_STOPPED; 595 status = QDF_STATUS_E_ALREADY; 596 break; 597 598 case QDF_TIMER_STATE_STOPPED: 599 status = QDF_STATUS_E_ALREADY; 600 break; 601 602 case QDF_TIMER_STATE_UNUSED: 603 status = QDF_STATUS_E_EXISTS; 604 break; 605 606 case QDF_TIMER_STATE_RUNNING: 607 /* need to go to stop state here because the call-back function 608 * may restart timer (to emulate periodic timer) 609 */ 610 timer->state = QDF_TIMER_STATE_STOPPED; 611 /* copy the relevant timer information to local variables; 612 * once we exits from this critical section, the timer content 613 * may be modified by other tasks 614 */ 615 callback = timer->callback; 616 user_data = timer->user_data; 617 type = timer->type; 618 status = QDF_STATUS_SUCCESS; 619 break; 620 621 default: 622 QDF_ASSERT(0); 623 status = QDF_STATUS_E_FAULT; 624 break; 625 } 626 627 qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock); 628 629 if (QDF_IS_STATUS_ERROR(status)) { 630 sched_debug("MC timer fired but is not running; skip callback"); 631 return; 632 } 633 634 qdf_try_allowing_sleep(type); 635 636 QDF_BUG(callback); 637 if (!callback) 638 return; 639 640 /* serialize to scheduler controller thread */ 641 msg.type = SYS_MSG_ID_MC_TIMER; 642 msg.reserved = SYS_MSG_COOKIE; 643 msg.callback = callback; 644 msg.bodyptr = user_data; 645 msg.bodyval = 0; 646 647 /* bodyptr points to user data, do not free it during msg flush */ 648 msg.flush_callback = scheduler_msg_flush_noop; 649 650 status = scheduler_post_message(QDF_MODULE_ID_SCHEDULER, 651 QDF_MODULE_ID_SCHEDULER, 652 QDF_MODULE_ID_SYS, &msg); 653 if (QDF_IS_STATUS_ERROR(status)) 654 sched_err("Could not enqueue timer to timer queue"); 655 } 656 657 QDF_STATUS scheduler_get_queue_size(QDF_MODULE_ID qid, uint32_t *size) 658 { 659 uint8_t qidx; 660 struct scheduler_mq_type *target_mq; 661 struct scheduler_ctx *sched_ctx; 662 663 sched_ctx = scheduler_get_context(); 664 if (!sched_ctx) 665 return QDF_STATUS_E_INVAL; 666 667 /* WMA also uses the target_if queue, so replace the QID */ 668 if (QDF_MODULE_ID_WMA == qid) 669 qid = QDF_MODULE_ID_TARGET_IF; 670 671 qidx = sched_ctx->queue_ctx.scheduler_msg_qid_to_qidx[qid]; 672 if (qidx >= SCHEDULER_NUMBER_OF_MSG_QUEUE) { 673 sched_err("Scheduler is deinitialized"); 674 return QDF_STATUS_E_FAILURE; 675 } 676 677 target_mq = &(sched_ctx->queue_ctx.sch_msg_q[qidx]); 678 679 *size = qdf_list_size(&target_mq->mq_list); 680 681 return QDF_STATUS_SUCCESS; 682 } 683 684 QDF_STATUS scheduler_post_message_debug(QDF_MODULE_ID src_id, 685 QDF_MODULE_ID dest_id, 686 QDF_MODULE_ID que_id, 687 struct scheduler_msg *msg, 688 int line, 689 const char *func) 690 { 691 QDF_STATUS status; 692 693 status = scheduler_post_msg(scheduler_get_qid(src_id, dest_id, que_id), 694 msg); 695 696 if (QDF_IS_STATUS_ERROR(status)) 697 sched_err("couldn't post from %d to %d - called from %d, %s", 698 src_id, dest_id, line, func); 699 700 return status; 701 } 702 703 qdf_export_symbol(scheduler_post_message_debug); 704