--- zzzz-none-000/linux-5.15.111/net/wireless/chan.c 2023-05-11 14:00:40.000000000 +0000 +++ puma7-atom-6670-761/linux-5.15.111/net/wireless/chan.c 2024-02-07 10:23:31.000000000 +0000 @@ -181,6 +181,9 @@ case NL80211_CHAN_WIDTH_160: mhz = 160; break; + case NL80211_CHAN_WIDTH_320: + mhz = 320; + break; default: WARN_ON_ONCE(1); return -1; @@ -287,6 +290,27 @@ if (chandef->center_freq2) return false; break; + case NL80211_CHAN_WIDTH_320: + if (chandef->center_freq1 != control_freq + 150 && + chandef->center_freq1 != control_freq + 130 && + chandef->center_freq1 != control_freq + 110 && + chandef->center_freq1 != control_freq + 90 && + chandef->center_freq1 != control_freq + 70 && + chandef->center_freq1 != control_freq + 50 && + chandef->center_freq1 != control_freq + 30 && + chandef->center_freq1 != control_freq + 10 && + chandef->center_freq1 != control_freq - 10 && + chandef->center_freq1 != control_freq - 30 && + chandef->center_freq1 != control_freq - 50 && + chandef->center_freq1 != control_freq - 70 && + chandef->center_freq1 != control_freq - 90 && + chandef->center_freq1 != control_freq - 110 && + chandef->center_freq1 != control_freq - 130 && + chandef->center_freq1 != control_freq - 150) + return false; + if (chandef->center_freq2) + return false; + break; default: return false; } @@ -305,7 +329,7 @@ EXPORT_SYMBOL(cfg80211_chandef_valid); static void chandef_primary_freqs(const struct cfg80211_chan_def *c, - u32 *pri40, u32 *pri80) + u32 *pri40, u32 *pri80, u32 *pri160) { int tmp; @@ -313,9 +337,11 @@ case NL80211_CHAN_WIDTH_40: *pri40 = c->center_freq1; *pri80 = 0; + *pri160 = 0; break; case NL80211_CHAN_WIDTH_80: case NL80211_CHAN_WIDTH_80P80: + *pri160 = 0; *pri80 = c->center_freq1; /* n_P20 */ tmp = (30 + c->chan->center_freq - c->center_freq1)/20; @@ -325,6 +351,7 @@ *pri40 = c->center_freq1 - 20 + 40 * tmp; break; case NL80211_CHAN_WIDTH_160: + *pri160 = c->center_freq1; /* n_P20 */ tmp = (70 + c->chan->center_freq - c->center_freq1)/20; /* n_P40 */ @@ -335,6 +362,18 @@ tmp /= 2; *pri80 = c->center_freq1 - 40 + 80 * tmp; break; + case NL80211_CHAN_WIDTH_320: + *pri160 = c->center_freq1; + /* n_P20 */ + tmp = (150 + c->chan->center_freq - c->center_freq1)/20; + /* n_P40 */ + tmp /= 2; + /* freq_P40 */ + *pri40 = c->center_freq1 - 140 + 40 * tmp; + /* n_P80 */ + tmp /= 2; + *pri80 = c->center_freq1 - 120 + 80 * tmp; + break; default: WARN_ON_ONCE(1); } @@ -344,7 +383,7 @@ cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1, const struct cfg80211_chan_def *c2) { - u32 c1_pri40, c1_pri80, c2_pri40, c2_pri80; + u32 c1_pri40, c1_pri80, c2_pri40, c2_pri80, c1_pri160, c2_pri160; /* If they are identical, return */ if (cfg80211_chandef_identical(c1, c2)) @@ -379,8 +418,8 @@ c2->width == NL80211_CHAN_WIDTH_20) return c1; - chandef_primary_freqs(c1, &c1_pri40, &c1_pri80); - chandef_primary_freqs(c2, &c2_pri40, &c2_pri80); + chandef_primary_freqs(c1, &c1_pri40, &c1_pri80, &c1_pri160); + chandef_primary_freqs(c2, &c2_pri40, &c2_pri80, &c2_pri160); if (c1_pri40 != c2_pri40) return NULL; @@ -389,6 +428,10 @@ if (c1_pri80 && c2_pri80 && c1_pri80 != c2_pri80) return NULL; + WARN_ON(!c1_pri160 && !c2_pri160); + if (c1_pri160 && c2_pri160 && c1_pri160 != c2_pri160) + return NULL; + if (c1->width > c2->width) return c1; return c2; @@ -862,9 +905,16 @@ return max(t1, t2); } +#ifndef CFG80211_PROP_MULTI_LINK_SUPPORT static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, u32 center_freq, u32 bandwidth, u32 prohibited_flags) +#else /* CFG80211_PROP_MULTI_LINK_SUPPORT */ +static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, + u32 center_freq, u32 bandwidth, + u32 prohibited_flags, + u32 puncture_bitmap) +#endif /* CFG80211_PROP_MULTI_LINK_SUPPORT */ { struct ieee80211_channel *c; u32 freq, start_freq, end_freq; @@ -873,6 +923,15 @@ end_freq = cfg80211_get_end_freq(center_freq, bandwidth); for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) { +#ifdef CFG80211_PROP_MULTI_LINK_SUPPORT + u32 disabled_sub_chan = 0; + + disabled_sub_chan = + (1 << (KHZ_TO_MHZ(freq) - KHZ_TO_MHZ(start_freq)) / 20) & + puncture_bitmap; + if (disabled_sub_chan) + continue; +#endif /* CFG80211_PROP_MULTI_LINK_SUPPORT */ c = ieee80211_get_channel_khz(wiphy, freq); if (!c || c->flags & prohibited_flags) return false; @@ -943,6 +1002,15 @@ struct ieee80211_edmg *edmg_cap; u32 width, control_freq, cap; bool ext_nss_cap, support_80_80 = false; +#ifdef CFG80211_PROP_MULTI_LINK_SUPPORT + struct ieee80211_supported_band *sband; + const struct ieee80211_sband_iftype_data *iftd; + enum nl80211_band band; + bool has_eht = false; + int i = 0; + u32 puncture_bitmap_cfreq1 = 0; + u32 puncture_bitmap_cfreq2 = 0; +#endif /* CFG80211_PROP_MULTI_LINK_SUPPORT */ if (WARN_ON(!cfg80211_chandef_valid(chandef))) return false; @@ -1044,6 +1112,38 @@ (vht_cap->cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK))) return false; break; +#ifdef CFG80211_PROP_MULTI_LINK_SUPPORT + case NL80211_CHAN_WIDTH_320: + prohibited_flags |= IEEE80211_CHAN_NO_320MHZ; + width = 320; + + band = chandef->chan->band; + if (band == NL80211_BAND_6GHZ) + break; + + sband = wiphy->bands[band]; + if (!sband) + return false; + + for (i = 0; i < sband->n_iftype_data; i++) { + iftd = &sband->iftype_data[i]; + if (!iftd) + continue; + + if (i == 0) + has_eht = iftd->eht_cap.has_eht; + else + has_eht = has_eht && iftd->eht_cap.has_eht; + } + + if (!has_eht) + return false; + + /* TODO: + * Check ieee80211_eht_cap_elem for 320 MHz capability + */ + break; +#endif /* CFG80211_PROP_MULTI_LINK_SUPPORT */ default: WARN_ON_ONCE(1); return false; @@ -1067,7 +1167,7 @@ if (width < 20) prohibited_flags |= IEEE80211_CHAN_NO_OFDM; - +#ifndef CFG80211_PROP_MULTI_LINK_SUPPORT if (!cfg80211_secondary_chans_ok(wiphy, ieee80211_chandef_to_khz(chandef), width, prohibited_flags)) @@ -1078,6 +1178,25 @@ return cfg80211_secondary_chans_ok(wiphy, MHZ_TO_KHZ(chandef->center_freq2), width, prohibited_flags); +#else /* CFG80211_PROP_MULTI_LINK_SUPPORT */ + if (chandef->center_freq2) + puncture_bitmap_cfreq2 = chandef->puncture_bitmap; + else + puncture_bitmap_cfreq1 = chandef->puncture_bitmap; + + if (!cfg80211_secondary_chans_ok(wiphy, + ieee80211_chandef_to_khz(chandef), + width, prohibited_flags, + puncture_bitmap_cfreq1)) + return false; + + if (!chandef->center_freq2) + return true; + return cfg80211_secondary_chans_ok(wiphy, + MHZ_TO_KHZ(chandef->center_freq2), + width, prohibited_flags, + puncture_bitmap_cfreq2); +#endif /* CFG80211_PROP_MULTI_LINK_SUPPORT */ } EXPORT_SYMBOL(cfg80211_chandef_usable);