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
diff --git a/Kbuild b/Kbuild
index f991e56..a24f2fc 100644
--- a/Kbuild
+++ b/Kbuild
@@ -2434,6 +2434,10 @@
#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_QCACLD_WLAN_LFR3) += -DWLAN_FEATURE_ROAM_OFFLOAD
diff --git a/components/tdls/core/src/wlan_tdls_main.h b/components/tdls/core/src/wlan_tdls_main.h
index 722eedf..f9df6d9 100644
--- a/components/tdls/core/src/wlan_tdls_main.h
+++ b/components/tdls/core/src/wlan_tdls_main.h
@@ -165,6 +165,7 @@
* @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 @@
* @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 @@
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;
};
diff --git a/components/tdls/core/src/wlan_tdls_peer.c b/components/tdls/core/src/wlan_tdls_peer.c
index 241924a..43ce1e8 100644
--- a/components/tdls/core/src/wlan_tdls_peer.c
+++ b/components/tdls/core/src/wlan_tdls_peer.c
@@ -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 @@
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 @@
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 @@
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 @@
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 @@
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");
diff --git a/components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c b/components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c
index 4c31074..3176a20 100644
--- a/components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c
+++ b/components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c
@@ -226,9 +226,50 @@
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;
@@ -240,13 +281,16 @@
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;
}