qcacld-3.0: Enable roaming only on wlan0

Current implementation of host driver will support fast roaming only
on a single device even in DBS mode. It is allowed on the first
STA, i.e. wlan device created in driver initialization. Dynamic roaming
disable/enable is allowed only on that device. Roaming is marked as not
allowed on other devices.

Change-Id: I3e3a72eb4d8fe81f6d3b784ab70023d2e3ac5618
CRs-Fixed: 1092386
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index 737d798..1148b9f 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -1138,6 +1138,8 @@
 	uint8_t pre_cac_chan;
 	struct hdd_connect_pm_context connect_rpm_ctx;
 	struct power_stats_response *chip_power_stats;
+
+	bool fast_roaming_allowed;
 };
 
 #define WLAN_HDD_GET_STATION_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.station)
diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c
index de08e4f..f0b8a5c 100644
--- a/core/hdd/src/wlan_hdd_assoc.c
+++ b/core/hdd/src/wlan_hdd_assoc.c
@@ -1322,7 +1322,6 @@
 		memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
 		cds_decr_session_set_pcl(pAdapter->device_mode,
 					pAdapter->sessionId);
-		wlan_hdd_enable_roaming(pAdapter);
 
 #ifdef FEATURE_WLAN_AUTO_SHUTDOWN
 		wlan_hdd_auto_shutdown_enable(pHddCtx, true);
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index caeb2e9..1f0f003 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -8049,11 +8049,18 @@
 
 	is_fast_roam_enabled = nla_get_u32(
 				tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
-	hdd_notice("isFastRoamEnabled %d", is_fast_roam_enabled);
+	hdd_notice("isFastRoamEnabled %d fast_roaming_allowed %d",
+		   is_fast_roam_enabled, adapter->fast_roaming_allowed);
 
+	if (!adapter->fast_roaming_allowed) {
+		hdd_err("fast roaming not allowed on %s interface",
+			adapter->dev->name);
+		return -EINVAL;
+	}
 	/* Update roaming */
 	ret = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
-					is_fast_roam_enabled);
+				      (is_fast_roam_enabled &&
+				       adapter->fast_roaming_allowed));
 	if (ret)
 		hdd_err("sme_config_fast_roaming failed");
 	EXIT();
@@ -11551,7 +11558,7 @@
 		qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
 			     ssid, ssid_len);
 
-		pRoamProfile->do_not_roam = false;
+		pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
 		if (bssid) {
 			pRoamProfile->BSSIDs.numOfBSSIDs = 1;
 			pRoamProfile->do_not_roam = true;
@@ -12676,8 +12683,6 @@
 	if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
 		return status;
 
-	wlan_hdd_disable_roaming(pAdapter);
-
 	/* Try disconnecting if already in connected state */
 	status = wlan_hdd_try_disconnect(pAdapter);
 	if (0 > status) {
diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c
index ba48e4c..33f3bbb 100644
--- a/core/hdd/src/wlan_hdd_ioctl.c
+++ b/core/hdd/src/wlan_hdd_ioctl.c
@@ -3281,6 +3281,11 @@
 	uint8_t *value = command;
 	uint8_t roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
 
+	if (!adapter->fast_roaming_allowed) {
+		hdd_err("Roaming is always disabled on this interface");
+		goto exit;
+	}
+
 	/* Move pointer to ahead of SETROAMMODE<delimiter> */
 	value = value + SIZE_OF_SETROAMMODE + 1;
 
@@ -4315,6 +4320,11 @@
 	uint8_t *value = command;
 	uint8_t lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
 
+	if (!adapter->fast_roaming_allowed) {
+		hdd_err("Roaming is always disabled on this interface");
+		goto exit;
+	}
+
 	/* Move pointer to ahead of SETFASTROAM<delimiter> */
 	value = value + command_len + 1;
 
@@ -5644,6 +5654,12 @@
 		goto exit;
 	}
 
+	if (!adapter->fast_roaming_allowed) {
+		hdd_warn("Fast roaming is not allowed on this device hence this operation is not permitted!");
+		ret = -EPERM;
+		goto exit;
+	}
+
 	/* Move pointer to ahead of SETCCXMODE<delimiter> */
 	value = value + command_len + 1;
 
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index db281de..a3b7649 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -2701,6 +2701,9 @@
 	hdd_notice("Set HDD connState to eConnectionState_NotConnected");
 	pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
 
+	/* set fast roaming capability in sme session */
+	status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
+					 adapter->fast_roaming_allowed);
 	/* Set the default operation channel */
 	pHddStaCtx->conn_info.operationChannel =
 		hdd_ctx->config->OperatingChannel;
@@ -6859,6 +6862,9 @@
 
 	if (adapter == NULL)
 		return ERR_PTR(-ENOSPC);
+	/* fast roaming is allowed only on first STA, i.e. wlan adapter */
+	adapter->fast_roaming_allowed = true;
+
 	ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
 	if (ret)
 		goto err_close_adapter;
diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h
index ffb844a..eea5647 100644
--- a/core/sme/inc/csr_internal.h
+++ b/core/sme/inc/csr_internal.h
@@ -1003,6 +1003,7 @@
 	bool dhcp_done;
 	uint8_t disconnect_reason;
 	uint8_t uapsd_mask;
+	bool fast_roam_enabled;
 } tCsrRoamSession;
 
 typedef struct tagCsrRoamStruct {
diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c
index 5e3aa84..390bc02 100644
--- a/core/sme/src/common/sme_api.c
+++ b/core/sme/src/common/sme_api.c
@@ -9022,8 +9022,8 @@
 		return  QDF_STATUS_E_FAILURE;
 	}
 
-	if (is_fast_roam_enabled && session && session->pCurRoamProfile)
-		session->pCurRoamProfile->do_not_roam = false;
+	if (session && session->pCurRoamProfile)
+		session->pCurRoamProfile->do_not_roam = !is_fast_roam_enabled;
 
 	status = csr_neighbor_roam_update_fast_roaming_enabled(mac_ctx,
 					 session_id, is_fast_roam_enabled);
diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c
index 084c595..e5e07f8 100644
--- a/core/sme/src/csr/csr_api_roam.c
+++ b/core/sme/src/csr/csr_api_roam.c
@@ -17715,8 +17715,10 @@
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	if ((ROAM_SCAN_OFFLOAD_START == command) && session->pCurRoamProfile &&
-	    session->pCurRoamProfile->do_not_roam) {
+	if ((ROAM_SCAN_OFFLOAD_START == command) &&
+	    ((session->pCurRoamProfile &&
+	      session->pCurRoamProfile->do_not_roam) ||
+	      !session->fast_roam_enabled)) {
 		sms_log(mac_ctx, LOGE,
 			FL("Supplicant disabled driver roaming"));
 		return QDF_STATUS_E_FAILURE;
diff --git a/core/sme/src/csr/csr_neighbor_roam.c b/core/sme/src/csr/csr_neighbor_roam.c
index 97cfb05..43f75ef 100644
--- a/core/sme/src/csr/csr_neighbor_roam.c
+++ b/core/sme/src/csr/csr_neighbor_roam.c
@@ -132,41 +132,52 @@
 }
 #endif
 
-QDF_STATUS
-csr_neighbor_roam_update_fast_roaming_enabled(tpAniSirGlobal pMac,
-					      uint8_t sessionId,
-					      const bool fastRoamEnabled)
+/**
+ * csr_neighbor_roam_update_fast_roaming_enabled() - update roaming capability
+ *
+ * @mac_ctx: Global MAC context
+ * @session_id: Session
+ * @fast_roam_enabled: Is fast roaming enabled on this device?
+ *                     This capability can be changed dynamically.
+ *
+ * Return: None
+ */
+QDF_STATUS csr_neighbor_roam_update_fast_roaming_enabled(tpAniSirGlobal mac_ctx,
+						uint8_t session_id,
+						const bool fast_roam_enabled)
 {
 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
-	tpCsrNeighborRoamControlInfo pNeighborRoamInfo =
-		&pMac->roam.neighborRoamInfo[sessionId];
+	tpCsrNeighborRoamControlInfo neighbor_roam_info =
+		&mac_ctx->roam.neighborRoamInfo[session_id];
+	tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id);
 
-	switch (pNeighborRoamInfo->neighborRoamState) {
+	switch (neighbor_roam_info->neighborRoamState) {
 	case eCSR_NEIGHBOR_ROAM_STATE_CONNECTED:
-		if (true == fastRoamEnabled) {
-			csr_roam_offload_scan(pMac, sessionId,
+		if (fast_roam_enabled) {
+			csr_roam_offload_scan(mac_ctx, session_id,
 					      ROAM_SCAN_OFFLOAD_START,
 					      REASON_CONNECT);
 		} else {
-			csr_roam_offload_scan(pMac, sessionId,
+			csr_roam_offload_scan(mac_ctx, session_id,
 					      ROAM_SCAN_OFFLOAD_STOP,
 					      REASON_DISCONNECTED);
 		}
 	break;
 	case eCSR_NEIGHBOR_ROAM_STATE_INIT:
-		NEIGHBOR_ROAM_DEBUG(pMac, LOG2,
-				FL
-				("Currently in INIT state, Nothing to do"));
+		NEIGHBOR_ROAM_DEBUG(mac_ctx, LOG2,
+				    FL
+				    ("Currently in INIT state, Nothing to do"));
 		break;
 	default:
-		NEIGHBOR_ROAM_DEBUG(pMac, LOGE,
-				FL
-				("Unexpected state %s, returning failure"),
-				mac_trace_get_neighbour_roam_state
-				(pNeighborRoamInfo->neighborRoamState));
+		NEIGHBOR_ROAM_DEBUG(mac_ctx, LOGE,
+				    FL
+				    ("Unexpected state %s, returning failure"),
+				    mac_trace_get_neighbour_roam_state
+				    (neighbor_roam_info->neighborRoamState));
 		qdf_status = QDF_STATUS_E_FAILURE;
 		break;
 	}
+	session->fast_roam_enabled = fast_roam_enabled;
 	return qdf_status;
 }
 QDF_STATUS csr_neighbor_roam_update_config(tpAniSirGlobal mac_ctx,