Commit f209f529 authored by Felix Fietkau's avatar Felix Fietkau Committed by John W. Linville

ath9k: fix channel flag / regd issues with multiple cards

Since the regulatory code touches the channel array, it needs to be
copied for each device instance. That way the original channel array
can also be made const.
Signed-off-by: default avatarFelix Fietkau <nbd@openwrt.org>
Cc: stable@kernel.org [all]
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 2234362c
...@@ -56,7 +56,7 @@ MODULE_PARM_DESC(blink, "Enable LED blink on activity"); ...@@ -56,7 +56,7 @@ MODULE_PARM_DESC(blink, "Enable LED blink on activity");
* on 5 MHz steps, we support the channels which we know * on 5 MHz steps, we support the channels which we know
* we have calibration data for all cards though to make * we have calibration data for all cards though to make
* this static */ * this static */
static struct ieee80211_channel ath9k_2ghz_chantable[] = { static const struct ieee80211_channel ath9k_2ghz_chantable[] = {
CHAN2G(2412, 0), /* Channel 1 */ CHAN2G(2412, 0), /* Channel 1 */
CHAN2G(2417, 1), /* Channel 2 */ CHAN2G(2417, 1), /* Channel 2 */
CHAN2G(2422, 2), /* Channel 3 */ CHAN2G(2422, 2), /* Channel 3 */
...@@ -77,7 +77,7 @@ static struct ieee80211_channel ath9k_2ghz_chantable[] = { ...@@ -77,7 +77,7 @@ static struct ieee80211_channel ath9k_2ghz_chantable[] = {
* on 5 MHz steps, we support the channels which we know * on 5 MHz steps, we support the channels which we know
* we have calibration data for all cards though to make * we have calibration data for all cards though to make
* this static */ * this static */
static struct ieee80211_channel ath9k_5ghz_chantable[] = { static const struct ieee80211_channel ath9k_5ghz_chantable[] = {
/* _We_ call this UNII 1 */ /* _We_ call this UNII 1 */
CHAN5G(5180, 14), /* Channel 36 */ CHAN5G(5180, 14), /* Channel 36 */
CHAN5G(5200, 15), /* Channel 40 */ CHAN5G(5200, 15), /* Channel 40 */
...@@ -477,10 +477,17 @@ static int ath9k_init_queues(struct ath_softc *sc) ...@@ -477,10 +477,17 @@ static int ath9k_init_queues(struct ath_softc *sc)
return -EIO; return -EIO;
} }
static void ath9k_init_channels_rates(struct ath_softc *sc) static int ath9k_init_channels_rates(struct ath_softc *sc)
{ {
void *channels;
if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) { if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) {
sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable; channels = kmemdup(ath9k_2ghz_chantable,
sizeof(ath9k_2ghz_chantable), GFP_KERNEL);
if (!channels)
return -ENOMEM;
sc->sbands[IEEE80211_BAND_2GHZ].channels = channels;
sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
sc->sbands[IEEE80211_BAND_2GHZ].n_channels = sc->sbands[IEEE80211_BAND_2GHZ].n_channels =
ARRAY_SIZE(ath9k_2ghz_chantable); ARRAY_SIZE(ath9k_2ghz_chantable);
...@@ -490,7 +497,15 @@ static void ath9k_init_channels_rates(struct ath_softc *sc) ...@@ -490,7 +497,15 @@ static void ath9k_init_channels_rates(struct ath_softc *sc)
} }
if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) { if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) {
sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable; channels = kmemdup(ath9k_5ghz_chantable,
sizeof(ath9k_5ghz_chantable), GFP_KERNEL);
if (!channels) {
if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
return -ENOMEM;
}
sc->sbands[IEEE80211_BAND_5GHZ].channels = channels;
sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
sc->sbands[IEEE80211_BAND_5GHZ].n_channels = sc->sbands[IEEE80211_BAND_5GHZ].n_channels =
ARRAY_SIZE(ath9k_5ghz_chantable); ARRAY_SIZE(ath9k_5ghz_chantable);
...@@ -499,6 +514,7 @@ static void ath9k_init_channels_rates(struct ath_softc *sc) ...@@ -499,6 +514,7 @@ static void ath9k_init_channels_rates(struct ath_softc *sc)
sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates = sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
ARRAY_SIZE(ath9k_legacy_rates) - 4; ARRAY_SIZE(ath9k_legacy_rates) - 4;
} }
return 0;
} }
static void ath9k_init_misc(struct ath_softc *sc) static void ath9k_init_misc(struct ath_softc *sc)
...@@ -594,8 +610,11 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, ...@@ -594,8 +610,11 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
if (ret) if (ret)
goto err_btcoex; goto err_btcoex;
ret = ath9k_init_channels_rates(sc);
if (ret)
goto err_btcoex;
ath9k_init_crypto(sc); ath9k_init_crypto(sc);
ath9k_init_channels_rates(sc);
ath9k_init_misc(sc); ath9k_init_misc(sc);
return 0; return 0;
...@@ -755,6 +774,12 @@ static void ath9k_deinit_softc(struct ath_softc *sc) ...@@ -755,6 +774,12 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
{ {
int i = 0; int i = 0;
if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
if (sc->sbands[IEEE80211_BAND_5GHZ].channels)
kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels);
if ((sc->btcoex.no_stomp_timer) && if ((sc->btcoex.no_stomp_timer) &&
sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer); ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment