浏览代码

qcacld-3.0: Add support for roaming in case of NUD failure

Add support for roaming in case the driver
detects a nud failure. The STA then would roam
to another BSSID, else if the roaming gets failed
the STA would remain connected to the same BSSID
as connected before.

Change-Id: Idbc99b0ce2f9cacd97564dd8cf9892120958eda2
CRs-Fixed: 2461675
gaurank kathpalia 6 年之前
父节点
当前提交
20105bb92b

+ 21 - 0
blacklist_mgr/core/inc/wlan_blm_core.h

@@ -121,6 +121,7 @@ struct blm_reject_ap_timestamp {
  * @bad_bssid_counter: It represent how many times data stall happened.
  * @ap_timestamp: Ap timestamp.
  * @reject_ap_type: what is the type of rejection for the AP (avoid, black etc.)
+ * @connect_timestamp: Timestamp when the STA got connected with this BSSID
  */
 struct blm_reject_ap {
 	qdf_list_node_t node;
@@ -139,6 +140,7 @@ struct blm_reject_ap {
 		};
 		uint8_t reject_ap_type;
 	};
+	qdf_time_t connect_timestamp;
 };
 
 /**
@@ -197,6 +199,25 @@ blm_add_userspace_black_list(struct wlan_objmgr_pdev *pdev,
 			     struct qdf_mac_addr *bssid_black_list,
 			     uint8_t num_of_bssid);
 
+/**
+ * blm_update_bssid_connect_params() - Inform the BLM about connect/disconnect
+ * with the current AP.
+ * @pdev: pdev object
+ * @bssid: BSSID of the AP
+ * @con_state: Connection stae (connected/disconnected)
+ *
+ * This API will inform the BLM about the state with the AP so that if the AP
+ * is selected, and the connection went through, and the connection did not
+ * face any data stall till the bad bssid reset timer, BLM can remove the
+ * AP from the reject ap list maintained by it.
+ *
+ * Return: None
+ */
+void
+blm_update_bssid_connect_params(struct wlan_objmgr_pdev *pdev,
+				struct qdf_mac_addr bssid,
+				enum blm_connection_state con_state);
+
 /**
  * blm_delete_reject_ap_list() - Clear away BSSID and destroy the reject ap list
  * @blm_ctx: blacklist manager pdev priv object

+ 87 - 15
blacklist_mgr/core/src/wlan_blm_core.c

@@ -300,6 +300,8 @@ blm_handle_avoid_list(struct blm_reject_ap *entry,
 	blm_debug("Added %pM to avoid list type %d, counter %d",
 		  entry->bssid.bytes, ap_info->reject_ap_type,
 		  entry->bad_bssid_counter);
+
+	entry->connect_timestamp = qdf_mc_timer_get_system_time();
 }
 
 static void
@@ -454,7 +456,14 @@ blm_is_oldest_entry(enum blm_reject_ap_type list_type,
 {
 	switch (list_type) {
 	case DRIVER_RSSI_REJECT_TYPE:
-		if (cur_node_delta < oldest_node_delta)
+		/*
+		 * For RSSI reject type, the lowest retry delay has to be found
+		 * out hence if oldest_node_delta is 0, mean this is the first
+		 * entry and thus return true, If oldest_node_delta is non
+		 * zero, compare the delta and return true if the cur entry
+		 * has lower retry delta.
+		 */
+		if (!oldest_node_delta || (cur_node_delta < oldest_node_delta))
 			return true;
 		break;
 	case USERSPACE_AVOID_TYPE:
@@ -483,17 +492,6 @@ blm_try_delete_bssid_in_list(qdf_list_t *reject_ap_list,
 	qdf_time_t oldest_node_delta = 0;
 	qdf_time_t cur_node_delta = 0;
 
-	/*
-	 * For RSSI reject type, the lowest retry delay has to be found out,
-	 * hence for reference oldest node delta should be max, and then the
-	 * first entry entry would always be less than oldest entry delta. For
-	 * every other case the delta is the current timestamp minus the time
-	 * when the AP was added, hence it has to be maximum, so a greater than
-	 * check has to be there, so the oldest node delta should be minimum.
-	 */
-	if (list_type == DRIVER_RSSI_REJECT_TYPE)
-		oldest_node_delta = 0xFFFFFFFFFFFFFFFF;
-
 	qdf_list_peek_front(reject_ap_list, &cur_node);
 
 	while (cur_node) {
@@ -641,7 +639,7 @@ blm_send_reject_ap_list_to_fw(struct wlan_objmgr_pdev *pdev,
 			      struct blm_config *cfg)
 {
 	QDF_STATUS status;
-	struct reject_ap_params reject_params;
+	struct reject_ap_params reject_params = {0};
 
 	reject_params.bssid_list =
 			qdf_mem_malloc(sizeof(*reject_params.bssid_list) *
@@ -699,7 +697,7 @@ blm_add_bssid_to_reject_list(struct wlan_objmgr_pdev *pdev,
 	blm_ctx = blm_get_pdev_obj(pdev);
 	blm_psoc_obj = blm_get_psoc_obj(wlan_pdev_get_psoc(pdev));
 
-	if (!blm_ctx || blm_psoc_obj) {
+	if (!blm_ctx || !blm_psoc_obj) {
 		blm_err("blm_ctx or blm_psoc_obj is NULL");
 		return QDF_STATUS_E_INVAL;
 	}
@@ -893,7 +891,7 @@ blm_get_bssid_reject_list(struct wlan_objmgr_pdev *pdev,
 	blm_ctx = blm_get_pdev_obj(pdev);
 	blm_psoc_obj = blm_get_psoc_obj(wlan_pdev_get_psoc(pdev));
 
-	if (!blm_ctx || blm_psoc_obj) {
+	if (!blm_ctx || !blm_psoc_obj) {
 		blm_err("blm_ctx or blm_psoc_obj is NULL");
 		return 0;
 	}
@@ -912,3 +910,77 @@ blm_get_bssid_reject_list(struct wlan_objmgr_pdev *pdev,
 
 	return num_of_reject_bssid;
 }
+
+void
+blm_update_bssid_connect_params(struct wlan_objmgr_pdev *pdev,
+				struct qdf_mac_addr bssid,
+				enum blm_connection_state con_state)
+{
+	struct blm_pdev_priv_obj *blm_ctx;
+	struct blm_psoc_priv_obj *blm_psoc_obj;
+	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
+	QDF_STATUS status;
+	struct blm_reject_ap *blm_entry = NULL;
+	qdf_time_t connection_age = 0;
+	bool entry_found = false;
+
+	blm_ctx = blm_get_pdev_obj(pdev);
+	blm_psoc_obj = blm_get_psoc_obj(wlan_pdev_get_psoc(pdev));
+
+	if (!blm_ctx || !blm_psoc_obj) {
+		blm_err("blm_ctx or blm_psoc_obj is NULL");
+		return;
+	}
+
+	status = qdf_mutex_acquire(&blm_ctx->reject_ap_list_lock);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		blm_err("failed to acquire reject_ap_list_lock");
+		return;
+	}
+
+	qdf_list_peek_front(&blm_ctx->reject_ap_list, &cur_node);
+
+	while (cur_node) {
+		qdf_list_peek_next(&blm_ctx->reject_ap_list, cur_node,
+				   &next_node);
+		blm_entry = qdf_container_of(cur_node, struct blm_reject_ap,
+					     node);
+
+		if (!qdf_mem_cmp(blm_entry->bssid.bytes, bssid.bytes,
+				 QDF_MAC_ADDR_SIZE)) {
+			blm_debug("%pM present in BLM reject list, updating connect info",
+				  blm_entry->bssid.bytes);
+			entry_found = true;
+			break;
+		}
+		cur_node = next_node;
+		next_node = NULL;
+	}
+
+	/* This means that the BSSID was not added in the reject list of BLM */
+	if (!entry_found) {
+		qdf_mutex_release(&blm_ctx->reject_ap_list_lock);
+		return;
+	}
+	switch (con_state) {
+	case BLM_AP_CONNECTED:
+		blm_entry->connect_timestamp = qdf_mc_timer_get_system_time();
+		break;
+	case BLM_AP_DISCONNECTED:
+		connection_age = qdf_mc_timer_get_system_time() -
+						blm_entry->connect_timestamp;
+		if (connection_age >
+		    blm_psoc_obj->blm_cfg.bad_bssid_counter_reset_time) {
+			blm_debug("Bad Bssid timer expired, removed %pM from list",
+				  blm_entry->bssid.bytes);
+			qdf_list_remove_node(&blm_ctx->reject_ap_list,
+					     &blm_entry->node);
+			qdf_mem_free(blm_entry);
+		}
+		break;
+	default:
+		blm_debug("Invalid AP connection state recevied %d", con_state);
+	};
+
+	qdf_mutex_release(&blm_ctx->reject_ap_list_lock);
+}

+ 10 - 0
blacklist_mgr/dispatcher/inc/wlan_blm_public_struct.h

@@ -56,6 +56,16 @@ enum blm_reject_ap_type {
 	DRIVER_MONITOR_TYPE =      5
 };
 
+/**
+ * enum blm_connection_state - State with AP (Connected, Disconnected)
+ * @BLM_AP_CONNECTED: Connected with the AP
+ * @BLM_AP_DISCONNECTED: Disconnected with the AP
+ */
+enum blm_connection_state {
+	BLM_AP_CONNECTED,
+	BLM_AP_DISCONNECTED,
+};
+
 /**
  * struct reject_ap_config_params - Structure to send reject ap list to FW
  * @bssid: BSSID of the AP

+ 27 - 0
blacklist_mgr/dispatcher/inc/wlan_blm_ucfg_api.h

@@ -83,6 +83,25 @@ ucfg_blm_add_userspace_black_list(struct wlan_objmgr_pdev *pdev,
 				  struct qdf_mac_addr *bssid_black_list,
 				  uint8_t num_of_bssid);
 
+/**
+ * ucfg_blm_update_bssid_connect_params() - Inform the BLM about connect or
+ * disconnect with the current AP.
+ * @pdev: pdev object
+ * @bssid: BSSID of the AP
+ * @con_state: Connection stae (connected/disconnected)
+ *
+ * This API will inform the BLM about the state with the AP so that if the AP
+ * is selected, and the connection went through, and the connection did not
+ * face any data stall till the bad bssid reset timer, BLM can remove the
+ * AP from the reject ap list maintained by it.
+ *
+ * Return: None
+ */
+void
+ucfg_blm_update_bssid_connect_params(struct wlan_objmgr_pdev *pdev,
+				     struct qdf_mac_addr bssid,
+				     enum blm_connection_state con_state);
+
 /**
  * ucfg_blm_add_bssid_to_reject_list() - Add BSSID to the specific reject list.
  * @pdev: Pdev object
@@ -137,5 +156,13 @@ ucfg_blm_add_userspace_black_list(struct wlan_objmgr_pdev *pdev,
 {
 	return QDF_STATUS_SUCCESS;
 }
+
+static inline void
+ucfg_blm_update_bssid_connect_params(struct wlan_objmgr_pdev *pdev,
+				     struct qdf_mac_addr bssid,
+				     enum blm_connection_state con_state)
+{
+}
+
 #endif
 #endif /* _WLAN_BLM_UCFG_H_ */

+ 8 - 0
blacklist_mgr/dispatcher/src/wlan_blm_ucfg_api.c

@@ -130,3 +130,11 @@ ucfg_blm_add_userspace_black_list(struct wlan_objmgr_pdev *pdev,
 	return blm_add_userspace_black_list(pdev, bssid_black_list,
 					    num_of_bssid);
 }
+
+void
+ucfg_blm_update_bssid_connect_params(struct wlan_objmgr_pdev *pdev,
+				     struct qdf_mac_addr bssid,
+				     enum blm_connection_state con_state)
+{
+	blm_update_bssid_connect_params(pdev, bssid, con_state);
+}

+ 11 - 0
mlme/core/inc/wlan_mlme_main.h

@@ -75,6 +75,7 @@ enum vdev_assoc_type {
  * @dynamic_cfg: current configuration of nss, chains for vdev.
  * @ini_cfg: Max configuration of nss, chains supported for vdev.
  * @sta_dynamic_oce_value: Dyanmic oce flags value for sta
+ * @roam_invoke_params: Roam invoke params
  */
 struct mlme_legacy_priv {
 	bool chan_switch_in_progress;
@@ -86,6 +87,7 @@ struct mlme_legacy_priv {
 	struct wlan_mlme_nss_chains dynamic_cfg;
 	struct wlan_mlme_nss_chains ini_cfg;
 	uint8_t sta_dynamic_oce_value;
+	struct mlme_roam_after_data_stall roam_invoke_params;
 };
 
 #ifndef CRYPTO_SET_KEY_CONVERGED
@@ -200,6 +202,15 @@ struct wlan_mlme_nss_chains *mlme_get_dynamic_vdev_config(
 struct wlan_mlme_nss_chains *mlme_get_ini_vdev_config(
 					struct wlan_objmgr_vdev *vdev);
 
+/**
+ * mlme_get_roam_invoke_params() - get the roam invoke params
+ * @vdev: vdev pointer
+ *
+ * Return: pointer to the vdev roam invoke config structure
+ */
+struct mlme_roam_after_data_stall *
+mlme_get_roam_invoke_params(struct wlan_objmgr_vdev *vdev);
+
 /**
  * mlme_psoc_object_created_notification(): mlme psoc create handler
  * @psoc: psoc which is going to created by objmgr

+ 15 - 0
mlme/core/src/wlan_mlme_main.c

@@ -78,6 +78,21 @@ struct wlan_mlme_nss_chains *mlme_get_ini_vdev_config(
 	return &mlme_priv->ini_cfg;
 }
 
+struct mlme_roam_after_data_stall *
+mlme_get_roam_invoke_params(struct wlan_objmgr_vdev *vdev)
+{
+	struct vdev_mlme_obj *vdev_mlme;
+	struct mlme_legacy_priv *mlme_priv;
+
+	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
+	if (!vdev_mlme)
+		return NULL;
+
+	mlme_priv = vdev_mlme->ext_vdev_ptr;
+
+	return &mlme_priv->roam_invoke_params;
+}
+
 uint8_t *mlme_get_dynamic_oce_flags(struct wlan_objmgr_vdev *vdev)
 {
 	struct vdev_mlme_obj *vdev_mlme;

+ 11 - 0
mlme/dispatcher/inc/wlan_mlme_api.h

@@ -62,6 +62,17 @@ QDF_STATUS wlan_mlme_set_cfg_str(uint8_t *src, struct mlme_cfg_str *dst_cfg_str,
 QDF_STATUS wlan_mlme_get_edca_params(struct wlan_mlme_edca_params *edca_params,
 				     uint8_t *data, enum e_edca_type edca_ac);
 
+/**
+ * wlan_mlme_update_cfg_with_tgt_caps() - Update mlme cfg with tgt caps
+ * @psoc: pointer to psoc object
+ * @tgt_caps:  Pointer to the mlme related capability structure
+ *
+ * Return: None
+ */
+void
+wlan_mlme_update_cfg_with_tgt_caps(struct wlan_objmgr_psoc *psoc,
+				   struct mlme_tgt_caps *tgt_caps);
+
 /*
  * mlme_get_wep_key() - get the wep key to process during auth frame
  * @vdev: VDEV object for which the wep key is being requested

+ 33 - 0
mlme/dispatcher/inc/wlan_mlme_public_struct.h

@@ -189,6 +189,26 @@ struct wlan_mlme_dot11_mode {
 	enum mlme_dot11_mode dot11_mode;
 };
 
+/**
+ * enum roam_invoke_source_entity - Source of invoking roam invoke command.
+ * @USERSPACE_INITIATED: Userspace (supplicant)
+ * @CONNECTION_MGR_INITIATED: connection mgr initiated.
+ */
+enum roam_invoke_source_entity {
+	USERSPACE_INITIATED,
+	CONNECTION_MGR_INITIATED,
+};
+
+/**
+ * struct mlme_roam_after_data_stall - roam invoke entity params
+ * @roam_invoke_in_progress: is roaming already in progress.
+ * @source: source of the roam invoke command.
+ */
+struct mlme_roam_after_data_stall {
+	bool roam_invoke_in_progress;
+	enum roam_invoke_source_entity source;
+};
+
 /**
  * struct mlme_edca_ac_vi - cwmin, cwmax and  aifs value for edca_ac_vi
  *
@@ -865,6 +885,17 @@ struct wlan_mlme_chain_cfg {
 	uint8_t max_rx_chains_5g;
 };
 
+/**
+ * struct mlme_tgt_caps - mlme related capability coming from target (FW)
+ * @data_stall_recovery_fw_support: does target supports data stall recovery.
+ *
+ * Add all the mlme-tgt related capablities here, and the public API would fill
+ * the related capability in the required mlme cfg structure.
+ */
+struct mlme_tgt_caps {
+	bool data_stall_recovery_fw_support;
+};
+
 /**
  * struct wlan_mlme_rates - RATES related config items
  * @cfpPeriod: cfp period info
@@ -1029,6 +1060,7 @@ struct wlan_mlme_chainmask {
  * @enabled_11d: enable 11d flag
  * @enable_beacon_reception_stats: enable beacon reception stats
  * @enable_remove_time_stamp_sync_cmd: Enable remove time stamp sync cmd
+ * @data_stall_recovery_fw_support: whether FW supports Data stall recovery.
  * @enable_change_channel_bandwidth: enable/disable change channel bw in mission
  * mode
  */
@@ -1059,6 +1091,7 @@ struct wlan_mlme_generic {
 	bool enable_deauth_to_disassoc_map;
 	bool enable_beacon_reception_stats;
 	bool enable_remove_time_stamp_sync_cmd;
+	bool data_stall_recovery_fw_support;
 	bool enable_change_channel_bandwidth;
 };
 

+ 16 - 0
mlme/dispatcher/src/wlan_mlme_api.c

@@ -440,6 +440,22 @@ QDF_STATUS wlan_mlme_get_tx_chainmask_1ss(struct wlan_objmgr_psoc *psoc,
 	return QDF_STATUS_SUCCESS;
 }
 
+void
+wlan_mlme_update_cfg_with_tgt_caps(struct wlan_objmgr_psoc *psoc,
+				   struct mlme_tgt_caps *tgt_caps)
+{
+	struct wlan_mlme_psoc_obj *mlme_obj;
+
+	mlme_obj = mlme_get_psoc_obj(psoc);
+	if (!mlme_obj)
+		return;
+
+	/* Update the mlme cfg according to the tgt capability received */
+
+	mlme_obj->cfg.gen.data_stall_recovery_fw_support =
+				tgt_caps->data_stall_recovery_fw_support;
+}
+
 #ifdef WLAN_FEATURE_11AX
 QDF_STATUS wlan_mlme_cfg_get_he_ul_mumimo(struct wlan_objmgr_psoc *psoc,
 					  uint32_t *value)