qcacmn: Support adaptive 11R BSS in scan

Adaptive 11r is a feature by which the network supports 11r
even though the bss doesn't advertise 11r. This is done with the
help of advertising vendor specific adaptive 11r IE and MD IE
in the beacon/probe. When vendor specific adaptive 11r
IE (oui 0x00 40 96 type 0x2C) is present in the beacon/probe,
and 1st bit of the IE data is  set to 1, then the BSS supports
adaptive 11r.

The BSS advertises, non-11r akm in RSN IE and user space will
send the 11r akm in the connect start. So the scan module
shouldn't filter out the candidate adaptive 11r supported BSS
with AKM mismatch reason.

Add changes in scan module to parse the Vendor specific adaptive
11r IE and copy it to the scan_entry ie_list. Check if
negotiated akm is non-11r akm, and the filter akm sent from csr
is a 11r akm (which is received from user space), then mark the
bss as matching.

Change-Id: I65f32c67016ad634f1592a7453e77aaf0c5a327c
CRs-Fixed: 2431074
diff --git a/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/umac/scan/dispatcher/src/wlan_scan_utils_api.c
index e9049fe..75da0cc 100644
--- a/umac/scan/dispatcher/src/wlan_scan_utils_api.c
+++ b/umac/scan/dispatcher/src/wlan_scan_utils_api.c
@@ -471,6 +471,13 @@
 		scan_params->ie_list.mbo_oce = (uint8_t *)ie;
 	} else if (is_extender_oui((uint8_t *)ie)) {
 		scan_params->ie_list.extender = (uint8_t *)ie;
+	} else if (is_adaptive_11r_oui((uint8_t *)ie)) {
+		if ((ie->ie_len < OUI_LENGTH) ||
+		    (ie->ie_len > MAX_ADAPTIVE_11R_IE_LEN))
+			return QDF_STATUS_E_INVAL;
+
+		scan_params->ie_list.adaptive_11r = (uint8_t *)ie +
+						sizeof(struct ie_header);
 	}
 	return QDF_STATUS_SUCCESS;
 }
@@ -977,6 +984,36 @@
 	return QDF_STATUS_SUCCESS;
 }
 #endif /* WLAN_DFS_CHAN_HIDDEN_SSID */
+
+#ifdef WLAN_ADAPTIVE_11R
+/**
+ * scm_fill_adaptive_11r_cap() - Check if the AP supports adaptive 11r
+ * @scan_entry: Pointer to the scan entry
+ *
+ * Return: true if adaptive 11r is advertised else false
+ */
+static void scm_fill_adaptive_11r_cap(struct scan_cache_entry *scan_entry)
+{
+	uint8_t *ie;
+	uint8_t data;
+	bool adaptive_11r;
+
+	ie = util_scan_entry_adaptive_11r(scan_entry);
+	if (!ie)
+		return;
+
+	data = *(ie + OUI_LENGTH);
+	adaptive_11r = (data & 0x1) ? true : false;
+
+	scan_entry->adaptive_11r_ap = adaptive_11r;
+}
+#else
+static void scm_fill_adaptive_11r_cap(struct scan_cache_entry *scan_entry)
+{
+	scan_entry->adaptive_11r_ap = false;
+}
+#endif
+
 static QDF_STATUS
 util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev,
 			 uint8_t *frame, qdf_size_t frame_len,
@@ -1114,6 +1151,8 @@
 		scan_entry->phy_mode = util_scan_get_phymode_2g(scan_entry);
 
 	scan_entry->nss = util_scan_scm_calc_nss_supported_by_ap(scan_entry);
+	scm_fill_adaptive_11r_cap(scan_entry);
+
 	util_scan_scm_update_bss_with_esp_data(scan_entry);
 	qbss_load = (struct qbss_load_ie *)
 			util_scan_entry_qbssload(scan_entry);