If we run multiple instances of ath10k the supported band structures were shared with all instances. This is wrong and would cause corruption. Fix it by making a private copy for each instance.
I didn't copy the rate structure ath10k_rates as ath9k also doesn't copy it. Most likely nothing modifies that structure, but that needs to be verified. Signed-off-by: Kalle Valo <kv...@qca.qualcomm.com> --- drivers/net/wireless/ath/ath10k/core.h | 4 ++ drivers/net/wireless/ath/ath10k/mac.c | 63 ++++++++++++++++++++------------ 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 42d9e72..c50ef59 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -322,6 +322,10 @@ struct ath10k { int vdev_id; } scan; + struct { + struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; + } mac; + /* should never be NULL; needed for regular htt rx */ struct ieee80211_channel __rcu *rx_channel; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 8f58dda..20fba5d 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -2429,7 +2429,7 @@ static const struct ieee80211_ops ath10k_ops = { .max_power = 30, \ } -static struct ieee80211_channel ath10k_2ghz_channels[] = { +static const struct ieee80211_channel ath10k_2ghz_channels[] = { CHAN2G(1, 2412, 0), CHAN2G(2, 2417, 0), CHAN2G(3, 2422, 0), @@ -2446,7 +2446,7 @@ static struct ieee80211_channel ath10k_2ghz_channels[] = { CHAN2G(14, 2484, 0), }; -static struct ieee80211_channel ath10k_5ghz_channels[] = { +static const struct ieee80211_channel ath10k_5ghz_channels[] = { CHAN5G(36, 5180, 14), CHAN5G(40, 5200, 15), CHAN5G(44, 5220, 16), @@ -2495,22 +2495,6 @@ static struct ieee80211_rate ath10k_rates[] = { #define ath10k_g_rates (ath10k_rates + 0) #define ath10k_g_rates_size (ARRAY_SIZE(ath10k_rates)) -static struct ieee80211_supported_band ath10k_band_2ghz = { - .n_channels = ARRAY_SIZE(ath10k_2ghz_channels), - .channels = ath10k_2ghz_channels, - .n_bitrates = ath10k_g_rates_size, - .bitrates = ath10k_g_rates, - /* .ht_cap depends on FW capabilities */ -}; - -static struct ieee80211_supported_band ath10k_band_5ghz = { - .n_channels = ARRAY_SIZE(ath10k_5ghz_channels), - .channels = ath10k_5ghz_channels, - .n_bitrates = ath10k_a_rates_size, - .bitrates = ath10k_a_rates, - /* .ht_cap depends on FW capabilities */ -}; - struct ath10k *ath10k_mac_create(void) { struct ieee80211_hw *hw; @@ -2652,7 +2636,9 @@ struct ath10k_vif *ath10k_get_arvif(struct ath10k *ar, u32 vdev_id) int ath10k_mac_register(struct ath10k *ar) { struct ath_common *common = ath10k_common(ar); + struct ieee80211_supported_band *band; struct ieee80211_sta_ht_cap ht_cap; + void *channels; int ret; SET_IEEE80211_PERM_ADDR(ar->hw, ar->mac_addr); @@ -2660,14 +2646,40 @@ int ath10k_mac_register(struct ath10k *ar) SET_IEEE80211_DEV(ar->hw, ar->dev); ht_cap = ath10k_get_ht_cap(ar); - ath10k_band_2ghz.ht_cap = ht_cap; - ath10k_band_5ghz.ht_cap = ht_cap; - if (ar->phy_capability & WHAL_WLAN_11G_CAPABILITY) - ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &ath10k_band_2ghz; + if (ar->phy_capability & WHAL_WLAN_11G_CAPABILITY) { + channels = kmemdup(ath10k_2ghz_channels, + sizeof(ath10k_2ghz_channels), + GFP_KERNEL); + if (!channels) + return -ENOMEM; + + band = &ar->mac.sbands[IEEE80211_BAND_2GHZ]; + band->n_channels = ARRAY_SIZE(ath10k_2ghz_channels); + band->channels = channels; + band->n_bitrates = ath10k_g_rates_size; + band->bitrates = ath10k_g_rates; + band->ht_cap = ht_cap; + ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = band; + } - if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) - ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &ath10k_band_5ghz; + + + if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) { + channels = kmemdup(ath10k_5ghz_channels, + sizeof(ath10k_5ghz_channels), + GFP_KERNEL); + if (!channels) + return -ENOMEM; + + band = &ar->mac.sbands[IEEE80211_BAND_2GHZ]; + band->n_channels = ARRAY_SIZE(ath10k_5ghz_channels); + band->channels = channels; + band->n_bitrates = ath10k_a_rates_size; + band->bitrates = ath10k_a_rates; + band->ht_cap = ht_cap; + ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = band; + } ar->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | @@ -2745,5 +2757,8 @@ void ath10k_mac_unregister(struct ath10k *ar) { ieee80211_unregister_hw(ar->hw); + kfree(ar->mac.sbands[IEEE80211_BAND_2GHZ].channels); + kfree(ar->mac.sbands[IEEE80211_BAND_5GHZ].channels); + SET_IEEE80211_DEV(ar->hw, NULL); } _______________________________________________ ath9k-devel mailing list ath9k-devel@lists.ath9k.org https://lists.ath9k.org/mailman/listinfo/ath9k-devel