Browse Source

qcacld-3.0: Add support for TWT re-negotiation failure

1. If the TWT setup parameter re-negotiation results in failure,
   then host driver shall trigger TWT teardown for the
   existing TWT session.
2. Upon receiving the TWT teardown confirmation from the firmware,
   host driver shall cleanup TWT session, send teardown notification
   to the user space and ready for next TWT setup command.

Change-Id: I553ae7de8d900a3dc12d563b781f9fefa36f8a0b
CRs-Fixed: 2916548
Srinivas Girigowda 4 năm trước cách đây
mục cha
commit
6879ad5d67

+ 1 - 1
components/mlme/core/src/wlan_mlme_twt_api.c

@@ -127,7 +127,7 @@ void mlme_set_twt_setup_done(struct wlan_objmgr_psoc *psoc,
 	for (i = 0; i < peer_priv->twt_ctx.num_twt_sessions; i++) {
 	for (i = 0; i < peer_priv->twt_ctx.num_twt_sessions; i++) {
 		if (peer_priv->twt_ctx.session_info[i].dialog_id == dialog_id) {
 		if (peer_priv->twt_ctx.session_info[i].dialog_id == dialog_id) {
 			peer_priv->twt_ctx.session_info[i].setup_done = is_set;
 			peer_priv->twt_ctx.session_info[i].setup_done = is_set;
-			mlme_legacy_debug("setup done dialog:%d",
+			mlme_legacy_debug("setup done:%d dialog:%d", is_set,
 					  dialog_id);
 					  dialog_id);
 			break;
 			break;
 		}
 		}

+ 46 - 3
core/hdd/src/wlan_hdd_twt.c

@@ -98,6 +98,10 @@ qca_wlan_vendor_twt_nudge_dialog_policy[QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAX + 1]
 	[QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAC_ADDR] = VENDOR_NLA_POLICY_MAC_ADDR,
 	[QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAC_ADDR] = VENDOR_NLA_POLICY_MAC_ADDR,
 };
 };
 
 
+static
+int hdd_send_twt_del_dialog_cmd(struct hdd_context *hdd_ctx,
+				struct wmi_twt_del_dialog_param *twt_params);
+
 /**
 /**
  * hdd_twt_setup_req_type_to_cmd() - Converts twt setup request type to twt cmd
  * hdd_twt_setup_req_type_to_cmd() - Converts twt setup request type to twt cmd
  * @req_type: twt setup request type
  * @req_type: twt setup request type
@@ -1276,17 +1280,52 @@ static QDF_STATUS hdd_send_twt_setup_response(
 	return status;
 	return status;
 }
 }
 
 
+/**
+ * hdd_twt_handle_renego_failure() - Upon re-nego failure send TWT teardown
+ *
+ * @adapter: Adapter pointer
+ * @add_dialog_event: Pointer to Add dialog complete event structure
+ *
+ * Upon re-negotiation failure, this function constructs TWT teardown
+ * message to the target.
+ *
+ * Return: None
+ */
+static void
+hdd_twt_handle_renego_failure(struct hdd_adapter *adapter,
+			      struct twt_add_dialog_complete_event *add_dialog_event)
+{
+	struct wmi_twt_del_dialog_param params = {0};
+
+	if (!add_dialog_event)
+		return;
+
+	qdf_mem_copy(params.peer_macaddr,
+		     add_dialog_event->params.peer_macaddr,
+		     QDF_MAC_ADDR_SIZE);
+	params.vdev_id = add_dialog_event->params.vdev_id;
+	params.dialog_id = add_dialog_event->params.dialog_id;
+
+	hdd_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));
+
+	hdd_send_twt_del_dialog_cmd(adapter->hdd_ctx, &params);
+}
+
 /**
 /**
  * hdd_twt_add_dialog_comp_cb() - HDD callback for twt add dialog
  * hdd_twt_add_dialog_comp_cb() - HDD callback for twt add dialog
  * complete event
  * complete event
  * @psoc: Pointer to global psoc
  * @psoc: Pointer to global psoc
  * @add_dialog_event: Pointer to Add dialog complete event structure
  * @add_dialog_event: Pointer to Add dialog complete event structure
+ * @renego_fail: Flag to indicate if its re-negotiation failure case
  *
  *
  * Return: None
  * Return: None
  */
  */
 static void
 static void
 hdd_twt_add_dialog_comp_cb(struct wlan_objmgr_psoc *psoc,
 hdd_twt_add_dialog_comp_cb(struct wlan_objmgr_psoc *psoc,
-			   struct twt_add_dialog_complete_event *add_dialog_event)
+			   struct twt_add_dialog_complete_event *add_dialog_event,
+			   bool renego_fail)
 {
 {
 	struct hdd_adapter *adapter;
 	struct hdd_adapter *adapter;
 	uint8_t vdev_id = add_dialog_event->params.vdev_id;
 	uint8_t vdev_id = add_dialog_event->params.vdev_id;
@@ -1297,11 +1336,15 @@ hdd_twt_add_dialog_comp_cb(struct wlan_objmgr_psoc *psoc,
 		return;
 		return;
 	}
 	}
 
 
-	hdd_debug("TWT: add dialog_id:%d, status:%d vdev_id %d peer mac_addr "
+	hdd_debug("TWT: add dialog_id:%d, status:%d vdev_id:%d renego_fail:%d peer mac_addr "
 		  QDF_MAC_ADDR_FMT, add_dialog_event->params.dialog_id,
 		  QDF_MAC_ADDR_FMT, add_dialog_event->params.dialog_id,
-		  add_dialog_event->params.status, vdev_id,
+		  add_dialog_event->params.status, vdev_id, renego_fail,
 		  QDF_MAC_ADDR_REF(add_dialog_event->params.peer_macaddr));
 		  QDF_MAC_ADDR_REF(add_dialog_event->params.peer_macaddr));
+
 	hdd_send_twt_setup_response(adapter, add_dialog_event);
 	hdd_send_twt_setup_response(adapter, add_dialog_event);
+
+	if (renego_fail)
+		hdd_twt_handle_renego_failure(adapter, add_dialog_event);
 }
 }
 
 
 /**
 /**

+ 5 - 2
core/sme/inc/sme_internal.h

@@ -164,10 +164,12 @@ typedef void (*twt_disable_cb)(hdd_handle_t hdd_handle);
  * typedef twt_add_dialog_cb - TWT add dialog callback signature.
  * typedef twt_add_dialog_cb - TWT add dialog callback signature.
  * @psoc: Pointer to global psoc
  * @psoc: Pointer to global psoc
  * @add_dialog_evt: pointer to event buf containing twt response parameters
  * @add_dialog_evt: pointer to event buf containing twt response parameters
+ * @renego_fail: Flag to indicate if its re-negotiation failure case
  */
  */
 typedef
 typedef
 void (*twt_add_dialog_cb)(struct wlan_objmgr_psoc *psoc,
 void (*twt_add_dialog_cb)(struct wlan_objmgr_psoc *psoc,
-			  struct twt_add_dialog_complete_event *add_dialog_evt);
+			  struct twt_add_dialog_complete_event *add_dialog_evt,
+			  bool renego_fail);
 
 
 /**
 /**
  * typedef twt_del_dialog_cb - TWT delete dialog callback signature.
  * typedef twt_del_dialog_cb - TWT delete dialog callback signature.
@@ -229,7 +231,8 @@ struct twt_callbacks {
 			      struct wmi_twt_enable_complete_event_param *params);
 			      struct wmi_twt_enable_complete_event_param *params);
 	void (*twt_disable_cb)(hdd_handle_t hdd_handle);
 	void (*twt_disable_cb)(hdd_handle_t hdd_handle);
 	void (*twt_add_dialog_cb)(struct wlan_objmgr_psoc *psoc,
 	void (*twt_add_dialog_cb)(struct wlan_objmgr_psoc *psoc,
-				  struct twt_add_dialog_complete_event *add_dialog_event);
+				  struct twt_add_dialog_complete_event *add_dialog_event,
+				  bool renego);
 	void (*twt_del_dialog_cb)(struct wlan_objmgr_psoc *psoc,
 	void (*twt_del_dialog_cb)(struct wlan_objmgr_psoc *psoc,
 				  struct wmi_twt_del_dialog_complete_event_param *params);
 				  struct wmi_twt_del_dialog_complete_event_param *params);
 	void (*twt_pause_dialog_cb)(struct wlan_objmgr_psoc *psoc,
 	void (*twt_pause_dialog_cb)(struct wlan_objmgr_psoc *psoc,

+ 71 - 17
core/sme/src/common/sme_api.c

@@ -1935,33 +1935,47 @@ static QDF_STATUS sme_process_antenna_mode_resp(struct mac_context *mac,
 
 
 #ifdef WLAN_SUPPORT_TWT
 #ifdef WLAN_SUPPORT_TWT
 /**
 /**
- * sme_process_twt_add_dialog_event() - Process twt add dialog event
- * response from firmware
+ * sme_process_twt_add_renego_failure() - Process TWT re-negotiation failure
+ *
  * @mac: Global MAC pointer
  * @mac: Global MAC pointer
  * @add_dialog_event: pointer to event buf containing twt response parameters
  * @add_dialog_event: pointer to event buf containing twt response parameters
  *
  *
  * Return: None
  * Return: None
  */
  */
 static void
 static void
-sme_process_twt_add_dialog_event(struct mac_context *mac,
+sme_process_twt_add_renego_failure(struct mac_context *mac,
 				 struct twt_add_dialog_complete_event *add_dialog_event)
 				 struct twt_add_dialog_complete_event *add_dialog_event)
 {
 {
 	twt_add_dialog_cb callback;
 	twt_add_dialog_cb callback;
-	bool is_evt_allowed;
 
 
-	is_evt_allowed = mlme_twt_is_command_in_progress(
+	/* Reset the active TWT command to none */
+	mlme_set_twt_command_in_progress(
 		mac->psoc,
 		mac->psoc,
 		(struct qdf_mac_addr *)add_dialog_event->params.peer_macaddr,
 		(struct qdf_mac_addr *)add_dialog_event->params.peer_macaddr,
-		add_dialog_event->params.dialog_id, WLAN_TWT_SETUP);
-	if (!is_evt_allowed) {
-		sme_debug("add dialog event dropped for id:%d",
-			  add_dialog_event->params.dialog_id);
-		return;
-	}
+		add_dialog_event->params.dialog_id, WLAN_TWT_NONE);
 
 
 	callback = mac->sme.twt_add_dialog_cb;
 	callback = mac->sme.twt_add_dialog_cb;
 	if (callback)
 	if (callback)
-		callback(mac->psoc, add_dialog_event);
+		callback(mac->psoc, add_dialog_event, true);
+}
+
+/**
+ * sme_process_twt_add_initial_nego() - Process initial TWT setup or
+ * re-negotiation successful setup
+ * @mac: Global MAC pointer
+ * @add_dialog_event: pointer to event buf containing twt response parameters
+ *
+ * Return: None
+ */
+static void
+sme_process_twt_add_initial_nego(struct mac_context *mac,
+				 struct twt_add_dialog_complete_event *add_dialog_event)
+{
+	twt_add_dialog_cb callback;
+
+	callback = mac->sme.twt_add_dialog_cb;
+	if (callback)
+		callback(mac->psoc, add_dialog_event, false);
 
 
 	/* Reset the active TWT command to none */
 	/* Reset the active TWT command to none */
 	mlme_set_twt_command_in_progress(
 	mlme_set_twt_command_in_progress(
@@ -1988,6 +2002,46 @@ sme_process_twt_add_dialog_event(struct mac_context *mac,
 		WLAN_TWT_SETUP_STATE_ACTIVE);
 		WLAN_TWT_SETUP_STATE_ACTIVE);
 }
 }
 
 
+/**
+ * sme_process_twt_add_dialog_event() - Process twt add dialog event
+ * response from firmware
+ * @mac: Global MAC pointer
+ * @add_dialog_event: pointer to event buf containing twt response parameters
+ *
+ * Return: None
+ */
+static void
+sme_process_twt_add_dialog_event(struct mac_context *mac,
+				 struct twt_add_dialog_complete_event *add_dialog_event)
+{
+	bool is_evt_allowed;
+	bool setup_done;
+	enum WMI_HOST_ADD_TWT_STATUS status;
+
+	is_evt_allowed = mlme_twt_is_command_in_progress(
+		mac->psoc,
+		(struct qdf_mac_addr *)add_dialog_event->params.peer_macaddr,
+		add_dialog_event->params.dialog_id, WLAN_TWT_SETUP);
+	if (!is_evt_allowed) {
+		sme_debug("add dialog event dropped for id:%d",
+			  add_dialog_event->params.dialog_id);
+		return;
+	}
+
+	setup_done = ucfg_mlme_is_twt_setup_done(mac->psoc,
+		(struct qdf_mac_addr *)add_dialog_event->params.peer_macaddr,
+		add_dialog_event->params.dialog_id);
+	status = add_dialog_event->params.status;
+	sme_debug("setup_done: %d status: %d", setup_done, status);
+
+	if (setup_done && status) {
+		/* This is re-negotiation failure case */
+		sme_process_twt_add_renego_failure(mac, add_dialog_event);
+	} else {
+		sme_process_twt_add_initial_nego(mac, add_dialog_event);
+	}
+}
+
 static bool
 static bool
 sme_is_twt_teardown_failed(enum WMI_HOST_DEL_TWT_STATUS teardown_status)
 sme_is_twt_teardown_failed(enum WMI_HOST_DEL_TWT_STATUS teardown_status)
 {
 {
@@ -13792,7 +13846,7 @@ QDF_STATUS sme_add_dialog_cmd(mac_handle_t mac_handle,
 			twt_params->dialog_id, WLAN_TWT_ANY);
 			twt_params->dialog_id, WLAN_TWT_ANY);
 	if (is_twt_cmd_in_progress) {
 	if (is_twt_cmd_in_progress) {
 		sme_debug("Already TWT command is in progress");
 		sme_debug("Already TWT command is in progress");
-		return QDF_STATUS_E_AGAIN;
+		return QDF_STATUS_E_PENDING;
 	}
 	}
 
 
 	wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
 	wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
@@ -13875,7 +13929,7 @@ QDF_STATUS sme_del_dialog_cmd(mac_handle_t mac_handle,
 			twt_params->dialog_id, WLAN_TWT_TERMINATE);
 			twt_params->dialog_id, WLAN_TWT_TERMINATE);
 	if (is_twt_cmd_in_progress) {
 	if (is_twt_cmd_in_progress) {
 		sme_debug("Already TWT command is in progress");
 		sme_debug("Already TWT command is in progress");
-		return QDF_STATUS_E_AGAIN;
+		return QDF_STATUS_E_PENDING;
 	}
 	}
 
 
 	wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
 	wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
@@ -13943,7 +13997,7 @@ sme_pause_dialog_cmd(mac_handle_t mac_handle,
 			twt_params->dialog_id, WLAN_TWT_ANY);
 			twt_params->dialog_id, WLAN_TWT_ANY);
 	if (is_twt_cmd_in_progress) {
 	if (is_twt_cmd_in_progress) {
 		sme_debug("Already TWT command is in progress");
 		sme_debug("Already TWT command is in progress");
-		return QDF_STATUS_E_AGAIN;
+		return QDF_STATUS_E_PENDING;
 	}
 	}
 
 
 	wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
 	wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
@@ -14010,7 +14064,7 @@ sme_nudge_dialog_cmd(mac_handle_t mac_handle,
 			twt_params->dialog_id, WLAN_TWT_ANY);
 			twt_params->dialog_id, WLAN_TWT_ANY);
 	if (is_twt_cmd_in_progress) {
 	if (is_twt_cmd_in_progress) {
 		sme_debug("Already TWT command is in progress");
 		sme_debug("Already TWT command is in progress");
-		return QDF_STATUS_E_AGAIN;
+		return QDF_STATUS_E_PENDING;
 	}
 	}
 	wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
 	wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
 	if (!wma_handle) {
 	if (!wma_handle) {
@@ -14078,7 +14132,7 @@ sme_resume_dialog_cmd(mac_handle_t mac_handle,
 			twt_params->dialog_id, WLAN_TWT_ANY);
 			twt_params->dialog_id, WLAN_TWT_ANY);
 	if (is_twt_cmd_in_progress) {
 	if (is_twt_cmd_in_progress) {
 		sme_debug("Already TWT command is in progress");
 		sme_debug("Already TWT command is in progress");
-		return QDF_STATUS_E_AGAIN;
+		return QDF_STATUS_E_PENDING;
 	}
 	}
 
 
 	wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
 	wma_handle = cds_get_context(QDF_MODULE_ID_WMA);