qcacld-3.0: Reduce packet loss while roaming

As soon as the firmware is done with the roaming scan and about to
start hand-off, it will notify the host that the roaming is about
to start using WMI_ROAM_NOTIF_ROAM_START. The host driver will
then notify the upper layers to stop sending the packets and
the host later informs them as part of roam synch propagation
after roaming is done to start sending the packets.

Once the firmware sends the notification and if it fails to roam
for some reason, then it will send another notification
WMI_ROAM_NOTIF_ROAM_ABORT to let the host know the upper layers
to resume sending the packets again.

Introduce an operation code for the CSR roaming callback to determine
what it needs to do when called by the lower layers.

CRs-Fixed: 996949
Change-Id: I674262b95f1781747b34fb675ad179952a8ae4d1
diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c
index 3475a18..cad7ae0 100644
--- a/core/hdd/src/wlan_hdd_assoc.c
+++ b/core/hdd/src/wlan_hdd_assoc.c
@@ -4038,6 +4038,18 @@
 		       FL("hdd_ReassocScenario set to: %d, due to eCSR_ROAM_FT_START, session: %d"),
 		       pHddStaCtx->hdd_ReassocScenario, pAdapter->sessionId);
 		break;
+	case eCSR_ROAM_DISABLE_QUEUES:
+		hdd_info("Disabling queues");
+		wlan_hdd_netif_queue_control(pAdapter,
+				WLAN_NETIF_TX_DISABLE,
+				WLAN_CONTROL_PATH);
+		break;
+	case eCSR_ROAM_ENABLE_QUEUES:
+		hdd_info("Enabling queues");
+		wlan_hdd_netif_queue_control(pAdapter,
+				WLAN_WAKE_ALL_NETIF_QUEUE,
+				WLAN_CONTROL_PATH);
+		break;
 
 	case eCSR_ROAM_SHOULD_ROAM:
 		/* notify apps that we can't pass traffic anymore */
diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h
index e54d512..0a9b8a9 100644
--- a/core/mac/inc/sir_api.h
+++ b/core/mac/inc/sir_api.h
@@ -170,11 +170,22 @@
 #define SIR_UAPSD_FLAG_ACBE     (1 << SIR_UAPSD_BITOFFSET_ACBE)
 #define SIR_UAPSD_GET(ac, mask)      (((mask) & (SIR_UAPSD_FLAG_ ## ac)) >> SIR_UAPSD_BITOFFSET_ ## ac)
 
-#define ROAM_SYNCH_PROPAGATION 1
-#define ROAMING_TX_QUEUE_DISABLE 2
 #endif
 
 /**
+ * enum sir_roam_op_code - Operation to be done by the callback.
+ * @SIR_ROAM_SYNCH_PROPAGATION: Propagate the new BSS info after roaming.
+ * @SIR_ROAMING_DEREGISTER_STA: Deregister the old STA after roaming.
+ * @SIR_ROAMING_TX_QUEUE_DISABLE: Disable the network queues while roaming.
+ * @SIR_ROAMING_TX_QUEUE_ENABLE: Enable back the n/w queues in case roam fails.
+ */
+enum sir_roam_op_code {
+	SIR_ROAM_SYNCH_PROPAGATION = 1,
+	SIR_ROAMING_DEREGISTER_STA,
+	SIR_ROAMING_TX_QUEUE_DISABLE,
+	SIR_ROAMING_TX_QUEUE_ENABLE,
+};
+/**
  * Module ID definitions.
  */
 enum {
diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h
index 0d06b3a..ae0c987 100644
--- a/core/sme/inc/csr_api.h
+++ b/core/sme/inc/csr_api.h
@@ -493,6 +493,8 @@
 	eCSR_ROAM_DFS_CHAN_SW_NOTIFY,
 	eCSR_ROAM_EXT_CHG_CHNL_IND,
 	eCSR_ROAM_STATUS_UPDATE_HW_MODE,
+	eCSR_ROAM_DISABLE_QUEUES,
+	eCSR_ROAM_ENABLE_QUEUES,
 } eRoamCmdStatus;
 
 /* comment inside indicates what roaming callback gets */
diff --git a/core/sme/inc/csr_neighbor_roam.h b/core/sme/inc/csr_neighbor_roam.h
index f56c2e3..b8b8e87 100644
--- a/core/sme/inc/csr_neighbor_roam.h
+++ b/core/sme/inc/csr_neighbor_roam.h
@@ -364,11 +364,11 @@
 		roam_offload_synch_ind *roam_synch_ind_ptr, uint8_t sessionId);
 void csr_roam_synch_callback(tpAniSirGlobal mac,
 	roam_offload_synch_ind *roam_synch_data,
-	tpSirBssDescription  bss_desc_ptr, uint8_t reason);
+	tpSirBssDescription  bss_desc_ptr, enum sir_roam_op_code reason);
 #else
 static inline void csr_roam_synch_callback(tpAniSirGlobal mac,
 	roam_offload_synch_ind *roam_synch_data,
-	tpSirBssDescription  bss_desc_ptr, uint8_t reason)
+	tpSirBssDescription  bss_desc_ptr, enum sir_roam_op_code reason)
 {}
 #endif
 void csr_neighbor_roam_state_transition(tpAniSirGlobal mac_ctx,
diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c
index 832b828..b869161 100644
--- a/core/sme/src/csr/csr_api_roam.c
+++ b/core/sme/src/csr/csr_api_roam.c
@@ -18693,7 +18693,7 @@
  */
 void csr_roam_synch_callback(tpAniSirGlobal mac_ctx,
 		roam_offload_synch_ind *roam_synch_data,
-		tpSirBssDescription  bss_desc, uint8_t reason)
+		tpSirBssDescription  bss_desc, enum sir_roam_op_code reason)
 {
 	uint8_t session_id = roam_synch_data->roamedVdevId;
 	tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id);
@@ -18721,11 +18721,28 @@
 		return;
 	}
 	session->roam_synch_in_progress = true;
-	if (reason == ROAMING_TX_QUEUE_DISABLE) {
+	switch (reason) {
+	case SIR_ROAMING_DEREGISTER_STA:
 		csr_roam_call_callback(mac_ctx, session_id, NULL, 0,
 				eCSR_ROAM_FT_START, eSIR_SME_SUCCESS);
 		sme_release_global_lock(&mac_ctx->sme);
 		return;
+	case SIR_ROAMING_TX_QUEUE_DISABLE:
+		csr_roam_call_callback(mac_ctx, session_id, NULL, 0,
+				eCSR_ROAM_DISABLE_QUEUES, eSIR_SME_SUCCESS);
+		sme_release_global_lock(&mac_ctx->sme);
+		return;
+	case SIR_ROAMING_TX_QUEUE_ENABLE:
+		csr_roam_call_callback(mac_ctx, session_id, NULL, 0,
+				eCSR_ROAM_ENABLE_QUEUES, eSIR_SME_SUCCESS);
+		sme_release_global_lock(&mac_ctx->sme);
+		return;
+	case SIR_ROAM_SYNCH_PROPAGATION:
+		break;
+	default:
+		sms_log(mac_ctx, LOGE, FL("LFR3: callback reason %d"), reason);
+		sme_release_global_lock(&mac_ctx->sme);
+		return;
 	}
 	session->roam_synch_data = roam_synch_data;
 	if (!QDF_IS_STATUS_SUCCESS(csr_get_parsed_bss_description_ies(mac_ctx,
diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h
index 886179f..06f19bf 100644
--- a/core/wma/inc/wma.h
+++ b/core/wma/inc/wma.h
@@ -1339,7 +1339,8 @@
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 	void (*csr_roam_synch_cb)(tpAniSirGlobal mac,
 		roam_offload_synch_ind *roam_synch_data,
-		tpSirBssDescription  bss_desc_ptr, uint8_t reason);
+		tpSirBssDescription  bss_desc_ptr,
+		enum sir_roam_op_code reason);
 	QDF_STATUS (*pe_roam_synch_cb)(tpAniSirGlobal mac,
 		roam_offload_synch_ind *roam_synch_data,
 		tpSirBssDescription  bss_desc_ptr);
diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h
index dfd8f8a..c82cfa0 100644
--- a/core/wma/inc/wma_types.h
+++ b/core/wma/inc/wma_types.h
@@ -704,7 +704,8 @@
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 		void (*csr_roam_synch_cb)(tpAniSirGlobal mac,
 			roam_offload_synch_ind *roam_synch_data,
-			tpSirBssDescription  bss_desc_ptr, uint8_t reason),
+			tpSirBssDescription  bss_desc_ptr,
+			enum sir_roam_op_code reason),
 		QDF_STATUS (*pe_roam_synch_cb)(tpAniSirGlobal mac,
 			roam_offload_synch_ind *roam_synch_data,
 			tpSirBssDescription  bss_desc_ptr));
@@ -712,7 +713,8 @@
 static inline QDF_STATUS wma_register_roaming_callbacks(void *cds_ctx,
 		void (*csr_roam_synch_cb)(tpAniSirGlobal mac,
 			roam_offload_synch_ind *roam_synch_data,
-			tpSirBssDescription  bss_desc_ptr, uint8_t reason),
+			tpSirBssDescription  bss_desc_ptr,
+			enum sir_roam_op_code reason),
 		QDF_STATUS (*pe_roam_synch_cb)(tpAniSirGlobal mac,
 			roam_offload_synch_ind *roam_synch_data,
 			tpSirBssDescription  bss_desc_ptr))
diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c
index 6a2ddde..e9fe644 100644
--- a/core/wma/src/wma_mgmt.c
+++ b/core/wma/src/wma_mgmt.c
@@ -3173,7 +3173,8 @@
 QDF_STATUS wma_register_roaming_callbacks(void *cds_ctx,
 	void (*csr_roam_synch_cb)(tpAniSirGlobal mac,
 		roam_offload_synch_ind *roam_synch_data,
-		tpSirBssDescription  bss_desc_ptr, uint8_t reason),
+		tpSirBssDescription  bss_desc_ptr,
+		enum sir_roam_op_code reason),
 	QDF_STATUS (*pe_roam_synch_cb)(tpAniSirGlobal mac,
 		roam_offload_synch_ind *roam_synch_data,
 		tpSirBssDescription  bss_desc_ptr))
diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c
index 91212cd..78d57ac 100644
--- a/core/wma/src/wma_scan_roam.c
+++ b/core/wma/src/wma_scan_roam.c
@@ -1883,7 +1883,7 @@
 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&synch_event->bssid,
 				   roam_synch_ind_ptr->bssid.bytes);
 	wma->csr_roam_synch_cb((tpAniSirGlobal)wma->mac_context,
-		roam_synch_ind_ptr, NULL, ROAMING_TX_QUEUE_DISABLE);
+		roam_synch_ind_ptr, NULL, SIR_ROAMING_DEREGISTER_STA);
 	/* Beacon/Probe Rsp data */
 	roam_synch_ind_ptr->beaconProbeRespOffset =
 		sizeof(roam_offload_synch_ind);
@@ -2088,7 +2088,7 @@
 			roam_synch_ind_ptr, bss_desc_ptr);
 	wma_roam_update_vdev(wma, roam_synch_ind_ptr);
 	wma->csr_roam_synch_cb((tpAniSirGlobal)wma->mac_context,
-		roam_synch_ind_ptr, bss_desc_ptr, ROAM_SYNCH_PROPAGATION);
+		roam_synch_ind_ptr, bss_desc_ptr, SIR_ROAM_SYNCH_PROPAGATION);
 	wma_process_roam_synch_complete(wma, synch_event->vdev_id);
 cleanup_label:
 	if (roam_synch_ind_ptr->join_rsp)
@@ -2380,7 +2380,6 @@
 }
 
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
-
 /**
  * wma_roam_ho_fail_handler() - LFR3.0 roam hand off failed handler
  * @wma: wma handle
@@ -5367,6 +5366,8 @@
 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
 	WMI_ROAM_EVENTID_param_tlvs *param_buf;
 	wmi_roam_event_fixed_param *wmi_event;
+	struct sSirSmeRoamOffloadSynchInd *roam_synch_data;
+	enum sir_roam_op_code op_code = {0};
 
 	param_buf = (WMI_ROAM_EVENTID_param_tlvs *) event_buf;
 	if (!param_buf) {
@@ -5375,9 +5376,9 @@
 	}
 
 	wmi_event = param_buf->fixed_param;
-	WMA_LOGD("%s: Reason %x for vdevid %x, rssi %d",
-		 __func__, wmi_event->reason, wmi_event->vdev_id,
-		 wmi_event->rssi);
+	WMA_LOGD("%s: Reason %x, Notif %x for vdevid %x, rssi %d",
+		 __func__, wmi_event->reason, wmi_event->notif,
+		 wmi_event->vdev_id, wmi_event->rssi);
 
 	switch (wmi_event->reason) {
 	case WMI_ROAM_REASON_BMISS:
@@ -5403,6 +5404,22 @@
 		wma_roam_ho_fail_handler(wma_handle, wmi_event->vdev_id);
 		break;
 #endif
+	case WMI_ROAM_REASON_INVALID:
+		roam_synch_data = qdf_mem_malloc(sizeof(*roam_synch_data));
+		if (NULL == roam_synch_data) {
+			WMA_LOGE("Memory unavailable for roam synch data");
+			return -ENOMEM;
+		}
+		if (wmi_event->notif == WMI_ROAM_NOTIF_ROAM_START)
+			op_code = SIR_ROAMING_TX_QUEUE_DISABLE;
+		if (wmi_event->notif == WMI_ROAM_NOTIF_ROAM_ABORT)
+			op_code = SIR_ROAMING_TX_QUEUE_ENABLE;
+		roam_synch_data->roamedVdevId = wmi_event->vdev_id;
+		wma_handle->csr_roam_synch_cb(
+				(tpAniSirGlobal)wma_handle->mac_context,
+				roam_synch_data, NULL, op_code);
+		qdf_mem_free(roam_synch_data);
+		break;
 	default:
 		WMA_LOGD("%s:Unhandled Roam Event %x for vdevid %x", __func__,
 			 wmi_event->reason, wmi_event->vdev_id);