ath9k: change the BSSID mask calculation to fix setting arbitrary MAC address on interfaces

Signed-off-by: Felix Fietkau <nbd@openwrt.org>

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@36344 3c298f89-4303-0410-b956-a3cf2f4a3e73
master
Felix Fietkau 2013-04-16 10:53:02 +00:00
parent 270bb2883c
commit a2043c1856
8 changed files with 123 additions and 14 deletions

View File

@ -607,6 +607,23 @@
if (!ath9k_hw_set_reset_reg(ah, reset_type)) if (!ath9k_hw_set_reset_reg(ah, reset_type))
return false; return false;
@@ -1876,13 +1878,12 @@ int ath9k_hw_reset(struct ath_hw *ah, st
ENABLE_REGWRITE_BUFFER(ah);
- REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr));
- REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4)
- | macStaId1
+ REG_RMW(ah, AR_STA_ID1, macStaId1
| AR_STA_ID1_RTS_USE_DEF
| (ah->config.
ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0)
- | ah->sta_id1_defaults);
+ | ah->sta_id1_defaults,
+ ~AR_STA_ID1_SADH_MASK);
ath_hw_setbssidmask(common);
REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
ath9k_hw_write_associd(ah);
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -1236,8 +1236,10 @@ static inline void rt2x00lib_set_if_comb @@ -1236,8 +1236,10 @@ static inline void rt2x00lib_set_if_comb
@ -1629,3 +1646,95 @@
p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u " p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u "
"%3u(%3u) %8llu %8llu\n", "%3u(%3u) %8llu %8llu\n",
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -657,11 +657,10 @@ enum sc_op_flags {
struct ath_rate_table;
struct ath9k_vif_iter_data {
- const u8 *hw_macaddr; /* phy's hardware address, set
- * before starting iteration for
- * valid bssid mask.
- */
+ u8 hw_macaddr[ETH_ALEN]; /* address of the first vif */
u8 mask[ETH_ALEN]; /* bssid mask */
+ bool has_hw_macaddr;
+
int naps; /* number of AP vifs */
int nmeshes; /* number of mesh vifs */
int nstations; /* number of station vifs */
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -835,10 +835,14 @@ static void ath9k_vif_iter(void *data, u
struct ath9k_vif_iter_data *iter_data = data;
int i;
- if (iter_data->hw_macaddr)
+ if (iter_data->has_hw_macaddr) {
for (i = 0; i < ETH_ALEN; i++)
iter_data->mask[i] &=
~(iter_data->hw_macaddr[i] ^ mac[i]);
+ } else {
+ memcpy(iter_data->hw_macaddr, mac, ETH_ALEN);
+ iter_data->has_hw_macaddr = true;
+ }
switch (vif->type) {
case NL80211_IFTYPE_AP:
@@ -887,7 +891,6 @@ void ath9k_calculate_iter_data(struct ie
* together with the BSSID mask when matching addresses.
*/
memset(iter_data, 0, sizeof(*iter_data));
- iter_data->hw_macaddr = common->macaddr;
memset(&iter_data->mask, 0xff, ETH_ALEN);
if (vif)
@@ -897,6 +900,8 @@ void ath9k_calculate_iter_data(struct ie
ieee80211_iterate_active_interfaces_atomic(
sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
ath9k_vif_iter, iter_data);
+
+ memcpy(common->macaddr, iter_data->hw_macaddr, ETH_ALEN);
}
/* Called with sc->mutex held. */
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -1493,9 +1493,6 @@ enum {
#define AR9271_RADIO_RF_RST 0x20
#define AR9271_GATE_MAC_CTL 0x4000
-#define AR_STA_ID0 0x8000
-#define AR_STA_ID1 0x8004
-#define AR_STA_ID1_SADH_MASK 0x0000FFFF
#define AR_STA_ID1_STA_AP 0x00010000
#define AR_STA_ID1_ADHOC 0x00020000
#define AR_STA_ID1_PWR_SAV 0x00040000
--- a/drivers/net/wireless/ath/hw.c
+++ b/drivers/net/wireless/ath/hw.c
@@ -118,6 +118,12 @@
void ath_hw_setbssidmask(struct ath_common *common)
{
void *ah = common->ah;
+ u32 id1;
+
+ REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr));
+ id1 = REG_READ(ah, AR_STA_ID1) & ~AR_STA_ID1_SADH_MASK;
+ id1 |= get_unaligned_le16(common->macaddr + 4);
+ REG_WRITE(ah, AR_STA_ID1, id1);
REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(common->bssidmask));
REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(common->bssidmask + 4));
--- a/drivers/net/wireless/ath/reg.h
+++ b/drivers/net/wireless/ath/reg.h
@@ -23,6 +23,10 @@
#define AR_MIBC_CMC 0x00000004
#define AR_MIBC_MCS 0x00000008
+#define AR_STA_ID0 0x8000
+#define AR_STA_ID1 0x8004
+#define AR_STA_ID1_SADH_MASK 0x0000ffff
+
/*
* BSSID mask registers. See ath_hw_set_bssid_mask()
* for detailed documentation about these registers.

View File

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/hw.c --- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1947,8 +1947,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st @@ -1946,8 +1946,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
REG_WRITE(ah, AR_OBS, 8); REG_WRITE(ah, AR_OBS, 8);
if (ah->config.rx_intr_mitigation) { if (ah->config.rx_intr_mitigation) {

View File

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/ath9k.h --- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -690,6 +690,7 @@ struct ath_softc { @@ -689,6 +689,7 @@ struct ath_softc {
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
struct device *dev; struct device *dev;
@ -8,7 +8,7 @@
struct survey_info *cur_survey; struct survey_info *cur_survey;
struct survey_info survey[ATH9K_NUM_CHANNELS]; struct survey_info survey[ATH9K_NUM_CHANNELS];
@@ -894,6 +895,7 @@ struct fft_sample_ht20 { @@ -893,6 +894,7 @@ struct fft_sample_ht20 {
u8 data[SPECTRAL_HT20_NUM_BINS]; u8 data[SPECTRAL_HT20_NUM_BINS];
} __packed; } __packed;
@ -80,7 +80,7 @@
debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc, debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc,
--- a/drivers/net/wireless/ath/ath9k/main.c --- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1131,7 +1131,7 @@ int ath9k_spectral_scan_config(struct ie @@ -1136,7 +1136,7 @@ int ath9k_spectral_scan_config(struct ie
return 0; return 0;
} }
@ -89,7 +89,7 @@
{ {
struct ath_softc *sc = hw->priv; struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
@@ -1185,9 +1185,11 @@ static int ath9k_config(struct ieee80211 @@ -1190,9 +1190,11 @@ static int ath9k_config(struct ieee80211
if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) { if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) {
struct ieee80211_channel *curchan = hw->conf.channel; struct ieee80211_channel *curchan = hw->conf.channel;
@ -101,7 +101,7 @@
if (ah->curchan) if (ah->curchan)
old_pos = ah->curchan - &ah->channels[0]; old_pos = ah->curchan - &ah->channels[0];
@@ -1230,7 +1232,23 @@ static int ath9k_config(struct ieee80211 @@ -1235,7 +1237,23 @@ static int ath9k_config(struct ieee80211
memset(&sc->survey[pos], 0, sizeof(struct survey_info)); memset(&sc->survey[pos], 0, sizeof(struct survey_info));
} }

View File

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/main.c --- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1255,6 +1255,8 @@ int ath9k_config(struct ieee80211_hw *hw @@ -1260,6 +1260,8 @@ int ath9k_config(struct ieee80211_hw *hw
return -EINVAL; return -EINVAL;
} }
@ -9,7 +9,7 @@
/* /*
* The most recent snapshot of channel->noisefloor for the old * The most recent snapshot of channel->noisefloor for the old
* channel is only available after the hardware reset. Copy it to * channel is only available after the hardware reset. Copy it to
@@ -1274,6 +1276,7 @@ int ath9k_config(struct ieee80211_hw *hw @@ -1279,6 +1281,7 @@ int ath9k_config(struct ieee80211_hw *hw
sc->config.txpowlimit = 2 * conf->power_level; sc->config.txpowlimit = 2 * conf->power_level;
ath9k_cmn_update_txpow(ah, sc->curtxpow, ath9k_cmn_update_txpow(ah, sc->curtxpow,
sc->config.txpowlimit, &sc->curtxpow); sc->config.txpowlimit, &sc->curtxpow);

View File

@ -10,7 +10,7 @@
--- a/drivers/net/wireless/ath/ath9k/hw.c --- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -2818,7 +2818,7 @@ void ath9k_hw_apply_txpower(struct ath_h @@ -2817,7 +2817,7 @@ void ath9k_hw_apply_txpower(struct ath_h
channel = chan->chan; channel = chan->chan;
chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER); chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
new_pwr = min_t(int, chan_pwr, reg->power_limit); new_pwr = min_t(int, chan_pwr, reg->power_limit);
@ -21,7 +21,7 @@
if (ant_gain > max_gain) if (ant_gain > max_gain)
--- a/drivers/net/wireless/ath/ath9k/main.c --- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1272,7 +1272,10 @@ int ath9k_config(struct ieee80211_hw *hw @@ -1277,7 +1277,10 @@ int ath9k_config(struct ieee80211_hw *hw
} }
if (changed & IEEE80211_CONF_CHANGE_POWER) { if (changed & IEEE80211_CONF_CHANGE_POWER) {

View File

@ -10,7 +10,7 @@
#else #else
static inline void ath_init_leds(struct ath_softc *sc) static inline void ath_init_leds(struct ath_softc *sc)
{ {
@@ -686,6 +689,13 @@ enum spectral_mode { @@ -685,6 +688,13 @@ enum spectral_mode {
SPECTRAL_CHANSCAN, SPECTRAL_CHANSCAN,
}; };
@ -24,7 +24,7 @@
struct ath_softc { struct ath_softc {
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
struct device *dev; struct device *dev;
@@ -727,9 +737,8 @@ struct ath_softc { @@ -726,9 +736,8 @@ struct ath_softc {
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
#ifdef CONFIG_MAC80211_LEDS #ifdef CONFIG_MAC80211_LEDS

View File

@ -115,7 +115,7 @@
int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
struct ath9k_hw_cal_data *caldata, bool fastcc) struct ath9k_hw_cal_data *caldata, bool fastcc)
{ {
@@ -2024,6 +2038,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st @@ -2023,6 +2037,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
} }
ath9k_hw_apply_gpio_override(ah); ath9k_hw_apply_gpio_override(ah);

View File

@ -12,7 +12,7 @@
--- a/drivers/net/wireless/ath/ath9k/hw.c --- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -2414,17 +2414,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw @@ -2413,17 +2413,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw
} }
eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE);