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(5, 4, 0)) 269 QDF_STATUS qdf_wake_lock_create(qdf_wake_lock_t *lock, const char *name) 270 { 271 lock->priv = wakeup_source_register(lock->lock.dev, name); 272 if (!(lock->priv)) { 273 QDF_BUG(0); 274 return QDF_STATUS_E_FAILURE; 275 } 276 277 lock->lock = *(lock->priv); 278 279 return QDF_STATUS_SUCCESS; 280 } 281 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) 282 QDF_STATUS qdf_wake_lock_create(qdf_wake_lock_t *lock, const char *name) 283 { 284 wakeup_source_init(&(lock->lock), name); 285 lock->priv = &(lock->lock); 286 return QDF_STATUS_SUCCESS; 287 } 288 #else 289 QDF_STATUS qdf_wake_lock_create(qdf_wake_lock_t *lock, const char *name) 290 { 291 return QDF_STATUS_SUCCESS; 292 } 293 #endif 294 qdf_export_symbol(qdf_wake_lock_create); 295 296 /** 297 * qdf_wake_lock_acquire() - acquires a wake lock 298 * @lock: The wake lock to acquire 299 * @reason: Reason for wakelock 300 * 301 * Return: 302 * QDF status success: if wake lock is acquired 303 * QDF status failure: if wake lock was not acquired 304 */ 305 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) 306 QDF_STATUS qdf_wake_lock_acquire(qdf_wake_lock_t *lock, uint32_t reason) 307 { 308 host_diag_log_wlock(reason, qdf_wake_lock_name(lock), 309 WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT, 310 WIFI_POWER_EVENT_WAKELOCK_TAKEN); 311 __pm_stay_awake(lock->priv); 312 313 return QDF_STATUS_SUCCESS; 314 } 315 #else 316 QDF_STATUS qdf_wake_lock_acquire(qdf_wake_lock_t *lock, uint32_t reason) 317 { 318 return QDF_STATUS_SUCCESS; 319 } 320 #endif 321 qdf_export_symbol(qdf_wake_lock_acquire); 322 323 /** 324 * qdf_wake_lock_timeout_acquire() - acquires a wake lock with a timeout 325 * @lock: The wake lock to acquire 326 * @reason: Reason for wakelock 327 * 328 * Return: 329 * QDF status success: if wake lock is acquired 330 * QDF status failure: if wake lock was not acquired 331 */ 332 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) 333 QDF_STATUS qdf_wake_lock_timeout_acquire(qdf_wake_lock_t *lock, uint32_t msec) 334 { 335 pm_wakeup_ws_event(lock->priv, msec, true); 336 return QDF_STATUS_SUCCESS; 337 } 338 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) 339 QDF_STATUS qdf_wake_lock_timeout_acquire(qdf_wake_lock_t *lock, uint32_t msec) 340 { 341 /* Wakelock for Rx is frequent. 342 * It is reported only during active debug 343 */ 344 __pm_wakeup_event(&(lock->lock), msec); 345 return QDF_STATUS_SUCCESS; 346 } 347 #else /* LINUX_VERSION_CODE */ 348 QDF_STATUS qdf_wake_lock_timeout_acquire(qdf_wake_lock_t *lock, uint32_t msec) 349 { 350 return QDF_STATUS_SUCCESS; 351 } 352 #endif /* LINUX_VERSION_CODE */ 353 qdf_export_symbol(qdf_wake_lock_timeout_acquire); 354 355 /** 356 * qdf_wake_lock_release() - releases a wake lock 357 * @lock: the wake lock to release 358 * @reason: Reason for wakelock 359 * 360 * Return: 361 * QDF status success: if wake lock is acquired 362 * QDF status failure: if wake lock was not acquired 363 */ 364 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) 365 QDF_STATUS qdf_wake_lock_release(qdf_wake_lock_t *lock, uint32_t reason) 366 { 367 host_diag_log_wlock(reason, qdf_wake_lock_name(lock), 368 WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT, 369 WIFI_POWER_EVENT_WAKELOCK_RELEASED); 370 __pm_relax(lock->priv); 371 372 return QDF_STATUS_SUCCESS; 373 } 374 #else 375 QDF_STATUS qdf_wake_lock_release(qdf_wake_lock_t *lock, uint32_t reason) 376 { 377 return QDF_STATUS_SUCCESS; 378 } 379 #endif 380 qdf_export_symbol(qdf_wake_lock_release); 381 382 /** 383 * qdf_wake_lock_destroy() - destroys a wake lock 384 * @lock: The wake lock to destroy 385 * 386 * Return: 387 * QDF status success: if wake lock is acquired 388 * QDF status failure: if wake lock was not acquired 389 */ 390 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0)) 391 QDF_STATUS qdf_wake_lock_destroy(qdf_wake_lock_t *lock) 392 { 393 wakeup_source_unregister(lock->priv); 394 return QDF_STATUS_SUCCESS; 395 } 396 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) 397 QDF_STATUS qdf_wake_lock_destroy(qdf_wake_lock_t *lock) 398 { 399 wakeup_source_trash(&(lock->lock)); 400 return QDF_STATUS_SUCCESS; 401 } 402 #else 403 QDF_STATUS qdf_wake_lock_destroy(qdf_wake_lock_t *lock) 404 { 405 return QDF_STATUS_SUCCESS; 406 } 407 #endif 408 qdf_export_symbol(qdf_wake_lock_destroy); 409 410 /** 411 * qdf_pm_system_wakeup() - wakeup system 412 * 413 * Return: None 414 */ 415 void qdf_pm_system_wakeup(void) 416 { 417 pm_system_wakeup(); 418 } 419 420 qdf_export_symbol(qdf_pm_system_wakeup); 421 422 #ifdef FEATURE_RUNTIME_PM 423 /** 424 * qdf_runtime_pm_get() - do a get opperation on the device 425 * 426 * A get opperation will prevent a runtime suspend until a 427 * corresponding put is done. This api should be used when sending 428 * data. 429 * 430 * CONTRARY TO THE REGULAR RUNTIME PM, WHEN THE BUS IS SUSPENDED, 431 * THIS API WILL ONLY REQUEST THE RESUME AND NOT TO A GET!!! 432 * 433 * return: success if the bus is up and a get has been issued 434 * otherwise an error code. 435 */ 436 QDF_STATUS qdf_runtime_pm_get(void) 437 { 438 void *ol_sc; 439 int ret; 440 441 ol_sc = cds_get_context(QDF_MODULE_ID_HIF); 442 443 if (!ol_sc) { 444 QDF_ASSERT(0); 445 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 446 "%s: HIF context is null!", __func__); 447 return QDF_STATUS_E_INVAL; 448 } 449 450 ret = hif_pm_runtime_get(ol_sc); 451 452 if (ret) 453 return QDF_STATUS_E_FAILURE; 454 return QDF_STATUS_SUCCESS; 455 } 456 qdf_export_symbol(qdf_runtime_pm_get); 457 458 /** 459 * qdf_runtime_pm_put() - do a put opperation on the device 460 * 461 * A put opperation will allow a runtime suspend after a corresponding 462 * get was done. This api should be used when sending data. 463 * 464 * This api will return a failure if the hif module hasn't been 465 * initialized 466 * 467 * return: QDF_STATUS_SUCCESS if the put is performed 468 */ 469 QDF_STATUS qdf_runtime_pm_put(void) 470 { 471 void *ol_sc; 472 int ret; 473 474 ol_sc = cds_get_context(QDF_MODULE_ID_HIF); 475 476 if (!ol_sc) { 477 QDF_ASSERT(0); 478 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 479 "%s: HIF context is null!", __func__); 480 return QDF_STATUS_E_INVAL; 481 } 482 483 ret = hif_pm_runtime_put(ol_sc); 484 485 if (ret) 486 return QDF_STATUS_E_FAILURE; 487 return QDF_STATUS_SUCCESS; 488 } 489 qdf_export_symbol(qdf_runtime_pm_put); 490 491 /** 492 * qdf_runtime_pm_prevent_suspend() - prevent a runtime bus suspend 493 * @lock: an opaque context for tracking 494 * 495 * The lock can only be acquired once per lock context and is tracked. 496 * 497 * return: QDF_STATUS_SUCCESS or failure code. 498 */ 499 QDF_STATUS qdf_runtime_pm_prevent_suspend(qdf_runtime_lock_t *lock) 500 { 501 void *ol_sc; 502 int ret; 503 504 ol_sc = cds_get_context(QDF_MODULE_ID_HIF); 505 506 if (!ol_sc) { 507 QDF_ASSERT(0); 508 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 509 "%s: HIF context is null!", __func__); 510 return QDF_STATUS_E_INVAL; 511 } 512 513 ret = hif_pm_runtime_prevent_suspend(ol_sc, lock->lock); 514 515 if (ret) 516 return QDF_STATUS_E_FAILURE; 517 return QDF_STATUS_SUCCESS; 518 } 519 qdf_export_symbol(qdf_runtime_pm_prevent_suspend); 520 521 /** 522 * qdf_runtime_pm_allow_suspend() - prevent a runtime bus suspend 523 * @lock: an opaque context for tracking 524 * 525 * The lock can only be acquired once per lock context and is tracked. 526 * 527 * return: QDF_STATUS_SUCCESS or failure code. 528 */ 529 QDF_STATUS qdf_runtime_pm_allow_suspend(qdf_runtime_lock_t *lock) 530 { 531 void *ol_sc; 532 int ret; 533 534 ol_sc = cds_get_context(QDF_MODULE_ID_HIF); 535 if (!ol_sc) { 536 QDF_ASSERT(0); 537 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 538 "%s: HIF context is null!", __func__); 539 return QDF_STATUS_E_INVAL; 540 } 541 542 ret = hif_pm_runtime_allow_suspend(ol_sc, lock->lock); 543 if (ret) 544 return QDF_STATUS_E_FAILURE; 545 546 return QDF_STATUS_SUCCESS; 547 } 548 qdf_export_symbol(qdf_runtime_pm_allow_suspend); 549 550 /** 551 * qdf_runtime_lock_init() - initialize runtime lock 552 * @name: name of the runtime lock 553 * 554 * Initialize a runtime pm lock. This lock can be used 555 * to prevent the runtime pm system from putting the bus 556 * to sleep. 557 * 558 * Return: runtime_pm_lock_t 559 */ 560 QDF_STATUS __qdf_runtime_lock_init(qdf_runtime_lock_t *lock, const char *name) 561 { 562 int ret = hif_runtime_lock_init(lock, name); 563 564 if (ret) 565 return QDF_STATUS_E_NOMEM; 566 567 return QDF_STATUS_SUCCESS; 568 } 569 qdf_export_symbol(__qdf_runtime_lock_init); 570 571 /** 572 * qdf_runtime_lock_deinit() - deinitialize runtime pm lock 573 * @lock: the lock to deinitialize 574 * 575 * Ensures the lock is released. Frees the runtime lock. 576 * 577 * Return: void 578 */ 579 void qdf_runtime_lock_deinit(qdf_runtime_lock_t *lock) 580 { 581 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF); 582 hif_runtime_lock_deinit(hif_ctx, lock->lock); 583 } 584 qdf_export_symbol(qdf_runtime_lock_deinit); 585 586 #else 587 588 QDF_STATUS qdf_runtime_pm_get(void) 589 { 590 return QDF_STATUS_SUCCESS; 591 } 592 qdf_export_symbol(qdf_runtime_pm_get); 593 594 QDF_STATUS qdf_runtime_pm_put(void) 595 { 596 return QDF_STATUS_SUCCESS; 597 } 598 qdf_export_symbol(qdf_runtime_pm_put); 599 600 QDF_STATUS qdf_runtime_pm_prevent_suspend(qdf_runtime_lock_t *lock) 601 { 602 return QDF_STATUS_SUCCESS; 603 } 604 qdf_export_symbol(qdf_runtime_pm_prevent_suspend); 605 606 QDF_STATUS qdf_runtime_pm_allow_suspend(qdf_runtime_lock_t *lock) 607 { 608 return QDF_STATUS_SUCCESS; 609 } 610 qdf_export_symbol(qdf_runtime_pm_allow_suspend); 611 612 QDF_STATUS __qdf_runtime_lock_init(qdf_runtime_lock_t *lock, const char *name) 613 { 614 return QDF_STATUS_SUCCESS; 615 } 616 qdf_export_symbol(__qdf_runtime_lock_init); 617 618 void qdf_runtime_lock_deinit(qdf_runtime_lock_t *lock) 619 { 620 } 621 qdf_export_symbol(qdf_runtime_lock_deinit); 622 623 #endif /* FEATURE_RUNTIME_PM */ 624 625 /** 626 * qdf_spinlock_acquire() - acquires a spin lock 627 * @lock: Spin lock to acquire 628 * 629 * Return: 630 * QDF status success: if wake lock is acquired 631 */ 632 QDF_STATUS qdf_spinlock_acquire(qdf_spinlock_t *lock) 633 { 634 spin_lock(&lock->lock.spinlock); 635 return QDF_STATUS_SUCCESS; 636 } 637 qdf_export_symbol(qdf_spinlock_acquire); 638 639 640 /** 641 * qdf_spinlock_release() - release a spin lock 642 * @lock: Spin lock to release 643 * 644 * Return: 645 * QDF status success : if wake lock is acquired 646 */ 647 QDF_STATUS qdf_spinlock_release(qdf_spinlock_t *lock) 648 { 649 spin_unlock(&lock->lock.spinlock); 650 return QDF_STATUS_SUCCESS; 651 } 652 qdf_export_symbol(qdf_spinlock_release); 653 654 /** 655 * qdf_mutex_destroy() - destroy a QDF lock 656 * @lock: Pointer to the opaque lock object to be destroyed 657 * 658 * function shall destroy the lock object referenced by lock. After a 659 * successful return from qdf_mutex_destroy() 660 * the lock object becomes, in effect, uninitialized. 661 * 662 * A destroyed lock object can be reinitialized using qdf_mutex_create(); 663 * the results of otherwise referencing the object after it has been destroyed 664 * are undefined. Calls to QDF lock functions to manipulate the lock such 665 * as qdf_mutex_acquire() will fail if the lock is destroyed. Therefore, 666 * don't use the lock after it has been destroyed until it has 667 * been re-initialized. 668 * 669 * Return: 670 * QDF_STATUS_SUCCESS: lock was successfully initialized 671 * QDF failure reason codes: lock is not initialized and can't be used 672 */ 673 QDF_STATUS qdf_mutex_destroy(qdf_mutex_t *lock) 674 { 675 /* check for invalid pointer */ 676 if (!lock) { 677 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 678 "%s: NULL pointer passed in", __func__); 679 return QDF_STATUS_E_FAULT; 680 } 681 682 if (LINUX_LOCK_COOKIE != lock->cookie) { 683 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 684 "%s: uninitialized lock", __func__); 685 return QDF_STATUS_E_INVAL; 686 } 687 688 if (in_interrupt()) { 689 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 690 "%s cannot be called from interrupt context!!!", 691 __func__); 692 return QDF_STATUS_E_FAULT; 693 } 694 695 /* check if lock is released */ 696 if (!mutex_trylock(&lock->m_lock)) { 697 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 698 "%s: lock is not released", __func__); 699 return QDF_STATUS_E_BUSY; 700 } 701 lock->cookie = 0; 702 lock->state = LOCK_DESTROYED; 703 lock->process_id = 0; 704 lock->refcount = 0; 705 706 qdf_lock_stats_destroy(&lock->stats); 707 mutex_unlock(&lock->m_lock); 708 709 return QDF_STATUS_SUCCESS; 710 } 711 qdf_export_symbol(qdf_mutex_destroy); 712 713 #if QDF_LOCK_STATS_LIST 714 struct qdf_lock_cookie { 715 union { 716 struct { 717 struct lock_stats *stats; 718 const char *func; 719 int line; 720 } cookie; 721 struct { 722 struct qdf_lock_cookie *next; 723 } empty_node; 724 } u; 725 }; 726 727 #ifndef QDF_LOCK_STATS_LIST_SIZE 728 #define QDF_LOCK_STATS_LIST_SIZE 256 729 #endif 730 731 static qdf_spinlock_t qdf_lock_list_spinlock; 732 static struct qdf_lock_cookie lock_cookies[QDF_LOCK_STATS_LIST_SIZE]; 733 static struct qdf_lock_cookie *lock_cookie_freelist; 734 static qdf_atomic_t lock_cookie_get_failures; 735 static qdf_atomic_t lock_cookie_untracked_num; 736 /* dummy value */ 737 #define DUMMY_LOCK_COOKIE 0xc00c1e 738 739 /** 740 * qdf_is_lock_cookie - check if memory is a valid lock cookie 741 * 742 * return true if the memory is within the range of the lock cookie 743 * memory. 744 */ 745 static bool qdf_is_lock_cookie(struct qdf_lock_cookie *lock_cookie) 746 { 747 return lock_cookie >= &lock_cookies[0] && 748 lock_cookie <= &lock_cookies[QDF_LOCK_STATS_LIST_SIZE-1]; 749 } 750 751 /** 752 * qdf_is_lock_cookie_free() - check if the lock cookie is on the freelist 753 * @lock_cookie: lock cookie to check 754 * 755 * Check that the next field of the lock cookie points to a lock cookie. 756 * currently this is only true if the cookie is on the freelist. 757 * 758 * Checking for the function and line being NULL and 0 should also have worked. 759 */ 760 static bool qdf_is_lock_cookie_free(struct qdf_lock_cookie *lock_cookie) 761 { 762 struct qdf_lock_cookie *tmp = lock_cookie->u.empty_node.next; 763 764 return qdf_is_lock_cookie(tmp) || (!tmp); 765 } 766 767 static struct qdf_lock_cookie *qdf_get_lock_cookie(void) 768 { 769 struct qdf_lock_cookie *lock_cookie; 770 771 qdf_spin_lock_bh(&qdf_lock_list_spinlock); 772 lock_cookie = lock_cookie_freelist; 773 if (lock_cookie_freelist) 774 lock_cookie_freelist = lock_cookie_freelist->u.empty_node.next; 775 qdf_spin_unlock_bh(&qdf_lock_list_spinlock); 776 return lock_cookie; 777 } 778 779 static void __qdf_put_lock_cookie(struct qdf_lock_cookie *lock_cookie) 780 { 781 if (!qdf_is_lock_cookie(lock_cookie)) 782 QDF_BUG(0); 783 784 lock_cookie->u.empty_node.next = lock_cookie_freelist; 785 lock_cookie_freelist = lock_cookie; 786 } 787 788 static void qdf_put_lock_cookie(struct qdf_lock_cookie *lock_cookie) 789 { 790 qdf_spin_lock_bh(&qdf_lock_list_spinlock); 791 __qdf_put_lock_cookie(lock_cookie); 792 qdf_spin_unlock_bh(&qdf_lock_list_spinlock); 793 } 794 795 void qdf_lock_stats_init(void) 796 { 797 int i; 798 799 for (i = 0; i < QDF_LOCK_STATS_LIST_SIZE; i++) 800 __qdf_put_lock_cookie(&lock_cookies[i]); 801 802 /* stats must be allocated for the spinlock before the cookie, 803 * otherwise this qdf_lock_list_spinlock wouldnt get initialized 804 * properly 805 */ 806 qdf_spinlock_create(&qdf_lock_list_spinlock); 807 qdf_atomic_init(&lock_cookie_get_failures); 808 qdf_atomic_init(&lock_cookie_untracked_num); 809 } 810 811 void qdf_lock_stats_deinit(void) 812 { 813 int i; 814 815 qdf_spinlock_destroy(&qdf_lock_list_spinlock); 816 for (i = 0; i < QDF_LOCK_STATS_LIST_SIZE; i++) { 817 if (!qdf_is_lock_cookie_free(&lock_cookies[i])) 818 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG, 819 "%s: lock_not_destroyed, fun: %s, line %d", 820 __func__, lock_cookies[i].u.cookie.func, 821 lock_cookies[i].u.cookie.line); 822 } 823 } 824 825 /* allocated separate memory in case the lock memory is freed without 826 * running the deinitialization code. The cookie list will not be 827 * corrupted. 828 */ 829 void qdf_lock_stats_cookie_create(struct lock_stats *stats, 830 const char *func, int line) 831 { 832 struct qdf_lock_cookie *cookie = qdf_get_lock_cookie(); 833 834 if (!cookie) { 835 int count; 836 837 qdf_atomic_inc(&lock_cookie_get_failures); 838 count = qdf_atomic_inc_return(&lock_cookie_untracked_num); 839 stats->cookie = (void *) DUMMY_LOCK_COOKIE; 840 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG, 841 "%s: cookie allocation failure, using dummy (%s:%d) count %d", 842 __func__, func, line, count); 843 return; 844 } 845 846 stats->cookie = cookie; 847 stats->cookie->u.cookie.stats = stats; 848 stats->cookie->u.cookie.func = func; 849 stats->cookie->u.cookie.line = line; 850 } 851 852 void qdf_lock_stats_cookie_destroy(struct lock_stats *stats) 853 { 854 struct qdf_lock_cookie *cookie = stats->cookie; 855 856 if (!cookie) { 857 QDF_DEBUG_PANIC("Lock destroyed twice or never created"); 858 return; 859 } 860 861 stats->cookie = NULL; 862 if (cookie == (void *)DUMMY_LOCK_COOKIE) { 863 qdf_atomic_dec(&lock_cookie_untracked_num); 864 return; 865 } 866 867 cookie->u.cookie.stats = NULL; 868 cookie->u.cookie.func = NULL; 869 cookie->u.cookie.line = 0; 870 871 qdf_put_lock_cookie(cookie); 872 } 873 #endif 874