2023-01-31 00:12:47

by Aloka Dixit

[permalink] [raw]
Subject: [PATCH v4 0/4] v4: Puncturing support in AP mode

- Moved bitmap validation from MAC80211 to CFG80211.
- Combined start_ap() and switch_channel() patches for a given module.
- Changed the order of patches.

Aloka Dixit (4):
cfg80211: move puncturing bitmap validation from mac80211
wifi: nl80211: validate and configure puncturing bitmap
wifi: cfg80211: include puncturing bitmap in channel switch events
wifi: mac80211: configure puncturing bitmap

drivers/net/wireless/ath/ath6kl/cfg80211.c | 2 +-
drivers/net/wireless/marvell/mwifiex/11h.c | 2 +-
include/net/cfg80211.h | 26 +++++++-
include/net/mac80211.h | 3 +
include/uapi/linux/nl80211.h | 12 ++++
net/mac80211/cfg.c | 23 ++++++-
net/mac80211/mlme.c | 77 +++-------------------
net/wireless/chan.c | 69 +++++++++++++++++++
net/wireless/nl80211.c | 58 ++++++++++++++--
net/wireless/trace.h | 24 ++++---
10 files changed, 205 insertions(+), 91 deletions(-)


base-commit: 4ca69027691a0039279b64cfa0aa511d9c9fde59
prerequisite-patch-id: f3e39c8c03c23c977baa8946066285e597b93c7e
--
2.39.0



2023-01-31 00:12:48

by Aloka Dixit

[permalink] [raw]
Subject: [PATCH v4 4/4] wifi: mac80211: configure puncturing bitmap

- Configure the bitmap in link_conf and notify the driver.
- Modify 'change' in ieee80211_start_ap() from u32 to u64 to support
BSS_CHANGED_EHT_PUNCTURING.
- Propagate the bitmap in channel switch events to userspace.

Signed-off-by: Aloka Dixit <[email protected]>
Signed-off-by: Muna Sinada <[email protected]>
---
include/net/mac80211.h | 3 +++
net/mac80211/cfg.c | 22 +++++++++++++++++++---
2 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 54ffc0cc2918..9fbbaf8e9a85 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -645,6 +645,7 @@ struct ieee80211_fils_discovery {
* @csa_active: marks whether a channel switch is going on. Internally it is
* write-protected by sdata_lock and local->mtx so holding either is fine
* for read access.
+ * @csa_punct_bitmap: new puncturing bitmap for channel switch
* @mu_mimo_owner: indicates interface owns MU-MIMO capability
* @chanctx_conf: The channel context this interface is assigned to, or %NULL
* when it is not assigned. This pointer is RCU-protected due to the TX
@@ -741,6 +742,8 @@ struct ieee80211_bss_conf {
u16 eht_puncturing;

bool csa_active;
+ u16 csa_punct_bitmap;
+
bool mu_mimo_owner;
struct ieee80211_chanctx_conf __rcu *chanctx_conf;

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 6e830d1b82b2..5cd7ae4deb84 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1220,7 +1220,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_local *local = sdata->local;
struct beacon_data *old;
struct ieee80211_sub_if_data *vlan;
- u32 changed = BSS_CHANGED_BEACON_INT |
+ u64 changed = BSS_CHANGED_BEACON_INT |
BSS_CHANGED_BEACON_ENABLED |
BSS_CHANGED_BEACON |
BSS_CHANGED_P2P_PS |
@@ -1296,6 +1296,11 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO;
}

+ if (params->eht_cap) {
+ link_conf->eht_puncturing = params->punct_bitmap;
+ changed |= BSS_CHANGED_EHT_PUNCTURING;
+ }
+
if (sdata->vif.type == NL80211_IFTYPE_AP &&
params->mbssid_config.tx_wdev) {
err = ieee80211_set_ap_mbssid_options(sdata,
@@ -3546,6 +3551,12 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
lockdep_assert_held(&local->mtx);
lockdep_assert_held(&local->chanctx_mtx);

+ if (sdata->vif.bss_conf.eht_puncturing != sdata->vif.bss_conf.csa_punct_bitmap) {
+ sdata->vif.bss_conf.eht_puncturing =
+ sdata->vif.bss_conf.csa_punct_bitmap;
+ changed |= BSS_CHANGED_EHT_PUNCTURING;
+ }
+
/*
* using reservation isn't immediate as it may be deferred until later
* with multi-vif. once reservation is complete it will re-schedule the
@@ -3588,7 +3599,7 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
return err;

cfg80211_ch_switch_notify(sdata->dev, &sdata->deflink.csa_chandef, 0,
- 0);
+ sdata->vif.bss_conf.eht_puncturing);

return 0;
}
@@ -3850,9 +3861,13 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
goto out;
}

+ if (params->punct_bitmap && !sdata->vif.bss_conf.eht_support)
+ goto out;
+
sdata->deflink.csa_chandef = params->chandef;
sdata->deflink.csa_block_tx = params->block_tx;
sdata->vif.bss_conf.csa_active = true;
+ sdata->vif.bss_conf.csa_punct_bitmap = params->punct_bitmap;

if (sdata->deflink.csa_block_tx)
ieee80211_stop_vif_queues(local, sdata,
@@ -3860,7 +3875,8 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,

cfg80211_ch_switch_started_notify(sdata->dev,
&sdata->deflink.csa_chandef, 0,
- params->count, params->block_tx, 0);
+ params->count, params->block_tx,
+ sdata->vif.bss_conf.csa_punct_bitmap);

if (changed) {
ieee80211_link_info_change_notify(sdata, &sdata->deflink,
--
2.39.0


2023-01-31 00:12:49

by Aloka Dixit

[permalink] [raw]
Subject: [PATCH v4 3/4] wifi: cfg80211: include puncturing bitmap in channel switch events

Add punctruing bitmap in channel switch notifications (CFG80211, NL80211)
and corresponding trace functions.

Signed-off-by: Aloka Dixit <[email protected]>
---
drivers/net/wireless/ath/ath6kl/cfg80211.c | 2 +-
drivers/net/wireless/marvell/mwifiex/11h.c | 2 +-
include/net/cfg80211.h | 6 ++++--
net/mac80211/cfg.c | 5 +++--
net/mac80211/mlme.c | 4 ++--
net/wireless/nl80211.c | 20 +++++++++++-------
net/wireless/trace.h | 24 ++++++++++++++--------
7 files changed, 40 insertions(+), 23 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index a20e0aeae284..0c2b8b1a10d5 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -1119,7 +1119,7 @@ void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq,
NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT);

mutex_lock(&vif->wdev.mtx);
- cfg80211_ch_switch_notify(vif->ndev, &chandef, 0);
+ cfg80211_ch_switch_notify(vif->ndev, &chandef, 0, 0);
mutex_unlock(&vif->wdev.mtx);
}

diff --git a/drivers/net/wireless/marvell/mwifiex/11h.c b/drivers/net/wireless/marvell/mwifiex/11h.c
index 6a9d7bc1f41e..b0c40a776a2e 100644
--- a/drivers/net/wireless/marvell/mwifiex/11h.c
+++ b/drivers/net/wireless/marvell/mwifiex/11h.c
@@ -292,6 +292,6 @@ void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work)
mwifiex_dbg(priv->adapter, MSG,
"indicating channel switch completion to kernel\n");
mutex_lock(&priv->wdev.mtx);
- cfg80211_ch_switch_notify(priv->netdev, &priv->dfs_chandef, 0);
+ cfg80211_ch_switch_notify(priv->netdev, &priv->dfs_chandef, 0, 0);
mutex_unlock(&priv->wdev.mtx);
}
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index f70f28776dc0..6b30ad4423f9 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -8280,13 +8280,14 @@ bool cfg80211_reg_can_beacon_relax(struct wiphy *wiphy,
* @dev: the device which switched channels
* @chandef: the new channel definition
* @link_id: the link ID for MLO, must be 0 for non-MLO
+ * @punct_bitmap: the new puncturing bitmap
*
* Caller must acquire wdev_lock, therefore must only be called from sleepable
* driver context!
*/
void cfg80211_ch_switch_notify(struct net_device *dev,
struct cfg80211_chan_def *chandef,
- unsigned int link_id);
+ unsigned int link_id, u16 punct_bitmap);

/*
* cfg80211_ch_switch_started_notify - notify channel switch start
@@ -8295,6 +8296,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
* @link_id: the link ID for MLO, must be 0 for non-MLO
* @count: the number of TBTTs until the channel switch happens
* @quiet: whether or not immediate quiet was requested by the AP
+ * @punct_bitmap: the future puncturing bitmap
*
* Inform the userspace about the channel switch that has just
* started, so that it can take appropriate actions (eg. starting
@@ -8303,7 +8305,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
void cfg80211_ch_switch_started_notify(struct net_device *dev,
struct cfg80211_chan_def *chandef,
unsigned int link_id, u8 count,
- bool quiet);
+ bool quiet, u16 punct_bitmap);

/**
* ieee80211_operating_class_to_band - convert operating class to band
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 24b8648cfafa..6e830d1b82b2 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3587,7 +3587,8 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
if (err)
return err;

- cfg80211_ch_switch_notify(sdata->dev, &sdata->deflink.csa_chandef, 0);
+ cfg80211_ch_switch_notify(sdata->dev, &sdata->deflink.csa_chandef, 0,
+ 0);

return 0;
}
@@ -3859,7 +3860,7 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,

cfg80211_ch_switch_started_notify(sdata->dev,
&sdata->deflink.csa_chandef, 0,
- params->count, params->block_tx);
+ params->count, params->block_tx, 0);

if (changed) {
ieee80211_link_info_change_notify(sdata, &sdata->deflink,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 09703cae2fbb..60792dfabc9d 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1778,7 +1778,7 @@ static void ieee80211_chswitch_post_beacon(struct ieee80211_link_data *link)
return;
}

- cfg80211_ch_switch_notify(sdata->dev, &link->reserved_chandef, 0);
+ cfg80211_ch_switch_notify(sdata->dev, &link->reserved_chandef, 0, 0);
}

void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
@@ -1988,7 +1988,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
mutex_unlock(&local->mtx);

cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chandef, 0,
- csa_ie.count, csa_ie.mode);
+ csa_ie.count, csa_ie.mode, 0);

if (local->ops->channel_switch) {
/* use driver's channel switch callback */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d2219f43a2ea..ed467ef3ee74 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -18994,7 +18994,7 @@ static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
struct cfg80211_chan_def *chandef,
gfp_t gfp,
enum nl80211_commands notif,
- u8 count, bool quiet)
+ u8 count, bool quiet, u16 punct_bitmap)
{
struct wireless_dev *wdev = netdev->ieee80211_ptr;
struct sk_buff *msg;
@@ -19028,6 +19028,9 @@ static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
goto nla_put_failure;
}

+ if (nla_put_u32(msg, NL80211_ATTR_PUNCT_BITMAP, punct_bitmap))
+ goto nla_put_failure;
+
genlmsg_end(msg, hdr);

genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
@@ -19040,7 +19043,7 @@ static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,

void cfg80211_ch_switch_notify(struct net_device *dev,
struct cfg80211_chan_def *chandef,
- unsigned int link_id)
+ unsigned int link_id, u16 punct_bitmap)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy;
@@ -19049,7 +19052,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
ASSERT_WDEV_LOCK(wdev);
WARN_INVALID_LINK_ID(wdev, link_id);

- trace_cfg80211_ch_switch_notify(dev, chandef, link_id);
+ trace_cfg80211_ch_switch_notify(dev, chandef, link_id, punct_bitmap);

switch (wdev->iftype) {
case NL80211_IFTYPE_STATION:
@@ -19077,14 +19080,15 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
cfg80211_sched_dfs_chan_update(rdev);

nl80211_ch_switch_notify(rdev, dev, link_id, chandef, GFP_KERNEL,
- NL80211_CMD_CH_SWITCH_NOTIFY, 0, false);
+ NL80211_CMD_CH_SWITCH_NOTIFY, 0, false,
+ punct_bitmap);
}
EXPORT_SYMBOL(cfg80211_ch_switch_notify);

void cfg80211_ch_switch_started_notify(struct net_device *dev,
struct cfg80211_chan_def *chandef,
unsigned int link_id, u8 count,
- bool quiet)
+ bool quiet, u16 punct_bitmap)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy;
@@ -19093,11 +19097,13 @@ void cfg80211_ch_switch_started_notify(struct net_device *dev,
ASSERT_WDEV_LOCK(wdev);
WARN_INVALID_LINK_ID(wdev, link_id);

- trace_cfg80211_ch_switch_started_notify(dev, chandef, link_id);
+ trace_cfg80211_ch_switch_started_notify(dev, chandef, link_id,
+ punct_bitmap);
+

nl80211_ch_switch_notify(rdev, dev, link_id, chandef, GFP_KERNEL,
NL80211_CMD_CH_SWITCH_STARTED_NOTIFY,
- count, quiet);
+ count, quiet, punct_bitmap);
}
EXPORT_SYMBOL(cfg80211_ch_switch_started_notify);

diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index a405c3edbc47..eee3e27e1652 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -3245,39 +3245,47 @@ TRACE_EVENT(cfg80211_chandef_dfs_required,
TRACE_EVENT(cfg80211_ch_switch_notify,
TP_PROTO(struct net_device *netdev,
struct cfg80211_chan_def *chandef,
- unsigned int link_id),
- TP_ARGS(netdev, chandef, link_id),
+ unsigned int link_id,
+ u16 punct_bitmap),
+ TP_ARGS(netdev, chandef, link_id, punct_bitmap),
TP_STRUCT__entry(
NETDEV_ENTRY
CHAN_DEF_ENTRY
__field(unsigned int, link_id)
+ __field(u16, punct_bitmap)
),
TP_fast_assign(
NETDEV_ASSIGN;
CHAN_DEF_ASSIGN(chandef);
__entry->link_id = link_id;
+ __entry->punct_bitmap = punct_bitmap;
),
- TP_printk(NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT ", link:%d",
- NETDEV_PR_ARG, CHAN_DEF_PR_ARG, __entry->link_id)
+ TP_printk(NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT ", link:%d, punct_bitmap:%u",
+ NETDEV_PR_ARG, CHAN_DEF_PR_ARG, __entry->link_id,
+ __entry->punct_bitmap)
);

TRACE_EVENT(cfg80211_ch_switch_started_notify,
TP_PROTO(struct net_device *netdev,
struct cfg80211_chan_def *chandef,
- unsigned int link_id),
- TP_ARGS(netdev, chandef, link_id),
+ unsigned int link_id,
+ u16 punct_bitmap),
+ TP_ARGS(netdev, chandef, link_id, punct_bitmap),
TP_STRUCT__entry(
NETDEV_ENTRY
CHAN_DEF_ENTRY
__field(unsigned int, link_id)
+ __field(u16, punct_bitmap)
),
TP_fast_assign(
NETDEV_ASSIGN;
CHAN_DEF_ASSIGN(chandef);
__entry->link_id = link_id;
+ __entry->punct_bitmap = punct_bitmap;
),
- TP_printk(NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT ", link:%d",
- NETDEV_PR_ARG, CHAN_DEF_PR_ARG, __entry->link_id)
+ TP_printk(NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT ", link:%d, punct_bitmap:%u",
+ NETDEV_PR_ARG, CHAN_DEF_PR_ARG, __entry->link_id,
+ __entry->punct_bitmap)
);

TRACE_EVENT(cfg80211_radar_event,
--
2.39.0


2023-01-31 00:12:51

by Aloka Dixit

[permalink] [raw]
Subject: [PATCH v4 2/4] wifi: nl80211: validate and configure puncturing bitmap

- New feature flag, NL80211_EXT_FEATURE_PUNCTURING, to advertise
driver support for preamble puncturing.
- New attribute, NL80211_ATTR_PUNCT_BITMAP, to receive a puncturing
bitmap from the userspace during AP bring up (NL80211_CMD_START_AP)
and channel switch (NL80211_CMD_CHANNEL_SWITCH) operations. Each bit
corresponds to a 20 MHz channel in the operating bandwidth, lowest bit
for the lowest channel. Bit set to 1 indicates that the channel is
punctured. Higher 16 bits are reserved.
- New members added to structures cfg80211_ap_settings and
cfg80211_csa_settings to propagate the bitmap to MAC80211 after
validation.

Signed-off-by: Aloka Dixit <[email protected]>
Signed-off-by: Muna Sinada <[email protected]>
---
include/net/cfg80211.h | 8 ++++++++
include/uapi/linux/nl80211.h | 12 ++++++++++++
net/wireless/nl80211.c | 38 ++++++++++++++++++++++++++++++++++++
3 files changed, 58 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 505a1072b5b4..f70f28776dc0 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1316,6 +1316,9 @@ struct cfg80211_unsol_bcast_probe_resp {
* @fils_discovery: FILS discovery transmission parameters
* @unsol_bcast_probe_resp: Unsolicited broadcast probe response parameters
* @mbssid_config: AP settings for multiple bssid
+ * @punct_bitmap: Preamble puncturing bitmap. Each bit represents
+ * a 20 MHz channel, lowest bit corresponding to the lowest channel.
+ * Bit set to 1 indicates that the channel is punctured.
*/
struct cfg80211_ap_settings {
struct cfg80211_chan_def chandef;
@@ -1350,6 +1353,7 @@ struct cfg80211_ap_settings {
struct cfg80211_fils_discovery fils_discovery;
struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp;
struct cfg80211_mbssid_config mbssid_config;
+ u16 punct_bitmap;
};

/**
@@ -1367,6 +1371,9 @@ struct cfg80211_ap_settings {
* @radar_required: whether radar detection is required on the new channel
* @block_tx: whether transmissions should be blocked while changing
* @count: number of beacons until switch
+ * @punct_bitmap: Preamble puncturing bitmap. Each bit represents
+ * a 20 MHz channel, lowest bit corresponding to the lowest channel.
+ * Bit set to 1 indicates that the channel is punctured.
*/
struct cfg80211_csa_settings {
struct cfg80211_chan_def chandef;
@@ -1379,6 +1386,7 @@ struct cfg80211_csa_settings {
bool radar_required;
bool block_tx;
u8 count;
+ u16 punct_bitmap;
};

/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 8ecb0fbee721..4dfd6990fa97 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2752,6 +2752,12 @@ enum nl80211_commands {
* the incoming frame RX timestamp.
* @NL80211_ATTR_TD_BITMAP: Transition Disable bitmap, for subsequent
* (re)associations.
+ *
+ * @NL80211_ATTR_PUNCT_BITMAP: (u32) Preamble puncturing bitmap, lowest
+ * bit corresponds to the lowest 20 MHz channel. Each bit set to 1
+ * indicates that the sub-channel is punctured. Higher 16 bits are
+ * reserved.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3281,6 +3287,8 @@ enum nl80211_attrs {
NL80211_ATTR_RX_HW_TIMESTAMP,
NL80211_ATTR_TD_BITMAP,

+ NL80211_ATTR_PUNCT_BITMAP,
+
/* add attributes here, update the policy in nl80211.c */

__NL80211_ATTR_AFTER_LAST,
@@ -6296,6 +6304,8 @@ enum nl80211_feature_flags {
* might apply, e.g. no scans in progress, no offchannel operations
* in progress, and no active connections.
*
+ * @NL80211_EXT_FEATURE_PUNCT: Driver supports preamble puncturing in AP mode.
+ *
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
*/
@@ -6365,6 +6375,8 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_RADAR_BACKGROUND,
NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE,

+ NL80211_EXT_FEATURE_PUNCT,
+
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
MAX_NL80211_EXT_FEATURES = NUM_NL80211_EXT_FEATURES - 1
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 64cf6110ce9d..d2219f43a2ea 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -805,6 +805,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN),
[NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
[NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT },
+ [NL80211_ATTR_PUNCT_BITMAP] = { .type = NLA_U32 },
};

/* policy for the key attributes */
@@ -3173,6 +3174,27 @@ static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev)
wdev->iftype == NL80211_IFTYPE_P2P_GO;
}

+static int nl80211_parse_punct_bitmap(struct cfg80211_registered_device *rdev,
+ struct genl_info *info,
+ const struct cfg80211_chan_def *chandef,
+ u16 *punct_bitmap)
+{
+ u32 bitmap;
+
+ if (!wiphy_ext_feature_isset(&rdev->wiphy, NL80211_EXT_FEATURE_PUNCT))
+ return -EINVAL;
+
+ bitmap = nla_get_u32(info->attrs[NL80211_ATTR_PUNCT_BITMAP]);
+ if (bitmap & 0xFFFF0000)
+ return -EINVAL;
+
+ *punct_bitmap = bitmap;
+ if (!cfg80211_valid_disable_subchannel_bitmap(punct_bitmap, chandef))
+ return -EINVAL;
+
+ return 0;
+}
+
int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
struct genl_info *info,
struct cfg80211_chan_def *chandef)
@@ -5918,6 +5940,14 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
goto out;
}

+ if (info->attrs[NL80211_ATTR_PUNCT_BITMAP]) {
+ err = nl80211_parse_punct_bitmap(rdev, info,
+ &params->chandef,
+ &params->punct_bitmap);
+ if (err)
+ goto out;
+ }
+
if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params->chandef,
wdev->iftype)) {
err = -EINVAL;
@@ -10057,6 +10087,14 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
params.block_tx = true;

+ if (info->attrs[NL80211_ATTR_PUNCT_BITMAP]) {
+ err = nl80211_parse_punct_bitmap(rdev, info,
+ &params.chandef,
+ &params.punct_bitmap);
+ if (err)
+ goto free;
+ }
+
wdev_lock(wdev);
err = rdev_channel_switch(rdev, dev, &params);
wdev_unlock(wdev);
--
2.39.0


2023-01-31 00:12:52

by Aloka Dixit

[permalink] [raw]
Subject: [PATCH v4 1/4] cfg80211: move puncturing bitmap validation from mac80211

- Move ieee80211_valid_disable_subchannel_bitmap() from mlme.c to
chan.c, rename it as cfg80211_valid_disable_subchannel_bitmap() and
export it.
- Modify the prototype to include struct cfg80211_chan_def instead of
only bandwidth to support a check which returns false if the primary
channel is punctured.

Signed-off-by: Aloka Dixit <[email protected]>
---
include/net/cfg80211.h | 12 +++++++
net/mac80211/mlme.c | 73 ++++--------------------------------------
net/wireless/chan.c | 69 +++++++++++++++++++++++++++++++++++++++
3 files changed, 87 insertions(+), 67 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 54a77d906b2d..505a1072b5b4 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -8906,4 +8906,16 @@ static inline int cfg80211_color_change_notify(struct net_device *dev)
0, 0);
}

+/**
+ * cfg80211_valid_disable_subchannel_bitmap - validate puncturing bitmap
+ * @bitmap: bitmap to be validated
+ * @chandef: channel definition
+ *
+ * Validate the puncturing bitmap.
+ *
+ * Return: %true if the bitmap is valid. %false otherwise.
+ */
+bool cfg80211_valid_disable_subchannel_bitmap(u16 *bitmap,
+ const struct cfg80211_chan_def *chandef);
+
#endif /* __NET_CFG80211_H */
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index a14a5ea2bffd..09703cae2fbb 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -88,67 +88,6 @@ MODULE_PARM_DESC(probe_wait_ms,
*/
#define IEEE80211_SIGNAL_AVE_MIN_COUNT 4

-struct ieee80211_per_bw_puncturing_values {
- u8 len;
- const u16 *valid_values;
-};
-
-static const u16 puncturing_values_80mhz[] = {
- 0x8, 0x4, 0x2, 0x1
-};
-
-static const u16 puncturing_values_160mhz[] = {
- 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1, 0xc0, 0x30, 0xc, 0x3
-};
-
-static const u16 puncturing_values_320mhz[] = {
- 0xc000, 0x3000, 0xc00, 0x300, 0xc0, 0x30, 0xc, 0x3, 0xf000, 0xf00,
- 0xf0, 0xf, 0xfc00, 0xf300, 0xf0c0, 0xf030, 0xf00c, 0xf003, 0xc00f,
- 0x300f, 0xc0f, 0x30f, 0xcf, 0x3f
-};
-
-#define IEEE80211_PER_BW_VALID_PUNCTURING_VALUES(_bw) \
- { \
- .len = ARRAY_SIZE(puncturing_values_ ## _bw ## mhz), \
- .valid_values = puncturing_values_ ## _bw ## mhz \
- }
-
-static const struct ieee80211_per_bw_puncturing_values per_bw_puncturing[] = {
- IEEE80211_PER_BW_VALID_PUNCTURING_VALUES(80),
- IEEE80211_PER_BW_VALID_PUNCTURING_VALUES(160),
- IEEE80211_PER_BW_VALID_PUNCTURING_VALUES(320)
-};
-
-static bool ieee80211_valid_disable_subchannel_bitmap(u16 *bitmap,
- enum nl80211_chan_width bw)
-{
- u32 idx, i;
-
- switch (bw) {
- case NL80211_CHAN_WIDTH_80:
- idx = 0;
- break;
- case NL80211_CHAN_WIDTH_160:
- idx = 1;
- break;
- case NL80211_CHAN_WIDTH_320:
- idx = 2;
- break;
- default:
- *bitmap = 0;
- break;
- }
-
- if (!*bitmap)
- return true;
-
- for (i = 0; i < per_bw_puncturing[idx].len; i++)
- if (per_bw_puncturing[idx].valid_values[i] == *bitmap)
- return true;
-
- return false;
-}
-
/*
* Extract from the given disabled subchannel bitmap (raw format
* from the EHT Operation Element) the bits for the subchannel
@@ -206,8 +145,8 @@ ieee80211_handle_puncturing_bitmap(struct ieee80211_link_data *link,
ieee80211_extract_dis_subch_bmap(eht_oper, chandef,
bitmap);

- if (ieee80211_valid_disable_subchannel_bitmap(&bitmap,
- chandef->width))
+ if (cfg80211_valid_disable_subchannel_bitmap(&bitmap,
+ chandef))
break;
link->u.mgd.conn_flags |=
ieee80211_chandef_downgrade(chandef);
@@ -5638,8 +5577,8 @@ static bool ieee80211_config_puncturing(struct ieee80211_link_data *link,
extracted == link->conf->eht_puncturing)
return true;

- if (!ieee80211_valid_disable_subchannel_bitmap(&bitmap,
- link->conf->chandef.width)) {
+ if (!cfg80211_valid_disable_subchannel_bitmap(&bitmap,
+ &link->conf->chandef)) {
link_info(link,
"Got an invalid disable subchannel bitmap from AP %pM: bitmap = 0x%x, bw = 0x%x. disconnect\n",
link->u.mgd.bssid,
@@ -7132,8 +7071,8 @@ ieee80211_setup_assoc_link(struct ieee80211_sub_if_data *sdata,
u16 bitmap;

bitmap = get_unaligned_le16(disable_subchannel_bitmap);
- if (ieee80211_valid_disable_subchannel_bitmap(&bitmap,
- link->conf->chandef.width))
+ if (cfg80211_valid_disable_subchannel_bitmap(&bitmap,
+ &link->conf->chandef))
ieee80211_handle_puncturing_bitmap(link,
eht_oper,
bitmap,
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 0e5835cd8c61..0b7e81db383d 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -1460,3 +1460,72 @@ struct cfg80211_chan_def *wdev_chandef(struct wireless_dev *wdev,
}
}
EXPORT_SYMBOL(wdev_chandef);
+
+struct cfg80211_per_bw_puncturing_values {
+ u8 len;
+ const u16 *valid_values;
+};
+
+static const u16 puncturing_values_80mhz[] = {
+ 0x8, 0x4, 0x2, 0x1
+};
+
+static const u16 puncturing_values_160mhz[] = {
+ 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1, 0xc0, 0x30, 0xc, 0x3
+};
+
+static const u16 puncturing_values_320mhz[] = {
+ 0xc000, 0x3000, 0xc00, 0x300, 0xc0, 0x30, 0xc, 0x3, 0xf000, 0xf00,
+ 0xf0, 0xf, 0xfc00, 0xf300, 0xf0c0, 0xf030, 0xf00c, 0xf003, 0xc00f,
+ 0x300f, 0xc0f, 0x30f, 0xcf, 0x3f
+};
+
+#define CFG80211_PER_BW_VALID_PUNCTURING_VALUES(_bw) \
+ { \
+ .len = ARRAY_SIZE(puncturing_values_ ## _bw ## mhz), \
+ .valid_values = puncturing_values_ ## _bw ## mhz \
+ }
+
+static const struct cfg80211_per_bw_puncturing_values per_bw_puncturing[] = {
+ CFG80211_PER_BW_VALID_PUNCTURING_VALUES(80),
+ CFG80211_PER_BW_VALID_PUNCTURING_VALUES(160),
+ CFG80211_PER_BW_VALID_PUNCTURING_VALUES(320)
+};
+
+bool cfg80211_valid_disable_subchannel_bitmap(u16 *bitmap,
+ const struct cfg80211_chan_def *chandef)
+{
+ u32 idx, i, start_freq;
+
+ switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_80:
+ idx = 0;
+ start_freq = chandef->center_freq1 - 40;
+ break;
+ case NL80211_CHAN_WIDTH_160:
+ idx = 1;
+ start_freq = chandef->center_freq1 - 80;
+ break;
+ case NL80211_CHAN_WIDTH_320:
+ idx = 2;
+ start_freq = chandef->center_freq1 - 160;
+ break;
+ default:
+ *bitmap = 0;
+ break;
+ }
+
+ if (!*bitmap)
+ return true;
+
+ /* check if primary channel is punctured */
+ if (*bitmap & (u16)BIT((chandef->chan->center_freq - start_freq) / 20))
+ return false;
+
+ for (i = 0; i < per_bw_puncturing[idx].len; i++)
+ if (per_bw_puncturing[idx].valid_values[i] == *bitmap)
+ return true;
+
+ return false;
+}
+EXPORT_SYMBOL(cfg80211_valid_disable_subchannel_bitmap);
--
2.39.0