summaryrefslogtreecommitdiff
path: root/qdf/linux/src/qdf_lock.c
diff options
context:
space:
mode:
authorChouhan, Anurag <achouhan@codeaurora.org>2016-03-03 18:57:27 +0530
committerGerrit - the friendly Code Review server <code-review@localhost>2016-03-16 12:18:26 -0700
commit5776318d1934b14c3b4eb4eb98c74830d64d00a7 (patch)
tree911b2792f6d5ce402cd339455bc17bebf4e2dfb6 /qdf/linux/src/qdf_lock.c
parent5693683262e239d48dbc3134404db1bf3f380252 (diff)
qcacmn: Add QDF OS abstraction convergence
Converge ADF and CDF API's and move them to QDF folder. MCL/WIN driver use this QDF converged module for OS abstraction. Change-Id: I1d0cdfd8730a5c021aaa50b7dc8549d491d760b3 CRs-Fixed: 981187
Diffstat (limited to 'qdf/linux/src/qdf_lock.c')
-rw-r--r--qdf/linux/src/qdf_lock.c660
1 files changed, 660 insertions, 0 deletions
diff --git a/qdf/linux/src/qdf_lock.c b/qdf/linux/src/qdf_lock.c
new file mode 100644
index 000000000000..0afb06790bf4
--- /dev/null
+++ b/qdf/linux/src/qdf_lock.c
@@ -0,0 +1,660 @@
+/*
+ * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved.
+ *
+ * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This file was originally distributed by Qualcomm Atheros, Inc.
+ * under proprietary terms before Copyright ownership was assigned
+ * to the Linux Foundation.
+ */
+
+#include <linux/module.h>
+#include <qdf_lock.h>
+#include <qdf_trace.h>
+
+#include <qdf_types.h>
+#ifdef CONFIG_CNSS
+#include <net/cnss.h>
+#endif
+#ifdef CONFIG_MCL
+#include <i_host_diag_core_event.h>
+#include <cds_api.h>
+#endif
+#include <ani_global.h>
+#include <i_qdf_lock.h>
+#include <hif.h>
+
+/* Function declarations and documenation */
+typedef __qdf_mutex_t qdf_mutex_t;
+
+/**
+ * qdf_mutex_create() - Initialize a mutex
+ * @m: mutex to initialize
+ *
+ * Returns: QDF_STATUS
+ * =0 success
+ * else fail status
+ */
+QDF_STATUS qdf_mutex_create(qdf_mutex_t *lock)
+{
+ /* check for invalid pointer */
+ if (lock == NULL) {
+ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+ "%s: NULL pointer passed in", __func__);
+ return QDF_STATUS_E_FAULT;
+ }
+ /* check for 'already initialized' lock */
+ if (LINUX_LOCK_COOKIE == lock->cookie) {
+ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+ "%s: already initialized lock", __func__);
+ return QDF_STATUS_E_BUSY;
+ }
+
+ if (in_interrupt()) {
+ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+ "%s cannot be called from interrupt context!!!",
+ __func__);
+ return QDF_STATUS_E_FAULT;
+ }
+
+ /* initialize new lock */
+ mutex_init(&lock->m_lock);
+ lock->cookie = LINUX_LOCK_COOKIE;
+ lock->state = LOCK_RELEASED;
+ lock->process_id = 0;
+ lock->refcount = 0;
+
+ return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(qdf_mutex_create);
+
+/**
+ * qdf_mutex_acquire() - acquire a QDF lock
+ * @lock: Pointer to the opaque lock object to acquire
+ *
+ * A lock object is acquired by calling qdf_mutex_acquire(). If the lock
+ * is already locked, the calling thread shall block until the lock becomes
+ * available. This operation shall return with the lock object referenced by
+ * lock in the locked state with the calling thread as its owner.
+ *
+ * Return:
+ * QDF_STATUS_SUCCESS: lock was successfully initialized
+ * QDF failure reason codes: lock is not initialized and can't be used
+ */
+QDF_STATUS qdf_mutex_acquire(qdf_mutex_t *lock)
+{
+ int rc;
+ /* check for invalid pointer */
+ if (lock == NULL) {
+ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+ "%s: NULL pointer passed in", __func__);
+ QDF_ASSERT(0);
+ return QDF_STATUS_E_FAULT;
+ }
+ /* check if lock refers to an initialized object */
+ if (LINUX_LOCK_COOKIE != lock->cookie) {
+ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+ "%s: uninitialized lock", __func__);
+ QDF_ASSERT(0);
+ return QDF_STATUS_E_INVAL;
+ }
+
+ if (in_interrupt()) {
+ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+ "%s cannot be called from interrupt context!!!",
+ __func__);
+ QDF_ASSERT(0);
+ return QDF_STATUS_E_FAULT;
+ }
+ if ((lock->process_id == current->pid) &&
+ (lock->state == LOCK_ACQUIRED)) {
+ lock->refcount++;
+#ifdef QDF_NESTED_LOCK_DEBUG
+ pe_err("%s: %x %d %d", __func__, lock, current->pid,
+ lock->refcount);
+#endif
+ return QDF_STATUS_SUCCESS;
+ }
+ /* acquire a Lock */
+ mutex_lock(&lock->m_lock);
+ rc = mutex_is_locked(&lock->m_lock);
+ if (rc == 0) {
+ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+ "%s: unable to lock mutex (rc = %d)", __func__, rc);
+ QDF_ASSERT(0);
+ return QDF_STATUS_E_FAILURE;
+ }
+#ifdef QDF_NESTED_LOCK_DEBUG
+ pe_err("%s: %x %d", __func__, lock, current->pid);
+#endif
+ if (LOCK_DESTROYED != lock->state) {
+ lock->process_id = current->pid;
+ lock->refcount++;
+ lock->state = LOCK_ACQUIRED;
+ return QDF_STATUS_SUCCESS;
+ } else {
+ /* lock is already destroyed */
+ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+ "%s: Lock is already destroyed", __func__);
+ mutex_unlock(&lock->m_lock);
+ QDF_ASSERT(0);
+ return QDF_STATUS_E_FAILURE;
+ }
+}
+EXPORT_SYMBOL(qdf_mutex_acquire);
+
+/**
+ * qdf_mutex_release() - release a QDF lock
+ * @lock: Pointer to the opaque lock object to be released
+ *
+ * qdf_mutex_release() function shall release the lock object
+ * referenced by 'lock'.
+ *
+ * If a thread attempts to release a lock that it unlocked or is not
+ * initialized, an error is returned.
+ *
+ * Return:
+ * QDF_STATUS_SUCCESS: lock was successfully initialized
+ * QDF failure reason codes: lock is not initialized and can't be used
+ */
+QDF_STATUS qdf_mutex_release(qdf_mutex_t *lock)
+{
+ /* check for invalid pointer */
+ if (lock == NULL) {
+ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+ "%s: NULL pointer passed in", __func__);
+ QDF_ASSERT(0);
+ return QDF_STATUS_E_FAULT;
+ }
+
+ /* check if lock refers to an uninitialized object */
+ if (LINUX_LOCK_COOKIE != lock->cookie) {
+ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+ "%s: uninitialized lock", __func__);
+ QDF_ASSERT(0);
+ return QDF_STATUS_E_INVAL;
+ }
+
+ if (in_interrupt()) {
+ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+ "%s cannot be called from interrupt context!!!",
+ __func__);
+ QDF_ASSERT(0);
+ return QDF_STATUS_E_FAULT;
+ }
+
+ /* current_thread = get_current_thread_id();
+ * Check thread ID of caller against thread ID
+ * of the thread which acquire the lock
+ */
+ if (lock->process_id != current->pid) {
+ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+ "%s: current task pid does not match original task pid!!",
+ __func__);
+#ifdef QDF_NESTED_LOCK_DEBUG
+ pe_err("%s: Lock held by=%d being released by=%d",
+ __func__, lock->process_id, current->pid);
+#endif
+ QDF_ASSERT(0);
+ return QDF_STATUS_E_PERM;
+ }
+ if ((lock->process_id == current->pid) &&
+ (lock->state == LOCK_ACQUIRED)) {
+ if (lock->refcount > 0)
+ lock->refcount--;
+ }
+#ifdef QDF_NESTED_LOCK_DEBUG
+ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "%s: %x %d %d", __func__, lock, lock->process_id,
+ lock->refcount);
+#endif
+ if (lock->refcount)
+ return QDF_STATUS_SUCCESS;
+
+ lock->process_id = 0;
+ lock->refcount = 0;
+ lock->state = LOCK_RELEASED;
+ /* release a Lock */
+ mutex_unlock(&lock->m_lock);
+#ifdef QDF_NESTED_LOCK_DEBUG
+ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "%s: Freeing lock %x %d %d", lock, lock->process_id,
+ lock->refcount);
+#endif
+ return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(qdf_mutex_release);
+
+/**
+ * qdf_wake_lock_name() - This function returns the name of the wakelock
+ * @lock: Pointer to the wakelock
+ *
+ * This function returns the name of the wakelock
+ *
+ * Return: Pointer to the name if it is valid or a default string
+ */
+static const char *qdf_wake_lock_name(qdf_wake_lock_t *lock)
+{
+#if defined CONFIG_CNSS
+ if (lock->name)
+ return lock->name;
+#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK)
+ if (lock->ws.name)
+ return lock->ws.name;
+#endif
+ return "UNNAMED_WAKELOCK";
+}
+EXPORT_SYMBOL(qdf_wake_lock_name);
+
+/**
+ * qdf_wake_lock_create() - initializes a wake lock
+ * @lock: The wake lock to initialize
+ * @name: Name of wake lock
+ *
+ * Return:
+ * QDF status success: if wake lock is initialized
+ * QDF status failure: if wake lock was not initialized
+ */
+QDF_STATUS qdf_wake_lock_create(qdf_wake_lock_t *lock, const char *name)
+{
+#if defined CONFIG_CNSS
+ cnss_pm_wake_lock_init(lock, name);
+#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK)
+ wake_lock_init(lock, WAKE_LOCK_SUSPEND, name);
+#endif
+ return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(qdf_wake_lock_create);
+
+/**
+ * qdf_wake_lock_acquire() - acquires a wake lock
+ * @lock: The wake lock to acquire
+ * @reason: Reason for wakelock
+ *
+ * Return:
+ * QDF status success: if wake lock is acquired
+ * QDF status failure: if wake lock was not acquired
+ */
+QDF_STATUS qdf_wake_lock_acquire(qdf_wake_lock_t *lock, uint32_t reason)
+{
+#ifdef CONFIG_MCL
+ host_diag_log_wlock(reason, qdf_wake_lock_name(lock),
+ WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT,
+ WIFI_POWER_EVENT_WAKELOCK_TAKEN);
+#endif
+#if defined CONFIG_CNSS
+ cnss_pm_wake_lock(lock);
+#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK)
+ wake_lock(lock);
+#endif
+ return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(qdf_wake_lock_acquire);
+
+/**
+ * qdf_wake_lock_timeout_acquire() - acquires a wake lock with a timeout
+ * @lock: The wake lock to acquire
+ * @reason: Reason for wakelock
+ *
+ * Return:
+ * QDF status success: if wake lock is acquired
+ * QDF status failure: if wake lock was not acquired
+ */
+QDF_STATUS qdf_wake_lock_timeout_acquire(qdf_wake_lock_t *lock, uint32_t msec,
+ uint32_t reason)
+{
+ /* Wakelock for Rx is frequent.
+ * It is reported only during active debug
+ */
+#ifdef CONFIG_MCL
+ if (((cds_get_ring_log_level(RING_ID_WAKELOCK) >= WLAN_LOG_LEVEL_ACTIVE)
+ && (WIFI_POWER_EVENT_WAKELOCK_HOLD_RX == reason)) ||
+ (WIFI_POWER_EVENT_WAKELOCK_HOLD_RX != reason)) {
+ host_diag_log_wlock(reason, qdf_wake_lock_name(lock), msec,
+ WIFI_POWER_EVENT_WAKELOCK_TAKEN);
+ }
+#endif
+#if defined CONFIG_CNSS
+ cnss_pm_wake_lock_timeout(lock, msec);
+#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK)
+ wake_lock_timeout(lock, msecs_to_jiffies(msec));
+#endif
+ return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(qdf_wake_lock_timeout_acquire);
+
+/**
+ * qdf_wake_lock_release() - releases a wake lock
+ * @lock: the wake lock to release
+ * @reason: Reason for wakelock
+ *
+ * Return:
+ * QDF status success: if wake lock is acquired
+ * QDF status failure: if wake lock was not acquired
+ */
+QDF_STATUS qdf_wake_lock_release(qdf_wake_lock_t *lock, uint32_t reason)
+{
+#ifdef CONFIG_MCL
+ host_diag_log_wlock(reason, qdf_wake_lock_name(lock),
+ WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT,
+ WIFI_POWER_EVENT_WAKELOCK_RELEASED);
+#endif
+#if defined CONFIG_CNSS
+ cnss_pm_wake_lock_release(lock);
+#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK)
+ wake_unlock(lock);
+#endif
+ return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(qdf_wake_lock_release);
+
+/**
+ * qdf_wake_lock_destroy() - destroys a wake lock
+ * @lock: The wake lock to destroy
+ *
+ * Return:
+ * QDF status success: if wake lock is acquired
+ * QDF status failure: if wake lock was not acquired
+ */
+QDF_STATUS qdf_wake_lock_destroy(qdf_wake_lock_t *lock)
+{
+#if defined CONFIG_CNSS
+ cnss_pm_wake_lock_destroy(lock);
+#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK)
+ wake_lock_destroy(lock);
+#endif
+ return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(qdf_wake_lock_destroy);
+
+/**
+ * qdf_runtime_pm_get() - do a get opperation on the device
+ *
+ * A get opperation will prevent a runtime suspend untill a
+ * corresponding put is done. This api should be used when sending
+ * data.
+ *
+ * CONTRARY TO THE REGULAR RUNTIME PM, WHEN THE BUS IS SUSPENDED,
+ * THIS API WILL ONLY REQUEST THE RESUME AND NOT TO A GET!!!
+ *
+ * return: success if the bus is up and a get has been issued
+ * otherwise an error code.
+ */
+QDF_STATUS qdf_runtime_pm_get(void)
+{
+ void *ol_sc;
+ int ret;
+
+ ol_sc = cds_get_context(QDF_MODULE_ID_HIF);
+
+ if (ol_sc == NULL) {
+ QDF_ASSERT(0);
+ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+ "%s: HIF context is null!", __func__);
+ return QDF_STATUS_E_INVAL;
+ }
+
+ ret = hif_pm_runtime_get(ol_sc);
+
+ if (ret)
+ return QDF_STATUS_E_FAILURE;
+ return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(qdf_runtime_pm_get);
+
+/**
+ * qdf_runtime_pm_put() - do a put opperation on the device
+ *
+ * A put opperation will allow a runtime suspend after a corresponding
+ * get was done. This api should be used when sending data.
+ *
+ * This api will return a failure if the hif module hasn't been
+ * initialized
+ *
+ * return: QDF_STATUS_SUCCESS if the put is performed
+ */
+QDF_STATUS qdf_runtime_pm_put(void)
+{
+ void *ol_sc;
+ int ret;
+
+ ol_sc = cds_get_context(QDF_MODULE_ID_HIF);
+
+ if (ol_sc == NULL) {
+ QDF_ASSERT(0);
+ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+ "%s: HIF context is null!", __func__);
+ return QDF_STATUS_E_INVAL;
+ }
+
+ ret = hif_pm_runtime_put(ol_sc);
+
+ if (ret)
+ return QDF_STATUS_E_FAILURE;
+ return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(qdf_runtime_pm_put);
+
+/**
+ * qdf_runtime_pm_prevent_suspend() - prevent a runtime bus suspend
+ * @lock: an opaque context for tracking
+ *
+ * The lock can only be acquired once per lock context and is tracked.
+ *
+ * return: QDF_STATUS_SUCCESS or failure code.
+ */
+QDF_STATUS qdf_runtime_pm_prevent_suspend(qdf_runtime_lock_t lock)
+{
+ void *ol_sc;
+ int ret;
+
+ ol_sc = cds_get_context(QDF_MODULE_ID_HIF);
+
+ if (ol_sc == NULL) {
+ QDF_ASSERT(0);
+ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+ "%s: HIF context is null!", __func__);
+ return QDF_STATUS_E_INVAL;
+ }
+
+ ret = hif_pm_runtime_prevent_suspend(ol_sc, lock);
+
+ if (ret)
+ return QDF_STATUS_E_FAILURE;
+ return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(qdf_runtime_pm_prevent_suspend);
+
+/**
+ * qdf_runtime_pm_prevent_suspend() - prevent a runtime bus suspend
+ * @lock: an opaque context for tracking
+ *
+ * The lock can only be acquired once per lock context and is tracked.
+ *
+ * return: QDF_STATUS_SUCCESS or failure code.
+ */
+QDF_STATUS qdf_runtime_pm_allow_suspend(qdf_runtime_lock_t lock)
+{
+ void *ol_sc;
+ int ret;
+ ol_sc = cds_get_context(QDF_MODULE_ID_HIF);
+
+ if (ol_sc == NULL) {
+ QDF_ASSERT(0);
+ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+ "%s: HIF context is null!", __func__);
+ return QDF_STATUS_E_INVAL;
+ }
+
+ ret = hif_pm_runtime_allow_suspend(ol_sc, lock);
+ if (ret)
+ return QDF_STATUS_E_FAILURE;
+ return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(qdf_runtime_pm_allow_suspend);
+
+/**
+ * qdf_runtime_lock_init() - initialize runtime lock
+ * @name: name of the runtime lock
+ *
+ * Initialize a runtime pm lock. This lock can be used
+ * to prevent the runtime pm system from putting the bus
+ * to sleep.
+ *
+ * Return: runtime_pm_lock_t
+ */
+qdf_runtime_lock_t qdf_runtime_lock_init(const char *name)
+{
+ return hif_runtime_lock_init(name);
+}
+EXPORT_SYMBOL(qdf_runtime_lock_init);
+
+/**
+ * qdf_runtime_lock_deinit() - deinitialize runtime pm lock
+ * @lock: the lock to deinitialize
+ *
+ * Ensures the lock is released. Frees the runtime lock.
+ *
+ * Return: void
+ */
+void qdf_runtime_lock_deinit(qdf_runtime_lock_t lock)
+{
+ void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
+ hif_runtime_lock_deinit(hif_ctx, lock);
+}
+EXPORT_SYMBOL(qdf_runtime_lock_deinit);
+
+/**
+ * qdf_spinlock_acquire() - acquires a spin lock
+ * @lock: Spin lock to acquire
+ *
+ * Return:
+ * QDF status success: if wake lock is acquired
+ */
+QDF_STATUS qdf_spinlock_acquire(qdf_spinlock_t *lock)
+{
+ spin_lock(&lock->spinlock);
+ return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(qdf_spinlock_acquire);
+
+
+/**
+ * qdf_spinlock_release() - release a spin lock
+ * @lock: Spin lock to release
+ *
+ * Return:
+ * QDF status success : if wake lock is acquired
+ */
+QDF_STATUS qdf_spinlock_release(qdf_spinlock_t *lock)
+{
+ spin_unlock(&lock->spinlock);
+ return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(qdf_spinlock_release);
+
+/**
+ * qdf_mutex_destroy() - destroy a QDF lock
+ * @lock: Pointer to the opaque lock object to be destroyed
+ *
+ * function shall destroy the lock object referenced by lock. After a
+ * successful return from qdf_mutex_destroy()
+ * the lock object becomes, in effect, uninitialized.
+ *
+ * A destroyed lock object can be reinitialized using qdf_mutex_create();
+ * the results of otherwise referencing the object after it has been destroyed
+ * are undefined. Calls to QDF lock functions to manipulate the lock such
+ * as qdf_mutex_acquire() will fail if the lock is destroyed. Therefore,
+ * don't use the lock after it has been destroyed until it has
+ * been re-initialized.
+ *
+ * Return:
+ * QDF_STATUS_SUCCESS: lock was successfully initialized
+ * QDF failure reason codes: lock is not initialized and can't be used
+ */
+QDF_STATUS qdf_mutex_destroy(qdf_mutex_t *lock)
+{
+ /* check for invalid pointer */
+ if (NULL == lock) {
+ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+ "%s: NULL pointer passed in", __func__);
+ return QDF_STATUS_E_FAULT;
+ }
+
+ if (LINUX_LOCK_COOKIE != lock->cookie) {
+ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+ "%s: uninitialized lock", __func__);
+ return QDF_STATUS_E_INVAL;
+ }
+
+ if (in_interrupt()) {
+ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+ "%s cannot be called from interrupt context!!!",
+ __func__);
+ return QDF_STATUS_E_FAULT;
+ }
+
+ /* check if lock is released */
+ if (!mutex_trylock(&lock->m_lock)) {
+ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+ "%s: lock is not released", __func__);
+ return QDF_STATUS_E_BUSY;
+ }
+ lock->cookie = 0;
+ lock->state = LOCK_DESTROYED;
+ lock->process_id = 0;
+ lock->refcount = 0;
+
+ mutex_unlock(&lock->m_lock);
+
+ return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(qdf_mutex_destroy);
+
+/**
+ * qdf_spin_trylock_bh_outline() - spin trylock bottomhalf
+ * @lock: spinlock object
+ * Retrun: int
+ */
+int qdf_spin_trylock_bh_outline(qdf_spinlock_t *lock)
+{
+ return qdf_spin_trylock_bh(lock);
+}
+EXPORT_SYMBOL(qdf_spin_trylock_bh_outline);
+
+/**
+ * qdf_spin_lock_bh_outline() - locks the spinlock in soft irq context
+ * @lock: spinlock object pointer
+ * Return: none
+ */
+void qdf_spin_lock_bh_outline(qdf_spinlock_t *lock)
+{
+ qdf_spin_lock_bh(lock);
+}
+EXPORT_SYMBOL(qdf_spin_lock_bh_outline);
+
+/**
+ * qdf_spin_unlock_bh_outline() - unlocks spinlock in soft irq context
+ * @lock: spinlock object pointer
+ * Return: none
+ */
+void qdf_spin_unlock_bh_outline(qdf_spinlock_t *lock)
+{
+ qdf_spin_unlock_bh(lock);
+}
+EXPORT_SYMBOL(qdf_spin_unlock_bh_outline);