]> err.no Git - linux-2.6/commitdiff
[PATCH] rt2x00: Reorganize configuration handler
authorIvo van Doorn <IvDoorn@gmail.com>
Sat, 6 Oct 2007 11:34:52 +0000 (13:34 +0200)
committerDavid S. Miller <davem@sunset.davemloft.net>
Wed, 10 Oct 2007 23:55:15 +0000 (16:55 -0700)
Reorganize configuration handling by creating a extra
structure which contains precalculated values based
on the mac80211 values which are usefull for all
individual drivers.

This also fixes the preamble configuration problem,
up untill now preamble was never configured since
by default the rate->val value was used when changing
the mode.
Now rate->val will only be used to set the basic rate mask.
The preamble configuration will now be done correctly
through the erp_ie_changed callback function.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/rt2x00/rt2400pci.c
drivers/net/wireless/rt2x00/rt2500pci.c
drivers/net/wireless/rt2x00/rt2500usb.c
drivers/net/wireless/rt2x00/rt2x00.h
drivers/net/wireless/rt2x00/rt2x00config.c
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/rt2x00/rt2x00mac.c
drivers/net/wireless/rt2x00/rt61pci.c
drivers/net/wireless/rt2x00/rt73usb.c

index bfab5a165b7633452860a38f66a326072d78f616..31c1dd271627191813d37278d23abc08bcb48455 100644 (file)
@@ -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,
 };
 
index c8c6a848be9729544a006d336714834f1ecd2d36..ff2d63267b19e8acb41b356e8524e3451014f291 100644 (file)
@@ -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,
 };
 
index ef8dffbdffed557fec910ecc8753d87f5f82b151..45f8f744a12dabf201922be8dfb2d586334a3071 100644 (file)
@@ -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,
 };
 
index a392e2a9d087a24314937664f5d2ca45576f6924..aabbe425470faf7aec76359caa0b8de497f1defd 100644 (file)
@@ -351,6 +351,28 @@ struct hw_mode_spec {
        const struct rf_channel *channels;
 };
 
+/*
+ * 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.
  */
@@ -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);
 
index f8e87aa863357d015b1762856c2ca73447414d2e..12914cf7156cb4fc6582dd6cbfe06b96ed4fb4bb 100644 (file)
@@ -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;
index e1410486917240cc59c40173d14cfda22638b9c6..bb6f46cfbb9f87e27dc792d52a1aed4ba5218706 100644 (file)
@@ -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);
 
        /*
index f519d73968480fc5fb1686178215fac367ac20b1..4a6a0bd01ff192ead09ab3b929f33f57f7c18882 100644 (file)
@@ -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)
 {
index cd22817cced5b5bc8cd04f56a4da48941b1f861e..1a869a5cbe911eef2d561e6bb61157fcc8197318 100644 (file)
@@ -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,
 };
 
index 9e1bf4d77e102be48ef490e7c9d02e0b9664a5a5..984117fe1f5e4ae596e5c55a4a8e703148780f35 100644 (file)
@@ -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,
 };