qcacld-3.0: Add support for PMKID modes of PMK caching and OKC

Convert the boolean variables used for tracking okc_enable into
separate bit flags for OKC and PMK caching. Firmware will also
add support for bitwise enablement of OKC and PMK caching in 802.11i
configuration part of RSO command.

CRs-Fixed: 2004963
Change-Id: Ib2fcdc6318adb488eca5cf47b2b59541020e6009
diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h
index 1c76121..f4482ed 100644
--- a/core/hdd/inc/wlan_hdd_cfg.h
+++ b/core/hdd/inc/wlan_hdd_cfg.h
@@ -561,6 +561,19 @@
  *
  * This ini is used to enable or disable DFS channel
  * scan
+ */
+#define CFG_ENABLE_DFS_CHNL_SCAN_NAME              "gEnableDFSChnlScan"
+#define CFG_ENABLE_DFS_CHNL_SCAN_MIN               (0)
+#define CFG_ENABLE_DFS_CHNL_SCAN_MAX               (1)
+#define CFG_ENABLE_DFS_CHNL_SCAN_DEFAULT           (1)
+
+/*
+ * <ini>
+ * pmkidModes - Enable PMKID modes
+ * This INI is used to enable PMKID feature options
+ * @Min: 0
+ * @Max: 3
+ * @Default: 3
  *
  * Related: None
  *
@@ -570,10 +583,12 @@
  *
  * </ini>
  */
-#define CFG_ENABLE_DFS_CHNL_SCAN_NAME              "gEnableDFSChnlScan"
-#define CFG_ENABLE_DFS_CHNL_SCAN_MIN               (0)
-#define CFG_ENABLE_DFS_CHNL_SCAN_MAX               (1)
-#define CFG_ENABLE_DFS_CHNL_SCAN_DEFAULT           (1)
+#define CFG_PMKID_MODES_NAME                       "pmkidModes"
+#define CFG_PMKID_MODES_MIN                        (0x0)
+#define CFG_PMKID_MODES_MAX                        (0x3)
+#define CFG_PMKID_MODES_DEFAULT                    (0x3)
+#define CFG_PMKID_MODES_OKC                        (0x1)
+#define CFG_PMKID_MODES_PMKSA_CACHING              (0x2)
 
 /*
  * <ini>
@@ -10460,7 +10475,7 @@
 	bool isFastTransitionEnabled;
 	uint8_t RoamRssiDiff;
 	bool isWESModeEnabled;
-	bool isOkcIniFeatureEnabled;
+	uint32_t pmkid_modes;
 	bool isRoamOffloadScanEnabled;
 	bool bImplicitQosEnabled;
 
@@ -11171,6 +11186,8 @@
 
 bool hdd_is_okc_mode_enabled(hdd_context_t *pHddCtx);
 QDF_STATUS hdd_set_idle_ps_config(hdd_context_t *pHddCtx, uint32_t val);
+void hdd_get_pmkid_modes(hdd_context_t *pHddCtx,
+			 struct pmkid_mode_bits *pmkid_modes);
 
 void hdd_update_tgt_cfg(void *context, void *param);
 
diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c
index d640eff..36fc46c 100644
--- a/core/hdd/src/wlan_hdd_cfg.c
+++ b/core/hdd/src/wlan_hdd_cfg.c
@@ -1028,13 +1028,14 @@
 			     CFG_ENABLE_WES_MODE_NAME_MIN,
 			     CFG_ENABLE_WES_MODE_NAME_MAX,
 			     cb_notify_set_wes_mode, 0),
-	REG_VARIABLE(CFG_OKC_FEATURE_ENABLED_NAME, WLAN_PARAM_Integer,
-		     struct hdd_config, isOkcIniFeatureEnabled,
+	REG_VARIABLE(CFG_PMKID_MODES_NAME, WLAN_PARAM_Integer,
+		     struct hdd_config, pmkid_modes,
 		     VAR_FLAGS_OPTIONAL |
 		     VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
-		     CFG_OKC_FEATURE_ENABLED_DEFAULT,
-		     CFG_OKC_FEATURE_ENABLED_MIN,
-		     CFG_OKC_FEATURE_ENABLED_MAX),
+		     CFG_PMKID_MODES_DEFAULT,
+		     CFG_PMKID_MODES_MIN,
+		     CFG_PMKID_MODES_MAX),
+
 	REG_DYNAMIC_VARIABLE(CFG_ROAM_SCAN_OFFLOAD_ENABLED, WLAN_PARAM_Integer,
 			     struct hdd_config, isRoamOffloadScanEnabled,
 			     VAR_FLAGS_OPTIONAL |
@@ -5354,8 +5355,8 @@
 		  pHddCtx->config->RoamRssiDiff);
 	hdd_info("Name = [isWESModeEnabled] Value = [%u] ",
 		  pHddCtx->config->isWESModeEnabled);
-	hdd_info("Name = [OkcEnabled] Value = [%u] ",
-		  pHddCtx->config->isOkcIniFeatureEnabled);
+	hdd_info("Name = [pmkidModes] Value = [0x%x] ",
+		  pHddCtx->config->pmkid_modes);
 #ifdef FEATURE_WLAN_SCAN_PNO
 	hdd_info("Name = [configPNOScanSupport] Value = [%u] ",
 		  pHddCtx->config->configPNOScanSupport);
@@ -7602,18 +7603,18 @@
 }
 
 /**
- * hdd_is_okc_mode_enabled() - returns whether OKC mode is enabled or not
+ * hdd_get_pmkid_modes() - returns PMKID mode bits
  * @pHddCtx: the pointer to hdd context
  *
- * Return: true if OKC is enabled, otherwise false
+ * Return: value of pmkid_modes
  */
-bool hdd_is_okc_mode_enabled(hdd_context_t *pHddCtx)
+void hdd_get_pmkid_modes(hdd_context_t *pHddCtx,
+			 struct pmkid_mode_bits *pmkid_modes)
 {
-	if (NULL == pHddCtx) {
-		hdd_alert("pHddCtx is NULL");
-		return -EINVAL;
-	}
-	return pHddCtx->config->isOkcIniFeatureEnabled;
+	pmkid_modes->fw_okc = (pHddCtx->config->pmkid_modes &
+			       CFG_PMKID_MODES_OKC) ? 1 : 0;
+	pmkid_modes->fw_pmksa_cache = (pHddCtx->config->pmkid_modes &
+				       CFG_PMKID_MODES_PMKSA_CACHING) ? 1 : 0;
 }
 
 /**
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index 4ccc55a..0c55b0e 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -4285,6 +4285,7 @@
 	hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
 	hdd_context_t *hdd_ctx_ptr;
 	int status;
+	struct pmkid_mode_bits pmkid_modes;
 
 	ENTER_DEV(dev);
 
@@ -4308,10 +4309,13 @@
 	status = wlan_hdd_validate_context(hdd_ctx_ptr);
 	if (status)
 		return status;
+
+	hdd_get_pmkid_modes(hdd_ctx_ptr, &pmkid_modes);
+
 	sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
 			hdd_adapter_ptr->sessionId,
 			true,
-			hdd_is_okc_mode_enabled(hdd_ctx_ptr));
+			&pmkid_modes);
 	qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
 	qdf_mem_copy(local_pmk, data, data_len);
 	sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
@@ -13450,6 +13454,9 @@
  * @preauth: Preauth flag
  *
  * This function is used to notify the supplicant of a new PMKSA candidate.
+ * PMK value is notified to supplicant whether PMK caching or OKC is enabled
+ * in firmware or not. Supplicant needs this value becaue it uses PMK caching
+ * by default.
  *
  * Return: 0 for success, non-zero for failure
  */
@@ -13458,7 +13465,6 @@
 					     int index, bool preauth)
 {
 	struct net_device *dev = pAdapter->dev;
-	hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
 
 	ENTER();
 	hdd_debug("is going to notify supplicant of:");
@@ -13468,13 +13474,11 @@
 		return -EINVAL;
 	}
 
-	if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
-		hdd_notice(MAC_ADDRESS_STR,
-		       MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
-		cfg80211_pmksa_candidate_notify(dev, index,
-						pRoamInfo->bssid.bytes,
-						preauth, GFP_KERNEL);
-	}
+	hdd_notice(MAC_ADDRESS_STR,
+	       MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
+	cfg80211_pmksa_candidate_notify(dev, index,
+					pRoamInfo->bssid.bytes,
+					preauth, GFP_KERNEL);
 	return 0;
 }
 
diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c
index ba76227..ad0595b 100644
--- a/core/hdd/src/wlan_hdd_ioctl.c
+++ b/core/hdd/src/wlan_hdd_ioctl.c
@@ -3404,15 +3404,17 @@
 	bool eseMode = sme_get_is_ese_feature_enabled(hdd_ctx->hHal);
 	char extra[32];
 	uint8_t len = 0;
+	struct pmkid_mode_bits pmkid_modes;
 
+	hdd_get_pmkid_modes(hdd_ctx, &pmkid_modes);
 	/*
-	 * Check if the features OKC/ESE/11R are supported simultaneously,
+	 * Check if the features PMKID/ESE/11R are supported simultaneously,
 	 * then this operation is not permitted (return FAILURE)
 	 */
 	if (eseMode &&
-	    hdd_is_okc_mode_enabled(hdd_ctx) &&
+	    (pmkid_modes.fw_okc || pmkid_modes.fw_pmksa_cache) &&
 	    sme_get_is_ft_feature_enabled(hdd_ctx->hHal)) {
-		hdd_warn("OKC/ESE/11R are supported simultaneously hence this operation is not permitted!");
+		hdd_warn("PMKID/ESE/11R are supported simultaneously hence this operation is not permitted!");
 		ret = -EPERM;
 		goto exit;
 	}
@@ -3437,24 +3439,25 @@
 				hdd_priv_data_t *priv_data)
 {
 	int ret = 0;
-	bool okcMode = hdd_is_okc_mode_enabled(hdd_ctx);
+	struct pmkid_mode_bits pmkid_modes;
 	char extra[32];
 	uint8_t len = 0;
 
+	hdd_get_pmkid_modes(hdd_ctx, &pmkid_modes);
 	/*
 	 * Check if the features OKC/ESE/11R are supported simultaneously,
 	 * then this operation is not permitted (return FAILURE)
 	 */
-	if (okcMode &&
+	if (pmkid_modes.fw_okc &&
 	    sme_get_is_ese_feature_enabled(hdd_ctx->hHal) &&
 	    sme_get_is_ft_feature_enabled(hdd_ctx->hHal)) {
-		hdd_warn("OKC/ESE/11R are supported simultaneously hence this operation is not permitted!");
+		hdd_warn("PMKID/ESE/11R are supported simultaneously hence this operation is not permitted!");
 		ret = -EPERM;
 		goto exit;
 	}
 
 	len = scnprintf(extra, sizeof(extra), "%s %d",
-			"GETOKCMODE", okcMode);
+			"GETOKCMODE", pmkid_modes.fw_okc);
 	len = QDF_MIN(priv_data->total_len, len + 1);
 
 	if (copy_to_user(priv_data->buf, &extra, len)) {
@@ -4393,16 +4396,19 @@
 {
 	int ret = 0;
 	uint8_t *value = command;
-	uint8_t okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
+	uint32_t okc_mode;
+	struct pmkid_mode_bits pmkid_modes;
+
+	hdd_get_pmkid_modes(hdd_ctx, &pmkid_modes);
 
 	/*
-	 * Check if the features OKC/ESE/11R are supported simultaneously,
+	 * Check if the features PMKID/ESE/11R are supported simultaneously,
 	 * then this operation is not permitted (return FAILURE)
 	 */
 	if (sme_get_is_ese_feature_enabled(hdd_ctx->hHal) &&
-	    hdd_is_okc_mode_enabled(hdd_ctx) &&
+	    pmkid_modes.fw_okc &&
 	    sme_get_is_ft_feature_enabled(hdd_ctx->hHal)) {
-		hdd_warn("OKC/ESE/11R are supported simultaneously hence this operation is not permitted!");
+		hdd_warn("PMKID/ESE/11R are supported simultaneously hence this operation is not permitted!");
 		ret = -EPERM;
 		goto exit;
 	}
@@ -4410,33 +4416,35 @@
 	/* Move pointer to ahead of SETOKCMODE<delimiter> */
 	value = value + command_len + 1;
 
+	/* get the current configured value */
+	okc_mode = hdd_ctx->config->pmkid_modes & CFG_PMKID_MODES_OKC;
+
 	/* Convert the value from ascii to integer */
-	ret = kstrtou8(value, 10, &okcMode);
+	ret = kstrtou32(value, 10, &okc_mode);
 	if (ret < 0) {
 		/*
 		 * If the input value is greater than max value of datatype,
 		 * then also kstrtou8 fails
 		 */
-		hdd_err("kstrtou8 failed range [%d - %d]",
-			  CFG_OKC_FEATURE_ENABLED_MIN,
-			  CFG_OKC_FEATURE_ENABLED_MAX);
+		hdd_err("value out of range [0 - 1]");
 		ret = -EINVAL;
 		goto exit;
 	}
 
-	if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
-	    (okcMode > CFG_OKC_FEATURE_ENABLED_MAX)) {
-		hdd_err("Okc mode value %d is out of range (Min: %d Max: %d)",
-			  okcMode,
-			  CFG_OKC_FEATURE_ENABLED_MIN,
-			  CFG_OKC_FEATURE_ENABLED_MAX);
+	if ((okc_mode < 0) ||
+	    (okc_mode > 1)) {
+		hdd_err("Okc mode value %d is out of range (Min: 0 Max: 1)",
+			  okc_mode);
 		ret = -EINVAL;
 		goto exit;
 	}
 	hdd_debug("Received Command to change okc mode = %d",
-		  okcMode);
+		  okc_mode);
 
-	hdd_ctx->config->isOkcIniFeatureEnabled = okcMode;
+	if (okc_mode)
+		hdd_ctx->config->pmkid_modes |= CFG_PMKID_MODES_OKC;
+	else
+		hdd_ctx->config->pmkid_modes &= ~CFG_PMKID_MODES_OKC;
 
 exit:
 	return ret;
@@ -5491,13 +5499,15 @@
 	int ret = 0;
 	uint8_t *value = command;
 	uint8_t eseMode = CFG_ESE_FEATURE_ENABLED_DEFAULT;
+	struct pmkid_mode_bits pmkid_modes;
 
+	hdd_get_pmkid_modes(hdd_ctx, &pmkid_modes);
 	/*
 	 * Check if the features OKC/ESE/11R are supported simultaneously,
 	 * then this operation is not permitted (return FAILURE)
 	 */
 	if (sme_get_is_ese_feature_enabled(hdd_ctx->hHal) &&
-	    hdd_is_okc_mode_enabled(hdd_ctx) &&
+	    pmkid_modes.fw_okc &&
 	    sme_get_is_ft_feature_enabled(hdd_ctx->hHal)) {
 		hdd_warn("OKC/ESE/11R are supported simultaneously hence this operation is not permitted!");
 		ret = -EPERM;
diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h
index 8e34aa3..c7f5880 100644
--- a/core/mac/inc/sir_api.h
+++ b/core/mac/inc/sir_api.h
@@ -2963,6 +2963,18 @@
 	int traffic_threshold;
 };
 
+/**
+ * struct pmkid_mode_bits - Bit flags for PMKID usage in RSN IE
+ * @fw_okc: Opportunistic key caching enable in firmware
+ * @fw_pmksa_cache: PMKSA caching enable in firmware, remember previously
+ *                  visited BSSID/PMK pairs
+ */
+struct pmkid_mode_bits {
+	uint32_t fw_okc:1;
+	uint32_t fw_pmksa_cache:1;
+	uint32_t unused:30;
+};
+
 typedef struct sSirRoamOffloadScanReq {
 	uint16_t message_type;
 	uint16_t length;
@@ -3007,7 +3019,7 @@
 	uint8_t R0KH_ID[SIR_ROAM_R0KH_ID_MAX_LEN];
 	uint32_t R0KH_ID_Length;
 	uint8_t RoamKeyMgmtOffloadEnabled;
-	bool okc_enabled;
+	struct pmkid_mode_bits pmkid_modes;
 #endif
 	struct roam_ext_params roam_params;
 	uint8_t  middle_of_roaming;
diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h
index ded4457..4665b24 100644
--- a/core/sme/inc/csr_internal.h
+++ b/core/sme/inc/csr_internal.h
@@ -955,7 +955,7 @@
 	size_t pmk_len;
 	uint8_t RoamKeyMgmtOffloadEnabled;
 	roam_offload_synch_ind *roam_synch_data;
-	bool okc_enabled;
+	struct pmkid_mode_bits pmkid_modes;
 #endif
 	tftSMEContext ftSmeContext;
 	/* This count represents the number of bssid's we try to join. */
diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h
index 98b940e..f0d69fc 100644
--- a/core/sme/inc/sme_api.h
+++ b/core/sme/inc/sme_api.h
@@ -908,7 +908,7 @@
 QDF_STATUS sme_update_roam_key_mgmt_offload_enabled(tHalHandle hal_ctx,
 		uint8_t session_id,
 		bool key_mgmt_offload_enabled,
-		bool okc_enabled);
+		struct pmkid_mode_bits *pmkid_modes);
 #endif
 #ifdef WLAN_FEATURE_NAN
 QDF_STATUS sme_nan_event(tHalHandle hHal, void *pMsg);
diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c
index d7b74bb..60dcbed 100644
--- a/core/sme/src/common/sme_api.c
+++ b/core/sme/src/common/sme_api.c
@@ -13342,15 +13342,15 @@
  * @hal_ctx: The handle returned by mac_open.
  * @session_id: Session Identifier
  * @key_mgmt_offload_enabled: key mgmt enable/disable flag
- * @okc_enabled: Opportunistic key caching enable/disable flag
+ * @pmkid_modes: PMKID modes of PMKSA caching and OKC
  * Return: QDF_STATUS_SUCCESS - SME updated config successfully.
  * Other status means SME is failed to update.
  */
 
 QDF_STATUS sme_update_roam_key_mgmt_offload_enabled(tHalHandle hal_ctx,
-						uint8_t session_id,
-						bool key_mgmt_offload_enabled,
-						bool okc_enabled)
+					uint8_t session_id,
+					bool key_mgmt_offload_enabled,
+					struct pmkid_mode_bits *pmkid_modes)
 {
 	tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ctx);
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
@@ -13364,7 +13364,7 @@
 			status = csr_roam_set_key_mgmt_offload(mac_ctx,
 						session_id,
 						key_mgmt_offload_enabled,
-						okc_enabled);
+						pmkid_modes);
 		} else {
 			status = QDF_STATUS_E_INVAL;
 		}
diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c
index d7338d6..50d6609 100644
--- a/core/sme/src/csr/csr_api_roam.c
+++ b/core/sme/src/csr/csr_api_roam.c
@@ -16920,7 +16920,7 @@
  * @mac_ctx: mac context.
  * @session_id: Session Identifier
  * @roam_key_mgmt_offload_enabled: key mgmt enable/disable flag
- * @okc_enabled: Opportunistic key caching enable/disable flag
+ * @pmkid_modes: PMKID modes of PMKSA caching and OKC
  *
  * Return: QDF_STATUS_SUCCESS - CSR updated config successfully.
  * Other status means CSR is failed to update.
@@ -16929,7 +16929,7 @@
 QDF_STATUS csr_roam_set_key_mgmt_offload(tpAniSirGlobal mac_ctx,
 					 uint32_t session_id,
 					 bool roam_key_mgmt_offload_enabled,
-					 bool okc_enabled)
+					 struct pmkid_mode_bits *pmkid_modes)
 {
 	tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id);
 
@@ -16938,7 +16938,8 @@
 		return QDF_STATUS_E_FAILURE;
 	}
 	session->RoamKeyMgmtOffloadEnabled = roam_key_mgmt_offload_enabled;
-	session->okc_enabled = okc_enabled;
+	session->pmkid_modes.fw_okc = pmkid_modes->fw_okc;
+	session->pmkid_modes.fw_pmksa_cache = pmkid_modes->fw_pmksa_cache;
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -17517,7 +17518,7 @@
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 	req_buf->RoamOffloadEnabled = csr_roamIsRoamOffloadEnabled(mac_ctx);
 	req_buf->RoamKeyMgmtOffloadEnabled = session->RoamKeyMgmtOffloadEnabled;
-	req_buf->okc_enabled = session->okc_enabled;
+	req_buf->pmkid_modes = session->pmkid_modes;
 	/* Roam Offload piggybacks upon the Roam Scan offload command. */
 	if (req_buf->RoamOffloadEnabled)
 		csr_update_roam_scan_offload_request(mac_ctx, req_buf, session);
diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h
index e2c2328..17ae441 100644
--- a/core/sme/src/csr/csr_inside_api.h
+++ b/core/sme/src/csr/csr_inside_api.h
@@ -777,7 +777,7 @@
 QDF_STATUS csr_roam_set_key_mgmt_offload(tpAniSirGlobal mac_ctx,
 					 uint32_t session_id,
 					 bool roam_key_mgmt_offload_enabled,
-					 bool okc_enabled);
+					 struct pmkid_mode_bits *pmkid_modes);
 #endif
 /* ---------------------------------------------------------------------------
     \fn csr_roam_get_wpa_rsn_req_ie
diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c
index 9016a23..3236274 100644
--- a/core/wma/src/wma_scan_roam.c
+++ b/core/wma/src/wma_scan_roam.c
@@ -809,7 +809,8 @@
 				roam_req->RoamKeyMgmtOffloadEnabled;
 		wma_roam_scan_fill_self_caps(wma_handle,
 			&params->roam_offload_params, roam_req);
-		params->okc_enabled = roam_req->okc_enabled;
+		params->fw_okc = roam_req->pmkid_modes.fw_okc;
+		params->fw_pmksa_cache = roam_req->pmkid_modes.fw_pmksa_cache;
 #endif
 		params->is_ese_assoc = roam_req->IsESEAssoc;
 		params->mdid.mdie_present = roam_req->MDID.mdiePresent;