@@ -1617,9 +1617,11 @@ __freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 min_bw)
1617
1617
{
1618
1618
const struct ieee80211_regdomain * regd = reg_get_regdomain (wiphy );
1619
1619
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 ;
1620
1622
u32 bw ;
1621
1623
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 -- ]) ) {
1623
1625
reg_rule = freq_reg_info_regd (center_freq , regd , bw );
1624
1626
if (!IS_ERR (reg_rule ))
1625
1627
return reg_rule ;
@@ -1631,7 +1633,9 @@ __freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 min_bw)
1631
1633
const struct ieee80211_reg_rule * freq_reg_info (struct wiphy * wiphy ,
1632
1634
u32 center_freq )
1633
1635
{
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 ));
1635
1639
}
1636
1640
EXPORT_SYMBOL (freq_reg_info );
1637
1641
@@ -1659,6 +1663,7 @@ static uint32_t reg_rule_to_chan_bw_flags(const struct ieee80211_regdomain *regd
1659
1663
{
1660
1664
const struct ieee80211_freq_range * freq_range = NULL ;
1661
1665
u32 max_bandwidth_khz , center_freq_khz , bw_flags = 0 ;
1666
+ bool is_s1g = chan -> band == NL80211_BAND_S1GHZ ;
1662
1667
1663
1668
freq_range = & reg_rule -> freq_range ;
1664
1669
@@ -1678,16 +1683,57 @@ static uint32_t reg_rule_to_chan_bw_flags(const struct ieee80211_regdomain *regd
1678
1683
MHZ_TO_KHZ (20 )))
1679
1684
bw_flags |= IEEE80211_CHAN_NO_20MHZ ;
1680
1685
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
+ }
1691
1737
return bw_flags ;
1692
1738
}
1693
1739
0 commit comments