Commit 2ad2274c authored by Ilan Peer's avatar Ilan Peer Committed by Johannes Berg

mac80211: Add HE 6GHz capabilities element to probe request

On 6 GHz, the 6 GHz capabilities element should be added, do that.
Signed-off-by: default avatarIlan Peer <ilan.peer@intel.com>
[add commit message]
Link: https://lore.kernel.org/r/20200528213443.8ee764f0cde0.I2b0c66b60e11818c97c9803e04a6a197c6376243@changeidSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 1bb9a8a4
...@@ -512,6 +512,26 @@ ieee80211_get_he_sta_cap(const struct ieee80211_supported_band *sband) ...@@ -512,6 +512,26 @@ ieee80211_get_he_sta_cap(const struct ieee80211_supported_band *sband)
return ieee80211_get_he_iftype_cap(sband, NL80211_IFTYPE_STATION); return ieee80211_get_he_iftype_cap(sband, NL80211_IFTYPE_STATION);
} }
/**
* ieee80211_get_he_6ghz_capa - return HE 6 GHz capabilities
* @sband: the sband to search for the STA on
* @iftype: the iftype to search for
*
* Return: the 6GHz capabilities
*/
static inline __le16
ieee80211_get_he_6ghz_capa(const struct ieee80211_supported_band *sband,
enum nl80211_iftype iftype)
{
const struct ieee80211_sband_iftype_data *data =
ieee80211_get_sband_iftype_data(sband, iftype);
if (WARN_ON(!data || !data->he_cap.has_he))
return 0;
return data->he_6ghz_capa.capa;
}
/** /**
* wiphy_read_of_freq_limits - read frequency limits from device tree * wiphy_read_of_freq_limits - read frequency limits from device tree
* *
......
...@@ -2144,7 +2144,7 @@ enum { ...@@ -2144,7 +2144,7 @@ enum {
IEEE80211_PROBE_FLAG_RANDOM_SN = BIT(2), IEEE80211_PROBE_FLAG_RANDOM_SN = BIT(2),
}; };
int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, int ieee80211_build_preq_ies(struct ieee80211_sub_if_data *sdata, u8 *buffer,
size_t buffer_len, size_t buffer_len,
struct ieee80211_scan_ies *ie_desc, struct ieee80211_scan_ies *ie_desc,
const u8 *ie, size_t ie_len, const u8 *ie, size_t ie_len,
......
...@@ -313,8 +313,9 @@ ieee80211_prepare_scan_chandef(struct cfg80211_chan_def *chandef, ...@@ -313,8 +313,9 @@ ieee80211_prepare_scan_chandef(struct cfg80211_chan_def *chandef,
} }
/* return false if no more work */ /* return false if no more work */
static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) static bool ieee80211_prep_hw_scan(struct ieee80211_sub_if_data *sdata)
{ {
struct ieee80211_local *local = sdata->local;
struct cfg80211_scan_request *req; struct cfg80211_scan_request *req;
struct cfg80211_chan_def chandef; struct cfg80211_chan_def chandef;
u8 bands_used = 0; u8 bands_used = 0;
...@@ -361,7 +362,7 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) ...@@ -361,7 +362,7 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
if (req->flags & NL80211_SCAN_FLAG_MIN_PREQ_CONTENT) if (req->flags & NL80211_SCAN_FLAG_MIN_PREQ_CONTENT)
flags |= IEEE80211_PROBE_FLAG_MIN_CONTENT; flags |= IEEE80211_PROBE_FLAG_MIN_CONTENT;
ielen = ieee80211_build_preq_ies(local, ielen = ieee80211_build_preq_ies(sdata,
(u8 *)local->hw_scan_req->req.ie, (u8 *)local->hw_scan_req->req.ie,
local->hw_scan_ies_bufsize, local->hw_scan_ies_bufsize,
&local->hw_scan_req->ies, &local->hw_scan_req->ies,
...@@ -401,9 +402,12 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) ...@@ -401,9 +402,12 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
if (WARN_ON(!local->scan_req)) if (WARN_ON(!local->scan_req))
return; return;
scan_sdata = rcu_dereference_protected(local->scan_sdata,
lockdep_is_held(&local->mtx));
if (hw_scan && !aborted && if (hw_scan && !aborted &&
!ieee80211_hw_check(&local->hw, SINGLE_SCAN_ON_ALL_BANDS) && !ieee80211_hw_check(&local->hw, SINGLE_SCAN_ON_ALL_BANDS) &&
ieee80211_prep_hw_scan(local)) { ieee80211_prep_hw_scan(scan_sdata)) {
int rc; int rc;
rc = drv_hw_scan(local, rc = drv_hw_scan(local,
...@@ -432,9 +436,6 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) ...@@ -432,9 +436,6 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
cfg80211_scan_done(scan_req, &local->scan_info); cfg80211_scan_done(scan_req, &local->scan_info);
} }
RCU_INIT_POINTER(local->scan_req, NULL); RCU_INIT_POINTER(local->scan_req, NULL);
scan_sdata = rcu_dereference_protected(local->scan_sdata,
lockdep_is_held(&local->mtx));
RCU_INIT_POINTER(local->scan_sdata, NULL); RCU_INIT_POINTER(local->scan_sdata, NULL);
local->scanning = 0; local->scanning = 0;
...@@ -776,7 +777,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, ...@@ -776,7 +777,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
ieee80211_recalc_idle(local); ieee80211_recalc_idle(local);
if (hw_scan) { if (hw_scan) {
WARN_ON(!ieee80211_prep_hw_scan(local)); WARN_ON(!ieee80211_prep_hw_scan(sdata));
rc = drv_hw_scan(local, sdata, local->hw_scan_req); rc = drv_hw_scan(local, sdata, local->hw_scan_req);
} else { } else {
rc = ieee80211_start_sw_scan(local, sdata); rc = ieee80211_start_sw_scan(local, sdata);
...@@ -1274,7 +1275,7 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, ...@@ -1274,7 +1275,7 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
ieee80211_prepare_scan_chandef(&chandef, req->scan_width); ieee80211_prepare_scan_chandef(&chandef, req->scan_width);
ieee80211_build_preq_ies(local, ie, num_bands * iebufsz, ieee80211_build_preq_ies(sdata, ie, num_bands * iebufsz,
&sched_scan_ies, req->ie, &sched_scan_ies, req->ie,
req->ie_len, bands_used, rate_masks, &chandef, req->ie_len, bands_used, rate_masks, &chandef,
flags); flags);
......
...@@ -1663,7 +1663,20 @@ void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, ...@@ -1663,7 +1663,20 @@ void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
} }
} }
static int ieee80211_build_preq_ies_band(struct ieee80211_local *local, static u8 *ieee80211_write_he_6ghz_cap(u8 *pos, __le16 cap, u8 *end)
{
if ((end - pos) < 5)
return pos;
*pos++ = WLAN_EID_EXTENSION;
*pos++ = 1 + sizeof(cap);
*pos++ = WLAN_EID_EXT_HE_6GHZ_CAPA;
memcpy(pos, &cap, sizeof(cap));
return pos + 2;
}
static int ieee80211_build_preq_ies_band(struct ieee80211_sub_if_data *sdata,
u8 *buffer, size_t buffer_len, u8 *buffer, size_t buffer_len,
const u8 *ie, size_t ie_len, const u8 *ie, size_t ie_len,
enum nl80211_band band, enum nl80211_band band,
...@@ -1671,6 +1684,7 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local, ...@@ -1671,6 +1684,7 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local,
struct cfg80211_chan_def *chandef, struct cfg80211_chan_def *chandef,
size_t *offset, u32 flags) size_t *offset, u32 flags)
{ {
struct ieee80211_local *local = sdata->local;
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
const struct ieee80211_sta_he_cap *he_cap; const struct ieee80211_sta_he_cap *he_cap;
u8 *pos = buffer, *end = buffer + buffer_len; u8 *pos = buffer, *end = buffer + buffer_len;
...@@ -1848,6 +1862,14 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local, ...@@ -1848,6 +1862,14 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local,
pos = ieee80211_ie_build_he_cap(pos, he_cap, end); pos = ieee80211_ie_build_he_cap(pos, he_cap, end);
if (!pos) if (!pos)
goto out_err; goto out_err;
if (sband->band == NL80211_BAND_6GHZ) {
enum nl80211_iftype iftype =
ieee80211_vif_type_p2p(&sdata->vif);
__le16 cap = ieee80211_get_he_6ghz_capa(sband, iftype);
pos = ieee80211_write_he_6ghz_cap(pos, cap, end);
}
} }
/* /*
...@@ -1862,7 +1884,7 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local, ...@@ -1862,7 +1884,7 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local,
return pos - buffer; return pos - buffer;
} }
int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, int ieee80211_build_preq_ies(struct ieee80211_sub_if_data *sdata, u8 *buffer,
size_t buffer_len, size_t buffer_len,
struct ieee80211_scan_ies *ie_desc, struct ieee80211_scan_ies *ie_desc,
const u8 *ie, size_t ie_len, const u8 *ie, size_t ie_len,
...@@ -1877,7 +1899,7 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, ...@@ -1877,7 +1899,7 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
for (i = 0; i < NUM_NL80211_BANDS; i++) { for (i = 0; i < NUM_NL80211_BANDS; i++) {
if (bands_used & BIT(i)) { if (bands_used & BIT(i)) {
pos += ieee80211_build_preq_ies_band(local, pos += ieee80211_build_preq_ies_band(sdata,
buffer + pos, buffer + pos,
buffer_len - pos, buffer_len - pos,
ie, ie_len, i, ie, ie_len, i,
...@@ -1939,7 +1961,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, ...@@ -1939,7 +1961,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
return NULL; return NULL;
rate_masks[chan->band] = ratemask; rate_masks[chan->band] = ratemask;
ies_len = ieee80211_build_preq_ies(local, skb_tail_pointer(skb), ies_len = ieee80211_build_preq_ies(sdata, skb_tail_pointer(skb),
skb_tailroom(skb), &dummy_ie_desc, skb_tailroom(skb), &dummy_ie_desc,
ie, ie_len, BIT(chan->band), ie, ie_len, BIT(chan->band),
rate_masks, &chandef, flags); rate_masks, &chandef, flags);
...@@ -2879,10 +2901,8 @@ void ieee80211_ie_build_he_6ghz_cap(struct ieee80211_sub_if_data *sdata, ...@@ -2879,10 +2901,8 @@ void ieee80211_ie_build_he_6ghz_cap(struct ieee80211_sub_if_data *sdata,
} }
pos = skb_put(skb, 2 + 1 + sizeof(cap)); pos = skb_put(skb, 2 + 1 + sizeof(cap));
*pos++ = WLAN_EID_EXTENSION; ieee80211_write_he_6ghz_cap(pos, cpu_to_le16(cap),
*pos++ = 1 + sizeof(cap); pos + 2 + 1 + sizeof(cap));
*pos++ = WLAN_EID_EXT_HE_6GHZ_CAPA;
put_unaligned_le16(cap, pos);
} }
u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment