diff options
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/mac.c | 93 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/reg.c | 13 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/wmi.c | 9 |
3 files changed, 109 insertions, 6 deletions
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 302ad6da48f4..fa069ac30e0d 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -4152,8 +4152,9 @@ ath12k_mac_select_scan_device(struct ieee80211_hw *hw, band = NL80211_BAND_6GHZ; for_each_ar(ah, ar, i) { - /* TODO 5 GHz low high split changes */ - if (ar->mac.sbands[band].channels) + if (ar->mac.sbands[band].channels && + center_freq >= KHZ_TO_MHZ(ar->freq_range.start_freq) && + center_freq <= KHZ_TO_MHZ(ar->freq_range.end_freq)) return ar; } @@ -11881,6 +11882,32 @@ static u32 ath12k_get_phy_id(struct ath12k *ar, u32 band) return 0; } +static int ath12k_mac_update_band(struct ath12k *ar, + struct ieee80211_supported_band *orig_band, + struct ieee80211_supported_band *new_band) +{ + int i; + + if (!orig_band || !new_band) + return -EINVAL; + + if (orig_band->band != new_band->band) + return -EINVAL; + + for (i = 0; i < new_band->n_channels; i++) { + if (new_band->channels[i].flags & IEEE80211_CHAN_DISABLED) + continue; + /* An enabled channel in new_band should not be already enabled + * in the orig_band + */ + if (WARN_ON(!(orig_band->channels[i].flags & + IEEE80211_CHAN_DISABLED))) + return -EINVAL; + orig_band->channels[i].flags &= ~IEEE80211_CHAN_DISABLED; + } + return 0; +} + static int ath12k_mac_setup_channels_rates(struct ath12k *ar, u32 supported_bands, struct ieee80211_supported_band *bands[]) @@ -11891,6 +11918,7 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar, u32 phy_id, freq_low, freq_high; struct ath12k_hw *ah = ar->ah; void *channels; + int ret; BUILD_BUG_ON((ARRAY_SIZE(ath12k_2ghz_channels) + ARRAY_SIZE(ath12k_5ghz_channels) + @@ -11912,7 +11940,6 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar, band->channels = channels; band->n_bitrates = ath12k_g_rates_size; band->bitrates = ath12k_g_rates; - bands[NL80211_BAND_2GHZ] = band; if (ab->hw_params->single_pdev_only) { phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_2GHZ_CAP); @@ -11929,6 +11956,22 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar, reg_cap->high_2ghz_chan); ath12k_mac_update_freq_range(ar, freq_low, freq_high); + + if (!bands[NL80211_BAND_2GHZ]) { + bands[NL80211_BAND_2GHZ] = band; + } else { + /* Split mac in same band under same wiphy */ + ret = ath12k_mac_update_band(ar, bands[NL80211_BAND_2GHZ], band); + if (ret) { + kfree(channels); + band->channels = NULL; + return ret; + } + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac pdev %u identified as 2 GHz split mac with start freq %d end freq %d", + ar->pdev->pdev_id, + KHZ_TO_MHZ(ar->freq_range.start_freq), + KHZ_TO_MHZ(ar->freq_range.end_freq)); + } } if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP) { @@ -11947,7 +11990,6 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar, band->channels = channels; band->n_bitrates = ath12k_a_rates_size; band->bitrates = ath12k_a_rates; - bands[NL80211_BAND_6GHZ] = band; freq_low = max(reg_cap->low_5ghz_chan, ab->reg_freq_6ghz.start_freq); @@ -11960,6 +12002,26 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar, ath12k_mac_update_freq_range(ar, freq_low, freq_high); ah->use_6ghz_regd = true; + + if (!bands[NL80211_BAND_6GHZ]) { + bands[NL80211_BAND_6GHZ] = band; + } else { + /* Split mac in same band under same wiphy */ + ret = ath12k_mac_update_band(ar, + bands[NL80211_BAND_6GHZ], + band); + if (ret) { + kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels); + ar->mac.sbands[NL80211_BAND_2GHZ].channels = NULL; + kfree(channels); + band->channels = NULL; + return ret; + } + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac pdev %u identified as 6 GHz split mac with start freq %d end freq %d", + ar->pdev->pdev_id, + KHZ_TO_MHZ(ar->freq_range.start_freq), + KHZ_TO_MHZ(ar->freq_range.end_freq)); + } } if (reg_cap->low_5ghz_chan < ATH12K_MIN_6GHZ_FREQ) { @@ -11978,7 +12040,6 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar, band->channels = channels; band->n_bitrates = ath12k_a_rates_size; band->bitrates = ath12k_a_rates; - bands[NL80211_BAND_5GHZ] = band; if (ab->hw_params->single_pdev_only) { phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_5GHZ_CAP); @@ -11995,6 +12056,28 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar, reg_cap->high_5ghz_chan); ath12k_mac_update_freq_range(ar, freq_low, freq_high); + + if (!bands[NL80211_BAND_5GHZ]) { + bands[NL80211_BAND_5GHZ] = band; + } else { + /* Split mac in same band under same wiphy */ + ret = ath12k_mac_update_band(ar, + bands[NL80211_BAND_5GHZ], + band); + if (ret) { + kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels); + ar->mac.sbands[NL80211_BAND_2GHZ].channels = NULL; + kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels); + ar->mac.sbands[NL80211_BAND_2GHZ].channels = NULL; + kfree(channels); + band->channels = NULL; + return ret; + } + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac pdev %u identified as 5 GHz split mac with start freq %d end freq %d", + ar->pdev->pdev_id, + KHZ_TO_MHZ(ar->freq_range.start_freq), + KHZ_TO_MHZ(ar->freq_range.end_freq)); + } } } diff --git a/drivers/net/wireless/ath/ath12k/reg.c b/drivers/net/wireless/ath/ath12k/reg.c index 28bb26d2dd82..a7b9ecc14c39 100644 --- a/drivers/net/wireless/ath/ath12k/reg.c +++ b/drivers/net/wireless/ath/ath12k/reg.c @@ -176,6 +176,12 @@ int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait) if (bands[band]->channels[i].flags & IEEE80211_CHAN_DISABLED) continue; + /* Skip Channels that are not in current radio's range */ + if (bands[band]->channels[i].center_freq < + KHZ_TO_MHZ(ar->freq_range.start_freq) || + bands[band]->channels[i].center_freq > + KHZ_TO_MHZ(ar->freq_range.end_freq)) + continue; num_channels++; } @@ -207,6 +213,13 @@ int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait) if (channel->flags & IEEE80211_CHAN_DISABLED) continue; + /* Skip Channels that are not in current radio's range */ + if (bands[band]->channels[i].center_freq < + KHZ_TO_MHZ(ar->freq_range.start_freq) || + bands[band]->channels[i].center_freq > + KHZ_TO_MHZ(ar->freq_range.end_freq)) + continue; + /* TODO: Set to true/false based on some condition? */ ch->allow_ht = true; ch->allow_vht = true; diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index 465f877fc0fb..1b82fe0e5099 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -6445,9 +6445,16 @@ static int freq_to_idx(struct ath12k *ar, int freq) if (!sband) continue; - for (ch = 0; ch < sband->n_channels; ch++, idx++) + for (ch = 0; ch < sband->n_channels; ch++, idx++) { + if (sband->channels[ch].center_freq < + KHZ_TO_MHZ(ar->freq_range.start_freq) || + sband->channels[ch].center_freq > + KHZ_TO_MHZ(ar->freq_range.end_freq)) + continue; + if (sband->channels[ch].center_freq == freq) goto exit; + } } exit: |
