qcacld-3.0: Add wow support for TDLS

Prevent wow if TDLS is started, allow wow if TDLS link disabled. This
feature is enabled only if lithium plaform isn't drv supported.

Change-Id: Ie66d62cb139fe9a1d292925a78f2dd861f16ef69
CRs-Fixed: 2716922
This commit is contained in:
Wu Gao 2020-07-08 15:28:10 +08:00 committed by nshrivas
parent 9f6679e000
commit 7a5b681708
4 changed files with 148 additions and 2 deletions

4
Kbuild
View File

@ -2690,6 +2690,10 @@ endif
#normally, TDLS negative behavior is not needed
cppflags-$(CONFIG_QCOM_TDLS) += -DFEATURE_WLAN_TDLS
ifeq ($(CONFIG_LITHIUM), y)
cppflags-$(CONFIG_QCOM_TDLS) += -DTDLS_WOW_ENABLED
endif
cppflags-$(CONFIG_WLAN_GET_TDLS_PEERS) += -DWLAN_GET_TDLS_PEERS
cppflags-$(CONFIG_WLAN_SET_RANGE_EXT) += -DWLAN_SET_RANGE_EXT

View File

@ -165,6 +165,7 @@ struct tdls_set_state_info {
* @tdls_external_peer_count: external tdls peer count
* @tdls_nss_switch_in_progress: tdls antenna switch in progress
* @tdls_nss_teardown_complete: tdls tear down complete
* @tdls_disable_in_progress: tdls is disable in progress
* @tdls_nss_transition_mode: tdls nss transition mode
* @tdls_teardown_peers_cnt: tdls tear down peer count
* @set_state_info: set tdls state info
@ -182,6 +183,11 @@ struct tdls_set_state_info {
* @tdls_update_dp_vdev_flags store CDP_UPDATE_TDLS_FLAGS
* @tdls_idle_peer_data: provide information about idle peer
* @tdls_ct_spinlock: connection tracker spin lock
* @is_prevent_suspend: prevent suspend or not
* @is_drv_supported: platform supports drv or not, enable/disable tdls wow
* based on this flag.
* @wake_lock: wake lock
* @runtime_lock: runtime lock
* @tdls_osif_init_cb: Callback to initialize the tdls private
* @tdls_osif_deinit_cb: Callback to deinitialize the tdls private
*/
@ -224,6 +230,12 @@ struct tdls_soc_priv_obj {
uint16_t tdls_del_all_peers;
uint32_t tdls_update_dp_vdev_flags;
qdf_spinlock_t tdls_ct_spinlock;
#ifdef TDLS_WOW_ENABLED
bool is_prevent_suspend;
bool is_drv_supported;
qdf_wake_lock_t wake_lock;
qdf_runtime_lock_t runtime_lock;
#endif
tdls_vdev_init_cb tdls_osif_init_cb;
tdls_vdev_deinit_cb tdls_osif_deinit_cb;
};

View File

@ -27,6 +27,7 @@
#include <wlan_utility.h>
#include <wlan_policy_mgr_api.h>
#include "wlan_reg_ucfg_api.h"
#include <host_diag_core_event.h>
static uint8_t calculate_hash_key(const uint8_t *macaddr)
{
@ -552,6 +553,84 @@ void tdls_extract_peer_state_param(struct tdls_peer_update_state *peer_param,
peer->supported_oper_classes[i];
}
#ifdef TDLS_WOW_ENABLED
/**
* tdls_prevent_suspend(): Prevent suspend for TDLS
*
* Acquire wake lock and prevent suspend for TDLS
*
* Return None
*/
static void tdls_prevent_suspend(struct tdls_soc_priv_obj *tdls_soc)
{
if (tdls_soc->is_prevent_suspend)
return;
qdf_wake_lock_acquire(&tdls_soc->wake_lock,
WIFI_POWER_EVENT_WAKELOCK_TDLS);
qdf_runtime_pm_prevent_suspend(&tdls_soc->runtime_lock);
tdls_soc->is_prevent_suspend = true;
}
/**
* tdls_allow_suspend(): Allow suspend for TDLS
*
* Release wake lock and allow suspend for TDLS
*
* Return None
*/
static void tdls_allow_suspend(struct tdls_soc_priv_obj *tdls_soc)
{
if (!tdls_soc->is_prevent_suspend)
return;
qdf_wake_lock_release(&tdls_soc->wake_lock,
WIFI_POWER_EVENT_WAKELOCK_TDLS);
qdf_runtime_pm_allow_suspend(&tdls_soc->runtime_lock);
tdls_soc->is_prevent_suspend = false;
}
/**
* tdls_update_pmo_status() - Update PMO status by TDLS status
* @tdls_vdev: TDLS vdev object
* @old_status: old link status
* @new_status: new link status
*
* Return: None.
*/
static void tdls_update_pmo_status(struct tdls_vdev_priv_obj *tdls_vdev,
enum tdls_link_state old_status,
enum tdls_link_state new_status)
{
struct tdls_soc_priv_obj *tdls_soc;
tdls_soc = wlan_vdev_get_tdls_soc_obj(tdls_vdev->vdev);
if (!tdls_soc) {
tdls_err("NULL psoc object");
return;
}
if (tdls_soc->is_drv_supported)
return;
if ((old_status < TDLS_LINK_CONNECTING) &&
(new_status == TDLS_LINK_CONNECTING))
tdls_prevent_suspend(tdls_soc);
if ((old_status > TDLS_LINK_IDLE) &&
(new_status == TDLS_LINK_IDLE) &&
(!tdls_soc->connected_peer_count) &&
(!tdls_is_progress(tdls_vdev, NULL, 0)))
tdls_allow_suspend(tdls_soc);
}
#else
static void tdls_update_pmo_status(struct tdls_vdev_priv_obj *tdls_vdev,
enum tdls_link_state old_status,
enum tdls_link_state new_status)
{
}
#endif
/**
* tdls_set_link_status() - set link statue for TDLS peer
* @vdev_obj: TDLS vdev object
@ -572,6 +651,7 @@ void tdls_set_link_status(struct tdls_vdev_priv_obj *vdev_obj,
uint32_t channel = 0;
struct tdls_peer *peer;
struct tdls_soc_priv_obj *soc_obj;
enum tdls_link_state old_status;
peer = tdls_find_peer(vdev_obj, mac);
if (!peer) {
@ -580,7 +660,9 @@ void tdls_set_link_status(struct tdls_vdev_priv_obj *vdev_obj,
return;
}
old_status = peer->link_status;
peer->link_status = link_status;
tdls_update_pmo_status(vdev_obj, old_status, link_status);
if (link_status >= TDLS_LINK_DISCOVERED)
peer->discovery_attempt = 0;
@ -612,11 +694,16 @@ void tdls_set_peer_link_status(struct tdls_peer *peer,
uint32_t channel = 0;
struct tdls_soc_priv_obj *soc_obj;
struct tdls_vdev_priv_obj *vdev_obj;
enum tdls_link_state old_status;
tdls_debug("state %d reason %d peer:" QDF_MAC_ADDR_STR,
link_status, link_reason,
QDF_MAC_ADDR_ARRAY(peer->peer_mac.bytes));
vdev_obj = peer->vdev_priv;
old_status = peer->link_status;
peer->link_status = link_status;
tdls_update_pmo_status(vdev_obj, old_status, link_status);
if (link_status >= TDLS_LINK_DISCOVERED)
peer->discovery_attempt = 0;
@ -624,7 +711,6 @@ void tdls_set_peer_link_status(struct tdls_peer *peer,
if (peer->is_forced_peer && peer->state_change_notification) {
peer->reason = link_reason;
vdev_obj = peer->vdev_priv;
soc_obj = wlan_vdev_get_tdls_soc_obj(vdev_obj->vdev);
if (!soc_obj) {
tdls_err("NULL psoc object");

View File

@ -224,9 +224,50 @@ static QDF_STATUS tdls_object_init_params(
return QDF_STATUS_SUCCESS;
}
#ifdef TDLS_WOW_ENABLED
/**
* tdls_wow_init(): Create/init wake lock for TDLS
*
* Create/init wake lock for TDLS if DVR isn't supported
*
* Return None
*/
static void tdls_wow_init(struct tdls_soc_priv_obj *soc_obj)
{
soc_obj->is_prevent_suspend = false;
soc_obj->is_drv_supported = qdf_is_drv_supported();
if (!soc_obj->is_drv_supported) {
qdf_wake_lock_create(&soc_obj->wake_lock, "wlan_tdls");
qdf_runtime_lock_init(&soc_obj->runtime_lock);
}
}
/**
* tdls_wow_deinit(): Destroy/deinit wake lock for TDLS
*
* Destroy/deinit wake lock for TDLS if DVR isn't supported
*
* Return None
*/
static void tdls_wow_deinit(struct tdls_soc_priv_obj *soc_obj)
{
if (!soc_obj->is_drv_supported) {
qdf_runtime_lock_deinit(&soc_obj->runtime_lock);
qdf_wake_lock_destroy(&soc_obj->wake_lock);
}
}
#else
static void tdls_wow_init(struct tdls_soc_priv_obj *soc_obj)
{
}
static void tdls_wow_deinit(struct tdls_soc_priv_obj *soc_obj)
{
}
#endif
static QDF_STATUS tdls_global_init(struct tdls_soc_priv_obj *soc_obj)
{
tdls_object_init_params(soc_obj);
soc_obj->connected_peer_count = 0;
soc_obj->tdls_nss_switch_in_progress = false;
@ -238,13 +279,16 @@ static QDF_STATUS tdls_global_init(struct tdls_soc_priv_obj *soc_obj)
soc_obj->tdls_disable_in_progress = false;
qdf_spinlock_create(&soc_obj->tdls_ct_spinlock);
tdls_wow_init(soc_obj);
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS tdls_global_deinit(struct tdls_soc_priv_obj *soc_obj)
{
tdls_wow_deinit(soc_obj);
qdf_spinlock_destroy(&soc_obj->tdls_ct_spinlock);
return QDF_STATUS_SUCCESS;
}