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, ®);
-       value = ((conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) ?
-                SHORT_DIFS : DIFS) +
-           PLCP + preamble + get_duration(ACK_SIZE, 10);
-       rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, value);
-       value = SIFS + PLCP + preamble + get_duration(ACK_SIZE, 10);
-       rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, value);
+       rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, ack_timeout);
+       rt2x00_set_field32(®, 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, ®);
-       rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00 | preamble);
+       rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00 | preamble_mask);
        rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04);
        rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 10));
        rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
 
        rt2x00pci_register_read(rt2x00dev, ARCSR3, ®);
-       rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble);
+       rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask);
        rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04);
        rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 20));
        rt2x00pci_register_write(rt2x00dev, ARCSR3, reg);
 
        rt2x00pci_register_read(rt2x00dev, ARCSR4, ®);
-       rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble);
+       rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask);
        rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04);
        rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 55));
        rt2x00pci_register_write(rt2x00dev, ARCSR4, reg);
 
        rt2x00pci_register_read(rt2x00dev, ARCSR5, ®);
-       rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble);
+       rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask);
        rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84);
        rt2x00_set_field32(®, 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(®, &rt2x00dev->spec.channels[index], sizeof(reg));
-
        /*
         * Switch on tuning bits.
         */
-       rt2x00_set_field32(®.rf1, RF1_TUNER, 1);
-       rt2x00_set_field32(®.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.
         * 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(®.rf1, RF1_TUNER, 0);
-       rt2x00_set_field32(®.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, ®.rf1);
+       rt2x00pci_register_read(rt2x00dev, CNT0, &rf->rf1);
 }
 
 static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower)
 }
 
 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, ®);
-       rt2x00_set_field32(®, CSR11_SLOT_TIME,
-                          short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME);
+       rt2x00_set_field32(®, CSR11_SLOT_TIME, libconf->slot_time);
        rt2x00pci_register_write(rt2x00dev, CSR11, reg);
 
        rt2x00pci_register_read(rt2x00dev, CSR18, ®);
-       rt2x00_set_field32(®, CSR18_SIFS, SIFS);
-       rt2x00_set_field32(®, CSR18_PIFS,
-                          short_slot_time ? SHORT_PIFS : PIFS);
+       rt2x00_set_field32(®, CSR18_SIFS, libconf->sifs);
+       rt2x00_set_field32(®, CSR18_PIFS, libconf->pifs);
        rt2x00pci_register_write(rt2x00dev, CSR18, reg);
 
        rt2x00pci_register_read(rt2x00dev, CSR19, ®);
-       rt2x00_set_field32(®, CSR19_DIFS,
-                          short_slot_time ? SHORT_DIFS : DIFS);
-       rt2x00_set_field32(®, CSR19_EIFS, EIFS);
+       rt2x00_set_field32(®, CSR19_DIFS, libconf->difs);
+       rt2x00_set_field32(®, CSR19_EIFS, libconf->eifs);
        rt2x00pci_register_write(rt2x00dev, CSR19, reg);
 
        rt2x00pci_register_read(rt2x00dev, TXCSR1, ®);
        rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
 
        rt2x00pci_register_read(rt2x00dev, CSR12, ®);
-       rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, beacon_int * 16);
-       rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, beacon_int * 16);
+       rt2x00_set_field32(®, CSR12_BEACON_INTERVAL,
+                          libconf->conf->beacon_int * 16);
+       rt2x00_set_field32(®, 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,
        .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,
        .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,
 };
 
 
        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, ®);
-       value = ((conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) ?
-                SHORT_DIFS : DIFS) +
-           PLCP + preamble + get_duration(ACK_SIZE, 10);
-       rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, value);
-       value = SIFS + PLCP + preamble + get_duration(ACK_SIZE, 10);
-       rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, value);
+       rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, ack_timeout);
+       rt2x00_set_field32(®, 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, ®);
-       rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00 | preamble);
+       rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00 | preamble_mask);
        rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04);
        rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 10));
        rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
 
        rt2x00pci_register_read(rt2x00dev, ARCSR3, ®);
-       rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble);
+       rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask);
        rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04);
        rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 20));
        rt2x00pci_register_write(rt2x00dev, ARCSR3, reg);
 
        rt2x00pci_register_read(rt2x00dev, ARCSR4, ®);
-       rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble);
+       rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask);
        rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04);
        rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 55));
        rt2x00pci_register_write(rt2x00dev, ARCSR4, reg);
 
        rt2x00pci_register_read(rt2x00dev, ARCSR5, ®);
-       rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble);
+       rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask);
        rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84);
        rt2x00_set_field32(®, 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(®, &rt2x00dev->spec.channels[index], sizeof(reg));
-
        /*
         * Set TXpower.
         */
-       rt2x00_set_field32(®.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(®.rf1, RF1_TUNER, 1);
-       rt2x00_set_field32(®.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.
                        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);
         * For RT2523 devices we do not need to update the R1 register.
         */
        if (!rt2x00_rf(&rt2x00dev->chip, RF2523)) {
-               rt2x00_set_field32(®.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(®.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, ®.rf1);
+       rt2x00pci_register_read(rt2x00dev, CNT0, &rf->rf1);
 }
 
 static void rt2500pci_config_txpower(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, ®);
-       rt2x00_set_field32(®, CSR11_SLOT_TIME,
-                          short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME);
+       rt2x00_set_field32(®, CSR11_SLOT_TIME, libconf->slot_time);
        rt2x00pci_register_write(rt2x00dev, CSR11, reg);
 
        rt2x00pci_register_read(rt2x00dev, CSR18, ®);
-       rt2x00_set_field32(®, CSR18_SIFS, SIFS);
-       rt2x00_set_field32(®, CSR18_PIFS,
-                          short_slot_time ? SHORT_PIFS : PIFS);
+       rt2x00_set_field32(®, CSR18_SIFS, libconf->sifs);
+       rt2x00_set_field32(®, CSR18_PIFS, libconf->pifs);
        rt2x00pci_register_write(rt2x00dev, CSR18, reg);
 
        rt2x00pci_register_read(rt2x00dev, CSR19, ®);
-       rt2x00_set_field32(®, CSR19_DIFS,
-                          short_slot_time ? SHORT_DIFS : DIFS);
-       rt2x00_set_field32(®, CSR19_EIFS, EIFS);
+       rt2x00_set_field32(®, CSR19_DIFS, libconf->difs);
+       rt2x00_set_field32(®, CSR19_EIFS, libconf->eifs);
        rt2x00pci_register_write(rt2x00dev, CSR19, reg);
 
        rt2x00pci_register_read(rt2x00dev, TXCSR1, ®);
        rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
 
        rt2x00pci_register_read(rt2x00dev, CSR12, ®);
-       rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, beacon_int * 16);
-       rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, beacon_int * 16);
+       rt2x00_set_field32(®, CSR12_BEACON_INTERVAL,
+                          libconf->conf->beacon_int * 16);
+       rt2x00_set_field32(®, 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);
 }
 
 /*
        .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,
        .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,
 };
 
 
        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, ®);
-       value = ((conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) ?
-                SHORT_DIFS : DIFS) +
-           PLCP + preamble + get_duration(ACK_SIZE, 10);
-       rt2x00_set_field16(®, TXRX_CSR1_ACK_TIMEOUT, value);
+       rt2x00_set_field16(®, TXRX_CSR1_ACK_TIMEOUT, ack_timeout);
        rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg);
 
        rt2500usb_register_read(rt2x00dev, TXRX_CSR10, ®);
        rt2x00_set_field16(®, 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 {
 }
 
 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(®, &rt2x00dev->spec.channels[index], sizeof(reg));
-
        /*
         * Set TXpower.
         */
-       rt2x00_set_field32(®.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.
                        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,
 }
 
 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, ®);
-       rt2x00_set_field16(®, TXRX_CSR18_INTERVAL, beacon_int * 4);
+       rt2x00_set_field16(®, 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);
 }
 
 /*
        .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,
        .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,
 };
 
 
        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.
  */
        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 )
        CONFIG_EXTERNAL_LNA_BG,
        CONFIG_DOUBLE_ANTENNA,
        CONFIG_DISABLE_LINK_TUNING,
+       CONFIG_SHORT_PREAMBLE,
 };
 
 /*
         */
        struct work_struct beacon_work;
        struct work_struct filter_work;
+       struct work_struct config_work;
 
        /*
         * Data ring arrays for RX, TX and Beacon.
                        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);
 
 
 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
        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
        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;
 
                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.
                                             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.
  */
         */
        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);
 
        /*
 
 }
 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)
 {
 
        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, ®);
-       value = ((conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) ?
-                SHORT_DIFS : DIFS) +
-           PLCP + preamble + get_duration(ACK_SIZE, 10);
-       rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, value);
+       rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout);
        rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
 
        rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®);
        rt2x00_set_field32(®, 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;
        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)
 {
        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,
 }
 
 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, ®);
-       rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME,
-                          short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME);
+       rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, libconf->slot_time);
        rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg);
 
        rt2x00pci_register_read(rt2x00dev, MAC_CSR8, ®);
-       rt2x00_set_field32(®, MAC_CSR8_SIFS, SIFS);
+       rt2x00_set_field32(®, MAC_CSR8_SIFS, libconf->sifs);
        rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
-       rt2x00_set_field32(®, MAC_CSR8_EIFS, EIFS);
+       rt2x00_set_field32(®, MAC_CSR8_EIFS, libconf->eifs);
        rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg);
 
        rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®);
        rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
 
        rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®);
-       rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, beacon_int * 16);
+       rt2x00_set_field32(®, 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);
 }
 
 /*
        .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,
        .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,
 };
 
 
        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, ®);
-       value = ((conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) ?
-                SHORT_DIFS : DIFS) +
-           PLCP + preamble + get_duration(ACK_SIZE, 10);
-       rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, value);
+       rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout);
        rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
 
        rt73usb_register_read(rt2x00dev, TXRX_CSR4, ®);
        rt2x00_set_field32(®, 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;
        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)
 {
        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,
 }
 
 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, ®);
-       rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME,
-                          short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME);
+       rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, libconf->slot_time);
        rt73usb_register_write(rt2x00dev, MAC_CSR9, reg);
 
        rt73usb_register_read(rt2x00dev, MAC_CSR8, ®);
-       rt2x00_set_field32(®, MAC_CSR8_SIFS, SIFS);
+       rt2x00_set_field32(®, MAC_CSR8_SIFS, libconf->sifs);
        rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
-       rt2x00_set_field32(®, MAC_CSR8_EIFS, EIFS);
+       rt2x00_set_field32(®, MAC_CSR8_EIFS, libconf->eifs);
        rt73usb_register_write(rt2x00dev, MAC_CSR8, reg);
 
        rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®);
        rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg);
 
        rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®);
-       rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, beacon_int * 16);
+       rt2x00_set_field32(®, 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);
 }
 
 /*
        .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
        .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,
 };