qcacld-3.0: Add HDD DSC vdev operation start/stop

The Driver Synchronization Core (DSC) is a set of synchronization
primitives for use by the driver's orchestration layer. It provides APIs
for ensuring safe state transitions (including bring up and tear down)
of major driver objects: a single driver, associated psocs, and their
associated vdevs.

Add APIs in HDD for starting and stopping vdev-level operations. These
APIs also provide a register/unregister capability to atomically enable
and disable operation processing for a particular vdev.

Change-Id: I8bfb7a9bc6c16d219eb74eeeb98591fe4fd7984a
CRs-Fixed: 2365189
This commit is contained in:
Dustin Brown
2018-12-10 10:42:37 -08:00
committed by nshrivas
parent 19263c2574
commit fe50cef303
3 changed files with 217 additions and 4 deletions

View File

@@ -19,7 +19,22 @@
#ifndef __WLAN_HDD_DSC_H__
#define __WLAN_HDD_DSC_H__
#include <wlan_hdd_main.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);
/**
* hdd_dsc_psoc_from_wiphy() - get dsc psoc from wiphy
@@ -28,4 +43,58 @@
* Return: dsc_psoc on success, NULL on failure
*/
struct dsc_psoc *hdd_dsc_psoc_from_wiphy(struct wiphy *wiphy);
/**
* hdd_vdev_ops_register() - register a dsc_vdev to accept new operations
* @net_dev: the net_device which will be used for lookup during op start
* @dsc_vdev: the dsc_vdev to use to protect operations on @net_dev
*
* Return: None
*/
void hdd_vdev_ops_register(struct net_device *net_dev,
struct dsc_vdev *dsc_vdev);
/**
* hdd_vdev_ops_unregister() - unregister a dsc_vdev to reject future operations
* @net_dev: the net_device to use for lookup
*
* Return: None
*/
void hdd_vdev_ops_unregister(struct net_device *net_dev);
/**
* struct hdd_vdev_op - opaque handle used to identify a specific vdev operation
*/
struct hdd_vdev_op;
/**
* hdd_vdev_op_start() - attempt to start a vdev-level driver operation
* @net_dev: the net_device to start the operation on
*
* Return: an operation handle on success, NULL on failure
*/
#define hdd_vdev_op_start(net_dev) __hdd_vdev_op_start(net_dev, __func__)
/**
* hdd_vdev_op_start_with_wdev() - attempt to start a vdev-level driver
* operation using a wireless_dev instance
* @wdev: the wireless_dev to start the operation on
*
* Return: an operation handle on success, NULL on failure
*/
#define hdd_vdev_op_start_with_wdev(wdev) hdd_vdev_op_start((wdev)->netdev)
struct hdd_vdev_op *__hdd_vdev_op_start(struct net_device *net_dev,
const char *func);
/**
* hdd_vdev_op_stop() - stop a given vdev-level operation
* @op: an operation handle identifying the operation to stop
*
* Return: None
*/
#define hdd_vdev_op_stop(op) __hdd_vdev_op_stop(op, __func__)
void __hdd_vdev_op_stop(struct hdd_vdev_op *op, const char *func);
#endif

View File

@@ -15,6 +15,12 @@
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "sme_api.h"
#include "qdf_lock.h"
#include "qdf_status.h"
#include "qdf_types.h"
#include "wlan_dsc.h"
#include "wlan_hdd_dsc.h"
struct dsc_psoc *hdd_dsc_psoc_from_wiphy(struct wiphy *wiphy)
@@ -29,3 +35,132 @@ struct dsc_psoc *hdd_dsc_psoc_from_wiphy(struct wiphy *wiphy)
return hdd_ctx->hdd_psoc->dsc_psoc;
}
/**
* struct hdd_vdev_kvp - net_device/dsc_vdev key-value-pair for mapping a
* net_device to a dsc_vdev
* @net_dev: the net_device key
* @dsc_vdev: the dsc_vdev value
*/
struct hdd_vdev_kvp {
struct net_device *net_dev;
struct dsc_vdev *dsc_vdev;
};
static struct hdd_vdev_kvp __hdd_vdev_map[CSR_ROAM_SESSION_MAX];
static qdf_spinlock_t __hdd_vdev_lock;
#define hdd_vdev_map_lock() qdf_spin_lock_bh(&__hdd_vdev_lock)
#define hdd_vdev_map_unlock() qdf_spin_unlock_bh(&__hdd_vdev_lock)
#define hdd_vdev_map_lock_assert() QDF_BUG(qdf_spin_is_locked(&__hdd_vdev_lock))
static struct hdd_vdev_kvp *hdd_vdev_kvp_get(struct net_device *net_dev)
{
int i;
hdd_vdev_map_lock_assert();
for (i = 0; i < QDF_ARRAY_SIZE(__hdd_vdev_map); i++) {
struct hdd_vdev_kvp *kvp = __hdd_vdev_map + i;
if (kvp->net_dev == net_dev)
return kvp;
}
return NULL;
}
void hdd_vdev_ops_register(struct net_device *net_dev,
struct dsc_vdev *dsc_vdev)
{
struct hdd_vdev_kvp *kvp;
QDF_BUG(net_dev);
if (!net_dev)
return;
QDF_BUG(dsc_vdev);
if (!dsc_vdev)
return;
hdd_vdev_map_lock();
kvp = hdd_vdev_kvp_get(NULL);
QDF_BUG(kvp);
if (kvp) {
kvp->net_dev = net_dev;
kvp->dsc_vdev = dsc_vdev;
}
hdd_vdev_map_unlock();
}
void hdd_vdev_ops_unregister(struct net_device *net_dev)
{
struct hdd_vdev_kvp *kvp;
QDF_BUG(net_dev);
if (!net_dev)
return;
hdd_vdev_map_lock();
kvp = hdd_vdev_kvp_get(net_dev);
QDF_BUG(kvp);
if (kvp) {
kvp->net_dev = NULL;
kvp->dsc_vdev = NULL;
}
hdd_vdev_map_unlock();
}
static struct hdd_vdev_op *hdd_vdev_to_op(struct dsc_vdev *dsc_vdev)
{
return (struct hdd_vdev_op *)dsc_vdev;
}
static struct dsc_vdev *hdd_op_to_vdev(struct hdd_vdev_op *op)
{
return (struct dsc_vdev *)op;
}
struct hdd_vdev_op *__hdd_vdev_op_start(struct net_device *net_dev,
const char *func)
{
QDF_STATUS status = QDF_STATUS_E_NULL_VALUE;
struct hdd_vdev_kvp *kvp;
QDF_BUG(net_dev);
if (!net_dev)
return NULL;
hdd_vdev_map_lock();
kvp = hdd_vdev_kvp_get(net_dev);
if (kvp)
status = _dsc_vdev_op_start(kvp->dsc_vdev, func);
hdd_vdev_map_unlock();
if (QDF_IS_STATUS_ERROR(status))
return NULL;
return hdd_vdev_to_op(kvp->dsc_vdev);
}
void __hdd_vdev_op_stop(struct hdd_vdev_op *op, const char *func)
{
_dsc_vdev_op_stop(hdd_op_to_vdev(op), func);
}
void hdd_dsc_init(void)
{
qdf_spinlock_create(&__hdd_vdev_lock);
}
void hdd_dsc_deinit(void)
{
qdf_spinlock_destroy(&__hdd_vdev_lock);
}

View File

@@ -40,6 +40,7 @@
#include <dbglog_host.h>
#include <wlan_logging_sock_svc.h>
#include <wlan_roam_debug.h>
#include "wlan_hdd_dsc.h"
#include <wlan_hdd_wowl.h>
#include <wlan_hdd_misc.h>
#include <wlan_hdd_wext.h>
@@ -12917,13 +12918,15 @@ static inline int hdd_state_query_cb(void)
int hdd_init(void)
{
QDF_STATUS status;
int ret = 0;
int ret;
hdd_dsc_init();
status = cds_init();
if (QDF_IS_STATUS_ERROR(status)) {
hdd_err("Failed to allocate CDS context");
ret = -ENOMEM;
goto err_out;
goto deinit_dsc;
}
qdf_register_module_state_query_callback(hdd_state_query_cb);
@@ -12941,7 +12944,11 @@ int hdd_init(void)
hdd_register_debug_callback();
wlan_roam_debug_init();
err_out:
return 0;
deinit_dsc:
hdd_dsc_deinit();
return ret;
}
@@ -12963,6 +12970,8 @@ void hdd_deinit(void)
wlan_destroy_bug_report_lock();
cds_deinit();
hdd_dsc_deinit();
}
#ifdef QCA_WIFI_NAPIER_EMULATION