summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c132
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c147
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c112
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h32
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c61
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c13
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c34
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c101
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c103
9 files changed, 358 insertions, 377 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index bfab5a165b76..31c1dd271627 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -291,90 +291,67 @@ static void rt2400pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
}
-static void rt2400pci_config_rate(struct rt2x00_dev *rt2x00dev, const int rate)
+static void rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev,
+ const int short_preamble,
+ const int ack_timeout,
+ const int ack_consume_time)
{
- struct ieee80211_conf *conf = &rt2x00dev->hw->conf;
+ int preamble_mask;
u32 reg;
- u32 preamble;
- u16 value;
-
- if (DEVICE_GET_RATE_FIELD(rate, PREAMBLE))
- preamble = SHORT_PREAMBLE;
- else
- preamble = PREAMBLE;
- reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATEMASK;
- rt2x00pci_register_write(rt2x00dev, ARCSR1, reg);
+ /*
+ * When short preamble is enabled, we should set bit 0x08
+ */
+ preamble_mask = short_preamble << 3;
rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
- value = ((conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) ?
- SHORT_DIFS : DIFS) +
- PLCP + preamble + get_duration(ACK_SIZE, 10);
- rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, value);
- value = SIFS + PLCP + preamble + get_duration(ACK_SIZE, 10);
- rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, value);
+ rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, ack_timeout);
+ rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, ack_consume_time);
rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
- preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) ? 0x08 : 0x00;
-
rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
- rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00 | preamble);
+ rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 10));
rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
rt2x00pci_register_read(rt2x00dev, ARCSR3, &reg);
- rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble);
+ rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 20));
rt2x00pci_register_write(rt2x00dev, ARCSR3, reg);
rt2x00pci_register_read(rt2x00dev, ARCSR4, &reg);
- rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble);
+ rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 55));
rt2x00pci_register_write(rt2x00dev, ARCSR4, reg);
rt2x00pci_register_read(rt2x00dev, ARCSR5, &reg);
- rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble);
+ rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110));
rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
}
static void rt2400pci_config_phymode(struct rt2x00_dev *rt2x00dev,
- const int phymode)
+ const int basic_rate_mask)
{
- struct ieee80211_hw_mode *mode;
- struct ieee80211_rate *rate;
-
- rt2x00dev->curr_hwmode = HWMODE_B;
-
- mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode];
- rate = &mode->rates[mode->num_rates - 1];
-
- rt2400pci_config_rate(rt2x00dev, rate->val2);
+ rt2x00pci_register_write(rt2x00dev, ARCSR1, basic_rate_mask);
}
static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev,
- const int index, const int channel)
+ struct rf_channel *rf)
{
- struct rf_channel reg;
-
- /*
- * Fill rf_reg structure.
- */
- memcpy(&reg, &rt2x00dev->spec.channels[index], sizeof(reg));
-
/*
* Switch on tuning bits.
*/
- rt2x00_set_field32(&reg.rf1, RF1_TUNER, 1);
- rt2x00_set_field32(&reg.rf3, RF3_TUNER, 1);
+ rt2x00_set_field32(&rf->rf1, RF1_TUNER, 1);
+ rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1);
- rt2400pci_rf_write(rt2x00dev, 1, reg.rf1);
- rt2400pci_rf_write(rt2x00dev, 2, reg.rf2);
- rt2400pci_rf_write(rt2x00dev, 3, reg.rf3);
+ rt2400pci_rf_write(rt2x00dev, 1, rf->rf1);
+ rt2400pci_rf_write(rt2x00dev, 2, rf->rf2);
+ rt2400pci_rf_write(rt2x00dev, 3, rf->rf3);
/*
* RF2420 chipset don't need any additional actions.
@@ -387,31 +364,31 @@ static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev,
* reference clock rate to activate auto_tune.
* After that we set the value back to the correct channel.
*/
- rt2400pci_rf_write(rt2x00dev, 1, reg.rf1);
+ rt2400pci_rf_write(rt2x00dev, 1, rf->rf1);
rt2400pci_rf_write(rt2x00dev, 2, 0x000c2a32);
- rt2400pci_rf_write(rt2x00dev, 3, reg.rf3);
+ rt2400pci_rf_write(rt2x00dev, 3, rf->rf3);
msleep(1);
- rt2400pci_rf_write(rt2x00dev, 1, reg.rf1);
- rt2400pci_rf_write(rt2x00dev, 2, reg.rf2);
- rt2400pci_rf_write(rt2x00dev, 3, reg.rf3);
+ rt2400pci_rf_write(rt2x00dev, 1, rf->rf1);
+ rt2400pci_rf_write(rt2x00dev, 2, rf->rf2);
+ rt2400pci_rf_write(rt2x00dev, 3, rf->rf3);
msleep(1);
/*
* Switch off tuning bits.
*/
- rt2x00_set_field32(&reg.rf1, RF1_TUNER, 0);
- rt2x00_set_field32(&reg.rf3, RF3_TUNER, 0);
+ rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0);
+ rt2x00_set_field32(&rf->rf3, RF3_TUNER, 0);
- rt2400pci_rf_write(rt2x00dev, 1, reg.rf1);
- rt2400pci_rf_write(rt2x00dev, 3, reg.rf3);
+ rt2400pci_rf_write(rt2x00dev, 1, rf->rf1);
+ rt2400pci_rf_write(rt2x00dev, 3, rf->rf3);
/*
* Clear false CRC during channel switch.
*/
- rt2x00pci_register_read(rt2x00dev, CNT0, &reg.rf1);
+ rt2x00pci_register_read(rt2x00dev, CNT0, &rf->rf1);
}
static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower)
@@ -465,25 +442,22 @@ static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev,
}
static void rt2400pci_config_duration(struct rt2x00_dev *rt2x00dev,
- int short_slot_time, int beacon_int)
+ struct rt2x00lib_conf *libconf)
{
u32 reg;
rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
- rt2x00_set_field32(&reg, CSR11_SLOT_TIME,
- short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME);
+ rt2x00_set_field32(&reg, CSR11_SLOT_TIME, libconf->slot_time);
rt2x00pci_register_write(rt2x00dev, CSR11, reg);
rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
- rt2x00_set_field32(&reg, CSR18_SIFS, SIFS);
- rt2x00_set_field32(&reg, CSR18_PIFS,
- short_slot_time ? SHORT_PIFS : PIFS);
+ rt2x00_set_field32(&reg, CSR18_SIFS, libconf->sifs);
+ rt2x00_set_field32(&reg, CSR18_PIFS, libconf->pifs);
rt2x00pci_register_write(rt2x00dev, CSR18, reg);
rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
- rt2x00_set_field32(&reg, CSR19_DIFS,
- short_slot_time ? SHORT_DIFS : DIFS);
- rt2x00_set_field32(&reg, CSR19_EIFS, EIFS);
+ rt2x00_set_field32(&reg, CSR19_DIFS, libconf->difs);
+ rt2x00_set_field32(&reg, CSR19_EIFS, libconf->eifs);
rt2x00pci_register_write(rt2x00dev, CSR19, reg);
rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
@@ -492,30 +466,30 @@ static void rt2400pci_config_duration(struct rt2x00_dev *rt2x00dev,
rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
- rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL, beacon_int * 16);
- rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION, beacon_int * 16);
+ rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
+ libconf->conf->beacon_int * 16);
+ rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
+ libconf->conf->beacon_int * 16);
rt2x00pci_register_write(rt2x00dev, CSR12, reg);
}
static void rt2400pci_config(struct rt2x00_dev *rt2x00dev,
const unsigned int flags,
- struct ieee80211_conf *conf)
+ struct rt2x00lib_conf *libconf)
{
- int short_slot_time = conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME;
-
if (flags & CONFIG_UPDATE_PHYMODE)
- rt2400pci_config_phymode(rt2x00dev, conf->phymode);
+ rt2400pci_config_phymode(rt2x00dev, libconf->basic_rates);
if (flags & CONFIG_UPDATE_CHANNEL)
- rt2400pci_config_channel(rt2x00dev, conf->channel_val,
- conf->channel);
+ rt2400pci_config_channel(rt2x00dev, &libconf->rf);
if (flags & CONFIG_UPDATE_TXPOWER)
- rt2400pci_config_txpower(rt2x00dev, conf->power_level);
+ rt2400pci_config_txpower(rt2x00dev,
+ libconf->conf->power_level);
if (flags & CONFIG_UPDATE_ANTENNA)
- rt2400pci_config_antenna(rt2x00dev, conf->antenna_sel_tx,
- conf->antenna_sel_rx);
+ rt2400pci_config_antenna(rt2x00dev,
+ libconf->conf->antenna_sel_tx,
+ libconf->conf->antenna_sel_rx);
if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
- rt2400pci_config_duration(rt2x00dev, short_slot_time,
- conf->beacon_int);
+ rt2400pci_config_duration(rt2x00dev, libconf);
}
static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev,
@@ -1609,6 +1583,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
.configure_filter = rt2400pci_configure_filter,
.get_stats = rt2x00mac_get_stats,
.set_retry_limit = rt2400pci_set_retry_limit,
+ .erp_ie_changed = rt2x00mac_erp_ie_changed,
.conf_tx = rt2400pci_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt2400pci_get_tsf,
@@ -1634,6 +1609,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
.config_mac_addr = rt2400pci_config_mac_addr,
.config_bssid = rt2400pci_config_bssid,
.config_type = rt2400pci_config_type,
+ .config_preamble = rt2400pci_config_preamble,
.config = rt2400pci_config,
};
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index c8c6a848be97..ff2d63267b19 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -295,100 +295,72 @@ static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
}
-static void rt2500pci_config_rate(struct rt2x00_dev *rt2x00dev, const int rate)
+static void rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev,
+ const int short_preamble,
+ const int ack_timeout,
+ const int ack_consume_time)
{
- struct ieee80211_conf *conf = &rt2x00dev->hw->conf;
+ int preamble_mask;
u32 reg;
- u32 preamble;
- u16 value;
-
- if (DEVICE_GET_RATE_FIELD(rate, PREAMBLE))
- preamble = SHORT_PREAMBLE;
- else
- preamble = PREAMBLE;
- reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATEMASK;
- rt2x00pci_register_write(rt2x00dev, ARCSR1, reg);
+ /*
+ * When short preamble is enabled, we should set bit 0x08
+ */
+ preamble_mask = short_preamble << 3;
rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
- value = ((conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) ?
- SHORT_DIFS : DIFS) +
- PLCP + preamble + get_duration(ACK_SIZE, 10);
- rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, value);
- value = SIFS + PLCP + preamble + get_duration(ACK_SIZE, 10);
- rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, value);
+ rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, ack_timeout);
+ rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, ack_consume_time);
rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
- preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) ? 0x08 : 0x00;
-
rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
- rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00 | preamble);
+ rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 10));
rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
rt2x00pci_register_read(rt2x00dev, ARCSR3, &reg);
- rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble);
+ rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 20));
rt2x00pci_register_write(rt2x00dev, ARCSR3, reg);
rt2x00pci_register_read(rt2x00dev, ARCSR4, &reg);
- rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble);
+ rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 55));
rt2x00pci_register_write(rt2x00dev, ARCSR4, reg);
rt2x00pci_register_read(rt2x00dev, ARCSR5, &reg);
- rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble);
+ rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110));
rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
}
static void rt2500pci_config_phymode(struct rt2x00_dev *rt2x00dev,
- const int phymode)
+ const int basic_rate_mask)
{
- struct ieee80211_hw_mode *mode;
- struct ieee80211_rate *rate;
-
- if (phymode == MODE_IEEE80211A)
- rt2x00dev->curr_hwmode = HWMODE_A;
- else if (phymode == MODE_IEEE80211B)
- rt2x00dev->curr_hwmode = HWMODE_B;
- else
- rt2x00dev->curr_hwmode = HWMODE_G;
-
- mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode];
- rate = &mode->rates[mode->num_rates - 1];
-
- rt2500pci_config_rate(rt2x00dev, rate->val2);
+ rt2x00pci_register_write(rt2x00dev, ARCSR1, basic_rate_mask);
}
static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev,
- const int index, const int channel,
- const int txpower)
+ struct rf_channel *rf, const int txpower)
{
- struct rf_channel reg;
u8 r70;
/*
- * Fill rf_reg structure.
- */
- memcpy(&reg, &rt2x00dev->spec.channels[index], sizeof(reg));
-
- /*
* Set TXpower.
*/
- rt2x00_set_field32(&reg.rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
+ rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
/*
* Switch on tuning bits.
* For RT2523 devices we do not need to update the R1 register.
*/
if (!rt2x00_rf(&rt2x00dev->chip, RF2523))
- rt2x00_set_field32(&reg.rf1, RF1_TUNER, 1);
- rt2x00_set_field32(&reg.rf3, RF3_TUNER, 1);
+ rt2x00_set_field32(&rf->rf1, RF1_TUNER, 1);
+ rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1);
/*
* For RT2525 we should first set the channel to half band higher.
@@ -401,24 +373,24 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev,
0x00080d2e, 0x00080d3a
};
- rt2500pci_rf_write(rt2x00dev, 1, reg.rf1);
- rt2500pci_rf_write(rt2x00dev, 2, vals[channel - 1]);
- rt2500pci_rf_write(rt2x00dev, 3, reg.rf3);
- if (reg.rf4)
- rt2500pci_rf_write(rt2x00dev, 4, reg.rf4);
+ rt2500pci_rf_write(rt2x00dev, 1, rf->rf1);
+ rt2500pci_rf_write(rt2x00dev, 2, vals[rf->channel - 1]);
+ rt2500pci_rf_write(rt2x00dev, 3, rf->rf3);
+ if (rf->rf4)
+ rt2500pci_rf_write(rt2x00dev, 4, rf->rf4);
}
- rt2500pci_rf_write(rt2x00dev, 1, reg.rf1);
- rt2500pci_rf_write(rt2x00dev, 2, reg.rf2);
- rt2500pci_rf_write(rt2x00dev, 3, reg.rf3);
- if (reg.rf4)
- rt2500pci_rf_write(rt2x00dev, 4, reg.rf4);
+ rt2500pci_rf_write(rt2x00dev, 1, rf->rf1);
+ rt2500pci_rf_write(rt2x00dev, 2, rf->rf2);
+ rt2500pci_rf_write(rt2x00dev, 3, rf->rf3);
+ if (rf->rf4)
+ rt2500pci_rf_write(rt2x00dev, 4, rf->rf4);
/*
* Channel 14 requires the Japan filter bit to be set.
*/
r70 = 0x46;
- rt2x00_set_field8(&r70, BBP_R70_JAPAN_FILTER, channel == 14);
+ rt2x00_set_field8(&r70, BBP_R70_JAPAN_FILTER, rf->channel == 14);
rt2500pci_bbp_write(rt2x00dev, 70, r70);
msleep(1);
@@ -428,17 +400,17 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev,
* For RT2523 devices we do not need to update the R1 register.
*/
if (!rt2x00_rf(&rt2x00dev->chip, RF2523)) {
- rt2x00_set_field32(&reg.rf1, RF1_TUNER, 0);
- rt2500pci_rf_write(rt2x00dev, 1, reg.rf1);
+ rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0);
+ rt2500pci_rf_write(rt2x00dev, 1, rf->rf1);
}
- rt2x00_set_field32(&reg.rf3, RF3_TUNER, 0);
- rt2500pci_rf_write(rt2x00dev, 3, reg.rf3);
+ rt2x00_set_field32(&rf->rf3, RF3_TUNER, 0);
+ rt2500pci_rf_write(rt2x00dev, 3, rf->rf3);
/*
* Clear false CRC during channel switch.
*/
- rt2x00pci_register_read(rt2x00dev, CNT0, &reg.rf1);
+ rt2x00pci_register_read(rt2x00dev, CNT0, &rf->rf1);
}
static void rt2500pci_config_txpower(struct rt2x00_dev *rt2x00dev,
@@ -525,26 +497,22 @@ static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev,
}
static void rt2500pci_config_duration(struct rt2x00_dev *rt2x00dev,
- const int short_slot_time,
- const int beacon_int)
+ struct rt2x00lib_conf *libconf)
{
u32 reg;
rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
- rt2x00_set_field32(&reg, CSR11_SLOT_TIME,
- short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME);
+ rt2x00_set_field32(&reg, CSR11_SLOT_TIME, libconf->slot_time);
rt2x00pci_register_write(rt2x00dev, CSR11, reg);
rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
- rt2x00_set_field32(&reg, CSR18_SIFS, SIFS);
- rt2x00_set_field32(&reg, CSR18_PIFS,
- short_slot_time ? SHORT_PIFS : PIFS);
+ rt2x00_set_field32(&reg, CSR18_SIFS, libconf->sifs);
+ rt2x00_set_field32(&reg, CSR18_PIFS, libconf->pifs);
rt2x00pci_register_write(rt2x00dev, CSR18, reg);
rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
- rt2x00_set_field32(&reg, CSR19_DIFS,
- short_slot_time ? SHORT_DIFS : DIFS);
- rt2x00_set_field32(&reg, CSR19_EIFS, EIFS);
+ rt2x00_set_field32(&reg, CSR19_DIFS, libconf->difs);
+ rt2x00_set_field32(&reg, CSR19_EIFS, libconf->eifs);
rt2x00pci_register_write(rt2x00dev, CSR19, reg);
rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
@@ -553,30 +521,31 @@ static void rt2500pci_config_duration(struct rt2x00_dev *rt2x00dev,
rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
- rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL, beacon_int * 16);
- rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION, beacon_int * 16);
+ rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
+ libconf->conf->beacon_int * 16);
+ rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
+ libconf->conf->beacon_int * 16);
rt2x00pci_register_write(rt2x00dev, CSR12, reg);
}
static void rt2500pci_config(struct rt2x00_dev *rt2x00dev,
const unsigned int flags,
- struct ieee80211_conf *conf)
+ struct rt2x00lib_conf *libconf)
{
- int short_slot_time = conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME;
-
if (flags & CONFIG_UPDATE_PHYMODE)
- rt2500pci_config_phymode(rt2x00dev, conf->phymode);
+ rt2500pci_config_phymode(rt2x00dev, libconf->basic_rates);
if (flags & CONFIG_UPDATE_CHANNEL)
- rt2500pci_config_channel(rt2x00dev, conf->channel_val,
- conf->channel, conf->power_level);
+ rt2500pci_config_channel(rt2x00dev, &libconf->rf,
+ libconf->conf->power_level);
if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL))
- rt2500pci_config_txpower(rt2x00dev, conf->power_level);
+ rt2500pci_config_txpower(rt2x00dev,
+ libconf->conf->power_level);
if (flags & CONFIG_UPDATE_ANTENNA)
- rt2500pci_config_antenna(rt2x00dev, conf->antenna_sel_tx,
- conf->antenna_sel_rx);
+ rt2500pci_config_antenna(rt2x00dev,
+ libconf->conf->antenna_sel_tx,
+ libconf->conf->antenna_sel_rx);
if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
- rt2500pci_config_duration(rt2x00dev, short_slot_time,
- conf->beacon_int);
+ rt2500pci_config_duration(rt2x00dev, libconf);
}
/*
@@ -1921,6 +1890,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
.configure_filter = rt2500pci_configure_filter,
.get_stats = rt2x00mac_get_stats,
.set_retry_limit = rt2500pci_set_retry_limit,
+ .erp_ie_changed = rt2x00mac_erp_ie_changed,
.conf_tx = rt2x00mac_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt2500pci_get_tsf,
@@ -1946,6 +1916,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
.config_mac_addr = rt2500pci_config_mac_addr,
.config_bssid = rt2500pci_config_bssid,
.config_type = rt2500pci_config_type,
+ .config_preamble = rt2500pci_config_preamble,
.config = rt2500pci_config,
};
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index ef8dffbdffed..45f8f744a12d 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -302,54 +302,39 @@ static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,
rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
}
-static void rt2500usb_config_rate(struct rt2x00_dev *rt2x00dev, const int rate)
+static void rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev,
+ const int short_preamble,
+ const int ack_timeout,
+ const int ack_consume_time)
{
- struct ieee80211_conf *conf = &rt2x00dev->hw->conf;
u16 reg;
- u16 value;
- u16 preamble;
-
- if (DEVICE_GET_RATE_FIELD(rate, PREAMBLE))
- preamble = SHORT_PREAMBLE;
- else
- preamble = PREAMBLE;
- reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATEMASK;
-
- rt2500usb_register_write(rt2x00dev, TXRX_CSR11, reg);
+ /*
+ * When in atomic context, reschedule and let rt2x00lib
+ * call this function again.
+ */
+ if (in_atomic()) {
+ queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->config_work);
+ return;
+ }
rt2500usb_register_read(rt2x00dev, TXRX_CSR1, &reg);
- value = ((conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) ?
- SHORT_DIFS : DIFS) +
- PLCP + preamble + get_duration(ACK_SIZE, 10);
- rt2x00_set_field16(&reg, TXRX_CSR1_ACK_TIMEOUT, value);
+ rt2x00_set_field16(&reg, TXRX_CSR1_ACK_TIMEOUT, ack_timeout);
rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg);
rt2500usb_register_read(rt2x00dev, TXRX_CSR10, &reg);
rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE,
- (preamble == SHORT_PREAMBLE));
+ !!short_preamble);
rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg);
}
static void rt2500usb_config_phymode(struct rt2x00_dev *rt2x00dev,
- const int phymode)
+ const int phymode,
+ const int basic_rate_mask)
{
- struct ieee80211_hw_mode *mode;
- struct ieee80211_rate *rate;
+ rt2500usb_register_write(rt2x00dev, TXRX_CSR11, basic_rate_mask);
- if (phymode == MODE_IEEE80211A)
- rt2x00dev->curr_hwmode = HWMODE_A;
- else if (phymode == MODE_IEEE80211B)
- rt2x00dev->curr_hwmode = HWMODE_B;
- else
- rt2x00dev->curr_hwmode = HWMODE_G;
-
- mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode];
- rate = &mode->rates[mode->num_rates - 1];
-
- rt2500usb_config_rate(rt2x00dev, rate->val2);
-
- if (phymode == MODE_IEEE80211B) {
+ if (phymode == HWMODE_B) {
rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x000b);
rt2500usb_register_write(rt2x00dev, MAC_CSR12, 0x0040);
} else {
@@ -359,20 +344,12 @@ static void rt2500usb_config_phymode(struct rt2x00_dev *rt2x00dev,
}
static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev,
- const int index, const int channel,
- const int txpower)
+ struct rf_channel *rf, const int txpower)
{
- struct rf_channel reg;
-
- /*
- * Fill rf_reg structure.
- */
- memcpy(&reg, &rt2x00dev->spec.channels[index], sizeof(reg));
-
/*
* Set TXpower.
*/
- rt2x00_set_field32(&reg.rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
+ rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
/*
* For RT2525E we should first set the channel to half band higher.
@@ -385,16 +362,16 @@ static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev,
0x00000902, 0x00000906
};
- rt2500usb_rf_write(rt2x00dev, 2, vals[channel - 1]);
- if (reg.rf4)
- rt2500usb_rf_write(rt2x00dev, 4, reg.rf4);
+ rt2500usb_rf_write(rt2x00dev, 2, vals[rf->channel - 1]);
+ if (rf->rf4)
+ rt2500usb_rf_write(rt2x00dev, 4, rf->rf4);
}
- rt2500usb_rf_write(rt2x00dev, 1, reg.rf1);
- rt2500usb_rf_write(rt2x00dev, 2, reg.rf2);
- rt2500usb_rf_write(rt2x00dev, 3, reg.rf3);
- if (reg.rf4)
- rt2500usb_rf_write(rt2x00dev, 4, reg.rf4);
+ rt2500usb_rf_write(rt2x00dev, 1, rf->rf1);
+ rt2500usb_rf_write(rt2x00dev, 2, rf->rf2);
+ rt2500usb_rf_write(rt2x00dev, 3, rf->rf3);
+ if (rf->rf4)
+ rt2500usb_rf_write(rt2x00dev, 4, rf->rf4);
}
static void rt2500usb_config_txpower(struct rt2x00_dev *rt2x00dev,
@@ -484,38 +461,37 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev,
}
static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev,
- const int short_slot_time,
- const int beacon_int)
+ struct rt2x00lib_conf *libconf)
{
u16 reg;
- rt2500usb_register_write(rt2x00dev, MAC_CSR10,
- short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME);
+ rt2500usb_register_write(rt2x00dev, MAC_CSR10, libconf->slot_time);
rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
- rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL, beacon_int * 4);
+ rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL,
+ libconf->conf->beacon_int * 4);
rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
}
static void rt2500usb_config(struct rt2x00_dev *rt2x00dev,
const unsigned int flags,
- struct ieee80211_conf *conf)
+ struct rt2x00lib_conf *libconf)
{
- int short_slot_time = conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME;
-
if (flags & CONFIG_UPDATE_PHYMODE)
- rt2500usb_config_phymode(rt2x00dev, conf->phymode);
+ rt2500usb_config_phymode(rt2x00dev, libconf->phymode,
+ libconf->basic_rates);
if (flags & CONFIG_UPDATE_CHANNEL)
- rt2500usb_config_channel(rt2x00dev, conf->channel_val,
- conf->channel, conf->power_level);
+ rt2500usb_config_channel(rt2x00dev, &libconf->rf,
+ libconf->conf->power_level);
if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL))
- rt2500usb_config_txpower(rt2x00dev, conf->power_level);
+ rt2500usb_config_txpower(rt2x00dev,
+ libconf->conf->power_level);
if (flags & CONFIG_UPDATE_ANTENNA)
- rt2500usb_config_antenna(rt2x00dev, conf->antenna_sel_tx,
- conf->antenna_sel_rx);
+ rt2500usb_config_antenna(rt2x00dev,
+ libconf->conf->antenna_sel_tx,
+ libconf->conf->antenna_sel_rx);
if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
- rt2500usb_config_duration(rt2x00dev, short_slot_time,
- conf->beacon_int);
+ rt2500usb_config_duration(rt2x00dev, libconf);
}
/*
@@ -1733,6 +1709,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
.config_interface = rt2x00mac_config_interface,
.configure_filter = rt2500usb_configure_filter,
.get_stats = rt2x00mac_get_stats,
+ .erp_ie_changed = rt2x00mac_erp_ie_changed,
.conf_tx = rt2x00mac_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.beacon_update = rt2500usb_beacon_update,
@@ -1754,6 +1731,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
.config_mac_addr = rt2500usb_config_mac_addr,
.config_bssid = rt2500usb_config_bssid,
.config_type = rt2500usb_config_type,
+ .config_preamble = rt2500usb_config_preamble,
.config = rt2500usb_config,
};
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index a392e2a9d087..aabbe425470f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -352,6 +352,28 @@ struct hw_mode_spec {
};
/*
+ * Configuration structure wrapper around the
+ * mac80211 configuration structure.
+ * When mac80211 configures the driver, rt2x00lib
+ * can precalculate values which are equal for all
+ * rt2x00 drivers. Those values can be stored in here.
+ */
+struct rt2x00lib_conf {
+ struct ieee80211_conf *conf;
+ struct rf_channel rf;
+
+ int phymode;
+
+ int basic_rates;
+ int slot_time;
+
+ short sifs;
+ short pifs;
+ short difs;
+ short eifs;
+};
+
+/*
* rt2x00lib callback functions.
*/
struct rt2x00lib_ops {
@@ -414,8 +436,12 @@ struct rt2x00lib_ops {
void (*config_bssid) (struct rt2x00_dev *rt2x00dev, __le32 *bssid);
void (*config_type) (struct rt2x00_dev *rt2x00dev, const int type,
const int tsf_sync);
+ void (*config_preamble) (struct rt2x00_dev *rt2x00dev,
+ const int short_preamble,
+ const int ack_timeout,
+ const int ack_consume_time);
void (*config) (struct rt2x00_dev *rt2x00dev, const unsigned int flags,
- struct ieee80211_conf *conf);
+ struct rt2x00lib_conf *libconf);
#define CONFIG_UPDATE_PHYMODE ( 1 << 1 )
#define CONFIG_UPDATE_CHANNEL ( 1 << 2 )
#define CONFIG_UPDATE_TXPOWER ( 1 << 3 )
@@ -472,6 +498,7 @@ enum rt2x00_flags {
CONFIG_EXTERNAL_LNA_BG,
CONFIG_DOUBLE_ANTENNA,
CONFIG_DISABLE_LINK_TUNING,
+ CONFIG_SHORT_PREAMBLE,
};
/*
@@ -612,6 +639,7 @@ struct rt2x00_dev {
*/
struct work_struct beacon_work;
struct work_struct filter_work;
+ struct work_struct config_work;
/*
* Data ring arrays for RX, TX and Beacon.
@@ -792,6 +820,8 @@ int rt2x00mac_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats);
int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw,
struct ieee80211_tx_queue_stats *stats);
+void rt2x00mac_erp_ie_changed(struct ieee80211_hw *hw, u8 changes,
+ int cts_protection, int preamble);
int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue,
const struct ieee80211_tx_queue_params *params);
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index f8e87aa86335..12914cf7156c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -97,7 +97,11 @@ void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type)
void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf, const int force_config)
{
+ struct rt2x00lib_conf libconf;
+ struct ieee80211_hw_mode *mode;
+ struct ieee80211_rate *rate;
int flags = 0;
+ int short_slot_time;
/*
* In some situations we want to force all configurations
@@ -128,8 +132,62 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
flags |= CONFIG_UPDATE_SLOT_TIME;
flags |= CONFIG_UPDATE_BEACON_INT;
+ /*
+ * We have determined what options should be updated,
+ * now precalculate device configuration values depending
+ * on what configuration options need to be updated.
+ */
config:
- rt2x00dev->ops->lib->config(rt2x00dev, flags, conf);
+ memset(&libconf, 0, sizeof(libconf));
+
+ if (flags & CONFIG_UPDATE_PHYMODE) {
+ switch (conf->phymode) {
+ case MODE_IEEE80211A:
+ libconf.phymode = HWMODE_A;
+ break;
+ case MODE_IEEE80211B:
+ libconf.phymode = HWMODE_B;
+ break;
+ case MODE_IEEE80211G:
+ libconf.phymode = HWMODE_G;
+ break;
+ default:
+ ERROR(rt2x00dev,
+ "Attempt to configure unsupported mode (%d)"
+ "Defaulting to 802.11b", conf->phymode);
+ libconf.phymode = HWMODE_B;
+ }
+
+ mode = &rt2x00dev->hwmodes[libconf.phymode];
+ rate = &mode->rates[mode->num_rates - 1];
+
+ libconf.basic_rates =
+ DEVICE_GET_RATE_FIELD(rate->val, RATEMASK) & DEV_BASIC_RATEMASK;
+ }
+
+ if (flags & CONFIG_UPDATE_CHANNEL) {
+ memcpy(&libconf.rf,
+ &rt2x00dev->spec.channels[conf->channel_val],
+ sizeof(libconf.rf));
+ }
+
+ if (flags & CONFIG_UPDATE_SLOT_TIME) {
+ short_slot_time = conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME;
+
+ libconf.slot_time =
+ short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME;
+ libconf.sifs = SIFS;
+ libconf.pifs = short_slot_time ? SHORT_PIFS : PIFS;
+ libconf.difs = short_slot_time ? SHORT_DIFS : DIFS;
+ libconf.eifs = EIFS;
+ }
+
+ libconf.conf = conf;
+
+ /*
+ * Start configuration.
+ */
+ rt2x00dev->ops->lib->config(rt2x00dev, flags, &libconf);
/*
* Some configuration changes affect the link quality
@@ -138,6 +196,7 @@ config:
if (flags & (CONFIG_UPDATE_CHANNEL | CONFIG_UPDATE_ANTENNA))
rt2x00lib_reset_link_tuner(rt2x00dev);
+ rt2x00dev->curr_hwmode = libconf.phymode;
rt2x00dev->rx_status.phymode = conf->phymode;
rt2x00dev->rx_status.freq = conf->freq;
rt2x00dev->rx_status.channel = conf->channel;
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index e14104869172..bb6f46cfbb9f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -142,6 +142,8 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
cancel_work_sync(&rt2x00dev->beacon_work);
if (work_pending(&rt2x00dev->filter_work))
cancel_work_sync(&rt2x00dev->filter_work);
+ if (work_pending(&rt2x00dev->config_work))
+ cancel_work_sync(&rt2x00dev->config_work);
/*
* Stop the TX queues.
@@ -288,6 +290,16 @@ static void rt2x00lib_packetfilter_scheduled(struct work_struct *work)
filter, &filter, 0, NULL);
}
+static void rt2x00lib_configuration_scheduled(struct work_struct *work)
+{
+ struct rt2x00_dev *rt2x00dev =
+ container_of(work, struct rt2x00_dev, config_work);
+ int preamble = !test_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
+
+ rt2x00mac_erp_ie_changed(rt2x00dev->hw,
+ IEEE80211_ERP_CHANGE_PREAMBLE, 0, preamble);
+}
+
/*
* Interrupt context handlers.
*/
@@ -990,6 +1002,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
*/
INIT_WORK(&rt2x00dev->beacon_work, rt2x00lib_beacondone_scheduled);
INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled);
+ INIT_WORK(&rt2x00dev->config_work, rt2x00lib_configuration_scheduled);
INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner);
/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index f519d7396848..4a6a0bd01ff1 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -365,6 +365,40 @@ int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL_GPL(rt2x00mac_get_tx_stats);
+void rt2x00mac_erp_ie_changed(struct ieee80211_hw *hw, u8 changes,
+ int cts_protection, int preamble)
+{
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+ int short_preamble;
+ int ack_timeout;
+ int ack_consume_time;
+ int difs;
+
+ /*
+ * We only support changing preamble mode.
+ */
+ if (!(changes & IEEE80211_ERP_CHANGE_PREAMBLE))
+ return;
+
+ short_preamble = !preamble;
+ preamble = !!(preamble) ? PREAMBLE : SHORT_PREAMBLE;
+
+ difs = (hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) ?
+ SHORT_DIFS : DIFS;
+ ack_timeout = difs + PLCP + preamble + get_duration(ACK_SIZE, 10);
+
+ ack_consume_time = SIFS + PLCP + preamble + get_duration(ACK_SIZE, 10);
+
+ if (short_preamble)
+ __set_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
+ else
+ __clear_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
+
+ rt2x00dev->ops->lib->config_preamble(rt2x00dev, short_preamble,
+ ack_timeout, ack_consume_time);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_erp_ie_changed);
+
int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue,
const struct ieee80211_tx_queue_params *params)
{
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index cd22817cced5..1a869a5cbe91 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -328,62 +328,31 @@ static void rt61pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
}
-static void rt61pci_config_rate(struct rt2x00_dev *rt2x00dev, const int rate)
+static void rt61pci_config_preamble(struct rt2x00_dev *rt2x00dev,
+ const int short_preamble,
+ const int ack_timeout,
+ const int ack_consume_time)
{
- struct ieee80211_conf *conf = &rt2x00dev->hw->conf;
u32 reg;
- u32 value;
- u32 preamble;
-
- if (DEVICE_GET_RATE_FIELD(rate, PREAMBLE))
- preamble = SHORT_PREAMBLE;
- else
- preamble = PREAMBLE;
-
- /*
- * Extract the allowed ratemask from the device specific rate value,
- * We need to set TXRX_CSR5 to the basic rate mask so we need to mask
- * off the non-basic rates.
- */
- reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATEMASK;
-
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, reg);
rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
- value = ((conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) ?
- SHORT_DIFS : DIFS) +
- PLCP + preamble + get_duration(ACK_SIZE, 10);
- rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, value);
+ rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout);
rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
- (preamble == SHORT_PREAMBLE));
+ !!short_preamble);
rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
}
static void rt61pci_config_phymode(struct rt2x00_dev *rt2x00dev,
- const int phymode)
+ const int basic_rate_mask)
{
- struct ieee80211_hw_mode *mode;
- struct ieee80211_rate *rate;
-
- if (phymode == MODE_IEEE80211A)
- rt2x00dev->curr_hwmode = HWMODE_A;
- else if (phymode == MODE_IEEE80211B)
- rt2x00dev->curr_hwmode = HWMODE_B;
- else
- rt2x00dev->curr_hwmode = HWMODE_G;
-
- mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode];
- rate = &mode->rates[mode->num_rates - 1];
-
- rt61pci_config_rate(rt2x00dev, rate->val2);
+ rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, basic_rate_mask);
}
-static void rt61pci_config_lock_channel(struct rt2x00_dev *rt2x00dev,
- struct rf_channel *rf,
- const int txpower)
+static void rt61pci_config_channel(struct rt2x00_dev *rt2x00dev,
+ struct rf_channel *rf, const int txpower)
{
u8 r3;
u8 r94;
@@ -428,20 +397,6 @@ static void rt61pci_config_lock_channel(struct rt2x00_dev *rt2x00dev,
msleep(1);
}
-static void rt61pci_config_channel(struct rt2x00_dev *rt2x00dev,
- const int index, const int channel,
- const int txpower)
-{
- struct rf_channel rf;
-
- /*
- * Fill rf_reg structure.
- */
- memcpy(&rf, &rt2x00dev->spec.channels[index], sizeof(rf));
-
- rt61pci_config_lock_channel(rt2x00dev, &rf, txpower);
-}
-
static void rt61pci_config_txpower(struct rt2x00_dev *rt2x00dev,
const int txpower)
{
@@ -452,7 +407,7 @@ static void rt61pci_config_txpower(struct rt2x00_dev *rt2x00dev,
rt2x00_rf_read(rt2x00dev, 3, &rf.rf3);
rt2x00_rf_read(rt2x00dev, 4, &rf.rf4);
- rt61pci_config_lock_channel(rt2x00dev, &rf, txpower);
+ rt61pci_config_channel(rt2x00dev, &rf, txpower);
}
static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
@@ -714,20 +669,18 @@ static void rt61pci_config_antenna(struct rt2x00_dev *rt2x00dev,
}
static void rt61pci_config_duration(struct rt2x00_dev *rt2x00dev,
- const int short_slot_time,
- const int beacon_int)
+ struct rt2x00lib_conf *libconf)
{
u32 reg;
rt2x00pci_register_read(rt2x00dev, MAC_CSR9, &reg);
- rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME,
- short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME);
+ rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, libconf->slot_time);
rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg);
rt2x00pci_register_read(rt2x00dev, MAC_CSR8, &reg);
- rt2x00_set_field32(&reg, MAC_CSR8_SIFS, SIFS);
+ rt2x00_set_field32(&reg, MAC_CSR8_SIFS, libconf->sifs);
rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
- rt2x00_set_field32(&reg, MAC_CSR8_EIFS, EIFS);
+ rt2x00_set_field32(&reg, MAC_CSR8_EIFS, libconf->eifs);
rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg);
rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
@@ -739,29 +692,27 @@ static void rt61pci_config_duration(struct rt2x00_dev *rt2x00dev,
rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
- rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL, beacon_int * 16);
+ rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
+ libconf->conf->beacon_int * 16);
rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
}
static void rt61pci_config(struct rt2x00_dev *rt2x00dev,
const unsigned int flags,
- struct ieee80211_conf *conf)
+ struct rt2x00lib_conf *libconf)
{
- int short_slot_time = conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME;
-
if (flags & CONFIG_UPDATE_PHYMODE)
- rt61pci_config_phymode(rt2x00dev, conf->phymode);
+ rt61pci_config_phymode(rt2x00dev, libconf->basic_rates);
if (flags & CONFIG_UPDATE_CHANNEL)
- rt61pci_config_channel(rt2x00dev, conf->channel_val,
- conf->channel, conf->power_level);
+ rt61pci_config_channel(rt2x00dev, &libconf->rf,
+ libconf->conf->power_level);
if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL))
- rt61pci_config_txpower(rt2x00dev, conf->power_level);
+ rt61pci_config_txpower(rt2x00dev, libconf->conf->power_level);
if (flags & CONFIG_UPDATE_ANTENNA)
- rt61pci_config_antenna(rt2x00dev, conf->antenna_sel_tx,
- conf->antenna_sel_rx);
+ rt61pci_config_antenna(rt2x00dev, libconf->conf->antenna_sel_tx,
+ libconf->conf->antenna_sel_rx);
if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
- rt61pci_config_duration(rt2x00dev, short_slot_time,
- conf->beacon_int);
+ rt61pci_config_duration(rt2x00dev, libconf);
}
/*
@@ -2513,6 +2464,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
.configure_filter = rt61pci_configure_filter,
.get_stats = rt2x00mac_get_stats,
.set_retry_limit = rt61pci_set_retry_limit,
+ .erp_ie_changed = rt2x00mac_erp_ie_changed,
.conf_tx = rt2x00mac_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt61pci_get_tsf,
@@ -2539,6 +2491,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
.config_mac_addr = rt61pci_config_mac_addr,
.config_bssid = rt61pci_config_bssid,
.config_type = rt61pci_config_type,
+ .config_preamble = rt61pci_config_preamble,
.config = rt61pci_config,
};
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 9e1bf4d77e10..984117fe1f5e 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -308,57 +308,40 @@ static void rt73usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,
rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
}
-static void rt73usb_config_rate(struct rt2x00_dev *rt2x00dev, const int rate)
+static void rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev,
+ const int short_preamble,
+ const int ack_timeout,
+ const int ack_consume_time)
{
- struct ieee80211_conf *conf = &rt2x00dev->hw->conf;
u32 reg;
- u32 value;
- u32 preamble;
- if (DEVICE_GET_RATE_FIELD(rate, PREAMBLE))
- preamble = SHORT_PREAMBLE;
- else
- preamble = PREAMBLE;
-
- reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATEMASK;
-
- rt73usb_register_write(rt2x00dev, TXRX_CSR5, reg);
+ /*
+ * When in atomic context, reschedule and let rt2x00lib
+ * call this function again.
+ */
+ if (in_atomic()) {
+ queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->config_work);
+ return;
+ }
rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
- value = ((conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) ?
- SHORT_DIFS : DIFS) +
- PLCP + preamble + get_duration(ACK_SIZE, 10);
- rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, value);
+ rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout);
rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
rt73usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
- (preamble == SHORT_PREAMBLE));
+ !!short_preamble);
rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg);
}
static void rt73usb_config_phymode(struct rt2x00_dev *rt2x00dev,
- const int phymode)
+ const int basic_rate_mask)
{
- struct ieee80211_hw_mode *mode;
- struct ieee80211_rate *rate;
-
- if (phymode == MODE_IEEE80211A)
- rt2x00dev->curr_hwmode = HWMODE_A;
- else if (phymode == MODE_IEEE80211B)
- rt2x00dev->curr_hwmode = HWMODE_B;
- else
- rt2x00dev->curr_hwmode = HWMODE_G;
-
- mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode];
- rate = &mode->rates[mode->num_rates - 1];
-
- rt73usb_config_rate(rt2x00dev, rate->val2);
+ rt73usb_register_write(rt2x00dev, TXRX_CSR5, basic_rate_mask);
}
-static void rt73usb_config_lock_channel(struct rt2x00_dev *rt2x00dev,
- struct rf_channel *rf,
- const int txpower)
+static void rt73usb_config_channel(struct rt2x00_dev *rt2x00dev,
+ struct rf_channel *rf, const int txpower)
{
u8 r3;
u8 r94;
@@ -399,20 +382,6 @@ static void rt73usb_config_lock_channel(struct rt2x00_dev *rt2x00dev,
udelay(10);
}
-static void rt73usb_config_channel(struct rt2x00_dev *rt2x00dev,
- const int index, const int channel,
- const int txpower)
-{
- struct rf_channel rf;
-
- /*
- * Fill rf_reg structure.
- */
- memcpy(&rf, &rt2x00dev->spec.channels[index], sizeof(rf));
-
- rt73usb_config_lock_channel(rt2x00dev, &rf, txpower);
-}
-
static void rt73usb_config_txpower(struct rt2x00_dev *rt2x00dev,
const int txpower)
{
@@ -423,7 +392,7 @@ static void rt73usb_config_txpower(struct rt2x00_dev *rt2x00dev,
rt2x00_rf_read(rt2x00dev, 3, &rf.rf3);
rt2x00_rf_read(rt2x00dev, 4, &rf.rf4);
- rt73usb_config_lock_channel(rt2x00dev, &rf, txpower);
+ rt73usb_config_channel(rt2x00dev, &rf, txpower);
}
static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
@@ -577,20 +546,18 @@ static void rt73usb_config_antenna(struct rt2x00_dev *rt2x00dev,
}
static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev,
- const int short_slot_time,
- const int beacon_int)
+ struct rt2x00lib_conf *libconf)
{
u32 reg;
rt73usb_register_read(rt2x00dev, MAC_CSR9, &reg);
- rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME,
- short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME);
+ rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, libconf->slot_time);
rt73usb_register_write(rt2x00dev, MAC_CSR9, reg);
rt73usb_register_read(rt2x00dev, MAC_CSR8, &reg);
- rt2x00_set_field32(&reg, MAC_CSR8_SIFS, SIFS);
+ rt2x00_set_field32(&reg, MAC_CSR8_SIFS, libconf->sifs);
rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
- rt2x00_set_field32(&reg, MAC_CSR8_EIFS, EIFS);
+ rt2x00_set_field32(&reg, MAC_CSR8_EIFS, libconf->eifs);
rt73usb_register_write(rt2x00dev, MAC_CSR8, reg);
rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
@@ -602,29 +569,27 @@ static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev,
rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg);
rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
- rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL, beacon_int * 16);
+ rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
+ libconf->conf->beacon_int * 16);
rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
}
static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
const unsigned int flags,
- struct ieee80211_conf *conf)
+ struct rt2x00lib_conf *libconf)
{
- int short_slot_time = conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME;
-
if (flags & CONFIG_UPDATE_PHYMODE)
- rt73usb_config_phymode(rt2x00dev, conf->phymode);
+ rt73usb_config_phymode(rt2x00dev, libconf->basic_rates);
if (flags & CONFIG_UPDATE_CHANNEL)
- rt73usb_config_channel(rt2x00dev, conf->channel_val,
- conf->channel, conf->power_level);
+ rt73usb_config_channel(rt2x00dev, &libconf->rf,
+ libconf->conf->power_level);
if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL))
- rt73usb_config_txpower(rt2x00dev, conf->power_level);
+ rt73usb_config_txpower(rt2x00dev, libconf->conf->power_level);
if (flags & CONFIG_UPDATE_ANTENNA)
- rt73usb_config_antenna(rt2x00dev, conf->antenna_sel_tx,
- conf->antenna_sel_rx);
+ rt73usb_config_antenna(rt2x00dev, libconf->conf->antenna_sel_tx,
+ libconf->conf->antenna_sel_rx);
if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
- rt73usb_config_duration(rt2x00dev, short_slot_time,
- conf->beacon_int);
+ rt73usb_config_duration(rt2x00dev, libconf);
}
/*
@@ -2002,6 +1967,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
.configure_filter = rt73usb_configure_filter,
.get_stats = rt2x00mac_get_stats,
.set_retry_limit = rt73usb_set_retry_limit,
+ .erp_ie_changed = rt2x00mac_erp_ie_changed,
.conf_tx = rt2x00mac_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
#if 0
@@ -2032,6 +1998,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
.config_mac_addr = rt73usb_config_mac_addr,
.config_bssid = rt73usb_config_bssid,
.config_type = rt73usb_config_type,
+ .config_preamble = rt73usb_config_preamble,
.config = rt73usb_config,
};
OpenPOWER on IntegriCloud