From 6412d1f9cc2833bccdcbba29be247d12ebd89175 Mon Sep 17 00:00:00 2001 From: Dustin Brown Date: Tue, 5 Feb 2019 14:52:29 -0800 Subject: [PATCH] qcacld-3.0: Move hdd_dsc to osif/sync Move the contents of hdd_dsc to the new files added in osif/sync as part of Ica94d32028d10d344294d6cc12d91a06efe1ab6c. Change-Id: I556e9d2833edd2bd26266496b6000347649c5fbe CRs-Fixed: 2396512 --- Kbuild | 1 - components/dsc/inc/wlan_dsc_psoc.h | 3 +- components/dsc/inc/wlan_dsc_vdev.h | 3 +- core/hdd/inc/wlan_hdd_dsc.h | 340 --------------- core/hdd/src/wlan_hdd_cfg80211.c | 2 +- core/hdd/src/wlan_hdd_driver_ops.c | 2 +- core/hdd/src/wlan_hdd_dsc.c | 607 --------------------------- core/hdd/src/wlan_hdd_ext_scan.c | 2 +- core/hdd/src/wlan_hdd_he.c | 2 +- core/hdd/src/wlan_hdd_main.c | 2 +- core/hdd/src/wlan_hdd_nan.c | 2 +- core/hdd/src/wlan_hdd_nan_datapath.c | 2 +- core/hdd/src/wlan_hdd_p2p.c | 2 +- core/hdd/src/wlan_hdd_power.c | 2 +- core/hdd/src/wlan_hdd_scan.c | 2 +- core/hdd/src/wlan_hdd_sysfs.c | 2 +- os_if/sync/inc/osif_psoc_sync.h | 160 +++++++ os_if/sync/inc/osif_sync.h | 16 +- os_if/sync/inc/osif_vdev_sync.h | 150 ++++++- os_if/sync/src/__osif_psoc_sync.h | 29 ++ os_if/sync/src/__osif_vdev_sync.h | 14 + os_if/sync/src/osif_psoc_sync.c | 333 +++++++++++++++ os_if/sync/src/osif_sync.c | 16 +- os_if/sync/src/osif_vdev_sync.c | 287 ++++++++++++- 24 files changed, 1016 insertions(+), 965 deletions(-) delete mode 100644 core/hdd/inc/wlan_hdd_dsc.h delete mode 100644 core/hdd/src/wlan_hdd_dsc.c diff --git a/Kbuild b/Kbuild index 28cf66bcf3af..aeee601731a4 100644 --- a/Kbuild +++ b/Kbuild @@ -53,7 +53,6 @@ HDD_OBJS := $(HDD_SRC_DIR)/wlan_hdd_assoc.o \ $(HDD_SRC_DIR)/wlan_hdd_cfg80211.o \ $(HDD_SRC_DIR)/wlan_hdd_data_stall_detection.o \ $(HDD_SRC_DIR)/wlan_hdd_driver_ops.o \ - $(HDD_SRC_DIR)/wlan_hdd_dsc.o \ $(HDD_SRC_DIR)/wlan_hdd_ext_scan.o \ $(HDD_SRC_DIR)/wlan_hdd_ftm.o \ $(HDD_SRC_DIR)/wlan_hdd_hostapd.o \ diff --git a/components/dsc/inc/wlan_dsc_psoc.h b/components/dsc/inc/wlan_dsc_psoc.h index de4aed81fbc9..7354121d8942 100644 --- a/components/dsc/inc/wlan_dsc_psoc.h +++ b/components/dsc/inc/wlan_dsc_psoc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -24,6 +24,7 @@ #define __WLAN_DSC_PSOC_H #include "qdf_status.h" +#include "wlan_dsc_driver.h" /** * struct dsc_psoc - opaque dsc psoc context diff --git a/components/dsc/inc/wlan_dsc_vdev.h b/components/dsc/inc/wlan_dsc_vdev.h index c41919e3dddb..846c3c45ce5a 100644 --- a/components/dsc/inc/wlan_dsc_vdev.h +++ b/components/dsc/inc/wlan_dsc_vdev.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -24,6 +24,7 @@ #define __WLAN_DSC_VDEV_H #include "qdf_status.h" +#include "wlan_dsc_psoc.h" /** * struct dsc_vdev - opaque dsc vdev context diff --git a/core/hdd/inc/wlan_hdd_dsc.h b/core/hdd/inc/wlan_hdd_dsc.h deleted file mode 100644 index 693d0140f063..000000000000 --- a/core/hdd/inc/wlan_hdd_dsc.h +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * - * 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. - */ - -#ifndef __WLAN_HDD_DSC_H__ -#define __WLAN_HDD_DSC_H__ - -#include "qdf_types.h" -#include "wlan_dsc.h" -#include "wlan_hdd_main.h" - -/** - * hdd_dsc_init() - global initializer for HDD DSC - * - * Return: None - */ -void hdd_dsc_init(void); - -/** - * hdd_dsc_deinit() - global deinitializer for HDD DSC - * - * Return: None - */ -void hdd_dsc_deinit(void); - -/** - * struct hdd_psoc_sync - opaque synchronization handle for a psoc - */ -struct hdd_psoc_sync; - -/** - * hdd_psoc_sync_create() - create a psoc synchronization context - * @dsc_driver: parent dsc_driver to the psoc - * @out_psoc_sync: out parameter for the new synchronization context - * - * Return: Errno - */ -qdf_must_check int -hdd_psoc_sync_create(struct dsc_driver *dsc_driver, - struct hdd_psoc_sync **out_psoc_sync); - -/** - * hdd_psoc_sync_create_with_trans() - create a psoc synchronization context - * @dsc_driver: parent dsc_driver to the psoc - * @out_psoc_sync: out parameter for the new synchronization context - * - * For protecting the device creation process. - * - * Return: Errno - */ -#define hdd_psoc_sync_create_with_trans(dsc_driver, out_psoc_sync) \ - __hdd_psoc_sync_create_with_trans(dsc_driver, out_psoc_sync, __func__) - -qdf_must_check int -__hdd_psoc_sync_create_with_trans(struct dsc_driver *dsc_driver, - struct hdd_psoc_sync **out_psoc_sync, - const char *desc); - -/** - * hdd_psoc_sync_destroy() - destroy a psoc synchronization context - * @psoc_sync: the context to destroy - * - * Return: none - */ -void hdd_psoc_sync_destroy(struct hdd_psoc_sync *psoc_sync); - -/** - * hdd_psoc_sync_register() - register a psoc for operations/transitions - * @dev: the device to use as the operation/transition lookup key - * @psoc_sync: the psoc synchronization context to register - * - * Return: none - */ -void hdd_psoc_sync_register(struct device *dev, - struct hdd_psoc_sync *psoc_sync); - -/** - * hdd_psoc_sync_unregister() - unregister a psoc for operations/transitions - * @dev: the device originally used to register the psoc_sync context - * - * Return: the psoc synchronization context that was registered for @dev - */ -struct hdd_psoc_sync *hdd_psoc_sync_unregister(struct device *dev); - -/** - * hdd_psoc_sync_trans_start() - attempt to start a transition on @dev - * @dev: the device to transition - * @out_psoc_sync: out parameter for the synchronization context registered with - * @dev, populated on success - * - * Return: Errno - */ -#define hdd_psoc_sync_trans_start(dev, out_psoc_sync) \ - __hdd_psoc_sync_trans_start(dev, out_psoc_sync, __func__) - -qdf_must_check int -__hdd_psoc_sync_trans_start(struct device *dev, - struct hdd_psoc_sync **out_psoc_sync, - const char *desc); - -/** - * hdd_psoc_sync_trans_start_wait() - attempt to start a transition on @dev, - * blocking if a conflicting transition is in flight - * @dev: the device to transition - * @out_psoc_sync: out parameter for the synchronization context registered with - * @dev, populated on success - * - * Return: Errno - */ -#define hdd_psoc_sync_trans_start_wait(dev, out_psoc_sync) \ - __hdd_psoc_sync_trans_start_wait(dev, out_psoc_sync, __func__) - -qdf_must_check int -__hdd_psoc_sync_trans_start_wait(struct device *dev, - struct hdd_psoc_sync **out_psoc_sync, - const char *desc); - -/** - * hdd_psoc_sync_trans_resume() - resume a transition on @dev - * @dev: the device under transition - * @out_psoc_sync: out parameter for the synchronization context registered with - * @dev, populated on success - * - * Return: Errno - */ -int hdd_psoc_sync_trans_resume(struct device *dev, - struct hdd_psoc_sync **out_psoc_sync); - -/** - * hdd_psoc_sync_trans_stop() - stop a transition associated with @psoc_sync - * @psoc_sync: the synchonization context tracking the transition - * - * Return: none - */ -void hdd_psoc_sync_trans_stop(struct hdd_psoc_sync *psoc_sync); - -/** - * hdd_psoc_sync_assert_trans_protected() - assert that @dev is currently - * protected by a transition - * @dev: the device to check - * - * Return: none - */ -void hdd_psoc_sync_assert_trans_protected(struct device *dev); - -/** - * hdd_psoc_sync_op_start() - attempt to start an operation on @dev - * @dev: the device to operate against - * @out_psoc_sync: out parameter for the synchronization context registered with - * @dev, populated on success - * - * Return: Errno - */ -#define hdd_psoc_sync_op_start(dev, out_psoc_sync) \ - __hdd_psoc_sync_op_start(dev, out_psoc_sync, __func__) - -qdf_must_check int -__hdd_psoc_sync_op_start(struct device *dev, - struct hdd_psoc_sync **out_psoc_sync, - const char *func); - -/** - * hdd_psoc_sync_op_stop() - stop an operation associated with @psoc_sync - * @psoc_sync: the synchonization context tracking the operation - * - * Return: none - */ -#define hdd_psoc_sync_op_stop(dev) \ - __hdd_psoc_sync_op_stop(dev, __func__) - -void __hdd_psoc_sync_op_stop(struct hdd_psoc_sync *psoc_sync, - const char *func); - -/** - * hdd_psoc_sync_wait_for_ops() - wait until all @psoc_sync operations complete - * @psoc_sync: the synchonization context tracking the operations - * - * Return: None - */ -void hdd_psoc_sync_wait_for_ops(struct hdd_psoc_sync *psoc_sync); - -/** - * struct hdd_vdev_sync - opaque synchronization handle for a vdev - */ -struct hdd_vdev_sync; - -/** - * hdd_vdev_sync_create() - create a vdev synchronization context - * @dev: parent device to the vdev - * @out_vdev_sync: out parameter for the new synchronization context - * - * Return: Errno - */ -qdf_must_check int -hdd_vdev_sync_create(struct device *dev, struct hdd_vdev_sync **out_vdev_sync); - -/** - * hdd_vdev_sync_create_with_trans() - create a vdev synchronization context - * @dev: parent device to the vdev - * @out_vdev_sync: out parameter for the new synchronization context - * - * For protecting the net_device creation process. - * - * Return: Errno - */ -#define hdd_vdev_sync_create_with_trans(dev, out_vdev_sync) \ - __hdd_vdev_sync_create_with_trans(dev, out_vdev_sync, __func__) - -qdf_must_check int -__hdd_vdev_sync_create_with_trans(struct device *dev, - struct hdd_vdev_sync **out_vdev_sync, - const char *desc); - -/** - * hdd_vdev_sync_destroy() - destroy a vdev synchronization context - * @vdev_sync: the context to destroy - * - * Return: none - */ -void hdd_vdev_sync_destroy(struct hdd_vdev_sync *vdev_sync); - -/** - * hdd_vdev_sync_register() - register a vdev for operations/transitions - * @net_dev: the net_device to use as the operation/transition lookup key - * @vdev_sync: the vdev synchronization context to register - * - * Return: none - */ -void hdd_vdev_sync_register(struct net_device *net_dev, - struct hdd_vdev_sync *vdev_sync); - -/** - * hdd_vdev_sync_unregister() - unregister a vdev for operations/transitions - * @net_dev: the net_device originally used to register the vdev_sync context - * - * Return: the vdev synchronization context that was registered for @net_dev - */ -struct hdd_vdev_sync *hdd_vdev_sync_unregister(struct net_device *net_dev); - -/** - * hdd_vdev_sync_trans_start() - attempt to start a transition on @net_dev - * @net_dev: the net_device to transition - * @out_vdev_sync: out parameter for the synchronization context registered with - * @net_dev, populated on success - * - * Return: Errno - */ -#define hdd_vdev_sync_trans_start(net_dev, out_vdev_sync) \ - __hdd_vdev_sync_trans_start(net_dev, out_vdev_sync, __func__) - -qdf_must_check int -__hdd_vdev_sync_trans_start(struct net_device *net_dev, - struct hdd_vdev_sync **out_vdev_sync, - const char *desc); - -/** - * hdd_vdev_sync_trans_start_wait() - attempt to start a transition on @net_dev, - * blocking if a conflicting transition is in flight - * @net_dev: the net_device to transition - * @out_vdev_sync: out parameter for the synchronization context registered with - * @net_dev, populated on success - * - * Return: Errno - */ -#define hdd_vdev_sync_trans_start_wait(net_dev, out_vdev_sync) \ - __hdd_vdev_sync_trans_start_wait(net_dev, out_vdev_sync, __func__) - -qdf_must_check int -__hdd_vdev_sync_trans_start_wait(struct net_device *net_dev, - struct hdd_vdev_sync **out_vdev_sync, - const char *desc); - -/** - * hdd_vdev_sync_trans_stop() - stop a transition associated with @vdev_sync - * @vdev_sync: the synchonization context tracking the transition - * - * Return: none - */ -void hdd_vdev_sync_trans_stop(struct hdd_vdev_sync *vdev_sync); - -/** - * hdd_vdev_sync_assert_trans_protected() - assert that @net_dev is currently - * protected by a transition - * @net_dev: the net_device to check - * - * Return: none - */ -void hdd_vdev_sync_assert_trans_protected(struct net_device *net_dev); - -/** - * hdd_vdev_sync_op_start() - attempt to start an operation on @net_dev - * @net_dev: the net_device to operate against - * @out_vdev_sync: out parameter for the synchronization context registered with - * @net_dev, populated on success - * - * Return: Errno - */ -#define hdd_vdev_sync_op_start(net_dev, out_vdev_sync) \ - __hdd_vdev_sync_op_start(net_dev, out_vdev_sync, __func__) - -qdf_must_check int -__hdd_vdev_sync_op_start(struct net_device *net_dev, - struct hdd_vdev_sync **out_vdev_sync, - const char *func); - -/** - * hdd_vdev_sync_op_stop() - stop an operation associated with @vdev_sync - * @vdev_sync: the synchonization context tracking the operation - * - * Return: none - */ -#define hdd_vdev_sync_op_stop(net_dev) \ - __hdd_vdev_sync_op_stop(net_dev, __func__) - -void __hdd_vdev_sync_op_stop(struct hdd_vdev_sync *vdev_sync, - const char *func); - -/** - * hdd_vdev_sync_wait_for_ops() - wait until all @vdev_sync operations complete - * @vdev_sync: the synchonization context tracking the operations - * - * Return: None - */ -void hdd_vdev_sync_wait_for_ops(struct hdd_vdev_sync *vdev_sync); - -#endif diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index ca89ac726280..1e1869436f53 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -118,7 +118,7 @@ #include #include #include "wlan_policy_mgr_ucfg.h" -#include +#include "osif_sync.h" #include "wlan_mlme_ucfg_api.h" #include "wlan_mlme_public_struct.h" #include "wlan_extscan_ucfg_api.h" diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index f1bc796853af..e833c07c210a 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -26,7 +26,7 @@ #include "hif.h" #include "htc.h" #include "epping_main.h" -#include "wlan_hdd_dsc.h" +#include "osif_sync.h" #include "wlan_hdd_main.h" #include "wlan_hdd_power.h" #include "wlan_logging_sock_svc.h" diff --git a/core/hdd/src/wlan_hdd_dsc.c b/core/hdd/src/wlan_hdd_dsc.c deleted file mode 100644 index eec1da27d05f..000000000000 --- a/core/hdd/src/wlan_hdd_dsc.c +++ /dev/null @@ -1,607 +0,0 @@ -/* - * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * - * 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. - */ - -#include "qdf_lock.h" -#include "qdf_status.h" -#include "qdf_types.h" -#include "wlan_dsc.h" -#include "wlan_hdd_dsc.h" - -/** - * struct hdd_psoc_sync - a psoc synchronization context - * @dev: the device used as a lookup key - * @dsc_psoc: the dsc_psoc used for synchronization - * @in_use: indicates if the context is being used - */ -struct hdd_psoc_sync { - struct device *dev; - struct dsc_psoc *dsc_psoc; - bool in_use; -}; - -#define WLAN_MAX_PSOCS 1 -static struct hdd_psoc_sync __hdd_psoc_sync_arr[WLAN_MAX_PSOCS]; -static qdf_spinlock_t __hdd_psoc_sync_lock; - -#define hdd_psoc_sync_lock_create() qdf_spinlock_create(&__hdd_psoc_sync_lock) -#define hdd_psoc_sync_lock_destroy() qdf_spinlock_destroy(&__hdd_psoc_sync_lock) -#define hdd_psoc_sync_lock() qdf_spin_lock_bh(&__hdd_psoc_sync_lock) -#define hdd_psoc_sync_unlock() qdf_spin_unlock_bh(&__hdd_psoc_sync_lock) -#define hdd_psoc_sync_lock_assert() \ - QDF_BUG(qdf_spin_is_locked(&__hdd_psoc_sync_lock)) - -static struct hdd_psoc_sync *hdd_psoc_sync_lookup(struct device *dev) -{ - int i; - - hdd_psoc_sync_lock_assert(); - - for (i = 0; i < QDF_ARRAY_SIZE(__hdd_psoc_sync_arr); i++) { - struct hdd_psoc_sync *psoc_sync = __hdd_psoc_sync_arr + i; - - if (psoc_sync->dev == dev) - return psoc_sync; - } - - return NULL; -} - -static struct hdd_psoc_sync *hdd_psoc_sync_get(void) -{ - int i; - - hdd_psoc_sync_lock_assert(); - - for (i = 0; i < QDF_ARRAY_SIZE(__hdd_psoc_sync_arr); i++) { - struct hdd_psoc_sync *psoc_sync = __hdd_psoc_sync_arr + i; - - if (!psoc_sync->in_use) { - psoc_sync->in_use = true; - return psoc_sync; - } - } - - return NULL; -} - -static void hdd_psoc_sync_put(struct hdd_psoc_sync *psoc_sync) -{ - hdd_psoc_sync_lock_assert(); - - qdf_mem_zero(psoc_sync, sizeof(*psoc_sync)); -} - -int hdd_psoc_sync_create(struct dsc_driver *dsc_driver, - struct hdd_psoc_sync **out_psoc_sync) -{ - QDF_STATUS status; - struct hdd_psoc_sync *psoc_sync; - - QDF_BUG(dsc_driver); - if (!dsc_driver) - return -EINVAL; - - QDF_BUG(out_psoc_sync); - if (!out_psoc_sync) - return -EINVAL; - - hdd_psoc_sync_lock(); - psoc_sync = hdd_psoc_sync_get(); - hdd_psoc_sync_unlock(); - if (!psoc_sync) - return -ENOMEM; - - status = dsc_psoc_create(dsc_driver, &psoc_sync->dsc_psoc); - if (QDF_IS_STATUS_ERROR(status)) - goto sync_put; - - *out_psoc_sync = psoc_sync; - - return 0; - -sync_put: - hdd_psoc_sync_lock(); - hdd_psoc_sync_put(psoc_sync); - hdd_psoc_sync_unlock(); - - return qdf_status_to_os_return(status); -} - -int __hdd_psoc_sync_create_with_trans(struct dsc_driver *dsc_driver, - struct hdd_psoc_sync **out_psoc_sync, - const char *desc) -{ - struct hdd_psoc_sync *psoc_sync; - QDF_STATUS status; - int errno; - - errno = hdd_psoc_sync_create(dsc_driver, &psoc_sync); - if (errno) - return errno; - - status = dsc_psoc_trans_start(psoc_sync->dsc_psoc, desc); - if (QDF_IS_STATUS_ERROR(status)) - goto sync_destroy; - - *out_psoc_sync = psoc_sync; - - return 0; - -sync_destroy: - hdd_psoc_sync_destroy(psoc_sync); - - return qdf_status_to_os_return(status); -} - -void hdd_psoc_sync_destroy(struct hdd_psoc_sync *psoc_sync) -{ - QDF_BUG(psoc_sync); - if (!psoc_sync) - return; - - dsc_psoc_destroy(&psoc_sync->dsc_psoc); - - hdd_psoc_sync_lock(); - hdd_psoc_sync_put(psoc_sync); - hdd_psoc_sync_unlock(); -} - -void hdd_psoc_sync_register(struct device *dev, - struct hdd_psoc_sync *psoc_sync) -{ - QDF_BUG(dev); - QDF_BUG(psoc_sync); - if (!psoc_sync) - return; - - hdd_psoc_sync_lock(); - psoc_sync->dev = dev; - hdd_psoc_sync_unlock(); -} - -struct hdd_psoc_sync *hdd_psoc_sync_unregister(struct device *dev) -{ - struct hdd_psoc_sync *psoc_sync; - - QDF_BUG(dev); - if (!dev) - return NULL; - - hdd_psoc_sync_lock(); - psoc_sync = hdd_psoc_sync_lookup(dev); - if (psoc_sync) - psoc_sync->dev = NULL; - hdd_psoc_sync_unlock(); - - return psoc_sync; -} - -typedef QDF_STATUS (*psoc_start_func)(struct dsc_psoc *, const char *); - -static int __hdd_psoc_sync_start_callback(struct device *dev, - struct hdd_psoc_sync **out_psoc_sync, - const char *desc, - psoc_start_func psoc_start_cb) -{ - QDF_STATUS status; - struct hdd_psoc_sync *psoc_sync; - - hdd_psoc_sync_lock_assert(); - - *out_psoc_sync = NULL; - - psoc_sync = hdd_psoc_sync_lookup(dev); - if (!psoc_sync) - return -EAGAIN; - - status = psoc_start_cb(psoc_sync->dsc_psoc, desc); - if (QDF_IS_STATUS_ERROR(status)) - return qdf_status_to_os_return(status); - - *out_psoc_sync = psoc_sync; - - return 0; -} - -int __hdd_psoc_sync_trans_start(struct device *dev, - struct hdd_psoc_sync **out_psoc_sync, - const char *desc) -{ - int errno; - - hdd_psoc_sync_lock(); - errno = __hdd_psoc_sync_start_callback(dev, out_psoc_sync, desc, - dsc_psoc_trans_start); - hdd_psoc_sync_unlock(); - - return errno; -} - -int __hdd_psoc_sync_trans_start_wait(struct device *dev, - struct hdd_psoc_sync **out_psoc_sync, - const char *desc) -{ - int errno; - - hdd_psoc_sync_lock(); - errno = __hdd_psoc_sync_start_callback(dev, out_psoc_sync, desc, - dsc_psoc_trans_start_wait); - hdd_psoc_sync_unlock(); - - return errno; -} - -static QDF_STATUS __assert_trans_cb(struct dsc_psoc *dsc_psoc, const char *desc) -{ - dsc_psoc_assert_trans_protected(dsc_psoc); - - return QDF_STATUS_SUCCESS; -} - -int hdd_psoc_sync_trans_resume(struct device *dev, - struct hdd_psoc_sync **out_psoc_sync) -{ - int errno; - - hdd_psoc_sync_lock(); - errno = __hdd_psoc_sync_start_callback(dev, out_psoc_sync, NULL, - __assert_trans_cb); - hdd_psoc_sync_unlock(); - - return errno; -} - -void hdd_psoc_sync_trans_stop(struct hdd_psoc_sync *psoc_sync) -{ - dsc_psoc_trans_stop(psoc_sync->dsc_psoc); -} - -void hdd_psoc_sync_assert_trans_protected(struct device *dev) -{ - struct hdd_psoc_sync *psoc_sync; - - hdd_psoc_sync_lock(); - - psoc_sync = hdd_psoc_sync_lookup(dev); - QDF_BUG(psoc_sync); - if (psoc_sync) - dsc_psoc_assert_trans_protected(psoc_sync->dsc_psoc); - - hdd_psoc_sync_unlock(); -} - -int __hdd_psoc_sync_op_start(struct device *dev, - struct hdd_psoc_sync **out_psoc_sync, - const char *func) -{ - int errno; - - hdd_psoc_sync_lock(); - errno = __hdd_psoc_sync_start_callback(dev, out_psoc_sync, func, - _dsc_psoc_op_start); - hdd_psoc_sync_unlock(); - - return errno; -} - -void __hdd_psoc_sync_op_stop(struct hdd_psoc_sync *psoc_sync, - const char *func) -{ - _dsc_psoc_op_stop(psoc_sync->dsc_psoc, func); -} - -void hdd_psoc_sync_wait_for_ops(struct hdd_psoc_sync *psoc_sync) -{ - dsc_psoc_wait_for_ops(psoc_sync->dsc_psoc); -} - -/** - * struct hdd_vdev_sync - a vdev synchronization context - * @net_dev: the net_device used as a lookup key - * @dsc_vdev: the dsc_vdev used for synchronization - * @in_use: indicates if the context is being used - */ -struct hdd_vdev_sync { - struct net_device *net_dev; - struct dsc_vdev *dsc_vdev; - bool in_use; -}; - -static struct hdd_vdev_sync __hdd_vdev_sync_arr[WLAN_MAX_VDEVS]; -static qdf_spinlock_t __hdd_vdev_sync_lock; - -#define hdd_vdev_sync_lock_create() qdf_spinlock_create(&__hdd_vdev_sync_lock) -#define hdd_vdev_sync_lock_destroy() qdf_spinlock_destroy(&__hdd_vdev_sync_lock) -#define hdd_vdev_sync_lock() qdf_spin_lock_bh(&__hdd_vdev_sync_lock) -#define hdd_vdev_sync_unlock() qdf_spin_unlock_bh(&__hdd_vdev_sync_lock) -#define hdd_vdev_sync_lock_assert() \ - QDF_BUG(qdf_spin_is_locked(&__hdd_vdev_sync_lock)) - -static struct hdd_vdev_sync *hdd_vdev_sync_lookup(struct net_device *net_dev) -{ - int i; - - hdd_vdev_sync_lock_assert(); - - for (i = 0; i < QDF_ARRAY_SIZE(__hdd_vdev_sync_arr); i++) { - struct hdd_vdev_sync *vdev_sync = __hdd_vdev_sync_arr + i; - - if (vdev_sync->net_dev == net_dev) - return vdev_sync; - } - - return NULL; -} - -static struct hdd_vdev_sync *hdd_vdev_sync_get(void) -{ - int i; - - hdd_vdev_sync_lock_assert(); - - for (i = 0; i < QDF_ARRAY_SIZE(__hdd_vdev_sync_arr); i++) { - struct hdd_vdev_sync *vdev_sync = __hdd_vdev_sync_arr + i; - - if (!vdev_sync->in_use) { - vdev_sync->in_use = true; - return vdev_sync; - } - } - - return NULL; -} - -static void hdd_vdev_sync_put(struct hdd_vdev_sync *vdev_sync) -{ - hdd_vdev_sync_lock_assert(); - - qdf_mem_zero(vdev_sync, sizeof(*vdev_sync)); -} - -static QDF_STATUS hdd_vdev_dsc_create(struct device *dev, - struct dsc_vdev **out_dsc_vdev) -{ - struct hdd_psoc_sync *psoc_sync; - - hdd_psoc_sync_lock_assert(); - - psoc_sync = hdd_psoc_sync_lookup(dev); - if (!psoc_sync) - return QDF_STATUS_E_INVAL; - - return dsc_vdev_create(psoc_sync->dsc_psoc, out_dsc_vdev); -} - -int hdd_vdev_sync_create(struct device *dev, - struct hdd_vdev_sync **out_vdev_sync) -{ - struct hdd_vdev_sync *vdev_sync; - QDF_STATUS status; - - QDF_BUG(dev); - if (!dev) - return -EINVAL; - - QDF_BUG(out_vdev_sync); - if (!out_vdev_sync) - return -EINVAL; - - hdd_vdev_sync_lock(); - vdev_sync = hdd_vdev_sync_get(); - hdd_vdev_sync_unlock(); - if (!vdev_sync) - return -ENOMEM; - - hdd_psoc_sync_lock(); - status = hdd_vdev_dsc_create(dev, &vdev_sync->dsc_vdev); - hdd_psoc_sync_unlock(); - if (QDF_IS_STATUS_ERROR(status)) - goto sync_put; - - *out_vdev_sync = vdev_sync; - - return 0; - -sync_put: - hdd_vdev_sync_lock(); - hdd_vdev_sync_put(vdev_sync); - hdd_vdev_sync_unlock(); - - return qdf_status_to_os_return(status); -} - -int __hdd_vdev_sync_create_with_trans(struct device *dev, - struct hdd_vdev_sync **out_vdev_sync, - const char *desc) -{ - struct hdd_vdev_sync *vdev_sync; - QDF_STATUS status; - int errno; - - errno = hdd_vdev_sync_create(dev, &vdev_sync); - if (errno) - return errno; - - status = dsc_vdev_trans_start(vdev_sync->dsc_vdev, desc); - if (QDF_IS_STATUS_ERROR(status)) - goto sync_destroy; - - *out_vdev_sync = vdev_sync; - - return 0; - -sync_destroy: - hdd_vdev_sync_destroy(vdev_sync); - - return qdf_status_to_os_return(status); -} - -void hdd_vdev_sync_destroy(struct hdd_vdev_sync *vdev_sync) -{ - QDF_BUG(vdev_sync); - if (!vdev_sync) - return; - - dsc_vdev_destroy(&vdev_sync->dsc_vdev); - - hdd_vdev_sync_lock(); - hdd_vdev_sync_put(vdev_sync); - hdd_vdev_sync_unlock(); -} - -void hdd_vdev_sync_register(struct net_device *net_dev, - struct hdd_vdev_sync *vdev_sync) -{ - QDF_BUG(net_dev); - QDF_BUG(vdev_sync); - if (!vdev_sync) - return; - - hdd_vdev_sync_lock(); - vdev_sync->net_dev = net_dev; - hdd_vdev_sync_unlock(); -} - -struct hdd_vdev_sync *hdd_vdev_sync_unregister(struct net_device *net_dev) -{ - struct hdd_vdev_sync *vdev_sync; - - QDF_BUG(net_dev); - if (!net_dev) - return NULL; - - hdd_vdev_sync_lock(); - vdev_sync = hdd_vdev_sync_lookup(net_dev); - if (vdev_sync) - vdev_sync->net_dev = NULL; - hdd_vdev_sync_unlock(); - - return vdev_sync; -} - -typedef QDF_STATUS (*vdev_start_func)(struct dsc_vdev *, const char *); - -static int __hdd_vdev_sync_start_callback(struct net_device *net_dev, - struct hdd_vdev_sync **out_vdev_sync, - const char *desc, - vdev_start_func vdev_start_cb) -{ - QDF_STATUS status; - struct hdd_vdev_sync *vdev_sync; - - hdd_vdev_sync_lock_assert(); - - *out_vdev_sync = NULL; - - vdev_sync = hdd_vdev_sync_lookup(net_dev); - if (!vdev_sync) - return -EAGAIN; - - status = vdev_start_cb(vdev_sync->dsc_vdev, desc); - if (QDF_IS_STATUS_ERROR(status)) - return qdf_status_to_os_return(status); - - *out_vdev_sync = vdev_sync; - - return 0; -} - -int __hdd_vdev_sync_trans_start(struct net_device *net_dev, - struct hdd_vdev_sync **out_vdev_sync, - const char *desc) -{ - int errno; - - hdd_vdev_sync_lock(); - errno = __hdd_vdev_sync_start_callback(net_dev, out_vdev_sync, desc, - dsc_vdev_trans_start); - hdd_vdev_sync_unlock(); - - return errno; -} - -int __hdd_vdev_sync_trans_start_wait(struct net_device *net_dev, - struct hdd_vdev_sync **out_vdev_sync, - const char *desc) -{ - int errno; - - hdd_vdev_sync_lock(); - errno = __hdd_vdev_sync_start_callback(net_dev, out_vdev_sync, desc, - dsc_vdev_trans_start_wait); - hdd_vdev_sync_unlock(); - - return errno; -} - -void hdd_vdev_sync_trans_stop(struct hdd_vdev_sync *vdev_sync) -{ - dsc_vdev_trans_stop(vdev_sync->dsc_vdev); -} - -void hdd_vdev_sync_assert_trans_protected(struct net_device *net_dev) -{ - struct hdd_vdev_sync *vdev_sync; - - hdd_vdev_sync_lock(); - - vdev_sync = hdd_vdev_sync_lookup(net_dev); - QDF_BUG(vdev_sync); - if (vdev_sync) - dsc_vdev_assert_trans_protected(vdev_sync->dsc_vdev); - - hdd_vdev_sync_unlock(); -} - -int __hdd_vdev_sync_op_start(struct net_device *net_dev, - struct hdd_vdev_sync **out_vdev_sync, - const char *func) -{ - int errno; - - hdd_vdev_sync_lock(); - errno = __hdd_vdev_sync_start_callback(net_dev, out_vdev_sync, func, - _dsc_vdev_op_start); - hdd_vdev_sync_unlock(); - - return errno; -} - -void __hdd_vdev_sync_op_stop(struct hdd_vdev_sync *vdev_sync, - const char *func) -{ - _dsc_vdev_op_stop(vdev_sync->dsc_vdev, func); -} - -void hdd_vdev_sync_wait_for_ops(struct hdd_vdev_sync *vdev_sync) -{ - dsc_vdev_wait_for_ops(vdev_sync->dsc_vdev); -} - -void hdd_dsc_init(void) -{ - hdd_psoc_sync_lock_create(); - hdd_vdev_sync_lock_create(); -} - -void hdd_dsc_deinit(void) -{ - hdd_vdev_sync_lock_destroy(); - hdd_psoc_sync_lock_destroy(); -} - diff --git a/core/hdd/src/wlan_hdd_ext_scan.c b/core/hdd/src/wlan_hdd_ext_scan.c index 9779107abc69..73aefc97c5ac 100644 --- a/core/hdd/src/wlan_hdd_ext_scan.c +++ b/core/hdd/src/wlan_hdd_ext_scan.c @@ -27,7 +27,7 @@ #include "wlan_hdd_ext_scan.h" #include "wlan_hdd_regulatory.h" -#include +#include "osif_sync.h" #include "cds_utils.h" #include "cds_sched.h" #include diff --git a/core/hdd/src/wlan_hdd_he.c b/core/hdd/src/wlan_hdd_he.c index fd3f29ac9bbd..4d0eff24cca3 100644 --- a/core/hdd/src/wlan_hdd_he.c +++ b/core/hdd/src/wlan_hdd_he.c @@ -25,7 +25,7 @@ #include "wlan_hdd_main.h" #include "wlan_hdd_he.h" -#include +#include "osif_sync.h" #include "wma_he.h" #include "wlan_utility.h" #include "wlan_mlme_ucfg_api.h" diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 5a28ffb4e5e4..db04f6638fc9 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -40,7 +40,7 @@ #include #include #include -#include "wlan_hdd_dsc.h" +#include "osif_sync.h" #include #include #include diff --git a/core/hdd/src/wlan_hdd_nan.c b/core/hdd/src/wlan_hdd_nan.c index e1562c68683b..f788ca4690c2 100644 --- a/core/hdd/src/wlan_hdd_nan.c +++ b/core/hdd/src/wlan_hdd_nan.c @@ -30,7 +30,7 @@ #include "sme_api.h" #include "wlan_hdd_main.h" #include "wlan_hdd_nan.h" -#include +#include "osif_sync.h" #include #include "cfg_nan_api.h" #include "os_if_nan.h" diff --git a/core/hdd/src/wlan_hdd_nan_datapath.c b/core/hdd/src/wlan_hdd_nan_datapath.c index 65a87c36d75d..3ff0cd8e3443 100644 --- a/core/hdd/src/wlan_hdd_nan_datapath.c +++ b/core/hdd/src/wlan_hdd_nan_datapath.c @@ -28,7 +28,7 @@ #include #include "wlan_hdd_includes.h" #include "wlan_hdd_p2p.h" -#include +#include "osif_sync.h" #include "wma_api.h" #include "wlan_hdd_assoc.h" #include "sme_nan_datapath.h" diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c index cee87b310a61..18643ad75fb3 100644 --- a/core/hdd/src/wlan_hdd_p2p.c +++ b/core/hdd/src/wlan_hdd_p2p.c @@ -24,7 +24,7 @@ * */ -#include "wlan_hdd_dsc.h" +#include "osif_sync.h" #include #include #include diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 39af3425e3bc..d46b0ef5bffb 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -78,7 +78,7 @@ #include #include "wlan_p2p_ucfg_api.h" #include "wlan_mlme_ucfg_api.h" -#include "wlan_hdd_dsc.h" +#include "osif_sync.h" /* Preprocessor definitions and constants */ #ifdef QCA_WIFI_NAPIER_EMULATION diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c index 5aecb067e6e3..5e25bd3a2c85 100644 --- a/core/hdd/src/wlan_hdd_scan.c +++ b/core/hdd/src/wlan_hdd_scan.c @@ -34,7 +34,7 @@ #include "wlan_hdd_p2p.h" #include "wlan_hdd_trace.h" #include "wlan_hdd_scan.h" -#include +#include "osif_sync.h" #include "wlan_policy_mgr_api.h" #include "wlan_hdd_power.h" #include "wma_api.h" diff --git a/core/hdd/src/wlan_hdd_sysfs.c b/core/hdd/src/wlan_hdd_sysfs.c index 042cca2e2936..8d2736abeb47 100644 --- a/core/hdd/src/wlan_hdd_sysfs.c +++ b/core/hdd/src/wlan_hdd_sysfs.c @@ -34,7 +34,7 @@ #include #include #include -#include +#include "osif_sync.h" #define MAX_PSOC_ID_SIZE 10 diff --git a/os_if/sync/inc/osif_psoc_sync.h b/os_if/sync/inc/osif_psoc_sync.h index a338f8a5a59d..3b8b3b083215 100644 --- a/os_if/sync/inc/osif_psoc_sync.h +++ b/os_if/sync/inc/osif_psoc_sync.h @@ -19,5 +19,165 @@ #ifndef __OSIF_PSOC_SYNC_H #define __OSIF_PSOC_SYNC_H +#include "linux/device.h" +#include "wlan_dsc_driver.h" +#include "qdf_types.h" + +/** + * struct hdd_psoc_sync - opaque synchronization handle for a psoc + */ +struct hdd_psoc_sync; + +/** + * hdd_psoc_sync_create() - create a psoc synchronization context + * @dsc_driver: parent dsc_driver to the psoc + * @out_psoc_sync: out parameter for the new synchronization context + * + * Return: Errno + */ +qdf_must_check int +hdd_psoc_sync_create(struct dsc_driver *dsc_driver, + struct hdd_psoc_sync **out_psoc_sync); + +/** + * hdd_psoc_sync_create_with_trans() - create a psoc synchronization context + * @dsc_driver: parent dsc_driver to the psoc + * @out_psoc_sync: out parameter for the new synchronization context + * + * For protecting the device creation process. + * + * Return: Errno + */ +#define hdd_psoc_sync_create_with_trans(dsc_driver, out_psoc_sync) \ + __hdd_psoc_sync_create_with_trans(dsc_driver, out_psoc_sync, __func__) + +qdf_must_check int +__hdd_psoc_sync_create_with_trans(struct dsc_driver *dsc_driver, + struct hdd_psoc_sync **out_psoc_sync, + const char *desc); + +/** + * hdd_psoc_sync_destroy() - destroy a psoc synchronization context + * @psoc_sync: the context to destroy + * + * Return: none + */ +void hdd_psoc_sync_destroy(struct hdd_psoc_sync *psoc_sync); + +/** + * hdd_psoc_sync_register() - register a psoc for operations/transitions + * @dev: the device to use as the operation/transition lookup key + * @psoc_sync: the psoc synchronization context to register + * + * Return: none + */ +void hdd_psoc_sync_register(struct device *dev, + struct hdd_psoc_sync *psoc_sync); + +/** + * hdd_psoc_sync_unregister() - unregister a psoc for operations/transitions + * @dev: the device originally used to register the psoc_sync context + * + * Return: the psoc synchronization context that was registered for @dev + */ +struct hdd_psoc_sync *hdd_psoc_sync_unregister(struct device *dev); + +/** + * hdd_psoc_sync_trans_start() - attempt to start a transition on @dev + * @dev: the device to transition + * @out_psoc_sync: out parameter for the synchronization context registered with + * @dev, populated on success + * + * Return: Errno + */ +#define hdd_psoc_sync_trans_start(dev, out_psoc_sync) \ + __hdd_psoc_sync_trans_start(dev, out_psoc_sync, __func__) + +qdf_must_check int +__hdd_psoc_sync_trans_start(struct device *dev, + struct hdd_psoc_sync **out_psoc_sync, + const char *desc); + +/** + * hdd_psoc_sync_trans_start_wait() - attempt to start a transition on @dev, + * blocking if a conflicting transition is in flight + * @dev: the device to transition + * @out_psoc_sync: out parameter for the synchronization context registered with + * @dev, populated on success + * + * Return: Errno + */ +#define hdd_psoc_sync_trans_start_wait(dev, out_psoc_sync) \ + __hdd_psoc_sync_trans_start_wait(dev, out_psoc_sync, __func__) + +qdf_must_check int +__hdd_psoc_sync_trans_start_wait(struct device *dev, + struct hdd_psoc_sync **out_psoc_sync, + const char *desc); + +/** + * hdd_psoc_sync_trans_resume() - resume a transition on @dev + * @dev: the device under transition + * @out_psoc_sync: out parameter for the synchronization context registered with + * @dev, populated on success + * + * Return: Errno + */ +int hdd_psoc_sync_trans_resume(struct device *dev, + struct hdd_psoc_sync **out_psoc_sync); + +/** + * hdd_psoc_sync_trans_stop() - stop a transition associated with @psoc_sync + * @psoc_sync: the synchonization context tracking the transition + * + * Return: none + */ +void hdd_psoc_sync_trans_stop(struct hdd_psoc_sync *psoc_sync); + +/** + * hdd_psoc_sync_assert_trans_protected() - assert that @dev is currently + * protected by a transition + * @dev: the device to check + * + * Return: none + */ +void hdd_psoc_sync_assert_trans_protected(struct device *dev); + +/** + * hdd_psoc_sync_op_start() - attempt to start an operation on @dev + * @dev: the device to operate against + * @out_psoc_sync: out parameter for the synchronization context registered with + * @dev, populated on success + * + * Return: Errno + */ +#define hdd_psoc_sync_op_start(dev, out_psoc_sync) \ + __hdd_psoc_sync_op_start(dev, out_psoc_sync, __func__) + +qdf_must_check int +__hdd_psoc_sync_op_start(struct device *dev, + struct hdd_psoc_sync **out_psoc_sync, + const char *func); + +/** + * hdd_psoc_sync_op_stop() - stop an operation associated with @psoc_sync + * @psoc_sync: the synchonization context tracking the operation + * + * Return: none + */ +#define hdd_psoc_sync_op_stop(dev) \ + __hdd_psoc_sync_op_stop(dev, __func__) + +void __hdd_psoc_sync_op_stop(struct hdd_psoc_sync *psoc_sync, + const char *func); + +/** + * hdd_psoc_sync_wait_for_ops() - wait until all @psoc_sync operations complete + * @psoc_sync: the synchonization context tracking the operations + * + * Return: None + */ +void hdd_psoc_sync_wait_for_ops(struct hdd_psoc_sync *psoc_sync); + #endif /* __OSIF_PSOC_SYNC_H */ diff --git a/os_if/sync/inc/osif_sync.h b/os_if/sync/inc/osif_sync.h index 426cba52fd51..3c8abe11b195 100644 --- a/os_if/sync/inc/osif_sync.h +++ b/os_if/sync/inc/osif_sync.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -23,5 +23,19 @@ #include "osif_psoc_sync.h" #include "osif_vdev_sync.h" +/** + * hdd_dsc_init() - global initializer for HDD DSC + * + * Return: None + */ +void hdd_dsc_init(void); + +/** + * hdd_dsc_deinit() - global deinitializer for HDD DSC + * + * Return: None + */ +void hdd_dsc_deinit(void); + #endif /* __OSIF_SYNC_H */ diff --git a/os_if/sync/inc/osif_vdev_sync.h b/os_if/sync/inc/osif_vdev_sync.h index a26fda5c07c6..ed099cbc9401 100644 --- a/os_if/sync/inc/osif_vdev_sync.h +++ b/os_if/sync/inc/osif_vdev_sync.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -19,5 +19,153 @@ #ifndef __OSIF_VDEV_SYNC_H #define __OSIF_VDEV_SYNC_H +#include "linux/device.h" +#include "linux/netdevice.h" +#include "qdf_types.h" + +/** + * struct hdd_vdev_sync - opaque synchronization handle for a vdev + */ +struct hdd_vdev_sync; + +/** + * hdd_vdev_sync_create() - create a vdev synchronization context + * @dev: parent device to the vdev + * @out_vdev_sync: out parameter for the new synchronization context + * + * Return: Errno + */ +qdf_must_check int +hdd_vdev_sync_create(struct device *dev, struct hdd_vdev_sync **out_vdev_sync); + +/** + * hdd_vdev_sync_create_with_trans() - create a vdev synchronization context + * @dev: parent device to the vdev + * @out_vdev_sync: out parameter for the new synchronization context + * + * For protecting the net_device creation process. + * + * Return: Errno + */ +#define hdd_vdev_sync_create_with_trans(dev, out_vdev_sync) \ + __hdd_vdev_sync_create_with_trans(dev, out_vdev_sync, __func__) + +qdf_must_check int +__hdd_vdev_sync_create_with_trans(struct device *dev, + struct hdd_vdev_sync **out_vdev_sync, + const char *desc); + +/** + * hdd_vdev_sync_destroy() - destroy a vdev synchronization context + * @vdev_sync: the context to destroy + * + * Return: none + */ +void hdd_vdev_sync_destroy(struct hdd_vdev_sync *vdev_sync); + +/** + * hdd_vdev_sync_register() - register a vdev for operations/transitions + * @net_dev: the net_device to use as the operation/transition lookup key + * @vdev_sync: the vdev synchronization context to register + * + * Return: none + */ +void hdd_vdev_sync_register(struct net_device *net_dev, + struct hdd_vdev_sync *vdev_sync); + +/** + * hdd_vdev_sync_unregister() - unregister a vdev for operations/transitions + * @net_dev: the net_device originally used to register the vdev_sync context + * + * Return: the vdev synchronization context that was registered for @net_dev + */ +struct hdd_vdev_sync *hdd_vdev_sync_unregister(struct net_device *net_dev); + +/** + * hdd_vdev_sync_trans_start() - attempt to start a transition on @net_dev + * @net_dev: the net_device to transition + * @out_vdev_sync: out parameter for the synchronization context registered with + * @net_dev, populated on success + * + * Return: Errno + */ +#define hdd_vdev_sync_trans_start(net_dev, out_vdev_sync) \ + __hdd_vdev_sync_trans_start(net_dev, out_vdev_sync, __func__) + +qdf_must_check int +__hdd_vdev_sync_trans_start(struct net_device *net_dev, + struct hdd_vdev_sync **out_vdev_sync, + const char *desc); + +/** + * hdd_vdev_sync_trans_start_wait() - attempt to start a transition on @net_dev, + * blocking if a conflicting transition is in flight + * @net_dev: the net_device to transition + * @out_vdev_sync: out parameter for the synchronization context registered with + * @net_dev, populated on success + * + * Return: Errno + */ +#define hdd_vdev_sync_trans_start_wait(net_dev, out_vdev_sync) \ + __hdd_vdev_sync_trans_start_wait(net_dev, out_vdev_sync, __func__) + +qdf_must_check int +__hdd_vdev_sync_trans_start_wait(struct net_device *net_dev, + struct hdd_vdev_sync **out_vdev_sync, + const char *desc); + +/** + * hdd_vdev_sync_trans_stop() - stop a transition associated with @vdev_sync + * @vdev_sync: the synchonization context tracking the transition + * + * Return: none + */ +void hdd_vdev_sync_trans_stop(struct hdd_vdev_sync *vdev_sync); + +/** + * hdd_vdev_sync_assert_trans_protected() - assert that @net_dev is currently + * protected by a transition + * @net_dev: the net_device to check + * + * Return: none + */ +void hdd_vdev_sync_assert_trans_protected(struct net_device *net_dev); + +/** + * hdd_vdev_sync_op_start() - attempt to start an operation on @net_dev + * @net_dev: the net_device to operate against + * @out_vdev_sync: out parameter for the synchronization context registered with + * @net_dev, populated on success + * + * Return: Errno + */ +#define hdd_vdev_sync_op_start(net_dev, out_vdev_sync) \ + __hdd_vdev_sync_op_start(net_dev, out_vdev_sync, __func__) + +qdf_must_check int +__hdd_vdev_sync_op_start(struct net_device *net_dev, + struct hdd_vdev_sync **out_vdev_sync, + const char *func); + +/** + * hdd_vdev_sync_op_stop() - stop an operation associated with @vdev_sync + * @vdev_sync: the synchonization context tracking the operation + * + * Return: none + */ +#define hdd_vdev_sync_op_stop(net_dev) \ + __hdd_vdev_sync_op_stop(net_dev, __func__) + +void __hdd_vdev_sync_op_stop(struct hdd_vdev_sync *vdev_sync, + const char *func); + +/** + * hdd_vdev_sync_wait_for_ops() - wait until all @vdev_sync operations complete + * @vdev_sync: the synchonization context tracking the operations + * + * Return: None + */ +void hdd_vdev_sync_wait_for_ops(struct hdd_vdev_sync *vdev_sync); + #endif /* __OSIF_VDEV_SYNC_H */ diff --git a/os_if/sync/src/__osif_psoc_sync.h b/os_if/sync/src/__osif_psoc_sync.h index e6c1ce858c3e..ed6e5a50bab9 100644 --- a/os_if/sync/src/__osif_psoc_sync.h +++ b/os_if/sync/src/__osif_psoc_sync.h @@ -19,5 +19,34 @@ #ifndef ____OSIF_PSOC_SYNC_H #define ____OSIF_PSOC_SYNC_H +#include "linux/device.h" +#include "qdf_status.h" +#include "wlan_dsc_vdev.h" + +/** + * osif_psoc_sync_init() - global initializer + * + * Return: None + */ +void osif_psoc_sync_init(void); + +/** + * osif_psoc_sync_deinit() - global de-initializer + * + * Return: None + */ +void osif_psoc_sync_deinit(void); + +/** + * osif_psoc_sync_dsc_vdev_create() - create a dsc_vdev and attach it to a + * dsc_psoc keyed by @dev + * @dev: the device to key off of + * @out_dsc_vdev: output pointer parameter for the new dsc_vdev + * + * Return: QDF_STATUS + */ +QDF_STATUS osif_psoc_sync_dsc_vdev_create(struct device *dev, + struct dsc_vdev **out_dsc_vdev); + #endif /* ____OSIF_PSOC_SYNC_H */ diff --git a/os_if/sync/src/__osif_vdev_sync.h b/os_if/sync/src/__osif_vdev_sync.h index faa55f4717b3..a0ca21fb5c39 100644 --- a/os_if/sync/src/__osif_vdev_sync.h +++ b/os_if/sync/src/__osif_vdev_sync.h @@ -19,5 +19,19 @@ #ifndef ____OSIF_VDEV_SYNC_H #define ____OSIF_VDEV_SYNC_H +/** + * osif_vdev_sync_init() - global initializer + * + * Return: None + */ +void osif_vdev_sync_init(void); + +/** + * osif_vdev_sync_deinit() - global de-initializer + * + * Return: None + */ +void osif_vdev_sync_deinit(void); + #endif /* ____OSIF_VDEV_SYNC_H */ diff --git a/os_if/sync/src/osif_psoc_sync.c b/os_if/sync/src/osif_psoc_sync.c index 8c0beb376e41..0b689425cd2b 100644 --- a/os_if/sync/src/osif_psoc_sync.c +++ b/os_if/sync/src/osif_psoc_sync.c @@ -16,5 +16,338 @@ * PERFORMANCE OF THIS SOFTWARE. */ +#include "linux/device.h" +#include "__osif_psoc_sync.h" #include "osif_psoc_sync.h" +#include "qdf_lock.h" +#include "qdf_status.h" +#include "qdf_types.h" +#include "qdf_util.h" +#include "wlan_dsc_driver.h" +#include "wlan_dsc_psoc.h" +#include "wlan_dsc_vdev.h" + +/** + * struct hdd_psoc_sync - a psoc synchronization context + * @dev: the device used as a lookup key + * @dsc_psoc: the dsc_psoc used for synchronization + * @in_use: indicates if the context is being used + */ +struct hdd_psoc_sync { + struct device *dev; + struct dsc_psoc *dsc_psoc; + bool in_use; +}; + +static struct hdd_psoc_sync __hdd_psoc_sync_arr[WLAN_MAX_PSOCS]; +static qdf_spinlock_t __hdd_psoc_sync_lock; + +#define hdd_psoc_sync_lock_create() qdf_spinlock_create(&__hdd_psoc_sync_lock) +#define hdd_psoc_sync_lock_destroy() qdf_spinlock_destroy(&__hdd_psoc_sync_lock) +#define hdd_psoc_sync_lock() qdf_spin_lock_bh(&__hdd_psoc_sync_lock) +#define hdd_psoc_sync_unlock() qdf_spin_unlock_bh(&__hdd_psoc_sync_lock) +#define hdd_psoc_sync_lock_assert() \ + QDF_BUG(qdf_spin_is_locked(&__hdd_psoc_sync_lock)) + +static struct hdd_psoc_sync *hdd_psoc_sync_lookup(struct device *dev) +{ + int i; + + hdd_psoc_sync_lock_assert(); + + for (i = 0; i < QDF_ARRAY_SIZE(__hdd_psoc_sync_arr); i++) { + struct hdd_psoc_sync *psoc_sync = __hdd_psoc_sync_arr + i; + + if (psoc_sync->dev == dev) + return psoc_sync; + } + + return NULL; +} + +static struct hdd_psoc_sync *hdd_psoc_sync_get(void) +{ + int i; + + hdd_psoc_sync_lock_assert(); + + for (i = 0; i < QDF_ARRAY_SIZE(__hdd_psoc_sync_arr); i++) { + struct hdd_psoc_sync *psoc_sync = __hdd_psoc_sync_arr + i; + + if (!psoc_sync->in_use) { + psoc_sync->in_use = true; + return psoc_sync; + } + } + + return NULL; +} + +static void hdd_psoc_sync_put(struct hdd_psoc_sync *psoc_sync) +{ + hdd_psoc_sync_lock_assert(); + + qdf_mem_zero(psoc_sync, sizeof(*psoc_sync)); +} + +int hdd_psoc_sync_create(struct dsc_driver *dsc_driver, + struct hdd_psoc_sync **out_psoc_sync) +{ + QDF_STATUS status; + struct hdd_psoc_sync *psoc_sync; + + QDF_BUG(dsc_driver); + if (!dsc_driver) + return -EINVAL; + + QDF_BUG(out_psoc_sync); + if (!out_psoc_sync) + return -EINVAL; + + hdd_psoc_sync_lock(); + psoc_sync = hdd_psoc_sync_get(); + hdd_psoc_sync_unlock(); + if (!psoc_sync) + return -ENOMEM; + + status = dsc_psoc_create(dsc_driver, &psoc_sync->dsc_psoc); + if (QDF_IS_STATUS_ERROR(status)) + goto sync_put; + + *out_psoc_sync = psoc_sync; + + return 0; + +sync_put: + hdd_psoc_sync_lock(); + hdd_psoc_sync_put(psoc_sync); + hdd_psoc_sync_unlock(); + + return qdf_status_to_os_return(status); +} + +int __hdd_psoc_sync_create_with_trans(struct dsc_driver *dsc_driver, + struct hdd_psoc_sync **out_psoc_sync, + const char *desc) +{ + struct hdd_psoc_sync *psoc_sync; + QDF_STATUS status; + int errno; + + errno = hdd_psoc_sync_create(dsc_driver, &psoc_sync); + if (errno) + return errno; + + status = dsc_psoc_trans_start(psoc_sync->dsc_psoc, desc); + if (QDF_IS_STATUS_ERROR(status)) + goto sync_destroy; + + *out_psoc_sync = psoc_sync; + + return 0; + +sync_destroy: + hdd_psoc_sync_destroy(psoc_sync); + + return qdf_status_to_os_return(status); +} + +void hdd_psoc_sync_destroy(struct hdd_psoc_sync *psoc_sync) +{ + QDF_BUG(psoc_sync); + if (!psoc_sync) + return; + + dsc_psoc_destroy(&psoc_sync->dsc_psoc); + + hdd_psoc_sync_lock(); + hdd_psoc_sync_put(psoc_sync); + hdd_psoc_sync_unlock(); +} + +void hdd_psoc_sync_register(struct device *dev, + struct hdd_psoc_sync *psoc_sync) +{ + QDF_BUG(dev); + QDF_BUG(psoc_sync); + if (!psoc_sync) + return; + + hdd_psoc_sync_lock(); + psoc_sync->dev = dev; + hdd_psoc_sync_unlock(); +} + +struct hdd_psoc_sync *hdd_psoc_sync_unregister(struct device *dev) +{ + struct hdd_psoc_sync *psoc_sync; + + QDF_BUG(dev); + if (!dev) + return NULL; + + hdd_psoc_sync_lock(); + psoc_sync = hdd_psoc_sync_lookup(dev); + if (psoc_sync) + psoc_sync->dev = NULL; + hdd_psoc_sync_unlock(); + + return psoc_sync; +} + +typedef QDF_STATUS (*psoc_start_func)(struct dsc_psoc *, const char *); + +static int __hdd_psoc_sync_start_callback(struct device *dev, + struct hdd_psoc_sync **out_psoc_sync, + const char *desc, + psoc_start_func psoc_start_cb) +{ + QDF_STATUS status; + struct hdd_psoc_sync *psoc_sync; + + hdd_psoc_sync_lock_assert(); + + *out_psoc_sync = NULL; + + psoc_sync = hdd_psoc_sync_lookup(dev); + if (!psoc_sync) + return -EAGAIN; + + status = psoc_start_cb(psoc_sync->dsc_psoc, desc); + if (QDF_IS_STATUS_ERROR(status)) + return qdf_status_to_os_return(status); + + *out_psoc_sync = psoc_sync; + + return 0; +} + +int __hdd_psoc_sync_trans_start(struct device *dev, + struct hdd_psoc_sync **out_psoc_sync, + const char *desc) +{ + int errno; + + hdd_psoc_sync_lock(); + errno = __hdd_psoc_sync_start_callback(dev, out_psoc_sync, desc, + dsc_psoc_trans_start); + hdd_psoc_sync_unlock(); + + return errno; +} + +int __hdd_psoc_sync_trans_start_wait(struct device *dev, + struct hdd_psoc_sync **out_psoc_sync, + const char *desc) +{ + int errno; + + hdd_psoc_sync_lock(); + errno = __hdd_psoc_sync_start_callback(dev, out_psoc_sync, desc, + dsc_psoc_trans_start_wait); + hdd_psoc_sync_unlock(); + + return errno; +} + +static QDF_STATUS __assert_trans_cb(struct dsc_psoc *dsc_psoc, const char *desc) +{ + dsc_psoc_assert_trans_protected(dsc_psoc); + + return QDF_STATUS_SUCCESS; +} + +int hdd_psoc_sync_trans_resume(struct device *dev, + struct hdd_psoc_sync **out_psoc_sync) +{ + int errno; + + hdd_psoc_sync_lock(); + errno = __hdd_psoc_sync_start_callback(dev, out_psoc_sync, NULL, + __assert_trans_cb); + hdd_psoc_sync_unlock(); + + return errno; +} + +void hdd_psoc_sync_trans_stop(struct hdd_psoc_sync *psoc_sync) +{ + dsc_psoc_trans_stop(psoc_sync->dsc_psoc); +} + +void hdd_psoc_sync_assert_trans_protected(struct device *dev) +{ + struct hdd_psoc_sync *psoc_sync; + + hdd_psoc_sync_lock(); + + psoc_sync = hdd_psoc_sync_lookup(dev); + QDF_BUG(psoc_sync); + if (psoc_sync) + dsc_psoc_assert_trans_protected(psoc_sync->dsc_psoc); + + hdd_psoc_sync_unlock(); +} + +int __hdd_psoc_sync_op_start(struct device *dev, + struct hdd_psoc_sync **out_psoc_sync, + const char *func) +{ + int errno; + + hdd_psoc_sync_lock(); + errno = __hdd_psoc_sync_start_callback(dev, out_psoc_sync, func, + _dsc_psoc_op_start); + hdd_psoc_sync_unlock(); + + return errno; +} + +void __hdd_psoc_sync_op_stop(struct hdd_psoc_sync *psoc_sync, + const char *func) +{ + _dsc_psoc_op_stop(psoc_sync->dsc_psoc, func); +} + +void hdd_psoc_sync_wait_for_ops(struct hdd_psoc_sync *psoc_sync) +{ + dsc_psoc_wait_for_ops(psoc_sync->dsc_psoc); +} + +void osif_psoc_sync_init(void) +{ + hdd_psoc_sync_lock_create(); +} + +void osif_psoc_sync_deinit(void) +{ + hdd_psoc_sync_lock_destroy(); +} + +static QDF_STATUS +__osif_psoc_sync_dsc_vdev_create(struct device *dev, + struct dsc_vdev **out_dsc_vdev) +{ + struct hdd_psoc_sync *psoc_sync; + + hdd_psoc_sync_lock_assert(); + + psoc_sync = hdd_psoc_sync_lookup(dev); + if (!psoc_sync) + return QDF_STATUS_E_INVAL; + + return dsc_vdev_create(psoc_sync->dsc_psoc, out_dsc_vdev); +} + +QDF_STATUS osif_psoc_sync_dsc_vdev_create(struct device *dev, + struct dsc_vdev **out_dsc_vdev) +{ + QDF_STATUS status; + + hdd_psoc_sync_lock(); + status = __osif_psoc_sync_dsc_vdev_create(dev, out_dsc_vdev); + hdd_psoc_sync_unlock(); + + return status; +} diff --git a/os_if/sync/src/osif_sync.c b/os_if/sync/src/osif_sync.c index 0aa7f7219ff3..9dbcb22a0c8e 100644 --- a/os_if/sync/src/osif_sync.c +++ b/os_if/sync/src/osif_sync.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -16,5 +16,19 @@ * PERFORMANCE OF THIS SOFTWARE. */ +#include "__osif_psoc_sync.h" +#include "__osif_vdev_sync.h" #include "osif_sync.h" +void hdd_dsc_init(void) +{ + osif_psoc_sync_init(); + osif_vdev_sync_init(); +} + +void hdd_dsc_deinit(void) +{ + osif_vdev_sync_deinit(); + osif_psoc_sync_deinit(); +} + diff --git a/os_if/sync/src/osif_vdev_sync.c b/os_if/sync/src/osif_vdev_sync.c index 9d92d093b60d..1c16b320bdf0 100644 --- a/os_if/sync/src/osif_vdev_sync.c +++ b/os_if/sync/src/osif_vdev_sync.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -16,5 +16,290 @@ * PERFORMANCE OF THIS SOFTWARE. */ +#include "linux/device.h" +#include "linux/netdevice.h" +#include "__osif_psoc_sync.h" +#include "__osif_vdev_sync.h" #include "osif_vdev_sync.h" +#include "qdf_lock.h" +#include "qdf_status.h" +#include "qdf_types.h" +#include "qdf_util.h" + +/** + * struct hdd_vdev_sync - a vdev synchronization context + * @net_dev: the net_device used as a lookup key + * @dsc_vdev: the dsc_vdev used for synchronization + * @in_use: indicates if the context is being used + */ +struct hdd_vdev_sync { + struct net_device *net_dev; + struct dsc_vdev *dsc_vdev; + bool in_use; +}; + +static struct hdd_vdev_sync __hdd_vdev_sync_arr[WLAN_MAX_VDEVS]; +static qdf_spinlock_t __hdd_vdev_sync_lock; + +#define hdd_vdev_sync_lock_create() qdf_spinlock_create(&__hdd_vdev_sync_lock) +#define hdd_vdev_sync_lock_destroy() qdf_spinlock_destroy(&__hdd_vdev_sync_lock) +#define hdd_vdev_sync_lock() qdf_spin_lock_bh(&__hdd_vdev_sync_lock) +#define hdd_vdev_sync_unlock() qdf_spin_unlock_bh(&__hdd_vdev_sync_lock) +#define hdd_vdev_sync_lock_assert() \ + QDF_BUG(qdf_spin_is_locked(&__hdd_vdev_sync_lock)) + +static struct hdd_vdev_sync *hdd_vdev_sync_lookup(struct net_device *net_dev) +{ + int i; + + hdd_vdev_sync_lock_assert(); + + for (i = 0; i < QDF_ARRAY_SIZE(__hdd_vdev_sync_arr); i++) { + struct hdd_vdev_sync *vdev_sync = __hdd_vdev_sync_arr + i; + + if (vdev_sync->net_dev == net_dev) + return vdev_sync; + } + + return NULL; +} + +static struct hdd_vdev_sync *hdd_vdev_sync_get(void) +{ + int i; + + hdd_vdev_sync_lock_assert(); + + for (i = 0; i < QDF_ARRAY_SIZE(__hdd_vdev_sync_arr); i++) { + struct hdd_vdev_sync *vdev_sync = __hdd_vdev_sync_arr + i; + + if (!vdev_sync->in_use) { + vdev_sync->in_use = true; + return vdev_sync; + } + } + + return NULL; +} + +static void hdd_vdev_sync_put(struct hdd_vdev_sync *vdev_sync) +{ + hdd_vdev_sync_lock_assert(); + + qdf_mem_zero(vdev_sync, sizeof(*vdev_sync)); +} + +int hdd_vdev_sync_create(struct device *dev, + struct hdd_vdev_sync **out_vdev_sync) +{ + struct hdd_vdev_sync *vdev_sync; + QDF_STATUS status; + + QDF_BUG(dev); + if (!dev) + return -EINVAL; + + QDF_BUG(out_vdev_sync); + if (!out_vdev_sync) + return -EINVAL; + + hdd_vdev_sync_lock(); + vdev_sync = hdd_vdev_sync_get(); + hdd_vdev_sync_unlock(); + if (!vdev_sync) + return -ENOMEM; + + status = osif_psoc_sync_dsc_vdev_create(dev, &vdev_sync->dsc_vdev); + if (QDF_IS_STATUS_ERROR(status)) + goto sync_put; + + *out_vdev_sync = vdev_sync; + + return 0; + +sync_put: + hdd_vdev_sync_lock(); + hdd_vdev_sync_put(vdev_sync); + hdd_vdev_sync_unlock(); + + return qdf_status_to_os_return(status); +} + +int __hdd_vdev_sync_create_with_trans(struct device *dev, + struct hdd_vdev_sync **out_vdev_sync, + const char *desc) +{ + struct hdd_vdev_sync *vdev_sync; + QDF_STATUS status; + int errno; + + errno = hdd_vdev_sync_create(dev, &vdev_sync); + if (errno) + return errno; + + status = dsc_vdev_trans_start(vdev_sync->dsc_vdev, desc); + if (QDF_IS_STATUS_ERROR(status)) + goto sync_destroy; + + *out_vdev_sync = vdev_sync; + + return 0; + +sync_destroy: + hdd_vdev_sync_destroy(vdev_sync); + + return qdf_status_to_os_return(status); +} + +void hdd_vdev_sync_destroy(struct hdd_vdev_sync *vdev_sync) +{ + QDF_BUG(vdev_sync); + if (!vdev_sync) + return; + + dsc_vdev_destroy(&vdev_sync->dsc_vdev); + + hdd_vdev_sync_lock(); + hdd_vdev_sync_put(vdev_sync); + hdd_vdev_sync_unlock(); +} + +void hdd_vdev_sync_register(struct net_device *net_dev, + struct hdd_vdev_sync *vdev_sync) +{ + QDF_BUG(net_dev); + QDF_BUG(vdev_sync); + if (!vdev_sync) + return; + + hdd_vdev_sync_lock(); + vdev_sync->net_dev = net_dev; + hdd_vdev_sync_unlock(); +} + +struct hdd_vdev_sync *hdd_vdev_sync_unregister(struct net_device *net_dev) +{ + struct hdd_vdev_sync *vdev_sync; + + QDF_BUG(net_dev); + if (!net_dev) + return NULL; + + hdd_vdev_sync_lock(); + vdev_sync = hdd_vdev_sync_lookup(net_dev); + if (vdev_sync) + vdev_sync->net_dev = NULL; + hdd_vdev_sync_unlock(); + + return vdev_sync; +} + +typedef QDF_STATUS (*vdev_start_func)(struct dsc_vdev *, const char *); + +static int __hdd_vdev_sync_start_callback(struct net_device *net_dev, + struct hdd_vdev_sync **out_vdev_sync, + const char *desc, + vdev_start_func vdev_start_cb) +{ + QDF_STATUS status; + struct hdd_vdev_sync *vdev_sync; + + hdd_vdev_sync_lock_assert(); + + *out_vdev_sync = NULL; + + vdev_sync = hdd_vdev_sync_lookup(net_dev); + if (!vdev_sync) + return -EAGAIN; + + status = vdev_start_cb(vdev_sync->dsc_vdev, desc); + if (QDF_IS_STATUS_ERROR(status)) + return qdf_status_to_os_return(status); + + *out_vdev_sync = vdev_sync; + + return 0; +} + +int __hdd_vdev_sync_trans_start(struct net_device *net_dev, + struct hdd_vdev_sync **out_vdev_sync, + const char *desc) +{ + int errno; + + hdd_vdev_sync_lock(); + errno = __hdd_vdev_sync_start_callback(net_dev, out_vdev_sync, desc, + dsc_vdev_trans_start); + hdd_vdev_sync_unlock(); + + return errno; +} + +int __hdd_vdev_sync_trans_start_wait(struct net_device *net_dev, + struct hdd_vdev_sync **out_vdev_sync, + const char *desc) +{ + int errno; + + hdd_vdev_sync_lock(); + errno = __hdd_vdev_sync_start_callback(net_dev, out_vdev_sync, desc, + dsc_vdev_trans_start_wait); + hdd_vdev_sync_unlock(); + + return errno; +} + +void hdd_vdev_sync_trans_stop(struct hdd_vdev_sync *vdev_sync) +{ + dsc_vdev_trans_stop(vdev_sync->dsc_vdev); +} + +void hdd_vdev_sync_assert_trans_protected(struct net_device *net_dev) +{ + struct hdd_vdev_sync *vdev_sync; + + hdd_vdev_sync_lock(); + + vdev_sync = hdd_vdev_sync_lookup(net_dev); + QDF_BUG(vdev_sync); + if (vdev_sync) + dsc_vdev_assert_trans_protected(vdev_sync->dsc_vdev); + + hdd_vdev_sync_unlock(); +} + +int __hdd_vdev_sync_op_start(struct net_device *net_dev, + struct hdd_vdev_sync **out_vdev_sync, + const char *func) +{ + int errno; + + hdd_vdev_sync_lock(); + errno = __hdd_vdev_sync_start_callback(net_dev, out_vdev_sync, func, + _dsc_vdev_op_start); + hdd_vdev_sync_unlock(); + + return errno; +} + +void __hdd_vdev_sync_op_stop(struct hdd_vdev_sync *vdev_sync, + const char *func) +{ + _dsc_vdev_op_stop(vdev_sync->dsc_vdev, func); +} + +void hdd_vdev_sync_wait_for_ops(struct hdd_vdev_sync *vdev_sync) +{ + dsc_vdev_wait_for_ops(vdev_sync->dsc_vdev); +} + +void osif_vdev_sync_init(void) +{ + hdd_vdev_sync_lock_create(); +} + +void osif_vdev_sync_deinit(void) +{ + hdd_vdev_sync_lock_destroy(); +}