qcacld-3.0: Re-enable TWT before host TWT trigger mode
Disable the current TWT session and re-enable the TWT if the
current session in FW trigger mode before changing the TWT mode
to host trigger mode.
Change-Id: I7de2126605685c85a240d38356d439cb4be8cce1
CRs-Fixed: 2539353
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index 857a304..b1a8225 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -1953,6 +1953,7 @@
struct board_info hw_bd_info;
#ifdef WLAN_SUPPORT_TWT
enum twt_status twt_state;
+ qdf_event_t twt_disable_comp_evt;
#endif
#ifdef FEATURE_WLAN_APF
uint32_t apf_version;
diff --git a/core/hdd/inc/wlan_hdd_twt.h b/core/hdd/inc/wlan_hdd_twt.h
index 81e0435..909d3dc 100644
--- a/core/hdd/inc/wlan_hdd_twt.h
+++ b/core/hdd/inc/wlan_hdd_twt.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
@@ -82,6 +82,15 @@
*/
void hdd_send_twt_enable_cmd(struct hdd_context *hdd_ctx);
+#define TWT_DISABLE_COMPLETE_TIMEOUT 1000
+/**
+ * hdd_send_twt_disable_cmd() - Send TWT disable command to target
+ * @hdd_ctx: HDD Context
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS hdd_send_twt_disable_cmd(struct hdd_context *hdd_ctx);
+
/**
* wlan_hdd_twt_init() - Initialize TWT
* @hdd_ctx: pointer to global HDD Context
@@ -114,6 +123,11 @@
{
}
+static inline QDF_STATUS hdd_send_twt_disable_cmd(struct hdd_context *hdd_ctx)
+{
+ return QDF_STATUS_SUCCESS;
+}
+
static inline void wlan_hdd_twt_init(struct hdd_context *hdd_ctx)
{
}
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index f240a9f..5650e1c 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -8415,6 +8415,7 @@
struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX + 1];
struct nlattr *twt_session;
int tmp, rc;
+ uint32_t congestion_timeout = 0;
if ((adapter->device_mode != QDF_STA_MODE &&
adapter->device_mode != QDF_P2P_CLIENT_MODE) ||
@@ -8540,6 +8541,19 @@
params.flag_flow_type,
params.flag_protection);
+ ucfg_mlme_get_twt_congestion_timeout(hdd_ctx->psoc,
+ &congestion_timeout);
+ if (congestion_timeout) {
+ ret_val = qdf_status_to_os_return(
+ hdd_send_twt_disable_cmd(hdd_ctx));
+ if (ret_val) {
+ hdd_err("Failed to disable TWT");
+ goto send_err;
+ }
+ ucfg_mlme_set_twt_congestion_timeout(
+ hdd_ctx->psoc, 0);
+ hdd_send_twt_enable_cmd(hdd_ctx);
+ }
ret_val = qdf_status_to_os_return(
wma_twt_process_add_dialog(¶ms));
if (ret_val)
diff --git a/core/hdd/src/wlan_hdd_twt.c b/core/hdd/src/wlan_hdd_twt.c
index 649c37c..0d9cdce 100644
--- a/core/hdd/src/wlan_hdd_twt.c
+++ b/core/hdd/src/wlan_hdd_twt.c
@@ -74,6 +74,18 @@
wma_send_twt_enable_cmd(pdev_id, congestion_timeout, bcast_val);
}
+QDF_STATUS hdd_send_twt_disable_cmd(struct hdd_context *hdd_ctx)
+{
+ uint8_t pdev_id = hdd_ctx->pdev->pdev_objmgr.wlan_pdev_id;
+
+ hdd_debug("TWT disable cmd :pdev:%d", pdev_id);
+
+ wma_send_twt_disable_cmd(pdev_id);
+
+ return qdf_wait_single_event(&hdd_ctx->twt_disable_comp_evt,
+ TWT_DISABLE_COMPLETE_TIMEOUT);
+}
+
/**
* hdd_twt_enable_comp_cb() - TWT enable complete event callback
* @hdd_handle: opaque handle for the global HDD Context
@@ -126,6 +138,7 @@
{
struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
enum twt_status prev_state;
+ QDF_STATUS status;
if (!hdd_ctx) {
hdd_err("TWT: Invalid HDD Context");
@@ -136,6 +149,10 @@
hdd_debug("TWT: State transitioned from %d to %d",
prev_state, hdd_ctx->twt_state);
+
+ status = qdf_event_set(&hdd_ctx->twt_disable_comp_evt);
+ if (!QDF_IS_STATUS_SUCCESS(status))
+ hdd_err("Failed to set twt_disable_comp_evt");
}
void wlan_hdd_twt_init(struct hdd_context *hdd_ctx)
@@ -156,6 +173,14 @@
hdd_err("Register twt disable complete failed");
goto twt_init_fail;
}
+
+ status = qdf_event_create(&hdd_ctx->twt_disable_comp_evt);
+ if (!QDF_IS_STATUS_SUCCESS(status)) {
+ hdd_err("twt_disable_comp_evt init failed");
+ sme_deregister_twt_disable_complete_cb(hdd_ctx->mac_handle);
+ goto twt_init_fail;
+ }
+
hdd_send_twt_enable_cmd(hdd_ctx);
return;
@@ -175,5 +200,9 @@
if (!QDF_IS_STATUS_SUCCESS(status))
hdd_err("De-register of twt enable cb failed: %d", status);
+ if (!QDF_IS_STATUS_SUCCESS(qdf_event_destroy(
+ &hdd_ctx->twt_disable_comp_evt)))
+ hdd_err("Failed to destroy twt_disable_comp_evt");
+
hdd_ctx->twt_state = TWT_CLOSED;
}
diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h
index 247df03..94e7a3c 100644
--- a/core/wma/inc/wma_internal.h
+++ b/core/wma/inc/wma_internal.h
@@ -1751,8 +1751,43 @@
uint8_t *event,
uint32_t len);
+#ifdef WLAN_SUPPORT_TWT
+/**
+ * wma_twt_en_complete_event_handler - TWT enable complete event handler
+ * @handle: wma handle
+ * @event: buffer with event
+ * @len: buffer length
+ *
+ * Return: 0 on success
+ */
int wma_twt_en_complete_event_handler(void *handle,
uint8_t *event, uint32_t len);
+
+/**
+ * wma_twt_disable_comp_event_handler- TWT disable complete event handler
+ * @handle: wma handle
+ * @event: buffer with event
+ * @len: buffer length
+ *
+ * Return: 0 on success
+ */
+int wma_twt_disable_comp_event_handler(void *handle, uint8_t *event,
+ uint32_t len);
+#else
+static inline int wma_twt_en_complete_event_handler(void *handle,
+ uint8_t *event,
+ uint32_t len)
+{
+ return 0;
+}
+
+static inline int wma_twt_disable_comp_event_handler(void *handle,
+ uint8_t *event,
+ uint32_t len)
+{
+ return 0;
+}
+#endif
/**
* wma_get_roam_scan_stats() - Get roam scan stats request
* @handle: wma handle
diff --git a/core/wma/inc/wma_twt.h b/core/wma/inc/wma_twt.h
index 0cecfc2..43f64d8 100644
--- a/core/wma/inc/wma_twt.h
+++ b/core/wma/inc/wma_twt.h
@@ -46,6 +46,14 @@
struct peer_assoc_params *cmd);
/**
+ * wma_send_twt_disable_cmd() - Send TWT disable command to firmware
+ * @pdev_id: pdev id
+ *
+ * Return: None
+ */
+void wma_send_twt_disable_cmd(uint32_t pdev_id);
+
+/**
* wma_twt_process_add_dialog() - Process twt add dialog command
* @params: add dialog configuration param
*
@@ -69,6 +77,10 @@
WMA_LOGD(FL("TWT not supported as WLAN_SUPPORT_TWT is disabled"));
}
+static inline void wma_send_twt_disable_cmd(uint32_t pdev_id)
+{
+}
+
static inline void wma_set_twt_peer_caps(tpAddStaParams params,
struct peer_assoc_params *cmd)
{
diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c
index 98b5650..a4572ba 100644
--- a/core/wma/src/wma_main.c
+++ b/core/wma/src/wma_main.c
@@ -3631,6 +3631,10 @@
wmi_twt_enable_complete_event_id,
wma_twt_en_complete_event_handler,
WMA_RX_SERIALIZER_CTX);
+ wmi_unified_register_event_handler(wma_handle->wmi_handle,
+ wmi_twt_disable_complete_event_id,
+ wma_twt_disable_comp_event_handler,
+ WMA_RX_SERIALIZER_CTX);
#endif
wma_register_apf_events(wma_handle);
diff --git a/core/wma/src/wma_twt.c b/core/wma/src/wma_twt.c
index 029aab6..84e88a6 100644
--- a/core/wma/src/wma_twt.c
+++ b/core/wma/src/wma_twt.c
@@ -82,6 +82,42 @@
return status;
}
+void wma_send_twt_disable_cmd(uint32_t pdev_id)
+{
+ t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA);
+ struct wmi_twt_disable_param twt_disable_params = {0};
+ int32_t ret;
+
+ if (!wma) {
+ WMA_LOGE("Invalid WMA context, Disable TWT failed");
+ return;
+ }
+ twt_disable_params.pdev_id = pdev_id;
+ ret = wmi_unified_twt_disable_cmd(wma->wmi_handle, &twt_disable_params);
+
+ if (ret)
+ WMA_LOGE("Failed to disable TWT");
+}
+
+int wma_twt_disable_comp_event_handler(void *handle, uint8_t *event,
+ uint32_t len)
+{
+ struct mac_context *mac;
+
+ mac = (struct mac_context *)cds_get_context(QDF_MODULE_ID_PE);
+ if (!mac) {
+ WMA_LOGE("Invalid MAC context");
+ return -EINVAL;
+ }
+
+ WMA_LOGD("TWT: Rcvd TWT disable comp event");
+
+ if (mac->sme.twt_disable_cb)
+ mac->sme.twt_disable_cb(mac->hdd_handle);
+
+ return 0;
+}
+
void wma_set_twt_peer_caps(tpAddStaParams params, struct peer_assoc_params *cmd)
{
if (params->twt_requestor)