1 /* 2 * Copyright (c) 2014-2020 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <linux/module.h> 20 #include <qdf_lock.h> 21 #include <qdf_trace.h> 22 #include <qdf_module.h> 23 24 #include <qdf_types.h> 25 #include <i_host_diag_core_event.h> 26 #ifdef FEATURE_RUNTIME_PM 27 #include <cds_api.h> 28 #include <hif.h> 29 #endif 30 #include <i_qdf_lock.h> 31 #include <linux/suspend.h> 32 33 /** 34 * qdf_mutex_create() - Initialize a mutex 35 * @m: mutex to initialize 36 * 37 * Returns: QDF_STATUS 38 * =0 success 39 * else fail status 40 */ 41 #undef qdf_mutex_create 42 QDF_STATUS qdf_mutex_create(qdf_mutex_t *lock, const char *func, int line) 43 { 44 /* check for invalid pointer */ 45 if (!lock) { 46 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 47 "%s: NULL pointer passed in", __func__); 48 return QDF_STATUS_E_FAULT; 49 } 50 /* check for 'already initialized' lock */ 51 if (LINUX_LOCK_COOKIE == lock->cookie) { 52 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 53 "%s: already initialized lock", __func__); 54 return QDF_STATUS_E_BUSY; 55 } 56 57 if (in_interrupt()) { 58 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 59 "%s cannot be called from interrupt context!!!", 60 __func__); 61 return QDF_STATUS_E_FAULT; 62 } 63 64 qdf_lock_stats_create(&lock->stats, func, line); 65 66 /* initialize new lock */ 67 mutex_init(&lock->m_lock); 68 lock->cookie = LINUX_LOCK_COOKIE; 69 lock->state = LOCK_RELEASED; 70 lock->process_id = 0; 71 lock->refcount = 0; 72 73 return QDF_STATUS_SUCCESS; 74 } 75 qdf_export_symbol(qdf_mutex_create); 76 77 /** 78 * qdf_mutex_acquire() - acquire a QDF lock 79 * @lock: Pointer to the opaque lock object to acquire 80 * 81 * A lock object is acquired by calling qdf_mutex_acquire(). If the lock 82 * is already locked, the calling thread shall block until the lock becomes 83 * available. This operation shall return with the lock object referenced by 84 * lock in the locked state with the calling thread as its owner. 85 * 86 * Return: 87 * QDF_STATUS_SUCCESS: lock was successfully initialized 88 * QDF failure reason codes: lock is not initialized and can't be used 89 */ 90 QDF_STATUS qdf_mutex_acquire(qdf_mutex_t *lock) 91 { 92 int rc; 93 /* check for invalid pointer */ 94 if (!lock) { 95 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 96 "%s: NULL pointer passed in", __func__); 97 QDF_ASSERT(0); 98 return QDF_STATUS_E_FAULT; 99 } 100 /* check if lock refers to an initialized object */ 101 if (LINUX_LOCK_COOKIE != lock->cookie) { 102 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 103 "%s: uninitialized lock", __func__); 104 QDF_ASSERT(0); 105 return QDF_STATUS_E_INVAL; 106 } 107 108 if (in_interrupt()) { 109 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 110 "%s cannot be called from interrupt context!!!", 111 __func__); 112 QDF_ASSERT(0); 113 return QDF_STATUS_E_FAULT; 114 } 115 if ((lock->process_id == current->pid) && 116 (lock->state == LOCK_ACQUIRED)) { 117 lock->refcount++; 118 #ifdef QDF_NESTED_LOCK_DEBUG 119 pe_err("%s: %x %d %d", __func__, lock, current->pid, 120 lock->refcount); 121 #endif 122 return QDF_STATUS_SUCCESS; 123 } 124 125 BEFORE_LOCK(lock, mutex_is_locked(&lock->m_lock)); 126 /* acquire a Lock */ 127 mutex_lock(&lock->m_lock); 128 AFTER_LOCK(lock, __func__); 129 rc = mutex_is_locked(&lock->m_lock); 130 if (rc == 0) { 131 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 132 "%s: unable to lock mutex (rc = %d)", __func__, rc); 133 QDF_ASSERT(0); 134 return QDF_STATUS_E_FAILURE; 135 } 136 #ifdef QDF_NESTED_LOCK_DEBUG 137 pe_err("%s: %x %d", __func__, lock, current->pid); 138 #endif 139 if (LOCK_DESTROYED != lock->state) { 140 lock->process_id = current->pid; 141 lock->refcount++; 142 lock->state = LOCK_ACQUIRED; 143 return QDF_STATUS_SUCCESS; 144 } 145 146 /* lock is already destroyed */ 147 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 148 "%s: Lock is already destroyed", __func__); 149 mutex_unlock(&lock->m_lock); 150 QDF_ASSERT(0); 151 return QDF_STATUS_E_FAILURE; 152 } 153 qdf_export_symbol(qdf_mutex_acquire); 154 155 /** 156 * qdf_mutex_release() - release a QDF lock 157 * @lock: Pointer to the opaque lock object to be released 158 * 159 * qdf_mutex_release() function shall release the lock object 160 * referenced by 'lock'. 161 * 162 * If a thread attempts to release a lock that it unlocked or is not 163 * initialized, an error is returned. 164 * 165 * Return: 166 * QDF_STATUS_SUCCESS: lock was successfully initialized 167 * QDF failure reason codes: lock is not initialized and can't be used 168 */ 169 QDF_STATUS qdf_mutex_release(qdf_mutex_t *lock) 170 { 171 /* check for invalid pointer */ 172 if (!lock) { 173 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 174 "%s: NULL pointer passed in", __func__); 175 QDF_ASSERT(0); 176 return QDF_STATUS_E_FAULT; 177 } 178 179 /* check if lock refers to an uninitialized object */ 180 if (LINUX_LOCK_COOKIE != lock->cookie) { 181 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 182 "%s: uninitialized lock", __func__); 183 QDF_ASSERT(0); 184 return QDF_STATUS_E_INVAL; 185 } 186 187 if (in_interrupt()) { 188 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 189 "%s cannot be called from interrupt context!!!", 190 __func__); 191 QDF_ASSERT(0); 192 return QDF_STATUS_E_FAULT; 193 } 194 195 /* current_thread = get_current_thread_id(); 196 * Check thread ID of caller against thread ID 197 * of the thread which acquire the lock 198 */ 199 if (lock->process_id != current->pid) { 200 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 201 "%s: current task pid does not match original task pid!!", 202 __func__); 203 #ifdef QDF_NESTED_LOCK_DEBUG 204 pe_err("%s: Lock held by=%d being released by=%d", 205 __func__, lock->process_id, current->pid); 206 #endif 207 QDF_ASSERT(0); 208 return QDF_STATUS_E_PERM; 209 } 210 if ((lock->process_id == current->pid) && 211 (lock->state == LOCK_ACQUIRED)) { 212 if (lock->refcount > 0) 213 lock->refcount--; 214 } 215 #ifdef QDF_NESTED_LOCK_DEBUG 216 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "%s: %x %d %d", __func__, lock, lock->process_id, 217 lock->refcount); 218 #endif 219 if (lock->refcount) 220 return QDF_STATUS_SUCCESS; 221 222 lock->process_id = 0; 223 lock->refcount = 0; 224 lock->state = LOCK_RELEASED; 225 /* release a Lock */ 226 BEFORE_UNLOCK(lock, 0); 227 mutex_unlock(&lock->m_lock); 228 #ifdef QDF_NESTED_LOCK_DEBUG 229 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "%s: Freeing lock %x %d %d", lock, lock->process_id, 230 lock->refcount); 231 #endif 232 return QDF_STATUS_SUCCESS; 233 } 234 qdf_export_symbol(qdf_mutex_release); 235 236 /** 237 * qdf_wake_lock_name() - This function returns the name of the wakelock 238 * @lock: Pointer to the wakelock 239 * 240 * This function returns the name of the wakelock 241 * 242 * Return: Pointer to the name if it is valid or a default string 243 */ 244 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) 245 const char *qdf_wake_lock_name(qdf_wake_lock_t *lock) 246 { 247 if (lock) 248 return lock->lock.name; 249 return "UNNAMED_WAKELOCK"; 250 } 251 #else 252 const char *qdf_wake_lock_name(qdf_wake_lock_t *lock) 253 { 254 return "NO_WAKELOCK_SUPPORT"; 255 } 256 #endif 257 qdf_export_symbol(qdf_wake_lock_name); 258 259 /** 260 * qdf_wake_lock_create() - initializes a wake lock 261 * @lock: The wake lock to initialize 262 * @name: Name of wake lock 263 * 264 * Return: 265 * QDF status success: if wake lock is initialized 266 * QDF status failure: if wake lock was not initialized 267 */ 268 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 110)) || \ 269 defined(WAKEUP_SOURCE_DEV) 270 QDF_STATUS qdf_wake_lock_create(qdf_wake_lock_t *lock, const char *name) 271 { 272 qdf_mem_zero(lock, sizeof(*lock)); 273 lock->priv = wakeup_source_register(lock->lock.dev, name); 274 if (!(lock->priv)) { 275 QDF_BUG(0); 276 return QDF_STATUS_E_FAILURE; 277 } 278 279 lock->lock = *(lock->priv); 280 281 return QDF_STATUS_SUCCESS; 282 } 283 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) 284 QDF_STATUS qdf_wake_lock_create(qdf_wake_lock_t *lock, const char *name) 285 { 286 wakeup_source_init(&(lock->lock), name); 287 lock->priv = &(lock->lock); 288 return QDF_STATUS_SUCCESS; 289 } 290 #else 291 QDF_STATUS qdf_wake_lock_create(qdf_wake_lock_t *lock, const char *name) 292 { 293 return QDF_STATUS_SUCCESS; 294 } 295 #endif 296 qdf_export_symbol(qdf_wake_lock_create); 297 298 /** 299 * qdf_wake_lock_acquire() - acquires a wake lock 300 * @lock: The wake lock to acquire 301 * @reason: Reason for wakelock 302 * 303 * Return: 304 * QDF status success: if wake lock is acquired 305 * QDF status failure: if wake lock was not acquired 306 */ 307 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) 308 QDF_STATUS qdf_wake_lock_acquire(qdf_wake_lock_t *lock, uint32_t reason) 309 { 310 host_diag_log_wlock(reason, qdf_wake_lock_name(lock), 311 WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT, 312 WIFI_POWER_EVENT_WAKELOCK_TAKEN); 313 __pm_stay_awake(lock->priv); 314 315 return QDF_STATUS_SUCCESS; 316 } 317 #else 318 QDF_STATUS qdf_wake_lock_acquire(qdf_wake_lock_t *lock, uint32_t reason) 319 { 320 return QDF_STATUS_SUCCESS; 321 } 322 #endif 323 qdf_export_symbol(qdf_wake_lock_acquire); 324 325 /** 326 * qdf_wake_lock_timeout_acquire() - acquires a wake lock with a timeout 327 * @lock: The wake lock to acquire 328 * @reason: Reason for wakelock 329 * 330 * Return: 331 * QDF status success: if wake lock is acquired 332 * QDF status failure: if wake lock was not acquired 333 */ 334 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) 335 QDF_STATUS qdf_wake_lock_timeout_acquire(qdf_wake_lock_t *lock, uint32_t msec) 336 { 337 pm_wakeup_ws_event(lock->priv, msec, true); 338 return QDF_STATUS_SUCCESS; 339 } 340 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) 341 QDF_STATUS qdf_wake_lock_timeout_acquire(qdf_wake_lock_t *lock, uint32_t msec) 342 { 343 /* Wakelock for Rx is frequent. 344 * It is reported only during active debug 345 */ 346 __pm_wakeup_event(&(lock->lock), msec); 347 return QDF_STATUS_SUCCESS; 348 } 349 #else /* LINUX_VERSION_CODE */ 350 QDF_STATUS qdf_wake_lock_timeout_acquire(qdf_wake_lock_t *lock, uint32_t msec) 351 { 352 return QDF_STATUS_SUCCESS; 353 } 354 #endif /* LINUX_VERSION_CODE */ 355 qdf_export_symbol(qdf_wake_lock_timeout_acquire); 356 357 /** 358 * qdf_wake_lock_release() - releases a wake lock 359 * @lock: the wake lock to release 360 * @reason: Reason for wakelock 361 * 362 * Return: 363 * QDF status success: if wake lock is acquired 364 * QDF status failure: if wake lock was not acquired 365 */ 366 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) 367 QDF_STATUS qdf_wake_lock_release(qdf_wake_lock_t *lock, uint32_t reason) 368 { 369 host_diag_log_wlock(reason, qdf_wake_lock_name(lock), 370 WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT, 371 WIFI_POWER_EVENT_WAKELOCK_RELEASED); 372 __pm_relax(lock->priv); 373 374 return QDF_STATUS_SUCCESS; 375 } 376 #else 377 QDF_STATUS qdf_wake_lock_release(qdf_wake_lock_t *lock, uint32_t reason) 378 { 379 return QDF_STATUS_SUCCESS; 380 } 381 #endif 382 qdf_export_symbol(qdf_wake_lock_release); 383 384 /** 385 * qdf_wake_lock_destroy() - destroys a wake lock 386 * @lock: The wake lock to destroy 387 * 388 * Return: 389 * QDF status success: if wake lock is acquired 390 * QDF status failure: if wake lock was not acquired 391 */ 392 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 110)) || \ 393 defined(WAKEUP_SOURCE_DEV) 394 QDF_STATUS qdf_wake_lock_destroy(qdf_wake_lock_t *lock) 395 { 396 wakeup_source_unregister(lock->priv); 397 return QDF_STATUS_SUCCESS; 398 } 399 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) 400 QDF_STATUS qdf_wake_lock_destroy(qdf_wake_lock_t *lock) 401 { 402 wakeup_source_trash(&(lock->lock)); 403 return QDF_STATUS_SUCCESS; 404 } 405 #else 406 QDF_STATUS qdf_wake_lock_destroy(qdf_wake_lock_t *lock) 407 { 408 return QDF_STATUS_SUCCESS; 409 } 410 #endif 411 qdf_export_symbol(qdf_wake_lock_destroy); 412 413 /** 414 * qdf_pm_system_wakeup() - wakeup system 415 * 416 * Return: None 417 */ 418 void qdf_pm_system_wakeup(void) 419 { 420 pm_system_wakeup(); 421 } 422 423 qdf_export_symbol(qdf_pm_system_wakeup); 424 425 #ifdef FEATURE_RUNTIME_PM 426 /** 427 * qdf_runtime_pm_get() - do a get opperation on the device 428 * 429 * A get opperation will prevent a runtime suspend until a 430 * corresponding put is done. This api should be used when sending 431 * data. 432 * 433 * CONTRARY TO THE REGULAR RUNTIME PM, WHEN THE BUS IS SUSPENDED, 434 * THIS API WILL ONLY REQUEST THE RESUME AND NOT TO A GET!!! 435 * 436 * return: success if the bus is up and a get has been issued 437 * otherwise an error code. 438 */ 439 QDF_STATUS qdf_runtime_pm_get(void) 440 { 441 void *ol_sc; 442 int ret; 443 444 ol_sc = cds_get_context(QDF_MODULE_ID_HIF); 445 446 if (!ol_sc) { 447 QDF_ASSERT(0); 448 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 449 "%s: HIF context is null!", __func__); 450 return QDF_STATUS_E_INVAL; 451 } 452 453 ret = hif_pm_runtime_get(ol_sc, RTPM_ID_RESVERD); 454 455 if (ret) 456 return QDF_STATUS_E_FAILURE; 457 return QDF_STATUS_SUCCESS; 458 } 459 qdf_export_symbol(qdf_runtime_pm_get); 460 461 /** 462 * qdf_runtime_pm_put() - do a put opperation on the device 463 * 464 * A put opperation will allow a runtime suspend after a corresponding 465 * get was done. This api should be used when sending data. 466 * 467 * This api will return a failure if the hif module hasn't been 468 * initialized 469 * 470 * return: QDF_STATUS_SUCCESS if the put is performed 471 */ 472 QDF_STATUS qdf_runtime_pm_put(void) 473 { 474 void *ol_sc; 475 int ret; 476 477 ol_sc = cds_get_context(QDF_MODULE_ID_HIF); 478 479 if (!ol_sc) { 480 QDF_ASSERT(0); 481 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 482 "%s: HIF context is null!", __func__); 483 return QDF_STATUS_E_INVAL; 484 } 485 486 ret = hif_pm_runtime_put(ol_sc, RTPM_ID_RESVERD); 487 488 if (ret) 489 return QDF_STATUS_E_FAILURE; 490 return QDF_STATUS_SUCCESS; 491 } 492 qdf_export_symbol(qdf_runtime_pm_put); 493 494 /** 495 * qdf_runtime_pm_prevent_suspend() - prevent a runtime bus suspend 496 * @lock: an opaque context for tracking 497 * 498 * The lock can only be acquired once per lock context and is tracked. 499 * 500 * return: QDF_STATUS_SUCCESS or failure code. 501 */ 502 QDF_STATUS qdf_runtime_pm_prevent_suspend(qdf_runtime_lock_t *lock) 503 { 504 void *ol_sc; 505 int ret; 506 507 ol_sc = cds_get_context(QDF_MODULE_ID_HIF); 508 509 if (!ol_sc) { 510 QDF_ASSERT(0); 511 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 512 "%s: HIF context is null!", __func__); 513 return QDF_STATUS_E_INVAL; 514 } 515 516 ret = hif_pm_runtime_prevent_suspend(ol_sc, lock->lock); 517 518 if (ret) 519 return QDF_STATUS_E_FAILURE; 520 return QDF_STATUS_SUCCESS; 521 } 522 qdf_export_symbol(qdf_runtime_pm_prevent_suspend); 523 524 /** 525 * qdf_runtime_pm_allow_suspend() - prevent a runtime bus suspend 526 * @lock: an opaque context for tracking 527 * 528 * The lock can only be acquired once per lock context and is tracked. 529 * 530 * return: QDF_STATUS_SUCCESS or failure code. 531 */ 532 QDF_STATUS qdf_runtime_pm_allow_suspend(qdf_runtime_lock_t *lock) 533 { 534 void *ol_sc; 535 int ret; 536 537 ol_sc = cds_get_context(QDF_MODULE_ID_HIF); 538 if (!ol_sc) { 539 QDF_ASSERT(0); 540 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 541 "%s: HIF context is null!", __func__); 542 return QDF_STATUS_E_INVAL; 543 } 544 545 ret = hif_pm_runtime_allow_suspend(ol_sc, lock->lock); 546 if (ret) 547 return QDF_STATUS_E_FAILURE; 548 549 return QDF_STATUS_SUCCESS; 550 } 551 qdf_export_symbol(qdf_runtime_pm_allow_suspend); 552 553 /** 554 * qdf_runtime_lock_init() - initialize runtime lock 555 * @name: name of the runtime lock 556 * 557 * Initialize a runtime pm lock. This lock can be used 558 * to prevent the runtime pm system from putting the bus 559 * to sleep. 560 * 561 * Return: runtime_pm_lock_t 562 */ 563 QDF_STATUS __qdf_runtime_lock_init(qdf_runtime_lock_t *lock, const char *name) 564 { 565 int ret = hif_runtime_lock_init(lock, name); 566 567 if (ret) 568 return QDF_STATUS_E_NOMEM; 569 570 return QDF_STATUS_SUCCESS; 571 } 572 qdf_export_symbol(__qdf_runtime_lock_init); 573 574 /** 575 * qdf_runtime_lock_deinit() - deinitialize runtime pm lock 576 * @lock: the lock to deinitialize 577 * 578 * Ensures the lock is released. Frees the runtime lock. 579 * 580 * Return: void 581 */ 582 void qdf_runtime_lock_deinit(qdf_runtime_lock_t *lock) 583 { 584 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF); 585 586 if (!hif_ctx) 587 return; 588 589 if (!lock) 590 return; 591 592 hif_runtime_lock_deinit(hif_ctx, lock->lock); 593 } 594 qdf_export_symbol(qdf_runtime_lock_deinit); 595 596 #else 597 598 QDF_STATUS qdf_runtime_pm_get(void) 599 { 600 return QDF_STATUS_SUCCESS; 601 } 602 qdf_export_symbol(qdf_runtime_pm_get); 603 604 QDF_STATUS qdf_runtime_pm_put(void) 605 { 606 return QDF_STATUS_SUCCESS; 607 } 608 qdf_export_symbol(qdf_runtime_pm_put); 609 610 QDF_STATUS qdf_runtime_pm_prevent_suspend(qdf_runtime_lock_t *lock) 611 { 612 return QDF_STATUS_SUCCESS; 613 } 614 qdf_export_symbol(qdf_runtime_pm_prevent_suspend); 615 616 QDF_STATUS qdf_runtime_pm_allow_suspend(qdf_runtime_lock_t *lock) 617 { 618 return QDF_STATUS_SUCCESS; 619 } 620 qdf_export_symbol(qdf_runtime_pm_allow_suspend); 621 622 QDF_STATUS __qdf_runtime_lock_init(qdf_runtime_lock_t *lock, const char *name) 623 { 624 return QDF_STATUS_SUCCESS; 625 } 626 qdf_export_symbol(__qdf_runtime_lock_init); 627 628 void qdf_runtime_lock_deinit(qdf_runtime_lock_t *lock) 629 { 630 } 631 qdf_export_symbol(qdf_runtime_lock_deinit); 632 633 #endif /* FEATURE_RUNTIME_PM */ 634 635 /** 636 * qdf_spinlock_acquire() - acquires a spin lock 637 * @lock: Spin lock to acquire 638 * 639 * Return: 640 * QDF status success: if wake lock is acquired 641 */ 642 QDF_STATUS qdf_spinlock_acquire(qdf_spinlock_t *lock) 643 { 644 spin_lock(&lock->lock.spinlock); 645 return QDF_STATUS_SUCCESS; 646 } 647 qdf_export_symbol(qdf_spinlock_acquire); 648 649 650 /** 651 * qdf_spinlock_release() - release a spin lock 652 * @lock: Spin lock to release 653 * 654 * Return: 655 * QDF status success : if wake lock is acquired 656 */ 657 QDF_STATUS qdf_spinlock_release(qdf_spinlock_t *lock) 658 { 659 spin_unlock(&lock->lock.spinlock); 660 return QDF_STATUS_SUCCESS; 661 } 662 qdf_export_symbol(qdf_spinlock_release); 663 664 /** 665 * qdf_mutex_destroy() - destroy a QDF lock 666 * @lock: Pointer to the opaque lock object to be destroyed 667 * 668 * function shall destroy the lock object referenced by lock. After a 669 * successful return from qdf_mutex_destroy() 670 * the lock object becomes, in effect, uninitialized. 671 * 672 * A destroyed lock object can be reinitialized using qdf_mutex_create(); 673 * the results of otherwise referencing the object after it has been destroyed 674 * are undefined. Calls to QDF lock functions to manipulate the lock such 675 * as qdf_mutex_acquire() will fail if the lock is destroyed. Therefore, 676 * don't use the lock after it has been destroyed until it has 677 * been re-initialized. 678 * 679 * Return: 680 * QDF_STATUS_SUCCESS: lock was successfully initialized 681 * QDF failure reason codes: lock is not initialized and can't be used 682 */ 683 QDF_STATUS qdf_mutex_destroy(qdf_mutex_t *lock) 684 { 685 /* check for invalid pointer */ 686 if (!lock) { 687 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 688 "%s: NULL pointer passed in", __func__); 689 return QDF_STATUS_E_FAULT; 690 } 691 692 if (LINUX_LOCK_COOKIE != lock->cookie) { 693 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 694 "%s: uninitialized lock", __func__); 695 return QDF_STATUS_E_INVAL; 696 } 697 698 if (in_interrupt()) { 699 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 700 "%s cannot be called from interrupt context!!!", 701 __func__); 702 return QDF_STATUS_E_FAULT; 703 } 704 705 /* check if lock is released */ 706 if (!mutex_trylock(&lock->m_lock)) { 707 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 708 "%s: lock is not released", __func__); 709 return QDF_STATUS_E_BUSY; 710 } 711 lock->cookie = 0; 712 lock->state = LOCK_DESTROYED; 713 lock->process_id = 0; 714 lock->refcount = 0; 715 716 qdf_lock_stats_destroy(&lock->stats); 717 mutex_unlock(&lock->m_lock); 718 719 return QDF_STATUS_SUCCESS; 720 } 721 qdf_export_symbol(qdf_mutex_destroy); 722 723 #if QDF_LOCK_STATS_LIST 724 struct qdf_lock_cookie { 725 union { 726 struct { 727 struct lock_stats *stats; 728 const char *func; 729 int line; 730 } cookie; 731 struct { 732 struct qdf_lock_cookie *next; 733 } empty_node; 734 } u; 735 }; 736 737 #ifndef QDF_LOCK_STATS_LIST_SIZE 738 #define QDF_LOCK_STATS_LIST_SIZE 256 739 #endif 740 741 static qdf_spinlock_t qdf_lock_list_spinlock; 742 static struct qdf_lock_cookie lock_cookies[QDF_LOCK_STATS_LIST_SIZE]; 743 static struct qdf_lock_cookie *lock_cookie_freelist; 744 static qdf_atomic_t lock_cookie_get_failures; 745 static qdf_atomic_t lock_cookie_untracked_num; 746 /* dummy value */ 747 #define DUMMY_LOCK_COOKIE 0xc00c1e 748 749 /** 750 * qdf_is_lock_cookie - check if memory is a valid lock cookie 751 * 752 * return true if the memory is within the range of the lock cookie 753 * memory. 754 */ 755 static bool qdf_is_lock_cookie(struct qdf_lock_cookie *lock_cookie) 756 { 757 return lock_cookie >= &lock_cookies[0] && 758 lock_cookie <= &lock_cookies[QDF_LOCK_STATS_LIST_SIZE-1]; 759 } 760 761 /** 762 * qdf_is_lock_cookie_free() - check if the lock cookie is on the freelist 763 * @lock_cookie: lock cookie to check 764 * 765 * Check that the next field of the lock cookie points to a lock cookie. 766 * currently this is only true if the cookie is on the freelist. 767 * 768 * Checking for the function and line being NULL and 0 should also have worked. 769 */ 770 static bool qdf_is_lock_cookie_free(struct qdf_lock_cookie *lock_cookie) 771 { 772 struct qdf_lock_cookie *tmp = lock_cookie->u.empty_node.next; 773 774 return qdf_is_lock_cookie(tmp) || (!tmp); 775 } 776 777 static struct qdf_lock_cookie *qdf_get_lock_cookie(void) 778 { 779 struct qdf_lock_cookie *lock_cookie; 780 781 qdf_spin_lock_bh(&qdf_lock_list_spinlock); 782 lock_cookie = lock_cookie_freelist; 783 if (lock_cookie_freelist) 784 lock_cookie_freelist = lock_cookie_freelist->u.empty_node.next; 785 qdf_spin_unlock_bh(&qdf_lock_list_spinlock); 786 return lock_cookie; 787 } 788 789 static void __qdf_put_lock_cookie(struct qdf_lock_cookie *lock_cookie) 790 { 791 if (!qdf_is_lock_cookie(lock_cookie)) 792 QDF_BUG(0); 793 794 lock_cookie->u.empty_node.next = lock_cookie_freelist; 795 lock_cookie_freelist = lock_cookie; 796 } 797 798 static void qdf_put_lock_cookie(struct qdf_lock_cookie *lock_cookie) 799 { 800 qdf_spin_lock_bh(&qdf_lock_list_spinlock); 801 __qdf_put_lock_cookie(lock_cookie); 802 qdf_spin_unlock_bh(&qdf_lock_list_spinlock); 803 } 804 805 void qdf_lock_stats_init(void) 806 { 807 int i; 808 809 for (i = 0; i < QDF_LOCK_STATS_LIST_SIZE; i++) 810 __qdf_put_lock_cookie(&lock_cookies[i]); 811 812 /* stats must be allocated for the spinlock before the cookie, 813 * otherwise this qdf_lock_list_spinlock wouldnt get initialized 814 * properly 815 */ 816 qdf_spinlock_create(&qdf_lock_list_spinlock); 817 qdf_atomic_init(&lock_cookie_get_failures); 818 qdf_atomic_init(&lock_cookie_untracked_num); 819 } 820 821 void qdf_lock_stats_deinit(void) 822 { 823 int i; 824 825 qdf_spinlock_destroy(&qdf_lock_list_spinlock); 826 for (i = 0; i < QDF_LOCK_STATS_LIST_SIZE; i++) { 827 if (!qdf_is_lock_cookie_free(&lock_cookies[i])) 828 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG, 829 "%s: lock_not_destroyed, fun: %s, line %d", 830 __func__, lock_cookies[i].u.cookie.func, 831 lock_cookies[i].u.cookie.line); 832 } 833 lock_cookie_freelist = NULL; 834 } 835 836 /* allocated separate memory in case the lock memory is freed without 837 * running the deinitialization code. The cookie list will not be 838 * corrupted. 839 */ 840 void qdf_lock_stats_cookie_create(struct lock_stats *stats, 841 const char *func, int line) 842 { 843 struct qdf_lock_cookie *cookie = qdf_get_lock_cookie(); 844 845 if (!cookie) { 846 int count; 847 848 qdf_atomic_inc(&lock_cookie_get_failures); 849 count = qdf_atomic_inc_return(&lock_cookie_untracked_num); 850 stats->cookie = (void *) DUMMY_LOCK_COOKIE; 851 return; 852 } 853 854 stats->cookie = cookie; 855 stats->cookie->u.cookie.stats = stats; 856 stats->cookie->u.cookie.func = func; 857 stats->cookie->u.cookie.line = line; 858 } 859 860 void qdf_lock_stats_cookie_destroy(struct lock_stats *stats) 861 { 862 struct qdf_lock_cookie *cookie = stats->cookie; 863 864 if (!cookie) { 865 QDF_DEBUG_PANIC("Lock destroyed twice or never created"); 866 return; 867 } 868 869 stats->cookie = NULL; 870 if (cookie == (void *)DUMMY_LOCK_COOKIE) { 871 qdf_atomic_dec(&lock_cookie_untracked_num); 872 return; 873 } 874 875 cookie->u.cookie.stats = NULL; 876 cookie->u.cookie.func = NULL; 877 cookie->u.cookie.line = 0; 878 879 qdf_put_lock_cookie(cookie); 880 } 881 #endif 882