Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
authorDavid S. Miller <davem@davemloft.net>
Tue, 15 Jul 2008 03:23:54 +0000 (20:23 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 15 Jul 2008 03:23:54 +0000 (20:23 -0700)
Conflicts:

net/netfilter/nf_conntrack_proto_tcp.c

14 files changed:
1  2 
Documentation/networking/ip-sysctl.txt
drivers/net/tun.c
drivers/net/wireless/libertas/scan.c
drivers/net/wireless/rt2x00/rt2400pci.c
drivers/net/wireless/rt2x00/rt2500pci.c
drivers/net/wireless/rt2x00/rt2500usb.c
drivers/net/wireless/rt2x00/rt61pci.c
drivers/net/wireless/rt2x00/rt73usb.c
drivers/net/wireless/zd1211rw/zd_mac.c
net/ipv4/fib_trie.c
net/ipv6/exthdrs.c
net/mac80211/rc80211_pid.h
net/mac80211/rc80211_pid_algo.c
net/netfilter/nf_conntrack_proto_tcp.c

index a40feaee62ec084a0b4938ad5e97b27dfdee516c,946b66e1b65214f4becc5d2563f73180fe331837..d84932650fd3e926cc11d5fa0bcaee6cc8a8cd33
@@@ -148,9 -148,9 +148,9 @@@ tcp_available_congestion_control - STRI
        but not loaded.
  
  tcp_base_mss - INTEGER
-       The initial value of search_low to be used by Packetization Layer
-       Path MTU Discovery (MTU probing).  If MTU probing is enabled,
-       this is the inital MSS used by the connection.
+       The initial value of search_low to be used by the packetization layer
+       Path MTU discovery (MTU probing).  If MTU probing is enabled,
+       this is the initial MSS used by the connection.
  
  tcp_congestion_control - STRING
        Set the congestion control algorithm to be used for new
@@@ -185,10 -185,9 +185,9 @@@ tcp_frto - INTEGE
        timeouts.  It is particularly beneficial in wireless environments
        where packet loss is typically due to random radio interference
        rather than intermediate router congestion.  F-RTO is sender-side
-       only modification.  Therefore it does not require any support from
-       the peer, but in a typical case, however, where wireless link is
-       the local access link and most of the data flows downlink, the
-       faraway servers should have F-RTO enabled to take advantage of it.
+       only modification. Therefore it does not require any support from
+       the peer.
        If set to 1, basic version is enabled.  2 enables SACK enhanced
        F-RTO if flow uses SACK.  The basic version can be used also when
        SACK is in use though scenario(s) with it exists where F-RTO
@@@ -276,7 -275,7 +275,7 @@@ tcp_mem - vector of 3 INTEGERs: min, pr
        memory.
  
  tcp_moderate_rcvbuf - BOOLEAN
-       If set, TCP performs receive buffer autotuning, attempting to
+       If set, TCP performs receive buffer auto-tuning, attempting to
        automatically size the buffer (no greater than tcp_rmem[2]) to
        match the size required by the path for full throughput.  Enabled by
        default.
@@@ -336,7 -335,7 +335,7 @@@ tcp_rmem - vector of 3 INTEGERs: min, d
        pressure.
        Default: 8K
  
-       default: default size of receive buffer used by TCP sockets.
+       default: initial size of receive buffer used by TCP sockets.
        This value overrides net.core.rmem_default used by other protocols.
        Default: 87380 bytes. This value results in window of 65535 with
        default setting of tcp_adv_win_scale and tcp_app_win:0 and a bit
  
        max: maximal size of receive buffer allowed for automatically
        selected receiver buffers for TCP socket. This value does not override
-       net.core.rmem_max, "static" selection via SO_RCVBUF does not use this.
-       Default: 87380*2 bytes.
+       net.core.rmem_max.  Calling setsockopt() with SO_RCVBUF disables
+       automatic tuning of that socket's receive buffer size, in which
+       case this value is ignored.
+       Default: between 87380B and 4MB, depending on RAM size.
  
  tcp_sack - BOOLEAN
        Enable select acknowledgments (SACKS).
@@@ -358,7 -359,7 +359,7 @@@ tcp_slow_start_after_idle - BOOLEA
        Default: 1
  
  tcp_stdurg - BOOLEAN
-       Use the Host requirements interpretation of the TCP urg pointer field.
+       Use the Host requirements interpretation of the TCP urgent pointer field.
        Most hosts use the older BSD interpretation, so if you turn this on
        Linux might not communicate correctly with them.
        Default: FALSE
@@@ -371,12 -372,12 +372,12 @@@ tcp_synack_retries - INTEGE
  tcp_syncookies - BOOLEAN
        Only valid when the kernel was compiled with CONFIG_SYNCOOKIES
        Send out syncookies when the syn backlog queue of a socket
-       overflows. This is to prevent against the common 'syn flood attack'
+       overflows. This is to prevent against the common 'SYN flood attack'
        Default: FALSE
  
        Note, that syncookies is fallback facility.
        It MUST NOT be used to help highly loaded servers to stand
-       against legal connection rate. If you see synflood warnings
+       against legal connection rate. If you see SYN flood warnings
        in your logs, but investigation shows that they occur
        because of overload with legal connections, you should tune
        another parameters until this warning disappear.
        to use TCP extensions, can result in serious degradation
        of some services (f.e. SMTP relaying), visible not by you,
        but your clients and relays, contacting you. While you see
-       synflood warnings in logs not being really flooded, your server
+       SYN flood warnings in logs not being really flooded, your server
        is seriously misconfigured.
  
  tcp_syn_retries - INTEGER
@@@ -419,19 -420,21 +420,21 @@@ tcp_window_scaling - BOOLEA
        Enable window scaling as defined in RFC1323.
  
  tcp_wmem - vector of 3 INTEGERs: min, default, max
-       min: Amount of memory reserved for send buffers for TCP socket.
+       min: Amount of memory reserved for send buffers for TCP sockets.
        Each TCP socket has rights to use it due to fact of its birth.
        Default: 4K
  
-       default: Amount of memory allowed for send buffers for TCP socket
-       by default. This value overrides net.core.wmem_default used
-       by other protocols, it is usually lower than net.core.wmem_default.
+       default: initial size of send buffer used by TCP sockets.  This
+       value overrides net.core.wmem_default used by other protocols.
+       It is usually lower than net.core.wmem_default.
        Default: 16K
  
-       max: Maximal amount of memory allowed for automatically selected
-       send buffers for TCP socket. This value does not override
-       net.core.wmem_max, "static" selection via SO_SNDBUF does not use this.
-       Default: 128K
+       max: Maximal amount of memory allowed for automatically tuned
+       send buffers for TCP sockets. This value does not override
+       net.core.wmem_max.  Calling setsockopt() with SO_SNDBUF disables
+       automatic tuning of that socket's send buffer size, in which case
+       this value is ignored.
+       Default: between 64K and 4MB, depending on RAM size.
  
  tcp_workaround_signed_windows - BOOLEAN
        If set, assume no receipt of a window scaling option means the
@@@ -548,9 -551,8 +551,9 @@@ icmp_echo_ignore_broadcasts - BOOLEA
  icmp_ratelimit - INTEGER
        Limit the maximal rates for sending ICMP packets whose type matches
        icmp_ratemask (see below) to specific targets.
 -      0 to disable any limiting, otherwise the maximal rate in jiffies(1)
 -      Default: 100
 +      0 to disable any limiting,
 +      otherwise the minimal space between responses in milliseconds.
 +      Default: 1000
  
  icmp_ratemask - INTEGER
        Mask made of ICMP types for which rates are being limited.
@@@ -1021,23 -1023,11 +1024,23 @@@ max_addresses - INTEGE
        autoconfigured addresses.
        Default: 16
  
 +disable_ipv6 - BOOLEAN
 +      Disable IPv6 operation.
 +      Default: FALSE (enable IPv6 operation)
 +
 +accept_dad - INTEGER
 +      Whether to accept DAD (Duplicate Address Detection).
 +      0: Disable DAD
 +      1: Enable DAD (default)
 +      2: Enable DAD, and disable IPv6 operation if MAC-based duplicate
 +         link-local address has been found.
 +
  icmp/*:
  ratelimit - INTEGER
        Limit the maximal rates for sending ICMPv6 packets.
 -      0 to disable any limiting, otherwise the maximal rate in jiffies(1)
 -      Default: 100
 +      0 to disable any limiting,
 +      otherwise the minimal space between responses in milliseconds.
 +      Default: 1000
  
  
  IPv6 Update by:
@@@ -1073,24 -1063,193 +1076,193 @@@ bridge-nf-filter-pppoe-tagged - BOOLEA
        Default: 1
  
  
- UNDOCUMENTED:
+ proc/sys/net/sctp/* Variables:
+ addip_enable - BOOLEAN
+       Enable or disable extension of  Dynamic Address Reconfiguration
+       (ADD-IP) functionality specified in RFC5061.  This extension provides
+       the ability to dynamically add and remove new addresses for the SCTP
+       associations.
+       1: Enable extension.
+       0: Disable extension.
+       Default: 0
+ addip_noauth_enable - BOOLEAN
+       Dynamic Address Reconfiguration (ADD-IP) requires the use of
+       authentication to protect the operations of adding or removing new
+       addresses.  This requirement is mandated so that unauthorized hosts
+       would not be able to hijack associations.  However, older
+       implementations may not have implemented this requirement while
+       allowing the ADD-IP extension.  For reasons of interoperability,
+       we provide this variable to control the enforcement of the
+       authentication requirement.
+       1: Allow ADD-IP extension to be used without authentication.  This
+          should only be set in a closed environment for interoperability
+          with older implementations.
+       0: Enforce the authentication requirement
+       Default: 0
+ auth_enable - BOOLEAN
+       Enable or disable Authenticated Chunks extension.  This extension
+       provides the ability to send and receive authenticated chunks and is
+       required for secure operation of Dynamic Address Reconfiguration
+       (ADD-IP) extension.
+       1: Enable this extension.
+       0: Disable this extension.
+       Default: 0
+ prsctp_enable - BOOLEAN
+       Enable or disable the Partial Reliability extension (RFC3758) which
+       is used to notify peers that a given DATA should no longer be expected.
+       1: Enable extension
+       0: Disable
+       Default: 1
+ max_burst - INTEGER
+       The limit of the number of new packets that can be initially sent.  It
+       controls how bursty the generated traffic can be.
+       Default: 4
+ association_max_retrans - INTEGER
+       Set the maximum number for retransmissions that an association can
+       attempt deciding that the remote end is unreachable.  If this value
+       is exceeded, the association is terminated.
+       Default: 10
+ max_init_retransmits - INTEGER
+       The maximum number of retransmissions of INIT and COOKIE-ECHO chunks
+       that an association will attempt before declaring the destination
+       unreachable and terminating.
+       Default: 8
+ path_max_retrans - INTEGER
+       The maximum number of retransmissions that will be attempted on a given
+       path.  Once this threshold is exceeded, the path is considered
+       unreachable, and new traffic will use a different path when the
+       association is multihomed.
+       Default: 5
+ rto_initial - INTEGER
+       The initial round trip timeout value in milliseconds that will be used
+       in calculating round trip times.  This is the initial time interval
+       for retransmissions.
+       Default: 3000
  
- dev_weight FIXME
- discovery_slots FIXME
- discovery_timeout FIXME
- fast_poll_increase FIXME
- ip6_queue_maxlen FIXME
- lap_keepalive_time FIXME
- lo_cong FIXME
- max_baud_rate FIXME
- max_dgram_qlen FIXME
- max_noreply_time FIXME
- max_tx_data_size FIXME
- max_tx_window FIXME
- min_tx_turn_time FIXME
- mod_cong FIXME
- no_cong FIXME
- no_cong_thresh FIXME
- slot_timeout FIXME
- warn_noreply_time FIXME
+ rto_max - INTEGER
+       The maximum value (in milliseconds) of the round trip timeout.  This
+       is the largest time interval that can elapse between retransmissions.
+       Default: 60000
+ rto_min - INTEGER
+       The minimum value (in milliseconds) of the round trip timeout.  This
+       is the smallest time interval the can elapse between retransmissions.
+       Default: 1000
+ hb_interval - INTEGER
+       The interval (in milliseconds) between HEARTBEAT chunks.  These chunks
+       are sent at the specified interval on idle paths to probe the state of
+       a given path between 2 associations.
+       Default: 30000
+ sack_timeout - INTEGER
+       The amount of time (in milliseconds) that the implementation will wait
+       to send a SACK.
+       Default: 200
+ valid_cookie_life - INTEGER
+       The default lifetime of the SCTP cookie (in milliseconds).  The cookie
+       is used during association establishment.
+       Default: 60000
+ cookie_preserve_enable - BOOLEAN
+       Enable or disable the ability to extend the lifetime of the SCTP cookie
+       that is used during the establishment phase of SCTP association
+       1: Enable cookie lifetime extension.
+       0: Disable
+       Default: 1
+ rcvbuf_policy - INTEGER
+       Determines if the receive buffer is attributed to the socket or to
+       association.   SCTP supports the capability to create multiple
+       associations on a single socket.  When using this capability, it is
+       possible that a single stalled association that's buffering a lot
+       of data may block other associations from delivering their data by
+       consuming all of the receive buffer space.  To work around this,
+       the rcvbuf_policy could be set to attribute the receiver buffer space
+       to each association instead of the socket.  This prevents the described
+       blocking.
+       1: rcvbuf space is per association
+       0: recbuf space is per socket
+       Default: 0
+ sndbuf_policy - INTEGER
+       Similar to rcvbuf_policy above, this applies to send buffer space.
+       1: Send buffer is tracked per association
+       0: Send buffer is tracked per socket.
+       Default: 0
+ sctp_mem - vector of 3 INTEGERs: min, pressure, max
+       Number of pages allowed for queueing by all SCTP sockets.
+       min: Below this number of pages SCTP is not bothered about its
+       memory appetite. When amount of memory allocated by SCTP exceeds
+       this number, SCTP starts to moderate memory usage.
+       pressure: This value was introduced to follow format of tcp_mem.
+       max: Number of pages allowed for queueing by all SCTP sockets.
+       Default is calculated at boot time from amount of available memory.
+ sctp_rmem - vector of 3 INTEGERs: min, default, max
+       See tcp_rmem for a description.
+ sctp_wmem  - vector of 3 INTEGERs: min, default, max
+       See tcp_wmem for a description.
+ UNDOCUMENTED:
  
+ /proc/sys/net/core/*
+       dev_weight FIXME
+ /proc/sys/net/unix/*
+       max_dgram_qlen FIXME
+ /proc/sys/net/irda/*
+       fast_poll_increase FIXME
+       warn_noreply_time FIXME
+       discovery_slots FIXME
+       slot_timeout FIXME
+       max_baud_rate FIXME
+       discovery_timeout FIXME
+       lap_keepalive_time FIXME
+       max_noreply_time FIXME
+       max_tx_data_size FIXME
+       max_tx_window FIXME
+       min_tx_turn_time FIXME
diff --combined drivers/net/tun.c
index aa4ee4439f048e864d559764c5f57316d1b6a7b3,b9018bfa0a9724d2a28ee54d9f9af50429c55da0..2693f883ecda78d112fe181ddc39da8e17edfd42
@@@ -63,7 -63,6 +63,7 @@@
  #include <linux/if_tun.h>
  #include <linux/crc32.h>
  #include <linux/nsproxy.h>
 +#include <linux/virtio_net.h>
  #include <net/net_namespace.h>
  #include <net/netns/generic.h>
  
@@@ -284,7 -283,6 +284,7 @@@ static __inline__ ssize_t tun_get_user(
        struct tun_pi pi = { 0, __constant_htons(ETH_P_IP) };
        struct sk_buff *skb;
        size_t len = count, align = 0;
 +      struct virtio_net_hdr gso = { 0 };
  
        if (!(tun->flags & TUN_NO_PI)) {
                if ((len -= sizeof(pi)) > count)
                        return -EFAULT;
        }
  
 +      if (tun->flags & TUN_VNET_HDR) {
 +              if ((len -= sizeof(gso)) > count)
 +                      return -EINVAL;
 +
 +              if (memcpy_fromiovec((void *)&gso, iv, sizeof(gso)))
 +                      return -EFAULT;
 +
 +              if (gso.hdr_len > len)
 +                      return -EINVAL;
 +      }
 +
        if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) {
                align = NET_IP_ALIGN;
                if (unlikely(len < ETH_HLEN))
                return -EFAULT;
        }
  
 +      if (gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
 +              if (!skb_partial_csum_set(skb, gso.csum_start,
 +                                        gso.csum_offset)) {
 +                      tun->dev->stats.rx_frame_errors++;
 +                      kfree_skb(skb);
 +                      return -EINVAL;
 +              }
 +      } else if (tun->flags & TUN_NOCHECKSUM)
 +              skb->ip_summed = CHECKSUM_UNNECESSARY;
 +
        switch (tun->flags & TUN_TYPE_MASK) {
        case TUN_TUN_DEV:
                if (tun->flags & TUN_NO_PI) {
                break;
        };
  
 -      if (tun->flags & TUN_NOCHECKSUM)
 -              skb->ip_summed = CHECKSUM_UNNECESSARY;
 +      if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) {
 +              pr_debug("GSO!\n");
 +              switch (gso.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
 +              case VIRTIO_NET_HDR_GSO_TCPV4:
 +                      skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
 +                      break;
 +              case VIRTIO_NET_HDR_GSO_TCPV6:
 +                      skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
 +                      break;
 +              default:
 +                      tun->dev->stats.rx_frame_errors++;
 +                      kfree_skb(skb);
 +                      return -EINVAL;
 +              }
 +
 +              if (gso.gso_type & VIRTIO_NET_HDR_GSO_ECN)
 +                      skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN;
 +
 +              skb_shinfo(skb)->gso_size = gso.gso_size;
 +              if (skb_shinfo(skb)->gso_size == 0) {
 +                      tun->dev->stats.rx_frame_errors++;
 +                      kfree_skb(skb);
 +                      return -EINVAL;
 +              }
 +
 +              /* Header must be checked, and gso_segs computed. */
 +              skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
 +              skb_shinfo(skb)->gso_segs = 0;
 +      }
  
        netif_rx_ni(skb);
        tun->dev->last_rx = jiffies;
@@@ -434,39 -384,6 +434,39 @@@ static __inline__ ssize_t tun_put_user(
                total += sizeof(pi);
        }
  
 +      if (tun->flags & TUN_VNET_HDR) {
 +              struct virtio_net_hdr gso = { 0 }; /* no info leak */
 +              if ((len -= sizeof(gso)) < 0)
 +                      return -EINVAL;
 +
 +              if (skb_is_gso(skb)) {
 +                      struct skb_shared_info *sinfo = skb_shinfo(skb);
 +
 +                      /* This is a hint as to how much should be linear. */
 +                      gso.hdr_len = skb_headlen(skb);
 +                      gso.gso_size = sinfo->gso_size;
 +                      if (sinfo->gso_type & SKB_GSO_TCPV4)
 +                              gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
 +                      else if (sinfo->gso_type & SKB_GSO_TCPV6)
 +                              gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
 +                      else
 +                              BUG();
 +                      if (sinfo->gso_type & SKB_GSO_TCP_ECN)
 +                              gso.gso_type |= VIRTIO_NET_HDR_GSO_ECN;
 +              } else
 +                      gso.gso_type = VIRTIO_NET_HDR_GSO_NONE;
 +
 +              if (skb->ip_summed == CHECKSUM_PARTIAL) {
 +                      gso.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
 +                      gso.csum_start = skb->csum_start - skb_headroom(skb);
 +                      gso.csum_offset = skb->csum_offset;
 +              } /* else everything is zero */
 +
 +              if (unlikely(memcpy_toiovec(iv, (void *)&gso, sizeof(gso))))
 +                      return -EFAULT;
 +              total += sizeof(gso);
 +      }
 +
        len = min_t(int, skb->len, len);
  
        skb_copy_datagram_iovec(skb, 0, iv, len);
@@@ -681,15 -598,16 +681,21 @@@ static int tun_set_iff(struct net *net
        else
                tun->flags &= ~TUN_ONE_QUEUE;
  
 +      if (ifr->ifr_flags & IFF_VNET_HDR)
 +              tun->flags |= TUN_VNET_HDR;
 +      else
 +              tun->flags &= ~TUN_VNET_HDR;
 +
        file->private_data = tun;
        tun->attached = 1;
        get_net(dev_net(tun->dev));
  
+       /* Make sure persistent devices do not get stuck in
+        * xoff state.
+        */
+       if (netif_running(tun->dev))
+               netif_wake_queue(tun->dev);
        strcpy(ifr->ifr_name, tun->dev->name);
        return 0;
  
        return err;
  }
  
 +/* This is like a cut-down ethtool ops, except done via tun fd so no
 + * privs required. */
 +static int set_offload(struct net_device *dev, unsigned long arg)
 +{
 +      unsigned int old_features, features;
 +
 +      old_features = dev->features;
 +      /* Unset features, set them as we chew on the arg. */
 +      features = (old_features & ~(NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST
 +                                  |NETIF_F_TSO_ECN|NETIF_F_TSO|NETIF_F_TSO6));
 +
 +      if (arg & TUN_F_CSUM) {
 +              features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
 +              arg &= ~TUN_F_CSUM;
 +
 +              if (arg & (TUN_F_TSO4|TUN_F_TSO6)) {
 +                      if (arg & TUN_F_TSO_ECN) {
 +                              features |= NETIF_F_TSO_ECN;
 +                              arg &= ~TUN_F_TSO_ECN;
 +                      }
 +                      if (arg & TUN_F_TSO4)
 +                              features |= NETIF_F_TSO;
 +                      if (arg & TUN_F_TSO6)
 +                              features |= NETIF_F_TSO6;
 +                      arg &= ~(TUN_F_TSO4|TUN_F_TSO6);
 +              }
 +      }
 +
 +      /* This gives the user a way to test for new features in future by
 +       * trying to set them. */
 +      if (arg)
 +              return -EINVAL;
 +
 +      dev->features = features;
 +      if (old_features != dev->features)
 +              netdev_features_change(dev);
 +
 +      return 0;
 +}
 +
  static int tun_chr_ioctl(struct inode *inode, struct file *file,
                         unsigned int cmd, unsigned long arg)
  {
                return 0;
        }
  
 +      if (cmd == TUNGETFEATURES) {
 +              /* Currently this just means: "what IFF flags are valid?".
 +               * This is needed because we never checked for invalid flags on
 +               * TUNSETIFF. */
 +              return put_user(IFF_TUN | IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE |
 +                              IFF_VNET_HDR,
 +                              (unsigned int __user*)argp);
 +      }
 +
        if (!tun)
                return -EBADFD;
  
                break;
  #endif
  
 +      case TUNSETOFFLOAD:
 +      {
 +              int ret;
 +              rtnl_lock();
 +              ret = set_offload(tun->dev, arg);
 +              rtnl_unlock();
 +              return ret;
 +      }
 +
        case SIOCGIFFLAGS:
                ifr.ifr_flags = tun->if_flags;
                if (copy_to_user( argp, &ifr, sizeof ifr))
index 343ed38f772d6a30d4f38526d381c34f7b6eae22,387d4878af2f02488b32f95804e66ed0dea6e377..4b274562f965df9565003550e95a15c044e5e1ab
@@@ -567,11 -567,11 +567,11 @@@ static int lbs_process_bss(struct bss_d
        pos += 8;
  
        /* beacon interval is 2 bytes long */
-       bss->beaconperiod = le16_to_cpup((void *) pos);
+       bss->beaconperiod = get_unaligned_le16(pos);
        pos += 2;
  
        /* capability information is 2 bytes long */
-       bss->capability = le16_to_cpup((void *) pos);
+       bss->capability = get_unaligned_le16(pos);
        lbs_deb_scan("process_bss: capabilities 0x%04x\n", bss->capability);
        pos += 2;
  
@@@ -776,9 -776,8 +776,9 @@@ out
  #define MAX_CUSTOM_LEN 64
  
  static inline char *lbs_translate_scan(struct lbs_private *priv,
 -                                     char *start, char *stop,
 -                                     struct bss_descriptor *bss)
 +                                          struct iw_request_info *info,
 +                                          char *start, char *stop,
 +                                          struct bss_descriptor *bss)
  {
        struct chan_freq_power *cfp;
        char *current_val;      /* For rates */
        iwe.cmd = SIOCGIWAP;
        iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
        memcpy(iwe.u.ap_addr.sa_data, &bss->bssid, ETH_ALEN);
 -      start = iwe_stream_add_event(start, stop, &iwe, IW_EV_ADDR_LEN);
 +      start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
  
        /* SSID */
        iwe.cmd = SIOCGIWESSID;
        iwe.u.data.flags = 1;
        iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IW_ESSID_MAX_SIZE);
 -      start = iwe_stream_add_point(start, stop, &iwe, bss->ssid);
 +      start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid);
  
        /* Mode */
        iwe.cmd = SIOCGIWMODE;
        iwe.u.mode = bss->mode;
 -      start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN);
 +      start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
  
        /* Frequency */
        iwe.cmd = SIOCGIWFREQ;
        iwe.u.freq.m = (long)cfp->freq * 100000;
        iwe.u.freq.e = 1;
 -      start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN);
 +      start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
  
        /* Add quality statistics */
        iwe.cmd = IWEVQUAL;
                nf = priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
                iwe.u.qual.level = CAL_RSSI(snr, nf);
        }
 -      start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
 +      start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
  
        /* Add encryption capability */
        iwe.cmd = SIOCGIWENCODE;
                iwe.u.data.flags = IW_ENCODE_DISABLED;
        }
        iwe.u.data.length = 0;
 -      start = iwe_stream_add_point(start, stop, &iwe, bss->ssid);
 +      start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid);
  
 -      current_val = start + IW_EV_LCP_LEN;
 +      current_val = start + iwe_stream_lcp_len(info);
  
        iwe.cmd = SIOCGIWRATE;
        iwe.u.bitrate.fixed = 0;
        for (j = 0; bss->rates[j] && (j < sizeof(bss->rates)); j++) {
                /* Bit rate given in 500 kb/s units */
                iwe.u.bitrate.value = bss->rates[j] * 500000;
 -              current_val = iwe_stream_add_value(start, current_val,
 -                                       stop, &iwe, IW_EV_PARAM_LEN);
 +              current_val = iwe_stream_add_value(info, start, current_val,
 +                                                 stop, &iwe, IW_EV_PARAM_LEN);
        }
        if ((bss->mode == IW_MODE_ADHOC) && priv->adhoccreate
            && !lbs_ssid_cmp(priv->curbssparams.ssid,
                             priv->curbssparams.ssid_len,
                             bss->ssid, bss->ssid_len)) {
                iwe.u.bitrate.value = 22 * 500000;
 -              current_val = iwe_stream_add_value(start, current_val,
 +              current_val = iwe_stream_add_value(info, start, current_val,
                                                   stop, &iwe, IW_EV_PARAM_LEN);
        }
        /* Check if we added any event */
 -      if((current_val - start) > IW_EV_LCP_LEN)
 +      if ((current_val - start) > iwe_stream_lcp_len(info))
                start = current_val;
  
        memset(&iwe, 0, sizeof(iwe));
                memcpy(buf, bss->wpa_ie, bss->wpa_ie_len);
                iwe.cmd = IWEVGENIE;
                iwe.u.data.length = bss->wpa_ie_len;
 -              start = iwe_stream_add_point(start, stop, &iwe, buf);
 +              start = iwe_stream_add_point(info, start, stop, &iwe, buf);
        }
  
        memset(&iwe, 0, sizeof(iwe));
                memcpy(buf, bss->rsn_ie, bss->rsn_ie_len);
                iwe.cmd = IWEVGENIE;
                iwe.u.data.length = bss->rsn_ie_len;
 -              start = iwe_stream_add_point(start, stop, &iwe, buf);
 +              start = iwe_stream_add_point(info, start, stop, &iwe, buf);
        }
  
        if (bss->mesh) {
                p += snprintf(p, MAX_CUSTOM_LEN, "mesh-type: olpc");
                iwe.u.data.length = p - custom;
                if (iwe.u.data.length)
 -                      start = iwe_stream_add_point(start, stop, &iwe, custom);
 +                      start = iwe_stream_add_point(info, start, stop,
 +                                                   &iwe, custom);
        }
  
  out:
@@@ -1038,7 -1036,7 +1038,7 @@@ int lbs_get_scan(struct net_device *dev
                }
  
                /* Translate to WE format this entry */
 -              next_ev = lbs_translate_scan(priv, ev, stop, iter_bss);
 +              next_ev = lbs_translate_scan(priv, info, ev, stop, iter_bss);
                if (next_ev == NULL)
                        continue;
                ev = next_ev;
index ee953ca0c6a3fb7752f66b021fe7f8553fd57c19,b36ed1c6c746a037d943e174f7cba49bb06bc4fc..91cbd9e560bd93ff28983156b90c992f07f6d0aa
@@@ -277,17 -277,6 +277,17 @@@ static int rt2400pci_blink_set(struct l
  
        return 0;
  }
 +
 +static void rt2400pci_init_led(struct rt2x00_dev *rt2x00dev,
 +                             struct rt2x00_led *led,
 +                             enum led_type type)
 +{
 +      led->rt2x00dev = rt2x00dev;
 +      led->type = type;
 +      led->led_dev.brightness_set = rt2400pci_brightness_set;
 +      led->led_dev.blink_set = rt2400pci_blink_set;
 +      led->flags = LED_INITIALIZED;
 +}
  #endif /* CONFIG_RT2400PCI_LEDS */
  
  /*
@@@ -631,38 -620,48 +631,38 @@@ static void rt2400pci_link_tuner(struc
  static void rt2400pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
                                   struct queue_entry *entry)
  {
 -      struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
 +      struct queue_entry_priv_pci *entry_priv = entry->priv_data;
 +      struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
        u32 word;
  
 -      rt2x00_desc_read(priv_rx->desc, 2, &word);
 -      rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH,
 -                         entry->queue->data_size);
 -      rt2x00_desc_write(priv_rx->desc, 2, word);
 +      rt2x00_desc_read(entry_priv->desc, 2, &word);
 +      rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->skb->len);
 +      rt2x00_desc_write(entry_priv->desc, 2, word);
  
 -      rt2x00_desc_read(priv_rx->desc, 1, &word);
 -      rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, priv_rx->data_dma);
 -      rt2x00_desc_write(priv_rx->desc, 1, word);
 +      rt2x00_desc_read(entry_priv->desc, 1, &word);
 +      rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
 +      rt2x00_desc_write(entry_priv->desc, 1, word);
  
 -      rt2x00_desc_read(priv_rx->desc, 0, &word);
 +      rt2x00_desc_read(entry_priv->desc, 0, &word);
        rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
 -      rt2x00_desc_write(priv_rx->desc, 0, word);
 +      rt2x00_desc_write(entry_priv->desc, 0, word);
  }
  
  static void rt2400pci_init_txentry(struct rt2x00_dev *rt2x00dev,
                                   struct queue_entry *entry)
  {
 -      struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
 +      struct queue_entry_priv_pci *entry_priv = entry->priv_data;
        u32 word;
  
 -      rt2x00_desc_read(priv_tx->desc, 1, &word);
 -      rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, priv_tx->data_dma);
 -      rt2x00_desc_write(priv_tx->desc, 1, word);
 -
 -      rt2x00_desc_read(priv_tx->desc, 2, &word);
 -      rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH,
 -                         entry->queue->data_size);
 -      rt2x00_desc_write(priv_tx->desc, 2, word);
 -
 -      rt2x00_desc_read(priv_tx->desc, 0, &word);
 +      rt2x00_desc_read(entry_priv->desc, 0, &word);
        rt2x00_set_field32(&word, TXD_W0_VALID, 0);
        rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
 -      rt2x00_desc_write(priv_tx->desc, 0, word);
 +      rt2x00_desc_write(entry_priv->desc, 0, word);
  }
  
  static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev)
  {
 -      struct queue_entry_priv_pci_rx *priv_rx;
 -      struct queue_entry_priv_pci_tx *priv_tx;
 +      struct queue_entry_priv_pci *entry_priv;
        u32 reg;
  
        /*
        rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
        rt2x00pci_register_write(rt2x00dev, TXCSR2, reg);
  
 -      priv_tx = rt2x00dev->tx[1].entries[0].priv_data;
 +      entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, TXCSR3, &reg);
        rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
 -                         priv_tx->desc_dma);
 +                         entry_priv->desc_dma);
        rt2x00pci_register_write(rt2x00dev, TXCSR3, reg);
  
 -      priv_tx = rt2x00dev->tx[0].entries[0].priv_data;
 +      entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, TXCSR5, &reg);
        rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
 -                         priv_tx->desc_dma);
 +                         entry_priv->desc_dma);
        rt2x00pci_register_write(rt2x00dev, TXCSR5, reg);
  
 -      priv_tx = rt2x00dev->bcn[1].entries[0].priv_data;
 +      entry_priv = rt2x00dev->bcn[1].entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, TXCSR4, &reg);
        rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
 -                         priv_tx->desc_dma);
 +                         entry_priv->desc_dma);
        rt2x00pci_register_write(rt2x00dev, TXCSR4, reg);
  
 -      priv_tx = rt2x00dev->bcn[0].entries[0].priv_data;
 +      entry_priv = rt2x00dev->bcn[0].entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, TXCSR6, &reg);
        rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
 -                         priv_tx->desc_dma);
 +                         entry_priv->desc_dma);
        rt2x00pci_register_write(rt2x00dev, TXCSR6, reg);
  
        rt2x00pci_register_read(rt2x00dev, RXCSR1, &reg);
        rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
        rt2x00pci_register_write(rt2x00dev, RXCSR1, reg);
  
 -      priv_rx = rt2x00dev->rx->entries[0].priv_data;
 +      entry_priv = rt2x00dev->rx->entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, RXCSR2, &reg);
 -      rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER, priv_rx->desc_dma);
 +      rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER,
 +                         entry_priv->desc_dma);
        rt2x00pci_register_write(rt2x00dev, RXCSR2, reg);
  
        return 0;
@@@ -733,6 -731,17 +733,17 @@@ static int rt2400pci_init_registers(str
                           (rt2x00dev->rx->data_size / 128));
        rt2x00pci_register_write(rt2x00dev, CSR9, reg);
  
+       rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+       rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
+       rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 0);
+       rt2x00_set_field32(&reg, CSR14_TBCN, 0);
+       rt2x00_set_field32(&reg, CSR14_TCFP, 0);
+       rt2x00_set_field32(&reg, CSR14_TATIMW, 0);
+       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
+       rt2x00_set_field32(&reg, CSR14_CFP_COUNT_PRELOAD, 0);
+       rt2x00_set_field32(&reg, CSR14_TBCM_PRELOAD, 0);
+       rt2x00pci_register_write(rt2x00dev, CSR14, reg);
        rt2x00pci_register_write(rt2x00dev, CNT3, 0x3f080000);
  
        rt2x00pci_register_read(rt2x00dev, ARCSR0, &reg);
        return 0;
  }
  
 -static int rt2400pci_init_bbp(struct rt2x00_dev *rt2x00dev)
 +static int rt2400pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
  {
        unsigned int i;
 -      u16 eeprom;
 -      u8 reg_id;
        u8 value;
  
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
                rt2400pci_bbp_read(rt2x00dev, 0, &value);
                if ((value != 0xff) && (value != 0x00))
 -                      goto continue_csr_init;
 -              NOTICE(rt2x00dev, "Waiting for BBP register.\n");
 +                      return 0;
                udelay(REGISTER_BUSY_DELAY);
        }
  
        ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
        return -EACCES;
 +}
 +
 +static int rt2400pci_init_bbp(struct rt2x00_dev *rt2x00dev)
 +{
 +      unsigned int i;
 +      u16 eeprom;
 +      u8 reg_id;
 +      u8 value;
 +
 +      if (unlikely(rt2400pci_wait_bbp_ready(rt2x00dev)))
 +              return -EACCES;
  
 -continue_csr_init:
        rt2400pci_bbp_write(rt2x00dev, 1, 0x00);
        rt2400pci_bbp_write(rt2x00dev, 3, 0x27);
        rt2400pci_bbp_write(rt2x00dev, 4, 0x08);
@@@ -856,8 -858,7 +867,8 @@@ static void rt2400pci_toggle_rx(struct 
  
        rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
        rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX,
 -                         state == STATE_RADIO_RX_OFF);
 +                         (state == STATE_RADIO_RX_OFF) ||
 +                         (state == STATE_RADIO_RX_OFF_LINK));
        rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
  }
  
@@@ -894,10 -895,17 +905,10 @@@ static int rt2400pci_enable_radio(struc
        /*
         * Initialize all registers.
         */
 -      if (rt2400pci_init_queues(rt2x00dev) ||
 -          rt2400pci_init_registers(rt2x00dev) ||
 -          rt2400pci_init_bbp(rt2x00dev)) {
 -              ERROR(rt2x00dev, "Register initialization failed.\n");
 +      if (unlikely(rt2400pci_init_queues(rt2x00dev) ||
 +                   rt2400pci_init_registers(rt2x00dev) ||
 +                   rt2400pci_init_bbp(rt2x00dev)))
                return -EIO;
 -      }
 -
 -      /*
 -       * Enable interrupts.
 -       */
 -      rt2400pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_ON);
  
        return 0;
  }
@@@ -919,6 -927,11 +930,6 @@@ static void rt2400pci_disable_radio(str
        rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
        rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
        rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
 -
 -      /*
 -       * Disable interrupts.
 -       */
 -      rt2400pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_OFF);
  }
  
  static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,
                msleep(10);
        }
  
 -      NOTICE(rt2x00dev, "Device failed to enter state %d, "
 -             "current device state: bbp %d and rf %d.\n",
 -             state, bbp_state, rf_state);
 -
        return -EBUSY;
  }
  
@@@ -970,13 -987,11 +981,13 @@@ static int rt2400pci_set_device_state(s
                break;
        case STATE_RADIO_RX_ON:
        case STATE_RADIO_RX_ON_LINK:
 -              rt2400pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
 -              break;
        case STATE_RADIO_RX_OFF:
        case STATE_RADIO_RX_OFF_LINK:
 -              rt2400pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
 +              rt2400pci_toggle_rx(rt2x00dev, state);
 +              break;
 +      case STATE_RADIO_IRQ_ON:
 +      case STATE_RADIO_IRQ_OFF:
 +              rt2400pci_toggle_irq(rt2x00dev, state);
                break;
        case STATE_DEEP_SLEEP:
        case STATE_SLEEP:
                break;
        }
  
 +      if (unlikely(retval))
 +              ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
 +                    state, retval);
 +
        return retval;
  }
  
   */
  static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
                                    struct sk_buff *skb,
 -                                  struct txentry_desc *txdesc,
 -                                  struct ieee80211_tx_control *control)
 +                                  struct txentry_desc *txdesc)
  {
        struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
 +      struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data;
        __le32 *txd = skbdesc->desc;
        u32 word;
  
        /*
         * Start writing the descriptor words.
         */
 +      rt2x00_desc_read(entry_priv->desc, 1, &word);
 +      rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
 +      rt2x00_desc_write(entry_priv->desc, 1, word);
 +
        rt2x00_desc_read(txd, 2, &word);
 -      rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, skbdesc->data_len);
 +      rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, skb->len);
 +      rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, skb->len);
        rt2x00_desc_write(txd, 2, word);
  
        rt2x00_desc_read(txd, 3, &word);
                           test_bit(ENTRY_TXD_RTS_FRAME, &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));
 +                         test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
        rt2x00_desc_write(txd, 0, word);
  }
  
   * TX data initialization
   */
  static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
 -                                  const unsigned int queue)
 +                                  const enum data_queue_qid queue)
  {
        u32 reg;
  
 -      if (queue == RT2X00_BCN_QUEUE_BEACON) {
 +      if (queue == QID_BEACON) {
                rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
                if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) {
                        rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
        }
  
        rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
 -      rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO,
 -                         (queue == IEEE80211_TX_QUEUE_DATA0));
 -      rt2x00_set_field32(&reg, TXCSR0_KICK_TX,
 -                         (queue == IEEE80211_TX_QUEUE_DATA1));
 -      rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM,
 -                         (queue == RT2X00_BCN_QUEUE_ATIM));
 +      rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, (queue == QID_AC_BE));
 +      rt2x00_set_field32(&reg, TXCSR0_KICK_TX, (queue == QID_AC_BK));
 +      rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, (queue == QID_ATIM));
        rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
  }
  
  static void rt2400pci_fill_rxdone(struct queue_entry *entry,
                                  struct rxdone_entry_desc *rxdesc)
  {
 -      struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
 +      struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 +      struct queue_entry_priv_pci *entry_priv = entry->priv_data;
        u32 word0;
        u32 word2;
        u32 word3;
 +      u32 word4;
 +      u64 tsf;
 +      u32 rx_low;
 +      u32 rx_high;
  
 -      rt2x00_desc_read(priv_rx->desc, 0, &word0);
 -      rt2x00_desc_read(priv_rx->desc, 2, &word2);
 -      rt2x00_desc_read(priv_rx->desc, 3, &word3);
 +      rt2x00_desc_read(entry_priv->desc, 0, &word0);
 +      rt2x00_desc_read(entry_priv->desc, 2, &word2);
 +      rt2x00_desc_read(entry_priv->desc, 3, &word3);
 +      rt2x00_desc_read(entry_priv->desc, 4, &word4);
  
 -      rxdesc->flags = 0;
        if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
                rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
        if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
                rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
  
 +      /*
 +       * We only get the lower 32bits from the timestamp,
 +       * to get the full 64bits we must complement it with
 +       * the timestamp from get_tsf().
 +       * Note that when a wraparound of the lower 32bits
 +       * has occurred between the frame arrival and the get_tsf()
 +       * call, we must decrease the higher 32bits with 1 to get
 +       * to correct value.
 +       */
 +      tsf = rt2x00dev->ops->hw->get_tsf(rt2x00dev->hw);
 +      rx_low = rt2x00_get_field32(word4, RXD_W4_RX_END_TIME);
 +      rx_high = upper_32_bits(tsf);
 +
 +      if ((u32)tsf <= rx_low)
 +              rx_high--;
 +
        /*
         * Obtain the status about this packet.
         * The signal is the PLCP value, and needs to be stripped
         * of the preamble bit (0x08).
         */
 +      rxdesc->timestamp = ((u64)rx_high << 32) | rx_low;
        rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL) & ~0x08;
        rxdesc->rssi = rt2x00_get_field32(word2, RXD_W3_RSSI) -
            entry->queue->rt2x00dev->rssi_offset;
        rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
  
 -      rxdesc->dev_flags = RXDONE_SIGNAL_PLCP;
 +      rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
        if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
                rxdesc->dev_flags |= RXDONE_MY_BSS;
  }
   * Interrupt functions.
   */
  static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
 -                           const enum ieee80211_tx_queue queue_idx)
 +                           const enum data_queue_qid queue_idx)
  {
        struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
 -      struct queue_entry_priv_pci_tx *priv_tx;
 +      struct queue_entry_priv_pci *entry_priv;
        struct queue_entry *entry;
        struct txdone_entry_desc txdesc;
        u32 word;
  
        while (!rt2x00queue_empty(queue)) {
                entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
 -              priv_tx = entry->priv_data;
 -              rt2x00_desc_read(priv_tx->desc, 0, &word);
 +              entry_priv = entry->priv_data;
 +              rt2x00_desc_read(entry_priv->desc, 0, &word);
  
                if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
                    !rt2x00_get_field32(word, TXD_W0_VALID))
                /*
                 * Obtain the status about this packet.
                 */
 -              txdesc.status = rt2x00_get_field32(word, TXD_W0_RESULT);
 +              txdesc.flags = 0;
 +              switch (rt2x00_get_field32(word, TXD_W0_RESULT)) {
 +              case 0: /* Success */
 +              case 1: /* Success with retry */
 +                      __set_bit(TXDONE_SUCCESS, &txdesc.flags);
 +                      break;
 +              case 2: /* Failure, excessive retries */
 +                      __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags);
 +                      /* Don't break, this is a failed frame! */
 +              default: /* Failure */
 +                      __set_bit(TXDONE_FAILURE, &txdesc.flags);
 +              }
                txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
  
 -              rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
 +              rt2x00lib_txdone(entry, &txdesc);
        }
  }
  
@@@ -1221,19 -1198,19 +1232,19 @@@ static irqreturn_t rt2400pci_interrupt(
         * 3 - Atim ring transmit done interrupt.
         */
        if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING))
 -              rt2400pci_txdone(rt2x00dev, RT2X00_BCN_QUEUE_ATIM);
 +              rt2400pci_txdone(rt2x00dev, QID_ATIM);
  
        /*
         * 4 - Priority ring transmit done interrupt.
         */
        if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING))
 -              rt2400pci_txdone(rt2x00dev, IEEE80211_TX_QUEUE_DATA0);
 +              rt2400pci_txdone(rt2x00dev, QID_AC_BE);
  
        /*
         * 5 - Tx ring transmit done interrupt.
         */
        if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING))
 -              rt2400pci_txdone(rt2x00dev, IEEE80211_TX_QUEUE_DATA1);
 +              rt2400pci_txdone(rt2x00dev, QID_AC_BK);
  
        return IRQ_HANDLED;
  }
@@@ -1332,10 -1309,23 +1343,10 @@@ static int rt2400pci_init_eeprom(struc
  #ifdef CONFIG_RT2400PCI_LEDS
        value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
  
 -      rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
 -      rt2x00dev->led_radio.type = LED_TYPE_RADIO;
 -      rt2x00dev->led_radio.led_dev.brightness_set =
 -          rt2400pci_brightness_set;
 -      rt2x00dev->led_radio.led_dev.blink_set =
 -          rt2400pci_blink_set;
 -      rt2x00dev->led_radio.flags = LED_INITIALIZED;
 -
 -      if (value == LED_MODE_TXRX_ACTIVITY) {
 -              rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
 -              rt2x00dev->led_qual.type = LED_TYPE_ACTIVITY;
 -              rt2x00dev->led_qual.led_dev.brightness_set =
 -                  rt2400pci_brightness_set;
 -              rt2x00dev->led_qual.led_dev.blink_set =
 -                  rt2400pci_blink_set;
 -              rt2x00dev->led_qual.flags = LED_INITIALIZED;
 -      }
 +      rt2400pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
 +      if (value == LED_MODE_TXRX_ACTIVITY)
 +              rt2400pci_init_led(rt2x00dev, &rt2x00dev->led_qual,
 +                                 LED_TYPE_ACTIVITY);
  #endif /* CONFIG_RT2400PCI_LEDS */
  
        /*
@@@ -1385,11 -1375,13 +1396,11 @@@ static void rt2400pci_probe_hw_mode(str
        /*
         * Initialize all hw fields.
         */
 -      rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
 +      rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
 +                             IEEE80211_HW_SIGNAL_DBM;
        rt2x00dev->hw->extra_tx_headroom = 0;
 -      rt2x00dev->hw->max_signal = MAX_SIGNAL;
 -      rt2x00dev->hw->max_rssi = MAX_RX_SSI;
 -      rt2x00dev->hw->queues = 2;
  
 -      SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
 +      SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
        SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
                                rt2x00_eeprom_addr(rt2x00dev,
                                                   EEPROM_MAC_ADDR_0));
@@@ -1435,10 -1427,9 +1446,10 @@@ static int rt2400pci_probe_hw(struct rt
        rt2400pci_probe_hw_mode(rt2x00dev);
  
        /*
 -       * This device requires the atim queue
 +       * This device requires the atim queue and DMA-mapped skbs.
         */
        __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
 +      __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
  
        /*
         * Set the rssi offset.
@@@ -1465,7 -1456,8 +1476,7 @@@ static int rt2400pci_set_retry_limit(st
        return 0;
  }
  
 -static int rt2400pci_conf_tx(struct ieee80211_hw *hw,
 -                           int queue,
 +static int rt2400pci_conf_tx(struct ieee80211_hw *hw, u16 queue,
                             const struct ieee80211_tx_queue_params *params)
  {
        struct rt2x00_dev *rt2x00dev = hw->priv;
         * per queue. So by default we only configure the TX queue,
         * and ignore all other configurations.
         */
 -      if (queue != IEEE80211_TX_QUEUE_DATA0)
 +      if (queue != 0)
                return -EINVAL;
  
        if (rt2x00mac_conf_tx(hw, queue, params))
@@@ -1504,34 -1496,28 +1515,34 @@@ static u64 rt2400pci_get_tsf(struct iee
        return tsf;
  }
  
 -static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
 -                                 struct ieee80211_tx_control *control)
 +static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
  {
        struct rt2x00_dev *rt2x00dev = hw->priv;
 -      struct rt2x00_intf *intf = vif_to_intf(control->vif);
 -      struct queue_entry_priv_pci_tx *priv_tx;
 +      struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 +      struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
 +      struct queue_entry_priv_pci *entry_priv;
        struct skb_frame_desc *skbdesc;
 +      struct txentry_desc txdesc;
        u32 reg;
  
        if (unlikely(!intf->beacon))
                return -ENOBUFS;
 -      priv_tx = intf->beacon->priv_data;
 +      entry_priv = intf->beacon->priv_data;
 +
 +      /*
 +       * Copy all TX descriptor information into txdesc,
 +       * after that we are free to use the skb->cb array
 +       * for our information.
 +       */
 +      intf->beacon->skb = skb;
 +      rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);
  
        /*
         * Fill in skb descriptor
         */
        skbdesc = get_skb_frame_desc(skb);
        memset(skbdesc, 0, sizeof(*skbdesc));
 -      skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
 -      skbdesc->data = skb->data;
 -      skbdesc->data_len = skb->len;
 -      skbdesc->desc = priv_tx->desc;
 +      skbdesc->desc = entry_priv->desc;
        skbdesc->desc_len = intf->beacon->queue->desc_size;
        skbdesc->entry = intf->beacon;
  
        rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
        rt2x00pci_register_write(rt2x00dev, CSR14, 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);
 -
        /*
         * Enable beacon generation.
         * Write entire beacon with descriptor to register,
         * and kick the beacon generator.
         */
 -      memcpy(priv_tx->data, skb->data, skb->len);
 -      rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue);
 +      rt2x00queue_map_txskb(rt2x00dev, intf->beacon->skb);
 +      rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc);
 +      rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON);
  
        return 0;
  }
@@@ -1611,28 -1604,28 +1622,28 @@@ static const struct data_queue_desc rt2
        .entry_num              = RX_ENTRIES,
        .data_size              = DATA_FRAME_SIZE,
        .desc_size              = RXD_DESC_SIZE,
 -      .priv_size              = sizeof(struct queue_entry_priv_pci_rx),
 +      .priv_size              = sizeof(struct queue_entry_priv_pci),
  };
  
  static const struct data_queue_desc rt2400pci_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),
 +      .priv_size              = sizeof(struct queue_entry_priv_pci),
  };
  
  static const struct data_queue_desc rt2400pci_queue_bcn = {
        .entry_num              = BEACON_ENTRIES,
        .data_size              = MGMT_FRAME_SIZE,
        .desc_size              = TXD_DESC_SIZE,
 -      .priv_size              = sizeof(struct queue_entry_priv_pci_tx),
 +      .priv_size              = sizeof(struct queue_entry_priv_pci),
  };
  
  static const struct data_queue_desc rt2400pci_queue_atim = {
        .entry_num              = ATIM_ENTRIES,
        .data_size              = DATA_FRAME_SIZE,
        .desc_size              = TXD_DESC_SIZE,
 -      .priv_size              = sizeof(struct queue_entry_priv_pci_tx),
 +      .priv_size              = sizeof(struct queue_entry_priv_pci),
  };
  
  static const struct rt2x00_ops rt2400pci_ops = {
        .max_ap_intf    = 1,
        .eeprom_size    = EEPROM_SIZE,
        .rf_size        = RF_SIZE,
 +      .tx_queues      = NUM_TX_QUEUES,
        .rx             = &rt2400pci_queue_rx,
        .tx             = &rt2400pci_queue_tx,
        .bcn            = &rt2400pci_queue_bcn,
index 0423c251c78e5c0b069bc247d14b310b03d8c951,f7731fb82555745488391a0f4e3f9f72a81c3119..0f2a0e22fd713c2227f92f8cba87527658934ff6
@@@ -277,17 -277,6 +277,17 @@@ static int rt2500pci_blink_set(struct l
  
        return 0;
  }
 +
 +static void rt2500pci_init_led(struct rt2x00_dev *rt2x00dev,
 +                             struct rt2x00_led *led,
 +                             enum led_type type)
 +{
 +      led->rt2x00dev = rt2x00dev;
 +      led->type = type;
 +      led->led_dev.brightness_set = rt2500pci_brightness_set;
 +      led->led_dev.blink_set = rt2500pci_blink_set;
 +      led->flags = LED_INITIALIZED;
 +}
  #endif /* CONFIG_RT2500PCI_LEDS */
  
  /*
@@@ -328,7 -317,8 +328,7 @@@ static void rt2500pci_config_intf(struc
                                  struct rt2x00intf_conf *conf,
                                  const unsigned int flags)
  {
 -      struct data_queue *queue =
 -          rt2x00queue_get_queue(rt2x00dev, RT2X00_BCN_QUEUE_BEACON);
 +      struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON);
        unsigned int bcn_preload;
        u32 reg;
  
@@@ -726,34 -716,38 +726,34 @@@ dynamic_cca_tune
  static void rt2500pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
                                   struct queue_entry *entry)
  {
 -      struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
 +      struct queue_entry_priv_pci *entry_priv = entry->priv_data;
 +      struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
        u32 word;
  
 -      rt2x00_desc_read(priv_rx->desc, 1, &word);
 -      rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, priv_rx->data_dma);
 -      rt2x00_desc_write(priv_rx->desc, 1, word);
 +      rt2x00_desc_read(entry_priv->desc, 1, &word);
 +      rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
 +      rt2x00_desc_write(entry_priv->desc, 1, word);
  
 -      rt2x00_desc_read(priv_rx->desc, 0, &word);
 +      rt2x00_desc_read(entry_priv->desc, 0, &word);
        rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
 -      rt2x00_desc_write(priv_rx->desc, 0, word);
 +      rt2x00_desc_write(entry_priv->desc, 0, word);
  }
  
  static void rt2500pci_init_txentry(struct rt2x00_dev *rt2x00dev,
                                   struct queue_entry *entry)
  {
 -      struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
 +      struct queue_entry_priv_pci *entry_priv = entry->priv_data;
        u32 word;
  
 -      rt2x00_desc_read(priv_tx->desc, 1, &word);
 -      rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, priv_tx->data_dma);
 -      rt2x00_desc_write(priv_tx->desc, 1, word);
 -
 -      rt2x00_desc_read(priv_tx->desc, 0, &word);
 +      rt2x00_desc_read(entry_priv->desc, 0, &word);
        rt2x00_set_field32(&word, TXD_W0_VALID, 0);
        rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
 -      rt2x00_desc_write(priv_tx->desc, 0, word);
 +      rt2x00_desc_write(entry_priv->desc, 0, word);
  }
  
  static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev)
  {
 -      struct queue_entry_priv_pci_rx *priv_rx;
 -      struct queue_entry_priv_pci_tx *priv_tx;
 +      struct queue_entry_priv_pci *entry_priv;
        u32 reg;
  
        /*
        rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
        rt2x00pci_register_write(rt2x00dev, TXCSR2, reg);
  
 -      priv_tx = rt2x00dev->tx[1].entries[0].priv_data;
 +      entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, TXCSR3, &reg);
        rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
 -                         priv_tx->desc_dma);
 +                         entry_priv->desc_dma);
        rt2x00pci_register_write(rt2x00dev, TXCSR3, reg);
  
 -      priv_tx = rt2x00dev->tx[0].entries[0].priv_data;
 +      entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, TXCSR5, &reg);
        rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
 -                         priv_tx->desc_dma);
 +                         entry_priv->desc_dma);
        rt2x00pci_register_write(rt2x00dev, TXCSR5, reg);
  
 -      priv_tx = rt2x00dev->bcn[1].entries[0].priv_data;
 +      entry_priv = rt2x00dev->bcn[1].entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, TXCSR4, &reg);
        rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
 -                         priv_tx->desc_dma);
 +                         entry_priv->desc_dma);
        rt2x00pci_register_write(rt2x00dev, TXCSR4, reg);
  
 -      priv_tx = rt2x00dev->bcn[0].entries[0].priv_data;
 +      entry_priv = rt2x00dev->bcn[0].entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, TXCSR6, &reg);
        rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
 -                         priv_tx->desc_dma);
 +                         entry_priv->desc_dma);
        rt2x00pci_register_write(rt2x00dev, TXCSR6, reg);
  
        rt2x00pci_register_read(rt2x00dev, RXCSR1, &reg);
        rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
        rt2x00pci_register_write(rt2x00dev, RXCSR1, reg);
  
 -      priv_rx = rt2x00dev->rx->entries[0].priv_data;
 +      entry_priv = rt2x00dev->rx->entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, RXCSR2, &reg);
 -      rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER, priv_rx->desc_dma);
 +      rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER,
 +                         entry_priv->desc_dma);
        rt2x00pci_register_write(rt2x00dev, RXCSR2, reg);
  
        return 0;
@@@ -831,6 -824,17 +831,17 @@@ static int rt2500pci_init_registers(str
        rt2x00_set_field32(&reg, CSR11_CW_SELECT, 0);
        rt2x00pci_register_write(rt2x00dev, CSR11, reg);
  
+       rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+       rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
+       rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 0);
+       rt2x00_set_field32(&reg, CSR14_TBCN, 0);
+       rt2x00_set_field32(&reg, CSR14_TCFP, 0);
+       rt2x00_set_field32(&reg, CSR14_TATIMW, 0);
+       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
+       rt2x00_set_field32(&reg, CSR14_CFP_COUNT_PRELOAD, 0);
+       rt2x00_set_field32(&reg, CSR14_TBCM_PRELOAD, 0);
+       rt2x00pci_register_write(rt2x00dev, CSR14, reg);
        rt2x00pci_register_write(rt2x00dev, CNT3, 0);
  
        rt2x00pci_register_read(rt2x00dev, TXCSR8, &reg);
        return 0;
  }
  
 -static int rt2500pci_init_bbp(struct rt2x00_dev *rt2x00dev)
 +static int rt2500pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
  {
        unsigned int i;
 -      u16 eeprom;
 -      u8 reg_id;
        u8 value;
  
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
                rt2500pci_bbp_read(rt2x00dev, 0, &value);
                if ((value != 0xff) && (value != 0x00))
 -                      goto continue_csr_init;
 -              NOTICE(rt2x00dev, "Waiting for BBP register.\n");
 +                      return 0;
                udelay(REGISTER_BUSY_DELAY);
        }
  
        ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
        return -EACCES;
 +}
 +
 +static int rt2500pci_init_bbp(struct rt2x00_dev *rt2x00dev)
 +{
 +      unsigned int i;
 +      u16 eeprom;
 +      u8 reg_id;
 +      u8 value;
 +
 +      if (unlikely(rt2500pci_wait_bbp_ready(rt2x00dev)))
 +              return -EACCES;
  
 -continue_csr_init:
        rt2500pci_bbp_write(rt2x00dev, 3, 0x02);
        rt2500pci_bbp_write(rt2x00dev, 4, 0x19);
        rt2500pci_bbp_write(rt2x00dev, 14, 0x1c);
@@@ -1016,8 -1013,7 +1027,8 @@@ static void rt2500pci_toggle_rx(struct 
  
        rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
        rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX,
 -                         state == STATE_RADIO_RX_OFF);
 +                         (state == STATE_RADIO_RX_OFF) ||
 +                         (state == STATE_RADIO_RX_OFF_LINK));
        rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
  }
  
@@@ -1054,10 -1050,17 +1065,10 @@@ static int rt2500pci_enable_radio(struc
        /*
         * Initialize all registers.
         */
 -      if (rt2500pci_init_queues(rt2x00dev) ||
 -          rt2500pci_init_registers(rt2x00dev) ||
 -          rt2500pci_init_bbp(rt2x00dev)) {
 -              ERROR(rt2x00dev, "Register initialization failed.\n");
 +      if (unlikely(rt2500pci_init_queues(rt2x00dev) ||
 +                   rt2500pci_init_registers(rt2x00dev) ||
 +                   rt2500pci_init_bbp(rt2x00dev)))
                return -EIO;
 -      }
 -
 -      /*
 -       * Enable interrupts.
 -       */
 -      rt2500pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_ON);
  
        return 0;
  }
@@@ -1079,6 -1082,11 +1090,6 @@@ static void rt2500pci_disable_radio(str
        rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
        rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
        rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
 -
 -      /*
 -       * Disable interrupts.
 -       */
 -      rt2500pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_OFF);
  }
  
  static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev,
                msleep(10);
        }
  
 -      NOTICE(rt2x00dev, "Device failed to enter state %d, "
 -             "current device state: bbp %d and rf %d.\n",
 -             state, bbp_state, rf_state);
 -
        return -EBUSY;
  }
  
@@@ -1130,13 -1142,11 +1141,13 @@@ static int rt2500pci_set_device_state(s
                break;
        case STATE_RADIO_RX_ON:
        case STATE_RADIO_RX_ON_LINK:
 -              rt2500pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
 -              break;
        case STATE_RADIO_RX_OFF:
        case STATE_RADIO_RX_OFF_LINK:
 -              rt2500pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
 +              rt2500pci_toggle_rx(rt2x00dev, state);
 +              break;
 +      case STATE_RADIO_IRQ_ON:
 +      case STATE_RADIO_IRQ_OFF:
 +              rt2500pci_toggle_irq(rt2x00dev, state);
                break;
        case STATE_DEEP_SLEEP:
        case STATE_SLEEP:
                break;
        }
  
 +      if (unlikely(retval))
 +              ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
 +                    state, retval);
 +
        return retval;
  }
  
   */
  static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
                                    struct sk_buff *skb,
 -                                  struct txentry_desc *txdesc,
 -                                  struct ieee80211_tx_control *control)
 +                                  struct txentry_desc *txdesc)
  {
        struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
 +      struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data;
        __le32 *txd = skbdesc->desc;
        u32 word;
  
        /*
         * Start writing the descriptor words.
         */
 +      rt2x00_desc_read(entry_priv->desc, 1, &word);
 +      rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
 +      rt2x00_desc_write(entry_priv->desc, 1, word);
 +
        rt2x00_desc_read(txd, 2, &word);
        rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER);
        rt2x00_set_field32(&word, TXD_W2_AIFS, txdesc->aifs);
        rt2x00_set_field32(&word, TXD_W0_CIPHER_OWNER, 1);
        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_DATABYTE_COUNT, skbdesc->data_len);
 +                         test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
        rt2x00_desc_write(txd, 0, word);
  }
   * TX data initialization
   */
  static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
 -                                  const unsigned int queue)
 +                                  const enum data_queue_qid queue)
  {
        u32 reg;
  
 -      if (queue == RT2X00_BCN_QUEUE_BEACON) {
 +      if (queue == QID_BEACON) {
                rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
                if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) {
                        rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
        }
  
        rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
 -      rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO,
 -                         (queue == IEEE80211_TX_QUEUE_DATA0));
 -      rt2x00_set_field32(&reg, TXCSR0_KICK_TX,
 -                         (queue == IEEE80211_TX_QUEUE_DATA1));
 -      rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM,
 -                         (queue == RT2X00_BCN_QUEUE_ATIM));
 +      rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, (queue == QID_AC_BE));
 +      rt2x00_set_field32(&reg, TXCSR0_KICK_TX, (queue == QID_AC_BK));
 +      rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, (queue == QID_ATIM));
        rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
  }
  
  static void rt2500pci_fill_rxdone(struct queue_entry *entry,
                                  struct rxdone_entry_desc *rxdesc)
  {
 -      struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
 +      struct queue_entry_priv_pci *entry_priv = entry->priv_data;
        u32 word0;
        u32 word2;
  
 -      rt2x00_desc_read(priv_rx->desc, 0, &word0);
 -      rt2x00_desc_read(priv_rx->desc, 2, &word2);
 +      rt2x00_desc_read(entry_priv->desc, 0, &word0);
 +      rt2x00_desc_read(entry_priv->desc, 2, &word2);
  
 -      rxdesc->flags = 0;
        if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
                rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
        if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
            entry->queue->rt2x00dev->rssi_offset;
        rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
  
 -      rxdesc->dev_flags = 0;
        if (rt2x00_get_field32(word0, RXD_W0_OFDM))
                rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
        if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
   * Interrupt functions.
   */
  static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
 -                           const enum ieee80211_tx_queue queue_idx)
 +                           const enum data_queue_qid queue_idx)
  {
        struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
 -      struct queue_entry_priv_pci_tx *priv_tx;
 +      struct queue_entry_priv_pci *entry_priv;
        struct queue_entry *entry;
        struct txdone_entry_desc txdesc;
        u32 word;
  
        while (!rt2x00queue_empty(queue)) {
                entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
 -              priv_tx = entry->priv_data;
 -              rt2x00_desc_read(priv_tx->desc, 0, &word);
 +              entry_priv = entry->priv_data;
 +              rt2x00_desc_read(entry_priv->desc, 0, &word);
  
                if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
                    !rt2x00_get_field32(word, TXD_W0_VALID))
                /*
                 * Obtain the status about this packet.
                 */
 -              txdesc.status = rt2x00_get_field32(word, TXD_W0_RESULT);
 +              txdesc.flags = 0;
 +              switch (rt2x00_get_field32(word, TXD_W0_RESULT)) {
 +              case 0: /* Success */
 +              case 1: /* Success with retry */
 +                      __set_bit(TXDONE_SUCCESS, &txdesc.flags);
 +                      break;
 +              case 2: /* Failure, excessive retries */
 +                      __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags);
 +                      /* Don't break, this is a failed frame! */
 +              default: /* Failure */
 +                      __set_bit(TXDONE_FAILURE, &txdesc.flags);
 +              }
                txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
  
 -              rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
 +              rt2x00lib_txdone(entry, &txdesc);
        }
  }
  
@@@ -1356,19 -1354,19 +1367,19 @@@ static irqreturn_t rt2500pci_interrupt(
         * 3 - Atim ring transmit done interrupt.
         */
        if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING))
 -              rt2500pci_txdone(rt2x00dev, RT2X00_BCN_QUEUE_ATIM);
 +              rt2500pci_txdone(rt2x00dev, QID_ATIM);
  
        /*
         * 4 - Priority ring transmit done interrupt.
         */
        if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING))
 -              rt2500pci_txdone(rt2x00dev, IEEE80211_TX_QUEUE_DATA0);
 +              rt2500pci_txdone(rt2x00dev, QID_AC_BE);
  
        /*
         * 5 - Tx ring transmit done interrupt.
         */
        if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING))
 -              rt2500pci_txdone(rt2x00dev, IEEE80211_TX_QUEUE_DATA1);
 +              rt2500pci_txdone(rt2x00dev, QID_AC_BK);
  
        return IRQ_HANDLED;
  }
@@@ -1488,10 -1486,23 +1499,10 @@@ static int rt2500pci_init_eeprom(struc
  #ifdef CONFIG_RT2500PCI_LEDS
        value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
  
 -      rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
 -      rt2x00dev->led_radio.type = LED_TYPE_RADIO;
 -      rt2x00dev->led_radio.led_dev.brightness_set =
 -          rt2500pci_brightness_set;
 -      rt2x00dev->led_radio.led_dev.blink_set =
 -          rt2500pci_blink_set;
 -      rt2x00dev->led_radio.flags = LED_INITIALIZED;
 -
 -      if (value == LED_MODE_TXRX_ACTIVITY) {
 -              rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
 -              rt2x00dev->led_qual.type = LED_TYPE_ACTIVITY;
 -              rt2x00dev->led_qual.led_dev.brightness_set =
 -                  rt2500pci_brightness_set;
 -              rt2x00dev->led_qual.led_dev.blink_set =
 -                  rt2500pci_blink_set;
 -              rt2x00dev->led_qual.flags = LED_INITIALIZED;
 -      }
 +      rt2500pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
 +      if (value == LED_MODE_TXRX_ACTIVITY)
 +              rt2500pci_init_led(rt2x00dev, &rt2x00dev->led_qual,
 +                                 LED_TYPE_ACTIVITY);
  #endif /* CONFIG_RT2500PCI_LEDS */
  
        /*
@@@ -1684,12 -1695,13 +1695,12 @@@ static void rt2500pci_probe_hw_mode(str
        /*
         * Initialize all hw fields.
         */
 -      rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
 +      rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
 +                             IEEE80211_HW_SIGNAL_DBM;
 +
        rt2x00dev->hw->extra_tx_headroom = 0;
 -      rt2x00dev->hw->max_signal = MAX_SIGNAL;
 -      rt2x00dev->hw->max_rssi = MAX_RX_SSI;
 -      rt2x00dev->hw->queues = 2;
  
 -      SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
 +      SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
        SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
                                rt2x00_eeprom_addr(rt2x00dev,
                                                   EEPROM_MAC_ADDR_0));
@@@ -1753,10 -1765,9 +1764,10 @@@ static int rt2500pci_probe_hw(struct rt
        rt2500pci_probe_hw_mode(rt2x00dev);
  
        /*
 -       * This device requires the atim queue
 +       * This device requires the atim queue and DMA-mapped skbs.
         */
        __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
 +      __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
  
        /*
         * Set the rssi offset.
@@@ -1797,35 -1808,29 +1808,35 @@@ static u64 rt2500pci_get_tsf(struct iee
        return tsf;
  }
  
 -static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
 -                                 struct ieee80211_tx_control *control)
 +static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
  {
        struct rt2x00_dev *rt2x00dev = hw->priv;
 -      struct rt2x00_intf *intf = vif_to_intf(control->vif);
 -      struct queue_entry_priv_pci_tx *priv_tx;
 +      struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 +      struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
 +      struct queue_entry_priv_pci *entry_priv;
        struct skb_frame_desc *skbdesc;
 +      struct txentry_desc txdesc;
        u32 reg;
  
        if (unlikely(!intf->beacon))
                return -ENOBUFS;
  
 -      priv_tx = intf->beacon->priv_data;
 +      entry_priv = intf->beacon->priv_data;
 +
 +      /*
 +       * Copy all TX descriptor information into txdesc,
 +       * after that we are free to use the skb->cb array
 +       * for our information.
 +       */
 +      intf->beacon->skb = skb;
 +      rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);
  
        /*
         * Fill in skb descriptor
         */
        skbdesc = get_skb_frame_desc(skb);
        memset(skbdesc, 0, sizeof(*skbdesc));
 -      skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
 -      skbdesc->data = skb->data;
 -      skbdesc->data_len = skb->len;
 -      skbdesc->desc = priv_tx->desc;
 +      skbdesc->desc = entry_priv->desc;
        skbdesc->desc_len = intf->beacon->queue->desc_size;
        skbdesc->entry = intf->beacon;
  
        rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
        rt2x00pci_register_write(rt2x00dev, CSR14, 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);
 -
        /*
         * Enable beacon generation.
         * Write entire beacon with descriptor to register,
         * and kick the beacon generator.
         */
 -      memcpy(priv_tx->data, skb->data, skb->len);
 -      rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue);
 +      rt2x00queue_map_txskb(rt2x00dev, intf->beacon->skb);
 +      rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc);
 +      rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON);
  
        return 0;
  }
@@@ -1905,28 -1917,28 +1916,28 @@@ static const struct data_queue_desc rt2
        .entry_num              = RX_ENTRIES,
        .data_size              = DATA_FRAME_SIZE,
        .desc_size              = RXD_DESC_SIZE,
 -      .priv_size              = sizeof(struct queue_entry_priv_pci_rx),
 +      .priv_size              = sizeof(struct queue_entry_priv_pci),
  };
  
  static const struct data_queue_desc rt2500pci_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),
 +      .priv_size              = sizeof(struct queue_entry_priv_pci),
  };
  
  static const struct data_queue_desc rt2500pci_queue_bcn = {
        .entry_num              = BEACON_ENTRIES,
        .data_size              = MGMT_FRAME_SIZE,
        .desc_size              = TXD_DESC_SIZE,
 -      .priv_size              = sizeof(struct queue_entry_priv_pci_tx),
 +      .priv_size              = sizeof(struct queue_entry_priv_pci),
  };
  
  static const struct data_queue_desc rt2500pci_queue_atim = {
        .entry_num              = ATIM_ENTRIES,
        .data_size              = DATA_FRAME_SIZE,
        .desc_size              = TXD_DESC_SIZE,
 -      .priv_size              = sizeof(struct queue_entry_priv_pci_tx),
 +      .priv_size              = sizeof(struct queue_entry_priv_pci),
  };
  
  static const struct rt2x00_ops rt2500pci_ops = {
        .max_ap_intf    = 1,
        .eeprom_size    = EEPROM_SIZE,
        .rf_size        = RF_SIZE,
 +      .tx_queues      = NUM_TX_QUEUES,
        .rx             = &rt2500pci_queue_rx,
        .tx             = &rt2500pci_queue_tx,
        .bcn            = &rt2500pci_queue_bcn,
index 0dd1cb537b92999d71ffb038b19bbe38902f66e4,d90512f97b394f1049edf2981d3fe423ac6e7ed2..367db10b96d923046807b91232251976589620d8
@@@ -76,10 -76,10 +76,10 @@@ static inline void rt2500usb_register_m
                                                const unsigned int offset,
                                                void *value, const u16 length)
  {
 -      int timeout = REGISTER_TIMEOUT * (length / sizeof(u16));
        rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
                                      USB_VENDOR_REQUEST_IN, offset,
 -                                    value, length, timeout);
 +                                    value, length,
 +                                    REGISTER_TIMEOUT16(length));
  }
  
  static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
@@@ -106,10 -106,10 +106,10 @@@ static inline void rt2500usb_register_m
                                                 const unsigned int offset,
                                                 void *value, const u16 length)
  {
 -      int timeout = REGISTER_TIMEOUT * (length / sizeof(u16));
        rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
                                      USB_VENDOR_REQUEST_OUT, offset,
 -                                    value, length, timeout);
 +                                    value, length,
 +                                    REGISTER_TIMEOUT16(length));
  }
  
  static u16 rt2500usb_bbp_check(struct rt2x00_dev *rt2x00dev)
@@@ -322,17 -322,6 +322,17 @@@ static int rt2500usb_blink_set(struct l
  
        return 0;
  }
 +
 +static void rt2500usb_init_led(struct rt2x00_dev *rt2x00dev,
 +                             struct rt2x00_led *led,
 +                             enum led_type type)
 +{
 +      led->rt2x00dev = rt2x00dev;
 +      led->type = type;
 +      led->led_dev.brightness_set = rt2500usb_brightness_set;
 +      led->led_dev.blink_set = rt2500usb_blink_set;
 +      led->flags = LED_INITIALIZED;
 +}
  #endif /* CONFIG_RT2500USB_LEDS */
  
  /*
@@@ -812,6 -801,13 +812,13 @@@ static int rt2500usb_init_registers(str
        rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID1_VALID, 0);
        rt2500usb_register_write(rt2x00dev, TXRX_CSR8, reg);
  
+       rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+       rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
+       rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, 0);
+       rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
+       rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
        rt2500usb_register_write(rt2x00dev, TXRX_CSR21, 0xe78f);
        rt2500usb_register_write(rt2x00dev, MAC_CSR9, 0xff1d);
  
        return 0;
  }
  
 -static int rt2500usb_init_bbp(struct rt2x00_dev *rt2x00dev)
 +static int rt2500usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
  {
        unsigned int i;
 -      u16 eeprom;
        u8 value;
 -      u8 reg_id;
  
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
                rt2500usb_bbp_read(rt2x00dev, 0, &value);
                if ((value != 0xff) && (value != 0x00))
 -                      goto continue_csr_init;
 -              NOTICE(rt2x00dev, "Waiting for BBP register.\n");
 +                      return 0;
                udelay(REGISTER_BUSY_DELAY);
        }
  
        ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
        return -EACCES;
 +}
 +
 +static int rt2500usb_init_bbp(struct rt2x00_dev *rt2x00dev)
 +{
 +      unsigned int i;
 +      u16 eeprom;
 +      u8 value;
 +      u8 reg_id;
 +
 +      if (unlikely(rt2500usb_wait_bbp_ready(rt2x00dev)))
 +              return -EACCES;
  
 -continue_csr_init:
        rt2500usb_bbp_write(rt2x00dev, 3, 0x02);
        rt2500usb_bbp_write(rt2x00dev, 4, 0x19);
        rt2500usb_bbp_write(rt2x00dev, 14, 0x1c);
@@@ -945,8 -934,7 +952,8 @@@ static void rt2500usb_toggle_rx(struct 
  
        rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
        rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX,
 -                         state == STATE_RADIO_RX_OFF);
 +                         (state == STATE_RADIO_RX_OFF) ||
 +                         (state == STATE_RADIO_RX_OFF_LINK));
        rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
  }
  
@@@ -955,9 -943,11 +962,9 @@@ static int rt2500usb_enable_radio(struc
        /*
         * Initialize all registers.
         */
 -      if (rt2500usb_init_registers(rt2x00dev) ||
 -          rt2500usb_init_bbp(rt2x00dev)) {
 -              ERROR(rt2x00dev, "Register initialization failed.\n");
 +      if (unlikely(rt2500usb_init_registers(rt2x00dev) ||
 +                   rt2500usb_init_bbp(rt2x00dev)))
                return -EIO;
 -      }
  
        return 0;
  }
@@@ -1010,6 -1000,10 +1017,6 @@@ static int rt2500usb_set_state(struct r
                msleep(30);
        }
  
 -      NOTICE(rt2x00dev, "Device failed to enter state %d, "
 -             "current device state: bbp %d and rf %d.\n",
 -             state, bbp_state, rf_state);
 -
        return -EBUSY;
  }
  
@@@ -1027,13 -1021,11 +1034,13 @@@ static int rt2500usb_set_device_state(s
                break;
        case STATE_RADIO_RX_ON:
        case STATE_RADIO_RX_ON_LINK:
 -              rt2500usb_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
 -              break;
        case STATE_RADIO_RX_OFF:
        case STATE_RADIO_RX_OFF_LINK:
 -              rt2500usb_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
 +              rt2500usb_toggle_rx(rt2x00dev, state);
 +              break;
 +      case STATE_RADIO_IRQ_ON:
 +      case STATE_RADIO_IRQ_OFF:
 +              /* No support, but no error either */
                break;
        case STATE_DEEP_SLEEP:
        case STATE_SLEEP:
                break;
        }
  
 +      if (unlikely(retval))
 +              ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
 +                    state, retval);
 +
        return retval;
  }
  
   */
  static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
                                    struct sk_buff *skb,
 -                                  struct txentry_desc *txdesc,
 -                                  struct ieee80211_tx_control *control)
 +                                  struct txentry_desc *txdesc)
  {
        struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
        __le32 *txd = skbdesc->desc;
        rt2x00_desc_write(txd, 2, word);
  
        rt2x00_desc_read(txd, 0, &word);
 -      rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, control->retry_limit);
 +      rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, txdesc->retry_limit);
        rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
                           test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_ACK,
        rt2x00_set_field32(&word, TXD_W0_OFDM,
                           test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,
 -                         !!(control->flags & IEEE80211_TXCTL_FIRST_FRAGMENT));
 +                         test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
 -      rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
 +      rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT,
 +                         skb->len - skbdesc->desc_len);
        rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE);
        rt2x00_desc_write(txd, 0, word);
  }
@@@ -1119,14 -1107,12 +1126,14 @@@ static int rt2500usb_get_tx_data_len(st
   * TX data initialization
   */
  static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
 -                                  const unsigned int queue)
 +                                  const enum data_queue_qid queue)
  {
        u16 reg;
  
 -      if (queue != RT2X00_BCN_QUEUE_BEACON)
 +      if (queue != QID_BEACON) {
 +              rt2x00usb_kick_tx_queue(rt2x00dev, queue);
                return;
 +      }
  
        rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
        if (!rt2x00_get_field16(reg, TXRX_CSR19_BEACON_GEN)) {
  static void rt2500usb_fill_rxdone(struct queue_entry *entry,
                                  struct rxdone_entry_desc *rxdesc)
  {
 -      struct queue_entry_priv_usb_rx *priv_rx = entry->priv_data;
 +      struct queue_entry_priv_usb *entry_priv = entry->priv_data;
        struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
        __le32 *rxd =
            (__le32 *)(entry->skb->data +
 -                     (priv_rx->urb->actual_length - entry->queue->desc_size));
 -      unsigned int offset = entry->queue->desc_size + 2;
 +                     (entry_priv->urb->actual_length -
 +                      entry->queue->desc_size));
        u32 word0;
        u32 word1;
  
        /*
 -       * Copy descriptor to the available headroom inside the skbuffer.
 +       * Copy descriptor to the skbdesc->desc buffer, making it safe from moving of
 +       * frame data in rt2x00usb.
         */
 -      skb_push(entry->skb, offset);
 -      memcpy(entry->skb->data, rxd, entry->queue->desc_size);
 -      rxd = (__le32 *)entry->skb->data;
 +      memcpy(skbdesc->desc, rxd, skbdesc->desc_len);
 +      rxd = (__le32 *)skbdesc->desc;
  
        /*
 -       * The descriptor is now aligned to 4 bytes and thus it is
 -       * now safe to read it on all architectures.
 +       * It is now safe to read the descriptor on all architectures.
         */
        rt2x00_desc_read(rxd, 0, &word0);
        rt2x00_desc_read(rxd, 1, &word1);
  
 -      rxdesc->flags = 0;
        if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
                rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
        if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
            entry->queue->rt2x00dev->rssi_offset;
        rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
  
 -      rxdesc->dev_flags = 0;
        if (rt2x00_get_field32(word0, RXD_W0_OFDM))
                rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
        if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
        /*
         * Adjust the skb memory window to the frame boundaries.
         */
 -      skb_pull(entry->skb, offset);
        skb_trim(entry->skb, rxdesc->size);
 -
 -      /*
 -       * Set descriptor and data pointer.
 -       */
 -      skbdesc->data = entry->skb->data;
 -      skbdesc->data_len = rxdesc->size;
 -      skbdesc->desc = rxd;
 -      skbdesc->desc_len = entry->queue->desc_size;
  }
  
  /*
  static void rt2500usb_beacondone(struct urb *urb)
  {
        struct queue_entry *entry = (struct queue_entry *)urb->context;
 -      struct queue_entry_priv_usb_bcn *priv_bcn = entry->priv_data;
 +      struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
  
        if (!test_bit(DEVICE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags))
                return;
         * Otherwise we should free the sk_buffer, the device
         * should be doing the rest of the work now.
         */
 -      if (priv_bcn->guardian_urb == urb) {
 -              usb_submit_urb(priv_bcn->urb, GFP_ATOMIC);
 -      } else if (priv_bcn->urb == urb) {
 +      if (bcn_priv->guardian_urb == urb) {
 +              usb_submit_urb(bcn_priv->urb, GFP_ATOMIC);
 +      } else if (bcn_priv->urb == urb) {
                dev_kfree_skb(entry->skb);
                entry->skb = NULL;
        }
@@@ -1399,10 -1397,23 +1406,10 @@@ static int rt2500usb_init_eeprom(struc
  #ifdef CONFIG_RT2500USB_LEDS
        value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
  
 -      rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
 -      rt2x00dev->led_radio.type = LED_TYPE_RADIO;
 -      rt2x00dev->led_radio.led_dev.brightness_set =
 -          rt2500usb_brightness_set;
 -      rt2x00dev->led_radio.led_dev.blink_set =
 -          rt2500usb_blink_set;
 -      rt2x00dev->led_radio.flags = LED_INITIALIZED;
 -
 -      if (value == LED_MODE_TXRX_ACTIVITY) {
 -              rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
 -              rt2x00dev->led_qual.type = LED_TYPE_ACTIVITY;
 -              rt2x00dev->led_qual.led_dev.brightness_set =
 -                  rt2500usb_brightness_set;
 -              rt2x00dev->led_qual.led_dev.blink_set =
 -                  rt2500usb_blink_set;
 -              rt2x00dev->led_qual.flags = LED_INITIALIZED;
 -      }
 +      rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
 +      if (value == LED_MODE_TXRX_ACTIVITY)
 +              rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_qual,
 +                                 LED_TYPE_ACTIVITY);
  #endif /* CONFIG_RT2500USB_LEDS */
  
        /*
@@@ -1589,12 -1600,13 +1596,12 @@@ static void rt2500usb_probe_hw_mode(str
        rt2x00dev->hw->flags =
            IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
            IEEE80211_HW_RX_INCLUDES_FCS |
 -          IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
 +          IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
 +          IEEE80211_HW_SIGNAL_DBM;
 +
        rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
 -      rt2x00dev->hw->max_signal = MAX_SIGNAL;
 -      rt2x00dev->hw->max_rssi = MAX_RX_SSI;
 -      rt2x00dev->hw->queues = 2;
  
 -      SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev);
 +      SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
        SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
                                rt2x00_eeprom_addr(rt2x00dev,
                                                   EEPROM_MAC_ADDR_0));
@@@ -1675,15 -1687,15 +1682,15 @@@ static int rt2500usb_probe_hw(struct rt
  /*
   * IEEE80211 stack callback functions.
   */
 -static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
 -                                 struct sk_buff *skb,
 -                                 struct ieee80211_tx_control *control)
 +static int rt2500usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
  {
        struct rt2x00_dev *rt2x00dev = hw->priv;
 -      struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev);
 -      struct rt2x00_intf *intf = vif_to_intf(control->vif);
 -      struct queue_entry_priv_usb_bcn *priv_bcn;
 +      struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
 +      struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 +      struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
 +      struct queue_entry_priv_usb_bcn *bcn_priv;
        struct skb_frame_desc *skbdesc;
 +      struct txentry_desc txdesc;
        int pipe = usb_sndbulkpipe(usb_dev, 1);
        int length;
        u16 reg;
        if (unlikely(!intf->beacon))
                return -ENOBUFS;
  
 -      priv_bcn = intf->beacon->priv_data;
 +      bcn_priv = intf->beacon->priv_data;
 +
 +      /*
 +       * Copy all TX descriptor information into txdesc,
 +       * after that we are free to use the skb->cb array
 +       * for our information.
 +       */
 +      intf->beacon->skb = skb;
 +      rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);
  
        /*
         * Add the descriptor in front of the skb.
         */
        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;
        rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
        rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 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);
 +      rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc);
  
        /*
         * USB devices cannot blindly pass the skb->len as the
         */
        length = rt2500usb_get_tx_data_len(rt2x00dev, skb);
  
 -      usb_fill_bulk_urb(priv_bcn->urb, usb_dev, pipe,
 +      usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe,
                          skb->data, length, rt2500usb_beacondone,
                          intf->beacon);
  
         * We only need a single byte, so lets recycle
         * the 'flags' field we are not using for beacons.
         */
 -      priv_bcn->guardian_data = 0;
 -      usb_fill_bulk_urb(priv_bcn->guardian_urb, usb_dev, pipe,
 -                        &priv_bcn->guardian_data, 1, rt2500usb_beacondone,
 +      bcn_priv->guardian_data = 0;
 +      usb_fill_bulk_urb(bcn_priv->guardian_urb, usb_dev, pipe,
 +                        &bcn_priv->guardian_data, 1, rt2500usb_beacondone,
                          intf->beacon);
  
        /*
         * Send out the guardian byte.
         */
 -      usb_submit_urb(priv_bcn->guardian_urb, GFP_ATOMIC);
 +      usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC);
  
        /*
         * Enable beacon generation.
         */
 -      rt2500usb_kick_tx_queue(rt2x00dev, control->queue);
 +      rt2500usb_kick_tx_queue(rt2x00dev, QID_BEACON);
  
        return 0;
  }
@@@ -1803,14 -1816,14 +1810,14 @@@ static const struct data_queue_desc rt2
        .entry_num              = RX_ENTRIES,
        .data_size              = DATA_FRAME_SIZE,
        .desc_size              = RXD_DESC_SIZE,
 -      .priv_size              = sizeof(struct queue_entry_priv_usb_rx),
 +      .priv_size              = sizeof(struct queue_entry_priv_usb),
  };
  
  static const struct data_queue_desc rt2500usb_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),
 +      .priv_size              = sizeof(struct queue_entry_priv_usb),
  };
  
  static const struct data_queue_desc rt2500usb_queue_bcn = {
@@@ -1824,7 -1837,7 +1831,7 @@@ static const struct data_queue_desc rt2
        .entry_num              = ATIM_ENTRIES,
        .data_size              = DATA_FRAME_SIZE,
        .desc_size              = TXD_DESC_SIZE,
 -      .priv_size              = sizeof(struct queue_entry_priv_usb_tx),
 +      .priv_size              = sizeof(struct queue_entry_priv_usb),
  };
  
  static const struct rt2x00_ops rt2500usb_ops = {
        .max_ap_intf    = 1,
        .eeprom_size    = EEPROM_SIZE,
        .rf_size        = RF_SIZE,
 +      .tx_queues      = NUM_TX_QUEUES,
        .rx             = &rt2500usb_queue_rx,
        .tx             = &rt2500usb_queue_tx,
        .bcn            = &rt2500usb_queue_bcn,
index bbf1048f6400e89b18da2c8b74d202a13b0c0e2f,c3afb5cbe807f9a5387df50255b598a4f2d0027e..5a1330c5de71882a044e349ef906b8c40196be38
@@@ -330,17 -330,6 +330,17 @@@ static int rt61pci_blink_set(struct led
  
        return 0;
  }
 +
 +static void rt61pci_init_led(struct rt2x00_dev *rt2x00dev,
 +                           struct rt2x00_led *led,
 +                           enum led_type type)
 +{
 +      led->rt2x00dev = rt2x00dev;
 +      led->type = type;
 +      led->led_dev.brightness_set = rt61pci_brightness_set;
 +      led->led_dev.blink_set = rt61pci_blink_set;
 +      led->flags = LED_INITIALIZED;
 +}
  #endif /* CONFIG_RT61PCI_LEDS */
  
  /*
@@@ -1029,35 -1018,49 +1029,35 @@@ static int rt61pci_load_firmware(struc
  static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
                                 struct queue_entry *entry)
  {
 -      struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
 +      struct queue_entry_priv_pci *entry_priv = entry->priv_data;
 +      struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
        u32 word;
  
 -      rt2x00_desc_read(priv_rx->desc, 5, &word);
 +      rt2x00_desc_read(entry_priv->desc, 5, &word);
        rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS,
 -                         priv_rx->data_dma);
 -      rt2x00_desc_write(priv_rx->desc, 5, word);
 +                         skbdesc->skb_dma);
 +      rt2x00_desc_write(entry_priv->desc, 5, word);
  
 -      rt2x00_desc_read(priv_rx->desc, 0, &word);
 +      rt2x00_desc_read(entry_priv->desc, 0, &word);
        rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
 -      rt2x00_desc_write(priv_rx->desc, 0, word);
 +      rt2x00_desc_write(entry_priv->desc, 0, word);
  }
  
  static void rt61pci_init_txentry(struct rt2x00_dev *rt2x00dev,
                                 struct queue_entry *entry)
  {
 -      struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
 +      struct queue_entry_priv_pci *entry_priv = entry->priv_data;
        u32 word;
  
 -      rt2x00_desc_read(priv_tx->desc, 1, &word);
 -      rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
 -      rt2x00_desc_write(priv_tx->desc, 1, word);
 -
 -      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(priv_tx->desc, 5, word);
 -
 -      rt2x00_desc_read(priv_tx->desc, 6, &word);
 -      rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
 -                         priv_tx->data_dma);
 -      rt2x00_desc_write(priv_tx->desc, 6, word);
 -
 -      rt2x00_desc_read(priv_tx->desc, 0, &word);
 +      rt2x00_desc_read(entry_priv->desc, 0, &word);
        rt2x00_set_field32(&word, TXD_W0_VALID, 0);
        rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
 -      rt2x00_desc_write(priv_tx->desc, 0, word);
 +      rt2x00_desc_write(entry_priv->desc, 0, word);
  }
  
  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;
 +      struct queue_entry_priv_pci *entry_priv;
        u32 reg;
  
        /*
                           rt2x00dev->tx[0].desc_size / 4);
        rt2x00pci_register_write(rt2x00dev, TX_RING_CSR1, reg);
  
 -      priv_tx = rt2x00dev->tx[0].entries[0].priv_data;
 +      entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, AC0_BASE_CSR, &reg);
        rt2x00_set_field32(&reg, AC0_BASE_CSR_RING_REGISTER,
 -                         priv_tx->desc_dma);
 +                         entry_priv->desc_dma);
        rt2x00pci_register_write(rt2x00dev, AC0_BASE_CSR, reg);
  
 -      priv_tx = rt2x00dev->tx[1].entries[0].priv_data;
 +      entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, AC1_BASE_CSR, &reg);
        rt2x00_set_field32(&reg, AC1_BASE_CSR_RING_REGISTER,
 -                         priv_tx->desc_dma);
 +                         entry_priv->desc_dma);
        rt2x00pci_register_write(rt2x00dev, AC1_BASE_CSR, reg);
  
 -      priv_tx = rt2x00dev->tx[2].entries[0].priv_data;
 +      entry_priv = rt2x00dev->tx[2].entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, AC2_BASE_CSR, &reg);
        rt2x00_set_field32(&reg, AC2_BASE_CSR_RING_REGISTER,
 -                         priv_tx->desc_dma);
 +                         entry_priv->desc_dma);
        rt2x00pci_register_write(rt2x00dev, AC2_BASE_CSR, reg);
  
 -      priv_tx = rt2x00dev->tx[3].entries[0].priv_data;
 +      entry_priv = rt2x00dev->tx[3].entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, AC3_BASE_CSR, &reg);
        rt2x00_set_field32(&reg, AC3_BASE_CSR_RING_REGISTER,
 -                         priv_tx->desc_dma);
 +                         entry_priv->desc_dma);
        rt2x00pci_register_write(rt2x00dev, AC3_BASE_CSR, reg);
  
        rt2x00pci_register_read(rt2x00dev, RX_RING_CSR, &reg);
        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;
 +      entry_priv = rt2x00dev->rx->entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, RX_BASE_CSR, &reg);
        rt2x00_set_field32(&reg, RX_BASE_CSR_RING_REGISTER,
 -                         priv_rx->desc_dma);
 +                         entry_priv->desc_dma);
        rt2x00pci_register_write(rt2x00dev, RX_BASE_CSR, reg);
  
        rt2x00pci_register_read(rt2x00dev, TX_DMA_DST_CSR, &reg);
@@@ -1198,6 -1201,15 +1198,15 @@@ static int rt61pci_init_registers(struc
        rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_54MBS, 42);
        rt2x00pci_register_write(rt2x00dev, TXRX_CSR8, reg);
  
+       rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0);
+       rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
        rt2x00pci_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
  
        rt2x00pci_register_write(rt2x00dev, MAC_CSR6, 0x00000fff);
        return 0;
  }
  
 -static int rt61pci_init_bbp(struct rt2x00_dev *rt2x00dev)
 +static int rt61pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
  {
        unsigned int i;
 -      u16 eeprom;
 -      u8 reg_id;
        u8 value;
  
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
                rt61pci_bbp_read(rt2x00dev, 0, &value);
                if ((value != 0xff) && (value != 0x00))
 -                      goto continue_csr_init;
 -              NOTICE(rt2x00dev, "Waiting for BBP register.\n");
 +                      return 0;
                udelay(REGISTER_BUSY_DELAY);
        }
  
        ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
        return -EACCES;
 +}
 +
 +static int rt61pci_init_bbp(struct rt2x00_dev *rt2x00dev)
 +{
 +      unsigned int i;
 +      u16 eeprom;
 +      u8 reg_id;
 +      u8 value;
 +
 +      if (unlikely(rt61pci_wait_bbp_ready(rt2x00dev)))
 +              return -EACCES;
  
 -continue_csr_init:
        rt61pci_bbp_write(rt2x00dev, 3, 0x00);
        rt61pci_bbp_write(rt2x00dev, 15, 0x30);
        rt61pci_bbp_write(rt2x00dev, 21, 0xc8);
@@@ -1356,8 -1361,7 +1365,8 @@@ static void rt61pci_toggle_rx(struct rt
  
        rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
        rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX,
 -                         state == STATE_RADIO_RX_OFF);
 +                         (state == STATE_RADIO_RX_OFF) ||
 +                         (state == STATE_RADIO_RX_OFF_LINK));
        rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
  }
  
@@@ -1409,10 -1413,17 +1418,10 @@@ static int rt61pci_enable_radio(struct 
        /*
         * Initialize all registers.
         */
 -      if (rt61pci_init_queues(rt2x00dev) ||
 -          rt61pci_init_registers(rt2x00dev) ||
 -          rt61pci_init_bbp(rt2x00dev)) {
 -              ERROR(rt2x00dev, "Register initialization failed.\n");
 +      if (unlikely(rt61pci_init_queues(rt2x00dev) ||
 +                   rt61pci_init_registers(rt2x00dev) ||
 +                   rt61pci_init_bbp(rt2x00dev)))
                return -EIO;
 -      }
 -
 -      /*
 -       * Enable interrupts.
 -       */
 -      rt61pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_ON);
  
        /*
         * Enable RX.
@@@ -1444,6 -1455,11 +1453,6 @@@ static void rt61pci_disable_radio(struc
        rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC2, 1);
        rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC3, 1);
        rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
 -
 -      /*
 -       * Disable interrupts.
 -       */
 -      rt61pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_OFF);
  }
  
  static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
        u32 reg;
        unsigned int i;
        char put_to_sleep;
 -      char current_state;
  
        put_to_sleep = (state != STATE_AWAKE);
  
         */
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
                rt2x00pci_register_read(rt2x00dev, MAC_CSR12, &reg);
 -              current_state =
 -                  rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE);
 -              if (current_state == !put_to_sleep)
 +              state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE);
 +              if (state == !put_to_sleep)
                        return 0;
                msleep(10);
        }
  
 -      NOTICE(rt2x00dev, "Device failed to enter state %d, "
 -             "current device state %d.\n", !put_to_sleep, current_state);
 -
        return -EBUSY;
  }
  
@@@ -1489,13 -1510,11 +1498,13 @@@ static int rt61pci_set_device_state(str
                break;
        case STATE_RADIO_RX_ON:
        case STATE_RADIO_RX_ON_LINK:
 -              rt61pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
 -              break;
        case STATE_RADIO_RX_OFF:
        case STATE_RADIO_RX_OFF_LINK:
 -              rt61pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
 +              rt61pci_toggle_rx(rt2x00dev, state);
 +              break;
 +      case STATE_RADIO_IRQ_ON:
 +      case STATE_RADIO_IRQ_OFF:
 +              rt61pci_toggle_irq(rt2x00dev, state);
                break;
        case STATE_DEEP_SLEEP:
        case STATE_SLEEP:
                break;
        }
  
 +      if (unlikely(retval))
 +              ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
 +                    state, retval);
 +
        return retval;
  }
  
   */
  static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
                                    struct sk_buff *skb,
 -                                  struct txentry_desc *txdesc,
 -                                  struct ieee80211_tx_control *control)
 +                                  struct txentry_desc *txdesc)
  {
        struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
        __le32 *txd = skbdesc->desc;
        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_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
        rt2x00_desc_write(txd, 1, word);
  
        rt2x00_desc_read(txd, 2, &word);
        rt2x00_desc_write(txd, 2, word);
  
        rt2x00_desc_read(txd, 5, &word);
 +      rt2x00_set_field32(&word, TXD_W5_PID_TYPE, skbdesc->entry->queue->qid);
 +      rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE,
 +                         skbdesc->entry->entry_idx);
        rt2x00_set_field32(&word, TXD_W5_TX_POWER,
                           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, 6, &word);
 +      rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
 +                         skbdesc->skb_dma);
 +      rt2x00_desc_write(txd, 6, 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_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skb->len);
                rt2x00_desc_write(txd, 11, word);
        }
  
                           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));
 +                         test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
        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_DATABYTE_COUNT, skb->len);
        rt2x00_set_field32(&word, TXD_W0_BURST,
                           test_bit(ENTRY_TXD_BURST, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
   * TX data initialization
   */
  static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
 -                                const unsigned int queue)
 +                                const enum data_queue_qid queue)
  {
        u32 reg;
  
 -      if (queue == RT2X00_BCN_QUEUE_BEACON) {
 +      if (queue == QID_BEACON) {
                /*
                 * For Wi-Fi faily generated beacons between participating
                 * stations. Set TBTT phase adaptive adjustment step to 8us.
        }
  
        rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
 -      rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC0,
 -                         (queue == IEEE80211_TX_QUEUE_DATA0));
 -      rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC1,
 -                         (queue == IEEE80211_TX_QUEUE_DATA1));
 -      rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC2,
 -                         (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_AC0, (queue == QID_AC_BE));
 +      rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC1, (queue == QID_AC_BK));
 +      rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC2, (queue == QID_AC_VI));
 +      rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC3, (queue == QID_AC_VO));
        rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
  }
  
@@@ -1668,13 -1680,14 +1677,13 @@@ static int rt61pci_agc_to_rssi(struct r
  static void rt61pci_fill_rxdone(struct queue_entry *entry,
                                struct rxdone_entry_desc *rxdesc)
  {
 -      struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
 +      struct queue_entry_priv_pci *entry_priv = entry->priv_data;
        u32 word0;
        u32 word1;
  
 -      rt2x00_desc_read(priv_rx->desc, 0, &word0);
 -      rt2x00_desc_read(priv_rx->desc, 1, &word1);
 +      rt2x00_desc_read(entry_priv->desc, 0, &word0);
 +      rt2x00_desc_read(entry_priv->desc, 1, &word1);
  
 -      rxdesc->flags = 0;
        if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
                rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
  
        rxdesc->rssi = rt61pci_agc_to_rssi(entry->queue->rt2x00dev, word1);
        rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
  
 -      rxdesc->dev_flags = 0;
        if (rt2x00_get_field32(word0, RXD_W0_OFDM))
                rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
        if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
@@@ -1702,7 -1716,7 +1711,7 @@@ static void rt61pci_txdone(struct rt2x0
        struct data_queue *queue;
        struct queue_entry *entry;
        struct queue_entry *entry_done;
 -      struct queue_entry_priv_pci_tx *priv_tx;
 +      struct queue_entry_priv_pci *entry_priv;
        struct txdone_entry_desc txdesc;
        u32 word;
        u32 reg;
                        continue;
  
                entry = &queue->entries[index];
 -              priv_tx = entry->priv_data;
 -              rt2x00_desc_read(priv_tx->desc, 0, &word);
 +              entry_priv = entry->priv_data;
 +              rt2x00_desc_read(entry_priv->desc, 0, &word);
  
                if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
                    !rt2x00_get_field32(word, TXD_W0_VALID))
                                "TX status report missed for entry %d\n",
                                entry_done->entry_idx);
  
 -                      txdesc.status = TX_FAIL_OTHER;
 +                      txdesc.flags = 0;
 +                      __set_bit(TXDONE_UNKNOWN, &txdesc.flags);
                        txdesc.retry = 0;
  
 -                      rt2x00pci_txdone(rt2x00dev, entry_done, &txdesc);
 +                      rt2x00lib_txdone(entry_done, &txdesc);
                        entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
                }
  
                /*
                 * Obtain the status about this packet.
                 */
 -              txdesc.status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT);
 +              txdesc.flags = 0;
 +              switch (rt2x00_get_field32(reg, STA_CSR4_TX_RESULT)) {
 +              case 0: /* Success, maybe with retry */
 +                      __set_bit(TXDONE_SUCCESS, &txdesc.flags);
 +                      break;
 +              case 6: /* Failure, excessive retries */
 +                      __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags);
 +                      /* Don't break, this is a failed frame! */
 +              default: /* Failure */
 +                      __set_bit(TXDONE_FAILURE, &txdesc.flags);
 +              }
                txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
  
 -              rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
 +              rt2x00lib_txdone(entry, &txdesc);
        }
  }
  
@@@ -1973,7 -1976,7 +1982,7 @@@ static int rt61pci_init_eeprom(struct r
         * To determine the RT chip we have to read the
         * PCI header of the device.
         */
 -      pci_read_config_word(rt2x00dev_pci(rt2x00dev),
 +      pci_read_config_word(to_pci_dev(rt2x00dev->dev),
                             PCI_CONFIG_HEADER_DEVICE, &device);
        value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
        rt2x00pci_register_read(rt2x00dev, MAC_CSR0, &reg);
        rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
        value = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE);
  
 -      rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
 -      rt2x00dev->led_radio.type = LED_TYPE_RADIO;
 -      rt2x00dev->led_radio.led_dev.brightness_set =
 -          rt61pci_brightness_set;
 -      rt2x00dev->led_radio.led_dev.blink_set =
 -          rt61pci_blink_set;
 -      rt2x00dev->led_radio.flags = LED_INITIALIZED;
 -
 -      rt2x00dev->led_assoc.rt2x00dev = rt2x00dev;
 -      rt2x00dev->led_assoc.type = LED_TYPE_ASSOC;
 -      rt2x00dev->led_assoc.led_dev.brightness_set =
 -          rt61pci_brightness_set;
 -      rt2x00dev->led_assoc.led_dev.blink_set =
 -          rt61pci_blink_set;
 -      rt2x00dev->led_assoc.flags = LED_INITIALIZED;
 -
 -      if (value == LED_MODE_SIGNAL_STRENGTH) {
 -              rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
 -              rt2x00dev->led_qual.type = LED_TYPE_QUALITY;
 -              rt2x00dev->led_qual.led_dev.brightness_set =
 -                  rt61pci_brightness_set;
 -              rt2x00dev->led_qual.led_dev.blink_set =
 -                  rt61pci_blink_set;
 -              rt2x00dev->led_qual.flags = LED_INITIALIZED;
 -      }
 +      rt61pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
 +      rt61pci_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
 +      if (value == LED_MODE_SIGNAL_STRENGTH)
 +              rt61pci_init_led(rt2x00dev, &rt2x00dev->led_qual,
 +                               LED_TYPE_QUALITY);
  
        rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value);
        rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0,
@@@ -2235,11 -2258,13 +2244,11 @@@ static void rt61pci_probe_hw_mode(struc
         */
        rt2x00dev->hw->flags =
            IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
 -          IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
 +          IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
 +          IEEE80211_HW_SIGNAL_DBM;
        rt2x00dev->hw->extra_tx_headroom = 0;
 -      rt2x00dev->hw->max_signal = MAX_SIGNAL;
 -      rt2x00dev->hw->max_rssi = MAX_RX_SSI;
 -      rt2x00dev->hw->queues = 4;
  
 -      SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
 +      SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
        SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
                                rt2x00_eeprom_addr(rt2x00dev,
                                                   EEPROM_MAC_ADDR_0));
@@@ -2302,10 -2327,9 +2311,10 @@@ static int rt61pci_probe_hw(struct rt2x
        rt61pci_probe_hw_mode(rt2x00dev);
  
        /*
 -       * This device requires firmware.
 +       * This device requires firmware and DMA mapped skbs.
         */
        __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
 +      __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
  
        /*
         * Set the rssi offset.
@@@ -2346,37 -2370,31 +2355,37 @@@ static u64 rt61pci_get_tsf(struct ieee8
        return tsf;
  }
  
 -static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
 -                        struct ieee80211_tx_control *control)
 +static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
  {
        struct rt2x00_dev *rt2x00dev = hw->priv;
 -      struct rt2x00_intf *intf = vif_to_intf(control->vif);
 -      struct queue_entry_priv_pci_tx *priv_tx;
 +      struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 +      struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
 +      struct queue_entry_priv_pci *entry_priv;
        struct skb_frame_desc *skbdesc;
 +      struct txentry_desc txdesc;
        unsigned int beacon_base;
        u32 reg;
  
        if (unlikely(!intf->beacon))
                return -ENOBUFS;
  
 -      priv_tx = intf->beacon->priv_data;
 -      memset(priv_tx->desc, 0, intf->beacon->queue->desc_size);
 +      /*
 +       * Copy all TX descriptor information into txdesc,
 +       * after that we are free to use the skb->cb array
 +       * for our information.
 +       */
 +      intf->beacon->skb = skb;
 +      rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);
 +
 +      entry_priv = intf->beacon->priv_data;
 +      memset(entry_priv->desc, 0, intf->beacon->queue->desc_size);
  
        /*
         * Fill in skb descriptor
         */
        skbdesc = get_skb_frame_desc(skb);
        memset(skbdesc, 0, sizeof(*skbdesc));
 -      skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
 -      skbdesc->data = skb->data;
 -      skbdesc->data_len = skb->len;
 -      skbdesc->desc = priv_tx->desc;
 +      skbdesc->desc = entry_priv->desc;
        skbdesc->desc_len = intf->beacon->queue->desc_size;
        skbdesc->entry = intf->beacon;
  
        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.
         */
 +      rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc);
        beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
        rt2x00pci_register_multiwrite(rt2x00dev, beacon_base,
                                      skbdesc->desc, skbdesc->desc_len);
        rt2x00pci_register_multiwrite(rt2x00dev,
                                      beacon_base + skbdesc->desc_len,
 -                                    skbdesc->data, skbdesc->data_len);
 -      rt61pci_kick_tx_queue(rt2x00dev, control->queue);
 +                                    skb->data, skb->len);
 +      rt61pci_kick_tx_queue(rt2x00dev, QID_BEACON);
 +
 +      /*
 +       * Clean up beacon skb.
 +       */
 +      dev_kfree_skb_any(skb);
 +      intf->beacon->skb = NULL;
  
        return 0;
  }
@@@ -2459,21 -2478,21 +2468,21 @@@ static const struct data_queue_desc rt6
        .entry_num              = RX_ENTRIES,
        .data_size              = DATA_FRAME_SIZE,
        .desc_size              = RXD_DESC_SIZE,
 -      .priv_size              = sizeof(struct queue_entry_priv_pci_rx),
 +      .priv_size              = sizeof(struct queue_entry_priv_pci),
  };
  
  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),
 +      .priv_size              = sizeof(struct queue_entry_priv_pci),
  };
  
  static const struct data_queue_desc rt61pci_queue_bcn = {
        .entry_num              = 4 * BEACON_ENTRIES,
        .data_size              = 0, /* No DMA required for beacons */
        .desc_size              = TXINFO_SIZE,
 -      .priv_size              = sizeof(struct queue_entry_priv_pci_tx),
 +      .priv_size              = sizeof(struct queue_entry_priv_pci),
  };
  
  static const struct rt2x00_ops rt61pci_ops = {
        .max_ap_intf    = 4,
        .eeprom_size    = EEPROM_SIZE,
        .rf_size        = RF_SIZE,
 +      .tx_queues      = NUM_TX_QUEUES,
        .rx             = &rt61pci_queue_rx,
        .tx             = &rt61pci_queue_tx,
        .bcn            = &rt61pci_queue_bcn,
index 3ef318e098e7a372895723b2c969a4493bbbf895,46e9e081fbf1fcae1d491872ab5298bdce30520b..25d8b660051f48aa8c71bdd7db1f377c48a83f97
@@@ -74,10 -74,10 +74,10 @@@ static inline void rt73usb_register_mul
                                              const unsigned int offset,
                                              void *value, const u32 length)
  {
 -      int timeout = REGISTER_TIMEOUT * (length / sizeof(u32));
        rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
                                      USB_VENDOR_REQUEST_IN, offset,
 -                                    value, length, timeout);
 +                                    value, length,
 +                                    REGISTER_TIMEOUT32(length));
  }
  
  static inline void rt73usb_register_write(struct rt2x00_dev *rt2x00dev,
@@@ -102,10 -102,10 +102,10 @@@ static inline void rt73usb_register_mul
                                               const unsigned int offset,
                                               void *value, const u32 length)
  {
 -      int timeout = REGISTER_TIMEOUT * (length / sizeof(u32));
        rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
                                      USB_VENDOR_REQUEST_OUT, offset,
 -                                    value, length, timeout);
 +                                    value, length,
 +                                    REGISTER_TIMEOUT32(length));
  }
  
  static u32 rt73usb_bbp_check(struct rt2x00_dev *rt2x00dev)
@@@ -341,17 -341,6 +341,17 @@@ static int rt73usb_blink_set(struct led
  
        return 0;
  }
 +
 +static void rt73usb_init_led(struct rt2x00_dev *rt2x00dev,
 +                           struct rt2x00_led *led,
 +                           enum led_type type)
 +{
 +      led->rt2x00dev = rt2x00dev;
 +      led->type = type;
 +      led->led_dev.brightness_set = rt73usb_brightness_set;
 +      led->led_dev.blink_set = rt73usb_blink_set;
 +      led->flags = LED_INITIALIZED;
 +}
  #endif /* CONFIG_RT73USB_LEDS */
  
  /*
@@@ -893,6 -882,7 +893,6 @@@ static int rt73usb_load_firmware(struc
        char *ptr = data;
        char *cache;
        int buflen;
 -      int timeout;
  
        /*
         * Wait for stable hardware.
  
        for (i = 0; i < len; i += CSR_CACHE_SIZE_FIRMWARE) {
                buflen = min_t(int, len - i, CSR_CACHE_SIZE_FIRMWARE);
 -              timeout = REGISTER_TIMEOUT * (buflen / sizeof(u32));
  
                memcpy(cache, ptr, buflen);
  
                rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE,
                                         USB_VENDOR_REQUEST_OUT,
                                         FIRMWARE_IMAGE_BASE + i, 0,
 -                                       cache, buflen, timeout);
 +                                       cache, buflen,
 +                                       REGISTER_TIMEOUT32(buflen));
  
                ptr += buflen;
        }
@@@ -1016,6 -1006,15 +1016,15 @@@ static int rt73usb_init_registers(struc
        rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_54MBS, 42);
        rt73usb_register_write(rt2x00dev, TXRX_CSR8, reg);
  
+       rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0);
+       rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
        rt73usb_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
  
        rt73usb_register_read(rt2x00dev, MAC_CSR6, &reg);
        return 0;
  }
  
 -static int rt73usb_init_bbp(struct rt2x00_dev *rt2x00dev)
 +static int rt73usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
  {
        unsigned int i;
 -      u16 eeprom;
 -      u8 reg_id;
        u8 value;
  
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
                rt73usb_bbp_read(rt2x00dev, 0, &value);
                if ((value != 0xff) && (value != 0x00))
 -                      goto continue_csr_init;
 -              NOTICE(rt2x00dev, "Waiting for BBP register.\n");
 +                      return 0;
                udelay(REGISTER_BUSY_DELAY);
        }
  
        ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
        return -EACCES;
 +}
 +
 +static int rt73usb_init_bbp(struct rt2x00_dev *rt2x00dev)
 +{
 +      unsigned int i;
 +      u16 eeprom;
 +      u8 reg_id;
 +      u8 value;
 +
 +      if (unlikely(rt73usb_wait_bbp_ready(rt2x00dev)))
 +              return -EACCES;
  
 -continue_csr_init:
        rt73usb_bbp_write(rt2x00dev, 3, 0x80);
        rt73usb_bbp_write(rt2x00dev, 15, 0x30);
        rt73usb_bbp_write(rt2x00dev, 21, 0xc8);
@@@ -1176,8 -1168,7 +1185,8 @@@ static void rt73usb_toggle_rx(struct rt
  
        rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
        rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX,
 -                         state == STATE_RADIO_RX_OFF);
 +                         (state == STATE_RADIO_RX_OFF) ||
 +                         (state == STATE_RADIO_RX_OFF_LINK));
        rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
  }
  
@@@ -1186,9 -1177,11 +1195,9 @@@ static int rt73usb_enable_radio(struct 
        /*
         * Initialize all registers.
         */
 -      if (rt73usb_init_registers(rt2x00dev) ||
 -          rt73usb_init_bbp(rt2x00dev)) {
 -              ERROR(rt2x00dev, "Register initialization failed.\n");
 +      if (unlikely(rt73usb_init_registers(rt2x00dev) ||
 +                   rt73usb_init_bbp(rt2x00dev)))
                return -EIO;
 -      }
  
        return 0;
  }
@@@ -1210,6 -1203,7 +1219,6 @@@ static int rt73usb_set_state(struct rt2
        u32 reg;
        unsigned int i;
        char put_to_sleep;
 -      char current_state;
  
        put_to_sleep = (state != STATE_AWAKE);
  
         */
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
                rt73usb_register_read(rt2x00dev, MAC_CSR12, &reg);
 -              current_state =
 -                  rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE);
 -              if (current_state == !put_to_sleep)
 +              state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE);
 +              if (state == !put_to_sleep)
                        return 0;
                msleep(10);
        }
  
 -      NOTICE(rt2x00dev, "Device failed to enter state %d, "
 -             "current device state %d.\n", !put_to_sleep, current_state);
 -
        return -EBUSY;
  }
  
@@@ -1248,13 -1246,11 +1257,13 @@@ static int rt73usb_set_device_state(str
                break;
        case STATE_RADIO_RX_ON:
        case STATE_RADIO_RX_ON_LINK:
 -              rt73usb_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
 -              break;
        case STATE_RADIO_RX_OFF:
        case STATE_RADIO_RX_OFF_LINK:
 -              rt73usb_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
 +              rt73usb_toggle_rx(rt2x00dev, state);
 +              break;
 +      case STATE_RADIO_IRQ_ON:
 +      case STATE_RADIO_IRQ_OFF:
 +              /* No support, but no error either */
                break;
        case STATE_DEEP_SLEEP:
        case STATE_SLEEP:
                break;
        }
  
 +      if (unlikely(retval))
 +              ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
 +                    state, retval);
 +
        return retval;
  }
  
   */
  static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
                                    struct sk_buff *skb,
 -                                  struct txentry_desc *txdesc,
 -                                  struct ieee80211_tx_control *control)
 +                                  struct txentry_desc *txdesc)
  {
        struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
        __le32 *txd = skbdesc->desc;
                           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));
 +                         test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
        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_DATABYTE_COUNT,
 +                         skb->len - skbdesc->desc_len);
        rt2x00_set_field32(&word, TXD_W0_BURST2,
                           test_bit(ENTRY_TXD_BURST, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
@@@ -1353,14 -1346,12 +1362,14 @@@ static int rt73usb_get_tx_data_len(stru
   * TX data initialization
   */
  static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
 -                                const unsigned int queue)
 +                                const enum data_queue_qid queue)
  {
        u32 reg;
  
 -      if (queue != RT2X00_BCN_QUEUE_BEACON)
 +      if (queue != QID_BEACON) {
 +              rt2x00usb_kick_tx_queue(rt2x00dev, queue);
                return;
 +      }
  
        /*
         * For Wi-Fi faily generated beacons between participating stations.
@@@ -1430,22 -1421,25 +1439,22 @@@ static void rt73usb_fill_rxdone(struct 
  {
        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.
 +       * Copy descriptor to the skbdesc->desc buffer, making it safe from moving of
 +       * frame data in rt2x00usb.
         */
 -      skb_push(entry->skb, offset);
 -      memcpy(entry->skb->data, rxd, entry->queue->desc_size);
 -      rxd = (__le32 *)entry->skb->data;
 +      memcpy(skbdesc->desc, rxd, skbdesc->desc_len);
 +      rxd = (__le32 *)skbdesc->desc;
  
        /*
 -       * The descriptor is now aligned to 4 bytes and thus it is
 -       * now safe to read it on all architectures.
 +       * It is now safe to read the descriptor on all architectures.
         */
        rt2x00_desc_read(rxd, 0, &word0);
        rt2x00_desc_read(rxd, 1, &word1);
  
 -      rxdesc->flags = 0;
        if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
                rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
  
        rxdesc->rssi = rt73usb_agc_to_rssi(entry->queue->rt2x00dev, word1);
        rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
  
 -      rxdesc->dev_flags = 0;
        if (rt2x00_get_field32(word0, RXD_W0_OFDM))
                rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
        if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
                rxdesc->dev_flags |= RXDONE_MY_BSS;
  
        /*
 -       * Adjust the skb memory window to the frame boundaries.
 +       * Set skb pointers, and update frame information.
         */
 -      skb_pull(entry->skb, offset + entry->queue->desc_size);
 +      skb_pull(entry->skb, entry->queue->desc_size);
        skb_trim(entry->skb, rxdesc->size);
 -
 -      /*
 -       * Set descriptor and data pointer.
 -       */
 -      skbdesc->data = entry->skb->data;
 -      skbdesc->data_len = rxdesc->size;
 -      skbdesc->desc = rxd;
 -      skbdesc->desc_len = entry->queue->desc_size;
  }
  
  /*
@@@ -1641,11 -1644,31 +1650,11 @@@ static int rt73usb_init_eeprom(struct r
  #ifdef CONFIG_RT73USB_LEDS
        rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
  
 -      rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
 -      rt2x00dev->led_radio.type = LED_TYPE_RADIO;
 -      rt2x00dev->led_radio.led_dev.brightness_set =
 -          rt73usb_brightness_set;
 -      rt2x00dev->led_radio.led_dev.blink_set =
 -          rt73usb_blink_set;
 -      rt2x00dev->led_radio.flags = LED_INITIALIZED;
 -
 -      rt2x00dev->led_assoc.rt2x00dev = rt2x00dev;
 -      rt2x00dev->led_assoc.type = LED_TYPE_ASSOC;
 -      rt2x00dev->led_assoc.led_dev.brightness_set =
 -          rt73usb_brightness_set;
 -      rt2x00dev->led_assoc.led_dev.blink_set =
 -          rt73usb_blink_set;
 -      rt2x00dev->led_assoc.flags = LED_INITIALIZED;
 -
 -      if (value == LED_MODE_SIGNAL_STRENGTH) {
 -              rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
 -              rt2x00dev->led_qual.type = LED_TYPE_QUALITY;
 -              rt2x00dev->led_qual.led_dev.brightness_set =
 -                  rt73usb_brightness_set;
 -              rt2x00dev->led_qual.led_dev.blink_set =
 -                  rt73usb_blink_set;
 -              rt2x00dev->led_qual.flags = LED_INITIALIZED;
 -      }
 +      rt73usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
 +      rt73usb_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
 +      if (value == LED_MODE_SIGNAL_STRENGTH)
 +              rt73usb_init_led(rt2x00dev, &rt2x00dev->led_qual,
 +                               LED_TYPE_QUALITY);
  
        rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value);
        rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0,
@@@ -1823,11 -1846,13 +1832,11 @@@ static void rt73usb_probe_hw_mode(struc
         */
        rt2x00dev->hw->flags =
            IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
 -          IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
 +          IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
 +          IEEE80211_HW_SIGNAL_DBM;
        rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
 -      rt2x00dev->hw->max_signal = MAX_SIGNAL;
 -      rt2x00dev->hw->max_rssi = MAX_RX_SSI;
 -      rt2x00dev->hw->queues = 4;
  
 -      SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev);
 +      SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
        SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
                                rt2x00_eeprom_addr(rt2x00dev,
                                                   EEPROM_MAC_ADDR_0));
@@@ -1949,27 -1974,19 +1958,27 @@@ static u64 rt73usb_get_tsf(struct ieee8
  #define rt73usb_get_tsf       NULL
  #endif
  
 -static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
 -                               struct ieee80211_tx_control *control)
 +static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
  {
        struct rt2x00_dev *rt2x00dev = hw->priv;
 -      struct rt2x00_intf *intf = vif_to_intf(control->vif);
 +      struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 +      struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
        struct skb_frame_desc *skbdesc;
 +      struct txentry_desc txdesc;
        unsigned int beacon_base;
 -      unsigned int timeout;
        u32 reg;
  
        if (unlikely(!intf->beacon))
                return -ENOBUFS;
  
 +      /*
 +       * Copy all TX descriptor information into txdesc,
 +       * after that we are free to use the skb->cb array
 +       * for our information.
 +       */
 +      intf->beacon->skb = skb;
 +      rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);
 +
        /*
         * Add the descriptor in front of the skb.
         */
         */
        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;
        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.
         */
 +      rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc);
        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, beacon_base, 0,
 -                               skb->data, skb->len, timeout);
 -      rt73usb_kick_tx_queue(rt2x00dev, control->queue);
 +                               skb->data, skb->len,
 +                               REGISTER_TIMEOUT32(skb->len));
 +      rt73usb_kick_tx_queue(rt2x00dev, QID_BEACON);
 +
 +      /*
 +       * Clean up the beacon skb.
 +       */
 +      dev_kfree_skb(skb);
 +      intf->beacon->skb = NULL;
  
        return 0;
  }
@@@ -2062,21 -2083,21 +2071,21 @@@ static const struct data_queue_desc rt7
        .entry_num              = RX_ENTRIES,
        .data_size              = DATA_FRAME_SIZE,
        .desc_size              = RXD_DESC_SIZE,
 -      .priv_size              = sizeof(struct queue_entry_priv_usb_rx),
 +      .priv_size              = sizeof(struct queue_entry_priv_usb),
  };
  
  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),
 +      .priv_size              = sizeof(struct queue_entry_priv_usb),
  };
  
  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),
 +      .priv_size              = sizeof(struct queue_entry_priv_usb),
  };
  
  static const struct rt2x00_ops rt73usb_ops = {
        .max_ap_intf    = 4,
        .eeprom_size    = EEPROM_SIZE,
        .rf_size        = RF_SIZE,
 +      .tx_queues      = NUM_TX_QUEUES,
        .rx             = &rt73usb_queue_rx,
        .tx             = &rt73usb_queue_tx,
        .bcn            = &rt73usb_queue_bcn,
index 665f76af2fec134fcb53bad523dfee7593362088,694e95d35fd437afc0dcf269ad20ec98232ef648..feaf43d172498590f20b6cef32d29f9baae7cbcc
@@@ -224,6 -224,36 +224,6 @@@ out
        return r;
  }
  
 -/**
 - * clear_tx_skb_control_block - clears the control block of tx skbuffs
 - * @skb: a &struct sk_buff pointer
 - *
 - * This clears the control block of skbuff buffers, which were transmitted to
 - * the device. Notify that the function is not thread-safe, so prevent
 - * multiple calls.
 - */
 -static void clear_tx_skb_control_block(struct sk_buff *skb)
 -{
 -      struct zd_tx_skb_control_block *cb =
 -              (struct zd_tx_skb_control_block *)skb->cb;
 -
 -      kfree(cb->control);
 -      cb->control = NULL;
 -}
 -
 -/**
 - * kfree_tx_skb - frees a tx skbuff
 - * @skb: a &struct sk_buff pointer
 - *
 - * Frees the tx skbuff. Frees also the allocated control structure in the
 - * control block if necessary.
 - */
 -static void kfree_tx_skb(struct sk_buff *skb)
 -{
 -      clear_tx_skb_control_block(skb);
 -      dev_kfree_skb_any(skb);
 -}
 -
  static void zd_op_stop(struct ieee80211_hw *hw)
  {
        struct zd_mac *mac = zd_hw_mac(hw);
  
  
        while ((skb = skb_dequeue(ack_wait_queue)))
 -              kfree_tx_skb(skb);
 -}
 -
 -/**
 - * init_tx_skb_control_block - initializes skb control block
 - * @skb: a &sk_buff pointer
 - * @dev: pointer to the mac80221 device
 - * @control: mac80211 tx control applying for the frame in @skb
 - *
 - * Initializes the control block of the skbuff to be transmitted.
 - */
 -static int init_tx_skb_control_block(struct sk_buff *skb,
 -                                   struct ieee80211_hw *hw,
 -                                   struct ieee80211_tx_control *control)
 -{
 -      struct zd_tx_skb_control_block *cb =
 -              (struct zd_tx_skb_control_block *)skb->cb;
 -
 -      ZD_ASSERT(sizeof(*cb) <= sizeof(skb->cb));
 -      memset(cb, 0, sizeof(*cb));
 -      cb->hw= hw;
 -      cb->control = kmalloc(sizeof(*control), GFP_ATOMIC);
 -      if (cb->control == NULL)
 -              return -ENOMEM;
 -      memcpy(cb->control, control, sizeof(*control));
 -
 -      return 0;
 +              dev_kfree_skb_any(skb);
  }
  
  /**
   * tx_status - reports tx status of a packet if required
   * @hw - a &struct ieee80211_hw pointer
   * @skb - a sk-buffer
 - * @status - the tx status of the packet without control information
 + * @flags: extra flags to set in the TX status info
 + * @ackssi: ACK signal strength
   * @success - True for successfull transmission of the frame
   *
   * This information calls ieee80211_tx_status_irqsafe() if required by the
   * If no status information has been requested, the skb is freed.
   */
  static void tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
 -                    struct ieee80211_tx_status *status,
 -                    bool success)
 +                    u32 flags, int ackssi, bool success)
  {
 -      struct zd_tx_skb_control_block *cb = (struct zd_tx_skb_control_block *)
 -              skb->cb;
 +      struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 +
 +      memset(&info->status, 0, sizeof(info->status));
  
 -      ZD_ASSERT(cb->control != NULL);
 -      memcpy(&status->control, cb->control, sizeof(status->control));
        if (!success)
 -              status->excessive_retries = 1;
 -      clear_tx_skb_control_block(skb);
 -      ieee80211_tx_status_irqsafe(hw, skb, status);
 +              info->status.excessive_retries = 1;
 +      info->flags |= flags;
 +      info->status.ack_signal = ackssi;
 +      ieee80211_tx_status_irqsafe(hw, skb);
  }
  
  /**
@@@ -289,12 -345,15 +289,12 @@@ void zd_mac_tx_failed(struct ieee80211_
  {
        struct sk_buff_head *q = &zd_hw_mac(hw)->ack_wait_queue;
        struct sk_buff *skb;
 -      struct ieee80211_tx_status status;
  
        skb = skb_dequeue(q);
        if (skb == NULL)
                return;
  
 -      memset(&status, 0, sizeof(status));
 -
 -      tx_status(hw, skb, &status, 0);
 +      tx_status(hw, skb, 0, 0, 0);
  }
  
  /**
   */
  void zd_mac_tx_to_dev(struct sk_buff *skb, int error)
  {
 -      struct zd_tx_skb_control_block *cb =
 -              (struct zd_tx_skb_control_block *)skb->cb;
 -      struct ieee80211_hw *hw = cb->hw;
 -
 -      if (likely(cb->control)) {
 -              skb_pull(skb, sizeof(struct zd_ctrlset));
 -              if (unlikely(error ||
 -                  (cb->control->flags & IEEE80211_TXCTL_NO_ACK)))
 -              {
 -                      struct ieee80211_tx_status status;
 -                      memset(&status, 0, sizeof(status));
 -                      tx_status(hw, skb, &status, !error);
 -              } else {
 -                      struct sk_buff_head *q =
 -                              &zd_hw_mac(hw)->ack_wait_queue;
 +      struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 +      struct ieee80211_hw *hw = info->driver_data[0];
  
 -                      skb_queue_tail(q, skb);
 -                      while (skb_queue_len(q) > ZD_MAC_MAX_ACK_WAITERS)
 -                              zd_mac_tx_failed(hw);
 -              }
 +      skb_pull(skb, sizeof(struct zd_ctrlset));
 +      if (unlikely(error ||
 +          (info->flags & IEEE80211_TX_CTL_NO_ACK))) {
 +              tx_status(hw, skb, 0, 0, !error);
        } else {
 -              kfree_tx_skb(skb);
 +              struct sk_buff_head *q =
 +                      &zd_hw_mac(hw)->ack_wait_queue;
 +
 +              skb_queue_tail(q, skb);
 +              while (skb_queue_len(q) > ZD_MAC_MAX_ACK_WAITERS)
 +                      zd_mac_tx_failed(hw);
        }
  }
  
@@@ -376,6 -443,8 +376,6 @@@ static int zd_calc_tx_length_us(u8 *ser
  static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
                           struct ieee80211_hdr *header, u32 flags)
  {
 -      u16 fctl = le16_to_cpu(header->frame_control);
 -
        /*
         * CONTROL TODO:
         * - if backoff needed, enable bit 0
        cs->control = 0;
  
        /* First fragment */
 -      if (flags & IEEE80211_TXCTL_FIRST_FRAGMENT)
 +      if (flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
                cs->control |= ZD_CS_NEED_RANDOM_BACKOFF;
  
        /* Multicast */
                cs->control |= ZD_CS_MULTICAST;
  
        /* PS-POLL */
 -      if ((fctl & (IEEE80211_FCTL_FTYPE|IEEE80211_FCTL_STYPE)) ==
 -          (IEEE80211_FTYPE_CTL|IEEE80211_STYPE_PSPOLL))
 +      if (ieee80211_is_pspoll(header->frame_control))
                cs->control |= ZD_CS_PS_POLL_FRAME;
  
 -      if (flags & IEEE80211_TXCTL_USE_RTS_CTS)
 +      if (flags & IEEE80211_TX_CTL_USE_RTS_CTS)
                cs->control |= ZD_CS_RTS;
  
 -      if (flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
 +      if (flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
                cs->control |= ZD_CS_SELF_CTS;
  
        /* FIXME: Management frame? */
  }
  
 -void zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
 +static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
  {
        struct zd_mac *mac = zd_hw_mac(hw);
 +      int r;
        u32 tmp, j = 0;
        /* 4 more bytes for tail CRC */
        u32 full_len = beacon->len + 4;
 -      zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0);
 -      zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
 +
 +      r = zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0);
 +      if (r < 0)
 +              return r;
 +      r = zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
 +      if (r < 0)
 +              return r;
 +
        while (tmp & 0x2) {
 -              zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
 +              r = zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
 +              if (r < 0)
 +                      return r;
                if ((++j % 100) == 0) {
                        printk(KERN_ERR "CR_BCN_FIFO_SEMAPHORE not ready\n");
                        if (j >= 500)  {
                                printk(KERN_ERR "Giving up beacon config.\n");
 -                              return;
 +                              return -ETIMEDOUT;
                        }
                }
                msleep(1);
        }
  
 -      zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1);
 -      if (zd_chip_is_zd1211b(&mac->chip))
 -              zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1);
 +      r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1);
 +      if (r < 0)
 +              return r;
 +      if (zd_chip_is_zd1211b(&mac->chip)) {
 +              r = zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1);
 +              if (r < 0)
 +                      return r;
 +      }
  
 -      for (j = 0 ; j < beacon->len; j++)
 -              zd_iowrite32(&mac->chip, CR_BCN_FIFO,
 +      for (j = 0 ; j < beacon->len; j++) {
 +              r = zd_iowrite32(&mac->chip, CR_BCN_FIFO,
                                *((u8 *)(beacon->data + j)));
 +              if (r < 0)
 +                      return r;
 +      }
 +
 +      for (j = 0; j < 4; j++) {
 +              r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0);
 +              if (r < 0)
 +                      return r;
 +      }
  
 -      for (j = 0; j < 4; j++)
 -              zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0);
 +      r = zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1);
 +      if (r < 0)
 +              return r;
  
 -      zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1);
        /* 802.11b/g 2.4G CCK 1Mb
         * 802.11a, not yet implemented, uses different values (see GPL vendor
         * driver)
         */
 -      zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 |
 +      return zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 |
                        (full_len << 19));
  }
  
  static int fill_ctrlset(struct zd_mac *mac,
 -                      struct sk_buff *skb,
 -                      struct ieee80211_tx_control *control)
 +                      struct sk_buff *skb)
  {
        int r;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
        unsigned int frag_len = skb->len + FCS_LEN;
        unsigned int packet_length;
 +      struct ieee80211_rate *txrate;
        struct zd_ctrlset *cs = (struct zd_ctrlset *)
                skb_push(skb, sizeof(struct zd_ctrlset));
 +      struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
  
        ZD_ASSERT(frag_len <= 0xffff);
  
 -      cs->modulation = control->tx_rate->hw_value;
 -      if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
 -              cs->modulation = control->tx_rate->hw_value_short;
 +      txrate = ieee80211_get_tx_rate(mac->hw, info);
 +
 +      cs->modulation = txrate->hw_value;
 +      if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE)
 +              cs->modulation = txrate->hw_value_short;
  
        cs->tx_length = cpu_to_le16(frag_len);
  
 -      cs_set_control(mac, cs, hdr, control->flags);
 +      cs_set_control(mac, cs, hdr, info->flags);
  
        packet_length = frag_len + sizeof(struct zd_ctrlset) + 10;
        ZD_ASSERT(packet_length <= 0xffff);
   * control block of the skbuff will be initialized. If necessary the incoming
   * mac80211 queues will be stopped.
   */
 -static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
 -                   struct ieee80211_tx_control *control)
 +static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
  {
        struct zd_mac *mac = zd_hw_mac(hw);
 +      struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        int r;
  
 -      r = fill_ctrlset(mac, skb, control);
 +      r = fill_ctrlset(mac, skb);
        if (r)
                return r;
  
 -      r = init_tx_skb_control_block(skb, hw, control);
 -      if (r)
 -              return r;
 +      info->driver_data[0] = hw;
 +
        r = zd_usb_tx(&mac->chip.usb, skb);
 -      if (r) {
 -              clear_tx_skb_control_block(skb);
 +      if (r)
                return r;
 -      }
        return 0;
  }
  
  static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr,
                      struct ieee80211_rx_status *stats)
  {
 -      u16 fc = le16_to_cpu(rx_hdr->frame_control);
        struct sk_buff *skb;
        struct sk_buff_head *q;
        unsigned long flags;
  
 -      if ((fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) !=
 -          (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_ACK))
 +      if (!ieee80211_is_ack(rx_hdr->frame_control))
                return 0;
  
        q = &zd_hw_mac(hw)->ack_wait_queue;
                tx_hdr = (struct ieee80211_hdr *)skb->data;
                if (likely(!compare_ether_addr(tx_hdr->addr2, rx_hdr->addr1)))
                {
 -                      struct ieee80211_tx_status status;
 -
 -                      memset(&status, 0, sizeof(status));
 -                      status.flags = IEEE80211_TX_STATUS_ACK;
 -                      status.ack_signal = stats->ssi;
                        __skb_unlink(skb, q);
 -                      tx_status(hw, skb, &status, 1);
 +                      tx_status(hw, skb, IEEE80211_TX_STAT_ACK, stats->signal, 1);
                        goto out;
                }
        }
@@@ -602,8 -656,8 +602,8 @@@ int zd_mac_rx(struct ieee80211_hw *hw, 
        const struct rx_status *status;
        struct sk_buff *skb;
        int bad_frame = 0;
 -      u16 fc;
 -      bool is_qos, is_4addr, need_padding;
 +      __le16 fc;
 +      int need_padding;
        int i;
        u8 rate;
  
  
        stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq;
        stats.band = IEEE80211_BAND_2GHZ;
 -      stats.ssi = status->signal_strength;
 -      stats.signal = zd_rx_qual_percent(buffer,
 +      stats.signal = status->signal_strength;
 +      stats.qual = zd_rx_qual_percent(buffer,
                                          length - sizeof(struct rx_status),
                                          status);
  
                        && !mac->pass_ctrl)
                return 0;
  
 -      fc = le16_to_cpu(*((__le16 *) buffer));
 -
 -      is_qos = ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
 -               (fc & IEEE80211_STYPE_QOS_DATA);
 -      is_4addr = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
 -                 (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS);
 -      need_padding = is_qos ^ is_4addr;
 +      fc = *(__le16 *)buffer;
 +      need_padding = ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc);
  
        skb = dev_alloc_skb(length + (need_padding ? 2 : 0));
        if (skb == NULL)
@@@ -692,7 -751,6 +692,7 @@@ static int zd_op_add_interface(struct i
        case IEEE80211_IF_TYPE_MNTR:
        case IEEE80211_IF_TYPE_MESH_POINT:
        case IEEE80211_IF_TYPE_STA:
 +      case IEEE80211_IF_TYPE_IBSS:
                mac->type = conf->type;
                break;
        default:
@@@ -707,6 -765,7 +707,7 @@@ static void zd_op_remove_interface(stru
  {
        struct zd_mac *mac = zd_hw_mac(hw);
        mac->type = IEEE80211_IF_TYPE_INVALID;
+       zd_set_beacon_interval(&mac->chip, 0);
        zd_write_mac_addr(&mac->chip, NULL);
  }
  
@@@ -722,20 -781,14 +723,20 @@@ static int zd_op_config_interface(struc
  {
        struct zd_mac *mac = zd_hw_mac(hw);
        int associated;
 +      int r;
  
 -      if (mac->type == IEEE80211_IF_TYPE_MESH_POINT) {
 +      if (mac->type == IEEE80211_IF_TYPE_MESH_POINT ||
 +          mac->type == IEEE80211_IF_TYPE_IBSS) {
                associated = true;
                if (conf->beacon) {
 -                      zd_mac_config_beacon(hw, conf->beacon);
 -                      kfree_skb(conf->beacon);
 -                      zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS |
 +                      r = zd_mac_config_beacon(hw, conf->beacon);
 +                      if (r < 0)
 +                              return r;
 +                      r = zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS |
                                        hw->conf.beacon_int);
 +                      if (r < 0)
 +                              return r;
 +                      kfree_skb(conf->beacon);
                }
        } else
                associated = is_valid_ether_addr(conf->bssid);
@@@ -889,17 -942,6 +890,17 @@@ static void zd_op_bss_info_changed(stru
        }
  }
  
 +static int zd_op_beacon_update(struct ieee80211_hw *hw,
 +                             struct sk_buff *skb)
 +{
 +      struct zd_mac *mac = zd_hw_mac(hw);
 +      zd_mac_config_beacon(hw, skb);
 +      kfree_skb(skb);
 +      zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS |
 +                                      hw->conf.beacon_int);
 +      return 0;
 +}
 +
  static const struct ieee80211_ops zd_ops = {
        .tx                     = zd_op_tx,
        .start                  = zd_op_start,
        .config_interface       = zd_op_config_interface,
        .configure_filter       = zd_op_configure_filter,
        .bss_info_changed       = zd_op_bss_info_changed,
 +      .beacon_update          = zd_op_beacon_update,
  };
  
  struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
        hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band;
  
        hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
 -                  IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
 -      hw->max_rssi = 100;
 -      hw->max_signal = 100;
 +                  IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
 +                  IEEE80211_HW_SIGNAL_DB;
  
 +      hw->max_signal = 100;
        hw->queues = 1;
        hw->extra_tx_headroom = sizeof(struct zd_ctrlset);
  
diff --combined net/ipv4/fib_trie.c
index d16ae4623be64cbae61f97f0e28edbf7d2ca59b4,e1600ad8fb0e44fbd33657589ba84040b0ac8333..f155a66d6ebfe40916b3cc89216c8d4622ec0c2a
@@@ -22,6 -22,8 +22,6 @@@
   * IP-address lookup using LC-tries. Stefan Nilsson and Gunnar Karlsson
   * IEEE Journal on Selected Areas in Communications, 17(6):1083-1092, June 1999
   *
 - * Version:   $Id: fib_trie.c,v 1.3 2005/06/08 14:20:01 robert Exp $
 - *
   *
   * Code from fib_hash has been reused which includes the following header:
   *
@@@ -1271,7 -1273,7 +1271,7 @@@ static int fn_trie_insert(struct fib_ta
  
                        fib_release_info(fi_drop);
                        if (state & FA_S_ACCESSED)
 -                              rt_cache_flush(-1);
 +                              rt_cache_flush(cfg->fc_nlinfo.nl_net, -1);
                        rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen,
                                tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE);
  
        list_add_tail_rcu(&new_fa->fa_list,
                          (fa ? &fa->fa_list : fa_head));
  
 -      rt_cache_flush(-1);
 +      rt_cache_flush(cfg->fc_nlinfo.nl_net, -1);
        rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id,
                  &cfg->fc_nlinfo, 0);
  succeeded:
@@@ -1357,17 -1359,17 +1357,17 @@@ static int check_leaf(struct trie *t, s
                        t->stats.semantic_match_miss++;
  #endif
                if (err <= 0)
-                       return plen;
+                       return err;
        }
  
-       return -1;
+       return 1;
  }
  
  static int fn_trie_lookup(struct fib_table *tb, const struct flowi *flp,
                          struct fib_result *res)
  {
        struct trie *t = (struct trie *) tb->tb_data;
-       int plen, ret = 0;
+       int ret;
        struct node *n;
        struct tnode *pn;
        int pos, bits;
  
        /* Just a leaf? */
        if (IS_LEAF(n)) {
-               plen = check_leaf(t, (struct leaf *)n, key, flp, res);
-               if (plen < 0)
-                       goto failed;
-               ret = 0;
+               ret = check_leaf(t, (struct leaf *)n, key, flp, res);
                goto found;
        }
  
                }
  
                if (IS_LEAF(n)) {
-                       plen = check_leaf(t, (struct leaf *)n, key, flp, res);
-                       if (plen < 0)
+                       ret = check_leaf(t, (struct leaf *)n, key, flp, res);
+                       if (ret > 0)
                                goto backtrace;
-                       ret = 0;
                        goto found;
                }
  
@@@ -1664,7 -1661,7 +1659,7 @@@ static int fn_trie_delete(struct fib_ta
                trie_leaf_remove(t, l);
  
        if (fa->fa_state & FA_S_ACCESSED)
 -              rt_cache_flush(-1);
 +              rt_cache_flush(cfg->fc_nlinfo.nl_net, -1);
  
        fib_release_info(fa->fa_info);
        alias_free_mem_rcu(fa);
diff --combined net/ipv6/exthdrs.c
index 602ea826f0a59665c1b15b00088062be2b1623c1,dcf94fdfb863889bf1a9729010f4ffa3a6c3696a..9f1084b4c0e80d592fb475f968333cd48c05206c
@@@ -7,6 -7,8 +7,6 @@@
   *    Andi Kleen              <ak@muc.de>
   *    Alexey Kuznetsov        <kuznet@ms2.inr.ac.ru>
   *
 - *    $Id: exthdrs.c,v 1.13 2001/06/19 15:58:56 davem Exp $
 - *
   *    This program is free software; you can redistribute it and/or
   *      modify it under the terms of the GNU General Public License
   *      as published by the Free Software Foundation; either version
@@@ -443,7 -445,7 +443,7 @@@ looped_back
                        kfree_skb(skb);
                        return -1;
                }
-               if (!ipv6_chk_home_addr(&init_net, addr)) {
+               if (!ipv6_chk_home_addr(dev_net(skb->dst->dev), addr)) {
                        IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
                                         IPSTATS_MIB_INADDRERRORS);
                        kfree_skb(skb);
index 2078803d3581dfdb6c4268e03f482bf0792d3c1c,4ea7b97d1af1406737e94f22b85c7c2de0679d99..0a9135b974b5d11817f60534338d272dd249aef1
@@@ -61,7 -61,7 +61,7 @@@ enum rc_pid_event_type 
  union rc_pid_event_data {
        /* RC_PID_EVENT_TX_STATUS */
        struct {
 -              struct ieee80211_tx_status tx_status;
 +              struct ieee80211_tx_info tx_status;
        };
        /* RC_PID_EVENT_TYPE_RATE_CHANGE */
        /* RC_PID_EVENT_TYPE_TX_RATE */
@@@ -141,7 -141,6 +141,6 @@@ struct rc_pid_events_file_info 
   *    rate behaviour values (lower means we should trust more what we learnt
   *    about behaviour of rates, higher means we should trust more the natural
   *    ordering of rates)
-  * @fast_start: if Y, push high rates right after initialization
   */
  struct rc_pid_debugfs_entries {
        struct dentry *dir;
        struct dentry *sharpen_factor;
        struct dentry *sharpen_duration;
        struct dentry *norm_offset;
-       struct dentry *fast_start;
  };
  
  void rate_control_pid_event_tx_status(struct rc_pid_event_buffer *buf,
 -                                           struct ieee80211_tx_status *stat);
 +                                    struct ieee80211_tx_info *stat);
  
  void rate_control_pid_event_rate_change(struct rc_pid_event_buffer *buf,
                                               int index, int rate);
@@@ -267,9 -265,6 +265,6 @@@ struct rc_pid_info 
        /* Normalization offset. */
        unsigned int norm_offset;
  
-       /* Fast starst parameter. */
-       unsigned int fast_start;
        /* Rates information. */
        struct rc_pid_rateinfo *rinfo;
  
index 62388f8e9024ac1d52ca8133ede068c9abc1a072,bcd27c1d75941d8b56d1802d99d1d0209c5c1187..742c5b06cffd0d5cfa47b14617fabbb917788a45
@@@ -237,7 -237,8 +237,7 @@@ static void rate_control_pid_sample(str
  }
  
  static void rate_control_pid_tx_status(void *priv, struct net_device *dev,
 -                                     struct sk_buff *skb,
 -                                     struct ieee80211_tx_status *status)
 +                                     struct sk_buff *skb)
  {
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
        struct rc_pid_sta_info *spinfo;
        unsigned long period;
        struct ieee80211_supported_band *sband;
 +      struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
  
        rcu_read_lock();
  
  
        /* Ignore all frames that were sent with a different rate than the rate
         * we currently advise mac80211 to use. */
 -      if (status->control.tx_rate != &sband->bitrates[sta->txrate_idx])
 +      if (info->tx_rate_idx != sta->txrate_idx)
                goto unlock;
  
        spinfo = sta->rate_ctrl_priv;
        spinfo->tx_num_xmit++;
  
  #ifdef CONFIG_MAC80211_DEBUGFS
 -      rate_control_pid_event_tx_status(&spinfo->events, status);
 +      rate_control_pid_event_tx_status(&spinfo->events, info);
  #endif
  
        /* We count frames that totally failed to be transmitted as two bad
         * frames, those that made it out but had some retries as one good and
         * one bad frame. */
 -      if (status->excessive_retries) {
 +      if (info->status.excessive_retries) {
                spinfo->tx_num_failed += 2;
                spinfo->tx_num_xmit++;
 -      } else if (status->retry_count) {
 +      } else if (info->status.retry_count) {
                spinfo->tx_num_failed++;
                spinfo->tx_num_xmit++;
        }
  
 -      if (status->excessive_retries) {
 +      if (info->status.excessive_retries) {
                sta->tx_retry_failed++;
                sta->tx_num_consecutive_failures++;
                sta->tx_num_mpdu_fail++;
                sta->tx_num_consecutive_failures = 0;
                sta->tx_num_mpdu_ok++;
        }
 -      sta->tx_retry_count += status->retry_count;
 -      sta->tx_num_mpdu_fail += status->retry_count;
 +      sta->tx_retry_count += info->status.retry_count;
 +      sta->tx_num_mpdu_fail += info->status.retry_count;
  
        /* Update PID controller state. */
        period = (HZ * pinfo->sampling_period + 500) / 1000;
@@@ -330,7 -330,7 +330,7 @@@ static void rate_control_pid_get_rate(v
        fc = le16_to_cpu(hdr->frame_control);
        if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
            is_multicast_ether_addr(hdr->addr1) || !sta) {
 -              sel->rate = rate_lowest(local, sband, sta);
 +              sel->rate_idx = rate_lowest_index(local, sband, sta);
                rcu_read_unlock();
                return;
        }
  
        rcu_read_unlock();
  
 -      sel->rate = &sband->bitrates[rateidx];
 +      sel->rate_idx = rateidx;
  
  #ifdef CONFIG_MAC80211_DEBUGFS
        rate_control_pid_event_tx_rate(
@@@ -398,13 -398,25 +398,25 @@@ static void *rate_control_pid_alloc(str
                return NULL;
        }
  
+       pinfo->target = RC_PID_TARGET_PF;
+       pinfo->sampling_period = RC_PID_INTERVAL;
+       pinfo->coeff_p = RC_PID_COEFF_P;
+       pinfo->coeff_i = RC_PID_COEFF_I;
+       pinfo->coeff_d = RC_PID_COEFF_D;
+       pinfo->smoothing_shift = RC_PID_SMOOTHING_SHIFT;
+       pinfo->sharpen_factor = RC_PID_SHARPENING_FACTOR;
+       pinfo->sharpen_duration = RC_PID_SHARPENING_DURATION;
+       pinfo->norm_offset = RC_PID_NORM_OFFSET;
+       pinfo->rinfo = rinfo;
+       pinfo->oldrate = 0;
        /* Sort the rates. This is optimized for the most common case (i.e.
         * almost-sorted CCK+OFDM rates). Kind of bubble-sort with reversed
         * mapping too. */
        for (i = 0; i < sband->n_bitrates; i++) {
                rinfo[i].index = i;
                rinfo[i].rev_index = i;
-               if (pinfo->fast_start)
+               if (RC_PID_FAST_START)
                        rinfo[i].diff = 0;
                else
                        rinfo[i].diff = i * pinfo->norm_offset;
                        break;
        }
  
-       pinfo->target = RC_PID_TARGET_PF;
-       pinfo->sampling_period = RC_PID_INTERVAL;
-       pinfo->coeff_p = RC_PID_COEFF_P;
-       pinfo->coeff_i = RC_PID_COEFF_I;
-       pinfo->coeff_d = RC_PID_COEFF_D;
-       pinfo->smoothing_shift = RC_PID_SMOOTHING_SHIFT;
-       pinfo->sharpen_factor = RC_PID_SHARPENING_FACTOR;
-       pinfo->sharpen_duration = RC_PID_SHARPENING_DURATION;
-       pinfo->norm_offset = RC_PID_NORM_OFFSET;
-       pinfo->fast_start = RC_PID_FAST_START;
-       pinfo->rinfo = rinfo;
-       pinfo->oldrate = 0;
  #ifdef CONFIG_MAC80211_DEBUGFS
        de = &pinfo->dentries;
        de->dir = debugfs_create_dir("rc80211_pid",
        de->norm_offset = debugfs_create_u32("norm_offset",
                                             S_IRUSR | S_IWUSR, de->dir,
                                             &pinfo->norm_offset);
-       de->fast_start = debugfs_create_bool("fast_start",
-                                            S_IRUSR | S_IWUSR, de->dir,
-                                            &pinfo->fast_start);
  #endif
  
        return pinfo;
@@@ -479,7 -475,6 +475,6 @@@ static void rate_control_pid_free(void 
  #ifdef CONFIG_MAC80211_DEBUGFS
        struct rc_pid_debugfs_entries *de = &pinfo->dentries;
  
-       debugfs_remove(de->fast_start);
        debugfs_remove(de->norm_offset);
        debugfs_remove(de->sharpen_duration);
        debugfs_remove(de->sharpen_factor);
@@@ -540,6 -535,11 +535,6 @@@ static struct rate_control_ops mac80211
  #endif
  };
  
 -MODULE_DESCRIPTION("PID controller based rate control algorithm");
 -MODULE_AUTHOR("Stefano Brivio");
 -MODULE_AUTHOR("Mattias Nissler");
 -MODULE_LICENSE("GPL");
 -
  int __init rc80211_pid_init(void)
  {
        return ieee80211_rate_control_register(&mac80211_rcpid);
@@@ -549,3 -549,8 +544,3 @@@ void rc80211_pid_exit(void
  {
        ieee80211_rate_control_unregister(&mac80211_rcpid);
  }
 -
 -#ifdef CONFIG_MAC80211_RC_PID_MODULE
 -module_init(rc80211_pid_init);
 -module_exit(rc80211_pid_exit);
 -#endif
index 740acd6bc7d955328b22eb08273646727dcfec0d,dd28fb239a60438b28ed3c90b9f5d979c8c6b700..420a10d8eb1ec7fdc449cc4304afcbe00f4b9e98
@@@ -844,8 -844,15 +844,14 @@@ static int tcp_packet(struct nf_conn *c
                        /* Attempt to reopen a closed/aborted connection.
                         * Delete this connection and look up again. */
                        write_unlock_bh(&tcp_lock);
-                       nf_ct_kill(ct);
-                       return -NF_REPEAT;
++
+                       /* Only repeat if we can actually remove the timer.
+                        * Destruction may already be in progress in process
+                        * context and we must give it a chance to terminate.
+                        */
 -                      if (del_timer(&ct->timeout)) {
 -                              ct->timeout.function((unsigned long)ct);
++                      if (nf_ct_kill(ct))
+                               return -NF_REPEAT;
 -                      }
+                       return -NF_DROP;
                }
                /* Fall through */
        case TCP_CONNTRACK_IGNORE:
                        if (LOG_INVALID(IPPROTO_TCP))
                                nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
                                          "nf_ct_tcp: killing out of sync session ");
 -                      if (del_timer(&ct->timeout))
 -                              ct->timeout.function((unsigned long)ct);
 +                      nf_ct_kill(ct);
                        return -NF_DROP;
                }
                ct->proto.tcp.last_index = index;
                   problem case, so we can delete the conntrack
                   immediately.  --RR */
                if (th->rst) {
 -                      if (del_timer(&ct->timeout))
 -                              ct->timeout.function((unsigned long)ct);
 +                      nf_ct_kill_acct(ct, ctinfo, skb);
                        return NF_ACCEPT;
                }
        } else if (!test_bit(IPS_ASSURED_BIT, &ct->status)