]> err.no Git - linux-2.6/blobdiff - drivers/net/wireless/rt2x00/rt2500usb.c
rt2x00: Correctly set ACK bit in tx descriptors
[linux-2.6] / drivers / net / wireless / rt2x00 / rt2500usb.c
index 6d5444b58e6cffe2626b0eea0d864c0d47c9b7c0..e9f99c48ef2df41df5b888f62586945312069691 100644 (file)
  * between each attampt. When the busy bit is still set at that time,
  * the access attempt is considered to have failed,
  * and we will print an error.
+ * If the usb_cache_mutex is already held then the _lock variants must
+ * be used instead.
  */
-static inline void rt2500usb_register_read(const struct rt2x00_dev *rt2x00dev,
+static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
                                           const unsigned int offset,
                                           u16 *value)
 {
@@ -64,8 +66,18 @@ static inline void rt2500usb_register_read(const struct rt2x00_dev *rt2x00dev,
        *value = le16_to_cpu(reg);
 }
 
-static inline void rt2500usb_register_multiread(const struct rt2x00_dev
-                                               *rt2x00dev,
+static inline void rt2500usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
+                                               const unsigned int offset,
+                                               u16 *value)
+{
+       __le16 reg;
+       rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
+                                      USB_VENDOR_REQUEST_IN, offset,
+                                      &reg, sizeof(u16), REGISTER_TIMEOUT);
+       *value = le16_to_cpu(reg);
+}
+
+static inline void rt2500usb_register_multiread(struct rt2x00_dev *rt2x00dev,
                                                const unsigned int offset,
                                                void *value, const u16 length)
 {
@@ -75,7 +87,7 @@ static inline void rt2500usb_register_multiread(const struct rt2x00_dev
                                      value, length, timeout);
 }
 
-static inline void rt2500usb_register_write(const struct rt2x00_dev *rt2x00dev,
+static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
                                            const unsigned int offset,
                                            u16 value)
 {
@@ -85,8 +97,17 @@ static inline void rt2500usb_register_write(const struct rt2x00_dev *rt2x00dev,
                                      &reg, sizeof(u16), REGISTER_TIMEOUT);
 }
 
-static inline void rt2500usb_register_multiwrite(const struct rt2x00_dev
-                                                *rt2x00dev,
+static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
+                                                const unsigned int offset,
+                                                u16 value)
+{
+       __le16 reg = cpu_to_le16(value);
+       rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE,
+                                      USB_VENDOR_REQUEST_OUT, offset,
+                                      &reg, sizeof(u16), REGISTER_TIMEOUT);
+}
+
+static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
                                                 const unsigned int offset,
                                                 void *value, const u16 length)
 {
@@ -96,13 +117,13 @@ static inline void rt2500usb_register_multiwrite(const struct rt2x00_dev
                                      value, length, timeout);
 }
 
-static u16 rt2500usb_bbp_check(const struct rt2x00_dev *rt2x00dev)
+static u16 rt2500usb_bbp_check(struct rt2x00_dev *rt2x00dev)
 {
        u16 reg;
        unsigned int i;
 
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2500usb_register_read(rt2x00dev, PHY_CSR8, &reg);
+               rt2500usb_register_read_lock(rt2x00dev, PHY_CSR8, &reg);
                if (!rt2x00_get_field16(reg, PHY_CSR8_BUSY))
                        break;
                udelay(REGISTER_BUSY_DELAY);
@@ -111,17 +132,20 @@ static u16 rt2500usb_bbp_check(const struct rt2x00_dev *rt2x00dev)
        return reg;
 }
 
-static void rt2500usb_bbp_write(const struct rt2x00_dev *rt2x00dev,
+static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
                                const unsigned int word, const u8 value)
 {
        u16 reg;
 
+       mutex_lock(&rt2x00dev->usb_cache_mutex);
+
        /*
         * Wait until the BBP becomes ready.
         */
        reg = rt2500usb_bbp_check(rt2x00dev);
        if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) {
                ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n");
+               mutex_unlock(&rt2x00dev->usb_cache_mutex);
                return;
        }
 
@@ -133,14 +157,18 @@ static void rt2500usb_bbp_write(const struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field16(&reg, PHY_CSR7_REG_ID, word);
        rt2x00_set_field16(&reg, PHY_CSR7_READ_CONTROL, 0);
 
-       rt2500usb_register_write(rt2x00dev, PHY_CSR7, reg);
+       rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
+
+       mutex_unlock(&rt2x00dev->usb_cache_mutex);
 }
 
-static void rt2500usb_bbp_read(const struct rt2x00_dev *rt2x00dev,
+static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
                               const unsigned int word, u8 *value)
 {
        u16 reg;
 
+       mutex_lock(&rt2x00dev->usb_cache_mutex);
+
        /*
         * Wait until the BBP becomes ready.
         */
@@ -157,7 +185,7 @@ static void rt2500usb_bbp_read(const struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field16(&reg, PHY_CSR7_REG_ID, word);
        rt2x00_set_field16(&reg, PHY_CSR7_READ_CONTROL, 1);
 
-       rt2500usb_register_write(rt2x00dev, PHY_CSR7, reg);
+       rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
 
        /*
         * Wait until the BBP becomes ready.
@@ -166,14 +194,17 @@ static void rt2500usb_bbp_read(const struct rt2x00_dev *rt2x00dev,
        if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) {
                ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n");
                *value = 0xff;
+               mutex_unlock(&rt2x00dev->usb_cache_mutex);
                return;
        }
 
-       rt2500usb_register_read(rt2x00dev, PHY_CSR7, &reg);
+       rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, &reg);
        *value = rt2x00_get_field16(reg, PHY_CSR7_DATA);
+
+       mutex_unlock(&rt2x00dev->usb_cache_mutex);
 }
 
-static void rt2500usb_rf_write(const struct rt2x00_dev *rt2x00dev,
+static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
                               const unsigned int word, const u32 value)
 {
        u16 reg;
@@ -182,20 +213,23 @@ static void rt2500usb_rf_write(const struct rt2x00_dev *rt2x00dev,
        if (!word)
                return;
 
+       mutex_lock(&rt2x00dev->usb_cache_mutex);
+
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2500usb_register_read(rt2x00dev, PHY_CSR10, &reg);
+               rt2500usb_register_read_lock(rt2x00dev, PHY_CSR10, &reg);
                if (!rt2x00_get_field16(reg, PHY_CSR10_RF_BUSY))
                        goto rf_write;
                udelay(REGISTER_BUSY_DELAY);
        }
 
+       mutex_unlock(&rt2x00dev->usb_cache_mutex);
        ERROR(rt2x00dev, "PHY_CSR10 register busy. Write failed.\n");
        return;
 
 rf_write:
        reg = 0;
        rt2x00_set_field16(&reg, PHY_CSR9_RF_VALUE, value);
-       rt2500usb_register_write(rt2x00dev, PHY_CSR9, reg);
+       rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg);
 
        reg = 0;
        rt2x00_set_field16(&reg, PHY_CSR10_RF_VALUE, value >> 16);
@@ -203,20 +237,22 @@ rf_write:
        rt2x00_set_field16(&reg, PHY_CSR10_RF_IF_SELECT, 0);
        rt2x00_set_field16(&reg, PHY_CSR10_RF_BUSY, 1);
 
-       rt2500usb_register_write(rt2x00dev, PHY_CSR10, reg);
+       rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg);
        rt2x00_rf_write(rt2x00dev, word, value);
+
+       mutex_unlock(&rt2x00dev->usb_cache_mutex);
 }
 
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
 #define CSR_OFFSET(__word)     ( CSR_REG_BASE + ((__word) * sizeof(u16)) )
 
-static void rt2500usb_read_csr(const struct rt2x00_dev *rt2x00dev,
+static void rt2500usb_read_csr(struct rt2x00_dev *rt2x00dev,
                               const unsigned int word, u32 *data)
 {
        rt2500usb_register_read(rt2x00dev, CSR_OFFSET(word), (u16 *) data);
 }
 
-static void rt2500usb_write_csr(const struct rt2x00_dev *rt2x00dev,
+static void rt2500usb_write_csr(struct rt2x00_dev *rt2x00dev,
                                const unsigned int word, u32 data)
 {
        rt2500usb_register_write(rt2x00dev, CSR_OFFSET(word), data);
@@ -257,7 +293,7 @@ static const struct rt2x00debug rt2500usb_rt2x00debug = {
 static void rt2500usb_config_mac_addr(struct rt2x00_dev *rt2x00dev,
                                      __le32 *mac)
 {
-       rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, &mac,
+       rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, mac,
                                      (3 * sizeof(__le16)));
 }
 
@@ -280,7 +316,7 @@ static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,
         */
        rt2500usb_register_read(rt2x00dev, TXRX_CSR20, &reg);
        rt2x00_set_field16(&reg, TXRX_CSR20_OFFSET,
-                          (PREAMBLE + get_duration(IEEE80211_HEADER, 2)) >> 6);
+                          (PREAMBLE + get_duration(IEEE80211_HEADER, 20)) >> 6);
        if (type == IEEE80211_IF_TYPE_STA)
                rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW, 0);
        else
@@ -302,56 +338,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);
-       if (preamble == SHORT_PREAMBLE)
-               rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE, 1);
-       else
-               rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE, 0);
+       rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_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;
-
-       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);
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR11, basic_rate_mask);
 
-       if (phymode == MODE_IEEE80211B) {
+       if (phymode == HWMODE_B) {
                rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x000b);
                rt2500usb_register_write(rt2x00dev, MAC_CSR12, 0x0040);
        } else {
@@ -361,20 +380,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.
@@ -387,16 +398,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,
@@ -410,7 +421,7 @@ static void rt2500usb_config_txpower(struct rt2x00_dev *rt2x00dev,
 }
 
 static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev,
-                                    const int antenna_tx, const int antenna_rx)
+                                    struct antenna_setup *ant)
 {
        u8 r2;
        u8 r14;
@@ -425,8 +436,7 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev,
        /*
         * Configure the TX antenna.
         */
-       switch (antenna_tx) {
-       case ANTENNA_SW_DIVERSITY:
+       switch (ant->tx) {
        case ANTENNA_HW_DIVERSITY:
                rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 1);
                rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 1);
@@ -437,6 +447,13 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev,
                rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 0);
                rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 0);
                break;
+       case ANTENNA_SW_DIVERSITY:
+               /*
+                * NOTE: We should never come here because rt2x00lib is
+                * supposed to catch this and send us the correct antenna
+                * explicitely. However we are nog going to bug about this.
+                * Instead, just default to antenna B.
+                */
        case ANTENNA_B:
                rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2);
                rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 2);
@@ -447,14 +464,20 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev,
        /*
         * Configure the RX antenna.
         */
-       switch (antenna_rx) {
-       case ANTENNA_SW_DIVERSITY:
+       switch (ant->rx) {
        case ANTENNA_HW_DIVERSITY:
                rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 1);
                break;
        case ANTENNA_A:
                rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0);
                break;
+       case ANTENNA_SW_DIVERSITY:
+               /*
+                * NOTE: We should never come here because rt2x00lib is
+                * supposed to catch this and send us the correct antenna
+                * explicitely. However we are nog going to bug about this.
+                * Instead, just default to antenna B.
+                */
        case ANTENNA_B:
                rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2);
                break;
@@ -486,38 +509,35 @@ 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->ant);
        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);
 }
 
 /*
@@ -533,18 +553,10 @@ static void rt2500usb_enable_led(struct rt2x00_dev *rt2x00dev)
        rt2500usb_register_write(rt2x00dev, MAC_CSR21, reg);
 
        rt2500usb_register_read(rt2x00dev, MAC_CSR20, &reg);
-
-       if (rt2x00dev->led_mode == LED_MODE_TXRX_ACTIVITY) {
-               rt2x00_set_field16(&reg, MAC_CSR20_LINK, 1);
-               rt2x00_set_field16(&reg, MAC_CSR20_ACTIVITY, 0);
-       } else if (rt2x00dev->led_mode == LED_MODE_ASUS) {
-               rt2x00_set_field16(&reg, MAC_CSR20_LINK, 0);
-               rt2x00_set_field16(&reg, MAC_CSR20_ACTIVITY, 1);
-       } else {
-               rt2x00_set_field16(&reg, MAC_CSR20_LINK, 1);
-               rt2x00_set_field16(&reg, MAC_CSR20_ACTIVITY, 1);
-       }
-
+       rt2x00_set_field16(&reg, MAC_CSR20_LINK,
+                          (rt2x00dev->led_mode != LED_MODE_ASUS));
+       rt2x00_set_field16(&reg, MAC_CSR20_ACTIVITY,
+                          (rt2x00dev->led_mode != LED_MODE_TXRX_ACTIVITY));
        rt2500usb_register_write(rt2x00dev, MAC_CSR20, reg);
 }
 
@@ -561,7 +573,8 @@ static void rt2500usb_disable_led(struct rt2x00_dev *rt2x00dev)
 /*
  * Link tuning
  */
-static void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev)
+static void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev,
+                                struct link_qual *qual)
 {
        u16 reg;
 
@@ -569,14 +582,13 @@ static void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev)
         * Update FCS error count from register.
         */
        rt2500usb_register_read(rt2x00dev, STA_CSR0, &reg);
-       rt2x00dev->link.rx_failed = rt2x00_get_field16(reg, STA_CSR0_FCS_ERROR);
+       qual->rx_failed = rt2x00_get_field16(reg, STA_CSR0_FCS_ERROR);
 
        /*
         * Update False CCA count from register.
         */
        rt2500usb_register_read(rt2x00dev, STA_CSR3, &reg);
-       rt2x00dev->link.false_cca =
-           rt2x00_get_field16(reg, STA_CSR3_FALSE_CCA_ERROR);
+       qual->false_cca = rt2x00_get_field16(reg, STA_CSR3_FALSE_CCA_ERROR);
 }
 
 static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev)
@@ -699,10 +711,10 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev)
        if (r17 > up_bound) {
                rt2500usb_bbp_write(rt2x00dev, 17, up_bound);
                rt2x00dev->link.vgc_level = up_bound;
-       } else if (rt2x00dev->link.false_cca > 512 && r17 < up_bound) {
+       } else if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) {
                rt2500usb_bbp_write(rt2x00dev, 17, ++r17);
                rt2x00dev->link.vgc_level = r17;
-       } else if (rt2x00dev->link.false_cca < 100 && r17 > low_bound) {
+       } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) {
                rt2500usb_bbp_write(rt2x00dev, 17, --r17);
                rt2x00dev->link.vgc_level = r17;
        }
@@ -779,11 +791,13 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field16(&reg, MAC_CSR1_HOST_READY, 1);
        rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
 
-       if (rt2x00_get_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) {
+       if (rt2x00_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) {
                rt2500usb_register_read(rt2x00dev, PHY_CSR2, &reg);
-               reg &= ~0x0002;
+               rt2x00_set_field16(&reg, PHY_CSR2_LNA, 0);
        } else {
-               reg = 0x3002;
+               reg = 0;
+               rt2x00_set_field16(&reg, PHY_CSR2_LNA, 1);
+               rt2x00_set_field16(&reg, PHY_CSR2_LNA_MODE, 3);
        }
        rt2500usb_register_write(rt2x00dev, PHY_CSR2, reg);
 
@@ -1014,7 +1028,7 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev,
  * TX descriptor initialization
  */
 static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
-                                   struct data_desc *txd,
+                                   __le32 *txd,
                                    struct txdata_entry_desc *desc,
                                    struct ieee80211_hdr *ieee80211hdr,
                                    unsigned int length,
@@ -1044,7 +1058,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
                           test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
        rt2x00_set_field32(&word, TXD_W0_ACK,
-                          !(control->flags & IEEE80211_TXCTL_NO_ACK));
+                          test_bit(ENTRY_TXD_ACK, &desc->flags));
        rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
                           test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
        rt2x00_set_field32(&word, TXD_W0_OFDM,
@@ -1057,6 +1071,21 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
        rt2x00_desc_write(txd, 0, word);
 }
 
+static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
+                                    struct sk_buff *skb)
+{
+       int length;
+
+       /*
+        * The length _must_ be a multiple of 2,
+        * but it must _not_ be a multiple of the USB packet size.
+        */
+       length = roundup(skb->len, 2);
+       length += (2 * !(length % rt2x00dev->usb_maxpacket));
+
+       return length;
+}
+
 /*
  * TX data initialization
  */
@@ -1091,9 +1120,8 @@ static void rt2500usb_fill_rxdone(struct data_entry *entry,
                                  struct rxdata_entry_desc *desc)
 {
        struct urb *urb = entry->priv;
-       struct data_desc *rxd = (struct data_desc *)(entry->skb->data +
-                                                    (urb->actual_length -
-                                                     entry->ring->desc_size));
+       __le32 *rxd = (__le32 *)(entry->skb->data +
+                                (urb->actual_length - entry->ring->desc_size));
        u32 word0;
        u32 word1;
 
@@ -1174,9 +1202,12 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
        rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT, 0);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT, 0);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_LED_MODE, 0);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
+                                  ANTENNA_SW_DIVERSITY);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT,
+                                  ANTENNA_SW_DIVERSITY);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_LED_MODE,
+                                  LED_MODE_DEFAULT);
                rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0);
                rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
                rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2522);
@@ -1268,7 +1299,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
        rt2500usb_register_read(rt2x00dev, MAC_CSR0, &reg);
        rt2x00_set_chip(rt2x00dev, RT2570, value, reg);
 
-       if (rt2x00_rev(&rt2x00dev->chip, 0xffff0)) {
+       if (!rt2x00_check_rev(&rt2x00dev->chip, 0)) {
                ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
                return -ENODEV;
        }
@@ -1286,11 +1317,22 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
        /*
         * Identify default antenna configuration.
         */
-       rt2x00dev->hw->conf.antenna_sel_tx =
+       rt2x00dev->default_ant.tx =
            rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT);
-       rt2x00dev->hw->conf.antenna_sel_rx =
+       rt2x00dev->default_ant.rx =
            rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT);
 
+       /*
+        * When the eeprom indicates SW_DIVERSITY use HW_DIVERSITY instead.
+        * I am not 100% sure about this, but the legacy drivers do not
+        * indicate antenna swapping in software is required when
+        * diversity is enabled.
+        */
+       if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
+               rt2x00dev->default_ant.tx = ANTENNA_HW_DIVERSITY;
+       if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
+               rt2x00dev->default_ant.rx = ANTENNA_HW_DIVERSITY;
+
        /*
         * Store led mode, for correct led behaviour.
         */
@@ -1653,6 +1695,7 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
            rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
        struct data_entry *beacon;
        struct data_entry *guardian;
+       int pipe = usb_sndbulkpipe(usb_dev, 1);
        int length;
 
        /*
@@ -1674,21 +1717,16 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
         * First we create the beacon.
         */
        skb_push(skb, ring->desc_size);
-       rt2x00lib_write_tx_desc(rt2x00dev, (struct data_desc *)skb->data,
+       memset(skb->data, 0, ring->desc_size);
+
+       rt2x00lib_write_tx_desc(rt2x00dev, (__le32 *)skb->data,
                                (struct ieee80211_hdr *)(skb->data +
                                                         ring->desc_size),
                                skb->len - ring->desc_size, control);
 
-       /*
-        * Length passed to usb_fill_urb cannot be an odd number,
-        * so add 1 byte to make it even.
-        */
-       length = skb->len;
-       if (length % 2)
-               length++;
+       length = rt2500usb_get_tx_data_len(rt2x00dev, skb);
 
-       usb_fill_bulk_urb(beacon->priv, usb_dev,
-                         usb_sndbulkpipe(usb_dev, 1),
+       usb_fill_bulk_urb(beacon->priv, usb_dev, pipe,
                          skb->data, length, rt2500usb_beacondone, beacon);
 
        beacon->skb = skb;
@@ -1699,8 +1737,7 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
         * the 'flags' field we are not using for beacons.
         */
        guardian->flags = 0;
-       usb_fill_bulk_urb(guardian->priv, usb_dev,
-                         usb_sndbulkpipe(usb_dev, 1),
+       usb_fill_bulk_urb(guardian->priv, usb_dev, pipe,
                          &guardian->flags, 1, rt2500usb_beacondone, guardian);
 
        /*
@@ -1726,6 +1763,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,
@@ -1741,11 +1779,13 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
        .link_tuner             = rt2500usb_link_tuner,
        .write_tx_desc          = rt2500usb_write_tx_desc,
        .write_tx_data          = rt2x00usb_write_tx_data,
+       .get_tx_data_len        = rt2500usb_get_tx_data_len,
        .kick_tx_queue          = rt2500usb_kick_tx_queue,
        .fill_rxdone            = rt2500usb_fill_rxdone,
        .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,
 };