Browse Source

qcacld-3.0: Get CCA from firmware

Requirement is to get CCA from frmware when connection fails due to
assoc/auth/probe response timeout.

Change-Id: I062343ed065d7b0c38b9e3b24ecfa9851b9b1537
CRs-Fixed: 2018594
Padma, Santhosh Kumar 8 years ago
parent
commit
16dacfbec2

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

@@ -173,6 +173,7 @@ struct hdd_conn_flag {
  * @roam_count: roaming counter
  * @signal: holds rssi info
  * @assoc_status_code: holds assoc fail reason
+ * @congestion: holds congestion percentage
  */
 typedef struct connection_info_s {
 	eConnectionState connState;
@@ -204,6 +205,7 @@ typedef struct connection_info_s {
 	uint32_t roam_count;
 	int8_t signal;
 	int32_t assoc_status_code;
+	uint32_t cca;
 } connection_info_t;
 
 /* Forward declarations */

+ 32 - 0
core/hdd/src/wlan_hdd_cfg80211.c

@@ -3515,6 +3515,14 @@ static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
 		hdd_err("put fail");
 		goto fail;
 	}
+
+	hdd_info("congestion:%d", hdd_sta_ctx->conn_info.cca);
+	if (nla_put_u32(skb, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
+			hdd_sta_ctx->conn_info.cca)) {
+		hdd_err("put fail");
+		goto fail;
+	}
+
 	return cfg80211_vendor_cmd_reply(skb);
 fail:
 	if (skb)
@@ -9334,6 +9342,30 @@ static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
 	return ret;
 }
 
+
+void hdd_update_cca_info_cb(void *context, uint32_t congestion,
+			uint32_t vdev_id)
+{
+	hdd_context_t *hdd_ctx = (hdd_context_t *)context;
+	int status;
+	hdd_adapter_t *adapter = NULL;
+	hdd_station_ctx_t *hdd_sta_ctx;
+
+	status = wlan_hdd_validate_context(hdd_ctx);
+	if (status != 0)
+		return;
+
+	adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
+	if (adapter == NULL) {
+		hdd_err("vdev_id %d does not exist with host", vdev_id);
+		return;
+	}
+
+	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+	hdd_sta_ctx->conn_info.cca = congestion;
+	hdd_info("congestion:%d", congestion);
+}
+
 static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
 		QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
 	[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },

+ 11 - 0
core/hdd/src/wlan_hdd_cfg80211.h

@@ -489,4 +489,15 @@ int wlan_cfg80211_tdls_mgmt(struct wlan_objmgr_pdev *pdev,
 }
 
 #endif
+
+/**
+ * hdd_update_cca_info_cb() - stores congestion value in station context
+ * @context : HDD context
+ * @congestion : congestion
+ * @vdev_id : vdev id
+ *
+ * Return: None
+ */
+void hdd_update_cca_info_cb(void *context, uint32_t congestion,
+			uint32_t vdev_id);
 #endif

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

@@ -9358,6 +9358,12 @@ int hdd_register_cb(hdd_context_t *hdd_ctx)
 	sme_register_set_connection_info_cb(hdd_ctx->hHal,
 				hdd_set_connection_in_progress,
 				hdd_is_connection_in_progress);
+
+	status = sme_congestion_register_callback(hdd_ctx->hHal,
+					     hdd_update_cca_info_cb);
+	if (!QDF_IS_STATUS_SUCCESS(status))
+		hdd_err("set congestion callback failed");
+
 	EXIT();
 
 	return ret;

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

@@ -1437,6 +1437,16 @@ QDF_STATUS sme_get_beacon_frm(tHalHandle hal, tCsrRoamProfile *profile,
 			    const tSirMacAddr bssid,
 			    uint8_t **frame_buf, uint32_t *frame_len);
 
+/**
+ * sme_congestion_register_callback(): registers congestion callback
+ * @hal: handler for HAL
+ * @congestion_cb: congestion callback
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS sme_congestion_register_callback(tHalHandle hal,
+	void (*congestion_cb)(void *, uint32_t congestion, uint32_t vdev_id));
+
 QDF_STATUS sme_delete_all_tdls_peers(tHalHandle hal, uint8_t session_id);
 
 /**

+ 1 - 0
core/sme/inc/sme_internal.h

@@ -248,6 +248,7 @@ typedef struct tagSmeStruct {
 			enum scan_reject_states *reason);
 	void (*rso_cmd_status_cb)(void *hdd_context,
 			struct rso_cmd_status *rso_status);
+	void (*congestion_cb)(void *, uint32_t congestion, uint32_t vdev_id);
 } tSmeStruct, *tpSmeStruct;
 
 #endif /* #if !defined( __SMEINTERNAL_H ) */

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

@@ -16149,3 +16149,21 @@ void sme_store_pdev(tHalHandle hal, struct wlan_objmgr_pdev *pdev)
 	wma_store_pdev(wma_handle, pdev);
 }
 
+QDF_STATUS sme_congestion_register_callback(tHalHandle hal,
+	void (*congestion_cb)(void *, uint32_t congestion, uint32_t vdev_id))
+{
+	QDF_STATUS status;
+	tpAniSirGlobal mac = PMAC_STRUCT(hal);
+
+	status = sme_acquire_global_lock(&mac->sme);
+	if (QDF_IS_STATUS_SUCCESS(status)) {
+		mac->sme.congestion_cb = congestion_cb;
+		sme_release_global_lock(&mac->sme);
+		sms_log(mac, LOG1, FL("congestion callback set"));
+	} else {
+		QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
+			FL("Aquiring lock failed %d"), status);
+	}
+
+	return status;
+}

+ 10 - 0
core/wma/inc/wma.h

@@ -2171,6 +2171,16 @@ QDF_STATUS wma_create_peer(tp_wma_handle wma, struct cdp_pdev *pdev,
 			   u_int32_t peer_type, u_int8_t vdev_id,
 			   bool roam_synch_in_progress);
 
+/**
+ * wma_get_cca_stats() - send request to fw to get CCA
+ * @wmi_hdl: wma handle
+ * @vdev_id: vdev id
+ *
+ * Return: QDF status
+ */
+QDF_STATUS wma_get_cca_stats(tp_wma_handle wma_handle,
+				uint8_t vdev_id);
+
 struct wma_ini_config *wma_get_ini_handle(tp_wma_handle wma_handle);
 WLAN_PHY_MODE wma_chan_phy_mode(u8 chan, enum phy_ch_width chan_width,
 	u8 dot11_mode);

+ 4 - 0
core/wma/src/wma_dev_if.c

@@ -1510,6 +1510,10 @@ int wma_vdev_stop_resp_handler(void *handle, uint8_t *cmd_param_info,
 			goto free_req_msg;
 		}
 
+		/* CCA is required only for sta interface */
+		if (iface->type == WMI_VDEV_TYPE_STA)
+			wma_get_cca_stats(wma, resp_event->vdev_id);
+
 		/* Clear arp and ns offload cache */
 		qdf_mem_zero(&iface->ns_offload_req,
 			sizeof(iface->ns_offload_req));

+ 44 - 0
core/wma/src/wma_utils.c

@@ -1960,6 +1960,8 @@ int wma_stats_event_handler(void *handle, uint8_t *cmd_param_info,
 	wmi_per_chain_rssi_stats *rssi_event;
 	struct wma_txrx_node *node;
 	uint8_t i, *temp;
+	wmi_congestion_stats *congestion_stats;
+	tpAniSirGlobal mac;
 
 	param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) cmd_param_info;
 	if (!param_buf) {
@@ -2017,6 +2019,30 @@ int wma_stats_event_handler(void *handle, uint8_t *cmd_param_info,
 		}
 	}
 
+	congestion_stats = (wmi_congestion_stats *) param_buf->congestion_stats;
+	if (congestion_stats) {
+		if (((congestion_stats->tlv_header & 0xFFFF0000) >> 16 ==
+			  WMITLV_TAG_STRUC_wmi_congestion_stats) &&
+			  ((congestion_stats->tlv_header & 0x0000FFFF) ==
+			  WMITLV_GET_STRUCT_TLVLEN(wmi_congestion_stats))) {
+			mac = cds_get_context(QDF_MODULE_ID_PE);
+			if (!mac) {
+				WMA_LOGE("%s: Invalid mac", __func__);
+				return -EINVAL;
+			}
+			if (!mac->sme.congestion_cb) {
+				WMA_LOGE("%s: Callback not registered",
+					__func__);
+				return -EINVAL;
+			}
+			WMA_LOGI("%s: congestion %d", __func__,
+				congestion_stats->congestion);
+			mac->sme.congestion_cb(mac->hHdd,
+				congestion_stats->congestion,
+				congestion_stats->vdev_id);
+		}
+	}
+
 	for (i = 0; i < wma->max_bssid; i++) {
 		node = &wma->interfaces[i];
 		if (node->fw_stats_set & FW_PEER_STATS_SET) {
@@ -2544,6 +2570,24 @@ end:
 	return;
 }
 
+/**
+ * wma_get_cca_stats() - send request to fw to get CCA
+ * @wma_handle: wma handle
+ * @vdev_id: vdev id
+ *
+ * Return: QDF status
+ */
+QDF_STATUS wma_get_cca_stats(tp_wma_handle wma_handle,
+				uint8_t vdev_id)
+{
+	if (wmi_unified_congestion_request_cmd(wma_handle->wmi_handle,
+			vdev_id)) {
+		WMA_LOGE("Failed to congestion request to fw");
+		return QDF_STATUS_E_FAILURE;
+	}
+	return QDF_STATUS_SUCCESS;
+}
+
 /**
  * wma_get_beacon_buffer_by_vdev_id() - get the beacon buffer from vdev ID
  * @vdev_id: vdev id