浏览代码

qcacld-3.0: Disable Tx Queues upon sta kick out event

Upon receiving a STA kick out event or a beacon miss event,
disable the Tx Queues immediately so that there is no influx
of packets anymore as the STA is going to disconnect further.

Change-Id: Ic6d7a3acbd8b90aec68771c1520359d39e0534db
CRs-Fixed: 2171633
Varun Reddy Yeturu 7 年之前
父节点
当前提交
076eaa810d

+ 14 - 1
core/hdd/inc/wlan_hdd_tx_rx.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -66,6 +66,19 @@ QDF_STATUS hdd_get_peer_sta_id(struct hdd_station_ctx *sta_ctx,
 				struct qdf_mac_addr *peer_mac_addr,
 				uint8_t *sta_id);
 
+/**
+ * hdd_tx_queue_cb() - Disable/Enable the Transmit Queues
+ * @context: HDD context
+ * @vdev_id: vdev id
+ * @action: Action to be taken on the Tx Queues
+ * @reason: Reason for the netif action
+ *
+ * Return: None
+ */
+void hdd_tx_queue_cb(void *context, uint32_t vdev_id,
+		     enum netif_action_type action,
+		     enum netif_reason_type reason);
+
 #ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
 void hdd_tx_resume_cb(void *adapter_context, bool tx_resume);
 

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

@@ -10650,6 +10650,11 @@ int hdd_register_cb(struct hdd_context *hdd_ctx)
 	if (!QDF_IS_STATUS_SUCCESS(status))
 		hdd_err("set bt activity info callback failed");
 
+	status = sme_register_tx_queue_cb(hdd_ctx->hHal,
+					  hdd_tx_queue_cb);
+	if (!QDF_IS_STATUS_SUCCESS(status))
+		hdd_err("Register tx queue callback failed");
+
 	EXIT();
 
 	return ret;
@@ -10670,6 +10675,7 @@ void hdd_deregister_cb(struct hdd_context *hdd_ctx)
 
 	ENTER();
 
+	sme_deregister_tx_queue_cb(hdd_ctx->hHal);
 	status = sme_deregister_for_dcc_stats_event(hdd_ctx->hHal);
 	if (!QDF_IS_STATUS_SUCCESS(status))
 		hdd_err("De-register of dcc stats callback failed: %d",

+ 30 - 1
core/hdd/src/wlan_hdd_tx_rx.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -1893,6 +1893,35 @@ void hdd_send_rps_disable_ind(struct hdd_adapter *adapter)
 	cds_cfg->rps_enabled = false;
 }
 
+void hdd_tx_queue_cb(void *context, uint32_t vdev_id,
+		     enum netif_action_type action,
+		     enum netif_reason_type reason)
+{
+	struct hdd_context *hdd_ctx = (struct hdd_context *)context;
+	struct hdd_adapter *adapter = NULL;
+
+	/*
+	 * Validating the context is not required here.
+	 * if there is a driver unload/SSR in progress happening in a
+	 * different context and it has been scheduled to run and
+	 * driver got a firmware event of sta kick out, then it is
+	 * good to disable the Tx Queue to stop the influx of traffic.
+	 */
+	if (hdd_ctx == NULL) {
+		hdd_err("Invalid context passed");
+		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_debug("Tx Queue action %d on vdev %d", action, vdev_id);
+
+	wlan_hdd_netif_queue_control(adapter, action, reason);
+}
+
 #ifdef MSM_PLATFORM
 /**
  * hdd_reset_tcp_delack() - Reset tcp delack value to default

+ 10 - 3
core/mac/src/pe/lim/lim_link_monitoring_algo.c

@@ -485,15 +485,16 @@ void lim_handle_heart_beat_failure(tpAniSirGlobal mac_ctx,
 	    (session->limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE) &&
 	    (session->limSmeState != eLIM_SME_WT_DISASSOC_STATE) &&
 	    (session->limSmeState != eLIM_SME_WT_DEAUTH_STATE)) {
-		if (!mac_ctx->sys.gSysEnableLinkMonitorMode)
-			return;
+		if (!mac_ctx->sys.gSysEnableLinkMonitorMode) {
+			goto hb_handler_fail;
+		}
 
 		/* Ignore HB if channel switch is in progress */
 		if (session->gLimSpecMgmt.dot11hChanSwState ==
 		   eLIM_11H_CHANSW_RUNNING) {
 			pe_debug("Ignore Heartbeat failure as Channel switch is in progress");
 			session->pmmOffloadInfo.bcnmiss = false;
-			return;
+			goto hb_handler_fail;
 		}
 		/* Beacon frame not received within heartbeat timeout. */
 		pe_warn("Heartbeat Failure");
@@ -561,4 +562,10 @@ void lim_handle_heart_beat_failure(tpAniSirGlobal mac_ctx,
 		lim_print_mlm_state(mac_ctx, LOG1, session->limMlmState);
 		mac_ctx->lim.gLimHBfailureCntInOtherStates++;
 	}
+
+hb_handler_fail:
+	if (mac_ctx->sme.tx_queue_cb)
+		mac_ctx->sme.tx_queue_cb(mac_ctx->hHdd, session->smeSessionId,
+					 WLAN_WAKE_ALL_NETIF_QUEUE,
+					 WLAN_CONTROL_PATH);
 }

+ 0 - 1
core/mac/src/pe/lim/lim_process_message_queue.c

@@ -1715,7 +1715,6 @@ static void lim_process_messages(tpAniSirGlobal mac_ctx,
 	case SIR_LIM_PROBE_HB_FAILURE_TIMEOUT:
 		lim_handle_heart_beat_failure_timeout(mac_ctx);
 		break;
-		break;
 	case SIR_LIM_CNF_WAIT_TIMEOUT:
 		/* Does not receive CNF or dummy packet */
 		lim_handle_cnf_wait_timeout(mac_ctx, (uint16_t) msg->bodyval);

+ 5 - 0
core/mac/src/pe/lim/lim_utils.c

@@ -5546,6 +5546,11 @@ void lim_handle_heart_beat_failure_timeout(tpAniSirGlobal mac_ctx)
 			pe_err("Unexpected wt-probe-timeout in state");
 			lim_print_mlm_state(mac_ctx, LOGE,
 				psession_entry->limMlmState);
+			if (mac_ctx->sme.tx_queue_cb)
+				mac_ctx->sme.tx_queue_cb(mac_ctx->hHdd,
+						psession_entry->smeSessionId,
+						WLAN_WAKE_ALL_NETIF_QUEUE,
+						WLAN_CONTROL_PATH);
 		}
 	}
 	/*

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

@@ -1561,6 +1561,27 @@ QDF_STATUS sme_fast_reassoc(tHalHandle hal, tCsrRoamProfile *profile,
 QDF_STATUS sme_congestion_register_callback(tHalHandle hal,
 	void (*congestion_cb)(void *, uint32_t congestion, uint32_t vdev_id));
 
+/**
+ * sme_register_tx_queue_cb(): Register tx queue callback
+ * @hal: handler for HAL
+ * @tx_queue_cb: Transmit Queues callback
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS sme_register_tx_queue_cb(tHalHandle hal,
+				    void (*tx_queue_cb)(void *,
+				    uint32_t vdev_id,
+				    enum netif_action_type action,
+				    enum netif_reason_type reason));
+
+/**
+ * sme_deregister_tx_queue_cb() - Deregister the tx queue callback
+ * @hal: HAL handle
+ *
+ * Return: QDF status
+ */
+QDF_STATUS sme_deregister_tx_queue_cb(tHalHandle hal);
+
 /**
  * sme_rso_cmd_status_cb() - Set RSO cmd status callback
  * @hal: HAL Handle

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

@@ -264,6 +264,9 @@ typedef struct tagSmeStruct {
 	void (*get_arp_stats_cb)(void *, struct rsp_stats *);
 	get_chain_rssi_callback get_chain_rssi_cb;
 	void *get_chain_rssi_context;
+	void (*tx_queue_cb)(void *, uint32_t vdev_id,
+			    enum netif_action_type action,
+			    enum netif_reason_type reason);
 } tSmeStruct, *tpSmeStruct;
 
 #endif /* #if !defined( __SMEINTERNAL_H ) */

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

@@ -15499,6 +15499,32 @@ QDF_STATUS sme_congestion_register_callback(tHalHandle hal,
 	return status;
 }
 
+QDF_STATUS sme_register_tx_queue_cb(tHalHandle hal,
+				    void (*tx_queue_cb)(void *,
+				    uint32_t vdev_id,
+				    enum netif_action_type action,
+				    enum netif_reason_type reason))
+{
+	QDF_STATUS status;
+	tpAniSirGlobal mac = PMAC_STRUCT(hal);
+
+	status = sme_acquire_global_lock(&mac->sme);
+	if (QDF_IS_STATUS_SUCCESS(status)) {
+		mac->sme.tx_queue_cb = tx_queue_cb;
+		sme_release_global_lock(&mac->sme);
+		sme_debug("Tx queue callback set");
+	} else {
+		sme_err("Aquiring lock failed %d", status);
+	}
+
+	return status;
+}
+
+QDF_STATUS sme_deregister_tx_queue_cb(tHalHandle hal)
+{
+	return sme_register_tx_queue_cb(hal, NULL);
+}
+
 QDF_STATUS sme_set_smps_cfg(uint32_t vdev_id, uint32_t param_id,
 						uint32_t param_val)
 {

+ 5 - 0
core/wma/src/wma_mgmt.c

@@ -2772,6 +2772,7 @@ void wma_set_keepalive_req(tp_wma_handle wma,
 void wma_beacon_miss_handler(tp_wma_handle wma, uint32_t vdev_id, int32_t rssi)
 {
 	tSirSmeMissedBeaconInd *beacon_miss_ind;
+	tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
 
 	beacon_miss_ind = (tSirSmeMissedBeaconInd *) qdf_mem_malloc
 				  (sizeof(tSirSmeMissedBeaconInd));
@@ -2780,6 +2781,10 @@ void wma_beacon_miss_handler(tp_wma_handle wma, uint32_t vdev_id, int32_t rssi)
 		WMA_LOGE("%s: Memory allocation failure", __func__);
 		return;
 	}
+	if (mac && mac->sme.tx_queue_cb)
+		mac->sme.tx_queue_cb(mac->hHdd, vdev_id,
+				     WLAN_STOP_ALL_NETIF_QUEUE,
+				     WLAN_CONTROL_PATH);
 	beacon_miss_ind->messageType = WMA_MISSED_BEACON_IND;
 	beacon_miss_ind->length = sizeof(tSirSmeMissedBeaconInd);
 	beacon_miss_ind->bssIdx = vdev_id;