Browse Source

qcacld-3.0: Update connected APs beacon IE correctly

Currently host driver does not update connected APs beacon
IE and because of this host is not able to pass this information
to userspace when it request for this info.

To address above issue, update connected APs beacon IE
correclty in host driver.

Change-Id: Id08d0162704883ad8ccb0f1c436aa8f9886f28c6
CRs-Fixed: 3193823
Ashish 2 years ago
parent
commit
c0956f31ba

+ 2 - 0
core/hdd/inc/wlan_hdd_assoc.h

@@ -147,6 +147,7 @@ struct hdd_conn_flag {
  * @ch_width: channel width of operating channel
  * @max_tx_bitrate: Max tx bitrate supported by the AP
  * to which currently sta is connected.
+ * @prev_ap_bcn_ie: ap beacon IE information to which sta is currently connected
  */
 struct hdd_connection_info {
 	eConnectionState conn_state;
@@ -186,6 +187,7 @@ struct hdd_connection_info {
 	char connect_time[HDD_TIME_STRING_LEN];
 	enum phy_ch_width ch_width;
 	struct rate_info max_tx_bitrate;
+	struct element_info prev_ap_bcn_ie;
 };
 
 /* Forward declarations */

+ 39 - 0
core/hdd/src/wlan_hdd_cm_connect.c

@@ -766,6 +766,44 @@ static void hdd_cm_connect_failure(struct wlan_objmgr_vdev *vdev,
 	}
 }
 
+/**
+ * hdd_cm_update_prev_ap_ie() - Update the connected AP IEs
+ * @hdd_sta_ctx: Station context.
+ * @rsp: Connect response
+ *
+ * This API updates the connected ap beacon IEs to station context connection
+ * info.
+ *
+ * Return: None
+ */
+static void hdd_cm_update_prev_ap_ie(struct hdd_station_ctx *hdd_sta_ctx,
+				     struct wlan_cm_connect_resp *rsp)
+{
+	struct element_info *bcn_probe_rsp = &rsp->connect_ies.bcn_probe_rsp;
+	struct element_info *bcn_ie;
+	uint32_t len;
+
+	bcn_ie = &hdd_sta_ctx->conn_info.prev_ap_bcn_ie;
+	if (bcn_ie->ptr) {
+		qdf_mem_free(bcn_ie->ptr);
+		bcn_ie->ptr = NULL;
+		bcn_ie->len = 0;
+	}
+
+	if (bcn_probe_rsp->ptr &&
+	    bcn_probe_rsp->len > sizeof(struct wlan_frame_hdr)) {
+		len = bcn_probe_rsp->len - sizeof(struct wlan_frame_hdr);
+		bcn_ie->ptr = qdf_mem_malloc(len);
+		if (!bcn_ie->ptr) {
+			bcn_ie->len = 0;
+			return;
+		}
+		qdf_mem_copy(bcn_ie->ptr, bcn_probe_rsp->ptr +
+			     sizeof(struct wlan_frame_hdr), len);
+		bcn_ie->len = len;
+	}
+}
+
 static void hdd_cm_save_bss_info(struct hdd_adapter *adapter,
 				 struct wlan_cm_connect_resp *rsp)
 {
@@ -843,6 +881,7 @@ static void hdd_cm_save_bss_info(struct hdd_adapter *adapter,
 			     sizeof(hdd_sta_ctx->cache_conn_info));
 
 		hdd_copy_he_operation(hdd_sta_ctx, &assoc_resp->he_op);
+		hdd_cm_update_prev_ap_ie(hdd_sta_ctx, rsp);
 	}
 
 	qdf_mem_free(assoc_resp);

+ 8 - 0
core/hdd/src/wlan_hdd_main.c

@@ -6619,6 +6619,7 @@ void hdd_cleanup_conn_info(struct hdd_adapter *adapter)
 {
 	struct hdd_station_ctx *hdd_sta_ctx =
 					WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+	struct element_info *bcn_ie;
 
 	if (!hdd_sta_ctx)
 		return;
@@ -6627,6 +6628,13 @@ void hdd_cleanup_conn_info(struct hdd_adapter *adapter)
 		qdf_mem_free(hdd_sta_ctx->cache_conn_info.he_operation);
 		hdd_sta_ctx->cache_conn_info.he_operation = NULL;
 	}
+	bcn_ie = &hdd_sta_ctx->conn_info.prev_ap_bcn_ie;
+
+	if (bcn_ie->ptr) {
+		qdf_mem_free(bcn_ie->ptr);
+		bcn_ie->ptr = NULL;
+		bcn_ie->len = 0;
+	}
 }
 
 void hdd_sta_destroy_ctx_all(struct hdd_context *hdd_ctx)

+ 35 - 19
core/hdd/src/wlan_hdd_station_info.c

@@ -669,6 +669,35 @@ static uint32_t hdd_get_he_op_len(struct hdd_station_ctx *hdd_sta_ctx)
 }
 #endif
 
+static uint32_t hdd_get_prev_connected_bss_ies_len(
+					struct hdd_station_ctx *hdd_sta_ctx)
+{
+	return hdd_sta_ctx->conn_info.prev_ap_bcn_ie.len;
+}
+
+static uint32_t hdd_add_prev_connected_bss_ies(
+					struct sk_buff *skb,
+					struct hdd_station_ctx *hdd_sta_ctx)
+{
+	struct element_info *bcn_ie = &hdd_sta_ctx->conn_info.prev_ap_bcn_ie;
+
+	if (bcn_ie->len) {
+		if (nla_put(skb, BEACON_IES, bcn_ie->len, bcn_ie->ptr)) {
+			hdd_err("Failed to put beacon IEs: bytes left: %d, ie_len: %u ",
+				skb_tailroom(skb), bcn_ie->len);
+			return -EINVAL;
+		}
+
+		hdd_nofl_debug("Beacon IEs len: %u", bcn_ie->len);
+
+		qdf_mem_free(bcn_ie->ptr);
+		bcn_ie->ptr = NULL;
+		bcn_ie->len = 0;
+	}
+
+	return 0;
+}
+
 /**
  * hdd_get_station_info() - send BSS information to supplicant
  * @hdd_ctx: pointer to hdd context
@@ -680,10 +709,9 @@ static int hdd_get_station_info(struct hdd_context *hdd_ctx,
 				struct hdd_adapter *adapter)
 {
 	struct sk_buff *skb = NULL;
-	uint8_t *tmp_hs20 = NULL, *ies = NULL;
-	uint32_t nl_buf_len, ie_len = 0, hdd_he_op_len = 0;
+	uint8_t *tmp_hs20 = NULL;
+	uint32_t nl_buf_len, hdd_he_op_len = 0;
 	struct hdd_station_ctx *hdd_sta_ctx;
-	QDF_STATUS status;
 
 	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
 
@@ -721,11 +749,7 @@ static int hdd_get_station_info(struct hdd_context *hdd_ctx,
 	if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_op_present)
 		nl_buf_len += sizeof(hdd_sta_ctx->
 						cache_conn_info.vht_operation);
-	status = sme_get_prev_connected_bss_ies(hdd_ctx->mac_handle,
-						adapter->vdev_id,
-						&ies, &ie_len);
-	if (QDF_IS_STATUS_SUCCESS(status))
-		nl_buf_len += ie_len;
+	nl_buf_len += hdd_get_prev_connected_bss_ies_len(hdd_sta_ctx);
 
 	hdd_he_op_len = hdd_get_he_op_len(hdd_sta_ctx);
 	nl_buf_len += hdd_he_op_len;
@@ -809,16 +833,9 @@ static int hdd_get_station_info(struct hdd_context *hdd_ctx,
 		goto fail;
 	}
 
-	if (ie_len) {
-		if (nla_put(skb, BEACON_IES, ie_len, ies)) {
-			hdd_err("Failed to put beacon IEs: bytes left: %d, ie_len: %u total buf_len: %u",
-				skb_tailroom(skb), ie_len, nl_buf_len);
-			goto fail;
-		}
-
-		hdd_nofl_debug("Beacon IEs len: %u", ie_len);
-
-		qdf_mem_free(ies);
+	if (hdd_add_prev_connected_bss_ies(skb, hdd_sta_ctx)) {
+		hdd_err("put fail total buf_len: %u", nl_buf_len);
+		goto fail;
 	}
 
 	hdd_nofl_debug(
@@ -840,7 +857,6 @@ static int hdd_get_station_info(struct hdd_context *hdd_ctx,
 fail:
 	if (skb)
 		kfree_skb(skb);
-	qdf_mem_free(ies);
 	return -EINVAL;
 }
 

+ 0 - 15
core/sme/inc/sme_api.h

@@ -4347,21 +4347,6 @@ QDF_STATUS sme_get_ani_level(mac_handle_t mac_handle, uint32_t *freqs,
 			     void *context), void *context);
 #endif /* FEATURE_ANI_LEVEL_REQUEST */
 
-/**
- * sme_get_prev_connected_bss_ies() - Get the previous connected AP IEs
- * @mac_handle: The handle returned by mac_open.
- * @vdev_id: vdev id
- * @ies: IEs of the disconnected AP. Currently to carry beacon IEs.
- * @ie_len: Length of the @ies
- *
- * This API extracts the IEs from the previous connected AP info and update
- * them to the ies and ie_len.
- *
- * Return: QDF_STATUS
- */
-QDF_STATUS sme_get_prev_connected_bss_ies(mac_handle_t mac_handle,
-					  uint8_t vdev_id,
-					  uint8_t **ies, uint32_t *ie_len);
 /*
  * sme_vdev_self_peer_delete_resp() - Response for self peer delete
  * @del_vdev_params: parameters for which vdev self peer has been deleted

+ 0 - 47
core/sme/src/common/sme_api.c

@@ -15752,53 +15752,6 @@ QDF_STATUS sme_get_ani_level(mac_handle_t mac_handle, uint32_t *freqs,
 }
 #endif /* FEATURE_ANI_LEVEL_REQUEST */
 
-QDF_STATUS sme_get_prev_connected_bss_ies(mac_handle_t mac_handle,
-					  uint8_t vdev_id,
-					  uint8_t **ies, uint32_t *ie_len)
-{
-	struct mac_context *mac = MAC_CONTEXT(mac_handle);
-	QDF_STATUS status = QDF_STATUS_SUCCESS;
-	uint32_t len;
-	uint8_t *beacon_ie;
-	struct rso_config *rso_cfg;
-	struct wlan_objmgr_vdev *vdev;
-	struct element_info *bcn_ie;
-
-	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(mac->pdev, vdev_id,
-						    WLAN_LEGACY_SME_ID);
-	if (!vdev)
-		return QDF_STATUS_E_INVAL;
-
-	rso_cfg = wlan_cm_get_rso_config(vdev);
-	if (!rso_cfg) {
-		status = QDF_STATUS_E_INVAL;
-		goto end;
-	}
-
-	bcn_ie = &rso_cfg->prev_ap_bcn_ie;
-
-	if (!bcn_ie->len) {
-		sme_debug("No IEs to return");
-		status = QDF_STATUS_E_INVAL;
-		goto end;
-	}
-
-	len = bcn_ie->len;
-	beacon_ie = qdf_mem_malloc(len);
-	if (!beacon_ie) {
-		status = QDF_STATUS_E_NOMEM;
-		goto end;
-	}
-	qdf_mem_copy(beacon_ie, bcn_ie->ptr, len);
-
-	*ie_len = len;
-	*ies = beacon_ie;
-end:
-	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
-
-	return status;
-}
-
 #ifdef FEATURE_MONITOR_MODE_SUPPORT
 
 QDF_STATUS sme_set_monitor_mode_cb(mac_handle_t mac_handle,