Răsfoiți Sursa

qcacld-3.0: Handle TWT renegotiation failure case

Generally below process should happen in renegotiation failure
case.
1. TWT setup (successful)
2. TWT setup (renegotiation failure)
3. TWT teardown
4. TWT GET STATUS - 0(dialog ID) 0 0 0
5. TWT setup - successful

Since all WMI TWT events gets executed in WMI thread. So when
renegotiation failure case hits, driver sends TWT
teardown to firmware and waits for twt ack in worker thread.
In same worker thread TWT event needs to be processed.
TWT ack event will not process as it's waiting in same worker
thread and it will get timedout.

As part of fix, break the context in renegotiation and
send the teardown in the new worker context.

Change-Id: I13c8d44d6582e39d1cc2c2aa10a500fffbf150b1
CRs-Fixed: 3204750
Jyoti Kumari 2 ani în urmă
părinte
comite
72c3404391

+ 43 - 0
components/umac/twt/core/src/wlan_twt_main.c

@@ -2147,3 +2147,46 @@ QDF_STATUS wlan_twt_update_beacon_template(void)
 
 	return status;
 }
+
+void wlan_twt_set_work_params(
+			struct wlan_objmgr_vdev *vdev,
+			struct twt_add_dialog_complete_event_param *params,
+			uint32_t twt_next_action)
+{
+	struct twt_vdev_priv_obj *twt_vdev_priv;
+
+	twt_vdev_priv = wlan_objmgr_vdev_get_comp_private_obj(
+					vdev, WLAN_UMAC_COMP_TWT);
+
+	if (!twt_vdev_priv) {
+		twt_err("twt vdev private obj is null");
+		return;
+	}
+
+	qdf_copy_macaddr(&twt_vdev_priv->peer_macaddr, &params->peer_macaddr);
+	twt_vdev_priv->dialog_id = params->dialog_id;
+	twt_vdev_priv->next_action = twt_next_action;
+
+	twt_debug("renego: twt_terminate: dialog_id:%d next_action:%d peer mac_addr  "
+		   QDF_MAC_ADDR_FMT, twt_vdev_priv->dialog_id,
+		   twt_vdev_priv->next_action,
+		   QDF_MAC_ADDR_REF(twt_vdev_priv->peer_macaddr.bytes));
+}
+
+void wlan_twt_get_work_params(struct wlan_objmgr_vdev *vdev,
+			      struct twt_work_params *params,
+			      uint32_t *next_action)
+{
+	struct twt_vdev_priv_obj *twt_vdev_priv;
+
+	twt_vdev_priv = wlan_objmgr_vdev_get_comp_private_obj(
+					vdev, WLAN_UMAC_COMP_TWT);
+	if (!twt_vdev_priv) {
+		twt_err("twt vdev private obj is null");
+		return;
+	}
+
+	qdf_copy_macaddr(&params->peer_macaddr, &twt_vdev_priv->peer_macaddr);
+	params->dialog_id = twt_vdev_priv->dialog_id;
+	*next_action = twt_vdev_priv->next_action;
+}

+ 25 - 0
components/umac/twt/core/src/wlan_twt_main.h

@@ -287,3 +287,28 @@ bool wlan_twt_is_command_in_progress(struct wlan_objmgr_psoc *psoc,
 				     uint8_t dialog_id,
 				     enum wlan_twt_commands cmd,
 				     enum wlan_twt_commands *pactive_cmd);
+
+/**
+ * wlan_twt_set_work_params() - Set TWT work params
+ * @vdev: vdev pointer
+ * @params: TWT add dialog params
+ * @twt_next_action: Set next action to do before work scheduled
+ *
+ * Return: None
+ */
+void wlan_twt_set_work_params(
+			struct wlan_objmgr_vdev *vdev,
+			struct twt_add_dialog_complete_event_param *params,
+			uint32_t twt_next_action);
+
+/**
+ * wlan_twt_get_work_params() - Get TWT work params
+ * @vdev: vdev pointer
+ * @params: pointer to TWT work params
+ * @next_action: Get next action to do after work scheduled
+ *
+ * Return: None
+ */
+void wlan_twt_get_work_params(struct wlan_objmgr_vdev *vdev,
+			      struct twt_work_params *params,
+			      uint32_t *next_action);

+ 40 - 0
components/umac/twt/dispatcher/inc/wlan_twt_ucfg_ext_api.h

@@ -270,6 +270,30 @@ bool ucfg_twt_is_command_in_progress(struct wlan_objmgr_psoc *psoc,
 				     enum wlan_twt_commands cmd,
 				     enum wlan_twt_commands *pactive_cmd);
 
+/**
+ * ucfg_twt_set_work_params() - Set TWT work params
+ * @vdev: Vdev pointer
+ * @params: TWT params
+ * @twt_next_action: Set TWT next action to do before work schedule
+ *
+ * Return: None
+ */
+void ucfg_twt_set_work_params(
+		struct wlan_objmgr_vdev *vdev,
+		struct twt_add_dialog_complete_event_param *params,
+		uint32_t twt_next_action);
+
+/**
+ * ucfg_twt_get_work_params() - Get TWT work params
+ * @vdev: vdev pointer
+ * @params: TWT work params
+ * @next_action: Get TWT next action to do after work scheduled
+ *
+ * Return: None
+ */
+void ucfg_twt_get_work_params(struct wlan_objmgr_vdev *vdev,
+			      struct twt_work_params *params,
+			      uint32_t *next_action);
 #else
 static inline
 QDF_STATUS ucfg_twt_psoc_open(struct wlan_objmgr_psoc *psoc)
@@ -359,5 +383,21 @@ ucfg_twt_is_command_in_progress(struct wlan_objmgr_psoc *psoc,
 {
 	return false;
 }
+
+static inline void
+ucfg_twt_set_work_params(
+		struct wlan_objmgr_vdev *vdev,
+		struct twt_add_dialog_complete_event_param *params,
+		uint32_t twt_next_action)
+{
+}
+
+static inline void
+ucfg_twt_get_work_params(
+		struct wlan_objmgr_vdev *vdev,
+		struct twt_work_params *params,
+		uint32_t *next_action)
+{
+}
 #endif
 #endif

+ 16 - 0
components/umac/twt/dispatcher/src/wlan_twt_ucfg_ext_api.c

@@ -200,3 +200,19 @@ bool ucfg_twt_is_command_in_progress(struct wlan_objmgr_psoc *psoc,
 	return wlan_twt_is_command_in_progress(psoc, peer_mac, dialog_id, cmd,
 					       pactive_cmd);
 }
+
+void ucfg_twt_set_work_params(
+		struct wlan_objmgr_vdev *vdev,
+		struct twt_add_dialog_complete_event_param *params,
+		uint32_t twt_next_action)
+{
+	return wlan_twt_set_work_params(vdev, params, twt_next_action);
+}
+
+void ucfg_twt_get_work_params(
+		struct wlan_objmgr_vdev *vdev,
+		struct twt_work_params *params,
+		uint32_t *next_action)
+{
+	return wlan_twt_get_work_params(vdev, params, next_action);
+}

+ 40 - 0
os_if/twt/inc/osif_twt_ext_req.h

@@ -221,6 +221,37 @@ int osif_twt_clear_session_traffic_stats(struct wlan_objmgr_vdev *vdev,
 int osif_twt_set_param(struct wlan_objmgr_vdev *vdev,
 		       struct nlattr *twt_param_attr);
 
+/**
+ * __osif_twt_work_handler() - TWT work handler
+ * @vdev: vdev pointer
+ *
+ * Return: None
+ */
+void __osif_twt_work_handler(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * osif_twt_work_handler() - TWT work wrapper function
+ * @data: data pointer
+ *
+ * Return: None
+ */
+void osif_twt_work_handler(void *data);
+
+/**
+ * osif_twt_create_work() - TWT create work
+ * @vdev: vdev pointer
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS osif_twt_create_work(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * osif_twt_destroy_work() - TWT destroy work
+ * @vdev: vdev pointer
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS osif_twt_destroy_work(struct wlan_objmgr_vdev *vdev);
 #else
 static inline
 int osif_twt_setup_req(struct wlan_objmgr_vdev *vdev,
@@ -298,6 +329,15 @@ int osif_twt_set_param(struct wlan_objmgr_vdev *vdev,
 	return 0;
 }
 
+static inline
+void __osif_twt_work_handler(struct wlan_objmgr_vdev *vdev)
+{
+}
+
+static inline
+void osif_twt_work_handler(void *data)
+{
+}
 #endif
 #endif /* _OSIF_TWT_EXT_REQ_H_ */
 

+ 77 - 10
os_if/twt/src/osif_twt_ext_req.c

@@ -34,6 +34,7 @@
 #include "wlan_cp_stats_mc_ucfg_api.h"
 #include "wlan_mlme_ucfg_api.h"
 #include "wlan_cp_stats_ucfg_api.h"
+#include "osif_vdev_sync.h"
 
 #define TWT_ACK_COMPLETE_TIMEOUT 1000
 
@@ -1068,11 +1069,11 @@ void
 osif_twt_handle_renego_failure(struct wlan_objmgr_psoc *psoc,
 		       struct twt_add_dialog_complete_event *event)
 {
-	struct twt_del_dialog_param params = {0};
 	uint8_t pdev_id;
 	struct wlan_objmgr_pdev *pdev;
 	struct wlan_objmgr_vdev *vdev;
 	uint32_t vdev_id;
+	uint32_t twt_next_action = 0;
 
 	if (!event)
 		return;
@@ -1098,15 +1099,9 @@ osif_twt_handle_renego_failure(struct wlan_objmgr_psoc *psoc,
 		goto end;
 	}
 
-	qdf_copy_macaddr(&params.peer_macaddr, &event->params.peer_macaddr);
-	params.vdev_id = vdev_id;
-	params.dialog_id = event->params.dialog_id;
-
-	osif_debug("renego: twt_terminate: vdev_id:%d dialog_id:%d peer mac_addr "
-		  QDF_MAC_ADDR_FMT, params.vdev_id, params.dialog_id,
-		  QDF_MAC_ADDR_REF(params.peer_macaddr.bytes));
-
-	osif_send_sta_twt_teardown_req(vdev, psoc, &params);
+	twt_next_action = HOST_TWT_SEND_DELETE_CMD;
+	ucfg_twt_set_work_params(vdev, &event->params, twt_next_action);
+	qdf_sched_work(0, &vdev->twt_work);
 
 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID);
 
@@ -2364,3 +2359,75 @@ int osif_twt_set_param(struct wlan_objmgr_vdev *vdev,
 
 	return ret;
 }
+
+void __osif_twt_work_handler(struct wlan_objmgr_vdev *vdev)
+{
+	struct twt_del_dialog_param params = {0};
+	struct twt_work_params twt_work_params = {0};
+	struct wlan_objmgr_psoc *psoc;
+	uint8_t vdev_id;
+	uint32_t next_action;
+
+	psoc = wlan_vdev_get_psoc(vdev);
+	if (!psoc) {
+		osif_err("psoc is null");
+		return;
+	}
+
+	vdev_id = wlan_vdev_get_id(vdev);
+	ucfg_twt_get_work_params(vdev, &twt_work_params, &next_action);
+
+	if (next_action != HOST_TWT_SEND_DELETE_CMD) {
+		osif_debug("Do not send STA teardown req as TWT renegotiation work is not scheduled");
+		return;
+	}
+
+	qdf_copy_macaddr(&params.peer_macaddr, &twt_work_params.peer_macaddr);
+	params.dialog_id = twt_work_params.dialog_id;
+	params.vdev_id = vdev_id;
+
+	osif_send_sta_twt_teardown_req(vdev, psoc, &params);
+}
+
+void osif_twt_work_handler(void *data)
+{
+	struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)data;
+	struct net_device *net_dev;
+	struct osif_vdev_sync *vdev_sync;
+	struct vdev_osif_priv *priv;
+	int errno;
+
+	if (!vdev) {
+		osif_err("vdev is null");
+		return;
+	}
+
+	priv = wlan_vdev_get_ospriv(vdev);
+	if (!priv || !priv->wdev || !priv->wdev->netdev)
+		return;
+
+	net_dev = priv->wdev->netdev;
+	errno = osif_vdev_sync_op_start(net_dev, &vdev_sync);
+	if (errno)
+		return;
+
+	__osif_twt_work_handler(vdev);
+
+	osif_vdev_sync_op_stop(vdev_sync);
+}
+
+QDF_STATUS osif_twt_create_work(struct wlan_objmgr_vdev *vdev)
+{
+	qdf_create_work(0, &vdev->twt_work,
+			osif_twt_work_handler, vdev);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS osif_twt_destroy_work(struct wlan_objmgr_vdev *vdev)
+{
+	qdf_flush_work(&vdev->twt_work);
+	qdf_destroy_work(NULL, &vdev->twt_work);
+
+	return QDF_STATUS_SUCCESS;
+}

+ 3 - 0
os_if/twt/src/osif_twt_ext_util.c

@@ -22,6 +22,7 @@
 #include <osif_twt_rsp.h>
 #include <osif_twt_ext_rsp.h>
 #include <wlan_twt_ucfg_ext_api.h>
+#include <osif_twt_ext_req.h>
 
 static struct mlme_twt_ops twt_ops = {
 	.mlme_twt_enable_complete_cb = osif_twt_enable_complete_cb,
@@ -33,6 +34,8 @@ static struct mlme_twt_ops twt_ops = {
 	.mlme_twt_nudge_complete_cb = osif_twt_nudge_complete_cb,
 	.mlme_twt_notify_complete_cb = osif_twt_notify_complete_cb,
 	.mlme_twt_ack_complete_cb = osif_twt_ack_complete_cb,
+	.mlme_twt_vdev_create_cb = osif_twt_create_work,
+	.mlme_twt_vdev_destroy_cb = osif_twt_destroy_work,
 };
 
 /**