2019-05-19 05:08:55 -07:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
cfg80211/mac80211: better channel handling
Currently (all tested with hwsim) you can do stupid
things like setting up an AP on a certain channel,
then adding another virtual interface and making
that associate on another channel -- this will make
the beaconing to move channel but obviously without
the necessary IEs data update.
In order to improve this situation, first make the
configuration APIs (cfg80211 and nl80211) aware of
multi-channel operation -- we'll eventually need
that in the future anyway. There's one userland API
change and one API addition. The API change is that
now SET_WIPHY must be called with virtual interface
index rather than only wiphy index in order to take
effect for that interface -- luckily all current
users (hostapd) do that. For monitor interfaces, the
old setting is preserved, but monitors are always
slaved to other devices anyway so no guarantees.
The second userland API change is the introduction
of a per virtual interface SET_CHANNEL command, that
hostapd should use going forward to make it easier
to understand what's going on (it can automatically
detect a kernel with this command).
Other than mac80211, no existing cfg80211 drivers
are affected by this change because they only allow
a single virtual interface.
mac80211, however, now needs to be aware that the
channel settings are per interface now, and needs
to disallow (for now) real multi-channel operation,
which is another important part of this patch.
One of the immediate benefits is that you can now
start hostapd to operate on a hardware that already
has a connection on another virtual interface, as
long as you specify the same channel.
Note that two things are left unhandled (this is an
improvement -- not a complete fix):
* different HT/no-HT modes
currently you could start an HT AP and then
connect to a non-HT network on the same channel
which would configure the hardware for no HT;
that can be fixed fairly easily
* CSA
An AP we're connected to on a virtual interface
might indicate switching channels, and in that
case we would follow it, regardless of how many
other interfaces are operating; this requires
more effort to fix but is pretty rare after all
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2010-05-05 06:25:02 -07:00
|
|
|
/*
|
|
|
|
* mac80211 - channel management
|
2024-01-29 11:34:49 -07:00
|
|
|
* Copyright 2020 - 2024 Intel Corporation
|
cfg80211/mac80211: better channel handling
Currently (all tested with hwsim) you can do stupid
things like setting up an AP on a certain channel,
then adding another virtual interface and making
that associate on another channel -- this will make
the beaconing to move channel but obviously without
the necessary IEs data update.
In order to improve this situation, first make the
configuration APIs (cfg80211 and nl80211) aware of
multi-channel operation -- we'll eventually need
that in the future anyway. There's one userland API
change and one API addition. The API change is that
now SET_WIPHY must be called with virtual interface
index rather than only wiphy index in order to take
effect for that interface -- luckily all current
users (hostapd) do that. For monitor interfaces, the
old setting is preserved, but monitors are always
slaved to other devices anyway so no guarantees.
The second userland API change is the introduction
of a per virtual interface SET_CHANNEL command, that
hostapd should use going forward to make it easier
to understand what's going on (it can automatically
detect a kernel with this command).
Other than mac80211, no existing cfg80211 drivers
are affected by this change because they only allow
a single virtual interface.
mac80211, however, now needs to be aware that the
channel settings are per interface now, and needs
to disallow (for now) real multi-channel operation,
which is another important part of this patch.
One of the immediate benefits is that you can now
start hostapd to operate on a hardware that already
has a connection on another virtual interface, as
long as you specify the same channel.
Note that two things are left unhandled (this is an
improvement -- not a complete fix):
* different HT/no-HT modes
currently you could start an HT AP and then
connect to a non-HT network on the same channel
which would configure the hardware for no HT;
that can be fixed fairly easily
* CSA
An AP we're connected to on a virtual interface
might indicate switching channels, and in that
case we would follow it, regardless of how many
other interfaces are operating; this requires
more effort to fix but is pretty rare after all
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2010-05-05 06:25:02 -07:00
|
|
|
*/
|
|
|
|
|
2010-05-05 06:28:27 -07:00
|
|
|
#include <linux/nl80211.h>
|
2012-09-11 08:57:42 -07:00
|
|
|
#include <linux/export.h>
|
2012-12-11 12:38:41 -07:00
|
|
|
#include <linux/rtnetlink.h>
|
mac80211: Don't let regulatory make us deaf
When regulatory information changes our HT behavior (e.g,
when we get a country code from the AP we have just associated
with), we should use this information to change the power with
which we transmit, and what channels we transmit. Sometimes
the channel parameters we derive from regulatory information
contradicts the parameters we used in association. For example,
we could have associated specifying HT40, but the regulatory
rules we apply may forbid HT40 operation.
In the situation above, we should reconfigure ourselves to
transmit in HT20 only, however it makes no sense for us to
disable receive in HT40, since if we associated with these
parameters, the AP has every reason to expect we can and
will receive packets this way. The code in mac80211 does
not have the capability of sending the appropriate action
frames to signal a change in HT behaviour so the AP has
no clue we can no longer receive frames encoded this way.
In some broken AP implementations, this can leave us
effectively deaf if the AP never retries in lower HT rates.
This change breaks up the channel_type parameter in the
ieee80211_enable_ht function into a separate receive and
transmit part. It honors the channel flags set by regulatory
in order to configure the rate control algorithm, but uses
the capability flags to configure the channel on the radio,
since these were used in association to set the AP's transmit
rate.
Signed-off-by: Paul Stewart <pstew@chromium.org>
Cc: Sam Leffler <sleffler@chromium.org>
Cc: Johannes Berg <johannes@sipsolutions.net>
Reviewed-by: Luis R Rodriguez <mcgrof@frijolero.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2012-03-13 07:46:18 -07:00
|
|
|
#include <net/cfg80211.h>
|
cfg80211/mac80211: better channel handling
Currently (all tested with hwsim) you can do stupid
things like setting up an AP on a certain channel,
then adding another virtual interface and making
that associate on another channel -- this will make
the beaconing to move channel but obviously without
the necessary IEs data update.
In order to improve this situation, first make the
configuration APIs (cfg80211 and nl80211) aware of
multi-channel operation -- we'll eventually need
that in the future anyway. There's one userland API
change and one API addition. The API change is that
now SET_WIPHY must be called with virtual interface
index rather than only wiphy index in order to take
effect for that interface -- luckily all current
users (hostapd) do that. For monitor interfaces, the
old setting is preserved, but monitors are always
slaved to other devices anyway so no guarantees.
The second userland API change is the introduction
of a per virtual interface SET_CHANNEL command, that
hostapd should use going forward to make it easier
to understand what's going on (it can automatically
detect a kernel with this command).
Other than mac80211, no existing cfg80211 drivers
are affected by this change because they only allow
a single virtual interface.
mac80211, however, now needs to be aware that the
channel settings are per interface now, and needs
to disallow (for now) real multi-channel operation,
which is another important part of this patch.
One of the immediate benefits is that you can now
start hostapd to operate on a hardware that already
has a connection on another virtual interface, as
long as you specify the same channel.
Note that two things are left unhandled (this is an
improvement -- not a complete fix):
* different HT/no-HT modes
currently you could start an HT AP and then
connect to a non-HT network on the same channel
which would configure the hardware for no HT;
that can be fixed fairly easily
* CSA
An AP we're connected to on a virtual interface
might indicate switching channels, and in that
case we would follow it, regardless of how many
other interfaces are operating; this requires
more effort to fix but is pretty rare after all
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2010-05-05 06:25:02 -07:00
|
|
|
#include "ieee80211_i.h"
|
2012-06-26 05:37:20 -07:00
|
|
|
#include "driver-ops.h"
|
2020-12-06 05:54:50 -07:00
|
|
|
#include "rate.h"
|
cfg80211/mac80211: better channel handling
Currently (all tested with hwsim) you can do stupid
things like setting up an AP on a certain channel,
then adding another virtual interface and making
that associate on another channel -- this will make
the beaconing to move channel but obviously without
the necessary IEs data update.
In order to improve this situation, first make the
configuration APIs (cfg80211 and nl80211) aware of
multi-channel operation -- we'll eventually need
that in the future anyway. There's one userland API
change and one API addition. The API change is that
now SET_WIPHY must be called with virtual interface
index rather than only wiphy index in order to take
effect for that interface -- luckily all current
users (hostapd) do that. For monitor interfaces, the
old setting is preserved, but monitors are always
slaved to other devices anyway so no guarantees.
The second userland API change is the introduction
of a per virtual interface SET_CHANNEL command, that
hostapd should use going forward to make it easier
to understand what's going on (it can automatically
detect a kernel with this command).
Other than mac80211, no existing cfg80211 drivers
are affected by this change because they only allow
a single virtual interface.
mac80211, however, now needs to be aware that the
channel settings are per interface now, and needs
to disallow (for now) real multi-channel operation,
which is another important part of this patch.
One of the immediate benefits is that you can now
start hostapd to operate on a hardware that already
has a connection on another virtual interface, as
long as you specify the same channel.
Note that two things are left unhandled (this is an
improvement -- not a complete fix):
* different HT/no-HT modes
currently you could start an HT AP and then
connect to a non-HT network on the same channel
which would configure the hardware for no HT;
that can be fixed fairly easily
* CSA
An AP we're connected to on a virtual interface
might indicate switching channels, and in that
case we would follow it, regardless of how many
other interfaces are operating; this requires
more effort to fix but is pretty rare after all
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2010-05-05 06:25:02 -07:00
|
|
|
|
2014-04-09 06:29:33 -07:00
|
|
|
static int ieee80211_chanctx_num_assigned(struct ieee80211_local *local,
|
|
|
|
struct ieee80211_chanctx *ctx)
|
|
|
|
{
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_link_data *link;
|
2014-04-09 06:29:33 -07:00
|
|
|
int num = 0;
|
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2014-04-09 06:29:33 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
list_for_each_entry(link, &ctx->assigned_links, assigned_chanctx_list)
|
2014-04-09 06:29:33 -07:00
|
|
|
num++;
|
|
|
|
|
|
|
|
return num;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ieee80211_chanctx_num_reserved(struct ieee80211_local *local,
|
|
|
|
struct ieee80211_chanctx *ctx)
|
|
|
|
{
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_link_data *link;
|
2014-04-09 06:29:33 -07:00
|
|
|
int num = 0;
|
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2014-04-09 06:29:33 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
list_for_each_entry(link, &ctx->reserved_links, reserved_chanctx_list)
|
2014-04-09 06:29:33 -07:00
|
|
|
num++;
|
|
|
|
|
|
|
|
return num;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ieee80211_chanctx_refcount(struct ieee80211_local *local,
|
|
|
|
struct ieee80211_chanctx *ctx)
|
|
|
|
{
|
|
|
|
return ieee80211_chanctx_num_assigned(local, ctx) +
|
|
|
|
ieee80211_chanctx_num_reserved(local, ctx);
|
|
|
|
}
|
|
|
|
|
2024-07-09 01:38:35 -07:00
|
|
|
static int ieee80211_num_chanctx(struct ieee80211_local *local, int radio_idx)
|
2014-04-09 06:29:24 -07:00
|
|
|
{
|
|
|
|
struct ieee80211_chanctx *ctx;
|
|
|
|
int num = 0;
|
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2014-04-09 06:29:24 -07:00
|
|
|
|
2024-07-09 01:38:35 -07:00
|
|
|
list_for_each_entry(ctx, &local->chanctx_list, list) {
|
|
|
|
if (radio_idx >= 0 && ctx->conf.radio_idx != radio_idx)
|
|
|
|
continue;
|
2014-04-09 06:29:24 -07:00
|
|
|
num++;
|
2024-07-09 01:38:35 -07:00
|
|
|
}
|
2014-04-09 06:29:24 -07:00
|
|
|
|
|
|
|
return num;
|
|
|
|
}
|
|
|
|
|
2024-07-09 01:38:35 -07:00
|
|
|
static bool ieee80211_can_create_new_chanctx(struct ieee80211_local *local,
|
|
|
|
int radio_idx)
|
2014-04-09 06:29:24 -07:00
|
|
|
{
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
|
|
|
|
2024-07-09 01:38:35 -07:00
|
|
|
return ieee80211_num_chanctx(local, radio_idx) <
|
|
|
|
ieee80211_max_num_channels(local, radio_idx);
|
2014-04-09 06:29:24 -07:00
|
|
|
}
|
|
|
|
|
2014-06-25 03:35:06 -07:00
|
|
|
static struct ieee80211_chanctx *
|
2022-06-17 13:36:37 -07:00
|
|
|
ieee80211_link_get_chanctx(struct ieee80211_link_data *link)
|
2014-06-25 03:35:06 -07:00
|
|
|
{
|
2022-06-17 13:36:37 -07:00
|
|
|
struct ieee80211_local *local __maybe_unused = link->sdata->local;
|
2014-06-25 03:35:06 -07:00
|
|
|
struct ieee80211_chanctx_conf *conf;
|
|
|
|
|
2022-06-17 13:36:37 -07:00
|
|
|
conf = rcu_dereference_protected(link->conf->chanctx_conf,
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_is_held(&local->hw.wiphy->mtx));
|
2014-06-25 03:35:06 -07:00
|
|
|
if (!conf)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return container_of(conf, struct ieee80211_chanctx, conf);
|
|
|
|
}
|
|
|
|
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
bool ieee80211_chanreq_identical(const struct ieee80211_chan_req *a,
|
|
|
|
const struct ieee80211_chan_req *b)
|
|
|
|
{
|
|
|
|
if (!cfg80211_chandef_identical(&a->oper, &b->oper))
|
|
|
|
return false;
|
|
|
|
if (!a->ap.chan && !b->ap.chan)
|
|
|
|
return true;
|
|
|
|
return cfg80211_chandef_identical(&a->ap, &b->ap);
|
|
|
|
}
|
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
static const struct ieee80211_chan_req *
|
|
|
|
ieee80211_chanreq_compatible(const struct ieee80211_chan_req *a,
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
const struct ieee80211_chan_req *b,
|
|
|
|
struct ieee80211_chan_req *tmp)
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
{
|
|
|
|
const struct cfg80211_chan_def *compat;
|
|
|
|
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
if (a->ap.chan && b->ap.chan &&
|
|
|
|
!cfg80211_chandef_identical(&a->ap, &b->ap))
|
|
|
|
return NULL;
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
compat = cfg80211_chandef_compatible(&a->oper, &b->oper);
|
|
|
|
if (!compat)
|
|
|
|
return NULL;
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
/* Note: later code assumes this always fills & returns tmp if compat */
|
|
|
|
tmp->oper = *compat;
|
|
|
|
tmp->ap = a->ap.chan ? a->ap : b->ap;
|
|
|
|
return tmp;
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static const struct ieee80211_chan_req *
|
|
|
|
ieee80211_chanctx_compatible(struct ieee80211_chanctx *ctx,
|
|
|
|
const struct ieee80211_chan_req *req,
|
|
|
|
struct ieee80211_chan_req *tmp)
|
|
|
|
{
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
const struct ieee80211_chan_req *ret;
|
|
|
|
struct ieee80211_chan_req tmp2;
|
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
*tmp = (struct ieee80211_chan_req){
|
|
|
|
.oper = ctx->conf.def,
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
.ap = ctx->conf.ap,
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
};
|
|
|
|
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
ret = ieee80211_chanreq_compatible(tmp, req, &tmp2);
|
|
|
|
if (!ret)
|
|
|
|
return NULL;
|
|
|
|
*tmp = *ret;
|
|
|
|
return tmp;
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static const struct ieee80211_chan_req *
|
|
|
|
ieee80211_chanctx_reserved_chanreq(struct ieee80211_local *local,
|
2014-04-09 06:29:28 -07:00
|
|
|
struct ieee80211_chanctx *ctx,
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
const struct ieee80211_chan_req *req,
|
|
|
|
struct ieee80211_chan_req *tmp)
|
2014-04-09 06:29:28 -07:00
|
|
|
{
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_link_data *link;
|
2014-04-09 06:29:28 -07:00
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2014-04-09 06:29:28 -07:00
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
if (WARN_ON(!req))
|
2024-01-29 11:34:39 -07:00
|
|
|
return NULL;
|
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
list_for_each_entry(link, &ctx->reserved_links, reserved_chanctx_list) {
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
req = ieee80211_chanreq_compatible(&link->reserved, req, tmp);
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
if (!req)
|
2014-04-09 06:29:28 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
return req;
|
2014-04-09 06:29:28 -07:00
|
|
|
}
|
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
static const struct ieee80211_chan_req *
|
2014-04-09 06:29:29 -07:00
|
|
|
ieee80211_chanctx_non_reserved_chandef(struct ieee80211_local *local,
|
|
|
|
struct ieee80211_chanctx *ctx,
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
const struct ieee80211_chan_req *compat,
|
|
|
|
struct ieee80211_chan_req *tmp)
|
2014-04-09 06:29:29 -07:00
|
|
|
{
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_link_data *link;
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
const struct ieee80211_chan_req *comp_def = compat;
|
2014-04-09 06:29:29 -07:00
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2014-04-09 06:29:29 -07:00
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
list_for_each_entry(link, &ctx->assigned_links, assigned_chanctx_list) {
|
2022-06-17 13:36:37 -07:00
|
|
|
struct ieee80211_bss_conf *link_conf = link->conf;
|
2022-05-30 09:35:23 -07:00
|
|
|
|
|
|
|
if (link->reserved_chanctx)
|
2014-04-09 06:29:29 -07:00
|
|
|
continue;
|
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
comp_def = ieee80211_chanreq_compatible(&link_conf->chanreq,
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
comp_def, tmp);
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
if (!comp_def)
|
2014-04-09 06:29:29 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
return comp_def;
|
2014-04-09 06:29:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
ieee80211_chanctx_can_reserve(struct ieee80211_local *local,
|
|
|
|
struct ieee80211_chanctx *ctx,
|
|
|
|
const struct ieee80211_chan_req *req)
|
2014-04-09 06:29:29 -07:00
|
|
|
{
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
struct ieee80211_chan_req tmp;
|
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2014-04-09 06:29:29 -07:00
|
|
|
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
if (!ieee80211_chanctx_reserved_chanreq(local, ctx, req, &tmp))
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
return false;
|
|
|
|
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
if (!ieee80211_chanctx_non_reserved_chandef(local, ctx, req, &tmp))
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
return false;
|
2014-04-09 06:29:29 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
if (!list_empty(&ctx->reserved_links) &&
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
ieee80211_chanctx_reserved_chanreq(local, ctx, req, &tmp))
|
2014-04-09 06:29:29 -07:00
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct ieee80211_chanctx *
|
|
|
|
ieee80211_find_reservation_chanctx(struct ieee80211_local *local,
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
const struct ieee80211_chan_req *chanreq,
|
2014-04-09 06:29:29 -07:00
|
|
|
enum ieee80211_chanctx_mode mode)
|
|
|
|
{
|
|
|
|
struct ieee80211_chanctx *ctx;
|
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2014-04-09 06:29:29 -07:00
|
|
|
|
|
|
|
if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
list_for_each_entry(ctx, &local->chanctx_list, list) {
|
2014-06-25 03:35:06 -07:00
|
|
|
if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
|
|
|
|
continue;
|
|
|
|
|
2014-04-09 06:29:29 -07:00
|
|
|
if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
|
|
|
|
continue;
|
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
if (!ieee80211_chanctx_can_reserve(local, ctx, chanreq))
|
2014-04-09 06:29:29 -07:00
|
|
|
continue;
|
|
|
|
|
|
|
|
return ctx;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
static enum nl80211_chan_width ieee80211_get_sta_bw(struct sta_info *sta,
|
|
|
|
unsigned int link_id)
|
2013-11-11 11:14:01 -07:00
|
|
|
{
|
2022-06-15 00:20:45 -07:00
|
|
|
enum ieee80211_sta_rx_bandwidth width;
|
|
|
|
struct link_sta_info *link_sta;
|
|
|
|
|
2024-01-29 11:34:41 -07:00
|
|
|
link_sta = wiphy_dereference(sta->local->hw.wiphy, sta->link[link_id]);
|
2022-05-30 09:35:23 -07:00
|
|
|
|
|
|
|
/* no effect if this STA has no presence on this link */
|
2022-06-15 00:20:45 -07:00
|
|
|
if (!link_sta)
|
2022-05-30 09:35:23 -07:00
|
|
|
return NL80211_CHAN_WIDTH_20_NOHT;
|
2020-12-06 05:54:48 -07:00
|
|
|
|
2022-06-15 00:20:45 -07:00
|
|
|
width = ieee80211_sta_cap_rx_bw(link_sta);
|
|
|
|
|
2020-12-06 05:54:48 -07:00
|
|
|
switch (width) {
|
2013-11-11 11:14:01 -07:00
|
|
|
case IEEE80211_STA_RX_BW_20:
|
2022-06-15 00:20:45 -07:00
|
|
|
if (link_sta->pub->ht_cap.ht_supported)
|
2013-11-11 11:14:01 -07:00
|
|
|
return NL80211_CHAN_WIDTH_20;
|
|
|
|
else
|
|
|
|
return NL80211_CHAN_WIDTH_20_NOHT;
|
|
|
|
case IEEE80211_STA_RX_BW_40:
|
|
|
|
return NL80211_CHAN_WIDTH_40;
|
|
|
|
case IEEE80211_STA_RX_BW_80:
|
|
|
|
return NL80211_CHAN_WIDTH_80;
|
|
|
|
case IEEE80211_STA_RX_BW_160:
|
|
|
|
/*
|
|
|
|
* This applied for both 160 and 80+80. since we use
|
|
|
|
* the returned value to consider degradation of
|
|
|
|
* ctx->conf.min_def, we have to make sure to take
|
|
|
|
* the bigger one (NL80211_CHAN_WIDTH_160).
|
|
|
|
* Otherwise we might try degrading even when not
|
|
|
|
* needed, as the max required sta_bw returned (80+80)
|
|
|
|
* might be smaller than the configured bw (160).
|
|
|
|
*/
|
|
|
|
return NL80211_CHAN_WIDTH_160;
|
2022-02-14 09:30:00 -07:00
|
|
|
case IEEE80211_STA_RX_BW_320:
|
|
|
|
return NL80211_CHAN_WIDTH_320;
|
2013-11-11 11:14:01 -07:00
|
|
|
default:
|
|
|
|
WARN_ON(1);
|
|
|
|
return NL80211_CHAN_WIDTH_20;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static enum nl80211_chan_width
|
2024-01-29 11:34:41 -07:00
|
|
|
ieee80211_get_max_required_bw(struct ieee80211_link_data *link)
|
2013-11-11 11:14:01 -07:00
|
|
|
{
|
2024-01-29 11:34:41 -07:00
|
|
|
struct ieee80211_sub_if_data *sdata = link->sdata;
|
|
|
|
unsigned int link_id = link->link_id;
|
2013-11-11 11:14:01 -07:00
|
|
|
enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
|
|
|
|
struct sta_info *sta;
|
|
|
|
|
2024-08-27 00:49:40 -07:00
|
|
|
lockdep_assert_wiphy(sdata->local->hw.wiphy);
|
|
|
|
|
|
|
|
list_for_each_entry(sta, &sdata->local->sta_list, list) {
|
2013-11-11 11:14:01 -07:00
|
|
|
if (sdata != sta->sdata &&
|
|
|
|
!(sta->sdata->bss && sta->sdata->bss == sdata->bss))
|
|
|
|
continue;
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
max_bw = max(max_bw, ieee80211_get_sta_bw(sta, link_id));
|
2013-11-11 11:14:01 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return max_bw;
|
|
|
|
}
|
|
|
|
|
|
|
|
static enum nl80211_chan_width
|
2024-01-29 11:34:41 -07:00
|
|
|
ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
|
|
|
|
struct ieee80211_chanctx *ctx,
|
2024-06-12 05:32:06 -07:00
|
|
|
struct ieee80211_link_data *rsvd_for,
|
|
|
|
bool check_reserved)
|
2013-11-11 11:14:01 -07:00
|
|
|
{
|
2024-01-29 11:34:41 -07:00
|
|
|
struct ieee80211_sub_if_data *sdata;
|
|
|
|
struct ieee80211_link_data *link;
|
2013-11-11 11:14:01 -07:00
|
|
|
enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
|
|
|
|
|
2024-06-12 05:32:06 -07:00
|
|
|
if (WARN_ON(check_reserved && rsvd_for))
|
|
|
|
return ctx->conf.def.width;
|
|
|
|
|
2024-01-29 11:34:41 -07:00
|
|
|
for_each_sdata_link(local, link) {
|
2013-11-11 11:14:01 -07:00
|
|
|
enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20_NOHT;
|
|
|
|
|
2024-06-12 05:32:06 -07:00
|
|
|
if (check_reserved) {
|
|
|
|
if (link->reserved_chanctx != ctx)
|
|
|
|
continue;
|
|
|
|
} else if (link != rsvd_for &&
|
|
|
|
rcu_access_pointer(link->conf->chanctx_conf) != &ctx->conf)
|
2013-11-11 11:14:01 -07:00
|
|
|
continue;
|
|
|
|
|
2024-01-29 11:34:41 -07:00
|
|
|
switch (link->sdata->vif.type) {
|
2013-11-11 11:14:01 -07:00
|
|
|
case NL80211_IFTYPE_AP:
|
|
|
|
case NL80211_IFTYPE_AP_VLAN:
|
2024-01-29 11:34:41 -07:00
|
|
|
width = ieee80211_get_max_required_bw(link);
|
2013-11-11 11:14:01 -07:00
|
|
|
break;
|
2015-06-10 10:41:23 -07:00
|
|
|
case NL80211_IFTYPE_STATION:
|
|
|
|
/*
|
|
|
|
* The ap's sta->bandwidth is not set yet at this
|
|
|
|
* point, so take the width from the chandef, but
|
|
|
|
* account also for TDLS peers
|
|
|
|
*/
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
width = max(link->conf->chanreq.oper.width,
|
2024-01-29 11:34:41 -07:00
|
|
|
ieee80211_get_max_required_bw(link));
|
2015-06-10 10:41:23 -07:00
|
|
|
break;
|
2013-11-11 11:14:01 -07:00
|
|
|
case NL80211_IFTYPE_P2P_DEVICE:
|
2016-09-20 07:31:13 -07:00
|
|
|
case NL80211_IFTYPE_NAN:
|
2013-11-11 11:14:01 -07:00
|
|
|
continue;
|
|
|
|
case NL80211_IFTYPE_ADHOC:
|
|
|
|
case NL80211_IFTYPE_MESH_POINT:
|
2014-11-03 02:33:18 -07:00
|
|
|
case NL80211_IFTYPE_OCB:
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
width = link->conf->chanreq.oper.width;
|
2013-11-11 11:14:01 -07:00
|
|
|
break;
|
2020-11-09 02:57:46 -07:00
|
|
|
case NL80211_IFTYPE_WDS:
|
2013-11-11 11:14:01 -07:00
|
|
|
case NL80211_IFTYPE_UNSPECIFIED:
|
|
|
|
case NUM_NL80211_IFTYPES:
|
|
|
|
case NL80211_IFTYPE_MONITOR:
|
|
|
|
case NL80211_IFTYPE_P2P_CLIENT:
|
|
|
|
case NL80211_IFTYPE_P2P_GO:
|
|
|
|
WARN_ON_ONCE(1);
|
|
|
|
}
|
2022-05-30 09:35:23 -07:00
|
|
|
|
|
|
|
max_bw = max(max_bw, width);
|
|
|
|
}
|
2014-03-03 04:37:14 -07:00
|
|
|
|
|
|
|
/* use the configured bandwidth in case of monitor interface */
|
2024-01-29 11:34:41 -07:00
|
|
|
sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata);
|
2022-05-30 09:35:23 -07:00
|
|
|
if (sdata &&
|
2023-05-04 06:45:03 -07:00
|
|
|
rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) == &ctx->conf)
|
|
|
|
max_bw = max(max_bw, ctx->conf.def.width);
|
2014-03-03 04:37:14 -07:00
|
|
|
|
2013-11-11 11:14:01 -07:00
|
|
|
return max_bw;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* recalc the min required chan width of the channel context, which is
|
|
|
|
* the max of min required widths of all the interfaces bound to this
|
|
|
|
* channel context.
|
|
|
|
*/
|
2023-05-04 06:45:03 -07:00
|
|
|
static u32
|
|
|
|
_ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
|
|
|
|
struct ieee80211_chanctx *ctx,
|
2024-06-12 05:32:06 -07:00
|
|
|
struct ieee80211_link_data *rsvd_for,
|
|
|
|
bool check_reserved)
|
2013-11-11 11:14:01 -07:00
|
|
|
{
|
|
|
|
enum nl80211_chan_width max_bw;
|
|
|
|
struct cfg80211_chan_def min_def;
|
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2013-11-11 11:14:01 -07:00
|
|
|
|
2020-06-01 23:22:47 -07:00
|
|
|
/* don't optimize non-20MHz based and radar_enabled confs */
|
2013-11-11 11:14:01 -07:00
|
|
|
if (ctx->conf.def.width == NL80211_CHAN_WIDTH_5 ||
|
|
|
|
ctx->conf.def.width == NL80211_CHAN_WIDTH_10 ||
|
2020-06-01 23:22:47 -07:00
|
|
|
ctx->conf.def.width == NL80211_CHAN_WIDTH_1 ||
|
|
|
|
ctx->conf.def.width == NL80211_CHAN_WIDTH_2 ||
|
|
|
|
ctx->conf.def.width == NL80211_CHAN_WIDTH_4 ||
|
|
|
|
ctx->conf.def.width == NL80211_CHAN_WIDTH_8 ||
|
|
|
|
ctx->conf.def.width == NL80211_CHAN_WIDTH_16 ||
|
2013-11-11 11:14:01 -07:00
|
|
|
ctx->conf.radar_enabled) {
|
|
|
|
ctx->conf.min_def = ctx->conf.def;
|
2021-06-18 03:41:30 -07:00
|
|
|
return 0;
|
2013-11-11 11:14:01 -07:00
|
|
|
}
|
|
|
|
|
2024-06-12 05:32:06 -07:00
|
|
|
max_bw = ieee80211_get_chanctx_max_required_bw(local, ctx, rsvd_for,
|
|
|
|
check_reserved);
|
2013-11-11 11:14:01 -07:00
|
|
|
|
|
|
|
/* downgrade chandef up to max_bw */
|
|
|
|
min_def = ctx->conf.def;
|
|
|
|
while (min_def.width > max_bw)
|
2024-01-29 11:34:36 -07:00
|
|
|
ieee80211_chandef_downgrade(&min_def, NULL);
|
2013-11-11 11:14:01 -07:00
|
|
|
|
|
|
|
if (cfg80211_chandef_identical(&ctx->conf.min_def, &min_def))
|
2021-06-18 03:41:30 -07:00
|
|
|
return 0;
|
2013-11-11 11:14:01 -07:00
|
|
|
|
|
|
|
ctx->conf.min_def = min_def;
|
|
|
|
if (!ctx->driver_present)
|
2021-06-18 03:41:30 -07:00
|
|
|
return 0;
|
2013-11-11 11:14:01 -07:00
|
|
|
|
2021-06-18 03:41:30 -07:00
|
|
|
return IEEE80211_CHANCTX_CHANGE_MIN_WIDTH;
|
2013-11-11 11:14:01 -07:00
|
|
|
}
|
|
|
|
|
2020-12-06 05:54:50 -07:00
|
|
|
static void ieee80211_chan_bw_change(struct ieee80211_local *local,
|
2021-06-18 03:41:30 -07:00
|
|
|
struct ieee80211_chanctx *ctx,
|
2024-06-12 05:32:05 -07:00
|
|
|
bool reserved, bool narrowed)
|
2020-12-06 05:54:50 -07:00
|
|
|
{
|
|
|
|
struct sta_info *sta;
|
|
|
|
struct ieee80211_supported_band *sband =
|
|
|
|
local->hw.wiphy->bands[ctx->conf.def.chan->band];
|
|
|
|
|
|
|
|
rcu_read_lock();
|
|
|
|
list_for_each_entry_rcu(sta, &local->sta_list,
|
|
|
|
list) {
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
2020-12-06 05:54:50 -07:00
|
|
|
enum ieee80211_sta_rx_bandwidth new_sta_bw;
|
2022-05-30 09:35:23 -07:00
|
|
|
unsigned int link_id;
|
2020-12-06 05:54:50 -07:00
|
|
|
|
|
|
|
if (!ieee80211_sdata_running(sta->sdata))
|
|
|
|
continue;
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
for (link_id = 0; link_id < ARRAY_SIZE(sta->sdata->link); link_id++) {
|
2024-06-12 05:32:05 -07:00
|
|
|
struct ieee80211_link_data *link =
|
|
|
|
rcu_dereference(sdata->link[link_id]);
|
|
|
|
struct ieee80211_bss_conf *link_conf;
|
|
|
|
struct cfg80211_chan_def *new_chandef;
|
2022-06-15 00:20:45 -07:00
|
|
|
struct link_sta_info *link_sta;
|
2022-05-30 09:35:23 -07:00
|
|
|
|
2024-06-12 05:32:05 -07:00
|
|
|
if (!link)
|
2022-05-30 09:35:23 -07:00
|
|
|
continue;
|
2020-12-06 05:54:50 -07:00
|
|
|
|
2024-06-12 05:32:05 -07:00
|
|
|
link_conf = link->conf;
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
if (rcu_access_pointer(link_conf->chanctx_conf) != &ctx->conf)
|
|
|
|
continue;
|
2021-06-18 03:41:30 -07:00
|
|
|
|
2022-06-15 00:20:45 -07:00
|
|
|
link_sta = rcu_dereference(sta->link[link_id]);
|
|
|
|
if (!link_sta)
|
|
|
|
continue;
|
|
|
|
|
2024-06-12 05:32:05 -07:00
|
|
|
if (reserved)
|
|
|
|
new_chandef = &link->reserved.oper;
|
|
|
|
else
|
|
|
|
new_chandef = &link_conf->chanreq.oper;
|
|
|
|
|
|
|
|
new_sta_bw = _ieee80211_sta_cur_vht_bw(link_sta,
|
|
|
|
new_chandef);
|
2020-12-06 05:54:50 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
/* nothing change */
|
2022-06-15 00:20:45 -07:00
|
|
|
if (new_sta_bw == link_sta->pub->bandwidth)
|
2022-05-30 09:35:23 -07:00
|
|
|
continue;
|
|
|
|
|
|
|
|
/* vif changed to narrow BW and narrow BW for station wasn't
|
|
|
|
* requested or vise versa */
|
2022-06-15 00:20:45 -07:00
|
|
|
if ((new_sta_bw < link_sta->pub->bandwidth) == !narrowed)
|
2022-05-30 09:35:23 -07:00
|
|
|
continue;
|
2021-06-18 03:41:30 -07:00
|
|
|
|
2022-06-15 00:20:45 -07:00
|
|
|
link_sta->pub->bandwidth = new_sta_bw;
|
2022-05-30 09:35:23 -07:00
|
|
|
rate_control_rate_update(local, sband, sta, link_id,
|
|
|
|
IEEE80211_RC_BW_CHANGED);
|
|
|
|
}
|
2020-12-06 05:54:50 -07:00
|
|
|
}
|
|
|
|
rcu_read_unlock();
|
|
|
|
}
|
|
|
|
|
2021-06-18 03:41:30 -07:00
|
|
|
/*
|
|
|
|
* recalc the min required chan width of the channel context, which is
|
|
|
|
* the max of min required widths of all the interfaces bound to this
|
|
|
|
* channel context.
|
|
|
|
*/
|
|
|
|
void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
|
2023-05-04 06:45:03 -07:00
|
|
|
struct ieee80211_chanctx *ctx,
|
2024-06-12 05:32:06 -07:00
|
|
|
struct ieee80211_link_data *rsvd_for,
|
|
|
|
bool check_reserved)
|
2012-06-26 05:37:21 -07:00
|
|
|
{
|
2024-06-12 05:32:06 -07:00
|
|
|
u32 changed = _ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for,
|
|
|
|
check_reserved);
|
2020-12-06 05:54:50 -07:00
|
|
|
|
2021-06-18 03:41:30 -07:00
|
|
|
if (!changed)
|
2012-06-26 05:37:22 -07:00
|
|
|
return;
|
2010-05-05 06:28:27 -07:00
|
|
|
|
2021-06-18 03:41:30 -07:00
|
|
|
/* check is BW narrowed */
|
2024-06-12 05:32:05 -07:00
|
|
|
ieee80211_chan_bw_change(local, ctx, false, true);
|
2012-11-09 03:39:59 -07:00
|
|
|
|
2021-06-18 03:41:30 -07:00
|
|
|
drv_change_chanctx(local, ctx, changed);
|
|
|
|
|
|
|
|
/* check is BW wider */
|
2024-06-12 05:32:05 -07:00
|
|
|
ieee80211_chan_bw_change(local, ctx, false, false);
|
2021-06-18 03:41:30 -07:00
|
|
|
}
|
|
|
|
|
2023-05-04 06:45:03 -07:00
|
|
|
static void _ieee80211_change_chanctx(struct ieee80211_local *local,
|
|
|
|
struct ieee80211_chanctx *ctx,
|
|
|
|
struct ieee80211_chanctx *old_ctx,
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
const struct ieee80211_chan_req *chanreq,
|
2023-05-04 06:45:03 -07:00
|
|
|
struct ieee80211_link_data *rsvd_for)
|
2021-06-18 03:41:30 -07:00
|
|
|
{
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
const struct cfg80211_chan_def *chandef = &chanreq->oper;
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
struct ieee80211_chan_req ctx_req = {
|
|
|
|
.oper = ctx->conf.def,
|
|
|
|
.ap = ctx->conf.ap,
|
|
|
|
};
|
|
|
|
u32 changed = 0;
|
2020-12-06 05:54:50 -07:00
|
|
|
|
2022-02-14 09:30:00 -07:00
|
|
|
/* expected to handle only 20/40/80/160/320 channel widths */
|
2020-12-06 05:54:50 -07:00
|
|
|
switch (chandef->width) {
|
|
|
|
case NL80211_CHAN_WIDTH_20_NOHT:
|
|
|
|
case NL80211_CHAN_WIDTH_20:
|
|
|
|
case NL80211_CHAN_WIDTH_40:
|
|
|
|
case NL80211_CHAN_WIDTH_80:
|
|
|
|
case NL80211_CHAN_WIDTH_80P80:
|
|
|
|
case NL80211_CHAN_WIDTH_160:
|
2022-02-14 09:30:00 -07:00
|
|
|
case NL80211_CHAN_WIDTH_320:
|
2020-12-06 05:54:50 -07:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WARN_ON(1);
|
|
|
|
}
|
|
|
|
|
2021-06-18 03:41:30 -07:00
|
|
|
/* Check maybe BW narrowed - we do this _before_ calling recalc_chanctx_min_def
|
|
|
|
* due to maybe not returning from it, e.g in case new context was added
|
|
|
|
* first time with all parameters up to date.
|
|
|
|
*/
|
2024-06-12 05:32:05 -07:00
|
|
|
ieee80211_chan_bw_change(local, old_ctx, false, true);
|
2021-06-18 03:41:30 -07:00
|
|
|
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
if (ieee80211_chanreq_identical(&ctx_req, chanreq)) {
|
2024-06-12 05:32:06 -07:00
|
|
|
ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for, false);
|
2021-06-18 03:41:30 -07:00
|
|
|
return;
|
|
|
|
}
|
2020-12-06 05:54:50 -07:00
|
|
|
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
WARN_ON(ieee80211_chanctx_refcount(local, ctx) > 1 &&
|
|
|
|
!cfg80211_chandef_compatible(&ctx->conf.def, &chanreq->oper));
|
2021-06-18 03:41:30 -07:00
|
|
|
|
2023-12-11 03:06:25 -07:00
|
|
|
ieee80211_remove_wbrf(local, &ctx->conf.def);
|
|
|
|
|
2024-01-29 11:34:49 -07:00
|
|
|
if (!cfg80211_chandef_identical(&ctx->conf.def, &chanreq->oper)) {
|
|
|
|
if (ctx->conf.def.width != chanreq->oper.width)
|
|
|
|
changed |= IEEE80211_CHANCTX_CHANGE_WIDTH;
|
|
|
|
if (ctx->conf.def.punctured != chanreq->oper.punctured)
|
|
|
|
changed |= IEEE80211_CHANCTX_CHANGE_PUNCTURING;
|
|
|
|
}
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
if (!cfg80211_chandef_identical(&ctx->conf.ap, &chanreq->ap))
|
|
|
|
changed |= IEEE80211_CHANCTX_CHANGE_AP;
|
2021-06-18 03:41:30 -07:00
|
|
|
ctx->conf.def = *chandef;
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
ctx->conf.ap = chanreq->ap;
|
2021-06-18 03:41:30 -07:00
|
|
|
|
|
|
|
/* check if min chanctx also changed */
|
2024-06-12 05:32:06 -07:00
|
|
|
changed |= _ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for, false);
|
2023-12-11 03:06:25 -07:00
|
|
|
|
|
|
|
ieee80211_add_wbrf(local, &ctx->conf.def);
|
|
|
|
|
2021-06-18 03:41:30 -07:00
|
|
|
drv_change_chanctx(local, ctx, changed);
|
2012-07-26 08:24:39 -07:00
|
|
|
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
/* check if BW is wider */
|
2024-06-12 05:32:05 -07:00
|
|
|
ieee80211_chan_bw_change(local, old_ctx, false, false);
|
2010-05-05 06:28:27 -07:00
|
|
|
}
|
2012-06-26 05:37:16 -07:00
|
|
|
|
2023-05-04 06:45:03 -07:00
|
|
|
static void ieee80211_change_chanctx(struct ieee80211_local *local,
|
|
|
|
struct ieee80211_chanctx *ctx,
|
|
|
|
struct ieee80211_chanctx *old_ctx,
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
const struct ieee80211_chan_req *chanreq)
|
2023-05-04 06:45:03 -07:00
|
|
|
{
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
_ieee80211_change_chanctx(local, ctx, old_ctx, chanreq, NULL);
|
2023-05-04 06:45:03 -07:00
|
|
|
}
|
|
|
|
|
2024-04-18 02:52:19 -07:00
|
|
|
/* Note: if successful, the returned chanctx is reserved for the link */
|
2012-06-26 05:37:16 -07:00
|
|
|
static struct ieee80211_chanctx *
|
|
|
|
ieee80211_find_chanctx(struct ieee80211_local *local,
|
2024-04-18 02:52:19 -07:00
|
|
|
struct ieee80211_link_data *link,
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
const struct ieee80211_chan_req *chanreq,
|
2012-06-26 05:37:16 -07:00
|
|
|
enum ieee80211_chanctx_mode mode)
|
|
|
|
{
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
struct ieee80211_chan_req tmp;
|
2012-06-26 05:37:16 -07:00
|
|
|
struct ieee80211_chanctx *ctx;
|
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2012-06-26 05:37:16 -07:00
|
|
|
|
|
|
|
if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
|
|
|
|
return NULL;
|
|
|
|
|
2024-04-18 02:52:19 -07:00
|
|
|
if (WARN_ON(link->reserved_chanctx))
|
|
|
|
return NULL;
|
|
|
|
|
2012-06-26 05:37:16 -07:00
|
|
|
list_for_each_entry(ctx, &local->chanctx_list, list) {
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
const struct ieee80211_chan_req *compat;
|
2012-06-26 05:37:22 -07:00
|
|
|
|
2014-06-25 03:35:06 -07:00
|
|
|
if (ctx->replace_state != IEEE80211_CHANCTX_REPLACE_NONE)
|
|
|
|
continue;
|
|
|
|
|
2012-06-26 05:37:16 -07:00
|
|
|
if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
|
|
|
|
continue;
|
2012-11-09 03:39:59 -07:00
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
compat = ieee80211_chanctx_compatible(ctx, chanreq, &tmp);
|
2012-11-09 03:39:59 -07:00
|
|
|
if (!compat)
|
2012-06-26 05:37:16 -07:00
|
|
|
continue;
|
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
compat = ieee80211_chanctx_reserved_chanreq(local, ctx,
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
compat, &tmp);
|
2014-04-09 06:29:28 -07:00
|
|
|
if (!compat)
|
|
|
|
continue;
|
|
|
|
|
2024-04-18 02:52:19 -07:00
|
|
|
/*
|
|
|
|
* Reserve the chanctx temporarily, as the driver might change
|
|
|
|
* active links during callbacks we make into it below and/or
|
|
|
|
* later during assignment, which could (otherwise) cause the
|
|
|
|
* context to actually be removed.
|
|
|
|
*/
|
|
|
|
link->reserved_chanctx = ctx;
|
|
|
|
list_add(&link->reserved_chanctx_list,
|
|
|
|
&ctx->reserved_links);
|
|
|
|
|
2021-06-18 03:41:30 -07:00
|
|
|
ieee80211_change_chanctx(local, ctx, ctx, compat);
|
2012-06-26 05:37:22 -07:00
|
|
|
|
2012-06-26 05:37:16 -07:00
|
|
|
return ctx;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-01-07 08:50:09 -07:00
|
|
|
bool ieee80211_is_radar_required(struct ieee80211_local *local)
|
2013-04-08 13:43:16 -07:00
|
|
|
{
|
2024-01-29 11:34:41 -07:00
|
|
|
struct ieee80211_link_data *link;
|
2013-04-08 13:43:16 -07:00
|
|
|
|
2023-08-28 05:00:05 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2014-01-28 23:56:20 -07:00
|
|
|
|
2024-01-29 11:34:41 -07:00
|
|
|
for_each_sdata_link(local, link) {
|
|
|
|
if (link->radar_required)
|
|
|
|
return true;
|
2013-04-08 13:43:16 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-01-07 08:50:10 -07:00
|
|
|
static bool
|
|
|
|
ieee80211_chanctx_radar_required(struct ieee80211_local *local,
|
|
|
|
struct ieee80211_chanctx *ctx)
|
|
|
|
{
|
|
|
|
struct ieee80211_chanctx_conf *conf = &ctx->conf;
|
2024-01-29 11:34:41 -07:00
|
|
|
struct ieee80211_link_data *link;
|
2015-01-07 08:50:10 -07:00
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2015-01-07 08:50:10 -07:00
|
|
|
|
2024-01-29 11:34:41 -07:00
|
|
|
for_each_sdata_link(local, link) {
|
|
|
|
if (rcu_access_pointer(link->conf->chanctx_conf) != conf)
|
2015-01-07 08:50:10 -07:00
|
|
|
continue;
|
2024-01-29 11:34:41 -07:00
|
|
|
if (!link->radar_required)
|
|
|
|
continue;
|
|
|
|
return true;
|
2015-01-07 08:50:10 -07:00
|
|
|
}
|
|
|
|
|
2024-01-29 11:34:41 -07:00
|
|
|
return false;
|
2015-01-07 08:50:10 -07:00
|
|
|
}
|
|
|
|
|
2012-06-26 05:37:16 -07:00
|
|
|
static struct ieee80211_chanctx *
|
2014-04-09 06:29:30 -07:00
|
|
|
ieee80211_alloc_chanctx(struct ieee80211_local *local,
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
const struct ieee80211_chan_req *chanreq,
|
2024-07-09 01:38:34 -07:00
|
|
|
enum ieee80211_chanctx_mode mode,
|
|
|
|
int radio_idx)
|
2012-06-26 05:37:16 -07:00
|
|
|
{
|
|
|
|
struct ieee80211_chanctx *ctx;
|
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2012-06-26 05:37:16 -07:00
|
|
|
|
|
|
|
ctx = kzalloc(sizeof(*ctx) + local->hw.chanctx_data_size, GFP_KERNEL);
|
|
|
|
if (!ctx)
|
2014-04-09 06:29:30 -07:00
|
|
|
return NULL;
|
2012-06-26 05:37:16 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
INIT_LIST_HEAD(&ctx->assigned_links);
|
|
|
|
INIT_LIST_HEAD(&ctx->reserved_links);
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
ctx->conf.def = chanreq->oper;
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
ctx->conf.ap = chanreq->ap;
|
2012-09-11 05:34:12 -07:00
|
|
|
ctx->conf.rx_chains_static = 1;
|
|
|
|
ctx->conf.rx_chains_dynamic = 1;
|
2012-06-26 05:37:16 -07:00
|
|
|
ctx->mode = mode;
|
2015-01-07 08:50:10 -07:00
|
|
|
ctx->conf.radar_enabled = false;
|
2024-07-09 01:38:34 -07:00
|
|
|
ctx->conf.radio_idx = radio_idx;
|
wifi: mac80211: handle ieee80211_radar_detected() for MLO
Currently DFS works under assumption there could be only one channel
context in the hardware. Hence, drivers just calls the function
ieee80211_radar_detected() passing the hardware structure. However, with
MLO, this obviously will not work since number of channel contexts will be
more than one and hence drivers would need to pass the channel information
as well on which the radar is detected.
Also, when radar is detected in one of the links, other link's CAC should
not be cancelled.
Hence, in order to support DFS with MLO, do the following changes -
* Add channel context conf pointer as an argument to the function
ieee80211_radar_detected(). During MLO, drivers would have to pass on
which channel context conf radar is detected. Otherwise, drivers could
just pass NULL.
* ieee80211_radar_detected() will iterate over all channel contexts
present and
* if channel context conf is passed, only mark that as radar
detected
* if NULL is passed, then mark all channel contexts as radar
detected
* Then as usual, schedule the radar detected work.
* In the worker, go over all the contexts again and for all such context
which is marked with radar detected, cancel the ongoing CAC by calling
ieee80211_dfs_cac_cancel() and then notify cfg80211 via
cfg80211_radar_event().
* To cancel the CAC, pass the channel context as well where radar is
detected to ieee80211_dfs_cac_cancel(). This ensures that CAC is
canceled only on the links using the provided context, leaving other
links unaffected.
This would also help in scenarios where there is split phy 5 GHz radio,
which is capable of DFS channels in both lower and upper band. In this
case, simultaneous radars can be detected.
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
Link: https://patch.msgid.link/20240906064426.2101315-9-quic_adisi@quicinc.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-09-05 23:44:26 -07:00
|
|
|
ctx->radar_detected = false;
|
2024-06-12 05:32:06 -07:00
|
|
|
_ieee80211_recalc_chanctx_min_def(local, ctx, NULL, false);
|
2014-04-09 06:29:30 -07:00
|
|
|
|
|
|
|
return ctx;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ieee80211_add_chanctx(struct ieee80211_local *local,
|
|
|
|
struct ieee80211_chanctx *ctx)
|
|
|
|
{
|
|
|
|
u32 changed;
|
|
|
|
int err;
|
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2014-04-09 06:29:30 -07:00
|
|
|
|
2023-12-11 03:06:25 -07:00
|
|
|
ieee80211_add_wbrf(local, &ctx->conf.def);
|
|
|
|
|
2013-03-22 14:30:09 -07:00
|
|
|
/* turn idle off *before* setting channel -- some drivers need that */
|
|
|
|
changed = ieee80211_idle_off(local);
|
|
|
|
if (changed)
|
|
|
|
ieee80211_hw_config(local, changed);
|
|
|
|
|
2024-01-29 11:34:38 -07:00
|
|
|
err = drv_add_chanctx(local, ctx);
|
|
|
|
if (err) {
|
|
|
|
ieee80211_recalc_idle(local);
|
|
|
|
return err;
|
2012-06-26 05:37:20 -07:00
|
|
|
}
|
|
|
|
|
2014-04-09 06:29:30 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct ieee80211_chanctx *
|
|
|
|
ieee80211_new_chanctx(struct ieee80211_local *local,
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
const struct ieee80211_chan_req *chanreq,
|
2024-04-18 02:52:21 -07:00
|
|
|
enum ieee80211_chanctx_mode mode,
|
2024-07-09 01:38:37 -07:00
|
|
|
bool assign_on_failure,
|
|
|
|
int radio_idx)
|
2014-04-09 06:29:30 -07:00
|
|
|
{
|
|
|
|
struct ieee80211_chanctx *ctx;
|
|
|
|
int err;
|
2012-06-26 05:37:16 -07:00
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2012-06-26 05:37:16 -07:00
|
|
|
|
2024-07-09 01:38:37 -07:00
|
|
|
ctx = ieee80211_alloc_chanctx(local, chanreq, mode, radio_idx);
|
2014-04-09 06:29:30 -07:00
|
|
|
if (!ctx)
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
|
|
err = ieee80211_add_chanctx(local, ctx);
|
2024-04-18 02:52:21 -07:00
|
|
|
if (!assign_on_failure && err) {
|
2014-04-09 06:29:30 -07:00
|
|
|
kfree(ctx);
|
|
|
|
return ERR_PTR(err);
|
|
|
|
}
|
2024-04-18 02:52:21 -07:00
|
|
|
/* We ignored a driver error, see _ieee80211_set_active_links */
|
|
|
|
WARN_ON_ONCE(err && !local->in_reconfig);
|
2014-04-09 06:29:30 -07:00
|
|
|
|
|
|
|
list_add_rcu(&ctx->list, &local->chanctx_list);
|
2012-06-26 05:37:16 -07:00
|
|
|
return ctx;
|
|
|
|
}
|
|
|
|
|
2014-04-09 06:29:31 -07:00
|
|
|
static void ieee80211_del_chanctx(struct ieee80211_local *local,
|
2024-03-20 00:13:59 -07:00
|
|
|
struct ieee80211_chanctx *ctx,
|
|
|
|
bool skip_idle_recalc)
|
2012-06-26 05:37:16 -07:00
|
|
|
{
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2012-06-26 05:37:16 -07:00
|
|
|
|
2024-01-29 11:34:38 -07:00
|
|
|
drv_remove_chanctx(local, ctx);
|
2012-06-26 05:37:20 -07:00
|
|
|
|
2024-03-20 00:13:59 -07:00
|
|
|
if (!skip_idle_recalc)
|
|
|
|
ieee80211_recalc_idle(local);
|
2023-12-11 03:06:25 -07:00
|
|
|
|
|
|
|
ieee80211_remove_wbrf(local, &ctx->conf.def);
|
2012-06-26 05:37:16 -07:00
|
|
|
}
|
|
|
|
|
2014-04-09 06:29:31 -07:00
|
|
|
static void ieee80211_free_chanctx(struct ieee80211_local *local,
|
2024-03-20 00:13:59 -07:00
|
|
|
struct ieee80211_chanctx *ctx,
|
|
|
|
bool skip_idle_recalc)
|
2012-06-26 05:37:16 -07:00
|
|
|
{
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2012-06-26 05:37:16 -07:00
|
|
|
|
2014-04-09 06:29:33 -07:00
|
|
|
WARN_ON_ONCE(ieee80211_chanctx_refcount(local, ctx) != 0);
|
2013-02-13 05:50:51 -07:00
|
|
|
|
2014-04-09 06:29:31 -07:00
|
|
|
list_del_rcu(&ctx->list);
|
2024-03-20 00:13:59 -07:00
|
|
|
ieee80211_del_chanctx(local, ctx, skip_idle_recalc);
|
2014-04-09 06:29:31 -07:00
|
|
|
kfree_rcu(ctx, rcu_head);
|
2012-06-26 05:37:16 -07:00
|
|
|
}
|
|
|
|
|
2015-06-10 10:41:23 -07:00
|
|
|
void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
|
|
|
|
struct ieee80211_chanctx *ctx)
|
2012-06-26 05:37:22 -07:00
|
|
|
{
|
|
|
|
struct ieee80211_chanctx_conf *conf = &ctx->conf;
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
const struct ieee80211_chan_req *compat = NULL;
|
2024-01-29 11:34:41 -07:00
|
|
|
struct ieee80211_link_data *link;
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
struct ieee80211_chan_req tmp;
|
2015-06-10 10:41:23 -07:00
|
|
|
struct sta_info *sta;
|
2012-06-26 05:37:22 -07:00
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2012-06-26 05:37:22 -07:00
|
|
|
|
2024-01-29 11:34:41 -07:00
|
|
|
for_each_sdata_link(local, link) {
|
|
|
|
struct ieee80211_bss_conf *link_conf;
|
2012-11-09 03:39:59 -07:00
|
|
|
|
2024-01-29 11:34:41 -07:00
|
|
|
if (link->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
2012-06-26 05:37:22 -07:00
|
|
|
continue;
|
2022-05-30 09:35:23 -07:00
|
|
|
|
2024-01-29 11:34:41 -07:00
|
|
|
link_conf = link->conf;
|
2012-11-09 03:39:59 -07:00
|
|
|
|
2024-01-29 11:34:41 -07:00
|
|
|
if (rcu_access_pointer(link_conf->chanctx_conf) != conf)
|
|
|
|
continue;
|
2022-05-30 09:35:23 -07:00
|
|
|
|
2024-01-29 11:34:41 -07:00
|
|
|
if (!compat)
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
compat = &link_conf->chanreq;
|
2022-05-30 09:35:23 -07:00
|
|
|
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
compat = ieee80211_chanreq_compatible(&link_conf->chanreq,
|
|
|
|
compat, &tmp);
|
2024-01-29 11:34:41 -07:00
|
|
|
if (WARN_ON_ONCE(!compat))
|
|
|
|
return;
|
2012-06-26 05:37:22 -07:00
|
|
|
}
|
2015-06-10 10:41:23 -07:00
|
|
|
|
2024-01-29 11:34:41 -07:00
|
|
|
if (WARN_ON_ONCE(!compat))
|
2023-06-15 23:53:56 -07:00
|
|
|
return;
|
|
|
|
|
2015-06-10 10:41:23 -07:00
|
|
|
/* TDLS peers can sometimes affect the chandef width */
|
2024-01-29 11:34:41 -07:00
|
|
|
list_for_each_entry(sta, &local->sta_list, list) {
|
2024-06-12 05:35:57 -07:00
|
|
|
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
struct ieee80211_chan_req tdls_chanreq = {};
|
2024-06-12 05:35:57 -07:00
|
|
|
int tdls_link_id;
|
|
|
|
|
2015-06-10 10:41:23 -07:00
|
|
|
if (!sta->uploaded ||
|
|
|
|
!test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW) ||
|
|
|
|
!test_sta_flag(sta, WLAN_STA_AUTHORIZED) ||
|
|
|
|
!sta->tdls_chandef.chan)
|
|
|
|
continue;
|
|
|
|
|
2024-06-12 05:35:57 -07:00
|
|
|
tdls_link_id = ieee80211_tdls_sta_link_id(sta);
|
|
|
|
link = sdata_dereference(sdata->link[tdls_link_id], sdata);
|
|
|
|
if (!link)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (rcu_access_pointer(link->conf->chanctx_conf) != conf)
|
|
|
|
continue;
|
|
|
|
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
tdls_chanreq.oper = sta->tdls_chandef;
|
|
|
|
|
|
|
|
/* note this always fills and returns &tmp if compat */
|
|
|
|
compat = ieee80211_chanreq_compatible(&tdls_chanreq,
|
|
|
|
compat, &tmp);
|
2015-06-10 10:41:23 -07:00
|
|
|
if (WARN_ON_ONCE(!compat))
|
2024-01-29 11:34:41 -07:00
|
|
|
return;
|
2015-06-10 10:41:23 -07:00
|
|
|
}
|
2012-06-26 05:37:22 -07:00
|
|
|
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
ieee80211_change_chanctx(local, ctx, ctx, compat);
|
2012-06-26 05:37:22 -07:00
|
|
|
}
|
|
|
|
|
2013-12-18 01:36:09 -07:00
|
|
|
static void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
|
|
|
|
struct ieee80211_chanctx *chanctx)
|
|
|
|
{
|
|
|
|
bool radar_enabled;
|
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2013-12-18 01:36:09 -07:00
|
|
|
|
2015-01-07 08:50:10 -07:00
|
|
|
radar_enabled = ieee80211_chanctx_radar_required(local, chanctx);
|
2013-12-18 01:36:09 -07:00
|
|
|
|
|
|
|
if (radar_enabled == chanctx->conf.radar_enabled)
|
|
|
|
return;
|
|
|
|
|
|
|
|
chanctx->conf.radar_enabled = radar_enabled;
|
|
|
|
|
|
|
|
drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RADAR);
|
|
|
|
}
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link,
|
2024-04-18 02:52:21 -07:00
|
|
|
struct ieee80211_chanctx *new_ctx,
|
|
|
|
bool assign_on_failure)
|
2012-06-26 05:37:16 -07:00
|
|
|
{
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_sub_if_data *sdata = link->sdata;
|
2012-06-26 05:37:20 -07:00
|
|
|
struct ieee80211_local *local = sdata->local;
|
2014-03-11 09:24:12 -07:00
|
|
|
struct ieee80211_chanctx_conf *conf;
|
|
|
|
struct ieee80211_chanctx *curr_ctx = NULL;
|
2024-04-18 01:52:19 -07:00
|
|
|
bool new_idle;
|
2024-04-18 02:52:20 -07:00
|
|
|
int ret;
|
2012-06-26 05:37:16 -07:00
|
|
|
|
2016-09-20 07:31:14 -07:00
|
|
|
if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_NAN))
|
2023-12-11 00:05:25 -07:00
|
|
|
return -EOPNOTSUPP;
|
2016-09-20 07:31:14 -07:00
|
|
|
|
2022-06-17 13:36:37 -07:00
|
|
|
conf = rcu_dereference_protected(link->conf->chanctx_conf,
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_is_held(&local->hw.wiphy->mtx));
|
2012-06-26 05:37:16 -07:00
|
|
|
|
2014-03-11 09:24:12 -07:00
|
|
|
if (conf) {
|
|
|
|
curr_ctx = container_of(conf, struct ieee80211_chanctx, conf);
|
2012-06-26 05:37:20 -07:00
|
|
|
|
2022-07-03 08:04:15 -07:00
|
|
|
drv_unassign_vif_chanctx(local, sdata, link->conf, curr_ctx);
|
2014-03-11 09:24:12 -07:00
|
|
|
conf = NULL;
|
2022-05-30 09:35:23 -07:00
|
|
|
list_del(&link->assigned_chanctx_list);
|
2014-03-11 09:24:12 -07:00
|
|
|
}
|
2013-02-13 05:50:51 -07:00
|
|
|
|
2014-03-11 09:24:12 -07:00
|
|
|
if (new_ctx) {
|
2023-05-04 06:45:04 -07:00
|
|
|
/* recalc considering the link we'll use it for now */
|
2024-06-12 05:32:06 -07:00
|
|
|
ieee80211_recalc_chanctx_min_def(local, new_ctx, link, false);
|
2023-05-04 06:45:04 -07:00
|
|
|
|
2022-07-03 08:04:15 -07:00
|
|
|
ret = drv_assign_vif_chanctx(local, sdata, link->conf, new_ctx);
|
2024-04-18 02:52:21 -07:00
|
|
|
if (assign_on_failure || !ret) {
|
|
|
|
/* Need to continue, see _ieee80211_set_active_links */
|
|
|
|
WARN_ON_ONCE(ret && !local->in_reconfig);
|
|
|
|
ret = 0;
|
|
|
|
|
2024-04-18 02:52:20 -07:00
|
|
|
/* succeeded, so commit it to the data structures */
|
|
|
|
conf = &new_ctx->conf;
|
|
|
|
list_add(&link->assigned_chanctx_list,
|
|
|
|
&new_ctx->assigned_links);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ret = 0;
|
2014-03-11 09:24:12 -07:00
|
|
|
}
|
2012-06-26 05:37:22 -07:00
|
|
|
|
2022-06-17 13:36:37 -07:00
|
|
|
rcu_assign_pointer(link->conf->chanctx_conf, conf);
|
2013-02-06 16:14:51 -07:00
|
|
|
|
2014-04-09 06:29:33 -07:00
|
|
|
if (curr_ctx && ieee80211_chanctx_num_assigned(local, curr_ctx) > 0) {
|
2014-03-11 09:24:12 -07:00
|
|
|
ieee80211_recalc_chanctx_chantype(local, curr_ctx);
|
|
|
|
ieee80211_recalc_smps_chanctx(local, curr_ctx);
|
|
|
|
ieee80211_recalc_radar_chanctx(local, curr_ctx);
|
2024-06-12 05:32:06 -07:00
|
|
|
ieee80211_recalc_chanctx_min_def(local, curr_ctx, NULL, false);
|
2012-09-11 05:34:12 -07:00
|
|
|
}
|
2012-06-26 05:37:22 -07:00
|
|
|
|
2014-04-09 06:29:33 -07:00
|
|
|
if (new_ctx && ieee80211_chanctx_num_assigned(local, new_ctx) > 0) {
|
2015-01-14 04:55:08 -07:00
|
|
|
ieee80211_recalc_txpower(sdata, false);
|
2024-06-12 05:32:06 -07:00
|
|
|
ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL, false);
|
2012-09-11 05:34:12 -07:00
|
|
|
}
|
2014-03-11 09:24:12 -07:00
|
|
|
|
2024-04-18 01:52:19 -07:00
|
|
|
if (conf) {
|
|
|
|
new_idle = false;
|
|
|
|
} else {
|
|
|
|
struct ieee80211_link_data *tmp;
|
|
|
|
|
|
|
|
new_idle = true;
|
|
|
|
for_each_sdata_link(local, tmp) {
|
|
|
|
if (rcu_access_pointer(tmp->conf->chanctx_conf)) {
|
|
|
|
new_idle = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (new_idle != sdata->vif.cfg.idle) {
|
|
|
|
sdata->vif.cfg.idle = new_idle;
|
|
|
|
|
|
|
|
if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
|
|
|
|
sdata->vif.type != NL80211_IFTYPE_MONITOR)
|
|
|
|
ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_IDLE);
|
|
|
|
}
|
2014-03-11 09:24:12 -07:00
|
|
|
|
2015-03-21 07:25:43 -07:00
|
|
|
ieee80211_check_fast_xmit_iface(sdata);
|
|
|
|
|
2014-03-11 09:24:12 -07:00
|
|
|
return ret;
|
2012-06-26 05:37:16 -07:00
|
|
|
}
|
|
|
|
|
2012-09-11 05:34:12 -07:00
|
|
|
void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
|
|
|
|
struct ieee80211_chanctx *chanctx)
|
|
|
|
{
|
|
|
|
struct ieee80211_sub_if_data *sdata;
|
|
|
|
u8 rx_chains_static, rx_chains_dynamic;
|
2024-01-29 11:34:41 -07:00
|
|
|
struct ieee80211_link_data *link;
|
2012-09-11 05:34:12 -07:00
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2012-09-11 05:34:12 -07:00
|
|
|
|
|
|
|
rx_chains_static = 1;
|
|
|
|
rx_chains_dynamic = 1;
|
|
|
|
|
2024-01-29 11:34:41 -07:00
|
|
|
for_each_sdata_link(local, link) {
|
2012-09-11 05:34:12 -07:00
|
|
|
u8 needed_static, needed_dynamic;
|
|
|
|
|
2024-01-29 11:34:41 -07:00
|
|
|
switch (link->sdata->vif.type) {
|
2012-09-11 05:34:12 -07:00
|
|
|
case NL80211_IFTYPE_STATION:
|
2024-01-29 11:34:41 -07:00
|
|
|
if (!link->sdata->u.mgd.associated)
|
2012-09-11 05:34:12 -07:00
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
case NL80211_IFTYPE_AP:
|
|
|
|
case NL80211_IFTYPE_ADHOC:
|
|
|
|
case NL80211_IFTYPE_MESH_POINT:
|
2014-11-03 02:33:19 -07:00
|
|
|
case NL80211_IFTYPE_OCB:
|
2012-09-11 05:34:12 -07:00
|
|
|
break;
|
|
|
|
default:
|
2022-05-30 09:35:23 -07:00
|
|
|
continue;
|
2012-09-11 05:34:12 -07:00
|
|
|
}
|
|
|
|
|
2024-01-29 11:34:41 -07:00
|
|
|
if (rcu_access_pointer(link->conf->chanctx_conf) != &chanctx->conf)
|
|
|
|
continue;
|
2012-09-11 05:34:12 -07:00
|
|
|
|
2024-01-29 11:34:41 -07:00
|
|
|
switch (link->smps_mode) {
|
|
|
|
default:
|
|
|
|
WARN_ONCE(1, "Invalid SMPS mode %d\n",
|
|
|
|
link->smps_mode);
|
|
|
|
fallthrough;
|
|
|
|
case IEEE80211_SMPS_OFF:
|
|
|
|
needed_static = link->needed_rx_chains;
|
|
|
|
needed_dynamic = link->needed_rx_chains;
|
|
|
|
break;
|
|
|
|
case IEEE80211_SMPS_DYNAMIC:
|
|
|
|
needed_static = 1;
|
|
|
|
needed_dynamic = link->needed_rx_chains;
|
|
|
|
break;
|
|
|
|
case IEEE80211_SMPS_STATIC:
|
|
|
|
needed_static = 1;
|
|
|
|
needed_dynamic = 1;
|
|
|
|
break;
|
2022-05-30 09:35:23 -07:00
|
|
|
}
|
2024-01-29 11:34:41 -07:00
|
|
|
|
|
|
|
rx_chains_static = max(rx_chains_static, needed_static);
|
|
|
|
rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic);
|
2012-09-11 05:34:12 -07:00
|
|
|
}
|
2014-03-24 00:55:45 -07:00
|
|
|
|
|
|
|
/* Disable SMPS for the monitor interface */
|
2024-01-29 11:34:41 -07:00
|
|
|
sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata);
|
2014-03-24 00:55:45 -07:00
|
|
|
if (sdata &&
|
2022-06-17 13:36:37 -07:00
|
|
|
rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) == &chanctx->conf)
|
2014-03-24 00:55:45 -07:00
|
|
|
rx_chains_dynamic = rx_chains_static = local->rx_chains;
|
|
|
|
|
2012-09-11 05:34:12 -07:00
|
|
|
if (rx_chains_static == chanctx->conf.rx_chains_static &&
|
|
|
|
rx_chains_dynamic == chanctx->conf.rx_chains_dynamic)
|
|
|
|
return;
|
|
|
|
|
|
|
|
chanctx->conf.rx_chains_static = rx_chains_static;
|
|
|
|
chanctx->conf.rx_chains_dynamic = rx_chains_dynamic;
|
|
|
|
drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RX_CHAINS);
|
|
|
|
}
|
|
|
|
|
2013-10-30 04:09:39 -07:00
|
|
|
static void
|
2022-05-30 09:35:23 -07:00
|
|
|
__ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data *link,
|
|
|
|
bool clear)
|
2013-10-30 04:09:39 -07:00
|
|
|
{
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_sub_if_data *sdata = link->sdata;
|
|
|
|
unsigned int link_id = link->link_id;
|
2022-06-17 13:36:37 -07:00
|
|
|
struct ieee80211_bss_conf *link_conf = link->conf;
|
2014-04-09 12:31:13 -07:00
|
|
|
struct ieee80211_local *local __maybe_unused = sdata->local;
|
2013-10-30 04:09:39 -07:00
|
|
|
struct ieee80211_sub_if_data *vlan;
|
|
|
|
struct ieee80211_chanctx_conf *conf;
|
|
|
|
|
|
|
|
if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP))
|
|
|
|
return;
|
|
|
|
|
2023-08-28 05:00:05 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2013-10-30 04:09:39 -07:00
|
|
|
|
|
|
|
/* Check that conf exists, even when clearing this function
|
|
|
|
* must be called with the AP's channel context still there
|
|
|
|
* as it would otherwise cause VLANs to have an invalid
|
|
|
|
* channel context pointer for a while, possibly pointing
|
|
|
|
* to a channel context that has already been freed.
|
|
|
|
*/
|
2022-05-30 09:35:23 -07:00
|
|
|
conf = rcu_dereference_protected(link_conf->chanctx_conf,
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_is_held(&local->hw.wiphy->mtx));
|
2013-10-30 04:09:39 -07:00
|
|
|
WARN_ON(!conf);
|
|
|
|
|
|
|
|
if (clear)
|
|
|
|
conf = NULL;
|
|
|
|
|
2022-06-17 13:36:37 -07:00
|
|
|
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
|
|
|
|
struct ieee80211_bss_conf *vlan_conf;
|
|
|
|
|
2024-01-29 11:34:41 -07:00
|
|
|
vlan_conf = wiphy_dereference(local->hw.wiphy,
|
|
|
|
vlan->vif.link_conf[link_id]);
|
2022-06-17 13:36:37 -07:00
|
|
|
if (WARN_ON(!vlan_conf))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
rcu_assign_pointer(vlan_conf->chanctx_conf, conf);
|
|
|
|
}
|
2013-10-30 04:09:39 -07:00
|
|
|
}
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
void ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data *link,
|
|
|
|
bool clear)
|
2013-10-30 04:09:39 -07:00
|
|
|
{
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_local *local = link->sdata->local;
|
2013-10-30 04:09:39 -07:00
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2013-10-30 04:09:39 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
__ieee80211_link_copy_chanctx_to_vlans(link, clear);
|
2013-10-30 04:09:39 -07:00
|
|
|
}
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link)
|
2013-10-30 04:09:39 -07:00
|
|
|
{
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_sub_if_data *sdata = link->sdata;
|
|
|
|
struct ieee80211_chanctx *ctx = link->reserved_chanctx;
|
2014-04-09 06:29:27 -07:00
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(sdata->local->hw.wiphy);
|
2013-10-30 04:09:39 -07:00
|
|
|
|
2014-04-09 06:29:27 -07:00
|
|
|
if (WARN_ON(!ctx))
|
2013-07-11 07:09:06 -07:00
|
|
|
return -EINVAL;
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
list_del(&link->reserved_chanctx_list);
|
|
|
|
link->reserved_chanctx = NULL;
|
2013-10-30 04:09:39 -07:00
|
|
|
|
2014-06-25 03:35:06 -07:00
|
|
|
if (ieee80211_chanctx_refcount(sdata->local, ctx) == 0) {
|
|
|
|
if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) {
|
|
|
|
if (WARN_ON(!ctx->replace_ctx))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
WARN_ON(ctx->replace_ctx->replace_state !=
|
|
|
|
IEEE80211_CHANCTX_WILL_BE_REPLACED);
|
|
|
|
WARN_ON(ctx->replace_ctx->replace_ctx != ctx);
|
|
|
|
|
|
|
|
ctx->replace_ctx->replace_ctx = NULL;
|
|
|
|
ctx->replace_ctx->replace_state =
|
|
|
|
IEEE80211_CHANCTX_REPLACE_NONE;
|
|
|
|
|
|
|
|
list_del_rcu(&ctx->list);
|
|
|
|
kfree_rcu(ctx, rcu_head);
|
|
|
|
} else {
|
2024-03-20 00:13:59 -07:00
|
|
|
ieee80211_free_chanctx(sdata->local, ctx, false);
|
2014-06-25 03:35:06 -07:00
|
|
|
}
|
|
|
|
}
|
2014-04-09 06:29:27 -07:00
|
|
|
|
2013-10-30 04:09:39 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-07-09 01:38:36 -07:00
|
|
|
static struct ieee80211_chanctx *
|
|
|
|
ieee80211_replace_chanctx(struct ieee80211_local *local,
|
|
|
|
const struct ieee80211_chan_req *chanreq,
|
|
|
|
enum ieee80211_chanctx_mode mode,
|
|
|
|
struct ieee80211_chanctx *curr_ctx)
|
|
|
|
{
|
|
|
|
struct ieee80211_chanctx *new_ctx, *ctx;
|
2024-07-09 01:38:37 -07:00
|
|
|
struct wiphy *wiphy = local->hw.wiphy;
|
|
|
|
const struct wiphy_radio *radio;
|
2024-07-09 01:38:36 -07:00
|
|
|
|
|
|
|
if (!curr_ctx || (curr_ctx->replace_state ==
|
|
|
|
IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
|
|
|
|
!list_empty(&curr_ctx->reserved_links)) {
|
|
|
|
/*
|
|
|
|
* Another link already requested this context for a
|
|
|
|
* reservation. Find another one hoping all links assigned
|
|
|
|
* to it will also switch soon enough.
|
|
|
|
*
|
|
|
|
* TODO: This needs a little more work as some cases
|
|
|
|
* (more than 2 chanctx capable devices) may fail which could
|
|
|
|
* otherwise succeed provided some channel context juggling was
|
|
|
|
* performed.
|
|
|
|
*
|
|
|
|
* Consider ctx1..3, link1..6, each ctx has 2 links. link1 and
|
|
|
|
* link2 from ctx1 request new different chandefs starting 2
|
|
|
|
* in-place reserations with ctx4 and ctx5 replacing ctx1 and
|
|
|
|
* ctx2 respectively. Next link5 and link6 from ctx3 reserve
|
|
|
|
* ctx4. If link3 and link4 remain on ctx2 as they are then this
|
|
|
|
* fails unless `replace_ctx` from ctx5 is replaced with ctx3.
|
|
|
|
*/
|
|
|
|
list_for_each_entry(ctx, &local->chanctx_list, list) {
|
|
|
|
if (ctx->replace_state !=
|
|
|
|
IEEE80211_CHANCTX_REPLACE_NONE)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!list_empty(&ctx->reserved_links))
|
|
|
|
continue;
|
|
|
|
|
2024-07-09 01:38:37 -07:00
|
|
|
if (ctx->conf.radio_idx >= 0) {
|
|
|
|
radio = &wiphy->radio[ctx->conf.radio_idx];
|
|
|
|
if (!cfg80211_radio_chandef_valid(radio, &chanreq->oper))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2024-07-09 01:38:36 -07:00
|
|
|
curr_ctx = ctx;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If that's true then all available contexts already have reservations
|
|
|
|
* and cannot be used.
|
|
|
|
*/
|
|
|
|
if (!curr_ctx || (curr_ctx->replace_state ==
|
|
|
|
IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
|
|
|
|
!list_empty(&curr_ctx->reserved_links))
|
|
|
|
return ERR_PTR(-EBUSY);
|
|
|
|
|
|
|
|
new_ctx = ieee80211_alloc_chanctx(local, chanreq, mode, -1);
|
|
|
|
if (!new_ctx)
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
|
|
new_ctx->replace_ctx = curr_ctx;
|
|
|
|
new_ctx->replace_state = IEEE80211_CHANCTX_REPLACES_OTHER;
|
|
|
|
|
|
|
|
curr_ctx->replace_ctx = new_ctx;
|
|
|
|
curr_ctx->replace_state = IEEE80211_CHANCTX_WILL_BE_REPLACED;
|
|
|
|
|
|
|
|
list_add_rcu(&new_ctx->list, &local->chanctx_list);
|
|
|
|
|
|
|
|
return new_ctx;
|
|
|
|
}
|
|
|
|
|
2024-07-09 01:38:37 -07:00
|
|
|
static bool
|
|
|
|
ieee80211_find_available_radio(struct ieee80211_local *local,
|
|
|
|
const struct ieee80211_chan_req *chanreq,
|
|
|
|
int *radio_idx)
|
|
|
|
{
|
|
|
|
struct wiphy *wiphy = local->hw.wiphy;
|
|
|
|
const struct wiphy_radio *radio;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
*radio_idx = -1;
|
|
|
|
if (!wiphy->n_radio)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
for (i = 0; i < wiphy->n_radio; i++) {
|
|
|
|
radio = &wiphy->radio[i];
|
|
|
|
if (!cfg80211_radio_chandef_valid(radio, &chanreq->oper))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!ieee80211_can_create_new_chanctx(local, i))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
*radio_idx = i;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
int ieee80211_link_reserve_chanctx(struct ieee80211_link_data *link,
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
const struct ieee80211_chan_req *chanreq,
|
2022-05-30 09:35:23 -07:00
|
|
|
enum ieee80211_chanctx_mode mode,
|
|
|
|
bool radar_required)
|
2013-10-30 04:09:39 -07:00
|
|
|
{
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_sub_if_data *sdata = link->sdata;
|
2013-10-30 04:09:39 -07:00
|
|
|
struct ieee80211_local *local = sdata->local;
|
2024-07-09 01:38:36 -07:00
|
|
|
struct ieee80211_chanctx *new_ctx, *curr_ctx;
|
2024-07-09 01:38:37 -07:00
|
|
|
int radio_idx;
|
2013-10-30 04:09:39 -07:00
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2013-07-11 07:09:06 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
curr_ctx = ieee80211_link_get_chanctx(link);
|
2024-01-29 11:34:38 -07:00
|
|
|
if (curr_ctx && !local->ops->switch_vif_chanctx)
|
2023-12-11 00:05:25 -07:00
|
|
|
return -EOPNOTSUPP;
|
2013-10-30 04:09:39 -07:00
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
new_ctx = ieee80211_find_reservation_chanctx(local, chanreq, mode);
|
2013-10-30 04:09:39 -07:00
|
|
|
if (!new_ctx) {
|
2024-07-09 01:38:37 -07:00
|
|
|
if (ieee80211_can_create_new_chanctx(local, -1) &&
|
|
|
|
ieee80211_find_available_radio(local, chanreq, &radio_idx))
|
2024-04-18 02:52:21 -07:00
|
|
|
new_ctx = ieee80211_new_chanctx(local, chanreq, mode,
|
2024-07-09 01:38:37 -07:00
|
|
|
false, radio_idx);
|
2024-07-09 01:38:36 -07:00
|
|
|
else
|
|
|
|
new_ctx = ieee80211_replace_chanctx(local, chanreq,
|
|
|
|
mode, curr_ctx);
|
|
|
|
if (IS_ERR(new_ctx))
|
|
|
|
return PTR_ERR(new_ctx);
|
2013-10-30 04:09:39 -07:00
|
|
|
}
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
list_add(&link->reserved_chanctx_list, &new_ctx->reserved_links);
|
|
|
|
link->reserved_chanctx = new_ctx;
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
link->reserved = *chanreq;
|
2022-05-30 09:35:23 -07:00
|
|
|
link->reserved_radar_required = radar_required;
|
|
|
|
link->reserved_ready = false;
|
2014-06-25 03:35:06 -07:00
|
|
|
|
|
|
|
return 0;
|
2013-10-30 04:09:39 -07:00
|
|
|
}
|
|
|
|
|
2014-06-25 03:35:08 -07:00
|
|
|
static void
|
2022-05-30 09:35:23 -07:00
|
|
|
ieee80211_link_chanctx_reservation_complete(struct ieee80211_link_data *link)
|
2014-06-25 03:35:08 -07:00
|
|
|
{
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_sub_if_data *sdata = link->sdata;
|
|
|
|
|
2014-06-25 03:35:08 -07:00
|
|
|
switch (sdata->vif.type) {
|
|
|
|
case NL80211_IFTYPE_ADHOC:
|
|
|
|
case NL80211_IFTYPE_AP:
|
|
|
|
case NL80211_IFTYPE_MESH_POINT:
|
2014-11-03 02:33:18 -07:00
|
|
|
case NL80211_IFTYPE_OCB:
|
2023-08-28 04:59:50 -07:00
|
|
|
wiphy_work_queue(sdata->local->hw.wiphy,
|
2024-05-06 12:54:49 -07:00
|
|
|
&link->csa.finalize_work);
|
2014-06-25 03:35:08 -07:00
|
|
|
break;
|
|
|
|
case NL80211_IFTYPE_STATION:
|
2023-06-06 05:49:29 -07:00
|
|
|
wiphy_delayed_work_queue(sdata->local->hw.wiphy,
|
2024-05-06 12:54:49 -07:00
|
|
|
&link->u.mgd.csa.switch_work, 0);
|
2014-06-25 03:35:09 -07:00
|
|
|
break;
|
|
|
|
case NL80211_IFTYPE_UNSPECIFIED:
|
2014-06-25 03:35:08 -07:00
|
|
|
case NL80211_IFTYPE_AP_VLAN:
|
|
|
|
case NL80211_IFTYPE_WDS:
|
|
|
|
case NL80211_IFTYPE_MONITOR:
|
|
|
|
case NL80211_IFTYPE_P2P_CLIENT:
|
|
|
|
case NL80211_IFTYPE_P2P_GO:
|
|
|
|
case NL80211_IFTYPE_P2P_DEVICE:
|
2016-09-20 07:31:13 -07:00
|
|
|
case NL80211_IFTYPE_NAN:
|
2014-06-25 03:35:08 -07:00
|
|
|
case NUM_NL80211_IFTYPES:
|
|
|
|
WARN_ON(1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-24 10:12:16 -07:00
|
|
|
static void
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
ieee80211_link_update_chanreq(struct ieee80211_link_data *link,
|
|
|
|
const struct ieee80211_chan_req *chanreq)
|
2014-11-24 10:12:16 -07:00
|
|
|
{
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_sub_if_data *sdata = link->sdata;
|
|
|
|
unsigned int link_id = link->link_id;
|
2014-11-24 10:12:16 -07:00
|
|
|
struct ieee80211_sub_if_data *vlan;
|
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
link->conf->chanreq = *chanreq;
|
2014-11-24 10:12:16 -07:00
|
|
|
|
|
|
|
if (sdata->vif.type != NL80211_IFTYPE_AP)
|
|
|
|
return;
|
|
|
|
|
2022-06-17 13:36:37 -07:00
|
|
|
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
|
|
|
|
struct ieee80211_bss_conf *vlan_conf;
|
|
|
|
|
2024-01-29 11:34:41 -07:00
|
|
|
vlan_conf = wiphy_dereference(sdata->local->hw.wiphy,
|
|
|
|
vlan->vif.link_conf[link_id]);
|
2022-06-17 13:36:37 -07:00
|
|
|
if (WARN_ON(!vlan_conf))
|
|
|
|
continue;
|
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
vlan_conf->chanreq = *chanreq;
|
2022-06-17 13:36:37 -07:00
|
|
|
}
|
2014-11-24 10:12:16 -07:00
|
|
|
}
|
|
|
|
|
2014-06-25 03:35:06 -07:00
|
|
|
static int
|
2022-05-30 09:35:23 -07:00
|
|
|
ieee80211_link_use_reserved_reassign(struct ieee80211_link_data *link)
|
2013-10-30 04:09:39 -07:00
|
|
|
{
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_sub_if_data *sdata = link->sdata;
|
2022-06-17 13:36:37 -07:00
|
|
|
struct ieee80211_bss_conf *link_conf = link->conf;
|
2013-10-30 04:09:39 -07:00
|
|
|
struct ieee80211_local *local = sdata->local;
|
2014-06-25 03:35:06 -07:00
|
|
|
struct ieee80211_vif_chanctx_switch vif_chsw[1] = {};
|
|
|
|
struct ieee80211_chanctx *old_ctx, *new_ctx;
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
const struct ieee80211_chan_req *chanreq;
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
struct ieee80211_chan_req tmp;
|
2023-06-04 02:11:26 -07:00
|
|
|
u64 changed = 0;
|
2014-06-25 03:35:06 -07:00
|
|
|
int err;
|
2013-10-30 04:09:39 -07:00
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2013-10-30 04:09:39 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
new_ctx = link->reserved_chanctx;
|
|
|
|
old_ctx = ieee80211_link_get_chanctx(link);
|
2013-10-30 04:09:39 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
if (WARN_ON(!link->reserved_ready))
|
2014-06-25 03:35:06 -07:00
|
|
|
return -EBUSY;
|
2013-07-11 07:09:06 -07:00
|
|
|
|
2014-06-25 03:35:06 -07:00
|
|
|
if (WARN_ON(!new_ctx))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (WARN_ON(!old_ctx))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (WARN_ON(new_ctx->replace_state ==
|
|
|
|
IEEE80211_CHANCTX_REPLACES_OTHER))
|
|
|
|
return -EINVAL;
|
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
chanreq = ieee80211_chanctx_non_reserved_chandef(local, new_ctx,
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
&link->reserved,
|
|
|
|
&tmp);
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
if (WARN_ON(!chanreq))
|
2014-06-25 03:35:06 -07:00
|
|
|
return -EINVAL;
|
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
if (link_conf->chanreq.oper.width != link->reserved.oper.width)
|
2021-06-18 03:41:30 -07:00
|
|
|
changed = BSS_CHANGED_BANDWIDTH;
|
2020-12-06 05:54:50 -07:00
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
ieee80211_link_update_chanreq(link, &link->reserved);
|
2015-05-06 08:30:50 -07:00
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
_ieee80211_change_chanctx(local, new_ctx, old_ctx, chanreq, link);
|
2020-12-06 05:54:50 -07:00
|
|
|
|
2014-06-25 03:35:06 -07:00
|
|
|
vif_chsw[0].vif = &sdata->vif;
|
|
|
|
vif_chsw[0].old_ctx = &old_ctx->conf;
|
|
|
|
vif_chsw[0].new_ctx = &new_ctx->conf;
|
2022-07-03 08:04:15 -07:00
|
|
|
vif_chsw[0].link_conf = link->conf;
|
2014-06-25 03:35:06 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
list_del(&link->reserved_chanctx_list);
|
|
|
|
link->reserved_chanctx = NULL;
|
2014-06-25 03:35:06 -07:00
|
|
|
|
|
|
|
err = drv_switch_vif_chanctx(local, vif_chsw, 1,
|
|
|
|
CHANCTX_SWMODE_REASSIGN_VIF);
|
|
|
|
if (err) {
|
|
|
|
if (ieee80211_chanctx_refcount(local, new_ctx) == 0)
|
2024-03-20 00:13:59 -07:00
|
|
|
ieee80211_free_chanctx(local, new_ctx, false);
|
2014-06-25 03:35:06 -07:00
|
|
|
|
2014-06-25 03:35:08 -07:00
|
|
|
goto out;
|
2013-07-11 07:09:06 -07:00
|
|
|
}
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
list_move(&link->assigned_chanctx_list, &new_ctx->assigned_links);
|
|
|
|
rcu_assign_pointer(link_conf->chanctx_conf, &new_ctx->conf);
|
2014-06-25 03:35:06 -07:00
|
|
|
|
|
|
|
if (sdata->vif.type == NL80211_IFTYPE_AP)
|
2022-05-30 09:35:23 -07:00
|
|
|
__ieee80211_link_copy_chanctx_to_vlans(link, false);
|
2014-06-25 03:35:06 -07:00
|
|
|
|
2015-03-21 07:25:43 -07:00
|
|
|
ieee80211_check_fast_xmit_iface(sdata);
|
|
|
|
|
2014-06-25 03:35:06 -07:00
|
|
|
if (ieee80211_chanctx_refcount(local, old_ctx) == 0)
|
2024-03-20 00:13:59 -07:00
|
|
|
ieee80211_free_chanctx(local, old_ctx, false);
|
2013-07-11 07:09:06 -07:00
|
|
|
|
2024-06-12 05:32:06 -07:00
|
|
|
ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL, false);
|
2014-11-30 08:17:26 -07:00
|
|
|
ieee80211_recalc_smps_chanctx(local, new_ctx);
|
|
|
|
ieee80211_recalc_radar_chanctx(local, new_ctx);
|
|
|
|
|
2014-06-25 03:35:06 -07:00
|
|
|
if (changed)
|
2022-06-17 13:36:37 -07:00
|
|
|
ieee80211_link_info_change_notify(sdata, link, changed);
|
2014-06-25 03:35:06 -07:00
|
|
|
|
2014-06-25 03:35:08 -07:00
|
|
|
out:
|
2022-05-30 09:35:23 -07:00
|
|
|
ieee80211_link_chanctx_reservation_complete(link);
|
2014-06-25 03:35:06 -07:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2022-05-30 09:35:23 -07:00
|
|
|
ieee80211_link_use_reserved_assign(struct ieee80211_link_data *link)
|
2014-06-25 03:35:06 -07:00
|
|
|
{
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_sub_if_data *sdata = link->sdata;
|
2014-06-25 03:35:06 -07:00
|
|
|
struct ieee80211_local *local = sdata->local;
|
|
|
|
struct ieee80211_chanctx *old_ctx, *new_ctx;
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
const struct ieee80211_chan_req *chanreq;
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
struct ieee80211_chan_req tmp;
|
2014-06-25 03:35:06 -07:00
|
|
|
int err;
|
|
|
|
|
2022-06-17 13:36:37 -07:00
|
|
|
old_ctx = ieee80211_link_get_chanctx(link);
|
2022-05-30 09:35:23 -07:00
|
|
|
new_ctx = link->reserved_chanctx;
|
2014-06-25 03:35:06 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
if (WARN_ON(!link->reserved_ready))
|
2014-06-25 03:35:06 -07:00
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (WARN_ON(old_ctx))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (WARN_ON(!new_ctx))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (WARN_ON(new_ctx->replace_state ==
|
|
|
|
IEEE80211_CHANCTX_REPLACES_OTHER))
|
|
|
|
return -EINVAL;
|
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
chanreq = ieee80211_chanctx_non_reserved_chandef(local, new_ctx,
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
&link->reserved,
|
|
|
|
&tmp);
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
if (WARN_ON(!chanreq))
|
2014-06-25 03:35:06 -07:00
|
|
|
return -EINVAL;
|
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
ieee80211_change_chanctx(local, new_ctx, new_ctx, chanreq);
|
2015-05-06 08:30:50 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
list_del(&link->reserved_chanctx_list);
|
|
|
|
link->reserved_chanctx = NULL;
|
2013-10-30 04:09:39 -07:00
|
|
|
|
2024-04-18 02:52:21 -07:00
|
|
|
err = ieee80211_assign_link_chanctx(link, new_ctx, false);
|
2014-06-25 03:35:06 -07:00
|
|
|
if (err) {
|
|
|
|
if (ieee80211_chanctx_refcount(local, new_ctx) == 0)
|
2024-03-20 00:13:59 -07:00
|
|
|
ieee80211_free_chanctx(local, new_ctx, false);
|
2014-06-25 03:35:06 -07:00
|
|
|
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
2022-05-30 09:35:23 -07:00
|
|
|
ieee80211_link_chanctx_reservation_complete(link);
|
2014-06-25 03:35:06 -07:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
2022-05-30 09:35:23 -07:00
|
|
|
ieee80211_link_has_in_place_reservation(struct ieee80211_link_data *link)
|
2014-06-25 03:35:06 -07:00
|
|
|
{
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_sub_if_data *sdata = link->sdata;
|
2014-06-25 03:35:06 -07:00
|
|
|
struct ieee80211_chanctx *old_ctx, *new_ctx;
|
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(sdata->local->hw.wiphy);
|
2014-06-25 03:35:06 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
new_ctx = link->reserved_chanctx;
|
|
|
|
old_ctx = ieee80211_link_get_chanctx(link);
|
2014-06-25 03:35:06 -07:00
|
|
|
|
|
|
|
if (!old_ctx)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (WARN_ON(!new_ctx))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (old_ctx->replace_state != IEEE80211_CHANCTX_WILL_BE_REPLACED)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (new_ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ieee80211_chsw_switch_vifs(struct ieee80211_local *local,
|
|
|
|
int n_vifs)
|
|
|
|
{
|
|
|
|
struct ieee80211_vif_chanctx_switch *vif_chsw;
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_link_data *link;
|
2014-06-25 03:35:06 -07:00
|
|
|
struct ieee80211_chanctx *ctx, *old_ctx;
|
|
|
|
int i, err;
|
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2014-06-25 03:35:06 -07:00
|
|
|
|
treewide: kzalloc() -> kcalloc()
The kzalloc() function has a 2-factor argument form, kcalloc(). This
patch replaces cases of:
kzalloc(a * b, gfp)
with:
kcalloc(a * b, gfp)
as well as handling cases of:
kzalloc(a * b * c, gfp)
with:
kzalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kzalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kzalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kzalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kzalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kzalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kzalloc
+ kcalloc
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kzalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kzalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kzalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kzalloc(sizeof(THING) * C2, ...)
|
kzalloc(sizeof(TYPE) * C2, ...)
|
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(C1 * C2, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * E2
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-12 14:03:40 -07:00
|
|
|
vif_chsw = kcalloc(n_vifs, sizeof(vif_chsw[0]), GFP_KERNEL);
|
2014-06-25 03:35:06 -07:00
|
|
|
if (!vif_chsw)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
list_for_each_entry(ctx, &local->chanctx_list, list) {
|
|
|
|
if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (WARN_ON(!ctx->replace_ctx)) {
|
|
|
|
err = -EINVAL;
|
2014-02-27 05:33:47 -07:00
|
|
|
goto out;
|
|
|
|
}
|
2013-10-30 04:09:39 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
list_for_each_entry(link, &ctx->reserved_links,
|
2014-06-25 03:35:06 -07:00
|
|
|
reserved_chanctx_list) {
|
2022-05-30 09:35:23 -07:00
|
|
|
if (!ieee80211_link_has_in_place_reservation(link))
|
2014-06-25 03:35:06 -07:00
|
|
|
continue;
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
old_ctx = ieee80211_link_get_chanctx(link);
|
|
|
|
vif_chsw[i].vif = &link->sdata->vif;
|
2014-06-25 03:35:06 -07:00
|
|
|
vif_chsw[i].old_ctx = &old_ctx->conf;
|
|
|
|
vif_chsw[i].new_ctx = &ctx->conf;
|
2022-07-03 08:04:15 -07:00
|
|
|
vif_chsw[i].link_conf = link->conf;
|
2014-06-25 03:35:06 -07:00
|
|
|
|
|
|
|
i++;
|
|
|
|
}
|
2014-02-27 05:33:47 -07:00
|
|
|
}
|
2013-10-30 04:09:39 -07:00
|
|
|
|
2014-06-25 03:35:06 -07:00
|
|
|
err = drv_switch_vif_chanctx(local, vif_chsw, n_vifs,
|
|
|
|
CHANCTX_SWMODE_SWAP_CONTEXTS);
|
2013-07-11 07:09:06 -07:00
|
|
|
|
2013-10-30 04:09:39 -07:00
|
|
|
out:
|
2014-06-25 03:35:06 -07:00
|
|
|
kfree(vif_chsw);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ieee80211_chsw_switch_ctxs(struct ieee80211_local *local)
|
|
|
|
{
|
|
|
|
struct ieee80211_chanctx *ctx;
|
|
|
|
int err;
|
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2014-06-25 03:35:06 -07:00
|
|
|
|
|
|
|
list_for_each_entry(ctx, &local->chanctx_list, list) {
|
|
|
|
if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
|
|
|
|
continue;
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
if (!list_empty(&ctx->replace_ctx->assigned_links))
|
2014-06-25 03:35:06 -07:00
|
|
|
continue;
|
|
|
|
|
2024-03-20 00:13:59 -07:00
|
|
|
ieee80211_del_chanctx(local, ctx->replace_ctx, false);
|
2014-06-25 03:35:06 -07:00
|
|
|
err = ieee80211_add_chanctx(local, ctx);
|
|
|
|
if (err)
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err:
|
|
|
|
WARN_ON(ieee80211_add_chanctx(local, ctx));
|
|
|
|
list_for_each_entry_continue_reverse(ctx, &local->chanctx_list, list) {
|
|
|
|
if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
|
|
|
|
continue;
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
if (!list_empty(&ctx->replace_ctx->assigned_links))
|
2014-06-25 03:35:06 -07:00
|
|
|
continue;
|
|
|
|
|
2024-03-20 00:13:59 -07:00
|
|
|
ieee80211_del_chanctx(local, ctx, false);
|
2014-06-25 03:35:06 -07:00
|
|
|
WARN_ON(ieee80211_add_chanctx(local, ctx->replace_ctx));
|
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2014-07-25 06:01:59 -07:00
|
|
|
static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
|
2014-06-25 03:35:06 -07:00
|
|
|
{
|
|
|
|
struct ieee80211_chanctx *ctx, *ctx_tmp, *old_ctx;
|
2016-11-23 21:45:36 -07:00
|
|
|
int err, n_assigned, n_reserved, n_ready;
|
2014-06-25 03:35:06 -07:00
|
|
|
int n_ctx = 0, n_vifs_switch = 0, n_vifs_assign = 0, n_vifs_ctxless = 0;
|
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2014-06-25 03:35:06 -07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If there are 2 independent pairs of channel contexts performing
|
|
|
|
* cross-switch of their vifs this code will still wait until both are
|
|
|
|
* ready even though it could be possible to switch one before the
|
|
|
|
* other is ready.
|
|
|
|
*
|
|
|
|
* For practical reasons and code simplicity just do a single huge
|
|
|
|
* switch.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Verify if the reservation is still feasible.
|
|
|
|
* - if it's not then disconnect
|
|
|
|
* - if it is but not all vifs necessary are ready then defer
|
|
|
|
*/
|
|
|
|
|
|
|
|
list_for_each_entry(ctx, &local->chanctx_list, list) {
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_link_data *link;
|
|
|
|
|
2014-06-25 03:35:06 -07:00
|
|
|
if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (WARN_ON(!ctx->replace_ctx)) {
|
|
|
|
err = -EINVAL;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
n_ctx++;
|
|
|
|
|
|
|
|
n_assigned = 0;
|
|
|
|
n_reserved = 0;
|
|
|
|
n_ready = 0;
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
list_for_each_entry(link, &ctx->replace_ctx->assigned_links,
|
2014-06-25 03:35:06 -07:00
|
|
|
assigned_chanctx_list) {
|
|
|
|
n_assigned++;
|
2022-05-30 09:35:23 -07:00
|
|
|
if (link->reserved_chanctx) {
|
2014-06-25 03:35:06 -07:00
|
|
|
n_reserved++;
|
2022-05-30 09:35:23 -07:00
|
|
|
if (link->reserved_ready)
|
2014-06-25 03:35:06 -07:00
|
|
|
n_ready++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (n_assigned != n_reserved) {
|
|
|
|
if (n_ready == n_reserved) {
|
|
|
|
wiphy_info(local->hw.wiphy,
|
|
|
|
"channel context reservation cannot be finalized because some interfaces aren't switching\n");
|
|
|
|
err = -EBUSY;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -EAGAIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx->conf.radar_enabled = false;
|
2022-05-30 09:35:23 -07:00
|
|
|
list_for_each_entry(link, &ctx->reserved_links,
|
2014-06-25 03:35:06 -07:00
|
|
|
reserved_chanctx_list) {
|
2022-05-30 09:35:23 -07:00
|
|
|
if (ieee80211_link_has_in_place_reservation(link) &&
|
|
|
|
!link->reserved_ready)
|
2014-06-25 03:35:06 -07:00
|
|
|
return -EAGAIN;
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
old_ctx = ieee80211_link_get_chanctx(link);
|
2014-06-25 03:35:06 -07:00
|
|
|
if (old_ctx) {
|
|
|
|
if (old_ctx->replace_state ==
|
|
|
|
IEEE80211_CHANCTX_WILL_BE_REPLACED)
|
|
|
|
n_vifs_switch++;
|
|
|
|
else
|
|
|
|
n_vifs_assign++;
|
|
|
|
} else {
|
|
|
|
n_vifs_ctxless++;
|
|
|
|
}
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
if (link->reserved_radar_required)
|
2014-06-25 03:35:06 -07:00
|
|
|
ctx->conf.radar_enabled = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (WARN_ON(n_ctx == 0) ||
|
|
|
|
WARN_ON(n_vifs_switch == 0 &&
|
|
|
|
n_vifs_assign == 0 &&
|
2024-01-29 11:34:38 -07:00
|
|
|
n_vifs_ctxless == 0)) {
|
2014-06-25 03:35:06 -07:00
|
|
|
err = -EINVAL;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2024-06-12 05:32:06 -07:00
|
|
|
/* update station rate control and min width before switch */
|
|
|
|
list_for_each_entry(ctx, &local->chanctx_list, list) {
|
|
|
|
struct ieee80211_link_data *link;
|
|
|
|
|
|
|
|
if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (WARN_ON(!ctx->replace_ctx)) {
|
|
|
|
err = -EINVAL;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
list_for_each_entry(link, &ctx->reserved_links,
|
|
|
|
reserved_chanctx_list) {
|
|
|
|
if (!ieee80211_link_has_in_place_reservation(link))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
ieee80211_chan_bw_change(local,
|
|
|
|
ieee80211_link_get_chanctx(link),
|
|
|
|
true, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
ieee80211_recalc_chanctx_min_def(local, ctx, NULL, true);
|
|
|
|
}
|
|
|
|
|
2014-06-25 03:35:06 -07:00
|
|
|
/*
|
|
|
|
* All necessary vifs are ready. Perform the switch now depending on
|
|
|
|
* reservations and driver capabilities.
|
|
|
|
*/
|
|
|
|
|
2024-01-29 11:34:38 -07:00
|
|
|
if (n_vifs_switch > 0) {
|
|
|
|
err = ieee80211_chsw_switch_vifs(local, n_vifs_switch);
|
|
|
|
if (err)
|
|
|
|
goto err;
|
|
|
|
}
|
2014-06-25 03:35:06 -07:00
|
|
|
|
2024-01-29 11:34:38 -07:00
|
|
|
if (n_vifs_assign > 0 || n_vifs_ctxless > 0) {
|
|
|
|
err = ieee80211_chsw_switch_ctxs(local);
|
2014-06-25 03:35:06 -07:00
|
|
|
if (err)
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Update all structures, values and pointers to point to new channel
|
|
|
|
* context(s).
|
|
|
|
*/
|
|
|
|
list_for_each_entry(ctx, &local->chanctx_list, list) {
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_link_data *link, *link_tmp;
|
|
|
|
|
2014-06-25 03:35:06 -07:00
|
|
|
if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (WARN_ON(!ctx->replace_ctx)) {
|
|
|
|
err = -EINVAL;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
list_for_each_entry(link, &ctx->reserved_links,
|
2014-06-25 03:35:06 -07:00
|
|
|
reserved_chanctx_list) {
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_sub_if_data *sdata = link->sdata;
|
2022-06-17 13:36:37 -07:00
|
|
|
struct ieee80211_bss_conf *link_conf = link->conf;
|
2023-06-04 02:11:26 -07:00
|
|
|
u64 changed = 0;
|
2014-06-25 03:35:06 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
if (!ieee80211_link_has_in_place_reservation(link))
|
2014-06-25 03:35:06 -07:00
|
|
|
continue;
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
rcu_assign_pointer(link_conf->chanctx_conf,
|
wifi: mac80211: move some future per-link data to bss_conf
To add MLD, reuse the bss_conf structure later for per-link
information, so move some things into it that are per link.
Most transformations were done with the following spatch:
@@
expression sdata;
identifier var = { chanctx_conf, mu_mimo_owner, csa_active, color_change_active, color_change_color };
@@
-sdata->vif.var
+sdata->vif.bss_conf.var
@@
struct ieee80211_vif *vif;
identifier var = { chanctx_conf, mu_mimo_owner, csa_active, color_change_active, color_change_color };
@@
-vif->var
+vif->bss_conf.var
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2022-05-10 04:26:44 -07:00
|
|
|
&ctx->conf);
|
2014-06-25 03:35:06 -07:00
|
|
|
|
|
|
|
if (sdata->vif.type == NL80211_IFTYPE_AP)
|
2022-05-30 09:35:23 -07:00
|
|
|
__ieee80211_link_copy_chanctx_to_vlans(link,
|
|
|
|
false);
|
2014-06-25 03:35:06 -07:00
|
|
|
|
2015-03-21 07:25:43 -07:00
|
|
|
ieee80211_check_fast_xmit_iface(sdata);
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
link->radar_required = link->reserved_radar_required;
|
2014-06-25 03:35:06 -07:00
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
if (link_conf->chanreq.oper.width != link->reserved.oper.width)
|
2014-06-25 03:35:06 -07:00
|
|
|
changed = BSS_CHANGED_BANDWIDTH;
|
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
ieee80211_link_update_chanreq(link, &link->reserved);
|
2014-06-25 03:35:06 -07:00
|
|
|
if (changed)
|
2022-05-30 09:35:23 -07:00
|
|
|
ieee80211_link_info_change_notify(sdata,
|
2022-06-17 13:36:37 -07:00
|
|
|
link,
|
2022-05-24 01:55:56 -07:00
|
|
|
changed);
|
2014-06-25 03:35:06 -07:00
|
|
|
|
2015-01-14 04:55:08 -07:00
|
|
|
ieee80211_recalc_txpower(sdata, false);
|
2014-06-25 03:35:06 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
ieee80211_recalc_chanctx_chantype(local, ctx);
|
|
|
|
ieee80211_recalc_smps_chanctx(local, ctx);
|
|
|
|
ieee80211_recalc_radar_chanctx(local, ctx);
|
2024-06-12 05:32:06 -07:00
|
|
|
ieee80211_recalc_chanctx_min_def(local, ctx, NULL, false);
|
2014-06-25 03:35:06 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links,
|
2014-06-25 03:35:06 -07:00
|
|
|
reserved_chanctx_list) {
|
2022-05-30 09:35:23 -07:00
|
|
|
if (ieee80211_link_get_chanctx(link) != ctx)
|
2014-06-25 03:35:06 -07:00
|
|
|
continue;
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
list_del(&link->reserved_chanctx_list);
|
|
|
|
list_move(&link->assigned_chanctx_list,
|
|
|
|
&ctx->assigned_links);
|
|
|
|
link->reserved_chanctx = NULL;
|
2014-06-25 03:35:08 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
ieee80211_link_chanctx_reservation_complete(link);
|
2024-06-12 05:32:06 -07:00
|
|
|
ieee80211_chan_bw_change(local, ctx, false, false);
|
2014-06-25 03:35:06 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This context might have been a dependency for an already
|
|
|
|
* ready re-assign reservation interface that was deferred. Do
|
|
|
|
* not propagate error to the caller though. The in-place
|
|
|
|
* reservation for originally requested interface has already
|
|
|
|
* succeeded at this point.
|
|
|
|
*/
|
2022-05-30 09:35:23 -07:00
|
|
|
list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links,
|
2014-06-25 03:35:06 -07:00
|
|
|
reserved_chanctx_list) {
|
2022-05-30 09:35:23 -07:00
|
|
|
if (WARN_ON(ieee80211_link_has_in_place_reservation(link)))
|
2014-06-25 03:35:06 -07:00
|
|
|
continue;
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
if (WARN_ON(link->reserved_chanctx != ctx))
|
2014-06-25 03:35:06 -07:00
|
|
|
continue;
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
if (!link->reserved_ready)
|
2014-06-25 03:35:06 -07:00
|
|
|
continue;
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
if (ieee80211_link_get_chanctx(link))
|
|
|
|
err = ieee80211_link_use_reserved_reassign(link);
|
2014-06-25 03:35:06 -07:00
|
|
|
else
|
2022-05-30 09:35:23 -07:00
|
|
|
err = ieee80211_link_use_reserved_assign(link);
|
2014-06-25 03:35:06 -07:00
|
|
|
|
|
|
|
if (err) {
|
2022-05-30 09:35:23 -07:00
|
|
|
link_info(link,
|
|
|
|
"failed to finalize (re-)assign reservation (err=%d)\n",
|
|
|
|
err);
|
|
|
|
ieee80211_link_unreserve_chanctx(link);
|
2014-06-25 03:35:06 -07:00
|
|
|
cfg80211_stop_iface(local->hw.wiphy,
|
2022-05-30 09:35:23 -07:00
|
|
|
&link->sdata->wdev,
|
2014-06-25 03:35:06 -07:00
|
|
|
GFP_KERNEL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Finally free old contexts
|
|
|
|
*/
|
|
|
|
|
|
|
|
list_for_each_entry_safe(ctx, ctx_tmp, &local->chanctx_list, list) {
|
|
|
|
if (ctx->replace_state != IEEE80211_CHANCTX_WILL_BE_REPLACED)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
ctx->replace_ctx->replace_ctx = NULL;
|
|
|
|
ctx->replace_ctx->replace_state =
|
|
|
|
IEEE80211_CHANCTX_REPLACE_NONE;
|
|
|
|
|
|
|
|
list_del_rcu(&ctx->list);
|
|
|
|
kfree_rcu(ctx, rcu_head);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err:
|
|
|
|
list_for_each_entry(ctx, &local->chanctx_list, list) {
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_link_data *link, *link_tmp;
|
|
|
|
|
2014-06-25 03:35:06 -07:00
|
|
|
if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
|
|
|
|
continue;
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links,
|
2014-06-25 03:35:08 -07:00
|
|
|
reserved_chanctx_list) {
|
2022-05-30 09:35:23 -07:00
|
|
|
ieee80211_link_unreserve_chanctx(link);
|
|
|
|
ieee80211_link_chanctx_reservation_complete(link);
|
2014-06-25 03:35:08 -07:00
|
|
|
}
|
2014-06-25 03:35:06 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2024-03-20 00:13:59 -07:00
|
|
|
void __ieee80211_link_release_channel(struct ieee80211_link_data *link,
|
|
|
|
bool skip_idle_recalc)
|
2014-07-25 06:01:59 -07:00
|
|
|
{
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_sub_if_data *sdata = link->sdata;
|
2022-06-17 13:36:37 -07:00
|
|
|
struct ieee80211_bss_conf *link_conf = link->conf;
|
2014-07-25 06:01:59 -07:00
|
|
|
struct ieee80211_local *local = sdata->local;
|
|
|
|
struct ieee80211_chanctx_conf *conf;
|
|
|
|
struct ieee80211_chanctx *ctx;
|
|
|
|
bool use_reserved_switch = false;
|
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2014-07-25 06:01:59 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
conf = rcu_dereference_protected(link_conf->chanctx_conf,
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_is_held(&local->hw.wiphy->mtx));
|
2014-07-25 06:01:59 -07:00
|
|
|
if (!conf)
|
|
|
|
return;
|
|
|
|
|
|
|
|
ctx = container_of(conf, struct ieee80211_chanctx, conf);
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
if (link->reserved_chanctx) {
|
|
|
|
if (link->reserved_chanctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER &&
|
|
|
|
ieee80211_chanctx_num_reserved(local, link->reserved_chanctx) > 1)
|
2014-07-25 06:01:59 -07:00
|
|
|
use_reserved_switch = true;
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
ieee80211_link_unreserve_chanctx(link);
|
2014-07-25 06:01:59 -07:00
|
|
|
}
|
|
|
|
|
2024-04-18 02:52:21 -07:00
|
|
|
ieee80211_assign_link_chanctx(link, NULL, false);
|
2014-07-25 06:01:59 -07:00
|
|
|
if (ieee80211_chanctx_refcount(local, ctx) == 0)
|
2024-03-20 00:13:59 -07:00
|
|
|
ieee80211_free_chanctx(local, ctx, skip_idle_recalc);
|
2014-07-25 06:01:59 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
link->radar_required = false;
|
2015-02-08 03:36:07 -07:00
|
|
|
|
2014-07-25 06:01:59 -07:00
|
|
|
/* Unreserving may ready an in-place reservation. */
|
|
|
|
if (use_reserved_switch)
|
|
|
|
ieee80211_vif_use_reserved_switch(local);
|
|
|
|
}
|
|
|
|
|
2024-04-18 02:52:21 -07:00
|
|
|
int _ieee80211_link_use_channel(struct ieee80211_link_data *link,
|
|
|
|
const struct ieee80211_chan_req *chanreq,
|
|
|
|
enum ieee80211_chanctx_mode mode,
|
|
|
|
bool assign_on_failure)
|
2014-07-25 06:01:59 -07:00
|
|
|
{
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_sub_if_data *sdata = link->sdata;
|
2014-07-25 06:01:59 -07:00
|
|
|
struct ieee80211_local *local = sdata->local;
|
|
|
|
struct ieee80211_chanctx *ctx;
|
|
|
|
u8 radar_detect_width = 0;
|
2024-04-18 02:52:19 -07:00
|
|
|
bool reserved = false;
|
2024-07-09 01:38:37 -07:00
|
|
|
int radio_idx;
|
2014-07-25 06:01:59 -07:00
|
|
|
int ret;
|
|
|
|
|
2023-08-28 05:00:05 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2014-07-25 06:01:59 -07:00
|
|
|
|
2024-02-28 01:48:11 -07:00
|
|
|
if (!ieee80211_vif_link_active(&sdata->vif, link->link_id)) {
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
ieee80211_link_update_chanreq(link, chanreq);
|
2022-09-02 07:12:42 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-07-25 06:01:59 -07:00
|
|
|
ret = cfg80211_chandef_dfs_required(local->hw.wiphy,
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
&chanreq->oper,
|
2014-07-25 06:01:59 -07:00
|
|
|
sdata->wdev.iftype);
|
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
|
|
|
if (ret > 0)
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
radar_detect_width = BIT(chanreq->oper.width);
|
2014-07-25 06:01:59 -07:00
|
|
|
|
2022-06-17 13:36:37 -07:00
|
|
|
link->radar_required = ret;
|
2014-07-25 06:01:59 -07:00
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
ret = ieee80211_check_combinations(sdata, &chanreq->oper, mode,
|
2024-07-09 01:38:35 -07:00
|
|
|
radar_detect_width, -1);
|
2014-07-25 06:01:59 -07:00
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
|
|
|
|
2024-03-20 00:13:59 -07:00
|
|
|
__ieee80211_link_release_channel(link, false);
|
2014-07-25 06:01:59 -07:00
|
|
|
|
2024-04-18 02:52:19 -07:00
|
|
|
ctx = ieee80211_find_chanctx(local, link, chanreq, mode);
|
|
|
|
/* Note: context is now reserved */
|
|
|
|
if (ctx)
|
|
|
|
reserved = true;
|
2024-07-09 01:38:37 -07:00
|
|
|
else if (!ieee80211_find_available_radio(local, chanreq, &radio_idx))
|
|
|
|
ctx = ERR_PTR(-EBUSY);
|
2024-04-18 02:52:19 -07:00
|
|
|
else
|
2024-04-18 02:52:21 -07:00
|
|
|
ctx = ieee80211_new_chanctx(local, chanreq, mode,
|
2024-07-09 01:38:37 -07:00
|
|
|
assign_on_failure, radio_idx);
|
2014-07-25 06:01:59 -07:00
|
|
|
if (IS_ERR(ctx)) {
|
|
|
|
ret = PTR_ERR(ctx);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
ieee80211_link_update_chanreq(link, chanreq);
|
2014-07-25 06:01:59 -07:00
|
|
|
|
2024-04-18 02:52:21 -07:00
|
|
|
ret = ieee80211_assign_link_chanctx(link, ctx, assign_on_failure);
|
2024-04-18 02:52:19 -07:00
|
|
|
|
|
|
|
if (reserved) {
|
|
|
|
/* remove reservation */
|
|
|
|
WARN_ON(link->reserved_chanctx != ctx);
|
|
|
|
link->reserved_chanctx = NULL;
|
|
|
|
list_del(&link->reserved_chanctx_list);
|
|
|
|
}
|
|
|
|
|
2014-07-25 06:01:59 -07:00
|
|
|
if (ret) {
|
|
|
|
/* if assign fails refcount stays the same */
|
|
|
|
if (ieee80211_chanctx_refcount(local, ctx) == 0)
|
2024-03-20 00:13:59 -07:00
|
|
|
ieee80211_free_chanctx(local, ctx, false);
|
2014-07-25 06:01:59 -07:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ieee80211_recalc_smps_chanctx(local, ctx);
|
|
|
|
ieee80211_recalc_radar_chanctx(local, ctx);
|
|
|
|
out:
|
2015-02-08 03:36:07 -07:00
|
|
|
if (ret)
|
2022-05-30 09:35:23 -07:00
|
|
|
link->radar_required = false;
|
2015-02-08 03:36:07 -07:00
|
|
|
|
2014-07-25 06:01:59 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
int ieee80211_link_use_reserved_context(struct ieee80211_link_data *link)
|
2014-06-25 03:35:06 -07:00
|
|
|
{
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_sub_if_data *sdata = link->sdata;
|
2014-06-25 03:35:06 -07:00
|
|
|
struct ieee80211_local *local = sdata->local;
|
|
|
|
struct ieee80211_chanctx *new_ctx;
|
|
|
|
struct ieee80211_chanctx *old_ctx;
|
|
|
|
int err;
|
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2014-06-25 03:35:06 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
new_ctx = link->reserved_chanctx;
|
|
|
|
old_ctx = ieee80211_link_get_chanctx(link);
|
2014-06-25 03:35:06 -07:00
|
|
|
|
|
|
|
if (WARN_ON(!new_ctx))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (WARN_ON(new_ctx->replace_state ==
|
|
|
|
IEEE80211_CHANCTX_WILL_BE_REPLACED))
|
|
|
|
return -EINVAL;
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
if (WARN_ON(link->reserved_ready))
|
2014-06-25 03:35:06 -07:00
|
|
|
return -EINVAL;
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
link->reserved_ready = true;
|
2014-06-25 03:35:06 -07:00
|
|
|
|
|
|
|
if (new_ctx->replace_state == IEEE80211_CHANCTX_REPLACE_NONE) {
|
|
|
|
if (old_ctx)
|
2022-05-30 09:35:23 -07:00
|
|
|
return ieee80211_link_use_reserved_reassign(link);
|
2014-06-25 03:35:06 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
return ieee80211_link_use_reserved_assign(link);
|
2014-06-25 03:35:06 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* In-place reservation may need to be finalized now either if:
|
|
|
|
* a) sdata is taking part in the swapping itself and is the last one
|
|
|
|
* b) sdata has switched with a re-assign reservation to an existing
|
|
|
|
* context readying in-place switching of old_ctx
|
|
|
|
*
|
|
|
|
* In case of (b) do not propagate the error up because the requested
|
|
|
|
* sdata already switched successfully. Just spill an extra warning.
|
|
|
|
* The ieee80211_vif_use_reserved_switch() already stops all necessary
|
|
|
|
* interfaces upon failure.
|
|
|
|
*/
|
|
|
|
if ((old_ctx &&
|
|
|
|
old_ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
|
|
|
|
new_ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) {
|
|
|
|
err = ieee80211_vif_use_reserved_switch(local);
|
|
|
|
if (err && err != -EAGAIN) {
|
|
|
|
if (new_ctx->replace_state ==
|
|
|
|
IEEE80211_CHANCTX_REPLACES_OTHER)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
wiphy_info(local->hw.wiphy,
|
|
|
|
"depending in-place reservation failed (err=%d)\n",
|
|
|
|
err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2013-07-11 07:09:06 -07:00
|
|
|
}
|
|
|
|
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
/*
|
|
|
|
* This is similar to ieee80211_chanctx_compatible(), but rechecks
|
|
|
|
* against all the links actually using it (except the one that's
|
|
|
|
* passed, since that one is changing).
|
|
|
|
* This is done in order to allow changes to the AP's bandwidth for
|
|
|
|
* wider bandwidth OFDMA purposes, which wouldn't be treated as
|
|
|
|
* compatible by ieee80211_chanctx_recheck() but is OK if the link
|
|
|
|
* requesting the update is the only one using it.
|
|
|
|
*/
|
|
|
|
static const struct ieee80211_chan_req *
|
|
|
|
ieee80211_chanctx_recheck(struct ieee80211_local *local,
|
|
|
|
struct ieee80211_link_data *skip_link,
|
|
|
|
struct ieee80211_chanctx *ctx,
|
|
|
|
const struct ieee80211_chan_req *req,
|
|
|
|
struct ieee80211_chan_req *tmp)
|
|
|
|
{
|
|
|
|
const struct ieee80211_chan_req *ret = req;
|
|
|
|
struct ieee80211_link_data *link;
|
|
|
|
|
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
|
|
|
|
|
|
|
for_each_sdata_link(local, link) {
|
|
|
|
if (link == skip_link)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (rcu_access_pointer(link->conf->chanctx_conf) == &ctx->conf) {
|
|
|
|
ret = ieee80211_chanreq_compatible(ret,
|
|
|
|
&link->conf->chanreq,
|
|
|
|
tmp);
|
|
|
|
if (!ret)
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (link->reserved_chanctx == ctx) {
|
|
|
|
ret = ieee80211_chanreq_compatible(ret,
|
|
|
|
&link->reserved,
|
|
|
|
tmp);
|
|
|
|
if (!ret)
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*tmp = *ret;
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
int ieee80211_link_change_chanreq(struct ieee80211_link_data *link,
|
|
|
|
const struct ieee80211_chan_req *chanreq,
|
|
|
|
u64 *changed)
|
2013-02-07 13:37:29 -07:00
|
|
|
{
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_sub_if_data *sdata = link->sdata;
|
2022-06-17 13:36:37 -07:00
|
|
|
struct ieee80211_bss_conf *link_conf = link->conf;
|
2013-02-07 13:37:29 -07:00
|
|
|
struct ieee80211_local *local = sdata->local;
|
|
|
|
struct ieee80211_chanctx_conf *conf;
|
|
|
|
struct ieee80211_chanctx *ctx;
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
const struct ieee80211_chan_req *compat;
|
|
|
|
struct ieee80211_chan_req tmp;
|
2023-08-28 05:00:03 -07:00
|
|
|
|
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
2013-02-07 13:37:29 -07:00
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
if (!cfg80211_chandef_usable(sdata->local->hw.wiphy,
|
|
|
|
&chanreq->oper,
|
2013-02-07 13:37:29 -07:00
|
|
|
IEEE80211_CHAN_DISABLED))
|
|
|
|
return -EINVAL;
|
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
/* for non-HT 20 MHz the rest doesn't matter */
|
|
|
|
if (chanreq->oper.width == NL80211_CHAN_WIDTH_20_NOHT &&
|
|
|
|
cfg80211_chandef_identical(&chanreq->oper, &link_conf->chanreq.oper))
|
2023-08-28 05:00:03 -07:00
|
|
|
return 0;
|
2013-02-07 13:37:29 -07:00
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
/* but you cannot switch to/from it */
|
|
|
|
if (chanreq->oper.width == NL80211_CHAN_WIDTH_20_NOHT ||
|
|
|
|
link_conf->chanreq.oper.width == NL80211_CHAN_WIDTH_20_NOHT)
|
2023-08-28 05:00:03 -07:00
|
|
|
return -EINVAL;
|
2013-02-07 13:37:29 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
conf = rcu_dereference_protected(link_conf->chanctx_conf,
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_is_held(&local->hw.wiphy->mtx));
|
|
|
|
if (!conf)
|
|
|
|
return -EINVAL;
|
2013-02-07 13:37:29 -07:00
|
|
|
|
|
|
|
ctx = container_of(conf, struct ieee80211_chanctx, conf);
|
2014-06-25 03:35:06 -07:00
|
|
|
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
compat = ieee80211_chanctx_recheck(local, link, ctx, chanreq, &tmp);
|
2023-08-28 05:00:03 -07:00
|
|
|
if (!compat)
|
|
|
|
return -EINVAL;
|
2013-02-07 13:37:29 -07:00
|
|
|
|
2014-06-25 03:35:06 -07:00
|
|
|
switch (ctx->replace_state) {
|
|
|
|
case IEEE80211_CHANCTX_REPLACE_NONE:
|
wifi: mac80211: support wider bandwidth OFDMA config
EHT requires that stations are able to participate in
wider bandwidth OFDMA, i.e. parse downlink OFDMA and
uplink OFDMA triggers when they're not capable of (or
not connected at) the (wider) bandwidth that the AP
is using. This requires hardware configuration, since
the entity responsible for parsing (possibly hardware)
needs to know the AP bandwidth.
To support this, change the channel request to have
the AP's bandwidth for clients, and track that in the
channel context in mac80211. This means that the same
chandef might need to be split up into two different
contexts, if the APs are different. Interfaces other
than client are not participating in OFDMA the same
way, so they don't request any AP setting.
Note that this doesn't introduce any API to split a
channel context, so that there are cases where this
might lead to a disconnect, e.g. if there are two
client interfaces using the same channel context, e.g.
both 160 MHz connected to different 320 MHz APs, and
one of the APs switches to 160 MHz.
Note also there are possible cases where this can be
optimised, e.g. when using the upper or lower 160 Mhz,
but I haven't been able to really fully understand the
spec and/or hardware limitations.
If, for some reason, there are no hardware limits on
this because the OFDMA (downlink/trigger) parsing is
done in firmware and can take the transmitter into
account, then drivers can set the new flag
IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW on interfaces to
not have them request any AP bandwidth in the channel
context and ignore this issue entirely. The bss_conf
still contains the AP configuration (if any, i.e. EHT)
in the chanreq.
Link: https://msgid.link/20240129194108.d3d5b35dd783.I939d04674f4ff06f39934b1591c8d36a30ce74c2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:42 -07:00
|
|
|
if (!ieee80211_chanctx_reserved_chanreq(local, ctx, compat,
|
|
|
|
&tmp))
|
2023-08-28 05:00:03 -07:00
|
|
|
return -EBUSY;
|
2014-06-25 03:35:06 -07:00
|
|
|
break;
|
|
|
|
case IEEE80211_CHANCTX_WILL_BE_REPLACED:
|
2014-10-29 22:55:58 -07:00
|
|
|
/* TODO: Perhaps the bandwidth change could be treated as a
|
2014-06-25 03:35:06 -07:00
|
|
|
* reservation itself? */
|
2023-08-28 05:00:03 -07:00
|
|
|
return -EBUSY;
|
2014-06-25 03:35:06 -07:00
|
|
|
case IEEE80211_CHANCTX_REPLACES_OTHER:
|
|
|
|
/* channel context that is going to replace another channel
|
|
|
|
* context doesn't really exist and shouldn't be assigned
|
|
|
|
* anywhere yet */
|
|
|
|
WARN_ON(1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
wifi: mac80211: introduce 'channel request'
For channel contexts, mac80211 currently uses the cfg80211
chandef struct (control channel, center freq(s), width) to
define towards drivers and internally how these behave. In
fact, there are _two_ such structs used, where the min_def
can reduce bandwidth according to the stations connected.
Unfortunately, with EHT this is longer be sufficient, at
least not for all hardware. EHT requires that non-AP STAs
that are connected to an AP with a lower bandwidth than it
(the AP) advertises (e.g. 160 MHz STA connected to 320 MHz
AP) still be able to receive downlink OFDMA and respond to
trigger frames for uplink OFDMA that specify the position
and bandwidth for the non-AP STA relative to the channel
the AP is using. Therefore, they need to be aware of this,
and at least for some hardware (e.g. Intel) this awareness
is in the hardware. As a result, use of the "same" channel
may need to be split over two channel contexts where they
differ by the AP being used.
As a first step, introduce a concept of a channel request
('chanreq') for each interface, to control the context it
requests. This step does nothing but reorganise the code,
so that later the AP's chandef can be added to the request
in order to handle the EHT case described above.
Link: https://msgid.link/20240129194108.2e88e48bd2e9.I4256183debe975c5ed71621611206fdbb69ba330@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-01-29 11:34:40 -07:00
|
|
|
ieee80211_link_update_chanreq(link, chanreq);
|
2013-02-07 13:37:29 -07:00
|
|
|
|
|
|
|
ieee80211_recalc_chanctx_chantype(local, ctx);
|
|
|
|
|
|
|
|
*changed |= BSS_CHANGED_BANDWIDTH;
|
2023-08-28 05:00:03 -07:00
|
|
|
return 0;
|
2013-02-07 13:37:29 -07:00
|
|
|
}
|
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
void ieee80211_link_release_channel(struct ieee80211_link_data *link)
|
2012-06-26 05:37:16 -07:00
|
|
|
{
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_sub_if_data *sdata = link->sdata;
|
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(sdata->local->hw.wiphy);
|
|
|
|
|
2023-08-28 05:00:05 -07:00
|
|
|
if (rcu_access_pointer(link->conf->chanctx_conf))
|
2024-03-20 00:13:59 -07:00
|
|
|
__ieee80211_link_release_channel(link, false);
|
2012-06-26 05:37:16 -07:00
|
|
|
}
|
2012-09-11 08:57:42 -07:00
|
|
|
|
2022-05-30 09:35:23 -07:00
|
|
|
void ieee80211_link_vlan_copy_chanctx(struct ieee80211_link_data *link)
|
2012-12-11 12:38:41 -07:00
|
|
|
{
|
2022-05-30 09:35:23 -07:00
|
|
|
struct ieee80211_sub_if_data *sdata = link->sdata;
|
|
|
|
unsigned int link_id = link->link_id;
|
2022-06-17 13:36:37 -07:00
|
|
|
struct ieee80211_bss_conf *link_conf = link->conf;
|
|
|
|
struct ieee80211_bss_conf *ap_conf;
|
2012-12-11 12:38:41 -07:00
|
|
|
struct ieee80211_local *local = sdata->local;
|
|
|
|
struct ieee80211_sub_if_data *ap;
|
|
|
|
struct ieee80211_chanctx_conf *conf;
|
|
|
|
|
2023-08-28 05:00:03 -07:00
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
|
|
|
|
2012-12-11 12:38:41 -07:00
|
|
|
if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss))
|
|
|
|
return;
|
|
|
|
|
|
|
|
ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
|
|
|
|
|
2024-01-29 11:34:41 -07:00
|
|
|
ap_conf = wiphy_dereference(local->hw.wiphy,
|
|
|
|
ap->vif.link_conf[link_id]);
|
|
|
|
conf = wiphy_dereference(local->hw.wiphy,
|
|
|
|
ap_conf->chanctx_conf);
|
2022-05-30 09:35:23 -07:00
|
|
|
rcu_assign_pointer(link_conf->chanctx_conf, conf);
|
2012-12-11 12:38:41 -07:00
|
|
|
}
|
|
|
|
|
2012-09-11 08:57:42 -07:00
|
|
|
void ieee80211_iter_chan_contexts_atomic(
|
|
|
|
struct ieee80211_hw *hw,
|
|
|
|
void (*iter)(struct ieee80211_hw *hw,
|
|
|
|
struct ieee80211_chanctx_conf *chanctx_conf,
|
|
|
|
void *data),
|
|
|
|
void *iter_data)
|
|
|
|
{
|
|
|
|
struct ieee80211_local *local = hw_to_local(hw);
|
|
|
|
struct ieee80211_chanctx *ctx;
|
|
|
|
|
|
|
|
rcu_read_lock();
|
|
|
|
list_for_each_entry_rcu(ctx, &local->chanctx_list, list)
|
2012-12-13 09:42:30 -07:00
|
|
|
if (ctx->driver_present)
|
|
|
|
iter(hw, &ctx->conf, iter_data);
|
2012-09-11 08:57:42 -07:00
|
|
|
rcu_read_unlock();
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic);
|