summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
authorAndrei Otcheretianski <andrei.otcheretianski@intel.com>2014-09-02 18:55:40 +0400
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2014-11-23 20:57:29 +0300
commit66dc527296d8b3061cb7368927b5233f886c6f83 (patch)
treef728b6ea4f75128d84524d6e9d81deed6a561e4d /drivers/net/wireless/iwlwifi
parentaeb8f932080d62cdc305a7ccca9d60de34908b30 (diff)
downloadlinux-66dc527296d8b3061cb7368927b5233f886c6f83.tar.xz
iwlwifi: mvm: Insert DS Parameter Set placeholder in probes
Since it's too complicated for the fw to insert a DS Parameter Set element in the middle of the frame, it was decided that it should be done by the host. The fw will only parse the frame and update the current channel field. Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw.h4
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/scan.c53
2 files changed, 50 insertions, 7 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
index 6f7ae5f7bdae..598065b053de 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -148,8 +148,8 @@ enum iwl_ucode_tlv_api {
* @IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT: supports insertion of current
* tx power value into TPC Report action frame and Link Measurement Report
* action frame
- * @IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT: supports adding DS params
- * element in probe requests.
+ * @IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT: supports updating current
+ * channel in DS parameter set element in probe requests.
* @IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT: supports adding TPC Report IE in
* probe requests.
* @IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT: supports Quiet Period requests
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c
index fb2a8628b8fc..8a1f4a8e80e7 100644
--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
@@ -366,6 +366,10 @@ static int iwl_mvm_max_scan_ie_fw_cmd_room(struct iwl_mvm *mvm,
!is_sched_scan)
max_probe_len -= 32;
+ /* DS parameter set element is added on 2.4GHZ band if required */
+ if (iwl_mvm_rrm_scan_needed(mvm))
+ max_probe_len -= 3;
+
return max_probe_len;
}
@@ -1155,6 +1159,42 @@ iwl_mvm_lmac_scan_cfg_channels(struct iwl_mvm *mvm,
}
}
+static u8 *iwl_mvm_copy_and_insert_ds_elem(struct iwl_mvm *mvm, const u8 *ies,
+ size_t len, u8 *const pos)
+{
+ static const u8 before_ds_params[] = {
+ WLAN_EID_SSID,
+ WLAN_EID_SUPP_RATES,
+ WLAN_EID_REQUEST,
+ WLAN_EID_EXT_SUPP_RATES,
+ };
+ size_t offs;
+ u8 *newpos = pos;
+
+ if (!iwl_mvm_rrm_scan_needed(mvm)) {
+ memcpy(newpos, ies, len);
+ return newpos + len;
+ }
+
+ offs = ieee80211_ie_split(ies, len,
+ before_ds_params,
+ ARRAY_SIZE(before_ds_params),
+ 0);
+
+ memcpy(newpos, ies, offs);
+ newpos += offs;
+
+ /* Add a placeholder for DS Parameter Set element */
+ *newpos++ = WLAN_EID_DS_PARAMS;
+ *newpos++ = 1;
+ *newpos++ = 0;
+
+ memcpy(newpos, ies + offs, len - offs);
+ newpos += len - offs;
+
+ return newpos;
+}
+
static void
iwl_mvm_build_unified_scan_probe(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_scan_ies *ies,
@@ -1164,7 +1204,7 @@ iwl_mvm_build_unified_scan_probe(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
sizeof(struct iwl_scan_channel_cfg_lmac) *
mvm->fw->ucode_capa.n_scan_channels);
struct ieee80211_mgmt *frame = (struct ieee80211_mgmt *)preq->buf;
- u8 *pos;
+ u8 *pos, *newpos;
frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
eth_broadcast_addr(frame->da);
@@ -1179,11 +1219,14 @@ iwl_mvm_build_unified_scan_probe(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
preq->mac_header.offset = 0;
preq->mac_header.len = cpu_to_le16(24 + 2);
- memcpy(pos, ies->ies[IEEE80211_BAND_2GHZ],
- ies->len[IEEE80211_BAND_2GHZ]);
+ /* Insert ds parameter set element on 2.4 GHz band */
+ newpos = iwl_mvm_copy_and_insert_ds_elem(mvm,
+ ies->ies[IEEE80211_BAND_2GHZ],
+ ies->len[IEEE80211_BAND_2GHZ],
+ pos);
preq->band_data[0].offset = cpu_to_le16(pos - preq->buf);
- preq->band_data[0].len = cpu_to_le16(ies->len[IEEE80211_BAND_2GHZ]);
- pos += ies->len[IEEE80211_BAND_2GHZ];
+ preq->band_data[0].len = cpu_to_le16(newpos - pos);
+ pos = newpos;
memcpy(pos, ies->ies[IEEE80211_BAND_5GHZ],
ies->len[IEEE80211_BAND_5GHZ]);