Browse Source

qcacld-3.0: Add support to send QCA connect fail reason code

User requests for last disconnect reason code using
QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO vendor command. Host replies with
connect fail reason codes from enum qca_sta_connect_fail_reason_codes using
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE attribute, If
last connection attempt failed.

Change-Id: I723a9dcf025bb58fa524cbf16f16a7dcea8bd5b6
CRs-Fixed: 2799227
Abhishek Ambure 4 years ago
parent
commit
b2ea72cbbe

+ 3 - 3
Kbuild

@@ -866,11 +866,11 @@ OS_IF_INC += -I$(WLAN_COMMON_INC)/os_if/linux \
             -I$(WLAN_COMMON_INC)/os_if/linux/gpio/inc
 
 OS_IF_OBJ += $(OS_IF_DIR)/linux/wlan_osif_request_manager.o \
-	     $(OS_IF_DIR)/linux/crypto/src/wlan_nl_to_crypto_params.o
+	     $(OS_IF_DIR)/linux/crypto/src/wlan_nl_to_crypto_params.o \
+	     $(OS_IF_DIR)/linux/mlme/src/osif_cm_util.o
 
 ifeq ($(CONFIG_CM_ENABLE), y)
-OS_IF_OBJ += $(OS_IF_DIR)/linux/mlme/src/osif_cm_util.o \
-	     $(OS_IF_DIR)/linux/mlme/src/osif_cm_connect_rsp.o \
+OS_IF_OBJ += $(OS_IF_DIR)/linux/mlme/src/osif_cm_connect_rsp.o \
 	     $(OS_IF_DIR)/linux/mlme/src/osif_cm_disconnect_rsp.o \
 	     $(OS_IF_DIR)/linux/mlme/src/osif_cm_req.o \
 	     $(OS_IF_DIR)/linux/mlme/src/osif_cm_roam_rsp.o

+ 3 - 0
core/hdd/inc/wlan_hdd_main.h

@@ -1119,6 +1119,8 @@ struct hdd_context;
  * @latency_level: 0 - normal, 1 - moderate, 2 - low, 3 - ultralow
  * @last_disconnect_reason: Last disconnected internal reason code
  *                          as per enum qca_disconnect_reason_codes
+ * @connect_req_status: Last disconnected internal status code
+ *                          as per enum qca_sta_connect_fail_reason_codes
  * @upgrade_udp_qos_threshold: The threshold for user priority upgrade for
 			       any UDP packet.
  * @gro_disallowed: Flag to check if GRO is enabled or disable for adapter
@@ -1412,6 +1414,7 @@ struct hdd_adapter {
 	uint32_t motion_det_baseline_value;
 #endif /* WLAN_FEATURE_MOTION_DETECTION */
 	enum qca_disconnect_reason_codes last_disconnect_reason;
+	enum wlan_status_code connect_req_status;
 
 #ifdef WLAN_FEATURE_PERIODIC_STA_STATS
 	/* Indicate whether to display sta periodic stats */

+ 10 - 0
core/hdd/src/wlan_hdd_assoc.c

@@ -2823,6 +2823,15 @@ static inline void hdd_netif_queue_enable(struct hdd_adapter *adapter)
 	}
 }
 
+static void hdd_save_connect_status(struct hdd_adapter *adapter,
+				    struct csr_roam_info *roam_info)
+{
+	if (!roam_info)
+		return;
+
+	adapter->connect_req_status = roam_info->reasonCode;
+}
+
 /**
  * hdd_association_completion_handler() - association completion handler
  * @adapter: pointer to adapter
@@ -2887,6 +2896,7 @@ hdd_association_completion_handler(struct hdd_adapter *adapter,
 	sta_ctx->cache_conn_info.signal = sta_ctx->conn_info.signal;
 	sta_ctx->cache_conn_info.noise = sta_ctx->conn_info.noise;
 
+	hdd_save_connect_status(adapter, roam_info);
 	/*
 	 * reset scan reject params if connection is success or we received
 	 * final failure from CSR after trying with all APs.

+ 50 - 5
core/hdd/src/wlan_hdd_station_info.c

@@ -42,6 +42,7 @@
 #include <cdp_txrx_stats_struct.h>
 #include <cdp_txrx_peer_ops.h>
 #include <cdp_txrx_host_stats.h>
+#include <osif_cm_util.h>
 
 /*
  * define short names for the global vendor params
@@ -68,6 +69,8 @@
 	QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_MIC_ERROR_COUNT
 #define STA_INFO_BEACON_REPLAY_COUNT \
 	QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT
+#define STA_INFO_CONNECT_FAIL_REASON_CODE \
+	QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE
 #define STA_INFO_MAX \
 	QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX
 
@@ -1647,7 +1650,16 @@ hdd_get_pmf_bcn_protect_stats_len(struct hdd_adapter *adapter)
 		return 0;
 
 	/* 4 pmf becon protect counters each of 32 bit */
-	return nla_attr_size(sizeof(uint32_t) * 4);
+	return nla_total_size(sizeof(uint32_t)) * 4;
+}
+
+static uint32_t
+hdd_get_connect_fail_reason_code_len(struct hdd_adapter *adapter)
+{
+	if (adapter->connect_req_status == STATUS_SUCCESS)
+		return 0;
+
+	return nla_total_size(sizeof(uint32_t));
 }
 
 /**
@@ -1681,6 +1693,31 @@ static int hdd_add_pmf_bcn_protect_stats(struct sk_buff *skb,
 	return 0;
 }
 
+/**
+ * hdd_add_connect_fail_reason_code() - Fills connect fail reason code
+ * @skb: pointer to skb
+ * @adapter: pointer to hdd adapter
+ *
+ * Return: on success 0 else error code
+ */
+static int hdd_add_connect_fail_reason_code(struct sk_buff *skb,
+					    struct hdd_adapter *adapter)
+{
+	uint32_t reason;
+
+	reason = osif_cm_mac_to_qca_connect_fail_reason(
+					adapter->connect_req_status);
+	if (!reason)
+		return 0;
+
+	if (nla_put_u32(skb, STA_INFO_CONNECT_FAIL_REASON_CODE, reason)) {
+		hdd_err("put fail");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 /**
  * hdd_add_peer_stats - add peer statistics information
  * @skb: pointer to response skb buffer
@@ -1915,17 +1952,18 @@ static int hdd_get_station_info_ex(struct hdd_context *hdd_ctx,
 				   struct hdd_adapter *adapter)
 {
 	struct sk_buff *skb;
-	uint32_t nl_buf_len;
+	uint32_t nl_buf_len, connect_fail_rsn_len;
 	struct hdd_station_ctx *hdd_sta_ctx;
 
 	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
 
-	if (wlan_hdd_get_station_stats(adapter)) {
+	if (wlan_hdd_get_station_stats(adapter))
 		hdd_err_rl("wlan_hdd_get_station_stats fail");
-		return -EINVAL;
-	}
 
 	nl_buf_len = hdd_get_pmf_bcn_protect_stats_len(adapter);
+	connect_fail_rsn_len = hdd_get_connect_fail_reason_code_len(adapter);
+	nl_buf_len += connect_fail_rsn_len;
+
 	if (!nl_buf_len) {
 		hdd_err_rl("Failed to get bcn pmf stats");
 		return -EINVAL;
@@ -1944,6 +1982,13 @@ static int hdd_get_station_info_ex(struct hdd_context *hdd_ctx,
 		return -EINVAL;
 	}
 
+	if (connect_fail_rsn_len) {
+		if (hdd_add_connect_fail_reason_code(skb, adapter)) {
+			hdd_err_rl("hdd_add_connect_fail_reason_code fail");
+			return -ENOMEM;
+		}
+	}
+
 	return cfg80211_vendor_cmd_reply(skb);
 }
 

+ 13 - 9
core/mac/inc/ani_global.h

@@ -667,19 +667,22 @@ typedef struct sRrmContext {
 } tRrmContext, *tpRrmContext;
 
 /**
- * enum auth_tx_ack_status - Indicate TX status of AUTH
- * @LIM_AUTH_ACK_NOT_RCD : Default status while waiting for ack status.
- * @LIM_AUTH_ACK_RCD_SUCCESS : Ack is received.
- * @LIM_AUTH_ACK_RCD_FAILURE : No Ack received.
+ * enum tx_ack_status - Indicate TX status
+ * @LIM_ACK_NOT_RCD: Default status while waiting for ack status.
+ * @LIM_ACK_RCD_SUCCESS: Ack is received.
+ * @LIM_ACK_RCD_FAILURE: No Ack received.
+ * @LIM_TX_FAILED: Failed to TX
  *
  * Indicate if driver is waiting for ACK status of auth or ACK received for AUTH
  * OR NO ACK is received for the auth sent.
  */
-enum auth_tx_ack_status {
-	LIM_AUTH_ACK_NOT_RCD,
-	LIM_AUTH_ACK_RCD_SUCCESS,
-	LIM_AUTH_ACK_RCD_FAILURE,
+enum tx_ack_status {
+	LIM_ACK_NOT_RCD,
+	LIM_ACK_RCD_SUCCESS,
+	LIM_ACK_RCD_FAILURE,
+	LIM_TX_FAILED,
 };
+
 /**
  * struct vdev_type_nss - vdev type nss structure
  * @sta: STA Nss value.
@@ -771,7 +774,8 @@ struct mac_context {
 	void (*chan_info_cb)(struct scan_chan_info *chan_info);
 	enum  country_src reg_hint_src;
 	uint32_t rx_packet_drop_counter;
-	enum auth_tx_ack_status auth_ack_status;
+	enum tx_ack_status auth_ack_status;
+	enum tx_ack_status assoc_ack_status;
 	uint8_t user_configured_nss;
 	uint32_t peer_rssi;
 	uint32_t peer_txrate;

+ 32 - 10
core/mac/src/pe/lim/lim_process_mlm_req_messages.c

@@ -53,6 +53,19 @@ static void lim_process_auth_rsp_timeout(struct mac_context *, uint32_t);
 static void lim_process_periodic_join_probe_req_timer(struct mac_context *);
 static void lim_process_auth_retry_timer(struct mac_context *);
 
+static void lim_fill_status_code(enum tx_ack_status ack_status,
+				 enum wlan_status_code *proto_status_code)
+{
+	if (ack_status == LIM_TX_FAILED)
+		*proto_status_code = STATUS_AUTH_TX_FAIL;
+	else if (ack_status == LIM_ACK_RCD_FAILURE)
+		*proto_status_code = STATUS_AUTH_NO_ACK_RECEIVED;
+	else if (ack_status == LIM_ACK_RCD_SUCCESS)
+		*proto_status_code = STATUS_AUTH_NO_RESP_RECEIVED;
+	else
+		*proto_status_code = STATUS_UNSPECIFIED_FAILURE;
+}
+
 /**
  * lim_process_sae_auth_timeout() - This function is called to process sae
  * auth timeout
@@ -63,6 +76,7 @@ static void lim_process_auth_retry_timer(struct mac_context *);
 static void lim_process_sae_auth_timeout(struct mac_context *mac_ctx)
 {
 	struct pe_session *session;
+	enum wlan_status_code proto_status_code;
 
 	session = pe_find_session_by_session_id(mac_ctx,
 			mac_ctx->lim.lim_timers.sae_auth_timer.sessionId);
@@ -77,6 +91,8 @@ static void lim_process_sae_auth_timeout(struct mac_context *mac_ctx)
 
 	switch (session->limMlmState) {
 	case eLIM_MLM_WT_SAE_AUTH_STATE:
+		lim_fill_status_code(mac_ctx->auth_ack_status,
+				     &proto_status_code);
 		/*
 		 * SAE authentication is not completed. Restore from
 		 * auth state.
@@ -84,7 +100,7 @@ static void lim_process_sae_auth_timeout(struct mac_context *mac_ctx)
 		if (session->opmode == QDF_STA_MODE)
 			lim_restore_from_auth_state(mac_ctx,
 				eSIR_SME_AUTH_TIMEOUT_RESULT_CODE,
-				REASON_UNSPEC_FAILURE, session);
+				proto_status_code, session);
 		break;
 	default:
 		/* SAE authentication is timed out in unexpected state */
@@ -748,7 +764,7 @@ static void lim_process_mlm_auth_req(struct mac_context *mac_ctx, uint32_t *msg)
 	host_log_wlan_auth_info(auth_frame_body.authAlgoNumber,
 				auth_frame_body.authTransactionSeqNumber,
 				auth_frame_body.authStatusCode);
-	mac_ctx->auth_ack_status = LIM_AUTH_ACK_NOT_RCD;
+	mac_ctx->auth_ack_status = LIM_ACK_NOT_RCD;
 	lim_send_auth_mgmt_frame(mac_ctx,
 		&auth_frame_body, mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr,
 		LIM_NO_WEP_IN_FC, session);
@@ -1555,7 +1571,7 @@ void lim_process_join_failure_timeout(struct mac_context *mac_ctx)
 			QDF_MAC_ADDR_REF(session->bssId));
 
 		mlm_join_cnf.resultCode = eSIR_SME_JOIN_TIMEOUT_RESULT_CODE;
-		mlm_join_cnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE;
+		mlm_join_cnf.protStatusCode = STATUS_NO_NETWORK_FOUND;
 		session->limMlmState = eLIM_MLM_IDLE_STATE;
 		MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
 				 session->peSessionId, session->limMlmState));
@@ -1682,14 +1698,15 @@ static void lim_process_auth_retry_timer(struct mac_context *mac_ctx)
 	 */
 	if (tx_timer_running(&mac_ctx->lim.lim_timers.gLimAuthFailureTimer) &&
 	    (session_entry->limMlmState == eLIM_MLM_WT_AUTH_FRAME2_STATE) &&
-	     (LIM_AUTH_ACK_RCD_SUCCESS != mac_ctx->auth_ack_status)) {
+	     (LIM_ACK_RCD_SUCCESS != mac_ctx->auth_ack_status)) {
 		tSirMacAuthFrameBody    auth_frame;
 
 		/*
 		 * Send the auth retry only in case we have received ack failure
 		 * else just restart the retry timer.
 		 */
-		if (LIM_AUTH_ACK_RCD_FAILURE == mac_ctx->auth_ack_status &&
+		if (((mac_ctx->auth_ack_status == LIM_ACK_RCD_FAILURE) ||
+		     (mac_ctx->auth_ack_status == LIM_TX_FAILED)) &&
 		    mac_ctx->lim.gpLimMlmAuthReq) {
 			auth_type = mac_ctx->lim.gpLimMlmAuthReq->authType;
 
@@ -1704,7 +1721,7 @@ static void lim_process_auth_retry_timer(struct mac_context *mac_ctx)
 						SIR_MAC_AUTH_FRAME_1;
 			auth_frame.authStatusCode = 0;
 			pe_debug("Retry Auth");
-			mac_ctx->auth_ack_status = LIM_AUTH_ACK_NOT_RCD;
+			mac_ctx->auth_ack_status = LIM_ACK_NOT_RCD;
 			lim_increase_fils_sequence_number(session_entry);
 			lim_send_auth_mgmt_frame(mac_ctx, &auth_frame,
 				mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr,
@@ -1731,6 +1748,7 @@ void lim_process_auth_failure_timeout(struct mac_context *mac_ctx)
 	/* fetch the pe_session based on the sessionId */
 	struct pe_session *session;
 	uint32_t val;
+	enum wlan_status_code proto_status_code;
 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
 	host_log_rssi_pkt_type *rssi_log = NULL;
 #endif
@@ -1776,10 +1794,11 @@ void lim_process_auth_failure_timeout(struct mac_context *mac_ctx)
 			}
 			mac_ctx->mlme_cfg->timeouts.auth_failure_timeout = val;
 		}
-
+		lim_fill_status_code(mac_ctx->auth_ack_status,
+				     &proto_status_code);
 		lim_restore_from_auth_state(mac_ctx,
 				eSIR_SME_AUTH_TIMEOUT_RESULT_CODE,
-				REASON_UNSPEC_FAILURE, session);
+				proto_status_code, session);
 		break;
 	default:
 		/*
@@ -1850,11 +1869,12 @@ lim_process_auth_rsp_timeout(struct mac_context *mac_ctx, uint32_t auth_idx)
 }
 
 void lim_process_assoc_failure_timeout(struct mac_context *mac_ctx,
-						     uint32_t msg_type)
+				       uint32_t msg_type)
 {
 
 	tLimMlmAssocCnf mlm_assoc_cnf;
 	struct pe_session *session;
+	enum wlan_status_code proto_status_code;
 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
 	host_log_rssi_pkt_type *rssi_log = NULL;
 #endif
@@ -1950,9 +1970,11 @@ void lim_process_assoc_failure_timeout(struct mac_context *mac_ctx,
 			lim_delete_pre_auth_node(mac_ctx,
 						 session->bssId);
 		}
+		lim_fill_status_code(mac_ctx->assoc_ack_status,
+				     &proto_status_code);
 
 		mlm_assoc_cnf.resultCode = eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE;
-		mlm_assoc_cnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE;
+		mlm_assoc_cnf.protStatusCode = proto_status_code;
 		/* Update PE session Id */
 		mlm_assoc_cnf.sessionId = session->peSessionId;
 		if (msg_type == LIM_ASSOC) {

+ 1 - 1
core/mac/src/pe/lim/lim_security_utils.c

@@ -459,7 +459,7 @@ lim_restore_from_auth_state(struct mac_context *mac, tSirResultCodes resultCode,
 	 * host have received the auth rsp and no longer auth
 	 * retry is needed also cancel the auth rety timer
 	 */
-	mac->auth_ack_status = LIM_AUTH_ACK_RCD_SUCCESS;
+	mac->auth_ack_status = LIM_ACK_RCD_SUCCESS;
 
 	/* Auth retry and AUth failure timers are not started for SAE */
 	/* 'Change' timer for future activations */

+ 9 - 6
core/mac/src/pe/lim/lim_send_management_frames.c

@@ -1893,9 +1893,11 @@ static QDF_STATUS lim_assoc_tx_complete_cnf(void *context,
 	if (tx_complete == WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK) {
 		assoc_ack_status = ACKED;
 		reason_code = QDF_STATUS_SUCCESS;
+		mac_ctx->assoc_ack_status = LIM_ACK_RCD_SUCCESS;
 	} else {
 		assoc_ack_status = NOT_ACKED;
 		reason_code = QDF_STATUS_E_FAILURE;
+		mac_ctx->assoc_ack_status = LIM_ACK_RCD_FAILURE;
 	}
 	if (buf)
 		qdf_nbuf_free(buf);
@@ -2625,6 +2627,7 @@ lim_send_assoc_req_mgmt_frame(struct mac_context *mac_ctx,
 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
 		pe_err("Failed to send Association Request (%X)!",
 			qdf_status);
+		mac_ctx->assoc_ack_status = LIM_TX_FAILED;
 		lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_ASSOC_ACK_EVENT,
 				pe_session, SENT_FAIL, QDF_STATUS_E_FAILURE);
 		/* Pkt will be freed up by the callback */
@@ -2761,7 +2764,7 @@ static QDF_STATUS lim_auth_tx_complete_cnf(void *context,
 		     (tx_complete == WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK) ?
 		     "success" : "fail", tx_complete);
 	if (tx_complete == WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK) {
-		mac_ctx->auth_ack_status = LIM_AUTH_ACK_RCD_SUCCESS;
+		mac_ctx->auth_ack_status = LIM_ACK_RCD_SUCCESS;
 		auth_ack_status = ACKED;
 		reason_code = QDF_STATUS_SUCCESS;
 		sae_auth_acked = lim_is_ack_for_sae_auth(buf);
@@ -2773,7 +2776,7 @@ static QDF_STATUS lim_auth_tx_complete_cnf(void *context,
 			lim_deactivate_and_change_timer(mac_ctx,
 							eLIM_AUTH_RETRY_TIMER);
 	} else {
-		mac_ctx->auth_ack_status = LIM_AUTH_ACK_RCD_FAILURE;
+		mac_ctx->auth_ack_status = LIM_ACK_RCD_FAILURE;
 		auth_ack_status = NOT_ACKED;
 		reason_code = QDF_STATUS_E_FAILURE;
 	}
@@ -3084,7 +3087,7 @@ alloc_packet:
 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
 			 session->peSessionId, mac_hdr->fc.subType));
 
-	mac_ctx->auth_ack_status = LIM_AUTH_ACK_NOT_RCD;
+	mac_ctx->auth_ack_status = LIM_ACK_NOT_RCD;
 	min_rid = lim_get_min_session_txrate(session);
 	lim_diag_mgmt_tx_event_report(mac_ctx, mac_hdr,
 				      session, QDF_STATUS_SUCCESS, QDF_STATUS_SUCCESS);
@@ -3105,7 +3108,7 @@ alloc_packet:
 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
 		pe_err("*** Could not send Auth frame, retCode=%X ***",
 			qdf_status);
-		mac_ctx->auth_ack_status = LIM_AUTH_ACK_RCD_FAILURE;
+		mac_ctx->auth_ack_status = LIM_TX_FAILED;
 		lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_AUTH_ACK_EVENT,
 				session, SENT_FAIL, QDF_STATUS_E_FAILURE);
 	/* Pkt will be freed up by the callback */
@@ -5627,7 +5630,7 @@ static void lim_tx_mgmt_frame(struct mac_context *mac_ctx, uint8_t vdev_id,
 	qdf_mtrace(QDF_MODULE_ID_PE, QDF_MODULE_ID_WMA, TRACE_CODE_TX_MGMT,
 		   session->peSessionId, 0);
 
-	mac_ctx->auth_ack_status = LIM_AUTH_ACK_NOT_RCD;
+	mac_ctx->auth_ack_status = LIM_ACK_NOT_RCD;
 	min_rid = lim_get_min_session_txrate(session);
 
 	qdf_status = wma_tx_frameWithTxComplete(mac_ctx, packet,
@@ -5641,7 +5644,7 @@ static void lim_tx_mgmt_frame(struct mac_context *mac_ctx, uint8_t vdev_id,
 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
 		pe_err("*** Could not send Auth frame (subType: %d), retCode=%X ***",
 			fc->subType, qdf_status);
-		mac_ctx->auth_ack_status = LIM_AUTH_ACK_RCD_FAILURE;
+		mac_ctx->auth_ack_status = LIM_TX_FAILED;
 		auth_ack_status = SENT_FAIL;
 		lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_AUTH_ACK_EVENT,
 				session, auth_ack_status, QDF_STATUS_E_FAILURE);