summaryrefslogtreecommitdiff
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c102
1 files changed, 67 insertions, 35 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 32f1bc5908c5..0c46009a3d63 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1756,7 +1756,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
bool sched_scan_stopped = false;
bool suspended = local->suspended;
bool in_reconfig = false;
- u32 rts_threshold;
lockdep_assert_wiphy(local->hw.wiphy);
@@ -1832,7 +1831,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
/* setup RTS threshold */
if (hw->wiphy->n_radio > 0) {
for (i = 0; i < hw->wiphy->n_radio; i++) {
- rts_threshold = hw->wiphy->radio_cfg[i].rts_threshold;
+ u32 rts_threshold =
+ hw->wiphy->radio_cfg[i].rts_threshold;
+
drv_set_rts_threshold(local, i, rts_threshold);
}
} else {
@@ -2205,9 +2206,10 @@ int ieee80211_reconfig(struct ieee80211_local *local)
}
}
+ /* Passing NULL means an interface is picked for configuration */
if (local->virt_monitors > 0 &&
local->virt_monitors == local->open_count)
- ieee80211_add_virtual_monitor(local);
+ ieee80211_add_virtual_monitor(local, NULL);
if (!suspended)
return 0;
@@ -2346,7 +2348,7 @@ void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata,
chanctx = container_of(chanctx_conf, struct ieee80211_chanctx,
conf);
- ieee80211_recalc_chanctx_min_def(local, chanctx, NULL, false);
+ ieee80211_recalc_chanctx_min_def(local, chanctx);
}
}
@@ -3198,10 +3200,11 @@ bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_local *local,
return true;
}
-bool ieee80211_chandef_s1g_oper(const struct ieee80211_s1g_oper_ie *oper,
+bool ieee80211_chandef_s1g_oper(struct ieee80211_local *local,
+ const struct ieee80211_s1g_oper_ie *oper,
struct cfg80211_chan_def *chandef)
{
- u32 oper_freq;
+ u32 oper_khz, pri_1mhz_khz, pri_2mhz_khz;
if (!oper)
return false;
@@ -3226,12 +3229,36 @@ bool ieee80211_chandef_s1g_oper(const struct ieee80211_s1g_oper_ie *oper,
return false;
}
- oper_freq = ieee80211_channel_to_freq_khz(oper->oper_ch,
- NL80211_BAND_S1GHZ);
- chandef->center_freq1 = KHZ_TO_MHZ(oper_freq);
- chandef->freq1_offset = oper_freq % 1000;
+ chandef->s1g_primary_2mhz = false;
- return true;
+ switch (u8_get_bits(oper->ch_width, S1G_OPER_CH_WIDTH_PRIMARY)) {
+ case IEEE80211_S1G_PRI_CHANWIDTH_1MHZ:
+ pri_1mhz_khz = ieee80211_channel_to_freq_khz(
+ oper->primary_ch, NL80211_BAND_S1GHZ);
+ break;
+ case IEEE80211_S1G_PRI_CHANWIDTH_2MHZ:
+ chandef->s1g_primary_2mhz = true;
+ pri_2mhz_khz = ieee80211_channel_to_freq_khz(
+ oper->primary_ch, NL80211_BAND_S1GHZ);
+
+ if (u8_get_bits(oper->ch_width, S1G_OPER_CH_PRIMARY_LOCATION) ==
+ S1G_2M_PRIMARY_LOCATION_LOWER)
+ pri_1mhz_khz = pri_2mhz_khz - 500;
+ else
+ pri_1mhz_khz = pri_2mhz_khz + 500;
+ break;
+ default:
+ return false;
+ }
+
+ oper_khz = ieee80211_channel_to_freq_khz(oper->oper_ch,
+ NL80211_BAND_S1GHZ);
+ chandef->center_freq1 = KHZ_TO_MHZ(oper_khz);
+ chandef->freq1_offset = oper_khz % 1000;
+ chandef->chan =
+ ieee80211_get_channel_khz(local->hw.wiphy, pri_1mhz_khz);
+
+ return chandef->chan;
}
int ieee80211_put_srates_elem(struct sk_buff *skb,
@@ -3990,23 +4017,23 @@ static u8 ieee80211_chanctx_radar_detect(struct ieee80211_local *local,
if (WARN_ON(ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED))
return 0;
- list_for_each_entry(link, &ctx->reserved_links, reserved_chanctx_list)
- if (link->reserved_radar_required)
- radar_detect |= BIT(link->reserved.oper.width);
-
- /*
- * An in-place reservation context should not have any assigned vifs
- * until it replaces the other context.
- */
- WARN_ON(ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER &&
- !list_empty(&ctx->assigned_links));
+ for_each_sdata_link(local, link) {
+ if (rcu_access_pointer(link->conf->chanctx_conf) == &ctx->conf) {
+ /*
+ * An in-place reservation context should not have any
+ * assigned links until it replaces the other context.
+ */
+ WARN_ON(ctx->replace_state ==
+ IEEE80211_CHANCTX_REPLACES_OTHER);
- list_for_each_entry(link, &ctx->assigned_links, assigned_chanctx_list) {
- if (!link->radar_required)
- continue;
+ if (link->radar_required)
+ radar_detect |=
+ BIT(link->conf->chanreq.oper.width);
+ }
- radar_detect |=
- BIT(link->conf->chanreq.oper.width);
+ if (link->reserved_chanctx == ctx &&
+ link->reserved_radar_required)
+ radar_detect |= BIT(link->reserved.oper.width);
}
return radar_detect;
@@ -4022,16 +4049,13 @@ bool ieee80211_is_radio_idx_in_scan_req(struct wiphy *wiphy,
for (i = 0; i < scan_req->n_channels; i++) {
chan = scan_req->channels[i];
chan_radio_idx = cfg80211_get_radio_idx_by_chan(wiphy, chan);
- /*
- * The chan_radio_idx should be valid since it's taken from a
- * valid scan request.
- * However, if chan_radio_idx is unexpectedly invalid (negative),
- * we take a conservative approach and assume the scan request
- * might use the specified radio_idx. Hence, return true.
- */
- if (WARN_ON(chan_radio_idx < 0))
- return true;
+ /* The radio index either matched successfully, or an error
+ * occurred. For example, if radio-level information is
+ * missing, the same error value is returned. This
+ * typically implies a single-radio setup, in which case
+ * the operation should not be allowed.
+ */
if (chan_radio_idx == radio_idx)
return true;
}
@@ -4514,3 +4538,11 @@ void ieee80211_clear_tpe(struct ieee80211_parsed_tpe *tpe)
sizeof(tpe->psd_reg_client[i].power));
}
}
+
+bool ieee80211_vif_nan_started(struct ieee80211_vif *vif)
+{
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+
+ return vif->type == NL80211_IFTYPE_NAN && sdata->u.nan.started;
+}
+EXPORT_SYMBOL_GPL(ieee80211_vif_nan_started);