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

Reply via email to