iwlwifi: mvm: add WFA vendor specific TPC report IE to probe request
authorAvraham Stern <avraham.stern@intel.com>
Tue, 4 Jul 2017 07:05:15 +0000 (10:05 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Tue, 5 Dec 2017 19:01:39 +0000 (21:01 +0200)
Add the WFA vendor specific TPC report IE to probe requests
when it is not added by the FW. The FW will still need to set
the tx power field.

Signed-off-by: Avraham Stern <avraham.stern@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/mvm/scan.c

index e4fd476e9ccb0888d572ee296a4947c9fd3903ca..356b16f40e7849475e1715ab633ce52c36d5e898 100644 (file)
@@ -664,6 +664,22 @@ static u8 *iwl_mvm_copy_and_insert_ds_elem(struct iwl_mvm *mvm, const u8 *ies,
        return newpos;
 }
 
+#define WFA_TPC_IE_LEN 9
+
+static void iwl_mvm_add_tpc_report_ie(u8 *pos)
+{
+       pos[0] = WLAN_EID_VENDOR_SPECIFIC;
+       pos[1] = WFA_TPC_IE_LEN - 2;
+       pos[2] = (WLAN_OUI_MICROSOFT >> 16) & 0xff;
+       pos[3] = (WLAN_OUI_MICROSOFT >> 8) & 0xff;
+       pos[4] = WLAN_OUI_MICROSOFT & 0xff;
+       pos[5] = WLAN_OUI_TYPE_MICROSOFT_TPC;
+       pos[6] = 0;
+       /* pos[7] - tx power will be inserted by the FW */
+       pos[7] = 0;
+       pos[8] = 0;
+}
+
 static void
 iwl_mvm_build_scan_probe(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                         struct ieee80211_scan_ies *ies,
@@ -716,7 +732,16 @@ iwl_mvm_build_scan_probe(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 
        memcpy(pos, ies->common_ies, ies->common_ie_len);
        params->preq.common_data.offset = cpu_to_le16(pos - params->preq.buf);
-       params->preq.common_data.len = cpu_to_le16(ies->common_ie_len);
+
+       if (iwl_mvm_rrm_scan_needed(mvm) &&
+           !fw_has_capa(&mvm->fw->ucode_capa,
+                        IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT)) {
+               iwl_mvm_add_tpc_report_ie(pos + ies->common_ie_len);
+               params->preq.common_data.len = cpu_to_le16(ies->common_ie_len +
+                                                          WFA_TPC_IE_LEN);
+       } else {
+               params->preq.common_data.len = cpu_to_le16(ies->common_ie_len);
+       }
 }
 
 static void iwl_mvm_scan_lmac_dwell(struct iwl_mvm *mvm,
@@ -781,7 +806,9 @@ static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm,
        if (params->type == IWL_SCAN_TYPE_FRAGMENTED)
                flags |= IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED;
 
-       if (iwl_mvm_rrm_scan_needed(mvm))
+       if (iwl_mvm_rrm_scan_needed(mvm) &&
+           fw_has_capa(&mvm->fw->ucode_capa,
+                       IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT))
                flags |= IWL_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED;
 
        if (params->pass_all)
@@ -1183,7 +1210,9 @@ static u16 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm,
                        flags |= IWL_UMAC_SCAN_GEN_FLAGS_LMAC2_FRAGMENTED;
        }
 
-       if (iwl_mvm_rrm_scan_needed(mvm))
+       if (iwl_mvm_rrm_scan_needed(mvm) &&
+           fw_has_capa(&mvm->fw->ucode_capa,
+                       IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT))
                flags |= IWL_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED;
 
        if (params->pass_all)