Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
authorDavid S. Miller <davem@davemloft.net>
Tue, 18 Mar 2008 07:37:55 +0000 (00:37 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 18 Mar 2008 07:37:55 +0000 (00:37 -0700)
Conflicts:

drivers/net/wireless/rt2x00/rt2x00dev.c
net/8021q/vlan_dev.c

21 files changed:
1  2 
Documentation/feature-removal-schedule.txt
Documentation/laptops/acer-wmi.txt
MAINTAINERS
drivers/net/wireless/ath5k/hw.c
drivers/net/wireless/libertas/cmdresp.c
drivers/net/wireless/rt2x00/rt2x00.h
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/rt2x00/rt2x00lib.h
drivers/net/wireless/rt2x00/rt2x00rfkill.c
drivers/net/wireless/rt2x00/rt61pci.c
drivers/net/wireless/rt2x00/rt73usb.c
include/net/xfrm.h
net/8021q/vlan_dev.c
net/ipv4/af_inet.c
net/ipv4/ip_sockglue.c
net/ipv4/ipconfig.c
net/ipv4/tcp_output.c
net/sctp/input.c
net/sctp/ipv6.c
net/sctp/protocol.c
net/sctp/socket.c

@@@ -172,6 -172,16 +172,16 @@@ Who:     Len Brown <len.brown@intel.com
  
  ---------------------------
  
+ What: ide-tape driver
+ When: July 2008
+ Files:        drivers/ide/ide-tape.c
+ Why:  This driver might not have any users anymore and maintaining it for no
+       reason is an effort no one wants to make.
+ Who:  Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>, Borislav Petkov
+       <petkovbb@googlemail.com>
+ ---------------------------
  What: libata spindown skipping and warning
  When: Dec 2008
  Why:  Some halt(8) implementations synchronize caches for and spin
@@@ -230,6 -240,33 +240,6 @@@ Who:      Jean Delvare <khali@linux-fr.org
  
  ---------------------------
  
 -What: bcm43xx wireless network driver
 -When: 2.6.26
 -Files:        drivers/net/wireless/bcm43xx
 -Why:  This driver's functionality has been replaced by the
 -      mac80211-based b43 and b43legacy drivers.
 -Who:  John W. Linville <linville@tuxdriver.com>
 -
 ----------------------------
 -
 -What: ieee80211 softmac wireless networking component
 -When: 2.6.26 (or after removal of bcm43xx and port of zd1211rw to mac80211)
 -Files:        net/ieee80211/softmac
 -Why:  No in-kernel drivers will depend on it any longer.
 -Who:  John W. Linville <linville@tuxdriver.com>
 -
 ----------------------------
 -
 -What: rc80211-simple rate control algorithm for mac80211
 -When: 2.6.26
 -Files:        net/mac80211/rc80211-simple.c
 -Why:  This algorithm was provided for reference but always exhibited bad
 -      responsiveness and performance and has some serious flaws. It has been
 -      replaced by rc80211-pid.
 -Who:  Stefano Brivio <stefano.brivio@polimi.it>
 -
 ----------------------------
 -
  What (Why):
        - include/linux/netfilter_ipv4/ipt_TOS.h ipt_tos.h header files
          (superseded by xt_TOS/xt_tos target & match)
@@@ -279,3 -316,15 +289,15 @@@ Why:     Largely unmaintained and almost en
        is largely pointless as without a lot of work only the most
        trivial of Solaris binaries can work with the emulation code.
  Who:  David S. Miller <davem@davemloft.net>
+ ---------------------------
+ What: init_mm export
+ When: 2.6.26
+ Why:  Not used in-tree. The current out-of-tree users used it to
+       work around problems in the CPA code which should be resolved
+       by now. One usecase was described to provide verification code
+       of the CPA operation. That's a good idea in general, but such
+       code / infrastructure should be in the kernel and not in some
+       out-of-tree driver.
+ Who:  Thomas Gleixner <tglx@linutronix.de>
@@@ -48,7 -48,7 +48,7 @@@ DSDT
  
  To send me the DSDT, as root/sudo:
  
- cat /sys/firmware/acpi/DSDT > dsdt
+ cat /sys/firmware/acpi/tables/DSDT > dsdt
  
  And send me the resulting 'dsdt' file.
  
@@@ -80,7 -80,7 +80,7 @@@ once you enable the radio, will depend 
  e.g. With the BCM4318 on the Acer Aspire 5020 series:
  
  ndiswrapper: Light blinks on when transmitting
 -bcm43xx/b43: Solid light, blinks off when transmitting
 +b43: Solid light, blinks off when transmitting
  
  Wireless radio control is unconditionally enabled - all Acer laptops that support
  acer-wmi come with built-in wireless. However, should you feel so inclined to
@@@ -169,7 -169,7 +169,7 @@@ can be added to acer-wmi
  
  The LED is exposed through the LED subsystem, and can be found in:
  
- /sys/devices/platform/acer-wmi/leds/acer-mail:green/
+ /sys/devices/platform/acer-wmi/leds/acer-wmi::mail/
  
  The mail LED is autodetected, so if you don't have one, the LED device won't
  be registered.
diff --combined MAINTAINERS
@@@ -266,6 -266,15 +266,15 @@@ L:      linux-acpi@vger.kernel.or
  W:      http://www.lesswatts.org/projects/acpi/
  S:      Maintained
  
+ AD1889 ALSA SOUND DRIVER
+ P:     Kyle McMartin
+ M:     kyle@parisc-linux.org
+ P:     Thibaut Varene
+ M:     T-Bone@parisc-linux.org
+ W:     http://wiki.parisc-linux.org/AD1889
+ L:     linux-parisc@vger.kernel.org
+ S:     Maintained
  ADM1025 HARDWARE MONITOR DRIVER
  P:    Jean Delvare
  M:    khali@linux-fr.org
@@@ -767,14 -776,14 +776,14 @@@ S:      Maintaine
  
  BLACKFIN ARCHITECTURE
  P:    Bryan Wu
- M:    bryan.wu@analog.com
+ M:    cooloney@kernel.org
  L:    uclinux-dist-devel@blackfin.uclinux.org (subscribers-only)
  W:    http://blackfin.uclinux.org
  S:    Supported
  
  BLACKFIN EMAC DRIVER
  P:    Bryan Wu
- M:    bryan.wu@analog.com
+ M:    cooloney@kernel.org
  L:    uclinux-dist-devel@blackfin.uclinux.org (subscribers-only)
  W:    http://blackfin.uclinux.org
  S:    Supported
@@@ -825,6 -834,15 +834,6 @@@ L:        linux-wireless@vger.kernel.or
  W:    http://linuxwireless.org/en/users/Drivers/b43
  S:    Maintained
  
 -BCM43XX WIRELESS DRIVER (SOFTMAC BASED VERSION)
 -P:    Larry Finger
 -M:    Larry.Finger@lwfinger.net
 -P:    Stefano Brivio
 -M:    stefano.brivio@polimi.it
 -L:    linux-wireless@vger.kernel.org
 -W:    http://bcm43xx.berlios.de/
 -S:    Obsolete
 -
  BEFS FILE SYSTEM
  P:    Sergey S. Kostyliov
  M:    rathamahata@php4.ru
@@@ -1129,6 -1147,12 +1138,12 @@@ L:    accessrunner-general@lists.sourcefor
  W:    http://accessrunner.sourceforge.net/
  S:    Maintained
  
+ CONTROL GROUPS (CGROUPS)
+ P:    Paul Menage
+ M:    menage@google.com
+ L:    containers@lists.linux-foundation.org
+ S:    Maintained
  CORETEMP HARDWARE MONITORING DRIVER
  P:    Rudolf Marek
  M:    r.marek@assembler.cz
@@@ -1580,6 -1604,13 +1595,13 @@@ L:    linux-fbdev-devel@lists.sourceforge.
  W:    http://linux-fbdev.sourceforge.net/
  S:    Maintained
  
+ FREESCALE DMA DRIVER
+ P;    Zhang Wei
+ M:    wei.zhang@freescale.com
+ L:    linuxppc-embedded@ozlabs.org
+ L:    linux-kernel@vger.kernel.org
+ S:    Maintained
  FREESCALE SOC FS_ENET DRIVER
  P:    Pantelis Antoniou
  M:    pantelis.antoniou@gmail.com
@@@ -2110,7 -2141,7 +2132,7 @@@ L:      netdev@vger.kernel.or
  S:    Maintained
  
  IPATH DRIVER:
- P:    Arthur Jones
+ P:    Ralph Campbell
  M:    infinipath@qlogic.com
  L:    general@lists.openfabrics.org
  T:    git git://git.qlogic.com/ipath-linux-2.6
@@@ -2593,6 -2624,17 +2615,17 @@@ L:    linux-kernel@vger.kernel.or
  W:    http://www.linux-mm.org
  S:    Maintained
  
+ MEMORY RESOURCE CONTROLLER
+ P:    Balbir Singh
+ M:    balbir@linux.vnet.ibm.com
+ P:    Pavel Emelyanov
+ M:    xemul@openvz.org
+ P:    KAMEZAWA Hiroyuki
+ M:    kamezawa.hiroyu@jp.fujitsu.com
+ L:    linux-mm@kvack.org
+ L:    linux-kernel@vger.kernel.org
+ S:    Maintained
  MEI MN10300/AM33 PORT
  P:    David Howells
  M:    dhowells@redhat.com
@@@ -2717,6 -2759,8 +2750,8 @@@ S:      Maintaine
  NETEFFECT IWARP RNIC DRIVER (IW_NES)
  P:    Faisal Latif
  M:    flatif@neteffect.com
+ P:    Nishi Gupta
+ M:    ngupta@neteffect.com
  P:    Glenn Streiff
  M:    gstreiff@neteffect.com
  L:    general@lists.openfabrics.org
@@@ -3548,6 -3592,12 +3583,6 @@@ M:     mhoffman@lightlink.co
  L:    lm-sensors@lm-sensors.org
  S:    Maintained
  
 -SOFTMAC LAYER (IEEE 802.11)
 -P:    Daniel Drake
 -M:    dsd@gentoo.org
 -L:    linux-wireless@vger.kernel.org
 -S:    Obsolete
 -
  SOFTWARE RAID (Multiple Disks) SUPPORT
  P:    Ingo Molnar
  M:    mingo@redhat.com
@@@ -1,4 -1,4 +1,4 @@@
 - /*
 +/*
   * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
   * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com>
   * Copyright (c) 2007 Matthew W. S. Bell  <mentor@madwifi.org>
@@@ -48,18 -48,14 +48,18 @@@ static int ath5k_hw_setup_4word_tx_desc
  static int ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
        unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
        unsigned int);
 -static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *);
 +static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *,
 +                                       struct ath5k_tx_status *);
  static int ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
        unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
        unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
        unsigned int, unsigned int);
 -static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *);
 -static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *, struct ath5k_desc *);
 -static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *, struct ath5k_desc *);
 +static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *,
 +                                       struct ath5k_tx_status *);
 +static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *, struct ath5k_desc *,
 +                                      struct ath5k_rx_status *);
 +static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *, struct ath5k_desc *,
 +                                      struct ath5k_rx_status *);
  static int ath5k_hw_get_capabilities(struct ath5k_hw *);
  
  static int ath5k_eeprom_init(struct ath5k_hw *);
@@@ -85,12 -81,12 +85,12 @@@ static int ath5k_hw_disable_pspoll(stru
  
  static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo)
  {
 -      return turbo == true ? (usec * 80) : (usec * 40);
 +      return turbo ? (usec * 80) : (usec * 40);
  }
  
  static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo)
  {
 -      return turbo == true ? (clock / 80) : (clock / 40);
 +      return turbo ? (clock / 80) : (clock / 40);
  }
  
  /*
@@@ -104,7 -100,7 +104,7 @@@ int ath5k_hw_register_timeout(struct at
  
        for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
                data = ath5k_hw_reg_read(ah, reg);
 -              if ((is_set == true) && (data & flag))
 +              if (is_set && (data & flag))
                        break;
                else if ((data & flag) == val)
                        break;
@@@ -144,6 -140,9 +144,6 @@@ struct ath5k_hw *ath5k_hw_attach(struc
         * HW information
         */
  
 -      /* Get reg domain from eeprom */
 -      ath5k_get_regdomain(ah);
 -
        ah->ah_op_mode = IEEE80211_IF_TYPE_STA;
        ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
        ah->ah_turbo = false;
        }
  
        if (ah->ah_version == AR5K_AR5212)
 -              ah->ah_proc_rx_desc = ath5k_hw_proc_new_rx_status;
 +              ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status;
        else if (ah->ah_version <= AR5K_AR5211)
 -              ah->ah_proc_rx_desc = ath5k_hw_proc_old_rx_status;
 +              ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status;
  
        /* Bring device out of sleep and reset it's units */
        ret = ath5k_hw_nic_wakeup(ah, AR5K_INIT_MODE, true);
  
        /* Identify single chip solutions */
        if((srev <= AR5K_SREV_VER_AR5414) &&
 -      (srev >= AR5K_SREV_VER_AR2424)) {
 +      (srev >= AR5K_SREV_VER_AR2413)) {
                ah->ah_single_chip = true;
        } else {
                ah->ah_single_chip = false;
                ah->ah_radio = AR5K_RF5110;
        } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) {
                ah->ah_radio = AR5K_RF5111;
 -      } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) {
 +              ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5111;
 +      } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC0) {
 +
                ah->ah_radio = AR5K_RF5112;
 +
 +              if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) {
 +                      ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112;
 +              } else {
 +                      ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
 +              }
 +
 +      } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) {
 +              ah->ah_radio = AR5K_RF2413;
 +              ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
        } else {
 +
                ah->ah_radio = AR5K_RF5413;
 +
 +              if (ah->ah_mac_srev <= AR5K_SREV_VER_AR5424 &&
 +                      ah->ah_mac_srev >= AR5K_SREV_VER_AR2424)
 +                      ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5424;
 +              else if (ah->ah_mac_srev >= AR5K_SREV_VER_AR2425)
 +                      ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112;
 +              else
 +                      ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
 +
 +
        }
  
        ah->ah_phy = AR5K_PHY(0);
@@@ -304,8 -280,7 +304,8 @@@ err
   */
  static int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
  {
 -      u32 turbo, mode, clock;
 +      struct pci_dev *pdev = ah->ah_sc->pdev;
 +      u32 turbo, mode, clock, bus_flags;
        int ret;
  
        turbo = 0;
                                        AR5K_PHY_TURBO);
        }
  
 -      /* ...reset chipset and PCI device */
 -      if (ah->ah_single_chip == false && ath5k_hw_nic_reset(ah,
 -                              AR5K_RESET_CTL_CHIP | AR5K_RESET_CTL_PCI)) {
 +      /* reseting PCI on PCI-E cards results card to hang
 +       * and always return 0xffff... so we ingore that flag
 +       * for PCI-E cards */
 +      bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
 +
 +      /* Reset chipset */
 +      ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
 +              AR5K_RESET_CTL_BASEBAND | bus_flags);
 +      if (ret) {
                ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip + PCI\n");
                return -EIO;
        }
@@@ -436,15 -405,15 +436,15 @@@ const struct ath5k_rate_table *ath5k_hw
  
        /* Get rate tables */
        switch (mode) {
 -      case MODE_IEEE80211A:
 +      case AR5K_MODE_11A:
                return &ath5k_rt_11a;
 -      case MODE_ATHEROS_TURBO:
 +      case AR5K_MODE_11A_TURBO:
                return &ath5k_rt_turbo;
 -      case MODE_IEEE80211B:
 +      case AR5K_MODE_11B:
                return &ath5k_rt_11b;
 -      case MODE_IEEE80211G:
 +      case AR5K_MODE_11G:
                return &ath5k_rt_11g;
 -      case MODE_ATHEROS_TURBOG:
 +      case AR5K_MODE_11G_TURBO:
                return &ath5k_rt_xr;
        }
  
@@@ -458,6 -427,8 +458,8 @@@ void ath5k_hw_detach(struct ath5k_hw *a
  {
        ATH5K_TRACE(ah->ah_sc);
  
+       __set_bit(ATH_STAT_INVALID, ah->ah_sc->status);
        if (ah->ah_rf_banks != NULL)
                kfree(ah->ah_rf_banks);
  
@@@ -488,15 -459,15 +490,15 @@@ static inline int ath5k_hw_write_ofdm_t
                ds_coef_exp, ds_coef_man, clock;
  
        if (!(ah->ah_version == AR5K_AR5212) ||
 -              !(channel->val & CHANNEL_OFDM))
 +              !(channel->hw_value & CHANNEL_OFDM))
                BUG();
  
        /* Seems there are two PLLs, one for baseband sampling and one
         * for tuning. Tuning basebands are 40 MHz or 80MHz when in
         * turbo. */
 -      clock = channel->val & CHANNEL_TURBO ? 80 : 40;
 +      clock = channel->hw_value & CHANNEL_TURBO ? 80 : 40;
        coef_scaled = ((5 * (clock << 24)) / 2) /
 -      channel->freq;
 +      channel->center_freq;
  
        for (coef_exp = 31; coef_exp > 0; coef_exp--)
                if ((coef_scaled >> coef_exp) & 0x1)
   * ath5k_hw_write_rate_duration - set rate duration during hw resets
   *
   * @ah: the &struct ath5k_hw
 - * @driver_mode: one of enum ieee80211_phymode or our one of our own
 - *     vendor modes
 + * @mode: one of enum ath5k_driver_mode
   *
   * Write the rate duration table for the current mode upon hw reset. This
   * is a helper for ath5k_hw_reset(). It seems all this is doing is setting
   *
   */
  static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
 -       unsigned int driver_mode)
 +       unsigned int mode)
  {
        struct ath5k_softc *sc = ah->ah_sc;
        const struct ath5k_rate_table *rt;
 +      struct ieee80211_rate srate = {};
        unsigned int i;
  
        /* Get rate table for the current operating mode */
 -      rt = ath5k_hw_get_rate_table(ah,
 -              driver_mode);
 +      rt = ath5k_hw_get_rate_table(ah, mode);
  
        /* Write rate duration table */
        for (i = 0; i < rt->rate_count; i++) {
                const struct ath5k_rate *rate, *control_rate;
 +
                u32 reg;
                u16 tx_time;
  
                /* Set ACK timeout */
                reg = AR5K_RATE_DUR(rate->rate_code);
  
 +              srate.bitrate = control_rate->rate_kbps/100;
 +
                /* An ACK frame consists of 10 bytes. If you add the FCS,
                 * which ieee80211_generic_frame_duration() adds,
                 * its 14 bytes. Note we use the control rate and not the
                 * actual rate for this rate. See mac80211 tx.c
                 * ieee80211_duration() for a brief description of
                 * what rate we should choose to TX ACKs. */
 -              tx_time = ieee80211_generic_frame_duration(sc->hw,
 -                      sc->vif, 10, control_rate->rate_kbps/100);
 +              tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw,
 +                                                      sc->vif, 10, &srate));
  
                ath5k_hw_reg_write(ah, tx_time, reg);
  
@@@ -599,9 -568,8 +601,9 @@@ int ath5k_hw_reset(struct ath5k_hw *ah
        struct ieee80211_channel *channel, bool change_channel)
  {
        struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
 -      u32 data, s_seq, s_ant, s_led[3];
 -      unsigned int i, mode, freq, ee_mode, ant[2], driver_mode = -1;
 +      struct pci_dev *pdev = ah->ah_sc->pdev;
 +      u32 data, s_seq, s_ant, s_led[3], dma_size;
 +      unsigned int i, mode, freq, ee_mode, ant[2];
        int ret;
  
        ATH5K_TRACE(ah->ah_sc);
         */
        /*DCU/Antenna selection not available on 5210*/
        if (ah->ah_version != AR5K_AR5210) {
 -              if (change_channel == true) {
 +              if (change_channel) {
                        /* Seq number for queue 0 -do this for all queues ? */
                        s_seq = ath5k_hw_reg_read(ah,
                                        AR5K_QUEUE_DFS_SEQNUM(0));
        s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
        s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
  
 -      if (change_channel == true && ah->ah_rf_banks != NULL)
 +      if (change_channel && ah->ah_rf_banks != NULL)
                ath5k_hw_get_rf_gain(ah);
  
  
        /*Wakeup the device*/
 -      ret = ath5k_hw_nic_wakeup(ah, channel->val, false);
 +      ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false);
        if (ret)
                return ret;
  
        if (ah->ah_version != AR5K_AR5210) {
                if (ah->ah_radio != AR5K_RF5111 &&
                        ah->ah_radio != AR5K_RF5112 &&
 -                      ah->ah_radio != AR5K_RF5413) {
 +                      ah->ah_radio != AR5K_RF5413 &&
 +                      ah->ah_radio != AR5K_RF2413) {
                        ATH5K_ERR(ah->ah_sc,
                                "invalid phy radio: %u\n", ah->ah_radio);
                        return -EINVAL;
                }
  
 -              switch (channel->val & CHANNEL_MODES) {
 +              switch (channel->hw_value & CHANNEL_MODES) {
                case CHANNEL_A:
 -                      mode = AR5K_INI_VAL_11A;
 +                      mode = AR5K_MODE_11A;
                        freq = AR5K_INI_RFGAIN_5GHZ;
                        ee_mode = AR5K_EEPROM_MODE_11A;
 -                      driver_mode = MODE_IEEE80211A;
                        break;
                case CHANNEL_G:
 -                      mode = AR5K_INI_VAL_11G;
 +                      mode = AR5K_MODE_11G;
                        freq = AR5K_INI_RFGAIN_2GHZ;
                        ee_mode = AR5K_EEPROM_MODE_11G;
 -                      driver_mode = MODE_IEEE80211G;
                        break;
                case CHANNEL_B:
 -                      mode = AR5K_INI_VAL_11B;
 +                      mode = AR5K_MODE_11B;
                        freq = AR5K_INI_RFGAIN_2GHZ;
                        ee_mode = AR5K_EEPROM_MODE_11B;
 -                      driver_mode = MODE_IEEE80211B;
                        break;
                case CHANNEL_T:
 -                      mode = AR5K_INI_VAL_11A_TURBO;
 +                      mode = AR5K_MODE_11A_TURBO;
                        freq = AR5K_INI_RFGAIN_5GHZ;
                        ee_mode = AR5K_EEPROM_MODE_11A;
 -                      driver_mode = MODE_ATHEROS_TURBO;
                        break;
                /*Is this ok on 5211 too ?*/
                case CHANNEL_TG:
 -                      mode = AR5K_INI_VAL_11G_TURBO;
 +                      mode = AR5K_MODE_11G_TURBO;
                        freq = AR5K_INI_RFGAIN_2GHZ;
                        ee_mode = AR5K_EEPROM_MODE_11G;
 -                      driver_mode = MODE_ATHEROS_TURBOG;
                        break;
                case CHANNEL_XR:
                        if (ah->ah_version == AR5K_AR5211) {
                                        "XR mode not available on 5211");
                                return -EINVAL;
                        }
 -                      mode = AR5K_INI_VAL_XR;
 +                      mode = AR5K_MODE_XR;
                        freq = AR5K_INI_RFGAIN_5GHZ;
                        ee_mode = AR5K_EEPROM_MODE_11A;
 -                      driver_mode = MODE_IEEE80211A;
                        break;
                default:
                        ATH5K_ERR(ah->ah_sc,
 -                              "invalid channel: %d\n", channel->freq);
 +                              "invalid channel: %d\n", channel->center_freq);
                        return -EINVAL;
                }
  
                /*
                 * Write some more initial register settings
                 */
 -              if (ah->ah_version > AR5K_AR5211){ /* found on 5213+ */
 +              if (ah->ah_version == AR5K_AR5212) {
                        ath5k_hw_reg_write(ah, 0x0002a002, AR5K_PHY(11));
  
 -                      if (channel->val == CHANNEL_G)
 -                              ath5k_hw_reg_write(ah, 0x00f80d80, AR5K_PHY(83)); /* 0x00fc0ec0 */
 +                      if (channel->hw_value == CHANNEL_G)
 +                              if (ah->ah_mac_srev < AR5K_SREV_VER_AR2413)
 +                                      ath5k_hw_reg_write(ah, 0x00f80d80,
 +                                              AR5K_PHY(83));
 +                              else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2424)
 +                                      ath5k_hw_reg_write(ah, 0x00380140,
 +                                              AR5K_PHY(83));
 +                              else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2425)
 +                                      ath5k_hw_reg_write(ah, 0x00fc0ec0,
 +                                              AR5K_PHY(83));
 +                              else /* 2425 */
 +                                      ath5k_hw_reg_write(ah, 0x00fc0fc0,
 +                                              AR5K_PHY(83));
                        else
 -                              ath5k_hw_reg_write(ah, 0x00000000, AR5K_PHY(83));
 +                              ath5k_hw_reg_write(ah, 0x00000000,
 +                                      AR5K_PHY(83));
  
 -                      ath5k_hw_reg_write(ah, 0x000001b5, 0xa228); /* 0x000009b5 */
                        ath5k_hw_reg_write(ah, 0x000009b5, 0xa228);
                        ath5k_hw_reg_write(ah, 0x0000000f, 0x8060);
                        ath5k_hw_reg_write(ah, 0x00000000, 0xa254);
                                AR5K_SREV_RAD_5112A) {
                        ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
                                        AR5K_PHY_CCKTXCTL);
 -                      if (channel->val & CHANNEL_5GHZ)
 +                      if (channel->hw_value & CHANNEL_5GHZ)
                                data = 0xffb81020;
                        else
                                data = 0xffb80d20;
                 * mac80211 are integrated */
                if (ah->ah_version == AR5K_AR5212 &&
                        ah->ah_sc->vif != NULL)
 -                      ath5k_hw_write_rate_duration(ah, driver_mode);
 +                      ath5k_hw_write_rate_duration(ah, mode);
  
                /*
                 * Write RF registers
  
                /* Write OFDM timings on 5212*/
                if (ah->ah_version == AR5K_AR5212 &&
 -                      channel->val & CHANNEL_OFDM) {
 +                      channel->hw_value & CHANNEL_OFDM) {
                        ret = ath5k_hw_write_ofdm_timings(ah, channel);
                        if (ret)
                                return ret;
                /*Enable/disable 802.11b mode on 5111
                (enable 2111 frequency converter + CCK)*/
                if (ah->ah_radio == AR5K_RF5111) {
 -                      if (driver_mode == MODE_IEEE80211B)
 +                      if (mode == AR5K_MODE_11B)
                                AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG,
                                    AR5K_TXCFG_B_MODE);
                        else
  
        /*
         * Set Rx/Tx DMA Configuration
 -       *(passing dma size not available on 5210)
 +       *
 +       * Set maximum DMA size (512) except for PCI-E cards since
 +       * it causes rx overruns and tx errors (tested on 5424 but since
 +       * rx overruns also occur on 5416/5418 with madwifi we set 128
 +       * for all PCI-E cards to be safe).
 +       *
 +       * In dumps this is 128 for allchips.
 +       *
 +       * XXX: need to check 5210 for this
 +       * TODO: Check out tx triger level, it's always 64 on dumps but I
 +       * guess we can tweak it and see how it goes ;-)
         */
 +      dma_size = (pdev->is_pcie) ? AR5K_DMASIZE_128B : AR5K_DMASIZE_512B;
        if (ah->ah_version != AR5K_AR5210) {
 -              AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_SDMAMR,
 -                              AR5K_DMASIZE_512B | AR5K_TXCFG_DMASIZE);
 -              AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_SDMAMW,
 -                              AR5K_DMASIZE_512B);
 +              AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
 +                      AR5K_TXCFG_SDMAMR, dma_size);
 +              AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
 +                      AR5K_RXCFG_SDMAMW, dma_size);
        }
  
        /*
        if (ah->ah_version != AR5K_AR5210) {
                data = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
                        AR5K_PHY_RX_DELAY_M;
 -              data = (channel->val & CHANNEL_CCK) ?
 +              data = (channel->hw_value & CHANNEL_CCK) ?
                        ((data << 2) / 22) : (data / 10);
  
                udelay(100 + data);
        if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
                        AR5K_PHY_AGCCTL_CAL, 0, false)) {
                ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
 -                      channel->freq);
 +                      channel->center_freq);
                return -EAGAIN;
        }
  
 -      ret = ath5k_hw_noise_floor_calibration(ah, channel->freq);
 +      ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
        if (ret)
                return ret;
  
  
        /* A and G modes can use QAM modulation which requires enabling
         * I and Q calibration. Don't bother in B mode. */
 -      if (!(driver_mode == MODE_IEEE80211B)) {
 +      if (!(mode == AR5K_MODE_11B)) {
                ah->ah_calibration = true;
                AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
                                AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
  
        /*
         * Set the 32MHz reference clock on 5212 phy clock sleep register
 +       *
 +       * TODO: Find out how to switch to external 32Khz clock to save power
         */
        if (ah->ah_version == AR5K_AR5212) {
                ath5k_hw_reg_write(ah, AR5K_PHY_SCR_32MHZ, AR5K_PHY_SCR);
                ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ, AR5K_PHY_SCAL);
                ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
                ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
 -              ath5k_hw_reg_write(ah, ah->ah_radio == AR5K_RF5111 ?
 -                      AR5K_PHY_SPENDING_RF5111 : AR5K_PHY_SPENDING_RF5112,
 -                      AR5K_PHY_SPENDING);
 +              ath5k_hw_reg_write(ah, ah->ah_phy_spending, AR5K_PHY_SPENDING);
 +      }
 +
 +      if (ah->ah_version == AR5K_AR5212) {
 +              ath5k_hw_reg_write(ah, 0x000100aa, 0x8118);
 +              ath5k_hw_reg_write(ah, 0x00003210, 0x811c);
 +              ath5k_hw_reg_write(ah, 0x00000052, 0x8108);
 +              if (ah->ah_mac_srev >= AR5K_SREV_VER_AR2413)
 +                      ath5k_hw_reg_write(ah, 0x00000004, 0x8120);
        }
  
        /*
@@@ -1122,7 -1065,7 +1124,7 @@@ int ath5k_hw_set_power(struct ath5k_hw 
                staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA;
                /* fallthrough */
        case AR5K_PM_NETWORK_SLEEP:
 -              if (set_chip == true)
 +              if (set_chip)
                        ath5k_hw_reg_write(ah,
                                AR5K_SLEEP_CTL_SLE | sleep_duration,
                                AR5K_SLEEP_CTL);
                break;
  
        case AR5K_PM_FULL_SLEEP:
 -              if (set_chip == true)
 +              if (set_chip)
                        ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP,
                                AR5K_SLEEP_CTL);
  
                break;
  
        case AR5K_PM_AWAKE:
 -              if (set_chip == false)
 +              if (!set_chip)
                        goto commit;
  
                ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_WAKE,
@@@ -1446,7 -1389,7 +1448,7 @@@ int ath5k_hw_update_tx_triglevel(struc
        trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG),
                        AR5K_TXCFG_TXFULL);
  
 -      if (increase == false) {
 +      if (!increase) {
                if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES)
                        goto done;
        } else
@@@ -1649,10 -1592,9 +1651,10 @@@ static int ath5k_hw_eeprom_read(struct 
  /*
   * Write to eeprom - currently disabled, use at your own risk
   */
 +#if 0
  static int ath5k_hw_eeprom_write(struct ath5k_hw *ah, u32 offset, u16 data)
  {
 -#if 0
 +
        u32 status, timeout;
  
        ATH5K_TRACE(ah->ah_sc);
                }
                udelay(15);
        }
 -#endif
 +
        ATH5K_ERR(ah->ah_sc, "EEPROM Write is disabled!");
        return -EIO;
  }
 +#endif
  
  /*
   * Translate binary channel representation in EEPROM to frequency
@@@ -2104,6 -2045,50 +2106,6 @@@ static int ath5k_eeprom_read_mac(struc
  }
  
  /*
 - * Read/Write regulatory domain
 - */
 -static bool ath5k_eeprom_regulation_domain(struct ath5k_hw *ah, bool write,
 -      enum ath5k_regdom *regdomain)
 -{
 -      u16 ee_regdomain;
 -
 -      /* Read current value */
 -      if (write != true) {
 -              ee_regdomain = ah->ah_capabilities.cap_eeprom.ee_regdomain;
 -              *regdomain = ath5k_regdom_to_ieee(ee_regdomain);
 -              return true;
 -      }
 -
 -      ee_regdomain = ath5k_regdom_from_ieee(*regdomain);
 -
 -      /* Try to write a new value */
 -      if (ah->ah_capabilities.cap_eeprom.ee_protect &
 -                      AR5K_EEPROM_PROTECT_WR_128_191)
 -              return false;
 -      if (ath5k_hw_eeprom_write(ah, AR5K_EEPROM_REG_DOMAIN, ee_regdomain)!=0)
 -              return false;
 -
 -      ah->ah_capabilities.cap_eeprom.ee_regdomain = ee_regdomain;
 -
 -      return true;
 -}
 -
 -/*
 - * Use the above to write a new regulatory domain
 - */
 -int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain)
 -{
 -      enum ath5k_regdom ieee_regdomain;
 -
 -      ieee_regdomain = ath5k_regdom_to_ieee(regdomain);
 -
 -      if (ath5k_eeprom_regulation_domain(ah, true, &ieee_regdomain) == true)
 -              return 0;
 -
 -      return -EIO;
 -}
 -
 -/*
   * Fill the capabilities struct
   */
  static int ath5k_hw_get_capabilities(struct ath5k_hw *ah)
                ah->ah_capabilities.cap_range.range_2ghz_max = 0;
  
                /* Set supported modes */
 -              __set_bit(MODE_IEEE80211A, ah->ah_capabilities.cap_mode);
 -              __set_bit(MODE_ATHEROS_TURBO, ah->ah_capabilities.cap_mode);
 +              __set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode);
 +              __set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode);
        } else {
                /*
                 * XXX The tranceiver supports frequencies from 4920 to 6100GHz
                        ah->ah_capabilities.cap_range.range_5ghz_max = 6100;
  
                        /* Set supported modes */
 -                      __set_bit(MODE_IEEE80211A,
 +                      __set_bit(AR5K_MODE_11A,
                                        ah->ah_capabilities.cap_mode);
 -                      __set_bit(MODE_ATHEROS_TURBO,
 +                      __set_bit(AR5K_MODE_11A_TURBO,
                                        ah->ah_capabilities.cap_mode);
                        if (ah->ah_version == AR5K_AR5212)
 -                              __set_bit(MODE_ATHEROS_TURBOG,
 +                              __set_bit(AR5K_MODE_11G_TURBO,
                                                ah->ah_capabilities.cap_mode);
                }
  
                        ah->ah_capabilities.cap_range.range_2ghz_max = 2732;
  
                        if (AR5K_EEPROM_HDR_11B(ee_header))
 -                              __set_bit(MODE_IEEE80211B,
 +                              __set_bit(AR5K_MODE_11B,
                                                ah->ah_capabilities.cap_mode);
  
                        if (AR5K_EEPROM_HDR_11G(ee_header))
 -                              __set_bit(MODE_IEEE80211G,
 +                              __set_bit(AR5K_MODE_11G,
                                                ah->ah_capabilities.cap_mode);
                }
        }
@@@ -2294,8 -2279,8 +2296,8 @@@ void ath5k_hw_set_associd(struct ath5k_
         * Set simple BSSID mask on 5212
         */
        if (ah->ah_version == AR5K_AR5212) {
 -              ath5k_hw_reg_write(ah, 0xfffffff, AR5K_BSS_IDM0);
 -              ath5k_hw_reg_write(ah, 0xfffffff, AR5K_BSS_IDM1);
 +              ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM0);
 +              ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM1);
        }
  
        /*
@@@ -2440,8 -2425,6 +2442,8 @@@ void ath5k_hw_start_rx_pcu(struct ath5k
  {
        ATH5K_TRACE(ah->ah_sc);
        AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
 +
 +      /* TODO: ANI Support */
  }
  
  /*
@@@ -2451,8 -2434,6 +2453,8 @@@ void ath5k_hw_stop_pcu_recv(struct ath5
  {
        ATH5K_TRACE(ah->ah_sc);
        AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
 +
 +      /* TODO: ANI Support */
  }
  
  /*
@@@ -3205,19 -3186,19 +3207,19 @@@ int ath5k_hw_reset_tx_queue(struct ath5
                        return 0;
  
                /* Set Slot time */
 -              ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
 +              ath5k_hw_reg_write(ah, ah->ah_turbo ?
                        AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME,
                        AR5K_SLOT_TIME);
                /* Set ACK_CTS timeout */
 -              ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
 +              ath5k_hw_reg_write(ah, ah->ah_turbo ?
                        AR5K_INIT_ACK_CTS_TIMEOUT_TURBO :
                        AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME);
                /* Set Transmit Latency */
 -              ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
 +              ath5k_hw_reg_write(ah, ah->ah_turbo ?
                        AR5K_INIT_TRANSMIT_LATENCY_TURBO :
                        AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210);
                /* Set IFS0 */
 -              if (ah->ah_turbo == true)
 +              if (ah->ah_turbo)
                         ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO +
                                (ah->ah_aifs + tq->tqi_aifs) *
                                AR5K_INIT_SLOT_TIME_TURBO) <<
                                AR5K_INIT_SIFS, AR5K_IFS0);
  
                /* Set IFS1 */
 -              ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
 +              ath5k_hw_reg_write(ah, ah->ah_turbo ?
                        AR5K_INIT_PROTO_TIME_CNTRL_TURBO :
                        AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1);
                /* Set PHY register 0x9844 (??) */
 -              ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
 +              ath5k_hw_reg_write(ah, ah->ah_turbo ?
                        (ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x38 :
                        (ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x1C,
                        AR5K_PHY(17));
                /* Set Frame Control Register */
 -              ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
 +              ath5k_hw_reg_write(ah, ah->ah_turbo ?
                        (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE |
                        AR5K_PHY_TURBO_SHORT | 0x2020) :
                        (AR5K_PHY_FRAME_CTL_INI | 0x1020),
        /*
         * Calculate and set retry limits
         */
 -      if (ah->ah_software_retry == true) {
 +      if (ah->ah_software_retry) {
                /* XXX Need to test this */
                retry_lg = ah->ah_limit_tx_retries;
                retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ?
@@@ -3526,10 -3507,10 +3528,10 @@@ ath5k_hw_setup_2word_tx_desc(struct ath
        unsigned int rtscts_rate, unsigned int rtscts_duration)
  {
        u32 frame_type;
 -      struct ath5k_hw_2w_tx_desc *tx_desc;
 +      struct ath5k_hw_2w_tx_ctl *tx_ctl;
        unsigned int frame_len;
  
 -      tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0;
 +      tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
  
        /*
         * Validate input
                return -EINVAL;
        }
  
 -      /* Clear status descriptor */
 -      memset(desc->ds_hw, 0, sizeof(struct ath5k_hw_tx_status));
 -
 -      /* Initialize control descriptor */
 -      tx_desc->tx_control_0 = 0;
 -      tx_desc->tx_control_1 = 0;
 +      /* Clear descriptor */
 +      memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc));
  
        /* Setup control descriptor */
  
        if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
                return -EINVAL;
  
 -      tx_desc->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
 +      tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
  
        /* Verify and set buffer length */
  
        if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
                return -EINVAL;
  
 -      tx_desc->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
 +      tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
  
        /*
         * Verify and set header length
        if (ah->ah_version == AR5K_AR5210) {
                if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN)
                        return -EINVAL;
 -              tx_desc->tx_control_0 |=
 +              tx_ctl->tx_control_0 |=
                        AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN);
        }
  
                        frame_type = type /*<< 2 ?*/;
                }
  
 -              tx_desc->tx_control_0 |=
 +              tx_ctl->tx_control_0 |=
                        AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) |
                        AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
        } else {
 -              tx_desc->tx_control_0 |=
 +              tx_ctl->tx_control_0 |=
                        AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
                        AR5K_REG_SM(antenna_mode, AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
 -              tx_desc->tx_control_1 |=
 +              tx_ctl->tx_control_1 |=
                        AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE);
        }
  #define _TX_FLAGS(_c, _flag)                                          \
        if (flags & AR5K_TXDESC_##_flag)                                \
 -              tx_desc->tx_control_##_c |=                             \
 +              tx_ctl->tx_control_##_c |=                              \
                        AR5K_2W_TX_DESC_CTL##_c##_##_flag
  
        _TX_FLAGS(0, CLRDMASK);
         * WEP crap
         */
        if (key_index != AR5K_TXKEYIX_INVALID) {
 -              tx_desc->tx_control_0 |=
 +              tx_ctl->tx_control_0 |=
                        AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
 -              tx_desc->tx_control_1 |=
 +              tx_ctl->tx_control_1 |=
                        AR5K_REG_SM(key_index,
                        AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
        }
         */
        if ((ah->ah_version == AR5K_AR5210) &&
                        (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
 -              tx_desc->tx_control_1 |= rtscts_duration &
 +              tx_ctl->tx_control_1 |= rtscts_duration &
                                AR5K_2W_TX_DESC_CTL1_RTS_DURATION;
  
        return 0;
@@@ -3652,11 -3637,13 +3654,11 @@@ static int ath5k_hw_setup_4word_tx_desc
        unsigned int antenna_mode, unsigned int flags, unsigned int rtscts_rate,
        unsigned int rtscts_duration)
  {
 -      struct ath5k_hw_4w_tx_desc *tx_desc;
 -      struct ath5k_hw_tx_status *tx_status;
 +      struct ath5k_hw_4w_tx_ctl *tx_ctl;
        unsigned int frame_len;
  
        ATH5K_TRACE(ah->ah_sc);
 -      tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
 -      tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2];
 +      tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
  
        /*
         * Validate input
                return -EINVAL;
        }
  
 -      /* Clear status descriptor */
 -      memset(tx_status, 0, sizeof(struct ath5k_hw_tx_status));
 -
 -      /* Initialize control descriptor */
 -      tx_desc->tx_control_0 = 0;
 -      tx_desc->tx_control_1 = 0;
 -      tx_desc->tx_control_2 = 0;
 -      tx_desc->tx_control_3 = 0;
 +      /* Clear descriptor */
 +      memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
  
        /* Setup control descriptor */
  
        if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
                return -EINVAL;
  
 -      tx_desc->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
 +      tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
  
        /* Verify and set buffer length */
  
        if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
                return -EINVAL;
  
 -      tx_desc->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
 +      tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
  
 -      tx_desc->tx_control_0 |=
 +      tx_ctl->tx_control_0 |=
                AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
                AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
 -      tx_desc->tx_control_1 |= AR5K_REG_SM(type,
 +      tx_ctl->tx_control_1 |= AR5K_REG_SM(type,
                                        AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
 -      tx_desc->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
 +      tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
                                        AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
 -      tx_desc->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
 +      tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
  
  #define _TX_FLAGS(_c, _flag)                  \
        if (flags & AR5K_TXDESC_##_flag)        \
 -              tx_desc->tx_control_##_c |=     \
 +              tx_ctl->tx_control_##_c |=      \
                        AR5K_4W_TX_DESC_CTL##_c##_##_flag
  
        _TX_FLAGS(0, CLRDMASK);
         * WEP crap
         */
        if (key_index != AR5K_TXKEYIX_INVALID) {
 -              tx_desc->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
 -              tx_desc->tx_control_1 |= AR5K_REG_SM(key_index,
 +              tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
 +              tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index,
                                AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
        }
  
                if ((flags & AR5K_TXDESC_RTSENA) &&
                                (flags & AR5K_TXDESC_CTSENA))
                        return -EINVAL;
 -              tx_desc->tx_control_2 |= rtscts_duration &
 +              tx_ctl->tx_control_2 |= rtscts_duration &
                                AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
 -              tx_desc->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
 +              tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
                                AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
        }
  
@@@ -3757,7 -3750,7 +3759,7 @@@ ath5k_hw_setup_xr_tx_desc(struct ath5k_
        unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2,
        unsigned int tx_rate3, u_int tx_tries3)
  {
 -      struct ath5k_hw_4w_tx_desc *tx_desc;
 +      struct ath5k_hw_4w_tx_ctl *tx_ctl;
  
        /*
         * Rates can be 0 as long as the retry count is 0 too.
        }
  
        if (ah->ah_version == AR5K_AR5212) {
 -              tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
 +              tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
  
  #define _XTX_TRIES(_n)                                                        \
        if (tx_tries##_n) {                                             \
 -              tx_desc->tx_control_2 |=                                \
 +              tx_ctl->tx_control_2 |=                         \
                    AR5K_REG_SM(tx_tries##_n,                           \
                    AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n);               \
 -              tx_desc->tx_control_3 |=                                \
 +              tx_ctl->tx_control_3 |=                         \
                    AR5K_REG_SM(tx_rate##_n,                            \
                    AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n);                \
        }
   * Proccess the tx status descriptor on 5210/5211
   */
  static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
 -              struct ath5k_desc *desc)
 +              struct ath5k_desc *desc, struct ath5k_tx_status *ts)
  {
 +      struct ath5k_hw_2w_tx_ctl *tx_ctl;
        struct ath5k_hw_tx_status *tx_status;
 -      struct ath5k_hw_2w_tx_desc *tx_desc;
  
 -      tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0;
 -      tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[0];
 +      ATH5K_TRACE(ah->ah_sc);
 +
 +      tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
 +      tx_status = &desc->ud.ds_tx5210.tx_stat;
  
        /* No frame has been send or error */
        if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
        /*
         * Get descriptor status
         */
 -      desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
 +      ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
                AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
 -      desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
 +      ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
                AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
 -      desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
 +      ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
                AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
 -      /*TODO: desc->ds_us.tx.ts_virtcol + test*/
 -      desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
 +      /*TODO: ts->ts_virtcol + test*/
 +      ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
                AR5K_DESC_TX_STATUS1_SEQ_NUM);
 -      desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
 +      ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
                AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
 -      desc->ds_us.tx.ts_antenna = 1;
 -      desc->ds_us.tx.ts_status = 0;
 -      desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_0,
 +      ts->ts_antenna = 1;
 +      ts->ts_status = 0;
 +      ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_0,
                AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
  
        if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){
                if (tx_status->tx_status_0 &
                                AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
 -                      desc->ds_us.tx.ts_status |= AR5K_TXERR_XRETRY;
 +                      ts->ts_status |= AR5K_TXERR_XRETRY;
  
                if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
 -                      desc->ds_us.tx.ts_status |= AR5K_TXERR_FIFO;
 +                      ts->ts_status |= AR5K_TXERR_FIFO;
  
                if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
 -                      desc->ds_us.tx.ts_status |= AR5K_TXERR_FILT;
 +                      ts->ts_status |= AR5K_TXERR_FILT;
        }
  
        return 0;
   * Proccess a tx descriptor on 5212
   */
  static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
 -              struct ath5k_desc *desc)
 +              struct ath5k_desc *desc, struct ath5k_tx_status *ts)
  {
 +      struct ath5k_hw_4w_tx_ctl *tx_ctl;
        struct ath5k_hw_tx_status *tx_status;
 -      struct ath5k_hw_4w_tx_desc *tx_desc;
  
        ATH5K_TRACE(ah->ah_sc);
 -      tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
 -      tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2];
 +
 +      tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
 +      tx_status = &desc->ud.ds_tx5212.tx_stat;
  
        /* No frame has been send or error */
        if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
        /*
         * Get descriptor status
         */
 -      desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
 +      ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
                AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
 -      desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
 +      ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
                AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
 -      desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
 +      ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
                AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
 -      desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
 +      ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
                AR5K_DESC_TX_STATUS1_SEQ_NUM);
 -      desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
 +      ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
                AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
 -      desc->ds_us.tx.ts_antenna = (tx_status->tx_status_1 &
 +      ts->ts_antenna = (tx_status->tx_status_1 &
                AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
 -      desc->ds_us.tx.ts_status = 0;
 +      ts->ts_status = 0;
  
        switch (AR5K_REG_MS(tx_status->tx_status_1,
                        AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) {
        case 0:
 -              desc->ds_us.tx.ts_rate = tx_desc->tx_control_3 &
 +              ts->ts_rate = tx_ctl->tx_control_3 &
                        AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
                break;
        case 1:
 -              desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
 +              ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
                        AR5K_4W_TX_DESC_CTL3_XMIT_RATE1);
 -              desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
 +              ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
                        AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
                break;
        case 2:
 -              desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
 +              ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
                        AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
 -              desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
 +              ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
                        AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
                break;
        case 3:
 -              desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
 +              ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
                        AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
 -              desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
 +              ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
                        AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3);
                break;
        }
        if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){
                if (tx_status->tx_status_0 &
                                AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
 -                      desc->ds_us.tx.ts_status |= AR5K_TXERR_XRETRY;
 +                      ts->ts_status |= AR5K_TXERR_XRETRY;
  
                if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
 -                      desc->ds_us.tx.ts_status |= AR5K_TXERR_FIFO;
 +                      ts->ts_status |= AR5K_TXERR_FIFO;
  
                if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
 -                      desc->ds_us.tx.ts_status |= AR5K_TXERR_FILT;
 +                      ts->ts_status |= AR5K_TXERR_FILT;
        }
  
        return 0;
  int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
                        u32 size, unsigned int flags)
  {
 -      struct ath5k_rx_desc *rx_desc;
 +      struct ath5k_hw_rx_ctl *rx_ctl;
  
        ATH5K_TRACE(ah->ah_sc);
 -      rx_desc = (struct ath5k_rx_desc *)&desc->ds_ctl0;
 +      rx_ctl = &desc->ud.ds_rx.rx_ctl;
  
        /*
 -       *Clear ds_hw
 +       * Clear the descriptor
         * If we don't clean the status descriptor,
         * while scanning we get too many results,
         * most of them virtual, after some secs
         * of scanning system hangs. M.F.
        */
 -      memset(desc->ds_hw, 0, sizeof(desc->ds_hw));
 -
 -      /*Initialize rx descriptor*/
 -      rx_desc->rx_control_0 = 0;
 -      rx_desc->rx_control_1 = 0;
 +      memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc));
  
        /* Setup descriptor */
 -      rx_desc->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
 -      if (unlikely(rx_desc->rx_control_1 != size))
 +      rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
 +      if (unlikely(rx_ctl->rx_control_1 != size))
                return -EINVAL;
  
        if (flags & AR5K_RXDESC_INTREQ)
 -              rx_desc->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
 +              rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
  
        return 0;
  }
  /*
   * Proccess the rx status descriptor on 5210/5211
   */
 -static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *ah,
 -              struct ath5k_desc *desc)
 +static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
 +              struct ath5k_desc *desc, struct ath5k_rx_status *rs)
  {
 -      struct ath5k_hw_old_rx_status *rx_status;
 +      struct ath5k_hw_rx_status *rx_status;
  
 -      rx_status = (struct ath5k_hw_old_rx_status *)&desc->ds_hw[0];
 +      rx_status = &desc->ud.ds_rx.u.rx_stat;
  
        /* No frame received / not ready */
 -      if (unlikely((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_DONE)
 +      if (unlikely((rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_DONE)
                                == 0))
                return -EINPROGRESS;
  
        /*
         * Frame receive status
         */
 -      desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 &
 -              AR5K_OLD_RX_DESC_STATUS0_DATA_LEN;
 -      desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
 -              AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL);
 -      desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
 -              AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE);
 -      desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 &
 -              AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA;
 -      desc->ds_us.rx.rs_more = rx_status->rx_status_0 &
 -              AR5K_OLD_RX_DESC_STATUS0_MORE;
 -      desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
 -              AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
 -      desc->ds_us.rx.rs_status = 0;
 +      rs->rs_datalen = rx_status->rx_status_0 &
 +              AR5K_5210_RX_DESC_STATUS0_DATA_LEN;
 +      rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
 +              AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
 +      rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
 +              AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
 +      rs->rs_antenna = rx_status->rx_status_0 &
 +              AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA;
 +      rs->rs_more = rx_status->rx_status_0 &
 +              AR5K_5210_RX_DESC_STATUS0_MORE;
 +      /* TODO: this timestamp is 13 bit, later on we assume 15 bit */
 +      rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
 +              AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
 +      rs->rs_status = 0;
  
        /*
         * Key table status
         */
 -      if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID)
 -              desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
 -                      AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX);
 +      if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID)
 +              rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
 +                      AR5K_5210_RX_DESC_STATUS1_KEY_INDEX);
        else
 -              desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID;
 +              rs->rs_keyix = AR5K_RXKEYIX_INVALID;
  
        /*
         * Receive/descriptor errors
         */
 -      if ((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK)
 -                      == 0) {
 -              if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR)
 -                      desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC;
 +      if ((rx_status->rx_status_1 &
 +                      AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
 +              if (rx_status->rx_status_1 &
 +                              AR5K_5210_RX_DESC_STATUS1_CRC_ERROR)
 +                      rs->rs_status |= AR5K_RXERR_CRC;
  
                if (rx_status->rx_status_1 &
 -                              AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN)
 -                      desc->ds_us.rx.rs_status |= AR5K_RXERR_FIFO;
 +                              AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN)
 +                      rs->rs_status |= AR5K_RXERR_FIFO;
  
                if (rx_status->rx_status_1 &
 -                              AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR) {
 -                      desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY;
 -                      desc->ds_us.rx.rs_phyerr =
 -                              AR5K_REG_MS(rx_status->rx_status_1,
 -                                      AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR);
 +                              AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
 +                      rs->rs_status |= AR5K_RXERR_PHY;
 +                      rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1,
 +                                         AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
                }
  
                if (rx_status->rx_status_1 &
 -                              AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
 -                      desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT;
 +                              AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
 +                      rs->rs_status |= AR5K_RXERR_DECRYPT;
        }
  
        return 0;
  /*
   * Proccess the rx status descriptor on 5212
   */
 -static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *ah,
 -              struct ath5k_desc *desc)
 +static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
 +              struct ath5k_desc *desc, struct ath5k_rx_status *rs)
  {
 -      struct ath5k_hw_new_rx_status *rx_status;
 +      struct ath5k_hw_rx_status *rx_status;
        struct ath5k_hw_rx_error *rx_err;
  
        ATH5K_TRACE(ah->ah_sc);
 -      rx_status = (struct ath5k_hw_new_rx_status *)&desc->ds_hw[0];
 +      rx_status = &desc->ud.ds_rx.u.rx_stat;
  
        /* Overlay on error */
 -      rx_err = (struct ath5k_hw_rx_error *)&desc->ds_hw[0];
 +      rx_err = &desc->ud.ds_rx.u.rx_err;
  
        /* No frame received / not ready */
 -      if (unlikely((rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_DONE)
 +      if (unlikely((rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_DONE)
                                == 0))
                return -EINPROGRESS;
  
        /*
         * Frame receive status
         */
 -      desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 &
 -              AR5K_NEW_RX_DESC_STATUS0_DATA_LEN;
 -      desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
 -              AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL);
 -      desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
 -              AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE);
 -      desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 &
 -              AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA;
 -      desc->ds_us.rx.rs_more = rx_status->rx_status_0 &
 -              AR5K_NEW_RX_DESC_STATUS0_MORE;
 -      desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
 -              AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
 -      desc->ds_us.rx.rs_status = 0;
 +      rs->rs_datalen = rx_status->rx_status_0 &
 +              AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
 +      rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
 +              AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
 +      rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
 +              AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
 +      rs->rs_antenna = rx_status->rx_status_0 &
 +              AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA;
 +      rs->rs_more = rx_status->rx_status_0 &
 +              AR5K_5212_RX_DESC_STATUS0_MORE;
 +      rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
 +              AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
 +      rs->rs_status = 0;
  
        /*
         * Key table status
         */
 -      if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID)
 -              desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
 -                              AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX);
 +      if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
 +              rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
 +                              AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);
        else
 -              desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID;
 +              rs->rs_keyix = AR5K_RXKEYIX_INVALID;
  
        /*
         * Receive/descriptor errors
         */
        if ((rx_status->rx_status_1 &
 -                      AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
 -              if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR)
 -                      desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC;
 +                      AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
 +              if (rx_status->rx_status_1 &
 +                              AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
 +                      rs->rs_status |= AR5K_RXERR_CRC;
  
                if (rx_status->rx_status_1 &
 -                              AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR) {
 -                      desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY;
 -                      desc->ds_us.rx.rs_phyerr =
 -                              AR5K_REG_MS(rx_err->rx_error_1,
 -                                      AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
 +                              AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
 +                      rs->rs_status |= AR5K_RXERR_PHY;
 +                      rs->rs_phyerr = AR5K_REG_MS(rx_err->rx_error_1,
 +                                         AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
                }
  
                if (rx_status->rx_status_1 &
 -                              AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
 -                      desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT;
 +                              AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
 +                      rs->rs_status |= AR5K_RXERR_DECRYPT;
  
 -              if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR)
 -                      desc->ds_us.rx.rs_status |= AR5K_RXERR_MIC;
 +              if (rx_status->rx_status_1 &
 +                              AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
 +                      rs->rs_status |= AR5K_RXERR_MIC;
        }
  
        return 0;
@@@ -4258,6 -4250,35 +4260,6 @@@ void ath5k_hw_set_gpio_intr(struct ath5
  }
  
  
 -/*********************************\
 - Regulatory Domain/Channels Setup
 -\*********************************/
 -
 -u16 ath5k_get_regdomain(struct ath5k_hw *ah)
 -{
 -      u16 regdomain;
 -      enum ath5k_regdom ieee_regdomain;
 -#ifdef COUNTRYCODE
 -      u16 code;
 -#endif
 -
 -      ath5k_eeprom_regulation_domain(ah, false, &ieee_regdomain);
 -      ah->ah_capabilities.cap_regdomain.reg_hw = ieee_regdomain;
 -
 -#ifdef COUNTRYCODE
 -      /*
 -       * Get the regulation domain by country code. This will ignore
 -       * the settings found in the EEPROM.
 -       */
 -      code = ieee80211_name2countrycode(COUNTRYCODE);
 -      ieee_regdomain = ieee80211_countrycode2regdomain(code);
 -#endif
 -
 -      regdomain = ath5k_regdom_from_ieee(ieee_regdomain);
 -      ah->ah_capabilities.cap_regdomain.reg_current = regdomain;
 -
 -      return regdomain;
 -}
  
  
  /****************\
@@@ -74,7 -74,7 +74,7 @@@ void lbs_mac_event_disconnected(struct 
                lbs_deb_cmd("disconnected, so exit PS mode\n");
                lbs_ps_wakeup(priv, 0);
        }
 -      lbs_deb_leave(LBS_DEB_CMD);
 +      lbs_deb_leave(LBS_DEB_ASSOC);
  }
  
  /**
@@@ -204,6 -204,61 +204,6 @@@ static int lbs_ret_802_11_snmp_mib(stru
        return 0;
  }
  
 -static int lbs_ret_802_11_key_material(struct lbs_private *priv,
 -                                      struct cmd_ds_command *resp)
 -{
 -      struct cmd_ds_802_11_key_material *pkeymaterial =
 -          &resp->params.keymaterial;
 -      u16 action = le16_to_cpu(pkeymaterial->action);
 -
 -      lbs_deb_enter(LBS_DEB_CMD);
 -
 -      /* Copy the returned key to driver private data */
 -      if (action == CMD_ACT_GET) {
 -              u8 * buf_ptr = (u8 *) &pkeymaterial->keyParamSet;
 -              u8 * resp_end = (u8 *) (resp + le16_to_cpu(resp->size));
 -
 -              while (buf_ptr < resp_end) {
 -                      struct MrvlIEtype_keyParamSet * pkeyparamset =
 -                          (struct MrvlIEtype_keyParamSet *) buf_ptr;
 -                      struct enc_key * pkey;
 -                      u16 param_set_len = le16_to_cpu(pkeyparamset->length);
 -                      u16 key_len = le16_to_cpu(pkeyparamset->keylen);
 -                      u16 key_flags = le16_to_cpu(pkeyparamset->keyinfo);
 -                      u16 key_type = le16_to_cpu(pkeyparamset->keytypeid);
 -                      u8 * end;
 -
 -                      end = (u8 *) pkeyparamset + sizeof (pkeyparamset->type)
 -                                                + sizeof (pkeyparamset->length)
 -                                                + param_set_len;
 -                      /* Make sure we don't access past the end of the IEs */
 -                      if (end > resp_end)
 -                              break;
 -
 -                      if (key_flags & KEY_INFO_WPA_UNICAST)
 -                              pkey = &priv->wpa_unicast_key;
 -                      else if (key_flags & KEY_INFO_WPA_MCAST)
 -                              pkey = &priv->wpa_mcast_key;
 -                      else
 -                              break;
 -
 -                      /* Copy returned key into driver */
 -                      memset(pkey, 0, sizeof(struct enc_key));
 -                      if (key_len > sizeof(pkey->key))
 -                              break;
 -                      pkey->type = key_type;
 -                      pkey->flags = key_flags;
 -                      pkey->len = key_len;
 -                      memcpy(pkey->key, pkeyparamset->key, pkey->len);
 -
 -                      buf_ptr = end + 1;
 -              }
 -      }
 -
 -      lbs_deb_enter(LBS_DEB_CMD);
 -      return 0;
 -}
 -
  static int lbs_ret_802_11_mac_address(struct lbs_private *priv,
                                       struct cmd_ds_command *resp)
  {
@@@ -352,6 -407,10 +352,6 @@@ static inline int handle_cmd_response(s
                ret = lbs_ret_reg_access(priv, respcmd, resp);
                break;
  
 -      case CMD_RET(CMD_802_11_SCAN):
 -              ret = lbs_ret_80211_scan(priv, resp);
 -              break;
 -
        case CMD_RET(CMD_802_11_GET_LOG):
                ret = lbs_ret_get_log(priv, resp);
                break;
                ret = lbs_ret_80211_ad_hoc_stop(priv, resp);
                break;
  
 -      case CMD_RET(CMD_802_11_KEY_MATERIAL):
 -              ret = lbs_ret_802_11_key_material(priv, resp);
 -              break;
 -
        case CMD_RET(CMD_802_11_EEPROM_ACCESS):
                ret = lbs_ret_802_11_eeprom_access(priv, resp);
                break;
@@@ -503,9 -566,9 +503,9 @@@ int lbs_process_rx_command(struct lbs_p
        respcmd = le16_to_cpu(resp->command);
        result = le16_to_cpu(resp->result);
  
 -      lbs_deb_host("CMD_RESP: response 0x%04x, seq %d, size %d, jiffies %lu\n",
 +      lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d, jiffies %lu\n",
                     respcmd, le16_to_cpu(resp->seqnum), priv->upld_len, jiffies);
 -      lbs_deb_hex(LBS_DEB_HOST, "CMD_RESP", (void *) resp, priv->upld_len);
 +      lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, priv->upld_len);
  
        if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) {
                lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n",
                goto done;
        }
        if (respcmd != CMD_RET(curcmd) &&
-           respcmd != CMD_802_11_ASSOCIATE && curcmd != CMD_RET_802_11_ASSOCIATE) {
+           respcmd != CMD_RET_802_11_ASSOCIATE && curcmd != CMD_802_11_ASSOCIATE) {
                lbs_pr_info("Invalid CMD_RESP %x to command %x!\n", respcmd, curcmd);
                spin_unlock_irqrestore(&priv->driver_lock, flags);
                ret = -1;
@@@ -1,5 -1,5 +1,5 @@@
  /*
 -      Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
 +      Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
  
        This program is free software; you can redistribute it and/or modify
  #define RT2X00_H
  
  #include <linux/bitops.h>
 -#include <linux/prefetch.h>
  #include <linux/skbuff.h>
  #include <linux/workqueue.h>
  #include <linux/firmware.h>
 +#include <linux/leds.h>
  #include <linux/mutex.h>
  #include <linux/etherdevice.h>
  
  #include <net/mac80211.h>
  
  #include "rt2x00debug.h"
 +#include "rt2x00leds.h"
  #include "rt2x00reg.h"
 -#include "rt2x00ring.h"
 +#include "rt2x00queue.h"
  
  /*
   * Module information.
   */
 -#define DRV_VERSION   "2.0.14"
 +#define DRV_VERSION   "2.1.4"
  #define DRV_PROJECT   "http://rt2x00.serialmonkey.com"
  
  /*
        DEBUG_PRINTK(__dev, KERN_DEBUG, "EEPROM recovery", __msg, ##__args)
  
  /*
 - * Ring sizes.
 - * Ralink PCI devices demand the Frame size to be a multiple of 128 bytes.
 - * DATA_FRAME_SIZE is used for TX, RX, ATIM and PRIO rings.
 - * MGMT_FRAME_SIZE is used for the BEACON ring.
 - */
 -#define DATA_FRAME_SIZE       2432
 -#define MGMT_FRAME_SIZE       256
 -
 -/*
 - * Number of entries in a packet ring.
 - * PCI devices only need 1 Beacon entry,
 - * but USB devices require a second because they
 - * have to send a Guardian byte first.
 - */
 -#define RX_ENTRIES    12
 -#define TX_ENTRIES    12
 -#define ATIM_ENTRIES  1
 -#define BEACON_ENTRIES        2
 -
 -/*
   * Standard timing and size defines.
   * These values should follow the ieee80211 specifications.
   */
@@@ -345,22 -364,20 +345,22 @@@ static inline int rt2x00_update_ant_rss
  
  /*
   * Interface structure
 - * Configuration details about the current interface.
 + * Per interface configuration details, this structure
 + * is allocated as the private data for ieee80211_vif.
   */
 -struct interface {
 +struct rt2x00_intf {
        /*
 -       * Interface identification. The value is assigned
 -       * to us by the 80211 stack, and is used to request
 -       * new beacons.
 +       * All fields within the rt2x00_intf structure
 +       * must be protected with a spinlock.
         */
 -      struct ieee80211_vif *id;
 +      spinlock_t lock;
  
        /*
 -       * Current working type (IEEE80211_IF_TYPE_*).
 +       * BSS configuration. Copied from the structure
 +       * passed to us through the bss_info_changed()
 +       * callback funtion.
         */
 -      int type;
 +      struct ieee80211_bss_conf conf;
  
        /*
         * MAC of the device.
         * BBSID of the AP to associate with.
         */
        u8 bssid[ETH_ALEN];
 -};
  
 -static inline int is_interface_present(struct interface *intf)
 -{
 -      return !!intf->id;
 -}
 +      /*
 +       * Entry in the beacon queue which belongs to
 +       * this interface. Each interface has its own
 +       * dedicated beacon entry.
 +       */
 +      struct queue_entry *beacon;
 +
 +      /*
 +       * Actions that needed rescheduling.
 +       */
 +      unsigned int delayed_flags;
 +#define DELAYED_UPDATE_BEACON         0x00000001
 +#define DELAYED_CONFIG_ERP            0x00000002
 +};
  
 -static inline int is_interface_type(struct interface *intf, int type)
 +static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif)
  {
 -      return intf->type == type;
 +      return (struct rt2x00_intf *)vif->drv_priv;
  }
  
 -/*
 +/**
 + * struct hw_mode_spec: Hardware specifications structure
 + *
   * Details about the supported modes, rates and channels
   * of a particular chipset. This is used by rt2x00lib
   * to build the ieee80211_hw_mode array for mac80211.
 + *
 + * @supported_bands: Bitmask contained the supported bands (2.4GHz, 5.2GHz).
 + * @supported_rates: Rate types which are supported (CCK, OFDM).
 + * @num_channels: Number of supported channels. This is used as array size
 + *    for @tx_power_a, @tx_power_bg and @channels.
 + * channels: Device/chipset specific channel values (See &struct rf_channel).
 + * @tx_power_a: TX power values for all 5.2GHz channels (may be NULL).
 + * @tx_power_bg: TX power values for all 2.4GHz channels (may be NULL).
 + * @tx_power_default: Default TX power value to use when either
 + *    @tx_power_a or @tx_power_bg is missing.
   */
  struct hw_mode_spec {
 -      /*
 -       * Number of modes, rates and channels.
 -       */
 -      int num_modes;
 -      int num_rates;
 -      int num_channels;
 +      unsigned int supported_bands;
 +#define SUPPORT_BAND_2GHZ     0x00000001
 +#define SUPPORT_BAND_5GHZ     0x00000002
 +
 +      unsigned int supported_rates;
 +#define SUPPORT_RATE_CCK      0x00000001
 +#define SUPPORT_RATE_OFDM     0x00000002
 +
 +      unsigned int num_channels;
 +      const struct rf_channel *channels;
  
 -      /*
 -       * txpower values.
 -       */
        const u8 *tx_power_a;
        const u8 *tx_power_bg;
        u8 tx_power_default;
 -
 -      /*
 -       * Device/chipset specific value.
 -       */
 -      const struct rf_channel *channels;
  };
  
  /*
@@@ -439,10 -439,10 +439,10 @@@ struct rt2x00lib_conf 
  
        struct antenna_setup ant;
  
 -      int phymode;
 +      enum ieee80211_band band;
  
 -      int basic_rates;
 -      int slot_time;
 +      u32 basic_rates;
 +      u32 slot_time;
  
        short sifs;
        short pifs;
  };
  
  /*
 + * Configuration structure for erp settings.
 + */
 +struct rt2x00lib_erp {
 +      int short_preamble;
 +
 +      int ack_timeout;
 +      int ack_consume_time;
 +};
 +
 +/*
 + * Configuration structure wrapper around the
 + * rt2x00 interface configuration handler.
 + */
 +struct rt2x00intf_conf {
 +      /*
 +       * Interface type
 +       */
 +      enum ieee80211_if_types type;
 +
 +      /*
 +       * TSF sync value, this is dependant on the operation type.
 +       */
 +      enum tsf_sync sync;
 +
 +      /*
 +       * The MAC and BSSID addressess are simple array of bytes,
 +       * these arrays are little endian, so when sending the addressess
 +       * to the drivers, copy the it into a endian-signed variable.
 +       *
 +       * Note that all devices (except rt2500usb) have 32 bits
 +       * register word sizes. This means that whatever variable we
 +       * pass _must_ be a multiple of 32 bits. Otherwise the device
 +       * might not accept what we are sending to it.
 +       * This will also make it easier for the driver to write
 +       * the data to the device.
 +       */
 +      __le32 mac[2];
 +      __le32 bssid[2];
 +};
 +
 +/*
   * rt2x00lib callback functions.
   */
  struct rt2x00lib_ops {
         */
        int (*probe_hw) (struct rt2x00_dev *rt2x00dev);
        char *(*get_firmware_name) (struct rt2x00_dev *rt2x00dev);
 +      u16 (*get_firmware_crc) (void *data, const size_t len);
        int (*load_firmware) (struct rt2x00_dev *rt2x00dev, void *data,
                              const size_t len);
  
        void (*uninitialize) (struct rt2x00_dev *rt2x00dev);
  
        /*
 -       * Ring initialization handlers
 +       * queue initialization handlers
         */
        void (*init_rxentry) (struct rt2x00_dev *rt2x00dev,
 -                            struct data_entry *entry);
 +                            struct queue_entry *entry);
        void (*init_txentry) (struct rt2x00_dev *rt2x00dev,
 -                            struct data_entry *entry);
 +                            struct queue_entry *entry);
  
        /*
         * Radio control handlers.
                            struct link_qual *qual);
        void (*reset_tuner) (struct rt2x00_dev *rt2x00dev);
        void (*link_tuner) (struct rt2x00_dev *rt2x00dev);
 +      void (*led_brightness) (struct led_classdev *led_cdev,
 +                              enum led_brightness brightness);
  
        /*
         * TX control handlers
         */
        void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev,
                               struct sk_buff *skb,
 -                             struct txdata_entry_desc *desc,
 +                             struct txentry_desc *txdesc,
                               struct ieee80211_tx_control *control);
        int (*write_tx_data) (struct rt2x00_dev *rt2x00dev,
 -                            struct data_ring *ring, struct sk_buff *skb,
 +                            struct data_queue *queue, struct sk_buff *skb,
                              struct ieee80211_tx_control *control);
        int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev,
                                struct sk_buff *skb);
        void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev,
 -                             unsigned int queue);
 +                             const unsigned int queue);
  
        /*
         * RX control handlers
         */
 -      void (*fill_rxdone) (struct data_entry *entry,
 -                           struct rxdata_entry_desc *desc);
 +      void (*fill_rxdone) (struct queue_entry *entry,
 +                           struct rxdone_entry_desc *rxdesc);
  
        /*
         * Configuration handlers.
         */
 -      void (*config_mac_addr) (struct rt2x00_dev *rt2x00dev, __le32 *mac);
 -      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 rt2x00lib_conf *libconf);
 +      void (*config_intf) (struct rt2x00_dev *rt2x00dev,
 +                           struct rt2x00_intf *intf,
 +                           struct rt2x00intf_conf *conf,
 +                           const unsigned int flags);
 +#define CONFIG_UPDATE_TYPE            ( 1 << 1 )
 +#define CONFIG_UPDATE_MAC             ( 1 << 2 )
 +#define CONFIG_UPDATE_BSSID           ( 1 << 3 )
 +
 +      int (*config_erp) (struct rt2x00_dev *rt2x00dev,
 +                         struct rt2x00lib_erp *erp);
 +      void (*config) (struct rt2x00_dev *rt2x00dev,
 +                      struct rt2x00lib_conf *libconf,
 +                      const unsigned int flags);
  #define CONFIG_UPDATE_PHYMODE         ( 1 << 1 )
  #define CONFIG_UPDATE_CHANNEL         ( 1 << 2 )
  #define CONFIG_UPDATE_TXPOWER         ( 1 << 3 )
   */
  struct rt2x00_ops {
        const char *name;
 -      const unsigned int rxd_size;
 -      const unsigned int txd_size;
 +      const unsigned int max_sta_intf;
 +      const unsigned int max_ap_intf;
        const unsigned int eeprom_size;
        const unsigned int rf_size;
 +      const struct data_queue_desc *rx;
 +      const struct data_queue_desc *tx;
 +      const struct data_queue_desc *bcn;
 +      const struct data_queue_desc *atim;
        const struct rt2x00lib_ops *lib;
        const struct ieee80211_ops *hw;
  #ifdef CONFIG_RT2X00_LIB_DEBUGFS
@@@ -620,10 -569,8 +620,10 @@@ enum rt2x00_flags 
        /*
         * Driver features
         */
 +      DRIVER_SUPPORT_MIXED_INTERFACES,
        DRIVER_REQUIRE_FIRMWARE,
 -      DRIVER_REQUIRE_BEACON_RING,
 +      DRIVER_REQUIRE_BEACON_GUARD,
 +      DRIVER_REQUIRE_ATIM_QUEUE,
  
        /*
         * Driver configuration
        CONFIG_EXTERNAL_LNA_BG,
        CONFIG_DOUBLE_ANTENNA,
        CONFIG_DISABLE_LINK_TUNING,
 -      CONFIG_SHORT_PREAMBLE,
  };
  
  /*
@@@ -649,10 -597,8 +649,10 @@@ struct rt2x00_dev 
         * macro's should be used for correct typecasting.
         */
        void *dev;
 -#define rt2x00dev_pci(__dev)  ( (struct pci_dev*)(__dev)->dev )
 -#define rt2x00dev_usb(__dev)  ( (struct usb_interface*)(__dev)->dev )
 +#define rt2x00dev_pci(__dev)  ( (struct pci_dev *)(__dev)->dev )
 +#define rt2x00dev_usb(__dev)  ( (struct usb_interface *)(__dev)->dev )
 +#define rt2x00dev_usb_dev(__dev)\
 +      ( (struct usb_device *)interface_to_usbdev(rt2x00dev_usb(__dev)) )
  
        /*
         * Callback functions.
         * IEEE80211 control structure.
         */
        struct ieee80211_hw *hw;
 -      struct ieee80211_hw_mode *hwmodes;
 -      unsigned int curr_hwmode;
 -#define HWMODE_B      0
 -#define HWMODE_G      1
 -#define HWMODE_A      2
 +      struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
 +      enum ieee80211_band curr_band;
  
        /*
         * rfkill structure for RF state switching support.
         * This will only be compiled in when required.
         */
  #ifdef CONFIG_RT2X00_LIB_RFKILL
+ unsigned long rfkill_state;
+ #define RFKILL_STATE_ALLOCATED                1
+ #define RFKILL_STATE_REGISTERED               2
        struct rfkill *rfkill;
        struct input_polled_dev *poll_dev;
  #endif /* CONFIG_RT2X00_LIB_RFKILL */
  #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
  
        /*
 +       * LED structure for changing the LED status
 +       * by mac8011 or the kernel.
 +       */
 +#ifdef CONFIG_RT2X00_LIB_LEDS
 +      unsigned int led_flags;
 +      struct rt2x00_trigger trigger_qual;
 +      struct rt2x00_led led_radio;
 +      struct rt2x00_led led_assoc;
 +      struct rt2x00_led led_qual;
 +      u16 led_mcu_reg;
 +#endif /* CONFIG_RT2X00_LIB_LEDS */
 +
 +      /*
         * Device flags.
         * In these flags the current status and some
         * of the device capabilities are stored.
  
        /*
         * Register pointers
 -       * csr_addr: Base register address. (PCI)
 -       * csr_cache: CSR cache for usb_control_msg. (USB)
 +       * csr.base: CSR base register address. (PCI)
 +       * csr.cache: CSR cache for usb_control_msg. (USB)
         */
 -      void __iomem *csr_addr;
 -      void *csr_cache;
 +      union csr {
 +              void __iomem *base;
 +              void *cache;
 +      } csr;
  
        /*
         * Mutex to protect register accesses on USB devices.
        unsigned int packet_filter;
  
        /*
 -       * Interface configuration.
 +       * Interface details:
 +       *  - Open ap interface count.
 +       *  - Open sta interface count.
 +       *  - Association count.
         */
 -      struct interface interface;
 +      unsigned int intf_ap_count;
 +      unsigned int intf_sta_count;
 +      unsigned int intf_associated;
  
        /*
         * Link quality
        u16 tx_power;
  
        /*
 -       * LED register (for rt61pci & rt73usb).
 -       */
 -      u16 led_reg;
 -
 -      /*
 -       * Led mode (LED_MODE_*)
 -       */
 -      u8 led_mode;
 -
 -      /*
         * Rssi <-> Dbm offset
         */
        u8 rssi_offset;
        /*
         * Scheduled work.
         */
 -      struct work_struct beacon_work;
 +      struct work_struct intf_work;
        struct work_struct filter_work;
 -      struct work_struct config_work;
  
        /*
 -       * Data ring arrays for RX, TX and Beacon.
 -       * The Beacon array also contains the Atim ring
 +       * Data queue arrays for RX, TX and Beacon.
 +       * The Beacon array also contains the Atim queue
         * if that is supported by the device.
         */
 -      int data_rings;
 -      struct data_ring *rx;
 -      struct data_ring *tx;
 -      struct data_ring *bcn;
 +      int data_queues;
 +      struct data_queue *rx;
 +      struct data_queue *tx;
 +      struct data_queue *bcn;
  
        /*
         * Firmware image.
  };
  
  /*
 - * For-each loop for the ring array.
 - * All rings have been allocated as a single array,
 - * this means we can create a very simply loop macro
 - * that is capable of looping through all rings.
 - * ring_end(), txring_end() and ring_loop() are helper macro's which
 - * should not be used directly. Instead the following should be used:
 - * ring_for_each() - Loops through all rings (RX, TX, Beacon & Atim)
 - * txring_for_each() - Loops through TX data rings (TX only)
 - * txringall_for_each() - Loops through all TX rings (TX, Beacon & Atim)
 - */
 -#define ring_end(__dev) \
 -      &(__dev)->rx[(__dev)->data_rings]
 -
 -#define txring_end(__dev) \
 -      &(__dev)->tx[(__dev)->hw->queues]
 -
 -#define ring_loop(__entry, __start, __end)                    \
 -      for ((__entry) = (__start);                             \
 -           prefetch(&(__entry)[1]), (__entry) != (__end);     \
 -           (__entry) = &(__entry)[1])
 -
 -#define ring_for_each(__dev, __entry) \
 -      ring_loop(__entry, (__dev)->rx, ring_end(__dev))
 -
 -#define txring_for_each(__dev, __entry) \
 -      ring_loop(__entry, (__dev)->tx, txring_end(__dev))
 -
 -#define txringall_for_each(__dev, __entry) \
 -      ring_loop(__entry, (__dev)->tx, ring_end(__dev))
 -
 -/*
   * Generic RF access.
   * The RF is being accessed by word index.
   */
@@@ -924,43 -898,20 +927,43 @@@ static inline u16 get_duration_res(cons
        return ((size * 8 * 10) % rate);
  }
  
 -/*
 - * Library functions.
 +/**
 + * rt2x00queue_get_queue - Convert mac80211 queue index to rt2x00 queue
 + * @rt2x00dev: Pointer to &struct rt2x00_dev.
 + * @queue: mac80211/rt2x00 queue index
 + *    (see &enum ieee80211_tx_queue and &enum rt2x00_bcn_queue).
 + */
 +struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
 +                                       const unsigned int queue);
 +
 +/**
 + * rt2x00queue_get_entry - Get queue entry where the given index points to.
 + * @rt2x00dev: Pointer to &struct rt2x00_dev.
 + * @index: Index identifier for obtaining the correct index.
 + */
 +struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
 +                                        enum queue_index index);
 +
 +/**
 + * rt2x00queue_index_inc - Index incrementation function
 + * @queue: Queue (&struct data_queue) to perform the action on.
 + * @action: Index type (&enum queue_index) to perform the action on.
 + *
 + * This function will increase the requested index on the queue,
 + * it will grab the appropriate locks and handle queue overflow events by
 + * resetting the index to the start of the queue.
   */
 -struct data_ring *rt2x00lib_get_ring(struct rt2x00_dev *rt2x00dev,
 -                                   const unsigned int queue);
 +void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index);
 +
  
  /*
   * Interrupt context handlers.
   */
  void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev);
 -void rt2x00lib_txdone(struct data_entry *entry,
 -                    const int status, const int retry);
 -void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
 -                    struct rxdata_entry_desc *desc);
 +void rt2x00lib_txdone(struct queue_entry *entry,
 +                    struct txdone_entry_desc *txdesc);
 +void rt2x00lib_rxdone(struct queue_entry *entry,
 +                    struct rxdone_entry_desc *rxdesc);
  
  /*
   * TX descriptor initializer
@@@ -1,5 -1,5 +1,5 @@@
  /*
 -      Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
 +      Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
  
        This program is free software; you can redistribute it and/or modify
  #include "rt2x00dump.h"
  
  /*
 - * Ring handler.
 - */
 -struct data_ring *rt2x00lib_get_ring(struct rt2x00_dev *rt2x00dev,
 -                                   const unsigned int queue)
 -{
 -      int beacon = test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags);
 -
 -      /*
 -       * Check if we are requesting a reqular TX ring,
 -       * or if we are requesting a Beacon or Atim ring.
 -       * For Atim rings, we should check if it is supported.
 -       */
 -      if (queue < rt2x00dev->hw->queues && rt2x00dev->tx)
 -              return &rt2x00dev->tx[queue];
 -
 -      if (!rt2x00dev->bcn || !beacon)
 -              return NULL;
 -
 -      if (queue == IEEE80211_TX_QUEUE_BEACON)
 -              return &rt2x00dev->bcn[0];
 -      else if (queue == IEEE80211_TX_QUEUE_AFTER_BEACON)
 -              return &rt2x00dev->bcn[1];
 -
 -      return NULL;
 -}
 -EXPORT_SYMBOL_GPL(rt2x00lib_get_ring);
 -
 -/*
   * Link tuning handlers
   */
  void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev)
@@@ -85,6 -113,46 +85,6 @@@ static void rt2x00lib_stop_link_tuner(s
  }
  
  /*
 - * Ring initialization
 - */
 -static void rt2x00lib_init_rxrings(struct rt2x00_dev *rt2x00dev)
 -{
 -      struct data_ring *ring = rt2x00dev->rx;
 -      unsigned int i;
 -
 -      if (!rt2x00dev->ops->lib->init_rxentry)
 -              return;
 -
 -      if (ring->data_addr)
 -              memset(ring->data_addr, 0, rt2x00_get_ring_size(ring));
 -
 -      for (i = 0; i < ring->stats.limit; i++)
 -              rt2x00dev->ops->lib->init_rxentry(rt2x00dev, &ring->entry[i]);
 -
 -      rt2x00_ring_index_clear(ring);
 -}
 -
 -static void rt2x00lib_init_txrings(struct rt2x00_dev *rt2x00dev)
 -{
 -      struct data_ring *ring;
 -      unsigned int i;
 -
 -      if (!rt2x00dev->ops->lib->init_txentry)
 -              return;
 -
 -      txringall_for_each(rt2x00dev, ring) {
 -              if (ring->data_addr)
 -                      memset(ring->data_addr, 0, rt2x00_get_ring_size(ring));
 -
 -              for (i = 0; i < ring->stats.limit; i++)
 -                      rt2x00dev->ops->lib->init_txentry(rt2x00dev,
 -                                                        &ring->entry[i]);
 -
 -              rt2x00_ring_index_clear(ring);
 -      }
 -}
 -
 -/*
   * Radio control handlers.
   */
  int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
                return 0;
  
        /*
 -       * Initialize all data rings.
 +       * Initialize all data queues.
         */
 -      rt2x00lib_init_rxrings(rt2x00dev);
 -      rt2x00lib_init_txrings(rt2x00dev);
 +      rt2x00queue_init_rx(rt2x00dev);
 +      rt2x00queue_init_tx(rt2x00dev);
  
        /*
         * Enable radio.
@@@ -136,10 -204,12 +136,10 @@@ void rt2x00lib_disable_radio(struct rt2
        /*
         * Stop all scheduled work.
         */
 -      if (work_pending(&rt2x00dev->beacon_work))
 -              cancel_work_sync(&rt2x00dev->beacon_work);
 +      if (work_pending(&rt2x00dev->intf_work))
 +              cancel_work_sync(&rt2x00dev->intf_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.
@@@ -171,7 -241,7 +171,7 @@@ void rt2x00lib_toggle_rx(struct rt2x00_
         * When we are enabling the RX, we should also start the link tuner.
         */
        if (state == STATE_RADIO_RX_ON &&
 -          is_interface_present(&rt2x00dev->interface))
 +          (rt2x00dev->intf_ap_count || rt2x00dev->intf_sta_count))
                rt2x00lib_start_link_tuner(rt2x00dev);
  }
  
@@@ -379,11 -449,6 +379,11 @@@ static void rt2x00lib_link_tuner(struc
        rt2x00lib_precalculate_link_signal(&rt2x00dev->link.qual);
  
        /*
 +       * Send a signal to the led to update the led signal strength.
 +       */
 +      rt2x00leds_led_quality(rt2x00dev, rt2x00dev->link.qual.avg_rssi);
 +
 +      /*
         * Evaluate antenna setup, make this the last step since this could
         * possibly reset some statistics.
         */
@@@ -404,10 -469,10 +404,10 @@@ static void rt2x00lib_packetfilter_sche
        unsigned int filter = rt2x00dev->packet_filter;
  
        /*
 -       * Since we had stored the filter inside interface.filter,
 +       * Since we had stored the filter inside rt2x00dev->packet_filter,
         * we should now clear that field. Otherwise the driver will
         * assume nothing has changed (*total_flags will be compared
 -       * to interface.filter to determine if any action is required).
 +       * to rt2x00dev->packet_filter to determine if any action is required).
         */
        rt2x00dev->packet_filter = 0;
  
                                             filter, &filter, 0, NULL);
  }
  
 -static void rt2x00lib_configuration_scheduled(struct work_struct *work)
 +static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
 +                                        struct ieee80211_vif *vif)
  {
 -      struct rt2x00_dev *rt2x00dev =
 -          container_of(work, struct rt2x00_dev, config_work);
 -      struct ieee80211_bss_conf bss_conf;
 +      struct rt2x00_dev *rt2x00dev = data;
 +      struct rt2x00_intf *intf = vif_to_intf(vif);
 +      struct sk_buff *skb;
 +      struct ieee80211_tx_control control;
 +      struct ieee80211_bss_conf conf;
 +      int delayed_flags;
 +
 +      /*
 +       * Copy all data we need during this action under the protection
 +       * of a spinlock. Otherwise race conditions might occur which results
 +       * into an invalid configuration.
 +       */
 +      spin_lock(&intf->lock);
 +
 +      memcpy(&conf, &intf->conf, sizeof(conf));
 +      delayed_flags = intf->delayed_flags;
 +      intf->delayed_flags = 0;
 +
 +      spin_unlock(&intf->lock);
  
 -      bss_conf.use_short_preamble =
 -              test_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
 +      if (delayed_flags & DELAYED_UPDATE_BEACON) {
 +              skb = ieee80211_beacon_get(rt2x00dev->hw, vif, &control);
 +              if (skb) {
 +                      rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb,
 +                                                        &control);
 +                      dev_kfree_skb(skb);
 +              }
 +      }
 +
 +      if (delayed_flags & DELAYED_CONFIG_ERP)
 +              rt2x00lib_config_erp(rt2x00dev, intf, &intf->conf);
 +}
 +
 +static void rt2x00lib_intf_scheduled(struct work_struct *work)
 +{
 +      struct rt2x00_dev *rt2x00dev =
 +          container_of(work, struct rt2x00_dev, intf_work);
  
        /*
 -       * FIXME: shouldn't invoke it this way because all other contents
 -       *        of bss_conf is invalid.
 +       * Iterate over each interface and perform the
 +       * requested configurations.
         */
 -      rt2x00mac_bss_info_changed(rt2x00dev->hw, rt2x00dev->interface.id,
 -                                 &bss_conf, BSS_CHANGED_ERP_PREAMBLE);
 +      ieee80211_iterate_active_interfaces(rt2x00dev->hw,
 +                                          rt2x00lib_intf_scheduled_iter,
 +                                          rt2x00dev);
  }
  
  /*
   * Interrupt context handlers.
   */
 -static void rt2x00lib_beacondone_scheduled(struct work_struct *work)
 +static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
 +                                    struct ieee80211_vif *vif)
  {
 -      struct rt2x00_dev *rt2x00dev =
 -          container_of(work, struct rt2x00_dev, beacon_work);
 -      struct data_ring *ring =
 -          rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
 -      struct data_entry *entry = rt2x00_get_data_entry(ring);
 -      struct sk_buff *skb;
 +      struct rt2x00_intf *intf = vif_to_intf(vif);
  
 -      skb = ieee80211_beacon_get(rt2x00dev->hw,
 -                                 rt2x00dev->interface.id,
 -                                 &entry->tx_status.control);
 -      if (!skb)
 +      if (vif->type != IEEE80211_IF_TYPE_AP &&
 +          vif->type != IEEE80211_IF_TYPE_IBSS)
                return;
  
 -      rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb,
 -                                        &entry->tx_status.control);
 -
 -      dev_kfree_skb(skb);
 +      spin_lock(&intf->lock);
 +      intf->delayed_flags |= DELAYED_UPDATE_BEACON;
 +      spin_unlock(&intf->lock);
  }
  
  void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
        if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
                return;
  
 -      queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->beacon_work);
 +      ieee80211_iterate_active_interfaces(rt2x00dev->hw,
 +                                          rt2x00lib_beacondone_iter,
 +                                          rt2x00dev);
 +
 +      queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work);
  }
  EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
  
 -void rt2x00lib_txdone(struct data_entry *entry,
 -                    const int status, const int retry)
 +void rt2x00lib_txdone(struct queue_entry *entry,
 +                    struct txdone_entry_desc *txdesc)
  {
 -      struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev;
 -      struct ieee80211_tx_status *tx_status = &entry->tx_status;
 -      struct ieee80211_low_level_stats *stats = &rt2x00dev->low_level_stats;
 -      int success = !!(status == TX_SUCCESS || status == TX_SUCCESS_RETRY);
 -      int fail = !!(status == TX_FAIL_RETRY || status == TX_FAIL_INVALID ||
 -                    status == TX_FAIL_OTHER);
 +      struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 +      struct skb_frame_desc *skbdesc;
 +      struct ieee80211_tx_status tx_status;
 +      int success = !!(txdesc->status == TX_SUCCESS ||
 +                       txdesc->status == TX_SUCCESS_RETRY);
 +      int fail = !!(txdesc->status == TX_FAIL_RETRY ||
 +                    txdesc->status == TX_FAIL_INVALID ||
 +                    txdesc->status == TX_FAIL_OTHER);
  
        /*
         * Update TX statistics.
         */
 -      tx_status->flags = 0;
 -      tx_status->ack_signal = 0;
 -      tx_status->excessive_retries = (status == TX_FAIL_RETRY);
 -      tx_status->retry_count = retry;
        rt2x00dev->link.qual.tx_success += success;
 -      rt2x00dev->link.qual.tx_failed += retry + fail;
 +      rt2x00dev->link.qual.tx_failed += txdesc->retry + fail;
 +
 +      /*
 +       * Initialize TX status
 +       */
 +      tx_status.flags = 0;
 +      tx_status.ack_signal = 0;
 +      tx_status.excessive_retries = (txdesc->status == TX_FAIL_RETRY);
 +      tx_status.retry_count = txdesc->retry;
 +      memcpy(&tx_status.control, txdesc->control, sizeof(*txdesc->control));
  
 -      if (!(tx_status->control.flags & IEEE80211_TXCTL_NO_ACK)) {
 +      if (!(tx_status.control.flags & IEEE80211_TXCTL_NO_ACK)) {
                if (success)
 -                      tx_status->flags |= IEEE80211_TX_STATUS_ACK;
 +                      tx_status.flags |= IEEE80211_TX_STATUS_ACK;
                else
 -                      stats->dot11ACKFailureCount++;
 +                      rt2x00dev->low_level_stats.dot11ACKFailureCount++;
        }
  
 -      tx_status->queue_length = entry->ring->stats.limit;
 -      tx_status->queue_number = tx_status->control.queue;
 +      tx_status.queue_length = entry->queue->limit;
 +      tx_status.queue_number = tx_status.control.queue;
  
 -      if (tx_status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) {
 +      if (tx_status.control.flags & IEEE80211_TXCTL_USE_RTS_CTS) {
                if (success)
 -                      stats->dot11RTSSuccessCount++;
 +                      rt2x00dev->low_level_stats.dot11RTSSuccessCount++;
                else
 -                      stats->dot11RTSFailureCount++;
 +                      rt2x00dev->low_level_stats.dot11RTSFailureCount++;
        }
  
        /*
 -       * Send the tx_status to mac80211 & debugfs.
 -       * mac80211 will clean up the skb structure.
 +       * Send the tx_status to debugfs. Only send the status report
 +       * to mac80211 when the frame originated from there. If this was
 +       * a extra frame coming through a mac80211 library call (RTS/CTS)
 +       * then we should not send the status report back.
 +       * If send to mac80211, mac80211 will clean up the skb structure,
 +       * otherwise we have to do it ourself.
         */
 -      get_skb_desc(entry->skb)->frame_type = DUMP_FRAME_TXDONE;
 +      skbdesc = get_skb_frame_desc(entry->skb);
 +      skbdesc->frame_type = DUMP_FRAME_TXDONE;
 +
        rt2x00debug_dump_frame(rt2x00dev, entry->skb);
 -      ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb, tx_status);
 +
 +      if (!(skbdesc->flags & FRAME_DESC_DRIVER_GENERATED))
 +              ieee80211_tx_status_irqsafe(rt2x00dev->hw,
 +                                          entry->skb, &tx_status);
 +      else
 +              dev_kfree_skb(entry->skb);
        entry->skb = NULL;
  }
  EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
  
 -void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
 -                    struct rxdata_entry_desc *desc)
 +void rt2x00lib_rxdone(struct queue_entry *entry,
 +                    struct rxdone_entry_desc *rxdesc)
  {
 -      struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev;
 +      struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
        struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status;
 -      struct ieee80211_hw_mode *mode;
 -      struct ieee80211_rate *rate;
 +      struct ieee80211_supported_band *sband;
        struct ieee80211_hdr *hdr;
 +      const struct rt2x00_rate *rate;
        unsigned int i;
 -      int val = 0;
 +      int idx = -1;
        u16 fc;
  
        /*
         * Update RX statistics.
         */
 -      mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode];
 -      for (i = 0; i < mode->num_rates; i++) {
 -              rate = &mode->rates[i];
 +      sband = &rt2x00dev->bands[rt2x00dev->curr_band];
 +      for (i = 0; i < sband->n_bitrates; i++) {
 +              rate = rt2x00_get_rate(sband->bitrates[i].hw_value);
  
 -              /*
 -               * When frame was received with an OFDM bitrate,
 -               * the signal is the PLCP value. If it was received with
 -               * a CCK bitrate the signal is the rate in 0.5kbit/s.
 -               */
 -              if (!desc->ofdm)
 -                      val = DEVICE_GET_RATE_FIELD(rate->val, RATE);
 -              else
 -                      val = DEVICE_GET_RATE_FIELD(rate->val, PLCP);
 -
 -              if (val == desc->signal) {
 -                      val = rate->val;
 +              if ((rxdesc->signal_plcp && rate->plcp == rxdesc->signal) ||
 +                  (!rxdesc->signal_plcp && rate->bitrate == rxdesc->signal)) {
 +                      idx = i;
                        break;
                }
        }
        /*
         * Only update link status if this is a beacon frame carrying our bssid.
         */
 -      hdr = (struct ieee80211_hdr*)skb->data;
 +      hdr = (struct ieee80211_hdr *)entry->skb->data;
        fc = le16_to_cpu(hdr->frame_control);
 -      if (is_beacon(fc) && desc->my_bss)
 -              rt2x00lib_update_link_stats(&rt2x00dev->link, desc->rssi);
 +      if (is_beacon(fc) && rxdesc->my_bss)
 +              rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc->rssi);
  
        rt2x00dev->link.qual.rx_success++;
  
 -      rx_status->rate = val;
 +      rx_status->rate_idx = idx;
        rx_status->signal =
 -          rt2x00lib_calculate_link_signal(rt2x00dev, desc->rssi);
 -      rx_status->ssi = desc->rssi;
 -      rx_status->flag = desc->flags;
 +          rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc->rssi);
 +      rx_status->ssi = rxdesc->rssi;
 +      rx_status->flag = rxdesc->flags;
        rx_status->antenna = rt2x00dev->link.ant.active.rx;
  
        /*
 -       * Send frame to mac80211 & debugfs
 +       * Send frame to mac80211 & debugfs.
 +       * mac80211 will clean up the skb structure.
         */
 -      get_skb_desc(skb)->frame_type = DUMP_FRAME_RXDONE;
 -      rt2x00debug_dump_frame(rt2x00dev, skb);
 -      ieee80211_rx_irqsafe(rt2x00dev->hw, skb, rx_status);
 +      get_skb_frame_desc(entry->skb)->frame_type = DUMP_FRAME_RXDONE;
 +      rt2x00debug_dump_frame(rt2x00dev, entry->skb);
 +      ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb, rx_status);
 +      entry->skb = NULL;
  }
  EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
  
@@@ -622,69 -646,83 +622,69 @@@ void rt2x00lib_write_tx_desc(struct rt2
                             struct sk_buff *skb,
                             struct ieee80211_tx_control *control)
  {
 -      struct txdata_entry_desc desc;
 -      struct skb_desc *skbdesc = get_skb_desc(skb);
 -      struct ieee80211_hdr *ieee80211hdr = skbdesc->data;
 +      struct txentry_desc txdesc;
 +      struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
 +      struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skbdesc->data;
 +      const struct rt2x00_rate *rate;
        int tx_rate;
 -      int bitrate;
        int length;
        int duration;
        int residual;
        u16 frame_control;
        u16 seq_ctrl;
  
 -      memset(&desc, 0, sizeof(desc));
 -
 -      desc.cw_min = skbdesc->ring->tx_params.cw_min;
 -      desc.cw_max = skbdesc->ring->tx_params.cw_max;
 -      desc.aifs = skbdesc->ring->tx_params.aifs;
 +      memset(&txdesc, 0, sizeof(txdesc));
  
 -      /*
 -       * Identify queue
 -       */
 -      if (control->queue < rt2x00dev->hw->queues)
 -              desc.queue = control->queue;
 -      else if (control->queue == IEEE80211_TX_QUEUE_BEACON ||
 -               control->queue == IEEE80211_TX_QUEUE_AFTER_BEACON)
 -              desc.queue = QUEUE_MGMT;
 -      else
 -              desc.queue = QUEUE_OTHER;
 +      txdesc.queue = skbdesc->entry->queue->qid;
 +      txdesc.cw_min = skbdesc->entry->queue->cw_min;
 +      txdesc.cw_max = skbdesc->entry->queue->cw_max;
 +      txdesc.aifs = skbdesc->entry->queue->aifs;
  
        /*
         * Read required fields from ieee80211 header.
         */
 -      frame_control = le16_to_cpu(ieee80211hdr->frame_control);
 -      seq_ctrl = le16_to_cpu(ieee80211hdr->seq_ctrl);
 +      frame_control = le16_to_cpu(hdr->frame_control);
 +      seq_ctrl = le16_to_cpu(hdr->seq_ctrl);
  
 -      tx_rate = control->tx_rate;
 +      tx_rate = control->tx_rate->hw_value;
  
        /*
         * Check whether this frame is to be acked
         */
        if (!(control->flags & IEEE80211_TXCTL_NO_ACK))
 -              __set_bit(ENTRY_TXD_ACK, &desc.flags);
 +              __set_bit(ENTRY_TXD_ACK, &txdesc.flags);
  
        /*
         * Check if this is a RTS/CTS frame
         */
        if (is_rts_frame(frame_control) || is_cts_frame(frame_control)) {
 -              __set_bit(ENTRY_TXD_BURST, &desc.flags);
 +              __set_bit(ENTRY_TXD_BURST, &txdesc.flags);
                if (is_rts_frame(frame_control)) {
 -                      __set_bit(ENTRY_TXD_RTS_FRAME, &desc.flags);
 -                      __set_bit(ENTRY_TXD_ACK, &desc.flags);
 +                      __set_bit(ENTRY_TXD_RTS_FRAME, &txdesc.flags);
 +                      __set_bit(ENTRY_TXD_ACK, &txdesc.flags);
                } else
 -                      __clear_bit(ENTRY_TXD_ACK, &desc.flags);
 +                      __clear_bit(ENTRY_TXD_ACK, &txdesc.flags);
                if (control->rts_cts_rate)
 -                      tx_rate = control->rts_cts_rate;
 +                      tx_rate = control->rts_cts_rate->hw_value;
        }
  
 -      /*
 -       * Check for OFDM
 -       */
 -      if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATEMASK)
 -              __set_bit(ENTRY_TXD_OFDM_RATE, &desc.flags);
 +      rate = rt2x00_get_rate(tx_rate);
  
        /*
         * Check if more fragments are pending
         */
 -      if (ieee80211_get_morefrag(ieee80211hdr)) {
 -              __set_bit(ENTRY_TXD_BURST, &desc.flags);
 -              __set_bit(ENTRY_TXD_MORE_FRAG, &desc.flags);
 +      if (ieee80211_get_morefrag(hdr)) {
 +              __set_bit(ENTRY_TXD_BURST, &txdesc.flags);
 +              __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc.flags);
        }
  
        /*
         * Beacons and probe responses require the tsf timestamp
         * to be inserted into the frame.
         */
 -      if (control->queue == IEEE80211_TX_QUEUE_BEACON ||
 +      if (control->queue == RT2X00_BCN_QUEUE_BEACON ||
            is_probe_resp(frame_control))
 -              __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc.flags);
 +              __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc.flags);
  
        /*
         * Determine with what IFS priority this frame should be send.
         * or this fragment came after RTS/CTS.
         */
        if ((seq_ctrl & IEEE80211_SCTL_FRAG) > 0 ||
 -          test_bit(ENTRY_TXD_RTS_FRAME, &desc.flags))
 -              desc.ifs = IFS_SIFS;
 +          test_bit(ENTRY_TXD_RTS_FRAME, &txdesc.flags))
 +              txdesc.ifs = IFS_SIFS;
        else
 -              desc.ifs = IFS_BACKOFF;
 +              txdesc.ifs = IFS_BACKOFF;
  
        /*
         * PLCP setup
         * Length calculation depends on OFDM/CCK rate.
         */
 -      desc.signal = DEVICE_GET_RATE_FIELD(tx_rate, PLCP);
 -      desc.service = 0x04;
 +      txdesc.signal = rate->plcp;
 +      txdesc.service = 0x04;
  
        length = skbdesc->data_len + FCS_LEN;
 -      if (test_bit(ENTRY_TXD_OFDM_RATE, &desc.flags)) {
 -              desc.length_high = (length >> 6) & 0x3f;
 -              desc.length_low = length & 0x3f;
 -      } else {
 -              bitrate = DEVICE_GET_RATE_FIELD(tx_rate, RATE);
 +      if (rate->flags & DEV_RATE_OFDM) {
 +              __set_bit(ENTRY_TXD_OFDM_RATE, &txdesc.flags);
  
 +              txdesc.length_high = (length >> 6) & 0x3f;
 +              txdesc.length_low = length & 0x3f;
 +      } else {
                /*
                 * Convert length to microseconds.
                 */
 -              residual = get_duration_res(length, bitrate);
 -              duration = get_duration(length, bitrate);
 +              residual = get_duration_res(length, rate->bitrate);
 +              duration = get_duration(length, rate->bitrate);
  
                if (residual != 0) {
                        duration++;
                        /*
                         * Check if we need to set the Length Extension
                         */
 -                      if (bitrate == 110 && residual <= 30)
 -                              desc.service |= 0x80;
 +                      if (rate->bitrate == 110 && residual <= 30)
 +                              txdesc.service |= 0x80;
                }
  
 -              desc.length_high = (duration >> 8) & 0xff;
 -              desc.length_low = duration & 0xff;
 +              txdesc.length_high = (duration >> 8) & 0xff;
 +              txdesc.length_low = duration & 0xff;
  
                /*
                 * When preamble is enabled we should set the
                 * preamble bit for the signal.
                 */
 -              if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE))
 -                      desc.signal |= 0x08;
 +              if (rt2x00_get_rate_preamble(tx_rate))
 +                      txdesc.signal |= 0x08;
        }
  
 -      rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, skb, &desc, control);
 +      rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, skb, &txdesc, control);
  
        /*
 -       * Update ring entry.
 +       * Update queue entry.
         */
        skbdesc->entry->skb = skb;
 -      memcpy(&skbdesc->entry->tx_status.control, control, sizeof(*control));
  
        /*
         * The frame has been completely initialized and ready
@@@ -759,167 -798,133 +759,167 @@@ EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_de
  /*
   * Driver initialization handlers.
   */
 +const struct rt2x00_rate rt2x00_supported_rates[12] = {
 +      {
 +              .flags = DEV_RATE_CCK | DEV_RATE_BASIC,
 +              .bitrate = 10,
 +              .ratemask = BIT(0),
 +              .plcp = 0x00,
 +      },
 +      {
 +              .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC,
 +              .bitrate = 20,
 +              .ratemask = BIT(1),
 +              .plcp = 0x01,
 +      },
 +      {
 +              .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC,
 +              .bitrate = 55,
 +              .ratemask = BIT(2),
 +              .plcp = 0x02,
 +      },
 +      {
 +              .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC,
 +              .bitrate = 110,
 +              .ratemask = BIT(3),
 +              .plcp = 0x03,
 +      },
 +      {
 +              .flags = DEV_RATE_OFDM | DEV_RATE_BASIC,
 +              .bitrate = 60,
 +              .ratemask = BIT(4),
 +              .plcp = 0x0b,
 +      },
 +      {
 +              .flags = DEV_RATE_OFDM,
 +              .bitrate = 90,
 +              .ratemask = BIT(5),
 +              .plcp = 0x0f,
 +      },
 +      {
 +              .flags = DEV_RATE_OFDM | DEV_RATE_BASIC,
 +              .bitrate = 120,
 +              .ratemask = BIT(6),
 +              .plcp = 0x0a,
 +      },
 +      {
 +              .flags = DEV_RATE_OFDM,
 +              .bitrate = 180,
 +              .ratemask = BIT(7),
 +              .plcp = 0x0e,
 +      },
 +      {
 +              .flags = DEV_RATE_OFDM | DEV_RATE_BASIC,
 +              .bitrate = 240,
 +              .ratemask = BIT(8),
 +              .plcp = 0x09,
 +      },
 +      {
 +              .flags = DEV_RATE_OFDM,
 +              .bitrate = 360,
 +              .ratemask = BIT(9),
 +              .plcp = 0x0d,
 +      },
 +      {
 +              .flags = DEV_RATE_OFDM,
 +              .bitrate = 480,
 +              .ratemask = BIT(10),
 +              .plcp = 0x08,
 +      },
 +      {
 +              .flags = DEV_RATE_OFDM,
 +              .bitrate = 540,
 +              .ratemask = BIT(11),
 +              .plcp = 0x0c,
 +      },
 +};
 +
  static void rt2x00lib_channel(struct ieee80211_channel *entry,
                              const int channel, const int tx_power,
                              const int value)
  {
 -      entry->chan = channel;
 -      if (channel <= 14)
 -              entry->freq = 2407 + (5 * channel);
 -      else
 -              entry->freq = 5000 + (5 * channel);
 -      entry->val = value;
 -      entry->flag =
 -          IEEE80211_CHAN_W_IBSS |
 -          IEEE80211_CHAN_W_ACTIVE_SCAN |
 -          IEEE80211_CHAN_W_SCAN;
 -      entry->power_level = tx_power;
 -      entry->antenna_max = 0xff;
 +      entry->center_freq = ieee80211_channel_to_frequency(channel);
 +      entry->hw_value = value;
 +      entry->max_power = tx_power;
 +      entry->max_antenna_gain = 0xff;
  }
  
  static void rt2x00lib_rate(struct ieee80211_rate *entry,
 -                         const int rate, const int mask,
 -                         const int plcp, const int flags)
 +                         const u16 index, const struct rt2x00_rate *rate)
  {
 -      entry->rate = rate;
 -      entry->val =
 -          DEVICE_SET_RATE_FIELD(rate, RATE) |
 -          DEVICE_SET_RATE_FIELD(mask, RATEMASK) |
 -          DEVICE_SET_RATE_FIELD(plcp, PLCP);
 -      entry->flags = flags;
 -      entry->val2 = entry->val;
 -      if (entry->flags & IEEE80211_RATE_PREAMBLE2)
 -              entry->val2 |= DEVICE_SET_RATE_FIELD(1, PREAMBLE);
 -      entry->min_rssi_ack = 0;
 -      entry->min_rssi_ack_delta = 0;
 +      entry->flags = 0;
 +      entry->bitrate = rate->bitrate;
 +      entry->hw_value = rt2x00_create_rate_hw_value(index, 0);
 +      entry->hw_value_short = entry->hw_value;
 +
 +      if (rate->flags & DEV_RATE_SHORT_PREAMBLE) {
 +              entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE;
 +              entry->hw_value_short |= rt2x00_create_rate_hw_value(index, 1);
 +      }
  }
  
  static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
                                    struct hw_mode_spec *spec)
  {
        struct ieee80211_hw *hw = rt2x00dev->hw;
 -      struct ieee80211_hw_mode *hwmodes;
        struct ieee80211_channel *channels;
        struct ieee80211_rate *rates;
 +      unsigned int num_rates;
        unsigned int i;
        unsigned char tx_power;
  
 -      hwmodes = kzalloc(sizeof(*hwmodes) * spec->num_modes, GFP_KERNEL);
 -      if (!hwmodes)
 -              goto exit;
 +      num_rates = 0;
 +      if (spec->supported_rates & SUPPORT_RATE_CCK)
 +              num_rates += 4;
 +      if (spec->supported_rates & SUPPORT_RATE_OFDM)
 +              num_rates += 8;
  
        channels = kzalloc(sizeof(*channels) * spec->num_channels, GFP_KERNEL);
        if (!channels)
 -              goto exit_free_modes;
 +              return -ENOMEM;
  
 -      rates = kzalloc(sizeof(*rates) * spec->num_rates, GFP_KERNEL);
 +      rates = kzalloc(sizeof(*rates) * num_rates, GFP_KERNEL);
        if (!rates)
                goto exit_free_channels;
  
        /*
         * Initialize Rate list.
         */
 -      rt2x00lib_rate(&rates[0], 10, DEV_RATEMASK_1MB,
 -                     0x00, IEEE80211_RATE_CCK);
 -      rt2x00lib_rate(&rates[1], 20, DEV_RATEMASK_2MB,
 -                     0x01, IEEE80211_RATE_CCK_2);
 -      rt2x00lib_rate(&rates[2], 55, DEV_RATEMASK_5_5MB,
 -                     0x02, IEEE80211_RATE_CCK_2);
 -      rt2x00lib_rate(&rates[3], 110, DEV_RATEMASK_11MB,
 -                     0x03, IEEE80211_RATE_CCK_2);
 -
 -      if (spec->num_rates > 4) {
 -              rt2x00lib_rate(&rates[4], 60, DEV_RATEMASK_6MB,
 -                             0x0b, IEEE80211_RATE_OFDM);
 -              rt2x00lib_rate(&rates[5], 90, DEV_RATEMASK_9MB,
 -                             0x0f, IEEE80211_RATE_OFDM);
 -              rt2x00lib_rate(&rates[6], 120, DEV_RATEMASK_12MB,
 -                             0x0a, IEEE80211_RATE_OFDM);
 -              rt2x00lib_rate(&rates[7], 180, DEV_RATEMASK_18MB,
 -                             0x0e, IEEE80211_RATE_OFDM);
 -              rt2x00lib_rate(&rates[8], 240, DEV_RATEMASK_24MB,
 -                             0x09, IEEE80211_RATE_OFDM);
 -              rt2x00lib_rate(&rates[9], 360, DEV_RATEMASK_36MB,
 -                             0x0d, IEEE80211_RATE_OFDM);
 -              rt2x00lib_rate(&rates[10], 480, DEV_RATEMASK_48MB,
 -                             0x08, IEEE80211_RATE_OFDM);
 -              rt2x00lib_rate(&rates[11], 540, DEV_RATEMASK_54MB,
 -                             0x0c, IEEE80211_RATE_OFDM);
 -      }
 +      for (i = 0; i < num_rates; i++)
 +              rt2x00lib_rate(&rates[i], i, rt2x00_get_rate(i));
  
        /*
         * Initialize Channel list.
         */
        for (i = 0; i < spec->num_channels; i++) {
 -              if (spec->channels[i].channel <= 14)
 -                      tx_power = spec->tx_power_bg[i];
 -              else if (spec->tx_power_a)
 -                      tx_power = spec->tx_power_a[i];
 -              else
 -                      tx_power = spec->tx_power_default;
 +              if (spec->channels[i].channel <= 14) {
 +                      if (spec->tx_power_bg)
 +                              tx_power = spec->tx_power_bg[i];
 +                      else
 +                              tx_power = spec->tx_power_default;
 +              } else {
 +                      if (spec->tx_power_a)
 +                              tx_power = spec->tx_power_a[i];
 +                      else
 +                              tx_power = spec->tx_power_default;
 +              }
  
                rt2x00lib_channel(&channels[i],
                                  spec->channels[i].channel, tx_power, i);
        }
  
        /*
 -       * Intitialize 802.11b
 -       * Rates: CCK.
 -       * Channels: OFDM.
 -       */
 -      if (spec->num_modes > HWMODE_B) {
 -              hwmodes[HWMODE_B].mode = MODE_IEEE80211B;
 -              hwmodes[HWMODE_B].num_channels = 14;
 -              hwmodes[HWMODE_B].num_rates = 4;
 -              hwmodes[HWMODE_B].channels = channels;
 -              hwmodes[HWMODE_B].rates = rates;
 -      }
 -
 -      /*
 -       * Intitialize 802.11g
 +       * Intitialize 802.11b, 802.11g
         * Rates: CCK, OFDM.
 -       * Channels: OFDM.
 -       */
 -      if (spec->num_modes > HWMODE_G) {
 -              hwmodes[HWMODE_G].mode = MODE_IEEE80211G;
 -              hwmodes[HWMODE_G].num_channels = 14;
 -              hwmodes[HWMODE_G].num_rates = spec->num_rates;
 -              hwmodes[HWMODE_G].channels = channels;
 -              hwmodes[HWMODE_G].rates = rates;
 +       * Channels: 2.4 GHz
 +       */
 +      if (spec->supported_bands & SUPPORT_BAND_2GHZ) {
 +              rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_channels = 14;
 +              rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_bitrates = num_rates;
 +              rt2x00dev->bands[IEEE80211_BAND_2GHZ].channels = channels;
 +              rt2x00dev->bands[IEEE80211_BAND_2GHZ].bitrates = rates;
 +              hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
 +                  &rt2x00dev->bands[IEEE80211_BAND_2GHZ];
        }
  
        /*
         * Rates: OFDM.
         * Channels: OFDM, UNII, HiperLAN2.
         */
 -      if (spec->num_modes > HWMODE_A) {
 -              hwmodes[HWMODE_A].mode = MODE_IEEE80211A;
 -              hwmodes[HWMODE_A].num_channels = spec->num_channels - 14;
 -              hwmodes[HWMODE_A].num_rates = spec->num_rates - 4;
 -              hwmodes[HWMODE_A].channels = &channels[14];
 -              hwmodes[HWMODE_A].rates = &rates[4];
 +      if (spec->supported_bands & SUPPORT_BAND_5GHZ) {
 +              rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_channels =
 +                  spec->num_channels - 14;
 +              rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_bitrates =
 +                  num_rates - 4;
 +              rt2x00dev->bands[IEEE80211_BAND_5GHZ].channels = &channels[14];
 +              rt2x00dev->bands[IEEE80211_BAND_5GHZ].bitrates = &rates[4];
 +              hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
 +                  &rt2x00dev->bands[IEEE80211_BAND_5GHZ];
        }
  
 -      if (spec->num_modes > HWMODE_G &&
 -          ieee80211_register_hwmode(hw, &hwmodes[HWMODE_G]))
 -              goto exit_free_rates;
 -
 -      if (spec->num_modes > HWMODE_B &&
 -          ieee80211_register_hwmode(hw, &hwmodes[HWMODE_B]))
 -              goto exit_free_rates;
 -
 -      if (spec->num_modes > HWMODE_A &&
 -          ieee80211_register_hwmode(hw, &hwmodes[HWMODE_A]))
 -              goto exit_free_rates;
 -
 -      rt2x00dev->hwmodes = hwmodes;
 -
        return 0;
  
 -exit_free_rates:
 -      kfree(rates);
 -
 -exit_free_channels:
 + exit_free_channels:
        kfree(channels);
 -
 -exit_free_modes:
 -      kfree(hwmodes);
 -
 -exit:
        ERROR(rt2x00dev, "Allocation ieee80211 modes failed.\n");
        return -ENOMEM;
  }
@@@ -951,11 -975,11 +951,11 @@@ static void rt2x00lib_remove_hw(struct 
        if (test_bit(DEVICE_REGISTERED_HW, &rt2x00dev->flags))
                ieee80211_unregister_hw(rt2x00dev->hw);
  
 -      if (likely(rt2x00dev->hwmodes)) {
 -              kfree(rt2x00dev->hwmodes->channels);
 -              kfree(rt2x00dev->hwmodes->rates);
 -              kfree(rt2x00dev->hwmodes);
 -              rt2x00dev->hwmodes = NULL;
 +      if (likely(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ])) {
 +              kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
 +              kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->bitrates);
 +              rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
 +              rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
        }
  }
  
@@@ -988,13 -1012,93 +988,13 @@@ static int rt2x00lib_probe_hw(struct rt
  /*
   * Initialization/uninitialization handlers.
   */
 -static int rt2x00lib_alloc_entries(struct data_ring *ring,
 -                                 const u16 max_entries, const u16 data_size,
 -                                 const u16 desc_size)
 -{
 -      struct data_entry *entry;
 -      unsigned int i;
 -
 -      ring->stats.limit = max_entries;
 -      ring->data_size = data_size;
 -      ring->desc_size = desc_size;
 -
 -      /*
 -       * Allocate all ring entries.
 -       */
 -      entry = kzalloc(ring->stats.limit * sizeof(*entry), GFP_KERNEL);
 -      if (!entry)
 -              return -ENOMEM;
 -
 -      for (i = 0; i < ring->stats.limit; i++) {
 -              entry[i].flags = 0;
 -              entry[i].ring = ring;
 -              entry[i].skb = NULL;
 -              entry[i].entry_idx = i;
 -      }
 -
 -      ring->entry = entry;
 -
 -      return 0;
 -}
 -
 -static int rt2x00lib_alloc_ring_entries(struct rt2x00_dev *rt2x00dev)
 -{
 -      struct data_ring *ring;
 -
 -      /*
 -       * Allocate the RX ring.
 -       */
 -      if (rt2x00lib_alloc_entries(rt2x00dev->rx, RX_ENTRIES, DATA_FRAME_SIZE,
 -                                  rt2x00dev->ops->rxd_size))
 -              return -ENOMEM;
 -
 -      /*
 -       * First allocate the TX rings.
 -       */
 -      txring_for_each(rt2x00dev, ring) {
 -              if (rt2x00lib_alloc_entries(ring, TX_ENTRIES, DATA_FRAME_SIZE,
 -                                          rt2x00dev->ops->txd_size))
 -                      return -ENOMEM;
 -      }
 -
 -      if (!test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags))
 -              return 0;
 -
 -      /*
 -       * Allocate the BEACON ring.
 -       */
 -      if (rt2x00lib_alloc_entries(&rt2x00dev->bcn[0], BEACON_ENTRIES,
 -                                  MGMT_FRAME_SIZE, rt2x00dev->ops->txd_size))
 -              return -ENOMEM;
 -
 -      /*
 -       * Allocate the Atim ring.
 -       */
 -      if (rt2x00lib_alloc_entries(&rt2x00dev->bcn[1], ATIM_ENTRIES,
 -                                  DATA_FRAME_SIZE, rt2x00dev->ops->txd_size))
 -              return -ENOMEM;
 -
 -      return 0;
 -}
 -
 -static void rt2x00lib_free_ring_entries(struct rt2x00_dev *rt2x00dev)
 -{
 -      struct data_ring *ring;
 -
 -      ring_for_each(rt2x00dev, ring) {
 -              kfree(ring->entry);
 -              ring->entry = NULL;
 -      }
 -}
 -
  static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
  {
        if (!__test_and_clear_bit(DEVICE_INITIALIZED, &rt2x00dev->flags))
                return;
  
        /*
-        * Unregister rfkill.
+        * Unregister extra components.
         */
        rt2x00rfkill_unregister(rt2x00dev);
  
        rt2x00dev->ops->lib->uninitialize(rt2x00dev);
  
        /*
 -       * Free allocated ring entries.
 +       * Free allocated queue entries.
         */
 -      rt2x00lib_free_ring_entries(rt2x00dev);
 +      rt2x00queue_uninitialize(rt2x00dev);
  }
  
  static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
                return 0;
  
        /*
 -       * Allocate all ring entries.
 +       * Allocate all queue entries.
         */
 -      status = rt2x00lib_alloc_ring_entries(rt2x00dev);
 -      if (status) {
 -              ERROR(rt2x00dev, "Ring entries allocation failed.\n");
 +      status = rt2x00queue_initialize(rt2x00dev);
 +      if (status)
                return status;
 -      }
  
        /*
         * Initialize the device.
        __set_bit(DEVICE_INITIALIZED, &rt2x00dev->flags);
  
        /*
-        * Register the rfkill handler.
+        * Register the extra components.
         */
-       status = rt2x00rfkill_register(rt2x00dev);
-       if (status)
-               goto exit;
+       rt2x00rfkill_register(rt2x00dev);
  
        return 0;
  
 -exit_unitialize:
 -      rt2x00lib_uninitialize(rt2x00dev);
 -
  exit:
 -      rt2x00lib_free_ring_entries(rt2x00dev);
 +      rt2x00lib_uninitialize(rt2x00dev);
  
        return status;
  }
@@@ -1058,9 -1165,11 +1056,9 @@@ int rt2x00lib_start(struct rt2x00_dev *
         * If this is the first interface which is added,
         * we should load the firmware now.
         */
 -      if (test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) {
 -              retval = rt2x00lib_load_firmware(rt2x00dev);
 -              if (retval)
 -                      return retval;
 -      }
 +      retval = rt2x00lib_load_firmware(rt2x00dev);
 +      if (retval)
 +              return retval;
  
        /*
         * Initialize the device.
                return retval;
        }
  
 +      rt2x00dev->intf_ap_count = 0;
 +      rt2x00dev->intf_sta_count = 0;
 +      rt2x00dev->intf_associated = 0;
 +
        __set_bit(DEVICE_STARTED, &rt2x00dev->flags);
  
        return 0;
@@@ -1098,25 -1203,74 +1096,25 @@@ void rt2x00lib_stop(struct rt2x00_dev *
         */
        rt2x00lib_disable_radio(rt2x00dev);
  
 +      rt2x00dev->intf_ap_count = 0;
 +      rt2x00dev->intf_sta_count = 0;
 +      rt2x00dev->intf_associated = 0;
 +
        __clear_bit(DEVICE_STARTED, &rt2x00dev->flags);
  }
  
  /*
   * driver allocation handlers.
   */
 -static int rt2x00lib_alloc_rings(struct rt2x00_dev *rt2x00dev)
 +int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
  {
 -      struct data_ring *ring;
 -      unsigned int index;
 -
 -      /*
 -       * We need the following rings:
 -       * RX: 1
 -       * TX: hw->queues
 -       * Beacon: 1 (if required)
 -       * Atim: 1 (if required)
 -       */
 -      rt2x00dev->data_rings = 1 + rt2x00dev->hw->queues +
 -          (2 * test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags));
 -
 -      ring = kzalloc(rt2x00dev->data_rings * sizeof(*ring), GFP_KERNEL);
 -      if (!ring) {
 -              ERROR(rt2x00dev, "Ring allocation failed.\n");
 -              return -ENOMEM;
 -      }
 +      int retval = -ENOMEM;
  
        /*
 -       * Initialize pointers
 +       * Make room for rt2x00_intf inside the per-interface
 +       * structure ieee80211_vif.
         */
 -      rt2x00dev->rx = ring;
 -      rt2x00dev->tx = &rt2x00dev->rx[1];
 -      if (test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags))
 -              rt2x00dev->bcn = &rt2x00dev->tx[rt2x00dev->hw->queues];
 -
 -      /*
 -       * Initialize ring parameters.
 -       * RX: queue_idx = 0
 -       * TX: queue_idx = IEEE80211_TX_QUEUE_DATA0 + index
 -       * TX: cw_min: 2^5 = 32.
 -       * TX: cw_max: 2^10 = 1024.
 -       */
 -      rt2x00dev->rx->rt2x00dev = rt2x00dev;
 -      rt2x00dev->rx->queue_idx = 0;
 -
 -      index = IEEE80211_TX_QUEUE_DATA0;
 -      txring_for_each(rt2x00dev, ring) {
 -              ring->rt2x00dev = rt2x00dev;
 -              ring->queue_idx = index++;
 -              ring->tx_params.aifs = 2;
 -              ring->tx_params.cw_min = 5;
 -              ring->tx_params.cw_max = 10;
 -      }
 -
 -      return 0;
 -}
 -
 -static void rt2x00lib_free_rings(struct rt2x00_dev *rt2x00dev)
 -{
 -      kfree(rt2x00dev->rx);
 -      rt2x00dev->rx = NULL;
 -      rt2x00dev->tx = NULL;
 -      rt2x00dev->bcn = NULL;
 -}
 -
 -int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
 -{
 -      int retval = -ENOMEM;
 +      rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf);
  
        /*
         * Let the driver probe the device to detect the capabilities.
        /*
         * Initialize configuration work.
         */
 -      INIT_WORK(&rt2x00dev->beacon_work, rt2x00lib_beacondone_scheduled);
 +      INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_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);
  
        /*
 -       * Reset current working type.
 -       */
 -      rt2x00dev->interface.type = IEEE80211_IF_TYPE_INVALID;
 -
 -      /*
 -       * Allocate ring array.
 +       * Allocate queue array.
         */
 -      retval = rt2x00lib_alloc_rings(rt2x00dev);
 +      retval = rt2x00queue_allocate(rt2x00dev);
        if (retval)
                goto exit;
  
        }
  
        /*
-        * Register LED.
+        * Register extra components.
         */
-       /*
-        * Allocatie rfkill.
-        */
-       retval = rt2x00rfkill_allocate(rt2x00dev);
-       if (retval)
-               goto exit;
-       /*
-        * Open the debugfs entry.
-        */
 +      rt2x00leds_register(rt2x00dev);
+       rt2x00rfkill_allocate(rt2x00dev);
        rt2x00debug_register(rt2x00dev);
  
        __set_bit(DEVICE_PRESENT, &rt2x00dev->flags);
@@@ -1193,21 -1342,12 +1181,17 @@@ void rt2x00lib_remove_dev(struct rt2x00
        rt2x00lib_uninitialize(rt2x00dev);
  
        /*
-        * Close debugfs entry.
+        * Free extra components
         */
        rt2x00debug_deregister(rt2x00dev);
-       /*
-        * Free rfkill
-        */
        rt2x00rfkill_free(rt2x00dev);
  
        /*
 +       * Free LED.
 +       */
 +      rt2x00leds_unregister(rt2x00dev);
 +
 +      /*
         * Free ieee80211_hw memory.
         */
        rt2x00lib_remove_hw(rt2x00dev);
        rt2x00lib_free_firmware(rt2x00dev);
  
        /*
 -       * Free ring structures.
 +       * Free queue structures.
         */
 -      rt2x00lib_free_rings(rt2x00dev);
 +      rt2x00queue_free(rt2x00dev);
  }
  EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev);
  
@@@ -1243,12 -1383,15 +1227,16 @@@ int rt2x00lib_suspend(struct rt2x00_de
        __set_bit(DEVICE_STARTED_SUSPEND, &rt2x00dev->flags);
  
        /*
-        * Disable radio and unitialize all items
-        * that must be recreated on resume.
+        * Disable radio.
         */
        rt2x00lib_stop(rt2x00dev);
        rt2x00lib_uninitialize(rt2x00dev);
+       /*
+        * Suspend/disable extra components.
+        */
 +      rt2x00leds_suspend(rt2x00dev);
+       rt2x00rfkill_suspend(rt2x00dev);
        rt2x00debug_deregister(rt2x00dev);
  
  exit:
  }
  EXPORT_SYMBOL_GPL(rt2x00lib_suspend);
  
 +static void rt2x00lib_resume_intf(void *data, u8 *mac,
 +                                struct ieee80211_vif *vif)
 +{
 +      struct rt2x00_dev *rt2x00dev = data;
 +      struct rt2x00_intf *intf = vif_to_intf(vif);
 +
 +      spin_lock(&intf->lock);
 +
 +      rt2x00lib_config_intf(rt2x00dev, intf,
 +                            vif->type, intf->mac, intf->bssid);
 +
 +
 +      /*
 +       * Master or Ad-hoc mode require a new beacon update.
 +       */
 +      if (vif->type == IEEE80211_IF_TYPE_AP ||
 +          vif->type == IEEE80211_IF_TYPE_IBSS)
 +              intf->delayed_flags |= DELAYED_UPDATE_BEACON;
 +
 +      spin_unlock(&intf->lock);
 +}
 +
  int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
  {
 -      struct interface *intf = &rt2x00dev->interface;
        int retval;
  
        NOTICE(rt2x00dev, "Waking up.\n");
  
        /*
-        * Open the debugfs entry and restore led handling.
+        * Restore/enable extra components.
         */
        rt2x00debug_register(rt2x00dev);
+       rt2x00rfkill_resume(rt2x00dev);
 +      rt2x00leds_resume(rt2x00dev);
  
        /*
         * Only continue if mac80211 had open interfaces.
        if (!rt2x00dev->hw->conf.radio_enabled)
                rt2x00lib_disable_radio(rt2x00dev);
  
 -      rt2x00lib_config_mac_addr(rt2x00dev, intf->mac);
 -      rt2x00lib_config_bssid(rt2x00dev, intf->bssid);
 -      rt2x00lib_config_type(rt2x00dev, intf->type);
 +      /*
 +       * Iterator over each active interface to
 +       * reconfigure the hardware.
 +       */
 +      ieee80211_iterate_active_interfaces(rt2x00dev->hw,
 +                                          rt2x00lib_resume_intf, rt2x00dev);
  
        /*
         * We are ready again to receive requests from mac80211.
        ieee80211_start_queues(rt2x00dev->hw);
  
        /*
 -       * When in Master or Ad-hoc mode,
 -       * restart Beacon transmitting by faking a beacondone event.
 +       * During interface iteration we might have changed the
 +       * delayed_flags, time to handles the event by calling
 +       * the work handler directly.
         */
 -      if (intf->type == IEEE80211_IF_TYPE_AP ||
 -          intf->type == IEEE80211_IF_TYPE_IBSS)
 -              rt2x00lib_beacondone(rt2x00dev);
 +      rt2x00lib_intf_scheduled(&rt2x00dev->intf_work);
  
        return 0;
  
@@@ -1,5 -1,5 +1,5 @@@
  /*
 -      Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
 +      Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
  
        This program is free software; you can redistribute it and/or modify
  #define RFKILL_POLL_INTERVAL  ( 1000 )
  
  /*
 + * rt2x00_rate: Per rate device information
 + */
 +struct rt2x00_rate {
 +      unsigned short flags;
 +#define DEV_RATE_CCK                  0x0001
 +#define DEV_RATE_OFDM                 0x0002
 +#define DEV_RATE_SHORT_PREAMBLE               0x0004
 +#define DEV_RATE_BASIC                        0x0008
 +
 +      unsigned short bitrate; /* In 100kbit/s */
 +      unsigned short ratemask;
 +
 +      unsigned short plcp;
 +};
 +
 +extern const struct rt2x00_rate rt2x00_supported_rates[12];
 +
 +static inline u16 rt2x00_create_rate_hw_value(const u16 index,
 +                                            const u16 short_preamble)
 +{
 +      return (short_preamble << 8) | (index & 0xff);
 +}
 +
 +static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value)
 +{
 +      return &rt2x00_supported_rates[hw_value & 0xff];
 +}
 +
 +static inline int rt2x00_get_rate_preamble(const u16 hw_value)
 +{
 +      return (hw_value & 0xff00);
 +}
 +
 +/*
   * Radio control handlers.
   */
  int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev);
@@@ -84,29 -50,15 +84,29 @@@ void rt2x00lib_stop(struct rt2x00_dev *
  /*
   * Configuration handlers.
   */
 -void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac);
 -void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid);
 -void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type);
 +void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
 +                         struct rt2x00_intf *intf,
 +                         enum ieee80211_if_types type,
 +                         u8 *mac, u8 *bssid);
 +void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
 +                        struct rt2x00_intf *intf,
 +                        struct ieee80211_bss_conf *conf);
  void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
                              enum antenna rx, enum antenna tx);
  void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
                      struct ieee80211_conf *conf, const int force_config);
  
  /*
 + * Queue handlers.
 + */
 +void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev);
 +void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev);
 +int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev);
 +void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev);
 +int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev);
 +void rt2x00queue_free(struct rt2x00_dev *rt2x00dev);
 +
 +/*
   * Firmware handlers.
   */
  #ifdef CONFIG_RT2X00_LIB_FIRMWARE
@@@ -148,60 -100,36 +148,68 @@@ static inline void rt2x00debug_dump_fra
   * RFkill handlers.
   */
  #ifdef CONFIG_RT2X00_LIB_RFKILL
int rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev);
void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev);
  void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev);
int rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev);
void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev);
  void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev);
+ void rt2x00rfkill_suspend(struct rt2x00_dev *rt2x00dev);
+ void rt2x00rfkill_resume(struct rt2x00_dev *rt2x00dev);
  #else
- static inline int rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
+ static inline void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
  {
-       return 0;
  }
  
  static inline void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
  {
  }
  
- static inline int rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
+ static inline void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
  {
-       return 0;
  }
  
  static inline void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
  {
  }
+ static inline void rt2x00rfkill_suspend(struct rt2x00_dev *rt2x00dev)
+ {
+ }
+ static inline void rt2x00rfkill_resume(struct rt2x00_dev *rt2x00dev)
+ {
+ }
  #endif /* CONFIG_RT2X00_LIB_RFKILL */
  
 +/*
 + * LED handlers
 + */
 +#ifdef CONFIG_RT2X00_LIB_LEDS
 +void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi);
 +void rt2x00leds_register(struct rt2x00_dev *rt2x00dev);
 +void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev);
 +void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev);
 +void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev);
 +#else
 +static inline void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev,
 +                                        int rssi)
 +{
 +}
 +
 +static inline void rt2x00leds_register(struct rt2x00_dev *rt2x00dev)
 +{
 +}
 +
 +static inline void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev)
 +{
 +}
 +
 +static inline void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev)
 +{
 +}
 +
 +static inline void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev)
 +{
 +}
 +#endif /* CONFIG_RT2X00_LIB_LEDS */
 +
  #endif /* RT2X00LIB_H */
@@@ -1,5 -1,5 +1,5 @@@
  /*
 -      Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
 +      Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
  
        This program is free software; you can redistribute it and/or modify
@@@ -69,56 -69,81 +69,81 @@@ static void rt2x00rfkill_poll(struct in
        }
  }
  
int rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
  {
-       int retval;
-       if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
-               return 0;
+       if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags) ||
+           !test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state))
+               return;
  
-       retval = rfkill_register(rt2x00dev->rfkill);
-       if (retval) {
+       if (rfkill_register(rt2x00dev->rfkill)) {
                ERROR(rt2x00dev, "Failed to register rfkill handler.\n");
-               return retval;
+               return;
        }
  
-       retval = input_register_polled_device(rt2x00dev->poll_dev);
-       if (retval) {
+       if (input_register_polled_device(rt2x00dev->poll_dev)) {
                ERROR(rt2x00dev, "Failed to register polled device.\n");
                rfkill_unregister(rt2x00dev->rfkill);
-               return retval;
+               return;
        }
  
+       __set_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state);
        /*
         * Force initial poll which will detect the initial device state,
         * and correctly sends the signal to the rfkill layer about this
         * state.
         */
        rt2x00rfkill_poll(rt2x00dev->poll_dev);
-       return 0;
  }
  
  void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
  {
-       if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
+       if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags) ||
+           !test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state))
                return;
  
        input_unregister_polled_device(rt2x00dev->poll_dev);
        rfkill_unregister(rt2x00dev->rfkill);
+       __clear_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state);
  }
  
- int rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
+ static struct input_polled_dev *
+ rt2x00rfkill_allocate_polldev(struct rt2x00_dev *rt2x00dev)
  {
-       struct device *device = wiphy_dev(rt2x00dev->hw->wiphy);
+       struct input_polled_dev *poll_dev;
+       poll_dev = input_allocate_polled_device();
+       if (!poll_dev)
+               return NULL;
+       poll_dev->private = rt2x00dev;
+       poll_dev->poll = rt2x00rfkill_poll;
+       poll_dev->poll_interval = RFKILL_POLL_INTERVAL;
+       poll_dev->input->name = rt2x00dev->ops->name;
+       poll_dev->input->phys = wiphy_name(rt2x00dev->hw->wiphy);
+       poll_dev->input->id.bustype = BUS_HOST;
+       poll_dev->input->id.vendor = 0x1814;
+       poll_dev->input->id.product = rt2x00dev->chip.rt;
+       poll_dev->input->id.version = rt2x00dev->chip.rev;
+       poll_dev->input->dev.parent = wiphy_dev(rt2x00dev->hw->wiphy);
+       poll_dev->input->evbit[0] = BIT(EV_KEY);
+       set_bit(KEY_WLAN, poll_dev->input->keybit);
+       return poll_dev;
+ }
  
+ void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
+ {
        if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
-               return 0;
+               return;
  
-       rt2x00dev->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN);
+       rt2x00dev->rfkill =
+           rfkill_allocate(wiphy_dev(rt2x00dev->hw->wiphy), RFKILL_TYPE_WLAN);
        if (!rt2x00dev->rfkill) {
                ERROR(rt2x00dev, "Failed to allocate rfkill handler.\n");
-               goto exit;
+               return;
        }
  
        rt2x00dev->rfkill->name = rt2x00dev->ops->name;
        rt2x00dev->rfkill->state = -1;
        rt2x00dev->rfkill->toggle_radio = rt2x00rfkill_toggle_radio;
  
-       rt2x00dev->poll_dev = input_allocate_polled_device();
+       rt2x00dev->poll_dev = rt2x00rfkill_allocate_polldev(rt2x00dev);
        if (!rt2x00dev->poll_dev) {
                ERROR(rt2x00dev, "Failed to allocate polled device.\n");
-               goto exit_free_rfkill;
+               rfkill_free(rt2x00dev->rfkill);
+               rt2x00dev->rfkill = NULL;
+               return;
        }
  
-       rt2x00dev->poll_dev->private = rt2x00dev;
-       rt2x00dev->poll_dev->poll = rt2x00rfkill_poll;
-       rt2x00dev->poll_dev->poll_interval = RFKILL_POLL_INTERVAL;
+       return;
+ }
  
-       rt2x00dev->poll_dev->input->name = rt2x00dev->ops->name;
-       rt2x00dev->poll_dev->input->phys = wiphy_name(rt2x00dev->hw->wiphy);
-       rt2x00dev->poll_dev->input->id.bustype = BUS_HOST;
-       rt2x00dev->poll_dev->input->id.vendor = 0x1814;
-       rt2x00dev->poll_dev->input->id.product = rt2x00dev->chip.rt;
-       rt2x00dev->poll_dev->input->id.version = rt2x00dev->chip.rev;
-       rt2x00dev->poll_dev->input->dev.parent = device;
-       rt2x00dev->poll_dev->input->evbit[0] = BIT(EV_KEY);
-       set_bit(KEY_WLAN, rt2x00dev->poll_dev->input->keybit);
+ void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
+ {
+       if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags) ||
+           !test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state))
+               return;
  
-       return 0;
+       input_free_polled_device(rt2x00dev->poll_dev);
+       rt2x00dev->poll_dev = NULL;
  
- exit_free_rfkill:
        rfkill_free(rt2x00dev->rfkill);
- exit:
-       return -ENOMEM;
+       rt2x00dev->rfkill = NULL;
  }
  
- void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
+ void rt2x00rfkill_suspend(struct rt2x00_dev *rt2x00dev)
  {
-       if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
+       if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags) ||
+           !test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state))
                return;
  
        input_free_polled_device(rt2x00dev->poll_dev);
-       rfkill_free(rt2x00dev->rfkill);
+       rt2x00dev->poll_dev = NULL;
+ }
+ void rt2x00rfkill_resume(struct rt2x00_dev *rt2x00dev)
+ {
+       if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags) ||
+           !test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state))
+               return;
+       rt2x00dev->poll_dev = rt2x00rfkill_allocate_polldev(rt2x00dev);
+       if (!rt2x00dev->poll_dev) {
+               ERROR(rt2x00dev, "Failed to allocate polled device.\n");
+               return;
+       }
  }
@@@ -1,5 -1,5 +1,5 @@@
  /*
 -      Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
 +      Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
  
        This program is free software; you can redistribute it and/or modify
@@@ -24,7 -24,6 +24,7 @@@
        Supported chipsets: RT2561, RT2561s, RT2661.
   */
  
 +#include <linux/crc-itu-t.h>
  #include <linux/delay.h>
  #include <linux/etherdevice.h>
  #include <linux/init.h>
@@@ -156,12 -155,6 +156,12 @@@ rf_write
        rt2x00_rf_write(rt2x00dev, word, value);
  }
  
 +#ifdef CONFIG_RT61PCI_LEDS
 +/*
 + * This function is only called from rt61pci_led_brightness()
 + * make gcc happy by placing this function inside the
 + * same ifdef statement as the caller.
 + */
  static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,
                                const u8 command, const u8 token,
                                const u8 arg0, const u8 arg1)
        rt2x00_set_field32(&reg, HOST_CMD_CSR_INTERRUPT_MCU, 1);
        rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg);
  }
 +#endif /* CONFIG_RT61PCI_LEDS */
  
  static void rt61pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
  {
@@@ -270,119 -262,83 +270,119 @@@ static int rt61pci_rfkill_poll(struct r
        u32 reg;
  
        rt2x00pci_register_read(rt2x00dev, MAC_CSR13, &reg);
 -      return rt2x00_get_field32(reg, MAC_CSR13_BIT5);;
 +      return rt2x00_get_field32(reg, MAC_CSR13_BIT5);
  }
  #else
  #define rt61pci_rfkill_poll   NULL
  #endif /* CONFIG_RT61PCI_RFKILL */
  
 +#ifdef CONFIG_RT61PCI_LEDS
 +static void rt61pci_led_brightness(struct led_classdev *led_cdev,
 +                                 enum led_brightness brightness)
 +{
 +      struct rt2x00_led *led =
 +          container_of(led_cdev, struct rt2x00_led, led_dev);
 +      unsigned int enabled = brightness != LED_OFF;
 +      unsigned int a_mode =
 +          (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
 +      unsigned int bg_mode =
 +          (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
 +
 +      if (led->type == LED_TYPE_RADIO) {
 +              rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
 +                                 MCU_LEDCS_RADIO_STATUS, enabled);
 +
 +              rt61pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff,
 +                                  (led->rt2x00dev->led_mcu_reg & 0xff),
 +                                  ((led->rt2x00dev->led_mcu_reg >> 8)));
 +      } else if (led->type == LED_TYPE_ASSOC) {
 +              rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
 +                                 MCU_LEDCS_LINK_BG_STATUS, bg_mode);
 +              rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
 +                                 MCU_LEDCS_LINK_A_STATUS, a_mode);
 +
 +              rt61pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff,
 +                                  (led->rt2x00dev->led_mcu_reg & 0xff),
 +                                  ((led->rt2x00dev->led_mcu_reg >> 8)));
 +      } else if (led->type == LED_TYPE_QUALITY) {
 +              /*
 +               * The brightness is divided into 6 levels (0 - 5),
 +               * this means we need to convert the brightness
 +               * argument into the matching level within that range.
 +               */
 +              rt61pci_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff,
 +                                  brightness / (LED_FULL / 6), 0);
 +      }
 +}
 +#else
 +#define rt61pci_led_brightness        NULL
 +#endif /* CONFIG_RT61PCI_LEDS */
 +
  /*
   * Configuration handlers.
   */
 -static void rt61pci_config_mac_addr(struct rt2x00_dev *rt2x00dev, __le32 *mac)
 +static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
 +                              struct rt2x00_intf *intf,
 +                              struct rt2x00intf_conf *conf,
 +                              const unsigned int flags)
  {
 -      u32 tmp;
 -
 -      tmp = le32_to_cpu(mac[1]);
 -      rt2x00_set_field32(&tmp, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
 -      mac[1] = cpu_to_le32(tmp);
 -
 -      rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2, mac,
 -                                    (2 * sizeof(__le32)));
 -}
 +      unsigned int beacon_base;
 +      u32 reg;
  
 -static void rt61pci_config_bssid(struct rt2x00_dev *rt2x00dev, __le32 *bssid)
 -{
 -      u32 tmp;
 +      if (flags & CONFIG_UPDATE_TYPE) {
 +              /*
 +               * Clear current synchronisation setup.
 +               * For the Beacon base registers we only need to clear
 +               * the first byte since that byte contains the VALID and OWNER
 +               * bits which (when set to 0) will invalidate the entire beacon.
 +               */
 +              beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
 +              rt2x00pci_register_write(rt2x00dev, beacon_base, 0);
  
 -      tmp = le32_to_cpu(bssid[1]);
 -      rt2x00_set_field32(&tmp, MAC_CSR5_BSS_ID_MASK, 3);
 -      bssid[1] = cpu_to_le32(tmp);
 +              /*
 +               * Enable synchronisation.
 +               */
 +              rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
 +              rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
 +              rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
 +              rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
 +              rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
 +      }
  
 -      rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4, bssid,
 -                                    (2 * sizeof(__le32)));
 -}
 +      if (flags & CONFIG_UPDATE_MAC) {
 +              reg = le32_to_cpu(conf->mac[1]);
 +              rt2x00_set_field32(&reg, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
 +              conf->mac[1] = cpu_to_le32(reg);
  
 -static void rt61pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
 -                              const int tsf_sync)
 -{
 -      u32 reg;
 +              rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2,
 +                                            conf->mac, sizeof(conf->mac));
 +      }
  
 -      /*
 -       * Clear current synchronisation setup.
 -       * For the Beacon base registers we only need to clear
 -       * the first byte since that byte contains the VALID and OWNER
 -       * bits which (when set to 0) will invalidate the entire beacon.
 -       */
 -      rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0);
 -      rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
 -      rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
 -      rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
 -      rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
 +      if (flags & CONFIG_UPDATE_BSSID) {
 +              reg = le32_to_cpu(conf->bssid[1]);
 +              rt2x00_set_field32(&reg, MAC_CSR5_BSS_ID_MASK, 3);
 +              conf->bssid[1] = cpu_to_le32(reg);
  
 -      /*
 -       * Enable synchronisation.
 -       */
 -      rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
 -      rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
 -      rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE,
 -                        (tsf_sync == TSF_SYNC_BEACON));
 -      rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
 -      rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, tsf_sync);
 -      rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
 +              rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4,
 +                                            conf->bssid, sizeof(conf->bssid));
 +      }
  }
  
 -static void rt61pci_config_preamble(struct rt2x00_dev *rt2x00dev,
 -                                  const int short_preamble,
 -                                  const int ack_timeout,
 -                                  const int ack_consume_time)
 +static int rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
 +                            struct rt2x00lib_erp *erp)
  {
        u32 reg;
  
        rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
 -      rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout);
 +      rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout);
        rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
  
        rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
        rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
 -                         !!short_preamble);
 +                         !!erp->short_preamble);
        rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
 +
 +      return 0;
  }
  
  static void rt61pci_config_phymode(struct rt2x00_dev *rt2x00dev,
@@@ -471,21 -427,27 +471,21 @@@ static void rt61pci_config_antenna_5x(s
        case ANTENNA_HW_DIVERSITY:
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
                rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
 -                                (rt2x00dev->curr_hwmode != HWMODE_A));
 +                                (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ));
                break;
        case ANTENNA_A:
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
                rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
 -              if (rt2x00dev->curr_hwmode == HWMODE_A)
 +              if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
                        rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
                else
                        rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
                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:
 +      default:
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
                rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
 -              if (rt2x00dev->curr_hwmode == HWMODE_A)
 +              if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
                        rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
                else
                        rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
@@@ -524,8 -486,14 +524,8 @@@ static void rt61pci_config_antenna_2x(s
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
                rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
                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:
 +      default:
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
                rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
                break;
@@@ -563,6 -531,10 +563,6 @@@ static void rt61pci_config_antenna_2529
        rt61pci_bbp_read(rt2x00dev, 4, &r4);
        rt61pci_bbp_read(rt2x00dev, 77, &r77);
  
 -      /* FIXME: Antenna selection for the rf 2529 is very confusing in the
 -       * legacy driver. The code below should be ok for non-diversity setups.
 -       */
 -
        /*
         * Configure the RX antenna.
         */
                rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
                rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 0);
                break;
 -      case ANTENNA_SW_DIVERSITY:
        case ANTENNA_HW_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.
 +               * FIXME: Antenna selection for the rf 2529 is very confusing
 +               * in the legacy driver. Just default to antenna B until the
 +               * legacy code can be properly translated into rt2x00 code.
                 */
        case ANTENNA_B:
 +      default:
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
                rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
                rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1);
@@@ -630,14 -603,7 +630,14 @@@ static void rt61pci_config_antenna(stru
        unsigned int i;
        u32 reg;
  
 -      if (rt2x00dev->curr_hwmode == HWMODE_A) {
 +      /*
 +       * We should never come here because rt2x00lib is supposed
 +       * to catch this and send us the correct antenna explicitely.
 +       */
 +      BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
 +             ant->tx == ANTENNA_SW_DIVERSITY);
 +
 +      if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
                sel = antenna_sel_a;
                lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
        } else {
        rt2x00pci_register_read(rt2x00dev, PHY_CSR0, &reg);
  
        rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
 -                         (rt2x00dev->curr_hwmode == HWMODE_B ||
 -                          rt2x00dev->curr_hwmode == HWMODE_G));
 +                         rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
        rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A,
 -                         (rt2x00dev->curr_hwmode == HWMODE_A));
 +                         rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
  
        rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg);
  
@@@ -700,8 -667,8 +700,8 @@@ static void rt61pci_config_duration(str
  }
  
  static void rt61pci_config(struct rt2x00_dev *rt2x00dev,
 -                         const unsigned int flags,
 -                         struct rt2x00lib_conf *libconf)
 +                         struct rt2x00lib_conf *libconf,
 +                         const unsigned int flags)
  {
        if (flags & CONFIG_UPDATE_PHYMODE)
                rt61pci_config_phymode(rt2x00dev, libconf->basic_rates);
  }
  
  /*
 - * LED functions.
 - */
 -static void rt61pci_enable_led(struct rt2x00_dev *rt2x00dev)
 -{
 -      u32 reg;
 -      u8 arg0;
 -      u8 arg1;
 -
 -      rt2x00pci_register_read(rt2x00dev, MAC_CSR14, &reg);
 -      rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, 70);
 -      rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, 30);
 -      rt2x00pci_register_write(rt2x00dev, MAC_CSR14, reg);
 -
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1);
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS,
 -                         (rt2x00dev->rx_status.phymode == MODE_IEEE80211A));
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS,
 -                         (rt2x00dev->rx_status.phymode != MODE_IEEE80211A));
 -
 -      arg0 = rt2x00dev->led_reg & 0xff;
 -      arg1 = (rt2x00dev->led_reg >> 8) & 0xff;
 -
 -      rt61pci_mcu_request(rt2x00dev, MCU_LED, 0xff, arg0, arg1);
 -}
 -
 -static void rt61pci_disable_led(struct rt2x00_dev *rt2x00dev)
 -{
 -      u16 led_reg;
 -      u8 arg0;
 -      u8 arg1;
 -
 -      led_reg = rt2x00dev->led_reg;
 -      rt2x00_set_field16(&led_reg, MCU_LEDCS_RADIO_STATUS, 0);
 -      rt2x00_set_field16(&led_reg, MCU_LEDCS_LINK_BG_STATUS, 0);
 -      rt2x00_set_field16(&led_reg, MCU_LEDCS_LINK_A_STATUS, 0);
 -
 -      arg0 = led_reg & 0xff;
 -      arg1 = (led_reg >> 8) & 0xff;
 -
 -      rt61pci_mcu_request(rt2x00dev, MCU_LED, 0xff, arg0, arg1);
 -}
 -
 -static void rt61pci_activity_led(struct rt2x00_dev *rt2x00dev, int rssi)
 -{
 -      u8 led;
 -
 -      if (rt2x00dev->led_mode != LED_MODE_SIGNAL_STRENGTH)
 -              return;
 -
 -      /*
 -       * Led handling requires a positive value for the rssi,
 -       * to do that correctly we need to add the correction.
 -       */
 -      rssi += rt2x00dev->rssi_offset;
 -
 -      if (rssi <= 30)
 -              led = 0;
 -      else if (rssi <= 39)
 -              led = 1;
 -      else if (rssi <= 49)
 -              led = 2;
 -      else if (rssi <= 53)
 -              led = 3;
 -      else if (rssi <= 63)
 -              led = 4;
 -      else
 -              led = 5;
 -
 -      rt61pci_mcu_request(rt2x00dev, MCU_LED_STRENGTH, 0xff, led, 0);
 -}
 -
 -/*
   * Link tuning
   */
  static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev,
@@@ -750,12 -789,17 +750,12 @@@ static void rt61pci_link_tuner(struct r
        u8 up_bound;
        u8 low_bound;
  
 -      /*
 -       * Update Led strength
 -       */
 -      rt61pci_activity_led(rt2x00dev, rssi);
 -
        rt61pci_bbp_read(rt2x00dev, 17, &r17);
  
        /*
         * Determine r17 bounds.
         */
 -      if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
 +      if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
                low_bound = 0x28;
                up_bound = 0x48;
                if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
        }
  
        /*
 +       * If we are not associated, we should go straight to the
 +       * dynamic CCA tuning.
 +       */
 +      if (!rt2x00dev->intf_associated)
 +              goto dynamic_cca_tune;
 +
 +      /*
         * Special big-R17 for very short distance
         */
        if (rssi >= -35) {
                return;
        }
  
 +dynamic_cca_tune:
 +
        /*
         * r17 does not yet exceed upper limit, continue and base
         * the r17 tuning on the false CCA count.
  }
  
  /*
 - * Firmware name function.
 + * Firmware functions
   */
  static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
  {
        return fw_name;
  }
  
 -/*
 - * Initialization functions.
 - */
 +static u16 rt61pci_get_firmware_crc(void *data, const size_t len)
 +{
 +      u16 crc;
 +
 +      /*
 +       * Use the crc itu-t algorithm.
 +       * The last 2 bytes in the firmware array are the crc checksum itself,
 +       * this means that we should never pass those 2 bytes to the crc
 +       * algorithm.
 +       */
 +      crc = crc_itu_t(0, data, len - 2);
 +      crc = crc_itu_t_byte(crc, 0);
 +      crc = crc_itu_t_byte(crc, 0);
 +
 +      return crc;
 +}
 +
  static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
                                 const size_t len)
  {
        return 0;
  }
  
 +/*
 + * Initialization functions.
 + */
  static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
 -                               struct data_entry *entry)
 +                               struct queue_entry *entry)
  {
 -      __le32 *rxd = entry->priv;
 +      struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
        u32 word;
  
 -      rt2x00_desc_read(rxd, 5, &word);
 +      rt2x00_desc_read(priv_rx->desc, 5, &word);
        rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS,
 -                         entry->data_dma);
 -      rt2x00_desc_write(rxd, 5, word);
 +                         priv_rx->data_dma);
 +      rt2x00_desc_write(priv_rx->desc, 5, word);
  
 -      rt2x00_desc_read(rxd, 0, &word);
 +      rt2x00_desc_read(priv_rx->desc, 0, &word);
        rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
 -      rt2x00_desc_write(rxd, 0, word);
 +      rt2x00_desc_write(priv_rx->desc, 0, word);
  }
  
  static void rt61pci_init_txentry(struct rt2x00_dev *rt2x00dev,
 -                               struct data_entry *entry)
 +                               struct queue_entry *entry)
  {
 -      __le32 *txd = entry->priv;
 +      struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
        u32 word;
  
 -      rt2x00_desc_read(txd, 1, &word);
 +      rt2x00_desc_read(priv_tx->desc, 1, &word);
        rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
 -      rt2x00_desc_write(txd, 1, word);
 +      rt2x00_desc_write(priv_tx->desc, 1, word);
  
 -      rt2x00_desc_read(txd, 5, &word);
 -      rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->ring->queue_idx);
 +      rt2x00_desc_read(priv_tx->desc, 5, &word);
 +      rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->queue->qid);
        rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, entry->entry_idx);
 -      rt2x00_desc_write(txd, 5, word);
 +      rt2x00_desc_write(priv_tx->desc, 5, word);
  
 -      rt2x00_desc_read(txd, 6, &word);
 +      rt2x00_desc_read(priv_tx->desc, 6, &word);
        rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
 -                         entry->data_dma);
 -      rt2x00_desc_write(txd, 6, word);
 +                         priv_tx->data_dma);
 +      rt2x00_desc_write(priv_tx->desc, 6, word);
  
 -      rt2x00_desc_read(txd, 0, &word);
 +      rt2x00_desc_read(priv_tx->desc, 0, &word);
        rt2x00_set_field32(&word, TXD_W0_VALID, 0);
        rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
 -      rt2x00_desc_write(txd, 0, word);
 +      rt2x00_desc_write(priv_tx->desc, 0, word);
  }
  
 -static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev)
 +static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
  {
 +      struct queue_entry_priv_pci_rx *priv_rx;
 +      struct queue_entry_priv_pci_tx *priv_tx;
        u32 reg;
  
        /*
         */
        rt2x00pci_register_read(rt2x00dev, TX_RING_CSR0, &reg);
        rt2x00_set_field32(&reg, TX_RING_CSR0_AC0_RING_SIZE,
 -                         rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit);
 +                         rt2x00dev->tx[0].limit);
        rt2x00_set_field32(&reg, TX_RING_CSR0_AC1_RING_SIZE,
 -                         rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit);
 +                         rt2x00dev->tx[1].limit);
        rt2x00_set_field32(&reg, TX_RING_CSR0_AC2_RING_SIZE,
 -                         rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA2].stats.limit);
 +                         rt2x00dev->tx[2].limit);
        rt2x00_set_field32(&reg, TX_RING_CSR0_AC3_RING_SIZE,
 -                         rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA3].stats.limit);
 +                         rt2x00dev->tx[3].limit);
        rt2x00pci_register_write(rt2x00dev, TX_RING_CSR0, reg);
  
        rt2x00pci_register_read(rt2x00dev, TX_RING_CSR1, &reg);
 -      rt2x00_set_field32(&reg, TX_RING_CSR1_MGMT_RING_SIZE,
 -                         rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA4].stats.limit);
        rt2x00_set_field32(&reg, TX_RING_CSR1_TXD_SIZE,
 -                         rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size /
 -                         4);
 +                         rt2x00dev->tx[0].desc_size / 4);
        rt2x00pci_register_write(rt2x00dev, TX_RING_CSR1, reg);
  
 +      priv_tx = rt2x00dev->tx[0].entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, AC0_BASE_CSR, &reg);
        rt2x00_set_field32(&reg, AC0_BASE_CSR_RING_REGISTER,
 -                         rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma);
 +                         priv_tx->desc_dma);
        rt2x00pci_register_write(rt2x00dev, AC0_BASE_CSR, reg);
  
 +      priv_tx = rt2x00dev->tx[1].entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, AC1_BASE_CSR, &reg);
        rt2x00_set_field32(&reg, AC1_BASE_CSR_RING_REGISTER,
 -                         rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma);
 +                         priv_tx->desc_dma);
        rt2x00pci_register_write(rt2x00dev, AC1_BASE_CSR, reg);
  
 +      priv_tx = rt2x00dev->tx[2].entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, AC2_BASE_CSR, &reg);
        rt2x00_set_field32(&reg, AC2_BASE_CSR_RING_REGISTER,
 -                         rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA2].data_dma);
 +                         priv_tx->desc_dma);
        rt2x00pci_register_write(rt2x00dev, AC2_BASE_CSR, reg);
  
 +      priv_tx = rt2x00dev->tx[3].entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, AC3_BASE_CSR, &reg);
        rt2x00_set_field32(&reg, AC3_BASE_CSR_RING_REGISTER,
 -                         rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA3].data_dma);
 +                         priv_tx->desc_dma);
        rt2x00pci_register_write(rt2x00dev, AC3_BASE_CSR, reg);
  
 -      rt2x00pci_register_read(rt2x00dev, MGMT_BASE_CSR, &reg);
 -      rt2x00_set_field32(&reg, MGMT_BASE_CSR_RING_REGISTER,
 -                         rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA4].data_dma);
 -      rt2x00pci_register_write(rt2x00dev, MGMT_BASE_CSR, reg);
 -
        rt2x00pci_register_read(rt2x00dev, RX_RING_CSR, &reg);
 -      rt2x00_set_field32(&reg, RX_RING_CSR_RING_SIZE,
 -                         rt2x00dev->rx->stats.limit);
 +      rt2x00_set_field32(&reg, RX_RING_CSR_RING_SIZE, rt2x00dev->rx->limit);
        rt2x00_set_field32(&reg, RX_RING_CSR_RXD_SIZE,
                           rt2x00dev->rx->desc_size / 4);
        rt2x00_set_field32(&reg, RX_RING_CSR_RXD_WRITEBACK_SIZE, 4);
        rt2x00pci_register_write(rt2x00dev, RX_RING_CSR, reg);
  
 +      priv_rx = rt2x00dev->rx->entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, RX_BASE_CSR, &reg);
        rt2x00_set_field32(&reg, RX_BASE_CSR_RING_REGISTER,
 -                         rt2x00dev->rx->data_dma);
 +                         priv_rx->desc_dma);
        rt2x00pci_register_write(rt2x00dev, RX_BASE_CSR, reg);
  
        rt2x00pci_register_read(rt2x00dev, TX_DMA_DST_CSR, &reg);
        rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC1, 2);
        rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC2, 2);
        rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC3, 2);
 -      rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_MGMT, 0);
        rt2x00pci_register_write(rt2x00dev, TX_DMA_DST_CSR, reg);
  
        rt2x00pci_register_read(rt2x00dev, LOAD_TX_RING_CSR, &reg);
        rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC1, 1);
        rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC2, 1);
        rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC3, 1);
 -      rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_MGMT, 1);
        rt2x00pci_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg);
  
        rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, &reg);
@@@ -1172,11 -1194,6 +1172,11 @@@ static int rt61pci_init_registers(struc
  
        rt2x00pci_register_write(rt2x00dev, MAC_CSR13, 0x0000e000);
  
 +      rt2x00pci_register_read(rt2x00dev, MAC_CSR14, &reg);
 +      rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, 70);
 +      rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, 30);
 +      rt2x00pci_register_write(rt2x00dev, MAC_CSR14, reg);
 +
        /*
         * Invalidate all Shared Keys (SEC_CSR0),
         * and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5)
        rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR1, reg);
  
        /*
 +       * Clear all beacons
 +       * For the Beacon base registers we only need to clear
 +       * the first byte since that byte contains the VALID and OWNER
 +       * bits which (when set to 0) will invalidate the entire beacon.
 +       */
 +      rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
 +      rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
 +      rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
 +      rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
 +
 +      /*
         * We must clear the error counters.
         * These registers are cleared on read,
         * so we may pass a useless variable to store the value.
@@@ -1290,15 -1296,19 +1290,15 @@@ continue_csr_init
        rt61pci_bbp_write(rt2x00dev, 102, 0x16);
        rt61pci_bbp_write(rt2x00dev, 107, 0x04);
  
 -      DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
        for (i = 0; i < EEPROM_BBP_SIZE; i++) {
                rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
  
                if (eeprom != 0xffff && eeprom != 0x0000) {
                        reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
                        value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
 -                      DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
 -                            reg_id, value);
                        rt61pci_bbp_write(rt2x00dev, reg_id, value);
                }
        }
 -      DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
  
        return 0;
  }
@@@ -1365,7 -1375,7 +1365,7 @@@ static int rt61pci_enable_radio(struct 
        /*
         * Initialize all registers.
         */
 -      if (rt61pci_init_rings(rt2x00dev) ||
 +      if (rt61pci_init_queues(rt2x00dev) ||
            rt61pci_init_registers(rt2x00dev) ||
            rt61pci_init_bbp(rt2x00dev)) {
                ERROR(rt2x00dev, "Register initialization failed.\n");
        rt2x00_set_field32(&reg, RX_CNTL_CSR_ENABLE_RX_DMA, 1);
        rt2x00pci_register_write(rt2x00dev, RX_CNTL_CSR, reg);
  
 -      /*
 -       * Enable LED
 -       */
 -      rt61pci_enable_led(rt2x00dev);
 -
        return 0;
  }
  
@@@ -1391,6 -1406,11 +1391,6 @@@ static void rt61pci_disable_radio(struc
  {
        u32 reg;
  
 -      /*
 -       * Disable LED
 -       */
 -      rt61pci_disable_led(rt2x00dev);
 -
        rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
  
        /*
        rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC1, 1);
        rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC2, 1);
        rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC3, 1);
 -      rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_MGMT, 1);
        rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
  
        /*
@@@ -1487,10 -1508,10 +1487,10 @@@ static int rt61pci_set_device_state(str
   */
  static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
                                    struct sk_buff *skb,
 -                                  struct txdata_entry_desc *desc,
 +                                  struct txentry_desc *txdesc,
                                    struct ieee80211_tx_control *control)
  {
 -      struct skb_desc *skbdesc = get_skb_desc(skb);
 +      struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
        __le32 *txd = skbdesc->desc;
        u32 word;
  
         * Start writing the descriptor words.
         */
        rt2x00_desc_read(txd, 1, &word);
 -      rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, desc->queue);
 -      rt2x00_set_field32(&word, TXD_W1_AIFSN, desc->aifs);
 -      rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min);
 -      rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max);
 +      rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue);
 +      rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs);
 +      rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
 +      rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
        rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
        rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, 1);
        rt2x00_desc_write(txd, 1, word);
  
        rt2x00_desc_read(txd, 2, &word);
 -      rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, desc->signal);
 -      rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, desc->service);
 -      rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, desc->length_low);
 -      rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, desc->length_high);
 +      rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal);
 +      rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service);
 +      rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low);
 +      rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
        rt2x00_desc_write(txd, 2, word);
  
        rt2x00_desc_read(txd, 5, &word);
        rt2x00_set_field32(&word, TXD_W5_TX_POWER,
 -                         TXPOWER_TO_DEV(control->power_level));
 +                         TXPOWER_TO_DEV(rt2x00dev->tx_power));
        rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
        rt2x00_desc_write(txd, 5, word);
  
 -      rt2x00_desc_read(txd, 11, &word);
 -      rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skbdesc->data_len);
 -      rt2x00_desc_write(txd, 11, word);
 +      if (skbdesc->desc_len > TXINFO_SIZE) {
 +              rt2x00_desc_read(txd, 11, &word);
 +              rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skbdesc->data_len);
 +              rt2x00_desc_write(txd, 11, word);
 +      }
  
        rt2x00_desc_read(txd, 0, &word);
        rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
        rt2x00_set_field32(&word, TXD_W0_VALID, 1);
        rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
 -                         test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
 +                         test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_ACK,
 -                         test_bit(ENTRY_TXD_ACK, &desc->flags));
 +                         test_bit(ENTRY_TXD_ACK, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
 -                         test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
 +                         test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_OFDM,
 -                         test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags));
 -      rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
 +                         test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
 +      rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
        rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
                           !!(control->flags &
                              IEEE80211_TXCTL_LONG_RETRY_LIMIT));
        rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0);
        rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
        rt2x00_set_field32(&word, TXD_W0_BURST,
 -                         test_bit(ENTRY_TXD_BURST, &desc->flags));
 +                         test_bit(ENTRY_TXD_BURST, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
        rt2x00_desc_write(txd, 0, word);
  }
   * TX data initialization
   */
  static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
 -                                unsigned int queue)
 +                                const unsigned int queue)
  {
        u32 reg;
  
 -      if (queue == IEEE80211_TX_QUEUE_BEACON) {
 +      if (queue == RT2X00_BCN_QUEUE_BEACON) {
                /*
                 * For Wi-Fi faily generated beacons between participating
                 * stations. Set TBTT phase adaptive adjustment step to 8us.
  
                rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
                if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) {
 +                      rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
 +                      rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
                        rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
                        rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
                }
                           (queue == IEEE80211_TX_QUEUE_DATA2));
        rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC3,
                           (queue == IEEE80211_TX_QUEUE_DATA3));
 -      rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_MGMT,
 -                         (queue == IEEE80211_TX_QUEUE_DATA4));
        rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
  }
  
@@@ -1609,7 -1628,7 +1609,7 @@@ static int rt61pci_agc_to_rssi(struct r
                return 0;
        }
  
 -      if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
 +      if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
                if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
                        offset += 14;
  
        return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
  }
  
 -static void rt61pci_fill_rxdone(struct data_entry *entry,
 -                              struct rxdata_entry_desc *desc)
 +static void rt61pci_fill_rxdone(struct queue_entry *entry,
 +                              struct rxdone_entry_desc *rxdesc)
  {
 -      __le32 *rxd = entry->priv;
 +      struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
        u32 word0;
        u32 word1;
  
 -      rt2x00_desc_read(rxd, 0, &word0);
 -      rt2x00_desc_read(rxd, 1, &word1);
 +      rt2x00_desc_read(priv_rx->desc, 0, &word0);
 +      rt2x00_desc_read(priv_rx->desc, 1, &word1);
  
 -      desc->flags = 0;
 +      rxdesc->flags = 0;
        if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
 -              desc->flags |= RX_FLAG_FAILED_FCS_CRC;
 +              rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
  
        /*
         * Obtain the status about this packet.
 -       */
 -      desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
 -      desc->rssi = rt61pci_agc_to_rssi(entry->ring->rt2x00dev, word1);
 -      desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
 -      desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
 -      desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
 +       * When frame was received with an OFDM bitrate,
 +       * the signal is the PLCP value. If it was received with
 +       * a CCK bitrate the signal is the rate in 100kbit/s.
 +       */
 +      rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
 +      rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
 +      rxdesc->signal_plcp = rxdesc->ofdm;
 +      rxdesc->rssi = rt61pci_agc_to_rssi(entry->queue->rt2x00dev, word1);
 +      rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
 +      rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
  }
  
  /*
   */
  static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
  {
 -      struct data_ring *ring;
 -      struct data_entry *entry;
 -      struct data_entry *entry_done;
 -      __le32 *txd;
 +      struct data_queue *queue;
 +      struct queue_entry *entry;
 +      struct queue_entry *entry_done;
 +      struct queue_entry_priv_pci_tx *priv_tx;
 +      struct txdone_entry_desc txdesc;
        u32 word;
        u32 reg;
        u32 old_reg;
        int type;
        int index;
 -      int tx_status;
 -      int retry;
  
        /*
         * During each loop we will compare the freshly read
  
                /*
                 * Skip this entry when it contains an invalid
 -               * ring identication number.
 +               * queue identication number.
                 */
                type = rt2x00_get_field32(reg, STA_CSR4_PID_TYPE);
 -              ring = rt2x00lib_get_ring(rt2x00dev, type);
 -              if (unlikely(!ring))
 +              queue = rt2x00queue_get_queue(rt2x00dev, type);
 +              if (unlikely(!queue))
                        continue;
  
                /*
                 * index number.
                 */
                index = rt2x00_get_field32(reg, STA_CSR4_PID_SUBTYPE);
 -              if (unlikely(index >= ring->stats.limit))
 +              if (unlikely(index >= queue->limit))
                        continue;
  
 -              entry = &ring->entry[index];
 -              txd = entry->priv;
 -              rt2x00_desc_read(txd, 0, &word);
 +              entry = &queue->entries[index];
 +              priv_tx = entry->priv_data;
 +              rt2x00_desc_read(priv_tx->desc, 0, &word);
  
                if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
                    !rt2x00_get_field32(word, TXD_W0_VALID))
                        return;
  
 -              entry_done = rt2x00_get_data_entry_done(ring);
 +              entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
                while (entry != entry_done) {
 -                      /* Catch up. Just report any entries we missed as
 -                       * failed. */
 +                      /* Catch up.
 +                       * Just report any entries we missed as failed.
 +                       */
                        WARNING(rt2x00dev,
 -                              "TX status report missed for entry %p\n",
 -                              entry_done);
 -                      rt2x00pci_txdone(rt2x00dev, entry_done, TX_FAIL_OTHER,
 -                                       0);
 -                      entry_done = rt2x00_get_data_entry_done(ring);
 +                              "TX status report missed for entry %d\n",
 +                              entry_done->entry_idx);
 +
 +                      txdesc.status = TX_FAIL_OTHER;
 +                      txdesc.retry = 0;
 +
 +                      rt2x00pci_txdone(rt2x00dev, entry_done, &txdesc);
 +                      entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
                }
  
                /*
                 * Obtain the status about this packet.
                 */
 -              tx_status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT);
 -              retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
 +              txdesc.status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT);
 +              txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
  
 -              rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry);
 +              rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
        }
  }
  
@@@ -1894,7 -1906,7 +1894,7 @@@ static int rt61pci_validate_eeprom(stru
                rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
                rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
                rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
 -              EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
 +              EEPROM(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
        } else {
                value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
                if (value < -10 || value > 10)
@@@ -2023,51 -2035,35 +2023,51 @@@ static int rt61pci_init_eeprom(struct r
         * If the eeprom value is invalid,
         * switch to default led mode.
         */
 +#ifdef CONFIG_RT61PCI_LEDS
        rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
  
 -      rt2x00dev->led_mode = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE);
 +      value = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE);
 +
 +      switch (value) {
 +      case LED_MODE_TXRX_ACTIVITY:
 +      case LED_MODE_ASUS:
 +      case LED_MODE_ALPHA:
 +      case LED_MODE_DEFAULT:
 +              rt2x00dev->led_flags =
 +                  LED_SUPPORT_RADIO | LED_SUPPORT_ASSOC;
 +              break;
 +      case LED_MODE_SIGNAL_STRENGTH:
 +              rt2x00dev->led_flags =
 +                  LED_SUPPORT_RADIO | LED_SUPPORT_ASSOC |
 +                  LED_SUPPORT_QUALITY;
 +              break;
 +      }
  
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LED_MODE,
 -                         rt2x00dev->led_mode);
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_0,
 +      rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value);
 +      rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0,
                           rt2x00_get_field16(eeprom,
                                              EEPROM_LED_POLARITY_GPIO_0));
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_1,
 +      rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_1,
                           rt2x00_get_field16(eeprom,
                                              EEPROM_LED_POLARITY_GPIO_1));
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_2,
 +      rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_2,
                           rt2x00_get_field16(eeprom,
                                              EEPROM_LED_POLARITY_GPIO_2));
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_3,
 +      rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_3,
                           rt2x00_get_field16(eeprom,
                                              EEPROM_LED_POLARITY_GPIO_3));
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_4,
 +      rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_4,
                           rt2x00_get_field16(eeprom,
                                              EEPROM_LED_POLARITY_GPIO_4));
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_ACT,
 +      rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_ACT,
                           rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT));
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_BG,
 +      rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_BG,
                           rt2x00_get_field16(eeprom,
                                              EEPROM_LED_POLARITY_RDY_G));
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_A,
 +      rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A,
                           rt2x00_get_field16(eeprom,
                                              EEPROM_LED_POLARITY_RDY_A));
 +#endif /* CONFIG_RT61PCI_LEDS */
  
        return 0;
  }
@@@ -2201,7 -2197,7 +2201,7 @@@ static void rt61pci_probe_hw_mode(struc
        rt2x00dev->hw->extra_tx_headroom = 0;
        rt2x00dev->hw->max_signal = MAX_SIGNAL;
        rt2x00dev->hw->max_rssi = MAX_RX_SSI;
 -      rt2x00dev->hw->queues = 5;
 +      rt2x00dev->hw->queues = 4;
  
        SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
        SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
        /*
         * Initialize hw_mode information.
         */
 -      spec->num_modes = 2;
 -      spec->num_rates = 12;
 +      spec->supported_bands = SUPPORT_BAND_2GHZ;
 +      spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
        spec->tx_power_a = NULL;
        spec->tx_power_bg = txpower;
        spec->tx_power_default = DEFAULT_TXPOWER;
  
        if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
            rt2x00_rf(&rt2x00dev->chip, RF5325)) {
 -              spec->num_modes = 3;
 +              spec->supported_bands |= SUPPORT_BAND_5GHZ;
                spec->num_channels = ARRAY_SIZE(rf_vals_seq);
  
                txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
@@@ -2266,7 -2262,7 +2266,7 @@@ static int rt61pci_probe_hw(struct rt2x
        rt61pci_probe_hw_mode(rt2x00dev);
  
        /*
 -       * This device requires firmware
 +       * This device requires firmware.
         */
        __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
  
@@@ -2306,9 -2302,9 +2306,9 @@@ static void rt61pci_configure_filter(st
         * Apply some rules to the filters:
         * - Some filters imply different filters to be set.
         * - Some things we can't filter out at all.
+        * - Multicast filter seems to kill broadcast traffic so never use it.
         */
-       if (mc_count)
-               *total_flags |= FIF_ALLMULTI;
+       *total_flags |= FIF_ALLMULTI;
        if (*total_flags & FIF_OTHER_BSS ||
            *total_flags & FIF_PROMISC_IN_BSS)
                *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
        rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 1);
        rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST,
                           !(*total_flags & FIF_ALLMULTI));
 -      rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BORADCAST, 0);
 -      rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS, 1);
 +      rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BROADCAST, 0);
 +      rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS,
 +                         !(*total_flags & FIF_CONTROL));
        rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
  }
  
@@@ -2374,25 -2369,37 +2374,25 @@@ static u64 rt61pci_get_tsf(struct ieee8
        return tsf;
  }
  
 -static void rt61pci_reset_tsf(struct ieee80211_hw *hw)
 -{
 -      struct rt2x00_dev *rt2x00dev = hw->priv;
 -
 -      rt2x00pci_register_write(rt2x00dev, TXRX_CSR12, 0);
 -      rt2x00pci_register_write(rt2x00dev, TXRX_CSR13, 0);
 -}
 -
  static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
                          struct ieee80211_tx_control *control)
  {
        struct rt2x00_dev *rt2x00dev = hw->priv;
 -      struct skb_desc *desc;
 -      struct data_ring *ring;
 -      struct data_entry *entry;
 +      struct rt2x00_intf *intf = vif_to_intf(control->vif);
 +      struct skb_frame_desc *skbdesc;
 +      unsigned int beacon_base;
 +      u32 reg;
  
 -      /*
 -       * Just in case the ieee80211 doesn't set this,
 -       * but we need this queue set for the descriptor
 -       * initialization.
 -       */
 -      control->queue = IEEE80211_TX_QUEUE_BEACON;
 -      ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
 -      entry = rt2x00_get_data_entry(ring);
 +      if (unlikely(!intf->beacon))
 +              return -ENOBUFS;
  
        /*
         * We need to append the descriptor in front of the
         * beacon frame.
         */
 -      if (skb_headroom(skb) < TXD_DESC_SIZE) {
 -              if (pskb_expand_head(skb, TXD_DESC_SIZE, 0, GFP_ATOMIC)) {
 +      if (skb_headroom(skb) < intf->beacon->queue->desc_size) {
 +              if (pskb_expand_head(skb, intf->beacon->queue->desc_size,
 +                                   0, GFP_ATOMIC)) {
                        dev_kfree_skb(skb);
                        return -ENOMEM;
                }
        /*
         * Add the descriptor in front of the skb.
         */
 -      skb_push(skb, ring->desc_size);
 -      memset(skb->data, 0, ring->desc_size);
 +      skb_push(skb, intf->beacon->queue->desc_size);
 +      memset(skb->data, 0, intf->beacon->queue->desc_size);
  
        /*
         * Fill in skb descriptor
         */
 -      desc = get_skb_desc(skb);
 -      desc->desc_len = ring->desc_size;
 -      desc->data_len = skb->len - ring->desc_size;
 -      desc->desc = skb->data;
 -      desc->data = skb->data + ring->desc_size;
 -      desc->ring = ring;
 -      desc->entry = entry;
 +      skbdesc = get_skb_frame_desc(skb);
 +      memset(skbdesc, 0, sizeof(*skbdesc));
 +      skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
 +      skbdesc->data = skb->data + intf->beacon->queue->desc_size;
 +      skbdesc->data_len = skb->len - intf->beacon->queue->desc_size;
 +      skbdesc->desc = skb->data;
 +      skbdesc->desc_len = intf->beacon->queue->desc_size;
 +      skbdesc->entry = intf->beacon;
 +
 +      /*
 +       * Disable beaconing while we are reloading the beacon data,
 +       * otherwise we might be sending out invalid data.
 +       */
 +      rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
 +      rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
 +      rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
 +      rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
 +      rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
  
 +      /*
 +       * mac80211 doesn't provide the control->queue variable
 +       * for beacons. Set our own queue identification so
 +       * it can be used during descriptor initialization.
 +       */
 +      control->queue = RT2X00_BCN_QUEUE_BEACON;
        rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
  
        /*
         * Write entire beacon with descriptor to register,
         * and kick the beacon generator.
         */
 -      rt2x00pci_register_multiwrite(rt2x00dev, HW_BEACON_BASE0,
 +      beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
 +      rt2x00pci_register_multiwrite(rt2x00dev, beacon_base,
                                      skb->data, skb->len);
 -      rt61pci_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
 +      rt61pci_kick_tx_queue(rt2x00dev, control->queue);
  
        return 0;
  }
@@@ -2461,6 -2450,7 +2461,6 @@@ static const struct ieee80211_ops rt61p
        .conf_tx                = rt2x00mac_conf_tx,
        .get_tx_stats           = rt2x00mac_get_tx_stats,
        .get_tsf                = rt61pci_get_tsf,
 -      .reset_tsf              = rt61pci_reset_tsf,
        .beacon_update          = rt61pci_beacon_update,
  };
  
@@@ -2468,7 -2458,6 +2468,7 @@@ static const struct rt2x00lib_ops rt61p
        .irq_handler            = rt61pci_interrupt,
        .probe_hw               = rt61pci_probe_hw,
        .get_firmware_name      = rt61pci_get_firmware_name,
 +      .get_firmware_crc       = rt61pci_get_firmware_crc,
        .load_firmware          = rt61pci_load_firmware,
        .initialize             = rt2x00pci_initialize,
        .uninitialize           = rt2x00pci_uninitialize,
        .link_stats             = rt61pci_link_stats,
        .reset_tuner            = rt61pci_reset_tuner,
        .link_tuner             = rt61pci_link_tuner,
 +      .led_brightness         = rt61pci_led_brightness,
        .write_tx_desc          = rt61pci_write_tx_desc,
        .write_tx_data          = rt2x00pci_write_tx_data,
        .kick_tx_queue          = rt61pci_kick_tx_queue,
        .fill_rxdone            = rt61pci_fill_rxdone,
 -      .config_mac_addr        = rt61pci_config_mac_addr,
 -      .config_bssid           = rt61pci_config_bssid,
 -      .config_type            = rt61pci_config_type,
 -      .config_preamble        = rt61pci_config_preamble,
 +      .config_intf            = rt61pci_config_intf,
 +      .config_erp             = rt61pci_config_erp,
        .config                 = rt61pci_config,
  };
  
 +static const struct data_queue_desc rt61pci_queue_rx = {
 +      .entry_num              = RX_ENTRIES,
 +      .data_size              = DATA_FRAME_SIZE,
 +      .desc_size              = RXD_DESC_SIZE,
 +      .priv_size              = sizeof(struct queue_entry_priv_pci_rx),
 +};
 +
 +static const struct data_queue_desc rt61pci_queue_tx = {
 +      .entry_num              = TX_ENTRIES,
 +      .data_size              = DATA_FRAME_SIZE,
 +      .desc_size              = TXD_DESC_SIZE,
 +      .priv_size              = sizeof(struct queue_entry_priv_pci_tx),
 +};
 +
 +static const struct data_queue_desc rt61pci_queue_bcn = {
 +      .entry_num              = 4 * BEACON_ENTRIES,
 +      .data_size              = MGMT_FRAME_SIZE,
 +      .desc_size              = TXINFO_SIZE,
 +      .priv_size              = sizeof(struct queue_entry_priv_pci_tx),
 +};
 +
  static const struct rt2x00_ops rt61pci_ops = {
        .name           = KBUILD_MODNAME,
 -      .rxd_size       = RXD_DESC_SIZE,
 -      .txd_size       = TXD_DESC_SIZE,
 +      .max_sta_intf   = 1,
 +      .max_ap_intf    = 4,
        .eeprom_size    = EEPROM_SIZE,
        .rf_size        = RF_SIZE,
 +      .rx             = &rt61pci_queue_rx,
 +      .tx             = &rt61pci_queue_tx,
 +      .bcn            = &rt61pci_queue_bcn,
        .lib            = &rt61pci_rt2x00_ops,
        .hw             = &rt61pci_mac80211_ops,
  #ifdef CONFIG_RT2X00_LIB_DEBUGFS
@@@ -1,5 -1,5 +1,5 @@@
  /*
 -      Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
 +      Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
  
        This program is free software; you can redistribute it and/or modify
@@@ -24,7 -24,6 +24,7 @@@
        Supported chipsets: rt2571W & rt2671.
   */
  
 +#include <linux/crc-itu-t.h>
  #include <linux/delay.h>
  #include <linux/etherdevice.h>
  #include <linux/init.h>
@@@ -279,129 -278,86 +279,129 @@@ static const struct rt2x00debug rt73usb
  };
  #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
  
 -/*
 - * Configuration handlers.
 - */
 -static void rt73usb_config_mac_addr(struct rt2x00_dev *rt2x00dev, __le32 *mac)
 +#ifdef CONFIG_RT73USB_LEDS
 +static void rt73usb_led_brightness(struct led_classdev *led_cdev,
 +                                 enum led_brightness brightness)
  {
 -      u32 tmp;
 +      struct rt2x00_led *led =
 +         container_of(led_cdev, struct rt2x00_led, led_dev);
 +      unsigned int enabled = brightness != LED_OFF;
 +      unsigned int a_mode =
 +          (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
 +      unsigned int bg_mode =
 +          (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
  
 -      tmp = le32_to_cpu(mac[1]);
 -      rt2x00_set_field32(&tmp, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
 -      mac[1] = cpu_to_le32(tmp);
 +      if (in_atomic()) {
 +              NOTICE(led->rt2x00dev,
 +                     "Ignoring LED brightness command for led %d\n",
 +                     led->type);
 +              return;
 +      }
  
 -      rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2, mac,
 -                                  (2 * sizeof(__le32)));
 +      if (led->type == LED_TYPE_RADIO) {
 +              rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
 +                                 MCU_LEDCS_RADIO_STATUS, enabled);
 +
 +              rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
 +                                          0, led->rt2x00dev->led_mcu_reg,
 +                                          REGISTER_TIMEOUT);
 +      } else if (led->type == LED_TYPE_ASSOC) {
 +              rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
 +                                 MCU_LEDCS_LINK_BG_STATUS, bg_mode);
 +              rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
 +                                 MCU_LEDCS_LINK_A_STATUS, a_mode);
 +
 +              rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
 +                                          0, led->rt2x00dev->led_mcu_reg,
 +                                          REGISTER_TIMEOUT);
 +      } else if (led->type == LED_TYPE_QUALITY) {
 +              /*
 +               * The brightness is divided into 6 levels (0 - 5),
 +               * this means we need to convert the brightness
 +               * argument into the matching level within that range.
 +               */
 +              rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
 +                                          brightness / (LED_FULL / 6),
 +                                          led->rt2x00dev->led_mcu_reg,
 +                                          REGISTER_TIMEOUT);
 +      }
  }
 +#else
 +#define rt73usb_led_brightness        NULL
 +#endif /* CONFIG_RT73USB_LEDS */
  
 -static void rt73usb_config_bssid(struct rt2x00_dev *rt2x00dev, __le32 *bssid)
 +/*
 + * Configuration handlers.
 + */
 +static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
 +                              struct rt2x00_intf *intf,
 +                              struct rt2x00intf_conf *conf,
 +                              const unsigned int flags)
  {
 -      u32 tmp;
 +      unsigned int beacon_base;
 +      u32 reg;
  
 -      tmp = le32_to_cpu(bssid[1]);
 -      rt2x00_set_field32(&tmp, MAC_CSR5_BSS_ID_MASK, 3);
 -      bssid[1] = cpu_to_le32(tmp);
 +      if (flags & CONFIG_UPDATE_TYPE) {
 +              /*
 +               * Clear current synchronisation setup.
 +               * For the Beacon base registers we only need to clear
 +               * the first byte since that byte contains the VALID and OWNER
 +               * bits which (when set to 0) will invalidate the entire beacon.
 +               */
 +              beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
 +              rt73usb_register_write(rt2x00dev, beacon_base, 0);
  
 -      rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4, bssid,
 -                                  (2 * sizeof(__le32)));
 -}
 +              /*
 +               * Enable synchronisation.
 +               */
 +              rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
 +              rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
 +              rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
 +              rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
 +              rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
 +      }
  
 -static void rt73usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,
 -                              const int tsf_sync)
 -{
 -      u32 reg;
 +      if (flags & CONFIG_UPDATE_MAC) {
 +              reg = le32_to_cpu(conf->mac[1]);
 +              rt2x00_set_field32(&reg, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
 +              conf->mac[1] = cpu_to_le32(reg);
  
 -      /*
 -       * Clear current synchronisation setup.
 -       * For the Beacon base registers we only need to clear
 -       * the first byte since that byte contains the VALID and OWNER
 -       * bits which (when set to 0) will invalidate the entire beacon.
 -       */
 -      rt73usb_register_write(rt2x00dev, TXRX_CSR9, 0);
 -      rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
 -      rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
 -      rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
 -      rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
 +              rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2,
 +                                          conf->mac, sizeof(conf->mac));
 +      }
  
 -      /*
 -       * Enable synchronisation.
 -       */
 -      rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
 -      rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
 -      rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE,
 -                         (tsf_sync == TSF_SYNC_BEACON));
 -      rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
 -      rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, tsf_sync);
 -      rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
 +      if (flags & CONFIG_UPDATE_BSSID) {
 +              reg = le32_to_cpu(conf->bssid[1]);
 +              rt2x00_set_field32(&reg, MAC_CSR5_BSS_ID_MASK, 3);
 +              conf->bssid[1] = cpu_to_le32(reg);
 +
 +              rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4,
 +                                          conf->bssid, sizeof(conf->bssid));
 +      }
  }
  
 -static void rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev,
 -                                    const int short_preamble,
 -                                    const int ack_timeout,
 -                                    const int ack_consume_time)
 +static int rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
 +                            struct rt2x00lib_erp *erp)
  {
        u32 reg;
  
        /*
 -       * When in atomic context, reschedule and let rt2x00lib
 -       * call this function again.
 +       * When in atomic context, we should let rt2x00lib
 +       * try this configuration again later.
         */
 -      if (in_atomic()) {
 -              queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->config_work);
 -              return;
 -      }
 +      if (in_atomic())
 +              return -EAGAIN;
  
        rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
 -      rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout);
 +      rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout);
        rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
  
        rt73usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
        rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
 -                         !!short_preamble);
 +                         !!erp->short_preamble);
        rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg);
 +
 +      return 0;
  }
  
  static void rt73usb_config_phymode(struct rt2x00_dev *rt2x00dev,
@@@ -486,22 -442,28 +486,22 @@@ static void rt73usb_config_antenna_5x(s
        case ANTENNA_HW_DIVERSITY:
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
                temp = !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)
 -                     && (rt2x00dev->curr_hwmode != HWMODE_A);
 +                     && (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ);
                rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp);
                break;
        case ANTENNA_A:
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
                rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
 -              if (rt2x00dev->curr_hwmode == HWMODE_A)
 +              if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
                        rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
                else
                        rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
                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:
 +      default:
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
                rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
 -              if (rt2x00dev->curr_hwmode == HWMODE_A)
 +              if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
                        rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
                else
                        rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
@@@ -539,8 -501,14 +539,8 @@@ static void rt73usb_config_antenna_2x(s
                rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
                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:
 +      default:
                rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
                break;
@@@ -590,14 -558,7 +590,14 @@@ static void rt73usb_config_antenna(stru
        unsigned int i;
        u32 reg;
  
 -      if (rt2x00dev->curr_hwmode == HWMODE_A) {
 +      /*
 +       * We should never come here because rt2x00lib is supposed
 +       * to catch this and send us the correct antenna explicitely.
 +       */
 +      BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
 +             ant->tx == ANTENNA_SW_DIVERSITY);
 +
 +      if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
                sel = antenna_sel_a;
                lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
        } else {
        rt73usb_register_read(rt2x00dev, PHY_CSR0, &reg);
  
        rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
 -                         (rt2x00dev->curr_hwmode == HWMODE_B ||
 -                          rt2x00dev->curr_hwmode == HWMODE_G));
 +                         (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ));
        rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A,
 -                         (rt2x00dev->curr_hwmode == HWMODE_A));
 +                         (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ));
  
        rt73usb_register_write(rt2x00dev, PHY_CSR0, reg);
  
@@@ -655,8 -617,8 +655,8 @@@ static void rt73usb_config_duration(str
  }
  
  static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
 -                         const unsigned int flags,
 -                         struct rt2x00lib_conf *libconf)
 +                         struct rt2x00lib_conf *libconf,
 +                         const unsigned int flags)
  {
        if (flags & CONFIG_UPDATE_PHYMODE)
                rt73usb_config_phymode(rt2x00dev, libconf->basic_rates);
  }
  
  /*
 - * LED functions.
 - */
 -static void rt73usb_enable_led(struct rt2x00_dev *rt2x00dev)
 -{
 -      u32 reg;
 -
 -      rt73usb_register_read(rt2x00dev, MAC_CSR14, &reg);
 -      rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, 70);
 -      rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, 30);
 -      rt73usb_register_write(rt2x00dev, MAC_CSR14, reg);
 -
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1);
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS,
 -                         (rt2x00dev->rx_status.phymode == MODE_IEEE80211A));
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS,
 -                         (rt2x00dev->rx_status.phymode != MODE_IEEE80211A));
 -
 -      rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000,
 -                                  rt2x00dev->led_reg, REGISTER_TIMEOUT);
 -}
 -
 -static void rt73usb_disable_led(struct rt2x00_dev *rt2x00dev)
 -{
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 0);
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS, 0);
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS, 0);
 -
 -      rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000,
 -                                  rt2x00dev->led_reg, REGISTER_TIMEOUT);
 -}
 -
 -static void rt73usb_activity_led(struct rt2x00_dev *rt2x00dev, int rssi)
 -{
 -      u32 led;
 -
 -      if (rt2x00dev->led_mode != LED_MODE_SIGNAL_STRENGTH)
 -              return;
 -
 -      /*
 -       * Led handling requires a positive value for the rssi,
 -       * to do that correctly we need to add the correction.
 -       */
 -      rssi += rt2x00dev->rssi_offset;
 -
 -      if (rssi <= 30)
 -              led = 0;
 -      else if (rssi <= 39)
 -              led = 1;
 -      else if (rssi <= 49)
 -              led = 2;
 -      else if (rssi <= 53)
 -              led = 3;
 -      else if (rssi <= 63)
 -              led = 4;
 -      else
 -              led = 5;
 -
 -      rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, led,
 -                                  rt2x00dev->led_reg, REGISTER_TIMEOUT);
 -}
 -
 -/*
   * Link tuning
   */
  static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev,
@@@ -705,12 -729,17 +705,12 @@@ static void rt73usb_link_tuner(struct r
        u8 up_bound;
        u8 low_bound;
  
 -      /*
 -       * Update Led strength
 -       */
 -      rt73usb_activity_led(rt2x00dev, rssi);
 -
        rt73usb_bbp_read(rt2x00dev, 17, &r17);
  
        /*
         * Determine r17 bounds.
         */
 -      if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
 +      if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
                low_bound = 0x28;
                up_bound = 0x48;
  
        }
  
        /*
 +       * If we are not associated, we should go straight to the
 +       * dynamic CCA tuning.
 +       */
 +      if (!rt2x00dev->intf_associated)
 +              goto dynamic_cca_tune;
 +
 +      /*
         * Special big-R17 for very short distance
         */
        if (rssi > -35) {
                return;
        }
  
 +dynamic_cca_tune:
 +
        /*
         * r17 does not yet exceed upper limit, continue and base
         * the r17 tuning on the false CCA count.
  }
  
  /*
 - * Firmware name function.
 + * Firmware functions
   */
  static char *rt73usb_get_firmware_name(struct rt2x00_dev *rt2x00dev)
  {
        return FIRMWARE_RT2571;
  }
  
 -/*
 - * Initialization functions.
 - */
 +static u16 rt73usb_get_firmware_crc(void *data, const size_t len)
 +{
 +      u16 crc;
 +
 +      /*
 +       * Use the crc itu-t algorithm.
 +       * The last 2 bytes in the firmware array are the crc checksum itself,
 +       * this means that we should never pass those 2 bytes to the crc
 +       * algorithm.
 +       */
 +      crc = crc_itu_t(0, data, len - 2);
 +      crc = crc_itu_t_byte(crc, 0);
 +      crc = crc_itu_t_byte(crc, 0);
 +
 +      return crc;
 +}
 +
  static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
                                 const size_t len)
  {
  
                rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE,
                                         USB_VENDOR_REQUEST_OUT,
 -                                       FIRMWARE_IMAGE_BASE + i, 0x0000,
 +                                       FIRMWARE_IMAGE_BASE + i, 0,
                                         cache, buflen, timeout);
  
                ptr += buflen;
         * we need to specify a long timeout time.
         */
        status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE,
 -                                           0x0000, USB_MODE_FIRMWARE,
 +                                           0, USB_MODE_FIRMWARE,
                                             REGISTER_TIMEOUT_FIRMWARE);
        if (status < 0) {
                ERROR(rt2x00dev, "Failed to write Firmware to device.\n");
                return status;
        }
  
 -      rt73usb_disable_led(rt2x00dev);
 -
        return 0;
  }
  
 +/*
 + * Initialization functions.
 + */
  static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
  {
        u32 reg;
  
        rt73usb_register_write(rt2x00dev, MAC_CSR13, 0x00007f00);
  
 +      rt73usb_register_read(rt2x00dev, MAC_CSR14, &reg);
 +      rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, 70);
 +      rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, 30);
 +      rt73usb_register_write(rt2x00dev, MAC_CSR14, reg);
 +
        /*
         * Invalidate all Shared Keys (SEC_CSR0),
         * and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5)
        rt73usb_register_write(rt2x00dev, MAC_CSR9, reg);
  
        /*
 +       * Clear all beacons
 +       * For the Beacon base registers we only need to clear
 +       * the first byte since that byte contains the VALID and OWNER
 +       * bits which (when set to 0) will invalidate the entire beacon.
 +       */
 +      rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
 +      rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
 +      rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
 +      rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
 +
 +      /*
         * We must clear the error counters.
         * These registers are cleared on read,
         * so we may pass a useless variable to store the value.
@@@ -1105,15 -1094,19 +1105,15 @@@ continue_csr_init
        rt73usb_bbp_write(rt2x00dev, 102, 0x16);
        rt73usb_bbp_write(rt2x00dev, 107, 0x04);
  
 -      DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
        for (i = 0; i < EEPROM_BBP_SIZE; i++) {
                rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
  
                if (eeprom != 0xffff && eeprom != 0x0000) {
                        reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
                        value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
 -                      DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
 -                            reg_id, value);
                        rt73usb_bbp_write(rt2x00dev, reg_id, value);
                }
        }
 -      DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
  
        return 0;
  }
@@@ -1143,11 -1136,21 +1143,11 @@@ static int rt73usb_enable_radio(struct 
                return -EIO;
        }
  
 -      /*
 -       * Enable LED
 -       */
 -      rt73usb_enable_led(rt2x00dev);
 -
        return 0;
  }
  
  static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev)
  {
 -      /*
 -       * Disable LED
 -       */
 -      rt73usb_disable_led(rt2x00dev);
 -
        rt73usb_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
  
        /*
@@@ -1231,10 -1234,10 +1231,10 @@@ static int rt73usb_set_device_state(str
   */
  static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
                                    struct sk_buff *skb,
 -                                  struct txdata_entry_desc *desc,
 +                                  struct txentry_desc *txdesc,
                                    struct ieee80211_tx_control *control)
  {
 -      struct skb_desc *skbdesc = get_skb_desc(skb);
 +      struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
        __le32 *txd = skbdesc->desc;
        u32 word;
  
         * Start writing the descriptor words.
         */
        rt2x00_desc_read(txd, 1, &word);
 -      rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, desc->queue);
 -      rt2x00_set_field32(&word, TXD_W1_AIFSN, desc->aifs);
 -      rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min);
 -      rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max);
 +      rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue);
 +      rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs);
 +      rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
 +      rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
        rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
        rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, 1);
        rt2x00_desc_write(txd, 1, word);
  
        rt2x00_desc_read(txd, 2, &word);
 -      rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, desc->signal);
 -      rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, desc->service);
 -      rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, desc->length_low);
 -      rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, desc->length_high);
 +      rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal);
 +      rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service);
 +      rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low);
 +      rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
        rt2x00_desc_write(txd, 2, word);
  
        rt2x00_desc_read(txd, 5, &word);
        rt2x00_set_field32(&word, TXD_W5_TX_POWER,
 -                         TXPOWER_TO_DEV(control->power_level));
 +                         TXPOWER_TO_DEV(rt2x00dev->tx_power));
        rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
        rt2x00_desc_write(txd, 5, word);
  
        rt2x00_desc_read(txd, 0, &word);
        rt2x00_set_field32(&word, TXD_W0_BURST,
 -                         test_bit(ENTRY_TXD_BURST, &desc->flags));
 +                         test_bit(ENTRY_TXD_BURST, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_VALID, 1);
        rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
 -                         test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
 +                         test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_ACK,
 -                         test_bit(ENTRY_TXD_ACK, &desc->flags));
 +                         test_bit(ENTRY_TXD_ACK, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
 -                         test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
 +                         test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_OFDM,
 -                         test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags));
 -      rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
 +                         test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
 +      rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
        rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
                           !!(control->flags &
                              IEEE80211_TXCTL_LONG_RETRY_LIMIT));
        rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0);
        rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
        rt2x00_set_field32(&word, TXD_W0_BURST2,
 -                         test_bit(ENTRY_TXD_BURST, &desc->flags));
 +                         test_bit(ENTRY_TXD_BURST, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
        rt2x00_desc_write(txd, 0, word);
  }
@@@ -1306,11 -1309,11 +1306,11 @@@ static int rt73usb_get_tx_data_len(stru
   * TX data initialization
   */
  static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
 -                                unsigned int queue)
 +                                const unsigned int queue)
  {
        u32 reg;
  
 -      if (queue != IEEE80211_TX_QUEUE_BEACON)
 +      if (queue != RT2X00_BCN_QUEUE_BEACON)
                return;
  
        /*
  
        rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
        if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) {
 +              rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
 +              rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
                rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
                rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
        }
@@@ -1352,7 -1353,7 +1352,7 @@@ static int rt73usb_agc_to_rssi(struct r
                return 0;
        }
  
 -      if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
 +      if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
                if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
                        if (lna == 3 || lna == 2)
                                offset += 10;
        return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
  }
  
 -static void rt73usb_fill_rxdone(struct data_entry *entry,
 -                              struct rxdata_entry_desc *desc)
 +static void rt73usb_fill_rxdone(struct queue_entry *entry,
 +                              struct rxdone_entry_desc *rxdesc)
  {
 -      struct skb_desc *skbdesc = get_skb_desc(entry->skb);
 +      struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
        __le32 *rxd = (__le32 *)entry->skb->data;
 +      unsigned int offset = entry->queue->desc_size + 2;
        u32 word0;
        u32 word1;
  
 +      /*
 +       * Copy descriptor to the available headroom inside the skbuffer.
 +       */
 +      skb_push(entry->skb, offset);
 +      memcpy(entry->skb->data, rxd, entry->queue->desc_size);
 +      rxd = (__le32 *)entry->skb->data;
 +
 +      /*
 +       * The descriptor is now aligned to 4 bytes and thus it is
 +       * now safe to read it on all architectures.
 +       */
        rt2x00_desc_read(rxd, 0, &word0);
        rt2x00_desc_read(rxd, 1, &word1);
  
 -      desc->flags = 0;
 +      rxdesc->flags = 0;
        if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
 -              desc->flags |= RX_FLAG_FAILED_FCS_CRC;
 +              rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
  
        /*
         * Obtain the status about this packet.
 +       * When frame was received with an OFDM bitrate,
 +       * the signal is the PLCP value. If it was received with
 +       * a CCK bitrate the signal is the rate in 100kbit/s.
 +       */
 +      rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
 +      rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
 +      rxdesc->signal_plcp = rxdesc->ofdm;
 +      rxdesc->rssi = rt73usb_agc_to_rssi(entry->queue->rt2x00dev, word1);
 +      rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
 +      rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
 +
 +      /*
 +       * Adjust the skb memory window to the frame boundaries.
         */
 -      desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
 -      desc->rssi = rt73usb_agc_to_rssi(entry->ring->rt2x00dev, word1);
 -      desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
 -      desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
 -      desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
 +      skb_pull(entry->skb, offset + entry->queue->desc_size);
 +      skb_trim(entry->skb, rxdesc->size);
  
        /*
         * Set descriptor and data pointer.
         */
 -      skbdesc->desc = entry->skb->data;
 -      skbdesc->desc_len = entry->ring->desc_size;
 -      skbdesc->data = entry->skb->data + entry->ring->desc_size;
 -      skbdesc->data_len = desc->size;
 +      skbdesc->data = entry->skb->data;
 +      skbdesc->data_len = rxdesc->size;
 +      skbdesc->desc = rxd;
 +      skbdesc->desc_len = entry->queue->desc_size;
  }
  
  /*
@@@ -1520,7 -1499,7 +1520,7 @@@ static int rt73usb_validate_eeprom(stru
                rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
                rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
                rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
 -              EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
 +              EEPROM(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
        } else {
                value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
                if (value < -10 || value > 10)
@@@ -1598,49 -1577,33 +1598,49 @@@ static int rt73usb_init_eeprom(struct r
        /*
         * Store led settings, for correct led behaviour.
         */
 +#ifdef CONFIG_RT73USB_LEDS
        rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
  
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LED_MODE,
 -                         rt2x00dev->led_mode);
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_0,
 +      switch (value) {
 +      case LED_MODE_TXRX_ACTIVITY:
 +      case LED_MODE_ASUS:
 +      case LED_MODE_ALPHA:
 +      case LED_MODE_DEFAULT:
 +              rt2x00dev->led_flags =
 +                  LED_SUPPORT_RADIO | LED_SUPPORT_ASSOC;
 +              break;
 +      case LED_MODE_SIGNAL_STRENGTH:
 +              rt2x00dev->led_flags =
 +                  LED_SUPPORT_RADIO | LED_SUPPORT_ASSOC |
 +                  LED_SUPPORT_QUALITY;
 +              break;
 +      }
 +
 +      rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value);
 +      rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0,
                           rt2x00_get_field16(eeprom,
                                              EEPROM_LED_POLARITY_GPIO_0));
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_1,
 +      rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_1,
                           rt2x00_get_field16(eeprom,
                                              EEPROM_LED_POLARITY_GPIO_1));
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_2,
 +      rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_2,
                           rt2x00_get_field16(eeprom,
                                              EEPROM_LED_POLARITY_GPIO_2));
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_3,
 +      rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_3,
                           rt2x00_get_field16(eeprom,
                                              EEPROM_LED_POLARITY_GPIO_3));
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_4,
 +      rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_4,
                           rt2x00_get_field16(eeprom,
                                              EEPROM_LED_POLARITY_GPIO_4));
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_ACT,
 +      rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_ACT,
                           rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT));
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_BG,
 +      rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_BG,
                           rt2x00_get_field16(eeprom,
                                              EEPROM_LED_POLARITY_RDY_G));
 -      rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_A,
 +      rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A,
                           rt2x00_get_field16(eeprom,
                                              EEPROM_LED_POLARITY_RDY_A));
 +#endif /* CONFIG_RT73USB_LEDS */
  
        return 0;
  }
@@@ -1796,7 -1759,7 +1796,7 @@@ static void rt73usb_probe_hw_mode(struc
        rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
        rt2x00dev->hw->max_signal = MAX_SIGNAL;
        rt2x00dev->hw->max_rssi = MAX_RX_SSI;
 -      rt2x00dev->hw->queues = 5;
 +      rt2x00dev->hw->queues = 4;
  
        SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev);
        SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
        /*
         * Initialize hw_mode information.
         */
 -      spec->num_modes = 2;
 -      spec->num_rates = 12;
 +      spec->supported_bands = SUPPORT_BAND_2GHZ;
 +      spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
        spec->tx_power_a = NULL;
        spec->tx_power_bg = txpower;
        spec->tx_power_default = DEFAULT_TXPOWER;
                spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528);
                spec->channels = rf_vals_bg_2528;
        } else if (rt2x00_rf(&rt2x00dev->chip, RF5226)) {
 +              spec->supported_bands |= SUPPORT_BAND_5GHZ;
                spec->num_channels = ARRAY_SIZE(rf_vals_5226);
                spec->channels = rf_vals_5226;
        } else if (rt2x00_rf(&rt2x00dev->chip, RF2527)) {
                spec->num_channels = 14;
                spec->channels = rf_vals_5225_2527;
        } else if (rt2x00_rf(&rt2x00dev->chip, RF5225)) {
 +              spec->supported_bands |= SUPPORT_BAND_5GHZ;
                spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527);
                spec->channels = rf_vals_5225_2527;
        }
  
        if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
            rt2x00_rf(&rt2x00dev->chip, RF5226)) {
 -              spec->num_modes = 3;
 -
                txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
                for (i = 0; i < 14; i++)
                        txpower[i] = TXPOWER_FROM_DEV(txpower[i]);
@@@ -1866,7 -1829,7 +1866,7 @@@ static int rt73usb_probe_hw(struct rt2x
        rt73usb_probe_hw_mode(rt2x00dev);
  
        /*
 -       * This device requires firmware
 +       * This device requires firmware.
         */
        __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
  
@@@ -1906,9 -1869,9 +1906,9 @@@ static void rt73usb_configure_filter(st
         * Apply some rules to the filters:
         * - Some filters imply different filters to be set.
         * - Some things we can't filter out at all.
+        * - Multicast filter seems to kill broadcast traffic so never use it.
         */
-       if (mc_count)
-               *total_flags |= FIF_ALLMULTI;
+       *total_flags |= FIF_ALLMULTI;
        if (*total_flags & FIF_OTHER_BSS ||
            *total_flags & FIF_PROMISC_IN_BSS)
                *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
        rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST,
                           !(*total_flags & FIF_ALLMULTI));
        rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BROADCAST, 0);
 -      rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS, 1);
 +      rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS,
 +                         !(*total_flags & FIF_CONTROL));
        rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
  }
  
@@@ -1993,65 -1955,61 +1993,65 @@@ static u64 rt73usb_get_tsf(struct ieee8
  #define rt73usb_get_tsf       NULL
  #endif
  
 -static void rt73usb_reset_tsf(struct ieee80211_hw *hw)
 -{
 -      struct rt2x00_dev *rt2x00dev = hw->priv;
 -
 -      rt73usb_register_write(rt2x00dev, TXRX_CSR12, 0);
 -      rt73usb_register_write(rt2x00dev, TXRX_CSR13, 0);
 -}
 -
  static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
 -                        struct ieee80211_tx_control *control)
 +                               struct ieee80211_tx_control *control)
  {
        struct rt2x00_dev *rt2x00dev = hw->priv;
 -      struct skb_desc *desc;
 -      struct data_ring *ring;
 -      struct data_entry *entry;
 -      int timeout;
 +      struct rt2x00_intf *intf = vif_to_intf(control->vif);
 +      struct skb_frame_desc *skbdesc;
 +      unsigned int beacon_base;
 +      unsigned int timeout;
 +      u32 reg;
  
 -      /*
 -       * Just in case the ieee80211 doesn't set this,
 -       * but we need this queue set for the descriptor
 -       * initialization.
 -       */
 -      control->queue = IEEE80211_TX_QUEUE_BEACON;
 -      ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
 -      entry = rt2x00_get_data_entry(ring);
 +      if (unlikely(!intf->beacon))
 +              return -ENOBUFS;
  
        /*
         * Add the descriptor in front of the skb.
         */
 -      skb_push(skb, ring->desc_size);
 -      memset(skb->data, 0, ring->desc_size);
 +      skb_push(skb, intf->beacon->queue->desc_size);
 +      memset(skb->data, 0, intf->beacon->queue->desc_size);
  
        /*
         * Fill in skb descriptor
         */
 -      desc = get_skb_desc(skb);
 -      desc->desc_len = ring->desc_size;
 -      desc->data_len = skb->len - ring->desc_size;
 -      desc->desc = skb->data;
 -      desc->data = skb->data + ring->desc_size;
 -      desc->ring = ring;
 -      desc->entry = entry;
 +      skbdesc = get_skb_frame_desc(skb);
 +      memset(skbdesc, 0, sizeof(*skbdesc));
 +      skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
 +      skbdesc->data = skb->data + intf->beacon->queue->desc_size;
 +      skbdesc->data_len = skb->len - intf->beacon->queue->desc_size;
 +      skbdesc->desc = skb->data;
 +      skbdesc->desc_len = intf->beacon->queue->desc_size;
 +      skbdesc->entry = intf->beacon;
 +
 +      /*
 +       * Disable beaconing while we are reloading the beacon data,
 +       * otherwise we might be sending out invalid data.
 +       */
 +      rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
 +      rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
 +      rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
 +      rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
 +      rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
  
 +      /*
 +       * mac80211 doesn't provide the control->queue variable
 +       * for beacons. Set our own queue identification so
 +       * it can be used during descriptor initialization.
 +       */
 +      control->queue = RT2X00_BCN_QUEUE_BEACON;
        rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
  
        /*
         * Write entire beacon with descriptor to register,
         * and kick the beacon generator.
         */
 +      beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
        timeout = REGISTER_TIMEOUT * (skb->len / sizeof(u32));
        rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE,
 -                               USB_VENDOR_REQUEST_OUT,
 -                               HW_BEACON_BASE0, 0x0000,
 +                               USB_VENDOR_REQUEST_OUT, beacon_base, 0,
                                 skb->data, skb->len, timeout);
 -      rt73usb_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
 +      rt73usb_kick_tx_queue(rt2x00dev, control->queue);
  
        return 0;
  }
@@@ -2071,13 -2029,13 +2071,13 @@@ static const struct ieee80211_ops rt73u
        .conf_tx                = rt2x00mac_conf_tx,
        .get_tx_stats           = rt2x00mac_get_tx_stats,
        .get_tsf                = rt73usb_get_tsf,
 -      .reset_tsf              = rt73usb_reset_tsf,
        .beacon_update          = rt73usb_beacon_update,
  };
  
  static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
        .probe_hw               = rt73usb_probe_hw,
        .get_firmware_name      = rt73usb_get_firmware_name,
 +      .get_firmware_crc       = rt73usb_get_firmware_crc,
        .load_firmware          = rt73usb_load_firmware,
        .initialize             = rt2x00usb_initialize,
        .uninitialize           = rt2x00usb_uninitialize,
        .link_stats             = rt73usb_link_stats,
        .reset_tuner            = rt73usb_reset_tuner,
        .link_tuner             = rt73usb_link_tuner,
 +      .led_brightness         = rt73usb_led_brightness,
        .write_tx_desc          = rt73usb_write_tx_desc,
        .write_tx_data          = rt2x00usb_write_tx_data,
        .get_tx_data_len        = rt73usb_get_tx_data_len,
        .kick_tx_queue          = rt73usb_kick_tx_queue,
        .fill_rxdone            = rt73usb_fill_rxdone,
 -      .config_mac_addr        = rt73usb_config_mac_addr,
 -      .config_bssid           = rt73usb_config_bssid,
 -      .config_type            = rt73usb_config_type,
 -      .config_preamble        = rt73usb_config_preamble,
 +      .config_intf            = rt73usb_config_intf,
 +      .config_erp             = rt73usb_config_erp,
        .config                 = rt73usb_config,
  };
  
 +static const struct data_queue_desc rt73usb_queue_rx = {
 +      .entry_num              = RX_ENTRIES,
 +      .data_size              = DATA_FRAME_SIZE,
 +      .desc_size              = RXD_DESC_SIZE,
 +      .priv_size              = sizeof(struct queue_entry_priv_usb_rx),
 +};
 +
 +static const struct data_queue_desc rt73usb_queue_tx = {
 +      .entry_num              = TX_ENTRIES,
 +      .data_size              = DATA_FRAME_SIZE,
 +      .desc_size              = TXD_DESC_SIZE,
 +      .priv_size              = sizeof(struct queue_entry_priv_usb_tx),
 +};
 +
 +static const struct data_queue_desc rt73usb_queue_bcn = {
 +      .entry_num              = 4 * BEACON_ENTRIES,
 +      .data_size              = MGMT_FRAME_SIZE,
 +      .desc_size              = TXINFO_SIZE,
 +      .priv_size              = sizeof(struct queue_entry_priv_usb_tx),
 +};
 +
  static const struct rt2x00_ops rt73usb_ops = {
        .name           = KBUILD_MODNAME,
 -      .rxd_size       = RXD_DESC_SIZE,
 -      .txd_size       = TXD_DESC_SIZE,
 +      .max_sta_intf   = 1,
 +      .max_ap_intf    = 4,
        .eeprom_size    = EEPROM_SIZE,
        .rf_size        = RF_SIZE,
 +      .rx             = &rt73usb_queue_rx,
 +      .tx             = &rt73usb_queue_tx,
 +      .bcn            = &rt73usb_queue_bcn,
        .lib            = &rt73usb_rt2x00_ops,
        .hw             = &rt73usb_mac80211_ops,
  #ifdef CONFIG_RT2X00_LIB_DEBUGFS
@@@ -2163,6 -2098,7 +2163,7 @@@ static struct usb_device_id rt73usb_dev
        /* D-Link */
        { USB_DEVICE(0x07d1, 0x3c03), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x07d1, 0x3c04), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x07d1, 0x3c07), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Gemtek */
        { USB_DEVICE(0x15a9, 0x0004), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Gigabyte */
diff --combined include/net/xfrm.h
@@@ -121,7 -121,6 +121,7 @@@ extern struct mutex xfrm_cfg_mutex
  struct xfrm_state
  {
        /* Note: bydst is re-used during gc */
 +      struct list_head        all;
        struct hlist_node       bydst;
        struct hlist_node       bysrc;
        struct hlist_node       byspi;
@@@ -278,7 -277,7 +278,7 @@@ extern int __xfrm_state_delete(struct x
  struct xfrm_state_afinfo {
        unsigned int            family;
        unsigned int            proto;
-       unsigned int            eth_proto;
+       __be16                  eth_proto;
        struct module           *owner;
        const struct xfrm_type  *type_map[IPPROTO_MAX];
        struct xfrm_mode        *mode_map[XFRM_MODE_MAX];
@@@ -425,7 -424,6 +425,7 @@@ struct xfrm_tmp
  struct xfrm_policy
  {
        struct xfrm_policy      *next;
 +      struct list_head        bytype;
        struct hlist_node       bydst;
        struct hlist_node       byidx;
  
@@@ -1162,18 -1160,6 +1162,18 @@@ struct xfrm6_tunnel 
        int priority;
  };
  
 +struct xfrm_state_walk {
 +      struct xfrm_state *state;
 +      int count;
 +      u8 proto;
 +};
 +
 +struct xfrm_policy_walk {
 +      struct xfrm_policy *policy;
 +      int count;
 +      u8 type, cur_type;
 +};
 +
  extern void xfrm_init(void);
  extern void xfrm4_init(void);
  extern void xfrm_state_init(void);
@@@ -1198,23 -1184,7 +1198,23 @@@ static inline void xfrm6_fini(void
  extern int xfrm_proc_init(void);
  #endif
  
 -extern int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), void *);
 +static inline void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto)
 +{
 +      walk->proto = proto;
 +      walk->state = NULL;
 +      walk->count = 0;
 +}
 +
 +static inline void xfrm_state_walk_done(struct xfrm_state_walk *walk)
 +{
 +      if (walk->state != NULL) {
 +              xfrm_state_put(walk->state);
 +              walk->state = NULL;
 +      }
 +}
 +
 +extern int xfrm_state_walk(struct xfrm_state_walk *walk,
 +                         int (*func)(struct xfrm_state *, int, void*), void *);
  extern struct xfrm_state *xfrm_state_alloc(void);
  extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, 
                                          struct flowi *fl, struct xfrm_tmpl *tmpl,
@@@ -1336,25 -1306,7 +1336,25 @@@ static inline int xfrm4_udp_encap_rcv(s
  #endif
  
  struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp);
 -extern int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*), void *);
 +
 +static inline void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type)
 +{
 +      walk->cur_type = XFRM_POLICY_TYPE_MAIN;
 +      walk->type = type;
 +      walk->policy = NULL;
 +      walk->count = 0;
 +}
 +
 +static inline void xfrm_policy_walk_done(struct xfrm_policy_walk *walk)
 +{
 +      if (walk->policy != NULL) {
 +              xfrm_pol_put(walk->policy);
 +              walk->policy = NULL;
 +      }
 +}
 +
 +extern int xfrm_policy_walk(struct xfrm_policy_walk *walk,
 +      int (*func)(struct xfrm_policy *, int, int, void*), void *);
  int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
  struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
                                          struct xfrm_selector *sel,
diff --combined net/8021q/vlan_dev.c
@@@ -171,7 -171,7 +171,7 @@@ int vlan_skb_recv(struct sk_buff *skb, 
        skb->dev = __find_vlan_dev(dev, vid);
        if (!skb->dev) {
                pr_debug("%s: ERROR: No net_device for VID: %u on dev: %s\n",
 -                       __FUNCTION__, (unsigned int)vid, dev->name);
 +                       __func__, (unsigned int)vid, dev->name);
                goto err_unlock;
        }
  
                                                  ntohs(vhdr->h_vlan_TCI));
  
        pr_debug("%s: priority: %u for TCI: %hu\n",
 -               __FUNCTION__, skb->priority, ntohs(vhdr->h_vlan_TCI));
 +               __func__, skb->priority, ntohs(vhdr->h_vlan_TCI));
  
        switch (skb->pkt_type) {
        case PACKET_BROADCAST: /* Yeah, stats collect these together.. */
@@@ -268,7 -268,7 +268,7 @@@ static int vlan_dev_hard_header(struct 
        struct net_device *vdev = dev;
  
        pr_debug("%s: skb: %p type: %hx len: %u vlan_id: %hx, daddr: %p\n",
 -               __FUNCTION__, skb, type, len, vlan_dev_info(dev)->vlan_id,
 +               __func__, skb, type, len, vlan_dev_info(dev)->vlan_id,
                 daddr);
  
        /* build vlan header only if re_order_header flag is NOT set.  This
                        return -ENOMEM;
                }
                vlan_dev_info(vdev)->cnt_inc_headroom_on_tx++;
 -              pr_debug("%s: %s: had to grow skb\n", __FUNCTION__, vdev->name);
 +              pr_debug("%s: %s: had to grow skb\n", __func__, vdev->name);
        }
  
        if (build_vlan_header) {
@@@ -382,7 -382,7 +382,7 @@@ static int vlan_dev_hard_start_xmit(str
                vlan_dev_info(dev)->cnt_encap_on_xmit++;
  
                pr_debug("%s: proto to encap: 0x%hx\n",
-                        __func__, htons(veth->h_vlan_proto));
 -                       __FUNCTION__, ntohs(veth->h_vlan_proto));
++                       __func__, ntohs(veth->h_vlan_proto));
                /* Construct the second two bytes. This field looks something
                 * like:
                 * usr_priority: 3 bits  (high bits)
        }
  
        pr_debug("%s: about to send skb: %p to dev: %s\n",
 -              __FUNCTION__, skb, skb->dev->name);
 +              __func__, skb, skb->dev->name);
        pr_debug("  " MAC_FMT " " MAC_FMT " %4hx %4hx %4hx\n",
                 veth->h_dest[0], veth->h_dest[1], veth->h_dest[2],
                 veth->h_dest[3], veth->h_dest[4], veth->h_dest[5],
diff --combined net/ipv4/af_inet.c
@@@ -458,7 -458,7 +458,7 @@@ int inet_bind(struct socket *sock, stru
        err = -EADDRNOTAVAIL;
        if (!sysctl_ip_nonlocal_bind &&
            !inet->freebind &&
-           addr->sin_addr.s_addr != INADDR_ANY &&
+           addr->sin_addr.s_addr != htonl(INADDR_ANY) &&
            chk_addr_ret != RTN_LOCAL &&
            chk_addr_ret != RTN_MULTICAST &&
            chk_addr_ret != RTN_BROADCAST)
@@@ -784,7 -784,6 +784,7 @@@ int inet_ioctl(struct socket *sock, uns
  {
        struct sock *sk = sock->sk;
        int err = 0;
 +      struct net *net = sk->sk_net;
  
        switch (cmd) {
                case SIOCGSTAMP:
                case SIOCADDRT:
                case SIOCDELRT:
                case SIOCRTMSG:
 -                      err = ip_rt_ioctl(sk->sk_net, cmd, (void __user *)arg);
 +                      err = ip_rt_ioctl(net, cmd, (void __user *)arg);
                        break;
                case SIOCDARP:
                case SIOCGARP:
                case SIOCSARP:
 -                      err = arp_ioctl(sk->sk_net, cmd, (void __user *)arg);
 +                      err = arp_ioctl(net, cmd, (void __user *)arg);
                        break;
                case SIOCGIFADDR:
                case SIOCSIFADDR:
                case SIOCSIFPFLAGS:
                case SIOCGIFPFLAGS:
                case SIOCSIFFLAGS:
 -                      err = devinet_ioctl(cmd, (void __user *)arg);
 +                      err = devinet_ioctl(net, cmd, (void __user *)arg);
                        break;
                default:
                        if (sk->sk_prot->ioctl)
@@@ -1060,7 -1059,7 +1060,7 @@@ static int inet_sk_reselect_saddr(struc
        if (sysctl_ip_dynaddr > 1) {
                printk(KERN_INFO "%s(): shifting inet->"
                                 "saddr from %d.%d.%d.%d to %d.%d.%d.%d\n",
 -                     __FUNCTION__,
 +                     __func__,
                       NIPQUAD(old_saddr),
                       NIPQUAD(new_saddr));
        }
@@@ -1415,7 -1414,7 +1415,7 @@@ static int __init inet_init(void
  
        ip_init();
  
 -      tcp_v4_init(&inet_family_ops);
 +      tcp_v4_init();
  
        /* Setup TCP slab cache for open requests. */
        tcp_init();
         *      Set the ICMP layer up
         */
  
 -      icmp_init(&inet_family_ops);
 +      if (icmp_init() < 0)
 +              panic("Failed to create the ICMP control socket.\n");
  
        /*
         *      Initialise the multicast router
diff --combined net/ipv4/ip_sockglue.c
@@@ -57,7 -57,7 +57,7 @@@
  static void ip_cmsg_recv_pktinfo(struct msghdr *msg, struct sk_buff *skb)
  {
        struct in_pktinfo info;
 -      struct rtable *rt = (struct rtable *)skb->dst;
 +      struct rtable *rt = skb->rtable;
  
        info.ipi_addr.s_addr = ip_hdr(skb)->daddr;
        if (rt) {
@@@ -583,7 -583,7 +583,7 @@@ static int do_ip_setsockopt(struct soc
                }
  
                if (!mreq.imr_ifindex) {
-                       if (mreq.imr_address.s_addr == INADDR_ANY) {
+                       if (mreq.imr_address.s_addr == htonl(INADDR_ANY)) {
                                inet->mc_index = 0;
                                inet->mc_addr  = 0;
                                err = 0;
diff --combined net/ipv4/ipconfig.c
                                           - '3' from resolv.h */
  
  #define NONE __constant_htonl(INADDR_NONE)
+ #define ANY __constant_htonl(INADDR_ANY)
  
  /*
   * Public IP configuration
@@@ -291,7 -292,7 +292,7 @@@ static int __init ic_dev_ioctl(unsigne
  
        mm_segment_t oldfs = get_fs();
        set_fs(get_ds());
 -      res = devinet_ioctl(cmd, (struct ifreq __user *) arg);
 +      res = devinet_ioctl(&init_net, cmd, (struct ifreq __user *) arg);
        set_fs(oldfs);
        return res;
  }
@@@ -459,7 -460,10 +460,7 @@@ ic_rarp_recv(struct sk_buff *skb, struc
        if (rarp->ar_pro != htons(ETH_P_IP))
                goto drop;
  
 -      if (!pskb_may_pull(skb,
 -                         sizeof(struct arphdr) +
 -                         (2 * dev->addr_len) +
 -                         (2 * 4)))
 +      if (!pskb_may_pull(skb, arp_hdr_len(dev)))
                goto drop;
  
        /* OK, it is all there and looks valid, process... */
@@@ -1476,19 -1480,19 +1477,19 @@@ static int __init ip_auto_config_setup(
                        DBG(("IP-Config: Parameter #%d: `%s'\n", num, ip));
                        switch (num) {
                        case 0:
-                               if ((ic_myaddr = in_aton(ip)) == INADDR_ANY)
+                               if ((ic_myaddr = in_aton(ip)) == ANY)
                                        ic_myaddr = NONE;
                                break;
                        case 1:
-                               if ((ic_servaddr = in_aton(ip)) == INADDR_ANY)
+                               if ((ic_servaddr = in_aton(ip)) == ANY)
                                        ic_servaddr = NONE;
                                break;
                        case 2:
-                               if ((ic_gateway = in_aton(ip)) == INADDR_ANY)
+                               if ((ic_gateway = in_aton(ip)) == ANY)
                                        ic_gateway = NONE;
                                break;
                        case 3:
-                               if ((ic_netmask = in_aton(ip)) == INADDR_ANY)
+                               if ((ic_netmask = in_aton(ip)) == ANY)
                                        ic_netmask = NONE;
                                break;
                        case 4:
diff --combined net/ipv4/tcp_output.c
@@@ -1035,6 -1035,13 +1035,13 @@@ static void tcp_cwnd_validate(struct so
   * introducing MSS oddities to segment boundaries. In rare cases where
   * mss_now != mss_cache, we will request caller to create a small skb
   * per input skb which could be mostly avoided here (if desired).
+  *
+  * We explicitly want to create a request for splitting write queue tail
+  * to a small skb for Nagle purposes while avoiding unnecessary modulos,
+  * thus all the complexity (cwnd_len is always MSS multiple which we
+  * return whenever allowed by the other factors). Basically we need the
+  * modulo only when the receiver window alone is the limiting factor or
+  * when we would be allowed to send the split-due-to-Nagle skb fully.
   */
  static unsigned int tcp_mss_split_point(struct sock *sk, struct sk_buff *skb,
                                        unsigned int mss_now, unsigned int cwnd)
        if (likely(cwnd_len <= window && skb != tcp_write_queue_tail(sk)))
                return cwnd_len;
  
-       if (skb == tcp_write_queue_tail(sk) && cwnd_len <= skb->len)
+       needed = min(skb->len, window);
+       if (skb == tcp_write_queue_tail(sk) && cwnd_len <= needed)
                return cwnd_len;
  
-       needed = min(skb->len, window);
        return needed - needed % mss_now;
  }
  
@@@ -2560,7 -2568,6 +2568,7 @@@ void tcp_send_probe0(struct sock *sk
        }
  }
  
 +EXPORT_SYMBOL(tcp_select_initial_window);
  EXPORT_SYMBOL(tcp_connect);
  EXPORT_SYMBOL(tcp_make_synack);
  EXPORT_SYMBOL(tcp_simple_retransmit);
diff --combined net/sctp/input.c
@@@ -409,7 -409,7 +409,7 @@@ void sctp_icmp_proto_unreachable(struc
                           struct sctp_association *asoc,
                           struct sctp_transport *t)
  {
 -      SCTP_DEBUG_PRINTK("%s\n",  __FUNCTION__);
 +      SCTP_DEBUG_PRINTK("%s\n",  __func__);
  
        sctp_do_sm(SCTP_EVENT_T_OTHER,
                   SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
@@@ -944,7 -944,7 +944,7 @@@ static struct sctp_association *__sctp_
  static struct sctp_association *__sctp_rcv_asconf_lookup(
                                        sctp_chunkhdr_t *ch,
                                        const union sctp_addr *laddr,
-                                       __be32 peer_port,
+                                       __be16 peer_port,
                                        struct sctp_transport **transportp)
  {
        sctp_addip_chunk_t *asconf = (struct sctp_addip_chunk *)ch;
diff --combined net/sctp/ipv6.c
@@@ -89,6 -89,7 +89,7 @@@ static int sctp_inet6addr_event(struct 
        struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
        struct sctp_sockaddr_entry *addr = NULL;
        struct sctp_sockaddr_entry *temp;
+       int found = 0;
  
        switch (ev) {
        case NETDEV_UP:
                                        &sctp_local_addr_list, list) {
                        if (ipv6_addr_equal(&addr->a.v6.sin6_addr,
                                             &ifa->addr)) {
+                               found = 1;
                                addr->valid = 0;
                                list_del_rcu(&addr->list);
                                break;
                        }
                }
                spin_unlock_bh(&sctp_local_addr_lock);
-               if (addr && !addr->valid)
+               if (found)
                        call_rcu(&addr->rcu, sctp_local_addr_free);
                break;
        }
@@@ -223,7 -225,7 +225,7 @@@ static int sctp_v6_xmit(struct sk_buff 
  
        SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, "
                          "src:" NIP6_FMT " dst:" NIP6_FMT "\n",
 -                        __FUNCTION__, skb, skb->len,
 +                        __func__, skb, skb->len,
                          NIP6(fl.fl6_src), NIP6(fl.fl6_dst));
  
        SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
@@@ -248,7 -250,7 +250,7 @@@ static struct dst_entry *sctp_v6_get_ds
  
  
        SCTP_DEBUG_PRINTK("%s: DST=" NIP6_FMT " ",
 -                        __FUNCTION__, NIP6(fl.fl6_dst));
 +                        __func__, NIP6(fl.fl6_dst));
  
        if (saddr) {
                ipv6_addr_copy(&fl.fl6_src, &saddr->v6.sin6_addr);
                        NIP6(fl.fl6_src));
        }
  
 -      dst = ip6_route_output(NULL, &fl);
 +      dst = ip6_route_output(&init_net, NULL, &fl);
        if (!dst->error) {
                struct rt6_info *rt;
                rt = (struct rt6_info *)dst;
@@@ -310,11 -312,10 +312,11 @@@ static void sctp_v6_get_saddr(struct sc
  
        SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p "
                          "daddr:" NIP6_FMT " ",
 -                        __FUNCTION__, asoc, dst, NIP6(daddr->v6.sin6_addr));
 +                        __func__, asoc, dst, NIP6(daddr->v6.sin6_addr));
  
        if (!asoc) {
 -              ipv6_get_saddr(dst, &daddr->v6.sin6_addr,&saddr->v6.sin6_addr);
 +              ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL,
 +                                 &daddr->v6.sin6_addr, &saddr->v6.sin6_addr);
                SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: " NIP6_FMT "\n",
                                  NIP6(saddr->v6.sin6_addr));
                return;
        } else {
                printk(KERN_ERR "%s: asoc:%p Could not find a valid source "
                       "address for the dest:" NIP6_FMT "\n",
 -                     __FUNCTION__, asoc, NIP6(daddr->v6.sin6_addr));
 +                     __func__, asoc, NIP6(daddr->v6.sin6_addr));
        }
  
        rcu_read_unlock();
diff --combined net/sctp/protocol.c
@@@ -337,14 -337,14 +337,14 @@@ static int sctp_v4_cmp_addr(const unio
  static void sctp_v4_inaddr_any(union sctp_addr *addr, __be16 port)
  {
        addr->v4.sin_family = AF_INET;
-       addr->v4.sin_addr.s_addr = INADDR_ANY;
+       addr->v4.sin_addr.s_addr = htonl(INADDR_ANY);
        addr->v4.sin_port = port;
  }
  
  /* Is this a wildcard address? */
  static int sctp_v4_is_any(const union sctp_addr *addr)
  {
-       return INADDR_ANY == addr->v4.sin_addr.s_addr;
+       return htonl(INADDR_ANY) == addr->v4.sin_addr.s_addr;
  }
  
  /* This function checks if the address is a valid address to be used for
@@@ -363,7 -363,7 +363,7 @@@ static int sctp_v4_addr_valid(union sct
                return 0;
  
        /* Is this a broadcast address? */
 -      if (skb && ((struct rtable *)skb->dst)->rt_flags & RTCF_BROADCAST)
 +      if (skb && skb->rtable->rt_flags & RTCF_BROADCAST)
                return 0;
  
        return 1;
@@@ -375,7 -375,7 +375,7 @@@ static int sctp_v4_available(union sctp
        int ret = inet_addr_type(&init_net, addr->v4.sin_addr.s_addr);
  
  
-       if (addr->v4.sin_addr.s_addr != INADDR_ANY &&
+       if (addr->v4.sin_addr.s_addr != htonl(INADDR_ANY) &&
           ret != RTN_LOCAL &&
           !sp->inet.freebind &&
           !sysctl_ip_nonlocal_bind)
@@@ -451,7 -451,7 +451,7 @@@ static struct dst_entry *sctp_v4_get_ds
                fl.fl4_src = saddr->v4.sin_addr.s_addr;
  
        SCTP_DEBUG_PRINTK("%s: DST:%u.%u.%u.%u, SRC:%u.%u.%u.%u - ",
 -                        __FUNCTION__, NIPQUAD(fl.fl4_dst),
 +                        __func__, NIPQUAD(fl.fl4_dst),
                          NIPQUAD(fl.fl4_src));
  
        if (!ip_route_output_key(&init_net, &rt, &fl)) {
@@@ -539,7 -539,7 +539,7 @@@ static void sctp_v4_get_saddr(struct sc
  /* What interface did this skb arrive on? */
  static int sctp_v4_skb_iif(const struct sk_buff *skb)
  {
 -      return ((struct rtable *)skb->dst)->rt_iif;
 +      return skb->rtable->rt_iif;
  }
  
  /* Was this packet marked by Explicit Congestion Notification? */
@@@ -628,10 -628,8 +628,11 @@@ static int sctp_inetaddr_event(struct n
        struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
        struct sctp_sockaddr_entry *addr = NULL;
        struct sctp_sockaddr_entry *temp;
+       int found = 0;
  
 +      if (ifa->ifa_dev->dev->nd_net != &init_net)
 +              return NOTIFY_DONE;
 +
        switch (ev) {
        case NETDEV_UP:
                addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
                list_for_each_entry_safe(addr, temp,
                                        &sctp_local_addr_list, list) {
                        if (addr->a.v4.sin_addr.s_addr == ifa->ifa_local) {
+                               found = 1;
                                addr->valid = 0;
                                list_del_rcu(&addr->list);
                                break;
                        }
                }
                spin_unlock_bh(&sctp_local_addr_lock);
-               if (addr && !addr->valid)
+               if (found)
                        call_rcu(&addr->rcu, sctp_local_addr_free);
                break;
        }
@@@ -786,8 -785,8 +788,8 @@@ static int sctp_inet_cmp_addr(const uni
        /* PF_INET only supports AF_INET addresses. */
        if (addr1->sa.sa_family != addr2->sa.sa_family)
                return 0;
-       if (INADDR_ANY == addr1->v4.sin_addr.s_addr ||
-           INADDR_ANY == addr2->v4.sin_addr.s_addr)
+       if (htonl(INADDR_ANY) == addr1->v4.sin_addr.s_addr ||
+           htonl(INADDR_ANY) == addr2->v4.sin_addr.s_addr)
                return 1;
        if (addr1->v4.sin_addr.s_addr == addr2->v4.sin_addr.s_addr)
                return 1;
@@@ -827,9 -826,9 +829,9 @@@ static inline int sctp_v4_xmit(struct s
  {
        SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, "
                          "src:%u.%u.%u.%u, dst:%u.%u.%u.%u\n",
 -                        __FUNCTION__, skb, skb->len,
 -                        NIPQUAD(((struct rtable *)skb->dst)->rt_src),
 -                        NIPQUAD(((struct rtable *)skb->dst)->rt_dst));
 +                        __func__, skb, skb->len,
 +                        NIPQUAD(skb->rtable->rt_src),
 +                        NIPQUAD(skb->rtable->rt_dst));
  
        SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
        return ip_queue_xmit(skb, ipfragok);
diff --combined net/sctp/socket.c
@@@ -525,7 -525,7 +525,7 @@@ static int sctp_send_asconf_add_ip(stru
        ep = sp->ep;
  
        SCTP_DEBUG_PRINTK("%s: (sk: %p, addrs: %p, addrcnt: %d)\n",
 -                        __FUNCTION__, sk, addrs, addrcnt);
 +                        __func__, sk, addrs, addrcnt);
  
        list_for_each(pos, &ep->asocs) {
                asoc = list_entry(pos, struct sctp_association, asocs);
@@@ -711,7 -711,7 +711,7 @@@ static int sctp_send_asconf_del_ip(stru
        ep = sp->ep;
  
        SCTP_DEBUG_PRINTK("%s: (sk: %p, addrs: %p, addrcnt: %d)\n",
 -                        __FUNCTION__, sk, addrs, addrcnt);
 +                        __func__, sk, addrs, addrcnt);
  
        list_for_each(pos, &ep->asocs) {
                asoc = list_entry(pos, struct sctp_association, asocs);
@@@ -1197,7 -1197,7 +1197,7 @@@ SCTP_STATIC int sctp_setsockopt_connect
        struct sockaddr *kaddrs;
  
        SCTP_DEBUG_PRINTK("%s - sk %p addrs %p addrs_size %d\n",
 -                        __FUNCTION__, sk, addrs, addrs_size);
 +                        __func__, sk, addrs, addrs_size);
  
        if (unlikely(addrs_size <= 0))
                return -EINVAL;
@@@ -2933,17 -2933,39 +2933,39 @@@ static int sctp_setsockopt_maxburst(str
                                    char __user *optval,
                                    int optlen)
  {
+       struct sctp_assoc_value params;
+       struct sctp_sock *sp;
+       struct sctp_association *asoc;
        int val;
+       int assoc_id = 0;
  
-       if (optlen != sizeof(int))
+       if (optlen < sizeof(int))
                return -EINVAL;
-       if (get_user(val, (int __user *)optval))
-               return -EFAULT;
  
-       if (val < 0)
+       if (optlen == sizeof(int)) {
+               printk(KERN_WARNING
+                  "SCTP: Use of int in max_burst socket option deprecated\n");
+               printk(KERN_WARNING
+                  "SCTP: Use struct sctp_assoc_value instead\n");
+               if (copy_from_user(&val, optval, optlen))
+                       return -EFAULT;
+       } else if (optlen == sizeof(struct sctp_assoc_value)) {
+               if (copy_from_user(&params, optval, optlen))
+                       return -EFAULT;
+               val = params.assoc_value;
+               assoc_id = params.assoc_id;
+       } else
                return -EINVAL;
  
-       sctp_sk(sk)->max_burst = val;
+       sp = sctp_sk(sk);
+       if (assoc_id != 0) {
+               asoc = sctp_id2assoc(sk, assoc_id);
+               if (!asoc)
+                       return -EINVAL;
+               asoc->max_burst = val;
+       } else
+               sp->max_burst = val;
  
        return 0;
  }
@@@ -3280,7 -3302,7 +3302,7 @@@ SCTP_STATIC int sctp_connect(struct soc
        sctp_lock_sock(sk);
  
        SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d\n",
 -                        __FUNCTION__, sk, addr, addr_len);
 +                        __func__, sk, addr, addr_len);
  
        /* Validate addr_len before calling common connect/connectx routine. */
        af = sctp_get_af_specific(addr->sa_family);
@@@ -3801,7 -3823,7 +3823,7 @@@ static int sctp_getsockopt_peeloff(stru
                goto out;
        }
  
 -      SCTP_DEBUG_PRINTK("%s: sk: %p asoc: %p\n", __FUNCTION__, sk, asoc);
 +      SCTP_DEBUG_PRINTK("%s: sk: %p asoc: %p\n", __func__, sk, asoc);
  
        retval = sctp_do_peeloff(asoc, &newsock);
        if (retval < 0)
        }
  
        SCTP_DEBUG_PRINTK("%s: sk: %p asoc: %p newsk: %p sd: %d\n",
 -                        __FUNCTION__, sk, asoc, newsock->sk, retval);
 +                        __func__, sk, asoc, newsock->sk, retval);
  
        /* Return the fd mapped to the new socket.  */
        peeloff.sd = retval;
@@@ -5005,20 -5027,45 +5027,45 @@@ static int sctp_getsockopt_maxburst(str
                                    char __user *optval,
                                    int __user *optlen)
  {
-       int val;
+       struct sctp_assoc_value params;
+       struct sctp_sock *sp;
+       struct sctp_association *asoc;
  
        if (len < sizeof(int))
                return -EINVAL;
  
-       len = sizeof(int);
+       if (len == sizeof(int)) {
+               printk(KERN_WARNING
+                  "SCTP: Use of int in max_burst socket option deprecated\n");
+               printk(KERN_WARNING
+                  "SCTP: Use struct sctp_assoc_value instead\n");
+               params.assoc_id = 0;
+       } else if (len == sizeof (struct sctp_assoc_value)) {
+               if (copy_from_user(&params, optval, len))
+                       return -EFAULT;
+       } else
+               return -EINVAL;
  
-       val = sctp_sk(sk)->max_burst;
-       if (put_user(len, optlen))
-               return -EFAULT;
-       if (copy_to_user(optval, &val, len))
-               return -EFAULT;
+       sp = sctp_sk(sk);
+       if (params.assoc_id != 0) {
+               asoc = sctp_id2assoc(sk, params.assoc_id);
+               if (!asoc)
+                       return -EINVAL;
+               params.assoc_value = asoc->max_burst;
+       } else
+               params.assoc_value = sp->max_burst;
+       if (len == sizeof(int)) {
+               if (copy_to_user(optval, &params.assoc_value, len))
+                       return -EFAULT;
+       } else {
+               if (copy_to_user(optval, &params, len))
+                       return -EFAULT;
+       }
+       return 0;
  
-       return -ENOTSUPP;
  }
  
  static int sctp_getsockopt_hmac_ident(struct sock *sk, int len,
@@@ -6186,7 -6233,7 +6233,7 @@@ static int sctp_wait_for_connect(struc
        long current_timeo = *timeo_p;
        DEFINE_WAIT(wait);
  
 -      SCTP_DEBUG_PRINTK("%s: asoc=%p, timeo=%ld\n", __FUNCTION__, asoc,
 +      SCTP_DEBUG_PRINTK("%s: asoc=%p, timeo=%ld\n", __func__, asoc,
                          (long)(*timeo_p));
  
        /* Increment the association's refcnt.  */