Skip to content

Commit 68dbad8

Browse files
twpedersenjmberg-intel
authored andcommitted
cfg80211: regulatory: handle S1G channels
S1G channels have a minimum bandwidth of 1Mhz, and there is a 1:1 mapping of allowed bandwidth to channel number. Signed-off-by: Thomas Pedersen <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Johannes Berg <[email protected]>
1 parent d65a977 commit 68dbad8

File tree

1 file changed

+58
-12
lines changed

1 file changed

+58
-12
lines changed

net/wireless/reg.c

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1617,9 +1617,11 @@ __freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 min_bw)
16171617
{
16181618
const struct ieee80211_regdomain *regd = reg_get_regdomain(wiphy);
16191619
const struct ieee80211_reg_rule *reg_rule = NULL;
1620+
const u32 bws[] = {0, 1, 2, 4, 5, 8, 10, 16, 20};
1621+
int i = ARRAY_SIZE(bws) - 1;
16201622
u32 bw;
16211623

1622-
for (bw = MHZ_TO_KHZ(20); bw >= min_bw; bw = bw / 2) {
1624+
for (bw = MHZ_TO_KHZ(bws[i]); bw >= min_bw; bw = MHZ_TO_KHZ(bws[i--])) {
16231625
reg_rule = freq_reg_info_regd(center_freq, regd, bw);
16241626
if (!IS_ERR(reg_rule))
16251627
return reg_rule;
@@ -1631,7 +1633,9 @@ __freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 min_bw)
16311633
const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy,
16321634
u32 center_freq)
16331635
{
1634-
return __freq_reg_info(wiphy, center_freq, MHZ_TO_KHZ(20));
1636+
u32 min_bw = center_freq < MHZ_TO_KHZ(1000) ? 1 : 20;
1637+
1638+
return __freq_reg_info(wiphy, center_freq, MHZ_TO_KHZ(min_bw));
16351639
}
16361640
EXPORT_SYMBOL(freq_reg_info);
16371641

@@ -1659,6 +1663,7 @@ static uint32_t reg_rule_to_chan_bw_flags(const struct ieee80211_regdomain *regd
16591663
{
16601664
const struct ieee80211_freq_range *freq_range = NULL;
16611665
u32 max_bandwidth_khz, center_freq_khz, bw_flags = 0;
1666+
bool is_s1g = chan->band == NL80211_BAND_S1GHZ;
16621667

16631668
freq_range = &reg_rule->freq_range;
16641669

@@ -1678,16 +1683,57 @@ static uint32_t reg_rule_to_chan_bw_flags(const struct ieee80211_regdomain *regd
16781683
MHZ_TO_KHZ(20)))
16791684
bw_flags |= IEEE80211_CHAN_NO_20MHZ;
16801685

1681-
if (max_bandwidth_khz < MHZ_TO_KHZ(10))
1682-
bw_flags |= IEEE80211_CHAN_NO_10MHZ;
1683-
if (max_bandwidth_khz < MHZ_TO_KHZ(20))
1684-
bw_flags |= IEEE80211_CHAN_NO_20MHZ;
1685-
if (max_bandwidth_khz < MHZ_TO_KHZ(40))
1686-
bw_flags |= IEEE80211_CHAN_NO_HT40;
1687-
if (max_bandwidth_khz < MHZ_TO_KHZ(80))
1688-
bw_flags |= IEEE80211_CHAN_NO_80MHZ;
1689-
if (max_bandwidth_khz < MHZ_TO_KHZ(160))
1690-
bw_flags |= IEEE80211_CHAN_NO_160MHZ;
1686+
if (is_s1g) {
1687+
/* S1G is strict about non overlapping channels. We can
1688+
* calculate which bandwidth is allowed per channel by finding
1689+
* the largest bandwidth which cleanly divides the freq_range.
1690+
*/
1691+
int edge_offset;
1692+
int ch_bw = max_bandwidth_khz;
1693+
1694+
while (ch_bw) {
1695+
edge_offset = (center_freq_khz - ch_bw / 2) -
1696+
freq_range->start_freq_khz;
1697+
if (edge_offset % ch_bw == 0) {
1698+
switch (KHZ_TO_MHZ(ch_bw)) {
1699+
case 1:
1700+
bw_flags |= IEEE80211_CHAN_1MHZ;
1701+
break;
1702+
case 2:
1703+
bw_flags |= IEEE80211_CHAN_2MHZ;
1704+
break;
1705+
case 4:
1706+
bw_flags |= IEEE80211_CHAN_4MHZ;
1707+
break;
1708+
case 8:
1709+
bw_flags |= IEEE80211_CHAN_8MHZ;
1710+
break;
1711+
case 16:
1712+
bw_flags |= IEEE80211_CHAN_16MHZ;
1713+
break;
1714+
default:
1715+
/* If we got here, no bandwidths fit on
1716+
* this frequency, ie. band edge.
1717+
*/
1718+
bw_flags |= IEEE80211_CHAN_DISABLED;
1719+
break;
1720+
}
1721+
break;
1722+
}
1723+
ch_bw /= 2;
1724+
}
1725+
} else {
1726+
if (max_bandwidth_khz < MHZ_TO_KHZ(10))
1727+
bw_flags |= IEEE80211_CHAN_NO_10MHZ;
1728+
if (max_bandwidth_khz < MHZ_TO_KHZ(20))
1729+
bw_flags |= IEEE80211_CHAN_NO_20MHZ;
1730+
if (max_bandwidth_khz < MHZ_TO_KHZ(40))
1731+
bw_flags |= IEEE80211_CHAN_NO_HT40;
1732+
if (max_bandwidth_khz < MHZ_TO_KHZ(80))
1733+
bw_flags |= IEEE80211_CHAN_NO_80MHZ;
1734+
if (max_bandwidth_khz < MHZ_TO_KHZ(160))
1735+
bw_flags |= IEEE80211_CHAN_NO_160MHZ;
1736+
}
16911737
return bw_flags;
16921738
}
16931739

0 commit comments

Comments
 (0)