Bladeren bron

qcacmn: Delete all peers in TDLS component

In case of heartbeat failure or deauth from AP,
From lim Del sta requests are sent to FW and with response
required false, Since del sta response is not received
TDLS component is not notified to reset the local
tdls component structures and also upper layers are
notified of this peer deletion.

Change-Id: Ica0b150df7646af60868b2806432795896c75bcd
CRs-Fixed: 2324559
Bala Venkatesh 6 jaren geleden
bovenliggende
commit
de41e8ac29

+ 134 - 0
umac/tdls/core/src/wlan_tdls_main.c

@@ -358,6 +358,106 @@ static void tdls_get_all_peers_from_list(
 	qdf_mem_free(get_tdls_peers);
 }
 
+/**
+ * tdls_process_reset_all_peers() - Reset all tdls peers
+ * @delete_all_peers_ind: Delete all peers indication
+ *
+ * This function is called to reset all tdls peers and
+ * notify upper layers of teardown inidcation
+ *
+ * Return: QDF_STATUS
+ */
+
+static QDF_STATUS tdls_process_reset_all_peers(struct wlan_objmgr_vdev *vdev)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	uint8_t staidx;
+	struct tdls_peer *curr_peer = NULL;
+	struct tdls_vdev_priv_obj *tdls_vdev;
+	struct tdls_soc_priv_obj *tdls_soc;
+	uint8_t reset_session_id;
+
+	status = tdls_get_vdev_objects(vdev, &tdls_vdev, &tdls_soc);
+	if (QDF_STATUS_SUCCESS != status) {
+		tdls_err("tdls objects are NULL ");
+		return status;
+	}
+
+	if (!tdls_soc->connected_peer_count) {
+		tdls_debug("No tdls connected peers");
+		return status;
+	}
+
+	reset_session_id = tdls_vdev->session_id;
+	for (staidx = 0; staidx < tdls_soc->max_num_tdls_sta;
+							staidx++) {
+		if (tdls_soc->tdls_conn_info[staidx].sta_id
+						== INVALID_TDLS_PEER_ID)
+			continue;
+		if (tdls_soc->tdls_conn_info[staidx].session_id !=
+		    reset_session_id)
+			continue;
+
+		curr_peer =
+		tdls_find_all_peer(tdls_soc,
+				   tdls_soc->tdls_conn_info[staidx].
+				   peer_mac.bytes);
+		if (!curr_peer)
+			continue;
+
+		tdls_notice("indicate TDLS teardown (staId %d)",
+			    curr_peer->sta_id);
+
+		/* Indicate teardown to supplicant */
+		tdls_indicate_teardown(tdls_vdev,
+				       curr_peer,
+				       TDLS_TEARDOWN_PEER_UNSPEC_REASON);
+
+		tdls_reset_peer(tdls_vdev, curr_peer->peer_mac.bytes);
+
+		if (tdls_soc->tdls_dereg_peer)
+			tdls_soc->tdls_dereg_peer(
+					tdls_soc->tdls_peer_context,
+					wlan_vdev_get_id(vdev),
+					curr_peer->sta_id);
+		tdls_decrement_peer_count(tdls_soc);
+		tdls_soc->tdls_conn_info[staidx].sta_id = INVALID_TDLS_PEER_ID;
+		tdls_soc->tdls_conn_info[staidx].session_id = 255;
+
+		qdf_mem_zero(&tdls_soc->tdls_conn_info[staidx].peer_mac,
+			     sizeof(struct qdf_mac_addr));
+	}
+	return status;
+}
+
+/**
+ * tdls_reset_all_peers() - Reset all tdls peers
+ * @delete_all_peers_ind: Delete all peers indication
+ *
+ * This function is called to reset all tdls peers and
+ * notify upper layers of teardown inidcation
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS tdls_reset_all_peers(
+		struct tdls_delete_all_peers_params *delete_all_peers_ind)
+{
+	QDF_STATUS status;
+
+	if (!delete_all_peers_ind || !delete_all_peers_ind->vdev) {
+		tdls_err("invalid param");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	status = tdls_process_reset_all_peers(delete_all_peers_ind->vdev);
+
+	if (delete_all_peers_ind->callback)
+		delete_all_peers_ind->callback(delete_all_peers_ind->vdev);
+
+	qdf_mem_free(delete_all_peers_ind);
+	return status;
+}
+
 QDF_STATUS tdls_process_cmd(struct scheduler_msg *msg)
 {
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
@@ -435,6 +535,9 @@ QDF_STATUS tdls_process_cmd(struct scheduler_msg *msg)
 	case TDLS_CMD_SET_SECOFFCHANOFFSET:
 		tdls_process_set_secoffchanneloffset(msg->bodyptr);
 		break;
+	case TDLS_DELETE_ALL_PEERS_INDICATION:
+		tdls_reset_all_peers(msg->bodyptr);
+		break;
 	default:
 		break;
 	}
@@ -1156,6 +1259,37 @@ QDF_STATUS tdls_peers_deleted_notification(
 	return QDF_STATUS_SUCCESS;
 }
 
+QDF_STATUS tdls_delete_all_peers_indication(
+		struct tdls_delete_all_peers_params *delete_peers_ind)
+{
+	struct scheduler_msg msg = {0, };
+	struct tdls_delete_all_peers_params *indication;
+	QDF_STATUS status;
+
+	indication = qdf_mem_malloc(sizeof(*indication));
+	if (!indication) {
+		tdls_err("memory allocation failed !!!");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	*indication = *delete_peers_ind;
+
+	msg.bodyptr = indication;
+	msg.callback = tdls_process_cmd;
+	msg.type = TDLS_DELETE_ALL_PEERS_INDICATION;
+
+	status = scheduler_post_message(QDF_MODULE_ID_TDLS,
+					QDF_MODULE_ID_TDLS,
+					QDF_MODULE_ID_OS_IF, &msg);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		qdf_mem_free(indication);
+		tdls_alert("message post failed ");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
 /**
  * tdls_set_mode_in_vdev() - set TDLS mode
  * @tdls_vdev: tdls vdev object

+ 11 - 0
umac/tdls/core/src/wlan_tdls_main.h

@@ -725,4 +725,15 @@ void tdls_scan_serialization_comp_info_cb(struct wlan_objmgr_vdev *vdev,
 QDF_STATUS tdls_set_offchan_mode(struct wlan_objmgr_psoc *psoc,
 				     struct tdls_channel_switch_params *param);
 
+/**
+ * tdls_delete_all_peers_indication() - update tdls status info
+ * @delete_peers_ind: Delete peers indication params
+ *
+ * Notify tdls component to cleanup all peers
+ *
+ * Return: QDF_STATUS.
+ */
+
+QDF_STATUS tdls_delete_all_peers_indication(
+		struct tdls_delete_all_peers_params *delete_peers_ind);
 #endif

+ 18 - 1
umac/tdls/dispatcher/inc/wlan_tdls_public_structs.h

@@ -193,6 +193,7 @@ enum tdls_feature_mode {
  * @TDLS_CMD_SET_OFFCHANNEL: tdls offchannel
  * @TDLS_CMD_SET_OFFCHANMODE: tdls offchannel mode
  * @TDLS_CMD_SET_SECOFFCHANOFFSET: tdls secondary offchannel offset
+ * @TDLS_DELETE_ALL_PEERS_INDICATION: tdls delete all peers indication
  */
 enum tdls_command_type {
 	TDLS_CMD_TX_ACTION = 1,
@@ -217,7 +218,8 @@ enum tdls_command_type {
 	TDLS_CMD_ANTENNA_SWITCH,
 	TDLS_CMD_SET_OFFCHANNEL,
 	TDLS_CMD_SET_OFFCHANMODE,
-	TDLS_CMD_SET_SECOFFCHANOFFSET
+	TDLS_CMD_SET_SECOFFCHANOFFSET,
+	TDLS_DELETE_ALL_PEERS_INDICATION
 };
 
 /**
@@ -591,6 +593,11 @@ typedef void (*tdls_sta_notify_callback)(struct wlan_objmgr_vdev *vdev);
 /* This callback is to release vdev ref for tdls offchan param related msg */
 typedef void (*tdls_offchan_parms_callback)(struct wlan_objmgr_vdev *vdev);
 
+/* This callback is to release vdev ref for tdls_delete_all_peers_
+ * callback related msg.
+ */
+typedef void (*tdls_delete_all_peers_callback)(struct wlan_objmgr_vdev *vdev);
+
 /**
  * struct tdls_start_params - tdls start params
  * @config: tdls user config
@@ -1072,6 +1079,16 @@ struct tdls_sta_notify_params {
 	tdls_sta_notify_callback callback;
 };
 
+/**
+ * struct tdls_delete_all_peers_params - TDLS set mode params
+ * @vdev: vdev object
+ * @callback: callback to release vdev ref
+ */
+struct tdls_delete_all_peers_params {
+	struct wlan_objmgr_vdev *vdev;
+	tdls_delete_all_peers_callback callback;
+};
+
 /**
  * struct tdls_set_mode_params - TDLS set mode params
  * @vdev: vdev object

+ 13 - 1
umac/tdls/dispatcher/inc/wlan_tdls_tgt_api.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018 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
@@ -158,4 +158,16 @@ QDF_STATUS tgt_tdls_mgmt_frame_rx_cb(struct wlan_objmgr_psoc *psoc,
 void tgt_tdls_peers_deleted_notification(struct wlan_objmgr_psoc *psoc,
 					 uint32_t session_id);
 
+/**
+ * tgt_tdls_delete_all_peers_indication()- Indication to tdls component
+ * @psoc: soc object
+ * @session_id: session id
+ *
+ * This function called from legacy lim to tdls component to delete tdls peers.
+ *
+ * Return: None
+ */
+void tgt_tdls_delete_all_peers_indication(struct wlan_objmgr_psoc *psoc,
+					  uint32_t session_id);
+
 #endif

+ 47 - 0
umac/tdls/dispatcher/src/wlan_tdls_tgt_api.c

@@ -375,3 +375,50 @@ void tgt_tdls_peers_deleted_notification(struct wlan_objmgr_psoc *psoc,
 	}
 }
 
+/**
+ * tgt_tdls_delete_all_peers_ind_callback()- Callback to call from
+ * TDLS component
+ * @psoc: soc object
+ * @session_id: session id
+ *
+ * This function release the obj mgr vdev ref
+ *
+ * Return: None
+ */
+static void tgt_tdls_delete_all_peers_ind_callback(
+			struct wlan_objmgr_vdev *vdev)
+{
+	if (!vdev) {
+		tdls_err("vdev is NULL");
+		return;
+	}
+
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID);
+}
+
+void tgt_tdls_delete_all_peers_indication(struct wlan_objmgr_psoc *psoc,
+					  uint32_t session_id)
+{
+	struct wlan_objmgr_vdev *vdev;
+	struct tdls_delete_all_peers_params delete_peers_ind;
+	QDF_STATUS status;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
+						    session_id,
+						    WLAN_TDLS_SB_ID);
+
+	if (!vdev) {
+		tdls_err("vdev not exist for the session id %d",
+			 session_id);
+		return;
+	}
+
+	delete_peers_ind.vdev = vdev;
+	delete_peers_ind.callback = tgt_tdls_delete_all_peers_ind_callback;
+	status = tdls_delete_all_peers_indication(&delete_peers_ind);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		tdls_err("tdls_delete_all_peers_indication failed");
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID);
+	}
+}
+