wifi: 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 <quic_alokad@quicinc.com>
Link: https://lore.kernel.org/r/20230131001227.25014-2-quic_alokad@quicinc.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Aloka Dixit 2023-01-30 16:12:24 -08:00 committed by Johannes Berg
parent 90b2c3cc4b
commit b25413fed3
3 changed files with 87 additions and 67 deletions

View file

@ -8952,4 +8952,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 */

View file

@ -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,

View file

@ -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);